mirror of
https://github.com/sfall-team/sfall.git
synced 2026-07-27 16:52:34 -07:00
Rewrote ASM code of WorldMapFPSPatch in C++
This commit is contained in:
+2
-1
@@ -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
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
}
|
||||
|
||||
@@ -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
@@ -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
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user