shithub: cstory

Download patch

ref: 10d946aca25bc0db5f3d31544dc6b6a4d6085d0d
parent: a042b627f81e1964c1841acb515d618699acd004
author: cuckydev <cuckydev@users.noreply.github.com>
date: Tue Jan 29 04:17:13 EST 2019

map system doesn't work

--- a/Makefile
+++ b/Makefile
@@ -53,6 +53,7 @@
 	Main \
 	Map \
 	MapName \
+	MiniMap \
 	MyChar \
 	MycHit \
 	MycParam \
--- a/src/ArmsItem.cpp
+++ b/src/ArmsItem.cpp
@@ -17,7 +17,7 @@
 int gSelectedArms;
 int gSelectedItem;
 int gCampTitleY;
-int gCampActive;
+bool gCampActive;
 
 void ClearArmsData()
 {
@@ -132,6 +132,205 @@
 	return false;
 }
 
+void MoveCampCursor()
+{
+	int arms_num = 0;
+	int item_num = 0;
+	while ( gArmsData[arms_num].code != 0 )
+		++arms_num;
+	while ( gItemData[item_num].code != 0 )
+		++item_num;
+	
+	if (arms_num || item_num)
+	{
+		bool bChange = false;
+		if (gCampActive)
+		{
+			if (gKeyTrg & gKeyLeft)
+			{
+				if (gSelectedItem % 6)
+					--gSelectedItem;
+				else
+					gSelectedItem += 5;
+				
+				bChange = true;
+			}
+			
+			if (gKeyTrg & gKeyRight)
+			{
+				if (item_num - 1 == gSelectedItem)
+					gSelectedItem = 6 * (gSelectedItem / 6);
+				else if (gSelectedItem % 6 == 5)
+					gSelectedItem -= 5;
+				else
+					++gSelectedItem;
+				
+				bChange = true;
+			}
+			
+			if (gKeyTrg & gKeyUp)
+			{
+				if (gSelectedItem + 5 > 10)
+					gSelectedItem -= 6;
+				else
+					gCampActive = false;
+				
+				bChange = true;
+			}
+			
+			if ( gKeyTrg & gKeyDown )
+			{
+				if ( gSelectedItem / 6 == (item_num - 1) / 6 )
+					gCampActive = false;
+				else
+					gSelectedItem += 6;
+				
+				bChange = true;
+			}
+			
+			if (gSelectedItem >= item_num)
+				gSelectedItem = item_num - 1;
+			
+			if (gCampActive && gKeyTrg & gKeyOk)
+				StartTextScript(gItemData[gSelectedItem].code + 6000);
+		}
+		else
+		{
+			if (gKeyTrg & gKeyLeft)
+			{
+				--gSelectedArms;
+				bChange = true;
+			}
+			if (gKeyTrg & gKeyRight)
+			{
+				++gSelectedArms;
+				bChange = true;
+			}
+			if ((gKeyDown | gKeyUp) & gKeyTrg)
+			{
+				if (item_num)
+					gCampActive = true;
+				bChange = true;
+			}
+			
+			if (gSelectedArms < 0)
+				gSelectedArms = arms_num - 1;
+			if (arms_num - 1 < gSelectedArms)
+				gSelectedArms = 0;
+		}
+		
+		if (bChange)
+		{
+			if (gCampActive)
+			{
+				PlaySoundObject(1, 1);
+				
+				if (item_num)
+					StartTextScript(gItemData[gSelectedItem].code + 5000);
+				else
+					StartTextScript(5000);
+			}
+			else
+			{
+				PlaySoundObject(4, 1);
+				
+				if (arms_num)
+					StartTextScript(gArmsData[gSelectedArms].code + 1000);
+				else
+					StartTextScript(1000);
+			}
+		}
+	}
+}
+
+void PutCampObject()
+{
+	//Get rects
+	RECT rcPer = {72, 48, 80, 56};
+	RECT rcNone = {80, 48, 96, 56};
+	RECT rcLv = {80, 80, 96, 88};
+	RECT rcView = {0, 0, WINDOW_WIDTH, WINDOW_HEIGHT};
+	RECT rcCur1[2];
+	RECT rcCur2[2];
+	rcCur1[0] = {0, 88, 40, 128};
+	rcCur1[1] = {40, 88, 80, 128};
+	rcCur2[0] = {80, 88, 112, 104};
+	rcCur2[1] = {80, 104, 112, 120};
+	RECT rcTitle1 = {80, 48, 144, 56};
+	RECT rcTitle2 = {80, 56, 144, 64};
+	RECT rcBoxTop = {0, 0, 244, 8};
+	RECT rcBoxBody = {0, 8, 244, 16};
+	RECT rcBoxBottom = {0, 16, 244, 24};
+	
+	//Draw box
+	int y;
+	PutBitmap3(&rcView, (WINDOW_WIDTH - 244) / 2, (WINDOW_HEIGHT - 224) / 2, &rcBoxTop, 26);
+	for (y = 1; y < 18; y++)
+		PutBitmap3(&rcView, (WINDOW_WIDTH - 244) / 2, (WINDOW_HEIGHT - 224) / 2 * (y + 1), &rcBoxBody, 26);
+	PutBitmap3(&rcView, (WINDOW_WIDTH - 244) / 2, (WINDOW_HEIGHT - 224) / 2 * (y + 1), &rcBoxBottom, 26);
+	
+	//Move titles
+	if (gCampTitleY > (WINDOW_HEIGHT - 208) / 2)
+		--gCampTitleY;
+	
+	//Draw titles
+	PutBitmap3(&rcView, (WINDOW_WIDTH - 224) / 2, gCampTitleY, &rcTitle1, 26);
+	PutBitmap3(&rcView, (WINDOW_WIDTH - 224) / 2, gCampTitleY + 52, &rcTitle2, 26);
+	
+	//Draw arms cursor
+	static int flash;
+	++flash;
+	
+	if (gCampActive)
+		PutBitmap3(&rcView, 40 * gSelectedArms + (WINDOW_WIDTH - 224) / 2, 24, &rcCur1[1], 26);
+	else
+		PutBitmap3(&rcView, 40 * gSelectedArms + (WINDOW_WIDTH - 224) / 2, 24, &rcCur1[(flash >> 1) & 1], 26);
+	
+	//Draw arms
+	for (int i = 0; i < ARMS_MAX && gArmsData[i].code; i++)
+	{
+		RECT rcArms;
+		rcArms.left = 16 * (gArmsData[i].code % 16);
+		rcArms.right = rcArms.left + 16;
+		rcArms.top = 16 * (gArmsData[i].code / 16);
+		rcArms.bottom = rcArms.top + 16;
+		
+		PutBitmap3(&rcView, 40 * i + (WINDOW_WIDTH - 224) / 2, (WINDOW_HEIGHT - 192) / 2, &rcArms, 12);
+		PutBitmap3(&rcView, 40 * i + (WINDOW_WIDTH - 224) / 2, (WINDOW_HEIGHT - 128) / 2, &rcPer, 26);
+		PutBitmap3(&rcView, 40 * i + (WINDOW_WIDTH - 224) / 2, (WINDOW_HEIGHT - 160) / 2, &rcLv, 26);
+		PutNumber4(40 * i + (WINDOW_WIDTH - 224) / 2, (WINDOW_HEIGHT - 160) / 2, gArmsData[i].level, 0);
+		
+		//Draw ammo
+		if ( gArmsData[i].max_num )
+		{
+			PutNumber4(40 * i + (WINDOW_WIDTH - 224) / 2, (WINDOW_HEIGHT - 144) / 2, gArmsData[i].num, 0);
+			PutNumber4(40 * i + (WINDOW_WIDTH - 224) / 2, (WINDOW_HEIGHT - 128) / 2, gArmsData[i].max_num, 0);
+		}
+		else
+		{
+			PutBitmap3(&rcView, 40 * i + (WINDOW_WIDTH - 192) / 2, (WINDOW_HEIGHT - 144) / 2, &rcNone, 26);
+			PutBitmap3(&rcView, 40 * i + (WINDOW_WIDTH - 192) / 2, (WINDOW_HEIGHT - 128) / 2, &rcNone, 26);
+		}
+	}
+	
+	//Draw items cursor
+	if (gCampActive)
+		PutBitmap3(&rcView, 32 * (gSelectedItem % 6) + (WINDOW_WIDTH - 224) / 2, 16 * (gSelectedItem / 6) + (WINDOW_HEIGHT - 88) / 2, &rcCur2[(flash >> 1) & 1], 26);
+	else
+		PutBitmap3(&rcView, 32 * (gSelectedItem % 6) + (WINDOW_WIDTH - 224) / 2, 16 * (gSelectedItem / 6) + (WINDOW_HEIGHT - 88) / 2, &rcCur2[1], 26);
+
+	for (int i = 0; i < ITEM_MAX && gItemData[i].code; i++)
+	{
+		RECT rcItem;
+		rcItem.left = 32 * (gItemData[i].code % 8);
+		rcItem.right = rcItem.left + 32;
+		rcItem.top = 16 * (gItemData[i].code / 8);
+		rcItem.bottom = rcItem.top + 16;
+		
+		PutBitmap3(&rcView, 32 * (i % 6) + (WINDOW_WIDTH - 224) / 2, 16 * (i / 6) + (WINDOW_HEIGHT - 88) / 2, &rcItem, 8);
+	}
+}
+
 int CampLoop()
 {
 	RECT rcView = {0, 0, WINDOW_WIDTH, WINDOW_HEIGHT};
@@ -144,7 +343,7 @@
 	strcpy(name, "ArmsItem.tsc");
 	LoadTextScript2(name);
 	
-	gCampTitleY = 24;
+	gCampTitleY = (WINDOW_HEIGHT - 192) / 2;
 	gCampActive = 0;
 	gSelectedItem = 0;
 	
@@ -170,8 +369,8 @@
 				return 1;
 		}
 		
