📄 debug.cpp
字号:
/* * Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. * * (c) Copyright 1996 - 2001 Gary Henderson (gary@daniver.demon.co.uk) and * Jerremy Koot (jkoot@snes9x.com) * * Super FX C emulator code * (c) Copyright 1997 - 1999 Ivar (Ivar@snes9x.com) and * Gary Henderson. * Super FX assembler emulator code (c) Copyright 1998 zsKnight and _Demo_. * * DSP1 emulator code (c) Copyright 1998 Ivar, _Demo_ and Gary Henderson. * C4 asm and some C emulation code (c) Copyright 2000 zsKnight and _Demo_. * C4 C code (c) Copyright 2001 Gary Henderson (gary@daniver.demon.co.uk). * * DOS port code contains the works of other authors. See headers in * individual files. * * Snes9x homepage: www.snes9x.com * * Permission to use, copy, modify and distribute Snes9x in both binary and * source form, for non-commercial purposes, is hereby granted without fee, * providing that this license information and copyright notice appear with * all copies and any derived work. * * This software is provided 'as-is', without any express or implied * warranty. In no event shall the authors be held liable for any damages * arising from the use of this software. * * Snes9x is freeware for PERSONAL USE only. Commercial users should * seek permission of the copyright holders first. Commercial use includes * charging money for Snes9x or software derived from Snes9x. * * The copyright holders request that bug fixes and improvements to the code * should be forwarded to them so everyone can benefit from the modifications * in future versions. * * Super NES and Super Nintendo Entertainment System are trademarks of * Nintendo Co., Limited and its subsidiary companies. */#include <string.h>#include "snes9x.h"#include "memmap.h"#include "cpuops.h"#include "cheats.h"#include "ppu.h"#include "cpuexec.h"#include "debug.h"#include "missing.h"#include "display.h"#include "apu.h"#include "sa1.h"#ifdef DEBUGGERstatic void WhatsMissing ();static void WhatsUsed ();EXTERN_C SDMA DMA[8];extern struct SCheatData Cheat;#ifdef SPCTOOL#include "spctool/spc700.h"extern "C" void TraceSPC (unsigned char *PC, unsigned short YA, unsigned char X, SPCFlags PS, unsigned char *SP);#endifFILE *trace = NULL;FILE *trace2 = NULL;struct SBreakPoint S9xBreakpoint[6];struct SDebug{ struct { uint8 Bank; uint16 Address; } Dump; struct { uint8 Bank; uint16 Address; } Unassemble;} Debug ={ { 0, 0 }, { 0, 0 }};char *HelpMessage[] = { "Command Help:", "? - Shows this Command Help", "r - Shows the Registers", "i - Shows the interrupt vectors", "t - Trace current instruction [Step-into]", "T - Toggle CPU instruction tracing to trace.log", "D - Toggle DMA tracing to stdout", "H - Toggle H-DMA tracing to stdout", "P - Toggle DSP tracing to stdout", "U - Toggle unknown register read/write tracing", "V - Toggle non-DMA V-RAM read/write tracing", "R - Reset ROM.", "p - Proceed to next instruction [Step-over]", "s - Skip to next instruction [Skip]", "S - dump sprite (OBJ) status", "g [Address] - Go or Go to [Address]", "u [Address] - Disassemble from PC or [Address]", "d [Address] - Dump from PC or [Address]", "bv [Number] - View Breakpoints or View Breakpoint [Number]", "bs [Number] [Address] - Enable/Disable Breakpoint", " [Enable example: BS #2 $02:8002]", " [Disable example: BS #2]", "c - Dump SNES colour palette", "W - Show what SNES hardware features a ROM is using", " which might not be implemented yet.", "w - Show some SNES hardware features used so far in this frame", "q - Quit emulator", "", "[Address] - $Bank:Address or $Address", " [For example: $01:8123]", "[Number] - #Number", " [For example: #1]", "a - Show Sound CPU status", "A - Toggle sound CPU instruction tracing to aputrace.log", "B - Toggle sound DSP register tracing", "C - Dump sound sample addresses", "ad [Address] - Dump sound CPU RAM from PC or [Address]", "", NULL};char *S9xMnemonics[256] = { "BRK", "ORA", "COP", "ORA", "TSB", "ORA", "ASL", "ORA", "PHP", "ORA", "ASL", "PHD", "TSB", "ORA", "ASL", "ORA", "BPL", "ORA", "ORA", "ORA", "TRB", "ORA", "ASL", "ORA", "CLC", "ORA", "INC", "TCS", "TRB", "ORA", "ASL", "ORA", "JSR", "AND", "JSL", "AND", "BIT", "AND", "ROL", "AND", "PLP", "AND", "ROL", "PLD", "BIT", "AND", "ROL", "AND", "BMI", "AND", "AND", "AND", "BIT", "AND", "ROL", "AND", "SEC", "AND", "DEC", "TSC", "BIT", "AND", "ROL", "AND", "RTI", "EOR", "DB ", "EOR", "MVP", "EOR", "LSR", "EOR", "PHA", "EOR", "LSR", "PHK", "JMP", "EOR", "LSR", "EOR", "BVC", "EOR", "EOR", "EOR", "MVN", "EOR", "LSR", "EOR", "CLI", "EOR", "PHY", "TCD", "JMP", "EOR", "LSR", "EOR", "RTS", "ADC", "PER", "ADC", "STZ", "ADC", "ROR", "ADC", "PLA", "ADC", "ROR", "RTL", "JMP", "ADC", "ROR", "ADC", "BVS", "ADC", "ADC", "ADC", "STZ", "ADC", "ROR", "ADC", "SEI", "ADC", "PLY", "TDC", "JMP", "ADC", "ROR", "ADC", "BRA", "STA", "BRL", "STA", "STY", "STA", "STX", "STA", "DEY", "BIT", "TXA", "PHB", "STY", "STA", "STX", "STA", "BCC", "STA", "STA", "STA", "STY", "STA", "STX", "STA", "TYA", "STA", "TXS", "TXY", "STZ", "STA", "STZ", "STA", "LDY", "LDA", "LDX", "LDA", "LDY", "LDA", "LDX", "LDA", "TAY", "LDA", "TAX", "PLB", "LDY", "LDA", "LDX", "LDA", "BCS", "LDA", "LDA", "LDA", "LDY", "LDA", "LDX", "LDA", "CLV", "LDA", "TSX", "TYX", "LDY", "LDA", "LDX", "LDA", "CPY", "CMP", "REP", "CMP", "CPY", "CMP", "DEC", "CMP", "INY", "CMP", "DEX", "WAI", "CPY", "CMP", "DEC", "CMP", "BNE", "CMP", "CMP", "CMP", "PEI", "CMP", "DEC", "CMP", "CLD", "CMP", "PHX", "STP", "JML", "CMP", "DEC", "CMP", "CPX", "SBC", "SEP", "SBC", "CPX", "SBC", "INC", "SBC", "INX", "SBC", "NOP", "XBA", "CPX", "SBC", "INC", "SBC", "BEQ", "SBC", "SBC", "SBC", "PEA", "SBC", "INC", "SBC", "SED", "SBC", "PLX", "XCE", "JSR", "SBC", "INC", "SBC"};int AddrModes[256] = { //0 1 2 3 4 5 6 7 8 9 A B C D E F 3, 10, 3, 19, 6, 6, 6, 12, 0, 1,24, 0, 14, 14, 14, 17, //0 4, 11, 9, 20, 6, 7, 7, 13, 0, 16,24, 0, 14, 15, 15, 18, //1 14, 10,17, 19, 6, 6, 6, 12, 0, 1,24, 0, 14, 14, 14, 17, //2 4, 11, 9, 20, 7, 7, 7, 13, 0, 16,24, 0, 15, 15, 15, 18, //3 0, 10, 3, 19, 25,6, 6, 12, 0, 1,24, 0, 14, 14, 14, 17, //4 4, 11, 9, 20, 25,7, 7, 13, 0, 16, 0, 0, 17, 15, 15, 18, //5 0, 10, 5, 19, 6, 6, 6, 12, 0, 1,24, 0, 21, 14, 14, 17, //6 4, 11, 9, 20, 7, 7, 7, 13, 0, 16, 0, 0, 23, 15, 15, 18, //7 4, 10, 5, 19, 6, 6, 6, 12, 0, 1, 0, 0, 14, 14, 14, 17, //8 4, 11, 9, 20, 7, 7, 8, 13, 0, 16, 0, 0, 14, 15, 15, 18, //9 2, 10, 2, 19, 6, 6, 6, 12, 0, 1, 0, 0, 14, 14, 14, 17, //A 4, 11, 9, 20, 7, 7, 8, 13, 0, 16, 0, 0, 15, 15, 16, 18, //B 2, 10, 3, 19, 6, 6, 6, 12, 0, 1, 0, 0, 14, 14, 14, 17, //C 4, 11, 9, 9, 0, 7, 7, 13, 0, 16, 0, 0, 22, 15, 15, 18, //D 2, 10, 3, 19, 6, 6, 6, 12, 0, 1, 0, 0, 14, 14, 14, 17, //E 4, 11, 9, 20,14, 7, 7, 13, 0, 16, 0, 0, 23, 15, 15, 18 //F};uint8 S9xOPrint (char *Line, uint8 Bank, uint16 Address){ uint8 S9xOpcode; uint8 Operant[3]; uint16 Word; uint8 Byte; uint8 Size = 0; char SByte; short SWord;#if 0 sprintf (Line, "%04X%04X%04X%04X%02X%04X%c%c%c%c%c%c%c%c%c%03d%03d", Registers.A.W, Registers.X.W, Registers.Y.W, Registers.D.W, Registers.DB, Registers.S.W, CheckEmulation () ? 'E' : 'e', CheckNegative () ? 'N' : 'n', CheckOverflow () ? 'V' : 'v', CheckMemory () ? 'M' : 'm', CheckIndex () ? 'X' : 'x', CheckDecimal () ? 'D' : 'd', CheckIRQ () ? 'I' : 'i', CheckZero () ? 'Z' : 'z', CheckCarry () ? 'C' : 'c', CPU.Cycles, CPU.V_Counter); return (0);#else uint32 Cycles = CPU.Cycles; uint8 *WaitAddress = CPU.WaitAddress; S9xOpcode = S9xGetByte ((Bank << 16) + Address); sprintf (Line, "$%02X:%04X %02X ", Bank, Address, S9xOpcode); Operant[0] = S9xGetByte ((Bank << 16) + Address + 1); Operant[1] = S9xGetByte ((Bank << 16) + Address + 2); Operant[2] = S9xGetByte ((Bank << 16) + Address + 3); switch (AddrModes[S9xOpcode]) { case 0: //Implied sprintf (Line, "%s %s", Line, S9xMnemonics[S9xOpcode]); Size = 1; break; case 1: //Immediate[MemoryFlag] if (!CheckFlag (MemoryFlag)) { //Accumulator 16 - Bit sprintf (Line, "%s%02X %02X %s #$%02X%02X", Line, Operant[0], Operant[1], S9xMnemonics[S9xOpcode], Operant[1], Operant[0]); Size = 3; } else { //Accumulator 8 - Bit sprintf (Line, "%s%02X %s #$%02X", Line, Operant[0], S9xMnemonics[S9xOpcode], Operant[0]); Size = 2; } break; case 2: //Immediate[IndexFlag] if (!CheckFlag (IndexFlag)) { //X / Y 16 - Bit sprintf (Line, "%s%02X %02X %s #$%02X%02X", Line, Operant[0], Operant[1], S9xMnemonics[S9xOpcode], Operant[1], Operant[0]); Size = 3; } else { //X / Y 8 - Bit sprintf (Line, "%s%02X %s #$%02X", Line, Operant[0], S9xMnemonics[S9xOpcode], Operant[0]); Size = 2; } break; case 3: //Immediate[Always 8 - Bit] if (1) { //Always 8 - Bit sprintf (Line, "%s%02X %s #$%02X", Line, Operant[0], S9xMnemonics[S9xOpcode], Operant[0]); Size = 2; } break; case 4: //Relative sprintf (Line, "%s%02X %s $%02X", Line, Operant[0], S9xMnemonics[S9xOpcode], Operant[0]); SByte = Operant[0]; Word = Address; Word += SByte; Word += 2; sprintf (Line, "%-32s[$%04X]", Line, Word); Size = 2; break; case 5: //Relative Long sprintf (Line, "%s%02X %02X %s $%02X%02X", Line, Operant[0], Operant[1], S9xMnemonics[S9xOpcode], Operant[1], Operant[0]); SWord = (Operant[1] << 8) | Operant[0]; Word = Address; Word += SWord; Word += 3; sprintf (Line, "%-32s[$%04X]", Line, Word); Size = 3; break; case 6: //Direct sprintf (Line, "%s%02X %s $%02X", Line, Operant[0], S9xMnemonics[S9xOpcode], Operant[0]); Word = Operant[0]; Word += Registers.D.W; sprintf (Line, "%-32s[$00:%04X]", Line, Word); Size = 2; break; case 7: //Direct indexed (with x) sprintf (Line, "%s%02X %s $%02X,x", Line, Operant[0], S9xMnemonics[S9xOpcode], Operant[0]); Word = Operant[0]; Word += Registers.D.W; Word += Registers.X.W; sprintf (Line, "%-32s[$00:%04X]", Line, Word); Size = 2; break; case 8: //Direct indexed (with y) sprintf (Line, "%s%02X %s $%02X,y", Line, Operant[0], S9xMnemonics[S9xOpcode], Operant[0]); Word = Operant[0]; Word += Registers.D.W; Word += Registers.Y.W; sprintf (Line, "%-32s[$00:%04X]", Line, Word); Size = 2; break; case 9: //Direct Indirect sprintf (Line, "%s%02X %s ($%02X)", Line, Operant[0], S9xMnemonics[S9xOpcode], Operant[0]); Word = Operant[0]; Word += Registers.D.W; Word = S9xGetWord (Word); sprintf (Line, "%-32s[$%02X:%04X]", Line, Registers.DB, Word); Size = 2; break; case 10: //Direct Indexed Indirect sprintf (Line, "%s%02X %s ($%02X,x)", Line, Operant[0], S9xMnemonics[S9xOpcode], Operant[0]); Word = Operant[0]; Word += Registers.D.W; Word += Registers.X.W; Word = S9xGetWord (Word); sprintf (Line, "%-32s[$%02X:%04X]", Line, Registers.DB, Word); Size = 2; break; case 11: //Direct Indirect Indexed sprintf (Line, "%s%02X %s ($%02X),y", Line, Operant[0], S9xMnemonics[S9xOpcode], Operant[0]); Word = Operant[0]; Word += Registers.D.W; Word = S9xGetWord (Word); Word += Registers.Y.W; sprintf (Line, "%-32s[$%02X:%04X]", Line, Registers.DB, Word); Size = 2; break; case 12: //Direct Indirect Long sprintf (Line, "%s%02X %s [$%02X]", Line, Operant[0], S9xMnemonics[S9xOpcode], Operant[0]); Word = Operant[0]; Word += Registers.D.W; Byte = S9xGetByte (Word + 2); Word = S9xGetWord (Word); sprintf (Line, "%-32s[$%02X:%04X]", Line, Byte, Word); Size = 2; break; case 13: //Direct Indirect Indexed Long sprintf (Line, "%s%02X %s [$%02X],y", Line, Operant[0], S9xMnemonics[S9xOpcode], Operant[0]); Word = Operant[0]; Word += Registers.D.W; Byte = S9xGetByte (Word + 2); Word = S9xGetWord (Word); Word += Registers.Y.W; sprintf (Line, "%-32s[$%02X:%04X]", Line, Byte, Word); Size = 2; break; case 14: //Absolute sprintf (Line, "%s%02X %02X %s $%02X%02X", Line, Operant[0], Operant[1], S9xMnemonics[S9xOpcode], Operant[1], Operant[0]); Word = (Operant[1] << 8) | Operant[0]; sprintf (Line, "%-32s[$%02X:%04X]", Line, Registers.DB, Word); Size = 3; break; case 15: //Absolute Indexed (With X) sprintf (Line, "%s%02X %02X %s $%02X%02X,x", Line, Operant[0], Operant[1], S9xMnemonics[S9xOpcode], Operant[1], Operant[0]); Word = (Operant[1] << 8) | Operant[0]; Word += Registers.X.W; sprintf (Line, "%-32s[$%02X:%04X]", Line, Registers.DB, Word); Size = 3; break; case 16: //Absolute Indexed (With Y) sprintf (Line, "%s%02X %02X %s $%02X%02X,y", Line, Operant[0], Operant[1], S9xMnemonics[S9xOpcode], Operant[1], Operant[0]); Word = (Operant[1] << 8) | Operant[0]; Word += Registers.Y.W; sprintf (Line, "%-32s[$%02X:%04X]", Line, Registers.DB, Word); Size = 3; break; case 17: //Absolute long sprintf (Line, "%s%02X %02X %02X %s $%02X%02X%02X", Line, Operant[0], Operant[1], Operant[2], S9xMnemonics[S9xOpcode], Operant[2], Operant[1], Operant[0]); Word = (Operant[1] << 8) | Operant[0]; sprintf (Line, "%-32s[$%02X:%04X]", Line, Operant[2], Word); Size = 4; break; case 18: //Absolute Indexed long sprintf (Line, "%s%02X %02X %02X %s $%02X%02X%02X,x", Line, Operant[0], Operant[1], Operant[2], S9xMnemonics[S9xOpcode], Operant[2], Operant[1], Operant[0]); Word = (Operant[1] << 8) | Operant[0]; Word += Registers.X.W; sprintf (Line, "%-32s[$%02X:%04X]", Line, Operant[2], Word); Size = 4; break; case 19: //StackRelative sprintf (Line, "%s%02X %s $%02X,s", Line, Operant[0], S9xMnemonics[S9xOpcode], Operant[0]); Word = Registers.S.W; Word += Operant[0]; sprintf (Line, "%-32s[$00:%04X]", Line, Word); Size = 2; break; case 20: //Stack Relative Indirect Indexed sprintf (Line, "%s%02X %s ($%02X,s),y", Line, Operant[0], S9xMnemonics[S9xOpcode], Operant[0]); Word = Registers.S.W; Word += Operant[0]; Word = S9xGetWord (Word); Word += Registers.Y.W; sprintf (Line, "%-32s[$%02X:%04X]", Line, Registers.DB, Word); Size = 2; break; case 21: //Absolute Indirect sprintf (Line, "%s%02X %02X %s ($%02X%02X)", Line, Operant[0],
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -