From 0a672c1e105529bd00d53024c84568269236bac4 Mon Sep 17 00:00:00 2001 From: NovaRain Date: Mon, 28 May 2018 10:15:02 +0800 Subject: [PATCH] Added MoreTiles option to increase the limit of FRM images for tiles from 4096 to 16383 (from Crafty) Added sfall log messages to both options in Tiles.cpp and edited the code style. --- artifacts/ddraw.ini | 12 +-- sfall/Tiles.cpp | 242 ++++++++++++++++++++++++++++++-------------- sfall/main.cpp | 2 +- 3 files changed, 174 insertions(+), 82 deletions(-) diff --git a/artifacts/ddraw.ini b/artifacts/ddraw.ini index 74007d68..bad96f11 100644 --- a/artifacts/ddraw.ini +++ b/artifacts/ddraw.ini @@ -180,7 +180,7 @@ WorldMapEncounterRate=5 ;The number of slots available in the locations list panel of the world map ;Set to 0 to leave unchanged. 17 is default. -;Setting this greater than 17 requires a replacement background frm, or you'll get glitched graphics +;Setting this greater than 17 requires a replacement background FRM, or you'll get glitched graphics WorldMapSlots=0 ;To start a new game somewhere other than artemple.map, uncomment the next line and set it to the map you want to load @@ -360,7 +360,10 @@ NPCsTryToSpendExtraAP=0 ;Set to 2 if you provide a XLtiles.lst file in art/tiles/ containing a list of the tile ids that need checking AllowLargeTiles=0 -;Change the Skilldex cursor frm numbers +;Set to 1 to boost the maximum number of tile FRMs from 4096 to 16383 +MoreTiles=0 + +;Change the Skilldex cursor FRM numbers ;Default is 293 for all skills Lockpick=293 Steal=293 @@ -396,7 +399,7 @@ ExtraSaveSlots=0 ;Set to 2 to update the HP/AC counters instantly SpeedInterfaceCounterAnims=0 -;These lines allow you to control the karma frm's displayed on the character screen +;These lines allow you to control the karma FRMs displayed on the character screen ;Number of KarmaPoints should be 1 less than number of KarmaFRMs ;KarmaFRMsCount=3 ;KarmaFRMs=47,48,49 @@ -568,9 +571,6 @@ CanSellUsedGeiger=1 ;Set to 1 to fix the issue with being able to charge the car by using cells on other scenary/critters CarChargingFix=1 -;Set to 1 to display the range of the second attack mode in the inventory when you switch weapon modes in active item slots -DisplaySecondWeaponRange=1 - ;Set to 1 to skip weapon equip/unequip animations when performing various actions InstantWeaponEquip=0 diff --git a/sfall/Tiles.cpp b/sfall/Tiles.cpp index 061f97e5..9f0e3410 100644 --- a/sfall/Tiles.cpp +++ b/sfall/Tiles.cpp @@ -32,11 +32,11 @@ struct sArt { int total; sArt(char* str) { - flags=0; + flags = 0; strncpy_s(path, str, 16); - names=0; - d18=0; - total=0; + names = 0; + d18 = 0; + total = 0; } }; struct OverrideEntry { @@ -46,9 +46,9 @@ struct OverrideEntry { DWORD replacementid; OverrideEntry(DWORD _xtiles, DWORD _ytiles, DWORD _repid) { - xtiles=_xtiles; - ytiles=_ytiles; - replacementid=_repid; + xtiles = _xtiles; + ytiles = _ytiles; + replacementid = _repid; } }; #pragma pack(push, 1) @@ -70,7 +70,28 @@ struct frm { #pragma pack(pop) static OverrideEntry** overrides; -static DWORD origTileCount=0; +static DWORD origTileCount = 0; + +static const DWORD Tiles_0E[] = { + 0x484255, 0x48429D, 0x484377, 0x484385, 0x48A897, 0x48A89A, 0x4B2231, + 0x4B2374, 0x4B2381, 0x4B2480, 0x4B248D, 0x4B2A7C, 0x4B2BDA, +}; + +static const DWORD Tiles_3F[] = { + 0x41875D, 0x4839E6, 0x483A2F, 0x484380, 0x48A803, 0x48A9F2, 0x48C96C, + 0x48C99F, 0x48C9D2, 0x4B2247, 0x4B2334, 0x4B2440, 0x4B2AB9, 0x4B2B8F, + 0x4B2BF4, +}; + +static const DWORD Tiles_40[] = { + 0x48C941, 0x48C955, 0x48CA5F, 0x48CA71, 0x48CA9B, 0x48CAAD, 0x48CADB, + 0x48CAEB, 0x48CAF7, 0x48CB20, 0x48CB32, 0x48CB61, +}; + +static const DWORD Tiles_C0[] = { + 0x48424E, 0x484296, 0x484372, 0x48A88D, 0x48A892, 0x4B222C, 0x4B236F, + 0x4B247B, 0x4B2A77, 0x4B2BD5, +}; static DWORD db_fopen(const char* path, const char* mode) { DWORD result; @@ -82,6 +103,7 @@ static DWORD db_fopen(const char* path, const char* mode) { } return result; } + static char* db_fgets(char* buf, int max_count, DWORD file) { char* result; __asm { @@ -93,12 +115,14 @@ static char* db_fgets(char* buf, int max_count, DWORD file) { } return result; } + static void db_fclose(DWORD file) { __asm { mov eax, file; call db_fclose_; } } + static short db_freadShort(DWORD file) { short rout=0; __asm { @@ -108,6 +132,7 @@ static short db_freadShort(DWORD file) { } return rout; } + static void db_freadByteCount(DWORD file, void* cptr, int count) { __asm { mov eax, file; @@ -116,6 +141,7 @@ static void db_freadByteCount(DWORD file, void* cptr, int count) { call db_freadByteCount_; } } + static void db_fwriteByteCount(DWORD file, void* cptr, int count) { __asm { mov eax, file; @@ -124,6 +150,7 @@ static void db_fwriteByteCount(DWORD file, void* cptr, int count) { call db_fwriteByteCount_; } } + static void db_fseek(DWORD file, long pos/*, int origin*/) { __asm { mov eax, file; @@ -132,6 +159,7 @@ static void db_fseek(DWORD file, long pos/*, int origin*/) { call db_fseek_; } } + static void* mem_realloc(void* lpmem, DWORD msize) { void* result; __asm { @@ -144,109 +172,116 @@ static void* mem_realloc(void* lpmem, DWORD msize) { } typedef int (_stdcall *functype)(); -static const functype _art_init=(functype)art_init_; +static const functype _art_init = (functype)art_init_; static BYTE* mask; static void CreateMask() { - mask=new BYTE[80*36]; - DWORD file=db_fopen("art\\tiles\\grid000.frm", "r"); + mask = new BYTE[80*36]; + DWORD file = db_fopen("art\\tiles\\grid000.frm", "r"); db_fseek(file, 0x4a); db_freadByteCount(file, mask, 80*36); db_fclose(file); } + static WORD ByteSwapW(WORD w) { return ((w&0xff) << 8) | ((w&0xff00) >> 8); } static DWORD ByteSwapD(DWORD w) { return ((w&0xff) << 24) | ((w&0xff00) << 8) | ((w&0xff0000) >> 8) | ((w&0xff000000) >> 24); } static int ProcessTile(sArt* tiles, int tile, int listpos) { char buf[32]; //sprintf_s(buf, "art\\tiles\\%s", &tiles->names[13*tile]); strcpy_s(buf, "art\\tiles\\"); - strcat_s(buf, &tiles->names[13*tile]); - - DWORD art=db_fopen(buf, "r"); - if(!art) return 0; + strcat_s(buf, &tiles->names[13 * tile]); + + DWORD art = db_fopen(buf, "r"); + if (!art) return 0; db_fseek(art, 0x3e); - int width=db_freadShort(art); //80; - if(width==80) { + int width = db_freadShort(art); //80; + if (width == 80) { db_fclose(art); return 0; } - int height=db_freadShort(art); //36 + int height = db_freadShort(art); //36 db_fseek(art, 0x4A); - BYTE* pixeldata=new BYTE[width*height]; + BYTE* pixeldata = new BYTE[width*height]; db_freadByteCount(art, pixeldata, width*height); - DWORD listid=listpos-tiles->total; - float newwidth = (float)(width - width%8); - float newheight = (float)(height - height%12); - int xsize = (int)floor(newwidth/32.0f - newheight/24.0f); - int ysize = (int)floor(newheight/16.0f - newwidth/64.0f); - for(int y=0;ytotal; + float newwidth = (float)(width - width % 8); + float newheight = (float)(height - height % 12); + int xsize = (int)floor(newwidth / 32.0f - newheight / 24.0f); + int ysize = (int)floor(newheight / 16.0f - newwidth / 64.0f); + for (int y = 0; y < ysize; y++) { + for (int x = 0; x < xsize; x++) { frm frame; db_fseek(art, 0); db_freadByteCount(art, &frame, 0x4a); - frame.height=ByteSwapW(36); - frame.width=ByteSwapW(80); - frame.frmsize=ByteSwapD(80*36); - frame.size=ByteSwapD(80*36 + 12); - int xoffset=x*48 + (ysize-(y+1))*32; - int yoffset=height - (36 + x*12 + y*24); - for(int y2=0;y2<36;y2++) { - for(int x2=0;x2<80;x2++) { - if(mask[y2*80+x2]) { - frame.pixels[y2*80+x2]=pixeldata[(yoffset+y2)*width+xoffset+x2]; - } else frame.pixels[y2*80+x2]=0; + frame.height = ByteSwapW(36); + frame.width = ByteSwapW(80); + frame.frmsize = ByteSwapD(80 * 36); + frame.size = ByteSwapD(80 * 36 + 12); + int xoffset = x * 48 + (ysize - (y + 1)) * 32; + int yoffset = height - (36 + x * 12 + y * 24); + for (int y2 = 0; y2 < 36; y2++) { + for (int x2 = 0; x2 < 80; x2++) { + if (mask[y2 * 80 + x2]) { + frame.pixels[y2 * 80 + x2] = pixeldata[(yoffset + y2) * width + xoffset + x2]; + } else { + frame.pixels[y2 * 80 + x2] = 0; + } } } - + sprintf_s(buf, 32, "art\\tiles\\zzz%04d.frm", listid++); //FScreateFromData(buf, &frame, sizeof(frame)); - DWORD file=db_fopen(buf, "w"); + DWORD file = db_fopen(buf, "w"); db_fwriteByteCount(file, &frame, sizeof(frame)); db_fclose(file); } } - overrides[tile]=new OverrideEntry(xsize, ysize, listpos); + overrides[tile] = new OverrideEntry(xsize, ysize, listpos); db_fclose(art); delete[] pixeldata; - return xsize*ysize; + return xsize * ysize; } + static DWORD tileMode; static int _stdcall ArtInitHook2() { - if(_art_init()) return 1; + if (_art_init()) { + return 1; + } CreateMask(); - sArt* tiles=&((sArt*)_art)[4]; + sArt* tiles = &((sArt*)_art)[4]; char buf[32]; - DWORD listpos=tiles->total; - origTileCount=listpos; - overrides=new OverrideEntry*[listpos]; - ZeroMemory(overrides, 4*(listpos-1)); + DWORD listpos = tiles->total; + origTileCount = listpos; + overrides = new OverrideEntry*[listpos]; + ZeroMemory(overrides, 4 * (listpos - 1)); - if(tileMode==2) { - DWORD file=db_fopen("art\\tiles\\xltiles.lst", "rt"); - if(!file) return 0; + if (tileMode == 2) { + DWORD file = db_fopen("art\\tiles\\xltiles.lst", "rt"); + if (!file) return 0; DWORD id; char* comment; - while(db_fgets(buf, 31, file)>0) { - if(comment=strchr(buf, ';')) *comment=0; - id=atoi(buf); - if(id>1) listpos+=ProcessTile(tiles, id, listpos); + while (db_fgets(buf, 31, file) > 0) { + if (comment = strchr(buf, ';')) *comment = 0; + id = atoi(buf); + if (id > 1) listpos += ProcessTile(tiles, id, listpos); } db_fclose(file); } else { - for(int i=2;itotal;i++) listpos+=ProcessTile(tiles, i, listpos); + for (int i = 2; i < tiles->total; i++) listpos += ProcessTile(tiles, i, listpos); } - if(listpos!=tiles->total) { - tiles->names=(char*)mem_realloc(tiles->names, listpos*13); - for(DWORD i=tiles->total;inames[i*13], 12, "zzz%04d.frm", i-tiles->total); + if (listpos != tiles->total) { + tiles->names = (char*)mem_realloc(tiles->names, listpos * 13); + for (DWORD i = tiles->total; i < listpos; i++) { + sprintf_s(&tiles->names[i * 13], 12, "zzz%04d.frm", i - tiles->total); } - tiles->total=listpos; + tiles->total = listpos; } delete[] mask; return 0; } + static void __declspec(naked) ArtInitHook() { __asm { pushad; @@ -263,19 +298,22 @@ static void __declspec(naked) ArtInitHook() { } } -struct tilestruct { short tile[2]; }; +struct tilestruct { + short tile[2]; +}; + static void _stdcall SquareLoadCheck(tilestruct* data) { - for(DWORD y=0;y<100;y++) { - for(DWORD x=0;x<100;x++) { - for(DWORD z=0;z<2;z++) { - DWORD tile=data[y*100+x].tile[z]; - if(tile>1&&tilereplacementid - 1; - for(DWORD y2=0;y2ytiles;y2++) { - for(DWORD x2=0;x2xtiles;x2++) { + for (DWORD y = 0; y < 100; y++) { + for (DWORD x = 0; x < 100; x++) { + for (DWORD z = 0; z < 2; z++) { + DWORD tile = data[y * 100 + x].tile[z]; + if (tile > 1 && tile < origTileCount && overrides[tile]) { + DWORD newtile = overrides[tile]->replacementid - 1; + for (DWORD y2 = 0; y2 < overrides[tile]->ytiles; y2++) { + for (DWORD x2 = 0; x2 < overrides[tile]->xtiles; x2++) { newtile++; - if(x-x2<0||y-y2<0) continue; - data[(y-y2)*100+x-x2].tile[z]=(short)newtile; + if (x - x2 < 0 || y - y2 < 0) continue; + data[(y - y2) * 100 + x - x2].tile[z] = (short)newtile; } } } @@ -299,9 +337,63 @@ end: } } +static void __declspec(naked) art_id_hack() { + __asm { + cmp esi, (OBJ_TYPE_TILE << 24); // 0x4000000 + jne end; + and eax, 0x3FFF; + retn; +end: + and eax, 0x0FFF; + retn; + } +} + +static void __declspec(naked) art_get_name_hack() { + __asm { + sar eax, 24; + cmp eax, OBJ_TYPE_TILE; + jne end; + mov esi, edx; + mov ebp, edx; + and esi, 0x3FFF; + and ebp, 0xC000; + sar ebp, 0x0E; +end: + test esi, esi; + retn; + } +} + void TilesInit() { - tileMode=GetPrivateProfileIntA("Misc", "AllowLargeTiles", 0, ini); - if(!tileMode) return; - HookCall(0x481D72, &ArtInitHook); - HookCall(0x48434C, SquareLoadHook); + tileMode = GetPrivateProfileIntA("Misc", "AllowLargeTiles", 0, ini); + if (tileMode) { + dlog("Applying allow large tiles patch.", DL_INIT); + HookCall(0x481D72, &ArtInitHook); + HookCall(0x48434C, SquareLoadHook); + dlogr(" Done", DL_INIT); + } + + if (GetPrivateProfileIntA("Misc", "MoreTiles", 0, ini)) { + dlog("Applying tile FRM limit patch.", DL_INIT); + MakeCall(0x419D46, art_id_hack); + MakeCall(0x419479, art_get_name_hack); + for (int i = 0; i < sizeof(Tiles_0E) / 4; i++) { + SafeWrite8(Tiles_0E[i], 0x0E); + } + for (int i = 0; i < sizeof(Tiles_3F) / 4; i++) { + SafeWrite8(Tiles_3F[i], 0x3F); + } + for (int i = 0; i < sizeof(Tiles_40) / 4; i++) { + SafeWrite8(Tiles_40[i], 0x40); + } + for (int i = 0; i < sizeof(Tiles_C0) / 4; i++) { + SafeWrite8(Tiles_C0[i], 0xC0); + } + if (*(long*)0x1000E1BF == 0x1000 && *(long*)0x1000E1D9 == 0x0FFF) { // Check HRP 4.1.8 + SafeWrite8(0x1000E1C0, 0x40); + SafeWrite8(0x1000E1DA, 0x3F); + } + dlogr(" Done", DL_INIT); + } } diff --git a/sfall/main.cpp b/sfall/main.cpp index adaf90c2..36cb2116 100644 --- a/sfall/main.cpp +++ b/sfall/main.cpp @@ -1280,7 +1280,7 @@ static void DllMain2() { if (KarmaFrmCount) { KarmaFrms = new DWORD[KarmaFrmCount]; KarmaPoints = new int[KarmaFrmCount - 1]; - dlog("Applying karma frm patch.", DL_INIT); + dlog("Applying karma FRM patch.", DL_INIT); char buf[512]; GetPrivateProfileStringA("Misc", "KarmaFRMs", "", buf, 512, ini); char *ptr = buf, *ptr2;