-		//if (g_GameFlags & 2)
-		//	MoveCampCursor();
+		if (g_GameFlags & 2)
+			MoveCampCursor();
 		
 		int tscRet = TextScriptProc();
 		if (tscRet == 0)
@@ -180,14 +379,13 @@
 			return 2;
 		
 		PutBitmap4(&rcView, 0, 0, &rcView, 10);
-		//PutCampObject();
+		PutCampObject();
 		PutTextScript();
 		PutFramePerSecound();
 		
 		if (!gCampActive && (gKeyItem | gKeyCancel | gKeyOk) & gKeyTrg)
 			break;
-		
-		if (g_GameFlags & 2 && (gKeyItem | gKeyCancel) & gKeyTrg)
+		else if (g_GameFlags & 2 && (gKeyItem | gKeyCancel) & gKeyTrg)
 			break;
 		
 		if (!Flip_SystemTask())
--- a/src/ArmsItem.h
+++ b/src/ArmsItem.h
@@ -26,7 +26,7 @@
 extern int gSelectedArms;
 extern int gSelectedItem;
 extern int gCampTitleY;
-extern int gCampActive;
+extern bool gCampActive;
 
 void ClearArmsData();
 void ClearItemData();
--- a/src/Flags.h
+++ b/src/Flags.h
@@ -1,4 +1,8 @@
 #pragma once
