diff --git a/CMakeLists.txt b/CMakeLists.txt index 84d26fd0..44bfc4a7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -222,6 +222,7 @@ add_library(sead OBJECT include/stream/seadStreamSrc.h modules/src/stream/seadRamStream.cpp modules/src/stream/seadStream.cpp + modules/src/stream/seadStreamFormat.cpp include/thread/seadAtomic.h include/thread/seadCriticalSection.h diff --git a/include/prim/seadEndian.h b/include/prim/seadEndian.h index 5e43d0a9..4dbf320a 100644 --- a/include/prim/seadEndian.h +++ b/include/prim/seadEndian.h @@ -65,6 +65,7 @@ class Endian { return cConvFuncTable.conv32[from ^ to](v); } + static u32 convertU32(s32 endian, u32 v) { return cConvFuncTable.conv32[endian](v); } static u64 convertU64(Types from, Types to, u64 v) { return cConvFuncTable.conv64[from ^ to](v); @@ -74,9 +75,9 @@ class Endian static s16 convertS16(Types from, Types to, s16 v) { return convertU16(from, to, v); } static s32 convertS32(Types from, Types to, s32 v) { return convertU32(from, to, v); } static s64 convertS64(Types from, Types to, s64 v) { return convertU64(from, to, v); } - static u32 convertF32(Types from, Types to, const void* ptr) + static f32 convertF32(s32 endian, const void* ptr) { - return convertU32(from, to, *static_cast(ptr)); + return BitUtil::bitCast(convertU32(endian, *static_cast(ptr))); } static u8 toHostU8(Types from, u8 v) { return convertU8(from, cHostEndian, v); } @@ -95,15 +96,15 @@ class Endian static s64 toHostS64(Types from, s64 v) { return toHostU64(from, v); } static s8 fromHostS8(Types to, s8 v) { return fromHostU8(to, v); } - static s16 fromHostS16(Types to, s16 v) { return fromHostU8(to, v); } - static s32 fromHostS32(Types to, s32 v) { return fromHostU8(to, v); } - static s64 fromHostS64(Types to, s64 v) { return fromHostU8(to, v); } + static s16 fromHostS16(Types to, s16 v) { return fromHostU16(to, v); } + static s32 fromHostS32(Types to, s32 v) { return fromHostU32(to, v); } + static s64 fromHostS64(Types to, s64 v) { return fromHostU64(to, v); } - static f32 toHostF32(Types from, const u32* ptr) + static f32 toHostF32(Types from, const u32* ptr) { return convertF32(from ^ cHostEndian, ptr); } + static u32 fromHostF32(Types to, const f32* ptr) { - return BitUtil::bitCast(convertF32(from, cHostEndian, ptr)); + return convertU32(cHostEndian, to, *reinterpret_cast(ptr)); } - static u32 fromHostF32(Types to, const f32* ptr) { return convertF32(cHostEndian, to, ptr); } private: static const Types cHostEndian; diff --git a/include/stream/seadStreamFormat.h b/include/stream/seadStreamFormat.h index 3a9fbb34..b360cefd 100644 --- a/include/stream/seadStreamFormat.h +++ b/include/stream/seadStreamFormat.h @@ -11,103 +11,103 @@ class StreamSrc; class StreamFormat { public: - virtual u8 readU8(StreamSrc*, Endian::Types) = 0; - virtual u16 readU16(StreamSrc*, Endian::Types) = 0; - virtual u32 readU32(StreamSrc*, Endian::Types) = 0; - virtual u64 readU64(StreamSrc*, Endian::Types) = 0; - virtual s8 readS8(StreamSrc*, Endian::Types) = 0; - virtual s16 readS16(StreamSrc*, Endian::Types) = 0; - virtual s32 readS32(StreamSrc*, Endian::Types) = 0; - virtual s64 readS64(StreamSrc*, Endian::Types) = 0; - virtual f32 readF32(StreamSrc*, Endian::Types) = 0; - virtual void readBit(StreamSrc*, void*, u32) = 0; - virtual void readString(StreamSrc*, BufferedSafeString*, u32) = 0; - virtual u32 readMemBlock(StreamSrc*, void*, u32) = 0; - virtual void writeU8(StreamSrc*, Endian::Types, u8) = 0; - virtual void writeU16(StreamSrc*, Endian::Types, u16) = 0; - virtual void writeU32(StreamSrc*, Endian::Types, u32) = 0; - virtual void writeU64(StreamSrc*, Endian::Types, u64) = 0; - virtual void writeS8(StreamSrc*, Endian::Types, s8) = 0; - virtual void writeS16(StreamSrc*, Endian::Types, s16) = 0; - virtual void writeS32(StreamSrc*, Endian::Types, s32) = 0; - virtual void writeS64(StreamSrc*, Endian::Types, s64) = 0; - virtual void writeF32(StreamSrc*, Endian::Types, f32) = 0; - virtual void writeBit(StreamSrc*, const void*, u32) = 0; - virtual void writeString(StreamSrc*, const SafeString&, u32) = 0; - virtual void writeMemBlock(StreamSrc*, const void*, u32) = 0; - virtual void writeDecorationText(StreamSrc*, const SafeString&) = 0; - virtual void writeNullChar(StreamSrc*) = 0; - virtual void skip(StreamSrc*, u32) = 0; - virtual void flush(StreamSrc*) = 0; - virtual void rewind(StreamSrc*) = 0; + virtual u8 readU8(StreamSrc* src, Endian::Types endian) = 0; + virtual u16 readU16(StreamSrc* src, Endian::Types endian) = 0; + virtual u32 readU32(StreamSrc* src, Endian::Types endian) = 0; + virtual u64 readU64(StreamSrc* src, Endian::Types endian) = 0; + virtual s8 readS8(StreamSrc* src, Endian::Types endian) = 0; + virtual s16 readS16(StreamSrc* src, Endian::Types endian) = 0; + virtual s32 readS32(StreamSrc* src, Endian::Types endian) = 0; + virtual s64 readS64(StreamSrc* src, Endian::Types endian) = 0; + virtual f32 readF32(StreamSrc* src, Endian::Types endian) = 0; + virtual void readBit(StreamSrc* src, void* data, u32 bits) = 0; + virtual void readString(StreamSrc* src, BufferedSafeString* str, u32 size) = 0; + virtual u32 readMemBlock(StreamSrc* src, void* buffer, u32 size) = 0; + virtual void writeU8(StreamSrc* src, Endian::Types endian, u8 value) = 0; + virtual void writeU16(StreamSrc* src, Endian::Types endian, u16 value) = 0; + virtual void writeU32(StreamSrc* src, Endian::Types endian, u32 value) = 0; + virtual void writeU64(StreamSrc* src, Endian::Types endian, u64 value) = 0; + virtual void writeS8(StreamSrc* src, Endian::Types endian, s8 value) = 0; + virtual void writeS16(StreamSrc* src, Endian::Types endian, s16 value) = 0; + virtual void writeS32(StreamSrc* src, Endian::Types endian, s32 value) = 0; + virtual void writeS64(StreamSrc* src, Endian::Types endian, s64 value) = 0; + virtual void writeF32(StreamSrc* src, Endian::Types endian, f32 value) = 0; + virtual void writeBit(StreamSrc* src, const void* data, u32 bits) = 0; + virtual void writeString(StreamSrc* src, const SafeString& str, u32 size) = 0; + virtual void writeMemBlock(StreamSrc* src, const void* buffer, u32 size) = 0; + virtual void writeDecorationText(StreamSrc* src, const SafeString& text) = 0; + virtual void writeNullChar(StreamSrc* src) = 0; + virtual void skip(StreamSrc* src, u32 offset) = 0; + virtual void flush(StreamSrc* src) = 0; + virtual void rewind(StreamSrc* src) = 0; }; class BinaryStreamFormat : public StreamFormat { public: - u8 readU8(StreamSrc*, Endian::Types) override; - u16 readU16(StreamSrc*, Endian::Types) override; - u32 readU32(StreamSrc*, Endian::Types) override; - u64 readU64(StreamSrc*, Endian::Types) override; - s8 readS8(StreamSrc*, Endian::Types) override; - s16 readS16(StreamSrc*, Endian::Types) override; - s32 readS32(StreamSrc*, Endian::Types) override; - s64 readS64(StreamSrc*, Endian::Types) override; - f32 readF32(StreamSrc*, Endian::Types) override; - void readBit(StreamSrc*, void*, u32) override; - void readString(StreamSrc*, BufferedSafeString*, u32) override; - u32 readMemBlock(StreamSrc*, void*, u32) override; - void writeU8(StreamSrc*, Endian::Types, u8) override; - void writeU16(StreamSrc*, Endian::Types, u16) override; - void writeU32(StreamSrc*, Endian::Types, u32) override; - void writeU64(StreamSrc*, Endian::Types, u64) override; - void writeS8(StreamSrc*, Endian::Types, s8) override; - void writeS16(StreamSrc*, Endian::Types, s16) override; - void writeS32(StreamSrc*, Endian::Types, s32) override; - void writeS64(StreamSrc*, Endian::Types, s64) override; - void writeF32(StreamSrc*, Endian::Types, f32) override; - void writeBit(StreamSrc*, const void*, u32) override; - void writeString(StreamSrc*, const SafeString&, u32) override; - void writeMemBlock(StreamSrc*, const void*, u32) override; - void writeDecorationText(StreamSrc*, const SafeString&) override; - void writeNullChar(StreamSrc*) override; - void skip(StreamSrc*, u32) override; - void flush(StreamSrc*) override; - void rewind(StreamSrc*) override; + u8 readU8(StreamSrc* src, Endian::Types endian) override; + u16 readU16(StreamSrc* src, Endian::Types endian) override; + u32 readU32(StreamSrc* src, Endian::Types endian) override; + u64 readU64(StreamSrc* src, Endian::Types endian) override; + s8 readS8(StreamSrc* src, Endian::Types endian) override; + s16 readS16(StreamSrc* src, Endian::Types endian) override; + s32 readS32(StreamSrc* src, Endian::Types endian) override; + s64 readS64(StreamSrc* src, Endian::Types endian) override; + f32 readF32(StreamSrc* src, Endian::Types endian) override; + void readBit(StreamSrc* src, void* data, u32 bits) override; + void readString(StreamSrc* src, BufferedSafeString* str, u32 size) override; + u32 readMemBlock(StreamSrc* src, void* buffer, u32 size) override; + void writeU8(StreamSrc* src, Endian::Types endian, u8 value) override; + void writeU16(StreamSrc* src, Endian::Types endian, u16 value) override; + void writeU32(StreamSrc* src, Endian::Types endian, u32 value) override; + void writeU64(StreamSrc* src, Endian::Types endian, u64 value) override; + void writeS8(StreamSrc* src, Endian::Types endian, s8 value) override; + void writeS16(StreamSrc* src, Endian::Types endian, s16 value) override; + void writeS32(StreamSrc* src, Endian::Types endian, s32 value) override; + void writeS64(StreamSrc* src, Endian::Types endian, s64 value) override; + void writeF32(StreamSrc* src, Endian::Types endian, f32 value) override; + void writeBit(StreamSrc* src, const void* data, u32 bits) override; + void writeString(StreamSrc* src, const SafeString& str, u32 size) override; + void writeMemBlock(StreamSrc* src, const void* buffer, u32 size) override; + void writeDecorationText(StreamSrc* src, const SafeString& text) override; + void writeNullChar(StreamSrc* src) override; + void skip(StreamSrc* src, u32 offset) override; + void flush(StreamSrc* src) override; + void rewind(StreamSrc* src) override; }; class TextStreamFormat : public StreamFormat { public: - u8 readU8(StreamSrc*, Endian::Types) override; - u16 readU16(StreamSrc*, Endian::Types) override; - u32 readU32(StreamSrc*, Endian::Types) override; - u64 readU64(StreamSrc*, Endian::Types) override; - s8 readS8(StreamSrc*, Endian::Types) override; - s16 readS16(StreamSrc*, Endian::Types) override; - s32 readS32(StreamSrc*, Endian::Types) override; - s64 readS64(StreamSrc*, Endian::Types) override; - f32 readF32(StreamSrc*, Endian::Types) override; - void readBit(StreamSrc*, void*, u32) override; - void readString(StreamSrc*, BufferedSafeString*, u32) override; - u32 readMemBlock(StreamSrc*, void*, u32) override; - void writeU8(StreamSrc*, Endian::Types, u8) override; - void writeU16(StreamSrc*, Endian::Types, u16) override; - void writeU32(StreamSrc*, Endian::Types, u32) override; - void writeU64(StreamSrc*, Endian::Types, u64) override; - void writeS8(StreamSrc*, Endian::Types, s8) override; - void writeS16(StreamSrc*, Endian::Types, s16) override; - void writeS32(StreamSrc*, Endian::Types, s32) override; - void writeS64(StreamSrc*, Endian::Types, s64) override; - void writeF32(StreamSrc*, Endian::Types, f32) override; - void writeBit(StreamSrc*, const void*, u32) override; - void writeString(StreamSrc*, const SafeString&, u32) override; - void writeMemBlock(StreamSrc*, const void*, u32) override; - void writeDecorationText(StreamSrc*, const SafeString&) override; - void writeNullChar(StreamSrc*) override; - void skip(StreamSrc*, u32) override; - void flush(StreamSrc*) override; - void rewind(StreamSrc*) override; + u8 readU8(StreamSrc* src, Endian::Types endian) override; + u16 readU16(StreamSrc* src, Endian::Types endian) override; + u32 readU32(StreamSrc* src, Endian::Types endian) override; + u64 readU64(StreamSrc* src, Endian::Types endian) override; + s8 readS8(StreamSrc* src, Endian::Types endian) override; + s16 readS16(StreamSrc* src, Endian::Types endian) override; + s32 readS32(StreamSrc* src, Endian::Types endian) override; + s64 readS64(StreamSrc* src, Endian::Types endian) override; + f32 readF32(StreamSrc* src, Endian::Types endian) override; + void readBit(StreamSrc* src, void* data, u32 bits) override; + void readString(StreamSrc* src, BufferedSafeString* str, u32 size) override; + u32 readMemBlock(StreamSrc* src, void* buffer, u32 size) override; + void writeU8(StreamSrc* src, Endian::Types endian, u8 value) override; + void writeU16(StreamSrc* src, Endian::Types endian, u16 value) override; + void writeU32(StreamSrc* src, Endian::Types endian, u32 value) override; + void writeU64(StreamSrc* src, Endian::Types endian, u64 value) override; + void writeS8(StreamSrc* src, Endian::Types endian, s8 value) override; + void writeS16(StreamSrc* src, Endian::Types endian, s16 value) override; + void writeS32(StreamSrc* src, Endian::Types endian, s32 value) override; + void writeS64(StreamSrc* src, Endian::Types endian, s64 value) override; + void writeF32(StreamSrc* src, Endian::Types endian, f32 value) override; + void writeBit(StreamSrc* src, const void* data, u32 bits) override; + void writeString(StreamSrc* src, const SafeString& str, u32 size) override; + void writeMemBlock(StreamSrc* src, const void* buffer, u32 size) override; + void writeDecorationText(StreamSrc* src, const SafeString& text) override; + void writeNullChar(StreamSrc* src) override; + void skip(StreamSrc* src, u32 offset) override; + void flush(StreamSrc* src) override; + void rewind(StreamSrc* src) override; }; } // namespace sead diff --git a/modules/src/stream/seadStreamFormat.cpp b/modules/src/stream/seadStreamFormat.cpp new file mode 100644 index 00000000..a439ac3d --- /dev/null +++ b/modules/src/stream/seadStreamFormat.cpp @@ -0,0 +1,223 @@ +#include "stream/seadStreamFormat.h" + +#include "math/seadMathCalcCommon.h" +#include "stream/seadStreamSrc.h" + +namespace sead +{ +u8 BinaryStreamFormat::readU8(StreamSrc* src, Endian::Types endian) +{ + u8 rawValue = 0; + src->read(&rawValue, sizeof(u8)); + return Endian::toHostU8(endian, rawValue); +} + +u16 BinaryStreamFormat::readU16(StreamSrc* src, Endian::Types endian) +{ + u16 rawValue = 0; + src->read(&rawValue, sizeof(u16)); + return Endian::toHostU16(endian, rawValue); +} + +u32 BinaryStreamFormat::readU32(StreamSrc* src, Endian::Types endian) +{ + u32 rawValue = 0; + src->read(&rawValue, sizeof(u32)); + return Endian::toHostU32(endian, rawValue); +} + +u64 BinaryStreamFormat::readU64(StreamSrc* src, Endian::Types endian) +{ + u64 rawValue = 0; + src->read(&rawValue, sizeof(u64)); + return Endian::toHostU64(endian, rawValue); +} + +s8 BinaryStreamFormat::readS8(StreamSrc* src, Endian::Types endian) +{ + s8 rawValue = 0; + src->read(&rawValue, sizeof(s8)); + return Endian::toHostU8(endian, rawValue); +} + +s16 BinaryStreamFormat::readS16(StreamSrc* src, Endian::Types endian) +{ + s16 rawValue = 0; + src->read(&rawValue, sizeof(s16)); + return Endian::toHostU16(endian, rawValue); +} + +s32 BinaryStreamFormat::readS32(StreamSrc* src, Endian::Types endian) +{ + s32 rawValue = 0; + src->read(&rawValue, sizeof(s32)); + return Endian::toHostU32(endian, rawValue); +} + +s64 BinaryStreamFormat::readS64(StreamSrc* src, Endian::Types endian) +{ + s64 rawValue = 0; + src->read(&rawValue, sizeof(s64)); + return Endian::toHostU64(endian, rawValue); +} + +f32 BinaryStreamFormat::readF32(StreamSrc* src, Endian::Types endian) +{ + u32 rawValue = 0; + src->read(&rawValue, sizeof(f32)); + return Endian::toHostF32(endian, &rawValue); +} + +void BinaryStreamFormat::readBit(StreamSrc* src, void* data, u32 bits) +{ + u8* dataU8 = static_cast(data); + + u32 size = bits / 8; + src->read(dataU8, size); + bits -= size * 8; + + if (bits <= 0) + return; + + u8 lastByte; + src->read(&lastByte, 1); + + u8 mask = 0xFF << bits; + dataU8[size] &= mask; + dataU8[size] |= lastByte & ~mask; +} + +// NON_MATCHING: Potential wrong imlementation https://decomp.me/scratch/jCek1 +void BinaryStreamFormat::readString(StreamSrc* src, BufferedSafeString* str, u32 size) +{ + u32 remainingSize = 0; + if (size > (u32)str->getBufferSize()) + { + remainingSize = size - str->getBufferSize(); + size = str->getBufferSize(); + } + + src->read(str->getBuffer(), size); + + if (size + 1 < (u32)str->getBufferSize()) + str->trim(size); + else + str->trim(str->getBufferSize() - 1); + + if (remainingSize != 0) + { + // Note: what happens if remaining size is bigger than the buffer? + src->read(str->getBuffer(), remainingSize); + } +} + +u32 BinaryStreamFormat::readMemBlock(StreamSrc* src, void* buffer, u32 size) +{ + return src->read(buffer, size); +} + +void BinaryStreamFormat::writeU8(StreamSrc* src, Endian::Types endian, u8 value) +{ + u8 rawValue = Endian::fromHostU8(endian, value); + src->write(&rawValue, sizeof(u8)); +} + +void BinaryStreamFormat::writeU16(StreamSrc* src, Endian::Types endian, u16 value) +{ + u16 rawValue = Endian::fromHostU16(endian, value); + src->write(&rawValue, sizeof(u16)); +} + +void BinaryStreamFormat::writeU32(StreamSrc* src, Endian::Types endian, u32 value) +{ + u32 rawValue = Endian::fromHostU32(endian, value); + src->write(&rawValue, sizeof(u32)); +} + +void BinaryStreamFormat::writeU64(StreamSrc* src, Endian::Types endian, u64 value) +{ + u64 rawValue = Endian::fromHostU64(endian, value); + src->write(&rawValue, sizeof(u64)); +} + +void BinaryStreamFormat::writeS8(StreamSrc* src, Endian::Types endian, s8 value) +{ + s8 rawValue = Endian::fromHostS8(endian, value); + src->write(&rawValue, sizeof(s8)); +} + +void BinaryStreamFormat::writeS16(StreamSrc* src, Endian::Types endian, s16 value) +{ + s16 rawValue = Endian::fromHostS16(endian, value); + src->write(&rawValue, sizeof(s16)); +} + +void BinaryStreamFormat::writeS32(StreamSrc* src, Endian::Types endian, s32 value) +{ + s32 rawValue = Endian::fromHostS32(endian, value); + src->write(&rawValue, sizeof(s32)); +} + +void BinaryStreamFormat::writeS64(StreamSrc* src, Endian::Types endian, s64 value) +{ + s64 rawValue = Endian::fromHostS64(endian, value); + src->write(&rawValue, sizeof(s64)); +} + +void BinaryStreamFormat::writeF32(StreamSrc* src, Endian::Types endian, f32 value) +{ + u32 rawValue = Endian::fromHostF32(endian, &value); + src->write(&rawValue, sizeof(f32)); +} + +void BinaryStreamFormat::writeBit(StreamSrc* src, const void* data, u32 bits) +{ + const u8* dataU8 = static_cast(data); + + u8 size = bits / 8; + src->write(dataU8, size); + + if (size * 8 == bits) + return; + + const u8& lastByte = dataU8[size]; + src->write(&lastByte, 1); +} + +void BinaryStreamFormat::writeString(StreamSrc* src, const SafeString& str, u32 size) +{ + u32 strSize = str.calcLength(); + if (strSize > size) + strSize = size; + + src->write(str.cstr(), strSize); + + char nullchar = '\0'; + for (; strSize < size; strSize++) + src->write(&nullchar, 1); +} + +void BinaryStreamFormat::writeMemBlock(StreamSrc* src, const void* buffer, u32 size) +{ + src->write(buffer, size); +} + +void BinaryStreamFormat::writeDecorationText([[maybe_unused]] StreamSrc* src, + [[maybe_unused]] const SafeString& text) +{ +} + +void BinaryStreamFormat::writeNullChar([[maybe_unused]] StreamSrc* src) {} + +void BinaryStreamFormat::skip(StreamSrc* src, u32 offset) +{ + src->skip(offset); +} + +void BinaryStreamFormat::flush([[maybe_unused]] StreamSrc* src) {} + +void BinaryStreamFormat::rewind(StreamSrc* src) +{ + src->rewind(); +} +} // namespace sead