Metric/Imperial check based on Windows locale settings and on INI/debug menu override (III/VC)

This commit is contained in:
Silent 2019-08-24 22:35:35 +02:00
parent da5b5b1e12
commit bb02824c91
No known key found for this signature in database
GPG Key ID: AE53149BB0C45AF1
8 changed files with 208 additions and 0 deletions

View File

@ -98,5 +98,10 @@ namespace Common {
{
DelayedPatches::Func = std::move(func);
}
void III_VC_DelayedCommon( bool /*hasDebugMenu*/, const wchar_t* /*iniPath*/ )
{
}
}
}

View File

@ -4,6 +4,7 @@ namespace Common
{
namespace Patches
{
void III_VC_DelayedCommon( bool hasDebugMenu, const wchar_t* iniPath );
void III_VC_Common();
void III_VC_SetDelayedPatchesFunc( void(*func)() );
}

View File

@ -7,6 +7,11 @@
#include "Common_ddraw.h"
#include <memory>
#include <Shlwapi.h>
#include "debugmenu_public.h"
#pragma comment(lib, "shlwapi.lib")
struct PsGlobalType
{
@ -44,6 +49,10 @@ struct RwV2d
float y; /**< Y value */
};
DebugMenuAPI gDebugMenuAPI;
static HMODULE hDLLModule;
static void (*DrawRect)(const CRect&,const CRGBA&);
static void (*SetScale)(float,float);
@ -426,6 +435,68 @@ namespace KeyboardInputFix
}
}
namespace Localization
{
static int8_t forcedUnits = -1; // 0 - metric, 1 - imperial
bool IsMetric_LocaleBased()
{
if ( forcedUnits != -1 ) return forcedUnits == 0;
unsigned int LCData;
if ( GetLocaleInfo( LOCALE_USER_DEFAULT, LOCALE_IMEASURE|LOCALE_RETURN_NUMBER, reinterpret_cast<LPTSTR>(&LCData), sizeof(LCData) / sizeof(TCHAR) ) != 0 )
{
return LCData == 0;
}
// If fails, default to metric. Hopefully never fails though
return true;
}
static void (__thiscall* orgUpdateCompareFlag_IsMetric)(void* pThis, uint8_t flag);
void __fastcall UpdateCompareFlag_IsMetric(void* pThis, void*, uint8_t)
{
std::invoke( orgUpdateCompareFlag_IsMetric, pThis, IsMetric_LocaleBased() );
}
uint32_t PrefsLanguage_IsMetric()
{
return IsMetric_LocaleBased();
}
}
void InjectDelayedPatches_III_Common( bool bHasDebugMenu, const wchar_t* wcModulePath )
{
// Locale based metric/imperial system INI/debug menu
{
using namespace Localization;
forcedUnits = static_cast<int8_t>(GetPrivateProfileIntW(L"SilentPatch", L"Units", -1, wcModulePath));
if ( bHasDebugMenu )
{
static const char * const str[] = { "Default", "Metric", "Imperial" };
DebugMenuEntry *e = DebugMenuAddVar( "SilentPatch", "Forced units", &forcedUnits, nullptr, 1, -1, 1, str );
DebugMenuEntrySetWrap(e, true);
}
}
}
void InjectDelayedPatches_III_Common()
{
std::unique_ptr<ScopedUnprotect::Unprotect> Protect = ScopedUnprotect::UnprotectSectionOrFullModule( GetModuleHandle( nullptr ), ".text" );
// Obtain a path to the ASI
wchar_t wcModulePath[MAX_PATH];
GetModuleFileNameW(hDLLModule, wcModulePath, _countof(wcModulePath) - 3); // Minus max required space for extension
PathRenameExtensionW(wcModulePath, L".ini");
const bool hasDebugMenu = DebugMenuLoad();
InjectDelayedPatches_III_Common( hasDebugMenu, wcModulePath );
Common::Patches::III_VC_DelayedCommon( hasDebugMenu, wcModulePath );
}
void Patch_III_10(const RECT& desktop)
{
@ -953,6 +1024,32 @@ void Patch_III_Common()
InjectHook( simButtonCheckers, ClearSimButtonPressCheckers );
InjectHook( updatePads.get<void>( 10 ), jmpDest, PATCH_JUMP );
}
// Locale based metric/imperial system
{
using namespace Localization;
void* updateCompareFlag = get_pattern( "89 E9 6A 00 E8 ? ? ? ? 30 C0 83 C4 70 5D 5E 5B C2 04 00", 4 );
ReadCall( updateCompareFlag, orgUpdateCompareFlag_IsMetric );
InjectHook( updateCompareFlag, UpdateCompareFlag_IsMetric );
// Stats
auto constructStatLine = pattern( "FF 24 9D ? ? ? ? 39 D0" ).get_one();
// push eax
// push edx
// call IsMetric_LocaleBased
// movzx ebx, al
// pop edx
// pop eax
// nop...
Patch( constructStatLine.get<void>( -0xF ), { 0x50, 0x52 } );
InjectHook( constructStatLine.get<void>( -0xF + 2 ), PrefsLanguage_IsMetric, PATCH_CALL );
Patch( constructStatLine.get<void>( -0xF + 7 ), { 0x0F, 0xB6, 0xD8, 0x5A, 0x58 } );
Nop( constructStatLine.get<void>( -0xF + 12 ), 3 );
}
}
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
@ -962,6 +1059,8 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
if ( fdwReason == DLL_PROCESS_ATTACH )
{
hDLLModule = hinstDLL;
RECT desktop;
GetWindowRect(GetDesktopWindow(), &desktop);
sprintf_s(aNoDesktopMode, "Cannot find %dx%dx32 video mode", desktop.right, desktop.bottom);
@ -978,6 +1077,8 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
Patch_III_Common();
Common::Patches::III_VC_Common();
Common::Patches::DDraw_Common();
Common::Patches::III_VC_SetDelayedPatchesFunc( InjectDelayedPatches_III_Common );
}
Common::Patches::FixRwcseg_Patterns();