+#include <stdint.h>
+extern uint8_t gFlagNPC[1000];
+extern uint8_t gSkipFlag[0x40];
+
 void InitFlags();
 void InitSkipFlags();
 void SetNPCFlag(int a);
--- a/src/Game.cpp
+++ b/src/Game.cpp
@@ -8,6 +8,7 @@
 #include "NpcTbl.h"
 #include "NpChar.h"
 #include "NpcHit.h"
+#include "MiniMap.h"
 #include "Generic.h"
 #include "GenericLoad.h"
 #include "ArmsItem.h"
@@ -108,7 +109,7 @@
 	grcGame.left = 0;
 	g_GameFlags = 3;
 	
-	//CutNoise();
+	CutNoise();
 	
 	int wait = 0;
 	while (wait < 500)
@@ -238,7 +239,7 @@
 	//Reset everything
 	InitCaret();
 	//InitStar();
-	//CutNoise();
+	CutNoise();
 	
 	//Create variables
 	int anime = 0;
@@ -527,19 +528,19 @@
 						return 0;
 					if (campRet == 2)
 						return 1;
+					
 					gMC.cond &= ~1;
 				}
-				/*
-				else if ( unk_81C8598 & 2 && gKeyTrg & gKeyMap )
+				else if (gMC.equip & 2 && gKeyTrg & gKeyMap)
 				{
-				BackupSurface(10, &grcGame);
-				v3 = MiniMapLoop();
-				if ( !v3 )
-				return 0;
-				if ( v3 == 2 )
-				return 1;
+					BackupSurface(10, &grcGame);
+					
+					int miniRet = MiniMapLoop();
+					if (miniRet == 0)
+						return 0;
+					if (miniRet == 2)
+						return 1;
 				}
-				*/
 			}
 			
 			if (g_GameFlags & 2)
