Advertisement
Guest User

Untitled

a guest
Jan 23rd, 2017
78
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Rust 10.30 KB | None | 0 0
  1. // this line feels empty
  2.  
  3. // this code feels dumb.
  4.  
  5. fn pp_opcode(first_byte: u8, second_byte: u8, third_byte: u8, pc: u16)
  6.              -> (String, u8)
  7. {
  8.     let x = (first_byte >> 6) & 0b011;
  9.     let y = (first_byte >> 3) & 0b111;
  10.     let z = (first_byte >> 0) & 0b111;
  11.     let p = (first_byte >> 4) & 0b011;
  12.     let q = (first_byte >> 3) & 0b001;
  13.  
  14.     let mut instruction_size = 1;
  15.  
  16.     // This garbage is here because two closures can't borrow same var.
  17.     let mut prefix_used = 0;
  18.     let mut used_a8 = 0;
  19.     let mut used_d8 = 0;
  20.     let mut used_r8 = 0;
  21.     let mut used_a16 = 0;
  22.     let mut used_d16 = 0;
  23.  
  24.     // This moved here to create a scope for closures to allow accessing
  25.     // "used_*" vars later.
  26.     let mnemonic = {
  27.         let mut prefix = || {
  28.             prefix_used += 1
  29.         };
  30.  
  31.         // Argument accessors. Will brake if used twice in a
  32.         // row. Because of this, there is almost no point in using
  33.         // them.
  34.         let mut a8 = || {
  35.             used_a8 += 1; //instruction_size += 1;
  36.             format!("${:02X}", second_byte)
  37.         };
  38.        
  39.         let mut d8 = || {
  40.             used_d8 += 1; //instruction_size += 1;
  41.             format!("${:02X}", second_byte)
  42.         };
  43.  
  44.         // Because jump is relative to post pc increment we need to
  45.         // know instruction size here.
  46.         let mut r8 = |insize| {
  47.             used_r8 += 1; //instruction_size += 1;
  48.             // jump is relative to post pc increment!
  49.             format!("Addr_{:04X}", (((pc + insize) as i32) +
  50.                                 ((second_byte as i8) as i32)) as u16)
  51.         };
  52.  
  53.         let mut a16 = || {
  54.             used_a16 += 2; //instruction_size += 2;
  55.             format!("${:04X}", (((third_byte as u16) << 8) | (second_byte as u16)))
  56.         };
  57.  
  58.         let mut d16 = || {
  59.             used_d16 += 2; //instruction_size += 2;
  60.             format!("${:04X}", (((third_byte as u16) << 8) | (second_byte as u16)))
  61.         };
  62.  
  63.        
  64.         // Converting indexes encoded in commands to symbolic arguments
  65.         fn idx_r(i: u8) -> &'static str {
  66.            ["B", "C", "D", "E", "H", "L", "(HL)", "A"][i as usize]
  67.        };
  68.  
  69.        fn idx_rp(i: u8) -> &'static str {
  70.             ["BC", "DE", "HL", "SP"][i as usize]
  71.         };
  72.  
  73.         fn idx_rp2(i: u8) -> &'static str {
  74.            ["BC", "DE", "HL", "AF"][i as usize]
  75.        };
  76.  
  77.        fn idx_cc(i: u8) -> &'static str {
  78.             ["NZ", "Z", "NC", "C"][i as usize]
  79.         };
  80.  
  81.         fn idx_alu(i: u8) -> &'static str {
  82.            ["ADD A,", "ADC A,", "SUB", "SBC A,", "AND", "XOR", "OR", "CP"][i as usize]
  83.        };
  84.  
  85.        fn idx_rot(i: u8) -> &'static str {
  86.             ["RLC", "RRC", "RL", "RR", "SLA", "SRA", "SWAP", "SRL"][i as usize]
  87.         };
  88.  
  89.         fn illegal_op(byte: u8) -> String {
  90.             format!(".DB ${:02X}", byte)
  91.         }
  92.  
  93.         // The value of mnemonic =
  94.         match x {
  95.             0 => match z {
  96.                 0 => match y {
  97.                     0 => format!("NOP"),
  98.                     1 => format!("LD ({}),SP", a16()),
  99.                     2 => format!("STOP {}", d8()),
  100.                     3 => format!("JR {}", r8(2)),
  101.                     4 => format!("JR NZ,{}", r8(2)),
  102.                     5 => format!("JR Z,{}", r8(2)),
  103.                     6 => format!("JR NC,{}", r8(2)),
  104.                     7 => format!("JR C,{}", r8(2)),
  105.                     _ => unreachable!("Impossible opcode"),
  106.                 },
  107.                 1 => match q {
  108.                     0 => format!("LD {},{}", idx_rp(p), d16()),
  109.                     1 => format!("ADD HL,{}", idx_rp(p)),
  110.                     _ => unreachable!("Impossible opcode"),
  111.                 },
  112.                 2 => match q {
  113.                     0 => match p {
  114.                         0 => format!("LD (BC),A"),
  115.                         1 => format!("LD (DE),A"),
  116.                         2 => format!("LD (HL+),A"),
  117.                         3 => format!("LD (HL-),A"),
  118.                         _ => unreachable!("Impossible opcode"),
  119.                     },
  120.                     1 => match p {
  121.                         0 => format!("LD A,(BC)"),
  122.                         1 => format!("LD A,(DE)"),
  123.                         2 => format!("LD A,(HL+)"),
  124.                         3 => format!("LD A,(HL-)"),
  125.                         _ => unreachable!("Impossible opcode"),
  126.                     },
  127.                     _ => unreachable!("Impossible opcode"),
  128.                 },
  129.                 3 => match q {
  130.                     0 => format!("INC {}", idx_rp(p)),
  131.                     1 => format!("DEC {}", idx_rp(p)),
  132.                     _ => unreachable!("Impossible opcode"),
  133.                 },
  134.                 4 => format!("INC {}", idx_r(y)),
  135.                 5 => format!("DEC {}", idx_r(y)),
  136.                 6 => format!("LD {},{}", idx_r(y), d8()),
  137.                 7 => match y {
  138.                     0 => format!("RLCA"),
  139.                     1 => format!("RRCA"),
  140.                     2 => format!("RLA"),
  141.                     3 => format!("RRA"),
  142.                     4 => format!("DAA"),
  143.                     5 => format!("CPL"),
  144.                     6 => format!("SCF"),
  145.                     7 => format!("CCF"),
  146.                     _ => unreachable!("Impossible opcode"),
  147.                 },
  148.                 _ => unreachable!("Impossible opcode"),
  149.             },
  150.             1 => match (z,y) {
  151.                 (6,6) => format!("HALT"),
  152.                 _ => format!("LD {},{}", idx_r(y), idx_r(z)),
  153.             },
  154.             // FIXME cheating here a bit with idx_alu value
  155.             2 => format!("{} {}", idx_alu(y), idx_r(z)),
  156.             3 => match z {
  157.                 0 => match y {
  158.                     0...3 => format!("RET {}", idx_cc(y)),
  159.                     //4 => format!("LDH ({}),A", a8()),
  160.                     4 => format!("LD ($FF00+{}),A", a8()),
  161.                     5 => format!("ADD SP,{}", r8(0)), // FIXME
  162.                     // 6 => format!("LDH A,({})", a8()),
  163.                     6 => format!("LD A,($FF00+{})", a8()),
  164.                     7 => format!("LD HL,(sp + {})", r8(0)), // FIXME
  165.                     _ => unreachable!("Impossible opcode"),
  166.                 },
  167.                 1 => match q {
  168.                     0 => format!("POP {}", idx_rp2(p)),
  169.                     1 => match p {
  170.                         0 => format!("RET"),
  171.                         1 => format!("RETI"),
  172.                         2 => format!("JP (HL)"),
  173.                         3 => format!("LD SP,HL"),
  174.                         _ => unreachable!("Impossible opcode"),
  175.                     },
  176.                     _ => unreachable!("Impossible opcode"),
  177.                 },
  178.                 2 => match y {
  179.                     0...3 => format!("JP {},{}", idx_cc(y), a16()),
  180.                     4 => format!("LD ($FF00+C),A"),
  181.                     5 => format!("LD ({}),A", a16()),
  182.                     6 => format!("LD A,($FF00+C)"),
  183.                     7 => format!("LD A,({})", a16()),
  184.                     _ => unreachable!("Impossible opcode"),
  185.                 },
  186.                 3 => match y {
  187.                     0 => format!("JP {}", a16()),
  188.                     1 => { // Prefix
  189.                         prefix();
  190.                         let x = (second_byte >> 6) & 0b011;
  191.                         let y = (second_byte >> 3) & 0b111;
  192.                         let z = (second_byte >> 0) & 0b111;
  193.  
  194.                         // WARNING: a8, d8, d16, etc. are broken here
  195.                         match x {
  196.                             0 => format!("{} {}", idx_rot(y), idx_r(z)),
  197.                             1 => format!("BIT {},{}", y, idx_r(z)),
  198.                             2 => format!("RES {},{}", y, idx_r(z)),
  199.                             3 => format!("SET {},{}", y, idx_r(z)),
  200.                             _ => unreachable!("Impossible opcode"),
  201.                         }
  202.                     },
  203.                     2...5 => illegal_op(first_byte),
  204.                     6 => format!("DI"),
  205.                     7 => format!("EI"),
  206.                     _ => unreachable!("Impossible opcode"),
  207.                 },
  208.                 4 => match y {
  209.                     0...3 => format!("CALL {},{}", idx_cc(y), a16()),
  210.                     4...7 => illegal_op(first_byte),
  211.                     _ => unreachable!("Impossible opcode"),
  212.                 },
  213.                 5 => match q {
  214.                     0 => format!("PUSH {}", idx_rp2(p)),
  215.                     1 => match p {
  216.                         0 => format!("CALL {}", a16()),
  217.                         1...3 => illegal_op(first_byte),
  218.                         _ => unreachable!("Impossible opcode"),
  219.                     },
  220.                     _ => unreachable!("Impossible opcode"),
  221.                 },
  222.                 6 => format!("{} {}", idx_alu(y), d8()),
  223.                 7 => format!("RST {}", y*8),
  224.                 _ => unreachable!("Impossible opcode"),
  225.             },
  226.             _ => unreachable!("Impossible opcode"),
  227.         }
  228.     };
  229.    
  230.     // This garbage is here because two closures can't borrow same var.
  231.     instruction_size += prefix_used;
  232.     instruction_size += used_a8;
  233.     instruction_size += used_r8;
  234.     instruction_size += used_d8;
  235.     instruction_size += used_a16;
  236.     instruction_size += used_d16;
  237.     (mnemonic, instruction_size)
  238. }
  239.  
  240. fn disasm_rom(rom: [u8; 0x8000], rom_size: usize) {
  241.     let mut pc = 0;
  242.  
  243.     while pc < rom_size {
  244.         let (mnemonic, size) = pp_opcode(rom[pc], rom[pc+1], rom[pc+2], pc as u16);
  245.         println!("\t{}\t\t; ${:04X} 0x{:02X} {}", mnemonic, pc, rom[pc], size);
  246.         pc += size as usize;
  247.     }
  248. }
  249.  
  250. fn main() {
  251.     // // Print "[prefix] opcode size mnemonic" table
  252.     // for i in 0..255 {
  253.     //     let (mnemonic, size) = pp_opcode(i, 0xF2, 0x02, 0x2FFF);
  254.     //     println!("0x{:02X} {} {:?}", i, size, mnemonic);
  255.     // }
  256.     // for i in 0..255 {
  257.     //     let (mnemonic, size) = pp_opcode(0xCB, i, 0x02, 0x2FFF);
  258.     //     println!("0xCB 0x{:02X} {} {:?}", i, size, mnemonic);
  259.     // }
  260.     use std::fs::File;
  261.     use std::io::Read;
  262.     let file_path = "DMG_ROM.bin";
  263.     let mut rom = File::open(file_path).expect("Could not open rom file");
  264.     let mut rom_buffer: [u8; 0x8000] = [0u8; 0x8000];
  265.    
  266.     let rom_size = rom.read(&mut rom_buffer).unwrap();
  267.  
  268.     disasm_rom(rom_buffer, rom_size);
  269. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement