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