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
|
;sfall configuration settings
|
||||||
;v4.2.9
|
;v4.3
|
||||||
|
|
||||||
[Main]
|
[Main]
|
||||||
;Change to 1 if you want to use command line args to tell sfall to use another ini file.
|
;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
|
WorldMapFPSPatch=1
|
||||||
|
|
||||||
;Controls the world map speed if WorldMapFPSPatch is 1. Higher values cause slower movement
|
;Controls the world map speed if WorldMapFPSPatch is 1. Higher values cause slower movement
|
||||||
|
;Default is 66 milliseconds
|
||||||
WorldMapDelay2=66
|
WorldMapDelay2=66
|
||||||
|
|
||||||
;Set to 1 to enable Ray's patch to make world map encounter rate independent of your travel speed
|
;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
|
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
|
// 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 __fastcall Items::item_w_mp_cost(fo::GameObject* source, long hitMode, long isCalled) {
|
||||||
long cost = fo::func::item_w_mp_cost(source, hitMode, 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() {
|
void Items::init() {
|
||||||
|
|||||||
@@ -97,7 +97,7 @@ static long CalcApCostHook_Script(fo::GameObject* source, long hitMode, long isC
|
|||||||
return cost;
|
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))
|
return (HookScripts::HookHasScript(HOOK_CALCAPCOST))
|
||||||
? CalcApCostHook_Script(source, hitMode, isCalled, cost, weapon)
|
? CalcApCostHook_Script(source, hitMode, isCalled, cost, weapon)
|
||||||
: cost;
|
: cost;
|
||||||
|
|||||||
@@ -21,6 +21,6 @@ void Inject_TargetObjectHook();
|
|||||||
|
|
||||||
int __fastcall AmmoCostHook_Script(DWORD hookType, fo::GameObject* weapon, DWORD &rounds);
|
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
|
* sfall
|
||||||
* Copyright (C) 2008-2017 The sfall team
|
* Copyright (C) 2008-2017 The sfall team
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
* (at your option) any later version.
|
* (at your option) any later version.
|
||||||
*
|
*
|
||||||
* This program is distributed in the hope that it will be useful,
|
* This program is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
|
||||||
@@ -39,8 +39,12 @@ static const DWORD offsets[] = {
|
|||||||
0x4F4E53, 0x4F5542, 0x4F56CC, 0x4F59C6, // for mve
|
0x4F4E53, 0x4F5542, 0x4F56CC, 0x4F59C6, // for mve
|
||||||
};
|
};
|
||||||
|
|
||||||
DWORD sf_GetTickCount = (DWORD)&GetTickCount;
|
static DWORD getLocalTimeOffs;
|
||||||
DWORD sf_GetLocalTime;
|
DWORD SpeedPatch::getTickCountOffs = (DWORD)&GetTickCount;
|
||||||
|
|
||||||
|
DWORD SpeedPatch::getTickCount() {
|
||||||
|
return ((DWORD (__stdcall*)())getTickCountOffs)();
|
||||||
|
}
|
||||||
|
|
||||||
static bool enabled = true;
|
static bool enabled = true;
|
||||||
static bool toggled = false;
|
static bool toggled = false;
|
||||||
@@ -146,7 +150,7 @@ void TimerInit() {
|
|||||||
char buf[2], spKey[10] = "SpeedKey#";
|
char buf[2], spKey[10] = "SpeedKey#";
|
||||||
char spMulti[12] = "SpeedMulti#";
|
char spMulti[12] = "SpeedMulti#";
|
||||||
for (int i = 0; i < 10; i++) {
|
for (int i = 0; i < 10; i++) {
|
||||||
_itoa_s(i, buf, 10);
|
_itoa(i, buf, 10);
|
||||||
spKey[8] = spMulti[10] = buf[0];
|
spKey[8] = spMulti[10] = buf[0];
|
||||||
speed[i].key = GetConfigInt("Input", spKey, 0);
|
speed[i].key = GetConfigInt("Input", spKey, 0);
|
||||||
speed[i].multiplier = GetConfigInt("Speed", spMulti, 0) / 100.0;
|
speed[i].multiplier = GetConfigInt("Speed", spMulti, 0) / 100.0;
|
||||||
@@ -164,16 +168,16 @@ void SpeedPatch::init() {
|
|||||||
multi = (double)init / 100.0;
|
multi = (double)init / 100.0;
|
||||||
toggleKey = GetConfigInt("Input", "SpeedToggleKey", 0);
|
toggleKey = GetConfigInt("Input", "SpeedToggleKey", 0);
|
||||||
|
|
||||||
sf_GetTickCount = (DWORD)&FakeGetTickCount;
|
getTickCountOffs = (DWORD)&FakeGetTickCount;
|
||||||
sf_GetLocalTime = (DWORD)&FakeGetLocalTime;
|
getLocalTimeOffs = (DWORD)&FakeGetLocalTime;
|
||||||
|
|
||||||
int size = sizeof(offsets) / 4;
|
int size = sizeof(offsets) / 4;
|
||||||
if (GetConfigInt("Speed", "AffectPlayback", 0) == 0) size -= 4;
|
if (GetConfigInt("Speed", "AffectPlayback", 0) == 0) size -= 4;
|
||||||
|
|
||||||
for (int i = 0; i < size; i++) {
|
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);
|
HookCall(0x4A433E, scripts_check_state_hook);
|
||||||
|
|
||||||
TimerInit();
|
TimerInit();
|
||||||
|
|||||||
+21
-18
@@ -1,20 +1,20 @@
|
|||||||
/*
|
/*
|
||||||
* sfall
|
* sfall
|
||||||
* Copyright (C) 2008-2017 The sfall team
|
* Copyright (C) 2008-2017 The sfall team
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
* (at your option) any later version.
|
* (at your option) any later version.
|
||||||
*
|
*
|
||||||
* This program is distributed in the hope that it will be useful,
|
* This program is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
@@ -28,8 +28,11 @@ public:
|
|||||||
const char* name() { return "SpeedPatch"; }
|
const char* name() { return "SpeedPatch"; }
|
||||||
void init();
|
void init();
|
||||||
void exit() override;
|
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 restMode;
|
||||||
static bool restTime;
|
static bool restTime;
|
||||||
|
|
||||||
|
static bool worldMapLongDelay = false;
|
||||||
static DWORD worldMapDelay;
|
static DWORD worldMapDelay;
|
||||||
static DWORD worldMapTicks;
|
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 {
|
__asm {
|
||||||
push dword ptr ds:[FO_VAR_last_buttons];
|
push dword ptr ds:[FO_VAR_last_buttons];
|
||||||
push dword ptr ds:[0x6AC7B0]; // _mouse_buttons
|
push dword ptr ds:[FO_VAR_mouse_buttons];
|
||||||
mov esi, worldMapTicks;
|
call WorldMapFPS;
|
||||||
mov ebx, esi; // previous ticks
|
pop dword ptr ds:[FO_VAR_mouse_buttons];
|
||||||
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
|
|
||||||
pop dword ptr ds:[FO_VAR_last_buttons];
|
pop dword ptr ds:[FO_VAR_last_buttons];
|
||||||
call ds:[sf_GetTickCount];
|
|
||||||
mov worldMapTicks, eax;
|
|
||||||
jmp fo::funcoffs::get_input_;
|
jmp fo::funcoffs::get_input_;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __declspec(naked) WorldMapFpsPatch2() {
|
static void __declspec(naked) wmWorldMap_hook_patch2() {
|
||||||
__asm {
|
__asm {
|
||||||
mov esi, worldMapTicks;
|
call WorldMapFPS;
|
||||||
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;
|
|
||||||
jmp fo::funcoffs::get_input_;
|
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
|
// Only used if the world map speed patch is disabled, so that world map scripts are still run
|
||||||
static void __declspec(naked) wmWorldMap_hook() {
|
static void __declspec(naked) wmWorldMap_hook() {
|
||||||
__asm {
|
__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;
|
call WorldmapLoopHook;
|
||||||
//popadc;
|
skipHook:
|
||||||
jmp fo::funcoffs::get_input_;
|
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 const char* automap = "automap"; // no/yes overrides the value in the table to display the automap in pipboy
|
||||||
|
|
||||||
static void __declspec(naked) wmMapInit_hack() {
|
static void __declspec(naked) wmMapInit_hack() {
|
||||||
__asm {
|
__asm {
|
||||||
mov esi, [esp + 0xA0 - 0x20 + 4]; // curent map number
|
mov esi, [esp + 0xA0 - 0x20 + 4]; // curent map number
|
||||||
@@ -401,12 +398,12 @@ static void WorldmapFpsPatch() {
|
|||||||
bool fpsPatchOK = (*(DWORD*)0x4BFE5E == 0x8D16);
|
bool fpsPatchOK = (*(DWORD*)0x4BFE5E == 0x8D16);
|
||||||
if (GetConfigInt("Misc", "WorldMapFPSPatch", 0)) {
|
if (GetConfigInt("Misc", "WorldMapFPSPatch", 0)) {
|
||||||
dlog("Applying world map fps patch.", DL_INIT);
|
dlog("Applying world map fps patch.", DL_INIT);
|
||||||
if (!fpsPatchOK) {
|
if (fpsPatchOK) {
|
||||||
dlogr(" Failed", DL_INIT);
|
|
||||||
} else {
|
|
||||||
int delay = GetConfigInt("Misc", "WorldMapDelay2", 66);
|
int delay = GetConfigInt("Misc", "WorldMapDelay2", 66);
|
||||||
worldMapDelay = max(1, delay);
|
worldMapDelay = max(1, delay);
|
||||||
dlogr(" Done", DL_INIT);
|
dlogr(" Done", DL_INIT);
|
||||||
|
} else {
|
||||||
|
dlogr(" Failed", DL_INIT);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (fpsPatchOK) {
|
if (fpsPatchOK) {
|
||||||
@@ -414,11 +411,12 @@ static void WorldmapFpsPatch() {
|
|||||||
if (worldMapDelay == 0) {
|
if (worldMapDelay == 0) {
|
||||||
func = wmWorldMap_hook;
|
func = wmWorldMap_hook;
|
||||||
} else if (worldMapDelay > 25) {
|
} else if (worldMapDelay > 25) {
|
||||||
func = WorldMapFpsPatch;
|
worldMapLongDelay = true;
|
||||||
|
func = wmWorldMap_hook_patch1;
|
||||||
} else {
|
} else {
|
||||||
func = WorldMapFpsPatch2;
|
func = wmWorldMap_hook_patch2;
|
||||||
}
|
}
|
||||||
HookCall(0x4BFE5D, func);
|
HookCall(0x4BFE5D, func); // wmWorldMap_
|
||||||
::sfall::availableGlobalScriptTypes |= 2;
|
::sfall::availableGlobalScriptTypes |= 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user