shithub: cstory

Download patch

ref: cbc5542cca4a6bd23779b91bc2530e009b7d508b
parent: fd47245c236c677d03a9f88e55187262a005556a
author: cuckydev <cuckydev@users.noreply.github.com>
date: Thu Jan 24 17:19:56 EST 2019

added some stuff

--- a/Makefile
+++ b/Makefile
@@ -1,16 +1,24 @@
 RELEASE = 0
 
-ifeq ($(RELEASE), 0)
-CXXFLAGS := -O0 -g -static -mconsole
-FILENAME = debug
+ifeq ($(JAPANESE), 1)
+	ifeq ($(RELEASE), 0)
+	CXXFLAGS := -DJAPANESE -O0 -g -static -mconsole
+	FILENAME := debugjp
+	else
+	CXXFLAGS := -DJAPANESE -O3 -s -static
+	FILENAME := releasejp
+	endif
+
 else
-CXXFLAGS := -O3 -s -static
-FILENAME = release
+	ifeq ($(RELEASE), 0)
+	CXXFLAGS := -O0 -g -static -mconsole
+	FILENAME := debug
+	else
+	CXXFLAGS := -O3 -s -static
+	FILENAME := release
+	endif
 endif
 
-ifeq ($(JAPANESE), 1)
-CXXFLAGS += -DJAPANESE
-endif
 ifeq ($(FIX_BUGS), 1)
 CXXFLAGS += -DFIX_BUGS
 endif
@@ -21,6 +29,7 @@
 # For an accurate result to the original's code, compile in alphabetical order
 SOURCES = \
 	Back \
+	Caret \
 	Config \
 	Draw \
 	Ending \
@@ -28,6 +37,7 @@
 	Fade \
 	Flags \
 	Font \
+	Frame \
 	Game \
 	Generic \
 	GenericLoad \
@@ -36,6 +46,7 @@
 	Main \
 	Map \
 	MapName \
+	MyChar \
 	NpChar \
 	NpcTbl \
 	Organya \
--- a/src/Back.cpp
+++ b/src/Back.cpp
@@ -25,9 +25,136 @@
 	
 	//Set background stuff and load texture
 	gBack.flag = 1;
-	if (!ReloadBitmap_File(fName, 28))
+	if (!ReloadBitmap_File(fName, SURFACE_ID_LEVEL_BACKGROUND))
 		return false;
 	gBack.type = type;
 	gWaterY = 0x1E0000;
 	return true;
