Created
January 2, 2016 03:55
-
-
Save Qix-/8b651c93fbf05a904fee to your computer and use it in GitHub Desktop.
NES Header Checker
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
#include <stdio.h> | |
#include <stdlib.h> | |
#include <string.h> | |
#include "ines-header.h" | |
#define max(a,b) \ | |
({ __typeof__ (a) _a = (a); \ | |
__typeof__ (b) _b = (b); \ | |
_a > _b ? _a : _b; }) | |
static const char magic[4] = { 0x4E, 0x45, 0x53, 0x1A }; | |
const char * toBool(unsigned char val) { | |
return val ? "Yes" : "No"; | |
} | |
const char * getArrangement(unsigned char low, unsigned char high) { | |
char val = (high << 1) | low; | |
switch (val) { | |
case 0: return "Vertical Arrangement / Horizontal Mirroring"; | |
case 1: return "Horizontal Arrangement / Vertical Mirroring"; | |
case 2: return "2x2 (4 Page) Grid (No Mirroring)"; | |
default: return "UNKNOWN (Bad Value)"; | |
} | |
} | |
const char getMapper(unsigned char low, unsigned char high) { | |
return (high << 4) | low; | |
} | |
const char * getTVSystem(unsigned char system) { | |
return system ? "PAL" : "NTSC"; | |
} | |
int main(int argc, const char **argv) { | |
if (argc != 2) { | |
fprintf(stderr, "usage: %s <.NES rom or header binary>\n", argv[0]); | |
return 1; | |
} | |
FILE *file = fopen(argv[1], "rb"); | |
if (!file) { | |
fprintf(stderr, "could not open file"); | |
return 1; | |
} | |
INESHeader header; | |
size_t count = fread(&header, 1, sizeof(header), file); | |
if (count != sizeof(header)) { | |
fclose(file); | |
fprintf(stderr, "could not read file; is it 16 bytes long?\n"); | |
return 2; | |
} | |
fclose(file); | |
if (memcmp(&header.magic, &magic, 4) != 0) { | |
fprintf(stderr, "given file has an invalid magic number\n"); | |
return 3; | |
} | |
printf( | |
"Mapper:\t\t%03d\n" | |
"TV System:\t%s\n" | |
"PRG ROM size:\t%dKb (%d 16Kb banks)\n" | |
"PRG RAM size:\t%dKb (%d 8Kb banks)\n" | |
"CHR ROM size:\t%dKb (%d 8Kb banks)\n" | |
"Arrangement:\t%s\n" | |
"Trainer?:\t%s\n" | |
"Battery RAM?\t%s\n" | |
"iNES2 Header?\t%s\n" | |
"Playchoice-10?\t%s\n" | |
"VSUnisystem?\t%s\n", | |
getMapper(header.mapperLow, header.mapperHigh), | |
getTVSystem(header.tvSystem), | |
header.prgRomSize * 16, header.prgRomSize, | |
max(1, header.prgRamSize) * 8, max(1, header.prgRamSize), | |
header.chrRomSize * 8, header.chrRomSize, | |
getArrangement(header.arrangementLow, header.arrangementHigh), | |
toBool(header.hasTrainer), | |
toBool(header.hasBatteryRam), | |
toBool(header.ines2Header), | |
toBool(header.playchoice10), | |
toBool(header.vsUnisystem)); | |
return 0; | |
} |
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
typedef struct __attribute__((packed)) { | |
unsigned char magic[4]; | |
unsigned char prgRomSize; | |
unsigned char chrRomSize; | |
unsigned char arrangementLow : 1; | |
unsigned char hasBatteryRam : 1; | |
unsigned char hasTrainer : 1; | |
unsigned char arrangementHigh : 1; | |
unsigned char mapperLow : 4; | |
unsigned char vsUnisystem : 1; | |
unsigned char playchoice10 : 1; | |
unsigned char ines2Header : 2; | |
unsigned char mapperHigh : 4; | |
unsigned char prgRamSize; | |
unsigned char tvSystem : 1; | |
unsigned char reserved : 7; | |
unsigned char reservedZeroFill[6]; | |
} INESHeader; | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment