NES opcodes library
unit module dispelpotion;
### 6502 processor opcodes (Nintendo ES)
class NESopcodes {
has %.nesopcodes;
method BUILD() {
self.buildtable();
return %.nesopcodes;
}
method buildtable() {
### Everything is 2 bytes except where noted otherwise
%.nesopcodes[0x69] = "ADC.1"; # immediate
%.nesopcodes[0x65] = "ADC.2"; # zero page
%.nesopcodes[0x29] = "AND.1"; # immediate
%.nesopcodes[0x25] = "AND.2"; # zero page
%.nesopcodes[0x0A] = "ASL.1"; # accumulator len 1
%.nesopcodes[0x06] = "ASL.2"; # zero page
%.nesopcodes[0x24] = "BIT.1"; # zero page
%.nesopcodes[0x2C] = "BIT.2"; # absolute len 3
%.nesopcodes[0x10] = "BPL"; # branch on plus
%.nesopcodes[0x30] = "BMI"; # branch in minus
%.nesopcodes[0x50] = "BVC"; # branch on overflow clear
%.nesopcodes[0x70] = "BVS"; # branch on overflow set
%.nesopcodes[0x90] = "BCC"; # branch on carry clear
%.nesopcodes[0xB0] = "BCS"; # branch on carry set
%.nesopcodes[0xD0] = "BNE"; # branch on neq
%.nesopcodes[0xF0] = "BEQ"; # branch on eq
%.nesopcodes[0x00] = "BRK"; # break
%.nesopcodes[0xC9] = "CMP.1"; # immediate
%.nesopcodes[0xC5] = "CMP.2"; # zero page
%.nesopcodes[0xE0] = "CPX.1"; # immediate
%.nesopcodes[0xE4] = "CPX.2"; # zero page
%.nesopcodes[0xC0] = "CPY.1"; # immediate
%.nesopcodes[0xC4] = "CPY.2"; # zero page
%.nesopcodes[0xC6] = "DEC.1"; # immediate
%.nesopcodes[0xD6] = "DEC.2"; # zero page
%.nesopcodes[0x49] = "EOR.1"; # immediate
%.nesopcodes[0x45] = "EOR.2"; # zero page
%.nesopcodes[0x18] = "CLC"; # clear carry
%.nesopcodes[0x38] = "SEC"; # set carry
%.nesopcodes[0x58] = "CLI"; # clear interrupt
%.nesopcodes[0x78] = "SEI"; # set interrupt
%.nesopcodes[0xB8] = "CLV"; # clear overflow
%.nesopcodes[0xD8] = "CLD"; # clear decimal
%.nesopcodes[0xF8] = "SED"; # set decimal
%.nesopcodes[0xE6] = "INC.1"; # immediate
%.nesopcodes[0xF6] = "INC.2"; # zero page
%.nesopcodes[0x4C] = "JMP.1"; # abs len 3
%.nesopcodes[0x6C] = "JMP.2"; # indirect len 3
%.nesopcodes[0x20] = "JSR"; # abs len 3
%.nesopcodes[0xA9] = "LDA"; # immediate
%.nesopcodes[0xA5] = "LDA"; # zero page
%.nesopcodes[0xA2] = "LDX"; # immediate
%.nesopcodes[0xA6] = "LDX"; # zero page
%.nesopcodes[0xA0] = "LDY"; # immediate
%.nesopcodes[0xA4] = "LDY"; # zero page
%.nesopcodes[0x4A] = "LSR.1"; # accumulator len 1
%.nesopcodes[0x46] = "LSR.2"; # zero page
%.nesopcodes[0x86] = "STX.1"; # accumulator len 1
%.nesopcodes[0x96] = "STX.2"; # zero page
%.nesopcodes[0x84] = "STY.1"; # accumulator len 1
%.nesopcodes[0x8C] = "STY.2"; # zero page
%.nesopcodes[0x9A] = "STA.1"; # accumulator len 1
%.nesopcodes[0xBA] = "STA.2"; # zero page
### Note padding and wrap around
}
}
Note that there's not switch :
unit module dispelpotion;
class Disassembler {
has %.nesopcodesmap;
method BUILD() {
my $nesopcodes = NESopcodes.new();
%.nesopcodesmap = $nesopcodes.nesopcodes;
}
method disasm(@bytebuffer) {
loop (my $i = 0; $i < length @bytebuffer; ) {
my $opcode = %.nesopcodesmap[@bytebuffer[$i]*1
+6+@bytebuffer[$i+1]];
if ($opcode) {
say $opcode + "\n";
if (not %.nesopcodesmap[@bytebuffer[$i
++2]*16+@bytebuffer[$i+3]]) {
$i+=2;
}
if (not %.nesopcodesmap[@bytebuffer[$i
++4]*16+@bytebuffer[$i+5]]) {
$i+=2;
}
if (not %.nesopcodesmap[@bytebuffer[$i
++6]*16+@bytebuffer[$i+7]]) {
$i+=2;
}
$i += 2;
}
}
}
}