home *** CD-ROM | disk | FTP | other *** search
- /*
- * gbe - gameboy emulator
- * Copyright (C) 1999 Chuck Mason, Steven Fuller
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- *
- * Chuck Mason <chuckjr@sinclair.net>
- * Steven Fuller <relnev@atdot.org>
- */
- #ifdef CPU_DEBUG
-
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <readline/readline.h>
- #include <readline/history.h>
-
- #include "mem.h"
- #include "cpu.h"
- #include "rom.h"
- #include "vram.h"
- #include "regs.h"
- #include "debug.h"
-
- static int gbz80_debug_status = 0;
- static char *inputline;
-
- static void gbz80_debug_exit(gameboy_proc_t *);
- static void gbz80_debug_step(gameboy_proc_t *);
- static void gbz80_debug_skip(gameboy_proc_t *);
- static void gbz80_debug_help(gameboy_proc_t *);
- static void gbz80_debug_continue(gameboy_proc_t *);
- static void gbz80_debug_run_until(gameboy_proc_t *);
- static void gbz80_debug_dumpmem(gameboy_proc_t *);
- static void gbz80_stats(gameboy_proc_t *);
- static void gbz80_debug_writemem(gameboy_proc_t *);
- static void gbz80_debug_setreg(gameboy_proc_t *);
- static void gbz80_debug_force_screen(gameboy_proc_t *);
- static void gbz80_debug_force_dma(gameboy_proc_t *);
-
- static void dump_ptrs(gameboy_proc_t *gbz80)
- {
- int i;
-
- for(i =0 ; i < 16; i++)
- printf("bank %d = %p\n", i, gameboy_memory[i]);
- }
-
- typedef struct _cmds {
- char cmd;
- char *cmdinfo;
- void (*func)(gameboy_proc_t *);
- } command;
-
- static command commands[] = {
- { 'h', "Show this help", gbz80_debug_help },
- { '?', "Show this help", gbz80_debug_help },
- { 's', "Step one instruction", gbz80_debug_step },
- { 'k', "Skip next instruction", gbz80_debug_skip },
- { 'c', "Continue execution until invalid opcode", gbz80_debug_continue },
- { 'q', "Exits the debugger (also e)", gbz80_debug_exit },
- { 'e', "Exits the debugger (also q)", gbz80_debug_exit },
- { 'u', "Execute until address", gbz80_debug_run_until },
- { 'd', "Dump memory", gbz80_debug_dumpmem },
- { 'r', "Show processor information", gbz80_stats },
- { 'w', "\"w a b\" writes \'b\' address \'a\' in memory", gbz80_debug_writemem },
- { 'm', "\"m <register or flag> <value>\" sets the register/flag to \'value\'", gbz80_debug_setreg },
- { 'v', "Force video refresh", gbz80_debug_force_screen },
- { 'o', "Force DMA copy", gbz80_debug_force_dma },
- { 'p', "Display all bank pointers\n", dump_ptrs },
- { 0x00, (char *)NULL, gbz80_debug_exit },
- };
-
- void gbz80_stats(gameboy_proc_t *gbz80)
- {
- char instruction[512];
-
- gameboy_cpu_create_instruction(instruction, gbz80);
-
- printf("[AF: $%04X]\t[HL: $%04X]\t[BC: $%04X]\t%s\n"
- "[DE: $%04X]\t[SP: $%04X]\t[PC: $%04X]\t[%c%c%c%c....]\n"
- "[(SP): $%04X]\t[(PC): $%02X - %s]\n",
- gbz80->AF.uw,
- gbz80->HL.uw,
- gbz80->BC.uw,
- (gbz80->IFF == 1) ? "EI" : "DI",
- gbz80->DE.uw,
- gbz80->SP.uw,
- gbz80->PC.uw,
- (FLAGS_ISZERO(gbz80)) ? 'Z' : 'z',
- (FLAGS_ISNEGATIVE(gbz80)) ? 'N' : 'n',
- (FLAGS_ISHALFCARRY(gbz80)) ? 'H' : 'h',
- (FLAGS_ISCARRY(gbz80)) ? 'C' : 'c',
- memory_read_word(gbz80->SP.uw),
- memory_read_byte(gbz80->PC.uw),
- instruction
- );
- }
-
-
- void gbz80_debugger(gameboy_proc_t *gbz80)
- {
- char *in;
- char cmd;
- int oldcmd = 0;
- char oldcmdc;
- int i;
-
- /* A just-in-case-er */
- gbe_close_gfx();
-
- gameboy_proc = gbz80;
-
- while(gbz80_debug_status == 0) {
- in = readline("gbz80> ");
- cmd = *in;
- add_history(in);
-
- inputline = in + 1;
-
- if(strlen(in) == 0 && oldcmd != 0)
- cmd = oldcmdc;
- else {
- oldcmd = 1;
- oldcmdc = cmd;
- }
-
- for(i = 0; commands[i].cmd != 0x00; i++) {
- if(cmd == commands[i].cmd) {
- commands[i].func(gbz80);
- break;
- }
- }
- }
- }
-
- void gbz80_debug_exit(gameboy_proc_t *gbz80)
- {
- gbz80_debug_status = 1;
- }
-
- void gbz80_debug_step(gameboy_proc_t *gbz80)
- {
- gameboy_cpu_execute_opcode();
- gbz80_stats(gbz80);
- }
-
- void gbz80_debug_skip(gameboy_proc_t *gbz80)
- {
- gbz80->PC.uw ++;
- gbz80_stats(gbz80);
- }
-
- void gbz80_debug_help(gameboy_proc_t *gbz80)
- {
- int i;
- for(i = 0; commands[i].cmd != 0x00; i++)
- printf("%c - %s\n", commands[i].cmd, commands[i].cmdinfo);
- }
-
- void gbz80_debug_continue(gameboy_proc_t *gbz80)
- {
- for(gbz80->running = 1; gbz80->running; )
- gameboy_cpu_execute_opcode();
- gbz80_stats(gbz80);
- }
-
- void gbz80_debug_run_until(gameboy_proc_t *gbz80)
- {
- unsigned short int address = 0;
-
- if(*inputline == ' ')
- inputline++;
- address = strtoul(inputline, NULL, 16) & 0xFFFF;
-
- for(gbz80->running = 1; gbz80->running && gbz80->PC.uw != address; )
- gameboy_cpu_execute_opcode();
- gbz80_stats(gbz80);
- }
-
- void gbz80_debug_dumpmem(gameboy_proc_t *gbz80)
- {
- unsigned short int address = 0;
- int i, j, k;
-
- if(*inputline == ' ')
- inputline++;
- address = strtoul(inputline, NULL, 16) & 0xFFFF;
-
- for(j = 0; j < 16; j++) {
- printf("%04X: ", address + (j * 16));
- for(k = 0; k < 2; k++) {
- for(i = 0; i < 16; i++) {
- int offs = address + (j * 16) + i;
- unsigned char b;
-
- b = memory_read_byte(offs);
-
- if(k == 0) {
- printf("%02X ", b);
- if(i == 7)
- printf("- ");
- } else {
- printf("%c", isprint(b) ? b : '.');
- }
- }
- }
- printf("\n");
- }
- }
-
- void gbz80_debug_writemem(gameboy_proc_t *gbz80)
- {
- unsigned short int address = 0;
- unsigned char value = 0;
- char *ptr;
-
- if(*inputline == ' ')
- inputline++;
-
- if((ptr = strchr(inputline, ' ')) == NULL) {
- printf("gbz80_debugger: expected arguments\n");
- return;
- }
- *ptr++ = '\0';
- address = strtoul(inputline, NULL, 16) & 0xFFFF;
- value = strtoul(ptr, NULL, 16) & 0xFF;
-
- memory_write_byte(address, value);
-
- printf("gbz80_debugger: wrote 0x%02X to 0x%04X\n", value, address);
- }
-
- void gbz80_debug_setreg(gameboy_proc_t *gbz80)
- {
- char *regname;
- unsigned short int value;
-
- if(*inputline == ' ')
- inputline++;
-
- if(strlen(inputline) == 0) { /* help */
- printf("gbz80_debugger: possible Registers are:\n");
- printf("\t16bit: PC AF BC DE HL SP\n");
- printf("\t 8bit: A B C D E F H L\n");
- printf("\tflags: zero halfcarry carry negative IFF\n");
- return;
- }
-
- regname = inputline;
-
- if((inputline = strchr(inputline, ' ')) == NULL) {
- printf("gbz80_debugger: expected arguments\n");
- return;
- }
- *inputline++ = '\0';
-
- value = strtoul(inputline, NULL, 16) & 0xFFFF;
-
- if(strcasecmp(regname, "AF") == 0)
- gbz80->AF.uw = value;
- else if(strcasecmp(regname, "PC") == 0)
- gbz80->PC.uw = value;
- else if(strcasecmp(regname, "BC") == 0)
- gbz80->BC.uw = value;
- else if(strcasecmp(regname, "DE") == 0)
- gbz80->DE.uw = value;
- else if(strcasecmp(regname, "HL") == 0)
- gbz80->HL.uw = value;
- else if(strcasecmp(regname, "SP") == 0)
- gbz80->SP.uw = value;
- else if(strcasecmp(regname, "A") == 0)
- gbz80->AF.b.h = value & 0xFF;
- else if(strcasecmp(regname, "B") == 0)
- gbz80->BC.b.h = value & 0xFF;
- else if(strcasecmp(regname, "C") == 0)
- gbz80->BC.b.l = value & 0xFF;
- else if(strcasecmp(regname, "D") == 0)
- gbz80->DE.b.h = value & 0xFF;
- else if(strcasecmp(regname, "E") == 0)
- gbz80->DE.b.l = value & 0xFF;
- else if(strcasecmp(regname, "F") == 0)
- gbz80->AF.b.l = value & 0xFF;
- else if(strcasecmp(regname, "H") == 0)
- gbz80->HL.b.h = value & 0xFF;
- else if(strcasecmp(regname, "L") == 0)
- gbz80->HL.b.l = value & 0xFF;
- else if(strcasecmp(regname, "ZERO") == 0) {
- if(value)
- FLAGS_SET(gbz80, FLAGS_ZERO);
- else
- FLAGS_CLEAR(gbz80, FLAGS_ZERO);
- } else if(strcasecmp(regname, "CARRY") == 0) {
- if(value)
- FLAGS_SET(gbz80, FLAGS_CARRY);
- else
- FLAGS_CLEAR(gbz80, FLAGS_CARRY);
- } else if(strcasecmp(regname, "HALFCARRY") == 0) {
- if(value)
- FLAGS_SET(gbz80, FLAGS_HALFCARRY);
- else
- FLAGS_CLEAR(gbz80, FLAGS_HALFCARRY);
- } else if(strcasecmp(regname, "NEGATIVE") == 0) {
- if(value)
- FLAGS_SET(gbz80, FLAGS_NEGATIVE);
- else
- FLAGS_CLEAR(gbz80, FLAGS_NEGATIVE);
- } else if(strcasecmp(regname, "IFF") == 0) {
- gbz80->IFF = (value) ? 1 : 0;
- } else {
- printf("gbz80_debugger: unknown register \'%s\'\n", regname);
- return;
- }
-
- printf("gbz80_debugger: \'%s\' set to %X\n", regname, value);
- return;
- }
-
- void gbz80_debug_force_screen(gameboy_proc_t *gbz80)
- {
- unsigned char temp;
- temp = CURLINE;
-
- for(CURLINE = 0; CURLINE < 144; CURLINE++)
- vram_plot_screen();
- CURLINE = temp;
- vram_blit();
- }
-
- void gbz80_debug_force_dma(gameboy_proc_t *gbz80)
- {
- gameboy_do_dma();
- }
-
- #else
-
- #include <stdio.h>
-
- void gbz80_debugger(void *garbage)
- {
- printf("Debugger not available!\n");
- }
-
- #endif
-