--- a/src/Main.cpp
+++ b/src/Main.cpp
@@ -13,6 +13,7 @@
 #include "Sound.h"
 #include "Game.h"
 #include "Generic.h"
+#include "MyChar.h"
 #include "Main.h"
 #include "Config.h"
 #include "KeyControl.h"
@@ -312,7 +313,7 @@
 	{
 		bActive = false;
 		StopOrganyaMusic();
-		//SleepNoise();
+		SleepNoise();
 	}
 	
 	PlaySoundObject(7, 0);
@@ -325,7 +326,7 @@
 		bActive = true;
 		StopOrganyaMusic();
 		PlayOrganyaMusic();
-		//ResetNoise();
+		ResetNoise();
 	}
 
 	PlaySoundObject(7, -1);
--- /dev/null
+++ b/src/MiniMap.cpp
@@ -1,0 +1,176 @@
+#include "WindowsWrapper.h"
+
+#include "CommonDefines.h"
+#include "MapName.h"
+#include "Draw.h"
+#include "Escape.h"
+#include "Game.h"
+#include "KeyControl.h"
+#include "Map.h"
+#include "MyChar.h"
+#include "Main.h"
+
+void WriteMiniMapLine(int line)
+{
+	RECT rcLevel[4];
+	rcLevel[0] = {240, 24, 241, 25};
+	rcLevel[1] = {241, 24, 242, 25};
+	rcLevel[2] = {242, 24, 243, 25};
+	rcLevel[3] = {243, 24, 244, 25};
+	
+	for (int x = 0; x < gMap.width; x++)
+	{
+		uint8_t a = GetAttribute(x, line);
+		
+		printf("x: %d y: %d a: %d\n", x, line, a);
+		
+		switch (a)
+		{
+			case 0:
+				Surface2Surface(x, line, &rcLevel[0], 9, 26);
+				break;
+				
+			case 68:
+			case 1:
+			case 64:
+			case 128:
+			case 129:
+			case 130:
+			case 131:
+			case 81:
+			case 82:
+			case 85:
+			case 86:
+			case 2:
+			case 96:
+			case 113:
+			case 114:
+			case 117:
+			case 118:
+			case 160:
+			case 161:
+			case 162:
+			case 163:
+				Surface2Surface(x, line, &rcLevel[1], 9, 26);
+				break;
+				
+			case 67:
+			case 99:
+			case 80:
+			case 83:
+			case 84:
+			case 87:
+			case 112:
+			case 115:
+			case 116:
+			case 119:
+				Surface2Surface(x, line, &rcLevel[2], 9, 26);
+				break;
+				
+			default:
+				Surface2Surface(x, line, &rcLevel[3], 9, 26);
+				break;
+		}
+	}
+	return;
+}
+
+int MiniMapLoop()
+{
+	RECT my_rect = {0, 57, 1, 58};
+	int my_x = (gMC.x / 0x200 + 8) / 16;
+	int my_y = (gMC.y / 0x200 + 8) / 16;
+	
+	RECT rcView;
+	for (int f = 0; f <= 8; f++)
+	{
+		GetTrg();
+		
+		if (gKey & KEY_ESCAPE)
+		{
+			int escRet = Call_Escape();
+			if (escRet == 0)
+				return 0;
+			if (escRet == 2)
+				return 2;
+		}
+		
+		PutBitmap4(&grcGame, 0, 0, &grcGame, 10);
+		
+		rcView = {(WINDOW_WIDTH / 2) - f * gMap.width / 16, (WINDOW_HEIGHT / 2) - f * gMap.length / 16, (WINDOW_WIDTH / 2) + f * gMap.width / 16, (WINDOW_HEIGHT / 2) + f * gMap.length / 16};
+		PutMapName(true);
+		CortBox(&rcView, 0);
+		
+		PutFramePerSecound();
+		if (!Flip_SystemTask())
+		return 0;
+	}
+	
+	RECT rcMiniMap = {0, gMap.width, 0, gMap.length};
+	rcView.right = --rcView.left + gMap.width + 2;
+	rcView.bottom = --rcView.top + gMap.length + 2;
+	CortBox2(&rcMiniMap, 0, 9);
+	
+	int line = 0;
+	uint8_t my_wait = 0;
+	while (true)
+	{
+		GetTrg();
+		
+		if ((gKeyCancel | gKeyOk) & gKeyTrg)
+			break;
+		
+		if (gKey & KEY_ESCAPE)
+		{
+			int escRet = Call_Escape();
+			if (escRet == 0)
+				return 0;
+			if (escRet == 2)
+				return 2;
+		}
+		
+		PutBitmap4(&grcGame, 0, 0, &grcGame, 10);
+		CortBox(&rcView, 0);
+		
+		if (gMap.length > line)
+			WriteMiniMapLine(line++);
+		if (gMap.length > line)
+			WriteMiniMapLine(line++);
+		PutBitmap3(&grcGame, rcView.left + 1, rcView.top + 1, &rcMiniMap, 9);
+		
+		PutMapName(true);
+		
+		if ((++my_wait >> 3) & 1)
+			PutBitmap3(&grcGame, my_x + rcView.left + 1, my_y + rcView.top + 1, &my_rect, 26);
+		
+		PutFramePerSecound();
+		if (!Flip_SystemTask())
+			return 0;
+	}
+	/*
+	for ( f = 8; f >= -1; --f )
+	{
+	GetTrg();
+	if ( gKey & 0x8000 )
+	{
+	v3 = Call_Escape(gscreen);
+	if ( !v3 )
+	return 0;
+	if ( v3 == 2 )
+	return 2;
+	}
+	PutBitmap4(&grcGame, 0, 0, &grcGame, 10);
+	rcView.left = 160 - f * gMap.width / 16;
+	rcView.right = f * gMap.width / 16 + 160;
+	rcView.top = 120 - f * gMap.length / 16;
+	rcView.bottom = f * gMap.length / 16 + 120;
+	PutMapName(1);
+	CortBox(&rcView, 0);
+	PutFramePerSecound();
+	if ( !Flip_SystemTask(gscreen) )
+	return 0;
+	}
+	*/
+	
+	return 1;
+}
\ No newline at end of file
--- /dev/null
+++ b/src/MiniMap.h
@@ -1,0 +1,2 @@
+#pragma once
+int MiniMapLoop();
--- a/src/MyChar.cpp
+++ b/src/MyChar.cpp
@@ -18,6 +18,9 @@
 
 MYCHAR gMC;
 
