rlm@1: #include rlm@1: #include rlm@1: rlm@1: #include "gbGlobals.h" rlm@1: rlm@1: typedef struct rlm@1: { rlm@1: u8 mask; rlm@1: u8 value; rlm@1: char *mnen; rlm@1: } GBOPCODE; rlm@1: rlm@1: static char *registers[] = rlm@1: { "B", "C", "D", "E", "H", "L", "(HL)", "A" }; rlm@1: rlm@1: static char *registers16[] = rlm@1: { "BC", "DE", "HL", "SP", // for some operations rlm@1: "BC", "DE", "HL", "AF" }; // for push/pop rlm@1: rlm@1: static char *cond[] = rlm@1: { "NZ", "Z", "NC", "C" }; rlm@1: rlm@1: static char hexDigits[16] = { rlm@1: '0', '1', '2', '3', '4', '5', '6', '7', rlm@1: '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' rlm@1: }; rlm@1: rlm@1: static GBOPCODE opcodes[] = { rlm@1: { 0xff, 0x00, "NOP" }, rlm@1: { 0xcf, 0x01, "LD %R4,%W" }, rlm@1: { 0xff, 0x02, "LD (BC),A" }, rlm@1: { 0xcf, 0x03, "INC %R4" }, rlm@1: { 0xc7, 0x04, "INC %r3" }, rlm@1: { 0xc7, 0x05, "DEC %r3" }, rlm@1: { 0xc7, 0x06, "LD %r3,%B" }, rlm@1: { 0xff, 0x07, "RLCA" }, rlm@1: { 0xff, 0x08, "LD (%W),SP" }, rlm@1: { 0xcf, 0x09, "ADD HL,%R4" }, rlm@1: { 0xff, 0x0a, "LD A,(BC)" }, rlm@1: { 0xcf, 0x0b, "DEC %R4" }, rlm@1: { 0xff, 0x0f, "RRCA" }, rlm@1: { 0xff, 0x10, "STOP" }, rlm@1: { 0xff, 0x12, "LD (DE),A" }, rlm@1: { 0xff, 0x17, "RLA" }, rlm@1: { 0xff, 0x18, "JR %d" }, rlm@1: { 0xff, 0x1a, "LD A,(DE)" }, rlm@1: { 0xff, 0x1f, "RRA" }, rlm@1: { 0xe7, 0x20, "JR %c3,%d" }, rlm@1: { 0xff, 0x22, "LDI (HL),A" }, rlm@1: { 0xff, 0x27, "DAA" }, rlm@1: { 0xff, 0x2a, "LDI A,(HL)" }, rlm@1: { 0xff, 0x2f, "CPL" }, rlm@1: { 0xff, 0x32, "LDD (HL),A" }, rlm@1: { 0xff, 0x37, "SCF" }, rlm@1: { 0xff, 0x3a, "LDD A,(HL)" }, rlm@1: { 0xff, 0x3f, "CCF" }, rlm@1: { 0xff, 0x76, "HALT" }, rlm@1: { 0xc0, 0x40, "LD %r3,%r0" }, rlm@1: { 0xf8, 0x80, "ADD A,%r0" }, rlm@1: { 0xf8, 0x88, "ADC A,%r0" }, rlm@1: { 0xf8, 0x90, "SUB %r0" }, rlm@1: { 0xf8, 0x98, "SBC A,%r0" }, rlm@1: { 0xf8, 0xa0, "AND %r0" }, rlm@1: { 0xf8, 0xa8, "XOR %r0" }, rlm@1: { 0xf8, 0xb0, "OR %r0" }, rlm@1: { 0xf8, 0xb8, "CP %r0" }, rlm@1: { 0xe7, 0xc0, "RET %c3" }, rlm@1: { 0xcf, 0xc1, "POP %t4" }, rlm@1: { 0xe7, 0xc2, "JP %c3,%W" }, rlm@1: { 0xff, 0xc3, "JP %W" }, rlm@1: { 0xe7, 0xc4, "CALL %c3,%W" }, rlm@1: { 0xcf, 0xc5, "PUSH %t4" }, rlm@1: { 0xff, 0xc6, "ADD A,%B" }, rlm@1: { 0xc7, 0xc7, "RST %P" }, rlm@1: { 0xff, 0xc9, "RET" }, rlm@1: { 0xff, 0xcd, "CALL %W" }, rlm@1: { 0xff, 0xce, "ADC %B" }, rlm@1: { 0xff, 0xd6, "SUB %B" }, rlm@1: { 0xff, 0xd9, "RETI" }, rlm@1: { 0xff, 0xde, "SBC %B" }, rlm@1: { 0xff, 0xe0, "LD (FF%B),A" }, rlm@1: { 0xff, 0xe2, "LD (FF00h+C),A" }, rlm@1: { 0xff, 0xe6, "AND %B" }, rlm@1: { 0xff, 0xe8, "ADD SP,%D" }, rlm@1: { 0xff, 0xe9, "LD PC,HL" }, rlm@1: { 0xff, 0xea, "LD (%W),A" }, rlm@1: { 0xff, 0xee, "XOR %B" }, rlm@1: { 0xff, 0xf0, "LD A,(FF%B)" }, rlm@1: { 0xff, 0xf2, "LD A,(FF00h+C)" }, rlm@1: { 0xff, 0xf3, "DI" }, rlm@1: { 0xff, 0xf6, "OR %B" }, rlm@1: { 0xff, 0xf8, "LD HL,SP%D" }, rlm@1: { 0xff, 0xf9, "LD SP,HL" }, rlm@1: { 0xff, 0xfa, "LD A,(%W)" }, rlm@1: { 0xff, 0xfb, "EI" }, rlm@1: { 0xff, 0xfe, "CP %B" }, rlm@1: { 0x00, 0x00, "DB %B" } rlm@1: }; rlm@1: rlm@1: static GBOPCODE cbOpcodes[] = { rlm@1: { 0xf8, 0x00, "RLC %r0" }, rlm@1: { 0xf8, 0x08, "RRC %r0" }, rlm@1: { 0xf8, 0x10, "RL %r0" }, rlm@1: { 0xf8, 0x18, "RR %r0" }, rlm@1: { 0xf8, 0x20, "SLA %r0" }, rlm@1: { 0xf8, 0x28, "SRA %r0" }, rlm@1: { 0xf8, 0x30, "SWAP %r0" }, rlm@1: { 0xf8, 0x38, "SRL %r0" }, rlm@1: { 0xc0, 0x40, "BIT %b,%r0" }, rlm@1: { 0xc0, 0x80, "RES %b,%r0" }, rlm@1: { 0xc0, 0xc0, "SET %b,%r0" }, rlm@1: { 0x00, 0x00, "DB CBh,%B" } rlm@1: }; rlm@1: rlm@1: static char *addHex(char *p, u8 value) rlm@1: { rlm@1: *p++ = hexDigits[value >> 4]; rlm@1: *p++ = hexDigits[value & 15]; rlm@1: return p; rlm@1: } rlm@1: rlm@1: static char *addHex16(char *p, u16 value) rlm@1: { rlm@1: p = addHex(p, value>>8); rlm@1: return addHex(p, value & 255); rlm@1: } rlm@1: rlm@1: static char *addStr(char *p, char *s) rlm@1: { rlm@1: while (*s) rlm@1: { rlm@1: *p++ = *s++; rlm@1: } rlm@1: return p; rlm@1: } rlm@1: rlm@1: int gbDis(char *buffer, u16 address) rlm@1: { rlm@1: char *p = buffer; rlm@1: int instr = 1; rlm@1: u16 addr = address; rlm@1: sprintf(p, "%04x ", address); rlm@1: p += 12; rlm@1: rlm@1: u8 opcode = gbReadMemoryQuick(address); rlm@1: address++; rlm@1: char * mnen; rlm@1: GBOPCODE *op; rlm@1: if (opcode == 0xcb) rlm@1: { rlm@1: opcode = gbReadMemoryQuick(address); rlm@1: address++; rlm@1: instr++; rlm@1: op = cbOpcodes; rlm@1: } rlm@1: else rlm@1: { rlm@1: op = opcodes; rlm@1: } rlm@1: while (op->value != (opcode & op->mask)) rlm@1: op++; rlm@1: mnen = op->mnen; rlm@1: rlm@1: u8 b0, b1; rlm@1: s8 disp; rlm@1: int shift; rlm@1: rlm@1: while (*mnen) rlm@1: { rlm@1: if (*mnen == '%') rlm@1: { rlm@1: mnen++; rlm@1: switch (*mnen++) rlm@1: { rlm@1: case 'W': rlm@1: b0 = gbReadMemoryQuick(address); rlm@1: address++; rlm@1: b1 = gbReadMemoryQuick(address); rlm@1: address++; rlm@1: p = addHex16(p, b0|b1<<8); rlm@1: instr += 2; rlm@1: *p++ = 'h'; rlm@1: break; rlm@1: case 'B': rlm@1: p = addHex(p, gbReadMemoryQuick(address)); rlm@1: *p++ = 'h'; rlm@1: address++; rlm@1: instr++; rlm@1: break; rlm@1: case 'D': rlm@1: disp = gbReadMemoryQuick(address); rlm@1: if (disp >= 0) rlm@1: *p++ = '+'; rlm@1: p += sprintf(p, "%d", disp); rlm@1: instr++; rlm@1: break; rlm@1: case 'd': rlm@1: disp = gbReadMemoryQuick(address); rlm@1: address++; rlm@1: p = addHex16(p, address+disp); rlm@1: *p++ = 'h'; rlm@1: instr++; rlm@1: break; rlm@1: case 'b': rlm@1: // kind of a hack, but it works :-) rlm@1: *p++ = hexDigits[(opcode >> 3) & 7]; rlm@1: break; rlm@1: case 'r': rlm@1: shift = *mnen++ - '0'; rlm@1: p = addStr(p, registers[(opcode >> shift) & 7]); rlm@1: break; rlm@1: case 'R': rlm@1: shift = *mnen++ - '0'; rlm@1: p = addStr(p, registers16[(opcode >> shift) & 3]); rlm@1: break; rlm@1: case 't': rlm@1: shift = *mnen++ - '0'; rlm@1: p = addStr(p, registers16[4+((opcode >> shift) & 3)]); rlm@1: break; rlm@1: case 'P': rlm@1: p = addHex(p, ((opcode >> 3) & 7) * 8); rlm@1: break; rlm@1: case 'c': rlm@1: shift = *mnen++ - '0'; rlm@1: p = addStr(p, cond[(opcode >> shift) & 3]); rlm@1: break; rlm@1: } rlm@1: } rlm@1: else rlm@1: *p++ = *mnen++; rlm@1: } rlm@1: for (int i = 0; i < instr; i++) rlm@1: { rlm@1: u16 a = addr + i; rlm@1: addHex(buffer+5+i*2, gbReadMemoryQuick(a)); rlm@1: } rlm@1: *p = 0; rlm@1: return instr; rlm@1: }