From 92a213af50fe4f6b6cf1d20eb828507c5467ff39 Mon Sep 17 00:00:00 2001 From: FallBackITA27 Date: Sun, 16 Feb 2025 12:58:58 +0100 Subject: [PATCH 1/7] set up gitignore for zed so vabold doesn't yell at me --- .gitignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitignore b/.gitignore index fbffad63..87691ac0 100644 --- a/.gitignore +++ b/.gitignore @@ -1,9 +1,12 @@ build build.ninja +compile_commands.json +.cache/** __pycache__ out .vs .vscode +.zed *.szs statusTestCases.json .env From 0f766f5019316ff8c64ae1f289a6e977de045208 Mon Sep 17 00:00:00 2001 From: FallBackITA27 Date: Sun, 16 Feb 2025 14:35:52 +0100 Subject: [PATCH 2/7] i have a feeling this doesn't work --- source/game/system/GhostFile.cc | 18 +++++++++++++++++- source/game/system/GhostFile.hh | 1 + 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/source/game/system/GhostFile.cc b/source/game/system/GhostFile.cc index b2d38a02..df28fdca 100644 --- a/source/game/system/GhostFile.cc +++ b/source/game/system/GhostFile.cc @@ -142,13 +142,22 @@ bool RawGhostFile::decompress(const u8 *rkg) { /// @addr{0x8051C120} /// @todo Check for valid controller type? -/// @todo Check lap times sum to race time? bool RawGhostFile::isValid(const u8 *rkg) const { if (strncmp(reinterpret_cast(rkg), "RKGD", 4) != 0) { PANIC("RKG header malformed"); return false; } + + u32 finalTime = RawGhostFile::readRKGTime(reinterpret_cast(rkg + 0x4)); + u32 lapSum = 0; + for (u8 i = 0; i < 8; i++) { + lapSum += RawGhostFile::readRKGTime(reinterpret_cast(rkg + 0x11 + (i*3))); + } + if (finalTime != lapSum) { + return false; + } + u32 ids = parse(*reinterpret_cast(rkg + 0x8)); Vehicle vehicle = static_cast(ids >> 0x1a); Character character = static_cast((ids >> 0x14) & 0x3f); @@ -181,6 +190,13 @@ bool RawGhostFile::isValid(const u8 *rkg) const { return true; } +u32 RawGhostFile::readRKGTime(const u8 *timeBytes) const { + u32 minutes = *timeBytes; // The minutes are doubled here + u32 seconds = (*reinterpret_cast(timeBytes + 1)) >> 2; + u32 milliseconds = *reinterpret_cast(timeBytes + 1) & 0b0000001111111111; + return (minutes * 30000) + (seconds * 1000) + milliseconds; +} + const u8 *RawGhostFile::buffer() const { return m_buffer; } diff --git a/source/game/system/GhostFile.hh b/source/game/system/GhostFile.hh index e82e70b3..8b746595 100644 --- a/source/game/system/GhostFile.hh +++ b/source/game/system/GhostFile.hh @@ -70,6 +70,7 @@ public: private: [[nodiscard]] bool compressed(const u8 *rkg) const; + [[nodiscard]] u32 readRKGTime(const u8 *rkg) const; u8 m_buffer[RKG_UNCOMPRESSED_FILE_SIZE]; }; From 3377658298f71b0b2c107f741865072e99aceda2 Mon Sep 17 00:00:00 2001 From: FallBackITA27 Date: Sun, 16 Feb 2025 15:26:32 +0100 Subject: [PATCH 3/7] bugfix --- source/game/system/GhostFile.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/game/system/GhostFile.cc b/source/game/system/GhostFile.cc index df28fdca..f9e2ac14 100644 --- a/source/game/system/GhostFile.cc +++ b/source/game/system/GhostFile.cc @@ -193,7 +193,7 @@ bool RawGhostFile::isValid(const u8 *rkg) const { u32 RawGhostFile::readRKGTime(const u8 *timeBytes) const { u32 minutes = *timeBytes; // The minutes are doubled here u32 seconds = (*reinterpret_cast(timeBytes + 1)) >> 2; - u32 milliseconds = *reinterpret_cast(timeBytes + 1) & 0b0000001111111111; + u32 milliseconds = parse(*reinterpret_cast(timeBytes + 1)) & 0b1111111111; return (minutes * 30000) + (seconds * 1000) + milliseconds; } From 0309482875ca44528fbd9a9ba85fc69ae7529e9b Mon Sep 17 00:00:00 2001 From: FallBackITA27 Date: Sun, 16 Feb 2025 15:42:36 +0100 Subject: [PATCH 4/7] check controller validity --- source/game/system/GhostFile.cc | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/source/game/system/GhostFile.cc b/source/game/system/GhostFile.cc index f9e2ac14..01e906f2 100644 --- a/source/game/system/GhostFile.cc +++ b/source/game/system/GhostFile.cc @@ -162,8 +162,9 @@ bool RawGhostFile::isValid(const u8 *rkg) const { Vehicle vehicle = static_cast(ids >> 0x1a); Character character = static_cast((ids >> 0x14) & 0x3f); u8 year = (ids >> 0xd) & 0x7f; - u8 day = (ids >> 0x4) & 0x1f; u8 month = (ids >> 0x9) & 0xf; + u8 day = (ids >> 0x4) & 0x1f; + u8 controllerType = ids & 0b1111; if (vehicle >= Vehicle::Max || character >= Character::Max) { return false; @@ -172,6 +173,10 @@ bool RawGhostFile::isValid(const u8 *rkg) const { if (year >= 100 || day >= 32 || month > 12) { return false; } + + if (controllerType > 3) { + return false; + } // Validate weight class match WeightClass charWeight = CharacterToWeight(character); From 4d85ff2ae97ec2f4f724383ec15b3c8637bf08b0 Mon Sep 17 00:00:00 2001 From: FallBackITA27 Date: Sun, 16 Feb 2025 19:42:17 +0100 Subject: [PATCH 5/7] suggested changes and Timer::operator+= --- source/game/system/GhostFile.cc | 25 ++++++++++++------------- source/game/system/GhostFile.hh | 1 - source/game/system/TimerManager.hh | 26 ++++++++++++++++++++++++++ 3 files changed, 38 insertions(+), 14 deletions(-) diff --git a/source/game/system/GhostFile.cc b/source/game/system/GhostFile.cc index 01e906f2..c80f12d5 100644 --- a/source/game/system/GhostFile.cc +++ b/source/game/system/GhostFile.cc @@ -141,17 +141,23 @@ bool RawGhostFile::decompress(const u8 *rkg) { } /// @addr{0x8051C120} -/// @todo Check for valid controller type? bool RawGhostFile::isValid(const u8 *rkg) const { if (strncmp(reinterpret_cast(rkg), "RKGD", 4) != 0) { PANIC("RKG header malformed"); return false; } - u32 finalTime = RawGhostFile::readRKGTime(reinterpret_cast(rkg + 0x4)); - u32 lapSum = 0; - for (u8 i = 0; i < 8; i++) { - lapSum += RawGhostFile::readRKGTime(reinterpret_cast(rkg + 0x11 + (i*3))); + u8 laps = *(rkg+0x10); + + if (laps > 5) { + return false; + } + + Timer finalTime = Timer(parse(*reinterpret_cast(rkg+0x4))); + Timer lapSum = Timer(0); + for (u8 i = 0; i < laps; i++) { + Timer lapTime = Timer(parse(*reinterpret_cast(rkg + 0x11 + (i*3)))); + lapSum += lapTime; } if (finalTime != lapSum) { @@ -164,7 +170,7 @@ bool RawGhostFile::isValid(const u8 *rkg) const { u8 year = (ids >> 0xd) & 0x7f; u8 month = (ids >> 0x9) & 0xf; u8 day = (ids >> 0x4) & 0x1f; - u8 controllerType = ids & 0b1111; + u8 controllerType = ids & 0xf; if (vehicle >= Vehicle::Max || character >= Character::Max) { return false; @@ -195,13 +201,6 @@ bool RawGhostFile::isValid(const u8 *rkg) const { return true; } -u32 RawGhostFile::readRKGTime(const u8 *timeBytes) const { - u32 minutes = *timeBytes; // The minutes are doubled here - u32 seconds = (*reinterpret_cast(timeBytes + 1)) >> 2; - u32 milliseconds = parse(*reinterpret_cast(timeBytes + 1)) & 0b1111111111; - return (minutes * 30000) + (seconds * 1000) + milliseconds; -} - const u8 *RawGhostFile::buffer() const { return m_buffer; } diff --git a/source/game/system/GhostFile.hh b/source/game/system/GhostFile.hh index 8b746595..e82e70b3 100644 --- a/source/game/system/GhostFile.hh +++ b/source/game/system/GhostFile.hh @@ -70,7 +70,6 @@ public: private: [[nodiscard]] bool compressed(const u8 *rkg) const; - [[nodiscard]] u32 readRKGTime(const u8 *rkg) const; u8 m_buffer[RKG_UNCOMPRESSED_FILE_SIZE]; }; diff --git a/source/game/system/TimerManager.hh b/source/game/system/TimerManager.hh index 154351b3..757fdf94 100644 --- a/source/game/system/TimerManager.hh +++ b/source/game/system/TimerManager.hh @@ -82,6 +82,32 @@ struct Timer { return Timer(newMin, newSec, newMs); } + + Timer operator+=(Timer &rhs) const { + s16 addMin = 0; + s16 addSec = 0; + + s16 newMs = rhs.mil + mil; + if (newMs > 999) { + addSec = 1; + newMs -= 1000; + } + + s16 newSec = rhs.sec + sec + addSec; + if (newSec > 59) { + addMin = 1; + newSec -= 60; + } + + s16 newMin = rhs.min + min + addMin; + if (newMin > 999) { + newMin = 999; + newSec = 59; + newMs = 999; + } + + return Timer(newMin, newSec, newMs); + } u16 min; u8 sec; From f0011138be7755247475fb12a142a397636a048e Mon Sep 17 00:00:00 2001 From: FallBackITA27 Date: Sun, 16 Feb 2025 19:45:17 +0100 Subject: [PATCH 6/7] use `Timer()` instead of `Timer(0)` --- source/game/system/GhostFile.cc | 2 +- source/game/system/TimerManager.hh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/source/game/system/GhostFile.cc b/source/game/system/GhostFile.cc index c80f12d5..4d579c19 100644 --- a/source/game/system/GhostFile.cc +++ b/source/game/system/GhostFile.cc @@ -154,7 +154,7 @@ bool RawGhostFile::isValid(const u8 *rkg) const { } Timer finalTime = Timer(parse(*reinterpret_cast(rkg+0x4))); - Timer lapSum = Timer(0); + Timer lapSum = Timer(); for (u8 i = 0; i < laps; i++) { Timer lapTime = Timer(parse(*reinterpret_cast(rkg + 0x11 + (i*3)))); lapSum += lapTime; diff --git a/source/game/system/TimerManager.hh b/source/game/system/TimerManager.hh index 757fdf94..fb1c64bb 100644 --- a/source/game/system/TimerManager.hh +++ b/source/game/system/TimerManager.hh @@ -6,7 +6,7 @@ namespace System { /// @brief A simple struct to represent a lap or race finish time. struct Timer { - Timer(); ///< @unused Creates a zero'd timer. + Timer(); /// Creates a zero'd timer. Timer(u16 min_, u8 sec_, u16 mil_); Timer(u32 data); ~Timer(); From b53840aa5e81f8892c52ebfd4552001d7ac06c0d Mon Sep 17 00:00:00 2001 From: FallBackITA27 Date: Sun, 16 Feb 2025 20:02:15 +0100 Subject: [PATCH 7/7] better implementation --- source/game/system/TimerManager.hh | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/source/game/system/TimerManager.hh b/source/game/system/TimerManager.hh index fb1c64bb..f2b9fc84 100644 --- a/source/game/system/TimerManager.hh +++ b/source/game/system/TimerManager.hh @@ -83,7 +83,7 @@ struct Timer { return Timer(newMin, newSec, newMs); } - Timer operator+=(Timer &rhs) const { + Timer operator+(const Timer &rhs) const { s16 addMin = 0; s16 addSec = 0; @@ -108,7 +108,11 @@ struct Timer { return Timer(newMin, newSec, newMs); } - + + Timer &operator+=(const Timer &rhs) { + return *this = *this + rhs; + } + u16 min; u8 sec; u16 mil; ///< @todo We will likely want to expand this to a float for more precise finish times.