+int noise_no;
+unsigned int noise_freq;
+
 void InitMyChar()
 {
 	memset(&gMC, 0, sizeof(MYCHAR));
@@ -569,7 +572,7 @@
 				if (gMC.xm > 0x200 || gMC.xm < -0x200)
 				{
 					for (int a = 0; a < 8; a++)
-						SetNpChar(73, gMC.x + (Random(-8, 8) << 9), gMC.y, gMC.xm + Random(-0x200, 0x200), gMC.ym + Random(-0x200, 0x80), dir, 0, 0);
+						SetNpChar(73, gMC.x + (Random(-8, 8) << 9), gMC.y, gMC.xm + Random(-0x200, 0x200), Random(-0x200, 0x80), dir, 0, 0);
 					
 					PlaySoundObject(56, 1);
 				}
@@ -745,3 +748,119 @@
 	gMC.x = x;
 	gMC.y = y;
 }
+
+void ZeroMyCharXMove()
+{
+  gMC.xm = 0;
+}
+
+int GetUnitMyChar()
+{
+	return gMC.unit;
+}
+
+void SetMyCharDirect(uint8_t dir)
+{
+	switch (dir)
+	{
+		case 3:
+			gMC.cond |= 1;
+			break;
+			
+		default:
+			gMC.cond &= ~1;
+			
+			if (dir < 10)
+			{
+				gMC.direct = dir;
+				break;
+			}
+			
+			for (int i = 0; i < NPC_MAX; i++)
+			{
+				if (gNPC[i].code_event == dir)
+				{
+					if (gMC.x <= gNPC[i].x)
+						gMC.direct = 2;
+					else
+						gMC.direct = 0;
+					break;
+				}
+			}
+			break;
+	}
+	
+	gMC.xm = 0;
+	AnimationMyChar(false);
+}
+
+void ChangeMyUnit(uint8_t a)
+{
+	gMC.unit = a;
+}
+
+void PitMyChar()
+{
+	gMC.y += 0x4000;
+}
+
+void EquipItem(int flag, bool b)
+{
+	if (b)
+		gMC.equip |= flag;
+	else
+		gMC.equip &= ~flag;
+}
+
+void ResetCheck()
+{
+	gMC.cond &= ~1;
+}
+
+void SetNoise(int no, int freq)
+{
+	noise_freq = freq;
+	noise_no = no;
+	
+	if (no == 1)
+	{
+		ChangeSoundFrequency(40, noise_freq);
+		ChangeSoundFrequency(41, noise_freq + 100);
+		PlaySoundObject(40, -1);
+		PlaySoundObject(41, -1);
+	}
+	else if (no == 2)
+	{
+		PlaySoundObject(58, -1);
+	}
+}
+
+void CutNoise()
+{
+	noise_no = 0;
+	PlaySoundObject(40, 0);
+	PlaySoundObject(41, 0);
+	PlaySoundObject(58, 0);
+}
+
+void ResetNoise()
+{
+	if (noise_no == 1)
+	{
+		ChangeSoundFrequency(40, noise_freq);
+		ChangeSoundFrequency(41, noise_freq + 100);
+		PlaySoundObject(40, -1);
+		PlaySoundObject(41, -1);
+	}
+	else if (noise_no == 2)
+	{
+		PlaySoundObject(58, -1);
+	}
+}
+
+void SleepNoise()
+{
+	PlaySoundObject(40, 0);
+	PlaySoundObject(41, 0);
+	PlaySoundObject(58, 0);
+}
\ No newline at end of file
--- a/src/MyChar.h
+++ b/src/MyChar.h
@@ -57,3 +57,14 @@
 void GetMyCharPosition(int *x, int *y);
 void SetMyCharPosition(int x, int y);
 void MoveMyChar(int x, int y);
