Skip to content

Instantly share code, notes, and snippets.

@Slipyx
Last active July 8, 2023 10:36
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Slipyx/706d7cba8847e2c2de270baee79239aa to your computer and use it in GitHub Desktop.
Save Slipyx/706d7cba8847e2c2de270baee79239aa to your computer and use it in GitHub Desktop.
A Sega Genesis/Megadrive ROM checksum validator.
/*
** 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