summaryrefslogtreecommitdiff
path: root/src/KingSystem/Utils
diff options
context:
space:
mode:
authornotyourav <65437533+notyourav@users.noreply.github.com>2020-11-16 15:49:02 -0800
committerGitHub <noreply@github.com>2020-11-16 15:49:02 -0800
commitd4f80d7cf97641742dd56cabc0b1d503cfdf7b0d (patch)
tree05b09142b74869f74779a00deff410019b8dcaac /src/KingSystem/Utils
parent8205744abcae5784138629038976f2449269a81f (diff)
parentb0498a15bf6f1782f1429ffbd0b03c187f61d7c9 (diff)
Merge branch 'master' into placement
Diffstat (limited to 'src/KingSystem/Utils')
-rw-r--r--src/KingSystem/Utils/Byaml.cpp1
-rw-r--r--src/KingSystem/Utils/Byaml/Byaml.cpp402
-rw-r--r--src/KingSystem/Utils/Byaml/Byaml.h (renamed from src/KingSystem/Utils/Byaml.h)158
-rw-r--r--src/KingSystem/Utils/Byaml/ByamlArrayIter.cpp29
-rw-r--r--src/KingSystem/Utils/Byaml/ByamlArrayIter.h28
-rw-r--r--src/KingSystem/Utils/Byaml/ByamlData.cpp7
-rw-r--r--src/KingSystem/Utils/Byaml/ByamlData.h45
-rw-r--r--src/KingSystem/Utils/Byaml/ByamlHashIter.cpp110
-rw-r--r--src/KingSystem/Utils/Byaml/ByamlHashIter.h38
-rw-r--r--src/KingSystem/Utils/Byaml/ByamlLocal.cpp3
-rw-r--r--src/KingSystem/Utils/Byaml/ByamlLocal.h38
-rw-r--r--src/KingSystem/Utils/Byaml/ByamlStringTableIter.cpp50
-rw-r--r--src/KingSystem/Utils/Byaml/ByamlStringTableIter.h27
-rw-r--r--src/KingSystem/Utils/Byaml/ByamlUtil.cpp (renamed from src/KingSystem/Utils/ByamlUtil.cpp)2
-rw-r--r--src/KingSystem/Utils/ByamlLocal.cpp1
-rw-r--r--src/KingSystem/Utils/ByamlLocal.h16
-rw-r--r--src/KingSystem/Utils/CMakeLists.txt19
-rw-r--r--src/KingSystem/Utils/ParamIO.h5
18 files changed, 887 insertions, 92 deletions
diff --git a/src/KingSystem/Utils/Byaml.cpp b/src/KingSystem/Utils/Byaml.cpp
deleted file mode 100644
index 23d82bb9..00000000
--- a/src/KingSystem/Utils/Byaml.cpp
+++ /dev/null
@@ -1 +0,0 @@
-#include "KingSystem/Utils/Byaml.h"
diff --git a/src/KingSystem/Utils/Byaml/Byaml.cpp b/src/KingSystem/Utils/Byaml/Byaml.cpp
new file mode 100644
index 00000000..2fe0dac1
--- /dev/null
+++ b/src/KingSystem/Utils/Byaml/Byaml.cpp
@@ -0,0 +1,402 @@
+#include "KingSystem/Utils/Byaml/Byaml.h"
+#include <math/seadMathCalcCommon.h>
+#include <prim/seadMemUtil.h>
+#include "KingSystem/Utils/Byaml/ByamlArrayIter.h"
+#include "KingSystem/Utils/Byaml/ByamlData.h"
+#include "KingSystem/Utils/Byaml/ByamlHashIter.h"
+#include "KingSystem/Utils/Byaml/ByamlLocal.h"
+#include "KingSystem/Utils/Byaml/ByamlStringTableIter.h"
+
+namespace al {
+
+ByamlIter::ByamlIter() : mData(nullptr), mRootNode(nullptr) {}
+
+ByamlIter::ByamlIter(const u8* data) {
+ mData = data;
+ mRootNode = nullptr;
+ if (mData) {
+ if (ByamlLocalUtil::verifiByaml(mData)) {
+ const ByamlHeader* header = reinterpret_cast<const ByamlHeader*>(mData);
+ u32 data_root_offset = header->getDataOffset();
+ if (data_root_offset) {
+ mRootNode = &mData[data_root_offset];
+ }
+ } else {
+ mData = nullptr;
+ mRootNode = nullptr;
+ }
+ }
+}
+
+ByamlIter::ByamlIter(const u8* data, const u8* root_node) : mData(data), mRootNode(root_node) {}
+
+ByamlIter::ByamlIter(const ByamlIter& other) : mData(other.mData), mRootNode(other.mRootNode) {}
+
+ByamlIter& ByamlIter::operator=(const ByamlIter& rhs) {
+ if (this != &rhs) {
+ // This is formally undefined behavior because ByamlIter is not trivially copyable
+ // (since it has non-trivial copy constructors and copy assignment operators)
+ // but those are effectively trivial so this will work in practice.
+ // This is what Nintendo did and it is required for matching.
+ sead::MemUtil::copy(this, &rhs, sizeof(*this));
+ }
+ return *this;
+}
+
+bool ByamlIter::isValid() const {
+ return mData != nullptr;
+}
+
+bool ByamlIter::isTypeHash() const {
+ const ByamlContainerHeader* node = reinterpret_cast<const ByamlContainerHeader*>(mRootNode);
+ return node && node->getType() == ByamlType::Hash;
+}
+
+bool ByamlIter::isTypeArray() const {
+ const ByamlContainerHeader* node = reinterpret_cast<const ByamlContainerHeader*>(mRootNode);
+ return node && node->getType() == ByamlType::Array;
+}
+
+bool ByamlIter::isTypeContainer() const {
+ return isTypeArray() || isTypeHash();
+}
+
+bool ByamlIter::isExistKey(const char* key) const {
+ if (!mRootNode) {
+ return false;
+ }
+
+ if (!isTypeHash()) {
+ return false;
+ }
+
+ const s32 index = getKeyIndex(key);
+ if (index < 0) {
+ return 0;
+ }
+
+ ByamlHashIter node_hash(mRootNode);
+ return node_hash.findPair(index);
+}
+
+s32 ByamlIter::getKeyIndex(const char* key) const {
+ const ByamlStringTableIter table = ByamlLocalUtil::getHashKeyTableIter(mData);
+ return table.findStringIndex(key);
+}
+
+s32 ByamlIter::getSize() const {
+ if (!mRootNode) {
+ return 0;
+ }
+
+ if (isTypeContainer()) {
+ return ByamlLocalUtil::getContainerSize(mRootNode);
+ }
+
+ return 0;
+}
+
+ByamlIter ByamlIter::getIterByIndex(s32 index) const {
+ ByamlData data;
+ if (!getByamlDataByIndex(&data, index)) {
+ return ByamlIter();
+ }
+
+ return getIterFromData(data);
+}
+
+ByamlIter ByamlIter::getIterByKey(const char* key) const {
+ ByamlData data;
+ if (!getByamlDataByKey(&data, key)) {
+ return ByamlIter();
+ }
+
+ return getIterFromData(data);
+}
+
+ByamlIter ByamlIter::getIterFromData(const ByamlData& data) const {
+ if (data.getType() == ByamlType::Hash || data.getType() == ByamlType::Array) {
+ return ByamlIter(mData, &mData[data.getValue()]);
+ }
+
+ if (data.getType() == ByamlType::Null) {
+ return ByamlIter(mData, nullptr);
+ }
+
+ return ByamlIter();
+}
+
+bool ByamlIter::getByamlDataByIndex(ByamlData* data, s32 index) const {
+ if (isTypeArray()) {
+ ByamlArrayIter array_node(mRootNode);
+ return array_node.getDataByIndex(data, index);
+ } else if (isTypeHash()) {
+ ByamlHashIter hash_node(mRootNode);
+ return hash_node.getDataByIndex(data, index);
+ }
+
+ return false;
+}
+
+bool ByamlIter::getByamlDataByKey(ByamlData* data, const char* key) const {
+ if (!isTypeHash()) {
+ return false;
+ }
+
+ auto* header = reinterpret_cast<const al::ByamlHeader*>(mData);
+ const s32 offset = header->getHashKeyTableOffset();
+ if (!offset) {
+ return false;
+ }
+ const ByamlStringTableIter table = ByamlStringTableIter(&mData[offset]);
+
+ ByamlHashIter hash_node(mRootNode);
+ const s32 size = hash_node.getSize();
+ if (size < 1) {
+ return false;
+ }
+
+ // Binary Search
+ const ByamlHashPair* pair;
+ s32 start = 0;
+ s32 end = size;
+ s32 index;
+ while (true) {
+ if (start >= end) {
+ return false;
+ }
+
+ index = (start + end) / 2;
+ pair = hash_node.getPairByIndex(index);
+ const char* str = table.getString(pair->getKey());
+ s32 result = std::strcmp(key, str);
+ if (result == 0)
+ break;
+ if (result > 0)
+ start = index + 1;
+ else if (result < 0)
+ end = index;
+ }
+
+ data->set(pair);
+
+ return true;
+}
+
+bool ByamlIter::getByamlDataAndKeyNameByIndex(ByamlData* data, const char** key, s32 index) const {
+ if (!isTypeHash()) {
+ return false;
+ }
+
+ const ByamlHashIter hash_iter(mRootNode);
+ const ByamlHashPair* pair = hash_iter.getPairByIndex(index);
+ if (!pair) {
+ return false;
+ }
+
+ if (data) {
+ data->set(pair);
+ }
+
+ ByamlStringTableIter table_iter = ByamlLocalUtil::getHashKeyTableIter(mData);
+ *key = table_iter.getString(pair->getKey());
+ return true;
+}
+
+bool ByamlIter::getKeyName(const char** key, s32 index) const {
+ if (!mRootNode) {
+ return false;
+ }
+
+ if (!isTypeHash()) {
+ return false;
+ }
+
+ ByamlHashIter hash_node(mRootNode);
+ const ByamlHashPair* pair = hash_node.getPairByIndex(index);
+ if (!pair) {
+ return false;
+ }
+
+ const ByamlStringTableIter hash_table = ByamlLocalUtil::getHashKeyTableIter(mData);
+ *key = hash_table.getString(pair->getKey());
+
+ return true;
+}
+
+bool ByamlIter::tryGetIterByIndex(ByamlIter* iter, s32 index) const {
+ *iter = getIterByIndex(index);
+ return iter->isValid();
+}
+
+bool ByamlIter::tryGetIterByKey(ByamlIter* iter, const char* key) const {
+ *iter = getIterByKey(key);
+ return iter->isValid();
+}
+
+bool ByamlIter::tryGetIterAndKeyNameByIndex(ByamlIter* iter, const char** key, s32 index) const {
+ ByamlData data;
+ if (!getByamlDataAndKeyNameByIndex(&data, key, index)) {
+ *key = nullptr;
+ return tryGetIterByIndex(iter, index);
+ }
+
+ *iter = getIterFromData(data);
+ return true;
+}
+
+bool ByamlIter::tryGetStringByIndex(const char** value, s32 index) const {
+ ByamlData data;
+ if (!getByamlDataByIndex(&data, index)) {
+ return false;
+ }
+
+ return tryConvertString(value, &data);
+}
+
+bool ByamlIter::tryGetStringByKey(const char** value, const char* key) const {
+ ByamlData data;
+ if (!getByamlDataByKey(&data, key)) {
+ return false;
+ }
+
+ return tryConvertString(value, &data);
+}
+
+bool ByamlIter::tryConvertString(const char** value, const ByamlData* data) const {
+ if (data->getType() != ByamlType::String) {
+ return false;
+ }
+
+ const auto string_table = ByamlLocalUtil::getStringTableIter(mData);
+ *value = string_table.getString(data->getValue());
+
+ return true;
+}
+
+bool ByamlIter::tryGetIntByIndex(s32* value, s32 index) const {
+ ByamlData data;
+ if (!getByamlDataByIndex(&data, index)) {
+ return false;
+ }
+
+ return tryConvertInt(value, &data);
+}
+
+bool ByamlIter::tryGetIntByKey(s32* value, const char* key) const {
+ ByamlData data;
+ if (!getByamlDataByKey(&data, key)) {
+ return false;
+ }
+
+ return tryConvertInt(value, &data);
+}
+
+bool ByamlIter::tryConvertInt(s32* value, const ByamlData* data) const {
+ if (data->getType() != ByamlType::Int) {
+ return false;
+ }
+
+ *value = data->getValue();
+ return true;
+}
+
+bool ByamlIter::tryGetUIntByIndex(u32* value, s32 index) const {
+ ByamlData data;
+ if (!getByamlDataByIndex(&data, index)) {
+ return false;
+ }
+
+ return tryConvertUInt(value, &data);
+}
+
+bool ByamlIter::tryGetUIntByKey(u32* value, const char* key) const {
+ ByamlData data;
+ if (!getByamlDataByKey(&data, key)) {
+ return false;
+ }
+
+ return tryConvertUInt(value, &data);
+}
+
+bool ByamlIter::tryConvertUInt(u32* value, const ByamlData* data) const {
+ if (data->getType() == ByamlType::Int) {
+ s32 signed_value = data->getValue<s32>();
+ if (signed_value < 0) {
+ *value = 0;
+ return false;
+ } else {
+ *value = signed_value;
+ return true;
+ }
+ } else if (data->getType() == ByamlType::UInt) {
+ *value = data->getValue();
+ return true;
+ }
+
+ return false;
+}
+
+bool ByamlIter::tryGetFloatByIndex(f32* value, s32 index) const {
+ ByamlData data;
+ if (!getByamlDataByIndex(&data, index)) {
+ return false;
+ }
+
+ return tryConvertFloat(value, &data);
+}
+
+bool ByamlIter::tryGetFloatByKey(f32* value, const char* key) const {
+ ByamlData data;
+ if (!getByamlDataByKey(&data, key)) {
+ return false;
+ }
+
+ return tryConvertFloat(value, &data);
+}
+
+bool ByamlIter::tryConvertFloat(f32* value, const ByamlData* data) const {
+ if (data->getType() != ByamlType::Float) {
+ return false;
+ }
+
+ *value = data->getValue<f32>();
+ return true;
+}
+
+bool ByamlIter::tryGetBoolByIndex(bool* value, s32 index) const {
+ ByamlData data;
+ if (!getByamlDataByIndex(&data, index)) {
+ return false;
+ }
+
+ return tryConvertBool(value, &data);
+}
+
+bool ByamlIter::tryGetBoolByKey(bool* value, const char* key) const {
+ ByamlData data;
+ if (!getByamlDataByKey(&data, key)) {
+ return false;
+ }
+
+ return tryConvertBool(value, &data);
+}
+
+bool ByamlIter::tryConvertBool(bool* value, const ByamlData* data) const {
+ if (data->getType() != ByamlType::Bool) {
+ return false;
+ }
+
+ *value = data->getValue() != 0;
+ return true;
+}
+
+bool ByamlIter::isEqualData(const ByamlIter& other) const {
+ if (!mData || !other.mData) {
+ return false;
+ }
+
+ return mData == other.mData && mRootNode == other.mRootNode;
+}
+
+} // namespace al
diff --git a/src/KingSystem/Utils/Byaml.h b/src/KingSystem/Utils/Byaml/Byaml.h
index 5c600627..c13500d7 100644
--- a/src/KingSystem/Utils/Byaml.h
+++ b/src/KingSystem/Utils/Byaml/Byaml.h
@@ -4,12 +4,14 @@
#include <basis/seadTypes.h>
#include <math/seadVector.h>
+#include <prim/seadEndian.h>
#include <prim/seadSizedEnum.h>
#include "KingSystem/Utils/Types.h"
namespace al {
struct ByamlData;
+struct ByamlHashPair;
enum class ByamlType {
Invalid = 0,
@@ -41,6 +43,9 @@ public:
ByamlIter& operator=(const ByamlIter& rhs);
+ const u8* getData() const { return mData; }
+ const u8* getRootNode() const { return mRootNode; }
+
bool isValid() const;
bool isTypeHash() const;
bool isTypeArray() const;
@@ -51,11 +56,13 @@ public:
s32 getSize() const;
- void getByamlDataByIndex(ByamlData* data, s32 index) const;
- bool getByamlDataByKey(ByamlData* data, const char* key) const;
- bool getByamlDataByKeyIndex(ByamlData* data, s32 index) const;
ByamlIter getIterByIndex(s32 index) const;
ByamlIter getIterByKey(const char* key) const;
+ ByamlIter getIterFromData(const ByamlData& data) const;
+ bool getByamlDataByIndex(ByamlData* data, s32 index) const;
+ bool getByamlDataByKey(ByamlData* data, const char* key) const;
+ bool getByamlDataAndKeyNameByIndex(ByamlData* data, const char** key, s32 index) const;
+
bool getKeyName(const char** key, s32 index) const;
bool tryGetIterByIndex(ByamlIter* iter, s32 index) const;
@@ -68,6 +75,7 @@ public:
bool tryGetIntByIndex(s32* value, s32 index) const;
bool tryGetIntByKey(s32* value, const char* key) const;
+ bool tryConvertInt(s32* value, const ByamlData* data) const;
bool tryGetUIntByIndex(u32* value, s32 index) const;
bool tryGetUIntByKey(u32* value, const char* key) const;
@@ -75,61 +83,96 @@ public:
bool tryGetFloatByIndex(f32* value, s32 index) const;
bool tryGetFloatByKey(f32* value, const char* key) const;
+ bool tryConvertFloat(f32* value, const ByamlData* data) const;
bool tryGetBoolByIndex(bool* value, s32 index) const;
bool tryGetBoolByKey(bool* value, const char* key) const;
+ bool tryConvertBool(bool* value, const ByamlData* data) const;
bool isEqualData(const ByamlIter& other) const;
+ const char* getStringByIndex(s32 index) const {
+ const char* value;
+ if (!tryGetStringByIndex(&value, index))
+ return "";
+ return value;
+ }
+
+ const char* getStringByKey(const char* key) const {
+ const char* value;
+ if (!tryGetStringByKey(&value, key))
+ return "";
+ return value;
+ }
+
+ s32 getIntByIndex(s32 index) const {
+ s32 value;
+ if (!tryGetIntByIndex(&value, index))
+ return {};
+ return value;
+ }
+
+ s32 getIntByKey(const char* key) const {
+ s32 value;
+ if (!tryGetIntByKey(&value, key))
+ return {};
+ return value;
+ }
+
+ u32 getUIntByIndex(s32 index) const {
+ u32 value;
+ if (!tryGetUIntByIndex(&value, index))
+ return {};
+ return value;
+ }
+
+ u32 getUIntByKey(const char* key) const {
+ u32 value;
+ if (!tryGetUIntByKey(&value, key))
+ return {};
+ return value;
+ }
+
+ f32 getFloatByIndex(s32 index) const {
+ f32 value;
+ if (!tryGetFloatByIndex(&value, index))
+ return {};
+ return value;
+ }
+
+ f32 getFloatByKey(const char* key) const {
+ f32 value;
+ if (!tryGetFloatByKey(&value, key))
+ return {};
+ return value;
+ }
+
+ bool getBoolByIndex(s32 index) const {
+ bool value;
+ if (!tryGetBoolByIndex(&value, index))
+ return {};
+ return value;
+ }
+
+ bool getBoolByKey(const char* key) const {
+ bool value;
+ if (!tryGetBoolByKey(&value, key))
+ return {};
+ return value;
+ }
+
private:
const u8* mData = nullptr;
const u8* mRootNode = nullptr;
};
-class ByamlStringTableIter {
-public:
- explicit ByamlStringTableIter(const u8* data) : mData(data) {}
-
- const char* getString(s32 index) const;
- s32 findStringIndex(const char* string) const;
-
-private:
- const u8* mData;
-};
-
-class ByamlArrayIter {
-public:
- explicit ByamlArrayIter(const u8* data);
-
- const u8* getDataTable() const;
- bool getDataByIndex(ByamlData* data, s32 index);
-
-private:
- const u8* mData;
-};
-
-class ByamlHashIter {
-public:
- explicit ByamlHashIter(const u8* data);
-
- s32 getSize() const;
- const u8* getPairTable() const;
- bool getDataByIndex(ByamlData* data, s32 index) const;
- bool getDataByKey(ByamlData* data, s32 key_index) const;
- const u8* findPair(s32 key_index) const;
- const u8* getPairByIndex(s32 index) const;
-
-private:
- const u8* mData;
-};
-
struct ByamlHeader {
u16 getTag() const;
bool isInvertHeader() const;
- u16 getVersion() const;
- u16 getHashKeyTableOffset() const;
- u16 getStringTableOffset() const;
- u16 getDataOffset() const;
+ u16 getVersion() const { return version; };
+ u32 getHashKeyTableOffset() const { return hash_key_table_offset; };
+ u32 getStringTableOffset() const { return string_table_offset; };
+ u32 getDataOffset() const { return data_offset; };
u16 magic;
u16 version;
@@ -140,32 +183,15 @@ struct ByamlHeader {
KSYS_CHECK_SIZE_NX150(ByamlHeader, 0x10);
struct ByamlContainerHeader {
- ByamlType getType() const;
- u32 getCount(bool byteswap) const;
+ ByamlType getType() const {
+ // Type is only the first byte
+ return ByamlType(*reinterpret_cast<const u8*>(&type_and_size));
+ }
+ u32 getCount() const { return type_and_size >> 8; };
u32 type_and_size;
};
-struct ByamlHashPair {
- u32 getKey(bool byteswap) const;
- ByamlType getType() const;
- u32 getValue(bool byteswap) const;
-
- u32 name_and_type;
- u32 value;
-};
-
-struct ByamlData {
- u32 getValue() const { return value; }
- ByamlType getType() const { return type; }
-
- void set(const ByamlHashPair* pair, bool byteswap);
- void set(u8, u32, bool byteswap);
-
- u32 value = 0;
- sead::SizedEnum<ByamlType, u8> type = ByamlType::Invalid;
-};
-
bool tryGetByamlS32(s32* value, const ByamlIter& iter, const char* key);
bool tryGetByamlU32(u32* value, const ByamlIter& iter, const char* key);
bool tryGetByamlF32(f32* value, const ByamlIter& iter, const char* key);
diff --git a/src/KingSystem/Utils/Byaml/ByamlArrayIter.cpp b/src/KingSystem/Utils/Byaml/ByamlArrayIter.cpp
new file mode 100644
index 00000000..fe5db205
--- /dev/null
+++ b/src/KingSystem/Utils/Byaml/ByamlArrayIter.cpp
@@ -0,0 +1,29 @@
+#include "KingSystem/Utils/Byaml/ByamlArrayIter.h"
+#include "KingSystem/Utils/Byaml/Byaml.h"
+#include "KingSystem/Utils/Byaml/ByamlData.h"
+#include "KingSystem/Utils/Byaml/ByamlLocal.h"
+
+namespace al {
+ByamlArrayIter::ByamlArrayIter(const u8* data) {
+ mData = data;
+}
+
+const u32* ByamlArrayIter::getDataTable() const {
+ return reinterpret_cast<const u32*>(&mData[TypeTableOffset + getDataOffset()]);
+}
+
+bool ByamlArrayIter::getDataByIndex(ByamlData* data, s32 index) {
+ if (index < 0) {
+ return false;
+ }
+
+ if (index >= ByamlLocalUtil::getContainerSize(mData)) {
+ return false;
+ }
+
+ data->setType(ByamlType(mData[TypeTableOffset + index]));
+ data->setValue(getDataTable()[index]);
+
+ return true;
+}
+} // namespace al \ No newline at end of file
diff --git a/src/KingSystem/Utils/Byaml/ByamlArrayIter.h b/src/KingSystem/Utils/Byaml/ByamlArrayIter.h
new file mode 100644
index 00000000..a29cefc1
--- /dev/null
+++ b/src/KingSystem/Utils/Byaml/ByamlArrayIter.h
@@ -0,0 +1,28 @@
+#pragma once
+
+#include <basis/seadTypes.h>
+#include <math/seadMathCalcCommon.h>
+#include "KingSystem/Utils/Byaml/Byaml.h"
+#include "KingSystem/Utils/Byaml/ByamlLocal.h"
+
+namespace al {
+
+class ByamlArrayIter {
+public:
+ explicit ByamlArrayIter(const u8* data);
+
+ const u32* getDataTable() const;
+ bool getDataByIndex(ByamlData* data, s32 index);
+
+private:
+ s32 getDataOffset() const {
+ const s32 size = ByamlLocalUtil::getContainerSize(mData);
+ return sead::Mathu::roundUp(size, 4);
+ }
+
+ static constexpr s32 TypeTableOffset = 4;
+
+ const u8* mData;
+};
+
+} // namespace al
diff --git a/src/KingSystem/Utils/Byaml/ByamlData.cpp b/src/KingSystem/Utils/Byaml/ByamlData.cpp
new file mode 100644
index 00000000..2aff5f96
--- /dev/null
+++ b/src/KingSystem/Utils/Byaml/ByamlData.cpp
@@ -0,0 +1,7 @@
+#include "KingSystem/Utils/Byaml/ByamlData.h"
+#include "KingSystem/Utils/Byaml/Byaml.h"
+
+namespace al {
+ByamlData::ByamlData() = default;
+
+} // namespace al \ No newline at end of file
diff --git a/src/KingSystem/Utils/Byaml/ByamlData.h b/src/KingSystem/Utils/Byaml/ByamlData.h
new file mode 100644
index 00000000..ed41dc82
--- /dev/null
+++ b/src/KingSystem/Utils/Byaml/ByamlData.h
@@ -0,0 +1,45 @@
+#pragma once
+
+#include <basis/seadTypes.h>
+#include "KingSystem/Utils/Byaml/Byaml.h"
+#include "KingSystem/Utils/Byaml/ByamlHashIter.h"
+
+namespace al {
+
+struct ByamlData {
+ ByamlData();
+
+ template <typename T = u32>
+ T getValue() const {
+ return *reinterpret_cast<const T*>(&mValue);
+ }
+ ByamlType getType() const { return mType; }
+
+ void set(const ByamlHashPair* pair) {
+ mType = pair->getType();
+ mValue = pair->getValue();
+ }
+ template <typename T = u32>
+ void set(const ByamlType& type, const T& value) {
+ mType = type;
+ mValue = *reinterpret_cast<const u32*>(&value);
+ }
+
+ void setType(const ByamlType& type) { mType = type; }
+
+ template <typename T = u32>
+ void setValue(const T& value) {
+ mValue = *reinterpret_cast<const u32*>(&value);
+ }
+
+ void clear() {
+ mValue = 0;
+ mType = ByamlType::Invalid;
+ }
+
+private:
+ u32 mValue = 0;
+ sead::SizedEnum<ByamlType, u8> mType = ByamlType::Invalid;
+};
+
+} // namespace al
diff --git a/src/KingSystem/Utils/Byaml/ByamlHashIter.cpp b/src/KingSystem/Utils/Byaml/ByamlHashIter.cpp
new file mode 100644
index 00000000..edce10ee
--- /dev/null
+++ b/src/KingSystem/Utils/Byaml/ByamlHashIter.cpp
@@ -0,0 +1,110 @@
+#include "KingSystem/Utils/Byaml/ByamlHashIter.h"
+#include "KingSystem/Utils/Byaml/Byaml.h"
+#include "KingSystem/Utils/Byaml/ByamlData.h"
+#include "KingSystem/Utils/Byaml/ByamlLocal.h"
+
+namespace al {
+
+ByamlHashIter::ByamlHashIter(const u8* data) {
+ mData = data;
+}
+
+s32 ByamlHashIter::getSize() const {
+ if (!mData) {
+ return 0;
+ }
+
+ return ByamlLocalUtil::getContainerSize(mData);
+}
+
+const ByamlHashPair* ByamlHashIter::getPairTable() const {
+ if (!mData) {
+ return nullptr;
+ }
+
+ return reinterpret_cast<const ByamlHashPair*>(&mData[mTableOffset]);
+}
+
+bool ByamlHashIter::getDataByIndex(ByamlData* data, s32 index) const {
+ if (!mData) {
+ return false;
+ }
+
+ if (ByamlLocalUtil::getContainerSize(mData) == 0) {
+ return false;
+ }
+
+ const ByamlHashPair* pair_table = getPairTable();
+ const ByamlHashPair* pair = &pair_table[index];
+ if (!pair) // This seems wrong, this can never be null?
+ {
+ return false;
+ }
+
+ data->set(pair);
+
+ return true;
+}
+
+bool ByamlHashIter::getDataByKey(ByamlData* data, s32 key_index) const {
+ if (getSize() == 0) {
+ return false;
+ }
+
+ const ByamlHashPair* pair = findPair(key_index);
+ if (!pair) {
+ return false;
+ }
+
+ data->set(pair);
+ return true;
+}
+
+const ByamlHashPair* ByamlHashIter::findPair(s32 key_index) const {
+ const ByamlHashPair* pair_table = getPairTable();
+ if (!pair_table) {
+ return nullptr;
+ }
+
+ if (ByamlLocalUtil::getContainerSize(mData) == 0) {
+ return nullptr;
+ }
+
+ // Binary Search
+ s32 start = 0;
+ s32 end = getSize();
+ s32 index;
+ const ByamlHashPair* pair;
+ while (true) {
+ if (start >= end) {
+ return nullptr;
+ }
+
+ index = (start + end) / 2;
+ pair = &pair_table[index];
+ s32 result = key_index - pair->getKey();
+ if (result == 0)
+ break;
+ if (result > 0)
+ start = index + 1;
+ else if (result < 0)
+ end = index;
+ }
+
+ return pair;
+}
+
+const ByamlHashPair* ByamlHashIter::getPairByIndex(s32 index) const {
+ if (index < 0) {
+ return nullptr;
+ }
+
+ if (getSize() <= index) {
+ return nullptr;
+ }
+
+ const ByamlHashPair* pair_table = getPairTable();
+ return pair_table + index;
+}
+
+} // namespace al
diff --git a/src/KingSystem/Utils/Byaml/ByamlHashIter.h b/src/KingSystem/Utils/Byaml/ByamlHashIter.h
new file mode 100644
index 00000000..2ad55877
--- /dev/null
+++ b/src/KingSystem/Utils/Byaml/ByamlHashIter.h
@@ -0,0 +1,38 @@
+#pragma once
+
+#include <basis/seadTypes.h>
+#include "KingSystem/Utils/Byaml/Byaml.h"
+#include "prim/seadEndian.h"
+
+namespace al {
+
+struct ByamlData;
+struct ByamlHashPair;
+
+class ByamlHashIter {
+public:
+ explicit ByamlHashIter(const u8* data);
+
+ s32 getSize() const;
+ const ByamlHashPair* getPairTable() const;
+ bool getDataByIndex(ByamlData* data, s32 index) const;
+ bool getDataByKey(ByamlData* data, s32 key_index) const;
+ const ByamlHashPair* findPair(s32 key_index) const;
+ const ByamlHashPair* getPairByIndex(s32 index) const;
+
+private:
+ const u8* mData;
+
+ static constexpr s32 mTableOffset = 4;
+};
+
+struct ByamlHashPair {
+ u32 getKey() const { return mKeyAndType & 0xFFFFFF; }
+ ByamlType getType() const { return ByamlType(mKeyAndType >> 24); }
+ u32 getValue() const { return mValue; }
+
+ u32 mKeyAndType;
+ u32 mValue;
+};
+
+} // namespace al
diff --git a/src/KingSystem/Utils/Byaml/ByamlLocal.cpp b/src/KingSystem/Utils/Byaml/ByamlLocal.cpp
new file mode 100644
index 00000000..321fc879
--- /dev/null
+++ b/src/KingSystem/Utils/Byaml/ByamlLocal.cpp
@@ -0,0 +1,3 @@
+#include "KingSystem/Utils/Byaml/ByamlLocal.h"
+
+namespace al::ByamlLocalUtil {} // namespace al::ByamlLocalUtil \ No newline at end of file
diff --git a/src/KingSystem/Utils/Byaml/ByamlLocal.h b/src/KingSystem/Utils/Byaml/ByamlLocal.h
new file mode 100644
index 00000000..faf51cac
--- /dev/null
+++ b/src/KingSystem/Utils/Byaml/ByamlLocal.h
@@ -0,0 +1,38 @@
+#pragma once
+
+#include "KingSystem/Utils/Byaml/Byaml.h"
+#include "KingSystem/Utils/Byaml/ByamlStringTableIter.h"
+
+#include <basis/seadTypes.h>
+
+namespace al::ByamlLocalUtil {
+
+inline ByamlStringTableIter getHashKeyTableIter(const u8* data) {
+ auto* header = reinterpret_cast<const al::ByamlHeader*>(data);
+ const u8* ptr = &data[header->getHashKeyTableOffset()];
+ return ByamlStringTableIter(ptr);
+}
+
+inline ByamlStringTableIter getStringTableIter(const u8* data) {
+ auto* header = reinterpret_cast<const al::ByamlHeader*>(data);
+ const u8* ptr = &data[header->getStringTableOffset()];
+ return ByamlStringTableIter(ptr);
+}
+
+inline s32 getContainerSize(const u8* data) {
+ auto* node = reinterpret_cast<const al::ByamlContainerHeader*>(data);
+ return node->getCount();
+}
+
+inline al::ByamlType getType(const u8* data) {
+ auto* node = reinterpret_cast<const al::ByamlContainerHeader*>(data);
+ return node->getType();
+}
+
+const char* getDataTypeString(s32 type);
+
+bool verifiByaml(const u8* data);
+bool verifiByamlHeader(const u8* data);
+bool verifiByamlStringTable(const u8* data);
+
+} // namespace al::ByamlLocalUtil
diff --git a/src/KingSystem/Utils/Byaml/ByamlStringTableIter.cpp b/src/KingSystem/Utils/Byaml/ByamlStringTableIter.cpp
new file mode 100644
index 00000000..f55e69c8
--- /dev/null
+++ b/src/KingSystem/Utils/Byaml/ByamlStringTableIter.cpp
@@ -0,0 +1,50 @@
+#include "KingSystem/Utils/Byaml/ByamlStringTableIter.h"
+#include "KingSystem/Utils/Byaml/Byaml.h"
+#include "KingSystem/Utils/Byaml/ByamlLocal.h"
+
+namespace al {
+
+ByamlStringTableIter::ByamlStringTableIter(const u8* data) {
+ mData = data;
+}
+
+ByamlStringTableIter::ByamlStringTableIter(const ByamlStringTableIter& other) {
+ mData = other.mData;
+}
+
+const char* ByamlStringTableIter::getString(s32 index) const {
+ const u32* string_offset_array = getStringOffsetArray();
+ return reinterpret_cast<const char*>(&mData[string_offset_array[index]]);
+}
+
+s32 ByamlStringTableIter::findStringIndex(const char* string) const {
+ const u32* string_offset_array = getStringOffsetArray();
+ u32 table_size = ByamlLocalUtil::getContainerSize(mData);
+ if (table_size == 0) {
+ return -1;
+ }
+
+ // Binary Search
+ s32 start = 0;
+ s32 end = table_size;
+ s32 index;
+ while (true) {
+ if (start >= end) {
+ return -1;
+ }
+
+ index = (start + end) / 2;
+ const char* str = reinterpret_cast<const char*>(&mData[string_offset_array[index]]);
+ s32 result = std::strcmp(string, str);
+ if (result == 0)
+ break;
+ if (result > 0)
+ start = index + 1;
+ else if (result < 0)
+ end = index;
+ }
+
+ return index;
+}
+
+} // namespace al
diff --git a/src/KingSystem/Utils/Byaml/ByamlStringTableIter.h b/src/KingSystem/Utils/Byaml/ByamlStringTableIter.h
new file mode 100644
index 00000000..5e397ab4
--- /dev/null
+++ b/src/KingSystem/Utils/Byaml/ByamlStringTableIter.h
@@ -0,0 +1,27 @@
+#pragma once
+
+#include <basis/seadTypes.h>
+
+namespace al {
+
+class ByamlStringTableIter {
+public:
+ explicit ByamlStringTableIter(const u8* data);
+ ByamlStringTableIter(const ByamlStringTableIter& other);
+
+ const char* getString(s32 index) const;
+ s32 findStringIndex(const char* string) const;
+
+ bool isValid() const { return mData != nullptr; }
+
+ const u32* getStringOffsetArray() const {
+ return reinterpret_cast<const u32*>(&mData[TableOffset]);
+ }
+
+private:
+ const u8* mData;
+
+ static constexpr u32 TableOffset = 4u;
+};
+
+} // namespace al \ No newline at end of file
diff --git a/src/KingSystem/Utils/ByamlUtil.cpp b/src/KingSystem/Utils/Byaml/ByamlUtil.cpp
index 6c46fff5..ef0df072 100644
--- a/src/KingSystem/Utils/ByamlUtil.cpp
+++ b/src/KingSystem/Utils/Byaml/ByamlUtil.cpp
@@ -1,4 +1,4 @@
-#include "KingSystem/Utils/Byaml.h"
+#include "KingSystem/Utils/Byaml/Byaml.h"
namespace al {
diff --git a/src/KingSystem/Utils/ByamlLocal.cpp b/src/KingSystem/Utils/ByamlLocal.cpp
deleted file mode 100644
index e981e804..00000000
--- a/src/KingSystem/Utils/ByamlLocal.cpp
+++ /dev/null
@@ -1 +0,0 @@
-#include "KingSystem/Utils/ByamlLocal.h"
diff --git a/src/KingSystem/Utils/ByamlLocal.h b/src/KingSystem/Utils/ByamlLocal.h
deleted file mode 100644
index f10c68b8..00000000
--- a/src/KingSystem/Utils/ByamlLocal.h
+++ /dev/null
@@ -1,16 +0,0 @@
-#pragma once
-
-#include <basis/seadTypes.h>
-
-namespace alByamlLocalUtil {
-
-const char* getDataTypeString(s32 type);
-
-const u8* getHashKeyTable(const u8* data);
-const u8* getStringTable(const u8* data);
-
-bool verifiByaml(const u8* data);
-bool verifiByamlHeader(const u8* data);
-bool verifiByamlStringTable(const u8* data);
-
-} // namespace alByamlLocalUtil
diff --git a/src/KingSystem/Utils/CMakeLists.txt b/src/KingSystem/Utils/CMakeLists.txt
index 1fa59cff..45b8ecdd 100644
--- a/src/KingSystem/Utils/CMakeLists.txt
+++ b/src/KingSystem/Utils/CMakeLists.txt
@@ -21,11 +21,20 @@ target_sources(uking PRIVATE
Thread/TaskThread.cpp
Thread/TaskThread.h
- Byaml.cpp
- Byaml.h
- ByamlLocal.cpp
- ByamlLocal.h
- ByamlUtil.cpp
+ Byaml/Byaml.cpp
+ Byaml/Byaml.h
+ Byaml/ByamlArrayIter.cpp
+ Byaml/ByamlArrayIter.h
+ Byaml/ByamlData.cpp
+ Byaml/ByamlData.h
+ Byaml/ByamlStringTableIter.cpp
+ Byaml/ByamlStringTableIter.h
+ Byaml/ByamlHashIter.cpp
+ Byaml/ByamlHashIter.h
+ Byaml/ByamlLocal.cpp
+ Byaml/ByamlLocal.h
+ Byaml/ByamlUtil.cpp
+
Debug.h
FixedString.h
HashUtil.h
diff --git a/src/KingSystem/Utils/ParamIO.h b/src/KingSystem/Utils/ParamIO.h
index 58f14e55..820cdc76 100644
--- a/src/KingSystem/Utils/ParamIO.h
+++ b/src/KingSystem/Utils/ParamIO.h
@@ -16,12 +16,13 @@ public:
bool applyResourceUpdate(const char* data, const char* data1);
u32 getIdx() const { return mIdx; }
- const sead::SafeString& getId() const { return mId; }
+ sead::BufferedSafeString& getPath() { return mPath; }
+ const sead::BufferedSafeString& getPath() const { return mPath; }
void setIndex(u32 idx) { mIdx = idx; }
protected:
u32 mIdx = 0x1c;
- sead::FixedSafeString<128> mId;
+ sead::FixedSafeString<128> mPath;
};
KSYS_CHECK_SIZE_NX150(ParamIO, 0x278);