Skip to content

Commit

Permalink
FixPegasusClopping: fixes looping clop sound effect remaining active …
Browse files Browse the repository at this point in the history
…through the session

Moves lens flare fix to bugfixes.cpp, and added INI settings for toggling all fixes
  • Loading branch information
emoose committed Jun 10, 2024
1 parent 8c9d32d commit 4576640
Show file tree
Hide file tree
Showing 6 changed files with 112 additions and 42 deletions.
18 changes: 18 additions & 0 deletions Outrun2006Tweaks.ini
Original file line number Diff line number Diff line change
Expand Up @@ -80,3 +80,21 @@ SkipIntroLogos = false
# DisableCountdownTimer: disables the countdown timer, may be useful for modders, or those who just want to take a leisurely drive.
# Can also be enabled via -OuttaTime launch parameter.
DisableCountdownTimer = false

[Bugfixes]
# FixPegasusClopping: fixes looping clop sound effect remaining active through the session.
FixPegasusClopping = true

# FixC2CRankings: fixes C2C scoreboard rankings not updating due to incomplete anti-piracy checks.
# (game still contained "SecuROM_Tripwire" checks inside it, despite Steam release not using SecuROM...)
FixC2CRankings = true

# PreventDESTSaveCorruption: prevents the save corruption caused by trying to remap controls with many devices connected.
# This usually resulted in player name replaced with "DEST" and some garbage text, along with player character model disappearing along with all unlocks/miles.
# (if you got hit by this bug, you can restore name/model by replacing first 0xB0 bytes in your corrupted License.dat file with the contents of a different one)
PreventDESTSaveCorruption = true

# FixLensFlarePath: game tries to load in lens flare data from common/, but the game files have it inside media/, causing lens flare not to be drawn.
# If lens flare is still present inside media/ then this will just patch game to load it from there instead.
# (if you already moved the lens flare file yourself then no change will be applied)
FixLensFlarePath = true
10 changes: 10 additions & 0 deletions src/dllmain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,11 @@ namespace Settings

spdlog::info(" - SkipIntroLogos: {}", SkipIntroLogos);
spdlog::info(" - CountdownTimerDisable: {}", CountdownTimerDisable);

spdlog::info(" - FixPegasusClopping: {}", FixPegasusClopping);
spdlog::info(" - FixC2CRankings: {}", FixC2CRankings);
spdlog::info(" - PreventDESTSaveCorruption: {}", PreventDESTSaveCorruption);
spdlog::info(" - FixLensFlarePath: {}", FixLensFlarePath);
}

bool read(std::filesystem::path& iniPath)
Expand Down Expand Up @@ -114,6 +119,11 @@ namespace Settings
SkipIntroLogos = ini.Get("Misc", "SkipIntroLogos", std::move(SkipIntroLogos));
CountdownTimerDisable = ini.Get("Misc", "CountdownTimerDisable", std::move(CountdownTimerDisable));

FixPegasusClopping = ini.Get("Bugfixes", "FixPegasusClopping", std::move(FixPegasusClopping));
FixC2CRankings = ini.Get("Bugfixes", "FixC2CRankings", std::move(FixC2CRankings));
PreventDESTSaveCorruption = ini.Get("Bugfixes", "PreventDESTSaveCorruption", std::move(PreventDESTSaveCorruption));
FixLensFlarePath = ini.Get("Bugfixes", "FixLensFlarePath", std::move(FixLensFlarePath));

return true;
}
};
Expand Down
4 changes: 4 additions & 0 deletions src/game_addrs.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ namespace Game
inline fn_0args GhostCarExecServer = nullptr;
inline fn_0args fn4666A0 = nullptr;

inline fn_1arg PrjSndRequest = nullptr;

inline void init()
{
current_mode = Module::exe_ptr<GameState>(0x38026C);
Expand Down Expand Up @@ -82,5 +84,7 @@ namespace Game
EventControl = Module::fn_ptr<fn_0args>(0x3FAB0); // EventControl
GhostCarExecServer = Module::fn_ptr<fn_0args>(0x80F80); // GhostCarExecServer
fn4666A0 = Module::fn_ptr<fn_0args>(0x666A0);

PrjSndRequest = Module::fn_ptr<fn_1arg>(0x249F0);
}
};
77 changes: 75 additions & 2 deletions src/hooks_bugfixes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,40 @@
#include "plugin.hpp"
#include "game_addrs.hpp"

