mirror of
https://github.com/isledecomp/LEGOIslandRebuilder.git
synced 2024-11-27 09:35:41 -05:00
finished last of the patches
This commit is contained in:
parent
3816530f4e
commit
08c3ac2f54
6 changed files with 127 additions and 12 deletions
|
@ -190,16 +190,8 @@ LONG WINAPI InterceptRegQueryValueExA(HKEY hKey, LPCSTR lpValueName, LPDWORD lpR
|
||||||
|
|
||||||
void WINAPI InterceptSleep(DWORD dwMilliseconds)
|
void WINAPI InterceptSleep(DWORD dwMilliseconds)
|
||||||
{
|
{
|
||||||
// Do nothing
|
// If uncapped, do nothing. Otherwise pass through as normal.
|
||||||
std::string fps_behavior = config.GetString(_T("FPSLimit"));
|
if (config.GetString(_T("FPSLimit")) != "Uncapped") {
|
||||||
|
|
||||||
// If uncapped, do nothing
|
|
||||||
if (fps_behavior != "Uncapped") {
|
|
||||||
// If not default, pass through new FPS
|
|
||||||
if (fps_behavior == "Limited") {
|
|
||||||
dwMilliseconds = 1000.0f / config.GetFloat(_T("CustomFPS"));
|
|
||||||
}
|
|
||||||
|
|
||||||
Sleep(dwMilliseconds);
|
Sleep(dwMilliseconds);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -216,6 +208,37 @@ HRESULT WINAPI InterceptD3DRMViewportSetField(LPDIRECT3DRMVIEWPORT viewport, D3D
|
||||||
return d3drmViewportSetFieldOriginal(viewport, field);
|
return d3drmViewportSetFieldOriginal(viewport, field);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const SIZE_T max_frame_numbers = 60;
|
||||||
|
SIZE_T current_frame = 0;
|
||||||
|
DWORD frame_deltas[max_frame_numbers];
|
||||||
|
DWORD last_time = 0;
|
||||||
|
|
||||||
|
typedef HRESULT (WINAPI *d3drmDeviceUpdateFunction)(LPDIRECT3DRMDEVICE device);
|
||||||
|
d3drmDeviceUpdateFunction d3drmDeviceUpdateOriginal = NULL;
|
||||||
|
HRESULT WINAPI InterceptD3DRMDeviceUpdate(LPDIRECT3DRMDEVICE device)
|
||||||
|
{
|
||||||
|
DWORD now = timeGetTime();
|
||||||
|
|
||||||
|
if (last_time != 0) {
|
||||||
|
DWORD diff = now - last_time;
|
||||||
|
frame_deltas[current_frame%max_frame_numbers] = diff;
|
||||||
|
current_frame++;
|
||||||
|
|
||||||
|
if (current_frame >= max_frame_numbers) {
|
||||||
|
double avg_delta = 0;
|
||||||
|
for (size_t i=0; i<max_frame_numbers; i++) {
|
||||||
|
avg_delta += frame_deltas[i];
|
||||||
|
}
|
||||||
|
avg_delta /= max_frame_numbers;
|
||||||
|
printf("Avg FPS: %f\n", 1000.0 / avg_delta);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
last_time = now;
|
||||||
|
|
||||||
|
return d3drmDeviceUpdateOriginal(device);
|
||||||
|
}
|
||||||
|
|
||||||
typedef HRESULT (WINAPI *d3drmCreateViewportFunction)(LPDIRECT3DRM d3drm, LPDIRECT3DRMDEVICE device, LPDIRECT3DRMFRAME frame, DWORD x, DWORD y, DWORD w, DWORD h, LPDIRECT3DRMVIEWPORT *viewport);
|
typedef HRESULT (WINAPI *d3drmCreateViewportFunction)(LPDIRECT3DRM d3drm, LPDIRECT3DRMDEVICE device, LPDIRECT3DRMFRAME frame, DWORD x, DWORD y, DWORD w, DWORD h, LPDIRECT3DRMVIEWPORT *viewport);
|
||||||
d3drmCreateViewportFunction d3drmCreateViewportOriginal = NULL;
|
d3drmCreateViewportFunction d3drmCreateViewportOriginal = NULL;
|
||||||
HRESULT WINAPI InterceptD3DRMCreateViewport(LPDIRECT3DRM d3drm, LPDIRECT3DRMDEVICE device, LPDIRECT3DRMFRAME frame, DWORD x, DWORD y, DWORD w, DWORD h, LPDIRECT3DRMVIEWPORT *viewport)
|
HRESULT WINAPI InterceptD3DRMCreateViewport(LPDIRECT3DRM d3drm, LPDIRECT3DRMDEVICE device, LPDIRECT3DRMFRAME frame, DWORD x, DWORD y, DWORD w, DWORD h, LPDIRECT3DRMVIEWPORT *viewport)
|
||||||
|
@ -223,6 +246,10 @@ HRESULT WINAPI InterceptD3DRMCreateViewport(LPDIRECT3DRM d3drm, LPDIRECT3DRMDEVI
|
||||||
HRESULT res = d3drmCreateViewportOriginal(d3drm, device, frame, x, y, w, h, viewport);
|
HRESULT res = d3drmCreateViewportOriginal(d3drm, device, frame, x, y, w, h, viewport);
|
||||||
|
|
||||||
if (res == DD_OK) {
|
if (res == DD_OK) {
|
||||||
|
if (!d3drmDeviceUpdateOriginal) {
|
||||||
|
d3drmDeviceUpdateOriginal = (d3drmDeviceUpdateFunction)OverwriteVirtualTable(device, 14, (LPVOID)InterceptD3DRMDeviceUpdate);
|
||||||
|
}
|
||||||
|
|
||||||
if (!d3drmViewportSetFieldOriginal) {
|
if (!d3drmViewportSetFieldOriginal) {
|
||||||
d3drmViewportSetFieldOriginal = (d3drmViewportSetFieldFunction)OverwriteVirtualTable(*viewport, 0x10, (LPVOID)InterceptD3DRMViewportSetField);
|
d3drmViewportSetFieldOriginal = (d3drmViewportSetFieldFunction)OverwriteVirtualTable(*viewport, 0x10, (LPVOID)InterceptD3DRMViewportSetField);
|
||||||
}
|
}
|
||||||
|
|
43
lib/util.cpp
43
lib/util.cpp
|
@ -135,3 +135,46 @@ BOOL OverwriteCall(LPVOID destination, LPVOID localCall)
|
||||||
|
|
||||||
return WriteMemory(destination, callInst, 5);
|
return WriteMemory(destination, callInst, 5);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LPVOID SearchPattern(LPVOID imageBase, LPCVOID search, SIZE_T count)
|
||||||
|
{
|
||||||
|
LPVOID ret = NULL;
|
||||||
|
|
||||||
|
HANDLE process = GetCurrentProcess();
|
||||||
|
|
||||||
|
MEMORY_BASIC_INFORMATION mbi = {0};
|
||||||
|
|
||||||
|
// Loop through memory pages
|
||||||
|
UINT_PTR addr = (UINT_PTR)imageBase;
|
||||||
|
while (VirtualQueryEx(process, (LPVOID)addr, &mbi, sizeof(mbi)) && mbi.AllocationBase == imageBase) {
|
||||||
|
if (mbi.State == MEM_COMMIT && mbi.Protect != PAGE_NOACCESS) {
|
||||||
|
DWORD oldProtec;
|
||||||
|
|
||||||
|
// Try to gain access to this memory page
|
||||||
|
if (VirtualProtect(mbi.BaseAddress, mbi.RegionSize, PAGE_EXECUTE_READWRITE, &oldProtec)) {
|
||||||
|
// Loop through every byte to find the pattern
|
||||||
|
SIZE_T maxOffset = mbi.RegionSize - count;
|
||||||
|
for (SIZE_T i=0; i<maxOffset; i++) {
|
||||||
|
LPVOID offset = (LPVOID)((UINT_PTR)(mbi.BaseAddress)+i);
|
||||||
|
|
||||||
|
if (!memcmp(offset, search, count)) {
|
||||||
|
// Found pattern, overwrite it
|
||||||
|
ret = offset;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Restore original permissions
|
||||||
|
VirtualProtect(mbi.BaseAddress, mbi.RegionSize, oldProtec, &oldProtec);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ret) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
addr += mbi.RegionSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
|
@ -7,6 +7,8 @@ BOOL WriteMemory(LPVOID destination, LPVOID source, size_t length, LPVOID oldDat
|
||||||
|
|
||||||
BOOL OverwriteCall(LPVOID destination, LPVOID localCall);
|
BOOL OverwriteCall(LPVOID destination, LPVOID localCall);
|
||||||
|
|
||||||
|
LPVOID SearchPattern(LPVOID imageBase, LPCVOID search, SIZE_T count);
|
||||||
|
|
||||||
SIZE_T SearchReplacePattern(LPVOID imageBase, LPCVOID search, LPCVOID replace, SIZE_T count, BOOL only_once = FALSE);
|
SIZE_T SearchReplacePattern(LPVOID imageBase, LPCVOID search, LPCVOID replace, SIZE_T count, BOOL only_once = FALSE);
|
||||||
|
|
||||||
LPVOID OverwriteImport(LPVOID imageBase, LPCSTR overrideFunction, LPVOID override);
|
LPVOID OverwriteImport(LPVOID imageBase, LPCSTR overrideFunction, LPVOID override);
|
||||||
|
|
|
@ -43,6 +43,15 @@ DWORD WINAPI Patch()
|
||||||
OverwriteImport(exeBase, "FindWindowA", (LPVOID)InterceptFindWindowA);
|
OverwriteImport(exeBase, "FindWindowA", (LPVOID)InterceptFindWindowA);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Speed up startup
|
||||||
|
if (config.GetInt(_T("SpeedUpStartUp"))) {
|
||||||
|
// Replace "200" frame wait value with "1"
|
||||||
|
const char *speedup_pattern = "\xC8\x00\x00\x00\x00\x00\x00\x00";
|
||||||
|
const char *speedup_replace = "\x01\x00\x00\x00\x00\x00\x00\x00";
|
||||||
|
|
||||||
|
SearchReplacePattern(exeBase, speedup_pattern, speedup_replace, 8, TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
// Debug mode
|
// Debug mode
|
||||||
if (config.GetInt(_T("DebugToggle"))) {
|
if (config.GetInt(_T("DebugToggle"))) {
|
||||||
// LEGO1 uses a string pointer to know if OGEL has been typed, if the string pointer sees 0x0
|
// LEGO1 uses a string pointer to know if OGEL has been typed, if the string pointer sees 0x0
|
||||||
|
@ -65,6 +74,20 @@ DWORD WINAPI Patch()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Unhook turn speed
|
||||||
|
float turn_max_spd = config.GetFloat(_T("TurnMaxSpeed"), 20.0f);
|
||||||
|
|
||||||
|
if (config.GetInt(_T("UnhookTurnSpeed"))) {
|
||||||
|
LPVOID code_offset = SearchPattern(dllBase, "\x74\x26\xD9\x46\x34", 5);
|
||||||
|
if (code_offset) {
|
||||||
|
const char *new_code = "\xD9\x46\x24\xD8\x4C\x24\x14\xD8\x4E\x34\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90";
|
||||||
|
WriteMemory(code_offset, (LPVOID)new_code, 36);
|
||||||
|
turn_max_spd *= 2.0f;
|
||||||
|
} else {
|
||||||
|
printf("Failed to find code for unhooking turn speed\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Patch navigation
|
// Patch navigation
|
||||||
{
|
{
|
||||||
const int nav_block_sz = 0x30;
|
const int nav_block_sz = 0x30;
|
||||||
|
@ -78,7 +101,7 @@ DWORD WINAPI Patch()
|
||||||
float movement_max_spd = config.GetFloat(_T("MovementMaxSpeed"), 40.0f);
|
float movement_max_spd = config.GetFloat(_T("MovementMaxSpeed"), 40.0f);
|
||||||
memcpy(nav_block_dst+0x8, &movement_max_spd, sizeof(movement_max_spd));
|
memcpy(nav_block_dst+0x8, &movement_max_spd, sizeof(movement_max_spd));
|
||||||
|
|
||||||
float turn_max_spd = config.GetFloat(_T("TurnMaxSpeed"), 20.0f);
|
// Value retrieved above
|
||||||
memcpy(nav_block_dst+0xC, &turn_max_spd, sizeof(turn_max_spd));
|
memcpy(nav_block_dst+0xC, &turn_max_spd, sizeof(turn_max_spd));
|
||||||
|
|
||||||
float movement_max_accel = config.GetFloat(_T("MovementMaxAcceleration"), 15.0f);
|
float movement_max_accel = config.GetFloat(_T("MovementMaxAcceleration"), 15.0f);
|
||||||
|
@ -133,6 +156,20 @@ DWORD WINAPI Patch()
|
||||||
memcpy(fov_replace, &fov, sizeof(fov)); // Store back into bytes
|
memcpy(fov_replace, &fov, sizeof(fov)); // Store back into bytes
|
||||||
SearchReplacePattern(dllBase, fov_pattern, fov_replace, 12);
|
SearchReplacePattern(dllBase, fov_pattern, fov_replace, 12);
|
||||||
|
|
||||||
|
// FPS Cap
|
||||||
|
std::string fps_behavior = config.GetString(_T("FPSLimit"));
|
||||||
|
if (fps_behavior != "Default") {
|
||||||
|
UINT32 frame_delta;
|
||||||
|
|
||||||
|
if (fps_behavior == "Limited") {
|
||||||
|
frame_delta = 1000.0f / config.GetFloat(_T("CustomFPS"));
|
||||||
|
} else {
|
||||||
|
frame_delta = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
WriteMemory((char*)exeBase+0x10B4, &frame_delta, sizeof(UINT32));
|
||||||
|
}
|
||||||
|
|
||||||
// Window size hack
|
// Window size hack
|
||||||
/*SearchReplacePattern(exeBase,
|
/*SearchReplacePattern(exeBase,
|
||||||
"\x80\x02\x00\x00\xE0\x01\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x80\x02\x00\x00\xE0\x01\x00\x00",
|
"\x80\x02\x00\x00\xE0\x01\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x80\x02\x00\x00\xE0\x01\x00\x00",
|
||||||
|
|
|
@ -21,6 +21,11 @@ PatchGrid::PatchGrid()
|
||||||
"This patch allows infinite instances of LEGO Island to run."),
|
"This patch allows infinite instances of LEGO Island to run."),
|
||||||
AddBoolItem(sectionGeneral, _T("Allow Multiple Instances"), false));
|
AddBoolItem(sectionGeneral, _T("Allow Multiple Instances"), false));
|
||||||
|
|
||||||
|
AddPatch("SpeedUpStartUp",
|
||||||
|
_T("By default, LEGO Island waits 200 frames to ensure everything is initialized before starting. "
|
||||||
|
"That interval can be skipped without consequence in many cases."),
|
||||||
|
AddBoolItem(sectionGeneral, _T("Speed Up Startup"), false));
|
||||||
|
|
||||||
AddPatch("StayActiveWhenDefocused",
|
AddPatch("StayActiveWhenDefocused",
|
||||||
_T("By default, LEGO Island pauses when it's not the active window. "
|
_T("By default, LEGO Island pauses when it's not the active window. "
|
||||||
"This patch prevents that behavior."),
|
"This patch prevents that behavior."),
|
||||||
|
|
|
@ -57,7 +57,8 @@ CRebuilderWindow::CRebuilderWindow()
|
||||||
// Create property grid
|
// Create property grid
|
||||||
m_cPatchGrid.Create(AfxRegisterWndClass(CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW), _T("Patch Grid"), WS_CHILD | WS_VISIBLE, CRect(), &m_cTabCtrl, ID_PATCHGRID);
|
m_cPatchGrid.Create(AfxRegisterWndClass(CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW), _T("Patch Grid"), WS_CHILD | WS_VISIBLE, CRect(), &m_cTabCtrl, ID_PATCHGRID);
|
||||||
|
|
||||||
m_cMusicTable.Create(_T("Coming back soon"), WS_CHILD | SS_CENTER, CRect(), &m_cTabCtrl);
|
m_cMusicTable.Create(_T("Coming back soon. If you need music replacement, download the old .NET version here."),
|
||||||
|
WS_CHILD | SS_CENTER, CRect(), &m_cTabCtrl);
|
||||||
|
|
||||||
// Create run button
|
// Create run button
|
||||||
m_cRunBtn.Create(GetResourceString(IDS_RUN), WS_CHILD | WS_VISIBLE, CRect(), this, ID_RUN);
|
m_cRunBtn.Create(GetResourceString(IDS_RUN), WS_CHILD | WS_VISIBLE, CRect(), this, ID_RUN);
|
||||||
|
|
Loading…
Reference in a new issue