2022-07-03 11:57:43 -04:00
|
|
|
#include "sitypes.h"
|
|
|
|
|
|
|
|
#include "chunk.h"
|
|
|
|
|
|
|
|
namespace si {
|
|
|
|
|
|
|
|
Data ReadU32(std::ifstream &is)
|
|
|
|
{
|
2022-07-11 00:09:39 -04:00
|
|
|
uint32_t u;
|
2022-07-03 11:57:43 -04:00
|
|
|
is.read((char *) &u, sizeof(u));
|
|
|
|
return u;
|
|
|
|
}
|
|
|
|
|
2022-07-11 12:06:04 -04:00
|
|
|
void WriteU32(std::ofstream &os, uint32_t u)
|
|
|
|
{
|
|
|
|
os.write((const char *) &u, sizeof(u));
|
|
|
|
}
|
|
|
|
|
2022-07-03 11:57:43 -04:00
|
|
|
Data ReadU16(std::ifstream &is)
|
|
|
|
{
|
2022-07-11 00:09:39 -04:00
|
|
|
uint16_t u;
|
2022-07-03 11:57:43 -04:00
|
|
|
is.read((char *) &u, sizeof(u));
|
|
|
|
return u;
|
|
|
|
}
|
|
|
|
|
2022-07-11 12:06:04 -04:00
|
|
|
void WriteU16(std::ofstream &os, uint16_t u)
|
|
|
|
{
|
|
|
|
os.write((const char *) &u, sizeof(u));
|
|
|
|
}
|
|
|
|
|
2022-07-04 13:59:47 -04:00
|
|
|
Data ReadU8(std::ifstream &is)
|
|
|
|
{
|
2022-07-11 00:09:39 -04:00
|
|
|
uint8_t u;
|
2022-07-04 13:59:47 -04:00
|
|
|
is.read((char *) &u, sizeof(u));
|
|
|
|
return u;
|
|
|
|
}
|
|
|
|
|
2022-07-11 12:06:04 -04:00
|
|
|
void WriteU8(std::ofstream &os, uint8_t u)
|
|
|
|
{
|
|
|
|
os.write((const char *) &u, sizeof(u));
|
|
|
|
}
|
|
|
|
|
2022-07-04 02:33:38 -04:00
|
|
|
Data ReadVector3(std::ifstream &is)
|
|
|
|
{
|
|
|
|
Vector3 u;
|
|
|
|
is.read((char *) &u, sizeof(u));
|
|
|
|
return u;
|
|
|
|
}
|
|
|
|
|
2022-07-11 12:06:04 -04:00
|
|
|
void WriteVector3(std::ofstream &os, Vector3 v)
|
|
|
|
{
|
|
|
|
os.write((const char *) &v, sizeof(v));
|
|
|
|
}
|
|
|
|
|
2022-07-03 11:57:43 -04:00
|
|
|
Data ReadString(std::ifstream &is)
|
|
|
|
{
|
|
|
|
bytearray d;
|
|
|
|
|
|
|
|
while (true) {
|
|
|
|
char c;
|
|
|
|
is.read(&c, 1);
|
|
|
|
if (c == 0) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
d.push_back(c);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Append null terminator
|
|
|
|
d.push_back(0);
|
|
|
|
|
|
|
|
return d;
|
|
|
|
}
|
|
|
|
|
2022-07-11 12:06:04 -04:00
|
|
|
void WriteString(std::ofstream &os, const std::string &d)
|
|
|
|
{
|
|
|
|
if (!d.empty()) {
|
|
|
|
// Write every byte that isn't null
|
|
|
|
const char *s = &d[0];
|
|
|
|
while ((*s) != 0) {
|
|
|
|
os.write(s, 1);
|
2022-07-11 17:18:56 -04:00
|
|
|
s++;
|
2022-07-11 12:06:04 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Ensure null terminator
|
|
|
|
const char nullterm = 0;
|
|
|
|
os.write(&nullterm, 1);
|
|
|
|
}
|
|
|
|
|
2022-07-03 11:57:43 -04:00
|
|
|
Data ReadBytes(std::ifstream &is, size_t size)
|
|
|
|
{
|
|
|
|
bytearray d;
|
|
|
|
|
|
|
|
d.resize(size);
|
|
|
|
is.read(d.data(), size);
|
|
|
|
|
|
|
|
return d;
|
|
|
|
}
|
|
|
|
|
2022-07-11 12:06:04 -04:00
|
|
|
void WriteBytes(std::ofstream &os, const bytearray &ba)
|
|
|
|
{
|
|
|
|
os.write(ba.data(), ba.size());
|
|
|
|
}
|
|
|
|
|
2022-07-11 00:09:39 -04:00
|
|
|
void RIFF::Read(std::ifstream &is, DataMap &data, uint32_t version, uint32_t size)
|
2022-07-03 11:57:43 -04:00
|
|
|
{
|
|
|
|
data["Format"] = ReadU32(is);
|
|
|
|
}
|
|
|
|
|
2022-07-11 12:06:04 -04:00
|
|
|
void RIFF::Write(std::ofstream &os, const DataMap &data, uint32_t version)
|
|
|
|
{
|
|
|
|
WriteU32(os, data.at("Format"));
|
|
|
|
}
|
|
|
|
|
2022-07-11 00:09:39 -04:00
|
|
|
void LIST::Read(std::ifstream &is, DataMap &data, uint32_t version, uint32_t size)
|
2022-07-03 11:57:43 -04:00
|
|
|
{
|
|
|
|
data["Format"] = ReadU32(is);
|
|
|
|
|
|
|
|
if (data["Format"] == Chunk::TYPE_MxCh) {
|
|
|
|
data["Count"] = ReadU32(is);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-07-11 12:06:04 -04:00
|
|
|
void LIST::Write(std::ofstream &os, const DataMap &data, uint32_t version)
|
|
|
|
{
|
|
|
|
WriteU32(os, data.at("Format"));
|
|
|
|
|
|
|
|
if (data.at("Format") == Chunk::TYPE_MxCh) {
|
|
|
|
WriteU32(os, data.at("Count"));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-07-11 00:09:39 -04:00
|
|
|
void MxSt::Read(std::ifstream &is, DataMap &data, uint32_t version, uint32_t size)
|
2022-07-03 11:57:43 -04:00
|
|
|
{
|
|
|
|
// MxSt is a container type only and has no members, so nothing needs to be done here
|
|
|
|
}
|
|
|
|
|
2022-07-11 12:06:04 -04:00
|
|
|
void MxSt::Write(std::ofstream &os, const DataMap &data, uint32_t version)
|
|
|
|
{
|
|
|
|
// MxSt is a container type only and has no members, so nothing needs to be done here
|
|
|
|
}
|
|
|
|
|
2022-07-11 00:09:39 -04:00
|
|
|
void MxHd::Read(std::ifstream &is, DataMap &data, uint32_t version, uint32_t size)
|
2022-07-03 11:57:43 -04:00
|
|
|
{
|
|
|
|
Data v = ReadU32(is);
|
|
|
|
data["Version"] = v;
|
|
|
|
data["BufferSize"] = ReadU32(is);
|
|
|
|
data["BufferCount"] = ReadU32(is);
|
|
|
|
}
|
|
|
|
|
2022-07-11 12:06:04 -04:00
|
|
|
void MxHd::Write(std::ofstream &os, const DataMap &data, uint32_t version)
|
|
|
|
{
|
|
|
|
WriteU32(os, data.at("Version"));
|
|
|
|
WriteU32(os, data.at("BufferSize"));
|
|
|
|
WriteU32(os, data.at("BufferCount"));
|
|
|
|
}
|
|
|
|
|
2022-07-11 00:09:39 -04:00
|
|
|
void MxCh::Read(std::ifstream &is, DataMap &data, uint32_t version, uint32_t size)
|
2022-07-03 11:57:43 -04:00
|
|
|
{
|
|
|
|
data["Flags"] = ReadU16(is);
|
|
|
|
data["Object"] = ReadU32(is);
|
|
|
|
data["Time"] = ReadU32(is);
|
|
|
|
data["DataSize"] = ReadU32(is);
|
|
|
|
data["Data"] = ReadBytes(is, size - 0xE);
|
|
|
|
}
|
|
|
|
|
2022-07-11 12:06:04 -04:00
|
|
|
void MxCh::Write(std::ofstream &os, const DataMap &data, uint32_t version)
|
|
|
|
{
|
|
|
|
WriteU16(os, data.at("Flags"));
|
|
|
|
WriteU32(os, data.at("Object"));
|
|
|
|
WriteU32(os, data.at("Time"));
|
|
|
|
WriteU32(os, data.at("DataSize"));
|
|
|
|
WriteBytes(os, data.at("Data"));
|
|
|
|
}
|
|
|
|
|
2022-07-11 00:09:39 -04:00
|
|
|
void MxOf::Read(std::ifstream &is, DataMap &data, uint32_t version, uint32_t size)
|
2022-07-03 11:57:43 -04:00
|
|
|
{
|
|
|
|
data["Count"] = ReadU32(is);
|
2022-07-11 00:09:39 -04:00
|
|
|
data["Offsets"] = ReadBytes(is, size - sizeof(uint32_t));
|
2022-07-03 11:57:43 -04:00
|
|
|
}
|
|
|
|
|
2022-07-11 12:06:04 -04:00
|
|
|
void MxOf::Write(std::ofstream &os, const DataMap &data, uint32_t version)
|
|
|
|
{
|
|
|
|
WriteU32(os, data.at("Count"));
|
|
|
|
WriteBytes(os, data.at("Offsets"));
|
|
|
|
}
|
|
|
|
|
2022-07-11 00:09:39 -04:00
|
|
|
void pad_::Read(std::ifstream &is, DataMap &data, uint32_t version, uint32_t size)
|
2022-07-03 11:57:43 -04:00
|
|
|
{
|
2022-07-11 17:18:56 -04:00
|
|
|
data["Size"] = size;
|
2022-07-03 11:57:43 -04:00
|
|
|
is.seekg(size, std::ios::cur);
|
|
|
|
}
|
|
|
|
|
2022-07-11 17:18:56 -04:00
|
|
|
void pad_::Write(std::ofstream &os, const DataMap &data, uint32_t version)
|
2022-07-11 12:06:04 -04:00
|
|
|
{
|
2022-07-11 17:18:56 -04:00
|
|
|
uint32_t sz = data.at("Size").toU32();
|
|
|
|
if (sz > 0) {
|
|
|
|
bytearray b;
|
|
|
|
b.resize(sz);
|
|
|
|
b.fill(0xCD);
|
|
|
|
WriteBytes(os, b);
|
|
|
|
}
|
2022-07-11 12:06:04 -04:00
|
|
|
}
|
|
|
|
|
2022-07-17 19:25:06 -04:00
|
|
|
void pad_::WriteArbitraryPadding(std::ofstream &os, uint32_t size)
|
|
|
|
{
|
|
|
|
uint32_t pad_id = Chunk::TYPE_pad_;
|
|
|
|
os.write((const char *) &pad_id, sizeof(uint32_t));
|
|
|
|
os.write((const char *) &size, sizeof(uint32_t));
|
|
|
|
bytearray b(size);
|
|
|
|
b.fill(0xCD);
|
|
|
|
WriteBytes(os, b);
|
|
|
|
}
|
|
|
|
|
2022-07-03 11:57:43 -04:00
|
|
|
const char *MxOb::GetTypeName(Type type)
|
|
|
|
{
|
|
|
|
switch (type) {
|
2022-07-11 04:48:20 -04:00
|
|
|
case Video:
|
2022-07-03 11:57:43 -04:00
|
|
|
return "SMK";
|
2022-07-11 04:48:20 -04:00
|
|
|
case Sound:
|
2022-07-03 11:57:43 -04:00
|
|
|
return "WAV";
|
|
|
|
case Presenter:
|
|
|
|
return "MxPresenter";
|
2022-07-17 19:25:06 -04:00
|
|
|
case Bitmap:
|
2022-07-03 11:57:43 -04:00
|
|
|
return "BMP";
|
2022-07-17 19:25:06 -04:00
|
|
|
case Object:
|
2022-07-03 11:57:43 -04:00
|
|
|
return "3D Object";
|
|
|
|
case World:
|
|
|
|
return "World";
|
|
|
|
case Event:
|
|
|
|
return "Event";
|
|
|
|
case Animation:
|
|
|
|
return "Animation";
|
2022-07-17 19:25:06 -04:00
|
|
|
case Null:
|
2022-07-03 11:57:43 -04:00
|
|
|
case TYPE_COUNT:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return "Unknown";
|
|
|
|
}
|
|
|
|
|
2022-07-04 13:59:47 -04:00
|
|
|
std::vector<const char*> MxOb::GetFlagsName(Flags flags)
|
|
|
|
{
|
|
|
|
std::vector<const char*> names;
|
|
|
|
|
|
|
|
if (flags == FLAGS_COUNT) {
|
|
|
|
return names;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (flags & Transparent) {
|
|
|
|
names.push_back("Transparent");
|
|
|
|
}
|
|
|
|
if (flags & NoLoop) {
|
|
|
|
names.push_back("NoLoop");
|
|
|
|
}
|
|
|
|
if (flags & LoopCache) {
|
|
|
|
names.push_back("LoopCache");
|
|
|
|
}
|
|
|
|
if (flags & LoopStream) {
|
|
|
|
names.push_back("LoopStream");
|
|
|
|
}
|
|
|
|
if (flags & Unknown) {
|
|
|
|
names.push_back("Unknown");
|
|
|
|
}
|
|
|
|
|
|
|
|
return names;
|
|
|
|
}
|
|
|
|
|
2022-07-11 00:09:39 -04:00
|
|
|
void MxOb::Read(std::ifstream &is, DataMap &data, uint32_t version, uint32_t size)
|
2022-07-03 11:57:43 -04:00
|
|
|
{
|
|
|
|
Data obj_type = ReadU16(is);
|
|
|
|
data["Type"] = obj_type;
|
|
|
|
data["Presenter"] = ReadString(is);
|
|
|
|
data["Unknown1"] = ReadU32(is);
|
|
|
|
data["Name"] = ReadString(is);
|
|
|
|
data["ID"] = ReadU32(is);
|
2022-07-04 22:50:23 -04:00
|
|
|
data["Flags"] = ReadU32(is);
|
2022-07-03 11:57:43 -04:00
|
|
|
data["Unknown4"] = ReadU32(is);
|
2022-07-04 13:59:47 -04:00
|
|
|
data["Duration"] = ReadU32(is);
|
|
|
|
data["Loops"] = ReadU32(is);
|
2022-07-04 02:33:38 -04:00
|
|
|
data["Position"] = ReadVector3(is);
|
|
|
|
data["Direction"] = ReadVector3(is);
|
|
|
|
data["Up"] = ReadVector3(is);
|
2022-07-03 11:57:43 -04:00
|
|
|
|
|
|
|
Data extra_sz = ReadU16(is);
|
|
|
|
data["ExtraLength"] = extra_sz;
|
|
|
|
data["ExtraData"] = ReadBytes(is, extra_sz);
|
|
|
|
|
|
|
|
if (obj_type != Presenter && obj_type != World) {
|
|
|
|
data["FileName"] = ReadString(is);
|
|
|
|
|
|
|
|
data["Unknown26"] = ReadU32(is);
|
|
|
|
data["Unknown27"] = ReadU32(is);
|
|
|
|
data["Unknown28"] = ReadU32(is);
|
|
|
|
|
|
|
|
data["FileType"] = ReadU32(is);
|
|
|
|
|
|
|
|
data["Unknown29"] = ReadU32(is);
|
|
|
|
data["Unknown30"] = ReadU32(is);
|
|
|
|
|
2022-07-11 04:48:20 -04:00
|
|
|
if (obj_type == MxOb::Sound) {
|
2022-07-03 11:57:43 -04:00
|
|
|
data["Unknown31"] = ReadU32(is);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-07-11 12:06:04 -04:00
|
|
|
void MxOb::Write(std::ofstream &os, const DataMap &data, uint32_t version)
|
|
|
|
{
|
|
|
|
const Data &obj_type = data.at("Type");
|
|
|
|
WriteU16(os, obj_type);
|
|
|
|
WriteString(os, data.at("Presenter"));
|
|
|
|
WriteU32(os, data.at("Unknown1"));
|
|
|
|
WriteString(os, data.at("Name"));
|
|
|
|
WriteU32(os, data.at("ID"));
|
|
|
|
WriteU32(os, data.at("Flags"));
|
|
|
|
WriteU32(os, data.at("Unknown4"));
|
|
|
|
WriteU32(os, data.at("Duration"));
|
|
|
|
WriteU32(os, data.at("Loops"));
|
|
|
|
WriteVector3(os, data.at("Position"));
|
|
|
|
WriteVector3(os, data.at("Direction"));
|
|
|
|
WriteVector3(os, data.at("Up"));
|
|
|
|
|
|
|
|
const Data &extra = data.at("ExtraData");
|
|
|
|
WriteU16(os, extra.size());
|
|
|
|
WriteBytes(os, extra);
|
|
|
|
|
|
|
|
if (obj_type != Presenter && obj_type != World) {
|
|
|
|
WriteString(os, data.at("FileName"));
|
|
|
|
|
|
|
|
WriteU32(os, data.at("Unknown26"));
|
|
|
|
WriteU32(os, data.at("Unknown27"));
|
|
|
|
WriteU32(os, data.at("Unknown28"));
|
|
|
|
|
|
|
|
WriteU32(os, data.at("FileType"));
|
|
|
|
|
|
|
|
WriteU32(os, data.at("Unknown29"));
|
|
|
|
WriteU32(os, data.at("Unknown30"));
|
|
|
|
|
|
|
|
if (obj_type == MxOb::Sound) {
|
|
|
|
WriteU32(os, data.at("Unknown31"));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-07-03 11:57:43 -04:00
|
|
|
}
|