diff --git a/source/egg/util/Stream.cc b/source/egg/util/Stream.cc index 6a946ccb..d72ba2af 100644 --- a/source/egg/util/Stream.cc +++ b/source/egg/util/Stream.cc @@ -8,12 +8,12 @@ Stream::~Stream() = default; void Stream::skip(u32 count) { m_index += count; - ASSERT(!eof()); + ASSERT(!bad()); } void Stream::jump(u32 index) { m_index = index; - ASSERT(!eof()); + ASSERT(!bad()); } void Stream::setEndian(std::endian endian) { @@ -66,8 +66,8 @@ f64 Stream::read_f64() { RamStream::RamStream() : m_buffer(nullptr), m_size(0) {} -RamStream::RamStream(u8 *buffer, u32 size) { - setBufferAndSize(buffer, size); +RamStream::RamStream(const void *buffer, u32 size) { + setBufferAndSize(const_cast(buffer), size); } RamStream::~RamStream() = default; @@ -86,7 +86,15 @@ void RamStream::write(void *input, u32 size) { } } -bool RamStream::eof() { +bool RamStream::eof() const { + return m_index == m_size; +} + +bool RamStream::safe(u32 size) const { + return m_index + size <= m_size; +} + +bool RamStream::bad() const { return m_index > m_size; } @@ -94,7 +102,7 @@ bool RamStream::eof() { std::string RamStream::read_string() { std::string ret(reinterpret_cast(m_buffer + m_index)); m_index += ret.size() + 1; - ASSERT(!eof()); + ASSERT(!bad()); return ret; } @@ -118,7 +126,7 @@ u8 *RamStream::dataAtIndex() { RamStream RamStream::split(u32 size) { RamStream stream = RamStream(m_buffer + m_index, size); m_index += size; - ASSERT(!eof()); + ASSERT(!bad()); return stream; } diff --git a/source/egg/util/Stream.hh b/source/egg/util/Stream.hh index baa1799e..5a5183d2 100644 --- a/source/egg/util/Stream.hh +++ b/source/egg/util/Stream.hh @@ -14,7 +14,9 @@ public: virtual void read(void *output, u32 size) = 0; virtual void write(void *input, u32 size) = 0; - virtual bool eof() = 0; + virtual bool eof() const = 0; + virtual bool safe(u32 size) const = 0; + virtual bool bad() const = 0; void skip(u32 count); void jump(u32 index); @@ -41,10 +43,10 @@ protected: private: template [[nodiscard]] T read() { + ASSERT(safe(sizeof(T))); T val; read(&val, sizeof(val)); m_index += sizeof(val); - ASSERT(!eof()); return parse(val, m_endian); } @@ -58,12 +60,14 @@ private: class RamStream : public Stream { public: RamStream(); - RamStream(u8 *buffer, u32 size); + RamStream(const void *buffer, u32 size); ~RamStream() override; void read(void *output, u32 size) override; void write(void *input, u32 size) override; - [[nodiscard]] bool eof() override; + [[nodiscard]] bool eof() const override; + [[nodiscard]] bool safe(u32 size) const override; + [[nodiscard]] bool bad() const override; [[nodiscard]] std::string read_string(); [[nodiscard]] RamStream split(u32 size); diff --git a/source/game/field/KColData.cc b/source/game/field/KColData.cc index ae73962b..eae54ee2 100644 --- a/source/game/field/KColData.cc +++ b/source/game/field/KColData.cc @@ -15,8 +15,7 @@ KColData::KColData(const void *file) { auto addOffset = [](const void *file, u32 offset) -> const void * { return reinterpret_cast(reinterpret_cast(file) + offset); }; - u8 *unsafeData = reinterpret_cast(const_cast(file)); - EGG::RamStream stream = EGG::RamStream(unsafeData, sizeof(KColHeader)); + EGG::RamStream stream = EGG::RamStream(file, sizeof(KColHeader)); u32 posOffset = stream.read_u32(); u32 nrmOffset = stream.read_u32(); @@ -288,8 +287,7 @@ void KColData::preloadPrisms() { (reinterpret_cast(m_blockData) - reinterpret_cast(m_prismData)) / sizeof(KCollisionPrism); - u8 *unsafeData = reinterpret_cast(const_cast(m_prismData)); - EGG::RamStream stream = EGG::RamStream(unsafeData, sizeof(KCollisionPrism) * prismCount); + EGG::RamStream stream = EGG::RamStream(m_prismData, sizeof(KCollisionPrism) * prismCount); m_prisms = std::span(new KCollisionPrism[prismCount], prismCount); @@ -317,9 +315,7 @@ void KColData::preloadNormals() { sizeof(EGG::Vector3f); m_nrms = std::span(new EGG::Vector3f[normalCount], normalCount); - - u8 *unsafeData = reinterpret_cast(const_cast(m_nrmData)); - EGG::RamStream stream = EGG::RamStream(unsafeData, sizeof(EGG::Vector3f) * normalCount); + EGG::RamStream stream = EGG::RamStream(m_nrmData, sizeof(EGG::Vector3f) * normalCount); for (auto &nrm : m_nrms) { nrm.read(stream); @@ -335,9 +331,7 @@ void KColData::preloadVertices() { sizeof(EGG::Vector3f); m_vertices = std::span(new EGG::Vector3f[vertexCount], vertexCount); - - u8 *unsafeData = reinterpret_cast(const_cast(m_posData)); - EGG::RamStream stream = EGG::RamStream(unsafeData, sizeof(EGG::Vector3f) * vertexCount); + EGG::RamStream stream = EGG::RamStream(m_posData, sizeof(EGG::Vector3f) * vertexCount); for (auto &vert : m_vertices) { vert.read(stream); diff --git a/source/game/field/ObjectHitTable.cc b/source/game/field/ObjectHitTable.cc index fbe141e2..30c4d8b7 100644 --- a/source/game/field/ObjectHitTable.cc +++ b/source/game/field/ObjectHitTable.cc @@ -12,7 +12,7 @@ ObjectHitTable::ObjectHitTable(const char *filename) { void *file = System::ResourceManager::Instance()->getFile(filename, &size, System::ArchiveId::Core); - EGG::RamStream stream = EGG::RamStream(reinterpret_cast(file), size); + EGG::RamStream stream = EGG::RamStream(file, size); m_count = stream.read_s16(); m_fieldCount = stream.read_s16(); diff --git a/source/game/kart/KartParamFileManager.cc b/source/game/kart/KartParamFileManager.cc index 6ffe8271..aeda0b00 100644 --- a/source/game/kart/KartParamFileManager.cc +++ b/source/game/kart/KartParamFileManager.cc @@ -64,8 +64,7 @@ EGG::RamStream KartParamFileManager::getDriverStream(Character character) const auto *file = reinterpret_cast *>(m_driverParam.file); ASSERT(file); void *offset = &file->params[idx]; - u32 size = sizeof(KartParam::Stats); - return EGG::RamStream(reinterpret_cast(offset), size); + return EGG::RamStream(offset, sizeof(KartParam::Stats)); } EGG::RamStream KartParamFileManager::getVehicleStream(Vehicle vehicle) const { @@ -77,8 +76,7 @@ EGG::RamStream KartParamFileManager::getVehicleStream(Vehicle vehicle) const { auto *file = reinterpret_cast *>(m_kartParam.file); ASSERT(file); void *offset = &file->params[idx]; - u32 size = sizeof(KartParam::Stats); - return EGG::RamStream(reinterpret_cast(offset), size); + return EGG::RamStream(offset, sizeof(KartParam::Stats)); } EGG::RamStream KartParamFileManager::getHitboxStream(Vehicle vehicle) const { @@ -92,7 +90,7 @@ EGG::RamStream KartParamFileManager::getHitboxStream(Vehicle vehicle) const { auto *file = resourceManager->getBsp(vehicle, &size); ASSERT(file); ASSERT(size == sizeof(BSP)); - return EGG::RamStream(reinterpret_cast(file), size); + return EGG::RamStream(file, size); } EGG::RamStream KartParamFileManager::getBikeDispParamsStream(Vehicle vehicle) const { @@ -107,8 +105,7 @@ EGG::RamStream KartParamFileManager::getBikeDispParamsStream(Vehicle vehicle) co auto *file = reinterpret_cast *>(m_bikeDispParam.file); ASSERT(file); void *offset = &file->params[idx]; - u32 size = sizeof(KartParam::BikeDisp); - return EGG::RamStream(reinterpret_cast(offset), size); + return EGG::RamStream(offset, sizeof(KartParam::BikeDisp)); } KartParamFileManager *KartParamFileManager::CreateInstance() { diff --git a/source/game/system/KPadController.cc b/source/game/system/KPadController.cc index 0c337205..e77724b6 100644 --- a/source/game/system/KPadController.cc +++ b/source/game/system/KPadController.cc @@ -87,8 +87,7 @@ void KPadGhostController::readGhostBuffer(const u8 *buffer, bool driftIsAuto) { m_ghostBuffer = buffer; m_driftIsAuto = driftIsAuto; - EGG::RamStream stream = - EGG::RamStream(const_cast(buffer), RKG_UNCOMPRESSED_INPUT_DATA_SECTION_SIZE); + EGG::RamStream stream = EGG::RamStream(buffer, RKG_UNCOMPRESSED_INPUT_DATA_SECTION_SIZE); u16 faceCount = stream.read_u16(); u16 directionCount = stream.read_u16(); @@ -270,11 +269,15 @@ u8 KPadGhostButtonsStream::readFrame() { } else { if (readIsNewSequence()) { readSequenceFrames = 0; + currentSequence = buffer.read_u16(); + + // In the base game, this check normally occurs before the read. As a result, the base + // game does not know that it has run out of inputs until the frame that it tries to + // access past the last valid input. We stray from this behavior so that we can know + // when we are on the last frame of input. if (buffer.eof()) { state = 2; - return 0; } - currentSequence = buffer.read_u16(); } } diff --git a/source/game/system/map/MapdataCannonPoint.cc b/source/game/system/map/MapdataCannonPoint.cc index 305c9f3c..b716f729 100644 --- a/source/game/system/map/MapdataCannonPoint.cc +++ b/source/game/system/map/MapdataCannonPoint.cc @@ -5,8 +5,7 @@ namespace System { MapdataCannonPoint::MapdataCannonPoint(const SData *data) : m_rawData(data) { - u8 *unsafeData = reinterpret_cast(const_cast(data)); - EGG::RamStream stream = EGG::RamStream(unsafeData, sizeof(SData)); + EGG::RamStream stream = EGG::RamStream(data, sizeof(SData)); read(stream); } diff --git a/source/game/system/map/MapdataCheckPath.cc b/source/game/system/map/MapdataCheckPath.cc index 70c958ef..9a5cbdf4 100644 --- a/source/game/system/map/MapdataCheckPath.cc +++ b/source/game/system/map/MapdataCheckPath.cc @@ -4,8 +4,7 @@ namespace System { /// @addr{0x80515098} MapdataCheckPath::MapdataCheckPath(const SData *data) : m_rawData(data), m_depth(-1) { - u8 *unsafeData = reinterpret_cast(const_cast(data)); - EGG::RamStream stream = EGG::RamStream(unsafeData, sizeof(SData)); + EGG::RamStream stream = EGG::RamStream(data, sizeof(SData)); read(stream); m_oneOverCount = 1.0f / m_size; } diff --git a/source/game/system/map/MapdataCheckPoint.cc b/source/game/system/map/MapdataCheckPoint.cc index 9643293f..d1c0a95d 100644 --- a/source/game/system/map/MapdataCheckPoint.cc +++ b/source/game/system/map/MapdataCheckPoint.cc @@ -10,8 +10,7 @@ namespace System { /// @addr{0x805154E4} MapdataCheckPoint::MapdataCheckPoint(const SData *data) : m_rawData(data), m_nextCount(0), m_prevCount(0) { - u8 *unsafeData = reinterpret_cast(const_cast(data)); - EGG::RamStream stream = EGG::RamStream(unsafeData, sizeof(SData)); + EGG::RamStream stream = EGG::RamStream(data, sizeof(SData)); read(stream); m_midpoint = 0.5f * (m_left + m_right); m_dir = EGG::Vector2f(m_right.y - m_left.y, m_left.x - m_right.x); diff --git a/source/game/system/map/MapdataGeoObj.cc b/source/game/system/map/MapdataGeoObj.cc index 63813f95..967d67d7 100644 --- a/source/game/system/map/MapdataGeoObj.cc +++ b/source/game/system/map/MapdataGeoObj.cc @@ -3,8 +3,7 @@ namespace System { MapdataGeoObj::MapdataGeoObj(const SData *data) : m_rawData(data) { - u8 *unsafeData = reinterpret_cast(const_cast(data)); - EGG::RamStream stream = EGG::RamStream(unsafeData, sizeof(SData)); + EGG::RamStream stream = EGG::RamStream(data, sizeof(SData)); read(stream); } diff --git a/source/game/system/map/MapdataJugemPoint.cc b/source/game/system/map/MapdataJugemPoint.cc index 9b2a25d6..4a5442ca 100644 --- a/source/game/system/map/MapdataJugemPoint.cc +++ b/source/game/system/map/MapdataJugemPoint.cc @@ -6,8 +6,7 @@ namespace System { /// @addr{0x805183A8} MapdataJugemPoint::MapdataJugemPoint(const SData *data) : m_rawData(data) { - u8 *unsafeData = reinterpret_cast(const_cast(data)); - EGG::RamStream stream = EGG::RamStream(unsafeData, sizeof(SData)); + EGG::RamStream stream = EGG::RamStream(data, sizeof(SData)); read(stream); } diff --git a/source/game/system/map/MapdataStageInfo.cc b/source/game/system/map/MapdataStageInfo.cc index 4cd14afd..d3125ff7 100644 --- a/source/game/system/map/MapdataStageInfo.cc +++ b/source/game/system/map/MapdataStageInfo.cc @@ -5,8 +5,7 @@ namespace System { MapdataStageInfo::MapdataStageInfo(const SData *data) : m_rawData(data) { - u8 *unsafeData = reinterpret_cast(const_cast(data)); - EGG::RamStream stream = EGG::RamStream(unsafeData, sizeof(SData)); + EGG::RamStream stream = EGG::RamStream(data, sizeof(SData)); read(stream); } diff --git a/source/game/system/map/MapdataStartPoint.cc b/source/game/system/map/MapdataStartPoint.cc index b91166dd..701eb37d 100644 --- a/source/game/system/map/MapdataStartPoint.cc +++ b/source/game/system/map/MapdataStartPoint.cc @@ -40,8 +40,7 @@ static constexpr s8 Z_TRANSLATION_TABLE[12][12] = { }; MapdataStartPoint::MapdataStartPoint(const SData *data) : m_rawData(data) { - u8 *unsafeData = reinterpret_cast(const_cast(data)); - EGG::RamStream stream = EGG::RamStream(unsafeData, sizeof(SData)); + EGG::RamStream stream = EGG::RamStream(data, sizeof(SData)); read(stream); }