+void ZeroMyCharXMove();
+int GetUnitMyChar();
+void SetMyCharDirect(uint8_t dir);
+void ChangeMyUnit(uint8_t a);
+void PitMyChar();
+void EquipItem(int flag, bool b);
+void ResetCheck();
+void SetNoise(int no, int freq);
+void CutNoise();
+void ResetNoise();
+void SleepNoise();
--- a/src/MycHit.cpp
+++ b/src/MycHit.cpp
@@ -770,7 +770,7 @@
 				if (hit && gNPC[i].code_char == 1)
 				{
 					PlaySoundObject(14, 1);
-					//AddExpMyChar(gNPC[i].exp);
+					AddExpMyChar(gNPC[i].exp);
 					gNPC[i].cond = 0;
 				}
 				
--- a/src/MycParam.cpp
+++ b/src/MycParam.cpp
@@ -141,6 +141,42 @@
 	}
 }
 
+void ZeroArmsEnergy_All()
+{
+	for (int a = 0; a < ARMS_MAX; a++)
+	{
+		gArmsData[a].level = 1;
+		gArmsData[a].exp = 0;
+	}
+}
+
+void AddBulletMyChar(int no, int val)
+{
+	//Missile Launcher
+	for (int a = 0; a < ARMS_MAX; a++)
+	{
+		if (gArmsData[a].code == 5)
+		{
+			gArmsData[a].num += val;
+			if (gArmsData[a].num > gArmsData[a].max_num)
+				gArmsData[a].num = gArmsData[a].max_num;
+			break;
+		}
+	}
+	
+	//Super Missile Launcher
+	for (int a = 0; a < ARMS_MAX; a++)
+	{
+		if (gArmsData[a].code == 10)
+		{
+			gArmsData[a].num += val;
+			if (gArmsData[a].num > gArmsData[a].max_num)
+				gArmsData[a].num = gArmsData[a].max_num;
+			break;
+		}
+	}
+}
+
 void AddLifeMyChar(int x)
 {
 	gMC.life += x;
--- a/src/MycParam.h
+++ b/src/MycParam.h
@@ -6,7 +6,12 @@
 
 extern ARMS_LEVEL gArmsLevelTable[14];
 
+void AddExpMyChar(int x);
+void ZeroExpMyChar();
+bool IsMaxExpMyChar();
 void DamageMyChar(int damage);
+void ZeroArmsEnergy_All();
+void AddBulletMyChar(int no, int val);
 void AddLifeMyChar(int x);
 void AddMaxLifeMyChar(int val);
 void PutArmsEnergy(bool flash);
--- a/src/NpChar.cpp
+++ b/src/NpChar.cpp
@@ -6,6 +6,7 @@
 #include "CommonDefines.h"
 #include "Tags.h"
 #include "NpChar.h"
+#include "Caret.h"
 #include "MyChar.h"
 #include "Game.h"
 #include "Flags.h"
@@ -148,7 +149,7 @@
 	}
 
 	//Flash effect
