Big-endian support (#909)

This commit is contained in:
GaryOderNichts 2022-07-27 23:50:56 +02:00 committed by GitHub
parent 477cf7f6ec
commit 6818247317
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
22 changed files with 762 additions and 62 deletions

View File

@ -3,7 +3,7 @@
void OTRExporter::WriteHeader(ZResource* res, const fs::path& outPath, BinaryWriter* writer, Ship::ResourceType resType, Ship::Version resVersion) void OTRExporter::WriteHeader(ZResource* res, const fs::path& outPath, BinaryWriter* writer, Ship::ResourceType resType, Ship::Version resVersion)
{ {
writer->Write((uint8_t)Endianess::Little); // 0x00 writer->Write((uint8_t)Endianness::Little); // 0x00
writer->Write((uint8_t)0); // 0x01 writer->Write((uint8_t)0); // 0x01
writer->Write((uint8_t)0); // 0x02 writer->Write((uint8_t)0); // 0x02
writer->Write((uint8_t)0); // 0x03 writer->Write((uint8_t)0); // 0x03

View File

@ -18,6 +18,16 @@ void BinaryReader::Close()
stream->Close(); stream->Close();
} }
void BinaryReader::SetEndianness(Endianness endianness)
{
this->endianness = endianness;
}
Endianness BinaryReader::GetEndianness() const
{
return endianness;
}
void BinaryReader::Seek(uint32_t offset, SeekOffsetType seekType) void BinaryReader::Seek(uint32_t offset, SeekOffsetType seekType)
{ {
stream->Seek(offset, seekType); stream->Seek(offset, seekType);
@ -28,11 +38,16 @@ uint32_t BinaryReader::GetBaseAddress()
return stream->GetBaseAddress(); return stream->GetBaseAddress();
} }
void BinaryReader::Read([[maybe_unused]] char* buffer, int32_t length) void BinaryReader::Read(int32_t length)
{ {
stream->Read(length); stream->Read(length);
} }
void BinaryReader::Read(char* buffer, int32_t length)
{
stream->Read(buffer, length);
}
char BinaryReader::ReadChar() char BinaryReader::ReadChar()
{ {
return (char)stream->ReadByte(); return (char)stream->ReadByte();
@ -53,6 +68,10 @@ int16_t BinaryReader::ReadInt16()
int16_t result = 0; int16_t result = 0;
stream->Read((char*)&result, sizeof(int16_t)); stream->Read((char*)&result, sizeof(int16_t));
if (endianness != Endianness::Native)
result = BSWAP16(result);
return result; return result;
} }
@ -61,6 +80,10 @@ int32_t BinaryReader::ReadInt32()
int32_t result = 0; int32_t result = 0;
stream->Read((char*)&result, sizeof(int32_t)); stream->Read((char*)&result, sizeof(int32_t));
if (endianness != Endianness::Native)
result = BSWAP32(result);
return result; return result;
} }
@ -69,6 +92,10 @@ uint16_t BinaryReader::ReadUInt16()
uint16_t result = 0; uint16_t result = 0;
stream->Read((char*)&result, sizeof(uint16_t)); stream->Read((char*)&result, sizeof(uint16_t));
if (endianness != Endianness::Native)
result = BSWAP16(result);
return result; return result;
} }
@ -77,6 +104,10 @@ uint32_t BinaryReader::ReadUInt32()
uint32_t result = 0; uint32_t result = 0;
stream->Read((char*)&result, sizeof(uint32_t)); stream->Read((char*)&result, sizeof(uint32_t));
if (endianness != Endianness::Native)
result = BSWAP32(result);
return result; return result;
} }
@ -85,6 +116,10 @@ uint64_t BinaryReader::ReadUInt64()
uint64_t result = 0; uint64_t result = 0;
stream->Read((char*)&result, sizeof(uint64_t)); stream->Read((char*)&result, sizeof(uint64_t));
if (endianness != Endianness::Native)
result = BSWAP64(result);
return result; return result;
} }
@ -94,6 +129,9 @@ float BinaryReader::ReadSingle()
stream->Read((char*)&result, sizeof(float)); stream->Read((char*)&result, sizeof(float));
if (endianness != Endianness::Native)
result = BitConverter::ToFloatBE((uint8_t*)&result, 0);
if (std::isnan(result)) if (std::isnan(result))
throw std::runtime_error("BinaryReader::ReadSingle(): Error reading stream"); throw std::runtime_error("BinaryReader::ReadSingle(): Error reading stream");
@ -105,6 +143,10 @@ double BinaryReader::ReadDouble()
double result = NAN; double result = NAN;
stream->Read((char*)&result, sizeof(double)); stream->Read((char*)&result, sizeof(double));
if (endianness != Endianness::Native)
result = BitConverter::ToDoubleBE((uint8_t*)&result, 0);
if (std::isnan(result)) if (std::isnan(result))
throw std::runtime_error("BinaryReader::ReadDouble(): Error reading stream"); throw std::runtime_error("BinaryReader::ReadDouble(): Error reading stream");

View File

@ -8,6 +8,7 @@
#include "../Vec2f.h" #include "../Vec2f.h"
#include "../Vec3f.h" #include "../Vec3f.h"
#include "../Vec3s.h" #include "../Vec3s.h"
#include "BitConverter.h"
#include "Stream.h" #include "Stream.h"
class BinaryReader class BinaryReader
@ -18,9 +19,13 @@ public:
void Close(); void Close();
void SetEndianness(Endianness endianness);
Endianness GetEndianness() const;
void Seek(uint32_t offset, SeekOffsetType seekType); void Seek(uint32_t offset, SeekOffsetType seekType);
uint32_t GetBaseAddress(); uint32_t GetBaseAddress();
void Read(int32_t length);
void Read(char* buffer, int32_t length); void Read(char* buffer, int32_t length);
char ReadChar(); char ReadChar();
int8_t ReadByte(); int8_t ReadByte();
@ -41,4 +46,5 @@ public:
protected: protected:
std::shared_ptr<Stream> stream; std::shared_ptr<Stream> stream;
Endianness endianness = Endianness::Native;
}; };

View File

