SIEdit/lib/interleaf.cpp

104 lines
2.2 KiB
C++
Raw Normal View History

2022-07-11 00:16:20 -04:00
#include "interleaf.h"
2022-07-11 04:48:20 -04:00
#include <iostream>
#include "object.h"
2022-07-11 00:16:20 -04:00
namespace si {
Interleaf::Interleaf()
{
}
bool Interleaf::Parse(Chunk *riff)
{
if (riff->id() != Chunk::TYPE_RIFF) {
return false;
}
Chunk *hd = riff->FindChildWithType(Chunk::TYPE_MxHd);
if (!hd) {
return false;
}
version_ = hd->data("Version");
if (version_ == 0) {
// Unknown version
return false;
}
buffer_size_ = hd->data("BufferSize");
buffer_count_ = hd->data("BufferCount");
Chunk *of = riff->FindChildWithType(Chunk::TYPE_MxOf);
if (!of) {
return false;
}
2022-07-11 04:48:20 -04:00
const Data &offset_data = of->data("Offsets");
const uint32_t *offset_table = reinterpret_cast<const uint32_t *>(offset_data.data());
size_t offset_count = offset_data.size() / sizeof(uint32_t);
2022-07-11 00:16:20 -04:00
DeleteChildren();
for (size_t i=0; i<offset_count; i++) {
2022-07-11 04:48:20 -04:00
if (offset_table[i]) {
Chunk *st = riff->FindChildWithOffset(offset_table[i]);
if (!ParseStream(st)) {
return false;
}
} else {
//Object *nullobj = new Object();
//AppendChild(nullobj);
}
}
return true;
}
bool Interleaf::ParseStream(Chunk *chunk)
{
if (chunk->type() != Chunk::TYPE_MxSt) {
return false;
}
Chunk *obj_chunk = static_cast<Chunk*>(chunk->GetChildAt(0));
if (!obj_chunk) {
return false;
}
Object *obj = new Object();
if (!obj->Parse(obj_chunk)) {
return false;
}
AppendChild(obj);
Chunk *list = static_cast<Chunk*>(chunk->GetChildAt(1));
if (list) {
2022-07-11 12:05:28 -04:00
typedef std::map<uint32_t, Object::ChunkedData> ChunkMap;
2022-07-11 04:48:20 -04:00
ChunkMap data;
2022-07-11 12:05:28 -04:00
for (Children::const_iterator it=list->GetChildren().begin(); it!=list->GetChildren().end(); it++) {
Chunk *mxch = static_cast<Chunk*>(*it);
2022-07-11 04:48:20 -04:00
if (mxch->id() == Chunk::TYPE_pad_) {
// Ignore this chunk
} else if (mxch->id() == Chunk::TYPE_MxCh) {
uint32_t obj_id = mxch->data("Object");
data[obj_id].push_back(mxch->data("Data"));
}
}
for (ChunkMap::const_iterator it=data.begin(); it!=data.end(); it++) {
Object *o = obj->FindSubObjectWithID(it->first);
if (o) {
2022-07-11 11:04:47 -04:00
o->SetChunkedData(it->second);
2022-07-11 04:48:20 -04:00
} else {
std::cout << "Failed to find object with ID " << it->first << std::endl;
}
2022-07-11 00:16:20 -04:00
}
}
return true;
}
}