-	//SetCaret(x, y, 12, 0);
+	SetCaret(x, y, 12, 0);
 }
 
 void SetDestroyNpCharUp(int x, int y, int w, int num)
@@ -163,7 +164,7 @@
 	}
 
 	//Flash effect
-	//SetCaret(x, y, 12, 0);
+	SetCaret(x, y, 12, 0);
 }
 
 void SetExpObjects(int x, int y, int exp)
--- a/src/Profile.cpp
+++ b/src/Profile.cpp
@@ -38,7 +38,104 @@
 
 bool LoadProfile(char *name)
 {
-	return false;
+	char path[PATH_LENGTH];
+	
+	//Get path
+	if (name)
+		strcpy(path, name);
+	else
+		sprintf(path, "%s/%s", gModulePath, gDefaultName);
+	
+	//Open file
+	PROFILE profile;
+	
+	SDL_RWops *fp = SDL_RWFromFile(path, "rb");
+	if (!fp)
+		return false;
+	
+	//Check header code
+	SDL_RWread(fp, profile.code, 8, 1);
+	if (memcmp(profile.code, gProfileCode, 8))
+		return false;
+	
+	//Read data
+	SDL_RWseek(fp, 0, RW_SEEK_SET); //Pixel epic redundant code 😎😎😎
+	SDL_RWread(fp, profile.code, 8, 1);
+	profile.stage = SDL_ReadLE32(fp);
+	profile.music = SDL_ReadLE32(fp);
+	profile.x = SDL_ReadLE32(fp);
+	profile.y = SDL_ReadLE32(fp);
+	profile.direct = SDL_ReadLE32(fp);
+	profile.max_life = SDL_ReadLE16(fp);
+	profile.star = SDL_ReadLE16(fp);
+	profile.life = SDL_ReadLE16(fp);
+	profile.a = SDL_ReadLE16(fp);
+	profile.select_arms = SDL_ReadLE32(fp);
+	profile.select_item = SDL_ReadLE32(fp);
+	profile.equip = SDL_ReadLE32(fp);
+	profile.unit = SDL_ReadLE32(fp);
+	profile.counter = SDL_ReadLE32(fp);
+	for (int arm = 0; arm < 8; arm++)
+	{
+		profile.arms[arm].code = SDL_ReadLE32(fp);
+		profile.arms[arm].level = SDL_ReadLE32(fp);
+		profile.arms[arm].exp = SDL_ReadLE32(fp);
+		profile.arms[arm].max_num = SDL_ReadLE32(fp);
+		profile.arms[arm].num = SDL_ReadLE32(fp);
+	}
+	for (int item = 0; item < 32; item++)
+		profile.items[item].code = SDL_ReadLE32(fp);
+	SDL_RWread(fp, profile.permitstage, 8, 8);
+	SDL_RWread(fp, profile.permit_mapping, 0x80, 1);
+	SDL_RWread(fp, profile.FLAG, 4, 1);
+	SDL_RWread(fp, profile.flags, 1000, 1);
+	SDL_RWclose(fp);
+	
+	//Set things
+	gSelectedArms = profile.select_arms;
+	gSelectedItem = profile.select_item;
+	gCounter = profile.counter;
+
+	memcpy(gArmsData, profile.arms, sizeof(gArmsData));
+	memcpy(gItemData, profile.items, sizeof(gItemData));
+	//memcpy(gPermitStage, profile.permitstage, 0x40u);
+	//memcpy(gMapping, profile.permit_mapping, 0x80u);
+	memcpy(gFlagNPC, profile.flags, 1000);
+	
+	//Load stage
+	ChangeMusic(profile.music);
+	InitMyChar();
+	if (!TransferStage(profile.stage, 0, 0, 1))
+		return false;
+	
+	//Set character properties
+	gMC.equip = profile.equip;
+	gMC.unit = profile.unit;
+	gMC.direct = profile.direct;
+	gMC.max_life = profile.max_life;
+	gMC.life = profile.life;
+	gMC.star = profile.star;
+	gMC.cond = 0x80;
+	gMC.air = 1000;
+	gMC.lifeBr = profile.life;
+	gMC.x = profile.x;
+	gMC.y = profile.y;
+	
+	gMC.rect_arms.left = 24 * (gArmsData[gSelectedArms].code % 10);
+	gMC.rect_arms.right = gMC.rect_arms.left + 24;
+	gMC.rect_arms.top = 32 * (gArmsData[gSelectedArms].code / 10);
+	gMC.rect_arms.bottom = gMC.rect_arms.top + 16;
+	
+	//Reset stuff
+	ClearFade();
+	SetFrameMyChar();
+	SetFrameTargetMyChar(16);
+	//InitBossLife();
+	CutNoise();
+	//InitStar();
+	ClearValueView();
+	//gCurlyShoot_wait = 0;
+	return true;
 }
 
 bool InitializeGame()