+}
+
+void ActBack()
+{
+	if (gBack.type == 5)
+	{
+		gBack.fx += 0xC00;
+	}
+	else if (gBack.type >= 5 && gBack.type <= 7)
+	{
+		++gBack.fx;
+		gBack.fx %= 640;
+	}
+}
+
+void PutBack(int fx, int fy)
+{
+	RECT rect = {0, 0, gBack.partsW, gBack.partsH};
+	
+	switch (gBack.type)
+	{
+		case 0:
+			for (int y = 0; y < WINDOW_HEIGHT; y += gBack.partsH)
+			{
+				for (int x = 0; x < WINDOW_WIDTH; x += gBack.partsW)
+					PutBitmap4(&grcGame, x, y, &rect, SURFACE_ID_LEVEL_BACKGROUND);
+			}
+			break;
+			
+		case 1:
+			for (int y = -(fy / 0x400 % gBack.partsH); y < WINDOW_HEIGHT; y += gBack.partsH)
+			{
+				for (int x = -(fx / 0x400 % gBack.partsW); x < WINDOW_WIDTH; x += gBack.partsW)
+					PutBitmap4(&grcGame, x, y, &rect, SURFACE_ID_LEVEL_BACKGROUND);
+			}
+			break;
+			
+		case 2:
+			for (int y = -(fy / 0x200 % gBack.partsH); y < WINDOW_HEIGHT; y += gBack.partsH)
+			{
+				for (int x = -(fx / 0x200 % gBack.partsW); x < WINDOW_WIDTH; x += gBack.partsW)
+					PutBitmap4(&grcGame, x, y, &rect, SURFACE_ID_LEVEL_BACKGROUND);
+			}
+			break;
+			
+		case 5:
+			for (int y = -gBack.partsH; y < WINDOW_HEIGHT; y += gBack.partsH)
+			{
+				for (int x = -(gBack.fx / 0x200 % gBack.partsW); x < WINDOW_WIDTH; x += gBack.partsW)
+					PutBitmap4(&grcGame, x, y, &rect, SURFACE_ID_LEVEL_BACKGROUND);
+			}
+			break;
+			
+		case 6:
+		case 7:
+			rect.top = 0;
+			rect.bottom = 88;
+			rect.left = 0;
+			rect.right = 320;
+			PutBitmap4(&grcGame, 0, 0, &rect, SURFACE_ID_LEVEL_BACKGROUND);
+			rect.top = 88;
+			rect.bottom = 123;
+			rect.left = gBack.fx / 2;
+			rect.right = 320;
+			PutBitmap4(&grcGame, 0, 88, &rect, SURFACE_ID_LEVEL_BACKGROUND);
+			rect.left = 0;
+			PutBitmap4(&grcGame, 320 - gBack.fx / 2 % 320, 88, &rect, SURFACE_ID_LEVEL_BACKGROUND);
+			rect.top = 123;
+			rect.bottom = 146;
+			rect.left = gBack.fx % 320;
+			rect.right = 320;
+			PutBitmap4(&grcGame, 0, 123, &rect, SURFACE_ID_LEVEL_BACKGROUND);
+			rect.left = 0;
+			PutBitmap4(&grcGame, 320 - gBack.fx % 320, 123, &rect, SURFACE_ID_LEVEL_BACKGROUND);
+			rect.top = 146;
+			rect.bottom = 176;
+			rect.left = 2 * gBack.fx % 320;
+			rect.right = 320;
+			PutBitmap4(&grcGame, 0, 146, &rect, SURFACE_ID_LEVEL_BACKGROUND);
+			rect.left = 0;
+			PutBitmap4(&grcGame, 320 - 2 * gBack.fx % 320, 146, &rect, SURFACE_ID_LEVEL_BACKGROUND);
+			rect.top = 176;
+			rect.bottom = 240;
+			rect.left = 4 * gBack.fx % 320;
+			rect.right = 320;
+			PutBitmap4(&grcGame, 0, 176, &rect, SURFACE_ID_LEVEL_BACKGROUND);
+			rect.left = 0;
+			PutBitmap4(&grcGame, 320 - 4 * gBack.fx % 320, 176, &rect, SURFACE_ID_LEVEL_BACKGROUND);
+			break;
+			
+		default:
+			return;
+	}
+}
+
+void PutFront(int fx, int fy)
+{
+	RECT rcWater[2];
+	rcWater[0] = {0, 0, 32, 16};
+	rcWater[1] = {0, 16, 32, 48};
+
+	if (gBack.type == 3)
+	{
+		int x_1 = fx / 0x4000;
+		int x_2 = fx / 0x4000 + 11;
+		int y_1 = 0;
+		int y_2 = 32;
+		
+		for (int y = 0; y < y_2; y++)
+		{
+			int ypos = (y << 14) / 0x200 - fy / 0x200 + gWaterY / 0x200;
+			
+			if (ypos >= -32)
+			{
+				if (ypos > WINDOW_HEIGHT)
+					return;
+				
+				for (int x = x_1; x < x_2; x++)
+				{
+					int xpos = (x << 14) / 0x200 - fx / 0x200;
+					PutBitmap3(&grcGame, xpos, ypos, &rcWater[1], SURFACE_ID_LEVEL_BACKGROUND);
+					if (!y)
+						PutBitmap3(&grcGame, xpos, ypos, rcWater, SURFACE_ID_LEVEL_BACKGROUND);
+				}
+			}
+		}
+	}
 }
--- a/src/Back.h
+++ b/src/Back.h
@@ -14,3 +14,6 @@
 extern int gWaterY;
 
 bool InitBack(char *fName, int type);
