romdump.c 3.42 KB
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define B2S(b) ( (((b)[0^(swapped)] & 0xffL) << 8) | \
                           (((b)[1^(swapped)] & 0xffL) << 0) )

#define B2L(b) ( (((b)[0^(swapped)] & 0xffL) << 24) | \
                           (((b)[1^(swapped)] & 0xffL) << 16) | \
                           (((b)[2^(swapped)] & 0xffL) <<  8) | \
                           (((b)[3^(swapped)] & 0xffL)) )

#define HEADER_MAGIC 0x80371240

extern void swab(const void *from, void *to, ssize_t n);

int swapped;

struct ccode {
    int code;
    char* name;
} ccode[] = {
{ 0x00 , "  (NONE)"},
{ 0x4A , "J (JAPAN)"},
{ 0x37 , "7 (BETA)"},
{ 0x41 , "A (NTSC)"},
{ 0x44 , "D (GERMANY)"},
{ 0x45 , "E (USA)"},
{ 0x46 , "F (FRANCE)"},
{ 0x49 , "I (ITALY)"},
{ 0x50 , "P (EUROPE)"},
{ 0x53 , "S (SPAIN)"},
{ 0x55 , "U (AUSTRALIA)"},
{ 0x58 , "X (PAL)"},
{ 0x59 , "Y (PAL)"},
{ 0, 0},
};

char* find_ccode(long code) {
    int i;
    for (i = 0; ccode[i].name; i++)
	if (code == ccode[i].code) return ccode[i].name;
    return "";
}

int
main(int argc, char **argv)
{
  FILE *f;
  int i;
  unsigned int a, b = 0xffffffff, entry, e = 0xffffffff;
  unsigned char buf[20];
  
  if (argc != 2) {
    fprintf(stderr, "Usage: romdump <rom name>\n");
    return 1;
  }

  f = fopen(argv[1], "rb");
  if (f == NULL) {
    char err[21 + strlen(argv[1])];
    sprintf(err, "Couldn't open file %s", argv[1]);
    perror(err);
    return 1;
  }

  if( fread(buf, 1, 12, f) != 12 ) {
    exit(1);
  }

  if ( B2L(buf) == HEADER_MAGIC ) {
    swapped = 0;
  } else if ( (swapped=1) && B2L(buf) == HEADER_MAGIC ) {
    swapped = 1;
  } else {
    fprintf(stderr, "%s: not a rom file\n", argv[1]);
    exit(1);
  }
  fseek(f, 0, SEEK_SET);
  fread(buf, 1, 4, f);
  printf("header = 0x%lx\n", B2L(buf));
  fread(buf, 1, 4, f);
  printf("clock rate = 0x%lx\n", B2L(buf));
  fread(buf, 1, 4, f);
  printf("boot addr = 0x%x\n", entry = B2L(buf));
  fread(buf, 1, 4, f);
  printf("release = OS %ld%c\n", B2L(buf)>>8,  (int)B2L(buf)&0xff);
  fread(buf, 1, 4, f);
  printf("crc1 = 0x%lx\n", B2L(buf));
  fread(buf, 1, 4, f);
  printf("crc2 = 0x%lx\n", B2L(buf));
  fread(buf, 1, 4, f);
  //printf("u0 = 0x%lx\n", B2L(buf));
  fread(buf, 1, 4, f);
  //printf("u1 = 0x%lx\n", B2L(buf));
  fread(buf, 1, 20, f);
  if (swapped) swab(buf, buf, 20);
  printf("name = %.20s\n", buf);
  fread(buf, 1, 4, f);
  //printf("u3 = 0x%lx\n", B2L(buf));
  fread(buf, 1, 4, f);
  printf("manuf id = 0x%lx (%d)\n", B2L(buf), (int)B2L(buf));
  buf[2] = 0; buf[3] = 0;
  fread(buf, 1, 2, f);
  printf("cart id = 0x%lx\n", B2S(buf));
  fread(buf, 1, 2, f);
  printf("country code = 0x%lx/%s\nrevision = 0x%lx\n", B2S(buf)>>8,
	  find_ccode(B2S(buf)>>8), B2S(buf)&0xff);
  fseek(f, 4096, SEEK_SET);
  for(i = 0; i < 16; i++) {
      fread(buf, 1, 4, f); a = B2L(buf);
      /*               lui t0 */
      if ((a >> 16) == 0x3c08) b = a << 16;
      /*             addui t0                ori t0 */
      else if ((a>>16) == 0x2508 || (a>>16) == 0x3508) b|=(a&0xffff);
      /*                   lui t2 */
      else if ((a>>16) == 0x3c0a) e = a << 16;
      /*		  addui t2             ori t2 */
      else if ((a>>16) == 0x254a || (a>>16) == 0x354a) e|=(a&0xffff);
  }
  printf("boot: bss start 0x%x\n", b);
  printf("boot: text/data size 0x%x (%d)\n", b-entry, b-entry);
  printf("boot: entry 2 0x%x\n", e);
  fseek(f, 0, SEEK_END);
  printf("rom size 0x%lx  %.1fM\n", ftell(f), ftell(f)/(1024.*1024));
  fclose(f);
  return 0;
}