@@ -58,7 +155,7 @@
 	SetFrameMyChar();
 	SetFrameTargetMyChar(16);
 	//InitBossLife();
-	//CutNoise();
+	CutNoise();
 	ClearValueView();
 	//gCurlyShoot_wait = 0;
 	SetFadeMask();
--- a/src/Profile.h
+++ b/src/Profile.h
@@ -1,5 +1,31 @@
 #pragma once
 #include <stdint.h>
+#include "ArmsItem.h"
+
+struct PROFILE
+{
+	char code[8];
+	int stage;
+	int music;
+	int x;
+	int y;
+	int direct;
+	int16_t max_life;
+	int16_t star;
+	int16_t life;
+	int16_t a;
+	int select_arms;
+	int select_item;
+	int equip;
+	int unit;
+	int counter;
+	ARMS arms[8];
+	ITEM items[32];
+	char permitstage[8][8];
+	char permit_mapping[0x80];
+	char FLAG[4];
+	uint8_t flags[1000];
+};
 
 bool IsProfile();
 bool SaveProfile(char *name);
--- a/src/TextScr.cpp
+++ b/src/TextScr.cpp
@@ -638,6 +638,18 @@
 						SubItemData(z);
 						gTS.p_read += 8;
 					}
+					else if (IS_COMMAND('E','Q','+'))
+					{
+						z = GetTextScriptNo(gTS.p_read + 4);
+						EquipItem(z, true);
+						gTS.p_read += 8;
+					}
+					else if (IS_COMMAND('E','Q','-'))
+					{
+						z = GetTextScriptNo(gTS.p_read + 4);
+						EquipItem(z, false);
+						gTS.p_read += 8;
+					}
 					else if (IS_COMMAND('A','M','+'))
 					{
 						w = GetTextScriptNo(gTS.p_read + 4);
--