+void ActBack();
+void PutBack(int fx, int fy);
+void PutFront(int fx, int fy);
--- /dev/null
+++ b/src/Caret.cpp
@@ -1,0 +1,109 @@
+#include <string>
+
+#include "WindowsWrapper.h"
+
+#include "Caret.h"
+#include "Draw.h"
+
+#define CARET_MAX 0x40
+CARET gCrt[CARET_MAX];
+
+void InitCaret()
+{
+	memset(gCrt, 0, sizeof(gCrt));
+}
+
+void ActCaret00(CARET *crt)
+{
+	;
+}
+
+//Tables
+CARET_TABLE gCaretTable[18] =
+{
+	{0, 0},
+	{0x800, 0x800},
+	{0x1000, 0x1000},
+	{0x1000, 0x1000},
+	{0x1000, 0x1000},
+	{0x800, 0x800},
+	{0x1000, 0x1000},
+	{0x800, 0x800},
+	{0x1000, 0x1000},
+	{0x1000, 0x1000},
+	{0x3800, 0x1000},
+	{0x800, 0x800},
+	{0x2000, 0x2000},
+	{0x800, 0x800},
+	{0x2800, 0x2800},
+	{0x800, 0x800},
+	{0x2800, 0x800},
+	{0x6800, 0x800}
+};
+
+typedef void (*CARETFUNCTION)(CARET*);
+CARETFUNCTION gpCaretFuncTbl[] =
+{
+	&ActCaret00,
+	nullptr, //&ActCaret01,
+	nullptr, //&ActCaret02,
+	nullptr, //&ActCaret03,
+	nullptr, //&ActCaret04,
+	nullptr, //&ActCaret05,
+	nullptr, //&ActCaret04,
+	nullptr, //&ActCaret07,
+	nullptr, //&ActCaret08,
+	nullptr, //&ActCaret09,
+	nullptr, //&ActCaret10,
+	nullptr, //&ActCaret11,
+	nullptr, //&ActCaret12,
+	nullptr, //&ActCaret13,
+	nullptr, //&ActCaret14,
+	nullptr, //&ActCaret15,
+	nullptr, //&ActCaret16,
+	nullptr //&ActCaret17
+};
+
+void ActCaret()
+{
+	for (int i = 0; i < CARET_MAX; i++)
+	{
+		if (gCrt[i].cond & 0x80 && gpCaretFuncTbl[gCrt[i].code] != nullptr)
+			gpCaretFuncTbl[gCrt[i].code](&gCrt[i]);
+	}
+}
+
+void PutCaret(int fx, int fy)
+{
+	for (int i = 0; i < CARET_MAX; i++)
+	{
+		if (gCrt[i].cond & 0x80)
+		{
+			PutBitmap3(
+				&grcGame,
+				(gCrt[i].x - gCrt[i].view_left) / 0x200 - fx / 0x200,
+				(gCrt[i].y - gCrt[i].view_top) / 0x200 - fy / 0x200,
+				&gCrt[i].rect,
+				19);
+		}
+	}
+}
+
+void SetCaret(int x, int y, int code, int dir)
+{
+	for (int c = 0; c < CARET_MAX; c++)
+	{
+		if (gCrt[c].cond)
+		{
+			memset(&gCrt[c], 0, sizeof(CARET));
+			gCrt[c].cond = 0x80;
+			gCrt[c].code = code;
+			gCrt[c].x = x;
+			gCrt[c].y = y;
+			gCrt[c].view_left = gCaretTable[code].view_left;
+			gCrt[c].view_top = gCaretTable[code].view_top;
+			gCrt[c].direct = dir;
+			break;
+		}
+	}
+}
--- /dev/null
+++ b/src/Caret.h
@@ -1,0 +1,31 @@
+#pragma once
+#include "WindowsWrapper.h"
+
+struct CARET_TABLE
+{
+	int view_left;
+	int view_top;
+};
+
+struct CARET
+{
+	int cond;
+	int code;
+	int direct;
+	int x;
+	int y;
+	int xm;
+	int ym;
+	int act_no;
+	int act_wait;
+	int ani_no;
+	int ani_wait;
+	int view_left;
+	int view_top;
+	RECT rect;
+};
+
+void InitCaret();
+void ActCaret();
+void PutCaret(int fx, int fy);
+void SetCaret(int x, int y, int code, int dir);
--- a/src/Ending.cpp
+++ b/src/Ending.cpp
@@ -286,7 +286,7 @@
 				Credit.offset += 4;
 				
 				//If flag is set
