SIEdit/lib/object.cpp

218 lines
4.8 KiB
C++
Raw Normal View History

2022-07-11 00:16:20 -04:00
#include "object.h"
2022-07-11 17:19:36 -04:00
#include <iostream>
2022-07-17 21:51:16 -04:00
#include "util.h"
2022-07-11 00:16:20 -04:00
namespace si {
Object::Object()
{
2022-07-11 17:19:36 -04:00
type_ = MxOb::Null;
id_ = 0;
2022-07-11 00:16:20 -04:00
}
2022-07-17 21:51:16 -04:00
/*bool Object::Read(std::ifstream &is)
2022-07-11 00:16:20 -04:00
{
2022-07-17 21:51:16 -04:00
2022-07-11 00:16:20 -04:00
2022-07-11 04:48:20 -04:00
if (chunk->HasChildren()) {
Chunk *child = static_cast<Chunk*>(chunk->GetChildAt(0));
if (child->id() == Chunk::TYPE_LIST) {
for (Children::const_iterator it=child->GetChildren().begin(); it!=child->GetChildren().end(); it++) {
2022-07-11 04:48:20 -04:00
Object *o = new Object();
if (!o->Parse(static_cast<Chunk*>(*it))) {
2022-07-11 04:48:20 -04:00
return false;
}
AppendChild(o);
}
}
}
2022-07-11 00:16:20 -04:00
return true;
}
2022-07-17 21:51:16 -04:00
void Object::Write(std::ofstream &os) const
2022-07-11 17:19:36 -04:00
{
2022-07-17 21:51:16 -04:00
WriteU16(os, type_);
WriteString(os, presenter_);
WriteU32(os, unknown1_);
WriteString(os, name_);
WriteU32(os, id_);
WriteU32(os, flags_);
WriteU32(os, unknown4_);
WriteU32(os, duration_);
WriteU32(os, loops_);
WriteVector3(os, position_);
WriteVector3(os, direction_);
WriteVector3(os, up_);
WriteU16(os, extra_.size());
WriteBytes(os, extra_);
WriteString(os, filename_);
WriteU32(os, unknown26_);
WriteU32(os, unknown27_);
WriteU32(os, unknown28_);
WriteU32(os, filetype_);
WriteU32(os, unknown29_);
WriteU32(os, unknown30_);
WriteU32(os, unknown31_);
2022-07-11 17:19:36 -04:00
if (HasChildren()) {
Chunk *list = new Chunk(Chunk::TYPE_LIST);
list->data("Format") = Chunk::TYPE_MxCh;
list->data("Count") = list->GetChildCount();
2022-07-11 17:19:36 -04:00
chunk->AppendChild(list);
for (Children::const_iterator it=GetChildren().begin(); it!=GetChildren().end(); it++) {
Object *child = static_cast<Object*>(*it);
list->AppendChild(child->Export());
}
}
return chunk;
2022-07-17 21:51:16 -04:00
}*/
2022-07-11 17:19:36 -04:00
2022-07-11 11:04:47 -04:00
bytearray Object::GetNormalizedData() const
2022-07-11 04:48:20 -04:00
{
2022-07-11 11:04:47 -04:00
return ToPackedData(filetype(), data_);
}
void Object::SetNormalizedData(const bytearray &d)
{
SetChunkedData(ToChunkedData(filetype(), d));
}
bytearray Object::ToPackedData(MxOb::FileType filetype, const ChunkedData &chunks)
{
bytearray data;
switch (filetype) {
2022-07-11 04:48:20 -04:00
case MxOb::WAV:
{
// Make space for WAVE header
2022-07-11 11:04:47 -04:00
data.resize(0x2C);
2022-07-11 04:48:20 -04:00
// Merge all chunks after the first one
for (size_t i=1; i<chunks.size(); i++) {
2022-07-11 11:04:47 -04:00
data.append(chunks[i]);
2022-07-11 04:48:20 -04:00
}
// Copy boilerplate bytes for header
2022-07-11 11:04:47 -04:00
uint32_t *header = reinterpret_cast<uint32_t *>(data.data());
2022-07-17 21:51:16 -04:00
header[0] = SI::RIFF; // "RIFF"
2022-07-11 11:04:47 -04:00
header[1] = data.size() - 8; // Size of total file
2022-07-11 04:48:20 -04:00
header[2] = 0x45564157; // "WAVE"
header[3] = 0x20746D66; // "fmt "
header[4] = 16; // Size of fmt chunk
header[9] = 0x61746164; // "data"
2022-07-11 11:04:47 -04:00
header[10] = data.size() - 0x2C; // Size of data chunk
2022-07-11 04:48:20 -04:00
// Copy fmt header from chunk 1
memcpy(&header[5], chunks[0].data(), 16);
break;
}
case MxOb::STL:
{
// Make space for BMP header
2022-07-11 11:04:47 -04:00
data.resize(14);
2022-07-11 04:48:20 -04:00
// Merge all chunks after the first one
for (size_t i=0; i<chunks.size(); i++) {
2022-07-11 11:04:47 -04:00
data.append(chunks[i]);
2022-07-11 04:48:20 -04:00
}
// Set BM identifier
2022-07-11 11:04:47 -04:00
*(uint16_t *)(data.data()) = 0x4D42;
2022-07-11 04:48:20 -04:00
// Set file size
2022-07-11 11:04:47 -04:00
*(uint32_t*)(data.data()+2) = data.size();
2022-07-11 04:48:20 -04:00
// Set reserved bytes
2022-07-11 11:04:47 -04:00
*(uint32_t*)(data.data()+6) = 0;
2022-07-11 04:48:20 -04:00
// Set offset
2022-07-11 11:04:47 -04:00
*(uint32_t*)(data.data()+10) = chunks.at(0).size() + 14;
2022-07-11 04:48:20 -04:00
break;
}
2022-07-11 17:20:56 -04:00
case MxOb::FLC:
{
// First chunk is a complete FLIC header, so add it as-is
data.append(chunks[0]);
// Subsequent chunks are FLIC frames with an additional 20 byte header that needs to be stripped
const int CUSTOM_HEADER_SZ = 20;
for (size_t i=1; i<chunks.size(); i++) {
data.append(chunks.at(i).data() + CUSTOM_HEADER_SZ, chunks.at(i).size() - CUSTOM_HEADER_SZ);
}
break;
}
case MxOb::SMK:
case MxOb::OBJ:
{
// Simply merge
for (size_t i=0; i<chunks.size(); i++) {
data.append(chunks[i]);
}
break;
}
2022-07-11 17:20:56 -04:00
default:
std::cout << "Didn't know how to extract type '" << std::string((const char *)&filetype, sizeof(filetype)) << "', merging..." << std::endl;
for (size_t i=0; i<chunks.size(); i++) {
data.append(chunks[i]);
}
break;
2022-07-11 04:48:20 -04:00
}
2022-07-11 11:04:47 -04:00
return data;
}
Object::ChunkedData Object::ToChunkedData(MxOb::FileType filetype, const bytearray &chunks)
{
// FIXME: STUB
return ChunkedData();
}
const bytearray &Object::GetFileHeader() const
2022-07-11 11:04:47 -04:00
{
return data_.at(0);
2022-07-11 11:04:47 -04:00
}
bytearray Object::GetFileBody() const
{
bytearray b;
for (size_t i=1; i<data_.size(); i++) {
b.append(data_.at(i));
2022-07-11 11:04:47 -04:00
}
return b;
}
size_t Object::GetFileBodySize() const
{
size_t s = 0;
for (size_t i=1; i<data_.size(); i++) {
s += data_.at(i).size();
2022-07-11 11:04:47 -04:00
}
return s;
2022-07-11 04:48:20 -04:00
}
Object *Object::FindSubObjectWithID(uint32_t id)
{
if (this->id() == id) {
return this;
}
for (Children::const_iterator it=GetChildren().begin(); it!=GetChildren().end(); it++) {
if (Object *o = static_cast<Object*>(*it)->FindSubObjectWithID(id)) {
2022-07-11 04:48:20 -04:00
return o;
}
}
return NULL;
}
2022-07-11 00:16:20 -04:00
}