Added WorldMapInterface option to expand the world map interface.

Fixed the up/down button images in the world map interface.
Added loading sfall.dat resource file, which contains new WorldMap.frm
and AppHeroWin.frm.
This commit is contained in:
NovaRain
2019-06-08 23:53:56 +08:00
parent 02a3bbd536
commit 808ba05a0b
4 changed files with 246 additions and 0 deletions
+5
View File
@@ -196,6 +196,11 @@ WorldMapEncounterRate=5
;Setting this greater than 17 requires a replacement background FRM, or you'll get glitched graphics
WorldMapSlots=0
;Set to 1 to use the expanded world map interface
;Requires High Resolution Patch v4.1.8 and a new worldmap.frm file in art\intrface\ (included in sfall.dat)
;The fullscreen resolution of hi-res patch must be set to at least 890x720
WorldMapInterface=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
;StartingMap=
Binary file not shown.
+3
View File
@@ -325,6 +325,9 @@ static void RemoveSavFiles() {
}
void LoadOrder::init() {
// Load external sfall resource file
patchFiles.push_back("sfall.dat");
GetExtraPatches();
if (GetConfigInt("Misc", "DataLoadOrderPatch", 0)) {
+238
View File
@@ -651,6 +651,243 @@ long __fastcall Worldmap::GetRestMapLevel(long elev, int mapId) {
return -1;
}
////////////////////////////// WORLDMAP INTERFACE //////////////////////////////
#define WMAP_WIN_WIDTH (890)
#define WMAP_WIN_HEIGHT (720)
#define WMAP_TOWN_BUTTONS (15)
static DWORD wmTownMapSubButtonIds[WMAP_TOWN_BUTTONS + 1]; // replace _wmTownMapSubButtonIds (index 0 - unused element)
// Window width
static const DWORD wmWinWidth[] = {
// wmInterfaceInit_
0x4C239E, 0x4C247A,
// wmInterfaceRefresh_
0x4C38EA, 0x4C3978,
// wmInterfaceDrawCircleOverlay_
0x4C3FCA, 0x4C408E,
// wmRefreshInterfaceDial_
0x4C5757,
// wmInterfaceRefreshDate_
0x4C3D0A, 0x4C3D79, 0x4C3DBB, 0x4C3E87, 0x4C3E1F,
// wmRefreshTabs_
0x4C52BF, 0x4C53F5, 0x4C55A5, 0x4C557E, 0x4C54B2, 0x4C53E8,
// wmRefreshInterfaceOverlay_
0x4C50FD, 0x4C51CF, 0x4C51F8, 0x4C517F,
// wmInterfaceRefreshCarFuel_
0x4C528B, 0x4C529F, 0x4C52AA,
// wmInterfaceDrawSubTileList_
0x4C41C1, 0x4C41D2,
// wmTownMapRefresh_
0x4C4BDF,
// wmDrawCursorStopped_
0x4C42EE, 0x4C43C8, 0x4C445F,
// wmTownMapRefresh_
0x4C4BDF
};
// Right limit of the viewport (450)
static const DWORD wmViewportEndRight[] = {
0x4C3937, 0x4C393E, 0x4C39BB, 0x4C3B2F, 0x4C3B36, 0x4C3C4B, // wmInterfaceRefresh_
0x4C4288, 0x4C436A, 0x4C4409, // wmDrawCursorStopped_
0x4BC91F, // wmWorldMap_init_
0x4C44B4, // wmCursorIsVisible_
};
// Bottom limit of viewport (443)
static const DWORD wmViewportEndBottom[] = {
0x4C3963, 0x4C38D7, 0x4C39DA, 0x4C3B62, 0x4C3AE7, 0x4C3C74, // wmInterfaceRefresh_
0x4C429A, 0x4C4378, 0x4C4413, // wmDrawCursorStopped_
0x4BC947, // wmWorldMap_init_
0x4C44BE, // wmCursorIsVisible_
};
static const DWORD wmInterfaceInit_Ret = 0x4C23A7;
static void __declspec(naked) wmInterfaceInit_hack() {
__asm {
push eax;
mov eax, 640 - WMAP_WIN_WIDTH;
mov edx, 480 - WMAP_WIN_HEIGHT;
jmp wmInterfaceInit_Ret;
}
}
static void __declspec(naked) wmInterfaceDrawSubTileList_hack() {
__asm {
mov edx, [esp + 0x10 - 0x10 + 4];
imul edx, WMAP_WIN_WIDTH;
add edx, ecx;
retn;
}
}
static void __declspec(naked) wmInterfaceDrawCircleOverlay_hack() {
__asm {
mov eax, ecx;
imul eax, WMAP_WIN_WIDTH;
retn;
}
}
static void __declspec(naked) wmDrawCursorStopped_hack0() {
__asm {
mov ebx, ecx;
imul ebx, WMAP_WIN_WIDTH;
retn;
}
}
static void __declspec(naked) wmDrawCursorStopped_hack1() {
__asm {
mov ebx, eax;
imul ebx, WMAP_WIN_WIDTH;
retn;
}
}
static void __declspec(naked) wmRefreshTabs_hook() {
__asm {
mov eax, edx;
imul eax, WMAP_WIN_WIDTH;
sub ebp, eax;
retn;
}
}
static void __declspec(naked) wmTownMapRefresh_hook() {
__asm {
cmp edx, 700; //_wmTownWidth
jl scale;
cmp ebx, 682; //_wmTownHeight
jl scale;
jmp fo::funcoffs::buf_to_buf_;
scale:
push WMAP_WIN_WIDTH; // to_width
push 684; // height
push 702; // width
push eax; // to_buff
mov ecx, edx; // from_width
mov eax, esi; // from_buff
call fo::funcoffs::cscale_;
retn; // don't delete
}
}
void WorldmapViewportPatch() {
// Fix images for up/down buttons
SafeWrite32(0x4C2C0A, 199); // index of UPARWOFF.FRM
SafeWrite8(0x4C2C7C, 0x43); // dec ebx > inc ebx
SafeWrite32(0x4C2C92, 181); // index of DNARWOFF.FRM
SafeWrite8(0x4C2D04, 0x46); // dec esi > inc esi
// check enabled HRP
if (*(DWORD*)0x4E4480 == 0x278805C7 || GetConfigInt("Misc", "WorldMapInterface", 0) == 0 || GetPrivateProfileIntA("MAIN", "SCR_HEIGHT", 0, ".\\f2_res.ini") < WMAP_WIN_HEIGHT) return;
dlog("Applying world map interface patch.", DL_INIT);
mapSlotsScrollMax -= 216;
if (mapSlotsScrollMax < 0) mapSlotsScrollMax = 0;
SafeWriteBatch<DWORD>(135, {0x4C23BD, 0x4C2408}); // use unused worldmap.frm for new world map interface (wmInterfaceInit_)
// x/y axis offset of interface window
MakeJump(0x4C23A2, wmInterfaceInit_hack);
// size of the created window/buffer
SafeWriteBatch<DWORD>(WMAP_WIN_WIDTH, wmWinWidth); // width
SafeWrite32(0x4C238B, WMAP_WIN_HEIGHT); // height (wmInterfaceInit_)
// Mouse scrolling area (wmMouseBkProc_)
SafeWrite32(0x4C331D, WMAP_WIN_WIDTH - 1);
SafeWrite32(0x4C3337, WMAP_WIN_HEIGHT - 1);
MakeCall(0x4C41A4, wmInterfaceDrawSubTileList_hack); // 640 * 21
MakeCall(0x4C4082, wmInterfaceDrawCircleOverlay_hack); // 640 * y
MakeCall(0x4C4452, wmDrawCursorStopped_hack1);
MakeCalls(wmDrawCursorStopped_hack0, {0x4C43BB, 0x4C42E1});
MakeCall(0x4C5325, wmRefreshTabs_hook);
HookCall(0x4C4BFF, wmTownMapRefresh_hook);
// up/down buttons of the location list (wmInterfaceInit_)
SafeWriteBatch<DWORD>(WMAP_WIN_WIDTH - (640 - 480), { // offset by X (480)
0x4C2D3C,
0x4C2D7A
});
// town/world button (wmInterfaceInit_)
SafeWrite32(0x4C2B9B, WMAP_WIN_HEIGHT - (480 - 439)); // offset by Y (439)
SafeWrite32(0x4C2BAF, WMAP_WIN_WIDTH - (640 - 519)); // offset by X (508)
// viewport size for mouse click
SafeWriteBatch<DWORD>(WMAP_WIN_HEIGHT - (480 - 465), { // height/offset by Y (465 - 21 = 444 (443))
0x4C0154, 0x4C02BA, // wmWorldMap_
0x4C3A47, // wmInterfaceRefresh_
});
SafeWriteBatch<DWORD>(WMAP_WIN_WIDTH - (640 - 472), { // width/offset by X (472 - 22 = 450)
0x4C0159, 0x4C02BF, // wmWorldMap_
0x4C3A3A, // wmInterfaceRefresh_
0x4C417C, 0x4C4184 // wmInterfaceDrawSubTileList_
});
SafeWriteBatch<DWORD>(WMAP_WIN_HEIGHT - (480 - 464), { // width/offset by X (464)
0x4C3FED, // wmInterfaceDrawCircleOverlay_
0x4C4157, 0x4C415F, // wmInterfaceDrawSubTileList_
});
// right limit of the viewport (450)
SafeWriteBatch<DWORD>(WMAP_WIN_WIDTH - (640 - 450), wmViewportEndRight); // 890 - 190 = 700 + 22 = 722
// bottom limit of the viewport (443)
SafeWriteBatch<DWORD>(WMAP_WIN_HEIGHT - (480 - 443), wmViewportEndBottom); // 720 - 37 = 683 + 21 = 704
// Night/Day frm (wmRefreshInterfaceDial_)
SafeWrite32(0x4C577F, WMAP_WIN_WIDTH - (640 - 532)); // X offset (532)
SafeWrite32(0x4C575D, (WMAP_WIN_WIDTH * 49) - ((640 * 49) - 31252)); // start offset in buffer (31252 / 640 = 49)
// Date/Time frm
SafeWrite32(0x4C3EC7, WMAP_WIN_WIDTH - (640 - 487)); // start offset by X (487)
SafeWrite32(0x4C3ED1, WMAP_WIN_WIDTH - (640 - 630)); // end offset by X (630)
SafeWrite32(0x4C3D10, (WMAP_WIN_WIDTH * 13) - ((640 * 13) - 8167)); // 8167 start offset in buffer (12327)
SafeWrite32(0x4C3DC1, WMAP_WIN_WIDTH + (666 - 640)); // 666
// WMCARMVE/WMGLOBE/WMSCREEN frms (wmRefreshInterfaceOverlay_)
SafeWrite32(0x4C51D5, (WMAP_WIN_WIDTH * 577) - ((640 * 337) - 215554)); // start offset for image WMCARMVE
SafeWrite32(0x4C5184, (WMAP_WIN_WIDTH * 571) - ((640 * 331) - 211695)); // start offset for image WMGLOBE
SafeWrite32(0x4C51FD, (WMAP_WIN_WIDTH * 571) - ((640 * 331) - 211699)); // start offset for image WMSCREEN
// Car gas indicator
SafeWrite32(0x4C527E, (WMAP_WIN_WIDTH * 580) - ((640 * 340) - 217460)); // start offset in buffer (217460 / 640 = 340 + (720 - 480) = 580 Y-axes)
// WMTABS.frm
SafeWriteBatch<DWORD>((WMAP_WIN_WIDTH * 136) - ((640 * 136) - 86901), {
0x4C52C4, 0x4C55AA // wmRefreshTabs_
});
SafeWrite32(0x4C52FF, (WMAP_WIN_WIDTH * 139) - ((640 * 139) - 88850)); // wmRefreshTabs_
SafeWriteBatch<DWORD>((WMAP_WIN_WIDTH * 27), { // start offset in buffer (17280)
0x4C54DE, 0x4C5424 // wmRefreshTabs_
});
SafeWrite32(0x4C52E5, WMAP_WIN_HEIGHT - 480 + 178 - 19); // height (178)
// Buttons of cities, now 15
SafeWrite32(0x4C2BD9, WMAP_WIN_WIDTH - (640 - 508)); // offset of the buttons by X (508)
SafeWriteBatch<BYTE>(WMAP_TOWN_BUTTONS * 4, {0x4C2C01, 0x4C21B6, 0x4C2289}); // number of buttons (28 = 7 * 4)
int btn = (mapSlotsScrollLimit) ? WMAP_TOWN_BUTTONS : WMAP_TOWN_BUTTONS + 1;
SafeWrite32(0x4C21FD, 27 * btn); // scroll limit for buttons
// number of city labels (6) wmRefreshTabs_
SafeWriteBatch<BYTE>(WMAP_TOWN_BUTTONS - 1, {0x4C54F6, 0x4C542A});
SafeWrite8(0x4C555E, 0);
SafeWrite32(0x4C0348, 350 + WMAP_TOWN_BUTTONS); // buttons input code (wmWorldMap_)
SafeWrite32(0x4C2BFB, (DWORD)&wmTownMapSubButtonIds[0]); // wmInterfaceInit_
SafeWriteBatch<DWORD>((DWORD)&wmTownMapSubButtonIds[1], {
// 0x4C22DD, 0x4C230A, // wmInterfaceScrollTabsUpdate_ (never called)
0x4C227B, // wmInterfaceScrollTabsStop_
0x4C21A8 // wmInterfaceScrollTabsStart_
});
// WMTBEDGE.frm (wmRefreshTabs_)
BlockCall(0x4C55BF);
// Town map frm images (wmTownMapRefresh_)
SafeWrite32(0x4C4BE4, (WMAP_WIN_WIDTH * 21) + 22); // start offset for town map image (13462)
dlogr(" Done", DL_INIT);
}
void Worldmap::init() {
PathfinderFixInit();
StartingStatePatches();
@@ -660,6 +897,7 @@ void Worldmap::init() {
WorldmapFpsPatch();
WorldMapFontPatch();
PipBoyAutomapsPatch();
WorldmapViewportPatch(); // must be located after WorldMapSlots patch
LoadGameHook::OnGameReset() += []() {
SetCarInterfaceArt(433); // set index