-				if ((uint8_t)GetNPCFlag(a))
+				if (GetNPCFlag(a))
 				{
 					//Jump to label
 					while ( Credit.offset < Credit.size )
--- a/src/Frame.cpp
+++ b/src/Frame.cpp
@@ -1,0 +1,149 @@
+#include <string.h>
+
+#include "Frame.h"
+#include "Map.h"
+#include "MyChar.h"
+#include "NpChar.h"
+#include "Game.h"
+#include "CommonDefines.h"
+
+FRAME gFrame;
+
+void MoveFrame3()
+{
+	int16_t map_w, map_l;
+	GetMapData(0, &map_w, &map_l);
+	
+	gFrame.x += (*gFrame.tgt_x - (WINDOW_WIDTH << 8) - gFrame.x) / gFrame.wait;
+	gFrame.y += (*gFrame.tgt_y - (WINDOW_HEIGHT << 8) - gFrame.y) / gFrame.wait;
+	
+	//Keep in bounds
+	if (gFrame.x <= -0x200)
+		gFrame.x = 0;
+	if (gFrame.y <= -0x200)
+		gFrame.y = 0;
+	
+	if (gFrame.x > ((((map_w - 1) << 4) - WINDOW_WIDTH)) << 9);
+		gFrame.x = (((map_w - 1) << 4) - WINDOW_WIDTH) << 9;
+	if (gFrame.y > ((((map_l - 1) << 4) - WINDOW_HEIGHT)) << 9);
+		gFrame.y = (((map_l - 1) << 4) - WINDOW_HEIGHT) << 9;
+
+	//Quake
+	if (gFrame.quake2)
+	{
+		gFrame.x += (Random(-5, 5) << 9);
+		gFrame.y += (Random(-3, 3) << 9);
+		--gFrame.quake2;
+	}
+	else if (gFrame.quake)
+	{
+		gFrame.x += (Random(-1, 1) << 9);
+		gFrame.y += (Random(-1, 1) << 9);
+		--gFrame.quake;
+	}
+	
+	//Keep in bounds
+	if (gFrame.x <= -0x200)
+		gFrame.x = 0;
+	if (gFrame.y <= -0x200)
+		gFrame.y = 0;
+}
+
+void GetFramePosition(int *fx, int *fy)
+{
+	*fx = gFrame.x;
+	*fy = gFrame.y;
+}
+
+void SetFramePosition(int fx, int fy)
+{
+	//End quake
+	gFrame.quake = 0;
+	gFrame.quake2 = 0;
+
+	//Move frame position
+	int16_t map_w, map_l;
+	GetMapData(0, &map_w, &map_l);
+	
+	gFrame.x = fx;
+	gFrame.y = fy;
+	
+	//Keep in bounds
+	if (gFrame.x <= -0x200)
+		gFrame.x = 0;
+	if (gFrame.y <= -0x200)
+		gFrame.y = 0;
+
+	if (gFrame.x > ((((map_w - 1) << 4) - WINDOW_WIDTH)) << 9);
+		gFrame.x = (((map_w - 1) << 4) - WINDOW_WIDTH) << 9;
+	if (gFrame.y > ((((map_l - 1) << 4) - WINDOW_HEIGHT)) << 9);
+		gFrame.y = (((map_l - 1) << 4) - WINDOW_HEIGHT) << 9;
+}
+
+void SetFrameMyChar()
+{
+	//Move frame position
+	int mc_x, mc_y;
+	GetMyCharPosition(&mc_x, &mc_y);
+	
+	int16_t map_w, map_l;
+	GetMapData(0, &map_w, &map_l);
+	
+	gFrame.x = mc_x - 81920;
+	gFrame.y = mc_y - 61440;
+	
+	//Keep in bounds
+	if (gFrame.x <= -0x200)
+		gFrame.x = 0;
+	if (gFrame.y <= -0x200)
+		gFrame.y = 0;
+
+	if (gFrame.x > ((((map_w - 1) << 4) - WINDOW_WIDTH)) << 9);
+		gFrame.x = (((map_w - 1) << 4) - WINDOW_WIDTH) << 9;
+	if (gFrame.y > ((((map_l - 1) << 4) - WINDOW_HEIGHT)) << 9);
+		gFrame.y = (((map_l - 1) << 4) - WINDOW_HEIGHT) << 9;
+}
+
+void SetFrameTargetMyChar(int wait)
+{
+	gFrame.tgt_x = &gMC.x;
+	gFrame.tgt_y = &gMC.y;
+	gFrame.wait = wait;
+}
+
+void SetFrameTargetNpChar(int event, int wait)
+{
+	for (int i = 0; i < NPC_MAX; i++)
+	{
+		if (gNPC[i].code_event == event)
+		{
+			gFrame.tgt_x = &gNPC[i].x;
+			gFrame.tgt_y = &gNPC[i].y;
+			gFrame.wait = wait;
+			break;
+		}
+	}
+}
+
+void SetFrameTargetBoss(int no, int wait)
+{
+	//gFrame.tgt_x = &gBoss[no].x;
+	//gFrame.tgt_y = &gBoss[no].y;
+	gFrame.wait = wait;
+}
+
+void SetQuake(int time)
+{
+	gFrame.quake = time;
+}
+
+void SetQuake2(int time)
+{
+	gFrame.quake2 = time;
+}
+
+void ResetQuake()
+{
+	gFrame.quake = 0;
+	gFrame.quake2 = 0;
+}
--- a/src/Frame.h
+++ b/src/Frame.h
@@ -1,0 +1,22 @@
+#pragma once
+struct FRAME
+{
+	int x;
+	int y;
+	int *tgt_x;
+	int *tgt_y;
+	int wait;
+	int quake;
+	int quake2;
+};
+
+void MoveFrame3();
+void GetFramePosition(int *fx, int *fy);
+void SetFramePosition(int fx, int fy);
+void SetFrameMyChar();
+void SetFrameTargetMyChar(int wait);
+void SetFrameTargetNpChar(int event, int wait);
+void SetFrameTargetBoss(int no, int wait);
+void SetQuake(int time);
+void SetQuake2(int time);
+void ResetQuake();
--- a/src/Game.cpp
+++ b/src/Game.cpp
@@ -11,9 +11,12 @@
 #include "GenericLoad.h"
 #include "TextScr.h"
 #include "Fade.h"
+#include "Frame.h"
 #include "Flags.h"
 #include "Escape.h"
 #include "Stage.h"
+#include "MyChar.h"
+#include "Caret.h"
 #include "Map.h"
 #include "Main.h"
 #include "MapName.h"
@@ -86,7 +89,7 @@
 int ModeOpening()
 {
 	InitNpChar();
-	//InitCaret();
+	InitCaret();
 	//InitStar();
 	InitFade();
 	//InitFlash();
@@ -93,7 +96,7 @@
 	//InitBossLife();
 	ChangeMusic(0);
 	TransferStage(72, 100, 3, 3);
-	//SetFrameTargetMyChar(16);
+	SetFrameTargetMyChar(16);
 	SetFadeMask();
 	
 	//Reset cliprect and flags
@@ -126,9 +129,9 @@
 			break;
 		
 		//Update everything
-		//ActNpChar();
+		ActNpChar();
 		//ActBossChar();
-		//ActBack();
+		ActBack();
 		//ResetMyCharFlag();
 		//HitMyCharMap();
 		//HitMyCharNpChar();
@@ -137,24 +140,23 @@
 		//HitBossMap();
 		//HitBossBullet();
 		//ActCaret();
-		//MoveFrame3();
+		MoveFrame3();
 		ProcFade();
 		
 		//Draw everything
 		CortBox(&grcFull, 0x000000);
 		
-		int frame_x = 0;
-		int frame_y = 0;
-		//GetFramePosition(&frame_x, &frame_y);
-		//PutBack(frame_x, frame_y);
+		int frame_x, frame_y;
+		GetFramePosition(&frame_x, &frame_y);
+		PutBack(frame_x, frame_y);
 		PutStage_Back(frame_x, frame_y);
 		//PutBossChar(frame_x, frame_y);
-		//PutNpChar(frame_x, frame_y);
+		PutNpChar(frame_x, frame_y);
 		PutMapDataVector(frame_x, frame_y);
 		PutStage_Front(frame_x, frame_y);
-		//PutFront(frame_x, frame_y);
+		PutFront(frame_x, frame_y);
 		//PutCaret(frame_x, frame_y);
-		PutFade();
+		//PutFade();
 		
 		//Update Text Script
 		//int tscRet = TextScriptProc();
@@ -229,7 +231,7 @@
 	rcSu[3] = {48, 16, 64, 32};
 	
 	//Reset everything
-	//InitCaret();
+	InitCaret();
 	//InitStar();
 	//CutNoise();
 	
--- /dev/null
+++ b/src/MyChar.cpp
@@ -1,0 +1,165 @@
+#include <string>
+#include <stdint.h>
+
+#include "WindowsWrapper.h"
+
+#include "MyChar.h"
+#include "Draw.h"
+#include "Sound.h"
+#include "KeyControl.h"
+
+MYCHAR gMC;
+
+void InitMyChar()
+{
+	memset(&gMC, 0, sizeof(MYCHAR));
+	gMC.cond = 0x80;
+	gMC.direct = 2;
+	gMC.view = {0x1000, 0x1000, 0x1000, 0x1000};
+	gMC.hit = {0xA00, 0x1000, 0xA00, 0x1000};
+	gMC.life = 3;
+	gMC.max_life = 3;
+	gMC.unit = 0;
+}
+
+void AnimationMyChar(bool bKey)
+{
+	RECT rcLeft[12];
+	RECT rcRight[12];
+	
+	rcLeft[0] = {0, 0, 16, 16};
+	rcLeft[1] = {16, 0, 32, 16};
+	rcLeft[2] = {0, 0, 16, 16};
+	rcLeft[3] = {32, 0, 48, 16};
+	rcLeft[4] = {0, 0, 16, 16};
+	rcLeft[5] = {48, 0, 64, 16};
+	rcLeft[6] = {64, 0, 80, 16};
+	rcLeft[7] = {48, 0, 64, 16};
+	rcLeft[8] = {80, 0, 96, 16};
+	rcLeft[9] = {48, 0, 64, 16};
+	rcLeft[10] = {96, 0, 112, 16};
+	rcLeft[11] = {112, 0, 128, 16};
+
+	rcRight[0] = {0, 16, 16, 32};
+	rcRight[1] = {16, 16, 32, 32};
+	rcRight[2] = {0, 16, 16, 32};
+	rcRight[3] = {32, 16, 48, 32};
+	rcRight[4] = {0, 16, 16, 32};
+	rcRight[5] = {48, 16, 64, 32};
+	rcRight[6] = {64, 16, 80, 32};
+	rcRight[7] = {48, 16, 64, 32};
+	rcRight[8] = {80, 16, 96, 32};
+	rcRight[9] = {48, 16, 64, 32};
+	rcRight[10] = {96, 16, 112, 32};
+	rcRight[11] = {112, 16, 128, 32};
+	
+	if (!(gMC.cond & 2))
+	{
+		if (gMC.flag & 8)
+		{
+			if (gMC.cond & 1)
+			{
+				gMC.ani_no = 11;
+			}
+			else if (gKey & gKeyUp && (gKeyRight | gKeyLeft) & gKey && bKey)
+			{
+				gMC.cond |= 4;
+				
+				if (++gMC.ani_wait > 4)
+				{
+					gMC.ani_wait = 0;
+					if (++gMC.ani_no == 7 || gMC.ani_no == 9)
+						PlaySoundObject(24, 1);
+				}
+				
+				if (gMC.ani_no > 9 || gMC.ani_no < 6)
+					gMC.ani_no = 6;
+			}
+			else if ((gKeyRight | gKeyLeft) & gKey && bKey)
+			{
+				gMC.cond |= 4;
+				
+				if (++gMC.ani_wait > 4)
+				{
+					gMC.ani_wait = 0;
+					if (++gMC.ani_no == 2 || gMC.ani_no == 4)
+						PlaySoundObject(24, 1);
+				}
+				
+				if (gMC.ani_no > 4 || gMC.ani_no < 1)
+					gMC.ani_no = 1;
+			}
+			else if ( gKey & gKeyUp && bKey )
+			{
+				if (gMC.cond & 4)
+					PlaySoundObject(24, 1);
+				
+				gMC.cond &= ~4;
+				gMC.ani_no = 5;
+			}
+			else
+			{
+				if (gMC.cond & 4)
+					PlaySoundObject(24, 1);
+				
+				gMC.cond &= ~4;
+				gMC.ani_no = 0;
+			}
+		}
+		else if (gMC.up)
+		{
+			gMC.ani_no = 6;
+		}
+		else if (gMC.down)
+		{
+			gMC.ani_no = 10;
+		}
+		else if ( gMC.ym <= 0 )
+		{
+			gMC.ani_no = 3;
+		}
+		else
+		{
+			gMC.ani_no = 1;
+		}
+		
+		if (gMC.direct)
+			gMC.rect = rcRight[gMC.ani_no];
+		else
+			gMC.rect = rcLeft[gMC.ani_no];
+	}
+}
+
+void ShowMyChar(bool bShow)
+{
+	if (bShow)
+		gMC.cond &= ~2;
+	else
+		gMC.cond |= 2;
+}
+
+void GetMyCharPosition(int *x, int *y)
+{
+	*x = gMC.x;
+	*y = gMC.y;
+}
+
+void SetMyCharPosition(int x, int y)
+{
+	gMC.x = x;
+	gMC.y = y;
+	gMC.tgt_x = x;
+	gMC.tgt_y = y;
+	gMC.index_x = 0;
+	gMC.index_y = 0;
+	gMC.xm = 0;
+	gMC.ym = 0;
+	gMC.cond &= ~1;
+	//InitStar();
+}
+
+void MoveMyChar(int x, int y)
+{
+	gMC.x = x;
+	gMC.y = y;
+}
--- /dev/null
+++ b/src/MyChar.h
@@ -1,0 +1,56 @@
+#pragma once
+#include <stdint.h>
+#include "WindowsWrapper.h"
+
+struct MYCHAR
+{
+	uint8_t cond;
+	unsigned int flag;
+	int direct;
+	int up;
+	int down;
+	int unit;
+	int equip;
+	int x;
+	int y;
+	int tgt_x;
+	int tgt_y;
+	int index_x;
+	int index_y;
+	int xm;
+	int ym;
+	int ani_wait;
+	int ani_no;
+	RECT hit;
+	RECT view;
+	RECT rect;
+	RECT rect_arms;
+	int level;
+	int exp_wait;
+	int exp_count;
+	uint8_t shock;
+	uint8_t no_life;
+	uint8_t rensha;
+	uint8_t bubble;
+	int16_t life;
+	int16_t star;
+	int16_t max_life;
+	int16_t a;
+	int lifeBr;
+	int lifeBr_count;
+	int air;
+	int air_get;
+	char sprash;
+	char ques;
+	char boost_sw;
+	int boost_cnt;
+};
+
+extern MYCHAR gMC;
+
+void InitMyChar();
+void AnimationMyChar(bool bKey);
+void ShowMyChar(bool bShow);
+void GetMyCharPosition(int *x, int *y);
+void SetMyCharPosition(int x, int y);
+void MoveMyChar(int x, int y);
--- a/src/NpChar.cpp
+++ b/src/NpChar.cpp
@@ -9,9 +9,8 @@
 #include "Game.h"
 #include "Flags.h"
 #include "NpcTbl.h"
+#include "Draw.h"
 
-#define NPC_MAX 0x200
-
 NPCHAR gNPC[NPC_MAX];
 
 const char *gPassPixEve = "PXE\0";
@@ -203,6 +202,139 @@
 			gNPC[n].y = y;
 			gNPC[n].bits = gNpcTable[gNPC[n].code_char].bits;
 			gNPC[n].exp = sub_exp;
+		}
+	}
+}
+
+bool SetBulletObject(int x, int y, int val)
+{
+	int tamakazu_ari[10];
+
+	int t = 0;
+	memset(tamakazu_ari, 0, sizeof(tamakazu_ari));
+	for (int n = 0; n < 8; n++)
+	{
+		int code = 0; //gArmsData[n].code;
+		if (code == 5)
+			tamakazu_ari[t++] = 0;
+		else if (code == 10)
+			tamakazu_ari[t++] = 1;
+		else
+			tamakazu_ari[t] = 0;
+	}
+	
+	if (!t)
+		return false;
+	
+	int n = Random(1, 10 * t);
+	int bullet_no = tamakazu_ari[n % t];
+	for (n = 0x100; n < NPC_MAX; n++)
+	{
+		if (!gNPC[n].cond)
+		{
+			memset(&gNPC[n], 0, sizeof(NPCHAR));
+			gNPC[n].cond |= 0x80u;
+			gNPC[n].direct = 0;
+			gNPC[n].code_event = bullet_no;
+			gNPC[n].code_char = 86;
+			gNPC[n].x = x;
+			gNPC[n].y = y;
+			gNPC[n].bits = gNpcTable[gNPC[n].code_char].bits;
+			gNPC[n].exp = val;
+			SetUniqueParameter(&gNPC[n]);
+			return true;
+		}
+	}
+	
+	return false;
+}
+
+bool SetLifeObject(int x, int y, int val)
+{
+	for (int n = 0x100; n < NPC_MAX; n++)
+	{
+		if (!gNPC[n].cond)
+		{
+			memset(&gNPC[n], 0, sizeof(NPCHAR));
+			gNPC[n].cond |= 0x80u;
+			gNPC[n].direct = 0;
+			gNPC[n].code_char = 87;
+			gNPC[n].x = x;
+			gNPC[n].y = y;
+			gNPC[n].bits = gNpcTable[gNPC[n].code_char].bits;
+			gNPC[n].exp = val;
+			SetUniqueParameter(&gNPC[n]);
+			return true;
+		}
+	}
+	
+	return false;
+}
+
+void VanishNpChar(NPCHAR *npc)
+{
+	int x = npc->x;
+	int y = npc->y;
+	memset(npc, 0, sizeof(NPCHAR));
+	npc->count1 = 0;
+	npc->x = x;
+	npc->y = y;
+	npc->cond |= 0x80u;
+	npc->direct = 0;
+	npc->code_char = 3;
+	npc->bits = gNpcTable[npc->code_char].bits;
+	npc->exp = gNpcTable[npc->code_char].exp;
+	SetUniqueParameter(npc);
+}
+
+void PutNpChar(int fx, int fy)
+{
+	for (int n = 0; n < NPC_MAX; n++)
+	{
+		if (gNPC[n].cond & 0x80)
+		{
+			int8_t a;
+			
+			if (gNPC[n].shock)
+			{
+				a = 2 * ((gNPC[n].shock >> 1) & 1) - 1;
+			}
+			else
+			{
+				a = 0;
+				if (gNPC[n].bits & npc_showDamage && gNPC[n].damage_view)
+				{
+					//SetValueView(&gNPC[n].x, &gNPC[n].y, gNPC[n].damage_view);
+					gNPC[n].damage_view = 0;
+				}
+			}
+			
+			int side;
+			if (gNPC[n].direct)
+				side = gNPC[n].view.back;
+			else
+				side = gNPC[n].view.front;
+			
+			PutBitmap3(
+				&grcGame,
+				(gNPC[n].x - side) / 0x200 - fx / 0x200 + a,
+				(gNPC[n].y - gNPC[n].view.top) / 0x200 - fy / 0x200,
+				&gNPC[n].rect,
+				gNPC[n].surf);
+		}
+	}
+}
+
+void ActNpChar()
+{
+	for (int i = 0; i < NPC_MAX; i++)
+	{
+		if (gNPC[i].cond & 0x80)
+		{
+			if (gpNpcFuncTbl[gNPC[i].code_char] != nullptr)
+				gpNpcFuncTbl[gNPC[i].code_char](&gNPC[i]);
+			if (gNPC[i].shock)
+				--gNPC[i].shock;
 		}
 	}
 }
