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; 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 { raw_code: T } impl<'a, T> Disassembler<'a, T> where T: Iterator { 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 { type Item = String; fn next(&mut self) -> Option { 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()) }