import struct
import array
import struct
import sys

for f in sys.argv[1:]:
    nes = open(f)
    nes.read(4)
    (roms, vroms) = struct.unpack("BB", nes.read(2))
    # print roms, 'roms', vroms, 'vroms'
    nes.read(10)
    for r in range(roms):
        rom = nes.read(16384)
    vrom = nes.read(8192)

if 1:
    import Image
    full = Image.new("L", (128, 128))
    pattern = vrom[4096:8192]
    chars = [None for i in range(256)]
    for ch in range(256):
        cdata = pattern[16*ch:16*ch+16]
        b0 = cdata[:8]
        b1 = cdata[8:]
        def getpix(x, y):
            sh= x & 7
            return (1 & (ord(b0[y]) >> sh)) + 2 * (1 & (ord(b1[y]) >> sh))
        pix4 = [getpix(x,y) for y in range(8) for x in range(8)[::-1]]
        pix8 = [{0:0, 1:0x40, 2:0x80, 3:0xc0}[p] for p in pix4]
        im = Image.fromstring("P", (8,8), array.array('B', pix4).tostring())
        chars[ch] = im
        # full.paste(im, (8 * (ch%16), 8 * (ch/16)))

cpu = array.array('B', 0x10000 * [0])
ppu = array.array('B', 0x4000 * [0])
cpu[0xc000:0x10000] = array.array('B', rom)

def clear():
    for i in range(0x2000, 0x23c0):
        ppu[i] = 0x24
    for i in range(0x23c0, 0x2400):
        ppu[i] = 0x00

def word(a):
    return struct.unpack("<H", cpu[a:a+2])[0]

def expand(addr):
    while cpu[addr] != 0:
        (vp,code) = struct.unpack(">HB", cpu[addr:addr+3].tostring())
        addr += 3
        print "%x %x" % (vp,code)
        vertical = (code & 0x80) != 0
        rle = (code & 0x40) != 0
        length = code & 0x3f
        for i in range(length):
            ppu[vp] = cpu[addr]
            print "    %02x -> %04x" % (cpu[addr], vp)
            if vertical:
                vp += 32
            else:
                vp += 1
            if not rle:
                addr += 1
        if rle:
            addr += 1

import nes

clear()
screens = [word(0xc4a7 + 2 * i) for i in range(6)]
expand(screens[5])

palette = [nes.pal[b] for b in ppu[0x3f00:0x3f10]]
im = Image.new("RGB", (256,224))

for y in range(28):
    print y, 
    for x in range(32):
        ch = ppu[0x2000 + (y * 32) + x]
        attr = ppu[0x23C0 + (x / 4) + (y / 4) * 8]
        if y & 2:
            attr >>= 4
        if x & 2:
            attr >>= 2
        print attr&3,
        p = palette[(attr & 3) * 4:]
        pal = palette[0] + p[1] + p[2] + p[3] + (252 * 3) * (0,)
        chars[ch].putpalette(pal)
        im.paste(chars[ch], (8 * x, 8 * y))
    print
im.save("out.png")

if 1:
    import memory
    m = memory.Memory(cpu[0xc000:].tostring(), 0xc000)
    (vb,reset,) = struct.unpack("<HH", cpu[0xFFFa:0xfffe])
    starts = [vb, reset]
    m.add_symbol(vb, 'VBLANK')
    m.add_symbol(reset, 'START')
    m.trace_code(starts)
    m.dis()
