From: slack Date: Fri, 15 Aug 2008 19:04:33 +0000 (+0200) Subject: Moar disassembler work. Build still broken. X-Git-Tag: v0.1~15 X-Git-Url: http://slack.codemaniacs.com/git/?a=commitdiff_plain;h=5a3f7929acfa93e77ce23824c67fcb0be0cd84d8;p=wenboi.git Moar disassembler work. Build still broken. --- diff --git a/GBRom.cc b/GBRom.cc index 87eb926..56f5e05 100644 --- a/GBRom.cc +++ b/GBRom.cc @@ -83,6 +83,7 @@ GBRom *read_gbrom(std::string filename) #include +extern "C" int main(int argc, char *argv[]) { if (argc != 2) { diff --git a/GBVideo.cc b/GBVideo.cc index a316b20..526a74d 100644 --- a/GBVideo.cc +++ b/GBVideo.cc @@ -53,6 +53,7 @@ void GBVideo::reset() void GBVideo::DMA_OAM (const u16 src) { + logger.trace("DMA OAM from 0x",std::hex,src); for (u16 i=0; i<160; i++) { OAM.raw[i] = core->memory.read(src+i); @@ -378,6 +379,7 @@ void GBVideo::draw() for (int i=0; i<40; i++) { int y_orig = OAM.sprites[i].y - 16; + //logger.trace("sprite #", i, "y_orig = ", y_orig); if (LY >= y_orig && LY < y_orig+sprite_height) v.push_back(OAM.sprites[i]); } @@ -385,6 +387,7 @@ void GBVideo::draw() // sort sprites std::stable_sort(v.begin(), v.end()); + //logger.trace("LY=",LY," sprites=",v.size()); // draw sprites u16 tile_data_addr = 0x0000; int cur_x = 0; @@ -493,7 +496,7 @@ void GBVideo::draw() int tile_data_base = (tile_data_addr == 0x0800) ? -128 : 0; for (int row=0; row < 32; row++) { - logger.trace("bgmap row=", row); + logger.trace("window map row=", row); for (int col=0; col < 32; col++) { int ty = row*8; @@ -529,7 +532,7 @@ void GBVideo::draw() pallette[3] = (BGP>>6) & 3; u16 tile_map_addr = check_bit(LCDC,6) ? 0x1C00 : 0x1800; u16 tile_data_addr = 0x0000; - int tile_data_base = (tile_data_addr == 0x0800) ? -128 : 0; + int tile_data_base = 0; for (int row=0; row < 32; row++) { logger.trace("bgmap row=", row); diff --git a/Makefile b/Makefile index 1883f63..dbf4e2e 100644 --- a/Makefile +++ b/Makefile @@ -25,7 +25,7 @@ NoMBC.o: NoMBC.cc NoMBC.h Logger.h MBC1.o: MBC1.cc MBC1.h Logger.h g++ $(CXXFLAGS) -c -o $@ $< -gbcore.o: gbcore.cc gbcore.h opcodes.h disasm.h \ +gbcore.o: gbcore.cc gbcore.h opcodes.h \ GBRom.h Logger.h MBC.h GBMemory.h GBVideo.h util.h g++ $(CXXFLAGS) -c -o $@ $< @@ -39,8 +39,11 @@ tests/test_core: tests/test_core.cc gbcore.o MBC.o GBMemory.o GBRom.o \ wendi/CodeBlock.o: wendi/CodeBlock.cc wendi/CodeBlock.h g++ $(CXXFLAGS) -c -o $@ $< -wendi/wendi: wendi/wendi.cc wendi/CodeBlock.o gbcore.o MBC.o GBMemory.o GBRom.o \ - GBVideo.o util.o NoMBC.o MBC1.o +wendi/disasm.o: wendi/disasm.cc wendi/disasm.h + g++ $(CXXFLAGS) -c -o $@ $< + +wendi/wendi: wendi/wendi.cc wendi/CodeBlock.o wendi/disasm.o gbcore.o MBC.o \ + GBMemory.o GBRom.o GBVideo.o util.o NoMBC.o MBC1.o g++ $(CXXFLAGS) -o $@ $^ $(LDFLAGS) clean: diff --git a/gbcore.cc b/gbcore.cc index 0b66958..4526935 100644 --- a/gbcore.cc +++ b/gbcore.cc @@ -1429,8 +1429,8 @@ GameBoy::run_status GameBoy::run() std::string GameBoy::status_string() { std::string disassembled_instruction; - int length; - disassemble_opcode(regs.PC, disassembled_instruction, length); + //int length; + //disassemble_opcode(regs.PC, disassembled_instruction, length); std::ostringstream result; result << "t = " << std::dec << cycle_count << @@ -1454,324 +1454,3 @@ std::string GameBoy::status_string() return result.str(); } -#include "disasm.h" -void GameBoy::disassemble_opcode(u16 addr, std::string &instruction, int &length) -{ - int opcode; - u16 PC = addr; - opcode = memory.read(PC++, GBMemory::DONT_WATCH); - std::ostringstream result; - - result << std::hex << std::uppercase << std::setfill('0'); - - switch(opcode) - { - // LD n, nn - dis_for_each_register(0x3E, 0x06, 0x0E, 0x16, 0x1E, 0x26, 0x2E, "LD", dis_reg_inm) - - // LD r1,r2 - dis_for_each_register(0x7F, 0x78, 0x79, 0x7A, 0x7B, 0x7C, 0x7D, "LD", dis_A_reg) - dis_for_each_register(0x47, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, "LD", dis_B_reg) - dis_for_each_register(0x4F, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, "LD", dis_C_reg) - dis_for_each_register(0x57, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, "LD", dis_D_reg) - dis_for_each_register(0x5F, 0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, "LD", dis_E_reg) - dis_for_each_register(0x67, 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, "LD", dis_H_reg) - dis_for_each_register(0x6F, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, "LD", dis_L_reg) - - // LD reg, (HL) - dis_for_each_register(0x7E, 0x46, 0x4E, 0x56, 0x5E, 0x66, 0x6E, "LD", dis_reg__HL_) - - // LD (HL), reg - dis_for_each_register(0x77, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, "LD", dis__HL__reg) - - dis__reg16__inm(0x36, "LD", HL) - - dis_reg__reg16_(0x0A, "LD", A, BC) - dis_reg__reg16_(0x1A, "LD", A, DE) - dis_reg__inm_(0xFA, "LD", A) - - dis__reg16__reg(0x02, "LD", BC, A) - dis__reg16__reg(0x12, "LD", DE, A) - dis__inm__reg(0xEA, "LD", A) - - // LD A, (C) - dis(0xF2, "LD A, (0xFF00+C)") - // LD (C), A - dis(0xE2, "LD (0xFF00+C), A") - - // LD A, (HLD); LD A, (HL-); LDD A,(HL); - dis(0x3A, "LDD A, (HL)") - // LD (HLD), A; LD (HL-), A; LDD (HL), A; - dis(0x32, "LDD (HL), A") - // LD A, (HLI); LD A, (HL+); LDI A, (HL); - dis(0x2A, "LDI A, (HL)") - // LD (HLI), A; LD (HL+), A; LDI (HL), A; - dis(0x22, "LDI (HL), A") - - // LDH (n), A - case 0xE0: { - int port = int(memory.read(PC++, GBMemory::DONT_WATCH)); - - result << "LD (0xFF" << - std::setw(2) << port << "), A" << "\t[" << get_port_name(port) << "]"; - break; - } - // LDH A, (n) - case 0xF0: { - int port = int(memory.read(PC++, GBMemory::DONT_WATCH)); - result << "LD A, (0xFF" << - std::setw(2) << port << ")" << "\t[" << get_port_name(port) << "]"; - break; - } - - dis_reg16_inm(0x01, "LD", BC) - dis_reg16_inm(0x11, "LD", DE) - dis_reg16_inm(0x21, "LD", HL) - dis_reg16_inm(0x31, "LD", SP) - - // LD SP, HL - dis(0xF9, "LD SP, HL") - - // LD HL, SP+n - // LDHL SP, n - case 0xF8: - result << "LD HL, SP + 0x"<< std::setw(2) << int(memory.read(PC++, GBMemory::DONT_WATCH)); - break; - - // LD (nn), SP - dis__inm__reg16(0x08, "LD", SP) - - // PUSH nn - dis_reg16(0xF5, "PUSH", AF) - dis_reg16(0xC5, "PUSH", BC) - dis_reg16(0xD5, "PUSH", DE) - dis_reg16(0xE5, "PUSH", HL) - - // POP nn - dis_reg16(0xF1, "POP", AF) - dis_reg16(0xC1, "POP", BC) - dis_reg16(0xD1, "POP", DE) - dis_reg16(0xE1, "POP", HL) - - // 8-bit ALU - // ADD A,reg - dis_for_each_register(0x87, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, "ADD", dis_A_reg) - - dis_reg__reg16_(0x86, "ADD", A, HL) - dis_reg_inm(0xC6, "ADD", A) - - // ADC A, n - dis_for_each_register(0x8F, 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, "ADC", dis_A_reg) - - dis_reg__reg16_(0x8E, "ADC", A, HL) - dis_reg_inm(0xCE, "ADC", A) - - // SUB n - dis_for_each_register(0x97, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, "SUB", dis_reg) - - dis__reg16_(0x96, "SUB", HL) - dis_inm8(0xD6, "SUB") - - // SBC n - dis_for_each_register(0x9F, 0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x9D, "SBC", dis_reg) - - dis__reg16_(0x9E, "SBC", HL) - - // AND n - dis_for_each_register(0xA7, 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, "AND", dis_reg) - - dis__reg16_(0xA6, "AND", HL) - dis_inm8(0xE6, "AND") - - // OR n - dis_for_each_register(0xB7, 0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5, "OR", dis_reg) - - dis__reg16_(0xB6, "OR", HL) - dis_inm8(0xF6, "OR") - - // XOR n - dis_for_each_register(0xAF, 0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, "XOR", dis_reg) - - dis__reg16_(0xAE, "XOR", HL) - dis_inm8(0xEE, "XOR") - - // CP n - dis_for_each_register(0xBF, 0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, "CP", dis_reg) - - dis__reg16_(0xBE, "CP", HL) - dis_inm8(0xFE, "CP") - - // INC n - dis_for_each_register(0x3C, 0x04, 0x0C, 0x14, 0x1C, 0x24, 0x2C, "INC", dis_reg) - - dis__reg16_(0x34, "INC", HL) - - // DEC n - dis_for_each_register(0x3D, 0x05, 0x0D, 0x15, 0x1D, 0x25, 0x2D, "DEC", dis_reg) - - dis__reg16_(0x35, "DEC", HL) - - // 16-bit ALU - // ADD HL, n - dis_for_each_register16(0x09, 0x19, 0x29, 0x39, "ADD", dis_HL_reg16) - - // ADD SP, # - dis_reg16_inm8(0xE8, "ADD", SP) - - // INC nn - dis_for_each_register16(0x03, 0x13, 0x23, 0x33, "INC", dis_reg16) - - // DEC nn - dis_for_each_register16(0x0B, 0x1B, 0x2B, 0x3B, "DEC", dis_reg16) - - // Miscellaneous instructions - case 0xCB: { - int sub_opcode = memory.read(PC++, GBMemory::DONT_WATCH); - switch(sub_opcode) - { - // SWAP n - dis_for_each_register(0x37, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, "SWAP", dis_reg) - - // SWAP (HL) - dis__reg16_(0x36, "SWAP", HL) - - // RLC n - dis_for_each_register(0x07, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, "RLC", dis_reg) - - // RLC (HL) - dis__reg16_(0x06, "RLC", HL) - - // RL n (through carry) - dis_for_each_register(0x17, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, "RL", dis_reg) - - // RL (HL) (through carry) - dis__reg16_(0x16, "RL", HL) - - // RRC n - dis_for_each_register(0x0F, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, "RRC", dis_reg) - - // RRC (HL) - dis__reg16_(0x0E, "RRC", HL) - - // RR n (through carry) - dis_for_each_register(0x1F, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, "RR", dis_reg) - - // RR (HL) (through carry) - dis__reg16_(0x1E, "RR", HL) - - // SLA n - dis_for_each_register(0x27, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, "SLA", dis_reg) - - // SLA (HL) - dis__reg16_(0x26, "SLA", HL) - - // SRA n - dis_for_each_register(0x2F, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, "SRA", dis_reg) - - // SRA (HL) - dis__reg16_(0x2E, "SRA", HL) - - // SRL n - dis_for_each_register(0x3F, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, "SRA", dis_reg) - - // SRL (HL) - dis__reg16_(0x3E, "SRA", HL) - - default: { - int bit_op = sub_opcode >> 6; - int reg = sub_opcode & 7; - int b = (sub_opcode >> 3) & 7; - const char *bit_ops[4]={"Unknown", "BIT", "RES", "SET"}; - const char *regs[8]={"B","C","D","E","H","L","(HL)", "A"}; - result << bit_ops[bit_op] << " " << b << ", " << regs[reg]; - break; - } - - } - break; - } - - dis(0x27, "DAA") - - dis(0x2F, "CPL") - - dis(0x3F, "CCF") - - dis(0x37, "SCF") - dis(0x00, "NOP") - dis(0x76, "HALT") - - dis(0x10, "STOP") - - dis(0xF3, "DI") - - dis(0xFB, "EI") - - // Rotates and shifts - dis(0x07, "RLCA") - - dis(0x17, "RLA") - - dis(0x0F, "RRCA") - - dis(0x1F, "RRA") - - // TODO: Bit instructions - - // Jumps - dis_inm16(0xC3, "JP") - // JP cc, nn - dis_inm16(0xC2, "JP NZ") - dis_inm16(0xCA, "JP Z") - dis_inm16(0xD2, "JP NC") - dis_inm16(0xDA, "JP C") - dis(0xE9, "JP (HL)") - - dis_JR(0x18, "JR") - dis_JR(0x20, "JR NZ") - dis_JR(0x28, "JR Z") - dis_JR(0x30, "JR NC") - dis_JR(0x38, "JR C") - - // Calls - dis_inm16(0xCD, "CALL") - // CALL cc, nn - dis_inm16(0xC4, "CALL NZ") - dis_inm16(0xCC, "CALL Z") - dis_inm16(0xD4, "CALL NC") - dis_inm16(0xDC, "CALL C") - - // Restarts - dis(0xC7, "RST 0x00") - dis(0xCF, "RST 0x08") - dis(0xD7, "RST 0x10") - dis(0xDF, "RST 0x18") - dis(0xE7, "RST 0x20") - dis(0xEF, "RST 0x28") - dis(0xF7, "RST 0x30") - dis(0xFF, "RST 0x38") - - // Returns - dis(0xC9, "RET") - // RET cc - dis(0xC0, "RET NZ") - dis(0xC8, "RET Z") - dis(0xD0, "RET NC") - dis(0xD8, "RET C") - - dis(0xD9, "RETI") - - default: - std::ostringstream errmsg; - errmsg << "Unknown opcode 0x"; - errmsg << std::hex << std::setw(2) << std::setfill('0') << opcode; - errmsg << " at 0x" << std::hex << std::setw(4) << PC-1; - logger.trace(errmsg.str()); - break; - - } // end switch - - instruction = result.str(); - length = PC - addr; -} - diff --git a/gbcore.h b/gbcore.h index 48808ea..7e86e50 100644 --- a/gbcore.h +++ b/gbcore.h @@ -109,8 +109,6 @@ class GameBoy run_status run(); // debug methods - void disassemble_opcode(u16 addr, std::string &instruction, int &length); - int set_breakpoint (u16 addr); void delete_breakpoint (int id); void enable_breakpoint (int id); diff --git a/tests/test_core.cc b/tests/test_core.cc index e4c9c85..2d2775c 100644 --- a/tests/test_core.cc +++ b/tests/test_core.cc @@ -139,6 +139,7 @@ int main(int argc, char **argv) { break; } + /* else if (command == "disasm" || command == "d") { int start, end, pos; @@ -176,6 +177,7 @@ int main(int argc, char **argv) } } + */ else if (command == "x") { int addr = str2int(arguments[0]); diff --git a/wendi/Instruction.cc b/wendi/Instruction.cc new file mode 100644 index 0000000..1d75a48 --- /dev/null +++ b/wendi/Instruction.cc @@ -0,0 +1,54 @@ +#include "Instruction.h" + +#if 0 + // Jumps + dis_inm16(0xC3, "JP") + // JP cc, nn + dis_inm16(0xC2, "JP NZ") + dis_inm16(0xCA, "JP Z") + dis_inm16(0xD2, "JP NC") + dis_inm16(0xDA, "JP C") + case 0xE9: + result << "JP (HL)"; + opcode_str = "JP"; + op1.str="(HL)"; + op2.str=""; + op1.type = Instruction::MEM_INDIRECT; + op1.reg = Instruction::HL; + op2.type = Instruction::NONE; + break; + + dis_JR(0x18, "JR") + dis_JR(0x20, "JR NZ") + dis_JR(0x28, "JR Z") + dis_JR(0x30, "JR NC") + dis_JR(0x38, "JR C") + + // Calls + dis_inm16(0xCD, "CALL") + // CALL cc, nn + dis_inm16(0xC4, "CALL NZ") + dis_inm16(0xCC, "CALL Z") + dis_inm16(0xD4, "CALL NC") + dis_inm16(0xDC, "CALL C") + + // Restarts + dis(0xC7, "RST 0x00") + dis(0xCF, "RST 0x08") + dis(0xD7, "RST 0x10") + dis(0xDF, "RST 0x18") + dis(0xE7, "RST 0x20") + dis(0xEF, "RST 0x28") + dis(0xF7, "RST 0x30") + dis(0xFF, "RST 0x38") + + // Returns + dis(0xC9, "RET") + // RET cc + dis(0xC0, "RET NZ") + dis(0xC8, "RET Z") + dis(0xD0, "RET NC") + dis(0xD8, "RET C") + + dis(0xD9, "RETI") +#endif diff --git a/wendi/Instruction.h b/wendi/Instruction.h new file mode 100644 index 0000000..17816eb --- /dev/null +++ b/wendi/Instruction.h @@ -0,0 +1,56 @@ +#ifndef INSTRUCTION_H +#define INSTRUCTION_H + +struct Instruction +{ + enum InstructionType + { + JUMP, + CALL, + RESET, + ALU, + LOAD, + + }; + + enum Register { A=0,B,C,D,E,H,L,AF,BC,DE,HL,SP,PC }; + + enum OperandType + { + NONE=0, + REG, + MEM_DIRECT, + MEM_INDIRECT, + INM8, + INM16 + }; + + struct Operand + { + std::string str; + OperandType type; + // FIXME: An anonymous union doesn't work here :( + // union { + Register reg; + int val; + // } + + Operand(): str(""), type(NONE) {} + }; + + int length; + std::string all; + + u8 opcode; + u8 sub_opcode; + std::string str; + Operand op1, op2; + + Instruction(int length, u8 opcode, u8 sub_opcode, std::string all, std::string opcode_str, Operand op1, Operand op2): + length(length), opcode(opcode), sub_opcode(sub_opcode),all(all), str(opcode_str), op1(op1), op2(op2) + { + } +}; + +#endif + diff --git a/wendi/disasm.cc b/wendi/disasm.cc index 3f56883..37c323a 100644 --- a/wendi/disasm.cc +++ b/wendi/disasm.cc @@ -1,3 +1,6 @@ +#include + +#include "../Logger.h" #include "disasm.h" #include "disasm_macros.h" @@ -55,12 +58,11 @@ std::string get_port_name(int port) } -void disassemble_opcode(GameBoy &gb, u16 addr, std::string &instruction, int &length) +Instruction disassemble_opcode(GameBoy &gb, u16 addr) { - int opcode; + u8 opcode, sub_opcode=0xFF; std::ostringstream result; - std::string opcode_str, op1_str, op2_str; - Instruction::OperandType op1_type, op2_type; + std::string opcode_str; Instruction::Operand op1, op2; u16 PC = addr; @@ -99,18 +101,73 @@ void disassemble_opcode(GameBoy &gb, u16 addr, std::string &instruction, int &le dis__inm__reg(0xEA, "LD", A) // LD A, (C) - dis(0xF2, "LD A, (0xFF00+C)") + case 0xF2: + result << "LD A, (0xFF00+C)"; + opcode_str = "LDH"; + op1.str="A"; + op2.str="C"; + op1.type=Instruction::REG; + op1.reg =Instruction::A; + op2.type=Instruction::MEM_INDIRECT; + op2.reg =Instruction::C; + break; + // LD (C), A - dis(0xE2, "LD (0xFF00+C), A") + case 0xE2: + result << "LD (0xFF00+C), A"; + opcode_str = "LDH"; + op1.str="C"; + op2.str="A"; + op1.type=Instruction::MEM_INDIRECT; + op1.reg =Instruction::C; + op2.type=Instruction::REG; + op2.reg =Instruction::A; + break; // LD A, (HLD); LD A, (HL-); LDD A,(HL); - dis(0x3A, "LDD A, (HL)") + case 0x3A: + result << "LD A, (HL-)"; + opcode_str = "LDD"; + op1.str="A"; + op2.str="(HL)"; + op1.type=Instruction::REG; + op1.reg =Instruction::A; + op2.type=Instruction::MEM_INDIRECT; + op2.reg =Instruction::HL; + break; // LD (HLD), A; LD (HL-), A; LDD (HL), A; - dis(0x32, "LDD (HL), A") + case 0x32: + result << "LD (HL-), A"; + opcode_str = "LDD"; + op1.str="(HL)"; + op2.str="A"; + op1.type=Instruction::MEM_INDIRECT; + op1.reg =Instruction::HL; + op2.type=Instruction::REG; + op2.reg =Instruction::A; + break; // LD A, (HLI); LD A, (HL+); LDI A, (HL); - dis(0x2A, "LDI A, (HL)") + case 0x2A: + result << "LD A, (HL+)"; + opcode_str = "LDI"; + op1.str="A"; + op2.str="(HL)"; + op1.type=Instruction::REG; + op1.reg =Instruction::A; + op2.type=Instruction::MEM_INDIRECT; + op2.reg =Instruction::HL; + break; // LD (HLI), A; LD (HL+), A; LDI (HL), A; - dis(0x22, "LDI (HL), A") + case 0x22: + result << "LD (HL+), A"; + opcode_str = "LDI"; + op1.str="(HL)"; + op2.str="A"; + op1.type=Instruction::MEM_INDIRECT; + op1.reg =Instruction::HL; + op2.type=Instruction::REG; + op2.reg =Instruction::A; + break; // LDH (n), A case 0xE0: { @@ -118,6 +175,13 @@ void disassemble_opcode(GameBoy &gb, u16 addr, std::string &instruction, int &le result << "LD (0xFF" << std::setw(2) << port << "), A" << "\t[" << get_port_name(port) << "]"; + opcode_str = "LDH"; + op1.str=std::string("(") + ToString(port) + ")"; + op2.str="A"; + op1.type=Instruction::MEM_DIRECT; + op1.val =0xFF00+port; + op2.type=Instruction::REG; + op2.reg =Instruction::A; break; } // LDH A, (n) @@ -125,6 +189,13 @@ void disassemble_opcode(GameBoy &gb, u16 addr, std::string &instruction, int &le int port = int(gb.memory.read(PC++, GBMemory::DONT_WATCH)); result << "LD A, (0xFF" << std::setw(2) << port << ")" << "\t[" << get_port_name(port) << "]"; + opcode_str = "LDH"; + op1.str="A"; + op2.str=std::string("(") + ToString(port) + ")"; + op1.type=Instruction::REG; + op1.reg =Instruction::A; + op2.type=Instruction::MEM_DIRECT; + op2.val =0xFF00+port; break; } @@ -134,13 +205,28 @@ void disassemble_opcode(GameBoy &gb, u16 addr, std::string &instruction, int &le dis_reg16_inm(0x31, "LD", SP) // LD SP, HL - dis(0xF9, "LD SP, HL") + case 0xF9: + result << "LD SP, HL"; + opcode_str = "LD"; + op1.str = "SP"; + op2.str = "HL"; + op1.type = Instruction::REG; + op1.reg = Instruction::SP; + op2.type = Instruction::REG; + op2.reg = Instruction::HL; // LD HL, SP+n // LDHL SP, n - case 0xF8: - result << "LD HL, SP + 0x"<< std::setw(2) << int(gb.memory.read(PC++, GBMemory::DONT_WATCH)); + case 0xF8: { + int n = int(gb.memory.read(PC++, GBMemory::DONT_WATCH)); + result << "LD HL, SP + 0x"<< std::setw(2) << n; + opcode_str = "LD HL, SP+"; + op1.str = ToString(n); + op2.str = ""; + op1.type = Instruction::INM8; + op1.val = n; break; + } // LD (nn), SP dis__inm__reg16(0x08, "LD", SP) @@ -230,7 +316,7 @@ void disassemble_opcode(GameBoy &gb, u16 addr, std::string &instruction, int &le // Miscellaneous instructions case 0xCB: { - int sub_opcode = gb.memory.read(PC++, GBMemory::DONT_WATCH); + sub_opcode = gb.memory.read(PC++, GBMemory::DONT_WATCH); switch(sub_opcode) { // SWAP n @@ -320,8 +406,6 @@ void disassemble_opcode(GameBoy &gb, u16 addr, std::string &instruction, int &le dis(0x1F, "RRA") - // TODO: Bit instructions - // Jumps dis_inm16(0xC3, "JP") // JP cc, nn @@ -329,7 +413,15 @@ void disassemble_opcode(GameBoy &gb, u16 addr, std::string &instruction, int &le dis_inm16(0xCA, "JP Z") dis_inm16(0xD2, "JP NC") dis_inm16(0xDA, "JP C") - dis(0xE9, "JP (HL)") + case 0xE9: + result << "JP (HL)"; + opcode_str = "JP"; + op1.str="(HL)"; + op2.str=""; + op1.type = Instruction::MEM_INDIRECT; + op1.reg = Instruction::HL; + op2.type = Instruction::NONE; + break; dis_JR(0x18, "JR") dis_JR(0x20, "JR NZ") @@ -374,8 +466,7 @@ void disassemble_opcode(GameBoy &gb, u16 addr, std::string &instruction, int &le break; } // end switch - - instruction = result.str(); - length = PC - addr; + + return Instruction(PC-addr, opcode, sub_opcode, result.str(), opcode_str, op1, op2); } diff --git a/wendi/disasm.h b/wendi/disasm.h index c0bd640..3cb01eb 100644 --- a/wendi/disasm.h +++ b/wendi/disasm.h @@ -1,36 +1,11 @@ #ifndef DISASM_H #define DISASM_H +#include "../gbcore.h" + #include #include -struct Instruction -{ - enum Register { A=0,B,C,D,E,H,L,AF,BC,DE,HL,SP,PC }; - - enum OperandType - { - NONE=0, - REG, - MEM_DIRECT, - MEM_INDIRECT, - INM8, - INM16 - }; - - union Operand { - Register reg; - int val; - }; - - int length; - std::string all; - - std::string opcode_str, op1_str, op2_str; - OperandType op1_type, op2_type; - Operand op1, op2; -}; - template std::string ToString(const T &object) { diff --git a/wendi/disasm_macros.h b/wendi/disasm_macros.h index b9315d4..e7d6bdd 100644 --- a/wendi/disasm_macros.h +++ b/wendi/disasm_macros.h @@ -19,18 +19,23 @@ #define dis(opcode, name) \ case opcode: \ result << name; \ + opcode_str = name; \ + op1.str=""; \ + op2.str=""; \ + op1.type=Instruction::NONE; \ + op2.type=Instruction::NONE; \ break; // OP reg -#define dis_reg(opcode, name, reg) \ +#define dis_reg(opcode, name, reg8) \ case opcode: \ - result << name << " " << #reg; \ + result << name << " " << #reg8; \ opcode_str = name; \ - op1_str = #reg; \ - op2_str = ""; \ - op1_type = REG; \ - op1.reg = reg; \ - op2.type = NONE; \ + op1.str = #reg8; \ + op2.str = ""; \ + op1.type = Instruction::REG; \ + op1.reg = Instruction::reg8; \ + op2.type = Instruction::NONE; \ break; @@ -39,11 +44,11 @@ case opcode: \ result << name << " " << #reg16; \ opcode_str = name; \ - op1_str = #reg16; \ - op2_str = ""; \ - op1_type = REG; \ - op1.reg = reg16; \ - op2.type = NONE; \ + op1.str = #reg16; \ + op2.str = ""; \ + op1.type = Instruction::REG; \ + op1.reg = Instruction::reg16; \ + op2.type = Instruction::NONE; \ break; // OP (reg16) @@ -51,81 +56,81 @@ case opcode: \ result << name << " (" << #reg16 << ")"; \ opcode_str = name; \ - op1_str = std::string("(")+#reg16+")"; \ - op2_str = ""; \ - op1_type = MEM_INDIRECT; \ - op1.reg = reg16; \ - op2.type = NONE; \ + op1.str = std::string("(")+#reg16+")"; \ + op2.str = ""; \ + op1.type = Instruction::MEM_INDIRECT; \ + op1.reg = Instruction::reg16; \ + op2.type = Instruction::NONE; \ break; // OP inm8 #define dis_inm8(opcode, name) \ case opcode: {\ - int inm = int(memory.read(PC++, GBMemory::DONT_WATCH)); \ + int inm = int(gb.memory.read(PC++, GBMemory::DONT_WATCH)); \ result << name << " 0x" << std::setw(2) << inm; \ opcode_str = name; \ - op1_str = ToString(inm); \ - op2_str = ""; \ - op1_type = INM8; \ + op1.str = ToString(inm); \ + op2.str = ""; \ + op1.type = Instruction::INM8; \ op1.val = inm; \ - op2.type = NONE; \ + op2.type = Instruction::NONE; \ break; \ } // OP inm16 #define dis_inm16(opcode, name) \ case opcode: {\ - int inm = int(memory.read16(PC, GBMemory::DONT_WATCH)); \ + int inm = int(gb.memory.read16(PC, GBMemory::DONT_WATCH)); \ PC += 2; \ result << name << " 0x" << std::setw(4) << inm; \ opcode_str = name; \ - op1_str = ToString(inm); \ - op2_str = ""; \ - op1_type = INM16; \ + op1.str = ToString(inm); \ + op2.str = ""; \ + op1.type = Instruction::INM16; \ op1.val = inm; \ - op2.type = NONE; \ + op2.type = Instruction::NONE; \ break; \ } -#define dis_reg_inm(opcode, name, reg) \ +#define dis_reg_inm(opcode, name, reg8) \ case opcode: {\ - int inm = int(memory.read(PC++, GBMemory::DONT_WATCH)); \ - result << name << " " << #reg << ", 0x" << std::setw(2) << inm; \ + int inm = int(gb.memory.read(PC++, GBMemory::DONT_WATCH)); \ + result << name << " " << #reg8 << ", 0x" << std::setw(2) << inm; \ opcode_str = name; \ - op1_str = #reg; \ - op2_str = ToString(inm); \ - op1_type = REG; \ - op1.reg = reg; \ - op2.type = INM8; \ + op1.str = #reg8; \ + op2.str = ToString(inm); \ + op1.type = Instruction::REG; \ + op1.reg = Instruction::reg8; \ + op2.type = Instruction::INM8; \ op2.val = inm; \ break; \ } #define dis_reg16_inm(opcode, name, reg16) \ case opcode: {\ - int inm = int(memory.read16(PC, GBMemory::DONT_WATCH)); \ + int inm = int(gb.memory.read16(PC, GBMemory::DONT_WATCH)); \ PC += 2; \ result << name << " " << #reg16 << ", 0x" << std::setw(4) << inm; \ opcode_str = name; \ - op1_str = #reg16; \ - op2_str = ToString(inm); \ - op1_type = REG; \ - op1.reg = reg16; \ - op2.type = INM8; \ + op1.str = #reg16; \ + op2.str = ToString(inm); \ + op1.type = Instruction::REG; \ + op1.reg = Instruction::reg16; \ + op2.type = Instruction::INM8; \ op2.val = inm; \ break; \ } #define dis_reg16_inm8(opcode, name, reg16) \ case opcode: {\ - int inm = int(memory.read(PC++, GBMemory::DONT_WATCH)); \ + int inm = int(gb.memory.read(PC++, GBMemory::DONT_WATCH)); \ result << name << " " << #reg16 << ", 0x" << std::setw(2) << inm; \ opcode_str = name; \ - op1_str = #reg; \ - op2_str = ToString(inm); \ - op1_type = REG; \ - op1.reg = reg; \ - op2.type = INM8; \ + op1.str = #reg16; \ + op2.str = ToString(inm); \ + op1.type = Instruction::REG; \ + op1.reg = Instruction::reg16; \ + op2.type = Instruction::INM8; \ op2.val = inm; \ break; \ } @@ -134,12 +139,12 @@ case opcode: \ result << name << " " << #reg1 << ", " << #reg2; \ opcode_str = name; \ - op1_str = #reg1; \ - op2_str = #reg2; \ - op1_type = REG; \ - op1.reg = reg1; \ - op2.type = REG; \ - op2.val = reg2; \ + op1.str = #reg1; \ + op2.str = #reg2; \ + op1.type = Instruction::REG; \ + op1.reg = Instruction::reg1; \ + op2.type = Instruction::REG; \ + op2.val = Instruction::reg2; \ break; #define dis_A_reg(opcode, name, reg2) dis_reg_reg(opcode, name, A, reg2) @@ -154,111 +159,111 @@ case opcode: \ result << name << " " << #reg16_1 << ", " << #reg16_2; \ opcode_str = name; \ - op1_str = #reg16_1; \ - op2_str = #reg16_2; \ - op1_type = REG; \ - op1.reg = reg16_1; \ - op2.type = REG; \ - op2.val = reg16_2; \ + op1.str = #reg16_1; \ + op2.str = #reg16_2; \ + op1.type = Instruction::REG; \ + op1.reg = Instruction::reg16_1; \ + op2.type = Instruction::REG; \ + op2.val = Instruction::reg16_2; \ break; #define dis_HL_reg16(opcode, name, reg16_2) dis_reg16_reg16(opcode, name, HL, reg16_2) // OP reg, (reg16) -#define dis_reg__reg16_(opcode, name, reg, reg16) \ +#define dis_reg__reg16_(opcode, name, reg8, reg16) \ case opcode: \ - result << name << " " << #reg << ", (" << #reg16 << ")"; \ + result << name << " " << #reg8 << ", (" << #reg16 << ")"; \ opcode_str = name; \ - op1_str = #reg; \ - op2_str = std::string("(")+ #reg16 + ")"; \ - op1_type = REG; \ - op1.reg = reg; \ - op2.type = MEM_INDIRECT; \ - op2.val = reg16; \ + op1.str = #reg8; \ + op2.str = std::string("(")+ #reg16 + ")"; \ + op1.type = Instruction::REG; \ + op1.reg = Instruction::reg8; \ + op2.type = Instruction::MEM_INDIRECT; \ + op2.val = Instruction::reg16; \ break; // OP reg, (HL) #define dis_reg__HL_(opcode, name, reg) dis_reg__reg16_(opcode, name, reg, HL) // OP reg, (inm) -#define dis_reg__inm_(opcode, name, reg) \ +#define dis_reg__inm_(opcode, name, reg8) \ case opcode: {\ - int inm = int(memory.read16(PC, GBMemory::DONT_WATCH)); \ + int inm = int(gb.memory.read16(PC, GBMemory::DONT_WATCH)); \ PC += 2; \ - result << name << " " << #reg << ", (0x" << \ + result << name << " " << #reg8 << ", (0x" << \ std::setw(4) << inm << ")"; \ opcode_str = name; \ - op1_str = #reg; \ - op2_str = std::string("(") + ToString(inm) + ")"; \ - op1_type = REG; \ - op1.reg = reg; \ - op2.type = MEM_DIRECT; \ + op1.str = #reg8; \ + op2.str = std::string("(") + ToString(inm) + ")"; \ + op1.type = Instruction::REG; \ + op1.reg = Instruction::reg8; \ + op2.type = Instruction::MEM_DIRECT; \ op2.val = inm; \ break; \ } // OP (reg16), reg -#define dis__reg16__reg(opcode, name, reg16, reg) \ +#define dis__reg16__reg(opcode, name, reg16, reg8) \ case opcode: \ - result << name << " (" << #reg16 << "), " << #reg; \ + result << name << " (" << #reg16 << "), " << #reg8; \ opcode_str = name; \ - op1_str = std::string("(")+ #reg16 + ")"; \ - op2_str = #reg; \ - op1.type = MEM_INDIRECT; \ - op1.val = reg16; \ - op2_type = REG; \ - op2.reg = reg; \ + op1.str = std::string("(")+ #reg16 + ")"; \ + op2.str = #reg8; \ + op1.type = Instruction::MEM_INDIRECT; \ + op1.val = Instruction::reg16; \ + op2.type = Instruction::REG; \ + op2.reg = Instruction::reg8; \ break; // OP (HL), reg #define dis__HL__reg(opcode, name, reg) dis__reg16__reg(opcode, name, HL, reg) // OP (inm), reg -#define dis__inm__reg(opcode, name, reg) \ +#define dis__inm__reg(opcode, name, reg8) \ case opcode: {\ - int inm = int(memory.read16(PC, GBMemory::DONT_WATCH)); \ + int inm = int(gb.memory.read16(PC, GBMemory::DONT_WATCH)); \ PC += 2; \ result << name << " (0x" << \ - std::setw(4) << inm << "), " << #reg; \ + std::setw(4) << inm << "), " << #reg8; \ opcode_str = name; \ - op1_str = std::string("(") + ToString(inm) + ")"; \ - op2_str = #reg; \ - op1.type = MEM_DIRECT; \ + op1.str = std::string("(") + ToString(inm) + ")"; \ + op2.str = #reg8; \ + op1.type = Instruction::MEM_DIRECT; \ op1.val = inm; \ - op2_type = REG; \ - op2.reg = reg; \ + op2.type = Instruction::REG; \ + op2.reg = Instruction::reg8; \ break; \ } // OP (inm), reg16 #define dis__inm__reg16(opcode, name, reg16) \ case opcode: {\ - int inm = int(memory.read16(PC, GBMemory::DONT_WATCH)); \ + int inm = int(gb.memory.read16(PC, GBMemory::DONT_WATCH)); \ PC += 2; \ result << name << " (0x" << \ std::setw(4) << inm << "), " << #reg16; \ opcode_str = name; \ - op1_str = std::string("(") + ToString(inm) + ")"; \ - op2_str = #reg; \ - op1.type = MEM_DIRECT; \ + op1.str = std::string("(") + ToString(inm) + ")"; \ + op2.str = #reg16; \ + op1.type = Instruction::MEM_DIRECT; \ op1.val = inm; \ - op2_type = REG; \ - op2.reg = reg16; \ + op2.type = Instruction::REG; \ + op2.reg = Instruction::reg16; \ break; \ } // OP (reg16), inm #define dis__reg16__inm(opcode, name, reg16) \ case opcode: {\ - int inm = int(memory.read(PC++, GBMemory::DONT_WATCH)); \ + int inm = int(gb.memory.read(PC++, GBMemory::DONT_WATCH)); \ result << name << " (" << #reg16 << "), 0x" << \ std::setw(2) << inm; \ opcode_str = name; \ - op1_str = std::string("(") + #reg16 + ")"; \ - op2_str = ToString(inm); \ - op1.type = MEM_INDIRECT; \ - op1.reg = reg16; \ - op2.type = INM8; \ + op1.str = std::string("(") + #reg16 + ")"; \ + op2.str = ToString(inm); \ + op1.type = Instruction::MEM_INDIRECT; \ + op1.reg = Instruction::reg16; \ + op2.type = Instruction::INM8; \ op2.val = inm; \ break; \ } @@ -267,15 +272,15 @@ // Special routine for JR #define dis_JR(opcode, name) \ case opcode: { \ - s8 offset = memory.read(PC++); \ + s8 offset = gb.memory.read(PC++); \ result << name << " " << std::dec << int(offset) << "\t[0x" \ << std::hex << std::setw(2) << int(PC+offset) << "]"; \ opcode_str = name; \ - op1_str = ToString(int(offset)); \ - op2_str = ToString(int(PC+offset)); \ - op1.type = INM8; \ - op1.reg = offset; \ - op2.type = NONE; \ + op1.str = ToString(int(offset)); \ + op2.str = ToString(int(PC+offset)); \ + op1.type = Instruction::INM8; \ + op1.val = offset; \ + op2.type = Instruction::NONE; \ op2.val = int(PC+offset); \ break; \ } diff --git a/wendi/wendi.cc b/wendi/wendi.cc index 75c0d17..d177230 100644 --- a/wendi/wendi.cc +++ b/wendi/wendi.cc @@ -1,18 +1,20 @@ #include "../gbcore.h" #include "CodeBlock.h" +#include "disasm.h" #include #include #include #include #include -#include +#include +//#include using std::vector; using std::list; using std::pair; using std::string; -using std::tr1::unordered_map; +//using std::tr1::unordered_map; typedef u16 address; @@ -46,11 +48,16 @@ int main(int argc, char **argv) bool jump_reached = false; while(!jump_reached) { - string ins; - int len; - gb.disassemble_opcode(addr, ins, len); - blocks.back().add_instruction(ins, len); - addr += len; + Instruction ins(disassemble_opcode(gb, addr)); + blocks.back().add_instruction(ins.all, ins.length); + addr += ins.length; + + if (ins.is_jump()) jump_reached=true; } } + + //std::for_each(blocks, show_block); + for (list::iterator i = blocks.begin(); i != blocks.end(); i++) + show_block(*i); + return 0; }