ines-info.py with syntax coloring

This HTML file was generated with Kalle's syntaxcolor.py


   1"""
   2Prints information of an iNES ROM file (.nes).
   3By Kalle (http://qalle.net)
   4Sources:
   5    http://wiki.nesdev.com/w/index.php/INES
   6    http://wiki.nesdev.com/w/index.php/List_of_mappers
   7"""
   8
   9import sys
  10
  11MAPPERS = {
  12    0: "NROM",
  13    1: "SxROM, MMC1",
  14    2: "UxROM",
  15    3: "CNROM",
  16    4: "TxROM, MMC3, MMC6",
  17    5: "ExROM, MMC5",
  18    7: "AxROM",
  19    9: "PxROM, MMC2",
  20    10: "FxROM, MMC4",
  21    11: "Color Dreams",
  22    13: "CPROM",
  23    15: "100-in-1 Contra Function 16",
  24    16: "Bandai EPROM (24C02)",
  25    18: "Jaleco SS8806",
  26    19: "Namco 163",
  27    21: "VRC4a, VRC4c",
  28    22: "VRC2a",
  29    23: "VRC2b, VRC4e",
  30    24: "VRC6a",
  31    25: "VRC4b, VRC4d",
  32    26: "VRC6b",
  33    34: "BNROM, NINA-001",
  34    64: "RAMBO-1",
  35    66: "GxROM, MxROM",
  36    68: "After Burner",
  37    69: "FME-7, Sunsoft 5B",
  38    71: "Camerica/Codemasters",
  39    73: "VRC3",
  40    74: "Pirate MMC3 derivative",
  41    75: "VRC1",
  42    76: "Namco 109 variant",
  43    79: "NINA-03/NINA-06",
  44    85: "VRC7",
  45    86: "JALECO-JF-13",
  46    94: "Senjou no Ookami",
  47    105: "NES-EVENT",
  48    113: "NINA-03/NINA-06??",
  49    118: "TxSROM, MMC3",
  50    119: "TQROM, MMC3",
  51    159: "Bandai EPROM (24C01)",
  52    166: "SUBOR",
  53    167: "SUBOR",
  54    180: "Crazy Climber",
  55    185: "CNROM with protection diodes",
  56    192: "Pirate MMC3 derivative",
  57    206: "DxROM, Namco 118 / MIMIC-1",
  58    210: "Namco 175 and 340",
  59    228: "Action 52",
  60    232: "Camerica/Codemasters Quattro",
  61}
  62
  63HELP_TEXT = """\
  64Prints information of an iNES ROM file (.nes).
  65Argument: filename.\
  66"""
  67
  68def read_ines_file(handle):
  69    fileSize = handle.seek(0, 2)
  70    if fileSize < 16:
  71        exit("Invalid iNES file (less than 16 bytes).")
  72
  73    handle.seek(0)
  74    header = handle.read(16)
  75
  76    if header[:4] != b"NES\x1a":
  77        exit("Invalid iNES file (invalid identifier).")
  78
  79    # detect header version (see NESDev Wiki)
  80    # "old" = archaic iNES, "new" = all other versions
  81    newHeader = (
  82        header[7] & 0x0C == 0x08 or
  83        header[7] & 0x0C == 0x00 and max(header[12:]) == 0x00
  84    )
  85
  86    prgROMSize = header[4] * 16  # in kB
  87    chrROMSize = header[5] * 8  # in kB
  88    mapper = header[6] >> 4
  89    if newHeader:
  90        mapper |= header[7] & 0xF0
  91    fourScreenVRAM = bool(header[6] >> 3 & 0x1)
  92    saveRAM = bool(header[6] >> 1 & 0x1)
  93    verticalMirroring = bool(header[6] & 0x1)
  94
  95    if fourScreenVRAM:
  96        mirroringDesc = "four-screen"
  97    elif verticalMirroring:
  98        mirroringDesc = "vertical"
  99    else:
 100        mirroringDesc = "horizontal"
 101
 102    saveRAMDesc = ("yes" if saveRAM else "no")
 103
 104    print("PRG-ROM size: {:d} kB".format(prgROMSize))
 105    print("CHR-ROM size: {:d} kB".format(chrROMSize))
 106    print("mapper: #{:d} ({:s})".format(mapper, MAPPERS.get(mapper, "?")))
 107    print("Name Table mirroring: {:s}".format(mirroringDesc))
 108    print("contains battery-backed RAM: {:s}".format(saveRAMDesc))
 109
 110def main():
 111    if len(sys.argv) != 2:
 112        exit(HELP_TEXT)
 113
 114    file = sys.argv[1]
 115
 116    try:
 117        with open(file, "rb") as handle:
 118            read_ines_file(handle)
 119    except FileNotFoundError:
 120        exit("File not found.")
 121    except PermissionError:
 122        exit("Permission denied.")
 123    except OSError:
 124        exit("File read error.")
 125
 126if __name__ == "__main__":
 127    main()