git.y1.nz

SameBoy

Accurate GB/GBC emulator
download: https://git.y1.nz/archives/sameboy.tar.gz
README | Files | Log | Refs | LICENSE

Core/sm83_disassembler.c

      1 #include <stdio.h>
      2 #include <stdbool.h>
      3 #include "gb.h"
      4 
      5 #define GB_read_memory GB_safe_read_memory
      6 
      7 typedef void opcode_t(GB_gameboy_t *gb, uint8_t opcode, uint16_t *pc);
      8 
      9 static void ill(GB_gameboy_t *gb, uint8_t opcode, uint16_t *pc)
     10 {
     11     GB_log(gb, ".BYTE $%02x\n", opcode);
     12     (*pc)++;
     13 }
     14 
     15 static void nop(GB_gameboy_t *gb, uint8_t opcode, uint16_t *pc)
     16 {
     17     GB_log(gb, "NOP\n");
     18     (*pc)++;
     19 }
     20 
     21 static void stop(GB_gameboy_t *gb, uint8_t opcode, uint16_t *pc)
     22 {
     23     (*pc)++;
     24     uint8_t next = GB_read_memory(gb, (*pc)++);
     25     if (next) {
     26         GB_log(gb, "CORRUPTED STOP (%02x)\n", next);
     27     }
     28     else {
     29         GB_log(gb, "STOP\n");
     30     }
     31 }
     32 
     33 static char *register_names[] = {"af", "bc", "de", "hl", "sp"};
     34 
     35 static void ld_rr_d16(GB_gameboy_t *gb, uint8_t opcode, uint16_t *pc)
     36 {
     37     uint8_t register_id;
     38     uint16_t value;
     39     register_id = (GB_read_memory(gb, (*pc)++) >> 4) + 1;
     40     value = GB_read_memory(gb, (*pc)++);
     41     value |= GB_read_memory(gb, (*pc)++) << 8;
     42     const char *symbol = GB_debugger_name_for_address(gb, value);
     43     if (symbol) {
     44         GB_log(gb, "LD %s, %s ; =$%04x\n", register_names[register_id], symbol, value);
     45     }
     46     else {
     47         GB_log(gb, "LD %s, $%04x\n", register_names[register_id], value);
     48     }
     49 }
     50 
     51 static void ld_drr_a(GB_gameboy_t *gb, uint8_t opcode, uint16_t *pc)
     52 {
     53     uint8_t register_id;
     54     register_id = (GB_read_memory(gb, (*pc)++) >> 4) + 1;
     55     GB_log(gb, "LD [%s], a\n", register_names[register_id]);
     56 }
     57 
     58 static void inc_rr(GB_gameboy_t *gb, uint8_t opcode, uint16_t *pc)
     59 {
     60     uint8_t register_id;
     61     register_id = (GB_read_memory(gb, (*pc)++) >> 4) + 1;
     62     GB_log(gb, "INC %s\n", register_names[register_id]);
     63 }
     64 
     65 static void inc_hr(GB_gameboy_t *gb, uint8_t opcode, uint16_t *pc)
     66 {
     67     uint8_t register_id;
     68     (*pc)++;
     69     register_id = ((opcode >> 4) + 1) & 0x03;
     70     GB_log(gb, "INC %c\n", register_names[register_id][0]);
     71 
     72 }
     73 static void dec_hr(GB_gameboy_t *gb, uint8_t opcode, uint16_t *pc)
     74 {
     75     uint8_t register_id;
     76     (*pc)++;
     77     register_id = ((opcode >> 4) + 1) & 0x03;
     78     GB_log(gb, "DEC %c\n", register_names[register_id][0]);
     79 }
     80 
     81 static void ld_hr_d8(GB_gameboy_t *gb, uint8_t opcode, uint16_t *pc)
     82 {
     83     uint8_t register_id;
     84     (*pc)++;
     85     register_id = ((opcode >> 4) + 1) & 0x03;
     86     GB_log(gb, "LD %c, $%02x\n", register_names[register_id][0], GB_read_memory(gb, (*pc)++));
     87 }
     88 
     89 static void rlca(GB_gameboy_t *gb, uint8_t opcode, uint16_t *pc)
     90 {
     91     (*pc)++;
     92     GB_log(gb, "RLCA\n");
     93 }
     94 
     95 static void rla(GB_gameboy_t *gb, uint8_t opcode, uint16_t *pc)
     96 {
     97     (*pc)++;
     98     GB_log(gb, "RLA\n");
     99 }
    100 
    101 static void ld_da16_sp(GB_gameboy_t *gb, uint8_t opcode, uint16_t *pc)
    102 {
    103     uint16_t addr;
    104     (*pc)++;
    105     addr = GB_read_memory(gb, (*pc)++);
    106     addr |= GB_read_memory(gb, (*pc)++) << 8;
    107     const char *symbol = GB_debugger_name_for_address(gb, addr);
    108     if (symbol) {
    109         GB_log(gb, "LD [%s], sp ; =$%04x\n", symbol, addr);
    110     }
    111     else {
    112         GB_log(gb, "LD [$%04x], sp\n", addr);
    113     }
    114 }
    115 
    116 static void add_hl_rr(GB_gameboy_t *gb, uint8_t opcode, uint16_t *pc)
    117 {
    118     uint8_t register_id;
    119     (*pc)++;
    120     register_id = (opcode >> 4) + 1;
    121     GB_log(gb, "ADD hl, %s\n", register_names[register_id]);
    122 }
    123 
    124 static void ld_a_drr(GB_gameboy_t *gb, uint8_t opcode, uint16_t *pc)
    125 {
    126     uint8_t register_id;
    127     register_id = (GB_read_memory(gb, (*pc)++) >> 4) + 1;
    128     GB_log(gb, "LD a, [%s]\n", register_names[register_id]);
    129 }
    130 
    131 static void dec_rr(GB_gameboy_t *gb, uint8_t opcode, uint16_t *pc)
    132 {
    133     uint8_t register_id;
    134     register_id = (GB_read_memory(gb, (*pc)++) >> 4) + 1;
    135     GB_log(gb, "DEC %s\n", register_names[register_id]);
    136 }
    137 
    138 static void inc_lr(GB_gameboy_t *gb, uint8_t opcode, uint16_t *pc)
    139 {
    140     uint8_t register_id;
    141     register_id = (GB_read_memory(gb, (*pc)++) >> 4) + 1;
    142 
    143     GB_log(gb, "INC %c\n", register_names[register_id][1]);
    144 }
    145 static void dec_lr(GB_gameboy_t *gb, uint8_t opcode, uint16_t *pc)
    146 {
    147     uint8_t register_id;
    148     register_id = (GB_read_memory(gb, (*pc)++) >> 4) + 1;
    149 
    150     GB_log(gb, "DEC %c\n", register_names[register_id][1]);
    151 }
    152 
    153 static void ld_lr_d8(GB_gameboy_t *gb, uint8_t opcode, uint16_t *pc)
    154 {
    155     uint8_t register_id;
    156     register_id = (GB_read_memory(gb, (*pc)++) >> 4) + 1;
    157 
    158     GB_log(gb, "LD %c, $%02x\n", register_names[register_id][1], GB_read_memory(gb, (*pc)++));
    159 }
    160 
    161 static void rrca(GB_gameboy_t *gb, uint8_t opcode, uint16_t *pc)
    162 {
    163     GB_log(gb, "RRCA\n");
    164     (*pc)++;
    165 }
    166 
    167 static void rra(GB_gameboy_t *gb, uint8_t opcode, uint16_t *pc)
    168 {
    169     GB_log(gb, "RRA\n");
    170     (*pc)++;
    171 }
    172 
    173 static void jr_r8(GB_gameboy_t *gb, uint8_t opcode, uint16_t *pc)
    174 {
    175     (*pc)++;
    176     uint16_t addr = *pc + (int8_t) GB_read_memory(gb, (*pc)) + 1;
    177     const char *symbol = GB_debugger_name_for_address(gb, addr);
    178     if (symbol) {
    179         GB_attributed_log(gb, GB_LOG_UNDERLINE, "JR %s ; =$%04x\n", symbol, addr);
    180     }
    181     else {
    182         GB_attributed_log(gb, GB_LOG_UNDERLINE, "JR $%04x\n", addr);
    183     }
    184     (*pc)++;
    185 }
    186 
    187 static const char *condition_code(uint8_t opcode)
    188 {
    189     switch ((opcode >> 3) & 0x3) {
    190         case 0:
    191             return "nz";
    192         case 1:
    193             return "z";
    194         case 2:
    195             return "nc";
    196         case 3:
    197             return "c";
    198     }
    199 
    200     return NULL;
    201 }
    202 
    203 static void jr_cc_r8(GB_gameboy_t *gb, uint8_t opcode, uint16_t *pc)
    204 {
    205     (*pc)++;
    206     uint16_t addr = *pc + (int8_t) GB_read_memory(gb, (*pc)) + 1;
    207     const char *symbol = GB_debugger_name_for_address(gb, addr);
    208     if (symbol) {
    209         GB_attributed_log(gb,  GB_LOG_DASHED_UNDERLINE, "JR %s, %s ; =$%04x\n", condition_code(opcode), symbol, addr);
    210     }
    211     else {
    212         GB_attributed_log(gb,  GB_LOG_DASHED_UNDERLINE, "JR %s, $%04x\n", condition_code(opcode), addr);
    213     }
    214     (*pc)++;
    215 }
    216 
    217 static void daa(GB_gameboy_t *gb, uint8_t opcode, uint16_t *pc)
    218 {
    219     GB_log(gb, "DAA\n");
    220     (*pc)++;
    221 }
    222 
    223 static void cpl(GB_gameboy_t *gb, uint8_t opcode, uint16_t *pc)
    224 {
    225     GB_log(gb, "CPL\n");
    226     (*pc)++;
    227 }
    228 
    229 static void scf(GB_gameboy_t *gb, uint8_t opcode, uint16_t *pc)
    230 {
    231     GB_log(gb, "SCF\n");
    232     (*pc)++;
    233 }
    234 
    235 static void ccf(GB_gameboy_t *gb, uint8_t opcode, uint16_t *pc)
    236 {
    237     GB_log(gb, "CCF\n");
    238     (*pc)++;
    239 }
    240 
    241 static void ld_dhli_a(GB_gameboy_t *gb, uint8_t opcode, uint16_t *pc)
    242 {
    243     GB_log(gb, "LD [hli], a\n");
    244     (*pc)++;
    245 }
    246 
    247 static void ld_dhld_a(GB_gameboy_t *gb, uint8_t opcode, uint16_t *pc)
    248 {
    249     GB_log(gb, "LD [hld], a\n");
    250     (*pc)++;
    251 }
    252 
    253 static void ld_a_dhli(GB_gameboy_t *gb, uint8_t opcode, uint16_t *pc)
    254 {
    255     GB_log(gb, "LD a, [hli]\n");
    256     (*pc)++;
    257 }
    258 
    259 static void ld_a_dhld(GB_gameboy_t *gb, uint8_t opcode, uint16_t *pc)
    260 {
    261     GB_log(gb, "LD a, [hld]\n");
    262     (*pc)++;
    263 }
    264 
    265 static void inc_dhl(GB_gameboy_t *gb, uint8_t opcode, uint16_t *pc)
    266 {
    267     GB_log(gb, "INC [hl]\n");
    268     (*pc)++;
    269 }
    270 
    271 static void dec_dhl(GB_gameboy_t *gb, uint8_t opcode, uint16_t *pc)
    272 {
    273     GB_log(gb, "DEC [hl]\n");
    274     (*pc)++;
    275 }
    276 
    277 static void ld_dhl_d8(GB_gameboy_t *gb, uint8_t opcode, uint16_t *pc)
    278 {
    279     (*pc)++;
    280     GB_log(gb, "LD [hl], $%02x\n", GB_read_memory(gb, (*pc)++));
    281 }
    282 
    283 static const char *get_src_name(uint8_t opcode)
    284 {
    285     uint8_t src_register_id;
    286     uint8_t src_low;
    287     src_register_id = ((opcode >> 1) + 1) & 3;
    288     src_low = (opcode & 1);
    289     if (src_register_id == GB_REGISTER_AF) {
    290         return src_low? "a": "[hl]";
    291     }
    292     if (src_low) {
    293         return register_names[src_register_id] + 1;
    294     }
    295     static const char *high_register_names[] = {"a", "b", "d", "h"};
    296     return high_register_names[src_register_id];
    297 }
    298 
    299 static const char *get_dst_name(uint8_t opcode)
    300 {
    301     uint8_t dst_register_id;
    302     uint8_t dst_low;
    303     dst_register_id = ((opcode >> 4) + 1) & 3;
    304     dst_low = opcode & 8;
    305     if (dst_register_id == GB_REGISTER_AF) {
    306         return dst_low? "a": "[hl]";
    307     }
    308     if (dst_low) {
    309         return register_names[dst_register_id] + 1;
    310     }
    311     static const char *high_register_names[] = {"a", "b", "d", "h"};
    312     return high_register_names[dst_register_id];
    313 }
    314 
    315 static void ld_r_r(GB_gameboy_t *gb, uint8_t opcode, uint16_t *pc)
    316 {
    317     (*pc)++;
    318     GB_log(gb, "LD %s, %s\n", get_dst_name(opcode), get_src_name(opcode));
    319 }
    320 
    321 static void add_a_r(GB_gameboy_t *gb, uint8_t opcode, uint16_t *pc)
    322 {
    323     (*pc)++;
    324     GB_log(gb, "ADD %s\n",  get_src_name(opcode));
    325 }
    326 
    327 static void adc_a_r(GB_gameboy_t *gb, uint8_t opcode, uint16_t *pc)
    328 {
    329     (*pc)++;
    330     GB_log(gb, "ADC %s\n",  get_src_name(opcode));
    331 }
    332 
    333 static void sub_a_r(GB_gameboy_t *gb, uint8_t opcode, uint16_t *pc)
    334 {
    335     (*pc)++;
    336     GB_log(gb, "SUB %s\n",  get_src_name(opcode));
    337 }
    338 
    339 static void sbc_a_r(GB_gameboy_t *gb, uint8_t opcode, uint16_t *pc)
    340 {
    341     (*pc)++;
    342     GB_log(gb, "SBC %s\n",  get_src_name(opcode));
    343 }
    344 
    345 static void and_a_r(GB_gameboy_t *gb, uint8_t opcode, uint16_t *pc)
    346 {
    347     (*pc)++;
    348     GB_log(gb, "AND %s\n",  get_src_name(opcode));
    349 }
    350 
    351 static void xor_a_r(GB_gameboy_t *gb, uint8_t opcode, uint16_t *pc)
    352 {
    353     (*pc)++;
    354     GB_log(gb, "XOR %s\n",  get_src_name(opcode));
    355 }
    356 
    357 static void or_a_r(GB_gameboy_t *gb, uint8_t opcode, uint16_t *pc)
    358 {
    359     (*pc)++;
    360     GB_log(gb, "OR %s\n",  get_src_name(opcode));
    361 }
    362 
    363 static void cp_a_r(GB_gameboy_t *gb, uint8_t opcode, uint16_t *pc)
    364 {
    365     (*pc)++;
    366     GB_log(gb, "CP %s\n",  get_src_name(opcode));
    367 }
    368 
    369 static void halt(GB_gameboy_t *gb, uint8_t opcode, uint16_t *pc)
    370 {
    371     (*pc)++;
    372     GB_log(gb, "HALT\n");
    373 }
    374 
    375 static void ret_cc(GB_gameboy_t *gb, uint8_t opcode, uint16_t *pc)
    376 {
    377     (*pc)++;
    378     GB_attributed_log(gb,  GB_LOG_DASHED_UNDERLINE, "RET %s\n", condition_code(opcode));
    379 }
    380 
    381 static void pop_rr(GB_gameboy_t *gb, uint8_t opcode, uint16_t *pc)
    382 {
    383     uint8_t register_id;
    384     register_id = ((GB_read_memory(gb, (*pc)++) >> 4) + 1) & 3;
    385     GB_log(gb, "POP %s\n", register_names[register_id]);
    386 }
    387 
    388 static void jp_cc_a16(GB_gameboy_t *gb, uint8_t opcode, uint16_t *pc)
    389 {
    390     (*pc)++;
    391     uint16_t addr = GB_read_memory(gb, *pc) | (GB_read_memory(gb, *pc + 1) << 8);
    392     const char *symbol = GB_debugger_name_for_address(gb, addr);
    393     if (symbol) {
    394         GB_attributed_log(gb, GB_LOG_DASHED_UNDERLINE, "JP %s, %s ; =$%04x\n", condition_code(opcode), symbol, addr);
    395     }
    396     else {
    397         GB_attributed_log(gb, GB_LOG_DASHED_UNDERLINE, "JP %s, $%04x\n", condition_code(opcode), addr);
    398     }
    399     (*pc) += 2;
    400 }
    401 
    402 static void jp_a16(GB_gameboy_t *gb, uint8_t opcode, uint16_t *pc)
    403 {
    404     (*pc)++;
    405     uint16_t addr = GB_read_memory(gb, *pc) | (GB_read_memory(gb, *pc + 1) << 8);
    406     const char *symbol = GB_debugger_name_for_address(gb, addr);
    407     if (symbol) {
    408         GB_log(gb, "JP %s ; =$%04x\n", symbol, addr);
    409     }
    410     else {
    411         GB_log(gb, "JP $%04x\n", addr);
    412     }
    413     (*pc) += 2;
    414 }
    415 
    416 static void call_cc_a16(GB_gameboy_t *gb, uint8_t opcode, uint16_t *pc)
    417 {
    418     (*pc)++;
    419     uint16_t addr = GB_read_memory(gb, *pc) | (GB_read_memory(gb, *pc + 1) << 8);
    420     const char *symbol = GB_debugger_name_for_address(gb, addr);
    421     if (symbol) {
    422         GB_log(gb, "CALL %s, %s ; =$%04x\n", condition_code(opcode), symbol, addr);
    423     }
    424     else {
    425         GB_log(gb, "CALL %s, $%04x\n", condition_code(opcode), addr);
    426     }
    427     (*pc) += 2;
    428 }
    429 
    430 static void push_rr(GB_gameboy_t *gb, uint8_t opcode, uint16_t *pc)
    431 {
    432     uint8_t register_id;
    433     register_id = ((GB_read_memory(gb, (*pc)++) >> 4) + 1) & 3;
    434     GB_log(gb, "PUSH %s\n", register_names[register_id]);
    435 }
    436 
    437 static void add_a_d8(GB_gameboy_t *gb, uint8_t opcode, uint16_t *pc)
    438 {
    439     (*pc)++;
    440     GB_log(gb, "ADD $%02x\n", GB_read_memory(gb, (*pc)++));
    441 }
    442 
    443 static void adc_a_d8(GB_gameboy_t *gb, uint8_t opcode, uint16_t *pc)
    444 {
    445     (*pc)++;
    446     GB_log(gb, "ADC $%02x\n", GB_read_memory(gb, (*pc)++));
    447 }
    448 
    449 static void sub_a_d8(GB_gameboy_t *gb, uint8_t opcode, uint16_t *pc)
    450 {
    451     (*pc)++;
    452     GB_log(gb, "SUB $%02x\n", GB_read_memory(gb, (*pc)++));
    453 }
    454 
    455 static void sbc_a_d8(GB_gameboy_t *gb, uint8_t opcode, uint16_t *pc)
    456 {
    457     (*pc)++;
    458     GB_log(gb, "SBC $%02x\n", GB_read_memory(gb, (*pc)++));
    459 }
    460 
    461 static void and_a_d8(GB_gameboy_t *gb, uint8_t opcode, uint16_t *pc)
    462 {
    463     (*pc)++;
    464     GB_log(gb, "AND $%02x\n", GB_read_memory(gb, (*pc)++));
    465 }
    466 
    467 static void xor_a_d8(GB_gameboy_t *gb, uint8_t opcode, uint16_t *pc)
    468 {
    469     (*pc)++;
    470     GB_log(gb, "XOR $%02x\n", GB_read_memory(gb, (*pc)++));
    471 }
    472 
    473 static void or_a_d8(GB_gameboy_t *gb, uint8_t opcode, uint16_t *pc)
    474 {
    475     (*pc)++;
    476     GB_log(gb, "OR $%02x\n", GB_read_memory(gb, (*pc)++));
    477 }
    478 
    479 static void cp_a_d8(GB_gameboy_t *gb, uint8_t opcode, uint16_t *pc)
    480 {
    481     (*pc)++;
    482     GB_log(gb, "CP $%02x\n", GB_read_memory(gb, (*pc)++));
    483 }
    484 
    485 static void rst(GB_gameboy_t *gb, uint8_t opcode, uint16_t *pc)
    486 {
    487     (*pc)++;
    488     GB_log(gb, "RST $%02x\n", opcode ^ 0xC7);
    489 
    490 }
    491 
    492 static void ret(GB_gameboy_t *gb, uint8_t opcode, uint16_t *pc)
    493 {
    494     (*pc)++;
    495     GB_attributed_log(gb, GB_LOG_UNDERLINE, "RET\n");
    496 }
    497 
    498 static void reti(GB_gameboy_t *gb, uint8_t opcode, uint16_t *pc)
    499 {
    500     (*pc)++;
    501     GB_attributed_log(gb, GB_LOG_UNDERLINE, "RETI\n");
    502 }
    503 
    504 static void call_a16(GB_gameboy_t *gb, uint8_t opcode, uint16_t *pc)
    505 {
    506     (*pc)++;
    507     uint16_t addr = GB_read_memory(gb, *pc) | (GB_read_memory(gb, *pc + 1) << 8);
    508     const char *symbol = GB_debugger_name_for_address(gb, addr);
    509     if (symbol) {
    510         GB_log(gb, "CALL %s ; =$%04x\n", symbol, addr);
    511     }
    512     else {
    513         GB_log(gb, "CALL $%04x\n", addr);
    514     }
    515     (*pc) += 2;
    516 }
    517 
    518 static void ld_da8_a(GB_gameboy_t *gb, uint8_t opcode, uint16_t *pc)
    519 {
    520     (*pc)++;
    521     uint8_t addr = GB_read_memory(gb, (*pc)++);
    522     const char *symbol = GB_debugger_name_for_address(gb, 0xFF00 + addr);
    523     if (symbol) {
    524         GB_log(gb, "LDH [%s & $FF], a ; =$%02x\n", symbol, addr);
    525     }
    526     else {
    527         GB_log(gb, "LDH [$%02x], a\n", addr);
    528     }
    529 }
    530 
    531 static void ld_a_da8(GB_gameboy_t *gb, uint8_t opcode, uint16_t *pc)
    532 {
    533     (*pc)++;
    534     uint8_t addr = GB_read_memory(gb, (*pc)++);
    535     const char *symbol = GB_debugger_name_for_address(gb, 0xFF00 + addr);
    536     if (symbol) {
    537         GB_log(gb, "LDH a, [%s & $FF] ; =$%02x\n", symbol, addr);
    538     }
    539     else {
    540         GB_log(gb, "LDH a, [$%02x]\n", addr);
    541     }
    542 }
    543 
    544 static void ld_dc_a(GB_gameboy_t *gb, uint8_t opcode, uint16_t *pc)
    545 {
    546     (*pc)++;
    547     GB_log(gb, "LDH [c], a\n");
    548 }
    549 
    550 static void ld_a_dc(GB_gameboy_t *gb, uint8_t opcode, uint16_t *pc)
    551 {
    552     (*pc)++;
    553     GB_log(gb, "LDH a, [c]\n");
    554 }
    555 
    556 static void add_sp_r8(GB_gameboy_t *gb, uint8_t opcode, uint16_t *pc)
    557 {
    558     (*pc)++;
    559     int8_t temp = GB_read_memory(gb, (*pc)++);
    560     GB_log(gb, "ADD SP, %s$%02x\n", temp < 0? "-" : "", temp < 0? -temp : temp);
    561 }
    562 
    563 static void jp_hl(GB_gameboy_t *gb, uint8_t opcode, uint16_t *pc)
    564 {
    565     (*pc)++;
    566     GB_log(gb, "JP hl\n");
    567 }
    568 
    569 static void ld_da16_a(GB_gameboy_t *gb, uint8_t opcode, uint16_t *pc)
    570 {
    571     (*pc)++;
    572     uint16_t addr = GB_read_memory(gb, *pc) | (GB_read_memory(gb, *pc + 1) << 8);
    573     const char *symbol = GB_debugger_name_for_address(gb, addr);
    574     if (symbol) {
    575         GB_log(gb, "LD [%s], a ; =$%04x\n", symbol, addr);
    576     }
    577     else {
    578         GB_log(gb, "LD [$%04x], a\n", addr);
    579     }
    580     (*pc) += 2;
    581 }
    582 
    583 static void ld_a_da16(GB_gameboy_t *gb, uint8_t opcode, uint16_t *pc)
    584 {
    585     (*pc)++;
    586     uint16_t addr = GB_read_memory(gb, *pc) | (GB_read_memory(gb, *pc + 1) << 8);
    587     const char *symbol = GB_debugger_name_for_address(gb, addr);
    588     if (symbol) {
    589         GB_log(gb, "LD a, [%s] ; =$%04x\n", symbol, addr);
    590     }
    591     else {
    592         GB_log(gb, "LD a, [$%04x]\n", addr);
    593     }
    594     (*pc) += 2;
    595 }
    596 
    597 static void di(GB_gameboy_t *gb, uint8_t opcode, uint16_t *pc)
    598 {
    599     (*pc)++;
    600     GB_log(gb, "DI\n");
    601 }
    602 
    603 static void ei(GB_gameboy_t *gb, uint8_t opcode, uint16_t *pc)
    604 {
    605     (*pc)++;
    606     GB_log(gb, "EI\n");
    607 }
    608 
    609 static void ld_hl_sp_r8(GB_gameboy_t *gb, uint8_t opcode, uint16_t *pc)
    610 {
    611     (*pc)++;
    612     int8_t temp = GB_read_memory(gb, (*pc)++);
    613     GB_log(gb, "LD hl, sp, %s$%02x\n", temp < 0? "-" : "", temp < 0? -temp : temp);
    614 }
    615 
    616 static void ld_sp_hl(GB_gameboy_t *gb, uint8_t opcode, uint16_t *pc)
    617 {
    618     (*pc)++;
    619     GB_log(gb, "LD sp, hl\n");
    620 }
    621 
    622 static void rlc_r(GB_gameboy_t *gb, uint8_t opcode, uint16_t *pc)
    623 {
    624     (*pc)++;
    625     GB_log(gb, "RLC %s\n",  get_src_name(opcode));
    626 }
    627 
    628 static void rrc_r(GB_gameboy_t *gb, uint8_t opcode, uint16_t *pc)
    629 {
    630     (*pc)++;
    631     GB_log(gb, "RRC %s\n",  get_src_name(opcode));
    632 }
    633 
    634 static void rl_r(GB_gameboy_t *gb, uint8_t opcode, uint16_t *pc)
    635 {
    636     (*pc)++;
    637     GB_log(gb, "RL %s\n",  get_src_name(opcode));
    638 }
    639 
    640 static void rr_r(GB_gameboy_t *gb, uint8_t opcode, uint16_t *pc)
    641 {
    642     (*pc)++;
    643     GB_log(gb, "RR %s\n",  get_src_name(opcode));
    644 }
    645 
    646 static void sla_r(GB_gameboy_t *gb, uint8_t opcode, uint16_t *pc)
    647 {
    648     (*pc)++;
    649     GB_log(gb, "SLA %s\n",  get_src_name(opcode));
    650 }
    651 
    652 static void sra_r(GB_gameboy_t *gb, uint8_t opcode, uint16_t *pc)
    653 {
    654     (*pc)++;
    655     GB_log(gb, "SRA %s\n",  get_src_name(opcode));
    656 }
    657 
    658 static void srl_r(GB_gameboy_t *gb, uint8_t opcode, uint16_t *pc)
    659 {
    660     (*pc)++;
    661     GB_log(gb, "SRL %s\n",  get_src_name(opcode));
    662 }
    663 
    664 static void swap_r(GB_gameboy_t *gb, uint8_t opcode, uint16_t *pc)
    665 {
    666     (*pc)++;
    667     GB_log(gb, "SWAP %s\n",  get_src_name(opcode));
    668 }
    669 
    670 static void bit_r(GB_gameboy_t *gb, uint8_t opcode, uint16_t *pc)
    671 {
    672     uint8_t bit;
    673     (*pc)++;
    674     bit = ((opcode >> 3) & 7);
    675     if ((opcode & 0xC0) == 0x40) { /* Bit */
    676         GB_log(gb, "BIT %s, %d\n",  get_src_name(opcode), bit);
    677     }
    678     else if ((opcode & 0xC0) == 0x80) { /* res */
    679         GB_log(gb, "RES %s, %d\n",  get_src_name(opcode), bit);
    680     }
    681     else if ((opcode & 0xC0) == 0xC0) { /* set */
    682         GB_log(gb, "SET %s, %d\n",  get_src_name(opcode), bit);
    683     }
    684 }
    685 
    686 static void cb_prefix(GB_gameboy_t *gb, uint8_t opcode, uint16_t *pc)
    687 {
    688     opcode = GB_read_memory(gb, ++*pc);
    689     switch (opcode >> 3) {
    690         case 0:
    691             rlc_r(gb, opcode, pc);
    692             break;
    693         case 1:
    694             rrc_r(gb, opcode, pc);
    695             break;
    696         case 2:
    697             rl_r(gb, opcode, pc);
    698             break;
    699         case 3:
    700             rr_r(gb, opcode, pc);
    701             break;
    702         case 4:
    703             sla_r(gb, opcode, pc);
    704             break;
    705         case 5:
    706             sra_r(gb, opcode, pc);
    707             break;
    708         case 6:
    709             swap_r(gb, opcode, pc);
    710             break;
    711         case 7:
    712             srl_r(gb, opcode, pc);
    713             break;
    714         default:
    715             bit_r(gb, opcode, pc);
    716             break;
    717     }
    718 }
    719 
    720 static opcode_t *opcodes[256] = {
    721     /*  X0          X1          X2          X3          X4          X5          X6          X7                */
    722     /*  X8          X9          Xa          Xb          Xc          Xd          Xe          Xf                */
    723     nop,        ld_rr_d16,  ld_drr_a,   inc_rr,     inc_hr,     dec_hr,     ld_hr_d8,   rlca,       /* 0X */
    724     ld_da16_sp, add_hl_rr,  ld_a_drr,   dec_rr,     inc_lr,     dec_lr,     ld_lr_d8,   rrca,
    725     stop,       ld_rr_d16,  ld_drr_a,   inc_rr,     inc_hr,     dec_hr,     ld_hr_d8,   rla,        /* 1X */
    726     jr_r8,      add_hl_rr,  ld_a_drr,   dec_rr,     inc_lr,     dec_lr,     ld_lr_d8,   rra,
    727     jr_cc_r8,   ld_rr_d16,  ld_dhli_a,  inc_rr,     inc_hr,     dec_hr,     ld_hr_d8,   daa,        /* 2X */
    728     jr_cc_r8,   add_hl_rr,  ld_a_dhli,  dec_rr,     inc_lr,     dec_lr,     ld_lr_d8,   cpl,
    729     jr_cc_r8,   ld_rr_d16,  ld_dhld_a,  inc_rr,     inc_dhl,    dec_dhl,    ld_dhl_d8,  scf,        /* 3X */
    730     jr_cc_r8,   add_hl_rr,  ld_a_dhld,  dec_rr,     inc_hr,     dec_hr,     ld_hr_d8,   ccf,
    731     ld_r_r,     ld_r_r,     ld_r_r,     ld_r_r,     ld_r_r,     ld_r_r,     ld_r_r,     ld_r_r,     /* 4X */
    732     ld_r_r,     ld_r_r,     ld_r_r,     ld_r_r,     ld_r_r,     ld_r_r,     ld_r_r,     ld_r_r,
    733     ld_r_r,     ld_r_r,     ld_r_r,     ld_r_r,     ld_r_r,     ld_r_r,     ld_r_r,     ld_r_r,     /* 5X */
    734     ld_r_r,     ld_r_r,     ld_r_r,     ld_r_r,     ld_r_r,     ld_r_r,     ld_r_r,     ld_r_r,
    735     ld_r_r,     ld_r_r,     ld_r_r,     ld_r_r,     ld_r_r,     ld_r_r,     ld_r_r,     ld_r_r,     /* 6X */
    736     ld_r_r,     ld_r_r,     ld_r_r,     ld_r_r,     ld_r_r,     ld_r_r,     ld_r_r,     ld_r_r,
    737     ld_r_r,     ld_r_r,     ld_r_r,     ld_r_r,     ld_r_r,     ld_r_r,     halt,       ld_r_r,     /* 7X */
    738     ld_r_r,     ld_r_r,     ld_r_r,     ld_r_r,     ld_r_r,     ld_r_r,     ld_r_r,     ld_r_r,
    739     add_a_r,    add_a_r,    add_a_r,    add_a_r,    add_a_r,    add_a_r,    add_a_r,    add_a_r,    /* 8X */
    740     adc_a_r,    adc_a_r,    adc_a_r,    adc_a_r,    adc_a_r,    adc_a_r,    adc_a_r,    adc_a_r,
    741     sub_a_r,    sub_a_r,    sub_a_r,    sub_a_r,    sub_a_r,    sub_a_r,    sub_a_r,    sub_a_r,    /* 9X */
    742     sbc_a_r,    sbc_a_r,    sbc_a_r,    sbc_a_r,    sbc_a_r,    sbc_a_r,    sbc_a_r,    sbc_a_r,
    743     and_a_r,    and_a_r,    and_a_r,    and_a_r,    and_a_r,    and_a_r,    and_a_r,    and_a_r,    /* aX */
    744     xor_a_r,    xor_a_r,    xor_a_r,    xor_a_r,    xor_a_r,    xor_a_r,    xor_a_r,    xor_a_r,
    745     or_a_r,     or_a_r,     or_a_r,     or_a_r,     or_a_r,     or_a_r,     or_a_r,     or_a_r,     /* bX */
    746     cp_a_r,     cp_a_r,     cp_a_r,     cp_a_r,     cp_a_r,     cp_a_r,     cp_a_r,     cp_a_r,
    747     ret_cc,     pop_rr,     jp_cc_a16,  jp_a16,     call_cc_a16,push_rr,    add_a_d8,   rst,        /* cX */
    748     ret_cc,     ret,        jp_cc_a16,  cb_prefix,  call_cc_a16,call_a16,   adc_a_d8,   rst,
    749     ret_cc,     pop_rr,     jp_cc_a16,  ill,        call_cc_a16,push_rr,    sub_a_d8,   rst,        /* dX */
    750     ret_cc,     reti,       jp_cc_a16,  ill,        call_cc_a16,ill,        sbc_a_d8,   rst,
    751     ld_da8_a,   pop_rr,     ld_dc_a,    ill,        ill,        push_rr,    and_a_d8,   rst,        /* eX */
    752     add_sp_r8,  jp_hl,      ld_da16_a,  ill,        ill,        ill,        xor_a_d8,   rst,
    753     ld_a_da8,   pop_rr,     ld_a_dc,    di,         ill,        push_rr,    or_a_d8,    rst,        /* fX */
    754     ld_hl_sp_r8,ld_sp_hl,   ld_a_da16,  ei,         ill,        ill,        cp_a_d8,    rst,
    755 };
    756 
    757 
    758 
    759 void GB_cpu_disassemble(GB_gameboy_t *gb, uint16_t pc, uint16_t count)
    760 {
    761     const GB_bank_symbol_t *function_symbol = GB_debugger_find_symbol(gb, pc, false);
    762 
    763     if (function_symbol && pc - function_symbol->addr > 0x1000) {
    764         function_symbol = NULL;
    765     }
    766 
    767     if (function_symbol && pc != function_symbol->addr) {
    768         GB_log(gb, "%s:\n", function_symbol->name);
    769     }
    770 
    771     uint16_t current_function = function_symbol? function_symbol->addr : 0;
    772 
    773     while (count--) {
    774         function_symbol = GB_debugger_find_symbol(gb, pc, false);
    775         if (function_symbol && function_symbol->addr == pc) {
    776             if (current_function != function_symbol->addr) {
    777                 GB_log(gb, "\n");
    778             }
    779             GB_log(gb, "%s:\n", function_symbol->name);
    780         }
    781         if (function_symbol) {
    782             GB_log(gb, "%s%04x <+%03x>: ", pc == gb->pc? "  ->": "    ", pc, pc - function_symbol->addr);
    783         }
    784         else {
    785             GB_log(gb, "%s%04x: ", pc == gb->pc? "  ->": "    ", pc);
    786         }
    787         uint8_t opcode = GB_read_memory(gb, pc);
    788         opcodes[opcode](gb, opcode, &pc);
    789     }
    790 }

This webpage is intended to be an accessible preview of this repository. To get a fuller picture, clone it and use the git CLI.