View File

@ -42,6 +42,7 @@
<ItemGroup>
<ClInclude Include="..\SilentPatch\Common.h" />
<ClInclude Include="..\SilentPatch\Common_ddraw.h" />
<ClInclude Include="..\SilentPatch\debugmenu_public.h" />
<ClInclude Include="..\SilentPatch\General.h" />
<ClInclude Include="..\SilentPatch\StdAfx.h" />
<ClInclude Include="..\SilentPatch\StoredCar.h" />

View File

@ -74,6 +74,9 @@
<ClInclude Include="..\SilentPatch\Utils\Patterns.h">
<Filter>Header Files\Utils</Filter>
</ClInclude>
<ClInclude Include="..\SilentPatch\debugmenu_public.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="..\SilentPatch\SilentPatch.rc">

View File

@ -8,6 +8,11 @@
#include "ModelInfoVC.h"
#include <memory>
#include <Shlwapi.h>
#include "debugmenu_public.h"
#pragma comment(lib, "shlwapi.lib")
struct RsGlobalType
{
@ -23,6 +28,10 @@ struct RsGlobalType
void* pad;
};
DebugMenuAPI gDebugMenuAPI;
static HMODULE hDLLModule;
static const void* RosieAudioFix_JumpBack;
static void (*PrintString)(float,float,const wchar_t*);
@ -298,6 +307,68 @@ namespace KeyboardInputFix
}
}
namespace Localization
{
static int8_t forcedUnits = -1; // 0 - metric, 1 - imperial
bool IsMetric_LocaleBased()
{
if ( forcedUnits != -1 ) return forcedUnits == 0;
unsigned int LCData;
if ( GetLocaleInfo( LOCALE_USER_DEFAULT, LOCALE_IMEASURE|LOCALE_RETURN_NUMBER, reinterpret_cast<LPTSTR>(&LCData), sizeof(LCData) / sizeof(TCHAR) ) != 0 )
{
return LCData == 0;
}
// If fails, default to metric. Hopefully never fails though
return true;
}
static void (__thiscall* orgUpdateCompareFlag_IsMetric)(void* pThis, uint8_t flag);
void __fastcall UpdateCompareFlag_IsMetric(void* pThis, void*, uint8_t)
{
std::invoke( orgUpdateCompareFlag_IsMetric, pThis, IsMetric_LocaleBased() );
}
uint32_t PrefsLanguage_IsMetric()
{
return IsMetric_LocaleBased();
}
}
void InjectDelayedPatches_VC_Common( bool bHasDebugMenu, const wchar_t* wcModulePath )
{
// Locale based metric/imperial system INI/debug menu
{
using namespace Localization;
forcedUnits = static_cast<int8_t>(GetPrivateProfileIntW(L"SilentPatch", L"Units", -1, wcModulePath));
if ( bHasDebugMenu )
{
static const char * const str[] = { "Default", "Metric", "Imperial" };
DebugMenuEntry *e = DebugMenuAddVar( "SilentPatch", "Forced units", &forcedUnits, nullptr, 1, -1, 1, str );
DebugMenuEntrySetWrap(e, true);
}
}
}
void InjectDelayedPatches_VC_Common()
{
std::unique_ptr<ScopedUnprotect::Unprotect> Protect = ScopedUnprotect::UnprotectSectionOrFullModule( GetModuleHandle( nullptr ), ".text" );
// Obtain a path to the ASI
wchar_t wcModulePath[MAX_PATH];
GetModuleFileNameW(hDLLModule, wcModulePath, _countof(wcModulePath) - 3); // Minus max required space for extension
PathRenameExtensionW(wcModulePath, L".ini");
const bool hasDebugMenu = DebugMenuLoad();
InjectDelayedPatches_VC_Common( hasDebugMenu, wcModulePath );
Common::Patches::III_VC_DelayedCommon( hasDebugMenu, wcModulePath );
}
void Patch_VC_10(const RECT& desktop)
{
using namespace Memory;
@ -779,6 +850,24 @@ void Patch_VC_Common()
InjectHook( updatePads.get<void>( 9 ), jmpDest, PATCH_JUMP );
}
// Locale based metric/imperial system
{
using namespace Localization;
void* updateCompareFlag = get_pattern( "89 D9 6A 00 E8 ? ? ? ? 30 C0 83 C4 70 5D 5F 5E 5B C2 04 00", 4 );
ReadCall( updateCompareFlag, orgUpdateCompareFlag_IsMetric );
InjectHook( updateCompareFlag, UpdateCompareFlag_IsMetric );
// Stats
auto constructStatLine = pattern( "85 C0 74 11 83 E8 01 83 F8 03" ).get_one();
Nop( constructStatLine.get<void>( -11 ), 1 );
InjectHook( constructStatLine.get<void>( -11 + 1 ), PrefsLanguage_IsMetric, PATCH_CALL );
Nop( constructStatLine.get<void>( -2 ), 2 );
}
}
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
@ -788,6 +877,8 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
if ( fdwReason == DLL_PROCESS_ATTACH )
{
hDLLModule = hinstDLL;
RECT desktop;
GetWindowRect(GetDesktopWindow(), &desktop);
sprintf_s(aNoDesktopMode, "Cannot find %dx%dx32 video mode", desktop.right, desktop.bottom);
@ -807,6 +898,8 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
Patch_VC_Common();
Common::Patches::III_VC_Common();
Common::Patches::DDraw_Common();
Common::Patches::III_VC_SetDelayedPatchesFunc( InjectDelayedPatches_VC_Common );
}
Common::Patches::FixRwcseg_Patterns();

View File

@ -172,6 +172,7 @@
</ItemDefinitionGroup>
<ItemGroup>
<ClInclude Include="..\SilentPatch\Common_ddraw.h" />
<ClInclude Include="..\SilentPatch\debugmenu_public.h" />
<ClInclude Include="..\SilentPatch\General.h" />
<ClInclude Include="..\SilentPatch\StdAfx.h" />
<ClInclude Include="..\SilentPatch\StoredCar.h" />

View File

@ -51,6 +51,9 @@
<ClInclude Include="..\SilentPatch\Utils\Patterns.h">
<Filter>Header Files\Utils</Filter>
</ClInclude>
<ClInclude Include="..\SilentPatch\debugmenu_public.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\SilentPatch\Timer.cpp">