summaryrefslogtreecommitdiff
path: root/src/factories/MtxFactory.cpp
blob: cce6f996737a0db7a421b0114a0d89a3345ce20a (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
201
202
203
204
205
206
207
#include "MtxFactory.h"
#include "spdlog/spdlog.h"

#include "Companion.h"
#include "utils/Decompressor.h"

#define NUM(x) std::dec << std::setfill(' ') << std::setw(6) << x
#define COL(c) std::dec << std::setfill(' ') << std::setw(3) << c

ExportResult MtxHeaderExporter::Export(std::ostream &write, std::shared_ptr<IParsedData> raw, std::string& entryName, YAML::Node &node, std::string* replacement) {
    const auto symbol = GetSafeNode(node, "symbol", entryName);

    if(Companion::Instance->IsOTRMode()){
        write << "static const char " << symbol << "[] = \"__OTR__" << (*replacement) << "\";\n\n";
        return std::nullopt;
    }

    write << "extern Mtx " << symbol << "[];\n";
    return std::nullopt;
}

ExportResult MtxCodeExporter::Export(std::ostream &write, std::shared_ptr<IParsedData> raw, std::string& entryName, YAML::Node &node, std::string* replacement ) {
    auto m = std::static_pointer_cast<MtxData>(raw)->mMtxs;
    const auto symbol = GetSafeNode(node, "symbol", entryName);
    auto offset = GetSafeNode<uint32_t>(node, "offset");

    if (IS_SEGMENTED(offset)) {
        offset = SEGMENT_OFFSET(offset);
    }

    if (Companion::Instance->IsDebug()) {
        if (IS_SEGMENTED(offset)) {
            offset = SEGMENT_OFFSET(offset);
        }
        write << "// 0x" << std::hex << std::uppercase << offset << "\n";
    }
    
    #define fiveFourSpaceTabs fourSpaceTab << fourSpaceTab << fourSpaceTab << fourSpaceTab << fourSpaceTab << "   "

    /**
     * toFixedPointMatrix(1.0, 0.0, 0.0, 0.0,
     *                    0.0, 1.0, 0.0, 0.0,
     *                    0.0, 0.0, 1.0, 0.0,
     *                    0.0, 0.0, 0.0, 1.0);
     */
    
    write << "Mtx " << symbol << "[] = {\n";

    for (int i = 0; i < m.size(); ++i) {

        write << fourSpaceTab << "toFixedPointMatrix(";

        for (int j = 0; j < 16; ++j) {

            // Turn 1, 3, and 6 into 1.0, 3.0, and 6.0. Unless it has a decimal number then leave it alone.
            if (std::abs(m[i].mtx[j] - static_cast<int>(m[i].mtx[j])) < 1e-6) {
                write << std::fixed << std::setprecision(1) << m[i].mtx[j];
            } else {
                write << std::fixed << std::setprecision(6) << m[i].mtx[j];
            }
            
            // Add comma for all but the last arg
            if (j < 15) {
                write << ", ";
            }

            // Add closing bracket for last arg in matrix
            if (j == 15) {
                write << "),\n";

                // Do not add an extra \n on the last iteration.
                if (i < m.size() - 1) {
                    write << "\n";
                }
                break;
            }
            
            // Add lots of spaces for start of a new line
            if ((j + 1) % 4 == 0) {
                write << "\n" << fiveFourSpaceTabs;
            }
        }
    }

    write << "};\n";

    if (Companion::Instance->IsDebug()) {
        write << "// count: " << std::to_string(m.size()) << " Mtxs\n";
        write << "// 0x" << std::hex << std::uppercase << (offset + (sizeof(MtxRaw) * m.size())) << "\n";
    }

    write << "\n";

    #undef fiveFourSpaceTabs

    return offset + m.size() * sizeof(MtxRaw);
}

ExportResult MtxBinaryExporter::Export(std::ostream &write, std::shared_ptr<IParsedData> raw, std::string& entryName, YAML::Node &node, std::string* replacement ) {
    auto mtx = std::static_pointer_cast<MtxData>(raw);
    auto writer = LUS::BinaryWriter();

    WriteHeader(writer, LUS::ResourceType::Matrix, 0);
    writer.Write((uint32_t) mtx->mMtxs.size());
    for(auto m : mtx->mMtxs) {
        writer.Write(m.mtx[0]);
        writer.Write(m.mtx[1]);
        writer.Write(m.mtx[2]);
        writer.Write(m.mtx[3]);
        writer.Write(m.mtx[4]);
        writer.Write(m.mtx[5]);
        writer.Write(m.mtx[6]);
        writer.Write(m.mtx[7]);
        writer.Write(m.mtx[8]);
        writer.Write(m.mtx[9]);
        writer.Write(m.mtx[10]);
        writer.Write(m.mtx[11]);
        writer.Write(m.mtx[12]);
        writer.Write(m.mtx[13]);
        writer.Write(m.mtx[14]);
        writer.Write(m.mtx[15]);
    }
    throw std::runtime_error("Mtx not tested for otr/o2r.");
    writer.Finish(write);
    return std::nullopt;
}

std::optional<std::shared_ptr<IParsedData>> MtxFactory::parse(std::vector<uint8_t>& buffer, YAML::Node& node) {
    auto count = GetSafeNode<size_t>(node, "count");

    auto [_, segment] = Decompressor::AutoDecode(node, buffer);
    LUS::BinaryReader reader(segment.data, count * sizeof(MtxRaw));

    reader.SetEndianness(LUS::Endianness::Big);
    std::vector<MtxRaw> matrix;

    #define FIXTOF(x)      ((double)((x) / 65536.0))

    // Reads the inteer portion, the fractional portion, puts each together into a fixed-point value, and finally converts to float.
    for(size_t i = 0; i < count; i++) {
        // Read the integer portion of the fixed-point value (ex. 4)
        auto i1  = reader.ReadInt16();
        auto i2  = reader.ReadInt16();
        auto i3  = reader.ReadInt16();
        auto i4  = reader.ReadInt16();
        auto i5  = reader.ReadInt16();
        auto i6  = reader.ReadInt16();
        auto i7  = reader.ReadInt16();
        auto i8  = reader.ReadInt16();
        auto i9  = reader.ReadInt16();
        auto i10 = reader.ReadInt16();
        auto i11 = reader.ReadInt16();
        auto i12 = reader.ReadInt16();
        auto i13 = reader.ReadInt16();
        auto i14 = reader.ReadInt16();
        auto i15 = reader.ReadInt16();
        auto i16 = reader.ReadInt16();

        // Read the fractional portion of the fixed-point value (ex. 0.45)
        auto f1  = reader.ReadUInt16();
        auto f2  = reader.ReadUInt16();
        auto f3  = reader.ReadUInt16();
        auto f4  = reader.ReadUInt16();
        auto f5  = reader.ReadUInt16();
        auto f6  = reader.ReadUInt16();
        auto f7  = reader.ReadUInt16();
        auto f8  = reader.ReadUInt16();
        auto f9  = reader.ReadUInt16();
        auto f10 = reader.ReadUInt16();
        auto f11 = reader.ReadUInt16();
        auto f12 = reader.ReadUInt16();
        auto f13 = reader.ReadUInt16();
        auto f14 = reader.ReadUInt16();
        auto f15 = reader.ReadUInt16();
        auto f16 = reader.ReadUInt16();

        // Place the integer and fractional portions together (ex 4.45) and convert to floating-point
        auto m1  = FIXTOF( (int32_t) ( (i1 << 16) | f1 ) );
        auto m2  = FIXTOF( (int32_t) ( (i2 << 16) | f2 ) );
        auto m3  = FIXTOF( (int32_t) ( (i3 << 16) | f3 ) );
        auto m4  = FIXTOF( (int32_t) ( (i4 << 16) | f4 ) );
        auto m5  = FIXTOF( (int32_t) ( (i5 << 16) | f5 ) );
        auto m6  = FIXTOF( (int32_t) ( (i6 << 16) | f6 ) );
        auto m7  = FIXTOF( (int32_t) ( (i7 << 16) | f7 ) );
        auto m8  = FIXTOF( (int32_t) ( (i8 << 16) | f8 ) );
        auto m9  = FIXTOF( (int32_t) ( (i9 << 16) | f9 ) );
        auto m10 = FIXTOF( (int32_t) ( (i10 << 16) | f10 ) );
        auto m11 = FIXTOF( (int32_t) ( (i11 << 16) | f11 ) );
        auto m12 = FIXTOF( (int32_t) ( (i12 << 16) | f12 ) );
        auto m13 = FIXTOF( (int32_t) ( (i13 << 16) | f13 ) );
        auto m14 = FIXTOF( (int32_t) ( (i14 << 16) | f14 ) );
        auto m15 = FIXTOF( (int32_t) ( (i15 << 16) | f15 ) );
        auto m16 = FIXTOF( (int32_t) ( (i16 << 16) | f16 ) );


        matrix.push_back(MtxRaw({
           m1, m2, m3, m4,
           m5, m6, m7, m8,
           m9, m10, m11, m12,
           m13, m14, m15, m16,
       }));
    }
    
    #undef FIXTOF

    return std::make_shared<MtxData>(matrix);
}