class FixPegasusClopping : public Hook
{
const static int SndOff_PEGA_Addr = 0x4BCC0;

inline static SafetyHookInline SndOff_PEGA = {};
static void destination()
{
SndOff_PEGA.call();

const int SND_STOP = 0x8000;
Game::PrjSndRequest(SND_STOP | 0x8D); // 0x8D = clop
}

public:
std::string_view description() override
{
return "FixPegasusClopping";
}

bool validate() override
{
return Settings::FixPegasusClopping;
}

bool apply() override
{
SndOff_PEGA = safetyhook::create_inline(Module::exe_ptr(SndOff_PEGA_Addr), destination);
return !!SndOff_PEGA;
}

static FixPegasusClopping instance;
};
FixPegasusClopping FixPegasusClopping::instance;

class FixC2CRankings : public Hook
{
// A lot of the C2C ranking code has a strange check that tries to OpenEventA an existing named event based on current process ID
Expand All @@ -23,7 +57,7 @@ class FixC2CRankings : public Hook

bool validate() override
{
return true;
return Settings::FixC2CRankings;
}

bool apply() override
Expand Down Expand Up @@ -67,7 +101,7 @@ class PreventDESTSaveCorruption : public Hook

bool validate() override
{
return true;
return Settings::PreventDESTSaveCorruption;
}

bool apply() override
Expand All @@ -79,3 +113,42 @@ class PreventDESTSaveCorruption : public Hook
static PreventDESTSaveCorruption instance;
};
PreventDESTSaveCorruption PreventDESTSaveCorruption::instance;

class FixLensFlarePath : public Hook
{
// Game tries to load in lens flare data from common/, but the game files have it inside media/, causing lens flare not to be drawn.
// We'll just patch code to load from media/ instead
// (only patch it if file actually exists inside media/ though, some may have already moved it to common/)

const static int LoadLensFlareOffset_StringAddr = 0x1A29F8;

public:
std::string_view description() override
{
return "FixLensFlarePath";
}

bool validate() override
{
return Settings::FixLensFlarePath;
}

bool apply() override
{
std::string NewPath = "\\media\\lens_flare_offset.bin";
if (std::filesystem::exists("." + NewPath))
{
auto* patch_addr = Module::exe_ptr<char>(LoadLensFlareOffset_StringAddr);

DWORD dwProtect;
VirtualProtect((void*)patch_addr, NewPath.length(), PAGE_EXECUTE_READWRITE, &dwProtect);
strcpy(patch_addr, NewPath.c_str());
VirtualProtect((void*)patch_addr, NewPath.length(), dwProtect, &dwProtect);
}

return true;
}

static FixLensFlarePath instance;
};
FixLensFlarePath FixLensFlarePath::instance;
40 changes: 0 additions & 40 deletions src/hooks_graphics.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,46 +27,6 @@ class DisableDPIScaling : public Hook
};
DisableDPIScaling DisableDPIScaling::instance;

class LensFlarePathFix : public Hook
{
const static int LoadLensFlareOffset_StringAddr = 0x1A29F8;

public:
std::string_view description() override
{
return "LensFlarePathFix";
}

bool validate() override
{
return true;
}

bool apply() override
{
// Game code tries to load lens_flare_offset.bin from the wrong path
// Code tries loading from common/, but game files have it inside media/
// We'll just patch code to load from media/ instead
// (only patch it if file actually exists inside media/ though, some fix guides already told people to move it to common/)

std::string NewPath = "\\media\\lens_flare_offset.bin";
if (std::filesystem::exists("." + NewPath))
{
auto* patch_addr = Module::exe_ptr<char>(LoadLensFlareOffset_StringAddr);

DWORD dwProtect;
VirtualProtect((void*)patch_addr, NewPath.length(), PAGE_EXECUTE_READWRITE, &dwProtect);
strcpy(patch_addr, NewPath.c_str());
VirtualProtect((void*)patch_addr, NewPath.length(), dwProtect, &dwProtect);
}

return true;
}

static LensFlarePathFix instance;
};
LensFlarePathFix LensFlarePathFix::instance;

class ScreenEdgeCullFix : public Hook
{
const static int CalcBall3D2D_Addr = 0x49E70;
Expand Down
5 changes: 5 additions & 0 deletions src/plugin.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,11 @@ namespace Settings

inline bool SkipIntroLogos = false;
inline bool CountdownTimerDisable = false;

inline bool FixPegasusClopping = true;
inline bool FixC2CRankings = true;
inline bool PreventDESTSaveCorruption = true;
inline bool FixLensFlarePath = true;
}

namespace Util
Expand Down

0 comments on commit 4576640

Please sign in to comment.