mirror of
https://github.com/isledecomp/LEGOIslandRebuilder.git
synced 2025-06-06 10:24:53 -04:00
ported some patches
This commit is contained in:
parent
f5dae0804a
commit
f0904e54b9
12 changed files with 346 additions and 100 deletions
|
@ -11,6 +11,10 @@ option(BUILD_UNICODE "Build with Unicode support" ON)
|
||||||
# Build our code injected DLL
|
# Build our code injected DLL
|
||||||
#
|
#
|
||||||
add_library(Rebld SHARED
|
add_library(Rebld SHARED
|
||||||
|
cmn/path.cpp
|
||||||
|
cmn/path.h
|
||||||
|
lib/config.cpp
|
||||||
|
lib/config.h
|
||||||
lib/dllmain.cpp
|
lib/dllmain.cpp
|
||||||
lib/hooks.cpp
|
lib/hooks.cpp
|
||||||
lib/hooks.h
|
lib/hooks.h
|
||||||
|
@ -21,7 +25,7 @@ add_library(Rebld SHARED
|
||||||
lib/worker.h
|
lib/worker.h
|
||||||
)
|
)
|
||||||
target_compile_options(Rebld PRIVATE /MT)
|
target_compile_options(Rebld PRIVATE /MT)
|
||||||
target_link_libraries(Rebld PRIVATE winmm.lib)
|
target_link_libraries(Rebld PRIVATE winmm.lib shlwapi.lib)
|
||||||
|
|
||||||
# Add property grid
|
# Add property grid
|
||||||
set(PROPERTYGRID_BUILD_APP OFF CACHE BOOL "")
|
set(PROPERTYGRID_BUILD_APP OFF CACHE BOOL "")
|
||||||
|
@ -31,6 +35,8 @@ add_subdirectory(ext/PropertyGrid)
|
||||||
# Build launcher/configuration executable
|
# Build launcher/configuration executable
|
||||||
#
|
#
|
||||||
add_executable(Rebuilder WIN32
|
add_executable(Rebuilder WIN32
|
||||||
|
cmn/path.cpp
|
||||||
|
cmn/path.h
|
||||||
res/res.rc
|
res/res.rc
|
||||||
res/resource.h
|
res/resource.h
|
||||||
src/app.cpp
|
src/app.cpp
|
||||||
|
|
11
cmn/combo.h
Normal file
11
cmn/combo.h
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
#ifndef COMBO_H
|
||||||
|
#define COMBO_H
|
||||||
|
|
||||||
|
enum ModelQuality {
|
||||||
|
kModelQualityInfinite,
|
||||||
|
kModelQualityHigh,
|
||||||
|
kModelQualityMedium,
|
||||||
|
kModelQualityLow
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // COMBO_H
|
94
cmn/path.cpp
Normal file
94
cmn/path.cpp
Normal file
|
@ -0,0 +1,94 @@
|
||||||
|
#include "path.h"
|
||||||
|
|
||||||
|
#include <SHLOBJ.H>
|
||||||
|
#include <SHLWAPI.H>
|
||||||
|
#include <STRING>
|
||||||
|
#include <TCHAR.H>
|
||||||
|
|
||||||
|
LPCTSTR appName = TEXT("Rebuilder");
|
||||||
|
|
||||||
|
BOOL DirectoryExists(LPCTSTR szPath)
|
||||||
|
{
|
||||||
|
return PathFileExists(szPath) && PathIsDirectory(szPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL RecursivelyCreateDirectory(LPCTSTR directory)
|
||||||
|
{
|
||||||
|
if (DirectoryExists(directory)) {
|
||||||
|
// Directory already exists, do nothing
|
||||||
|
return TRUE;
|
||||||
|
} else {
|
||||||
|
// Determine directory of this directory
|
||||||
|
std::basic_string<TCHAR> copy = directory;
|
||||||
|
PathRemoveFileSpec(©[0]);
|
||||||
|
|
||||||
|
// Create if necessary
|
||||||
|
if (RecursivelyCreateDirectory(copy.c_str())) {
|
||||||
|
return CreateDirectory(directory, NULL);
|
||||||
|
} else {
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef UNICODE
|
||||||
|
typedef BOOL (WINAPI *SHGetSpecialFolderPathSignature)(HWND hwndOwner, LPWSTR lpszPath, int nFolder, BOOL fCreate);
|
||||||
|
#else
|
||||||
|
typedef BOOL (WINAPI *SHGetSpecialFolderPathSignature)(HWND hwndOwner, LPSTR lpszPath, int nFolder, BOOL fCreate);
|
||||||
|
#endif
|
||||||
|
BOOL GetAppDataPath(LPTSTR s)
|
||||||
|
{
|
||||||
|
OSVERSIONINFO info;
|
||||||
|
ZeroMemory(&info, sizeof(info));
|
||||||
|
info.dwOSVersionInfoSize = sizeof(info);
|
||||||
|
GetVersionEx(&info);
|
||||||
|
|
||||||
|
// Dynamically link to SHGetSpecialFolderPath because not all versions of Windows have it
|
||||||
|
#ifdef UNICODE
|
||||||
|
LPCSTR functionName = "SHGetSpecialFolderPathW";
|
||||||
|
#else
|
||||||
|
LPCSTR functionName = "SHGetSpecialFolderPathA";
|
||||||
|
#endif
|
||||||
|
|
||||||
|
SHGetSpecialFolderPathSignature GetSpecialFolderPath = (SHGetSpecialFolderPathSignature)GetProcAddress(GetModuleHandle(_T("SHELL32.DLL")), functionName);
|
||||||
|
BOOL haveDir = FALSE;
|
||||||
|
BOOL usedShell = FALSE;
|
||||||
|
if (GetSpecialFolderPath) {
|
||||||
|
haveDir = GetSpecialFolderPath(NULL, s, CSIDL_APPDATA, TRUE);
|
||||||
|
usedShell = TRUE;
|
||||||
|
} else {
|
||||||
|
// Assume we're on Windows 95 which has no application data folder, we bodge it to write to
|
||||||
|
// "C:\Windows\Application Data" which is roughly where 98/Me would do it
|
||||||
|
GetWindowsDirectory(s, MAX_PATH);
|
||||||
|
_tcscat(s, _T("\\Application Data"));
|
||||||
|
haveDir = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
//MessageBox(0, s, usedShell ? _T("Using API") : _T("Is this Windows 95?"), 0);
|
||||||
|
return haveDir;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL GetConfigFilename(LPTSTR s)
|
||||||
|
{
|
||||||
|
if (GetAppDataPath(s)) {
|
||||||
|
_tcscat(s, _T("\\LEGOIslandRebuilder"));
|
||||||
|
if (RecursivelyCreateDirectory(s)) {
|
||||||
|
_tcscat(s, _T("\\settings.ini"));
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL GetSafeLEGOIslandSavePath(LPTSTR s)
|
||||||
|
{
|
||||||
|
if (GetAppDataPath(s)) {
|
||||||
|
_tcscat(s, _T("\\LEGO Island"));
|
||||||
|
if (RecursivelyCreateDirectory(s)) {
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
12
cmn/path.h
Normal file
12
cmn/path.h
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
#ifndef PATH_H
|
||||||
|
#define PATH_H
|
||||||
|
|
||||||
|
#include <WINDOWS.H>
|
||||||
|
|
||||||
|
BOOL GetSafeLEGOIslandSavePath(LPTSTR s);
|
||||||
|
|
||||||
|
BOOL GetConfigFilename(LPTSTR s);
|
||||||
|
|
||||||
|
extern LPCTSTR appName;
|
||||||
|
|
||||||
|
#endif // PATH_H
|
24
lib/config.cpp
Normal file
24
lib/config.cpp
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#include <SHLWAPI.H>
|
||||||
|
|
||||||
|
#include "../cmn/path.h"
|
||||||
|
|
||||||
|
Config config;
|
||||||
|
|
||||||
|
Config::Config()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL Config::Load()
|
||||||
|
{
|
||||||
|
// Get config file
|
||||||
|
m_configFile.resize(MAX_PATH);
|
||||||
|
return GetConfigFilename(&m_configFile[0]) && PathFileExists(m_configFile.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
UINT Config::GetInt(LPCTSTR name, UINT defaultValue)
|
||||||
|
{
|
||||||
|
return GetPrivateProfileInt(appName, name, defaultValue, m_configFile.c_str());
|
||||||
|
}
|
24
lib/config.h
Normal file
24
lib/config.h
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
#ifndef CONFIG_H
|
||||||
|
#define CONFIG_H
|
||||||
|
|
||||||
|
#include <STRING>
|
||||||
|
#include <TCHAR.H>
|
||||||
|
#include <WINDOWS.H>
|
||||||
|
|
||||||
|
class Config
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Config();
|
||||||
|
|
||||||
|
BOOL Load();
|
||||||
|
|
||||||
|
UINT GetInt(LPCTSTR name, UINT defaultValue = 0);
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::basic_string<TCHAR> m_configFile;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
extern Config config;
|
||||||
|
|
||||||
|
#endif // CONFIG_H
|
|
@ -2,19 +2,23 @@
|
||||||
|
|
||||||
#include <STDIO.H>
|
#include <STDIO.H>
|
||||||
|
|
||||||
|
#include "../cmn/path.h"
|
||||||
|
#include "config.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
|
||||||
|
HWND isleWindow = NULL;
|
||||||
|
|
||||||
void InterceptOutputDebugStringA(LPCSTR s)
|
void InterceptOutputDebugStringA(LPCSTR s)
|
||||||
{
|
{
|
||||||
printf("%s\n", s);
|
printf("%s\n", s);
|
||||||
MessageBoxA(0,s,"LEGO Island sez",0);
|
MessageBoxA(isleWindow, s, "LEGO Island sez", 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
HWND WINAPI InterceptCreateWindowExA(DWORD dwExStyle, LPCSTR lpClassName, LPCSTR lpWindowName, DWORD dwStyle, int X, int Y, int nWidth, int nHeight, HWND hWndParent, HMENU hMenu, HINSTANCE hInstance, LPVOID lpParam)
|
HWND WINAPI InterceptCreateWindowExA(DWORD dwExStyle, LPCSTR lpClassName, LPCSTR lpWindowName, DWORD dwStyle, int X, int Y, int nWidth, int nHeight, HWND hWndParent, HMENU hMenu, HINSTANCE hInstance, LPVOID lpParam)
|
||||||
{
|
{
|
||||||
HWND window = CreateWindowExA(dwExStyle, lpClassName, "LEGO Island: Rebuilt", dwStyle, X, Y, nWidth, nHeight, hWndParent, hMenu, hInstance, lpParam);
|
// Grab a copy of the ISLE window so we can do stuff with it
|
||||||
|
isleWindow = CreateWindowExA(dwExStyle, lpClassName, "LEGO Island: Rebuilt", dwStyle, X, Y, nWidth, nHeight, hWndParent, hMenu, hInstance, lpParam);
|
||||||
return window;
|
return isleWindow;
|
||||||
}
|
}
|
||||||
|
|
||||||
HWND WINAPI InterceptFindWindowA(LPCSTR lpClassName, LPCSTR lpWindowName)
|
HWND WINAPI InterceptFindWindowA(LPCSTR lpClassName, LPCSTR lpWindowName)
|
||||||
|
@ -106,10 +110,71 @@ HRESULT WINAPI InterceptDirectDrawCreate(GUID *lpGUID, LPDIRECTDRAW *lplpDD, IUn
|
||||||
{
|
{
|
||||||
HRESULT res = ddCreateOriginal(lpGUID, lplpDD, pUnkOuter);
|
HRESULT res = ddCreateOriginal(lpGUID, lplpDD, pUnkOuter);
|
||||||
|
|
||||||
if (res == DD_OK && !originalGetDisplayMode) {
|
if (res == DD_OK) {
|
||||||
originalGetDisplayMode = (ddGetDisplayModeFunction)OverwriteVirtualTable(*lplpDD, 0xC, (LPVOID)InterceptGetDisplayMode);
|
if (!originalGetDisplayMode) {
|
||||||
originalCreateSurfaceFunction = (ddCreateSurfaceFunction)OverwriteVirtualTable(*lplpDD, 0x6, (LPVOID)InterceptCreateSurface);
|
originalGetDisplayMode = (ddGetDisplayModeFunction)OverwriteVirtualTable(*lplpDD, 0xC, (LPVOID)InterceptGetDisplayMode);
|
||||||
|
}
|
||||||
|
|
||||||
|
ddCreateSurfaceFunction f = (ddCreateSurfaceFunction)OverwriteVirtualTable(*lplpDD, 0x6, (LPVOID)InterceptCreateSurface);
|
||||||
|
if (f != InterceptCreateSurface) {
|
||||||
|
originalCreateSurfaceFunction = f;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ReturnRegistryYESNOFromBool(LPBYTE lpData, BOOL value)
|
||||||
|
{
|
||||||
|
strcpy((char*)lpData, value ? "YES" : "NO");
|
||||||
|
}
|
||||||
|
|
||||||
|
LONG WINAPI InterceptRegQueryValueExA(HKEY hKey, LPCSTR lpValueName, LPDWORD lpReserved, LPDWORD lpType, LPBYTE lpData, LPDWORD lpcbData)
|
||||||
|
{
|
||||||
|
if (!strcmp(lpValueName, "Music")) {
|
||||||
|
|
||||||
|
// Music option
|
||||||
|
ReturnRegistryYESNOFromBool(lpData, config.GetInt(_T("MusicToggle"), 1));
|
||||||
|
return ERROR_SUCCESS;
|
||||||
|
|
||||||
|
} else if (!strcmp(lpValueName, "UseJoystick")) {
|
||||||
|
|
||||||
|
ReturnRegistryYESNOFromBool(lpData, config.GetInt(_T("UseJoystick"), 0));
|
||||||
|
return ERROR_SUCCESS;
|
||||||
|
|
||||||
|
} else if (!strcmp(lpValueName, "Full Screen")) {
|
||||||
|
|
||||||
|
ReturnRegistryYESNOFromBool(lpData, config.GetInt(_T("FullScreen"), 1));
|
||||||
|
return ERROR_SUCCESS;
|
||||||
|
|
||||||
|
} else if (!strcmp(lpValueName, "Draw Cursor")) {
|
||||||
|
|
||||||
|
ReturnRegistryYESNOFromBool(lpData, config.GetInt(_T("DrawCursor"), 1));
|
||||||
|
return ERROR_SUCCESS;
|
||||||
|
|
||||||
|
} else if (!strcmp(lpValueName, "savepath")) {
|
||||||
|
|
||||||
|
// If enabled, return a safe %APPDATA% based save location rather than its default
|
||||||
|
// "C:\Program Files" location
|
||||||
|
if (config.GetInt(_T("RedirectSaveData"))) {
|
||||||
|
// Generate directory
|
||||||
|
TCHAR save_path[MAX_PATH];
|
||||||
|
if (GetSafeLEGOIslandSavePath(save_path)) {
|
||||||
|
strcpy((char*)lpData, save_path);
|
||||||
|
return ERROR_SUCCESS;
|
||||||
|
} else {
|
||||||
|
MessageBoxA(isleWindow, "Failed to redirect save path. Default will be used instead.", 0, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if (!strcmp(lpValueName, "diskpath") || !strcmp(lpValueName, "cdpath")) {
|
||||||
|
|
||||||
|
// Pass through
|
||||||
|
|
||||||
|
} else {
|
||||||
|
MessageBoxA(isleWindow, lpValueName, "ISLE asked for...", 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pass these through
|
||||||
|
return RegQueryValueExA(hKey, lpValueName, lpReserved, lpType, lpData, lpcbData);
|
||||||
|
}
|
||||||
|
|
11
lib/hooks.h
11
lib/hooks.h
|
@ -21,6 +21,17 @@ HWND WINAPI InterceptCreateWindowExA(
|
||||||
LPVOID lpParam
|
LPVOID lpParam
|
||||||
);
|
);
|
||||||
|
|
||||||
|
LONG
|
||||||
|
APIENTRY
|
||||||
|
InterceptRegQueryValueExA (
|
||||||
|
HKEY hKey,
|
||||||
|
LPCSTR lpValueName,
|
||||||
|
LPDWORD lpReserved,
|
||||||
|
LPDWORD lpType,
|
||||||
|
LPBYTE lpData,
|
||||||
|
LPDWORD lpcbData
|
||||||
|
);
|
||||||
|
|
||||||
HWND WINAPI InterceptFindWindowA(LPCSTR lpClassName, LPCSTR lpWindowName);
|
HWND WINAPI InterceptFindWindowA(LPCSTR lpClassName, LPCSTR lpWindowName);
|
||||||
|
|
||||||
typedef HRESULT (WINAPI *ddCreateFunction)(GUID *lpGUID, LPDIRECTDRAW *lplpDD, IUnknown *pUnkOuterS);
|
typedef HRESULT (WINAPI *ddCreateFunction)(GUID *lpGUID, LPDIRECTDRAW *lplpDD, IUnknown *pUnkOuterS);
|
||||||
|
|
|
@ -1,13 +1,18 @@
|
||||||
#include "worker.h"
|
#include "worker.h"
|
||||||
|
|
||||||
|
#include <TCHAR.H>
|
||||||
#include <VECTOR>
|
#include <VECTOR>
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
#include "hooks.h"
|
#include "hooks.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
|
||||||
DWORD WINAPI Patch()
|
DWORD WINAPI Patch()
|
||||||
{
|
{
|
||||||
MessageBoxA(0,"Connect debugger now",0,0);
|
if (!config.Load()) {
|
||||||
|
MessageBoxA(0, "Failed to find Rebuilder configuration. No patches will be active.", 0, 0);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
// Hook import address table
|
// Hook import address table
|
||||||
LPVOID exeBase = GetModuleHandle(TEXT("ISLE.EXE"));
|
LPVOID exeBase = GetModuleHandle(TEXT("ISLE.EXE"));
|
||||||
|
@ -15,31 +20,47 @@ DWORD WINAPI Patch()
|
||||||
|
|
||||||
// Redirect various imports
|
// Redirect various imports
|
||||||
OverwriteImport(exeBase, "CreateWindowExA", (LPVOID)InterceptCreateWindowExA);
|
OverwriteImport(exeBase, "CreateWindowExA", (LPVOID)InterceptCreateWindowExA);
|
||||||
OverwriteImport(exeBase, "FindWindowA", (LPVOID)InterceptFindWindowA);
|
|
||||||
OverwriteImport(dllBase, "OutputDebugStringA", (LPVOID)InterceptOutputDebugStringA);
|
OverwriteImport(dllBase, "OutputDebugStringA", (LPVOID)InterceptOutputDebugStringA);
|
||||||
|
OverwriteImport(exeBase, "RegQueryValueExA", (LPVOID)InterceptRegQueryValueExA);
|
||||||
ddCreateOriginal = (ddCreateFunction)OverwriteImport(dllBase, "DirectDrawCreate", (LPVOID)InterceptDirectDrawCreate);
|
ddCreateOriginal = (ddCreateFunction)OverwriteImport(dllBase, "DirectDrawCreate", (LPVOID)InterceptDirectDrawCreate);
|
||||||
|
|
||||||
// Stay active when defocused
|
// Stay active when defocused
|
||||||
SearchReplacePattern(exeBase, "\x89\x58\x70", "\x90\x90\x90", 3);
|
if (config.GetInt(_T("StayActiveWhenDefocused"))) {
|
||||||
SearchReplacePattern(dllBase, "\xC7\x44\x24\x24\xE0\x00\x00\x00", "\xC7\x44\x24\x24\xE0\x80\x00\x00", 8);
|
// Patch jump if window isn't active
|
||||||
SearchReplacePattern(dllBase, "\xC7\x44\x24\x24\xB0\x00\x00\x00", "\xC7\x44\x24\x24\xB0\x80\x00\x00", 8);
|
SearchReplacePattern(exeBase, "\x89\x58\x70", "\x90\x90\x90", 3);
|
||||||
SearchReplacePattern(dllBase, "\xC7\x45\xCC\x11\x00\x00\x00", "\xC7\x45\xCC\x11\x80\x00\x00", 7);
|
|
||||||
SearchReplacePattern(dllBase, "\xC7\x45\xCC\xE0\x00\x00\x00", "\xC7\x45\xCC\xE0\x80\x00\x00", 7);
|
// Patch DirectSound flags so that sound doesn't mute when inactive
|
||||||
|
SearchReplacePattern(dllBase, "\xC7\x44\x24\x24\xE0\x00\x00\x00", "\xC7\x44\x24\x24\xE0\x80\x00\x00", 8);
|
||||||
|
SearchReplacePattern(dllBase, "\xC7\x44\x24\x24\xB0\x00\x00\x00", "\xC7\x44\x24\x24\xB0\x80\x00\x00", 8);
|
||||||
|
SearchReplacePattern(dllBase, "\xC7\x45\xCC\x11\x00\x00\x00", "\xC7\x45\xCC\x11\x80\x00\x00", 7);
|
||||||
|
SearchReplacePattern(dllBase, "\xC7\x45\xCC\xE0\x00\x00\x00", "\xC7\x45\xCC\xE0\x80\x00\x00", 7);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Allow multiple instances
|
||||||
|
if (config.GetInt(_T("AllowMultipleInstances"))) {
|
||||||
|
// Patch FindWindowA import to always tell ISLE that no other ISLE window exists
|
||||||
|
OverwriteImport(exeBase, "FindWindowA", (LPVOID)InterceptFindWindowA);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Debug mode
|
||||||
|
if (config.GetInt(_T("DebugToggle"))) {
|
||||||
|
// LEGO1 uses a string pointer to know if OGEL has been typed, if the string pointer sees 0x0
|
||||||
|
// (null-terminator/end of string), then debug mode is enabled. So we just replace the first
|
||||||
|
// character with 0x0 and it's permanently on.
|
||||||
|
SearchReplacePattern(dllBase, "OGEL", "\x0GEL", 4, TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// DDRAW GetSurfaceDesc Override
|
// DDRAW GetSurfaceDesc Override
|
||||||
//OverwriteCall((LPVOID) ((UINT_PTR)dllBase+0xBA7D5), (LPVOID)InterceptSurfaceGetDesc);
|
OverwriteCall((LPVOID) ((UINT_PTR)dllBase+0xBA7D5), (LPVOID)InterceptSurfaceGetDesc);
|
||||||
|
|
||||||
// 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",
|
||||||
"\x40\x01\x00\x00\xE0\x01\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x80\x02\x00\x00\xE0\x01\x00\x00", 24);*/
|
"\x40\x01\x00\x00\xE0\x01\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x80\x02\x00\x00\xE0\x01\x00\x00", 24);*/
|
||||||
|
|
||||||
/*char debug[5];
|
|
||||||
debug[0] = 0xE8;
|
|
||||||
*(UINT_PTR*)(&debug[1]) = (UINT_PTR)InterceptOutputDebugStringA;
|
|
||||||
if (SIZE_T replacements = SearchReplacePattern(legoBase, "\xE8\x34\x08\x00\x00", debug, 5)) {
|
|
||||||
printf("Hooked some other debug function %lu times", replacements);
|
|
||||||
}*/
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,9 @@
|
||||||
#include "patchgrid.h"
|
#include "patchgrid.h"
|
||||||
|
|
||||||
|
#include <SSTREAM>
|
||||||
|
|
||||||
|
#include "../cmn/path.h"
|
||||||
|
|
||||||
PatchGrid::PatchGrid()
|
PatchGrid::PatchGrid()
|
||||||
{
|
{
|
||||||
SetBoldModified(true);
|
SetBoldModified(true);
|
||||||
|
@ -39,13 +43,14 @@ PatchGrid::PatchGrid()
|
||||||
HSECTION sectionControls = AddSection(_T("Controls"));
|
HSECTION sectionControls = AddSection(_T("Controls"));
|
||||||
|
|
||||||
AddPatch("UseWASD",
|
AddPatch("UseWASD",
|
||||||
_T(""),
|
_T("Enables the use of WASD keys for movement rather than the arrow keys. "
|
||||||
|
"NOTE: When using Debug Mode, this patch will re-map the conflicting debug keys to the arrow keys."),
|
||||||
AddBoolItem(sectionControls, _T("Use WASD"), false));
|
AddBoolItem(sectionControls, _T("Use WASD"), false));
|
||||||
AddPatch("UseJoystick",
|
AddPatch("UseJoystick",
|
||||||
_T(""),
|
_T("Enables Joystick functionality."),
|
||||||
AddBoolItem(sectionControls, _T("Use Joystick"), false));
|
AddBoolItem(sectionControls, _T("Use Joystick"), false));
|
||||||
AddPatch("MouseDeadzone",
|
AddPatch("MouseDeadzone",
|
||||||
_T(""),
|
_T("Sets the radius from the center of the screen where the mouse will do nothing (40 = default)."),
|
||||||
AddIntegerItem(sectionControls, _T("Mouse Deadzone"), 40));
|
AddIntegerItem(sectionControls, _T("Mouse Deadzone"), 40));
|
||||||
AddPatch("UnhookTurnSpeed",
|
AddPatch("UnhookTurnSpeed",
|
||||||
_T("LEGO Island contains a bug where the turning speed is influenced by the frame rate. Enable this to make the turn speed independent of the frame rate."),
|
_T("LEGO Island contains a bug where the turning speed is influenced by the frame rate. Enable this to make the turn speed independent of the frame rate."),
|
||||||
|
@ -129,12 +134,55 @@ PatchGrid::PatchGrid()
|
||||||
AddBoolItem(sectionMusic, _T("Play Music"), true));
|
AddBoolItem(sectionMusic, _T("Play Music"), true));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
std::string toString(const T &value)
|
||||||
|
{
|
||||||
|
std::ostringstream oss;
|
||||||
|
oss << value;
|
||||||
|
return oss.str();
|
||||||
|
}
|
||||||
|
|
||||||
BOOL PatchGrid::SaveConfiguration(LPCTSTR filename)
|
BOOL PatchGrid::SaveConfiguration(LPCTSTR filename)
|
||||||
{
|
{
|
||||||
LPCTSTR appName = TEXT("Rebuilder");
|
|
||||||
|
|
||||||
for (std::map<std::string, HITEM>::const_iterator it=m_mPatchItems.begin(); it!=m_mPatchItems.end(); it++) {
|
for (std::map<std::string, HITEM>::const_iterator it=m_mPatchItems.begin(); it!=m_mPatchItems.end(); it++) {
|
||||||
|
CItem *item = FindItem(it->second);
|
||||||
|
|
||||||
std::string value;
|
std::string value;
|
||||||
|
|
||||||
|
// Convert value to string
|
||||||
|
switch (item->m_type) {
|
||||||
|
case IT_STRING:
|
||||||
|
case IT_TEXT:
|
||||||
|
case IT_FILE:
|
||||||
|
case IT_FOLDER:
|
||||||
|
value = item->m_strValue;
|
||||||
|
break;
|
||||||
|
case IT_BOOLEAN:
|
||||||
|
value = toString(item->m_bValue);
|
||||||
|
break;
|
||||||
|
case IT_COMBO:
|
||||||
|
case IT_INTEGER:
|
||||||
|
value = toString(item->m_nValue);
|
||||||
|
break;
|
||||||
|
case IT_DOUBLE:
|
||||||
|
value = toString(item->m_dValue);
|
||||||
|
break;
|
||||||
|
case IT_COLOR:
|
||||||
|
value = toString(item->m_clrValue);
|
||||||
|
break;
|
||||||
|
case IT_CUSTOM:
|
||||||
|
case IT_DATE:
|
||||||
|
case IT_DATETIME:
|
||||||
|
case IT_FONT:
|
||||||
|
{
|
||||||
|
// Report inability to serialize
|
||||||
|
TCHAR buf[200];
|
||||||
|
sprintf(buf, "Failed to serialize %s to string.", it->first.c_str());
|
||||||
|
MessageBox(buf);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
this->GetItemValue(it->second, value);
|
this->GetItemValue(it->second, value);
|
||||||
if (!WritePrivateProfileString(appName, it->first.c_str(), value.c_str(), filename)) {
|
if (!WritePrivateProfileString(appName, it->first.c_str(), value.c_str(), filename)) {
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
#include "window.h"
|
#include "window.h"
|
||||||
|
|
||||||
#include <SHLWAPI.H>
|
|
||||||
#include <WINDOWS.H>
|
#include <WINDOWS.H>
|
||||||
|
|
||||||
|
#include "../cmn/path.h"
|
||||||
#include "launcher.h"
|
#include "launcher.h"
|
||||||
#include "../res/resource.h"
|
#include "../res/resource.h"
|
||||||
|
|
||||||
|
@ -91,10 +91,8 @@ DWORD WINAPI WaitForProcessToClose(HANDLE hProcess)
|
||||||
void CRebuilderWindow::OnRunClick()
|
void CRebuilderWindow::OnRunClick()
|
||||||
{
|
{
|
||||||
TCHAR configPath[MAX_PATH];
|
TCHAR configPath[MAX_PATH];
|
||||||
if (GetConfigPath(configPath)) {
|
|
||||||
// Append path and save configuration
|
|
||||||
_tcscat(configPath, _T("\\settings.ini"));
|
|
||||||
|
|
||||||
|
if (GetConfigFilename(configPath)) {
|
||||||
if (m_cPatchGrid.SaveConfiguration(configPath)) {
|
if (m_cPatchGrid.SaveConfiguration(configPath)) {
|
||||||
if (HANDLE proc = Launcher::Launch(this->GetSafeHwnd())) {
|
if (HANDLE proc = Launcher::Launch(this->GetSafeHwnd())) {
|
||||||
m_lProcesses.push_back(proc);
|
m_lProcesses.push_back(proc);
|
||||||
|
@ -252,72 +250,6 @@ void CRebuilderWindow::SwitchButtonMode(BOOL running)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOL DirectoryExists(LPCTSTR szPath)
|
|
||||||
{
|
|
||||||
return PathFileExists(szPath) && PathIsDirectory(szPath);
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOL RecursivelyCreateDirectory(LPCTSTR directory)
|
|
||||||
{
|
|
||||||
if (DirectoryExists(directory)) {
|
|
||||||
// Directory already exists, do nothing
|
|
||||||
return TRUE;
|
|
||||||
} else {
|
|
||||||
// Determine directory of this directory
|
|
||||||
std::basic_string<TCHAR> copy = directory;
|
|
||||||
PathRemoveFileSpec(©[0]);
|
|
||||||
|
|
||||||
// Create if necessary
|
|
||||||
if (RecursivelyCreateDirectory(copy.c_str())) {
|
|
||||||
return CreateDirectory(directory, NULL);
|
|
||||||
} else {
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef UNICODE
|
|
||||||
typedef BOOL (WINAPI *SHGetSpecialFolderPathSignature)(HWND hwndOwner, LPWSTR lpszPath, int nFolder, BOOL fCreate);
|
|
||||||
#else
|
|
||||||
typedef BOOL (WINAPI *SHGetSpecialFolderPathSignature)(HWND hwndOwner, LPSTR lpszPath, int nFolder, BOOL fCreate);
|
|
||||||
#endif
|
|
||||||
BOOL CRebuilderWindow::GetConfigPath(LPTSTR s)
|
|
||||||
{
|
|
||||||
OSVERSIONINFO info;
|
|
||||||
ZeroMemory(&info, sizeof(info));
|
|
||||||
info.dwOSVersionInfoSize = sizeof(info);
|
|
||||||
GetVersionEx(&info);
|
|
||||||
|
|
||||||
// Dynamically link to SHGetSpecialFolderPath because not all versions of Windows have it
|
|
||||||
#ifdef UNICODE
|
|
||||||
LPCSTR functionName = "SHGetSpecialFolderPathW";
|
|
||||||
#else
|
|
||||||
LPCSTR functionName = "SHGetSpecialFolderPathA";
|
|
||||||
#endif
|
|
||||||
|
|
||||||
SHGetSpecialFolderPathSignature GetSpecialFolderPath = (SHGetSpecialFolderPathSignature)GetProcAddress(GetModuleHandle(_T("SHELL32.DLL")), functionName);
|
|
||||||
BOOL haveDir = FALSE;
|
|
||||||
BOOL usedShell = FALSE;
|
|
||||||
if (GetSpecialFolderPath) {
|
|
||||||
haveDir = GetSpecialFolderPath(NULL, s, CSIDL_APPDATA, TRUE);
|
|
||||||
usedShell = TRUE;
|
|
||||||
} else {
|
|
||||||
// Assume we're on Windows 95 which has no application data folder, we bodge it to write to
|
|
||||||
// "C:\Windows\Application Data" which is roughly where 98/Me would do it
|
|
||||||
GetWindowsDirectory(s, MAX_PATH);
|
|
||||||
_tcscat(s, _T("\\Application Data"));
|
|
||||||
haveDir = TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (haveDir) {
|
|
||||||
_tcscat(s, _T("\\LEGOIslandRebuilder"));
|
|
||||||
MessageBox(s, usedShell ? _T("Using API") : _T("Is this Windows 95?"));
|
|
||||||
return RecursivelyCreateDirectory(s);
|
|
||||||
} else {
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
BEGIN_MESSAGE_MAP(CRebuilderWindow, super)
|
BEGIN_MESSAGE_MAP(CRebuilderWindow, super)
|
||||||
ON_WM_SIZE()
|
ON_WM_SIZE()
|
||||||
ON_WM_GETMINMAXINFO()
|
ON_WM_GETMINMAXINFO()
|
||||||
|
|
|
@ -34,8 +34,6 @@ private:
|
||||||
|
|
||||||
void SwitchButtonMode(BOOL running);
|
void SwitchButtonMode(BOOL running);
|
||||||
|
|
||||||
BOOL GetConfigPath(LPTSTR s);
|
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
ID_RUN = 1000,
|
ID_RUN = 1000,
|
||||||
ID_KILL,
|
ID_KILL,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue