Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
MorsGames
GitHub Repository: MorsGames/sm64plus
Path: blob/master/tools/n64cksum.c
7854 views
1
#include <stdio.h>
2
#include <stdlib.h>
3
4
#include "n64cksum.h"
5
#include "utils.h"
6
7
#define N64CKSUM_VERSION "0.1"
8
9
// compute N64 ROM checksums
10
// buf: buffer with extended SM64 data
11
// cksum: two element array to write CRC1 and CRC2 to
12
void n64cksum_calc_6102(unsigned char *buf, unsigned int cksum[]) {
13
uint32_t t2, t3, t4, t6, t7, t8, s0;
14
uint32_t a0, a1, a2, a3;
15
uint32_t v0, v1;
16
uint32_t seed, end_offset, cur_offset, buf_offset;
17
18
// derived from the SM64 boot code
19
seed = 0xF8CA4DDB; // 0x3f * 0x5d588b65;
20
end_offset = 0x100000;
21
cur_offset = 0;
22
buf_offset = 0x1000;
23
seed++;
24
a3 = seed;
25
t2 = seed;
26
t3 = seed;
27
s0 = seed;
28
a2 = seed;
29
t4 = seed;
30
31
do {
32
v0 = read_u32_be(&buf[buf_offset]);
33
v1 = a3 + v0;
34
a1 = v1;
35
if (v1 < a3) {
36
t2++;
37
}
38
v1 = v0 & 0x1F;
39
t7 = 32 - v1;
40
t8 = v0 >> t7;
41
t6 = v0 << v1;
42
a0 = t6 | t8;
43
a3 = a1;
44
t3 ^= v0;
45
s0 += a0;
46
if (a2 < v0) {
47
a2 ^= a3 ^ v0;
48
} else {
49
a2 ^= a0;
50
}
51
cur_offset += 4;
52
t7 = v0 ^ s0;
53
buf_offset += 4;
54
t4 += t7;
55
} while (cur_offset != end_offset);
56
57
cksum[0] = (a3 ^ t2) ^ t3;
58
cksum[1] = (s0 ^ a2) ^ t4;
59
}
60
61
void n64cksum_update_checksums(uint8_t *buf)
62
{
63
unsigned int cksum_offsets[] = {0x10, 0x14};
64
uint32_t read_cksum[2];
65
uint32_t calc_cksum[2];
66
int i;
67
68
// assume CIC-NUS-6102
69
INFO("BootChip: CIC-NUS-6102\n");
70
71
// calculate new N64 header checksum
72
n64cksum_calc_6102(buf, calc_cksum);
73
74
// mimic the n64sums output
75
for (i = 0; i < 2; i++) {
76
read_cksum[i] = read_u32_be(&buf[cksum_offsets[i]]);
77
INFO("CRC%d: 0x%08X ", i+1, read_cksum[i]);
78
INFO("Calculated: 0x%08X ", calc_cksum[i]);
79
if (calc_cksum[i] == read_cksum[i]) {
80
INFO("(Good)\n");
81
} else {
82
INFO("(Bad)\n");
83
}
84
}
85
86
// write checksums into header
87
INFO("Writing back calculated Checksum\n");
88
write_u32_be(&buf[cksum_offsets[0]], calc_cksum[0]);
89
write_u32_be(&buf[cksum_offsets[1]], calc_cksum[1]);
90
}
91
92
#ifdef N64CKSUM_STANDALONE
93
static void print_usage(void)
94
{
95
ERROR("Usage: n64cksum ROM [ROM_OUT]\n"
96
"\n"
97
"n64cksum v" N64CKSUM_VERSION ": N64 ROM checksum calculator\n"
98
"\n"
99
"File arguments:\n"
100
" ROM input ROM file\n"
101
" ROM_OUT output ROM file (default: overwrites input ROM)\n");
102
}
103
104
int main(int argc, char *argv[])
105
{
106
unsigned char *rom_data;
107
char *file_in;
108
char *file_out;
109
long length;
110
long write_length;
111
if (argc < 2) {
112
print_usage();
113
return EXIT_FAILURE;
114
}
115
116
file_in = argv[1];
117
if (argc > 2) {
118
file_out = argv[2];
119
} else {
120
file_out = argv[1];
121
}
122
123
length = read_file(file_in, &rom_data);
124
if (length < 0) {
125
ERROR("Error reading input file \"%s\"\n", file_in);
126
return EXIT_FAILURE;
127
}
128
129
n64cksum_update_checksums(rom_data);
130
131
write_length = write_file(file_out, rom_data, length);
132
133
free(rom_data);
134
135
if (write_length != length) {
136
ERROR("Error writing to output file \"%s\"\n", file_out);
137
return EXIT_FAILURE;
138
}
139
140
return EXIT_SUCCESS;
141
}
142
#endif // N64CKSUM_STANDALONE
143
144