Refactored and fixed speed patch related code (from Mr.Stalin)

Rewrote ASM code of WorldMapFpsPatch functions.
This commit is contained in:
NovaRain
2019-02-08 12:53:13 +08:00
parent 823d2b92f7
commit 222f3eaf68
7 changed files with 246 additions and 220 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
+17 -17
View File
@@ -386,25 +386,25 @@ static OpcodeHandler opHandler;
If you don't include opcode in this array, you should take care of all argument validation inside handler itself. If you don't include opcode in this array, you should take care of all argument validation inside handler itself.
*/ */
static const SfallOpcodeMetadata opcodeMetaArray[] = { static const SfallOpcodeMetadata opcodeMetaArray[] = {
{sf_create_win, "create_win", {DATATYPE_MASK_STR, DATATYPE_MASK_INT, DATATYPE_MASK_INT, DATATYPE_MASK_INT, DATATYPE_MASK_INT, DATATYPE_MASK_INT}}, {sf_create_win, "create_win", {DATATYPE_MASK_STR, DATATYPE_MASK_INT, DATATYPE_MASK_INT, DATATYPE_MASK_INT, DATATYPE_MASK_INT, DATATYPE_MASK_INT}},
{sf_critter_inven_obj2, "critter_inven_obj2", {DATATYPE_MASK_VALID_OBJ, DATATYPE_MASK_INT}}, {sf_critter_inven_obj2, "critter_inven_obj2", {DATATYPE_MASK_VALID_OBJ, DATATYPE_MASK_INT}},
{sf_get_current_inven_size, "get_current_inven_size", {DATATYPE_MASK_VALID_OBJ}}, {sf_get_current_inven_size, "get_current_inven_size", {DATATYPE_MASK_VALID_OBJ}},
{sf_get_flags, "get_flags", {DATATYPE_MASK_VALID_OBJ}}, {sf_get_flags, "get_flags", {DATATYPE_MASK_VALID_OBJ}},
{sf_get_object_data, "get_object_data", {DATATYPE_MASK_VALID_OBJ, DATATYPE_MASK_INT}}, {sf_get_object_data, "get_object_data", {DATATYPE_MASK_VALID_OBJ, DATATYPE_MASK_INT}},
{sf_get_outline, "get_outline", {DATATYPE_MASK_VALID_OBJ}}, {sf_get_outline, "get_outline", {DATATYPE_MASK_VALID_OBJ}},
{sf_inventory_redraw, "inventory_redraw", {DATATYPE_MASK_INT}}, {sf_inventory_redraw, "inventory_redraw", {DATATYPE_MASK_INT}},
{sf_item_weight, "item_weight", {DATATYPE_MASK_VALID_OBJ}}, {sf_item_weight, "item_weight", {DATATYPE_MASK_VALID_OBJ}},
{sf_lock_is_jammed, "lock_is_jammed", {DATATYPE_MASK_VALID_OBJ}}, {sf_lock_is_jammed, "lock_is_jammed", {DATATYPE_MASK_VALID_OBJ}},
{sf_get_obj_under_cursor, "obj_under_cursor", {DATATYPE_MASK_INT, DATATYPE_MASK_INT}}, {sf_get_obj_under_cursor, "obj_under_cursor", {DATATYPE_MASK_INT, DATATYPE_MASK_INT}},
{sf_set_cursor_mode, "set_cursor_mode", {DATATYPE_MASK_INT}}, {sf_set_cursor_mode, "set_cursor_mode", {DATATYPE_MASK_INT}},
{sf_set_flags, "set_flags", {DATATYPE_MASK_VALID_OBJ, DATATYPE_MASK_INT}}, {sf_set_flags, "set_flags", {DATATYPE_MASK_VALID_OBJ, DATATYPE_MASK_INT}},
{sf_set_ini_setting, "set_ini_setting", {DATATYPE_MASK_STR, DATATYPE_MASK_INT | DATATYPE_MASK_STR}}, {sf_set_ini_setting, "set_ini_setting", {DATATYPE_MASK_STR, DATATYPE_MASK_INT | DATATYPE_MASK_STR}},
{sf_set_map_enter_position, "set_map_enter_position", {DATATYPE_MASK_INT, DATATYPE_MASK_INT, DATATYPE_MASK_INT}}, {sf_set_map_enter_position, "set_map_enter_position", {DATATYPE_MASK_INT, DATATYPE_MASK_INT, DATATYPE_MASK_INT}},
{sf_set_object_data, "set_object_data", {DATATYPE_MASK_VALID_OBJ, DATATYPE_MASK_INT, DATATYPE_MASK_INT}}, {sf_set_object_data, "set_object_data", {DATATYPE_MASK_VALID_OBJ, DATATYPE_MASK_INT, DATATYPE_MASK_INT}},
{sf_set_outline, "set_outline", {DATATYPE_MASK_VALID_OBJ, DATATYPE_MASK_INT}}, {sf_set_outline, "set_outline", {DATATYPE_MASK_VALID_OBJ, DATATYPE_MASK_INT}},
{sf_spatial_radius, "spatial_radius", {DATATYPE_MASK_VALID_OBJ}}, {sf_spatial_radius, "spatial_radius", {DATATYPE_MASK_VALID_OBJ}},
{sf_unjam_lock, "unjam_lock", {DATATYPE_MASK_VALID_OBJ}}, {sf_unjam_lock, "unjam_lock", {DATATYPE_MASK_VALID_OBJ}},
{sf_test, "validate_test", {DATATYPE_MASK_INT, DATATYPE_MASK_INT | DATATYPE_MASK_FLOAT, DATATYPE_MASK_STR, DATATYPE_NONE}}, {sf_test, "validate_test", {DATATYPE_MASK_INT, DATATYPE_MASK_INT | DATATYPE_MASK_FLOAT, DATATYPE_MASK_STR, DATATYPE_NONE}},
//{op_message_str_game, {}} //{op_message_str_game, {}}
}; };
+32 -32
View File
@@ -103,39 +103,39 @@ static void sf_get_metarule_table() {
- minArgs/maxArgs - minimum and maximum number of arguments allowed for this function - minArgs/maxArgs - minimum and maximum number of arguments allowed for this function
*/ */
static const SfallMetarule metaruleArray[] = { static const SfallMetarule metaruleArray[] = {
{"art_cache_clear", sf_art_cache_flush, 0, 0}, {"art_cache_clear", sf_art_cache_flush, 0, 0},
{"attack_is_aimed", sf_attack_is_aimed, 0, 0}, {"attack_is_aimed", sf_attack_is_aimed, 0, 0},
{"critter_inven_obj2", sf_critter_inven_obj2, 2, 2}, {"critter_inven_obj2", sf_critter_inven_obj2, 2, 2},
{"create_win", sf_create_win, 5, 6}, {"create_win", sf_create_win, 5, 6},
{"display_stats", sf_display_stats, 0, 0}, {"display_stats", sf_display_stats, 0, 0},
{"exec_map_update_scripts", sf_exec_map_update_scripts, 0, 0}, {"exec_map_update_scripts", sf_exec_map_update_scripts, 0, 0},
{"floor2", sf_floor2, 1, 1}, {"floor2", sf_floor2, 1, 1},
{"get_current_inven_size", sf_get_current_inven_size, 1, 1}, {"get_current_inven_size", sf_get_current_inven_size, 1, 1},
{"get_cursor_mode", sf_get_cursor_mode, 0, 0}, {"get_cursor_mode", sf_get_cursor_mode, 0, 0},
{"get_flags", sf_get_flags, 1, 1}, {"get_flags", sf_get_flags, 1, 1},
{"get_map_enter_position", sf_get_map_enter_position, 0, 0}, {"get_map_enter_position", sf_get_map_enter_position, 0, 0},
{"get_metarule_table", sf_get_metarule_table, 0, 0}, {"get_metarule_table", sf_get_metarule_table, 0, 0},
{"get_object_data", sf_get_object_data, 2, 2}, {"get_object_data", sf_get_object_data, 2, 2},
{"get_outline", sf_get_outline, 1, 1}, {"get_outline", sf_get_outline, 1, 1},
{"intface_hide", sf_intface_hide, 0, 0}, {"intface_hide", sf_intface_hide, 0, 0},
{"intface_is_hidden", sf_intface_is_hidden, 0, 0}, {"intface_is_hidden", sf_intface_is_hidden, 0, 0},
{"intface_redraw", sf_intface_redraw, 0, 0}, {"intface_redraw", sf_intface_redraw, 0, 0},
{"intface_show", sf_intface_show, 0, 0}, {"intface_show", sf_intface_show, 0, 0},
{"inventory_redraw", sf_inventory_redraw, 1, 1}, {"inventory_redraw", sf_inventory_redraw, 1, 1},
{"item_weight", sf_item_weight, 1, 1}, {"item_weight", sf_item_weight, 1, 1},
{"lock_is_jammed", sf_lock_is_jammed, 1, 1}, {"lock_is_jammed", sf_lock_is_jammed, 1, 1},
{"obj_under_cursor", sf_get_obj_under_cursor, 2, 2}, {"obj_under_cursor", sf_get_obj_under_cursor, 2, 2},
{"outlined_object", sf_outlined_object, 0, 0}, {"outlined_object", sf_outlined_object, 0, 0},
{"set_cursor_mode", sf_set_cursor_mode, 1, 1}, {"set_cursor_mode", sf_set_cursor_mode, 1, 1},
{"set_flags", sf_set_flags, 2, 2}, {"set_flags", sf_set_flags, 2, 2},
{"set_ini_setting", sf_set_ini_setting, 2, 2}, {"set_ini_setting", sf_set_ini_setting, 2, 2},
{"set_map_enter_position", sf_set_map_enter_position, 3, 3}, {"set_map_enter_position", sf_set_map_enter_position, 3, 3},
{"set_object_data", sf_set_object_data, 3, 3}, {"set_object_data", sf_set_object_data, 3, 3},
{"set_outline", sf_set_outline, 2, 2}, {"set_outline", sf_set_outline, 2, 2},
{"spatial_radius", sf_spatial_radius, 1, 1}, {"spatial_radius", sf_spatial_radius, 1, 1},
{"tile_refresh_display", sf_tile_refresh_display, 0, 0}, {"tile_refresh_display", sf_tile_refresh_display, 0, 0},
{"unjam_lock", sf_unjam_lock, 1, 1}, {"unjam_lock", sf_unjam_lock, 1, 1},
{"validate_test", sf_test, 2, 5}, {"validate_test", sf_test, 2, 5},
}; };
static void InitMetaruleTable() { static void InitMetaruleTable() {
+12 -14
View File
@@ -50,7 +50,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;
@@ -112,9 +112,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);
} }
@@ -179,7 +179,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) {
@@ -198,10 +198,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;
} }
@@ -249,7 +249,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);
@@ -285,7 +285,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);
} }
@@ -295,8 +295,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);
} }
@@ -352,8 +352,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);
@@ -396,8 +396,6 @@ public:
}; };
HRESULT _stdcall FakeDirectInputCreate(HINSTANCE a, DWORD b, IDirectInputA** c, IUnknown* d) { HRESULT _stdcall FakeDirectInputCreate(HINSTANCE a, DWORD b, IDirectInputA** c, IUnknown* d) {
ZeroMemory(KeysDown, sizeof(KeysDown));
HMODULE dinput = LoadLibraryA("dinput.dll"); HMODULE dinput = LoadLibraryA("dinput.dll");
if (!dinput || dinput == INVALID_HANDLE_VALUE) return -1; if (!dinput || dinput == INVALID_HANDLE_VALUE) return -1;
DInputCreateProc proc = (DInputCreateProc)GetProcAddress(dinput, "DirectInputCreateA"); DInputCreateProc proc = (DInputCreateProc)GetProcAddress(dinput, "DirectInputCreateA");
+39 -83
View File
@@ -87,29 +87,6 @@ bool npcautolevel;
static int* scriptDialog = nullptr; static int* scriptDialog = nullptr;
//GetTickCount calls
static const DWORD offsetsA[] = {
0x4C8D34, 0x4C9375, 0x4C9384, 0x4C93C0, 0x4C93E8, 0x4C9D2E, 0x4FE01E,
};
//Delayed GetTickCount calls
static const DWORD offsetsB[] = {
0x4FDF64,
};
//timeGetTime calls
static const DWORD offsetsC[] = {
0x4A3179, 0x4A325D, 0x4F482B, 0x4F4E53, 0x4F5542, 0x4F56CC, 0x4F59C6,
0x4FE036,
};
static const DWORD getLocalTimePos = 0x4FDF58;
static const DWORD dinputPos = 0x50FB70;
static DWORD AddrGetTickCount;
static DWORD AddrGetLocalTime;
static DWORD ViewportX; static DWORD ViewportX;
static DWORD ViewportY; static DWORD ViewportY;
@@ -290,51 +267,61 @@ run:
static DWORD worldMapDelay; static DWORD worldMapDelay;
static DWORD worldMapTicks; static DWORD worldMapTicks;
static DWORD worldMapAdjustDelay = 4;
static void __declspec(naked) WorldMapFpsPatch() { static void __declspec(naked) WorldMapFpsPatch() {
__asm { __asm {
pushadc;
push dword ptr ds:[_last_buttons]; push dword ptr ds:[_last_buttons];
push dword ptr ds:[0x6AC7B0]; // _mouse_buttons push dword ptr ds:[0x6AC7B0]; // _mouse_buttons
xor ecx, ecx; mov esi, worldMapTicks;
mov ebx, esi; // previous ticks
loopDelay: loopDelay:
call process_bk_;
dec ecx;
jg subLoop; // jmp ecx > -1
call RunGlobalScripts3; call RunGlobalScripts3;
mov ecx, worldMapAdjustDelay; // adjust invoke frequency call process_bk_;
subLoop: subLoop:
mov eax, worldMapTicks; call ds:[sf_GetTickCount]; // current ticks
call elapsed_time_; mov edx, eax;
cmp eax, 10; // delay sub eax, ebx; // get elapsed time (cur.ticks - prev.ticks)
jle subLoop; cmp eax, 10; // delay - GetTickCount returns minimum difference of 15 units
cmp eax, worldMapDelay; jb subLoop; // elapsed < invoke delay
jl loopDelay; // elapsed < worldMapDelay mov ebx, edx;
sub edx, esi; // get elapsed time (cur.ticks - worldMapTicks)
cmp edx, worldMapDelay;
jb loopDelay; // elapsed < worldMapDelay
call get_time_;
mov worldMapTicks, eax;
pop dword ptr ds:[0x6AC7B0]; // _mouse_buttons pop dword ptr ds:[0x6AC7B0]; // _mouse_buttons
pop dword ptr ds:[_last_buttons]; pop dword ptr ds:[_last_buttons];
popadc; call ds:[sf_GetTickCount];
mov worldMapTicks, eax;
jmp get_input_; jmp get_input_;
} }
} }
static void __declspec(naked) WorldMapFpsPatch2() { static void __declspec(naked) WorldMapFpsPatch2() {
__asm { __asm {
pushadc; mov esi, worldMapTicks;
mov ebx, esi;
loopDelay: loopDelay:
call RunGlobalScripts3; call RunGlobalScripts3;
subLoop: subLoop:
mov eax, worldMapTicks; call ds:[sf_GetTickCount]; // current ticks
call elapsed_time_; mov edx, eax;
test eax, eax; // 1 min delay sub eax, ebx; // get elapsed time
jz subLoop; jz subLoop;
cmp eax, worldMapDelay; mov ebx, edx;
jl loopDelay; // elapsed < worldMapDelay sub edx, esi; // get elapsed time
cmp edx, worldMapDelay;
jb loopDelay; // elapsed < worldMapDelay
call get_time_; call ds:[sf_GetTickCount];
mov worldMapTicks, eax; mov worldMapTicks, eax;
jmp get_input_;
}
}
// 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 RunGlobalScripts3;
popadc; popadc;
jmp get_input_; jmp get_input_;
} }
@@ -404,16 +391,6 @@ end_cppf:
} }
} }
// 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 RunGlobalScripts3;
popadc;
jmp get_input_;
}
}
static void __declspec(naked) ViewportHook() { static void __declspec(naked) ViewportHook() {
__asm { __asm {
call wmWorldMapLoadTempData_; call wmWorldMapLoadTempData_;
@@ -861,32 +838,11 @@ static void DllMain2() {
dlogr("Running BugsInit().", DL_INIT); dlogr("Running BugsInit().", DL_INIT);
BugsInit(); BugsInit();
if (GetPrivateProfileIntA("Speed", "Enable", 0, ini)) { SpeedPatchInit();
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);
}
dlog(".", DL_INIT);
for (int i = 0; i < sizeof(offsetsB) / 4; i++) {
SafeWrite32(offsetsB[i], (DWORD)&AddrGetTickCount);
}
dlog(".", DL_INIT);
for (int i = 0; i < sizeof(offsetsC) / 4; i++) {
SafeWrite32(offsetsC[i], (DWORD)&AddrGetTickCount);
}
dlog(".", DL_INIT);
SafeWrite32(getLocalTimePos, (DWORD)&AddrGetLocalTime);
TimerInit();
dlogr(" Done", DL_INIT);
}
//if (GetPrivateProfileIntA("Input", "Enable", 0, ini)) { //if (GetPrivateProfileIntA("Input", "Enable", 0, ini)) {
dlog("Applying input patch.", DL_INIT); dlog("Applying input patch.", DL_INIT);
SafeWriteStr(dinputPos, "ddraw.dll"); SafeWriteStr(0x50FB70, "ddraw.dll");
AvailableGlobalScriptTypes |= 1; AvailableGlobalScriptTypes |= 1;
dlogr(" Done", DL_INIT); dlogr(" Done", DL_INIT);
//} //}
@@ -1052,12 +1008,12 @@ static void DllMain2() {
//} //}
bool fpsPatchOK = (*(DWORD*)0x4BFE5E == 0x8D16); bool fpsPatchOK = (*(DWORD*)0x4BFE5E == 0x8D16);
if (GetPrivateProfileInt("Misc", "WorldMapFPSPatch", 0, ini)) { if (GetPrivateProfileIntA("Misc", "WorldMapFPSPatch", 0, ini)) {
dlog("Applying world map fps patch.", DL_INIT); dlog("Applying world map fps patch.", DL_INIT);
if (!fpsPatchOK) { if (!fpsPatchOK) {
dlogr(" Failed", DL_INIT); dlogr(" Failed", DL_INIT);
} else { } else {
int delay = GetPrivateProfileInt("Misc", "WorldMapDelay2", 66, ini); int delay = GetPrivateProfileIntA("Misc", "WorldMapDelay2", 66, ini);
worldMapDelay = max(1, delay); worldMapDelay = max(1, delay);
dlogr(" Done", DL_INIT); dlogr(" Done", DL_INIT);
} }
@@ -1066,8 +1022,7 @@ static void DllMain2() {
void* func; void* func;
if (worldMapDelay == 0) { if (worldMapDelay == 0) {
func = wmWorldMap_hook; func = wmWorldMap_hook;
} else if (worldMapDelay > 15) { } else if (worldMapDelay > 25) {
worldMapAdjustDelay += worldMapDelay / 10;
func = WorldMapFpsPatch; func = WorldMapFpsPatch;
} else { } else {
func = WorldMapFpsPatch2; func = WorldMapFpsPatch2;
@@ -1592,6 +1547,7 @@ static void _stdcall OnExit() {
if (scriptDialog != nullptr) { if (scriptDialog != nullptr) {
delete[] scriptDialog; delete[] scriptDialog;
} }
SpeedPatchExit();
ClearReadExtraGameMsgFiles(); ClearReadExtraGameMsgFiles();
ConsoleExit(); ConsoleExit();
BooksExit(); BooksExit();
+132 -65
View File
@@ -1,6 +1,6 @@
/* /*
* sfall * sfall
* Copyright (C) 2008, 2009, 2010 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
@@ -16,67 +16,100 @@
* 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 "main.h" #include "main.h"
#include <math.h> #include "FalloutEngine.h"
#include "input.h" #include "input.h"
#include "LoadGameHook.h"
static bool Enabled; static const DWORD offsets[] = {
static bool Toggled; // 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
};
static double Multi; DWORD sf_GetTickCount = (DWORD)&GetTickCount;
static DWORD StoredTickCount; //DWORD sf_GetLocalTime;
static DWORD LastTickCount;
static double TickCountFraction;
static __int64 StartTime; static bool enabled = true;
static bool toggled = false;
static bool slideShow = false;
static double Multipliers[10]; static double multi;
static int Keys[10]; static DWORD storedTickCount = 0;
static int ModKey; static DWORD lastTickCount;
static int ToggleKey; static double tickCountFraction = 0.0;
DWORD _stdcall FakeGetTickCount() { static __int64 startTime;
//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])) static struct SpeedCfg {
Multi=Multipliers[i]; int key;
double multiplier;
} *speed = nullptr;
if(ToggleKey&&KeyDown(ToggleKey)) { static int modKey;
if(!Toggled) { static int toggleKey;
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; } else {
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) { && !(GetCurrentLoops() & (INVENTORY | INTFACEUSE | INTFACELOOT | 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.
@@ -88,29 +121,63 @@ MMRESULT _stdcall fTimeKillEvent(UINT id) {
return timeKillEvent(id); return timeKillEvent(id);
}*/ }*/
static void __declspec(naked) scripts_check_state_hook() {
__asm {
inc slideShow;
call endgame_slideshow_;
dec slideShow;
retn;
}
}
void TimerInit() { void TimerInit() {
StoredTickCount=0; lastTickCount = GetTickCount();
LastTickCount=GetTickCount();
TickCountFraction=0;
Multi=(double)GetPrivateProfileInt("Speed", "SpeedMultiInitial", 100, ini)/100.0;
Enabled=true;
Toggled=false;
SYSTEMTIME time; SYSTEMTIME time;
GetLocalTime(&time); GetLocalTime(&time);
SystemTimeToFileTime(&time, (FILETIME*)&StartTime); SystemTimeToFileTime(&time, (FILETIME*)&startTime);
ModKey=GetPrivateProfileInt("Input", "SpeedModKey", -1, ini); speed = new SpeedCfg[10];
ToggleKey=GetPrivateProfileInt("Input", "SpeedToggleKey", 0, ini);
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 = GetPrivateProfileIntA("Input", spKey, 0, ini);
Keys[i]=GetPrivateProfileInt("Input", key, 0, ini); speed[i].multiplier = GetPrivateProfileIntA("Speed", spMulti, 0, ini) / 100.0;
strcpy_s(key, "SpeedMulti");
strcat_s(key, c);
Multipliers[i]=GetPrivateProfileInt("Speed", key, 0x00, ini)/100.0;
} }
} }
void SpeedPatchInit() {
if (GetPrivateProfileIntA("Speed", "Enable", 0, ini)) {
modKey = GetPrivateProfileIntA("Input", "SpeedModKey", 0, ini);
int init = GetPrivateProfileIntA("Speed", "SpeedMultiInitial", 100, ini);
if (init == 100 && !modKey) return;
dlog("Applying speed patch.", DL_INIT);
multi = (double)init / 100.0;
toggleKey = GetPrivateProfileIntA("Input", "SpeedToggleKey", 0, ini);
sf_GetTickCount = (DWORD)&FakeGetTickCount;
//sf_GetLocalTime = (DWORD)&FakeGetLocalTime;
int size = sizeof(offsets) / 4;
if (GetPrivateProfileIntA("Speed", "AffectPlayback", 0, ini) == 0) {
size -= 4;
HookCall(0x4A433E, scripts_check_state_hook);
}
for (int i = 0; i < size; i++) {
SafeWrite32(offsets[i], (DWORD)&sf_GetTickCount);
}
SafeWrite32(0x4FDF58, (DWORD)&FakeGetLocalTime);
TimerInit();
dlogr(" Done", DL_INIT);
}
}
void SpeedPatchExit() {
if (speed) delete[] speed;
}
+4 -2
View File
@@ -18,6 +18,8 @@
#pragma once #pragma once
DWORD _stdcall FakeGetTickCount(); extern DWORD sf_GetTickCount;
void _stdcall FakeGetLocalTime(LPSYSTEMTIME); void _stdcall FakeGetLocalTime(LPSYSTEMTIME);
void TimerInit(); void SpeedPatchInit();
void SpeedPatchExit();