--- a/src/NpChar.h
+++ b/src/NpChar.h
@@ -2,6 +2,8 @@
 #include <stdint.h>
 #include "WindowsWrapper.h"
 
+#define NPC_MAX 0x200
+
 enum NPC_flags
 {
 	npc_solidSoft = 0x1, //Pushes quote out
@@ -69,6 +71,8 @@
   uint16_t bits;
 };
 
+extern NPCHAR gNPC[NPC_MAX];
+
 void InitNpChar();
 bool LoadEvent(char *path_event);
 void SetNpChar(int code_char, int x, int y, int xm, int ym, int dir, NPCHAR *npc, int start_index);
@@ -75,3 +79,7 @@
 void SetDestroyNpChar(int x, int y, int w, int num);
 void SetDestroyNpCharUp(int x, int y, int w, int num);
 void SetExpObjects(int x, int y, int exp);
+bool SetBulletObject(int x, int y, int val);
+void VanishNpChar(NPCHAR *npc);
+void PutNpChar(int fx, int fy);
+void ActNpChar();
--- a/src/NpcTbl.cpp
+++ b/src/NpcTbl.cpp
@@ -51,3 +51,368 @@
 	if (gNpcTable)
 		free(gNpcTable);
 }
+
+//Npc function table
+NPCFUNCTION gpNpcFuncTbl[] =
+{
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+	nullptr,
+};
--- a/src/NpcTbl.h
+++ b/src/NpcTbl.h
@@ -1,5 +1,6 @@
 #pragma once
 #include <stdint.h>
