From 3f96e42730cb4101d64136e9f73eb3fe7c3a97df Mon Sep 17 00:00:00 2001 From: NovaRain Date: Fri, 28 Jun 2019 21:40:57 +0800 Subject: [PATCH] Added ActionPointsBar option to [Interface] in INI Added a new Interface module. Moved WorldMapInterface to the new [Interface] section. Moved some code from Worldmap.cpp to Interface.cpp. Updated sfall.dat with new IFACE_E.frm and HR_IFACE_800E.frm files. --- artifacts/ddraw.ini | 21 +- artifacts/sfall.dat | Bin 99158 -> 155707 bytes sfall/FalloutEngine/VariableOffsets.h | 2 + sfall/FalloutEngine/Variables_def.h | 1 + sfall/Modules/Interface.cpp | 465 ++++++++++++++++++++++++++ sfall/Modules/Interface.h | 15 + sfall/Modules/Worldmap.cpp | 376 +-------------------- sfall/ddraw.vcxproj | 3 + sfall/ddraw.vcxproj.filters | 6 + sfall/main.cpp | 6 +- 10 files changed, 526 insertions(+), 369 deletions(-) create mode 100644 sfall/Modules/Interface.cpp create mode 100644 sfall/Modules/Interface.h diff --git a/artifacts/ddraw.ini b/artifacts/ddraw.ini index 284d712e..64591e54 100644 --- a/artifacts/ddraw.ini +++ b/artifacts/ddraw.ini @@ -101,6 +101,20 @@ AllowDShowMovies=0 ;Default is 100. Decrease/increase this value to speed up/slow down fade effects FadeMultiplier=100 +;XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +[Interface] +;Set to 1 to use the expanded world map interface +;Set to 2 to skip correcting the position of entrance markers on town maps +;You can use resized FRMs in 700x682 for town maps in 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 resolution of hi-res patch must be set to at least 890x720 +WorldMapInterface=0 + +;Set to 1 to expand the number of action points displayed on the interface bar +;Requires new IFACE_E.frm and HR_IFACE_800E.frm files in art\intrface\ (included in sfall.dat) to display correctly +;The minimum supported version of High Resolution Patch is 4.1.8 +ActionPointsBar=0 + ;XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX [Input] ;Set to 1 to enable the mouse scroll wheel to scroll through the inventory, barter, and loot screens @@ -204,13 +218,6 @@ 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 -;Set to 2 to skip correcting the position of entrance markers on town maps -;You can use resized FRMs in 700x682 for town maps in 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 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= diff --git a/artifacts/sfall.dat b/artifacts/sfall.dat index 60e5fc3934ccc54672e84b535eb853c8d5d2ccbf..fac955457e6ada869b108c13b715d7ddafc2280f 100644 GIT binary patch delta 57030 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. + */ + +#include "..\main.h" +#include "..\FalloutEngine\Fallout2.h" +#include "Graphics.h" +#include "LoadGameHook.h" + +#include "Interface.h" + +namespace sfall +{ + +bool hrpIsEnabled = false; + +static BYTE movePointBackground[16 * 9 * 5]; +static fo::UnlistedFrm* ifaceFrm = nullptr; + +static void* LoadIfaceFrm() { + ifaceFrm = fo::LoadUnlistedFrm("IFACE_E.frm", fo::OBJ_TYPE_INTRFACE); + if (!ifaceFrm) return nullptr; + return ifaceFrm->frames[0].indexBuff; +} + +static void __declspec(naked) intface_init_hook_lock() { + __asm { + pushadc; + call LoadIfaceFrm; + test eax, eax; + jz skip; + pop ecx; + add esp, 8; + mov dword ptr [ecx], 0; + retn; +skip: + popadc; + jmp fo::funcoffs::art_ptr_lock_data_; + } +} + +static void __declspec(naked) intface_init_hack() { + __asm { + add eax, 9276 - (54 / 2); // x offset + mov edx, 144 - 90; // width + add [esp + 4], edx; + add [esp + 0x10 + 4], edx; + retn; + } +} + +static const DWORD intface_update_move_points_ret = 0x45EE3E; +static void __declspec(naked) intface_update_move_points_hack() { + __asm { + mov eax, 16 * 9 + push eax; + push 5; + push eax; + jmp intface_update_move_points_ret; + } +} + +static void APBarRectPatch() { + fo::var::movePointRect.x -= (54 / 2); // 54 = 144(new width) - 90(old width) + fo::var::movePointRect.offx += (54 / 2); +} + +static void ActionPointsBarPatch() { + dlog("Applying expanded action points bar patch.", DL_INIT); + if (hrpIsEnabled) { + // check valid data + if (!strcmp((const char*)0x10039358, "HR_IFACE_%i.frm")) { // patching HRP + SafeWriteStr(0x10039363, "E.frm"); + SafeWriteStr(0x1003934F, "E.frm"); + } else { + dlog(" Incorrect HRP version!", DL_INIT); + } + } else { + APBarRectPatch(); + } + SafeWrite32(0x45E343, (DWORD)&movePointBackground); + SafeWrite32(0x45EE3F, (DWORD)&movePointBackground); + SafeWriteBatch(16, {0x45EE55, 0x45EE7B, 0x45EE82, 0x45EE9C, 0x45EEA0}); + SafeWriteBatch(9276 - (54 / 2), {0x45EE33, 0x45EEC8, 0x45EF16}); + + HookCall(0x45D918, intface_init_hook_lock); + MakeCall(0x45E356, intface_init_hack); + MakeJump(0x45EE38, intface_update_move_points_hack, 1); + dlogr(" Done", DL_INIT); +} + +////////////////////////////// WORLDMAP INTERFACE ////////////////////////////// + +static int mapSlotsScrollMax = 27 * (17 - 7); +static int mapSlotsScrollLimit = 0; + +static __declspec(naked) void ScrollCityListFix() { + __asm { + push ebx; + mov ebx, ds:[0x672F10]; // _wmLastTabsYOffset + test eax, eax; + jl up; + cmp ebx, mapSlotsScrollMax; + pop ebx; + jl run; + retn; +up: + test ebx, ebx; + pop ebx; + jnz run; + retn; +run: + jmp fo::funcoffs::wmInterfaceScrollTabsStart_; + } +} + +static void __declspec(naked) wmInterfaceInit_text_font_hook() { + __asm { + mov eax, 0x65; // normal text font + jmp fo::funcoffs::text_font_; + } +} + +#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) +static int worldmapInterface; + +// 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[] = { +// 0x4BC91F, // wmWorldMap_init_ + 0x4C3937, 0x4C393E, 0x4C39BB, 0x4C3B2F, 0x4C3B36, 0x4C3C4B, // wmInterfaceRefresh_ + 0x4C4288, 0x4C436A, 0x4C4409, // wmDrawCursorStopped_ + 0x4C44B4, // wmCursorIsVisible_ +}; + +// Bottom limit of viewport (443) +static const DWORD wmViewportEndBottom[] = { +// 0x4BC947, // wmWorldMap_init_ + 0x4C3963, 0x4C38D7, 0x4C39DA, 0x4C3B62, 0x4C3AE7, 0x4C3C74, // wmInterfaceRefresh_ + 0x4C429A, 0x4C4378, 0x4C4413, // wmDrawCursorStopped_ + 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 + } +} + +static void __declspec(naked) wmTownMapRefresh_hook_textpos() { + __asm { + push eax; + push ebx; + mov eax, ecx; // xpos + shr ebx, 2; // text_width / 4 + test ebx, ebx; + jz skipX; + sub ebx, 5; // x adjust +skipX: + sar eax, 1; + add ecx, eax; // xpos * 1.5 + add ecx, ebx; + pop ebx; + mov eax, dword ptr [esp + 8]; // ypos + sar eax, 1; + test eax, eax; + jz skipY; + sub eax, 5; // y adjust +skipY: + add dword ptr [esp + 8], eax; // ypos * 1.5 + pop eax; + jmp fo::funcoffs::win_print_; + } +} + +static void __declspec(naked) wmTownMapInit_hook() { + __asm { + push eax; + mov eax, edx; // xpos + shr eax, 1; + add edx, eax; // xpos * 1.5 + mov eax, ebx; // ypos + shr eax, 1; + add ebx, eax; // ypos * 1.5 + pop eax; + jmp fo::funcoffs::win_register_button_; + } +} + +static void WorldmapViewportPatch() { + if (Graphics::GetGameHeightRes() < WMAP_WIN_HEIGHT || Graphics::GetGameWidthRes() < WMAP_WIN_WIDTH) return; + if (!fo::func::db_access("art\\intrface\\worldmap.frm")) return; + dlog("Applying expanded world map interface patch.", DL_INIT); + + mapSlotsScrollMax -= 216; + if (mapSlotsScrollMax < 0) mapSlotsScrollMax = 0; + + fo::var::wmViewportRightScrlLimit = (350 * fo::var::wmNumHorizontalTiles) - (WMAP_WIN_WIDTH - (640 - 450)); + fo::var::wmViewportBottomtScrlLimit = (300 * (fo::var::wmMaxTileNum / fo::var::wmNumHorizontalTiles)) - (WMAP_WIN_HEIGHT - (480 - 443)); + + SafeWriteBatch(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(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); + if (worldmapInterface == 1) { + HookCall(0x4C4CD5, wmTownMapRefresh_hook_textpos); + HookCall(0x4C4B8F, wmTownMapInit_hook); + } + // up/down buttons of the location list (wmInterfaceInit_) + SafeWriteBatch(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(WMAP_WIN_HEIGHT - (480 - 465), { // height/offset by Y (465 - 21 = 444 (443)) + 0x4C0154, 0x4C02BA, // wmWorldMap_ + 0x4C3A47, // wmInterfaceRefresh_ + }); + SafeWriteBatch(WMAP_WIN_WIDTH - (640 - 472), { // width/offset by X (472 - 22 = 450) + 0x4C0159, 0x4C02BF, // wmWorldMap_ + 0x4C3A3A, // wmInterfaceRefresh_ + 0x4C417C, 0x4C4184 // wmInterfaceDrawSubTileList_ + }); + SafeWriteBatch(WMAP_WIN_HEIGHT - (480 - 464), { // width/offset by X (464) + 0x4C3FED, // wmInterfaceDrawCircleOverlay_ + 0x4C4157, 0x4C415F, // wmInterfaceDrawSubTileList_ + }); + // right limit of the viewport (450) + SafeWriteBatch(WMAP_WIN_WIDTH - (640 - 450), wmViewportEndRight); // 890 - 190 = 700 + 22 = 722 + // bottom limit of the viewport (443) + SafeWriteBatch(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((WMAP_WIN_WIDTH * 136) - ((640 * 136) - 86901), { + 0x4C52C4, 0x4C55AA // wmRefreshTabs_ + }); + SafeWrite32(0x4C52FF, (WMAP_WIN_WIDTH * 139) - ((640 * 139) - 88850)); // wmRefreshTabs_ + SafeWriteBatch((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(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(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)&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); +} + +static void WorldMapInterfacePatch() { + if (GetConfigInt("Misc", "WorldMapFontPatch", 0)) { + dlog("Applying world map font patch.", DL_INIT); + HookCall(0x4C2343, wmInterfaceInit_text_font_hook); + dlogr(" Done", DL_INIT); + } + // 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 + + //if(GetConfigInt("Misc", "WorldMapCitiesListFix", 0)) { + dlog("Applying world map cities list patch.", DL_INIT); + HookCalls(ScrollCityListFix, {0x4C04B9, 0x4C04C8, 0x4C4A34, 0x4C4A3D}); + dlogr(" Done", DL_INIT); + //} + + DWORD wmSlots = GetConfigInt("Misc", "WorldMapSlots", 0); + if (wmSlots && wmSlots < 128) { + dlog("Applying world map slots patch.", DL_INIT); + if (wmSlots < 7) wmSlots = 7; + mapSlotsScrollMax = (wmSlots - 7) * 27; // height value after which scrolling is not possible + mapSlotsScrollLimit = wmSlots * 27; + SafeWrite32(0x4C21FD, 189); // 27 * 7 + SafeWrite32(0x4C21F1, (DWORD)&mapSlotsScrollLimit); + dlogr(" Done", DL_INIT); + } + + if (hrpIsEnabled) { + if (worldmapInterface = GetConfigInt("Interface", "WorldMapInterface", 0)) { + LoadGameHook::OnAfterGameInit() += WorldmapViewportPatch; // Note: must be applied after WorldMapSlots patch + } + } +} + +void Interface::init() { + hrpIsEnabled = (*(DWORD*)0x4E4480 != 0x278805C7); // check if HRP is enabled + + if (GetConfigInt("Interface", "ActionPointsBar", 0)) { + ActionPointsBarPatch(); + if (hrpIsEnabled) LoadGameHook::OnAfterGameInit() += APBarRectPatch; + } + + WorldMapInterfacePatch(); +} + +void Interface::exit() { + if (ifaceFrm) delete ifaceFrm; +} + +} diff --git a/sfall/Modules/Interface.h b/sfall/Modules/Interface.h new file mode 100644 index 00000000..c9ec2dba --- /dev/null +++ b/sfall/Modules/Interface.h @@ -0,0 +1,15 @@ +#pragma once + +#include "Module.h" + +namespace sfall +{ + +class Interface : public Module { +public: + const char* name() { return "Interface"; } + void init(); + void exit() override; +}; + +} diff --git a/sfall/Modules/Worldmap.cpp b/sfall/Modules/Worldmap.cpp index ecfed2a7..d6d1afd1 100644 --- a/sfall/Modules/Worldmap.cpp +++ b/sfall/Modules/Worldmap.cpp @@ -1,27 +1,26 @@ /* -* sfall -* Copyright (C) 2008-2017 The sfall team -* -* This program is free software: you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation, either version 3 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program. If not, see . -*/ + * sfall + * Copyright (C) 2008-2017 The sfall team + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ #include #include #include "..\main.h" #include "..\FalloutEngine\Fallout2.h" -#include "Graphics.h" #include "LoadGameHook.h" #include "ScriptExtender.h" #include "SpeedPatch.h" @@ -47,9 +46,6 @@ static bool restMap; static bool restMode; static bool restTime; -static int mapSlotsScrollMax = 27 * (17 - 7); -static int mapSlotsScrollLimit = 0; - static DWORD worldMapDelay; static DWORD worldMapTicks; @@ -124,26 +120,6 @@ end: } } -static __declspec(naked) void ScrollCityListFix() { - __asm { - push ebx; - mov ebx, ds:[0x672F10]; // _wmLastTabsYOffset - test eax, eax; - jl up; - cmp ebx, mapSlotsScrollMax; - pop ebx; - jl run; - retn; -up: - test ebx, ebx; - pop ebx; - jnz run; - retn; -run: - jmp fo::funcoffs::wmInterfaceScrollTabsStart_; - } -} - static void __stdcall WorldmapLoopHook() { onWorldmapLoop.invoke(); } @@ -286,13 +262,6 @@ static __declspec(naked) void PathfinderFix() { } } -static void __declspec(naked) wmInterfaceInit_text_font_hook() { - __asm { - mov eax, 0x65; // normal text font - jmp fo::funcoffs::text_font_; - } -} - static void __declspec(naked) critter_can_obj_dude_rest_hook() { using namespace fo; __asm { @@ -370,12 +339,6 @@ void WorldLimitsPatches() { dlogr(" Done", DL_INIT); } - //if(GetConfigInt("Misc", "WorldMapCitiesListFix", 0)) { - dlog("Applying world map cities list patch.", DL_INIT); - HookCalls(ScrollCityListFix, {0x4C04B9, 0x4C04C8, 0x4C4A34, 0x4C4A3D}); - dlogr(" Done", DL_INIT); - //} - //if(GetConfigInt("Misc", "CitiesLimitFix", 0)) { dlog("Applying cities limit patch.", DL_INIT); if (*((BYTE*)0x4BF3BB) != 0xEB) { @@ -383,17 +346,6 @@ void WorldLimitsPatches() { } dlogr(" Done", DL_INIT); //} - - DWORD wmSlots = GetConfigInt("Misc", "WorldMapSlots", 0); - if (wmSlots && wmSlots < 128) { - dlog("Applying world map slots patch.", DL_INIT); - if (wmSlots < 7) wmSlots = 7; - mapSlotsScrollMax = (wmSlots - 7) * 27; // height value after which scrolling is not possible - mapSlotsScrollLimit = wmSlots * 27; - SafeWrite32(0x4C21FD, 189); // 27 * 7 - SafeWrite32(0x4C21F1, (DWORD)&mapSlotsScrollLimit); - dlogr(" Done", DL_INIT); - } } void TimeLimitPatch() { @@ -525,19 +477,6 @@ void StartingStatePatches() { if (ViewportX != -1 || ViewportY != -1) HookCall(0x4BCF07, ViewportHook); // game_reset_ } -void WorldMapInterfacePatch() { - if (GetConfigInt("Misc", "WorldMapFontPatch", 0)) { - dlog("Applying world map font patch.", DL_INIT); - HookCall(0x4C2343, wmInterfaceInit_text_font_hook); - dlogr(" Done", DL_INIT); - } - // 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 -} - void PipBoyAutomapsPatch() { dlog("Applying Pip-Boy automaps patch.", DL_INIT); MakeCall(0x4BF931, wmMapInit_hack, 2); @@ -657,284 +596,6 @@ 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) -static int worldmapInterface; - -// 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[] = { -// 0x4BC91F, // wmWorldMap_init_ - 0x4C3937, 0x4C393E, 0x4C39BB, 0x4C3B2F, 0x4C3B36, 0x4C3C4B, // wmInterfaceRefresh_ - 0x4C4288, 0x4C436A, 0x4C4409, // wmDrawCursorStopped_ - 0x4C44B4, // wmCursorIsVisible_ -}; - -// Bottom limit of viewport (443) -static const DWORD wmViewportEndBottom[] = { -// 0x4BC947, // wmWorldMap_init_ - 0x4C3963, 0x4C38D7, 0x4C39DA, 0x4C3B62, 0x4C3AE7, 0x4C3C74, // wmInterfaceRefresh_ - 0x4C429A, 0x4C4378, 0x4C4413, // wmDrawCursorStopped_ - 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 - } -} - -static void __declspec(naked) wmTownMapRefresh_hook_textpos() { - __asm { - push eax; - push ebx; - mov eax, ecx; // xpos - shr ebx, 2; // text_width / 4 - test ebx, ebx; - jz skipX; - sub ebx, 5; // x adjust -skipX: - sar eax, 1; - add ecx, eax; // xpos * 1.5 - add ecx, ebx; - pop ebx; - mov eax, dword ptr [esp + 8]; // ypos - sar eax, 1; - test eax, eax; - jz skipY; - sub eax, 5; // y adjust -skipY: - add dword ptr [esp + 8], eax; // ypos * 1.5 - pop eax; - jmp fo::funcoffs::win_print_; - } -} - -static void __declspec(naked) wmTownMapInit_hook() { - __asm { - push eax; - mov eax, edx; // xpos - shr eax, 1; - add edx, eax; // xpos * 1.5 - mov eax, ebx; // ypos - shr eax, 1; - add ebx, eax; // ypos * 1.5 - pop eax; - jmp fo::funcoffs::win_register_button_; - } -} - -void WorldmapViewportPatch() { - if (Graphics::GetGameHeightRes() < WMAP_WIN_HEIGHT || Graphics::GetGameWidthRes() < WMAP_WIN_WIDTH) return; - if (!fo::func::db_access("art\\intrface\\worldmap.frm")) return; - dlog("Applying world map interface patch.", DL_INIT); - - mapSlotsScrollMax -= 216; - if (mapSlotsScrollMax < 0) mapSlotsScrollMax = 0; - - fo::var::wmViewportRightScrlLimit = (350 * fo::var::wmNumHorizontalTiles) - (WMAP_WIN_WIDTH - (640 - 450)); - fo::var::wmViewportBottomtScrlLimit = (300 * (fo::var::wmMaxTileNum / fo::var::wmNumHorizontalTiles)) - (WMAP_WIN_HEIGHT - (480 - 443)); - - SafeWriteBatch(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(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); - if (worldmapInterface == 1) { - HookCall(0x4C4CD5, wmTownMapRefresh_hook_textpos); - HookCall(0x4C4B8F, wmTownMapInit_hook); - } - // up/down buttons of the location list (wmInterfaceInit_) - SafeWriteBatch(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(WMAP_WIN_HEIGHT - (480 - 465), { // height/offset by Y (465 - 21 = 444 (443)) - 0x4C0154, 0x4C02BA, // wmWorldMap_ - 0x4C3A47, // wmInterfaceRefresh_ - }); - SafeWriteBatch(WMAP_WIN_WIDTH - (640 - 472), { // width/offset by X (472 - 22 = 450) - 0x4C0159, 0x4C02BF, // wmWorldMap_ - 0x4C3A3A, // wmInterfaceRefresh_ - 0x4C417C, 0x4C4184 // wmInterfaceDrawSubTileList_ - }); - SafeWriteBatch(WMAP_WIN_HEIGHT - (480 - 464), { // width/offset by X (464) - 0x4C3FED, // wmInterfaceDrawCircleOverlay_ - 0x4C4157, 0x4C415F, // wmInterfaceDrawSubTileList_ - }); - // right limit of the viewport (450) - SafeWriteBatch(WMAP_WIN_WIDTH - (640 - 450), wmViewportEndRight); // 890 - 190 = 700 + 22 = 722 - // bottom limit of the viewport (443) - SafeWriteBatch(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((WMAP_WIN_WIDTH * 136) - ((640 * 136) - 86901), { - 0x4C52C4, 0x4C55AA // wmRefreshTabs_ - }); - SafeWrite32(0x4C52FF, (WMAP_WIN_WIDTH * 139) - ((640 * 139) - 88850)); // wmRefreshTabs_ - SafeWriteBatch((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(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(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)&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(); @@ -942,13 +603,8 @@ void Worldmap::init() { TownMapsHotkeyFix(); WorldLimitsPatches(); WorldmapFpsPatch(); - WorldMapInterfacePatch(); PipBoyAutomapsPatch(); - worldmapInterface = GetConfigInt("Misc", "WorldMapInterface", 0); - if (worldmapInterface && *(DWORD*)0x4E4480 != 0x278805C7) { // check if HRP is enabled - LoadGameHook::OnAfterGameInit() += WorldmapViewportPatch; // Note: must be applied after WorldMapSlots patch - } LoadGameHook::OnGameReset() += []() { SetCarInterfaceArt(433); // set index if (restTime) SetRestHealTime(180); diff --git a/sfall/ddraw.vcxproj b/sfall/ddraw.vcxproj index 5bf818ca..4f293bf3 100644 --- a/sfall/ddraw.vcxproj +++ b/sfall/ddraw.vcxproj @@ -259,6 +259,7 @@ stdafx.h;%(ForcedIncludeFiles) true false + AssemblyAndSourceCode kernel32.lib;user32.lib;d3d9.lib;d3dx9.lib;Strmiids.lib;dinput.lib;ws2_32.lib;%(AdditionalDependencies) @@ -295,6 +296,7 @@ + @@ -385,6 +387,7 @@ + diff --git a/sfall/ddraw.vcxproj.filters b/sfall/ddraw.vcxproj.filters index 03d437a6..2e04296f 100644 --- a/sfall/ddraw.vcxproj.filters +++ b/sfall/ddraw.vcxproj.filters @@ -281,6 +281,9 @@ Modules + + Modules + @@ -522,6 +525,9 @@ Modules + + Modules + diff --git a/sfall/main.cpp b/sfall/main.cpp index 22b384ce..61624cbc 100644 --- a/sfall/main.cpp +++ b/sfall/main.cpp @@ -45,6 +45,7 @@ #include "Modules\HookScripts.h" #include "Modules\HeroAppearance.h" #include "Modules\Input.h" +#include "Modules\Interface.h" #include "Modules\Inventory.h" #include "Modules\Karma.h" #include "Modules\KillCounter.h" @@ -139,6 +140,7 @@ static void InitModules() { manager.add(); manager.add(); manager.add(); + manager.add(); manager.add(); manager.add(); manager.add(); @@ -151,7 +153,6 @@ static void InitModules() { manager.add(); manager.add(); manager.add(); - manager.add(); manager.add(); manager.add(); manager.add(); @@ -171,7 +172,8 @@ static void InitModules() { manager.add(); manager.add(); manager.add(); - + manager.add(); + // manager.add(); manager.add(); manager.add();