mirror of
https://github.com/MonsterDruide1/OdysseyDecomp
synced 2026-05-09 16:58:22 +00:00
359 lines
11 KiB
C++
359 lines
11 KiB
C++
#include "Library/Yaml/Writer/ByamlWriter.h"
|
|
|
|
#include <heap/seadHeapMgr.h>
|
|
#include <stream/seadStream.h>
|
|
|
|
#include "Library/Yaml/ByamlIter.h"
|
|
#include "Library/Yaml/Writer/ByamlWriterBigDataList.h"
|
|
#include "Library/Yaml/Writer/ByamlWriterData.h"
|
|
#include "Library/Yaml/Writer/ByamlWriterStringTable.h"
|
|
|
|
namespace al {
|
|
|
|
ByamlWriter::ByamlWriter(sead::Heap* heap, bool _alwaysFalse)
|
|
: mHeap(heap), mAlwaysFalse(_alwaysFalse) {
|
|
sead::ScopedCurrentHeapSetter setter{mHeap};
|
|
mStringTable1 = new ByamlWriterStringTable();
|
|
mStringTable2 = new ByamlWriterStringTable();
|
|
mBigDataList = new ByamlWriterBigDataList();
|
|
mContainerStack = new ByamlWriterContainer*[mContainerStackSize];
|
|
}
|
|
|
|
ByamlWriter::~ByamlWriter() {
|
|
if (mAlwaysFalse) {
|
|
delete mStringTable1;
|
|
delete mStringTable2;
|
|
delete mBigDataList;
|
|
delete[] mContainerStack;
|
|
|
|
for (auto* node : mContainerList)
|
|
node->deleteData();
|
|
while (auto* node = mContainerList.popBack()) {
|
|
node->mList = nullptr;
|
|
delete node->mData;
|
|
delete node;
|
|
}
|
|
}
|
|
}
|
|
|
|
void ByamlWriter::addBool(bool value) {
|
|
sead::ScopedCurrentHeapSetter setter{mHeap};
|
|
mContainerStack[mCurrentContainerIndex]->addBool(value);
|
|
}
|
|
|
|
void ByamlWriter::addInt(s32 value) {
|
|
sead::ScopedCurrentHeapSetter setter{mHeap};
|
|
mContainerStack[mCurrentContainerIndex]->addInt(value);
|
|
}
|
|
|
|
void ByamlWriter::addUInt(u32 value) {
|
|
sead::ScopedCurrentHeapSetter setter{mHeap};
|
|
mContainerStack[mCurrentContainerIndex]->addUInt(value);
|
|
}
|
|
|
|
void ByamlWriter::addFloat(f32 value) {
|
|
sead::ScopedCurrentHeapSetter setter{mHeap};
|
|
mContainerStack[mCurrentContainerIndex]->addFloat(value);
|
|
}
|
|
|
|
void ByamlWriter::addInt64(s64 value) {
|
|
sead::ScopedCurrentHeapSetter setter{mHeap};
|
|
mContainerStack[mCurrentContainerIndex]->addInt64(value, mBigDataList);
|
|
}
|
|
|
|
void ByamlWriter::addUInt64(u64 value) {
|
|
sead::ScopedCurrentHeapSetter setter{mHeap};
|
|
mContainerStack[mCurrentContainerIndex]->addUInt64(value, mBigDataList);
|
|
}
|
|
|
|
void ByamlWriter::addDouble(f64 value) {
|
|
sead::ScopedCurrentHeapSetter setter{mHeap};
|
|
mContainerStack[mCurrentContainerIndex]->addDouble(value, mBigDataList);
|
|
}
|
|
|
|
void ByamlWriter::addString(const char* value) {
|
|
sead::ScopedCurrentHeapSetter setter{mHeap};
|
|
mContainerStack[mCurrentContainerIndex]->addString(value);
|
|
}
|
|
|
|
void ByamlWriter::addNull() {
|
|
sead::ScopedCurrentHeapSetter setter{mHeap};
|
|
mContainerStack[mCurrentContainerIndex]->addNull();
|
|
}
|
|
|
|
void ByamlWriter::addBool(const char* key, bool value) {
|
|
sead::ScopedCurrentHeapSetter setter{mHeap};
|
|
mContainerStack[mCurrentContainerIndex]->addBool(key, value);
|
|
}
|
|
|
|
void ByamlWriter::addInt(const char* key, s32 value) {
|
|
sead::ScopedCurrentHeapSetter setter{mHeap};
|
|
mContainerStack[mCurrentContainerIndex]->addInt(key, value);
|
|
}
|
|
|
|
void ByamlWriter::addUInt(const char* key, u32 value) {
|
|
sead::ScopedCurrentHeapSetter setter{mHeap};
|
|
mContainerStack[mCurrentContainerIndex]->addUInt(key, value);
|
|
}
|
|
|
|
void ByamlWriter::addFloat(const char* key, f32 value) {
|
|
sead::ScopedCurrentHeapSetter setter{mHeap};
|
|
mContainerStack[mCurrentContainerIndex]->addFloat(key, value);
|
|
}
|
|
|
|
void ByamlWriter::addInt64(const char* key, s64 value) {
|
|
sead::ScopedCurrentHeapSetter setter{mHeap};
|
|
mContainerStack[mCurrentContainerIndex]->addInt64(key, value, mBigDataList);
|
|
}
|
|
|
|
void ByamlWriter::addUInt64(const char* key, u64 value) {
|
|
sead::ScopedCurrentHeapSetter setter{mHeap};
|
|
mContainerStack[mCurrentContainerIndex]->addUInt64(key, value, mBigDataList);
|
|
}
|
|
|
|
void ByamlWriter::addDouble(const char* key, f64 value) {
|
|
sead::ScopedCurrentHeapSetter setter{mHeap};
|
|
mContainerStack[mCurrentContainerIndex]->addDouble(key, value, mBigDataList);
|
|
}
|
|
|
|
void ByamlWriter::addString(const char* key, const char* value) {
|
|
sead::ScopedCurrentHeapSetter setter{mHeap};
|
|
mContainerStack[mCurrentContainerIndex]->addString(key, value);
|
|
}
|
|
|
|
void ByamlWriter::addNull(const char* key) {
|
|
sead::ScopedCurrentHeapSetter setter{mHeap};
|
|
mContainerStack[mCurrentContainerIndex]->addNull(key);
|
|
}
|
|
|
|
ByamlWriterContainer* ByamlWriter::getCurrentContainer() {
|
|
return mContainerStack[mCurrentContainerIndex];
|
|
}
|
|
|
|
ByamlWriterArray* ByamlWriter::getArrayCurrentContainer() {
|
|
return static_cast<ByamlWriterArray*>(getCurrentContainer());
|
|
}
|
|
|
|
ByamlWriterHash* ByamlWriter::getHashCurrentContainer() {
|
|
return static_cast<ByamlWriterHash*>(getCurrentContainer());
|
|
}
|
|
|
|
void ByamlWriter::pushContainer(ByamlWriterContainer* container) {
|
|
mCurrentContainerIndex++;
|
|
mContainerStack[mCurrentContainerIndex] = container;
|
|
mContainerList.pushBack(new sead::TListNode<ByamlWriterContainer*>(container));
|
|
}
|
|
|
|
void ByamlWriter::pushHash() {
|
|
sead::ScopedCurrentHeapSetter setter{mHeap};
|
|
auto* hash = new ByamlWriterHash(mStringTable1, mStringTable2);
|
|
if (mCurrentContainerIndex >= 0)
|
|
mContainerStack[mCurrentContainerIndex]->addHash(hash);
|
|
|
|
pushContainer(hash);
|
|
}
|
|
|
|
void ByamlWriter::pushArray() {
|
|
sead::ScopedCurrentHeapSetter setter{mHeap};
|
|
auto* array = new ByamlWriterArray(mStringTable2);
|
|
if (mCurrentContainerIndex >= 0)
|
|
mContainerStack[mCurrentContainerIndex]->addArray(array);
|
|
|
|
pushContainer(array);
|
|
}
|
|
|
|
void ByamlWriter::pushHash(const char* key) {
|
|
sead::ScopedCurrentHeapSetter setter{mHeap};
|
|
auto* hash = new ByamlWriterHash(mStringTable1, mStringTable2);
|
|
mContainerStack[mCurrentContainerIndex]->addHash(key, hash);
|
|
|
|
pushContainer(hash);
|
|
}
|
|
|
|
void ByamlWriter::pushArray(const char* key) {
|
|
sead::ScopedCurrentHeapSetter setter{mHeap};
|
|
auto* array = new ByamlWriterArray(mStringTable2);
|
|
mContainerStack[mCurrentContainerIndex]->addArray(key, array);
|
|
|
|
pushContainer(array);
|
|
}
|
|
|
|
void ByamlWriter::pushIter(const ByamlIter& iter) {
|
|
pushLocalIter(iter, nullptr);
|
|
}
|
|
|
|
void ByamlWriter::pushIter(const char* key, const ByamlIter& iter) {
|
|
pushLocalIter(iter, key);
|
|
}
|
|
|
|
void ByamlWriter::pushLocalIter(const ByamlIter& iter, const char* iterKey) {
|
|
if (!iter.isValid())
|
|
return;
|
|
|
|
s32 size = iter.getSize();
|
|
if (iter.isTypeHash())
|
|
if (iterKey)
|
|
pushHash(iterKey);
|
|
else
|
|
pushHash();
|
|
else if (iter.isTypeArray())
|
|
if (iterKey)
|
|
pushArray(iterKey);
|
|
else
|
|
pushArray();
|
|
else
|
|
return;
|
|
|
|
for (s32 i = 0; i < size; i++) {
|
|
ByamlData data{};
|
|
const char* key = nullptr;
|
|
if (iter.isTypeHash())
|
|
iter.getByamlDataAndKeyName(&data, &key, i);
|
|
else
|
|
iter.getByamlDataByIndex(&data, i);
|
|
|
|
if (data.getType() == 0xD0) {
|
|
bool value;
|
|
if (iter.tryConvertBool(&value, &data)) {
|
|
if (key)
|
|
addBool(key, value);
|
|
else
|
|
addBool(value);
|
|
}
|
|
}
|
|
if (data.getType() == 0xD1) {
|
|
s32 value;
|
|
if (iter.tryConvertInt(&value, &data)) {
|
|
if (key)
|
|
addInt(key, value);
|
|
else
|
|
addInt(value);
|
|
}
|
|
}
|
|
if (data.getType() == 0xD2) {
|
|
f32 value;
|
|
if (iter.tryConvertFloat(&value, &data)) {
|
|
if (key)
|
|
addFloat(key, value);
|
|
else
|
|
addFloat(value);
|
|
}
|
|
}
|
|
if (data.getType() == 0xD3) {
|
|
u32 value;
|
|
if (iter.tryConvertUInt(&value, &data)) {
|
|
if (key)
|
|
addUInt(key, value);
|
|
else
|
|
addUInt(value);
|
|
}
|
|
}
|
|
if (data.getType() == 0xD4) {
|
|
s64 value;
|
|
if (iter.tryConvertInt64(&value, &data)) {
|
|
if (key)
|
|
addInt64(key, value);
|
|
else
|
|
addInt64(value);
|
|
}
|
|
}
|
|
if (data.getType() == 0xD6) {
|
|
f64 value;
|
|
if (iter.tryConvertDouble(&value, &data)) {
|
|
if (key)
|
|
addDouble(key, value);
|
|
else
|
|
addDouble(value);
|
|
}
|
|
}
|
|
if (data.getType() == 0xD5) {
|
|
u64 value;
|
|
if (iter.tryConvertUInt64(&value, &data)) {
|
|
if (key)
|
|
addUInt64(key, value);
|
|
else
|
|
addUInt64(value);
|
|
}
|
|
}
|
|
if (data.getType() == 0xA0) {
|
|
const char* value;
|
|
if (iter.tryConvertString(&value, &data)) {
|
|
if (key)
|
|
addString(key, value);
|
|
else
|
|
addString(value);
|
|
}
|
|
}
|
|
if (data.getType() == 0x00) {
|
|
if (key)
|
|
addNull(key);
|
|
else
|
|
addNull();
|
|
}
|
|
if (data.getType() == 0xC0 || data.getType() == 0xC1) {
|
|
ByamlIter value;
|
|
if (iter.tryConvertIter(&value, &data))
|
|
pushLocalIter(value, key);
|
|
}
|
|
}
|
|
pop();
|
|
}
|
|
|
|
void ByamlWriter::pop() {
|
|
mCurrentContainerIndex--;
|
|
}
|
|
|
|
u32 ByamlWriter::calcHeaderSize() const {
|
|
return 16;
|
|
}
|
|
|
|
u32 ByamlWriter::calcPackSize() const {
|
|
u32 size = 16;
|
|
if (mStringTable1)
|
|
size += mStringTable1->calcPackSize();
|
|
if (mStringTable2)
|
|
size += mStringTable2->calcPackSize();
|
|
if (mBigDataList)
|
|
size += mBigDataList->calcPackSize();
|
|
for (auto* container : mContainerList)
|
|
size += container->calcPackSize();
|
|
return size;
|
|
}
|
|
|
|
// NON_MATCHING: offsetBigDataList increased "too early" (https://decomp.me/scratch/xXvTw)
|
|
void ByamlWriter::write(sead::WriteStream* stream) {
|
|
stream->writeU16(0x4259);
|
|
stream->writeU16(3);
|
|
|
|
s32 sizeStringTable1 = mStringTable1->calcPackSize();
|
|
stream->writeU32(sizeStringTable1 > 0 ? 16 : 0);
|
|
|
|
u32 offsetStringTable2 = sizeStringTable1 + 16;
|
|
s32 sizeStringTable2 = mStringTable2->calcPackSize();
|
|
stream->writeU32(sizeStringTable2 > 0 ? offsetStringTable2 : 0);
|
|
|
|
u32 offsetBigDataList = mBigDataList->setOffset(offsetStringTable2 + sizeStringTable2);
|
|
stream->writeU32(mContainerList.size() > 0 ? offsetBigDataList : 0);
|
|
mStringTable1->write(stream);
|
|
mStringTable2->write(stream);
|
|
mBigDataList->write(stream);
|
|
|
|
for (auto* container : mContainerList) {
|
|
container->setOffset(offsetBigDataList);
|
|
offsetBigDataList += container->calcPackSize();
|
|
}
|
|
for (auto* container : mContainerList)
|
|
container->writeContainer(stream);
|
|
}
|
|
|
|
void ByamlWriter::print() const {
|
|
if (mStringTable1)
|
|
mStringTable1->print();
|
|
if (mStringTable2)
|
|
mStringTable2->print();
|
|
if (mCurrentContainerIndex >= 0)
|
|
mContainerStack[0]->print(1);
|
|
}
|
|
|
|
} // namespace al
|