Path: blob/main/misc/emulator/xnes/snes9x/debug.cpp
28515 views
/***********************************************************************************1Snes9x - Portable Super Nintendo Entertainment System (TM) emulator.23(c) Copyright 1996 - 2002 Gary Henderson ([email protected]),4Jerremy Koot ([email protected])56(c) Copyright 2002 - 2004 Matthew Kendora78(c) Copyright 2002 - 2005 Peter Bortas ([email protected])910(c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/)1112(c) Copyright 2001 - 2006 John Weidman ([email protected])1314(c) Copyright 2002 - 2006 funkyass ([email protected]),15Kris Bleakley ([email protected])1617(c) Copyright 2002 - 2010 Brad Jorsch ([email protected]),18Nach ([email protected]),1920(c) Copyright 2002 - 2011 zones ([email protected])2122(c) Copyright 2006 - 2007 nitsuja2324(c) Copyright 2009 - 2011 BearOso,25OV2262728BS-X C emulator code29(c) Copyright 2005 - 2006 Dreamer Nom,30zones3132C4 x86 assembler and some C emulation code33(c) Copyright 2000 - 2003 _Demo_ ([email protected]),34Nach,35zsKnight ([email protected])3637C4 C++ code38(c) Copyright 2003 - 2006 Brad Jorsch,39Nach4041DSP-1 emulator code42(c) Copyright 1998 - 2006 _Demo_,43Andreas Naive ([email protected]),44Gary Henderson,45Ivar ([email protected]),46John Weidman,47Kris Bleakley,48Matthew Kendora,49Nach,50neviksti ([email protected])5152DSP-2 emulator code53(c) Copyright 2003 John Weidman,54Kris Bleakley,55Lord Nightmare ([email protected]),56Matthew Kendora,57neviksti5859DSP-3 emulator code60(c) Copyright 2003 - 2006 John Weidman,61Kris Bleakley,62Lancer,63z80 gaiden6465DSP-4 emulator code66(c) Copyright 2004 - 2006 Dreamer Nom,67John Weidman,68Kris Bleakley,69Nach,70z80 gaiden7172OBC1 emulator code73(c) Copyright 2001 - 2004 zsKnight,74pagefault ([email protected]),75Kris Bleakley76Ported from x86 assembler to C by sanmaiwashi7778SPC7110 and RTC C++ emulator code used in 1.39-1.5179(c) Copyright 2002 Matthew Kendora with research by80zsKnight,81John Weidman,82Dark Force8384SPC7110 and RTC C++ emulator code used in 1.52+85(c) Copyright 2009 byuu,86neviksti8788S-DD1 C emulator code89(c) Copyright 2003 Brad Jorsch with research by90Andreas Naive,91John Weidman9293S-RTC C emulator code94(c) Copyright 2001 - 2006 byuu,95John Weidman9697ST010 C++ emulator code98(c) Copyright 2003 Feather,99John Weidman,100Kris Bleakley,101Matthew Kendora102103Super FX x86 assembler emulator code104(c) Copyright 1998 - 2003 _Demo_,105pagefault,106zsKnight107108Super FX C emulator code109(c) Copyright 1997 - 1999 Ivar,110Gary Henderson,111John Weidman112113Sound emulator code used in 1.5-1.51114(c) Copyright 1998 - 2003 Brad Martin115(c) Copyright 1998 - 2006 Charles Bilyue'116117Sound emulator code used in 1.52+118(c) Copyright 2004 - 2007 Shay Green ([email protected])119120SH assembler code partly based on x86 assembler code121(c) Copyright 2002 - 2004 Marcus Comstedt ([email protected])1221232xSaI filter124(c) Copyright 1999 - 2001 Derek Liauw Kie Fa125126HQ2x, HQ3x, HQ4x filters127(c) Copyright 2003 Maxim Stepin ([email protected])128129NTSC filter130(c) Copyright 2006 - 2007 Shay Green131132GTK+ GUI code133(c) Copyright 2004 - 2011 BearOso134135Win32 GUI code136(c) Copyright 2003 - 2006 blip,137funkyass,138Matthew Kendora,139Nach,140nitsuja141(c) Copyright 2009 - 2011 OV2142143Mac OS GUI code144(c) Copyright 1998 - 2001 John Stiles145(c) Copyright 2001 - 2011 zones146147148Specific ports contains the works of other authors. See headers in149individual files.150151152Snes9x homepage: http://www.snes9x.com/153154Permission to use, copy, modify and/or distribute Snes9x in both binary155and source form, for non-commercial purposes, is hereby granted without156fee, providing that this license information and copyright notice appear157with all copies and any derived work.158159This software is provided 'as-is', without any express or implied160warranty. In no event shall the authors be held liable for any damages161arising from the use of this software or it's derivatives.162163Snes9x is freeware for PERSONAL USE only. Commercial users should164seek permission of the copyright holders first. Commercial use includes,165but is not limited to, charging money for Snes9x or software derived from166Snes9x, including Snes9x or derivatives in commercial game bundles, and/or167using Snes9x as a promotion for your commercial product.168169The copyright holders request that bug fixes and improvements to the code170should be forwarded to them so everyone can benefit from the modifications171in future versions.172173Super NES and Super Nintendo Entertainment System are trademarks of174Nintendo Co., Limited and its subsidiary companies.175***********************************************************************************/176177178#ifdef DEBUGGER179180#include <stdarg.h>181#include "snes9x.h"182#include "memmap.h"183#include "cpuops.h"184#include "dma.h"185#include "apu/apu.h"186#include "display.h"187#include "debug.h"188#include "missing.h"189190extern SDMA DMA[8];191extern FILE *apu_trace;192FILE *trace = NULL, *trace2 = NULL;193194struct SBreakPoint S9xBreakpoint[6];195196struct SDebug197{198struct199{200uint8 Bank;201uint16 Address;202} Dump;203204struct205{206uint8 Bank;207uint16 Address;208} Unassemble;209};210211static struct SDebug Debug = { { 0, 0 }, { 0, 0 } };212213static const char *HelpMessage[] =214{215"Command Help:",216"?, help - Shows this command help",217"r - Shows the registers",218"i - Shows the interrupt vectors",219"t - Trace current instruction [step-into]",220"p - Proceed to next instruction [step-over]",221"s - Skip to next instruction [skip]",222"T - Toggle CPU instruction tracing to trace.log",223"TS - Toggle SA-1 instruction tracing to trace_sa1.log",224"E - Toggle HC-based event tracing to trace.log",225"V - Toggle non-DMA V-RAM read/write tracing to stdout",226"D - Toggle on-screen DMA tracing",227"H - Toggle on-screen HDMA tracing",228"U - Toggle on-screen unknown register read/write tracing",229"P - Toggle on-screen DSP tracing",230"S - Dump sprite (OBJ) status",231"g [Address] - Go or go to [Address]",232"u [Address] - Disassemble from PC or [Address]",233"d [Address] - Dump from PC or [Address]",234"bv [Number] - View breakpoints or view breakpoint [Number]",235"bs [Number] [Address] - Enable/disable breakpoint",236" [enable example: bs #2 $02:8002]",237" [disable example: bs #2]",238"c - Dump SNES colour palette",239"W - Show what SNES hardware features the ROM is using",240" which might not be implemented yet",241"w - Show some SNES hardware features used so far in this frame",242"R - Reset SNES",243"q - Quit emulation",244// "ai - Shou APU vectors",245// "a - Show APU status",246// "x - Show Sound DSP status",247// "A - Toggle APU instruction tracing to aputrace.log",248// "B - Toggle sound DSP register tracing to aputrace.log",249// "C - Dump sound sample addresses",250// "ad [Address] - Dump APU RAM from PC or [Address]",251"",252"[Address] - $Bank:Address or $Address",253" [for example: $01:8123]",254"[Number] - #Number",255" [for example: #1]",256"z - ",257"f - ",258"dump - ",259"",260NULL261};262263static const char *S9xMnemonics[256] =264{265"BRK", "ORA", "COP", "ORA", "TSB", "ORA", "ASL", "ORA",266"PHP", "ORA", "ASL", "PHD", "TSB", "ORA", "ASL", "ORA",267"BPL", "ORA", "ORA", "ORA", "TRB", "ORA", "ASL", "ORA",268"CLC", "ORA", "INC", "TCS", "TRB", "ORA", "ASL", "ORA",269"JSR", "AND", "JSL", "AND", "BIT", "AND", "ROL", "AND",270"PLP", "AND", "ROL", "PLD", "BIT", "AND", "ROL", "AND",271"BMI", "AND", "AND", "AND", "BIT", "AND", "ROL", "AND",272"SEC", "AND", "DEC", "TSC", "BIT", "AND", "ROL", "AND",273"RTI", "EOR", "WDM", "EOR", "MVP", "EOR", "LSR", "EOR",274"PHA", "EOR", "LSR", "PHK", "JMP", "EOR", "LSR", "EOR",275"BVC", "EOR", "EOR", "EOR", "MVN", "EOR", "LSR", "EOR",276"CLI", "EOR", "PHY", "TCD", "JMP", "EOR", "LSR", "EOR",277"RTS", "ADC", "PER", "ADC", "STZ", "ADC", "ROR", "ADC",278"PLA", "ADC", "ROR", "RTL", "JMP", "ADC", "ROR", "ADC",279"BVS", "ADC", "ADC", "ADC", "STZ", "ADC", "ROR", "ADC",280"SEI", "ADC", "PLY", "TDC", "JMP", "ADC", "ROR", "ADC",281"BRA", "STA", "BRL", "STA", "STY", "STA", "STX", "STA",282"DEY", "BIT", "TXA", "PHB", "STY", "STA", "STX", "STA",283"BCC", "STA", "STA", "STA", "STY", "STA", "STX", "STA",284"TYA", "STA", "TXS", "TXY", "STZ", "STA", "STZ", "STA",285"LDY", "LDA", "LDX", "LDA", "LDY", "LDA", "LDX", "LDA",286"TAY", "LDA", "TAX", "PLB", "LDY", "LDA", "LDX", "LDA",287"BCS", "LDA", "LDA", "LDA", "LDY", "LDA", "LDX", "LDA",288"CLV", "LDA", "TSX", "TYX", "LDY", "LDA", "LDX", "LDA",289"CPY", "CMP", "REP", "CMP", "CPY", "CMP", "DEC", "CMP",290"INY", "CMP", "DEX", "WAI", "CPY", "CMP", "DEC", "CMP",291"BNE", "CMP", "CMP", "CMP", "PEI", "CMP", "DEC", "CMP",292"CLD", "CMP", "PHX", "STP", "JML", "CMP", "DEC", "CMP",293"CPX", "SBC", "SEP", "SBC", "CPX", "SBC", "INC", "SBC",294"INX", "SBC", "NOP", "XBA", "CPX", "SBC", "INC", "SBC",295"BEQ", "SBC", "SBC", "SBC", "PEA", "SBC", "INC", "SBC",296"SED", "SBC", "PLX", "XCE", "JSR", "SBC", "INC", "SBC"297};298299static int AddrModes[256] =300{301// 0 1 2 3 4 5 6 7 8 9 A B C D E F3023, 10, 3, 19, 6, 6, 6, 12, 0, 1, 24, 0, 14, 14, 14, 17, // 03034, 11, 9, 20, 6, 7, 7, 13, 0, 16, 24, 0, 14, 15, 15, 18, // 130414, 10, 17, 19, 6, 6, 6, 12, 0, 1, 24, 0, 14, 14, 14, 17, // 23054, 11, 9, 20, 7, 7, 7, 13, 0, 16, 24, 0, 15, 15, 15, 18, // 33060, 10, 3, 19, 25, 6, 6, 12, 0, 1, 24, 0, 14, 14, 14, 17, // 43074, 11, 9, 20, 25, 7, 7, 13, 0, 16, 0, 0, 17, 15, 15, 18, // 53080, 10, 5, 19, 6, 6, 6, 12, 0, 1, 24, 0, 21, 14, 14, 17, // 63094, 11, 9, 20, 7, 7, 7, 13, 0, 16, 0, 0, 23, 15, 15, 18, // 73104, 10, 5, 19, 6, 6, 6, 12, 0, 1, 0, 0, 14, 14, 14, 17, // 83114, 11, 9, 20, 7, 7, 8, 13, 0, 16, 0, 0, 14, 15, 15, 18, // 93122, 10, 2, 19, 6, 6, 6, 12, 0, 1, 0, 0, 14, 14, 14, 17, // A3134, 11, 9, 20, 7, 7, 8, 13, 0, 16, 0, 0, 15, 15, 16, 18, // B3142, 10, 3, 19, 6, 6, 6, 12, 0, 1, 0, 0, 14, 14, 14, 17, // C3154, 11, 9, 9, 27, 7, 7, 13, 0, 16, 0, 0, 22, 15, 15, 18, // D3162, 10, 3, 19, 6, 6, 6, 12, 0, 1, 0, 0, 14, 14, 14, 17, // E3174, 11, 9, 20, 26, 7, 7, 13, 0, 16, 0, 0, 23, 15, 15, 18 // F318};319320static uint8 S9xDebugGetByte (uint32);321static uint16 S9xDebugGetWord (uint32);322static uint8 S9xDebugSA1GetByte (uint32);323static uint16 S9xDebugSA1GetWord (uint32);324static uint8 debug_cpu_op_print (char *, uint8, uint16);325static uint8 debug_sa1_op_print (char *, uint8, uint16);326static void debug_line_print (const char *);327static int debug_get_number (char *, uint16 *);328static short debug_get_start_address (char *, uint8 *, uint32 *);329static void debug_process_command (char *);330static void debug_print_window (uint8 *);331static const char * debug_clip_fn (int);332static void debug_whats_used (void);333static void debug_whats_missing (void);334335336static uint8 S9xDebugGetByte (uint32 Address)337{338int block = (Address & 0xffffff) >> MEMMAP_SHIFT;339uint8 *GetAddress = Memory.Map[block];340uint8 byte = 0;341342if (GetAddress >= (uint8 *) CMemory::MAP_LAST)343{344byte = *(GetAddress + (Address & 0xffff));345return (byte);346}347348switch ((pint) GetAddress)349{350case CMemory::MAP_LOROM_SRAM:351case CMemory::MAP_SA1RAM:352byte = *(Memory.SRAM + ((((Address & 0xff0000) >> 1) | (Address & 0x7fff)) & Memory.SRAMMask));353return (byte);354355case CMemory::MAP_LOROM_SRAM_B:356byte = *(Multi.sramB + ((((Address & 0xff0000) >> 1) | (Address & 0x7fff)) & Multi.sramMaskB));357return (byte);358359case CMemory::MAP_HIROM_SRAM:360case CMemory::MAP_RONLY_SRAM:361byte = *(Memory.SRAM + (((Address & 0x7fff) - 0x6000 + ((Address & 0xf0000) >> 3)) & Memory.SRAMMask));362return (byte);363364case CMemory::MAP_BWRAM:365byte = *(Memory.BWRAM + ((Address & 0x7fff) - 0x6000));366return (byte);367368default:369return (byte);370}371}372373static uint16 S9xDebugGetWord (uint32 Address)374{375uint16 word;376377word = S9xDebugGetByte(Address);378word |= S9xDebugGetByte(Address + 1) << 8;379380return (word);381}382383static uint8 S9xDebugSA1GetByte (uint32 Address)384{385int block = (Address & 0xffffff) >> MEMMAP_SHIFT;386uint8 *GetAddress = SA1.Map[block];387uint8 byte = 0;388389if (GetAddress >= (uint8 *) CMemory::MAP_LAST)390{391byte = *(GetAddress + (Address & 0xffff));392return (byte);393}394395switch ((pint) GetAddress)396{397case CMemory::MAP_LOROM_SRAM:398case CMemory::MAP_SA1RAM:399byte = *(Memory.SRAM + (Address & 0xffff));400return (byte);401402case CMemory::MAP_BWRAM:403byte = *(SA1.BWRAM + ((Address & 0x7fff) - 0x6000));404return (byte);405406case CMemory::MAP_BWRAM_BITMAP:407Address -= 0x600000;408if (SA1.VirtualBitmapFormat == 2)409byte = (Memory.SRAM[(Address >> 2) & 0xffff] >> ((Address & 3) << 1)) & 3;410else411byte = (Memory.SRAM[(Address >> 1) & 0xffff] >> ((Address & 1) << 2)) & 15;412return (byte);413414case CMemory::MAP_BWRAM_BITMAP2:415Address = (Address & 0xffff) - 0x6000;416if (SA1.VirtualBitmapFormat == 2)417byte = (SA1.BWRAM[(Address >> 2) & 0xffff] >> ((Address & 3) << 1)) & 3;418else419byte = (SA1.BWRAM[(Address >> 1) & 0xffff] >> ((Address & 1) << 2)) & 15;420return (byte);421422default:423return (byte);424}425}426427static uint16 S9xDebugSA1GetWord (uint32 Address)428{429uint16 word;430431word = S9xDebugSA1GetByte(Address);432word |= S9xDebugSA1GetByte(Address + 1) << 8;433434return (word);435}436437static uint8 debug_cpu_op_print (char *Line, uint8 Bank, uint16 Address)438{439uint8 S9xOpcode;440uint8 Operant[3];441uint16 Word;442uint8 Byte;443int16 SWord;444int8 SByte;445uint8 Size = 0;446447S9xOpcode = S9xDebugGetByte((Bank << 16) + Address);448sprintf(Line, "$%02X:%04X %02X ", Bank, Address, S9xOpcode);449450Operant[0] = S9xDebugGetByte((Bank << 16) + Address + 1);451Operant[1] = S9xDebugGetByte((Bank << 16) + Address + 2);452Operant[2] = S9xDebugGetByte((Bank << 16) + Address + 3);453454switch (AddrModes[S9xOpcode])455{456case 0:457// Implied458sprintf(Line, "%s %s",459Line,460S9xMnemonics[S9xOpcode]);461Size = 1;462break;463464case 1:465// Immediate[MemoryFlag]466if (!CheckFlag(MemoryFlag))467{468// Accumulator 16 - Bit469sprintf(Line, "%s%02X %02X %s #$%02X%02X",470Line,471Operant[0],472Operant[1],473S9xMnemonics[S9xOpcode],474Operant[1],475Operant[0]);476Size = 3;477}478else479{480// Accumulator 8 - Bit481sprintf(Line, "%s%02X %s #$%02X",482Line,483Operant[0],484S9xMnemonics[S9xOpcode],485Operant[0]);486Size = 2;487}488489break;490491case 2:492// Immediate[IndexFlag]493if (!CheckFlag(IndexFlag))494{495// X / Y 16 - Bit496sprintf(Line, "%s%02X %02X %s #$%02X%02X",497Line,498Operant[0],499Operant[1],500S9xMnemonics[S9xOpcode],501Operant[1],502Operant[0]);503Size = 3;504}505else506{507// X / Y 8 - Bit508sprintf(Line, "%s%02X %s #$%02X",509Line,510Operant[0],511S9xMnemonics[S9xOpcode],512Operant[0]);513Size = 2;514}515516break;517518case 3:519// Immediate[Always 8 - Bit]520sprintf(Line, "%s%02X %s #$%02X",521Line,522Operant[0],523S9xMnemonics[S9xOpcode],524Operant[0]);525Size = 2;526break;527528case 4:529// Relative530sprintf(Line, "%s%02X %s $%02X",531Line,532Operant[0],533S9xMnemonics[S9xOpcode],534Operant[0]);535SByte = Operant[0];536Word = Address;537Word += SByte;538Word += 2;539sprintf(Line, "%-32s[$%04X]", Line, Word);540Size = 2;541break;542543case 5:544// Relative Long545sprintf(Line, "%s%02X %02X %s $%02X%02X",546Line,547Operant[0],548Operant[1],549S9xMnemonics[S9xOpcode],550Operant[1],551Operant[0]);552SWord = (Operant[1] << 8) | Operant[0];553Word = Address;554Word += SWord;555Word += 3;556sprintf(Line, "%-32s[$%04X]", Line, Word);557Size = 3;558break;559560case 6:561// Direct562sprintf(Line, "%s%02X %s $%02X",563Line,564Operant[0],565S9xMnemonics[S9xOpcode],566Operant[0]);567Word = Operant[0];568Word += Registers.D.W;569sprintf(Line, "%-32s[$00:%04X]", Line, Word);570Size = 2;571break;572573case 7:574// Direct Indexed (with X)575sprintf(Line, "%s%02X %s $%02X,x",576Line,577Operant[0],578S9xMnemonics[S9xOpcode],579Operant[0]);580Word = Operant[0];581Word += Registers.D.W;582Word += Registers.X.W;583sprintf(Line, "%-32s[$00:%04X]", Line, Word);584Size = 2;585break;586587case 8:588// Direct Indexed (with Y)589sprintf(Line, "%s%02X %s $%02X,y",590Line,591Operant[0],592S9xMnemonics[S9xOpcode],593Operant[0]);594Word = Operant[0];595Word += Registers.D.W;596Word += Registers.Y.W;597sprintf(Line, "%-32s[$00:%04X]", Line, Word);598Size = 2;599break;600601case 9:602// Direct Indirect603sprintf(Line, "%s%02X %s ($%02X)",604Line,605Operant[0],606S9xMnemonics[S9xOpcode],607Operant[0]);608Word = Operant[0];609Word += Registers.D.W;610Word = S9xDebugGetWord(Word);611sprintf(Line, "%-32s[$%02X:%04X]", Line, Registers.DB, Word);612Size = 2;613break;614615case 10:616// Direct Indexed Indirect617sprintf(Line, "%s%02X %s ($%02X,x)",618Line,619Operant[0],620S9xMnemonics[S9xOpcode],621Operant[0]);622Word = Operant[0];623Word += Registers.D.W;624Word += Registers.X.W;625Word = S9xDebugGetWord(Word);626sprintf(Line, "%-32s[$%02X:%04X]", Line, Registers.DB, Word);627Size = 2;628break;629630case 11:631// Direct Indirect Indexed632sprintf(Line, "%s%02X %s ($%02X),y",633Line,634Operant[0],635S9xMnemonics[S9xOpcode],636Operant[0]);637Word = Operant[0];638Word += Registers.D.W;639Word = S9xDebugGetWord(Word);640Word += Registers.Y.W;641sprintf(Line, "%-32s[$%02X:%04X]", Line, Registers.DB, Word);642Size = 2;643break;644645case 12:646// Direct Indirect Long647sprintf(Line, "%s%02X %s [$%02X]",648Line,649Operant[0],650S9xMnemonics[S9xOpcode],651Operant[0]);652Word = Operant[0];653Word += Registers.D.W;654Byte = S9xDebugGetByte(Word + 2);655Word = S9xDebugGetWord(Word);656sprintf(Line, "%-32s[$%02X:%04X]", Line, Byte, Word);657Size = 2;658break;659660case 13:661// Direct Indirect Indexed Long662sprintf(Line, "%s%02X %s [$%02X],y",663Line,664Operant[0],665S9xMnemonics[S9xOpcode],666Operant[0]);667Word = Operant[0];668Word += Registers.D.W;669Byte = S9xDebugGetByte(Word + 2);670Word = S9xDebugGetWord(Word);671Word += Registers.Y.W;672sprintf(Line, "%-32s[$%02X:%04X]", Line, Byte, Word);673Size = 2;674break;675676case 14:677// Absolute678sprintf(Line, "%s%02X %02X %s $%02X%02X",679Line,680Operant[0],681Operant[1],682S9xMnemonics[S9xOpcode],683Operant[1],684Operant[0]);685Word = (Operant[1] << 8) | Operant[0];686sprintf(Line, "%-32s[$%02X:%04X]", Line, Registers.DB, Word);687Size = 3;688break;689690case 15:691// Absolute Indexed (with X)692sprintf(Line, "%s%02X %02X %s $%02X%02X,x",693Line,694Operant[0],695Operant[1],696S9xMnemonics[S9xOpcode],697Operant[1],698Operant[0]);699Word = (Operant[1] << 8) | Operant[0];700Word += Registers.X.W;701sprintf(Line, "%-32s[$%02X:%04X]", Line, Registers.DB, Word);702Size = 3;703break;704705case 16:706// Absolute Indexed (with Y)707sprintf(Line, "%s%02X %02X %s $%02X%02X,y",708Line,709Operant[0],710Operant[1],711S9xMnemonics[S9xOpcode],712Operant[1],713Operant[0]);714Word = (Operant[1] << 8) | Operant[0];715Word += Registers.Y.W;716sprintf(Line, "%-32s[$%02X:%04X]", Line, Registers.DB, Word);717Size = 3;718break;719720case 17:721// Absolute Long722sprintf(Line, "%s%02X %02X %02X %s $%02X%02X%02X",723Line,724Operant[0],725Operant[1],726Operant[2],727S9xMnemonics[S9xOpcode],728Operant[2],729Operant[1],730Operant[0]);731Word = (Operant[1] << 8) | Operant[0];732sprintf(Line, "%-32s[$%02X:%04X]", Line, Operant[2], Word);733Size = 4;734break;735736case 18:737// Absolute Indexed Long738sprintf(Line, "%s%02X %02X %02X %s $%02X%02X%02X,x",739Line,740Operant[0],741Operant[1],742Operant[2],743S9xMnemonics[S9xOpcode],744Operant[2],745Operant[1],746Operant[0]);747Word = (Operant[1] << 8) | Operant[0];748Word += Registers.X.W;749sprintf(Line, "%-32s[$%02X:%04X]", Line, Operant[2], Word);750Size = 4;751break;752753case 19:754// Stack Relative755sprintf(Line, "%s%02X %s $%02X,s",756Line,757Operant[0],758S9xMnemonics[S9xOpcode],759Operant[0]);760Word = Registers.S.W;761Word += Operant[0];762sprintf(Line, "%-32s[$00:%04X]", Line, Word);763Size = 2;764break;765766case 20:767// Stack Relative Indirect Indexed768sprintf(Line, "%s%02X %s ($%02X,s),y",769Line,770Operant[0],771S9xMnemonics[S9xOpcode],772Operant[0]);773Word = Registers.S.W;774Word += Operant[0];775Word = S9xDebugGetWord(Word);776Word += Registers.Y.W;777sprintf(Line, "%-32s[$%02X:%04X]", Line, Registers.DB, Word);778Size = 2;779break;780781case 21:782// Absolute Indirect783sprintf(Line, "%s%02X %02X %s ($%02X%02X)",784Line,785Operant[0],786Operant[1],787S9xMnemonics[S9xOpcode],788Operant[1],789Operant[0]);790Word = (Operant[1] << 8) | Operant[0];791Word = S9xDebugGetWord(Word);792sprintf(Line, "%-32s[$%02X:%04X]", Line, Registers.PB, Word);793Size = 3;794break;795796case 22:797// Absolute Indirect Long798sprintf(Line, "%s%02X %02X %s [$%02X%02X]",799Line,800Operant[0],801Operant[1],802S9xMnemonics[S9xOpcode],803Operant[1],804Operant[0]);805Word = (Operant[1] << 8) | Operant[0];806Byte = S9xDebugGetByte(Word + 2);807Word = S9xDebugGetWord(Word);808sprintf(Line, "%-32s[$%02X:%04X]", Line, Byte, Word);809Size = 3;810break;811812case 23:813// Absolute Indexed Indirect814sprintf(Line, "%s%02X %02X %s ($%02X%02X,x)",815Line,816Operant[0],817Operant[1],818S9xMnemonics[S9xOpcode],819Operant[1],820Operant[0]);821Word = (Operant[1] << 8) | Operant[0];822Word += Registers.X.W;823Word = S9xDebugGetWord(ICPU.ShiftedPB + Word);824sprintf(Line, "%-32s[$%02X:%04X]", Line, Registers.PB, Word);825Size = 3;826break;827828case 24:829// Implied Accumulator830sprintf(Line, "%s %s A",831Line,832S9xMnemonics[S9xOpcode]);833Size = 1;834break;835836case 25:837// MVN/MVP SRC DST838sprintf(Line, "%s%02X %02X %s %02X %02X",839Line,840Operant[0],841Operant[1],842S9xMnemonics[S9xOpcode],843Operant[1],844Operant[0]);845Size = 3;846break;847848case 26:849// PEA850sprintf(Line, "%s%02X %02X %s $%02X%02X",851Line,852Operant[0],853Operant[1],854S9xMnemonics[S9xOpcode],855Operant[1],856Operant[0]);857Size = 3;858break;859860case 27:861// PEI Direct Indirect862sprintf(Line, "%s%02X %s ($%02X)",863Line,864Operant[0],865S9xMnemonics[S9xOpcode],866Operant[0]);867Word = Operant[0];868Word += Registers.D.W;869Word = S9xDebugGetWord(Word);870sprintf(Line, "%-32s[$%04X]", Line, Word);871Size = 2;872break;873}874875sprintf(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:%04ld VC:%03ld FC:%02d %03x",876Line, Registers.A.W, Registers.X.W, Registers.Y.W,877Registers.D.W, Registers.DB, Registers.S.W,878CheckEmulation() ? 'E' : 'e',879CheckNegative() ? 'N' : 'n',880CheckOverflow() ? 'V' : 'v',881CheckMemory() ? 'M' : 'm',882CheckIndex() ? 'X' : 'x',883CheckDecimal() ? 'D' : 'd',884CheckIRQ() ? 'I' : 'i',885CheckZero() ? 'Z' : 'z',886CheckCarry() ? 'C' : 'c',887(long) CPU.Cycles,888(long) CPU.V_Counter,889IPPU.FrameCount,890(CPU.IRQExternal ? 0x100 : 0) | (PPU.HTimerEnabled ? 0x10 : 0) | (PPU.VTimerEnabled ? 0x01 : 0));891892return (Size);893}894895static uint8 debug_sa1_op_print (char *Line, uint8 Bank, uint16 Address)896{897uint8 S9xOpcode;898uint8 Operant[3];899uint16 Word;900uint8 Byte;901int16 SWord;902int8 SByte;903uint8 Size = 0;904905S9xOpcode = S9xDebugSA1GetByte((Bank << 16) + Address);906sprintf(Line, "$%02X:%04X %02X ", Bank, Address, S9xOpcode);907908Operant[0] = S9xDebugSA1GetByte((Bank << 16) + Address + 1);909Operant[1] = S9xDebugSA1GetByte((Bank << 16) + Address + 2);910Operant[2] = S9xDebugSA1GetByte((Bank << 16) + Address + 3);911912switch (AddrModes[S9xOpcode])913{914case 0:915// Implied916sprintf(Line, "%s %s",917Line,918S9xMnemonics[S9xOpcode]);919Size = 1;920break;921922case 1:923// Immediate[MemoryFlag]924if (!SA1CheckFlag(MemoryFlag))925{926// Accumulator 16 - Bit927sprintf(Line, "%s%02X %02X %s #$%02X%02X",928Line,929Operant[0],930Operant[1],931S9xMnemonics[S9xOpcode],932Operant[1],933Operant[0]);934Size = 3;935}936else937{938// Accumulator 8 - Bit939sprintf(Line, "%s%02X %s #$%02X",940Line,941Operant[0],942S9xMnemonics[S9xOpcode],943Operant[0]);944Size = 2;945}946947break;948949case 2:950// Immediate[IndexFlag]951if (!SA1CheckFlag(IndexFlag))952{953// X / Y 16 - Bit954sprintf(Line, "%s%02X %02X %s #$%02X%02X",955Line,956Operant[0],957Operant[1],958S9xMnemonics[S9xOpcode],959Operant[1],960Operant[0]);961Size = 3;962}963else964{965// X / Y 8 - Bit966sprintf(Line, "%s%02X %s #$%02X",967Line,968Operant[0],969S9xMnemonics[S9xOpcode],970Operant[0]);971Size = 2;972}973974break;975976case 3:977// Immediate[Always 8 - Bit]978sprintf(Line, "%s%02X %s #$%02X",979Line,980Operant[0],981S9xMnemonics[S9xOpcode],982Operant[0]);983Size = 2;984break;985986case 4:987// Relative988sprintf(Line, "%s%02X %s $%02X",989Line,990Operant[0],991S9xMnemonics[S9xOpcode],992Operant[0]);993SByte = Operant[0];994Word = Address;995Word += SByte;996Word += 2;997sprintf(Line, "%-32s[$%04X]", Line, Word);998Size = 2;999break;10001001case 5:1002// Relative Long1003sprintf(Line, "%s%02X %02X %s $%02X%02X",1004Line,1005Operant[0],1006Operant[1],1007S9xMnemonics[S9xOpcode],1008Operant[1],1009Operant[0]);1010SWord = (Operant[1] << 8) | Operant[0];1011Word = Address;1012Word += SWord;1013Word += 3;1014sprintf(Line, "%-32s[$%04X]", Line, Word);1015Size = 3;1016break;10171018case 6:1019// Direct1020sprintf(Line, "%s%02X %s $%02X",1021Line,1022Operant[0],1023S9xMnemonics[S9xOpcode],1024Operant[0]);1025Word = Operant[0];1026Word += SA1Registers.D.W;1027sprintf(Line, "%-32s[$00:%04X]", Line, Word);1028Size = 2;1029break;10301031case 7:1032// Direct Indexed (with X)1033sprintf(Line, "%s%02X %s $%02X,x",1034Line,1035Operant[0],1036S9xMnemonics[S9xOpcode],1037Operant[0]);1038Word = Operant[0];1039Word += SA1Registers.D.W;1040Word += SA1Registers.X.W;1041sprintf(Line, "%-32s[$00:%04X]", Line, Word);1042Size = 2;1043break;10441045case 8:1046// Direct Indexed (with Y)1047sprintf(Line, "%s%02X %s $%02X,y",1048Line,1049Operant[0],1050S9xMnemonics[S9xOpcode],1051Operant[0]);1052Word = Operant[0];1053Word += SA1Registers.D.W;1054Word += SA1Registers.Y.W;1055sprintf(Line, "%-32s[$00:%04X]", Line, Word);1056Size = 2;1057break;10581059case 9:1060// Direct Indirect1061sprintf(Line, "%s%02X %s ($%02X)",1062Line,1063Operant[0],1064S9xMnemonics[S9xOpcode],1065Operant[0]);1066Word = Operant[0];1067Word += SA1Registers.D.W;1068Word = S9xDebugSA1GetWord(Word);1069sprintf(Line, "%-32s[$%02X:%04X]", Line, SA1Registers.DB, Word);1070Size = 2;1071break;10721073case 10:1074// Direct Indexed Indirect1075sprintf(Line, "%s%02X %s ($%02X,x)",1076Line,1077Operant[0],1078S9xMnemonics[S9xOpcode],1079Operant[0]);1080Word = Operant[0];1081Word += SA1Registers.D.W;1082Word += SA1Registers.X.W;1083Word = S9xDebugSA1GetWord(Word);1084sprintf(Line, "%-32s[$%02X:%04X]", Line, SA1Registers.DB, Word);1085Size = 2;1086break;10871088case 11:1089// Direct Indirect Indexed1090sprintf(Line, "%s%02X %s ($%02X),y",1091Line,1092Operant[0],1093S9xMnemonics[S9xOpcode],1094Operant[0]);1095Word = Operant[0];1096Word += SA1Registers.D.W;1097Word = S9xDebugSA1GetWord(Word);1098Word += SA1Registers.Y.W;1099sprintf(Line, "%-32s[$%02X:%04X]", Line, SA1Registers.DB, Word);1100Size = 2;1101break;11021103case 12:1104// Direct Indirect Long1105sprintf(Line, "%s%02X %s [$%02X]",1106Line,1107Operant[0],1108S9xMnemonics[S9xOpcode],1109Operant[0]);1110Word = Operant[0];1111Word += SA1Registers.D.W;1112Byte = S9xDebugSA1GetByte(Word + 2);1113Word = S9xDebugSA1GetWord(Word);1114sprintf(Line, "%-32s[$%02X:%04X]", Line, Byte, Word);1115Size = 2;1116break;11171118case 13:1119// Direct Indirect Indexed Long1120sprintf(Line, "%s%02X %s [$%02X],y",1121Line,1122Operant[0],1123S9xMnemonics[S9xOpcode],1124Operant[0]);1125Word = Operant[0];1126Word += SA1Registers.D.W;1127Byte = S9xDebugSA1GetByte(Word + 2);1128Word = S9xDebugSA1GetWord(Word);1129Word += SA1Registers.Y.W;1130sprintf(Line, "%-32s[$%02X:%04X]", Line, Byte, Word);1131Size = 2;1132break;11331134case 14:1135// Absolute1136sprintf(Line, "%s%02X %02X %s $%02X%02X",1137Line,1138Operant[0],1139Operant[1],1140S9xMnemonics[S9xOpcode],1141Operant[1],1142Operant[0]);1143Word = (Operant[1] << 8) | Operant[0];1144sprintf(Line, "%-32s[$%02X:%04X]", Line, SA1Registers.DB, Word);1145Size = 3;1146break;11471148case 15:1149// Absolute Indexed (with X)1150sprintf(Line, "%s%02X %02X %s $%02X%02X,x",1151Line,1152Operant[0],1153Operant[1],1154S9xMnemonics[S9xOpcode],1155Operant[1],1156Operant[0]);1157Word = (Operant[1] << 8) | Operant[0];1158Word += SA1Registers.X.W;1159sprintf(Line, "%-32s[$%02X:%04X]", Line, SA1Registers.DB, Word);1160Size = 3;1161break;11621163case 16:1164// Absolute Indexed (with Y)1165sprintf(Line, "%s%02X %02X %s $%02X%02X,y",1166Line,1167Operant[0],1168Operant[1],1169S9xMnemonics[S9xOpcode],1170Operant[1],1171Operant[0]);1172Word = (Operant[1] << 8) | Operant[0];1173Word += SA1Registers.Y.W;1174sprintf(Line, "%-32s[$%02X:%04X]", Line, SA1Registers.DB, Word);1175Size = 3;1176break;11771178case 17:1179// Absolute Long1180sprintf(Line, "%s%02X %02X %02X %s $%02X%02X%02X",1181Line,1182Operant[0],1183Operant[1],1184Operant[2],1185S9xMnemonics[S9xOpcode],1186Operant[2],1187Operant[1],1188Operant[0]);1189Word = (Operant[1] << 8) | Operant[0];1190sprintf(Line, "%-32s[$%02X:%04X]", Line, Operant[2], Word);1191Size = 4;1192break;11931194case 18:1195// Absolute Indexed Long1196sprintf(Line, "%s%02X %02X %02X %s $%02X%02X%02X,x",1197Line,1198Operant[0],1199Operant[1],1200Operant[2],1201S9xMnemonics[S9xOpcode],1202Operant[2],1203Operant[1],1204Operant[0]);1205Word = (Operant[1] << 8) | Operant[0];1206Word += SA1Registers.X.W;1207sprintf(Line, "%-32s[$%02X:%04X]", Line, Operant[2], Word);1208Size = 4;1209break;12101211case 19:1212// Stack Relative1213sprintf(Line, "%s%02X %s $%02X,s",1214Line,1215Operant[0],1216S9xMnemonics[S9xOpcode],1217Operant[0]);1218Word = SA1Registers.S.W;1219Word += Operant[0];1220sprintf(Line, "%-32s[$00:%04X]", Line, Word);1221Size = 2;1222break;12231224case 20:1225// Stack Relative Indirect Indexed1226sprintf(Line, "%s%02X %s ($%02X,s),y",1227Line,1228Operant[0],1229S9xMnemonics[S9xOpcode],1230Operant[0]);1231Word = SA1Registers.S.W;1232Word += Operant[0];1233Word = S9xDebugSA1GetWord(Word);1234Word += SA1Registers.Y.W;1235sprintf(Line, "%-32s[$%02X:%04X]", Line, SA1Registers.DB, Word);1236Size = 2;1237break;12381239case 21:1240// Absolute Indirect1241sprintf(Line, "%s%02X %02X %s ($%02X%02X)",1242Line,1243Operant[0],1244Operant[1],1245S9xMnemonics[S9xOpcode],1246Operant[1],1247Operant[0]);1248Word = (Operant[1] << 8) | Operant[0];1249Word = S9xDebugSA1GetWord(Word);1250sprintf(Line, "%-32s[$%02X:%04X]", Line, SA1Registers.PB, Word);1251Size = 3;1252break;12531254case 22:1255// Absolute Indirect Long1256sprintf(Line, "%s%02X %02X %s [$%02X%02X]",1257Line,1258Operant[0],1259Operant[1],1260S9xMnemonics[S9xOpcode],1261Operant[1],1262Operant[0]);1263Word = (Operant[1] << 8) | Operant[0];1264Byte = S9xDebugSA1GetByte(Word + 2);1265Word = S9xDebugSA1GetWord(Word);1266sprintf(Line, "%-32s[$%02X:%04X]", Line, Byte, Word);1267Size = 3;1268break;12691270case 23:1271// Absolute Indexed Indirect1272sprintf(Line, "%s%02X %02X %s ($%02X%02X,x)",1273Line,1274Operant[0],1275Operant[1],1276S9xMnemonics[S9xOpcode],1277Operant[1],1278Operant[0]);1279Word = (Operant[1] << 8) | Operant[0];1280Word += SA1Registers.X.W;1281Word = S9xDebugSA1GetWord(SA1.ShiftedPB + Word);1282sprintf(Line, "%-32s[$%02X:%04X]", Line, SA1Registers.PB, Word);1283Size = 3;1284break;12851286case 24:1287// Implied Accumulator1288sprintf(Line, "%s %s A",1289Line,1290S9xMnemonics[S9xOpcode]);1291Size = 1;1292break;12931294case 25:1295// MVN/MVP SRC DST1296sprintf(Line, "%s %s %02X %02X",1297Line,1298S9xMnemonics[S9xOpcode],1299Operant[0],1300Operant[1]);1301Size = 3;1302break;1303}13041305sprintf(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:%04ld VC:%03ld FC:%02d",1306Line, SA1Registers.A.W, SA1Registers.X.W, SA1Registers.Y.W,1307SA1Registers.D.W, SA1Registers.DB, SA1Registers.S.W,1308SA1CheckEmulation() ? 'E' : 'e',1309SA1CheckNegative() ? 'N' : 'n',1310SA1CheckOverflow() ? 'V' : 'v',1311SA1CheckMemory() ? 'M' : 'm',1312SA1CheckIndex() ? 'X' : 'x',1313SA1CheckDecimal() ? 'D' : 'd',1314SA1CheckIRQ() ? 'I' : 'i',1315SA1CheckZero() ? 'Z' : 'z',1316SA1CheckCarry() ? 'C' : 'c',1317(long) CPU.Cycles,1318(long) CPU.V_Counter,1319IPPU.FrameCount);13201321return (Size);1322}13231324static void debug_line_print (const char *Line)1325{1326printf("%s\n", Line);1327}13281329static int debug_get_number (char *Line, uint16 *Number)1330{1331int i;13321333if (sscanf(Line, " #%d", &i) == 1)1334{1335*Number = i;1336return (1);1337}13381339return (-1);1340}13411342static short debug_get_start_address (char *Line, uint8 *Bank, uint32 *Address)1343{1344uint32 a, b;13451346if (sscanf(Line + 1, " $%x:%x", &b, &a) != 2)1347return (-1);13481349*Bank = b;1350*Address = a;13511352return (1);1353}13541355static void debug_process_command (char *Line)1356{1357uint8 Bank = Registers.PB;1358uint32 Address = Registers.PCw;1359uint16 Hold = 0;1360uint16 Number;1361short ErrorCode;1362char string[512];13631364if (strncasecmp(Line, "dump", 4) == 0)1365{1366int Count;13671368if (sscanf(&Line[4], "%x %d", &Address, &Count) == 2)1369{1370FILE *fs;13711372sprintf(string, "%06x%05d.sd2", Address, Count);1373fs = fopen(string, "wb");1374if (fs)1375{1376for (int i = 0; i < Count; i++)1377putc(S9xDebugGetByte(Address + i), fs);1378fclose(fs);1379}1380else1381printf("Can't open %s for writing\n", string);1382}1383else1384printf("Usage: dump start_address_in_hex count_in_decimal\n");13851386return;1387}13881389if (*Line == 'i')1390{1391printf("Vectors:\n");1392sprintf(string, " 8 Bit 16 Bit ");1393debug_line_print(string);1394sprintf(string, "ABT $00:%04X|$00:%04X", S9xDebugGetWord(0xFFF8), S9xDebugGetWord(0xFFE8));1395debug_line_print(string);1396sprintf(string, "BRK $00:%04X|$00:%04X", S9xDebugGetWord(0xFFFE), S9xDebugGetWord(0xFFE6));1397debug_line_print(string);1398sprintf(string, "COP $00:%04X|$00:%04X", S9xDebugGetWord(0xFFF4), S9xDebugGetWord(0xFFE4));1399debug_line_print(string);1400sprintf(string, "IRQ $00:%04X|$00:%04X", S9xDebugGetWord(0xFFFE), S9xDebugGetWord(0xFFEE));1401debug_line_print(string);1402sprintf(string, "NMI $00:%04X|$00:%04X", S9xDebugGetWord(0xFFFA), S9xDebugGetWord(0xFFEA));1403debug_line_print(string);1404sprintf(string, "RES $00:%04X", S9xDebugGetWord(0xFFFC));1405debug_line_print(string);1406}14071408/*1409if (strncmp(Line, "ai", 2) == 0)1410{1411printf("APU vectors:");14121413for (int i = 0; i < 0x40; i += 2)1414{1415if (i % 16 == 0)1416printf("\n%04x ", 0xffc0 + i);14171418printf("%04x ", APU.ExtraRAM[i]);1419}14201421printf("\n");1422}1423*/14241425if (*Line == 's')1426{1427Registers.PCw += debug_cpu_op_print(string, Bank, Address);1428Bank = Registers.PB;1429Address = Registers.PCw;1430*Line = 'r';1431}14321433if (*Line == 'z')1434{1435uint16 *p = (uint16 *) &Memory.VRAM[PPU.BG[2].SCBase << 1];14361437for (int l = 0; l < 32; l++)1438{1439for (int c = 0; c < 32; c++, p++)1440printf("%04x,", *p++);14411442printf("\n");1443}1444}14451446if (*Line == 'c')1447{1448printf("Colours:\n");14491450for (int i = 0; i < 256; i++)1451printf("%02x%02x%02x ", PPU.CGDATA[i] & 0x1f, (PPU.CGDATA[i] >> 5) & 0x1f, (PPU.CGDATA[i] >> 10) & 0x1f);14521453printf("\n");1454}14551456if (*Line == 'S')1457{1458int SmallWidth, LargeWidth, SmallHeight, LargeHeight;14591460switch ((Memory.FillRAM[0x2101] >> 5) & 7)1461{14621463case 0:1464SmallWidth = SmallHeight = 8;1465LargeWidth = LargeHeight = 16;1466break;14671468case 1:1469SmallWidth = SmallHeight = 8;1470LargeWidth = LargeHeight = 32;1471break;14721473case 2:1474SmallWidth = SmallHeight = 8;1475LargeWidth = LargeHeight = 64;1476break;14771478case 3:1479SmallWidth = SmallHeight = 16;1480LargeWidth = LargeHeight = 32;1481break;14821483case 4:1484SmallWidth = SmallHeight = 16;1485LargeWidth = LargeHeight = 64;1486break;14871488default:1489case 5:1490SmallWidth = SmallHeight = 32;1491LargeWidth = LargeHeight = 64;1492break;14931494case 6:1495SmallWidth = 16;1496SmallHeight = 32;1497LargeWidth = 32;1498LargeHeight = 64;1499break;15001501case 7:1502SmallWidth = 16;1503SmallHeight = 32;1504LargeWidth = LargeHeight = 32;1505break;1506}15071508printf("Sprites: Small: %dx%d, Large: %dx%d, OAMAddr: 0x%04x, OBJNameBase: 0x%04x, OBJNameSelect: 0x%04x, First: %d\n",1509SmallWidth, SmallHeight, LargeWidth, LargeHeight, PPU.OAMAddr, PPU.OBJNameBase, PPU.OBJNameSelect, PPU.FirstSprite);15101511for (int i = 0; i < 128; i++)1512{1513printf("X:%3d Y:%3d %c%c%d%c ",1514PPU.OBJ[i].HPos,1515PPU.OBJ[i].VPos,1516PPU.OBJ[i].VFlip ? 'V' : 'v',1517PPU.OBJ[i].HFlip ? 'H' : 'h',1518PPU.OBJ[i].Priority,1519PPU.OBJ[i].Size ? 'S' : 's');15201521if (i % 4 == 3)1522printf("\n");1523}1524}15251526if (*Line == 'T')1527{1528if (Line[1] == 'S')1529{1530SA1.Flags ^= TRACE_FLAG;15311532if (SA1.Flags & TRACE_FLAG)1533{1534printf("SA1 CPU instruction tracing enabled.\n");1535ENSURE_TRACE_OPEN(trace2, "trace_sa1.log", "wb")1536}1537else1538{1539printf("SA1 CPU instruction tracing disabled.\n");1540fclose(trace2);1541trace2 = NULL;1542}1543}1544else1545{1546CPU.Flags ^= TRACE_FLAG;15471548if (CPU.Flags & TRACE_FLAG)1549{1550printf("CPU instruction tracing enabled.\n");1551ENSURE_TRACE_OPEN(trace, "trace.log", "wb")1552}1553else1554{1555printf("CPU instruction tracing disabled.\n");1556fclose(trace);1557trace = NULL;1558}1559}1560}15611562if (*Line == 'E')1563{1564Settings.TraceHCEvent = !Settings.TraceHCEvent;1565printf("HC event tracing %s.\n", Settings.TraceHCEvent ? "enabled" : "disabled");1566}15671568if (*Line == 'A')1569spc_core->debug_toggle_trace();15701571/*1572if (*Line == 'B')1573{1574Settings.TraceSoundDSP = !Settings.TraceSoundDSP;1575printf("Sound DSP register tracing %s.\n", Settings.TraceSoundDSP ? "enabled" : "disabled");1576}15771578if (*Line == 'x')1579S9xPrintSoundDSPState();15801581if (*Line == 'C')1582{1583printf("SPC700 sample addresses at 0x%04x:\n", APU.DSP[APU_DIR] << 8);15841585for (int i = 0; i < 256; i++)1586{1587uint8 *dir = IAPU.RAM + (((APU.DSP[APU_DIR] << 8) + i * 4) & 0xffff);1588int addr = *dir + (*(dir + 1) << 8);1589int addr2 = *(dir + 2) + (*(dir + 3) << 8);1590printf("%04X %04X;", addr, addr2);15911592if (i % 8 == 7)1593printf("\n");1594}1595}1596*/15971598if (*Line == 'R')1599{1600S9xReset();1601printf("SNES reset.\n");1602CPU.Flags |= DEBUG_MODE_FLAG;1603}16041605/*1606if (strncmp(Line, "ad", 2) == 0)1607{1608uint32 Count = 16;1609Address = 0;16101611if (sscanf(Line + 2, "%x,%x", &Address, &Count) != 2)1612{1613if (sscanf(Line + 2, "%x", &Address) == 1)1614Count = 16;1615}16161617printf("APU RAM dump:\n");16181619for (uint32 l = 0; l < Count; l += 16)1620{1621printf("%04X ", Address);16221623for (int i = 0; i < 16; i++)1624printf("%02X ", IAPU.RAM[Address++]);16251626printf("\n");1627}16281629*Line = 0;1630}16311632if (*Line == 'a')1633{1634printf("APU in-ports : %02X %02X %02X %02X\n", IAPU.RAM[0xF4], IAPU.RAM[0xF5], IAPU.RAM[0xF6], IAPU.RAM[0xF7]);1635printf("APU out-ports: %02X %02X %02X %02X\n", APU.OutPorts[0], APU.OutPorts[1], APU.OutPorts[2], APU.OutPorts[3]);1636printf("ROM/RAM switch: %s\n", (IAPU.RAM[0xf1] & 0x80) ? "ROM" : "RAM");16371638for (int i = 0; i < 3; i++)1639if (APU.TimerEnabled[i])1640printf("Timer%d enabled, Value: 0x%03X, 4-bit: 0x%02X, Target: 0x%03X\n",1641i, APU.Timer[i], IAPU.RAM[0xfd + i], APU.TimerTarget[i]);1642}16431644if (*Line == 'P')1645{1646Settings.TraceDSP = !Settings.TraceDSP;1647printf("DSP tracing %s.\n", Settings.TraceDSP ? "enabled" : "disabled");1648}1649*/16501651if (*Line == 'p')1652{1653S9xBreakpoint[5].Enabled = FALSE;1654Address += debug_cpu_op_print(string, Bank, Address);16551656if (strncmp(&string[18], "JMP", 3) != 0 &&1657strncmp(&string[18], "JML", 3) != 0 &&1658strncmp(&string[18], "RT" , 2) != 0 &&1659strncmp(&string[18], "BRA", 3))1660{1661S9xBreakpoint[5].Enabled = TRUE;1662S9xBreakpoint[5].Bank = Bank;1663S9xBreakpoint[5].Address = Address;1664}1665else1666{1667CPU.Flags |= SINGLE_STEP_FLAG;1668CPU.Flags &= ~DEBUG_MODE_FLAG;1669}1670}16711672if (*Line == 'b')1673{1674if (Line[1] == 's')1675{1676debug_get_number(Line + 2, &Hold);16771678if (Hold > 4)1679Hold = 0;16801681if (Hold < 5)1682{1683if (debug_get_start_address(Line + 5, &Bank, &Address) == -1)1684S9xBreakpoint[Hold].Enabled = FALSE;1685else1686{1687S9xBreakpoint[Hold].Enabled = TRUE;1688S9xBreakpoint[Hold].Bank = Bank;1689S9xBreakpoint[Hold].Address = Address;1690CPU.Flags |= BREAK_FLAG;1691}1692}16931694Line[1] = 'v';1695}16961697if (Line[1] == 'v')1698{1699Number = 0;17001701if (debug_get_number(Line + 2, &Number) == -1 && Number < 5)1702{1703debug_line_print("Breakpoints:");17041705for (Number = 0; Number != 5; Number++)1706{1707if (S9xBreakpoint[Number].Enabled)1708sprintf(string, "%i @ $%02X:%04X", Number, S9xBreakpoint[Number].Bank, S9xBreakpoint[Number].Address);1709else1710sprintf(string, "%i @ Disabled", Number);17111712debug_line_print(string);1713}1714}1715else1716{1717debug_line_print("Breakpoint:");17181719if (S9xBreakpoint[Number].Enabled)1720sprintf(string, "%i @ $%02X:%04X", Number, S9xBreakpoint[Number].Bank, S9xBreakpoint[Number].Address);1721else1722sprintf(string, "%i @ Disabled", Number);17231724debug_line_print(string);1725}1726}1727}17281729if (*Line == '?' || strcasecmp(Line, "help") == 0)1730{1731for (int i = 0; HelpMessage[i] != NULL; i++)1732debug_line_print(HelpMessage[i]);1733}17341735if (*Line == 't')1736{1737CPU.Flags |= SINGLE_STEP_FLAG;1738CPU.Flags &= ~DEBUG_MODE_FLAG;1739}17401741if (*Line == 'f')1742{1743CPU.Flags |= FRAME_ADVANCE_FLAG;1744CPU.Flags &= ~DEBUG_MODE_FLAG;17451746IPPU.RenderThisFrame = TRUE;1747IPPU.FrameSkip = 0;17481749if (sscanf(&Line[1], "%u", &ICPU.FrameAdvanceCount) != 1)1750ICPU.Frame = 0;1751}17521753if (*Line == 'g')1754{1755S9xBreakpoint[5].Enabled = FALSE;17561757bool8 found = FALSE;17581759for (int i = 0; i < 5; i++)1760{1761if (S9xBreakpoint[i].Enabled)1762{1763found = TRUE;17641765if (S9xBreakpoint[i].Bank == Registers.PB && S9xBreakpoint[i].Address == Registers.PCw)1766{1767S9xBreakpoint[i].Enabled = 2;1768break;1769}1770}1771}17721773if (!found)1774CPU.Flags &= ~BREAK_FLAG;17751776ErrorCode = debug_get_start_address(Line, &Bank, &Address);17771778if (ErrorCode == 1)1779{1780S9xBreakpoint[5].Enabled = TRUE;1781S9xBreakpoint[5].Bank = Bank;1782S9xBreakpoint[5].Address = Address;1783CPU.Flags |= BREAK_FLAG;1784}17851786CPU.Flags &= ~DEBUG_MODE_FLAG;1787}17881789if (*Line == 'D')1790{1791Settings.TraceDMA = !Settings.TraceDMA;1792printf("DMA tracing %s.\n", Settings.TraceDMA ? "enabled" : "disabled");1793}17941795if (*Line == 'V')1796{1797Settings.TraceVRAM = !Settings.TraceVRAM;1798printf("Non-DMA VRAM write tracing %s.\n", Settings.TraceVRAM ? "enabled" : "disabled");1799}18001801if (*Line == 'H')1802{1803Settings.TraceHDMA = !Settings.TraceHDMA;1804printf("HDMA tracing %s.\n", Settings.TraceHDMA ? "enabled" : "disabled");1805}18061807if (*Line == 'U')1808{1809Settings.TraceUnknownRegisters = !Settings.TraceUnknownRegisters;1810printf("Unknown registers read/write tracing %s.\n", Settings.TraceUnknownRegisters ? "enabled" : "disabled");1811}18121813if (*Line == 'd')1814{1815int CLine;1816int CByte;1817uint8 MemoryByte;18181819if (Debug.Dump.Bank != 0 || Debug.Dump.Address != 0)1820{1821Bank = Debug.Dump.Bank;1822Address = Debug.Dump.Address;1823}18241825ErrorCode = debug_get_start_address(Line, &Bank, &Address);18261827for (CLine = 0; CLine != 10; CLine++)1828{1829sprintf(string, "$%02X:%04X", Bank, Address);18301831for (CByte = 0; CByte != 16; CByte++)1832{1833if (Address + CByte == 0x2140 ||1834Address + CByte == 0x2141 ||1835Address + CByte == 0x2142 ||1836Address + CByte == 0x2143 ||1837Address + CByte == 0x4210)1838MemoryByte = 0;1839else1840MemoryByte = S9xDebugGetByte((Bank << 16) + Address + CByte);18411842sprintf(string, "%s %02X", string, MemoryByte);1843}18441845sprintf(string, "%s-", string);18461847for (CByte = 0; CByte != 16; CByte++)1848{1849if (Address + CByte == 0x2140 ||1850Address + CByte == 0x2141 ||1851Address + CByte == 0x2142 ||1852Address + CByte == 0x2143 ||1853Address + CByte == 0x4210)1854MemoryByte = 0;1855else1856MemoryByte = S9xDebugGetByte((Bank << 16) + Address + CByte);18571858if (MemoryByte < 32 || MemoryByte >= 127)1859MemoryByte = '?';18601861sprintf(string, "%s%c", string, MemoryByte);1862}18631864Address += 16;18651866debug_line_print(string);1867}18681869Debug.Dump.Bank = Bank;1870Debug.Dump.Address = Address;1871}18721873if (*Line == 'q')1874S9xExit();18751876if (*Line == 'W')1877debug_whats_missing();18781879if (*Line == 'w')1880debug_whats_used();18811882if (*Line == 'r')1883{1884debug_cpu_op_print(string, Bank, Address);1885debug_line_print(string);1886}18871888if (*Line == 'u')1889{1890if (Debug.Unassemble.Bank != 0 || Debug.Unassemble.Address != 0)1891{1892Bank = Debug.Unassemble.Bank;1893Address = Debug.Unassemble.Address;1894}18951896ErrorCode = debug_get_start_address(Line, &Bank, &Address);18971898for (int i = 0; i != 10; i++)1899{1900Address += debug_cpu_op_print(string, Bank, Address);1901debug_line_print(string);1902}19031904Debug.Unassemble.Bank = Bank;1905Debug.Unassemble.Address = Address;1906}19071908debug_line_print("");19091910return;1911}19121913static void debug_print_window (uint8 *window)1914{1915for (int i = 0; i < 6; i++)1916{1917if (window[i])1918{1919switch (i)1920{1921case 0:1922printf("Background 0, ");1923break;19241925case 1:1926printf("Background 1, ");1927break;19281929case 2:1930printf("Background 2, ");1931break;19321933case 3:1934printf("Background 3, ");1935break;19361937case 4:1938printf("Objects, ");1939break;19401941case 5:1942printf("Color window, ");1943break;1944}1945}1946}1947}19481949static const char * debug_clip_fn (int logic)1950{1951switch (logic)1952{1953case CLIP_OR:1954return ("OR");19551956case CLIP_AND:1957return ("AND");19581959case CLIP_XOR:1960return ("XOR");19611962case CLIP_XNOR:1963return ("XNOR");19641965default:1966return ("???");1967}1968}19691970static void debug_whats_used (void)1971{1972printf("V-line: %ld, H-Pos: %ld, \n", (long) CPU.V_Counter, (long) CPU.Cycles);19731974printf("Screen mode: %d, ", PPU.BGMode);19751976if (PPU.BGMode <= 1 && (Memory.FillRAM[0x2105] & 8))1977printf("(BG#2 Priority), ");19781979printf("Brightness: %d, ", PPU.Brightness);19801981if (Memory.FillRAM[0x2100] & 0x80)1982printf("(screen blanked), ");19831984printf("\n");19851986if (Memory.FillRAM[0x2133] & 1)1987printf("Interlace, ");19881989if (Memory.FillRAM[0x2133] & 4)1990printf("240 line visible, ");19911992if (Memory.FillRAM[0x2133] & 8)1993printf("Pseudo 512 pixels horizontal resolution, ");19941995if (Memory.FillRAM[0x2133] & 0x40)1996printf("Mode 7 priority per pixel, ");19971998printf("\n");19992000if (PPU.BGMode == 7 && (Memory.FillRAM[0x211a] & 3))2001printf("Mode 7 flipping, ");20022003if (PPU.BGMode == 7)2004printf("Mode 7 screen repeat: %d, ", (Memory.FillRAM[0x211a] & 0xc0) >> 6);20052006if (Memory.FillRAM[0x2130] & 1)2007printf("32K colour mode, ");20082009printf("\n");20102011if (PPU.BGMode == 7)2012{2013// Sign extend 13 bit values to 16 bit values...2014if (PPU.CentreX & (1 << 12))2015PPU.CentreX |= 0xe000;20162017if (PPU.CentreY & (1 << 12))2018PPU.CentreY |= 0xe000;20192020printf("Matrix A: %.3f, B: %.3f, C: %.3f, D: %.3f, Centre X: %d Y:%d, \n",2021(double) PPU.MatrixA / 256, (double) PPU.MatrixB / 256,2022(double) PPU.MatrixC / 256, (double) PPU.MatrixD / 256,2023PPU.CentreX, PPU.CentreY);2024}20252026if ((Memory.FillRAM[0x2106] & 0xf0) && (Memory.FillRAM[0x2106] & 0x0f))2027{2028printf("Mosaic effect(%d) on, ", PPU.Mosaic);20292030for (int i = 0; i < 4; i++)2031if (Memory.FillRAM[0x2106] & (1 << i))2032printf("BG%d, ", i);2033}20342035printf("\n");20362037if (PPU.HVBeamCounterLatched)2038printf("V and H beam pos latched, \n");20392040if (Memory.FillRAM[0x4200] & 0x20)2041printf("V-IRQ enabled at %d, \n", PPU.IRQVBeamPos);20422043if (Memory.FillRAM[0x4200] & 0x10)2044printf("H-IRQ enabled at %d, \n", PPU.IRQHBeamPos);20452046if (Memory.FillRAM[0x4200] & 0x80)2047printf("V-blank NMI enabled, \n");20482049for (int i = 0; i < 8; i++)2050{2051if (missing.hdma_this_frame & (1 << i))2052{2053printf("H-DMA %d [%d] 0x%02X%04X->0x21%02X %s %s 0x%02X%04X %s addressing, \n",2054i, DMA[i].TransferMode, DMA[i].ABank, DMA[i].AAddress, DMA[i].BAddress,2055DMA[i].AAddressDecrement ? "dec" : "inc",2056DMA[i].Repeat ? "repeat" : "continue",2057DMA[i].IndirectBank, DMA[i].IndirectAddress,2058DMA[i].HDMAIndirectAddressing ? "indirect" : "absolute");2059}2060}20612062for (int i = 0; i < 8; i++)2063{2064if (missing.dma_this_frame & (1 << i))2065{2066printf("DMA %d [%d] 0x%02X%04X->0x21%02X Num: %d %s, \n",2067i, DMA[i].TransferMode, DMA[i].ABank, DMA[i].AAddress, DMA[i].BAddress, DMA[i].TransferBytes,2068DMA[i].AAddressFixed ? "fixed" : (DMA[i].AAddressDecrement ? "dec" : "inc"));2069}2070}20712072printf("VRAM write address: 0x%04x(%s), Full Graphic: %d, Address inc: %d, \n",2073PPU.VMA.Address,2074PPU.VMA.High ? "Byte" : "Word",2075PPU.VMA.FullGraphicCount, PPU.VMA.Increment);20762077for (int i = 0; i < 4; i++)2078{2079printf("BG%d: VOffset:%d, HOffset:%d, W:%d, H:%d, TS:%d, BA:0x%04x, TA:0x%04X, \n",2080i, PPU.BG[i].VOffset, PPU.BG[i].HOffset,2081(PPU.BG[i].SCSize & 1) * 32 + 32,2082(PPU.BG[i].SCSize & 2) * 16 + 32,2083PPU.BG[i].BGSize * 8 + 8,2084PPU.BG[i].SCBase,2085PPU.BG[i].NameBase);2086}20872088const char *s = "";20892090switch ((Memory.FillRAM[0x2130] & 0xc0) >> 6)2091{2092case 0:2093s = "always on";2094break;20952096case 1:2097s = "inside";2098break;20992100case 2:2101s = "outside";2102break;21032104case 3:2105s = "always off";2106break;2107}21082109printf("Main screen (%s): ", s);21102111for (int i = 0; i < 5; i++)2112{2113if (Memory.FillRAM[0x212c] & (1 << i))2114{2115switch (i)2116{2117case 0:2118printf("BG0, ");2119break;21202121case 1:2122printf("BG1, ");2123break;21242125case 2:2126printf("BG2, ");2127break;21282129case 3:2130printf("BG3, ");2131break;21322133case 4:2134printf("OBJ, ");2135break;2136}2137}2138}21392140printf("\n");21412142switch ((Memory.FillRAM[0x2130] & 0x30) >> 4)2143{2144case 0:2145s = "always on";2146break;21472148case 1:2149s = "inside";2150break;21512152case 2:2153s = "outside";2154break;21552156case 3:2157s = "always off";2158break;2159}21602161printf("Subscreen (%s): ", s);21622163for (int i = 0; i < 5; i++)2164{2165if (Memory.FillRAM[0x212d] & (1 << i))2166{2167switch (i)2168{2169case 0:2170printf("BG0, ");2171break;21722173case 1:2174printf("BG1, ");2175break;21762177case 2:2178printf("BG2, ");2179break;21802181case 3:2182printf("BG3, ");2183break;21842185case 4:2186printf("OBJ, ");2187break;2188}2189}2190}21912192printf("\n");21932194if ((Memory.FillRAM[0x2131] & 0x3f))2195{2196if (Memory.FillRAM[0x2131] & 0x80)2197{2198if (Memory.FillRAM[0x2130] & 0x02)2199printf("Subscreen subtract");2200else2201printf("Fixed colour subtract");2202}2203else2204{2205if (Memory.FillRAM[0x2130] & 0x02)2206printf("Subscreen addition");2207else2208printf("Fixed colour addition");2209}22102211if (Memory.FillRAM[0x2131] & 0x40)2212printf("(half): ");2213else2214printf(": ");22152216for (int i = 0; i < 6; i++)2217{2218if (Memory.FillRAM[0x2131] & (1 << i))2219{2220switch (i)2221{2222case 0:2223printf("BG0, ");2224break;22252226case 1:2227printf("BG1, ");2228break;22292230case 2:2231printf("BG2, ");2232break;22332234case 3:2235printf("BG3, ");2236break;22372238case 4:2239printf("OBJ, ");2240break;22412242case 5:2243printf("BACK, ");2244break;2245}2246}2247}22482249printf("\n");2250}22512252printf("Window 1 (%d, %d, %02x, %02x): ", PPU.Window1Left, PPU.Window1Right, Memory.FillRAM[0x212e], Memory.FillRAM[0x212f]);22532254for (int i = 0; i < 6; i++)2255{2256if (PPU.ClipWindow1Enable[i])2257{2258switch (i)2259{2260case 0:2261printf("BG0(%s-%s), ", PPU.ClipWindow1Inside[0] ? "I" : "O", debug_clip_fn(PPU.ClipWindowOverlapLogic[0]));2262break;22632264case 1:2265printf("BG1(%s-%s), ", PPU.ClipWindow1Inside[1] ? "I" : "O", debug_clip_fn(PPU.ClipWindowOverlapLogic[1]));2266break;22672268case 2:2269printf("BG2(%s-%s), ", PPU.ClipWindow1Inside[2] ? "I" : "O", debug_clip_fn(PPU.ClipWindowOverlapLogic[2]));2270break;22712272case 3:2273printf("BG3(%s-%s), ", PPU.ClipWindow1Inside[3] ? "I" : "O", debug_clip_fn(PPU.ClipWindowOverlapLogic[3]));2274break;22752276case 4:2277printf("OBJ(%s-%s), ", PPU.ClipWindow1Inside[4] ? "I" : "O", debug_clip_fn(PPU.ClipWindowOverlapLogic[4]));2278break;22792280case 5:2281printf("COL(%s-%s), ", PPU.ClipWindow1Inside[5] ? "I" : "O", debug_clip_fn(PPU.ClipWindowOverlapLogic[5]));2282break;2283}2284}2285}22862287printf("\n");22882289printf("Window 2 (%d, %d): ", PPU.Window2Left, PPU.Window2Right);22902291for (int i = 0; i < 6; i++)2292{2293if (PPU.ClipWindow2Enable[i])2294{2295switch (i)2296{2297case 0:2298printf("BG0(%s), ", PPU.ClipWindow2Inside[0] ? "I" : "O");2299break;23002301case 1:2302printf("BG1(%s), ", PPU.ClipWindow2Inside[1] ? "I" : "O");2303break;23042305case 2:2306printf("BG2(%s), ", PPU.ClipWindow2Inside[2] ? "I" : "O");2307break;23082309case 3:2310printf("BG3(%s), ", PPU.ClipWindow2Inside[3] ? "I" : "O");2311break;23122313case 4:2314printf("OBJ(%s), ", PPU.ClipWindow2Inside[4] ? "I" : "O");2315break;23162317case 5:2318printf("COL(%s), " , PPU.ClipWindow2Inside[5] ? "I" : "O");2319break;2320}2321}2322}23232324printf("\n");23252326printf("Fixed colour: %02x%02x%02x, \n", PPU.FixedColourRed, PPU.FixedColourGreen, PPU.FixedColourBlue);2327}23282329static void debug_whats_missing (void)2330{2331printf("Processor: ");23322333if (missing.emulate6502)2334printf("emulation mode, ");23352336if (missing.decimal_mode)2337printf("decimal mode, ");23382339if (missing.mv_8bit_index)2340printf("MVP/MVN with 8bit index registers and XH or YH > 0, ");23412342if (missing.mv_8bit_acc)2343printf("MVP/MVN with 8bit accumulator > 255, ");23442345printf("\n");23462347printf("Screen modes used: ");23482349for (int i = 0; i < 8; i++)2350if (missing.modes[i])2351printf("%d, ", i);23522353printf("\n");23542355if (missing.interlace)2356printf("Interlace, ");23572358if (missing.pseudo_512)2359printf("Pseudo 512 pixels horizontal resolution, ");23602361if (missing.lines_239)2362printf("240 lines visible, ");23632364if (missing.sprite_double_height)2365printf("double-hight sprites, ");23662367printf("\n");23682369if (missing.mode7_fx)2370printf("Mode 7 rotation/scaling, ");23712372if (missing.matrix_read)2373printf("Mode 7 read matrix registers, ");23742375if (missing.mode7_flip)2376printf("Mode 7 flipping, ");23772378if (missing.mode7_bgmode)2379printf("Mode 7 priority per pixel, ");23802381if (missing.direct)2382printf("Direct 32000 colour mode, ");23832384printf("\n");23852386if (missing.mosaic)2387printf("Mosaic effect, ");23882389if (missing.subscreen)2390printf("Subscreen enabled, ");23912392if (missing.subscreen_add)2393printf("Subscreen colour add, ");23942395if (missing.subscreen_sub)2396printf("Subscreen colour subtract, ");23972398if (missing.fixed_colour_add)2399printf("Fixed colour add, ");24002401if (missing.fixed_colour_sub)2402printf("Fixed colour subtract, ");24032404printf("\n");24052406printf("Window 1 enabled on: ");2407debug_print_window(missing.window1);24082409printf("\n");24102411printf("Window 2 enabled on: ");2412debug_print_window(missing.window2);24132414printf("\n");24152416if (missing.bg_offset_read)2417printf("BG offset read, ");24182419if (missing.oam_address_read)2420printf("OAM address read, ");24212422if (missing.sprite_priority_rotation)2423printf("Sprite priority rotation, ");24242425if (missing.fast_rom)2426printf("Fast 3.58MHz ROM access enabled, ");24272428if (missing.matrix_multiply)2429printf("Matrix multiply 16bit by 8bit used, ");24302431printf("\n");24322433if (missing.virq)2434printf("V-IRQ used at line %d, ", missing.virq_pos);24352436if (missing.hirq)2437printf("H-IRQ used at position %d, ", missing.hirq_pos);24382439printf("\n");24402441if (missing.h_v_latch)2442printf("H and V-Pos latched, ");24432444if (missing.h_counter_read)2445printf("H-Pos read, ");24462447if (missing.v_counter_read)2448printf("V-Pos read, ");24492450printf("\n");24512452if (missing.oam_read)2453printf("OAM read, ");24542455if (missing.vram_read)2456printf("VRAM read, ");24572458if (missing.cgram_read)2459printf("CG-RAM read, ");24602461if (missing.wram_read)2462printf("WRAM read, ");24632464if (missing.dma_read)2465printf("DMA read, ");24662467if (missing.vram_inc)2468printf("VRAM inc: %d, ", missing.vram_inc);24692470if (missing.vram_full_graphic_inc)2471printf("VRAM full graphic inc: %d, ", missing.vram_full_graphic_inc);24722473printf("\n");24742475for (int i = 0; i < 8; i++)2476{2477if (missing.hdma[i].used)2478{2479printf("HDMA %d 0x%02X%04X->0x21%02X %s, ",2480i, missing.hdma[i].abus_bank, missing.hdma[i].abus_address, missing.hdma[i].bbus_address,2481missing.hdma[i].indirect_address ? "indirect" : "absolute");24822483if (missing.hdma[i].force_table_address_write)2484printf("Forced address write, ");24852486if (missing.hdma[i].force_table_address_read)2487printf("Current address read, ");24882489if (missing.hdma[i].line_count_write)2490printf("Line count write, ");24912492if (missing.hdma[i].line_count_read)2493printf("Line count read, ");24942495printf("\n");2496}2497}24982499for (int i = 0; i < 8; i++)2500{2501if (missing.dma_channels & (1 << i))2502{2503printf("DMA %d [%d] 0x%02X%04X->0x21%02X Num: %d %s, \n",2504i, DMA[i].TransferMode, DMA[i].ABank, DMA[i].AAddress, DMA[i].BAddress, DMA[i].TransferBytes,2505DMA[i].AAddressFixed ? "fixed" : (DMA[i].AAddressDecrement ? "dec" : "inc"));2506}2507}25082509if (missing.unknownppu_read)2510printf("Read from unknown PPU register: $%04X, \n", missing.unknownppu_read);25112512if (missing.unknownppu_write)2513printf("Write to unknown PPU register: $%04X, \n", missing.unknownppu_write);25142515if (missing.unknowncpu_read)2516printf("Read from unknown CPU register: $%04X, \n", missing.unknowncpu_read);25172518if (missing.unknowncpu_write)2519printf("Write to unknown CPU register: $%04X, \n", missing.unknowncpu_write);25202521if (missing.unknowndsp_read)2522printf("Read from unknown DSP register: $%04X, \n", missing.unknowndsp_read);25232524if (missing.unknowndsp_write)2525printf("Write to unknown DSP register: $%04X, \n", missing.unknowndsp_write);2526}25272528void S9xDoDebug (void)2529{2530char Line[513];25312532Debug.Dump.Bank = 0;2533Debug.Dump.Address = 0;2534Debug.Unassemble.Bank = 0;2535Debug.Unassemble.Address = 0;25362537S9xTextMode();25382539strcpy(Line, "r");2540debug_process_command(Line);25412542while (CPU.Flags & DEBUG_MODE_FLAG)2543{2544int32 Cycles;2545char *p;25462547printf("> ");2548fflush(stdout);25492550p = fgets(Line, sizeof(Line) - 1, stdin);2551Line[strlen(Line) - 1] = 0;25522553Cycles = CPU.Cycles;2554debug_process_command(Line);2555CPU.Cycles = Cycles;2556}25572558if (!(CPU.Flags & SINGLE_STEP_FLAG))2559S9xGraphicsMode();2560}25612562void S9xTrace (void)2563{2564char msg[512];25652566ENSURE_TRACE_OPEN(trace, "trace.log", "a")25672568debug_cpu_op_print(msg, Registers.PB, Registers.PCw);2569fprintf(trace, "%s\n", msg);2570}25712572void S9xSA1Trace (void)2573{2574char msg[512];25752576ENSURE_TRACE_OPEN(trace2, "trace_sa1.log", "a")25772578debug_sa1_op_print(msg, SA1Registers.PB, SA1Registers.PCw);2579fprintf(trace2, "%s\n", msg);2580}25812582void S9xTraceMessage (const char *s)2583{2584if (s)2585{2586if (trace)2587fprintf(trace, "%s\n", s);2588else2589if (trace2)2590fprintf(trace2, "%s\n", s);2591}2592}25932594void S9xTraceFormattedMessage (const char *s, ...)2595{2596char msg[512];25972598if (s)2599{2600va_list argptr;26012602va_start(argptr, s);2603vsprintf(msg, s, argptr);2604va_end(argptr);26052606S9xTraceMessage(msg);2607}2608}26092610void S9xPrintHVPosition (char *s)2611{2612sprintf(s, "HC:%04ld VC:%03ld FC:%02d", (long) CPU.Cycles, (long) CPU.V_Counter, IPPU.FrameCount);2613}26142615#endif261626172618