Skip to content

Commit

Permalink
DrawDistance: read exclusions from outrun2006tweaks.lods.ini
Browse files Browse the repository at this point in the history
  • Loading branch information
emoose committed Dec 8, 2024
1 parent 9232871 commit f46d000
Show file tree
Hide file tree
Showing 6 changed files with 158 additions and 3 deletions.
1 change: 1 addition & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ jobs:
shell: pwsh
run: |
cp OutRun2006Tweaks.ini build/bin/OutRun2006Tweaks.ini
cp OutRun2006Tweaks.lods.ini build/bin/OutRun2006Tweaks.lods.ini
- name: Download OR2006C2C
shell: pwsh
Expand Down
10 changes: 10 additions & 0 deletions OutRun2006Tweaks.lods.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# This file contains known-bad object IDs that will be excluded from being drawn by the DrawDistanceIncrease tweak
# Such as LOD models or other bad stage models
#
# OutRun2006Tweaks includes an overlay that can help to find the IDs for bad objects if they appear
# Just make sure [Overlay] Enabled = true is set, then press F11 when you see a bad model while playing a stage

# AMAZON
[Stage 22]
# Jungle -> Skyscrapers bushes during bunki
0x5 = 0xBB
2 changes: 2 additions & 0 deletions src/dllmain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ namespace Module

constexpr std::string_view IniFileName = "OutRun2006Tweaks.ini";
constexpr std::string_view UserIniFileName = "OutRun2006Tweaks.user.ini";
constexpr std::string_view LodIniFileName = "OutRun2006Tweaks.lods.ini";
constexpr std::string_view LogFileName = "OutRun2006Tweaks.log";

void init()
Expand All @@ -34,6 +35,7 @@ namespace Module
LogPath = dllParent / LogFileName;
IniPath = dllParent / IniFileName;
UserIniPath = dllParent / UserIniFileName;
LodIniPath = dllParent / LodIniFileName;

Game::init();
}
Expand Down
2 changes: 2 additions & 0 deletions src/game_addrs.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ namespace Game
inline fn_1arg_int GetNowStageNum = nullptr;
inline fn_1arg_int GetStageUniqueNum = nullptr;
inline fn_1arg_int GetMaxCsLen = nullptr;
inline fn_1arg_char GetStageUniqueName = nullptr;

inline fn_stdcall_1arg_int Sumo_CheckRacerUnlocked = nullptr;

Expand Down Expand Up @@ -192,6 +193,7 @@ namespace Game
GetNowStageNum = Module::fn_ptr<fn_1arg_int>(0x50380);
GetStageUniqueNum = Module::fn_ptr<fn_1arg_int>(0x4DC50);
GetMaxCsLen = Module::fn_ptr<fn_1arg_int>(0x3D470);
GetStageUniqueName = Module::fn_ptr<fn_1arg_char>(0x4BE80);

Sumo_CheckRacerUnlocked = Module::fn_ptr<fn_stdcall_1arg_int>(0xE8410);

Expand Down
145 changes: 142 additions & 3 deletions src/hooks_drawdistance.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include <array>
#include <bitset>
#include <imgui.h>
#include <ini.h>

std::array<std::vector<uint16_t>, 256> ObjectNodes;
std::array<std::array<std::bitset<16384>, 256>, 128> ObjectExclusionsPerStage;
Expand Down Expand Up @@ -49,11 +50,24 @@ void Overlay_DrawDistOverlay()
}

ImGui::SliderInt("Draw Distance", &Settings::DrawDistanceIncrease, 0, 1024);

if (ImGui::Button("<<<"))
Settings::DrawDistanceIncrease--;
Settings::DrawDistanceIncrease -= 10;
ImGui::SameLine();
if (ImGui::Button("<<"))
Settings::DrawDistanceIncrease -= 5;
ImGui::SameLine();
if (ImGui::Button("<"))
Settings::DrawDistanceIncrease -= 1;
ImGui::SameLine();
if (ImGui::Button(">"))
Settings::DrawDistanceIncrease += 1;
ImGui::SameLine();
if (ImGui::Button(">>"))
Settings::DrawDistanceIncrease += 5;
ImGui::SameLine();
if (ImGui::Button(">>>"))
Settings::DrawDistanceIncrease++;
Settings::DrawDistanceIncrease += 10;