@ -10,6 +10,11 @@ BinaryWriter::BinaryWriter(std::shared_ptr<Stream> nStream)
stream = nStream; stream = nStream;
} }
void BinaryWriter::SetEndianness(Endianness endianness)
{
this->endianness = endianness;
}
void BinaryWriter::Close() void BinaryWriter::Close()
{ {
stream->Close(); stream->Close();
@ -47,16 +52,25 @@ void BinaryWriter::Write(uint8_t value)
void BinaryWriter::Write(int16_t value) void BinaryWriter::Write(int16_t value)
{ {
if (endianness != Endianness::Native)
value = BSWAP16(value);
stream->Write((char*)&value, sizeof(int16_t)); stream->Write((char*)&value, sizeof(int16_t));
} }
void BinaryWriter::Write(uint16_t value) void BinaryWriter::Write(uint16_t value)
{ {
if (endianness != Endianness::Native)
value = BSWAP16(value);
stream->Write((char*)&value, sizeof(uint16_t)); stream->Write((char*)&value, sizeof(uint16_t));
} }
void BinaryWriter::Write(int32_t value) void BinaryWriter::Write(int32_t value)
{ {
if (endianness != Endianness::Native)
value = BSWAP32(value);
stream->Write((char*)&value, sizeof(int32_t)); stream->Write((char*)&value, sizeof(int32_t));
} }
@ -68,33 +82,48 @@ void BinaryWriter::Write(int32_t valueA, int32_t valueB)
void BinaryWriter::Write(uint32_t value) void BinaryWriter::Write(uint32_t value)
{ {
if (endianness != Endianness::Native)
value = BSWAP32(value);
stream->Write((char*)&value, sizeof(uint32_t)); stream->Write((char*)&value, sizeof(uint32_t));
} }
void BinaryWriter::Write(int64_t value) void BinaryWriter::Write(int64_t value)
{ {
if (endianness != Endianness::Native)
value = BSWAP64(value);
stream->Write((char*)&value, sizeof(int64_t)); stream->Write((char*)&value, sizeof(int64_t));
} }
void BinaryWriter::Write(uint64_t value) void BinaryWriter::Write(uint64_t value)
{ {
if (endianness != Endianness::Native)
value = BSWAP64(value);
stream->Write((char*)&value, sizeof(uint64_t)); stream->Write((char*)&value, sizeof(uint64_t));
} }
void BinaryWriter::Write(float value) void BinaryWriter::Write(float value)
{ {
if (endianness != Endianness::Native)
value = BitConverter::ToFloatBE((uint8_t*)&value, 0);
stream->Write((char*)&value, sizeof(float)); stream->Write((char*)&value, sizeof(float));
} }
void BinaryWriter::Write(double value) void BinaryWriter::Write(double value)
{ {
if (endianness != Endianness::Native)
value = BitConverter::ToDoubleBE((uint8_t*)&value, 0);
stream->Write((char*)&value, sizeof(double)); stream->Write((char*)&value, sizeof(double));
} }
void BinaryWriter::Write(const std::string& str) void BinaryWriter::Write(const std::string& str)
{ {
int strLen = str.size(); int strLen = str.size();
stream->Write((char*)&strLen, sizeof(int)); Write(strLen);
for (char c : str) for (char c : str)
stream->WriteByte(c); stream->WriteByte(c);

View File

@ -4,6 +4,7 @@
#include <memory> #include <memory>
#include <string> #include <string>
#include <vector> #include <vector>
#include "BitConverter.h"
#include "Stream.h" #include "Stream.h"
class BinaryWriter class BinaryWriter
@ -12,6 +13,8 @@ public:
BinaryWriter(Stream* nStream); BinaryWriter(Stream* nStream);
BinaryWriter(std::shared_ptr<Stream> nStream); BinaryWriter(std::shared_ptr<Stream> nStream);
void SetEndianness(Endianness endianness);
std::shared_ptr<Stream> GetStream(); std::shared_ptr<Stream> GetStream();
uint64_t GetBaseAddress(); uint64_t GetBaseAddress();
uint64_t GetLength(); uint64_t GetLength();
@ -34,4 +37,5 @@ public:
protected: protected:
std::shared_ptr<Stream> stream; std::shared_ptr<Stream> stream;
Endianness endianness = Endianness::Native;
}; };

View File

@ -5,6 +5,28 @@
#include <vector> #include <vector>
#include <cstring> #include <cstring>
#ifdef _MSC_VER
#define BSWAP16 _byteswap_ushort
#define BSWAP32 _byteswap_ulong
#define BSWAP64 _byteswap_uint64
#else
#define BSWAP16 __builtin_bswap16
#define BSWAP32 __builtin_bswap32
#define BSWAP64 __builtin_bswap64
#endif
enum class Endianness
{
Little = 0,
Big = 1,
#if (defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)) || defined(__BIG_ENDIAN__)
Native = Big,
#else
Native = Little,
#endif
};
class BitConverter class BitConverter
{ {
public: public:

View File

@ -10,13 +10,6 @@ enum class SeekOffsetType
End End
}; };
// TODO: Eventually account for endianess in binaryreader and binarywriter
enum class Endianess
{
Little = 0,
Big = 1,
};
class Stream class Stream
{ {
public: public:

View File

@ -1,5 +1,103 @@
#include "Cutscene.h" #include "Cutscene.h"
enum class CutsceneCommands
{
Cmd00 = 0x0000,
SetCameraPos = 0x0001,
SetCameraFocus = 0x0002,
SpecialAction = 0x0003,
SetLighting = 0x0004,
SetCameraPosLink = 0x0005,
SetCameraFocusLink = 0x0006,
Cmd07 = 0x0007,
Cmd08 = 0x0008,
Cmd09 = 0x0009,
Unknown = 0x001A,
Textbox = 0x0013,
SetActorAction0 = 0x000A,
SetActorAction1 = 0x000F,
SetActorAction2 = 0x000E,
SetActorAction3 = 0x0019,
SetActorAction4 = 0x001D,
SetActorAction5 = 0x001E,
SetActorAction6 = 0x002C,
SetActorAction7 = 0x001F,
SetActorAction8 = 0x0031,
SetActorAction9 = 0x003E,
SetActorAction10 = 0x008F,
SetSceneTransFX = 0x002D,
Nop = 0x000B,
PlayBGM = 0x0056,
StopBGM = 0x0057,
FadeBGM = 0x007C,
SetTime = 0x008C,
Terminator = 0x03E8,
End = 0xFFFF,
Error = 0xFEAF,
};
static inline uint32_t read_CMD_BBBB(BinaryReader* reader)
{
uint32_t v;
reader->Read((char*)&v, sizeof(uint32_t));
return v;
}
static inline uint32_t read_CMD_BBH(BinaryReader* reader)
{
uint32_t v;
reader->Read((char*)&v, sizeof(uint32_t));
// swap the half word to match endianness
if (reader->GetEndianness() != Endianness::Native)
{
uint8_t* b = (uint8_t*)&v;
uint8_t tmp = b[2];
b[2] = b[3];
b[3] = tmp;
}
return v;
}
static inline uint32_t read_CMD_HBB(BinaryReader* reader)
{
uint32_t v;
reader->Read((char*)&v, sizeof(uint32_t));
// swap the half word to match endianness
if (reader->GetEndianness() != Endianness::Native)
{
uint8_t* b = (uint8_t*)&v;
uint8_t tmp = b[0];
b[0] = b[1];
b[1] = tmp;
}
return v;
}
static inline uint32_t read_CMD_HH(BinaryReader* reader)
{
uint32_t v;
reader->Read((char*)&v, sizeof(uint32_t));
// swap the half words to match endianness
if (reader->GetEndianness() != Endianness::Native)
{
uint8_t* b = (uint8_t*)&v;
uint8_t tmp = b[0];
b[0] = b[1];
b[1] = tmp;
tmp = b[2];
b[2] = b[3];
b[3] = tmp;
}
return v;
}
void Ship::CutsceneV0::ParseFileBinary(BinaryReader* reader, Resource* res) void Ship::CutsceneV0::ParseFileBinary(BinaryReader* reader, Resource* res)
{ {
Cutscene* cs = (Cutscene*)res; Cutscene* cs = (Cutscene*)res;
@ -9,11 +107,415 @@ void Ship::CutsceneV0::ParseFileBinary(BinaryReader* reader, Resource* res)
uint32_t numEntries = reader->ReadUInt32(); uint32_t numEntries = reader->ReadUInt32();
cs->commands.reserve(numEntries); cs->commands.reserve(numEntries);
for (uint32_t i = 0; i < numEntries; i++) uint32_t numCommands = reader->ReadUInt32();
{ cs->commands.push_back(numCommands);
uint32_t data = reader->ReadUInt32();
uint16_t opcode = data >> 16;
cs->commands.push_back(data); // endFrame
cs->commands.push_back(reader->ReadUInt32());
while (true)
{
uint32_t commandId = reader->ReadUInt32();
cs->commands.push_back(commandId);
switch (commandId)
{
case (uint32_t)CutsceneCommands::SetCameraPos:
{
cs->commands.push_back(read_CMD_HH(reader));
cs->commands.push_back(read_CMD_HH(reader));
while (true)
{
uint32_t val = read_CMD_BBH(reader);
int8_t continueFlag = ((int8_t*)&val)[0];
cs->commands.push_back(val);
cs->commands.push_back(reader->ReadUInt32());
cs->commands.push_back(read_CMD_HH(reader));
cs->commands.push_back(read_CMD_HH(reader));
if (continueFlag == -1)
break;
}
}
break;
case (uint32_t)CutsceneCommands::SetCameraFocus:
{
cs->commands.push_back(read_CMD_HH(reader));
cs->commands.push_back(read_CMD_HH(reader));
while (true)
{
uint32_t val = read_CMD_BBH(reader);
int8_t continueFlag = ((int8_t*)&val)[0];
cs->commands.push_back(val);
cs->commands.push_back(reader->ReadUInt32());
cs->commands.push_back(read_CMD_HH(reader));
cs->commands.push_back(read_CMD_HH(reader));
if (continueFlag == -1)
break;
}
break;
}
case (uint32_t)CutsceneCommands::SpecialAction:
{
uint32_t size = reader->ReadUInt32();
cs->commands.push_back(size);
for (uint32_t i = 0; i < size; i++)
{
cs->commands.push_back(read_CMD_HH(reader));
cs->commands.push_back(read_CMD_HH(reader));
cs->commands.push_back(reader->ReadUInt32());
cs->commands.push_back(reader->ReadUInt32());
cs->commands.push_back(reader->ReadUInt32());
cs->commands.push_back(reader->ReadUInt32());
cs->commands.push_back(reader->ReadUInt32());
cs->commands.push_back(reader->ReadUInt32());
cs->commands.push_back(reader->ReadUInt32());
cs->commands.push_back(reader->ReadUInt32());
cs->commands.push_back(reader->ReadUInt32());
cs->commands.push_back(reader->ReadUInt32());
}
break;
}
case (uint32_t)CutsceneCommands::SetLighting:
{
uint32_t size = reader->ReadUInt32();
cs->commands.push_back(size);
for (uint32_t i = 0; i < size; i++)
{
cs->commands.push_back(read_CMD_HH(reader));
cs->commands.push_back(read_CMD_HH(reader));
cs->commands.push_back(reader->ReadUInt32());
cs->commands.push_back(reader->ReadUInt32());
cs->commands.push_back(reader->ReadUInt32());
cs->commands.push_back(reader->ReadUInt32());
cs->commands.push_back(reader->ReadUInt32());
cs->commands.push_back(reader->ReadUInt32());
cs->commands.push_back(reader->ReadUInt32());
cs->commands.push_back(reader->ReadUInt32());
cs->commands.push_back(reader->ReadUInt32());
cs->commands.push_back(reader->ReadUInt32());
}
break;
}
case (uint32_t)CutsceneCommands::SetCameraPosLink:
{
cs->commands.push_back(read_CMD_HH(reader));
cs->commands.push_back(read_CMD_HH(reader));
while (true)
{
uint32_t val = read_CMD_BBH(reader);
int8_t continueFlag = ((int8_t*)&val)[0];
cs->commands.push_back(val);
cs->commands.push_back(reader->ReadUInt32());
cs->commands.push_back(read_CMD_HH(reader));
cs->commands.push_back(read_CMD_HH(reader));
if (continueFlag == -1)
break;
}
break;
}
case (uint32_t)CutsceneCommands::SetCameraFocusLink:
{
cs->commands.push_back(read_CMD_HH(reader));
cs->commands.push_back(read_CMD_HH(reader));
while (true)
{
uint32_t val = read_CMD_BBH(reader);
int8_t continueFlag = ((int8_t*)&val)[0];
cs->commands.push_back(val);
cs->commands.push_back(reader->ReadUInt32());
cs->commands.push_back(read_CMD_HH(reader));
cs->commands.push_back(read_CMD_HH(reader));
if (continueFlag == -1)
break;
}
break;
}
case (uint32_t)CutsceneCommands::Cmd09:
{
uint32_t size = reader->ReadUInt32();
cs->commands.push_back(size);
for (uint32_t i = 0; i < size; i++)
{
cs->commands.push_back(read_CMD_HH(reader));
cs->commands.push_back(read_CMD_HBB(reader));
cs->commands.push_back(read_CMD_BBH(reader));
}
break;
}
case 0x15:
case (uint32_t)CutsceneCommands::Unknown:
{
uint32_t size = reader->ReadUInt32();
cs->commands.push_back(size);
for (uint32_t i = 0; i < size; i++)
{
cs->commands.push_back(reader->ReadUInt32());
cs->commands.push_back(reader->ReadUInt32());
cs->commands.push_back(reader->ReadUInt32());
cs->commands.push_back(reader->ReadUInt32());
cs->commands.push_back(reader->ReadUInt32());
cs->commands.push_back(reader->ReadUInt32());
cs->commands.push_back(reader->ReadUInt32());
cs->commands.push_back(reader->ReadUInt32());
cs->commands.push_back(reader->ReadUInt32());
cs->commands.push_back(reader->ReadUInt32());
cs->commands.push_back(reader->ReadUInt32());
cs->commands.push_back(reader->ReadUInt32());
}
}
break;
case (uint32_t)CutsceneCommands::Textbox:
{
uint32_t size = reader->ReadUInt32();
cs->commands.push_back(size);
for (uint32_t i = 0; i < size; i++)
{
cs->commands.push_back(read_CMD_HH(reader));
cs->commands.push_back(read_CMD_HH(reader));
cs->commands.push_back(read_CMD_HH(reader));
}
break;
}
case (uint32_t)CutsceneCommands::SetActorAction0:
case (uint32_t)CutsceneCommands::SetActorAction1:
case 17:
case 18:
case 23:
case 34:
case 39:
case 46:
case 76:
case 85:
case 93:
case 105:
case 107:
case 110:
case 119:
case 123:
case 138:
case 139:
case 144:
case (uint32_t)CutsceneCommands::SetActorAction2:
case 16:
case 24:
case 35:
case 40:
case 48:
case 64:
case 68:
case 70:
case 78:
case 80:
case 94:
case 116:
case 118:
case 120:
case 125:
case 131:
case 141:
case (uint32_t)CutsceneCommands::SetActorAction3:
case 36:
case 41:
case 50:
case 67:
case 69:
case 72:
case 74:
case 81:
case 106:
case 117:
case 121:
case 126:
case 132:
case (uint32_t)CutsceneCommands::SetActorAction4:
case 37:
case 42:
case 51:
case 53:
case 63:
case 65:
case 66:
case 75:
case 82:
case 108:
case 127:
case 133:
case (uint32_t)CutsceneCommands::SetActorAction5:
case 38:
case 43:
case 47:
case 54:
case 79:
case 83:
case 128:
case 135:
case (uint32_t)CutsceneCommands::SetActorAction6:
case 55:
case 77:
case 84:
case 90:
case 129:
case 136:
case (uint32_t)CutsceneCommands::SetActorAction7:
case 52:
case 57:
case 58:
case 88:
case 115:
case 130:
case 137:
case (uint32_t)CutsceneCommands::SetActorAction8:
case 60:
case 89:
case 111:
case 114:
case 134:
case 142:
case (uint32_t)CutsceneCommands::SetActorAction9:
case (uint32_t)CutsceneCommands::SetActorAction10:
{
uint32_t size = reader->ReadUInt32();
cs->commands.push_back(size);
for (uint32_t i = 0; i < size; i++)
{
cs->commands.push_back(read_CMD_HH(reader));
cs->commands.push_back(read_CMD_HH(reader));
cs->commands.push_back(read_CMD_HH(reader));
cs->commands.push_back(reader->ReadUInt32());
cs->commands.push_back(reader->ReadUInt32());
cs->commands.push_back(reader->ReadUInt32());
cs->commands.push_back(reader->ReadUInt32());
cs->commands.push_back(reader->ReadUInt32());
cs->commands.push_back(reader->ReadUInt32());
cs->commands.push_back(reader->ReadUInt32());
cs->commands.push_back(reader->ReadUInt32());
cs->commands.push_back(reader->ReadUInt32());
}
break;
}
case (uint32_t)CutsceneCommands::SetSceneTransFX:
{
cs->commands.push_back(reader->ReadUInt32());
cs->commands.push_back(read_CMD_HH(reader));
cs->commands.push_back(read_CMD_HH(reader));
break;
}
case (uint32_t)CutsceneCommands::PlayBGM:
{
uint32_t size = reader->ReadUInt32();
cs->commands.push_back(size);
for (uint32_t i = 0; i < size; i++)
{
cs->commands.push_back(read_CMD_HH(reader));
cs->commands.push_back(read_CMD_HH(reader));
cs->commands.push_back(reader->ReadUInt32());
cs->commands.push_back(reader->ReadUInt32());
cs->commands.push_back(reader->ReadUInt32());
cs->commands.push_back(reader->ReadUInt32());
cs->commands.push_back(reader->ReadUInt32());
cs->commands.push_back(reader->ReadUInt32());
cs->commands.push_back(reader->ReadUInt32());
cs->commands.push_back(reader->ReadUInt32());
cs->commands.push_back(reader->ReadUInt32());
cs->commands.push_back(reader->ReadUInt32());
}
break;
}
case (uint32_t)CutsceneCommands::StopBGM:
{
uint32_t size = reader->ReadUInt32();
cs->commands.push_back(size);
for (uint32_t i = 0; i < size; i++)
{
cs->commands.push_back(read_CMD_HH(reader));
cs->commands.push_back(read_CMD_HH(reader));
cs->commands.push_back(reader->ReadUInt32());
cs->commands.push_back(reader->ReadUInt32());
cs->commands.push_back(reader->ReadUInt32());
cs->commands.push_back(reader->ReadUInt32());
cs->commands.push_back(reader->ReadUInt32());
cs->commands.push_back(reader->ReadUInt32());
cs->commands.push_back(reader->ReadUInt32());
cs->commands.push_back(reader->ReadUInt32());
cs->commands.push_back(reader->ReadUInt32());
cs->commands.push_back(reader->ReadUInt32());
}
break;
}
case (uint32_t)CutsceneCommands::FadeBGM:
{
uint32_t size = reader->ReadUInt32();
cs->commands.push_back(size);
for (uint32_t i = 0; i < size; i++)
{
cs->commands.push_back(read_CMD_HH(reader));
cs->commands.push_back(read_CMD_HH(reader));
cs->commands.push_back(reader->ReadUInt32());
cs->commands.push_back(reader->ReadUInt32());
cs->commands.push_back(reader->ReadUInt32());
cs->commands.push_back(reader->ReadUInt32());
cs->commands.push_back(reader->ReadUInt32());
cs->commands.push_back(reader->ReadUInt32());
cs->commands.push_back(reader->ReadUInt32());
cs->commands.push_back(reader->ReadUInt32());
cs->commands.push_back(reader->ReadUInt32());
cs->commands.push_back(reader->ReadUInt32());
}
break;
}
case (uint32_t)CutsceneCommands::SetTime:
{
uint32_t size = reader->ReadUInt32();
cs->commands.push_back(size);
for (uint32_t i = 0; i < size; i++)
{
cs->commands.push_back(read_CMD_HH(reader));
cs->commands.push_back(read_CMD_HBB(reader));
cs->commands.push_back(reader->ReadUInt32());
}
break;
}
case (uint32_t)CutsceneCommands::Terminator:
{
cs->commands.push_back(reader->ReadUInt32());
cs->commands.push_back(read_CMD_HH(reader));
cs->commands.push_back(read_CMD_HH(reader));
break;
}
case 0xFFFFFFFF: // CS_END
{
cs->commands.push_back(reader->ReadUInt32());
return;
}
default:
#ifdef _DEBUG
printf("CutsceneV0: Unknown command %x\n", commandId);
#endif
// error?
break;
}
} }
} }

View File

@ -14,23 +14,25 @@ namespace Ship
while (true) while (true)
{ {
uint64_t data = reader->ReadUInt64(); uint32_t w0 = reader->ReadUInt32();
uint32_t w1 = reader->ReadUInt32();
if (sizeof(uintptr_t) < 8){ if (sizeof(uintptr_t) < 8){
dl->instructions.push_back(data); dl->instructions.push_back(((uint64_t) w0 << 32) | w1);
uint8_t opcode = data >> 24; uint8_t opcode = w0 >> 24;
// These are 128-bit commands, so read an extra 64 bits... // These are 128-bit commands, so read an extra 64 bits...
if (opcode == G_SETTIMG_OTR || opcode == G_DL_OTR || opcode == G_VTX_OTR || opcode == G_BRANCH_Z_OTR || opcode == G_MARKER || opcode == G_MTX_OTR) if (opcode == G_SETTIMG_OTR || opcode == G_DL_OTR || opcode == G_VTX_OTR || opcode == G_BRANCH_Z_OTR || opcode == G_MARKER || opcode == G_MTX_OTR) {
dl->instructions.push_back(reader->ReadUInt64()); w0 = reader->ReadUInt32();
w1 = reader->ReadUInt32();
dl->instructions.push_back(((uint64_t) w0 << 32) | w1);
}
if (opcode == G_ENDDL) if (opcode == G_ENDDL)
break; break;
} else { } else {
uint32_t w0 = (uint32_t)data;
uint32_t w1 = (uint32_t)(data >> 32);
dl->instructions.push_back(w0); dl->instructions.push_back(w0);
dl->instructions.push_back(w1); dl->instructions.push_back(w1);
@ -38,10 +40,8 @@ namespace Ship
if (opcode == G_SETTIMG_OTR || opcode == G_DL_OTR || opcode == G_VTX_OTR || opcode == G_BRANCH_Z_OTR || opcode == G_MARKER || opcode == G_MTX_OTR) if (opcode == G_SETTIMG_OTR || opcode == G_DL_OTR || opcode == G_VTX_OTR || opcode == G_BRANCH_Z_OTR || opcode == G_MARKER || opcode == G_MTX_OTR)
{ {
data = reader->ReadUInt64(); w0 = reader->ReadUInt32();
w1 = reader->ReadUInt32();
w0 = (uint32_t)data;
w1 = (uint32_t)(data >> 32);
dl->instructions.push_back(w0); dl->instructions.push_back(w0);
dl->instructions.push_back(w1); dl->instructions.push_back(w1);

View File

@ -25,12 +25,12 @@ namespace Ship
auto memStream = std::make_shared<MemoryStream>(FileToLoad->buffer.get(), FileToLoad->dwBufferSize); auto memStream = std::make_shared<MemoryStream>(FileToLoad->buffer.get(), FileToLoad->dwBufferSize);
auto reader = std::make_shared<BinaryReader>(memStream); auto reader = std::make_shared<BinaryReader>(memStream);
Endianess endianess = (Endianess)reader->ReadByte(); Endianness endianness = (Endianness)reader->ReadByte();
for (int i = 0; i < 3; i++) for (int i = 0; i < 3; i++)
reader->ReadByte(); reader->ReadByte();
// OTRTODO: Setup the binaryreader to use the resource's endianess reader->SetEndianness(endianness);
ResourceType resourceType = (ResourceType)reader->ReadUInt32(); ResourceType resourceType = (ResourceType)reader->ReadUInt32();
Resource* result = nullptr; Resource* result = nullptr;

View File

@ -51,12 +51,6 @@ namespace Ship
F64 = 10 F64 = 10
}; };
enum class Endianess
{
Little = 0,
Big = 1,
};
enum class Version enum class Version
{ {
// BR // BR
@ -90,7 +84,7 @@ namespace Ship
class ResourceFile class ResourceFile
{ {
public: public:
Endianess endianess; // 0x00 - Endianess of the file Endianness endianness; // 0x00 - Endianness of the file
uint32_t resourceType; // 0x01 - 4 byte MAGIC uint32_t resourceType; // 0x01 - 4 byte MAGIC
Version version; // 0x05 - Based on Ship release numbers Version version; // 0x05 - Based on Ship release numbers
uint64_t id; // 0x09 - Unique Resource ID uint64_t id; // 0x09 - Unique Resource ID

View File

@ -10,7 +10,7 @@ namespace Ship {
SDL_AudioSpec want, have; SDL_AudioSpec want, have;
SDL_zero(want); SDL_zero(want);
want.freq = this->GetSampleRate(); want.freq = this->GetSampleRate();
want.format = AUDIO_S16; want.format = AUDIO_S16SYS;
want.channels = 2; want.channels = 2;
want.samples = 1024; want.samples = 1024;
want.callback = NULL; want.callback = NULL;

View File

@ -0,0 +1,67 @@
#ifndef ENDIANESS_H
#define ENDIANESS_H
#ifdef _MSC_VER
#include <stdlib.h>
#define BOMSWAP16 _byteswap_ushort
#define BOMSWAP32 _byteswap_ulong
#define BOMSWAP64 _byteswap_uint64
#define BOMSWAP16_CONST(x) \
((((x) >> 8) & 0x00FF) | (((x) << 8) & 0xFF00))
#define BOMSWAP32_CONST(x) \
((((x) >> 24) & 0x000000FF) | (((x) >> 8) & 0x0000FF00) | \
(((x) << 8) & 0x00FF0000) | (((x) << 24) & 0xFF000000))
#define BOMSWAP64_CONST(x) \
((((x) >> 56) & 0x00000000000000FF) | (((x) >> 40) & 0x000000000000FF00) | \
(((x) >> 24) & 0x0000000000FF0000) | (((x) >> 8) & 0x00000000FF000000) | \
(((x) << 8) & 0x000000FF00000000) | (((x) << 24) & 0x0000FF0000000000) | \
(((x) << 40) & 0x00FF000000000000) | (((x) << 56) & 0xFF00000000000000))
#else
#define BOMSWAP16 __builtin_bswap16
#define BOMSWAP32 __builtin_bswap32
#define BOMSWAP64 __builtin_bswap64
#define BOMSWAP16_CONST __builtin_bswap16
#define BOMSWAP32_CONST __builtin_bswap32
#define BOMSWAP64_CONST __builtin_bswap64
#endif
#if (defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)) || defined(__BIG_ENDIAN__)
#ifndef IS_BIGENDIAN
#define IS_BIGENDIAN
#endif
#endif
#ifdef IS_BIGENDIAN
#define BE16SWAP(x) (x)
#define BE32SWAP(x) (x)
#define BE64SWAP(x) (x)
#define LE16SWAP(x) BOMSWAP16(x)
#define LE32SWAP(x) BOMSWAP32(x)
#define LE64SWAP(x) BOMSWAP64(x)
#define BE16SWAP_CONST(x) (x)
#define BE32SWAP_CONST(x) (x)
#define BE64SWAP_CONST(x) (x)
#define LE16SWAP_CONST(x) BOMSWAP16_CONST(x)
#define LE32SWAP_CONST(x) BOMSWAP32_CONST(x)
#define LE64SWAP_CONST(x) BOMSWAP64_CONST(x)
#else
#define BE16SWAP(x) BOMSWAP16(x)
#define BE32SWAP(x) BOMSWAP32(x)
#define BE64SWAP(x) BOMSWAP64(x)
#define LE16SWAP(x) (x)
#define LE32SWAP(x) (x)
#define LE64SWAP(x) (x)
#define BE16SWAP_CONST(x) BOMSWAP16_CONST(x)
#define BE32SWAP_CONST(x) BOMSWAP32_CONST(x)
#define BE64SWAP_CONST(x) BOMSWAP64_CONST(x)
#define LE16SWAP_CONST(x) (x)
#define LE32SWAP_CONST(x) (x)
#define LE64SWAP_CONST(x) (x)
#endif
#endif

View File

@ -1,6 +1,8 @@
#ifndef COLOR_H #ifndef COLOR_H
#define COLOR_H #define COLOR_H
#include "endianness.h"
typedef struct { typedef struct {
u8 r, g, b; u8 r, g, b;
} Color_RGB8; } Color_RGB8;
@ -12,7 +14,11 @@ typedef struct {
// only use when necessary for alignment purposes // only use when necessary for alignment purposes
typedef union { typedef union {
struct { struct {
#ifdef IS_BIGENDIAN
u8 r, g, b, a;
#else
u8 a, b, g, r; u8 a, b, g, r;
#endif
}; };
u32 rgba; u32 rgba;
} Color_RGBA8_u32; } Color_RGBA8_u32;

View File

@ -6,6 +6,15 @@
* Each macro packs bytes (B), halfwords (H) and words (W, for consistency) into a single word * Each macro packs bytes (B), halfwords (H) and words (W, for consistency) into a single word
*/ */
#ifdef IS_BIGENDIAN
#define CMD_BBBB(a, b, c, d) (_SHIFTL(a, 24, 8) | _SHIFTL(b, 16, 8) | _SHIFTL(c, 8, 8) | _SHIFTL(d, 0, 8))
#define CMD_BBH(a, b, c) (_SHIFTL(a, 24, 8) | _SHIFTL(b, 16, 8) | _SHIFTL(c, 0, 16))
#define CMD_HBB(a, b, c) (_SHIFTL(a, 16, 16) | _SHIFTL(b, 8, 8) | _SHIFTL(c, 0, 8))
#define CMD_HH(a, b) (_SHIFTL(a, 16, 16) | _SHIFTL(b, 0, 16))
#else
#define CMD_BBBB(a, b, c, d) (_SHIFTL(a, 0, 8) | _SHIFTL(b, 8, 8) | _SHIFTL(c, 16, 8) | _SHIFTL(d, 24, 8)) #define CMD_BBBB(a, b, c, d) (_SHIFTL(a, 0, 8) | _SHIFTL(b, 8, 8) | _SHIFTL(c, 16, 8) | _SHIFTL(d, 24, 8))
#define CMD_BBH(a, b, c) (_SHIFTL(a, 0, 8) | _SHIFTL(b, 8, 8) | _SHIFTL(c, 16, 16)) #define CMD_BBH(a, b, c) (_SHIFTL(a, 0, 8) | _SHIFTL(b, 8, 8) | _SHIFTL(c, 16, 16))
@ -13,6 +22,7 @@
#define CMD_HBB(a, b, c) (_SHIFTL(a, 0, 16) | _SHIFTL(b, 16, 8) | _SHIFTL(c, 24, 8)) #define CMD_HBB(a, b, c) (_SHIFTL(a, 0, 16) | _SHIFTL(b, 16, 8) | _SHIFTL(c, 24, 8))
#define CMD_HH(a, b) (_SHIFTL(a, 0, 16) | _SHIFTL(b, 16, 16)) #define CMD_HH(a, b) (_SHIFTL(a, 0, 16) | _SHIFTL(b, 16, 16))
#endif
#define CMD_W(a) (a) #define CMD_W(a) (a)

View File

@ -1,6 +1,8 @@
#ifndef MACROS_H #ifndef MACROS_H
#define MACROS_H #define MACROS_H
#include "endianness.h"
#define ARRAY_COUNT(arr) (s32)(sizeof(arr) / sizeof(arr[0])) #define ARRAY_COUNT(arr) (s32)(sizeof(arr) / sizeof(arr[0]))
#define ARRAY_COUNTU(arr) (u32)(sizeof(arr) / sizeof(arr[0])) #define ARRAY_COUNTU(arr) (u32)(sizeof(arr) / sizeof(arr[0]))
@ -254,12 +256,5 @@ extern GraphicsContext* __gfxCtx;
#define SEG_ADDR(seg, addr) (addr | (seg << 24) | 1) #define SEG_ADDR(seg, addr) (addr | (seg << 24) | 1)
#ifdef _MSC_VER
#define BOMSWAP16 _byteswap_ushort
#define BOMSWAP32 _byteswap_ulong
#else
#define BOMSWAP16 __builtin_bswap16
#define BOMSWAP32 __builtin_bswap32
#endif
#endif #endif

View File

@ -1,6 +1,8 @@
#ifndef Z64_AUDIO_H #ifndef Z64_AUDIO_H
#define Z64_AUDIO_H #define Z64_AUDIO_H
#include "endianness.h"
#define MK_CMD(b0,b1,b2,b3) ((((b0) & 0xFF) << 0x18) | (((b1) & 0xFF) << 0x10) | (((b2) & 0xFF) << 0x8) | (((b3) & 0xFF) << 0)) #define MK_CMD(b0,b1,b2,b3) ((((b0) & 0xFF) << 0x18) | (((b1) & 0xFF) << 0x10) | (((b2) & 0xFF) << 0x8) | (((b3) & 0xFF) << 0))
#define NO_LAYER ((SequenceLayer*)(-1)) #define NO_LAYER ((SequenceLayer*)(-1))
@ -685,6 +687,35 @@ typedef struct {
} AudioPreloadReq; // size = 0x14 } AudioPreloadReq; // size = 0x14
typedef struct { typedef struct {
#ifdef IS_BIGENDIAN
union{
u32 opArgs;
struct {
u8 op;
u8 arg0;
u8 arg1;
u8 arg2;
};
};
union {
void* data;
f32 asFloat;
s32 asInt;
struct {
u16 asUShort;
u8 pad2[2];
};
struct {
s8 asSbyte;
u8 pad1[3];
};
struct {
u8 asUbyte;
u8 pad0[3];
};
u32 asUInt;
};
#else
union{ union{
u32 opArgs; u32 opArgs;
struct { struct {
@ -712,6 +743,7 @@ typedef struct {
}; };
u32 asUInt; u32 asUInt;
}; };
#endif
} AudioCmd; } AudioCmd;
typedef struct { typedef struct {

View File

@ -117,8 +117,7 @@ extern "C" void InitOTR() {
if (!t->bHasLoadError) if (!t->bHasLoadError)
{ {
//uint32_t gameVersion = BitConverter::ToUInt32BE((uint8_t*)t->buffer.get(), 0); uint32_t gameVersion = LE32SWAP(*((uint32_t*)t->buffer.get()));
uint32_t gameVersion = *((uint32_t*)t->buffer.get());
OTRGlobals::Instance->context->GetResourceManager()->SetGameVersion(gameVersion); OTRGlobals::Instance->context->GetResourceManager()->SetGameVersion(gameVersion);
} }
@ -795,8 +794,8 @@ extern "C" SoundFont* ResourceMgr_LoadAudioSoundFont(const char* path) {
for (size_t k = 0; k < soundFont->drums[i].env.size(); k++) for (size_t k = 0; k < soundFont->drums[i].env.size(); k++)
{ {
drum->envelope[k].delay = BOMSWAP16(soundFont->drums[i].env[k]->delay); drum->envelope[k].delay = BE16SWAP(soundFont->drums[i].env[k]->delay);
drum->envelope[k].arg = BOMSWAP16(soundFont->drums[i].env[k]->arg); drum->envelope[k].arg = BE16SWAP(soundFont->drums[i].env[k]->arg);
} }
} }
@ -827,8 +826,8 @@ extern "C" SoundFont* ResourceMgr_LoadAudioSoundFont(const char* path) {
for (int k = 0; k < soundFont->instruments[i].env.size(); k++) for (int k = 0; k < soundFont->instruments[i].env.size(); k++)
{ {
inst->envelope[k].delay = BOMSWAP16(soundFont->instruments[i].env[k]->delay); inst->envelope[k].delay = BE16SWAP(soundFont->instruments[i].env[k]->delay);
inst->envelope[k].arg = BOMSWAP16(soundFont->instruments[i].env[k]->arg); inst->envelope[k].arg = BE16SWAP(soundFont->instruments[i].env[k]->arg);
} }
} }
if (soundFont->instruments[i].lowNotesSound != nullptr) if (soundFont->instruments[i].lowNotesSound != nullptr)

View File

@ -544,10 +544,10 @@ u8 gDefaultShortNoteGateTimeTable[] = {
}; };
AdsrEnvelope gDefaultEnvelope[] = { AdsrEnvelope gDefaultEnvelope[] = {
{ 0x0100, 0x007D }, { BE16SWAP_CONST(1), BE16SWAP_CONST(32000) },
{ 0xE803, 0x007D }, { BE16SWAP_CONST(1000), BE16SWAP_CONST(32000) },
{ 0xFFFF, 0x0000 }, { BE16SWAP_CONST(-1), BE16SWAP_CONST(0) },
{ 0x0000, 0x0000 }, { BE16SWAP_CONST(0), BE16SWAP_CONST(0) },
}; };
NoteSubEu gZeroNoteSub = { 0 }; NoteSubEu gZeroNoteSub = { 0 };

View File

@ -246,7 +246,7 @@ f32 Audio_AdsrUpdate(AdsrState* adsr) {
retry: retry:
case ADSR_STATE_LOOP: case ADSR_STATE_LOOP:
adsr->delay = (s16)BOMSWAP16(adsr->envelope[adsr->envIndex].delay); adsr->delay = (s16)BE16SWAP(adsr->envelope[adsr->envIndex].delay);
switch (adsr->delay) { switch (adsr->delay) {
case ADSR_DISABLE: case ADSR_DISABLE:
adsr->action.s.state = ADSR_STATE_DISABLED; adsr->action.s.state = ADSR_STATE_DISABLED;
@ -255,7 +255,7 @@ f32 Audio_AdsrUpdate(AdsrState* adsr) {
adsr->action.s.state = ADSR_STATE_HANG; adsr->action.s.state = ADSR_STATE_HANG;
break; break;
case ADSR_GOTO: case ADSR_GOTO:
adsr->envIndex = (s16)BOMSWAP16(adsr->envelope[adsr->envIndex].arg); adsr->envIndex = (s16)BE16SWAP(adsr->envelope[adsr->envIndex].arg);
goto retry; goto retry;
case ADSR_RESTART: case ADSR_RESTART:
adsr->action.s.state = ADSR_STATE_INITIAL; adsr->action.s.state = ADSR_STATE_INITIAL;
@ -266,7 +266,7 @@ f32 Audio_AdsrUpdate(AdsrState* adsr) {
if (adsr->delay == 0) { if (adsr->delay == 0) {
adsr->delay = 1; adsr->delay = 1;
} }
adsr->target = (s16)BOMSWAP16(adsr->envelope[adsr->envIndex].arg) / 32767.0f; adsr->target = (s16)BE16SWAP(adsr->envelope[adsr->envIndex].arg) / 32767.0f;
adsr->target = adsr->target * adsr->target; adsr->target = adsr->target * adsr->target;
adsr->velocity = (adsr->target - adsr->current) / adsr->delay; adsr->velocity = (adsr->target - adsr->current) / adsr->delay;
adsr->action.s.state = ADSR_STATE_FADE; adsr->action.s.state = ADSR_STATE_FADE;

View File

@ -1340,13 +1340,13 @@ void AudioSeq_SequenceChannelProcessScript(SequenceChannel* channel) {
break; break;
case 0xB2: case 0xB2:
offset = (u16)parameters[0]; offset = (u16)parameters[0];
channel->unk_22 = BOMSWAP16(*(u16*)(seqPlayer->seqData + (uintptr_t)(offset + scriptState->value * 2))); channel->unk_22 = BE16SWAP(*(u16*)(seqPlayer->seqData + (uintptr_t)(offset + scriptState->value * 2)));
break; break;
case 0xB4: case 0xB4:
channel->dynTable = (void*)&seqPlayer->seqData[channel->unk_22]; channel->dynTable = (void*)&seqPlayer->seqData[channel->unk_22];
break; break;
case 0xB5: case 0xB5:
channel->unk_22 = BOMSWAP16(((u16*)(channel->dynTable))[scriptState->value]); channel->unk_22 = BE16SWAP(((u16*)(channel->dynTable))[scriptState->value]);
break; break;
case 0xB6: case 0xB6:
scriptState->value = (*channel->dynTable)[0][scriptState->value]; scriptState->value = (*channel->dynTable)[0][scriptState->value];

View File

@ -217,13 +217,12 @@ void func_80095D04(GlobalContext* globalCtx, Room* room, u32 flags) {
CLOSE_DISPS(globalCtx->state.gfxCtx); CLOSE_DISPS(globalCtx->state.gfxCtx);
} }
//#define JPEG_MARKER 0xFFD8FFE0 #define JPEG_MARKER 0xFFD8FFE0
#define JPEG_MARKER 0xE0FFD8FF
s32 func_80096238(void* data) { s32 func_80096238(void* data) {
OSTime time; OSTime time;
if (*(u32*)data == JPEG_MARKER) if (BE32SWAP(*(u32*)data) == JPEG_MARKER)
{ {
char* decodedJpeg = ResourceMgr_LoadJPEG(data, 320 * 240 * 2); char* decodedJpeg = ResourceMgr_LoadJPEG(data, 320 * 240 * 2);
//char* decodedJpeg = ResourceMgr_LoadJPEG(data, 480 * 240 * 2); //char* decodedJpeg = ResourceMgr_LoadJPEG(data, 480 * 240 * 2);