summaryrefslogtreecommitdiff
path: root/src/KingSystem/Utils/Byaml/Byaml.h
blob: fe715c3d88536648d7566c9dbd6e4d17302d2cf7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
#pragma once

/// BYML / BYAML utilities which seem to have been imported from Super Mario Odyssey.

#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,

    String = 0xa0,
    Binary = 0xa1,

    Array = 0xc0,
    Hash = 0xc1,
    StringTable = 0xc2,

    Bool = 0xd0,
    Int = 0xd1,
    Float = 0xd2,
    UInt = 0xd3,
    Int64 = 0xd4,
    UInt64 = 0xd5,
    Double = 0xd6,

    Null = 0xff,
};

class ByamlIter {
public:
    ByamlIter();
    explicit ByamlIter(const u8* data);
    ByamlIter(const u8* data, const u8* root_node);
    ByamlIter(const ByamlIter& other);

    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;
    bool isTypeContainer() const;

    bool isExistKey(const char* key) const;
    s32 getKeyIndex(const char* key) const;

    s32 getSize() 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;
    bool tryGetIterByKey(ByamlIter* iter, const char* key) const;
    bool tryGetIterAndKeyNameByIndex(ByamlIter* iter, const char** key, s32 index) const;

    bool tryGetStringByIndex(const char** value, s32 index) const;
    bool tryGetStringByKey(const char** value, const char* key) const;
    bool tryConvertString(const char** value, const ByamlData* data) const;

    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;
    bool tryConvertUInt(u32* value, const ByamlData* data) const;

    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;
};

struct ByamlHeader {
    u16 getTag() const;
    bool isInvertHeader() 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;
    u32 hash_key_table_offset;
    u32 string_table_offset;
    u32 data_offset;
};
KSYS_CHECK_SIZE_NX150(ByamlHeader, 0x10);

struct ByamlContainerHeader {
    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;
};

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);
bool tryGetByamlV3f(sead::Vector3f* value, const ByamlIter& iter, const char* key);

}  // namespace al