mirror of
https://github.com/isledecomp/SIEdit.git
synced 2024-11-27 01:25:45 -05:00
use abstract data storage
This commit is contained in:
parent
6eb38edad9
commit
ef5d9a0060
21 changed files with 543 additions and 626 deletions
|
@ -1,6 +1,5 @@
|
|||
#include "chunkmodel.h"
|
||||
|
||||
#include <data/riff.h>
|
||||
#include <iostream>
|
||||
|
||||
#define super QAbstractItemModel
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
#include "mxch.h"
|
||||
|
||||
#include <data/mxch.h>
|
||||
#include <QFontDatabase>
|
||||
#include <QGroupBox>
|
||||
#include <QLabel>
|
||||
|
@ -83,34 +82,31 @@ MxChPanel::MxChPanel(QWidget *parent) :
|
|||
|
||||
void MxChPanel::OnOpeningData(Chunk *chunk)
|
||||
{
|
||||
MxCh *mxch = chunk->data().cast<MxCh>();
|
||||
|
||||
flag_edit_->setText(QString::number(mxch->wFlags, 16));
|
||||
obj_edit_->setValue(mxch->dwObjectParent);
|
||||
ms_offset_edit_->setValue(mxch->dwMillisecondOffset);
|
||||
data_sz_edit_->setValue(mxch->dwDataSize);
|
||||
flag_edit_->setText(QString::number(chunk->data("Flags"), 16));
|
||||
obj_edit_->setValue(chunk->data("Object"));
|
||||
ms_offset_edit_->setValue(chunk->data("Time"));
|
||||
data_sz_edit_->setValue(chunk->data("DataSize"));
|
||||
|
||||
for (QCheckBox *cb : qAsConst(flag_checkboxes_)) {
|
||||
cb->setChecked(cb->property("flag").toUInt() & mxch->wFlags);
|
||||
cb->setChecked(cb->property("flag").toUInt() & chunk->data("Flags"));
|
||||
}
|
||||
|
||||
QByteArray ba((const char*) chunk->exdata().data(), chunk->exdata().size());
|
||||
const Data &data = chunk->data("Data");
|
||||
QByteArray ba(data.data(), data.size());
|
||||
data_edit_->setPlainText(ba.toHex());
|
||||
}
|
||||
|
||||
void MxChPanel::OnClosingData(Chunk *chunk)
|
||||
{
|
||||
MxCh *mxch = chunk->data().cast<MxCh>();
|
||||
|
||||
bool ok;
|
||||
u16 flags = flag_edit_->text().toUShort(&ok, 16);
|
||||
if (ok) {
|
||||
mxch->wFlags = flags;
|
||||
chunk->data("Flags") = flags;
|
||||
}
|
||||
|
||||
mxch->dwObjectParent = obj_edit_->value();
|
||||
mxch->dwMillisecondOffset = ms_offset_edit_->value();
|
||||
mxch->dwDataSize = data_sz_edit_->value();
|
||||
chunk->data("Object") = u32(obj_edit_->value());
|
||||
chunk->data("Time") = u32(ms_offset_edit_->value());
|
||||
chunk->data("DataSize") = u32(data_sz_edit_->value());
|
||||
}
|
||||
|
||||
void MxChPanel::FlagCheckBoxClicked(bool e)
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
#include "mxhd.h"
|
||||
|
||||
#include <data/mxhd.h>
|
||||
#include <QLabel>
|
||||
|
||||
using namespace si;
|
||||
|
@ -50,22 +49,19 @@ MxHdPanel::MxHdPanel(QWidget *parent)
|
|||
|
||||
void MxHdPanel::OnOpeningData(Chunk *chunk)
|
||||
{
|
||||
MxHd *mxhd = chunk->data().cast<MxHd>();
|
||||
|
||||
uint16_t major_ver = mxhd->dwVersion >> 16;
|
||||
uint16_t minor_ver = mxhd->dwVersion;
|
||||
si::u32 version = chunk->data("Version");
|
||||
uint16_t major_ver = version >> 16;
|
||||
uint16_t minor_ver = version;
|
||||
|
||||
major_version_edit_->setValue(major_ver);
|
||||
minor_version_edit_->setValue(minor_ver);
|
||||
buffer_alignment_edit_->setValue(mxhd->dwBufferSize);
|
||||
buffer_count_edit_->setValue(mxhd->dwBufferCount);
|
||||
buffer_alignment_edit_->setValue(chunk->data("BufferSize"));
|
||||
buffer_count_edit_->setValue(chunk->data("BufferCount"));
|
||||
}
|
||||
|
||||
void MxHdPanel::OnClosingData(Chunk *chunk)
|
||||
{
|
||||
MxHd *mxhd = chunk->data().cast<MxHd>();
|
||||
|
||||
mxhd->dwVersion = (major_version_edit_->value() << 16 | (minor_version_edit_->value() & 0xFFFF));
|
||||
mxhd->dwBufferSize = buffer_alignment_edit_->value();
|
||||
mxhd->dwBufferCount = buffer_count_edit_->value();
|
||||
chunk->data("Version") = (major_version_edit_->value() << 16 | (minor_version_edit_->value() & 0xFFFF));
|
||||
chunk->data("BufferSize") = buffer_alignment_edit_->value();
|
||||
chunk->data("BufferCount") = buffer_count_edit_->value();
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#include "mxob.h"
|
||||
|
||||
#include <data/mxob.h>
|
||||
#include <sitypes.h>
|
||||
#include <QLabel>
|
||||
|
||||
using namespace si;
|
||||
|
@ -53,18 +53,14 @@ MxObPanel::MxObPanel(QWidget *parent) :
|
|||
|
||||
void MxObPanel::OnOpeningData(si::Chunk *chunk)
|
||||
{
|
||||
auto mxob = chunk->data().cast<MxOb>();
|
||||
|
||||
type_combo_->setCurrentIndex(mxob->wType);
|
||||
name_edit_->setText(mxob->szName);
|
||||
filename_edit_->setText(mxob->szFilename);
|
||||
presenter_edit_->setText(mxob->szPresenter);
|
||||
obj_id_edit_->setValue(mxob->dwObjectID);
|
||||
type_combo_->setCurrentIndex(chunk->data("Type"));
|
||||
name_edit_->setText(QString(chunk->data("Name")));
|
||||
filename_edit_->setText(QString(chunk->data("FileName")));
|
||||
presenter_edit_->setText(QString(chunk->data("Presenter")));
|
||||
obj_id_edit_->setValue(chunk->data("ID"));
|
||||
}
|
||||
|
||||
void MxObPanel::OnClosingData(si::Chunk *chunk)
|
||||
{
|
||||
auto mxob = chunk->data().cast<MxOb>();
|
||||
|
||||
mxob->wType = type_combo_->currentIndex();
|
||||
chunk->data("Type") = type_combo_->currentIndex();
|
||||
}
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
#include "mxof.h"
|
||||
|
||||
#include <data/mxof.h>
|
||||
#include <QLabel>
|
||||
|
||||
using namespace si;
|
||||
|
@ -27,13 +26,13 @@ MxOfPanel::MxOfPanel(QWidget *parent) :
|
|||
|
||||
void MxOfPanel::OnOpeningData(si::Chunk *chunk)
|
||||
{
|
||||
u32 *offsets = reinterpret_cast<u32*>(chunk->exdata().data());
|
||||
size_t count = chunk->exdata().size() / sizeof(u32);
|
||||
const Data &offsets_bytes = chunk->data("Offsets");
|
||||
const u32 *offsets = reinterpret_cast<const u32*>(offsets_bytes.data());
|
||||
size_t offset_count = offsets_bytes.size() / sizeof(u32);
|
||||
|
||||
MxOf *mxof = chunk->data().cast<MxOf>();
|
||||
obj_count_edit_->setValue(mxof->dwObjectCount);
|
||||
obj_count_edit_->setValue(chunk->data("Count"));
|
||||
|
||||
for (size_t i=0; i<count; i++) {
|
||||
for (size_t i=0; i<offset_count; i++) {
|
||||
QString addr = QStringLiteral("0x%1").arg(offsets[i], 8, 16, QChar('0'));
|
||||
|
||||
list_->addItem(QStringLiteral("%1: %2").arg(QString::number(i), addr));
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
#include "riff.h"
|
||||
|
||||
#include <data/riff.h>
|
||||
#include <QLabel>
|
||||
|
||||
using namespace si;
|
||||
|
@ -21,16 +20,12 @@ RIFFPanel::RIFFPanel(QWidget *parent) :
|
|||
|
||||
void RIFFPanel::OnOpeningData(Chunk *chunk)
|
||||
{
|
||||
RIFF *riff = chunk->data().cast<RIFF>();
|
||||
|
||||
QString s = QString::fromLatin1((const char *) &riff->dwID, sizeof(u32));
|
||||
QString s = QString::fromLatin1(chunk->data("Format").c_str(), sizeof(u32));
|
||||
id_edit_->setText(s);
|
||||
}
|
||||
|
||||
void RIFFPanel::OnClosingData(Chunk *chunk)
|
||||
{
|
||||
RIFF *riff = chunk->data().cast<RIFF>();
|
||||
|
||||
QByteArray d = id_edit_->text().toLatin1();
|
||||
|
||||
const int target_sz = sizeof(u32);
|
||||
|
@ -43,5 +38,5 @@ void RIFFPanel::OnClosingData(Chunk *chunk)
|
|||
}
|
||||
}
|
||||
|
||||
riff->dwID = *(u32*)d.data();
|
||||
chunk->data("Format") = *(u32*)d.data();
|
||||
}
|
||||
|
|
|
@ -1,21 +1,11 @@
|
|||
option(LIBWEAVER_BUILD_DOXYGEN "Build Doxygen documentation" OFF)
|
||||
|
||||
set(LIBWEAVER_SOURCES
|
||||
# Data types
|
||||
data/mxch.h
|
||||
data/mxhd.h
|
||||
data/mxob.cpp
|
||||
data/mxob.h
|
||||
data/mxof.h
|
||||
data/mxst.h
|
||||
data/riff.h
|
||||
|
||||
# Main library
|
||||
bytearray.cpp
|
||||
bytearray.h
|
||||
chunk.cpp
|
||||
chunk.h
|
||||
common.h
|
||||
sitypes.cpp
|
||||
sitypes.h
|
||||
types.h
|
||||
)
|
||||
|
||||
|
|
|
@ -1,27 +0,0 @@
|
|||
#include "bytearray.h"
|
||||
|
||||
#include <iomanip>
|
||||
#include <ios>
|
||||
#include <sstream>
|
||||
|
||||
namespace si {
|
||||
|
||||
bytearray::bytearray()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
std::string bytearray::hex() const
|
||||
{
|
||||
std::ostringstream ss;
|
||||
|
||||
ss << std::hex << std::uppercase << std::setfill('0');
|
||||
|
||||
for (size_t i=0; i<size(); i++) {
|
||||
ss << std::setw(2) << at(i);
|
||||
}
|
||||
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
}
|
|
@ -1,24 +0,0 @@
|
|||
#ifndef BYTEARRAY_H
|
||||
#define BYTEARRAY_H
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "types.h"
|
||||
|
||||
namespace si {
|
||||
|
||||
class bytearray : public std::vector<s8>
|
||||
{
|
||||
public:
|
||||
bytearray();
|
||||
|
||||
template <typename T>
|
||||
T *cast() { return reinterpret_cast<T*>(data()); }
|
||||
|
||||
std::string hex() const;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // BYTEARRAY_H
|
171
lib/chunk.cpp
171
lib/chunk.cpp
|
@ -4,12 +4,7 @@
|
|||
#include <cstring>
|
||||
#include <iostream>
|
||||
|
||||
#include "data/mxch.h"
|
||||
#include "data/mxhd.h"
|
||||
#include "data/mxob.h"
|
||||
#include "data/mxof.h"
|
||||
#include "data/mxst.h"
|
||||
#include "data/riff.h"
|
||||
#include "sitypes.h"
|
||||
|
||||
namespace si {
|
||||
|
||||
|
@ -42,125 +37,18 @@ bool Chunk::Read(const char *f)
|
|||
return Read(file, version, alignment);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void CreateAndReadData(std::ifstream &f, bytearray &data, u32 size)
|
||||
{
|
||||
size_t read_sz = std::min(size_t(size), sizeof(T));
|
||||
data.resize(read_sz);
|
||||
f.read(data.data(), read_sz);
|
||||
}
|
||||
|
||||
void ReadNullTerminatedString(std::ifstream &f, char *str)
|
||||
{
|
||||
std::string s;
|
||||
|
||||
while (true) {
|
||||
f.read(str, 1);
|
||||
if (*str == 0) {
|
||||
break;
|
||||
} else {
|
||||
str++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Read_List(std::ifstream &f, LIST *ls)
|
||||
{
|
||||
f.read((char *) &ls->dwID, sizeof(ls->dwID));
|
||||
|
||||
if (ls->dwID == Chunk::TYPE_MxCh) {
|
||||
// MxCh type lists contain an element count
|
||||
f.read((char *) &ls->dwCount, sizeof(ls->dwCount));
|
||||
|
||||
// TEMP FOR 1.2 REMOVE
|
||||
//f.read((char *) &ls->dwCount, sizeof(ls->dwCount));
|
||||
} else {
|
||||
ls->dwCount = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void Read_MxOb(std::ifstream &f, Chunk *c, MxOb *ob)
|
||||
{
|
||||
f.read((char *) &ob->wType, sizeof(ob->wType));
|
||||
|
||||
ReadNullTerminatedString(f, ob->szPresenter);
|
||||
|
||||
f.read((char *) &ob->dwUnknown1, sizeof(ob->dwUnknown1));
|
||||
|
||||
ReadNullTerminatedString(f, ob->szName);
|
||||
|
||||
f.read((char *) &ob->dwObjectID, sizeof(ob->dwObjectID));
|
||||
f.read((char *) &ob->dwUnknown3, sizeof(ob->dwUnknown3));
|
||||
f.read((char *) &ob->dwUnknown4, sizeof(ob->dwUnknown4));
|
||||
f.read((char *) &ob->dwUnknown5, sizeof(ob->dwUnknown5));
|
||||
f.read((char *) &ob->dwUnknown6, sizeof(ob->dwUnknown6));
|
||||
f.read((char *) &ob->dwUnknown7, sizeof(ob->dwUnknown7));
|
||||
f.read((char *) &ob->dwUnknown8, sizeof(ob->dwUnknown8));
|
||||
f.read((char *) &ob->dwUnknown9, sizeof(ob->dwUnknown9));
|
||||
f.read((char *) &ob->dwUnknown10, sizeof(ob->dwUnknown10));
|
||||
f.read((char *) &ob->dwUnknown11, sizeof(ob->dwUnknown11));
|
||||
f.read((char *) &ob->dwUnknown12, sizeof(ob->dwUnknown12));
|
||||
f.read((char *) &ob->dwUnknown13, sizeof(ob->dwUnknown13));
|
||||
f.read((char *) &ob->dwUnknown14, sizeof(ob->dwUnknown14));
|
||||
f.read((char *) &ob->dwUnknown15, sizeof(ob->dwUnknown15));
|
||||
f.read((char *) &ob->dwUnknown16, sizeof(ob->dwUnknown16));
|
||||
f.read((char *) &ob->dwUnknown17, sizeof(ob->dwUnknown17));
|
||||
f.read((char *) &ob->fUnknown18, sizeof(ob->fUnknown18));
|
||||
f.read((char *) &ob->dwUnknown19, sizeof(ob->dwUnknown19));
|
||||
f.read((char *) &ob->dwUnknown20, sizeof(ob->dwUnknown20));
|
||||
f.read((char *) &ob->dwUnknown21, sizeof(ob->dwUnknown21));
|
||||
f.read((char *) &ob->fUnknown22, sizeof(ob->fUnknown22));
|
||||
f.read((char *) &ob->dwUnknown23, sizeof(ob->dwUnknown23));
|
||||
f.read((char *) &ob->dwUnknown24, sizeof(ob->dwUnknown24));
|
||||
f.read((char *) &ob->wCreationStringLength, sizeof(ob->wCreationStringLength));
|
||||
|
||||
if (ob->wCreationStringLength > 0) {
|
||||
f.read(ob->szCreationString, ob->wCreationStringLength);
|
||||
}
|
||||
|
||||
switch (static_cast<MxOb::Type>(ob->wType)) {
|
||||
case MxOb::Presenter:
|
||||
case MxOb::World:
|
||||
break;
|
||||
case MxOb::OBJ:
|
||||
case MxOb::BMP:
|
||||
case MxOb::SMK:
|
||||
case MxOb::WAV:
|
||||
case MxOb::Event:
|
||||
ReadNullTerminatedString(f, ob->szFilename);
|
||||
|
||||
if (ob->wType != MxOb::World) {
|
||||
f.read((char *) &ob->dwUnknown26, sizeof(ob->dwUnknown26));
|
||||
f.read((char *) &ob->dwUnknown27, sizeof(ob->dwUnknown27));
|
||||
f.read((char *) &ob->dwUnknown28, sizeof(ob->dwUnknown28));
|
||||
|
||||
f.read((char *) &ob->dwID, sizeof(ob->dwID));
|
||||
|
||||
f.read((char *) &ob->dwUnknown29, sizeof(ob->dwUnknown29));
|
||||
f.read((char *) &ob->dwUnknown30, sizeof(ob->dwUnknown30));
|
||||
|
||||
if (ob->wType == MxOb::WAV) {
|
||||
f.read((char *) &ob->dwUnknown31, sizeof(ob->dwUnknown31));
|
||||
}
|
||||
}
|
||||
break;
|
||||
case MxOb::TYPE_COUNT:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
bool Chunk::Read(std::ifstream &f, u32 &version, u32 &alignment)
|
||||
{
|
||||
u32 size;
|
||||
|
||||
offset_ = f.tellg();
|
||||
offset_ = u32(f.tellg());
|
||||
|
||||
// Read ID and size, which every chunk starts with
|
||||
f.read((char *) &id_, sizeof(id_));
|
||||
f.read((char *) &size, sizeof(size));
|
||||
|
||||
// Store end of this chunk
|
||||
u32 pos = f.tellg();
|
||||
u32 pos = u32(f.tellg());
|
||||
u32 end = pos + size;
|
||||
|
||||
// Read custom data from this chunk
|
||||
|
@ -168,54 +56,32 @@ bool Chunk::Read(std::ifstream &f, u32 &version, u32 &alignment)
|
|||
|
||||
switch (type()) {
|
||||
case TYPE_RIFF:
|
||||
CreateAndReadData<RIFF>(f, data_, size);
|
||||
break;
|
||||
case TYPE_LIST:
|
||||
data_.resize(sizeof(LIST));
|
||||
Read_List(f, data_.cast<LIST>());
|
||||
break;
|
||||
case TYPE_MxSt:
|
||||
// MxSt is 0 bytes in size, and an empty struct in C++ is one byte which throws things off,
|
||||
// so we just create nothing here
|
||||
size = 0;
|
||||
RIFF().Read(f, data_, version, size);
|
||||
break;
|
||||
case TYPE_MxHd:
|
||||
{
|
||||
CreateAndReadData<MxHd>(f, data_, size);
|
||||
|
||||
MxHd *mxhd = data_.cast<MxHd>();
|
||||
alignment = mxhd->dwBufferSize;
|
||||
version = mxhd->dwVersion;
|
||||
MxHd().Read(f, data_, version, size);
|
||||
version = data_["Version"];
|
||||
alignment = data_["BufferSize"];
|
||||
break;
|
||||
case TYPE_LIST:
|
||||
LIST().Read(f, data_, version, size);
|
||||
break;
|
||||
case TYPE_MxSt:
|
||||
MxSt().Read(f, data_, version, size);
|
||||
break;
|
||||
}
|
||||
case TYPE_MxCh:
|
||||
CreateAndReadData<MxCh>(f, data_, size);
|
||||
exdata_.resize(size - sizeof(MxCh));
|
||||
MxCh().Read(f, data_, version, size);
|
||||
break;
|
||||
case TYPE_MxOf:
|
||||
CreateAndReadData<MxOf>(f, data_, size);
|
||||
exdata_.resize(size - sizeof(MxOf));
|
||||
MxOf().Read(f, data_, version, size);
|
||||
break;
|
||||
case TYPE_pad_:
|
||||
pad_().Read(f, data_, version, size);
|
||||
break;
|
||||
case TYPE_MxOb:
|
||||
{
|
||||
data_.resize(sizeof(MxOb));
|
||||
Read_MxOb(f, this, data_.cast<MxOb>());
|
||||
MxOb().Read(f, data_, version, size);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Handle unknown data
|
||||
if (data_.empty() && size > 0) {
|
||||
data_.resize(size);
|
||||
f.read((char*)data_.data(), size);
|
||||
}
|
||||
|
||||
// Handle extended data
|
||||
if (!exdata_.empty()) {
|
||||
f.read((char*) exdata_.data(), exdata_.size());
|
||||
}
|
||||
|
||||
// Assume any remaining data is this chunk's children
|
||||
while (f.good() && (size_t(f.tellg()) + 4) < end) {
|
||||
|
@ -248,9 +114,6 @@ void Chunk::Clear()
|
|||
// Delete data
|
||||
data_.clear();
|
||||
|
||||
// Delete exdata
|
||||
exdata_.clear();
|
||||
|
||||
// Delete children
|
||||
for (Children::iterator it = children_.begin(); it != children_.end(); it++) {
|
||||
delete (*it);
|
||||
|
|
49
lib/chunk.h
49
lib/chunk.h
|
@ -2,9 +2,10 @@
|
|||
#define CHUNK_H
|
||||
|
||||
#include <fstream>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
|
||||
#include "bytearray.h"
|
||||
#include "common.h"
|
||||
#include "types.h"
|
||||
|
||||
namespace si {
|
||||
|
@ -24,33 +25,34 @@ public:
|
|||
TYPE_pad_ = 0x20646170
|
||||
};
|
||||
|
||||
Chunk();
|
||||
virtual ~Chunk();
|
||||
LIBWEAVER_EXPORT Chunk();
|
||||
virtual LIBWEAVER_EXPORT ~Chunk();
|
||||
|
||||
bool Read(const std::string &f);
|
||||
bool Read(const char *f);
|
||||
void Clear();
|
||||
LIBWEAVER_EXPORT bool Read(const std::string &f);
|
||||
LIBWEAVER_EXPORT bool Read(const char *f);
|
||||
LIBWEAVER_EXPORT void Clear();
|
||||
|
||||
typedef std::vector<Chunk*> Children;
|
||||
|
||||
Chunk *GetParent() const { return parent_; }
|
||||
const Children &GetChildren() const { return children_; }
|
||||
void AppendChild(Chunk *chunk);
|
||||
bool RemoveChild(Chunk *chunk);
|
||||
size_t IndexOfChild(Chunk *chunk);
|
||||
void InsertChild(size_t index, Chunk *chunk);
|
||||
Chunk *RemoveChild(size_t index);
|
||||
Chunk *GetChildAt(size_t index) const { return children_.at(index); }
|
||||
size_t GetChildCount() const { return children_.size(); }
|
||||
LIBWEAVER_EXPORT Chunk *GetParent() const { return parent_; }
|
||||
LIBWEAVER_EXPORT const Children &GetChildren() const { return children_; }
|
||||
LIBWEAVER_EXPORT void AppendChild(Chunk *chunk);
|
||||
LIBWEAVER_EXPORT bool RemoveChild(Chunk *chunk);
|
||||
LIBWEAVER_EXPORT size_t IndexOfChild(Chunk *chunk);
|
||||
LIBWEAVER_EXPORT void InsertChild(size_t index, Chunk *chunk);
|
||||
LIBWEAVER_EXPORT Chunk *RemoveChild(size_t index);
|
||||
LIBWEAVER_EXPORT Chunk *GetChildAt(size_t index) const { return children_.at(index); }
|
||||
LIBWEAVER_EXPORT size_t GetChildCount() const { return children_.size(); }
|
||||
|
||||
Type type() const { return static_cast<Type>(id_); }
|
||||
const u32 &id() const { return id_; }
|
||||
const u32 &offset() const { return offset_; }
|
||||
bytearray &data() { return data_; }
|
||||
bytearray &exdata() { return exdata_; }
|
||||
LIBWEAVER_EXPORT Type type() const { return static_cast<Type>(id_); }
|
||||
LIBWEAVER_EXPORT const u32 &id() const { return id_; }
|
||||
LIBWEAVER_EXPORT const u32 &offset() const { return offset_; }
|
||||
|
||||
static const char *GetTypeDescription(Type type);
|
||||
const char *GetTypeDescription() const
|
||||
LIBWEAVER_EXPORT Data &data(const std::string &key) { return data_[key]; }
|
||||
LIBWEAVER_EXPORT const Data &data(const std::string &key) const { return data_.at(key); }
|
||||
|
||||
LIBWEAVER_EXPORT static const char *GetTypeDescription(Type type);
|
||||
LIBWEAVER_EXPORT const char *GetTypeDescription() const
|
||||
{
|
||||
return GetTypeDescription(type());
|
||||
}
|
||||
|
@ -64,8 +66,7 @@ private:
|
|||
|
||||
u32 id_;
|
||||
u32 offset_;
|
||||
bytearray data_;
|
||||
bytearray exdata_;
|
||||
std::map<std::string, Data> data_;
|
||||
|
||||
Chunk *parent_;
|
||||
Children children_;
|
||||
|
|
|
@ -1,19 +0,0 @@
|
|||
#ifndef MXCH_H
|
||||
#define MXCH_H
|
||||
|
||||
#include "common.h"
|
||||
#include "types.h"
|
||||
|
||||
namespace si {
|
||||
|
||||
LIBWEAVER_PACK(struct MxCh
|
||||
{
|
||||
u16 wFlags;
|
||||
u32 dwObjectParent;
|
||||
u32 dwMillisecondOffset;
|
||||
u32 dwDataSize;
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
#endif // MXCH_H
|
|
@ -1,54 +0,0 @@
|
|||
#ifndef MXHDDATA_H
|
||||
#define MXHDDATA_H
|
||||
|
||||
#include "types.h"
|
||||
|
||||
namespace si {
|
||||
|
||||
/**
|
||||
* @brief The main header section of an Interleaf file.
|
||||
*
|
||||
* MxHd is generally the first section to appear in an Interleaf file. It contains information
|
||||
* about the file as a whole, including version information and settings for how the file should
|
||||
* be streamed.
|
||||
*/
|
||||
struct MxHd
|
||||
{
|
||||
/**
|
||||
* @brief The version of this Interleaf file.
|
||||
*
|
||||
* This is stored as two 16-bit words inside a 32-bit dword - the high word being the major
|
||||
* version and the low word being the minor version.
|
||||
*
|
||||
* If the version is 0x00010000, as it is in Warhammer: Shadow of the Horned Rat and early builds
|
||||
* of LEGO Island, the resulting version is 1.0. If the version is 0x00020002, as it is in the
|
||||
* retail release of LEGO Island, the resulting version number is 2.2.
|
||||
*/
|
||||
u32 dwVersion;
|
||||
|
||||
/**
|
||||
* @brief The amount of data to read from disk at a time
|
||||
*
|
||||
* MxStreamer will read data from the file in chunks of this size. This means all sections of the
|
||||
* file must be aligned around multiples of this number, i.e. a section starting before a multiple
|
||||
* of this number must either end before it if possible, or padding should be used to make it
|
||||
* start immediately on one. If dwBufferSize is 0x20000, sections must not cross 0x20000, 0x40000,
|
||||
* 0x60000, 0x80000, etc. If a section does, it will cause an out of bounds read as the game
|
||||
* tries to read past the buffer that it's allocated and read into.
|
||||
*/
|
||||
u32 dwBufferSize;
|
||||
|
||||
/**
|
||||
* @brief Buffer number
|
||||
*
|
||||
* It is currently not known exactly what this value does. Source .SS files leaked on the Korean
|
||||
* ISO call it "buffersNum", implying it's the number of buffers to read at a time (in tandem with
|
||||
* dwBufferSize), however that behavior has not been tested yet. This field also does not exist
|
||||
* on version 1.0 SI files.
|
||||
*/
|
||||
u32 dwBufferCount;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // MXHDDATA_H
|
|
@ -1,27 +0,0 @@
|
|||
#include "mxob.h"
|
||||
|
||||
const char *si::MxOb::GetTypeName(Type type)
|
||||
{
|
||||
switch (type) {
|
||||
case SMK:
|
||||
return "SMK";
|
||||
case WAV:
|
||||
return "WAV";
|
||||
case Presenter:
|
||||
return "MxPresenter";
|
||||
case BMP:
|
||||
return "BMP";
|
||||
case OBJ:
|
||||
return "3D Object";
|
||||
case World:
|
||||
return "World";
|
||||
case Event:
|
||||
return "Event";
|
||||
case Animation:
|
||||
return "Animation";
|
||||
case TYPE_COUNT:
|
||||
break;
|
||||
}
|
||||
|
||||
return "Unknown";
|
||||
}
|
176
lib/data/mxob.h
176
lib/data/mxob.h
|
@ -1,176 +0,0 @@
|
|||
#ifndef MXOB_H
|
||||
#define MXOB_H
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "common.h"
|
||||
#include "types.h"
|
||||
|
||||
namespace si {
|
||||
|
||||
class MxOb
|
||||
{
|
||||
public:
|
||||
enum Type
|
||||
{
|
||||
/// Smacker video
|
||||
SMK = 0x03,
|
||||
|
||||
/// WAVE audio
|
||||
WAV = 0x04,
|
||||
|
||||
/// World object for LegoWorldPresenter
|
||||
World = 0x06,
|
||||
|
||||
/// Custom MxPresenter
|
||||
Presenter = 0x07,
|
||||
|
||||
/// Event
|
||||
Event = 0x08,
|
||||
|
||||
/// Animation
|
||||
Animation = 0x09,
|
||||
|
||||
/// Bitmap image
|
||||
BMP = 0x0A,
|
||||
|
||||
/// 3D Object
|
||||
OBJ = 0x0B,
|
||||
|
||||
/// Total number of types (not a real type)
|
||||
TYPE_COUNT
|
||||
};
|
||||
|
||||
static const char *GetTypeName(Type type);
|
||||
|
||||
/**
|
||||
* @brief Member of MxObType enum identifying the type of object
|
||||
*/
|
||||
u16 wType;
|
||||
|
||||
/**
|
||||
* @brief The presenter to use (if applicable)
|
||||
*
|
||||
* If wType is set to MxOb_Presenter, this will be a string identifying which presenter to use.
|
||||
*/
|
||||
char szPresenter[128];
|
||||
|
||||
/// Currently unknown value
|
||||
u32 dwUnknown1;
|
||||
|
||||
/**
|
||||
* @brief Name of this object
|
||||
*/
|
||||
char szName[128];
|
||||
|
||||
/// Currently unknown value
|
||||
u32 dwObjectID;
|
||||
|
||||
/// Currently unknown value
|
||||
u32 dwUnknown3;
|
||||
|
||||
/// Currently unknown value
|
||||
u32 dwUnknown4;
|
||||
|
||||
/// Currently unknown value
|
||||
u32 dwUnknown5;
|
||||
|
||||
/// Currently unknown value
|
||||
u32 dwUnknown6;
|
||||
|
||||
/// Currently unknown value
|
||||
u32 dwUnknown7;
|
||||
|
||||
/// Currently unknown value
|
||||
u32 dwUnknown8;
|
||||
|
||||
/// Currently unknown value
|
||||
u32 dwUnknown9;
|
||||
|
||||
/// Currently unknown value
|
||||
u32 dwUnknown10;
|
||||
|
||||
/// Currently unknown value
|
||||
u32 dwUnknown11;
|
||||
|
||||
/// Currently unknown value
|
||||
u32 dwUnknown12;
|
||||
|
||||
/// Currently unknown value
|
||||
u32 dwUnknown13;
|
||||
|
||||
/// Currently unknown value
|
||||
u32 dwUnknown14;
|
||||
|
||||
/// Currently unknown value
|
||||
u32 dwUnknown15;
|
||||
|
||||
/// Currently unknown value
|
||||
u32 dwUnknown16;
|
||||
|
||||
/// Currently unknown value
|
||||
u32 dwUnknown17;
|
||||
|
||||
/// Currently unknown value
|
||||
f32 fUnknown18;
|
||||
|
||||
/// Currently unknown value
|
||||
u32 dwUnknown19;
|
||||
|
||||
/// Currently unknown value
|
||||
u32 dwUnknown20;
|
||||
|
||||
/// Currently unknown value
|
||||
u32 dwUnknown21;
|
||||
|
||||
/// Currently unknown value
|
||||
f32 fUnknown22;
|
||||
|
||||
/// Currently unknown value
|
||||
u32 dwUnknown23;
|
||||
|
||||
/// Currently unknown value
|
||||
u32 dwUnknown24;
|
||||
|
||||
/**
|
||||
* @brief Length of the szCreationString string
|
||||
*
|
||||
* If this is zero, szCreationString takes up no space in the file.
|
||||
*/
|
||||
u16 wCreationStringLength;
|
||||
|
||||
char szCreationString[128];
|
||||
|
||||
/**
|
||||
* @brief Original source filename
|
||||
*/
|
||||
char szFilename[128];
|
||||
|
||||
/// Currently unknown value
|
||||
u32 dwUnknown26;
|
||||
|
||||
/// Currently unknown value
|
||||
u32 dwUnknown27;
|
||||
|
||||
/// Currently unknown value
|
||||
u32 dwUnknown28;
|
||||
|
||||
/**
|
||||
* @brief 4-byte identifier for the file type
|
||||
*/
|
||||
u32 dwID;
|
||||
|
||||
/// Currently unknown value
|
||||
u32 dwUnknown29;
|
||||
|
||||
/// Currently unknown value
|
||||
u32 dwUnknown30;
|
||||
|
||||
/// Currently unknown value
|
||||
u32 dwUnknown31;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // MXOB_H
|
|
@ -1,16 +0,0 @@
|
|||
#ifndef MXOF_H
|
||||
#define MXOF_H
|
||||
|
||||
#include "common.h"
|
||||
#include "types.h"
|
||||
|
||||
namespace si {
|
||||
|
||||
struct MxOf
|
||||
{
|
||||
u32 dwObjectCount;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // MXOF_H
|
|
@ -1,20 +0,0 @@
|
|||
#ifndef MXSTDATA_H
|
||||
#define MXSTDATA_H
|
||||
|
||||
#include "types.h"
|
||||
|
||||
namespace si {
|
||||
|
||||
/**
|
||||
* @brief Stream
|
||||
*
|
||||
* Appears to encapsulate any streamable object in an Interleaf file.
|
||||
*/
|
||||
struct MxSt
|
||||
{
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // MXSTDATA_H
|
|
@ -1,21 +0,0 @@
|
|||
#ifndef RIFF_H
|
||||
#define RIFF_H
|
||||
|
||||
#include "types.h"
|
||||
|
||||
namespace si {
|
||||
|
||||
struct RIFF
|
||||
{
|
||||
u32 dwID;
|
||||
};
|
||||
|
||||
struct LIST
|
||||
{
|
||||
u32 dwID;
|
||||
u32 dwCount;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // RIFFDATA_H
|
176
lib/sitypes.cpp
Normal file
176
lib/sitypes.cpp
Normal file
|
@ -0,0 +1,176 @@
|
|||
#include "sitypes.h"
|
||||
|
||||
#include "chunk.h"
|
||||
|
||||
namespace si {
|
||||
|
||||
Data ReadU32(std::ifstream &is)
|
||||
{
|
||||
u32 u;
|
||||
is.read((char *) &u, sizeof(u));
|
||||
return u;
|
||||
}
|
||||
|
||||
Data ReadU16(std::ifstream &is)
|
||||
{
|
||||
u16 u;
|
||||
is.read((char *) &u, sizeof(u));
|
||||
return u;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
Data ReadBytes(std::ifstream &is, size_t size)
|
||||
{
|
||||
bytearray d;
|
||||
|
||||
d.resize(size);
|
||||
is.read(d.data(), size);
|
||||
|
||||
return d;
|
||||
}
|
||||
|
||||
void RIFF::Read(std::ifstream &is, DataMap &data, u32 version, u32 size)
|
||||
{
|
||||
data["Format"] = ReadU32(is);
|
||||
}
|
||||
|
||||
void LIST::Read(std::ifstream &is, DataMap &data, u32 version, u32 size)
|
||||
{
|
||||
data["Format"] = ReadU32(is);
|
||||
|
||||
if (data["Format"] == Chunk::TYPE_MxCh) {
|
||||
data["Count"] = ReadU32(is);
|
||||
}
|
||||
}
|
||||
|
||||
void MxSt::Read(std::ifstream &is, DataMap &data, u32 version, u32 size)
|
||||
{
|
||||
// MxSt is a container type only and has no members, so nothing needs to be done here
|
||||
}
|
||||
|
||||
void MxHd::Read(std::ifstream &is, DataMap &data, u32 version, u32 size)
|
||||
{
|
||||
Data v = ReadU32(is);
|
||||
data["Version"] = v;
|
||||
data["BufferSize"] = ReadU32(is);
|
||||
data["BufferCount"] = ReadU32(is);
|
||||
}
|
||||
|
||||
void MxCh::Read(std::ifstream &is, DataMap &data, u32 version, u32 size)
|
||||
{
|
||||
data["Flags"] = ReadU16(is);
|
||||
data["Object"] = ReadU32(is);
|
||||
data["Time"] = ReadU32(is);
|
||||
data["DataSize"] = ReadU32(is);
|
||||
data["Data"] = ReadBytes(is, size - 0xE);
|
||||
}
|
||||
|
||||
void MxOf::Read(std::ifstream &is, DataMap &data, u32 version, u32 size)
|
||||
{
|
||||
data["Count"] = ReadU32(is);
|
||||
data["Offsets"] = ReadBytes(is, size - sizeof(u32));
|
||||
}
|
||||
|
||||
void pad_::Read(std::ifstream &is, DataMap &data, u32 version, u32 size)
|
||||
{
|
||||
is.seekg(size, std::ios::cur);
|
||||
}
|
||||
|
||||
const char *MxOb::GetTypeName(Type type)
|
||||
{
|
||||
switch (type) {
|
||||
case SMK:
|
||||
return "SMK";
|
||||
case WAV:
|
||||
return "WAV";
|
||||
case Presenter:
|
||||
return "MxPresenter";
|
||||
case BMP:
|
||||
return "BMP";
|
||||
case OBJ:
|
||||
return "3D Object";
|
||||
case World:
|
||||
return "World";
|
||||
case Event:
|
||||
return "Event";
|
||||
case Animation:
|
||||
return "Animation";
|
||||
case TYPE_COUNT:
|
||||
break;
|
||||
}
|
||||
|
||||
return "Unknown";
|
||||
}
|
||||
|
||||
void MxOb::Read(std::ifstream &is, DataMap &data, u32 version, u32 size)
|
||||
{
|
||||
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);
|
||||
data["Unknown3"] = ReadU32(is);
|
||||
data["Unknown4"] = ReadU32(is);
|
||||
data["Unknown5"] = ReadU32(is);
|
||||
data["Unknown6"] = ReadU32(is);
|
||||
data["Unknown7"] = ReadU32(is);
|
||||
data["Unknown8"] = ReadU32(is);
|
||||
data["Unknown9"] = ReadU32(is);
|
||||
data["Unknown10"] = ReadU32(is);
|
||||
data["Unknown11"] = ReadU32(is);
|
||||
data["Unknown12"] = ReadU32(is);
|
||||
data["Unknown13"] = ReadU32(is);
|
||||
data["Unknown14"] = ReadU32(is);
|
||||
data["Unknown15"] = ReadU32(is);
|
||||
data["Unknown16"] = ReadU32(is);
|
||||
data["Unknown17"] = ReadU32(is);
|
||||
data["Unknown18"] = ReadU32(is);
|
||||
data["Unknown19"] = ReadU32(is);
|
||||
data["Unknown20"] = ReadU32(is);
|
||||
data["Unknown21"] = ReadU32(is);
|
||||
data["Unknown22"] = ReadU32(is);
|
||||
data["Unknown23"] = ReadU32(is);
|
||||
data["Unknown24"] = ReadU32(is);
|
||||
|
||||
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);
|
||||
|
||||
if (obj_type == MxOb::WAV) {
|
||||
data["Unknown31"] = ReadU32(is);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
194
lib/sitypes.h
Normal file
194
lib/sitypes.h
Normal file
|
@ -0,0 +1,194 @@
|
|||
#ifndef SI_H
|
||||
#define SI_H
|
||||
|
||||
#include <fstream>
|
||||
|
||||
#include "chunk.h"
|
||||
#include "types.h"
|
||||
|
||||
namespace si {
|
||||
|
||||
/**
|
||||
* @brief RIFF chunk type
|
||||
*
|
||||
* Name | Size | Type | Description
|
||||
* -------- | -------- | -------- | -----------
|
||||
* Format | 4 | u32 | 4-byte ASCII identifier for what type of RIFF this is (usually 'OMNI' in the case of LEGO Island)
|
||||
*/
|
||||
class RIFF
|
||||
{
|
||||
public:
|
||||
virtual ~RIFF(){}
|
||||
|
||||
virtual void Read(std::ifstream &is, DataMap &data, u32 version, u32 size);
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief LIST chunk type
|
||||
*
|
||||
* Name | Size | Type | Description
|
||||
* -------- | -------- | -------- | -----------
|
||||
* Format | 4 | u32 | 4-byte ASCII identifier for what type of LIST this is.
|
||||
* Count | 4 | u32 | (Optional) for 'MxCh' type LISTs, the number of elements in this list.
|
||||
*/
|
||||
class LIST : public RIFF
|
||||
{
|
||||
public:
|
||||
virtual void Read(std::ifstream &is, DataMap &data, u32 version, u32 size);
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief MxHd chunk type
|
||||
*
|
||||
* Name | Size | Type | Description
|
||||
* ----------- | -------- | -------- | -----------
|
||||
* Version | 4 | u32 | Version of this SI file stored as two packed 16-bit words, the high word being the major version and the low word being the minor version.
|
||||
* BufferSize | 4 | u32 | The amount of data to read from disk at a time.
|
||||
* BufferCount | 4 | u32 | FIXME: Currently not understood what this field does.
|
||||
*/
|
||||
class MxHd : public RIFF
|
||||
{
|
||||
public:
|
||||
virtual void Read(std::ifstream &is, DataMap &data, u32 version, u32 size);
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief MxSt chunk type
|
||||
*
|
||||
* MxSt is a container type only, it has none of its own members.
|
||||
*/
|
||||
class MxSt : public RIFF
|
||||
{
|
||||
public:
|
||||
virtual void Read(std::ifstream &is, DataMap &data, u32 version, u32 size);
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief MxCh chunk type
|
||||
*
|
||||
* Name | Size | Type | Description
|
||||
* ---------- | -------- | --------- | -----------
|
||||
* Flags | 2 | u16 | Flags determining the behavior of this chunk.
|
||||
* Object | 4 | u32 | ID of the MxOb that this chunk belongs to.
|
||||
* Time | 4 | u32 | Time in milliseconds that this chunk's data should be presented at.
|
||||
* DataSize | 4 | u32 | Size of the data in this chunk.
|
||||
* Data | DataSize | bytearray | Actual data in chunk.
|
||||
*/
|
||||
class MxCh : public RIFF
|
||||
{
|
||||
public:
|
||||
virtual void Read(std::ifstream &is, DataMap &data, u32 version, u32 size);
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief MxOf chunk type
|
||||
*
|
||||
* Name | Size | Type | Description
|
||||
* ---------- | -------- | ---------------- | -----------
|
||||
* Count | 4 | u32 | Number of objects in this list. Not necessarily the number of offsets, as one offset may point to an object with multiple sub-objects.
|
||||
* Offsets | Count*4 | bytearray/u32[] | List of 4-byte file offsets where objects begin.
|
||||
*/
|
||||
class MxOf : public RIFF
|
||||
{
|
||||
public:
|
||||
virtual void Read(std::ifstream &is, DataMap &data, u32 version, u32 size);
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief pad_ chunk type
|
||||
*
|
||||
* Denotes padding to optimize disc reads. Contains no useful information,
|
||||
* customarily filled with the byte 0xCD.
|
||||
*/
|
||||
class pad_ : public RIFF
|
||||
{
|
||||
public:
|
||||
virtual void Read(std::ifstream &is, DataMap &data, u32 version, u32 size);
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief MxOb chunk type
|
||||
*
|
||||
* Name | Size | Type | Description
|
||||
* ----------- | -------- | ---------------- | -----------
|
||||
* Type | 2 | u16 | Type of object (member of MxOb::Type enum)
|
||||
* Presenter | Variable | string | Null-terminated string identifying the presenter to use (if type is set to `Presenter`)
|
||||
* Unknown1 | 4 | u32 |
|
||||
* Name | Variable | string | Null-terminated string identifying object's name
|
||||
* ID | 4 | u32 | Unique object identifier within file (used to differentiate interleaved MxChs)
|
||||
* Unknown3 | 4 | u32 |
|
||||
* Unknown4 | 4 | u32 |
|
||||
* Unknown5 | 4 | u32 |
|
||||
* Unknown6 | 4 | u32 |
|
||||
* Unknown7 | 4 | u32 |
|
||||
* Unknown8 | 4 | u32 |
|
||||
* Unknown9 | 4 | u32 |
|
||||
* Unknown10 | 4 | u32 |
|
||||
* Unknown11 | 4 | u32 |
|
||||
* Unknown12 | 4 | u32 |
|
||||
* Unknown13 | 4 | u32 |
|
||||
* Unknown14 | 4 | u32 |
|
||||
* Unknown15 | 4 | u32 |
|
||||
* Unknown16 | 4 | u32 |
|
||||
* Unknown17 | 4 | u32 |
|
||||
* Unknown18 | 4 | u32 |
|
||||
* Unknown19 | 4 | u32 |
|
||||
* Unknown20 | 4 | u32 |
|
||||
* Unknown21 | 4 | u32 |
|
||||
* Unknown22 | 4 | u32 |
|
||||
* Unknown23 | 4 | u32 |
|
||||
* Unknown24 | 4 | u32 |
|
||||
* ExtraLength | 2 | u16 |
|
||||
* ExtraData | ExtraLength | bytearray |
|
||||
* FileName | Variable | string | Original filename of the file represented by this object.
|
||||
* Unknown26 | 4 | u32 |
|
||||
* Unknown27 | 4 | u32 |
|
||||
* Unknown28 | 4 | u32 |
|
||||
* FileType | 4 | u32 | 4-byte ASCII ID for the file type
|
||||
* Unknown29 | 4 | u32 |
|
||||
* Unknown30 | 4 | u32 |
|
||||
* Unknown31 | 4 | u32 | (Optional) only populated for WAV files
|
||||
*/
|
||||
class MxOb : public RIFF
|
||||
{
|
||||
public:
|
||||
enum Type
|
||||
{
|
||||
/// Smacker video
|
||||
SMK = 0x03,
|
||||
|
||||
/// WAVE audio
|
||||
WAV = 0x04,
|
||||
|
||||
/// World object for LegoWorldPresenter
|
||||
World = 0x06,
|
||||
|
||||
/// Custom MxPresenter
|
||||
Presenter = 0x07,
|
||||
|
||||
/// Event
|
||||
Event = 0x08,
|
||||
|
||||
/// Animation
|
||||
Animation = 0x09,
|
||||
|
||||
/// Bitmap image
|
||||
BMP = 0x0A,
|
||||
|
||||
/// 3D Object
|
||||
OBJ = 0x0B,
|
||||
|
||||
/// Total number of types (not a real type)
|
||||
TYPE_COUNT
|
||||
};
|
||||
|
||||
// FIXME: sitypes.h probably won't be part of the public API, so this should
|
||||
// probably be moved
|
||||
LIBWEAVER_EXPORT static const char *GetTypeName(Type type);
|
||||
|
||||
virtual void Read(std::ifstream &is, DataMap &data, u32 version, u32 size);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // SI_H
|
96
lib/types.h
96
lib/types.h
|
@ -1,6 +1,8 @@
|
|||
#ifndef TYPES_H
|
||||
#define TYPES_H
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace si {
|
||||
|
@ -14,6 +16,100 @@ typedef int s32;
|
|||
typedef float f32;
|
||||
typedef double f64;
|
||||
|
||||
class bytearray : public std::vector<s8>
|
||||
{
|
||||
public:
|
||||
bytearray() = default;
|
||||
|
||||
template <typename T>
|
||||
T *cast() { return reinterpret_cast<T*>(data()); }
|
||||
|
||||
template <typename T>
|
||||
const T *cast() const { return reinterpret_cast<const T*>(data()); }
|
||||
|
||||
};
|
||||
|
||||
class Data
|
||||
{
|
||||
public:
|
||||
inline Data()
|
||||
{
|
||||
data_.resize(sizeof(si::u32));
|
||||
//memset(data_.data(), 0, data_.size());
|
||||
}
|
||||
|
||||
inline Data(const u32 &u) { set(u); }
|
||||
inline Data(const bytearray &u) { set(u); }
|
||||
inline Data(const std::string &u)
|
||||
{
|
||||
data_.resize(u.size());
|
||||
memcpy(data_.data(), u.data(), u.size());
|
||||
}
|
||||
|
||||
inline operator u32() const
|
||||
{
|
||||
return toU32();
|
||||
}
|
||||
|
||||
inline operator const char *() const
|
||||
{
|
||||
return data();
|
||||
}
|
||||
|
||||
inline u16 toU16() const { return *data_.cast<si::u16>(); }
|
||||
inline s16 toS16() const { return *data_.cast<si::s16>(); }
|
||||
inline u32 toU32() const { return *data_.cast<si::u32>(); }
|
||||
inline s32 toS32() const { return *data_.cast<si::s32>(); }
|
||||
inline const char *data() const { return data_.data(); };
|
||||
inline char *data() { return data_.data(); };
|
||||
inline const char *c_str() const { return this->data(); };
|
||||
inline size_t size() const { return data_.size(); }
|
||||
inline const std::string toString() const
|
||||
{
|
||||
// Subtract 1 from size, assuming the last character is a null terminator
|
||||
return std::string(data_.data(), std::max(size_t(0), data_.size()-1));
|
||||
}
|
||||
|
||||
inline bool operator==(int u) const
|
||||
{
|
||||
return get<int>() == u;
|
||||
}
|
||||
|
||||
inline bool operator==(si::u32 u) const
|
||||
{
|
||||
return get<si::u32>() == u;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline const T &get() const
|
||||
{
|
||||
return *data_.cast<T>();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline void set(const T &value)
|
||||
{
|
||||
data_.resize(sizeof(T));
|
||||
memcpy(data_.data(), &value, sizeof(T));
|
||||
}
|
||||
|
||||
inline void set(const bytearray &value) { data_ = value; }
|
||||
|
||||
private:
|
||||
bytearray data_;
|
||||
|
||||
};
|
||||
|
||||
class Vector3
|
||||
{
|
||||
public:
|
||||
f32 x;
|
||||
f32 y;
|
||||
f32 z;
|
||||
};
|
||||
|
||||
using DataMap = std::map<std::string, Data>;
|
||||
|
||||
}
|
||||
|
||||
#endif // TYPES_H
|
||||
|
|
Loading…
Reference in a new issue