if (num_columns > 0)
{
Expand Down Expand Up @@ -133,7 +147,7 @@ void Overlay_DrawDistOverlay()
}
}
if (!clipboard.empty())
clipboard = std::format("[Stage {}]{}", cur_stage_num, clipboard);
clipboard = std::format("# {}\n[Stage {}]{}", Game::GetStageUniqueName(cur_stage_num), cur_stage_num, clipboard);

HGLOBAL hMem = GlobalAlloc(GMEM_MOVEABLE, clipboard.length() + 1);
if (hMem)
Expand Down Expand Up @@ -286,6 +300,129 @@ class DrawDistanceIncrease : public Hook
}
}

static int get_number(std::string_view sectionName)
{
int number = -1;

// Find the position of the numeric part
auto pos = sectionName.find_first_of("0123456789");
if (pos != std::string::npos)
{
auto result = std::from_chars(sectionName.data() + pos, sectionName.data() + sectionName.size(), number);
if (result.ec == std::errc())
return number;
}

return -1;
}

bool read_exclusions()
{
// Try reading exclusions
std::filesystem::path& iniPath = Module::LodIniPath;

if (!std::filesystem::exists(Module::LodIniPath))
{
spdlog::error("DrawDistanceIncrease::read_exclusions - failed to locate exclusion INI from path {}", iniPath.string());
return false;
}

spdlog::info("DrawDistanceIncrease::read_exclusions - reading INI from {}", iniPath.string());

const std::wstring iniPathStr = iniPath.wstring();

// Read INI via FILE* since INIReader doesn't support wstring
FILE* iniFile;
errno_t result = _wfopen_s(&iniFile, iniPathStr.c_str(), L"r");
if (result != 0 || !iniFile)
{
spdlog::error("DrawDistanceIncrease::read_exclusions - INI read failed! Error code {}", result);
return false;
}

inih::INIReader ini;
try
{
ini = inih::INIReader(iniFile);
}
catch (...)
{
spdlog::error("DrawDistanceIncrease::read_exclusions - INI read failed! The file may be invalid or have duplicate settings inside");
fclose(iniFile);
return false;
}
fclose(iniFile);

for (auto& section : ini.Sections())
{
int stageNum = get_number(section);
if (stageNum >= ObjectExclusionsPerStage.size())
{
spdlog::error("DrawDistanceIncrease::read_exclusions - INI contains invalid stage section \"{}\", skipping...", section);
continue;
}

for (auto& key : ini.Keys(section))
{
int objectId = -1;
try
{
objectId = std::stol(key, nullptr, 0);
}
catch (const std::invalid_argument& e)
{
continue;
}
catch (const std::out_of_range& e)
{
continue;
}

if (objectId < 0)
continue;

if (objectId >= ObjectExclusionsPerStage[stageNum].size())
{
spdlog::error("DrawDistanceIncrease::read_exclusions - INI contains invalid object number \"{}\", skipping...", key);
continue;
}

std::vector<int> nodes;

auto value = ini.Get(section, key);
std::istringstream stream(value);
std::string token;

// Tokenize the string using ',' as the delimiter
while (std::getline(stream, token, ','))
{
// Remove leading/trailing whitespace
token.erase(0, token.find_first_not_of(" \t"));
token.erase(token.find_last_not_of(" \t") + 1);

// Convert the token to an integer
try
{
nodes.push_back(std::stol(token, nullptr, 0));
}
catch (const std::invalid_argument& e)
{
}
catch (const std::out_of_range& e)
{
}
}

for (auto& node : nodes)
{
ObjectExclusionsPerStage[stageNum][objectId][node] = true;
}
}
}

return true;
}

public:
std::string_view description() override
{
Expand All @@ -309,6 +446,8 @@ class DrawDistanceIncrease : public Hook

DrawDistanceIncreaseEnabled = true;

read_exclusions();

return true;
}

Expand Down
1 change: 1 addition & 0 deletions src/plugin.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ namespace Module
inline std::filesystem::path LogPath{};
inline std::filesystem::path IniPath{};
inline std::filesystem::path UserIniPath{};
inline std::filesystem::path LodIniPath{};

template <typename T>
inline T* exe_ptr(uintptr_t offset) { if (ExeHandle) return (T*)(((uintptr_t)ExeHandle) + offset); else return nullptr; }
Expand Down

0 comments on commit f46d000

Please sign in to comment.