Made Map.cpp and some of NpcAct020.cpp ASM-accurate

Also added a new constant 'NONPORTABLE', for enabling bits of code that
are non-portable, but needed for accuracy
This commit is contained in:
Clownacy 2019-02-24 14:35:35 +00:00
parent 08ee4c96a7
commit 532661b0cf
6 changed files with 211 additions and 171 deletions

View file

@ -22,7 +22,7 @@
Name="VCCLCompilerTool" Name="VCCLCompilerTool"
Optimization="0" Optimization="0"
AdditionalIncludeDirectories=""SDL2-2.0.9/include";"freetype-2.9.1/include";./" AdditionalIncludeDirectories=""SDL2-2.0.9/include";"freetype-2.9.1/include";./"
PreprocessorDefinitions="WIN32;_DEBUG;WINDOWS" PreprocessorDefinitions="WIN32;_DEBUG;WINDOWS;NONPORTABLE"
MinimalRebuild="TRUE" MinimalRebuild="TRUE"
BasicRuntimeChecks="0" BasicRuntimeChecks="0"
RuntimeLibrary="1" RuntimeLibrary="1"
@ -73,7 +73,7 @@
Name="VCCLCompilerTool" Name="VCCLCompilerTool"
Optimization="0" Optimization="0"
AdditionalIncludeDirectories=""SDL2-2.0.9/include";"freetype-2.9.1/include";./" AdditionalIncludeDirectories=""SDL2-2.0.9/include";"freetype-2.9.1/include";./"
PreprocessorDefinitions="WIN32;NDEBUG;WINDOWS" PreprocessorDefinitions="WIN32;NDEBUG;WINDOWS;NONPORTABLE"
MinimalRebuild="TRUE" MinimalRebuild="TRUE"
RuntimeLibrary="0" RuntimeLibrary="0"
AssemblerOutput="4" AssemblerOutput="4"

View file

