aboutsummaryrefslogblamecommitdiff
path: root/src/disasm.rs
blob: c9b369639f00982d1ef8e1bcf8b5d6bcf010eb45 (plain) (tree)
































































































                                                                                   
use mos6502::{make_optable, make_addrtable};

mod disops {
    make_optable!(OPS, &str);
    ids2strs!(adc, and, asl, bcc, bcs, beq, bit, bmi,
              bne, bpl, brk, bvc, bvs, clc, cld, cli,
              clv, cmp, cpx, cpy, dec, dex, dey, eor,
              inc, inx, iny, jmp, jsr, lda, ldx, ldy,
              lsr, nop, ora, pha, php, pla, plp, rol,
              ror, rti, rts, sbc, sec, sed, sei, sta,
              stx, sty, tax, tay, tsx, txa, txs, tya, nil);
}

mod disaddr {
    pub type T<'a, 'b> = &'a mut Iterator<Item=&'b u8>;
    make_addrtable!(ADDR_MODES, fn (T) -> String);
    fn acc(_code: T) -> String {
        "a".to_string()
    }
    fn imm(code: T) -> String {
        format!("#${:02x}", code.next().unwrap())
    }
    fn zpg(code: T) -> String {
        format!("${:02x}", code.next().unwrap())
    }
    fn zpx(code: T) -> String {
        format!("${:02x}, x", code.next().unwrap())
    }
    fn zpy(code: T) -> String {
        format!("${:02x}, y", code.next().unwrap())
    }
    fn rel(code: T) -> String {
        let b = *code.next().unwrap() as i8 as i16;
        if b >= 0 {
            format!("+${:02x}, x", b)
        } else {
            format!("-${:02x}, x", -b)
        }
    }
    fn abs(code: T) -> String {
        let low = *code.next().unwrap() as u16;
        let high = *code.next().unwrap() as u16;
        format!("${:04x}", (high << 8) | low)
    }
    fn abx(code: T) -> String {
        let low = *code.next().unwrap() as u16;
        let high = *code.next().unwrap() as u16;
        format!("${:04x}, x", (high << 8) | low)
    }
    fn aby(code: T) -> String {
        let low = *code.next().unwrap() as u16;
        let high = *code.next().unwrap() as u16;
        format!("${:04x}, y", (high << 8) | low)
    }
    fn ind(code: T) -> String {
        let low = *code.next().unwrap() as u16;
        let high = *code.next().unwrap() as u16;
        format!("(${:04x})", (high << 8) | low)
    }
    fn xin(code: T) -> String {
        format!("(${:02x}, x)", code.next().unwrap())
    }
    fn iny(code: T) -> String {
        format!("(${:02x}), y", code.next().unwrap())
    }
    fn nil(_code: T) -> String {
        "".to_string()
    }
}

pub struct Disassembler<'a, T> where T: Iterator<Item=&'a u8> {
    raw_code: T
}

impl<'a, T> Disassembler<'a, T> where T: Iterator<Item=&'a u8> {
    pub fn new(raw_code: T) -> Self {
        Disassembler{raw_code}
    }
    fn parse(opcode: u8, code: &mut T) -> String {
        format!("{} {}", disops::OPS[opcode as usize],
                         disaddr::ADDR_MODES[opcode as usize](code))
    }
}

impl<'a, T> Iterator for Disassembler<'a, T> where T: Iterator<Item=&'a u8> {
    type Item = String;
    fn next(&mut self) -> Option<Self::Item> {
        match self.raw_code.next() {
            Some(opcode) => Some(Disassembler::parse(*opcode, &mut self.raw_code)),
            None => None
        }
    }
}

pub fn parse(opcode: u8, code: &[u8]) -> String {
    Disassembler::parse(opcode, &mut code.iter())
}