From d40ae99422e118188a7f48055dc340c6aca022aa Mon Sep 17 00:00:00 2001 From: Kitty Draper Date: Sat, 5 Mar 2011 21:39:25 -0500 Subject: first commit --- source/debug.cpp | 2220 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 2220 insertions(+) create mode 100644 source/debug.cpp (limited to 'source/debug.cpp') diff --git a/source/debug.cpp b/source/debug.cpp new file mode 100644 index 0000000..6ea02e9 --- /dev/null +++ b/source/debug.cpp @@ -0,0 +1,2220 @@ +/******************************************************************************* + Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. + + (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and + Jerremy Koot (jkoot@snes9x.com) + + (c) Copyright 2001 - 2004 John Weidman (jweidman@slip.net) + + (c) Copyright 2002 - 2004 Brad Jorsch (anomie@users.sourceforge.net), + funkyass (funkyass@spam.shaw.ca), + Joel Yliluoma (http://iki.fi/bisqwit/) + Kris Bleakley (codeviolation@hotmail.com), + Matthew Kendora, + Nach (n-a-c-h@users.sourceforge.net), + Peter Bortas (peter@bortas.org) and + zones (kasumitokoduck@yahoo.com) + + C4 x86 assembler and some C emulation code + (c) Copyright 2000 - 2003 zsKnight (zsknight@zsnes.com), + _Demo_ (_demo_@zsnes.com), and Nach + + C4 C++ code + (c) Copyright 2003 Brad Jorsch + + DSP-1 emulator code + (c) Copyright 1998 - 2004 Ivar (ivar@snes9x.com), _Demo_, Gary Henderson, + John Weidman, neviksti (neviksti@hotmail.com), + Kris Bleakley, Andreas Naive + + DSP-2 emulator code + (c) Copyright 2003 Kris Bleakley, John Weidman, neviksti, Matthew Kendora, and + Lord Nightmare (lord_nightmare@users.sourceforge.net + + OBC1 emulator code + (c) Copyright 2001 - 2004 zsKnight, pagefault (pagefault@zsnes.com) and + Kris Bleakley + Ported from x86 assembler to C by sanmaiwashi + + SPC7110 and RTC C++ emulator code + (c) Copyright 2002 Matthew Kendora with research by + zsKnight, John Weidman, and Dark Force + + S-DD1 C emulator code + (c) Copyright 2003 Brad Jorsch with research by + Andreas Naive and John Weidman + + S-RTC C emulator code + (c) Copyright 2001 John Weidman + + ST010 C++ emulator code + (c) Copyright 2003 Feather, Kris Bleakley, John Weidman and Matthew Kendora + + Super FX x86 assembler emulator code + (c) Copyright 1998 - 2003 zsKnight, _Demo_, and pagefault + + Super FX C emulator code + (c) Copyright 1997 - 1999 Ivar, Gary Henderson and John Weidman + + + SH assembler code partly based on x86 assembler code + (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) + + + Specific ports contains the works of other authors. See headers in + individual files. + + Snes9x homepage: http://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 +#ifdef HAVE_STRINGS_H +#include +#endif + +#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" +#include "spc7110.h" + +#ifdef DEBUGGER +static 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); +#endif + +FILE *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], + Operant[1], + S9xMnemonics[S9xOpcode], + Operant[1], + Operant[0]); + Word = (Operant[1] << 8) | Operant[0]; + Word = S9xGetWord (Word); + sprintf (Line, "%-32s[$%02X:%04X]", Line, Registers.PB, Word); + Size = 3; + break; + case 22: + //Absolute Indirect Long + 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]; + Byte = S9xGetByte (Word + 2); + Word = S9xGetWord (Word); + sprintf (Line, "%-32s[$%02X:%04X]", Line, Byte, Word); + Size = 3; + break; + case 23: + //Absolute Indexed Indirect + 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; + Word = S9xGetWord (ICPU.ShiftedPB + Word); + sprintf (Line, "%-32s[$%02X:%04X]", Line, Registers.PB, Word); + Size = 3; + break; + case 24: + //Implied accumulator + sprintf (Line, "%s %s A", Line, S9xMnemonics[S9xOpcode]); + Size = 1; + break; + case 25: + // MVN/MVP SRC DST + sprintf (Line, "%s %s %02X %02X", Line, S9xMnemonics[S9xOpcode], + Operant[0], Operant[1]); + Size = 3; + break; + } +// XXX: + sprintf (Line, "%-44s A:%04X X:%04X Y:%04X D:%04X DB:%02X S:%04X P:%c%c%c%c%c%c%c%c%c HC:%03d VC:%03ld %02x", + Line, 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', + Cycles, + CPU.V_Counter, + CPU.IRQActive); + + CPU.Cycles = Cycles; + CPU.WaitAddress = WaitAddress; + return Size; +#endif +} + +uint8 S9xSA1OPrint (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", + SA1Registers.A.W, SA1Registers.X.W, SA1Registers.Y.W, + SA1Registers.D.W, SA1Registers.DB, SA1Registers.S.W, + SA1CheckEmulation () ? 'E' : 'e', + SA1CheckNegative () ? 'N' : 'n', + SA1CheckOverflow () ? 'V' : 'v', + SA1CheckMemory () ? 'M' : 'm', + SA1CheckIndex () ? 'X' : 'x', + SA1CheckDecimal () ? 'D' : 'd', + SA1CheckIRQ () ? 'I' : 'i', + SA1CheckZero () ? 'Z' : 'z', + SA1CheckCarry () ? 'C' : 'c', + CPU.Cycles, + CPU.V_Counter); + return (0); + +#else + S9xOpcode = S9xSA1GetByte ((Bank << 16) + Address); + sprintf (Line, "$%02X:%04X %02X ", Bank, Address, S9xOpcode); + Operant[0] = S9xSA1GetByte ((Bank << 16) + Address + 1); + Operant[1] = S9xSA1GetByte ((Bank << 16) + Address + 2); + Operant[2] = S9xSA1GetByte ((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 (!SA1CheckFlag (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 (!SA1CheckFlag (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 += SA1Registers.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 += SA1Registers.D.W; + Word += SA1Registers.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 += SA1Registers.D.W; + Word += SA1Registers.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 += SA1Registers.D.W; + Word = S9xSA1GetWord (Word); + sprintf (Line, "%-32s[$%02X:%04X]", Line, SA1Registers.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 += SA1Registers.D.W; + Word += SA1Registers.X.W; + Word = S9xSA1GetWord (Word); + sprintf (Line, "%-32s[$%02X:%04X]", Line, SA1Registers.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 += SA1Registers.D.W; + Word = S9xSA1GetWord (Word); + Word += SA1Registers.Y.W; + sprintf (Line, "%-32s[$%02X:%04X]", Line, SA1Registers.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 += SA1Registers.D.W; + Byte = S9xSA1GetByte (Word + 2); + Word = S9xSA1GetWord (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 += SA1Registers.D.W; + Byte = S9xSA1GetByte (Word + 2); + Word = S9xSA1GetWord (Word); + Word += SA1Registers.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, SA1Registers.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 += SA1Registers.X.W; + sprintf (Line, "%-32s[$%02X:%04X]", Line, SA1Registers.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 += SA1Registers.Y.W; + sprintf (Line, "%-32s[$%02X:%04X]", Line, SA1Registers.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 += SA1Registers.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 = SA1Registers.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 = SA1Registers.S.W; + Word += Operant[0]; + Word = S9xSA1GetWord (Word); + Word += SA1Registers.Y.W; + sprintf (Line, "%-32s[$%02X:%04X]", Line, SA1Registers.DB, Word); + Size = 2; + break; + case 21: + //Absolute Indirect + 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]; + Word = S9xSA1GetWord (Word); + sprintf (Line, "%-32s[$%02X:%04X]", Line, SA1Registers.PB, Word); + Size = 3; + break; + case 22: + //Absolute Indirect Long + 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]; + Byte = S9xSA1GetByte (Word + 2); + Word = S9xSA1GetWord (Word); + sprintf (Line, "%-32s[$%02X:%04X]", Line, Byte, Word); + Size = 3; + break; + case 23: + //Absolute Indexed Indirect + 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 += SA1Registers.X.W; + Word = S9xSA1GetWord (SA1.ShiftedPB + Word); + sprintf (Line, "%-32s[$%02X:%04X]", Line, SA1Registers.PB, Word); + Size = 3; + break; + case 24: + //Implied accumulator + sprintf (Line, "%s %s A", Line, S9xMnemonics[S9xOpcode]); + Size = 1; + break; + case 25: + // MVN/MVP SRC DST + sprintf (Line, "%s %s %02X %02X", Line, S9xMnemonics[S9xOpcode], + Operant[0], Operant[1]); + Size = 3; + break; + } + sprintf (Line, "%-44s A:%04X X:%04X Y:%04X D:%04X DB:%02X S:%04X P:%c%c%c%c%c%c%c%c%c HC:%03ld VC:%03ld", + Line, SA1Registers.A.W, SA1Registers.X.W, SA1Registers.Y.W, + SA1Registers.D.W, SA1Registers.DB, SA1Registers.S.W, + SA1CheckEmulation () ? 'E' : 'e', + SA1CheckNegative () ? 'N' : 'n', + SA1CheckOverflow () ? 'V' : 'v', + SA1CheckMemory () ? 'M' : 'm', + SA1CheckIndex () ? 'X' : 'x', + SA1CheckDecimal () ? 'D' : 'd', + SA1CheckIRQ () ? 'I' : 'i', + SA1CheckZero () ? 'Z' : 'z', + SA1CheckCarry () ? 'C' : 'c', + CPU.Cycles, + CPU.V_Counter); + + return Size; +#endif +} + +/**********************************************************************************************/ +/* DPrint() */ +/* This function prints a line in the debug listbox and deletes upperlines if needed */ +/**********************************************************************************************/ +void DPrint (char *Line) +{ + printf ("%s\n", Line); +} +/**********************************************************************************************/ +/* GetNumber() */ +/* This function gets a number from a debug command */ +/**********************************************************************************************/ +int GetNumber (char *Line, uint16 * Number) +{ + int i; + if (sscanf (Line, " #%d", &i) == 1) + { + *Number = i; + return (1); + } + return (-1); +} +/**********************************************************************************************/ +/* GetStartAddress() */ +/* This function gets a starting address from a debug command */ +/**********************************************************************************************/ +short GetStartAddress (char *Line, uint8 *Bank, uint32 *Address) +{ + int a, b; + if (sscanf (Line + 1, " $%x:%x", &b, &a) != 2) + return (-1); + *Bank = b; + *Address = a; + return (1); +} +/**********************************************************************************************/ +/* ProcessDebugCommand() */ +/* This function processes a debug command */ +/**********************************************************************************************/ +void ProcessDebugCommand (char *Line) +{ + uint8 Bank = Registers.PB; + uint32 Address = CPU.PC - CPU.PCBase; + uint16 Hold; + uint16 Number; + char String [512]; + short ErrorCode; + + if (strcasecmp (Line, "cheat") == 0) + { + S9xStartCheatSearch (&Cheat); + printf ("Cheat Search Started\n"); + return; + } + if (strcasecmp (Line, "less") == 0) + { + S9xSearchForChange (&Cheat, S9X_LESS_THAN, S9X_8_BITS, FALSE, TRUE); + printf ("Recorded all values that have decreased\n"); + return; + } + if (strcasecmp (Line, "print") == 0) + { + printf ("Cheat search results:\n"); + S9xOutputCheatSearchResults (&Cheat); + return; + } + + if (strncasecmp (Line, "constant", 8) == 0) + { + uint32 Byte; + if (sscanf (&Line [8], "%x %x", &Address, &Byte) == 2) + S9xAddCheat (TRUE, TRUE, Address, Byte); + return; + } + + if (strncasecmp (Line, "dump", 4) == 0) + { + int Count; + if (sscanf (&Line [4], "%x %d", &Address, &Count) == 2) + { + sprintf (String, "%06x%05d.sd2", Address, Count); + FILE *fs = fopen (String, "wb"); + if (fs) + { + int i; + for (i = 0; i < Count; i++) + putc (S9xGetByte (Address + i), fs); + + fclose (fs); + } + else + printf ("Can't open %s for writing\n", String); + } + else + printf ("Usage: dump start_address_in_hex count_in_decimal\n"); + return; + } + if (Line[0] == 'i') + { + printf ("Vectors:\n"); + sprintf (String, " 8 Bit 16 Bit "); + DPrint (String); + sprintf (String, "ABT $00:%04X|$00:%04X", S9xGetWord (0xFFF8), S9xGetWord (0xFFE8)); + DPrint (String); + sprintf (String, "BRK $00:%04X|$00:%04X", S9xGetWord (0xFFFE), S9xGetWord (0xFFE6)); + DPrint (String); + sprintf (String, "COP $00:%04X|$00:%04X", S9xGetWord (0xFFF4), S9xGetWord (0xFFE4)); + DPrint (String); + sprintf (String, "IRQ $00:%04X|$00:%04X", S9xGetWord (0xFFFE), S9xGetWord (0xFFEE)); + DPrint (String); + sprintf (String, "NMI $00:%04X|$00:%04X", S9xGetWord (0xFFFA), S9xGetWord (0xFFEA)); + DPrint (String); + sprintf (String, "RES $00:%04X", S9xGetWord (0xFFFC)); + DPrint (String); + } + if (strncmp (Line, "ai", 2) == 0) + { + printf ("APU vectors:"); + for (int i = 0; i < 0x40; i += 2) + { + if (i % 16 == 0) + printf ("\n%04x ", 0xffc0 + i); + printf ("%04x ", APU.ExtraRAM [i]); + } + printf ("\n"); + } + if (Line[0] == 's') + { + CPU.PC += S9xOPrint (String, Bank, Address); + Bank = Registers.PB; + Address = CPU.PC - CPU.PCBase; + Line[0] = 'r'; + } + if (Line[0] == 'z') + { + uint16 *p = (uint16 *) &Memory.VRAM [PPU.BG[2].SCBase << 1]; + for (int l = 0; l < 32; l++) + { + for (int c = 0; c < 32; c++, p++) + { + printf ("%04x,", *p++); + } + printf ("\n"); + } + } + if (*Line == 'c') + { + printf ("Colours:\n"); + for (int i = 0; i < 256; i++) + { + printf ("%02x%02x%02x ", PPU.CGDATA[i] & 0x1f, + (PPU.CGDATA[i] >> 5) & 0x1f, + (PPU.CGDATA[i] >> 10) & 0x1f); + } + printf ("\n"); + } + if (*Line == 'S') + { + int SmallWidth, LargeWidth; + int SmallHeight, LargeHeight; + switch ((Memory.FillRAM[0x2101] >> 5) & 7) + { + case 0: + SmallWidth = SmallHeight = 8; + LargeWidth = LargeHeight = 16; + break; + case 1: + SmallWidth = SmallHeight = 8; + LargeWidth = LargeHeight = 32; + break; + case 2: + SmallWidth = SmallHeight = 8; + LargeWidth = LargeHeight = 64; + break; + case 3: + SmallWidth = SmallHeight = 16; + LargeWidth = LargeHeight = 32; + break; + case 4: + SmallWidth = SmallHeight = 16; + LargeWidth = LargeHeight = 64; + break; + default: + case 5: + SmallWidth = SmallHeight = 32; + LargeWidth = LargeHeight = 64; + break; + case 6: + SmallWidth = 16; SmallHeight = 32; + LargeWidth = 32; LargeHeight = 64; + break; + case 7: + SmallWidth = 16; SmallHeight = 32; + LargeWidth = LargeHeight = 32; + break; + } + printf ("Sprites: Small: %dx%d, Large: %dx%d, OAMAddr: 0x%04x, OBJNameBase: 0x%04x, OBJNameSelect: 0x%04x, First: %d\n", + SmallWidth,SmallHeight, LargeWidth,LargeHeight, PPU.OAMAddr, + PPU.OBJNameBase, PPU.OBJNameSelect, PPU.FirstSprite); +// for (int p = 0; p < 4; p++) +// { +// int c = 0; +// int i; +// for (i = 0; GFX.OBJList [i] >= 0; i++) +// { +// if (PPU.OBJ[GFX.OBJList [i]].Priority == p) +// c++; +// } +// printf ("Priority %d: %03d, ", p, c); +// } +// printf ("\n"); + for (int i = 0; i < 128; i++) + { + printf ("X:%3d Y:%3d %c%c%d%c ", + PPU.OBJ[i].HPos, + PPU.OBJ[i].VPos, + PPU.OBJ[i].VFlip ? 'V' : 'v', + PPU.OBJ[i].HFlip ? 'H' : 'h', + PPU.OBJ[i].Priority, + PPU.OBJ[i].Size ? 'S' : 's'); + if (i % 4 == 3) + printf ("\n"); + } + } + if (*Line == 'T') + { + if (Line [1] == 'S') + { + SA1.Flags ^= TRACE_FLAG; + if (SA1.Flags & TRACE_FLAG) + { + printf ("SA1 CPU instruction tracing enabled.\n"); + if (trace2 == NULL) + trace2 = fopen ("trace_sa1.log", "wb"); + } + else + { + printf ("SA1 CPU instruction tracing disabled.\n"); + fclose (trace2); + trace2 = NULL; + } + } + else + { + CPU.Flags ^= TRACE_FLAG; + if (CPU.Flags & TRACE_FLAG) + { + printf ("CPU instruction tracing enabled.\n"); + if (trace == NULL) + trace = fopen ("trace.log", "wb"); + } + else + { + printf ("CPU instruction tracing disabled.\n"); + fclose (trace); + trace = NULL; + } + } + } + if (*Line == 'A') + { + APU.Flags ^= TRACE_FLAG; + + extern FILE *apu_trace; + if (APU.Flags & TRACE_FLAG) + { +#ifdef SPCTOOL + printf ("ENABLED\n"); + _SetSPCDbg (TraceSPC); //Install debug handler +#endif + if (apu_trace == NULL) + apu_trace = fopen ("aputrace.log", "wb"); + } + else + { +#ifdef SPCTOOL + _SetSPCDbg (NULL); +#endif + if (apu_trace) + { + fclose (apu_trace); + apu_trace = NULL; + } + } + + printf ("APU tracing %s\n", APU.Flags & TRACE_FLAG ? "enabled" : + "disabled"); + } + if (*Line == 'B') + { + Settings.TraceSoundDSP ^= 1; + printf ("Sound DSP register tracing %s\n", Settings.TraceSoundDSP ? + "enabled" : "disabled"); + + S9xOpenCloseSoundTracingFile (Settings.TraceSoundDSP); + } + + if (*Line == 'b') + S9xPrintAPUState (); + + if (*Line == 'C') + { + printf ("SPC700 sample addresses at 0x%04x:\n", APU.DSP [APU_DIR] << 8); + for (int i = 0; i < 256; i++) + { + uint8 *dir = IAPU.RAM + + (((APU.DSP [APU_DIR] << 8) + + i * 4) & 0xffff); + int addr = *dir + (*(dir + 1) << 8); + int addr2 = *(dir + 2) + (*(dir + 3) << 8); + printf ("%04X %04X;", addr, addr2); + if (i % 8 == 7) + printf ("\n"); + } + } + if (*Line == 'R') + { + S9xReset (); + printf ("SNES reset.\n"); + CPU.Flags |= DEBUG_MODE_FLAG; + } + if (strncmp (Line, "ad", 2) == 0) + { + int Count = 16; + Address = 0; + if (sscanf (Line+2, "%x,%x", &Address, &Count) != 2) + { + if (sscanf (Line + 2, "%x", &Address) == 1) + Count = 16; + } + printf ("APU RAM dump:\n"); + for (int l = 0; l < Count; l += 16) + { + printf ("%04X ", Address); + for (int i = 0; i < 16; i++) + printf ("%02X ", IAPU.RAM [Address++]); + printf ("\n"); + } + *Line = 0; + } + if (*Line == 'a') + { + printf ("APU in-ports: %02X %02X %02X %02X\n", + IAPU.RAM [0xF4], IAPU.RAM [0xF5], IAPU.RAM [0xF6], IAPU.RAM [0xF7]); +#ifdef SPCTOOL + printf ("APU out-ports: %02X %02X %02X %02X\n", + _SPCOutP [0], _SPCOutP [1], _SPCOutP [2], _SPCOutP [3]); +#else + printf ("APU out-ports: %02X %02X %02X %02X\n", + APU.OutPorts [0], APU.OutPorts [1], APU.OutPorts [2], APU.OutPorts [3]); +#endif + printf ("ROM/RAM switch: %s\n", (IAPU.RAM [0xf1] & 0x80) ? "ROM" : "RAM"); + for (int i = 0; i < 3; i++) + if (APU.TimerEnabled [i]) + printf ("Timer%d enabled, Value: 0x%03X, 4-bit: 0x%02X, Target: 0x%03X\n", + i, APU.Timer [i], IAPU.RAM [0xfd + i], APU.TimerTarget [i]); + } + if (*Line == 'P') + { + Settings.TraceDSP = !Settings.TraceDSP; + printf ("DSP tracing %s\n", Settings.TraceDSP ? "enabled" : "disabled"); + } + if (Line[0] == 'p') + { + S9xBreakpoint[5].Enabled = FALSE; + Address += S9xOPrint (String, Bank, Address); + if (strncmp (&String[18], "JMP", 3) != 0 && + strncmp (&String[18], "JML", 3) != 0 && + strncmp (&String[18], "RT", 2) != 0 && + strncmp (&String[18], "BRA", 3)) + { + S9xBreakpoint[5].Enabled = TRUE; + S9xBreakpoint[5].Bank = Bank; + S9xBreakpoint[5].Address = Address; + } + else + { + CPU.Flags |= SINGLE_STEP_FLAG; + CPU.Flags &= ~DEBUG_MODE_FLAG; + } + } + if (Line[0] == 'b') + { + if (Line[1] == 's') + { + GetNumber (Line + 2, &Hold); + if (Hold > 4) + Hold = 0; + if (Hold < 5) + if (GetStartAddress (Line + 5, &Bank, &Address) == -1) + { + //Clear S9xBreakpoint + S9xBreakpoint[Hold].Enabled = FALSE; + } + else + { + //Set S9xBreakpoint + S9xBreakpoint[Hold].Enabled = TRUE; + S9xBreakpoint[Hold].Bank = Bank; + S9xBreakpoint[Hold].Address = Address; + CPU.Flags |= BREAK_FLAG; + } + Line = "bv"; + } + if (Line[1] == 'v') + { + Number = 0; + if (GetNumber (Line + 2, &Number) == -1 && + Number < 5) + { + //Show All Breakpoints + DPrint ("Breakpoints:"); + for (Number = 0; Number != 5; Number++) + { + if (S9xBreakpoint[Number].Enabled) + sprintf (String, "%i @ $%02X:%04X", Number, S9xBreakpoint[Number].Bank, S9xBreakpoint[Number].Address); + else + sprintf (String, "%i @ Disabled", Number); + DPrint (String); + } + } + else + { + //Show selected S9xBreakpoint + DPrint ("Breakpoint:"); + if (S9xBreakpoint[Number].Enabled) + sprintf (String, "%i @ $%02X:%04X", Number, S9xBreakpoint[Number].Bank, S9xBreakpoint[Number].Address); + else + sprintf (String, "%i @ Disabled", Number); + DPrint (String); + } + } + } + if (Line[0] == '?' || strcasecmp (Line, "help") == 0) + { + for (short Counter = 0; HelpMessage[Counter] != NULL; Counter++) + DPrint (HelpMessage[Counter]); + } + if (Line[0] == 't') + { + CPU.Flags |= SINGLE_STEP_FLAG; + CPU.Flags &= ~DEBUG_MODE_FLAG; + } + if (Line[0] == 'f') + { + CPU.Flags |= FRAME_ADVANCE_FLAG; + CPU.Flags &= ~DEBUG_MODE_FLAG; + // Render this frame + IPPU.RenderThisFrame = TRUE; + IPPU.FrameSkip = 0; + if (sscanf (&Line [1], "%d", &ICPU.FrameAdvanceCount) != 1) + ICPU.Frame = 0; + } + + if (Line[0] == 'g') + { + S9xBreakpoint[5].Enabled = FALSE; + int i; + bool8 found = FALSE; + for (i = 0; i < 5; i++) + { + if (S9xBreakpoint[i].Enabled) + { + found = TRUE; + if (S9xBreakpoint[i].Bank == Registers.PB && + S9xBreakpoint[i].Address == CPU.PC - CPU.PCBase) + { + S9xBreakpoint[i].Enabled = 2; + break; + } + } + } + if (!found) + CPU.Flags &= ~BREAK_FLAG; + ErrorCode = GetStartAddress (Line, &Bank, &Address); + if (ErrorCode == 1) + { + S9xBreakpoint[5].Enabled = TRUE; + S9xBreakpoint[5].Bank = Bank; + S9xBreakpoint[5].Address = Address; + CPU.Flags |= BREAK_FLAG; + } + CPU.Flags &= ~DEBUG_MODE_FLAG; + } + if (*Line == 'D') + { + Settings.TraceDMA = !Settings.TraceDMA; + printf ("DMA tracing %s\n", Settings.TraceDMA ? "enabled" : "disabled"); + } + if (*Line == 'V') + { + Settings.TraceVRAM = !Settings.TraceVRAM; + printf ("Non-DMA VRAM write tracing %s\n", Settings.TraceVRAM ? "enabled" : "disabled"); + } + if (*Line == 'H') + { + Settings.TraceHDMA = !Settings.TraceHDMA; + printf ("H-DMA tracing %s\n", Settings.TraceHDMA ? "enabled" : "disabled"); + } + if (*Line == 'U') + { + Settings.TraceUnknownRegisters = !Settings.TraceUnknownRegisters; + printf ("Unknown registers read/write tracing %s\n", + Settings.TraceUnknownRegisters ? "enabled" : "disabled"); + } + if (Line[0] == 'd') + { + int CLine; + int CByte; + uint32 Cycles = CPU.Cycles; + uint8 MemoryByte; + + if (Debug.Dump.Bank != 0 || Debug.Dump.Address != 0) + { + Bank = Debug.Dump.Bank; + Address = Debug.Dump.Address; + } + ErrorCode = GetStartAddress (Line, &Bank, &Address); + for (CLine = 0; CLine != 10; CLine++) + { + sprintf (String, "$%02X:%04X", Bank, Address); + for (CByte = 0; CByte != 16; CByte++) + { + if (Address + CByte == 0x2140 || + Address + CByte == 0x2141 || + Address + CByte == 0x2142 || + Address + CByte == 0x2143 || + Address + CByte == 0x4210) + { + MemoryByte = 0; + } + else + { + MemoryByte = S9xGetByte ((Bank << 16) + Address + CByte); + } + sprintf (String, "%s %02X", String, MemoryByte); + } + sprintf (String, "%s-", String); + for (CByte = 0; CByte != 16; CByte++) + { + if (Address + CByte == 0x2140 || + Address + CByte == 0x2141 || + Address + CByte == 0x2142 || + Address + CByte == 0x2143 || + Address + CByte == 0x4210) + { + MemoryByte = 0; + } + else + { + MemoryByte = S9xGetByte ((Bank << 16) + Address + CByte); + } + if (MemoryByte < 32 || MemoryByte >= 127) + MemoryByte = '?'; + sprintf (String, "%s%c", String, MemoryByte); + } + Address += 16; + DPrint (String); + } + Debug.Dump.Bank = Bank; + Debug.Dump.Address = Address; + CPU.Cycles = Cycles; + } + + if (*Line == 'q') + S9xExit (); + if (*Line == 'W') + WhatsMissing (); + if (*Line == 'w') + WhatsUsed (); + if (Line[0] == 'r') + { +#if 0 + sprintf (String, + "A[%04X] X[%04X] Y[%04X] S[%04X] D[%04X] DB[%02X] P[%02X] F[%s %s %s %s %s %s %s %s / %s]", + Registers.A.W, + Registers.X.W, + Registers.Y.W, + Registers.S.W, + Registers.D.W, + Registers.DB, + Registers.PL, + (Registers.P.W & 128) != 0 ? "N" : "n", + (Registers.P.W & 64) != 0 ? "V" : "v", + (Registers.P.W & 32) != 0 ? "M" : "m", + (Registers.P.W & 16) != 0 ? "X" : "x", + (Registers.P.W & 8) != 0 ? "D" : "d", + (Registers.P.W & 4) != 0 ? "I" : "i", + (Registers.P.W & 2) != 0 ? "Z" : "z", + (Registers.P.W & 1) != 0 ? "C" : "c", + (Registers.P.W & 256) != 0 ? "E" : "e"); + DPrint (String); +#endif + S9xOPrint (String, Bank, Address); + DPrint (String); + } + if (Line[0] == 'u') + { + if (Debug.Unassemble.Bank != 0 || Debug.Unassemble.Address != 0) + { + Bank = Debug.Unassemble.Bank; + Address = Debug.Unassemble.Address; + } + ErrorCode = GetStartAddress (Line, &Bank, &Address); + for (short Counter = 0; Counter != 10; Counter++) + { + Address += S9xOPrint (String, Bank, Address); + DPrint (String); + } + Debug.Unassemble.Bank = Bank; + Debug.Unassemble.Address = Address; + } + DPrint (""); + return; +} +static void PrintWindow (uint8 * a) +{ + for (int i = 0; i < 6; i++) + if (a[i]) + switch (i) + { + case 0: + printf ("Background 0, "); + break; + case 1: + printf ("Background 1, "); + break; + case 2: + printf ("Background 2, "); + break; + case 3: + printf ("Background 3, "); + break; + case 4: + printf ("Objects, "); + break; + case 5: + printf ("Colour window, "); + break; + } +} +static char *ClipFn (int logic) +{ + switch (logic) + { + case CLIP_OR: + return ("OR"); + case CLIP_AND: + return ("AND"); + case CLIP_XOR: + return ("XOR"); + case CLIP_XNOR: + return ("XNOR"); + default: + return ("???"); + } +} + +static void WhatsUsed () +{ + printf ("V-line: %ld, H-Pos: %ld\n", CPU.V_Counter, CPU.Cycles); + printf ("Screen mode: %d, ", PPU.BGMode); + if (PPU.BGMode <= 1 && (Memory.FillRAM [0x2105] & 8)) + printf ("(BG#2 Priority)"); + + printf ("Brightness: %d", PPU.Brightness); + if (Memory.FillRAM[0x2100] & 0x80) + printf (" (screen blanked)"); + printf ("\n"); + if (Memory.FillRAM[0x2133] & 1) + printf ("Interlace, "); + if (Memory.FillRAM[0x2133] & 4) + printf ("240 line visible, "); + if (Memory.FillRAM[0x2133] & 8) + printf ("Pseudo 512 pixels horizontal resolution, "); + if (Memory.FillRAM[0x2133] & 0x40) + printf ("Mode 7 priority per pixel, "); + printf ("\n"); + if (PPU.BGMode == 7 && (Memory.FillRAM[0x211a] & 3)) + printf ("Mode 7 flipping, "); + if (PPU.BGMode == 7) + printf ("Mode 7 screen repeat: %d,", (Memory.FillRAM[0x211a] & 0xc0) >> 6); + if (Memory.FillRAM[0x2130] & 1) + printf ("32K colour mode, "); + if (PPU.BGMode == 7) + { + // Sign extend 13 bit values to 16 bit values... + if (PPU.CentreX & (1 << 12)) + PPU.CentreX |= 0xe000; + if (PPU.CentreY & (1 << 12)) + PPU.CentreY |= 0xe000; + + printf ("\nMatrix A: %.3f, B: %.3f, C: %.3f, D: %.3f, Centre X: %d Y:%d\n", + (double) PPU.MatrixA / 256, (double) PPU.MatrixB / 256, + (double) PPU.MatrixC / 256, (double) PPU.MatrixD / 256, + PPU.CentreX, PPU.CentreY); + } + if ((Memory.FillRAM[0x2106] & 0xf0) && (Memory.FillRAM[0x2106] & 0x0f)) + { + printf ("\nMosaic effect(%d) on ", PPU.Mosaic); + for (int i = 0; i < 4; i++) + if (Memory.FillRAM[0x2106] & (1 << i)) + printf ("BG%d,", i); + printf (","); + } + if (PPU.HVBeamCounterLatched) + printf ("V and H beam pos latched, "); + if (Memory.FillRAM[0x4200] & 0x20) + printf ("V-IRQ enabled at %d\n", PPU.IRQVBeamPos); + if (Memory.FillRAM[0x4200] & 0x10) + printf ("H-IRQ enabled at %d\n", PPU.IRQHBeamPos); + if (Memory.FillRAM[0x4200] & 0x80) + printf ("V-blank NMI enabled\n"); + int i; + for (i = 0; i < 8; i++) + { + if (missing.hdma_this_frame & (1 << i)) + { + printf ("H-DMA %d [%d] 0x%02X%04X->0x21%02X %s %s 0x%02X%04X %s addressing\n", + i, DMA[i].TransferMode, + DMA[i].ABank, DMA[i].AAddress, DMA[i].BAddress, + DMA[i].AAddressDecrement ? "dec" : "inc", + DMA[i].Repeat ? "repeat" : "continue", + DMA[i].IndirectBank, DMA[i].IndirectAddress, + DMA[i].HDMAIndirectAddressing ? "indirect" : "absolute"); + } + } + for (i = 0; i < 8; i++) + { + if (missing.dma_this_frame & (1 << i)) + { + printf ("DMA %d %d 0x%02X%04X->0x21%02X Num: %d %s\n", + i, DMA[i].TransferMode, DMA[i].ABank, DMA[i].AAddress, + DMA[i].BAddress, DMA[i].TransferBytes, + DMA[i].AAddressFixed ? "fixed" : + (DMA[i].AAddressDecrement ? "dec" : "inc")); + } + } + printf ("VRAM write address: 0x%04x(%s), Full Graphic: %d, Address inc: %d\n", + PPU.VMA.Address, + PPU.VMA.High ? "Byte" : "Word", + PPU.VMA.FullGraphicCount, PPU.VMA.Increment); + + for (i = 0; i < 4; i++) + { + printf ("BG%d: VOffset:%d, HOffset:%d, W:%d, H:%d, TS:%d, BA:0x%04x, TA:0x%04X\n", + i, PPU.BG[i].VOffset, PPU.BG[i].HOffset, + (PPU.BG[i].SCSize & 1) * 32 + 32, + (PPU.BG[i].SCSize & 2) * 16 + 32, + PPU.BG[i].BGSize * 8 + 8, + PPU.BG[i].SCBase, + PPU.BG[i].NameBase); + } + char *s = ""; + switch ((Memory.FillRAM [0x2130] & 0xc0) >> 6) + { + case 0: s = "always on"; break; + case 1: s = "inside"; break; + case 2: s = "outside"; break; + case 3: s = "always off"; break; + } + printf ("Main screen (%s): ", s); + for (i = 0; i < 5; i++) + if (Memory.FillRAM[0x212c] & (1 << i)) + switch (i) + { + case 0: + printf ("BG0,"); + break; + case 1: + printf ("BG1,"); + break; + case 2: + printf ("BG2,"); + break; + case 3: + printf ("BG3,"); + break; + case 4: + printf ("OBJ,"); + break; + } + + switch ((Memory.FillRAM [0x2130] & 0x30) >> 4) + { + case 0: s = "always on"; break; + case 1: s = "inside"; break; + case 2: s = "outside"; break; + case 3: s = "always off"; break; + } + + printf ("\nSub-screen (%s): ", s); + for (i = 0; i < 5; i++) + if (Memory.FillRAM[0x212d] & (1 << i)) + switch (i) + { + case 0: + printf ("BG0,"); + break; + case 1: + printf ("BG1,"); + break; + case 2: + printf ("BG2,"); + break; + case 3: + printf ("BG3,"); + break; + case 4: + printf ("OBJ,"); + break; + } + printf ("\n"); + if ((Memory.FillRAM[0x2131] & 0x3f)) + { + if (Memory.FillRAM[0x2131] & 0x80) + { + if (Memory.FillRAM[0x2130] & 0x02) + printf ("Subscreen subtract"); + else + printf ("Fixed colour subtract"); + } + else + { + if (Memory.FillRAM[0x2130] & 0x02) + printf ("Subscreen addition"); + else + printf ("Fixed colour addition"); + } + if (Memory.FillRAM [0x2131] & 0x40) + printf ("(half):"); + else + printf (":"); + + for (i = 0; i < 6; i++) + if (Memory.FillRAM[0x2131] & (1 << i)) + { + switch (i) + { + case 0: + printf ("BG0,"); + break; + case 1: + printf ("BG1,"); + break; + case 2: + printf ("BG2,"); + break; + case 3: + printf ("BG3,"); + break; + case 4: + printf ("OBJ,"); + break; + case 5: + printf ("BACK,"); + break; + } + } + printf ("\n"); + } + printf ("\nWindow 1 (%d, %d, %02x, %02x): ", PPU.Window1Left, + PPU.Window1Right, Memory.FillRAM [0x212e], Memory.FillRAM [0x212f]); + for (i = 0; i < 6; i++) + if (PPU.ClipWindow1Enable [i]) + switch (i) + { + case 0: + printf ("BG0(%s-%s),", PPU.ClipWindow1Inside [i] ? "I" : "O", + ClipFn (PPU.ClipWindowOverlapLogic[0])); + break; + case 1: + printf ("BG1(%s-%s),", PPU.ClipWindow1Inside [i] ? "I" : "O", + ClipFn (PPU.ClipWindowOverlapLogic[1])); + break; + case 2: + printf ("BG2(%s-%s),", PPU.ClipWindow1Inside [i] ? "I" : "O", + ClipFn (PPU.ClipWindowOverlapLogic[2])); + break; + case 3: + printf ("BG3(%s-%s),", PPU.ClipWindow1Inside [i] ? "I" : "O", + ClipFn (PPU.ClipWindowOverlapLogic[3])); + break; + case 4: + printf ("OBJ(%s-%s),", PPU.ClipWindow1Inside [i] ? "I" : "O", + ClipFn (PPU.ClipWindowOverlapLogic[4])); + break; + case 5: + printf ("COL(%s-%s)", PPU.ClipWindow1Inside [i] ? "I" : "O", + ClipFn (PPU.ClipWindowOverlapLogic[5])); + break; + } + + printf ("\nWindow 2 (%d, %d): ", PPU.Window2Left, + PPU.Window2Right); + for (i = 0; i < 6; i++) + if (PPU.ClipWindow2Enable [i]) + switch (i) + { + case 0: + printf ("BG0(%s),", PPU.ClipWindow2Inside [i] ? "I" : "O"); + break; + case 1: + printf ("BG1(%s),", PPU.ClipWindow2Inside [i] ? "I" : "O"); + break; + case 2: + printf ("BG2(%s),", PPU.ClipWindow2Inside [i] ? "I" : "O"); + break; + case 3: + printf ("BG3(%s),", PPU.ClipWindow2Inside [i] ? "I" : "O"); + break; + case 4: + printf ("OBJ(%s),", PPU.ClipWindow2Inside [i] ? "I" : "O"); + break; + case 5: + printf ("COL(%s)", PPU.ClipWindow2Inside [i] ? "I" : "O"); + break; + } + + printf ("\nFixed colour: %02x%02x%02x\n", PPU.FixedColourRed, + PPU.FixedColourGreen, PPU.FixedColourBlue); +} + +static void WhatsMissing () +{ + printf ("Processor: "); + if (missing.emulate6502) + printf ("emulation mode, "); + if (missing.decimal_mode) + printf ("decimal mode,"); + if (missing.mv_8bit_index) + printf ("MVP/MVN with 8bit index registers and XH or YH > 0,"); + if (missing.mv_8bit_acc) + printf ("MVP/MVN with 8bit accumulator > 255"); + printf ("\nScreen modes used:"); + int i; + for (i = 0; i < 8; i++) + if (missing.modes[i]) + printf (" %d,", i); + printf ("\n"); + if (missing.interlace) + printf ("Interlace, "); + if (missing.pseudo_512) + printf ("Pseudo 512 pixels horizontal resolution, "); + if (missing.lines_239) + printf ("240 lines visible,"); + if (missing.sprite_double_height) + printf ("double-hight sprites,"); + printf ("\n"); + if (missing.mode7_fx) + printf ("Mode 7 rotation/scaling, "); + if (missing.matrix_read) + printf ("Mode 7 read matrix registers, "); + if (missing.mode7_flip) + printf ("Mode 7 flipping, "); + if (missing.mode7_bgmode) + printf ("Mode 7 priority per pixel, "); + if (missing.direct) + printf ("Direct 32000 colour mode"); + printf ("\n"); + if (missing.mosaic) + printf ("Mosaic effect, "); + if (missing.subscreen) + printf ("Subscreen enabled, "); + if (missing.subscreen_add) + printf ("Subscreen colour add, "); + if (missing.subscreen_sub) + printf ("Subscreen colour subtract, "); + if (missing.fixed_colour_add) + printf ("Fixed colour add, "); + if (missing.fixed_colour_sub) + printf ("Fixed colour subtract"); + printf ("\n"); + printf ("Window 1 enabled on:"); + PrintWindow (missing.window1); + printf ("\nWindow 2 enabled on:"); + PrintWindow (missing.window2); + printf ("\n"); + if (missing.bg_offset_read) + printf ("BG offset read, "); + if (missing.oam_address_read) + printf ("OAM address read,"); + if (missing.sprite_priority_rotation) + printf ("Sprite priority rotation, "); + if (missing.fast_rom) + printf ("Fast 3.58MHz ROM access enabled, "); + if (missing.matrix_multiply) + printf ("Matrix multiply 16bit by 8bit used"); + printf ("\n"); + if (missing.virq) + printf ("V-position IRQ used at line %d, ", missing.virq_pos); + if (missing.hirq) + printf ("H-position IRQ used at position %d, ", missing.hirq_pos); + printf ("\n"); + if (missing.h_v_latch) + printf ("H and V-Pos latched, "); + if (missing.h_counter_read) + printf ("H-Pos read, "); + if (missing.v_counter_read) + printf ("V-Pos read"); + printf ("\n"); + if (missing.oam_read) + printf ("OAM read, "); + if (missing.vram_read) + printf ("VRAM read, "); + if (missing.cgram_read) + printf ("CG-RAM read, "); + if (missing.wram_read) + printf ("WRAM read, "); + if (missing.dma_read) + printf ("DMA read,"); + if (missing.vram_inc) + printf ("VRAM inc: %d,", missing.vram_inc); + if (missing.vram_full_graphic_inc) + printf ("VRAM full graphic inc: %d,", missing.vram_full_graphic_inc); + printf ("\n"); + for (i = 0; i < 8; i++) + { + if (missing.hdma[i].used) + { + printf ("HDMA %d, 0x%02X%04X->0x21%02X %s ", i, + missing.hdma[i].abus_bank, missing.hdma[i].abus_address, + missing.hdma[i].bbus_address, + missing.hdma[i].indirect_address ? "indirect" : "absolute"); + if (missing.hdma[i].force_table_address_write) + printf ("Forced address write, "); + if (missing.hdma[i].force_table_address_read) + printf ("Current address read, "); + if (missing.hdma[i].line_count_write) + printf ("Line count write, "); + if (missing.hdma[i].line_count_read) + printf ("Line count read"); + printf ("\n"); + } + } + for (i = 0; i < 8; i++) + { + if (missing.dma_channels & (1 << i)) + { + printf ("DMA %d %d 0x%02X%04X->0x21%02X Num: %d %s\n", + i, DMA[i].TransferMode, DMA[i].ABank, DMA[i].AAddress, + DMA[i].BAddress, DMA[i].TransferBytes, + DMA[i].AAddressFixed ? "fixed" : + (DMA[i].AAddressDecrement ? "dec" : "inc")); + } + } + if (missing.unknownppu_read) + printf ("Read from unknown PPU register: $%04X\n", missing.unknownppu_read); + if (missing.unknownppu_write) + printf ("Write to unknown PPU register: $%04X\n", missing.unknownppu_write); + if (missing.unknowncpu_read) + printf ("Read from unknown CPU register: $%04X\n", missing.unknowncpu_read); + if (missing.unknowncpu_write) + printf ("Write to unknown CPU register: $%04X\n", missing.unknowncpu_write); + if (missing.unknowndsp_read) + printf ("Read from unknown DSP register: $%04X\n", missing.unknowndsp_read); + if (missing.unknowndsp_write) + printf ("Write to unknown DSP register: $%04X\n", missing.unknowndsp_write); +} + +void S9xDoDebug () +{ + char Line[513]; + Debug.Dump.Bank = 0; + Debug.Dump.Address = 0; + Debug.Unassemble.Bank = 0; + Debug.Unassemble.Address = 0; + S9xTextMode (); + ProcessDebugCommand ("r"); + while (CPU.Flags & DEBUG_MODE_FLAG) + { + printf ("> "); + fflush (stdout); + fgets (Line, sizeof (Line) - 1, stdin); + Line [strlen (Line) - 1] = 0; + ProcessDebugCommand (Line); + } + if (!(CPU.Flags & SINGLE_STEP_FLAG)) + S9xGraphicsMode (); +} + +void S9xTrace () +{ + if(!trace) + trace=fopen("trace.log", "a"); + char String [512]; + S9xOPrint (String, Registers.PB, CPU.PC - CPU.PCBase); + fprintf (trace, "%s\n", String); +} + +void S9xSA1Trace () +{ + char String [512]; + S9xSA1OPrint (String, SA1Registers.PB, SA1.PC - SA1.PCBase); + fprintf (trace2, "%s\n", String); + fflush (trace2); +} + +void S9xTraceMessage (const char *s) +{ + if(s) + { + if (trace) + fprintf (trace, "%s\n", s); + else + if (trace2) + fprintf (trace2, "%s\n", s); + } +} + +extern "C" void TraceSA1 () +{ + SA1.Flags ^= TRACE_FLAG; + if (SA1.Flags & TRACE_FLAG) + { + printf ("SA1 CPU instruction tracing enabled.\n"); + if (trace2 == NULL) + trace2 = fopen ("trace_sa1.log", "wb"); + } + else + { + printf ("SA1 CPU instruction tracing disabled.\n"); + fclose (trace2); + trace2 = NULL; + } +} + +extern "C" void Trace () +{ + CPU.Flags ^= TRACE_FLAG; + if (CPU.Flags & TRACE_FLAG) + { + if (trace == NULL) + trace = fopen ("trace.log", "wb"); + printf ("CPU instruction tracing enabled.\n"); + } + else + { + printf ("CPU instruction tracing disabled.\n"); + fclose (trace); + trace = NULL; + } +} + +#endif + -- cgit v1.2.3