+#include "NpChar.h"
 
 struct NPC_TBL_RECT
 {
@@ -27,3 +28,7 @@
 
 bool LoadNpcTable(const char *path);
 void ReleaseNpcTable();
+
+//NPC Function table
+typedef void (*NPCFUNCTION)(NPCHAR*);
+extern NPCFUNCTION gpNpcFuncTbl[];
--- a/src/Stage.cpp
+++ b/src/Stage.cpp
@@ -7,8 +7,11 @@
 #include "CommonDefines.h"
 #include "Map.h"
 #include "MapName.h"
+#include "MyChar.h"
 #include "Draw.h"
 #include "Tags.h"
+#include "Frame.h"
+#include "Caret.h"
 #include "NpChar.h"
 #include "TextScr.h"
 #include "Organya.h"
@@ -65,7 +68,7 @@
 bool TransferStage(int no, int w, int x, int y)
 {
 	//Move character
-	//SetMyCharPosition(x << 13, y << 13);
+	SetMyCharPosition(x << 13, y << 13);
 	
 	bool bError = false;
 	bool result;
@@ -127,11 +130,11 @@
 		ReadyMapName(gTMT[no].name);
 		
 		//StartTextScript(w);
-		//SetFrameMyChar();
+		SetFrameMyChar();
 		//ClearBullet();
-		//InitCaret();
+		InitCaret();
 		//ClearValueView();
-		//ResetQuake();
+		ResetQuake();
 		//InitBossChar(gTMT[no].boss_no);
 		//ResetFlash();
 		gStageNo = no;