Made NpChar.cpp almost ASM-accurate

For some damn reason I can't replicate SetBulletObject stack frame
layout.
This commit is contained in:
Clownacy 2019-05-12 23:46:16 +01:00
parent a711b34de7
commit fb87b8dd57
3 changed files with 354 additions and 235 deletions

View file

@ -2202,6 +2202,98 @@ addr = 0x46E9E0
name = "ActNpc360"
addr = 0x46EA90
[[func]]
name = "InitNpChar"
addr = 0x46EB30
[[func]]
name = "LoadEvent"
addr = 0x46EB50
[[func]]
name = "SetUniqueParameter"
addr = 0x46EE50
[[func]]
name = "SetNpChar"
addr = 0x46EFD0
[[func]]
name = "SetDestroyNpChar"
addr = 0x46F150
[[func]]
name = "SetDestroyNpCharUp"
addr = 0x46F200
[[func]]
name = "SetExpObjects"
addr = 0x46F2B0
[[func]]
name = "SetBulletObject"
addr = 0x46F430
[[func]]
name = "SetLifeObject"
addr = 0x46F630
[[func]]
name = "VanishNpChar"
addr = 0x46F760
[[func]]
name = "PutNpChar"
addr = 0x46F810
[[func]]
name = "ActNpChar"
addr = 0x46FA00
[[func]]
name = "ChangeNpCharByEvent"
addr = 0x46FAB0
[[func]]
name = "ChangeCheckableNpCharByEvent"
addr = 0x46FD10
[[func]]
name = "SetNpCharActionNo"
addr = 0x46FF90
[[func]]
name = "MoveNpChar"
addr = 0x470060
[[func]]
name = "BackStepMyChar"
addr = 0x470150
[[func]]
name = "DeleteNpCharEvent"
addr = 0x470250
[[func]]
name = "DeleteNpCharCode"
addr = 0x4702D0
[[func]]
name = "GetNpCharPosition"
addr = 0x470460
[[func]]
name = "IsNpCharCode"
addr = 0x470490
[[func]]
name = "GetNpCharAlive"
addr = 0x4704F0
[[func]]
name = "CountAliveNpChar"
addr = 0x470560
[[func]]
name = "LoadNpcTable"
addr = 0x472400

View file

