Refactored and fixed SpeedPatch module (from Mr.Stalin)

This commit is contained in:
NovaRain
2019-02-08 10:31:03 +08:00
parent d13f33e2ff
commit af531a3e1d
7 changed files with 142 additions and 123 deletions
+10 -7
View File
@@ -34,18 +34,21 @@ Enable=1
;The speeds corresponding to each slot in percent. (i.e. 100 is normal speed) ;The speeds corresponding to each slot in percent. (i.e. 100 is normal speed)
SpeedMulti0=50 SpeedMulti0=50
SpeedMulti1=100 SpeedMulti1=100
SpeedMulti2=150 SpeedMulti2=200
SpeedMulti3=200 SpeedMulti3=300
SpeedMulti4=300 SpeedMulti4=400
SpeedMulti5=500 SpeedMulti5=500
SpeedMulti6=1000 SpeedMulti6=600
SpeedMulti7=100 SpeedMulti7=700
SpeedMulti8=100 SpeedMulti8=800
SpeedMulti9=100 SpeedMulti9=900
;The initial speed at game startup ;The initial speed at game startup
SpeedMultiInitial=100 SpeedMultiInitial=100
;Set to 1 to also affect video playback and slideshow speed
AffectPlayback=0
;XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ;XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
[Graphics] [Graphics]
;Set to 0 for 8 bit fullscreen ;Set to 0 for 8 bit fullscreen
+13 -15
View File
@@ -49,7 +49,7 @@ static double mousePartX;
static double mousePartY; static double mousePartY;
#define MAX_KEYS (264) #define MAX_KEYS (264)
static DWORD keysDown[MAX_KEYS]; static DWORD keysDown[MAX_KEYS] = {0};
static int mouseX; static int mouseX;
static int mouseY; static int mouseY;
@@ -125,9 +125,9 @@ void _stdcall TapKey(DWORD key) {
data.dwTimeStamp = 0; data.dwTimeStamp = 0;
data.dwSequence = 0; data.dwSequence = 0;
data.dwOfs = key; data.dwOfs = key;
data.dwData = 0x80; data.dwData = 0x80; // flag pressed
bufferedPresses.push(data); bufferedPresses.push(data);
data.dwData = 0x00; data.dwData = 0x00; // flag released
bufferedPresses.push(data); bufferedPresses.push(data);
} }
@@ -193,7 +193,7 @@ public:
return RealDevice->Unacquire(); return RealDevice->Unacquire();
} }
//Only called for the mouse // Only called for the mouse
HRESULT _stdcall GetDeviceState(DWORD a, LPVOID b) { HRESULT _stdcall GetDeviceState(DWORD a, LPVOID b) {
if (forcingGraphicsRefresh) RefreshGraphics(); if (forcingGraphicsRefresh) RefreshGraphics();
if (DeviceType != kDeviceType_MOUSE) { if (DeviceType != kDeviceType_MOUSE) {
@@ -212,10 +212,10 @@ public:
MouseState.rgbButtons[1] = tmp; MouseState.rgbButtons[1] = tmp;
} }
if (adjustMouseSpeed) { if (adjustMouseSpeed) {
double d = ((double)MouseState.lX)*mouseSpeedMod + mousePartX; double d = ((double)MouseState.lX) * mouseSpeedMod + mousePartX;
mousePartX = modf(d, &d); mousePartX = modf(d, &d);
MouseState.lX = (LONG)d; MouseState.lX = (LONG)d;
d = ((double)MouseState.lY)*mouseSpeedMod + mousePartY; d = ((double)MouseState.lY) * mouseSpeedMod + mousePartY;
mousePartY = modf(d, &d); mousePartY = modf(d, &d);
MouseState.lY = (LONG)d; MouseState.lY = (LONG)d;
} }
@@ -263,7 +263,7 @@ public:
return 0; return 0;
} }
//Only called for the keyboard // Only called for the keyboard
HRESULT _stdcall GetDeviceData(DWORD a, DIDEVICEOBJECTDATA* b, DWORD* c, DWORD d) { HRESULT _stdcall GetDeviceData(DWORD a, DIDEVICEOBJECTDATA* b, DWORD* c, DWORD d) {
if (DeviceType != kDeviceType_KEYBOARD) { if (DeviceType != kDeviceType_KEYBOARD) {
return RealDevice->GetDeviceData(a, b, c, d); return RealDevice->GetDeviceData(a, b, c, d);
@@ -271,7 +271,7 @@ public:
onInputLoop.invoke(); onInputLoop.invoke();
if (!b || bufferedPresses.empty() || (d&DIGDD_PEEK)) { if (!b || bufferedPresses.empty() || (d & DIGDD_PEEK)) {
HRESULT hr = RealDevice->GetDeviceData(a, b, c, d); HRESULT hr = RealDevice->GetDeviceData(a, b, c, d);
if (FAILED(hr) || !b || !(*c)) return hr; if (FAILED(hr) || !b || !(*c)) return hr;
for (DWORD i = 0; i < *c; i++) { for (DWORD i = 0; i < *c; i++) {
@@ -295,7 +295,7 @@ public:
} }
HRESULT _stdcall SetDataFormat(const DIDATAFORMAT* a) { HRESULT _stdcall SetDataFormat(const DIDATAFORMAT* a) {
if (formatLock&&oldFormat.dwSize) return RealDevice->SetDataFormat(&oldFormat); if (formatLock && oldFormat.dwSize) return RealDevice->SetDataFormat(&oldFormat);
memcpy(&oldFormat, a, sizeof(DIDATAFORMAT)); memcpy(&oldFormat, a, sizeof(DIDATAFORMAT));
return RealDevice->SetDataFormat(a); return RealDevice->SetDataFormat(a);
} }
@@ -305,8 +305,8 @@ public:
} }
HRESULT _stdcall SetCooperativeLevel(HWND a, DWORD b) { HRESULT _stdcall SetCooperativeLevel(HWND a, DWORD b) {
if (DeviceType == kDeviceType_KEYBOARD&&backgroundKeyboard) b = DISCL_BACKGROUND | DISCL_NONEXCLUSIVE; if (DeviceType == kDeviceType_KEYBOARD && backgroundKeyboard) b = DISCL_BACKGROUND | DISCL_NONEXCLUSIVE;
if (DeviceType == kDeviceType_MOUSE&&backgroundMouse) b = DISCL_BACKGROUND | DISCL_NONEXCLUSIVE; if (DeviceType == kDeviceType_MOUSE && backgroundMouse) b = DISCL_BACKGROUND | DISCL_NONEXCLUSIVE;
return RealDevice->SetCooperativeLevel(a, b); return RealDevice->SetCooperativeLevel(a, b);
} }
@@ -362,8 +362,8 @@ public:
/*** IDirectInput8A methods ***/ /*** IDirectInput8A methods ***/
HRESULT _stdcall CreateDevice(REFGUID r, IDirectInputDeviceA** device, IUnknown* unused) { HRESULT _stdcall CreateDevice(REFGUID r, IDirectInputDeviceA** device, IUnknown* unused) {
GUID GUID_SysMouse = { 0x6F1D2B60, 0xD5A0, 0x11CF, { 0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00} }; GUID GUID_SysMouse = { 0x6F1D2B60, 0xD5A0, 0x11CF, { 0xBF, 0xC7, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00} };
GUID GUID_SysKeyboard = { 0x6F1D2B61, 0xD5A0, 0x11CF, { 0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00} }; GUID GUID_SysKeyboard = { 0x6F1D2B61, 0xD5A0, 0x11CF, { 0xBF, 0xC7, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00} };
if (r != GUID_SysKeyboard && r != GUID_SysMouse) { if (r != GUID_SysKeyboard && r != GUID_SysMouse) {
return RealInput->CreateDevice(r, device, unused); return RealInput->CreateDevice(r, device, unused);
@@ -406,8 +406,6 @@ public:
}; };
inline void InitInputFeatures() { inline void InitInputFeatures() {
ZeroMemory(keysDown, sizeof(keysDown));
reverseMouse = GetConfigInt("Input", "ReverseMouseButtons", 0) != 0; reverseMouse = GetConfigInt("Input", "ReverseMouseButtons", 0) != 0;
useScrollWheel = GetConfigInt("Input", "UseScrollWheel", 1) != 0; useScrollWheel = GetConfigInt("Input", "UseScrollWheel", 1) != 0;
+3 -5
View File
@@ -10,18 +10,16 @@
namespace sfall namespace sfall
{ {
static const DWORD dinputPos = 0x50FB70;
void Input::init() { void Input::init() {
//if(GetConfigInt("Input", "Enable", 0)) { //if(GetConfigInt("Input", "Enable", 0)) {
dlog("Applying input patch.", DL_INIT); dlog("Applying input patch.", DL_INIT);
SafeWriteStr(dinputPos, "ddraw.dll"); SafeWriteStr(0x50FB70, "ddraw.dll");
::sfall::availableGlobalScriptTypes |= 1; ::sfall::availableGlobalScriptTypes |= 1;
dlogr(" Done", DL_INIT); dlogr(" Done", DL_INIT);
//} //}
LoadGameHook::OnGameReset() += []() { LoadGameHook::OnGameReset() += []() {
ForceGraphicsRefresh(0); ForceGraphicsRefresh(0); // disable refresh
}; };
} }
+1 -2
View File
@@ -17,7 +17,6 @@
*/ */
#include "..\..\FalloutEngine\Fallout2.h" #include "..\..\FalloutEngine\Fallout2.h"
#include "..\..\InputFuncs.h"
#include "..\KillCounter.h" #include "..\KillCounter.h"
#include "Handlers\Anims.h" #include "Handlers\Anims.h"
@@ -258,7 +257,7 @@ void InitNewOpcodes() {
opcodes[0x169] = op_deactivate_shader; opcodes[0x169] = op_deactivate_shader;
opcodes[0x16a] = op_set_global_script_repeat; opcodes[0x16a] = op_set_global_script_repeat;
opcodes[0x16b] = op_input_funcs_available; opcodes[0x16b] = op_input_funcs_available;
opcodes[0x16c] = defaultOpcodeHandler;
opcodes[0x16d] = op_set_shader_int; opcodes[0x16d] = op_set_shader_int;
opcodes[0x16e] = op_set_shader_float; opcodes[0x16e] = op_set_shader_float;
opcodes[0x16f] = op_set_shader_vector; opcodes[0x16f] = op_set_shader_vector;
+107 -90
View File
@@ -21,91 +21,99 @@
#include "..\main.h" #include "..\main.h"
#include "..\FalloutEngine\Fallout2.h" #include "..\FalloutEngine\Fallout2.h"
#include "..\InputFuncs.h" #include "..\InputFuncs.h"
#include "LoadGameHook.h"
#include "SpeedPatch.h" #include "SpeedPatch.h"
namespace sfall namespace sfall
{ {
//GetTickCount calls static const DWORD offsets[] = {
static const DWORD offsetsA[] = { // GetTickCount calls
0x4C8D34, 0x4C9375, 0x4C9384, 0x4C93C0, 0x4C93E8, 0x4C9D2E, 0x4FE01E, 0x4C9375, 0x4C93E8, 0x4C93C0, 0x4FE01E,
}; 0x4C9384, 0x4C9D2E, 0x4C8D34,
// Delayed GetTickCount calls
//Delayed GetTickCount calls
static const DWORD offsetsB[] = {
0x4FDF64, 0x4FDF64,
// timeGetTime calls
0x4A3179, 0x4A325D, 0x4F482B, 0x4FE036,
0x4F4E53, 0x4F5542, 0x4F56CC, 0x4F59C6, // for mve
}; };
//timeGetTime calls DWORD sf_GetTickCount = (DWORD)&GetTickCount;
static const DWORD offsetsC[] = { //DWORD sf_GetLocalTime;
0x4A3179, 0x4A325D, 0x4F482B, 0x4F4E53, 0x4F5542, 0x4F56CC, 0x4F59C6,
0x4FE036,
};
static const DWORD getLocalTimePos = 0x4FDF58; static bool enabled = true;
static DWORD addrGetTickCount; static bool toggled = false;
static DWORD addrGetLocalTime; static bool slideShow = false;
static bool Enabled; static double multi;
static bool Toggled; static DWORD storedTickCount = 0;
static DWORD lastTickCount;
static double tickCountFraction = 0.0;
static double Multi; static __int64 startTime;
static DWORD StoredTickCount;
static DWORD LastTickCount;
static double TickCountFraction;
static __int64 StartTime; static struct SpeedCfg {
int key;
double multiplier;
} *speed = nullptr;
static double Multipliers[10]; static int modKey;
static int Keys[10]; static int toggleKey;
static int ModKey;
static int ToggleKey;
DWORD _stdcall FakeGetTickCount() { static DWORD _stdcall FakeGetTickCount() {
//Keyboard control // Keyboard control
if (!ModKey || (ModKey > 0 && KeyDown(ModKey)) if (modKey && ((modKey > 0 && KeyDown(modKey))
|| (ModKey == -1 && (KeyDown(DIK_LCONTROL) || KeyDown(DIK_RCONTROL))) || (modKey == -1 && (KeyDown(DIK_LCONTROL) || KeyDown(DIK_RCONTROL)))
|| (ModKey == -2 && (KeyDown(DIK_LMENU) || KeyDown(DIK_RMENU))) || (modKey == -2 && (KeyDown(DIK_LMENU) || KeyDown(DIK_RMENU)))
|| (ModKey == -3 && (KeyDown(DIK_LSHIFT) || KeyDown(DIK_RSHIFT))) || (modKey == -3 && (KeyDown(DIK_LSHIFT) || KeyDown(DIK_RSHIFT)))))
) { {
if (toggleKey && KeyDown(toggleKey)) {
for (int i = 0; i < 10; i++) if (Keys[i] && KeyDown(Keys[i])) { if (!toggled) {
Multi = Multipliers[i]; toggled = true;
} enabled = !enabled;
if (ToggleKey&&KeyDown(ToggleKey)) {
if (!Toggled) {
Toggled = true;
Enabled = !Enabled;
} }
} else { } else {
Toggled = false; toggled = false;
for (int i = 0; i < 10; i++) {
int key = speed[i].key;
if (key && KeyDown(key)) {
multi = speed[i].multiplier;
break;
}
}
} }
} }
DWORD NewTickCount = GetTickCount(); DWORD newTickCount = GetTickCount();
//Just in case someone's been running their computer for 49 days straight // Just in case someone's been running their computer for 49 days straight
if (NewTickCount < LastTickCount) { if (newTickCount < lastTickCount) {
NewTickCount = LastTickCount; newTickCount = lastTickCount;
return StoredTickCount; return storedTickCount;
} }
//Multiply the tick count difference by the multiplier double elapsed = (double)(newTickCount - lastTickCount);
double add = (double)(NewTickCount - LastTickCount)*(Enabled ? Multi : 1.0); lastTickCount = newTickCount;
LastTickCount = NewTickCount;
TickCountFraction += modf(add, &add); // Multiply the tick count difference by the multiplier
StoredTickCount += (DWORD)add; if (enabled && !slideShow
if (TickCountFraction > 1) { && !(GetLoopFlags() & (LoopFlag::INVENTORY | LoopFlag::INTFACEUSE | LoopFlag::INTFACELOOT | LoopFlag::DIALOG)))
TickCountFraction -= 1; {
StoredTickCount++; elapsed *= multi;
tickCountFraction += modf(elapsed, &elapsed);
} }
return StoredTickCount; storedTickCount += (DWORD)elapsed;
if (tickCountFraction > 1.0) {
tickCountFraction -= 1.0;
storedTickCount++;
}
return storedTickCount;
} }
void _stdcall FakeGetLocalTime(LPSYSTEMTIME time) { void _stdcall FakeGetLocalTime(LPSYSTEMTIME time) {
__int64 CurrentTime = StartTime + StoredTickCount * 10000; __int64 currentTime = startTime + storedTickCount * 10000;
FileTimeToSystemTime((FILETIME*)&CurrentTime, time); FileTimeToSystemTime((FILETIME*)&currentTime, time);
} }
//Could divide 'uDelay' by 'Multi', but doesn't seem to have any effect. //Could divide 'uDelay' by 'Multi', but doesn't seem to have any effect.
@@ -117,56 +125,65 @@ MMRESULT _stdcall fTimeKillEvent(UINT id) {
return timeKillEvent(id); return timeKillEvent(id);
}*/ }*/
static void __declspec(naked) scripts_check_state_hook() {
__asm {
inc slideShow;
call fo::funcoffs::endgame_slideshow_;
dec slideShow;
retn;
}
}
void TimerInit() { void TimerInit() {
StoredTickCount = 0; lastTickCount = GetTickCount();
LastTickCount = GetTickCount();
TickCountFraction = 0;
Multi = (double)GetConfigInt("Speed", "SpeedMultiInitial", 100) / 100.0;
Enabled = true;
Toggled = false;
SYSTEMTIME time; SYSTEMTIME time;
GetLocalTime(&time); GetLocalTime(&time);
SystemTimeToFileTime(&time, (FILETIME*)&StartTime); SystemTimeToFileTime(&time, (FILETIME*)&startTime);
ModKey = GetConfigInt("Input", "SpeedModKey", -1); speed = new SpeedCfg[10];
ToggleKey = GetConfigInt("Input", "SpeedToggleKey", 0);
char c[2]; char buf[2], spKey[10] = "SpeedKey#";
char key[12]; char spMulti[12] = "SpeedMulti#";
for (int i = 0; i < 10; i++) { for (int i = 0; i < 10; i++) {
_itoa_s(i, c, 10); _itoa_s(i, buf, 10);
strcpy_s(key, "SpeedKey"); spKey[8] = spMulti[10] = buf[0];
strcat_s(key, c); speed[i].key = GetConfigInt("Input", spKey, 0);
Keys[i] = GetConfigInt("Input", key, 0); speed[i].multiplier = GetConfigInt("Speed", spMulti, 0) / 100.0;
strcpy_s(key, "SpeedMulti");
strcat_s(key, c);
Multipliers[i] = GetConfigInt("Speed", key, 0x00) / 100.0;
} }
} }
void SpeedPatch::init() { void SpeedPatch::init() {
if (GetConfigInt("Speed", "Enable", 0)) { if (GetConfigInt("Speed", "Enable", 0)) {
modKey = GetConfigInt("Input", "SpeedModKey", 0);
int init = GetConfigInt("Speed", "SpeedMultiInitial", 100);
if (init == 100 && !modKey) return;
dlog("Applying speed patch.", DL_INIT); dlog("Applying speed patch.", DL_INIT);
addrGetTickCount = (DWORD)&FakeGetTickCount;
addrGetLocalTime = (DWORD)&FakeGetLocalTime;
for (int i = 0; i < sizeof(offsetsA) / 4; i++) { multi = (double)init / 100.0;
SafeWrite32(offsetsA[i], (DWORD)&addrGetTickCount); toggleKey = GetConfigInt("Input", "SpeedToggleKey", 0);
sf_GetTickCount = (DWORD)&FakeGetTickCount;
//sf_GetLocalTime = (DWORD)&FakeGetLocalTime;
int size = sizeof(offsets) / 4;
if (GetConfigInt("Speed", "AffectPlayback", 0) == 0) {
size -= 4;
HookCall(0x4A433E, scripts_check_state_hook);
} }
dlog(".", DL_INIT); for (int i = 0; i < size; i++) {
for (int i = 0; i < sizeof(offsetsB) / 4; i++) { SafeWrite32(offsets[i], (DWORD)&sf_GetTickCount);
SafeWrite32(offsetsB[i], (DWORD)&addrGetTickCount);
} }
dlog(".", DL_INIT); SafeWrite32(0x4FDF58, (DWORD)&FakeGetLocalTime);
for (int i = 0; i < sizeof(offsetsC) / 4; i++) {
SafeWrite32(offsetsC[i], (DWORD)&addrGetTickCount);
}
dlog(".", DL_INIT);
SafeWrite32(getLocalTimePos, (DWORD)&addrGetLocalTime);
TimerInit(); TimerInit();
dlogr(" Done", DL_INIT); dlogr(" Done", DL_INIT);
} }
} }
void SpeedPatch::exit() {
if (speed) delete[] speed;
}
} }
+3
View File
@@ -27,6 +27,9 @@ class SpeedPatch : public Module {
public: public:
const char* name() { return "SpeedPatch"; } const char* name() { return "SpeedPatch"; }
void init(); void init();
void exit() override;
}; };
extern DWORD sf_GetTickCount;
} }
+5 -4
View File
@@ -23,6 +23,7 @@
#include "..\FalloutEngine\Fallout2.h" #include "..\FalloutEngine\Fallout2.h"
#include "LoadGameHook.h" #include "LoadGameHook.h"
#include "ScriptExtender.h" #include "ScriptExtender.h"
#include "SpeedPatch.h"
#include "Worldmap.h" #include "Worldmap.h"
@@ -153,7 +154,7 @@ loopDelay:
call WorldmapLoopHook; call WorldmapLoopHook;
call fo::funcoffs::process_bk_; call fo::funcoffs::process_bk_;
subLoop: subLoop:
call GetTickCount; // current ticks call ds:[sf_GetTickCount]; // current ticks
mov edx, eax; mov edx, eax;
sub eax, ebx; // get elapsed time (cur.ticks - prev.ticks) sub eax, ebx; // get elapsed time (cur.ticks - prev.ticks)
cmp eax, 10; // delay - GetTickCount returns minimum difference of 15 units cmp eax, 10; // delay - GetTickCount returns minimum difference of 15 units
@@ -165,7 +166,7 @@ subLoop:
pop dword ptr ds:[0x6AC7B0]; // _mouse_buttons pop dword ptr ds:[0x6AC7B0]; // _mouse_buttons
pop dword ptr ds:[FO_VAR_last_buttons]; pop dword ptr ds:[FO_VAR_last_buttons];
call GetTickCount; call ds:[sf_GetTickCount];
mov worldMapTicks, eax; mov worldMapTicks, eax;
jmp fo::funcoffs::get_input_; jmp fo::funcoffs::get_input_;
} }
@@ -178,7 +179,7 @@ static void __declspec(naked) WorldMapFpsPatch2() {
loopDelay: loopDelay:
call WorldmapLoopHook; call WorldmapLoopHook;
subLoop: subLoop:
call GetTickCount; // current ticks call ds:[sf_GetTickCount]; // current ticks
mov edx, eax; mov edx, eax;
sub eax, ebx; // get elapsed time sub eax, ebx; // get elapsed time
jz subLoop; jz subLoop;
@@ -187,7 +188,7 @@ subLoop:
cmp edx, worldMapDelay; cmp edx, worldMapDelay;
jb loopDelay; // elapsed < worldMapDelay jb loopDelay; // elapsed < worldMapDelay
call GetTickCount; call ds:[sf_GetTickCount];
mov worldMapTicks, eax; mov worldMapTicks, eax;
jmp fo::funcoffs::get_input_; jmp fo::funcoffs::get_input_;
} }