Repository navigation
Expand file tree
/
Copy pathMain.cpp
More file actions
154 lines (122 loc) · 4.3 KB
/
Copy pathMain.cpp
File metadata and controls
154 lines (122 loc) · 4.3 KB
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
#include "R4i.hpp"
#include <fstream>
#include <iostream>
#include <string>
#include <vector>
using namespace r4i;
static std::vector<u8> readFile(std::string const &path) {
std::vector<u8> buffer;
std::ifstream h(path, std::ios::ate | std::ios::binary);
if (h.is_open()) {
buffer.resize(h.tellg());
h.seekg(0, h.beg);
h.read(reinterpret_cast<char *>(buffer.data()), buffer.size());
}
return buffer;
}
static bool writeFile(std::string const &path,
std::span<u8 const> const buffer) {
std::ofstream h(path, std::ios::binary);
if (h.is_open()) {
h.write(reinterpret_cast<char const *>(buffer.data()), buffer.size());
return true;
}
return false;
}
static void parseROM(std::vector<u8> &buffer, std::span<u8> &arm9,
std::span<u8> &arm7) {
if (buffer.size() < 0x40)
return;
auto const arm9off = *reinterpret_cast<u32 *>(buffer.data() + 0x20);
auto const arm9size = *reinterpret_cast<u32 *>(buffer.data() + 0x2C);
if (arm9off > buffer.size() || (arm9off + arm9size) > buffer.size())
return;
auto const arm7off = *reinterpret_cast<u32 *>(buffer.data() + 0x30);
auto const arm7size = *reinterpret_cast<u32 *>(buffer.data() + 0x3C);
if (arm7off > buffer.size() || (arm7off + arm7size) > buffer.size())
return;
arm9 = {buffer.data() + arm9off, arm9size};
arm7 = {buffer.data() + arm7off, arm7size};
}
int main(int argc, char const *const *argv) {
if (argc < 3) {
std::cout << "USAGE: path/to/R4.dat path/to/R4iLoader.dat\n";
return 1;
}
auto r4 = readFile(argv[1]);
if (r4.empty()) {
std::cout << "ERROR: Could not load R4.dat!\n";
return 2;
}
auto loader = readFile(argv[2]);
if (loader.empty()) {
std::cout << "ERROR: Could not load R4iLoader.dat!\n";
return 3;
}
std::span<u8> arm9;
std::span<u8> arm7;
parseROM(r4, arm9, arm7);
if (arm9.empty() || arm7.empty()) {
std::cout << "ERROR: R4.dat parsing failed!\n";
return 4;
}
std::span<u8> ldr9;
std::span<u8> ldr7;
parseROM(loader, ldr9, ldr7);
if (ldr9.empty() || ldr7.empty()) {
std::cout << "ERROR: R4iLoader.dat parsing failed!\n";
return 5;
}
auto secretArea = findSecretArea(arm9);
if (!secretArea) {
std::cout << "ERROR: Could not find secret area!\n";
return 6;
}
std::cout << "Secret area:\n";
std::cout << std::hex;
// Checksum9
auto const checksum9 = decodeU16(secretArea->arm9chk);
auto const computed9 = genChecksum9(arm9);
std::cout << "- checksum9: " << checksum9 << '\n';
std::cout << "- computed: " << computed9 << '\n';
if (checksum9 != computed9)
std::cout << "DOES NOT MATCH\n";
std::cout << '\n';
// Checksum7
auto const checksum7 = decodeU16(secretArea->arm7chk);
auto const computed7 = genChecksum7(arm7);
std::cout << "- checksum7: " << checksum7 << '\n';
std::cout << "- computed: " << computed7 << '\n';
if (checksum7 != computed7)
std::cout << "DOES NOT MATCH\n";
std::cout << '\n';
// ChecksumLdr
auto const checksumLdr = decodeU16(secretArea->ldrchk);
auto const computedLdr = genChecksumLdr(ldr9, ldr7);
std::cout << "- checksumLdr: " << checksumLdr << '\n';
std::cout << "- computed: " << computedLdr << '\n';
if (checksumLdr != computedLdr)
std::cout << "DOES NOT MATCH\n";
std::cout << '\n';
// Area checksum
auto checksumArea = (static_cast<u32>(secretArea->areachk_2) << 16) | secretArea->areachk_1;
auto const computedArea =
genAreaChk(encodeU16(computed9), encodeU16(computed7), encodeU16(computedLdr));
std::cout << "- checksumArea: " << checksumArea << '\n';
std::cout << "- computed: " << computedArea << '\n';
if (checksumArea != computedArea)
std::cout << "DOES NOT MATCH\n";
std::cout << '\n';
// FIX.
secretArea->arm9chk = encodeU16(computed9);
secretArea->arm7chk = encodeU16(computed7);
secretArea->ldrchk = encodeU16(computedLdr);
secretArea->areachk_2 = static_cast<u16>(computedArea >> 16);
secretArea->areachk_1 = static_cast<u16>(computedArea & 0xFFFF);
if (!writeFile("R4-fixed.dat", r4)) {
std::cout << "ERROR: Could not save R4-fixed.dat!\n";
return 7;
}
std::cout << "File fixed: R4-fixed.dat\n";
return 0;
}