@ -27,7 +27,7 @@ int gCurlyShoot_y;
int gSuperXpos;
int gSuperYpos;
const char *gPassPixEve = "PXE\0";
const char *gPassPixEve = "PXE";
void InitNpChar()
{
@ -55,10 +55,16 @@ void SetUniqueParameter(NPCHAR *npc)
BOOL LoadEvent(const char *path_event)
{
FILE *fp;
int count;
int i;
int n;
EVENT eve;
char path[PATH_LENGTH];
sprintf(path, "%s/%s", gDataPath, path_event);
FILE *fp = fopen(path, "rb");
fp = fopen(path, "rb");
if (fp == NULL)
return FALSE;
@ -75,33 +81,37 @@ BOOL LoadEvent(const char *path_event)
}
//Get amount of NPCs
int count = File_ReadLE32(fp);
#ifdef NONPORTABLE
fread(&count, 4, 1, fp);
#else
count = File_ReadLE32(fp);
#endif
//Load NPCs
memset(gNPC, 0, sizeof(gNPC));
int n = 170;
for (int i = 0; i < count; i++)
n = 170;
for (i = 0; i < count; i++)
{
//Get data from file
EVENT eve;
#ifdef NONPORTABLE
fread(&eve, sizeof(EVENT), 1, fp);
#else
eve.x = File_ReadLE16(fp);
eve.y = File_ReadLE16(fp);
eve.code_flag = File_ReadLE16(fp);
eve.code_event = File_ReadLE16(fp);
eve.code_char = File_ReadLE16(fp);
eve.bits = File_ReadLE16(fp);
#endif
//Set NPC parameters
if (eve.bits & npc_altDir)
gNPC[n].direct = 2;
else
gNPC[n].direct = 0;
gNPC[n].direct = (eve.bits & npc_altDir) ? 2 : 0;
gNPC[n].code_char = eve.code_char;
gNPC[n].code_event = eve.code_event;
gNPC[n].code_flag = eve.code_flag;
gNPC[n].x = eve.x << 13;
gNPC[n].y = eve.y << 13;
gNPC[n].x = eve.x * 0x10 * 0x200;
gNPC[n].y = eve.y * 0x10 * 0x200;
gNPC[n].bits = eve.bits;
gNPC[n].bits |= gNpcTable[gNPC[n].code_char].bits;
gNPC[n].exp = gNpcTable[gNPC[n].code_char].exp;
@ -110,13 +120,13 @@ BOOL LoadEvent(const char *path_event)
//Check flags
if (gNPC[n].bits & npc_appearSet)
{
if (GetNPCFlag(gNPC[n].code_flag))
gNPC[n].cond |= 0x80u;
if (GetNPCFlag(gNPC[n].code_flag) == TRUE)
gNPC[n].cond |= 0x80;
}
else if (gNPC[n].bits & npc_hideSet)
{
if (!GetNPCFlag(gNPC[n].code_flag))
gNPC[n].cond |= 0x80u;
if (GetNPCFlag(gNPC[n].code_flag) == FALSE)
gNPC[n].cond |= 0x80;
}
else
{
@ -133,10 +143,13 @@ BOOL LoadEvent(const char *path_event)
void SetNpChar(int code_char, int x, int y, int xm, int ym, int dir, NPCHAR *npc, int start_index)
{
for (int n = start_index; n < NPC_MAX; n++)
{
if (!gNPC[n].cond)
{
int n = start_index;
while (n < NPC_MAX && gNPC[n].cond)
++n;
if (n == NPC_MAX)
return;
//Set NPC parameters
memset(&gNPC[n], 0, sizeof(NPCHAR));
gNPC[n].cond |= 0x80u;
@ -150,20 +163,17 @@ void SetNpChar(int code_char, int x, int y, int xm, int ym, int dir, NPCHAR *npc
gNPC[n].bits = gNpcTable[gNPC[n].code_char].bits;
gNPC[n].exp = gNpcTable[gNPC[n].code_char].exp;
SetUniqueParameter(&gNPC[n]);
break;
}
}
}
void SetDestroyNpChar(int x, int y, int w, int num)
{
//Create smoke
int wa = w / 0x200;
w /= 0x200;
for (int i = 0; i < num; i++)
{
int offset_x = Random(-wa, wa) << 9;
int offset_y = Random(-wa, wa) << 9;
SetNpChar(4, x + offset_x, offset_y + y, 0, 0, 0, NULL, 0x100);
int offset_x = Random(-w, w) * 0x200;
int offset_y = Random(-w, w) * 0x200;
SetNpChar(4, x + offset_x, y + offset_y, 0, 0, 0, NULL, 0x100);
}
//Flash effect
@ -173,12 +183,12 @@ void SetDestroyNpChar(int x, int y, int w, int num)
void SetDestroyNpCharUp(int x, int y, int w, int num)
{
//Create smoke
int wa = w / 0x200;
w /= 0x200;
for (int i = 0; i < num; i++)
{
int offset_x = Random(-wa, wa) << 9;
int offset_y = Random(-wa, wa) << 9;
SetNpChar(4, x + offset_x, offset_y + y, 0, 0, 1, NULL, 0x100);
int offset_x = Random(-w, w) * 0x200;
int offset_y = Random(-w, w) * 0x200;
SetNpChar(4, x + offset_x, y + offset_y, 0, 0, 1, NULL, 0x100);
}
//Flash effect
@ -188,82 +198,84 @@ void SetDestroyNpCharUp(int x, int y, int w, int num)
void SetExpObjects(int x, int y, int exp)
{
int sub_exp;
for (int n = 0x100; exp; SetUniqueParameter(&gNPC[n]))
int n = 0x100;
while (exp)
{
while (true)
{
bool v3 = n < NPC_MAX && gNPC[n].cond;
if (!v3)
break;
while (n < NPC_MAX && gNPC[n].cond)
++n;
}
if (n == NPC_MAX)
break;
memset(&gNPC[n], 0, sizeof(NPCHAR));
if (exp < 20)
{
if (exp < 5)
{
if (exp > 0)
{
--exp;
sub_exp = 1;
}
}
else
{
exp -= 5;
sub_exp = 5;
}
}
else
if (exp >= 20)
{
exp -= 20;
sub_exp = 20;
}
else if (exp >= 5)
{
exp -= 5;
sub_exp = 5;
}
else if (exp >= 1)
{
exp -= 1;
sub_exp = 1;
}
gNPC[n].cond |= 0x80u;
gNPC[n].cond |= 0x80;
gNPC[n].direct = 0;
gNPC[n].code_char = 1;
gNPC[n].x = x;
gNPC[n].y = y;
gNPC[n].bits = gNpcTable[gNPC[n].code_char].bits;
gNPC[n].exp = sub_exp;
SetUniqueParameter(&gNPC[n]);
}
}
BOOL SetBulletObject(int x, int y, int val)
{
int t;
int tamakazu_ari[10];
int n;
int t = 0;
int bullet_no;
t = 0;
memset(tamakazu_ari, 0, sizeof(tamakazu_ari));
for (n = 0; n < 8; n++)
for (n = 0; n < 8; ++n)
{
int code = gArmsData[n].code;
if (code == 5)
switch (gArmsData[n].code)
{
case 5:
tamakazu_ari[t++] = 0;
else if (code == 10)
break;
case 10:
tamakazu_ari[t++] = 1;
else
break;
default:
tamakazu_ari[t] = 0;
break;
}
}
if (!t)
if (t == 0)
return FALSE;
n = Random(1, 10 * t);
int bullet_no = tamakazu_ari[n % t];
for (n = 0x100; n < NPC_MAX; n++)
{
if (!gNPC[n].cond)
{
bullet_no = tamakazu_ari[n % t];
n = 0x100;
while (n < NPC_MAX && gNPC[n].cond)
++n;
if (n == NPC_MAX)
return FALSE;
memset(&gNPC[n], 0, sizeof(NPCHAR));
gNPC[n].cond |= 0x80u;
gNPC[n].cond |= 0x80;
gNPC[n].direct = 0;
gNPC[n].code_event = bullet_no;
gNPC[n].code_char = 86;
@ -273,18 +285,17 @@ BOOL SetBulletObject(int x, int y, int val)
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)
{
int n = 0x100;
while (n < NPC_MAX && gNPC[n].cond)
++n;
if (n == NPC_MAX)
return FALSE;
memset(&gNPC[n], 0, sizeof(NPCHAR));
gNPC[n].cond |= 0x80u;
gNPC[n].direct = 0;
@ -295,10 +306,6 @@ BOOL SetLifeObject(int x, int y, int val)
gNPC[n].exp = val;
SetUniqueParameter(&gNPC[n]);
return TRUE;
}
}
return FALSE;
}
void VanishNpChar(NPCHAR *npc)
@ -309,7 +316,7 @@ void VanishNpChar(NPCHAR *npc)
npc->count1 = 0;
npc->x = x;
npc->y = y;
npc->cond |= 0x80u;
npc->cond |= 0x80;
npc->direct = 0;
npc->code_char = 3;
npc->bits = gNpcTable[npc->code_char].bits;
@ -319,15 +326,15 @@ void VanishNpChar(NPCHAR *npc)
void PutNpChar(int fx, int fy)
{
for (int n = 0; n < NPC_MAX; n++)
signed char a = 0;
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;
a = 2 * ((gNPC[n].shock / 2) % 2) - 1;
}
else
{
@ -340,10 +347,10 @@ void PutNpChar(int fx, int fy)
}
int side;
if (gNPC[n].direct)
side = gNPC[n].view.back;
else
if (gNPC[n].direct == 0)
side = gNPC[n].view.front;
else
side = gNPC[n].view.back;
PutBitmap3(
&grcGame,
@ -357,11 +364,13 @@ void PutNpChar(int fx, int fy)
void ActNpChar()
{
for (int i = 0; i < NPC_MAX; i++)
for (int i = 0; i < NPC_MAX; ++i)
{
if (gNPC[i].cond & 0x80)
{
gpNpcFuncTbl[gNPC[i].code_char](&gNPC[i]);
int code_char = gNPC[i].code_char;
gpNpcFuncTbl[code_char](&gNPC[i]);
if (gNPC[i].shock)
--gNPC[i].shock;
@ -373,14 +382,14 @@ void ChangeNpCharByEvent(int code_event, int code_char, int dir)
{
for (int n = 0; n < NPC_MAX; n++)
{
if ((gNPC[n].cond & 0x80u) && gNPC[n].code_event == code_event)
if ((gNPC[n].cond & 0x80) && gNPC[n].code_event == code_event)
{
gNPC[n].bits &= (npc_eventTouch | npc_eventDie | 0x400 | npc_appearSet | npc_altDir | npc_interact | npc_hideSet);
gNPC[n].code_char = code_char;
gNPC[n].bits |= gNpcTable[gNPC[n].code_char].bits;
gNPC[n].exp = gNpcTable[gNPC[n].code_char].exp;
SetUniqueParameter(&gNPC[n]);
gNPC[n].cond |= 0x80u;
gNPC[n].cond |= 0x80;
gNPC[n].act_no = 0;
gNPC[n].act_wait = 0;
gNPC[n].count1 = 0;
@ -390,20 +399,21 @@ void ChangeNpCharByEvent(int code_event, int code_char, int dir)
gNPC[n].xm = 0;
gNPC[n].ym = 0;
if (dir != 5)
if (dir == 5)
{
if (dir == 4)
// Another empty case that has to exist for the same assembly to be generated
}
else if (dir == 4)
{
if (gNPC[n].x >= gMC.x)
gNPC[n].direct = 0;
else
if (gNPC[n].x < gMC.x)
gNPC[n].direct = 2;
else
gNPC[n].direct = 0;
}
else
{
gNPC[n].direct = dir;
}
}
gpNpcFuncTbl[code_char](&gNPC[n]);
}
@ -414,15 +424,15 @@ void ChangeCheckableNpCharByEvent(int code_event, int code_char, int dir)
{
for (int n = 0; n < NPC_MAX; n++)
{
if ((gNPC[n].cond & 0x80u) != 0 && gNPC[n].code_event == code_event)
if ((gNPC[n].cond & 0x80) != 0 && gNPC[n].code_event == code_event)
{
gNPC[n].bits &= (npc_eventTouch | npc_eventDie | 0x400 | npc_appearSet | npc_altDir | npc_interact | npc_hideSet);
gNPC[n].bits &= ~(npc_showDamage | npc_rearTop | npc_solidHard | npc_shootable | npc_bouncy | npc_ignoreSolid | npc_invulnerable | npc_ignore44 | npc_solidSoft);
gNPC[n].bits |= npc_interact;
gNPC[n].code_char = code_char;
gNPC[n].bits |= gNpcTable[gNPC[n].code_char].bits;
gNPC[n].exp = gNpcTable[gNPC[n].code_char].exp;
SetUniqueParameter(&gNPC[n]);
gNPC[n].cond |= 0x80u;
gNPC[n].cond |= 0x80;
gNPC[n].act_no = 0;
gNPC[n].act_wait = 0;
gNPC[n].count1 = 0;
@ -432,19 +442,20 @@ void ChangeCheckableNpCharByEvent(int code_event, int code_char, int dir)
gNPC[n].xm = 0;
gNPC[n].ym = 0;
if (dir != 5)
if (dir == 5)
{
if (dir == 4)
// Another empty case that has to exist for the same assembly to be generated
}
else if (dir == 4)
{
if (gNPC[n].x >= gMC.x)
gNPC[n].direct = 0;
else
if (gNPC[n].x < gMC.x)
gNPC[n].direct = 2;
else
gNPC[n].direct = 0;
}
else
{
gNPC[n].direct = dir;
}
gNPC[n].direct = (signed char)dir;
}
gpNpcFuncTbl[code_char](&gNPC[n]);
@ -454,95 +465,111 @@ void ChangeCheckableNpCharByEvent(int code_event, int code_char, int dir)
void SetNpCharActionNo(int code_event, int act_no, int dir)
{
for (int n = 0; n < NPC_MAX; n++)
int n = 0;
while (n < NPC_MAX)
{
if ((gNPC[n].cond & 0x80) && gNPC[n].code_event == code_event)
{
break;
++n;
}
if (n == NPC_MAX)
return;
gNPC[n].act_no = act_no;
if (dir != 5)
if (dir == 5)
{
if (dir == 4)
// Another empty case that has to exist for the same assembly to be generated
}
else if (dir == 4)
{
if (gNPC[n].x >= gMC.x)
gNPC[n].direct = 0;
else
if (gNPC[n].x < gMC.x)
gNPC[n].direct = 2;
else
gNPC[n].direct = 0;
}
else
{
gNPC[n].direct = dir;
}
}
break;
}
}
}
void MoveNpChar(int code_event, int x, int y, int dir)
{
for (int n = 0; n < NPC_MAX; n++)
int n = 0;
while (n < NPC_MAX)
{
if ((gNPC[n].cond & 0x80) && gNPC[n].code_event == code_event)
{
break;
++n;
}
if (n == NPC_MAX)
return;
gNPC[n].x = x;
gNPC[n].y = y;
if (dir != 5)
if (dir == 5)
{
if (dir == 4)
// Another empty case that has to exist for the same assembly to be generated
}
else if (dir == 4)
{
if (gNPC[n].x >= gMC.x)
gNPC[n].direct = 0;
else
if (gNPC[n].x < gMC.x)
gNPC[n].direct = 2;
else
gNPC[n].direct = 0;
}
else
{
gNPC[n].direct = dir;
}
}
break;
}
gNPC[n].direct = (signed char)dir;
}
}
void BackStepMyChar(int code_event)
{
int n = 0;
gMC.cond &= ~1;
gMC.ym = -0x200;
if (code_event)
if (code_event == 0)
{
if (code_event == 2)
gMC.direct = 0;
gMC.xm = 0x200;
}
else if (code_event == 2)
{
gMC.direct = 2;
gMC.xm = -0x200;
}
else
{
for (int n = 0; n < NPC_MAX; n++)
while (n < NPC_MAX)
{
if ((gNPC[n].cond & 0x80) && gNPC[n].code_event == code_event)
break;
++n;
}
if (n == NPC_MAX)
return;
if (gNPC[n].x < gMC.x)
{
if (gNPC[n].x >= gMC.x)
gMC.direct = 0;
gMC.xm = 0x200;
}
else
{
gMC.direct = 2;
gMC.xm = -0x200;
}
else
{
gMC.direct = 0;
gMC.xm = 0x200;
}
}
}
}
}
else
{
gMC.direct = 0;
gMC.xm = 0x200;
}
}
@ -558,7 +585,7 @@ void DeleteNpCharEvent(int code)
}
}
void DeleteNpCharCode(int code, bool bSmoke)
void DeleteNpCharCode(int code, BOOL bSmoke)
{
for (int n = 0; n < NPC_MAX; n++)
{
@ -573,15 +600,15 @@ void DeleteNpCharCode(int code, bool bSmoke)
switch (gNPC[n].size)
{
case 1:
SetDestroyNpChar(gNPC[n].x, gNPC[n].y, gNPC[n].view.back, 4);
break;
case 2:
SetDestroyNpChar(gNPC[n].x, gNPC[n].y, gNPC[n].view.back, 8);
break;
case 3:
SetDestroyNpChar(gNPC[n].x, gNPC[n].y, gNPC[n].view.back, 16);
break;
case 1:
SetDestroyNpChar(gNPC[n].x, gNPC[n].y, gNPC[n].view.back, 4);
break;
}
}
}
@ -596,23 +623,23 @@ void GetNpCharPosition(int *x, int *y, int i)
BOOL IsNpCharCode(int code)
{
for (int i = 0; i < NPC_MAX; i++)
{
for (int i = 0; i < NPC_MAX; ++i)
if ((gNPC[i].cond & 0x80) && gNPC[i].code_char == code)
return TRUE;
}
return FALSE;
}
BOOL GetNpCharAlive(int code_event)
{
for (int i = 0; i < NPC_MAX; i++)
{
int i;
for (i = 0; i < NPC_MAX; ++i)
if ((gNPC[i].cond & 0x80) && gNPC[i].code_event == code_event)
return TRUE;
}
break;
if (i < NPC_MAX)
return TRUE;
else
return FALSE;
}

View file

@ -99,7 +99,7 @@ void SetNpCharActionNo(int code_event, int act_no, int dir);
void MoveNpChar(int code_event, int x, int y, int dir);
void BackStepMyChar(int code_event);
void DeleteNpCharEvent(int code);
void DeleteNpCharCode(int code, bool bSmoke);
void DeleteNpCharCode(int code, BOOL bSmoke);
void GetNpCharPosition(int *x, int *y, int i);
BOOL IsNpCharCode(int code);
BOOL GetNpCharAlive(int code_event);