mirror of
https://github.com/isledecomp/SIEdit.git
synced 2024-11-30 10:56:51 -05:00
lib: process data streams
This commit is contained in:
parent
09384dbe46
commit
4465f26c38
11 changed files with 207 additions and 79 deletions
|
@ -12,8 +12,6 @@ set(LIBWEAVER_SOURCES
|
|||
object.h
|
||||
sitypes.cpp
|
||||
sitypes.h
|
||||
stream.cpp
|
||||
stream.h
|
||||
types.h
|
||||
)
|
||||
|
||||
|
|
|
@ -27,6 +27,7 @@ public:
|
|||
LIBWEAVER_EXPORT Core *RemoveChild(size_t index);
|
||||
LIBWEAVER_EXPORT Core *GetChildAt(size_t index) const { return children_.at(index); }
|
||||
LIBWEAVER_EXPORT size_t GetChildCount() const { return children_.size(); }
|
||||
LIBWEAVER_EXPORT bool HasChildren() const { return !children_.empty(); }
|
||||
|
||||
protected:
|
||||
void DeleteChildren();
|
||||
|
|
|
@ -1,5 +1,9 @@
|
|||
#include "interleaf.h"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include "object.h"
|
||||
|
||||
namespace si {
|
||||
|
||||
Interleaf::Interleaf()
|
||||
|
@ -31,16 +35,66 @@ bool Interleaf::Parse(Chunk *riff)
|
|||
return false;
|
||||
}
|
||||
|
||||
const Data &offset_table = of->data("Offsets");
|
||||
size_t offset_count = offset_table.size() / sizeof(uint32_t);
|
||||
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);
|
||||
DeleteChildren();
|
||||
for (size_t i=0; i<offset_count; i++) {
|
||||
Stream *o = new Stream();
|
||||
if (offset_table[i]) {
|
||||
Chunk *st = riff->FindChildWithOffset(offset_table[i]);
|
||||
if (!o->Parse(st)) {
|
||||
if (!ParseStream(st)) {
|
||||
return false;
|
||||
}
|
||||
AppendChild(o);
|
||||
} 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) {
|
||||
using ChunkMap = std::map<uint32_t, std::vector<bytearray> >;
|
||||
ChunkMap data;
|
||||
|
||||
for (Core *chunk : list->GetChildren()) {
|
||||
Chunk *mxch = static_cast<Chunk*>(chunk);
|
||||
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) {
|
||||
o->ProcessData(it->second);
|
||||
} else {
|
||||
std::cout << "Failed to find object with ID " << it->first << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
|
||||
#include "chunk.h"
|
||||
#include "core.h"
|
||||
#include "stream.h"
|
||||
|
||||
namespace si {
|
||||
|
||||
|
@ -15,6 +14,8 @@ public:
|
|||
LIBWEAVER_EXPORT bool Parse(Chunk *riff);
|
||||
|
||||
private:
|
||||
bool ParseStream(Chunk *chunk);
|
||||
|
||||
uint32_t version_;
|
||||
uint32_t buffer_size_;
|
||||
uint32_t buffer_count_;
|
||||
|
|
|
@ -26,12 +26,93 @@ bool Object::Parse(Chunk *chunk)
|
|||
unknown26_ = chunk->data("Unknown26");
|
||||
unknown27_ = chunk->data("Unknown27");
|
||||
unknown28_ = chunk->data("Unknown28");
|
||||
filetype_ = chunk->data("FileType");
|
||||
filetype_ = static_cast<MxOb::FileType>(chunk->data("FileType").toU32());
|
||||
unknown29_ = chunk->data("Unknown29");
|
||||
unknown30_ = chunk->data("Unknown30");
|
||||
unknown31_ = chunk->data("Unknown31");
|
||||
|
||||
if (chunk->HasChildren()) {
|
||||
Chunk *child = static_cast<Chunk*>(chunk->GetChildAt(0));
|
||||
if (child->id() == Chunk::TYPE_LIST) {
|
||||
for (Core *entry : child->GetChildren()) {
|
||||
Object *o = new Object();
|
||||
if (!o->Parse(static_cast<Chunk*>(entry))) {
|
||||
return false;
|
||||
}
|
||||
AppendChild(o);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Object::ProcessData(const std::vector<bytearray> &chunks)
|
||||
{
|
||||
switch (filetype_) {
|
||||
case MxOb::WAV:
|
||||
{
|
||||
// Make space for WAVE header
|
||||
data_.resize(0x2C);
|
||||
|
||||
// Merge all chunks after the first one
|
||||
for (size_t i=1; i<chunks.size(); i++) {
|
||||
data_.append(chunks[i]);
|
||||
}
|
||||
|
||||
// Copy boilerplate bytes for header
|
||||
uint32_t *header = reinterpret_cast<uint32_t *>(data_.data());
|
||||
header[0] = Chunk::TYPE_RIFF; // "RIFF"
|
||||
header[1] = data_.size() - 8; // Size of total file
|
||||
header[2] = 0x45564157; // "WAVE"
|
||||
header[3] = 0x20746D66; // "fmt "
|
||||
header[4] = 16; // Size of fmt chunk
|
||||
header[9] = 0x61746164; // "data"
|
||||
header[10] = data_.size() - 0x2C; // Size of data chunk
|
||||
|
||||
// Copy fmt header from chunk 1
|
||||
memcpy(&header[5], chunks[0].data(), 16);
|
||||
break;
|
||||
}
|
||||
case MxOb::STL:
|
||||
{
|
||||
// Make space for BMP header
|
||||
data_.resize(14);
|
||||
|
||||
// Merge all chunks after the first one
|
||||
for (size_t i=0; i<chunks.size(); i++) {
|
||||
data_.append(chunks[i]);
|
||||
}
|
||||
|
||||
// Set BM identifier
|
||||
*(uint16_t *)(data_.data()) = 0x4D42;
|
||||
|
||||
// Set file size
|
||||
*(uint32_t*)(data_.data()+2) = data_.size();
|
||||
|
||||
// Set reserved bytes
|
||||
*(uint32_t*)(data_.data()+6) = 0;
|
||||
|
||||
// Set offset
|
||||
*(uint32_t*)(data_.data()+10) = chunks.at(0).size() + 14;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Object *Object::FindSubObjectWithID(uint32_t id)
|
||||
{
|
||||
if (this->id() == id) {
|
||||
return this;
|
||||
}
|
||||
|
||||
for (Core *child : GetChildren()) {
|
||||
if (Object *o = static_cast<Object*>(child)->FindSubObjectWithID(id)) {
|
||||
return o;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
14
lib/object.h
14
lib/object.h
|
@ -13,11 +13,15 @@ public:
|
|||
Object();
|
||||
|
||||
bool Parse(Chunk *chunk);
|
||||
void ProcessData(const std::vector<bytearray> &chunks);
|
||||
|
||||
bytearray &data()
|
||||
{
|
||||
return data_;
|
||||
}
|
||||
const MxOb::FileType &filetype() const { return filetype_; }
|
||||
const uint32_t &id() const { return id_; }
|
||||
const std::string &name() const { return name_; }
|
||||
const std::string &filename() const { return filename_; }
|
||||
bytearray &data() { return data_; }
|
||||
|
||||
Object *FindSubObjectWithID(uint32_t id);
|
||||
|
||||
private:
|
||||
MxOb::Type type_;
|
||||
|
@ -37,7 +41,7 @@ private:
|
|||
uint32_t unknown26_;
|
||||
uint32_t unknown27_;
|
||||
uint32_t unknown28_;
|
||||
uint32_t filetype_;
|
||||
MxOb::FileType filetype_;
|
||||
uint32_t unknown29_;
|
||||
uint32_t unknown30_;
|
||||
uint32_t unknown31_;
|
||||
|
|
|
@ -111,9 +111,9 @@ void pad_::Read(std::ifstream &is, DataMap &data, uint32_t version, uint32_t siz
|
|||
const char *MxOb::GetTypeName(Type type)
|
||||
{
|
||||
switch (type) {
|
||||
case SMK:
|
||||
case Video:
|
||||
return "SMK";
|
||||
case WAV:
|
||||
case Sound:
|
||||
return "WAV";
|
||||
case Presenter:
|
||||
return "MxPresenter";
|
||||
|
@ -193,7 +193,7 @@ void MxOb::Read(std::ifstream &is, DataMap &data, uint32_t version, uint32_t siz
|
|||
data["Unknown29"] = ReadU32(is);
|
||||
data["Unknown30"] = ReadU32(is);
|
||||
|
||||
if (obj_type == MxOb::WAV) {
|
||||
if (obj_type == MxOb::Sound) {
|
||||
data["Unknown31"] = ReadU32(is);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -139,11 +139,11 @@ class MxOb : public RIFF
|
|||
public:
|
||||
enum Type
|
||||
{
|
||||
/// Smacker video
|
||||
SMK = 0x03,
|
||||
/// Video
|
||||
Video = 0x03,
|
||||
|
||||
/// WAVE audio
|
||||
WAV = 0x04,
|
||||
/// Audio
|
||||
Sound = 0x04,
|
||||
|
||||
/// World object for LegoWorldPresenter
|
||||
World = 0x06,
|
||||
|
@ -185,7 +185,16 @@ public:
|
|||
Unknown = 0x20,
|
||||
|
||||
/// Total number of flags (not a real type)
|
||||
FLAGS_COUNT
|
||||
FLAGS_COUNT,
|
||||
};
|
||||
|
||||
enum FileType
|
||||
{
|
||||
/// WAVE audio
|
||||
WAV = 0x56415720,
|
||||
|
||||
/// Bitmap image
|
||||
STL = 0x4C545320,
|
||||
};
|
||||
|
||||
// FIXME: sitypes.h probably won't be part of the public API, so this should
|
||||
|
@ -196,6 +205,22 @@ public:
|
|||
virtual void Read(std::ifstream &is, DataMap &data, uint32_t version, uint32_t size);
|
||||
};
|
||||
|
||||
class WAVFormatHeader
|
||||
{
|
||||
public:
|
||||
// Standard WAV header
|
||||
uint16_t Format;
|
||||
uint16_t Channels;
|
||||
uint32_t SampleRate;
|
||||
uint32_t ByteRate;
|
||||
uint16_t BlockAlign;
|
||||
uint16_t BitsPerSample;
|
||||
|
||||
// Mx extensions (not confirmed yet)
|
||||
uint32_t DataSize;
|
||||
uint32_t Flags;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // SI_H
|
||||
|
|
|
@ -1,33 +0,0 @@
|
|||
#include "stream.h"
|
||||
|
||||
#include "object.h"
|
||||
|
||||
namespace si {
|
||||
|
||||
Stream::Stream()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
bool Stream::Parse(Chunk *chunk)
|
||||
{
|
||||
if (chunk->type() != Chunk::TYPE_MxSt) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Chunk *obj_chunk = chunk->FindChildWithType(Chunk::TYPE_MxOb);
|
||||
if (!obj_chunk) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Object *obj = new Object();
|
||||
if (!obj->Parse(obj_chunk)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// FIXME: Read MxCh into Objects
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
22
lib/stream.h
22
lib/stream.h
|
@ -1,22 +0,0 @@
|
|||
#ifndef STREAM_H
|
||||
#define STREAM_H
|
||||
|
||||
#include "chunk.h"
|
||||
#include "core.h"
|
||||
|
||||
namespace si {
|
||||
|
||||
class Stream : public Core
|
||||
{
|
||||
public:
|
||||
Stream();
|
||||
|
||||
bool Parse(Chunk *chunk);
|
||||
|
||||
private:
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // STREAM_H
|
19
lib/types.h
19
lib/types.h
|
@ -32,6 +32,25 @@ public:
|
|||
template <typename T>
|
||||
const T *cast() const { return reinterpret_cast<const T*>(data()); }
|
||||
|
||||
void append(const char *data, size_t size)
|
||||
{
|
||||
size_t current = this->size();
|
||||
this->resize(current + size);
|
||||
memcpy(this->data() + current, data, size);
|
||||
}
|
||||
|
||||
void append(const bytearray &other)
|
||||
{
|
||||
size_t current = this->size();
|
||||
this->resize(current + other.size());
|
||||
memcpy(this->data() + current, other.data(), other.size());
|
||||
}
|
||||
|
||||
void fill(char c)
|
||||
{
|
||||
memset(this->data(), c, this->size());
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
class Vector3
|
||||
|
|
Loading…
Reference in a new issue