diff --git a/Common Files/Game.cpp b/Common Files/Game.cpp index 17de6f1..cabb9ee 100644 --- a/Common Files/Game.cpp +++ b/Common Files/Game.cpp @@ -102,6 +102,21 @@ UINT8 Helpers::WriteNop(INT_PTR offset, bool isRelativeOffset) return nop; } +UINT8 Helpers::WriteNopBytes(INT_PTR offset, int countBytes, bool isRelativeOffset) +{ + U8 nop = 0x90; + SIZE_T written; + for (int i = 0; i < countBytes; i++) + { + offset = offset + i; + LPVOID trueOffset = (isRelativeOffset ? GetTranslatedOffset(offset) : (LPVOID)offset); + WriteProcessMemory(GetCurrentProcess(), trueOffset, &nop, 1, &written); + offset = offset - i; + } + return nop; +} + + int Helpers::ReadInt32(INT_PTR offset, bool isRelativeOffset) { int val = 0; diff --git a/Common Files/Game.h b/Common Files/Game.h index 3926adc..f433400 100644 --- a/Common Files/Game.h +++ b/Common Files/Game.h @@ -54,6 +54,7 @@ class Helpers { UINT8 WriteByte(INT_PTR offset, UINT8 val, bool isRelativeOffset); INT_PTR WriteIntPtr(INT_PTR offset, INT_PTR val, bool isRelativeOffset); UINT8 WriteNop(INT_PTR offset, bool isRelativeOffset); + UINT8 WriteNopBytes(INT_PTR offset, int countBytes, bool isRelativeOffset); INT_PTR ReadIntPtr(INT_PTR offset, bool isRelativeOffset); float ReadFloat32(INT_PTR offset, bool isRelativeOffset); }; diff --git a/Game Files/HarleyDavidson.cpp b/Game Files/HarleyDavidson.cpp new file mode 100644 index 0000000..3ff2979 --- /dev/null +++ b/Game Files/HarleyDavidson.cpp @@ -0,0 +1,53 @@ +/*This file is part of Output Blaster. + +Output Blaster is free software : you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +Output Blaster is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Output Blaster.If not, see < https://www.gnu.org/licenses/>.*/ + +#include "HarleyDavidson.h" + +static int WindowsLoop() +{ + UINT8 myLamp = helpers->ReadByte(0x88F4420, false); + Outputs->SetValue(OutputLampStart, !!(myLamp & 0x128)); + Outputs->SetValue(OutputLampLeader, !!(myLamp & 0x64)); + Outputs->SetValue(OutputLampLeader2, !!(myLamp & 0x32)); + return 0; +} + +static DWORD WINAPI OutputsAreGo(LPVOID lpParam) +{ + while (true) + { + WindowsLoop(); + Sleep(SleepA); + } +} + +void HarleyDavidson::OutputsGameLoop() +{ + if (!init) + { + Outputs = CreateOutputsFromConfig(); + m_game.name = "Harley Davidson King Of the Road"; + Outputs->SetGame(m_game); + Outputs->Initialize(); + Outputs->Attached(); + CreateThread(NULL, 0, OutputsAreGo, NULL, 0, NULL); + while (GetMessage(&Msg1, NULL, NULL, 0)) + { + TranslateMessage(&Msg1); + DispatchMessage(&Msg1); + } + init = true; + } +} \ No newline at end of file diff --git a/Game Files/HarleyDavidson.h b/Game Files/HarleyDavidson.h new file mode 100644 index 0000000..1983189 --- /dev/null +++ b/Game Files/HarleyDavidson.h @@ -0,0 +1,22 @@ +/*This file is part of Output Blaster. + +Output Blaster is free software : you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +Output Blaster is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Output Blaster.If not, see < https://www.gnu.org/licenses/>.*/ + +#pragma once +#include "../Common Files/Game.h" +class HarleyDavidson : public Game { + +public: + void OutputsGameLoop(); +}; \ No newline at end of file diff --git a/Game Files/Hummer.cpp b/Game Files/Hummer.cpp new file mode 100644 index 0000000..9a2701b --- /dev/null +++ b/Game Files/Hummer.cpp @@ -0,0 +1,54 @@ +/*This file is part of Output Blaster. + +Output Blaster is free software : you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +Output Blaster is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Output Blaster.If not, see < https://www.gnu.org/licenses/>.*/ + +#include "Hummer.h" + +static int WindowsLoop() +{ + UINT8 myLamp = helpers->ReadByte(0xa69fc24, false); + Outputs->SetValue(OutputLampStart, !!(myLamp & 0x80)); + Outputs->SetValue(OutputLampView1, !!(myLamp & 0x08)); + Outputs->SetValue(OutputLampView2, !!(myLamp & 0x10)); + Outputs->SetValue(OutputLampWhite, !!(myLamp & 0x64)); + return 0; +} + +static DWORD WINAPI OutputsAreGo(LPVOID lpParam) +{ + while (true) + { + WindowsLoop(); + Sleep(SleepA); + } +} + +void Hummer::OutputsGameLoop() +{ + if (!init) + { + Outputs = CreateOutputsFromConfig(); + m_game.name = "Hummer"; + Outputs->SetGame(m_game); + Outputs->Initialize(); + Outputs->Attached(); + CreateThread(NULL, 0, OutputsAreGo, NULL, 0, NULL); + while (GetMessage(&Msg1, NULL, NULL, 0)) + { + TranslateMessage(&Msg1); + DispatchMessage(&Msg1); + } + init = true; + } +} \ No newline at end of file diff --git a/Game Files/Hummer.h b/Game Files/Hummer.h new file mode 100644 index 0000000..84f2643 --- /dev/null +++ b/Game Files/Hummer.h @@ -0,0 +1,22 @@ +/*This file is part of Output Blaster. + +Output Blaster is free software : you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +Output Blaster is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Output Blaster.If not, see < https://www.gnu.org/licenses/>.*/ + +#pragma once +#include "../Common Files/Game.h" +class Hummer : public Game { + +public: + void OutputsGameLoop(); +}; \ No newline at end of file diff --git a/Game Files/M2Emulator.cpp b/Game Files/M2Emulator.cpp index fbc8a59..2ca6692 100644 --- a/Game Files/M2Emulator.cpp +++ b/Game Files/M2Emulator.cpp @@ -14,7 +14,7 @@ You should have received a copy of the GNU General Public License along with Output Blaster.If not, see < https://www.gnu.org/licenses/>.*/ #include "M2Emulator.h" - +static int detectedGameId = 0; static int WindowsLoop() { INT_PTR Rambase = helpers->ReadIntPtr(0x1AA888, true); @@ -29,9 +29,19 @@ static int WindowsLoop() Outputs->SetValue(OutputLampView4, !!(data & 0x40)); Outputs->SetValue(OutputRawLamps, data); + if (detectedGameId == 10) { + //do some custom stuff for this game + } + if (detectedGameId == 12) + { + //do some more custom stuff for this game :) + //And so on... + } + return 0; } + static DWORD WINAPI OutputsAreGo(LPVOID lpParam) { while (true) @@ -50,6 +60,30 @@ void M2Emulator::OutputsGameLoop() Outputs->SetGame(m_game); Outputs->Initialize(); Outputs->Attached(); + + + if(FindWindowA(0, ("Sega Rally Championship"))) detectedGameId = 1; + else if (FindWindowA(0, ("Daytona USA"))) detectedGameId = 2; + else if (FindWindowA(0, ("Indianapolis 500 (Rev A, Deluxe)"))) detectedGameId = 3; + else if (FindWindowA(0, ("Sega Touring Car Championship (Rev A)"))) detectedGameId = 4; + else if (FindWindowA(0, ("Over Rev"))) detectedGameId = 5; + else if (FindWindowA(0, ("Super GT 24h"))) detectedGameId = 6; + else if (FindWindowA(0, ("Daytona USA '93 Edition"))) detectedGameId = 7; + else if (FindWindowA(0, ("Daytona USA (Saturn Ads)"))) detectedGameId = 8; + else if (FindWindowA(0, ("Daytona USA Special Edition"))) detectedGameId = 9; + else if (FindWindowA(0, ("Daytona USA Turbo"))) detectedGameId = 10; + else if (FindWindowA(0, ("Daytona USA Turbo (Rev A)"))) detectedGameId = 11; + else if (FindWindowA(0, ("Daytona USA: GTX 2004"))) detectedGameId = 12; + else if (FindWindowA(0, ("Daytona USA: To The Maxx"))) detectedGameId = 13; + else if (FindWindowA(0, ("Sega Rally Championship (Rev B)"))) detectedGameId = 14; + else if (FindWindowA(0, ("Sega Rally Pro Drivin'"))) detectedGameId = 15; + else if (FindWindowA(0, ("Indianapolis 500 (Rev A, Twin, Newer rev)"))) detectedGameId = 16; + else if (FindWindowA(0, ("Indianapolis 500 (Rev A, Twin, Older rev)"))) detectedGameId = 17; + else if (FindWindowA(0, ("Sega Touring Car Championship"))) detectedGameId = 18; + else if (FindWindowA(0, ("Sega Touring Car Championship (Rev B)"))) detectedGameId = 19; + else if (FindWindowA(0, ("Over Rev (Model 2B)"))) detectedGameId = 20; + + CreateThread(NULL, 0, OutputsAreGo, NULL, 0, NULL); while (GetMessage(&Msg1, NULL, NULL, 0)) { @@ -58,4 +92,4 @@ void M2Emulator::OutputsGameLoop() } init = true; } -} \ No newline at end of file +} diff --git a/Game Files/SuperBikes2.cpp b/Game Files/SuperBikes2.cpp new file mode 100644 index 0000000..d42acc8 --- /dev/null +++ b/Game Files/SuperBikes2.cpp @@ -0,0 +1,154 @@ +/*This file is part of Output Blaster. + +Output Blaster is free software : you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +Output Blaster is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Output Blaster.If not, see < https://www.gnu.org/licenses/>.*/ + +#include "SuperBikes2.h" + + +bool sb2LampStart = false; +bool sb2LampView = false; +bool sb2LampMusic = false; +bool sb2Plate = false; +bool sb2Leader = false; +bool sb2Top = false; +bool sb2Dash = false; +bool sbSubWoofer = false; + +static void* (__cdecl* SetControlOrLampOrig)(unsigned int param_1, unsigned int param_2); +static void* __cdecl SetControlOrLamp(unsigned int param_1, unsigned int param_2) { + void* result = SetControlOrLampOrig(param_1, param_2); + if (param_1 == 0x1004a) { + + unsigned int lampId = (param_2 >> 16) & 0xFF; + unsigned int lampState = param_2 & 0xFFF; + + bool lampOn = (lampState != 0); + if (lampId == 0) sb2LampStart = lampOn; + if (lampId == 2) sb2LampView = lampOn; + if (lampId == 4) sb2Plate = lampOn; + if (lampId == 5) sb2LampMusic = lampOn; + if (lampId == 6) sb2Leader = lampOn; + if (lampId == 7) sb2Top = lampOn; + if (lampId == 10) sb2Dash = lampOn; + if (lampId == 11) sbSubWoofer = lampOn; + + } + return result; +} + +static void(__cdecl* HardwareDispatchOrig)(unsigned int param_1, unsigned int param_2); +static void __cdecl HardwareDispatch(unsigned int param_1, unsigned int param_2) { + return; +} + +static int(__cdecl* SerialInitOrig)(); +static int __cdecl SerialInit() { + return 1; +} + +static int(__cdecl* LedDisplayUpdateOrig)(); +static int __cdecl LedDisplayUpdate() { + return 1; +} + +static int(__cdecl* HidWriteOrig)(LPCVOID param_1); +static int __cdecl HidWrite(LPCVOID param_1) { + return 0; +} + +static int(__cdecl* UsbWriteOrig)(); +static int __cdecl UsbWrite() { + return 0; +} + +static int(__cdecl* HidDeviceScanOrig)(); +static int __cdecl HidDeviceScan() { + return 0; +} + +static int(__cdecl* InitUsbDeviceOrig)(); +static int __cdecl InitUsbDeviceHook() { + return 0; +} + +static int WindowsLoop() +{ + Outputs->SetValue(OutputLampStart, sb2LampStart); + Outputs->SetValue(OutputLampView1, sb2LampView); + Outputs->SetValue(OutputLampView2, sb2LampMusic); + Outputs->SetValue(OutputLampLeader, sb2Leader); + Outputs->SetValue(OutputFogLight1, sb2Top); + Outputs->SetValue(OutputRearCover, sb2Plate); + Outputs->SetValue(OutputDash, sb2Dash); + Outputs->SetValue(OutputWooferBlue, sbSubWoofer); + return 0; +} + +static DWORD WINAPI OutputsAreGo(LPVOID lpParam) +{ + MH_Initialize(); + MH_CreateHook((LPVOID)0x04bbc10, SetControlOrLamp, (LPVOID*)&SetControlOrLampOrig); + MH_CreateHook((LPVOID)0x04018d0, HardwareDispatch, (LPVOID*)&HardwareDispatchOrig); + MH_CreateHook((LPVOID)0x04ee430, SerialInit, (LPVOID*)&SerialInitOrig); + MH_CreateHook((LPVOID)0x04ee890, LedDisplayUpdate, (LPVOID*)&LedDisplayUpdateOrig); + + MH_CreateHook((LPVOID)0x0405800, HidWrite, (LPVOID*)&HidWriteOrig); + MH_CreateHook((LPVOID)0x0402bc0, UsbWrite, (LPVOID*)&UsbWriteOrig); + + MH_CreateHook((LPVOID)0x0405930, HidDeviceScan, (LPVOID*)&HidDeviceScanOrig); + MH_CreateHook((LPVOID)0x0405c80, InitUsbDeviceHook, (LPVOID*)&InitUsbDeviceOrig); + + MH_EnableHook(MH_ALL_HOOKS); + + + *(int*)0x089dfc40 = 1; + + DWORD* hidDev = *(DWORD**)0x0894b4c8; + if (hidDev != nullptr) { + HANDLE hRead = (HANDLE)hidDev[0]; + HANDLE hWrite = (HANDLE)hidDev[1]; + if (hWrite) { CancelIo(hWrite); CloseHandle(hWrite); hidDev[1] = 0; } + if (hRead) { CancelIo(hRead); CloseHandle(hRead); hidDev[0] = 0; } + } + *(DWORD**)0x0894b4c8 = nullptr; + + helpers->WriteNopBytes(0x0046d363, 2, false); + helpers->WriteNopBytes(0x00408f99, 6, false); + + while (true) + { + WindowsLoop(); + Sleep(SleepA); + } +} + +void SuperBikes2::OutputsGameLoop() +{ + if (!init) + { + Outputs = CreateOutputsFromConfig(); + m_game.name = "Super Bikes 2"; + Outputs->SetGame(m_game); + Outputs->Initialize(); + Outputs->Attached(); + OutputDebugStringA("Super Bikes 2 Outputs Initialized"); + CreateThread(NULL, 0, OutputsAreGo, NULL, 0, NULL); + while (GetMessage(&Msg1, NULL, NULL, 0)) + { + TranslateMessage(&Msg1); + DispatchMessage(&Msg1); + } + init = true; + } +} \ No newline at end of file diff --git a/Game Files/SuperBikes2.h b/Game Files/SuperBikes2.h new file mode 100644 index 0000000..5786798 --- /dev/null +++ b/Game Files/SuperBikes2.h @@ -0,0 +1,23 @@ +#pragma once +/*This file is part of Output Blaster. + +Output Blaster is free software : you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +Output Blaster is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Output Blaster.If not, see < https://www.gnu.org/licenses/>.*/ + +#pragma once +#include "../Common Files/Game.h" +class SuperBikes2 : public Game { + +public: + void OutputsGameLoop(); +}; diff --git a/Game Files/batman.cpp b/Game Files/batman.cpp new file mode 100644 index 0000000..07c85ce --- /dev/null +++ b/Game Files/batman.cpp @@ -0,0 +1,96 @@ +/*This file is part of Output Blaster. + +Output Blaster is free software : you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +Output Blaster is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Output Blaster.If not, see < https://www.gnu.org/licenses/>.*/ + +#include "batman.h" + +static bool lightsEnabled = false; + +static int WindowsLoop() +{ + if (lightsEnabled) { + + bool StartButton = helpers->ReadByte(0x1BEF942, false) > 0; + bool FireButtons = helpers->ReadByte(0x1BEF946, false) > 0; + bool BatLogo = helpers->ReadByte(0x1BEF952, false) > 0; + bool Marquee = helpers->ReadByte(0x1BEF97E, false) > 0; + bool SpeakersRed = helpers->ReadByte(0x1BEF962, false) > 0; + bool SpeakersOrange = helpers->ReadByte(0x1BEF966, false) > 0; + bool SpeakersYellow = helpers->ReadByte(0x1BEF96A, false) > 0; + bool CenterDashPanel = helpers->ReadByte(0x1BEF94E, false) > 0; + bool RightDashPanel = helpers->ReadByte(0x1BEF94A, false) > 0; + bool KeypadRed = helpers->ReadByte(0x1BEF96E, false) > 0; + bool KeypadGreen = helpers->ReadByte(0x1BEF972, false) > 0; + bool KeypadBlue = helpers->ReadByte(0x1BEF976, false) > 0; + bool Kickplates = helpers->ReadByte(0x1BEF97A, false) > 0; + + Outputs->SetValue(OutputLampStart, StartButton); + Outputs->SetValue(OutputShoot1p, FireButtons); + Outputs->SetValue(OutputBillboardWhite, BatLogo); + Outputs->SetValue(OutputBillboardLamp, Marquee); + Outputs->SetValue(OutputSpeaker1, SpeakersRed); + Outputs->SetValue(OutputSpeaker2, SpeakersOrange); + Outputs->SetValue(OutputSpeaker3, SpeakersYellow); + Outputs->SetValue(OutputDash, CenterDashPanel); + Outputs->SetValue(OutputSeatRight, RightDashPanel); + Outputs->SetValue(OutputLampRed, KeypadRed); + Outputs->SetValue(OutputLampGreen, KeypadGreen); + Outputs->SetValue(OutputLampBlue, KeypadBlue); + Outputs->SetValue(OutputBase, Kickplates); + + } + return 0; +} + +static DWORD WINAPI OutputsAreGo(LPVOID lpParam) +{ + while (true) + { + WindowsLoop(); + Sleep(SleepA); + } +} + +static DWORD(__fastcall* TurnOnIOORig)(int* param_1); +static DWORD __fastcall TurnOnIO(int* param_1) +{ + + lightsEnabled = true; + return 1; +} + +void Batman::OutputsGameLoop() +{ + if (!init) + { + + MH_Initialize(); + MH_CreateHook((void*)0x12f9440, &TurnOnIO, reinterpret_cast(&TurnOnIOORig)); + MH_EnableHook(MH_ALL_HOOKS); + init = true; + + Outputs = CreateOutputsFromConfig(); + m_game.name = "Batman"; + Outputs->SetGame(m_game); + Outputs->Initialize(); + Outputs->Attached(); + CreateThread(NULL, 0, OutputsAreGo, NULL, 0, NULL); + while (GetMessage(&Msg1, NULL, NULL, 0)) + { + TranslateMessage(&Msg1); + DispatchMessage(&Msg1); + } + init = true; + } +} \ No newline at end of file diff --git a/Game Files/batman.h b/Game Files/batman.h new file mode 100644 index 0000000..57581a6 --- /dev/null +++ b/Game Files/batman.h @@ -0,0 +1,22 @@ +/*This file is part of Output Blaster. + +Output Blaster is free software : you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +Output Blaster is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Output Blaster.If not, see < https://www.gnu.org/licenses/>.*/ + +#pragma once +#include "../Common Files/Game.h" +class Batman : public Game { + +public: + void OutputsGameLoop(); +}; \ No newline at end of file diff --git a/dllmain.cpp b/dllmain.cpp index 889eb8e..3a7607d 100644 --- a/dllmain.cpp +++ b/dllmain.cpp @@ -24,6 +24,7 @@ along with Output Blaster.If not, see < https://www.gnu.org/licenses/>.*/ #include "Game Files/BattleGear4.h" #include "Game Files/BattleGear4Tuned.h" #include "Game Files/BattlePod.h" +#include "Game Files/Batman.h" #include "Game Files/Cars.h" #include "Game Files/ChaseHQ2.h" #include "Game Files/CrazyRide.h" @@ -40,6 +41,8 @@ along with Output Blaster.If not, see < https://www.gnu.org/licenses/>.*/ #include "Game Files/H2Overdrive.h" #include "Game Files/HOTD4VerA.h" #include "Game Files/HOTD4VerC.h" +#include "Game Files/HarleyDavidson.h" +#include "Game Files/Hummer.h" #include "Game Files/HummerExtreme.h" #include "Game Files/ID0V131.h" #include "Game Files/ID0V211.h" @@ -64,6 +67,7 @@ along with Output Blaster.If not, see < https://www.gnu.org/licenses/>.*/ #include "Game Files/SegaRacingClassic.h" #include "Game Files/SegaRally3.h" #include "Game Files/SRG.h" +#include "Game Files/SuperBikes2.h" #include "Game Files/TheWalkingDead.h" #include "Game Files/Transformers.h" #include "Game Files/TransformersShadowsRising.h" @@ -240,10 +244,18 @@ DWORD WINAPI OutputsLoop(LPVOID lpParam) case 0x8505c794: game = new BattlePod; break; + case 0xB818B0BD: + game = new Batman; + break; case 0x55f66578: game = new TransformersShadowsRising; break; - + case 0x84d7854b: + game = new HarleyDavidson; + break; + case 0xFE7AFFF4: + game = new SuperBikes2; + break; default: break; } @@ -319,6 +331,10 @@ DWORD WINAPI OutputsLoop(LPVOID lpParam) { game = new HummerExtreme; } + else if (ReadWithoutCrashing((uint32_t*)0x8320C69) == (0x9AB3BC0)) + { + game = new Hummer; + } if (game != 0) //Load Lindbergh Game