#include #include enum { AROM = 0x00, ALOGO = 0x04, ATITLE = 0xA0, AGAME = 0xAC, AMAKER = 0xB0, AFIXED = 0xB2, AUNIT = 0xB3, ADEVTYPE = 0xB4, ARES0 = 0xB5, AVERSION = 0xBC, ACKSUM = 0xBD, ARES1 = 0xBE, AEND = 0xC0 }; typedef struct Header Header; struct Header { u32int start; /* ARM entry point branch opcode */ u8int logo[156]; /* the Nintendo logo */ u8int title[12]; u32int game; u16int maker; u8int fixed; /* 0x96 */ u8int unit; u8int devtype; u8int r0[7]; /* reserved area */ u8int version; u8int cksum; u8int r1[2]; /* reserved area */ }; u8int nintendō[156] = { 0x24,0xFF,0xAE,0x51,0x69,0x9A,0xA2,0x21,0x3D,0x84,0x82,0x0A,0x84,0xE4,0x09,0xAD, 0x11,0x24,0x8B,0x98,0xC0,0x81,0x7F,0x21,0xA3,0x52,0xBE,0x19,0x93,0x09,0xCE,0x20, 0x10,0x46,0x4A,0x4A,0xF8,0x27,0x31,0xEC,0x58,0xC7,0xE8,0x33,0x82,0xE3,0xCE,0xBF, 0x85,0xF4,0xDF,0x94,0xCE,0x4B,0x09,0xC1,0x94,0x56,0x8A,0xC0,0x13,0x72,0xA7,0xFC, 0x9F,0x84,0x4D,0x73,0xA3,0xCA,0x9A,0x61,0x58,0x97,0xA3,0x27,0xFC,0x03,0x98,0x76, 0x23,0x1D,0xC7,0x61,0x03,0x04,0xAE,0x56,0xBF,0x38,0x84,0x00,0x40,0xA7,0x0E,0xFD, 0xFF,0x52,0xFE,0x03,0x6F,0x95,0x30,0xF1,0x97,0xFB,0xC0,0x85,0x60,0xD6,0x80,0x25, 0xA9,0x63,0xBE,0x03,0x01,0x4E,0x38,0xE2,0xF9,0xA2,0x34,0xFF,0xBB,0x3E,0x03,0x44, 0x78,0x00,0x90,0xCB,0x88,0x11,0x3A,0x94,0x65,0xC0,0x7C,0x63,0x87,0xF0,0x3C,0xAF, 0xD6,0x25,0xE4,0x8B,0x38,0x0A,0xAC,0x72,0x21,0xD4,0xF8,0x07 }; char cksum(Header *h) { int n; char c, *p; c = 0; p = (char*)h; p += ATITLE; for(n = 0; n < ACKSUM-ATITLE; n++) c += *p++; return -(0x19+c); } void usage(void) { fprint(2, "usage: %s [-t title] [-g gamecode] [-m makercode] [-v version] rom\n", argv0); exits("usage"); } void main(int argc, char *argv[]) { Header h; char *title; u32int gcode; u16int mcode; u8int vcode; int fd; title = nil; gcode = mcode = vcode = 0; ARGBEGIN{ case 't': title = EARGF(usage()); break; case 'g': gcode = strtoul(EARGF(usage()), nil, 0); break; case 'm': mcode = strtoul(EARGF(usage()), nil, 0); break; case 'v': vcode = strtoul(EARGF(usage()), nil, 0); break; default: usage(); }ARGEND; if(argc != 1) usage(); fd = open(argv[0], ORDWR); if(fd < 0) sysfatal("open: %r"); memset(&h, 0, sizeof h); if(readn(fd, &h, sizeof(Header)) != sizeof(Header)) sysfatal("readn: %r"); memmove(h.logo, nintendō, sizeof(nintendō)); if(title) memmove(h.title, title, strlen(title) < sizeof(h.title)? strlen(title): sizeof(h.title)); if(gcode) h.game = gcode; if(mcode) h.maker = mcode; h.fixed = 0x96; h.devtype = 0x00; if(vcode) h.version = vcode; h.cksum = cksum(&h); seek(fd, 0, 0); if(write(fd, &h, sizeof(Header)) != sizeof(Header)) sysfatal("write: %r"); close(fd); exits(0); }