diff --git a/SilentPatchIII/SilentPatchIII.cpp b/SilentPatchIII/SilentPatchIII.cpp index 46c6ac2..97de0c4 100644 --- a/SilentPatchIII/SilentPatchIII.cpp +++ b/SilentPatchIII/SilentPatchIII.cpp @@ -839,6 +839,56 @@ namespace SitInBoat } +// ============= Fixed Brightness saving (fixed in VC) ============= +namespace FixedBrightnessSaving +{ + // Heuristics we use for determining whether the value is stock or from SilentPatch + // 0 - must have been the default brightness of 256 = stock + // >= 31 - must have been the default brightness of 256 + x = stock + // Otherwise, this must be the "value index" from SilentPatch + int (*orgRead)(int, char*, int); + int Read_Brightness(int file, int* brightness, int size) + { + // This should never happen + if (size != 1) + { + return orgRead(file, reinterpret_cast(brightness), size); + } + + uint8_t tmp; + int result = orgRead(file, reinterpret_cast(&tmp), sizeof(tmp)); + if (result != sizeof(tmp)) + { + return result; + } + + if (tmp == 0 || tmp >= 31) + { + *brightness = 256 + tmp; + } + else + { + *brightness = (tmp - 1) << 5; + } + + return result; + } + + int (*orgWrite)(int, const char*, int); + int Write_Brightness(int file, const int* brightness, int size) + { + // This should never happen + if (size != 1) + { + return orgWrite(file, reinterpret_cast(brightness), size); + } + + const uint32_t brightnessRounded = (*brightness + 31u) & -32; + const uint8_t brightnessPacked = static_cast(brightnessRounded >> 5) + 1; + return orgWrite(file, reinterpret_cast(&brightnessPacked), sizeof(brightnessPacked)); + } +} + namespace ModelIndicesReadyHook { static void (*orgInitialiseObjectData)(const char*); @@ -1824,6 +1874,35 @@ void Patch_III_Common() Patch(spawn_one_car, 0xEB); } TXN_CATCH(); + + + // Fixed Brightness saving (fixed in VC) + try + { + using namespace FixedBrightnessSaving; + + // Read and Write calls in CMenuManager::LoadSettings and CMenuManager::SaveSettings + // are virtually indistinguishable from each other, so we need to build raw patterns that include + // the pointer to CMenuManager::m_PrefsBrightness + auto prefs_brightness = *get_pattern("83 3D ? ? ? ? 00 7D 0B", 2); + uint8_t prefs_brightness_bytes[4]; + memcpy(&prefs_brightness_bytes, &prefs_brightness, sizeof(prefs_brightness_bytes)); + + const uint8_t mask[] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0, 0x0, 0x0, 0x0, 0xFF, 0xFF, 0xFF }; + const uint8_t read_pattern[] { 0x6A, 0x01, 0x68, + prefs_brightness_bytes[0], prefs_brightness_bytes[1], prefs_brightness_bytes[2], prefs_brightness_bytes[3], + 0x53, 0xE8, 0x0, 0x0, 0x0, 0x0, 0x83, 0xC4, 0x0C }; + const uint8_t write_pattern[] { 0x6A, 0x01, 0x68, + prefs_brightness_bytes[0], prefs_brightness_bytes[1], prefs_brightness_bytes[2], prefs_brightness_bytes[3], + 0x55, 0xE8, 0x0, 0x0, 0x0, 0x0, 0x83, 0xC4, 0x0C }; + + auto read = pattern({read_pattern, sizeof(read_pattern)}, {mask, sizeof(mask)}).get_first(8); + auto write = pattern({write_pattern, sizeof(write_pattern)}, {mask, sizeof(mask)}).get_first(8); + + InterceptCall(read, orgRead, Read_Brightness); + InterceptCall(write, orgWrite, Write_Brightness); + } + TXN_CATCH(); } BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)