diff options
| author | notyourav <65437533+notyourav@users.noreply.github.com> | 2020-11-16 15:49:02 -0800 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2020-11-16 15:49:02 -0800 |
| commit | d4f80d7cf97641742dd56cabc0b1d503cfdf7b0d (patch) | |
| tree | 05b09142b74869f74779a00deff410019b8dcaac /src/KingSystem/Utils | |
| parent | 8205744abcae5784138629038976f2449269a81f (diff) | |
| parent | b0498a15bf6f1782f1429ffbd0b03c187f61d7c9 (diff) | |
Merge branch 'master' into placement
Diffstat (limited to 'src/KingSystem/Utils')
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); |
