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.