@ -34,7 +34,31 @@ BOOL InitBack(const char *fName, int type)
return FALSE; return FALSE;
} }
#ifdef FIX_BUGS // TODO: Maybe we need a 'BETTER_PORTABILITY' flag #ifdef NONPORTABLE
// This is ridiculously platform-dependant:
// It should break on big-endian CPUs, and platforms
// where short isn't 16-bit and long isn't 32-bit.
short bmp_header_buffer[7];
long bmp_header_buffer2[10];
fread(bmp_header_buffer, 14, 1, fp);
// Check if this is a valid bitmap file
if (bmp_header_buffer[0] != 0x4D42) // 'MB' (we use hex to prevent a compiler warning)
{
#ifdef FIX_BUGS
// The original game forgets to close fp
fclose(fp);
#endif
return FALSE;
}
fread(bmp_header_buffer2, 40, 1, fp);
fclose(fp);
gBack.partsW = bmp_header_buffer2[1];
gBack.partsH = bmp_header_buffer2[2];
#else
if (fgetc(fp) != 'B' || fgetc(fp) != 'M') if (fgetc(fp) != 'B' || fgetc(fp) != 'M')
{ {
fclose(fp); fclose(fp);
@ -46,26 +70,6 @@ BOOL InitBack(const char *fName, int type)
gBack.partsW = File_ReadLE32(fp); gBack.partsW = File_ReadLE32(fp);
gBack.partsH = File_ReadLE32(fp); gBack.partsH = File_ReadLE32(fp);
fclose(fp); fclose(fp);
#else
// This is ridiculously platform-dependant:
// It should break on big-endian CPUs, and platforms
// where short isn't 16-bit and long isn't 32-bit.
// short bmp_header_buffer[7];
// long bmp_header_buffer2[10];
int16_t bmp_header_buffer[7];
int32_t bmp_header_buffer2[10]; // We'll need a better solution when we stop using stdint.h
fread(bmp_header_buffer, 14, 1, fp);
// Check if this is a valid bitmap file
if (bmp_header_buffer[0] != 0x4D42) // 'MB' (we use hex to prevent a compiler warning)
return FALSE; // The original game forgets to close fp
fread(bmp_header_buffer2, 40, 1, fp);
fclose(fp);
gBack.partsW = bmp_header_buffer2[1];
gBack.partsH = bmp_header_buffer2[2];
#endif #endif
//Set background stuff and load texture //Set background stuff and load texture

View file

@ -17,6 +17,8 @@
MAP_DATA gMap; MAP_DATA gMap;
static const char *code_pxma = "PXM";
BOOL InitMapData2() BOOL InitMapData2()
{ {
gMap.data = (uint8_t*)malloc(PXM_BUFFER_SIZE); gMap.data = (uint8_t*)malloc(PXM_BUFFER_SIZE);
@ -25,47 +27,54 @@ BOOL InitMapData2()
BOOL LoadMapData2(const char *path_map) BOOL LoadMapData2(const char *path_map)
{ {
unsigned char dum;
//Get path //Get path
char path[PATH_LENGTH]; char path[PATH_LENGTH];
sprintf(path, "%s/%s", gDataPath, path_map); sprintf(path, "%s/%s", gDataPath, path_map);
//Open file //Open file
FILE *fp = fopen(path, "rb"); FILE *fp = fopen(path, "rb");
if (fp == NULL) if (fp == NULL)
return FALSE; return FALSE;
//Make sure file begins with "PXM" //Make sure file begins with "PXM"
char check[3]; char check[3];
fread(check, 1, 3, fp); fread(check, 1, 3, fp);
if (!memcmp(check, "PXM", 3)) if (memcmp(check, code_pxma, 3))
{ {
uint8_t nul; fclose(fp);
fread(&nul, 1, 1, fp); return FALSE;
}
else
{
fread(&dum, 1, 1, fp);
//Get width and height //Get width and height
#ifdef NONPORTABLE
// This fails on big-endian hardware, and platforms
// where short is not two bytes long.
fread(&gMap.width, 2, 1, fp);
fread(&gMap.length, 2, 1, fp);
#else
gMap.width = File_ReadLE16(fp); gMap.width = File_ReadLE16(fp);
gMap.length = File_ReadLE16(fp); gMap.length = File_ReadLE16(fp);
#endif
if (gMap.data)
if (gMap.data == NULL)
{
fclose(fp);
return FALSE;
}
else
{ {
//Read tiledata //Read tiledata
fread(gMap.data, 1, gMap.length * gMap.width, fp); fread(gMap.data, 1, gMap.length * gMap.width, fp);
fclose(fp); fclose(fp);
return TRUE; return TRUE;
} }
else
{
fclose(fp);
return FALSE;
}
} }
else
{
fclose(fp);
return FALSE;
}
return FALSE; return FALSE;
} }
@ -74,11 +83,11 @@ BOOL LoadAttributeData(const char *path_atrb)
//Open file //Open file
char path[260]; char path[260];
sprintf(path, "%s/%s", gDataPath, path_atrb); sprintf(path, "%s/%s", gDataPath, path_atrb);
FILE *fp = fopen(path, "rb"); FILE *fp = fopen(path, "rb");
if (fp == NULL) if (fp == NULL)
return FALSE; return FALSE;
//Read data //Read data
fread(gMap.atrb, 1, 0x100, fp); fread(gMap.atrb, 1, 0x100, fp);
fclose(fp); fclose(fp);
@ -87,8 +96,7 @@ BOOL LoadAttributeData(const char *path_atrb)
void EndMapData() void EndMapData()
{ {
if (gMap.data) free(gMap.data);
free(gMap.data);
} }
void ReleasePartsImage() void ReleasePartsImage()
@ -106,60 +114,74 @@ void GetMapData(uint8_t **data, int16_t *mw, int16_t *ml)
*ml = gMap.length; *ml = gMap.length;
} }
int GetAttribute(int x, int y) unsigned char GetAttribute(int x, int y)
{ {
if (x >= 0 && y >= 0 && gMap.width > x && gMap.length > y) if (x < 0 || y < 0 || x >= gMap.width || y >= gMap.length)
return gMap.atrb[gMap.data[y * gMap.width + x]]; return 0;
return 0;
const size_t a = *(gMap.data + x + gMap.width * y);
return gMap.atrb[a];
} }
void DeleteMapParts(int x, int y) void DeleteMapParts(int x, int y)
{ {
gMap.data[y * gMap.width + x] = 0; *(gMap.data + x + gMap.width * y) = 0;
} }
void ShiftMapParts(int x, int y) void ShiftMapParts(int x, int y)
{ {
--gMap.data[y * gMap.width + x]; *(gMap.data + x + gMap.width * y) -= 1;
} }
BOOL ChangeMapParts(int x, int y, uint8_t no) BOOL ChangeMapParts(int x, int y, uint8_t no)
{ {
if (gMap.data[y * gMap.width + x] == no) if (*(gMap.data + x + gMap.width * y) == no)
return FALSE; return FALSE;
gMap.data[y * gMap.width + x] = no;
*(gMap.data + x + gMap.width * y) = no;
for (int i = 0; i < 3; i++) for (int i = 0; i < 3; i++)
SetNpChar(4, x << 13, y << 13, 0, 0, 0, 0, 0); SetNpChar(4, x * 0x200 * 0x10, y * 0x200 * 0x10, 0, 0, 0, 0, 0);
return TRUE; return TRUE;
} }
void PutStage_Back(int fx, int fy) void PutStage_Back(int fx, int fy)
{ {
int num_y;
int put_x;
int put_y;
int i;
int j;
int offset;
int atrb;
RECT rect;
int num_x;
//Get range to draw //Get range to draw
int num_x = ((WINDOW_WIDTH + 0xF) >> 4) + 1; num_x = ((WINDOW_WIDTH + 0xF) / 0x10) + 1;
int num_y = ((WINDOW_HEIGHT + 0xF) >> 4) + 1; num_y = ((WINDOW_HEIGHT + 0xF) / 0x10) + 1;
int put_x = (fx / 0x200 + 8) / 16; put_x = (fx / 0x200 + 8) / 0x10;
int put_y = (fy / 0x200 + 8) / 16; put_y = (fy / 0x200 + 8) / 0x10;
for (int j = put_y; put_y + num_y > j; j++) for (j = put_y; j < put_y + num_y; j++)
{ {
for (int i = put_x; put_x + num_x > i; i++) for (i = put_x; i < put_x + num_x; i++)
{ {
//Get attribute //Get attribute
int offset = i + j * gMap.width; offset = i + j * gMap.width;
int atrb = GetAttribute(i, j); atrb = GetAttribute(i, j);
if (atrb < 0x20) if (atrb >= 0x20)
{ continue;
//Draw tile
RECT rect; //Draw tile
rect.left = 16 * (gMap.data[offset] & 0xF); rect.left = 16 * (gMap.data[offset] % 0x10);
rect.top = 16 * (gMap.data[offset] >> 4); rect.top = 16 * (gMap.data[offset] / 0x10);
rect.right = rect.left + 16; rect.right = rect.left + 16;
rect.bottom = rect.top + 16; rect.bottom = rect.top + 16;
PutBitmap3(&grcGame, 8 * (2 * i - 1) - fx / 0x200, 8 * (2 * j - 1) - fy / 0x200, &rect, SURFACE_ID_LEVEL_TILESET); PutBitmap3(&grcGame, 0x10 * i - 8 - fx / 0x200, 0x10 * j - 8 - fy / 0x200, &rect, SURFACE_ID_LEVEL_TILESET);
}
} }
} }
} }
@ -167,106 +189,120 @@ void PutStage_Back(int fx, int fy)
void PutStage_Front(int fx, int fy) void PutStage_Front(int fx, int fy)
{ {
RECT rcSnack = {256, 48, 272, 64}; RECT rcSnack = {256, 48, 272, 64};
int num_y;
int put_x;
int put_y;
int j;
int i;
int offset;
int atrb;
RECT rect;
int num_x;
//Get range to draw //Get range to draw
int num_x = ((WINDOW_WIDTH + 0xF) >> 4) + 1; num_x = ((WINDOW_WIDTH + 0xF) >> 4) + 1;
int num_y = ((WINDOW_HEIGHT + 0xF) >> 4) + 1; num_y = ((WINDOW_HEIGHT + 0xF) >> 4) + 1;
int put_x = (fx / 0x200 + 8) / 16; put_x = (fx / 0x200 + 8) / 16;
int put_y = (fy / 0x200 + 8) / 16; put_y = (fy / 0x200 + 8) / 16;
for (int j = put_y; put_y + num_y > j; j++) for (j = put_y; j < put_y + num_y; j++)
{ {
for (int i = put_x; put_x + num_x > i; i++) for (i = put_x; i < put_x + num_x; i++)
{ {
//Get attribute //Get attribute
int offset = i + j * gMap.width; offset = i + j * gMap.width;
int atrb = GetAttribute(i, j); atrb = GetAttribute(i, j);
if (atrb >= 0x40 && atrb < 0x80) if (atrb < 0x40 || atrb >= 0x80)
{ continue;
//Draw tile
RECT rect; //Draw tile
rect.left = 16 * (gMap.data[offset] & 0xF); rect.left = 16 * (gMap.data[offset] % 0x10);
rect.top = 16 * (gMap.data[offset] >> 4); rect.top = 16 * (gMap.data[offset] / 0x10);
rect.right = rect.left + 16; rect.right = rect.left + 16;
rect.bottom = rect.top + 16; rect.bottom = rect.top + 16;
PutBitmap3(&grcGame, 8 * (2 * i - 1) - fx / 0x200, 8 * (2 * j - 1) - fy / 0x200, &rect, SURFACE_ID_LEVEL_TILESET); PutBitmap3(&grcGame, 16 * i - 8 - fx / 0x200, 16 * j - 8 - fy / 0x200, &rect, SURFACE_ID_LEVEL_TILESET);
if (atrb == 0x43) if (atrb == 0x43)
PutBitmap3(&grcGame, 8 * (2 * i - 1) - fx / 0x200, 8 * (2 * j - 1) - fy / 0x200, &rcSnack, SURFACE_ID_NPC_SYM); PutBitmap3(&grcGame, 16 * i - 8 - fx / 0x200, 16 * j - 8 - fy / 0x200, &rcSnack, SURFACE_ID_NPC_SYM);
}
} }
} }
} }
void PutMapDataVector(int fx, int fy) void PutMapDataVector(int fx, int fy)
{ {
//Get range to draw int num_y;
int num_x = ((WINDOW_WIDTH + 0xF) >> 4) + 1; int put_x;
int num_y = ((WINDOW_HEIGHT + 0xF) >> 4) + 1; int put_y;
int put_x = (fx / 0x200 + 8) / 16; int i;
int put_y = (fy / 0x200 + 8) / 16; int j;
int offset;
int atrb;
RECT rect;
int num_x;
//Animate the wind //Animate the wind
static int count = 0; static unsigned char count = 0;
count += 2; count += 2;
for (int j = put_y; put_y + num_y > j; j++) //Get range to draw
num_x = ((WINDOW_WIDTH + 0xF) >> 4) + 1;
num_y = ((WINDOW_HEIGHT + 0xF) >> 4) + 1;
put_x = (fx / 0x200 + 8) / 16;
put_y = (fy / 0x200 + 8) / 16;
for (j = put_y; j < put_y + num_y; j++)
{ {
for (int i = put_x; put_x + num_x > i; i++) for (i = put_x; i < put_x + num_x; i++)
{ {
//Get attribute //Get attribute
int offset = i + j * gMap.width; offset = i + j * gMap.width;
int atrb = GetAttribute(i, j); atrb = GetAttribute(i, j);
if ( atrb == 0x80 if (atrb != 0x80
|| atrb == 0x81 && atrb != 0x81
|| atrb == 0x82 && atrb != 0x82
|| atrb == 0x83 && atrb != 0x83
|| atrb == 0xA0 && atrb != 0xA0
|| atrb == 0xA1 && atrb != 0xA1
|| atrb == 0xA2 && atrb != 0xA2
|| atrb == 0xA3) && atrb != 0xA3)
continue;
switch (atrb)
{ {
RECT rect; case 128:
case 160:
switch ( atrb ) rect.left = 224 + (count % 0x10);
{ rect.right = rect.left + 16;
case 128: rect.top = 48;
case 160: rect.bottom = rect.top + 16;
rect.left = (count & 0xF) + 224; break;
rect.right = (count & 0xF) + 240; case 129:
rect.top = 48; case 161:
rect.bottom = 64; rect.left = 224;
break; rect.right = rect.left + 16;
case 129: rect.top = 48 + (count % 0x10);
case 161: rect.bottom = rect.top + 16;
rect.left = 224; break;
rect.right = 240; case 130:
rect.top = (count & 0xF) + 48; case 162:
rect.bottom = (count & 0xF) + 64; rect.left = 240 - (count % 0x10);
break; rect.right = rect.left + 16;
case 130: rect.top = 48;
case 162: rect.bottom = rect.top + 16;
rect.left = 240 - (count & 0xF); break;
rect.right = rect.left + 16; case 131:
rect.top = 48; case 163:
rect.bottom = 64; rect.left = 224;
break; rect.right = rect.left + 16;
case 131: rect.top = 64 - (count % 0x10);
case 163: rect.bottom = rect.top + 16;
rect.left = 224; break;
rect.right = 240;
rect.top = 64 - (count & 0xF);
rect.bottom = rect.top + 16;
break;
default:
break;
}
PutBitmap3(&grcGame, 8 * (2 * i - 1) - fx / 0x200, 8 * (2 * j - 1) - fy / 0x200, &rect, SURFACE_ID_CARET);
} }
PutBitmap3(&grcGame, 16 * i - 8 - fx / 0x200, 16 * j - 8 - fy / 0x200, &rect, SURFACE_ID_CARET);
} }
} }
} }

View file

@ -20,7 +20,7 @@ BOOL LoadAttributeData(const char *path_atrb);
void EndMapData(); void EndMapData();
void ReleasePartsImage(); void ReleasePartsImage();
void GetMapData(uint8_t **data, int16_t *mw, int16_t *ml); void GetMapData(uint8_t **data, int16_t *mw, int16_t *ml);
int GetAttribute(int x, int y); unsigned char GetAttribute(int x, int y);
void DeleteMapParts(int x, int y); void DeleteMapParts(int x, int y);
void ShiftMapParts(int x, int y); void ShiftMapParts(int x, int y);
BOOL ChangeMapParts(int x, int y, uint8_t no); BOOL ChangeMapParts(int x, int y, uint8_t no);

View file

@ -15,7 +15,7 @@
//Null //Null
void ActNpc000(NPCHAR *npc) void ActNpc000(NPCHAR *npc)
{ {
RECT rect[1] = {0x00, 0x00, 0x10, 0x10}; RECT rect = {0x00, 0x00, 0x10, 0x10};
if (npc->act_no == 0) if (npc->act_no == 0)
{ {
@ -25,7 +25,7 @@ void ActNpc000(NPCHAR *npc)
npc->y += 0x2000; npc->y += 0x2000;
} }
npc->rect = rect[0]; npc->rect = rect;
} }
//Experience //Experience

View file

@ -14,7 +14,7 @@
//Computer //Computer
void ActNpc020(NPCHAR *npc) void ActNpc020(NPCHAR *npc)
{ {
RECT rcLeft[1] = {288, 16, 320, 40}; RECT rcLeft = {288, 16, 320, 40};
RECT rcRight[3] = { RECT rcRight[3] = {
{288, 40, 320, 64}, {288, 40, 320, 64},
@ -32,7 +32,7 @@ void ActNpc020(NPCHAR *npc)
npc->ani_no = 0; npc->ani_no = 0;
if (npc->direct == 0) if (npc->direct == 0)
npc->rect = rcLeft[0]; npc->rect = rcLeft;
else else
npc->rect = rcRight[npc->ani_no]; npc->rect = rcRight[npc->ani_no];
} }
@ -48,9 +48,9 @@ void ActNpc021(NPCHAR *npc)
npc->y += 0x2000; npc->y += 0x2000;
} }
RECT rect[1] = {224, 40, 240, 48}; RECT rect = {224, 40, 240, 48};
npc->rect = rect[0]; npc->rect = rect;
} }
//Teleporter //Teleporter
@ -1008,13 +1008,13 @@ void ActNpc033(NPCHAR *npc)
//Bed //Bed
void ActNpc034(NPCHAR *npc) void ActNpc034(NPCHAR *npc)
{ {
RECT rcLeft[1] = {192, 48, 224, 64}; RECT rcLeft = {192, 48, 224, 64};
RECT rcRight[1] = {192, 184, 224, 200}; RECT rcRight = {192, 184, 224, 200};
if (npc->direct == 0) if (npc->direct == 0)
npc->rect = rcLeft[0]; npc->rect = rcLeft;
else else
npc->rect = rcRight[0]; npc->rect = rcRight;
} }
//Mannan //Mannan