Moar disassembler work. Build still broken.
authorslack <slack@codemaniacs.com>
Fri, 15 Aug 2008 19:04:33 +0000 (21:04 +0200)
committerslack <slack@codemaniacs.com>
Fri, 15 Aug 2008 19:04:33 +0000 (21:04 +0200)
12 files changed:
GBRom.cc
GBVideo.cc
Makefile
gbcore.cc
gbcore.h
tests/test_core.cc
wendi/Instruction.cc [new file with mode: 0644]
wendi/Instruction.h [new file with mode: 0644]
wendi/disasm.cc
wendi/disasm.h
wendi/disasm_macros.h
wendi/wendi.cc

index 87eb926490aec1426b958062b3ffd6011f6195c5..56f5e05215e402bcb6b65c62d05ed8eb548112db 100644 (file)
--- a/GBRom.cc
+++ b/GBRom.cc
@@ -83,6 +83,7 @@ GBRom *read_gbrom(std::string filename)
 
 #include <cstdlib>
 
+extern "C"
 int main(int argc, char *argv[])
 {
        if (argc != 2) {
index a316b206344b16c511bdc2733c29a18bc936a373..526a74d10b4571afadb06e0bab4968fff87adb65 100644 (file)
@@ -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);
index 1883f63b0bcf1ade2268600c7362e35e71dc92a3..dbf4e2e0d05a3e35bc30f7a99f0ef4d700a67ace 100644 (file)
--- 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:
index 0b6695807fbecaf4c05980c4aaf561787bc308e3..4526935b9acca5f305a0363c73ccf9d977510e89 100644 (file)
--- 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;
-}
-
index 48808ea576994cc9efe43c8a023b95acff2e3c23..7e86e5010d5e87e0dd564d34482aab45fdddc2a4 100644 (file)
--- 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);
index e4c9c855fecaf19eb7c2dde714f714d021808560..2d2775cc822ec8a09dd4d10e07aebe256a892ee9 100644 (file)
@@ -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 (file)
index 0000000..1d75a48
--- /dev/null
@@ -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 (file)
index 0000000..17816eb
--- /dev/null
@@ -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
+
index 3f56883d913247b26b4b6aaa4a4e076adfb871ec..37c323ac62835d6cef80a881a89a2fc75c0743cf 100644 (file)
@@ -1,3 +1,6 @@
+#include <iomanip>
+
+#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);
 }
 
index c0bd64020e5f216d6a58a920065a026808abf8d2..3cb01eb6ba185ab5e57374720d3323bb7ba4ece9 100644 (file)
@@ -1,36 +1,11 @@
 #ifndef DISASM_H
 #define DISASM_H
 
+#include "../gbcore.h"
+
 #include <string>
 #include <sstream>
 
-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 <class T> 
 std::string ToString(const T &object)
 {
index b9315d4f3be9d4bb43b47d70ca80c7ad4bdd4607..e7d6bddc63292ce931df2070dde3eb66883046dd 100644 (file)
 #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;
 
 
        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)
        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; \
        }
        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)
        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; \
        }
 // 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; \
        }
index 75c0d17279963035e7cdc05be3f7bcc5e0a05959..d177230662edaed0a1d399a52249273cf76be504 100644 (file)
@@ -1,18 +1,20 @@
 #include "../gbcore.h"
 #include "CodeBlock.h"
+#include "disasm.h"
 
 #include <vector>
 #include <utility>
 #include <string>
 #include <list>
 #include <iostream>
-#include <tr1/unordered_map>
+#include <algorithm>
+//#include <tr1/unordered_map>
 
 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<CodeBlock>::iterator i = blocks.begin(); i != blocks.end(); i++)
+               show_block(*i);
+       return 0;
 }