Last active
July 8, 2023 10:36
-
-
Save Slipyx/706d7cba8847e2c2de270baee79239aa to your computer and use it in GitHub Desktop.
A Sega Genesis/Megadrive ROM checksum validator.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
** A Sega Genesis/Megadrive ROM checksum validator. | |
** Reads existing checksum and then calculates the valid one. | |
** Attempts to fix if existing was not valid. | |
*/ | |
#include <stdlib.h> | |
#include <stdio.h> | |
#include <stdint.h> | |
#define CS_OFFS 398 // 256 + 142 | |
int main( int argc, char** argv ) { | |
if ( argc < 2 ) { | |
fprintf( stderr, "No rom file specified!\n" ); | |
return EXIT_FAILURE; | |
} | |
FILE* romFile = fopen( argv[1], "rb+" ); | |
if ( romFile == NULL ) { | |
fprintf( stderr, "File not found!\n" ); | |
return EXIT_FAILURE; | |
} | |
fseek( romFile, 0, SEEK_END ); | |
uint32_t chekSize = ftell( romFile ); | |
// check for valid size | |
// 128K - 4M and 128K aligned | |
if ( chekSize == 0 || chekSize > 0x00400000 || chekSize % (128*1024) != 0 ) { | |
fprintf( stderr, "Invalid file size!\n" ); | |
fclose( romFile ); romFile = NULL; | |
return EXIT_FAILURE; | |
} | |
// read existing cheksum | |
uint16_t prev_cs = 0; | |
fseek( romFile, CS_OFFS, SEEK_SET ); | |
fread( &prev_cs, 2, 1, romFile ); | |
// swap | |
prev_cs = (uint16_t)((prev_cs<<8)|(prev_cs>>8)); | |
printf( "Existing checksum: 0x%04x\n", prev_cs ); | |
// skip header | |
fseek( romFile, 512, SEEK_SET ); | |
chekSize -= 512; | |
//printf( "%u\n", chekSize ); | |
uint16_t checksum = 0; // actual | |
// calculate valid | |
while ( chekSize > 0 ) { | |
uint8_t cc; | |
fread( &cc, 1, 1, romFile ); | |
checksum += (uint16_t)(cc * 256); | |
fread( &cc, 1, 1, romFile ); | |
checksum += cc; | |
chekSize -= 2; | |
} | |
printf( "Valid checksum: 0x%04x\n", checksum ); | |
//return 0; | |
// fix if existing not valid | |
if ( prev_cs != checksum ) { | |
printf( "Existing checksum was not valid! Fixing...\n" ); | |
// swap | |
checksum = (uint16_t)((checksum<<8)|(checksum>>8)); | |
fseek( romFile, CS_OFFS, SEEK_SET ); | |
fwrite( &checksum, 2, 1, romFile ); | |
} else { | |
printf( "Existing checksum is valid! Nothing to do here!\n" ); | |
} | |
fclose( romFile ); romFile = NULL; | |
return EXIT_SUCCESS; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment