Refactor stadium.c to match pokecrystal

Fixes #106
This commit is contained in:
Rangi
2022-09-30 16:57:20 -04:00
parent c9a8d2f5cf
commit fa90aca18e
+24 -27
View File
@@ -5,24 +5,23 @@
// A matching ROM has 128 banks
#define NUMBANKS 128
// ROM banks are $4000 bytes
// ROM banks are 0x4000 bytes
#define BANKSIZE 0x4000
// A matching ROM is $200000 bytes
// A matching ROM is 2 MB
#define ROMSIZE (NUMBANKS * BANKSIZE)
// ASCII "N64PS3" header
#define N64PS3SIZE 6
uint8_t n64ps3[N64PS3SIZE] = {'N', '6', '4', 'P', 'S', '3'};
// "N64PS3" + 2-byte CRC
#define HEADERSIZE (N64PS3SIZE + 2)
// header + 2-byte half-bank checksums
#define DATASIZE (HEADERSIZE + NUMBANKS * 2 * 2)
// The Game Boy cartridge header stores a global checksum at 0x014E-0x014F
#define GLOBALOFF 0x014E
// ASCII "N64PS3" header (Stadium G/S was the third Japanese Stadium release for N64)
#define N64PS3SIZE 6
uint8_t n64ps3[N64PS3SIZE] = {'N', '6', '4', 'P', 'S', '3'};
// "N64PS3" + 2-byte CRC
#define N64PS3HEADERSIZE (N64PS3SIZE + 2)
// "N64PS3" + 2-byte CRC + per-half-bank 2-byte checksums
#define N64PS3DATASIZE (N64PS3HEADERSIZE + NUMBANKS * 2 * 2)
// The Stadium data is stored at the end of the ROM
#define DATAOFF (ROMSIZE - DATASIZE)
#define N64PS3DATAOFF (ROMSIZE - N64PS3DATASIZE)
// The CRC polynomial value
#define CRC_POLY 0xC387
@@ -34,9 +33,9 @@ uint8_t n64ps3[N64PS3SIZE] = {'N', '6', '4', 'P', 'S', '3'};
file[(off) + 1] = (uint8_t)(((v) & 0x00FF) >> 0); \
} while (0)
uint16_t calculate_checksum(uint16_t checksum, uint8_t *file, int start, int size) {
for (int j = start; j < start + size; j++) {
checksum += file[j];
uint16_t calculate_checksum(uint16_t checksum, uint8_t *file, size_t size) {
for (size_t i = 0; i < size; i++) {
checksum += file[i];
}
return checksum;
}
@@ -44,12 +43,10 @@ uint16_t calculate_checksum(uint16_t checksum, uint8_t *file, int start, int siz
void calculate_checksums(uint8_t *file) {
// Initialize the CRC table
uint16_t crc_table[256];
for (int i = 0; i < 256; i++) {
uint16_t c = i;
for (uint16_t i = 0; i < sizeof(crc_table) / sizeof(*crc_table); i++) {
uint16_t rem = 0;
for (int y = 0; y < 8; y++) {
for (uint16_t y = 0, c = i; y < 8; y++, c >>= 1) {
rem = (rem >> 1) ^ ((rem ^ c) & 1 ? CRC_POLY : 0);
c >>= 1;
}
crc_table[i] = rem;
}
@@ -58,24 +55,24 @@ void calculate_checksums(uint8_t *file) {
SET_U16BE(file, GLOBALOFF, 0);
// Initialize the Stadium data (this should be free space anyway)
memset(file + DATAOFF, 0, DATASIZE);
memcpy(file + DATAOFF, n64ps3, N64PS3SIZE);
memset(file + N64PS3DATAOFF, 0, N64PS3DATASIZE);
memcpy(file + N64PS3DATAOFF, n64ps3, N64PS3SIZE);
// Calculate the half-bank checksums
for (int i = 0; i < NUMBANKS * 2; i++) {
uint16_t checksum = calculate_checksum(CRC_INIT, file, i * BANKSIZE / 2, BANKSIZE / 2);
SET_U16BE(file, DATAOFF + HEADERSIZE + i * 2, checksum);
for (size_t i = 0; i < NUMBANKS * 2; i++) {
uint16_t checksum = calculate_checksum(CRC_INIT, file + i * BANKSIZE / 2, BANKSIZE / 2);
SET_U16BE(file, N64PS3DATAOFF + N64PS3HEADERSIZE + i * 2, checksum);
}
// Calculate the CRC of the half-bank checksums
uint16_t crc = CRC_INIT;
for (int i = DATAOFF + HEADERSIZE; i < DATAOFF + DATASIZE; i++) {
for (size_t i = N64PS3DATAOFF + N64PS3HEADERSIZE; i < N64PS3DATAOFF + N64PS3DATASIZE; i++) {
crc = (crc >> 8) ^ crc_table[(crc & 0xFF) ^ file[i]];
}
SET_U16BE(file, DATAOFF + HEADERSIZE - 2, crc);
SET_U16BE(file, N64PS3DATAOFF + N64PS3HEADERSIZE - 2, crc);
// Calculate the global checksum
uint16_t globalsum = calculate_checksum(0, file, 0, ROMSIZE);
uint16_t globalsum = calculate_checksum(0, file, ROMSIZE);
SET_U16BE(file, GLOBALOFF, globalsum);
}