#!/usr/bin/env python
# I, Danny Milosavljevic, hereby place this file into the public domain.

# Diassembler.

import sys
import getopt
import emulators
import emulators.chips.cpu
from emulators import symboltables
from emulators.chips import memory
from emulators.chips.symbols import *

class ImageMemory(memory.Memory):
    def __init__(self, file, base_offset, symbol_table):
        memory.Memory.__init__(self)
        self.base_offset = base_offset
        self.file = file
        self.file.seek(0, 2)
        self.size = self.file.tell()
        self.file.seek(0)
        self.known_addresses = symbol_table
    def read_memory(self, address, size = 1):
        file = self.file
        file.seek(address - self.base_offset)
        return memory.one_big_value(map(ord, file.read(size)))
    def write_memory(self, address, value, size):
        file = self.file
        file.seek(address - self.base_offset)
        pass # no.
        
def print_usage():
    print >>sys.stderr, "Usage: %s -l <load-address> -e <entry-point> [-s <symbols-file>] [...] <image-file>" % (sys.argv[0], )

symbol_table = {}
base_offset = None
PC = None
opts, args = getopt.getopt(sys.argv[1:], "l:s:e:h", longopts=[])
for key, value in opts:
    if key == "-s":
        a = symboltables.load_known_addresses(value)
        symbol_table.update(a)
    elif key == "-e":
        PC = int(value) if not value.startswith("$") else int(value[1:], 16)
    elif key == "-l":
        base_offset = int(value) if not value.startswith("$") else int(value[1:], 16)
    elif key == "-h":
        print_usage()
        sys.exit(0)
if len(args) < 1 or base_offset is None or PC is None:
    print_usage()
    sys.exit(1)
        
MMU = ImageMemory(open(args[0], "rb"), base_offset, symbol_table)
CPU = emulators.chips.cpu.CPU(MMU)
advances = {
    S_HASH: 1,
    S_ABS_X: 2,
    S_ABS: 2,
    S_ABS_Y: 2,
    S_Z: 1,
    S_Z_X: 1,
    S_Z_Y: 1,
    S_IND2: 2,
    S_IND_X: 1,
    S_IND_Y: 1,
    S_A: 0,
    S_NONE: 0,
    S_REL: 1,
}
#print MMU.size, PC, base_offset, base_offset + MMU.size
CPU.disable_JSR_masking()
while PC < base_offset + MMU.size:
    if PC in MMU.known_addresses:
        print ":%s" % (MMU.known_addresses[PC], )
    addressing_mode = CPU.disasm(PC)
    PC += advances[addressing_mode] + 1