Rewrote ASM code of WorldMapFPSPatch in C++

This commit is contained in:
NovaRain
2021-02-07 21:11:12 +08:00
parent 7c6f9df404
commit fe33dc2834
7 changed files with 98 additions and 92 deletions
+2 -1
View File
@@ -1,5 +1,5 @@
;sfall configuration settings
;v4.2.9
;v4.3
[Main]
;Change to 1 if you want to use command line args to tell sfall to use another ini file.
@@ -240,6 +240,7 @@ WorldMapTimeMod=100
WorldMapFPSPatch=1
;Controls the world map speed if WorldMapFPSPatch is 1. Higher values cause slower movement
;Default is 66 milliseconds
WorldMapDelay2=66
;Set to 1 to enable Ray's patch to make world map encounter rate independent of your travel speed
+2 -2
View File
@@ -37,13 +37,13 @@ long Items::item_weapon_mp_cost(fo::GameObject* source, fo::GameObject* weapon,
if (weapon) cost = 2; // default reload AP cost
}
return (cost != -1) ? sf::CalcApCostHook_CheckScript(source, hitMode, isCalled, cost, weapon) : cost;
return (cost != -1) ? sf::CalcApCostHook_ScriptCheck(source, hitMode, isCalled, cost, weapon) : cost;
}
// Implementation of item_w_mp_cost_ engine function with the HOOK_CALCAPCOST hook
long __fastcall Items::item_w_mp_cost(fo::GameObject* source, long hitMode, long isCalled) {
long cost = fo::func::item_w_mp_cost(source, hitMode, isCalled);
return sf::CalcApCostHook_CheckScript(source, hitMode, isCalled, cost, nullptr);
return sf::CalcApCostHook_ScriptCheck(source, hitMode, isCalled, cost, nullptr);
}
void Items::init() {
+1 -1
View File
@@ -97,7 +97,7 @@ static long CalcApCostHook_Script(fo::GameObject* source, long hitMode, long isC
return cost;
}
long CalcApCostHook_CheckScript(fo::GameObject* source, long hitMode, long isCalled, long cost, fo::GameObject* weapon) {
long CalcApCostHook_ScriptCheck(fo::GameObject* source, long hitMode, long isCalled, long cost, fo::GameObject* weapon) {
return (HookScripts::HookHasScript(HOOK_CALCAPCOST))
? CalcApCostHook_Script(source, hitMode, isCalled, cost, weapon)
: cost;
+1 -1
View File
@@ -21,6 +21,6 @@ void Inject_TargetObjectHook();
int __fastcall AmmoCostHook_Script(DWORD hookType, fo::GameObject* weapon, DWORD &rounds);
long CalcApCostHook_CheckScript(fo::GameObject* source, long hitMode, long isCalled, long cost, fo::GameObject* weapon);
long CalcApCostHook_ScriptCheck(fo::GameObject* source, long hitMode, long isCalled, long cost, fo::GameObject* weapon);
}
+27 -23
View File
@@ -1,20 +1,20 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
* 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 <http://www.gnu.org/licenses/>.
*/
#include <cmath>
@@ -39,8 +39,12 @@ static const DWORD offsets[] = {
0x4F4E53, 0x4F5542, 0x4F56CC, 0x4F59C6, // for mve
};
DWORD sf_GetTickCount = (DWORD)&GetTickCount;
DWORD sf_GetLocalTime;
static DWORD getLocalTimeOffs;
DWORD SpeedPatch::getTickCountOffs = (DWORD)&GetTickCount;
DWORD SpeedPatch::getTickCount() {
return ((DWORD (__stdcall*)())getTickCountOffs)();
}
static bool enabled = true;
static bool toggled = false;
@@ -146,7 +150,7 @@ void TimerInit() {
char buf[2], spKey[10] = "SpeedKey#";
char spMulti[12] = "SpeedMulti#";
for (int i = 0; i < 10; i++) {
_itoa_s(i, buf, 10);
_itoa(i, buf, 10);
spKey[8] = spMulti[10] = buf[0];
speed[i].key = GetConfigInt("Input", spKey, 0);
speed[i].multiplier = GetConfigInt("Speed", spMulti, 0) / 100.0;
@@ -164,16 +168,16 @@ void SpeedPatch::init() {
multi = (double)init / 100.0;
toggleKey = GetConfigInt("Input", "SpeedToggleKey", 0);
sf_GetTickCount = (DWORD)&FakeGetTickCount;
sf_GetLocalTime = (DWORD)&FakeGetLocalTime;
getTickCountOffs = (DWORD)&FakeGetTickCount;
getLocalTimeOffs = (DWORD)&FakeGetLocalTime;
int size = sizeof(offsets) / 4;
if (GetConfigInt("Speed", "AffectPlayback", 0) == 0) size -= 4;
for (int i = 0; i < size; i++) {
SafeWrite32(offsets[i], (DWORD)&sf_GetTickCount);
SafeWrite32(offsets[i], (DWORD)&getTickCountOffs);
}
SafeWrite32(0x4FDF58, (DWORD)&sf_GetLocalTime);
SafeWrite32(0x4FDF58, (DWORD)&getLocalTimeOffs);
HookCall(0x4A433E, scripts_check_state_hook);
TimerInit();
+21 -18
View File
@@ -1,20 +1,20 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
* 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 <http://www.gnu.org/licenses/>.
*/
#pragma once
@@ -28,8 +28,11 @@ public:
const char* name() { return "SpeedPatch"; }
void init();
void exit() override;
static DWORD getTickCountOffs;
// sfall implementation of the GetTickCount() function
static DWORD getTickCount();
};
extern DWORD sf_GetTickCount;
}
+44 -46
View File
@@ -52,6 +52,7 @@ static bool restMap;
static bool restMode;
static bool restTime;
static bool worldMapLongDelay = false;
static DWORD worldMapDelay;
static DWORD worldMapTicks;
@@ -130,52 +131,42 @@ end:
}
}
static void __declspec(naked) WorldMapFpsPatch() {
static void WorldMapFPS() {
DWORD prevTicks = worldMapTicks; // previous ticks
while (true) {
WorldmapLoopHook();
if (worldMapLongDelay) {
__asm call fo::funcoffs::process_bk_;
}
DWORD tick; // current ticks
while (true) {
tick = SpeedPatch::getTickCount();
// get elapsed time
if ((tick - prevTicks) >= 10) break; // delay 10 ms (GetTickCount returns a difference of 10-16 ms)
}
prevTicks = tick;
// get elapsed time
if ((tick - worldMapTicks) >= worldMapDelay) break;
}
worldMapTicks = prevTicks;
}
static void __declspec(naked) wmWorldMap_hook_patch1() {
__asm {
push dword ptr ds:[FO_VAR_last_buttons];
push dword ptr ds:[0x6AC7B0]; // _mouse_buttons
mov esi, worldMapTicks;
mov ebx, esi; // previous ticks
loopDelay:
call WorldmapLoopHook;
call fo::funcoffs::process_bk_;
subLoop:
call ds:[sf_GetTickCount]; // current ticks
mov edx, eax;
sub eax, ebx; // get elapsed time (cur.ticks - prev.ticks)
cmp eax, 10; // delay - GetTickCount returns minimum difference of 15 units
jb subLoop; // elapsed < invoke delay
mov ebx, edx;
sub edx, esi; // get elapsed time (cur.ticks - worldMapTicks)
cmp edx, worldMapDelay;
jb loopDelay; // elapsed < worldMapDelay
pop dword ptr ds:[0x6AC7B0]; // _mouse_buttons
push dword ptr ds:[FO_VAR_mouse_buttons];
call WorldMapFPS;
pop dword ptr ds:[FO_VAR_mouse_buttons];
pop dword ptr ds:[FO_VAR_last_buttons];
call ds:[sf_GetTickCount];
mov worldMapTicks, eax;
jmp fo::funcoffs::get_input_;
}
}
static void __declspec(naked) WorldMapFpsPatch2() {
static void __declspec(naked) wmWorldMap_hook_patch2() {
__asm {
mov esi, worldMapTicks;
mov ebx, esi;
loopDelay:
call WorldmapLoopHook;
subLoop:
call ds:[sf_GetTickCount]; // current ticks
mov edx, eax;
sub eax, ebx; // get elapsed time
jz subLoop;
mov ebx, edx;
sub edx, esi; // get elapsed time
cmp edx, worldMapDelay;
jb loopDelay; // elapsed < worldMapDelay
call ds:[sf_GetTickCount];
mov worldMapTicks, eax;
call WorldMapFPS;
jmp fo::funcoffs::get_input_;
}
}
@@ -183,9 +174,14 @@ subLoop:
// Only used if the world map speed patch is disabled, so that world map scripts are still run
static void __declspec(naked) wmWorldMap_hook() {
__asm {
//pushadc;
call ds:[SpeedPatch::getTickCountOffs]; // current ticks
mov edx, eax;
sub eax, worldMapTicks; // get elapsed time (cur.ticks - prev.ticks)
cmp eax, 10; // delay 10 ms (GetTickCount returns a difference of 10-16 ms)
jb skipHook;
mov worldMapTicks, edx;
call WorldmapLoopHook;
//popadc;
skipHook:
jmp fo::funcoffs::get_input_;
}
}
@@ -268,6 +264,7 @@ skip:
}
static const char* automap = "automap"; // no/yes overrides the value in the table to display the automap in pipboy
static void __declspec(naked) wmMapInit_hack() {
__asm {
mov esi, [esp + 0xA0 - 0x20 + 4]; // curent map number
@@ -401,12 +398,12 @@ static void WorldmapFpsPatch() {
bool fpsPatchOK = (*(DWORD*)0x4BFE5E == 0x8D16);
if (GetConfigInt("Misc", "WorldMapFPSPatch", 0)) {
dlog("Applying world map fps patch.", DL_INIT);
if (!fpsPatchOK) {
dlogr(" Failed", DL_INIT);
} else {
if (fpsPatchOK) {
int delay = GetConfigInt("Misc", "WorldMapDelay2", 66);
worldMapDelay = max(1, delay);
dlogr(" Done", DL_INIT);
} else {
dlogr(" Failed", DL_INIT);
}
}
if (fpsPatchOK) {
@@ -414,11 +411,12 @@ static void WorldmapFpsPatch() {
if (worldMapDelay == 0) {
func = wmWorldMap_hook;
} else if (worldMapDelay > 25) {
func = WorldMapFpsPatch;
worldMapLongDelay = true;
func = wmWorldMap_hook_patch1;
} else {
func = WorldMapFpsPatch2;
func = wmWorldMap_hook_patch2;
}
HookCall(0x4BFE5D, func);
HookCall(0x4BFE5D, func); // wmWorldMap_
::sfall::availableGlobalScriptTypes |= 2;
}