Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
RishiRecon
GitHub Repository: RishiRecon/exploits
Path: blob/main/misc/emulator/xnes/snes9x/debug.cpp
28515 views
1
/***********************************************************************************
2
Snes9x - Portable Super Nintendo Entertainment System (TM) emulator.
3
4
(c) Copyright 1996 - 2002 Gary Henderson ([email protected]),
5
Jerremy Koot ([email protected])
6
7
(c) Copyright 2002 - 2004 Matthew Kendora
8
9
(c) Copyright 2002 - 2005 Peter Bortas ([email protected])
10
11
(c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/)
12
13
(c) Copyright 2001 - 2006 John Weidman ([email protected])
14
15
(c) Copyright 2002 - 2006 funkyass ([email protected]),
16
Kris Bleakley ([email protected])
17
18
(c) Copyright 2002 - 2010 Brad Jorsch ([email protected]),
19
Nach ([email protected]),
20
21
(c) Copyright 2002 - 2011 zones ([email protected])
22
23
(c) Copyright 2006 - 2007 nitsuja
24
25
(c) Copyright 2009 - 2011 BearOso,
26
OV2
27
28
29
BS-X C emulator code
30
(c) Copyright 2005 - 2006 Dreamer Nom,
31
zones
32
33
C4 x86 assembler and some C emulation code
34
(c) Copyright 2000 - 2003 _Demo_ ([email protected]),
35
Nach,
36
zsKnight ([email protected])
37
38
C4 C++ code
39
(c) Copyright 2003 - 2006 Brad Jorsch,
40
Nach
41
42
DSP-1 emulator code
43
(c) Copyright 1998 - 2006 _Demo_,
44
Andreas Naive ([email protected]),
45
Gary Henderson,
46
Ivar ([email protected]),
47
John Weidman,
48
Kris Bleakley,
49
Matthew Kendora,
50
Nach,
51
neviksti ([email protected])
52
53
DSP-2 emulator code
54
(c) Copyright 2003 John Weidman,
55
Kris Bleakley,
56
Lord Nightmare ([email protected]),
57
Matthew Kendora,
58
neviksti
59
60
DSP-3 emulator code
61
(c) Copyright 2003 - 2006 John Weidman,
62
Kris Bleakley,
63
Lancer,
64
z80 gaiden
65
66
DSP-4 emulator code
67
(c) Copyright 2004 - 2006 Dreamer Nom,
68
John Weidman,
69
Kris Bleakley,
70
Nach,
71
z80 gaiden
72
73
OBC1 emulator code
74
(c) Copyright 2001 - 2004 zsKnight,
75
pagefault ([email protected]),
76
Kris Bleakley
77
Ported from x86 assembler to C by sanmaiwashi
78
79
SPC7110 and RTC C++ emulator code used in 1.39-1.51
80
(c) Copyright 2002 Matthew Kendora with research by
81
zsKnight,
82
John Weidman,
83
Dark Force
84
85
SPC7110 and RTC C++ emulator code used in 1.52+
86
(c) Copyright 2009 byuu,
87
neviksti
88
89
S-DD1 C emulator code
90
(c) Copyright 2003 Brad Jorsch with research by
91
Andreas Naive,
92
John Weidman
93
94
S-RTC C emulator code
95
(c) Copyright 2001 - 2006 byuu,
96
John Weidman
97
98
ST010 C++ emulator code
99
(c) Copyright 2003 Feather,
100
John Weidman,
101
Kris Bleakley,
102
Matthew Kendora
103
104
Super FX x86 assembler emulator code
105
(c) Copyright 1998 - 2003 _Demo_,
106
pagefault,
107
zsKnight
108
109
Super FX C emulator code
110
(c) Copyright 1997 - 1999 Ivar,
111
Gary Henderson,
112
John Weidman
113
114
Sound emulator code used in 1.5-1.51
115
(c) Copyright 1998 - 2003 Brad Martin
116
(c) Copyright 1998 - 2006 Charles Bilyue'
117
118
Sound emulator code used in 1.52+
119
(c) Copyright 2004 - 2007 Shay Green ([email protected])
120
121
SH assembler code partly based on x86 assembler code
122
(c) Copyright 2002 - 2004 Marcus Comstedt ([email protected])
123
124
2xSaI filter
125
(c) Copyright 1999 - 2001 Derek Liauw Kie Fa
126
127
HQ2x, HQ3x, HQ4x filters
128
(c) Copyright 2003 Maxim Stepin ([email protected])
129
130
NTSC filter
131
(c) Copyright 2006 - 2007 Shay Green
132
133
GTK+ GUI code
134
(c) Copyright 2004 - 2011 BearOso
135
136
Win32 GUI code
137
(c) Copyright 2003 - 2006 blip,
138
funkyass,
139
Matthew Kendora,
140
Nach,
141
nitsuja
142
(c) Copyright 2009 - 2011 OV2
143
144
Mac OS GUI code
145
(c) Copyright 1998 - 2001 John Stiles
146
(c) Copyright 2001 - 2011 zones
147
148
149
Specific ports contains the works of other authors. See headers in
150
individual files.
151
152
153
Snes9x homepage: http://www.snes9x.com/
154
155
Permission to use, copy, modify and/or distribute Snes9x in both binary
156
and source form, for non-commercial purposes, is hereby granted without
157
fee, providing that this license information and copyright notice appear
158
with all copies and any derived work.
159
160
This software is provided 'as-is', without any express or implied
161
warranty. In no event shall the authors be held liable for any damages
162
arising from the use of this software or it's derivatives.
163
164
Snes9x is freeware for PERSONAL USE only. Commercial users should
165
seek permission of the copyright holders first. Commercial use includes,
166
but is not limited to, charging money for Snes9x or software derived from
167
Snes9x, including Snes9x or derivatives in commercial game bundles, and/or
168
using Snes9x as a promotion for your commercial product.
169
170
The copyright holders request that bug fixes and improvements to the code
171
should be forwarded to them so everyone can benefit from the modifications
172
in future versions.
173
174
Super NES and Super Nintendo Entertainment System are trademarks of
175
Nintendo Co., Limited and its subsidiary companies.
176
***********************************************************************************/
177
178
179
#ifdef DEBUGGER
180
181
#include <stdarg.h>
182
#include "snes9x.h"
183
#include "memmap.h"
184
#include "cpuops.h"
185
#include "dma.h"
186
#include "apu/apu.h"
187
#include "display.h"
188
#include "debug.h"
189
#include "missing.h"
190
191
extern SDMA DMA[8];
192
extern FILE *apu_trace;
193
FILE *trace = NULL, *trace2 = NULL;
194
195
struct SBreakPoint S9xBreakpoint[6];
196
197
struct SDebug
198
{
199
struct
200
{
201
uint8 Bank;
202
uint16 Address;
203
} Dump;
204
205
struct
206
{
207
uint8 Bank;
208
uint16 Address;
209
} Unassemble;
210
};
211
212
static struct SDebug Debug = { { 0, 0 }, { 0, 0 } };
213
214
static const char *HelpMessage[] =
215
{
216
"Command Help:",
217
"?, help - Shows this command help",
218
"r - Shows the registers",
219
"i - Shows the interrupt vectors",
220
"t - Trace current instruction [step-into]",
221
"p - Proceed to next instruction [step-over]",
222
"s - Skip to next instruction [skip]",
223
"T - Toggle CPU instruction tracing to trace.log",
224
"TS - Toggle SA-1 instruction tracing to trace_sa1.log",
225
"E - Toggle HC-based event tracing to trace.log",
226
"V - Toggle non-DMA V-RAM read/write tracing to stdout",
227
"D - Toggle on-screen DMA tracing",
228
"H - Toggle on-screen HDMA tracing",
229
"U - Toggle on-screen unknown register read/write tracing",
230
"P - Toggle on-screen DSP tracing",
231
"S - Dump sprite (OBJ) status",
232
"g [Address] - Go or go to [Address]",
233
"u [Address] - Disassemble from PC or [Address]",
234
"d [Address] - Dump from PC or [Address]",
235
"bv [Number] - View breakpoints or view breakpoint [Number]",
236
"bs [Number] [Address] - Enable/disable breakpoint",
237
" [enable example: bs #2 $02:8002]",
238
" [disable example: bs #2]",
239
"c - Dump SNES colour palette",
240
"W - Show what SNES hardware features the ROM is using",
241
" which might not be implemented yet",
242
"w - Show some SNES hardware features used so far in this frame",
243
"R - Reset SNES",
244
"q - Quit emulation",
245
// "ai - Shou APU vectors",
246
// "a - Show APU status",
247
// "x - Show Sound DSP status",
248
// "A - Toggle APU instruction tracing to aputrace.log",
249
// "B - Toggle sound DSP register tracing to aputrace.log",
250
// "C - Dump sound sample addresses",
251
// "ad [Address] - Dump APU RAM from PC or [Address]",
252
"",
253
"[Address] - $Bank:Address or $Address",
254
" [for example: $01:8123]",
255
"[Number] - #Number",
256
" [for example: #1]",
257
"z - ",
258
"f - ",
259
"dump - ",
260
"",
261
NULL
262
};
263
264
static const char *S9xMnemonics[256] =
265
{
266
"BRK", "ORA", "COP", "ORA", "TSB", "ORA", "ASL", "ORA",
267
"PHP", "ORA", "ASL", "PHD", "TSB", "ORA", "ASL", "ORA",
268
"BPL", "ORA", "ORA", "ORA", "TRB", "ORA", "ASL", "ORA",
269
"CLC", "ORA", "INC", "TCS", "TRB", "ORA", "ASL", "ORA",
270
"JSR", "AND", "JSL", "AND", "BIT", "AND", "ROL", "AND",
271
"PLP", "AND", "ROL", "PLD", "BIT", "AND", "ROL", "AND",
272
"BMI", "AND", "AND", "AND", "BIT", "AND", "ROL", "AND",
273
"SEC", "AND", "DEC", "TSC", "BIT", "AND", "ROL", "AND",
274
"RTI", "EOR", "WDM", "EOR", "MVP", "EOR", "LSR", "EOR",
275
"PHA", "EOR", "LSR", "PHK", "JMP", "EOR", "LSR", "EOR",
276
"BVC", "EOR", "EOR", "EOR", "MVN", "EOR", "LSR", "EOR",
277
"CLI", "EOR", "PHY", "TCD", "JMP", "EOR", "LSR", "EOR",
278
"RTS", "ADC", "PER", "ADC", "STZ", "ADC", "ROR", "ADC",
279
"PLA", "ADC", "ROR", "RTL", "JMP", "ADC", "ROR", "ADC",
280
"BVS", "ADC", "ADC", "ADC", "STZ", "ADC", "ROR", "ADC",
281
"SEI", "ADC", "PLY", "TDC", "JMP", "ADC", "ROR", "ADC",
282
"BRA", "STA", "BRL", "STA", "STY", "STA", "STX", "STA",
283
"DEY", "BIT", "TXA", "PHB", "STY", "STA", "STX", "STA",
284
"BCC", "STA", "STA", "STA", "STY", "STA", "STX", "STA",
285
"TYA", "STA", "TXS", "TXY", "STZ", "STA", "STZ", "STA",
286
"LDY", "LDA", "LDX", "LDA", "LDY", "LDA", "LDX", "LDA",
287
"TAY", "LDA", "TAX", "PLB", "LDY", "LDA", "LDX", "LDA",
288
"BCS", "LDA", "LDA", "LDA", "LDY", "LDA", "LDX", "LDA",
289
"CLV", "LDA", "TSX", "TYX", "LDY", "LDA", "LDX", "LDA",
290
"CPY", "CMP", "REP", "CMP", "CPY", "CMP", "DEC", "CMP",
291
"INY", "CMP", "DEX", "WAI", "CPY", "CMP", "DEC", "CMP",
292
"BNE", "CMP", "CMP", "CMP", "PEI", "CMP", "DEC", "CMP",
293
"CLD", "CMP", "PHX", "STP", "JML", "CMP", "DEC", "CMP",
294
"CPX", "SBC", "SEP", "SBC", "CPX", "SBC", "INC", "SBC",
295
"INX", "SBC", "NOP", "XBA", "CPX", "SBC", "INC", "SBC",
296
"BEQ", "SBC", "SBC", "SBC", "PEA", "SBC", "INC", "SBC",
297
"SED", "SBC", "PLX", "XCE", "JSR", "SBC", "INC", "SBC"
298
};
299
300
static int AddrModes[256] =
301
{
302
// 0 1 2 3 4 5 6 7 8 9 A B C D E F
303
3, 10, 3, 19, 6, 6, 6, 12, 0, 1, 24, 0, 14, 14, 14, 17, // 0
304
4, 11, 9, 20, 6, 7, 7, 13, 0, 16, 24, 0, 14, 15, 15, 18, // 1
305
14, 10, 17, 19, 6, 6, 6, 12, 0, 1, 24, 0, 14, 14, 14, 17, // 2
306
4, 11, 9, 20, 7, 7, 7, 13, 0, 16, 24, 0, 15, 15, 15, 18, // 3
307
0, 10, 3, 19, 25, 6, 6, 12, 0, 1, 24, 0, 14, 14, 14, 17, // 4
308
4, 11, 9, 20, 25, 7, 7, 13, 0, 16, 0, 0, 17, 15, 15, 18, // 5
309
0, 10, 5, 19, 6, 6, 6, 12, 0, 1, 24, 0, 21, 14, 14, 17, // 6
310
4, 11, 9, 20, 7, 7, 7, 13, 0, 16, 0, 0, 23, 15, 15, 18, // 7
311
4, 10, 5, 19, 6, 6, 6, 12, 0, 1, 0, 0, 14, 14, 14, 17, // 8
312
4, 11, 9, 20, 7, 7, 8, 13, 0, 16, 0, 0, 14, 15, 15, 18, // 9
313
2, 10, 2, 19, 6, 6, 6, 12, 0, 1, 0, 0, 14, 14, 14, 17, // A
314
4, 11, 9, 20, 7, 7, 8, 13, 0, 16, 0, 0, 15, 15, 16, 18, // B
315
2, 10, 3, 19, 6, 6, 6, 12, 0, 1, 0, 0, 14, 14, 14, 17, // C
316
4, 11, 9, 9, 27, 7, 7, 13, 0, 16, 0, 0, 22, 15, 15, 18, // D
317
2, 10, 3, 19, 6, 6, 6, 12, 0, 1, 0, 0, 14, 14, 14, 17, // E
318
4, 11, 9, 20, 26, 7, 7, 13, 0, 16, 0, 0, 23, 15, 15, 18 // F
319
};
320
321
static uint8 S9xDebugGetByte (uint32);
322
static uint16 S9xDebugGetWord (uint32);
323
static uint8 S9xDebugSA1GetByte (uint32);
324
static uint16 S9xDebugSA1GetWord (uint32);
325
static uint8 debug_cpu_op_print (char *, uint8, uint16);
326
static uint8 debug_sa1_op_print (char *, uint8, uint16);
327
static void debug_line_print (const char *);
328
static int debug_get_number (char *, uint16 *);
329
static short debug_get_start_address (char *, uint8 *, uint32 *);
330
static void debug_process_command (char *);
331
static void debug_print_window (uint8 *);
332
static const char * debug_clip_fn (int);
333
static void debug_whats_used (void);
334
static void debug_whats_missing (void);
335
336
337
static uint8 S9xDebugGetByte (uint32 Address)
338
{
339
int block = (Address & 0xffffff) >> MEMMAP_SHIFT;
340
uint8 *GetAddress = Memory.Map[block];
341
uint8 byte = 0;
342
343
if (GetAddress >= (uint8 *) CMemory::MAP_LAST)
344
{
345
byte = *(GetAddress + (Address & 0xffff));
346
return (byte);
347
}
348
349
switch ((pint) GetAddress)
350
{
351
case CMemory::MAP_LOROM_SRAM:
352
case CMemory::MAP_SA1RAM:
353
byte = *(Memory.SRAM + ((((Address & 0xff0000) >> 1) | (Address & 0x7fff)) & Memory.SRAMMask));
354
return (byte);
355
356
case CMemory::MAP_LOROM_SRAM_B:
357
byte = *(Multi.sramB + ((((Address & 0xff0000) >> 1) | (Address & 0x7fff)) & Multi.sramMaskB));
358
return (byte);
359
360
case CMemory::MAP_HIROM_SRAM:
361
case CMemory::MAP_RONLY_SRAM:
362
byte = *(Memory.SRAM + (((Address & 0x7fff) - 0x6000 + ((Address & 0xf0000) >> 3)) & Memory.SRAMMask));
363
return (byte);
364
365
case CMemory::MAP_BWRAM:
366
byte = *(Memory.BWRAM + ((Address & 0x7fff) - 0x6000));
367
return (byte);
368
369
default:
370
return (byte);
371
}
372
}
373
374
static uint16 S9xDebugGetWord (uint32 Address)
375
{
376
uint16 word;
377
378
word = S9xDebugGetByte(Address);
379
word |= S9xDebugGetByte(Address + 1) << 8;
380
381
return (word);
382
}
383
384
static uint8 S9xDebugSA1GetByte (uint32 Address)
385
{
386
int block = (Address & 0xffffff) >> MEMMAP_SHIFT;
387
uint8 *GetAddress = SA1.Map[block];
388
uint8 byte = 0;
389
390
if (GetAddress >= (uint8 *) CMemory::MAP_LAST)
391
{
392
byte = *(GetAddress + (Address & 0xffff));
393
return (byte);
394
}
395
396
switch ((pint) GetAddress)
397
{
398
case CMemory::MAP_LOROM_SRAM:
399
case CMemory::MAP_SA1RAM:
400
byte = *(Memory.SRAM + (Address & 0xffff));
401
return (byte);
402
403
case CMemory::MAP_BWRAM:
404
byte = *(SA1.BWRAM + ((Address & 0x7fff) - 0x6000));
405
return (byte);
406
407
case CMemory::MAP_BWRAM_BITMAP:
408
Address -= 0x600000;
409
if (SA1.VirtualBitmapFormat == 2)
410
byte = (Memory.SRAM[(Address >> 2) & 0xffff] >> ((Address & 3) << 1)) & 3;
411
else
412
byte = (Memory.SRAM[(Address >> 1) & 0xffff] >> ((Address & 1) << 2)) & 15;
413
return (byte);
414
415
case CMemory::MAP_BWRAM_BITMAP2:
416
Address = (Address & 0xffff) - 0x6000;
417
if (SA1.VirtualBitmapFormat == 2)
418
byte = (SA1.BWRAM[(Address >> 2) & 0xffff] >> ((Address & 3) << 1)) & 3;
419
else
420
byte = (SA1.BWRAM[(Address >> 1) & 0xffff] >> ((Address & 1) << 2)) & 15;
421
return (byte);
422
423
default:
424
return (byte);
425
}
426
}
427
428
static uint16 S9xDebugSA1GetWord (uint32 Address)
429
{
430
uint16 word;
431
432
word = S9xDebugSA1GetByte(Address);
433
word |= S9xDebugSA1GetByte(Address + 1) << 8;
434
435
return (word);
436
}
437
438
static uint8 debug_cpu_op_print (char *Line, uint8 Bank, uint16 Address)
439
{
440
uint8 S9xOpcode;
441
uint8 Operant[3];
442
uint16 Word;
443
uint8 Byte;
444
int16 SWord;
445
int8 SByte;
446
uint8 Size = 0;
447
448
S9xOpcode = S9xDebugGetByte((Bank << 16) + Address);
449
sprintf(Line, "$%02X:%04X %02X ", Bank, Address, S9xOpcode);
450
451
Operant[0] = S9xDebugGetByte((Bank << 16) + Address + 1);
452
Operant[1] = S9xDebugGetByte((Bank << 16) + Address + 2);
453
Operant[2] = S9xDebugGetByte((Bank << 16) + Address + 3);
454
455
switch (AddrModes[S9xOpcode])
456
{
457
case 0:
458
// Implied
459
sprintf(Line, "%s %s",
460
Line,
461
S9xMnemonics[S9xOpcode]);
462
Size = 1;
463
break;
464
465
case 1:
466
// Immediate[MemoryFlag]
467
if (!CheckFlag(MemoryFlag))
468
{
469
// Accumulator 16 - Bit
470
sprintf(Line, "%s%02X %02X %s #$%02X%02X",
471
Line,
472
Operant[0],
473
Operant[1],
474
S9xMnemonics[S9xOpcode],
475
Operant[1],
476
Operant[0]);
477
Size = 3;
478
}
479
else
480
{
481
// Accumulator 8 - Bit
482
sprintf(Line, "%s%02X %s #$%02X",
483
Line,
484
Operant[0],
485
S9xMnemonics[S9xOpcode],
486
Operant[0]);
487
Size = 2;
488
}
489
490
break;
491
492
case 2:
493
// Immediate[IndexFlag]
494
if (!CheckFlag(IndexFlag))
495
{
496
// X / Y 16 - Bit
497
sprintf(Line, "%s%02X %02X %s #$%02X%02X",
498
Line,
499
Operant[0],
500
Operant[1],
501
S9xMnemonics[S9xOpcode],
502
Operant[1],
503
Operant[0]);
504
Size = 3;
505
}
506
else
507
{
508
// X / Y 8 - Bit
509
sprintf(Line, "%s%02X %s #$%02X",
510
Line,
511
Operant[0],
512
S9xMnemonics[S9xOpcode],
513
Operant[0]);
514
Size = 2;
515
}
516
517
break;
518
519
case 3:
520
// Immediate[Always 8 - Bit]
521
sprintf(Line, "%s%02X %s #$%02X",
522
Line,
523
Operant[0],
524
S9xMnemonics[S9xOpcode],
525
Operant[0]);
526
Size = 2;
527
break;
528
529
case 4:
530
// Relative
531
sprintf(Line, "%s%02X %s $%02X",
532
Line,
533
Operant[0],
534
S9xMnemonics[S9xOpcode],
535
Operant[0]);
536
SByte = Operant[0];
537
Word = Address;
538
Word += SByte;
539
Word += 2;
540
sprintf(Line, "%-32s[$%04X]", Line, Word);
541
Size = 2;
542
break;
543
544
case 5:
545
// Relative Long
546
sprintf(Line, "%s%02X %02X %s $%02X%02X",
547
Line,
548
Operant[0],
549
Operant[1],
550
S9xMnemonics[S9xOpcode],
551
Operant[1],
552
Operant[0]);
553
SWord = (Operant[1] << 8) | Operant[0];
554
Word = Address;
555
Word += SWord;
556
Word += 3;
557
sprintf(Line, "%-32s[$%04X]", Line, Word);
558
Size = 3;
559
break;
560
561
case 6:
562
// Direct
563
sprintf(Line, "%s%02X %s $%02X",
564
Line,
565
Operant[0],
566
S9xMnemonics[S9xOpcode],
567
Operant[0]);
568
Word = Operant[0];
569
Word += Registers.D.W;
570
sprintf(Line, "%-32s[$00:%04X]", Line, Word);
571
Size = 2;
572
break;
573
574
case 7:
575
// Direct Indexed (with X)
576
sprintf(Line, "%s%02X %s $%02X,x",
577
Line,
578
Operant[0],
579
S9xMnemonics[S9xOpcode],
580
Operant[0]);
581
Word = Operant[0];
582
Word += Registers.D.W;
583
Word += Registers.X.W;
584
sprintf(Line, "%-32s[$00:%04X]", Line, Word);
585
Size = 2;
586
break;
587
588
case 8:
589
// Direct Indexed (with Y)
590
sprintf(Line, "%s%02X %s $%02X,y",
591
Line,
592
Operant[0],
593
S9xMnemonics[S9xOpcode],
594
Operant[0]);
595
Word = Operant[0];
596
Word += Registers.D.W;
597
Word += Registers.Y.W;
598
sprintf(Line, "%-32s[$00:%04X]", Line, Word);
599
Size = 2;
600
break;
601
602
case 9:
603
// Direct Indirect
604
sprintf(Line, "%s%02X %s ($%02X)",
605
Line,
606
Operant[0],
607
S9xMnemonics[S9xOpcode],
608
Operant[0]);
609
Word = Operant[0];
610
Word += Registers.D.W;
611
Word = S9xDebugGetWord(Word);
612
sprintf(Line, "%-32s[$%02X:%04X]", Line, Registers.DB, Word);
613
Size = 2;
614
break;
615
616
case 10:
617
// Direct Indexed Indirect
618
sprintf(Line, "%s%02X %s ($%02X,x)",
619
Line,
620
Operant[0],
621
S9xMnemonics[S9xOpcode],
622
Operant[0]);
623
Word = Operant[0];
624
Word += Registers.D.W;
625
Word += Registers.X.W;
626
Word = S9xDebugGetWord(Word);
627
sprintf(Line, "%-32s[$%02X:%04X]", Line, Registers.DB, Word);
628
Size = 2;
629
break;
630
631
case 11:
632
// Direct Indirect Indexed
633
sprintf(Line, "%s%02X %s ($%02X),y",
634
Line,
635
Operant[0],
636
S9xMnemonics[S9xOpcode],
637
Operant[0]);
638
Word = Operant[0];
639
Word += Registers.D.W;
640
Word = S9xDebugGetWord(Word);
641
Word += Registers.Y.W;
642
sprintf(Line, "%-32s[$%02X:%04X]", Line, Registers.DB, Word);
643
Size = 2;
644
break;
645
646
case 12:
647
// Direct Indirect Long
648
sprintf(Line, "%s%02X %s [$%02X]",
649
Line,
650
Operant[0],
651
S9xMnemonics[S9xOpcode],
652
Operant[0]);
653
Word = Operant[0];
654
Word += Registers.D.W;
655
Byte = S9xDebugGetByte(Word + 2);
656
Word = S9xDebugGetWord(Word);
657
sprintf(Line, "%-32s[$%02X:%04X]", Line, Byte, Word);
658
Size = 2;
659
break;
660
661
case 13:
662
// Direct Indirect Indexed Long
663
sprintf(Line, "%s%02X %s [$%02X],y",
664
Line,
665
Operant[0],
666
S9xMnemonics[S9xOpcode],
667
Operant[0]);
668
Word = Operant[0];
669
Word += Registers.D.W;
670
Byte = S9xDebugGetByte(Word + 2);
671
Word = S9xDebugGetWord(Word);
672
Word += Registers.Y.W;
673
sprintf(Line, "%-32s[$%02X:%04X]", Line, Byte, Word);
674
Size = 2;
675
break;
676
677
case 14:
678
// Absolute
679
sprintf(Line, "%s%02X %02X %s $%02X%02X",
680
Line,
681
Operant[0],
682
Operant[1],
683
S9xMnemonics[S9xOpcode],
684
Operant[1],
685
Operant[0]);
686
Word = (Operant[1] << 8) | Operant[0];
687
sprintf(Line, "%-32s[$%02X:%04X]", Line, Registers.DB, Word);
688
Size = 3;
689
break;
690
691
case 15:
692
// Absolute Indexed (with X)
693
sprintf(Line, "%s%02X %02X %s $%02X%02X,x",
694
Line,
695
Operant[0],
696
Operant[1],
697
S9xMnemonics[S9xOpcode],
698
Operant[1],
699
Operant[0]);
700
Word = (Operant[1] << 8) | Operant[0];
701
Word += Registers.X.W;
702
sprintf(Line, "%-32s[$%02X:%04X]", Line, Registers.DB, Word);
703
Size = 3;
704
break;
705
706
case 16:
707
// Absolute Indexed (with Y)
708
sprintf(Line, "%s%02X %02X %s $%02X%02X,y",
709
Line,
710
Operant[0],
711
Operant[1],
712
S9xMnemonics[S9xOpcode],
713
Operant[1],
714
Operant[0]);
715
Word = (Operant[1] << 8) | Operant[0];
716
Word += Registers.Y.W;
717
sprintf(Line, "%-32s[$%02X:%04X]", Line, Registers.DB, Word);
718
Size = 3;
719
break;
720
721
case 17:
722
// Absolute Long
723
sprintf(Line, "%s%02X %02X %02X %s $%02X%02X%02X",
724
Line,
725
Operant[0],
726
Operant[1],
727
Operant[2],
728
S9xMnemonics[S9xOpcode],
729
Operant[2],
730
Operant[1],
731
Operant[0]);
732
Word = (Operant[1] << 8) | Operant[0];
733
sprintf(Line, "%-32s[$%02X:%04X]", Line, Operant[2], Word);
734
Size = 4;
735
break;
736
737
case 18:
738
// Absolute Indexed Long
739
sprintf(Line, "%s%02X %02X %02X %s $%02X%02X%02X,x",
740
Line,
741
Operant[0],
742
Operant[1],
743
Operant[2],
744
S9xMnemonics[S9xOpcode],
745
Operant[2],
746
Operant[1],
747
Operant[0]);
748
Word = (Operant[1] << 8) | Operant[0];
749
Word += Registers.X.W;
750
sprintf(Line, "%-32s[$%02X:%04X]", Line, Operant[2], Word);
751
Size = 4;
752
break;
753
754
case 19:
755
// Stack Relative
756
sprintf(Line, "%s%02X %s $%02X,s",
757
Line,
758
Operant[0],
759
S9xMnemonics[S9xOpcode],
760
Operant[0]);
761
Word = Registers.S.W;
762
Word += Operant[0];
763
sprintf(Line, "%-32s[$00:%04X]", Line, Word);
764
Size = 2;
765
break;
766
767
case 20:
768
// Stack Relative Indirect Indexed
769
sprintf(Line, "%s%02X %s ($%02X,s),y",
770
Line,
771
Operant[0],
772
S9xMnemonics[S9xOpcode],
773
Operant[0]);
774
Word = Registers.S.W;
775
Word += Operant[0];
776
Word = S9xDebugGetWord(Word);
777
Word += Registers.Y.W;
778
sprintf(Line, "%-32s[$%02X:%04X]", Line, Registers.DB, Word);
779
Size = 2;
780
break;
781
782
case 21:
783
// Absolute Indirect
784
sprintf(Line, "%s%02X %02X %s ($%02X%02X)",
785
Line,
786
Operant[0],
787
Operant[1],
788
S9xMnemonics[S9xOpcode],
789
Operant[1],
790
Operant[0]);
791
Word = (Operant[1] << 8) | Operant[0];
792
Word = S9xDebugGetWord(Word);
793
sprintf(Line, "%-32s[$%02X:%04X]", Line, Registers.PB, Word);
794
Size = 3;
795
break;
796
797
case 22:
798
// Absolute Indirect Long
799
sprintf(Line, "%s%02X %02X %s [$%02X%02X]",
800
Line,
801
Operant[0],
802
Operant[1],
803
S9xMnemonics[S9xOpcode],
804
Operant[1],
805
Operant[0]);
806
Word = (Operant[1] << 8) | Operant[0];
807
Byte = S9xDebugGetByte(Word + 2);
808
Word = S9xDebugGetWord(Word);
809
sprintf(Line, "%-32s[$%02X:%04X]", Line, Byte, Word);
810
Size = 3;
811
break;
812
813
case 23:
814
// Absolute Indexed Indirect
815
sprintf(Line, "%s%02X %02X %s ($%02X%02X,x)",
816
Line,
817
Operant[0],
818
Operant[1],
819
S9xMnemonics[S9xOpcode],
820
Operant[1],
821
Operant[0]);
822
Word = (Operant[1] << 8) | Operant[0];
823
Word += Registers.X.W;
824
Word = S9xDebugGetWord(ICPU.ShiftedPB + Word);
825
sprintf(Line, "%-32s[$%02X:%04X]", Line, Registers.PB, Word);
826
Size = 3;
827
break;
828
829
case 24:
830
// Implied Accumulator
831
sprintf(Line, "%s %s A",
832
Line,
833
S9xMnemonics[S9xOpcode]);
834
Size = 1;
835
break;
836
837
case 25:
838
// MVN/MVP SRC DST
839
sprintf(Line, "%s%02X %02X %s %02X %02X",
840
Line,
841
Operant[0],
842
Operant[1],
843
S9xMnemonics[S9xOpcode],
844
Operant[1],
845
Operant[0]);
846
Size = 3;
847
break;
848
849
case 26:
850
// PEA
851
sprintf(Line, "%s%02X %02X %s $%02X%02X",
852
Line,
853
Operant[0],
854
Operant[1],
855
S9xMnemonics[S9xOpcode],
856
Operant[1],
857
Operant[0]);
858
Size = 3;
859
break;
860
861
case 27:
862
// PEI Direct Indirect
863
sprintf(Line, "%s%02X %s ($%02X)",
864
Line,
865
Operant[0],
866
S9xMnemonics[S9xOpcode],
867
Operant[0]);
868
Word = Operant[0];
869
Word += Registers.D.W;
870
Word = S9xDebugGetWord(Word);
871
sprintf(Line, "%-32s[$%04X]", Line, Word);
872
Size = 2;
873
break;
874
}
875
876
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:%04ld VC:%03ld FC:%02d %03x",
877
Line, Registers.A.W, Registers.X.W, Registers.Y.W,
878
Registers.D.W, Registers.DB, Registers.S.W,
879
CheckEmulation() ? 'E' : 'e',
880
CheckNegative() ? 'N' : 'n',
881
CheckOverflow() ? 'V' : 'v',
882
CheckMemory() ? 'M' : 'm',
883
CheckIndex() ? 'X' : 'x',
884
CheckDecimal() ? 'D' : 'd',
885
CheckIRQ() ? 'I' : 'i',
886
CheckZero() ? 'Z' : 'z',
887
CheckCarry() ? 'C' : 'c',
888
(long) CPU.Cycles,
889
(long) CPU.V_Counter,
890
IPPU.FrameCount,
891
(CPU.IRQExternal ? 0x100 : 0) | (PPU.HTimerEnabled ? 0x10 : 0) | (PPU.VTimerEnabled ? 0x01 : 0));
892
893
return (Size);
894
}
895
896
static uint8 debug_sa1_op_print (char *Line, uint8 Bank, uint16 Address)
897
{
898
uint8 S9xOpcode;
899
uint8 Operant[3];
900
uint16 Word;
901
uint8 Byte;
902
int16 SWord;
903
int8 SByte;
904
uint8 Size = 0;
905
906
S9xOpcode = S9xDebugSA1GetByte((Bank << 16) + Address);
907
sprintf(Line, "$%02X:%04X %02X ", Bank, Address, S9xOpcode);
908
909
Operant[0] = S9xDebugSA1GetByte((Bank << 16) + Address + 1);
910
Operant[1] = S9xDebugSA1GetByte((Bank << 16) + Address + 2);
911
Operant[2] = S9xDebugSA1GetByte((Bank << 16) + Address + 3);
912
913
switch (AddrModes[S9xOpcode])
914
{
915
case 0:
916
// Implied
917
sprintf(Line, "%s %s",
918
Line,
919
S9xMnemonics[S9xOpcode]);
920
Size = 1;
921
break;
922
923
case 1:
924
// Immediate[MemoryFlag]
925
if (!SA1CheckFlag(MemoryFlag))
926
{
927
// Accumulator 16 - Bit
928
sprintf(Line, "%s%02X %02X %s #$%02X%02X",
929
Line,
930
Operant[0],
931
Operant[1],
932
S9xMnemonics[S9xOpcode],
933
Operant[1],
934
Operant[0]);
935
Size = 3;
936
}
937
else
938
{
939
// Accumulator 8 - Bit
940
sprintf(Line, "%s%02X %s #$%02X",
941
Line,
942
Operant[0],
943
S9xMnemonics[S9xOpcode],
944
Operant[0]);
945
Size = 2;
946
}
947
948
break;
949
950
case 2:
951
// Immediate[IndexFlag]
952
if (!SA1CheckFlag(IndexFlag))
953
{
954
// X / Y 16 - Bit
955
sprintf(Line, "%s%02X %02X %s #$%02X%02X",
956
Line,
957
Operant[0],
958
Operant[1],
959
S9xMnemonics[S9xOpcode],
960
Operant[1],
961
Operant[0]);
962
Size = 3;
963
}
964
else
965
{
966
// X / Y 8 - Bit
967
sprintf(Line, "%s%02X %s #$%02X",
968
Line,
969
Operant[0],
970
S9xMnemonics[S9xOpcode],
971
Operant[0]);
972
Size = 2;
973
}
974
975
break;
976
977
case 3:
978
// Immediate[Always 8 - Bit]
979
sprintf(Line, "%s%02X %s #$%02X",
980
Line,
981
Operant[0],
982
S9xMnemonics[S9xOpcode],
983
Operant[0]);
984
Size = 2;
985
break;
986
987
case 4:
988
// Relative
989
sprintf(Line, "%s%02X %s $%02X",
990
Line,
991
Operant[0],
992
S9xMnemonics[S9xOpcode],
993
Operant[0]);
994
SByte = Operant[0];
995
Word = Address;
996
Word += SByte;
997
Word += 2;
998
sprintf(Line, "%-32s[$%04X]", Line, Word);
999
Size = 2;
1000
break;
1001
1002
case 5:
1003
// Relative Long
1004
sprintf(Line, "%s%02X %02X %s $%02X%02X",
1005
Line,
1006
Operant[0],
1007
Operant[1],
1008
S9xMnemonics[S9xOpcode],
1009
Operant[1],
1010
Operant[0]);
1011
SWord = (Operant[1] << 8) | Operant[0];
1012
Word = Address;
1013
Word += SWord;
1014
Word += 3;
1015
sprintf(Line, "%-32s[$%04X]", Line, Word);
1016
Size = 3;
1017
break;
1018
1019
case 6:
1020
// Direct
1021
sprintf(Line, "%s%02X %s $%02X",
1022
Line,
1023
Operant[0],
1024
S9xMnemonics[S9xOpcode],
1025
Operant[0]);
1026
Word = Operant[0];
1027
Word += SA1Registers.D.W;
1028
sprintf(Line, "%-32s[$00:%04X]", Line, Word);
1029
Size = 2;
1030
break;
1031
1032
case 7:
1033
// Direct Indexed (with X)
1034
sprintf(Line, "%s%02X %s $%02X,x",
1035
Line,
1036
Operant[0],
1037
S9xMnemonics[S9xOpcode],
1038
Operant[0]);
1039
Word = Operant[0];
1040
Word += SA1Registers.D.W;
1041
Word += SA1Registers.X.W;
1042
sprintf(Line, "%-32s[$00:%04X]", Line, Word);
1043
Size = 2;
1044
break;
1045
1046
case 8:
1047
// Direct Indexed (with Y)
1048
sprintf(Line, "%s%02X %s $%02X,y",
1049
Line,
1050
Operant[0],
1051
S9xMnemonics[S9xOpcode],
1052
Operant[0]);
1053
Word = Operant[0];
1054
Word += SA1Registers.D.W;
1055
Word += SA1Registers.Y.W;
1056
sprintf(Line, "%-32s[$00:%04X]", Line, Word);
1057
Size = 2;
1058
break;
1059
1060
case 9:
1061
// Direct Indirect
1062
sprintf(Line, "%s%02X %s ($%02X)",
1063
Line,
1064
Operant[0],
1065
S9xMnemonics[S9xOpcode],
1066
Operant[0]);
1067
Word = Operant[0];
1068
Word += SA1Registers.D.W;
1069
Word = S9xDebugSA1GetWord(Word);
1070
sprintf(Line, "%-32s[$%02X:%04X]", Line, SA1Registers.DB, Word);
1071
Size = 2;
1072
break;
1073
1074
case 10:
1075
// Direct Indexed Indirect
1076
sprintf(Line, "%s%02X %s ($%02X,x)",
1077
Line,
1078
Operant[0],
1079
S9xMnemonics[S9xOpcode],
1080
Operant[0]);
1081
Word = Operant[0];
1082
Word += SA1Registers.D.W;
1083
Word += SA1Registers.X.W;
1084
Word = S9xDebugSA1GetWord(Word);
1085
sprintf(Line, "%-32s[$%02X:%04X]", Line, SA1Registers.DB, Word);
1086
Size = 2;
1087
break;
1088
1089
case 11:
1090
// Direct Indirect Indexed
1091
sprintf(Line, "%s%02X %s ($%02X),y",
1092
Line,
1093
Operant[0],
1094
S9xMnemonics[S9xOpcode],
1095
Operant[0]);
1096
Word = Operant[0];
1097
Word += SA1Registers.D.W;
1098
Word = S9xDebugSA1GetWord(Word);
1099
Word += SA1Registers.Y.W;
1100
sprintf(Line, "%-32s[$%02X:%04X]", Line, SA1Registers.DB, Word);
1101
Size = 2;
1102
break;
1103
1104
case 12:
1105
// Direct Indirect Long
1106
sprintf(Line, "%s%02X %s [$%02X]",
1107
Line,
1108
Operant[0],
1109
S9xMnemonics[S9xOpcode],
1110
Operant[0]);
1111
Word = Operant[0];
1112
Word += SA1Registers.D.W;
1113
Byte = S9xDebugSA1GetByte(Word + 2);
1114
Word = S9xDebugSA1GetWord(Word);
1115
sprintf(Line, "%-32s[$%02X:%04X]", Line, Byte, Word);
1116
Size = 2;
1117
break;
1118
1119
case 13:
1120
// Direct Indirect Indexed Long
1121
sprintf(Line, "%s%02X %s [$%02X],y",
1122
Line,
1123
Operant[0],
1124
S9xMnemonics[S9xOpcode],
1125
Operant[0]);
1126
Word = Operant[0];
1127
Word += SA1Registers.D.W;
1128
Byte = S9xDebugSA1GetByte(Word + 2);
1129
Word = S9xDebugSA1GetWord(Word);
1130
Word += SA1Registers.Y.W;
1131
sprintf(Line, "%-32s[$%02X:%04X]", Line, Byte, Word);
1132
Size = 2;
1133
break;
1134
1135
case 14:
1136
// Absolute
1137
sprintf(Line, "%s%02X %02X %s $%02X%02X",
1138
Line,
1139
Operant[0],
1140
Operant[1],
1141
S9xMnemonics[S9xOpcode],
1142
Operant[1],
1143
Operant[0]);
1144
Word = (Operant[1] << 8) | Operant[0];
1145
sprintf(Line, "%-32s[$%02X:%04X]", Line, SA1Registers.DB, Word);
1146
Size = 3;
1147
break;
1148
1149
case 15:
1150
// Absolute Indexed (with X)
1151
sprintf(Line, "%s%02X %02X %s $%02X%02X,x",
1152
Line,
1153
Operant[0],
1154
Operant[1],
1155
S9xMnemonics[S9xOpcode],
1156
Operant[1],
1157
Operant[0]);
1158
Word = (Operant[1] << 8) | Operant[0];
1159
Word += SA1Registers.X.W;
1160
sprintf(Line, "%-32s[$%02X:%04X]", Line, SA1Registers.DB, Word);
1161
Size = 3;
1162
break;
1163
1164
case 16:
1165
// Absolute Indexed (with Y)
1166
sprintf(Line, "%s%02X %02X %s $%02X%02X,y",
1167
Line,
1168
Operant[0],
1169
Operant[1],
1170
S9xMnemonics[S9xOpcode],
1171
Operant[1],
1172
Operant[0]);
1173
Word = (Operant[1] << 8) | Operant[0];
1174
Word += SA1Registers.Y.W;
1175
sprintf(Line, "%-32s[$%02X:%04X]", Line, SA1Registers.DB, Word);
1176
Size = 3;
1177
break;
1178
1179
case 17:
1180
// Absolute Long
1181
sprintf(Line, "%s%02X %02X %02X %s $%02X%02X%02X",
1182
Line,
1183
Operant[0],
1184
Operant[1],
1185
Operant[2],
1186
S9xMnemonics[S9xOpcode],
1187
Operant[2],
1188
Operant[1],
1189
Operant[0]);
1190
Word = (Operant[1] << 8) | Operant[0];
1191
sprintf(Line, "%-32s[$%02X:%04X]", Line, Operant[2], Word);
1192
Size = 4;
1193
break;
1194
1195
case 18:
1196
// Absolute Indexed Long
1197
sprintf(Line, "%s%02X %02X %02X %s $%02X%02X%02X,x",
1198
Line,
1199
Operant[0],
1200
Operant[1],
1201
Operant[2],
1202
S9xMnemonics[S9xOpcode],
1203
Operant[2],
1204
Operant[1],
1205
Operant[0]);
1206
Word = (Operant[1] << 8) | Operant[0];
1207
Word += SA1Registers.X.W;
1208
sprintf(Line, "%-32s[$%02X:%04X]", Line, Operant[2], Word);
1209
Size = 4;
1210
break;
1211
1212
case 19:
1213
// Stack Relative
1214
sprintf(Line, "%s%02X %s $%02X,s",
1215
Line,
1216
Operant[0],
1217
S9xMnemonics[S9xOpcode],
1218
Operant[0]);
1219
Word = SA1Registers.S.W;
1220
Word += Operant[0];
1221
sprintf(Line, "%-32s[$00:%04X]", Line, Word);
1222
Size = 2;
1223
break;
1224
1225
case 20:
1226
// Stack Relative Indirect Indexed
1227
sprintf(Line, "%s%02X %s ($%02X,s),y",
1228
Line,
1229
Operant[0],
1230
S9xMnemonics[S9xOpcode],
1231
Operant[0]);
1232
Word = SA1Registers.S.W;
1233
Word += Operant[0];
1234
Word = S9xDebugSA1GetWord(Word);
1235
Word += SA1Registers.Y.W;
1236
sprintf(Line, "%-32s[$%02X:%04X]", Line, SA1Registers.DB, Word);
1237
Size = 2;
1238
break;
1239
1240
case 21:
1241
// Absolute Indirect
1242
sprintf(Line, "%s%02X %02X %s ($%02X%02X)",
1243
Line,
1244
Operant[0],
1245
Operant[1],
1246
S9xMnemonics[S9xOpcode],
1247
Operant[1],
1248
Operant[0]);
1249
Word = (Operant[1] << 8) | Operant[0];
1250
Word = S9xDebugSA1GetWord(Word);
1251
sprintf(Line, "%-32s[$%02X:%04X]", Line, SA1Registers.PB, Word);
1252
Size = 3;
1253
break;
1254
1255
case 22:
1256
// Absolute Indirect Long
1257
sprintf(Line, "%s%02X %02X %s [$%02X%02X]",
1258
Line,
1259
Operant[0],
1260
Operant[1],
1261
S9xMnemonics[S9xOpcode],
1262
Operant[1],
1263
Operant[0]);
1264
Word = (Operant[1] << 8) | Operant[0];
1265
Byte = S9xDebugSA1GetByte(Word + 2);
1266
Word = S9xDebugSA1GetWord(Word);
1267
sprintf(Line, "%-32s[$%02X:%04X]", Line, Byte, Word);
1268
Size = 3;
1269
break;
1270
1271
case 23:
1272
// Absolute Indexed Indirect
1273
sprintf(Line, "%s%02X %02X %s ($%02X%02X,x)",
1274
Line,
1275
Operant[0],
1276
Operant[1],
1277
S9xMnemonics[S9xOpcode],
1278
Operant[1],
1279
Operant[0]);
1280
Word = (Operant[1] << 8) | Operant[0];
1281
Word += SA1Registers.X.W;
1282
Word = S9xDebugSA1GetWord(SA1.ShiftedPB + Word);
1283
sprintf(Line, "%-32s[$%02X:%04X]", Line, SA1Registers.PB, Word);
1284
Size = 3;
1285
break;
1286
1287
case 24:
1288
// Implied Accumulator
1289
sprintf(Line, "%s %s A",
1290
Line,
1291
S9xMnemonics[S9xOpcode]);
1292
Size = 1;
1293
break;
1294
1295
case 25:
1296
// MVN/MVP SRC DST
1297
sprintf(Line, "%s %s %02X %02X",
1298
Line,
1299
S9xMnemonics[S9xOpcode],
1300
Operant[0],
1301
Operant[1]);
1302
Size = 3;
1303
break;
1304
}
1305
1306
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:%04ld VC:%03ld FC:%02d",
1307
Line, SA1Registers.A.W, SA1Registers.X.W, SA1Registers.Y.W,
1308
SA1Registers.D.W, SA1Registers.DB, SA1Registers.S.W,
1309
SA1CheckEmulation() ? 'E' : 'e',
1310
SA1CheckNegative() ? 'N' : 'n',
1311
SA1CheckOverflow() ? 'V' : 'v',
1312
SA1CheckMemory() ? 'M' : 'm',
1313
SA1CheckIndex() ? 'X' : 'x',
1314
SA1CheckDecimal() ? 'D' : 'd',
1315
SA1CheckIRQ() ? 'I' : 'i',
1316
SA1CheckZero() ? 'Z' : 'z',
1317
SA1CheckCarry() ? 'C' : 'c',
1318
(long) CPU.Cycles,
1319
(long) CPU.V_Counter,
1320
IPPU.FrameCount);
1321
1322
return (Size);
1323
}
1324
1325
static void debug_line_print (const char *Line)
1326
{
1327
printf("%s\n", Line);
1328
}
1329
1330
static int debug_get_number (char *Line, uint16 *Number)
1331
{
1332
int i;
1333
1334
if (sscanf(Line, " #%d", &i) == 1)
1335
{
1336
*Number = i;
1337
return (1);
1338
}
1339
1340
return (-1);
1341
}
1342
1343
static short debug_get_start_address (char *Line, uint8 *Bank, uint32 *Address)
1344
{
1345
uint32 a, b;
1346
1347
if (sscanf(Line + 1, " $%x:%x", &b, &a) != 2)
1348
return (-1);
1349
1350
*Bank = b;
1351
*Address = a;
1352
1353
return (1);
1354
}
1355
1356
static void debug_process_command (char *Line)
1357
{
1358
uint8 Bank = Registers.PB;
1359
uint32 Address = Registers.PCw;
1360
uint16 Hold = 0;
1361
uint16 Number;
1362
short ErrorCode;
1363
char string[512];
1364
1365
if (strncasecmp(Line, "dump", 4) == 0)
1366
{
1367
int Count;
1368
1369
if (sscanf(&Line[4], "%x %d", &Address, &Count) == 2)
1370
{
1371
FILE *fs;
1372
1373
sprintf(string, "%06x%05d.sd2", Address, Count);
1374
fs = fopen(string, "wb");
1375
if (fs)
1376
{
1377
for (int i = 0; i < Count; i++)
1378
putc(S9xDebugGetByte(Address + i), fs);
1379
fclose(fs);
1380
}
1381
else
1382
printf("Can't open %s for writing\n", string);
1383
}
1384
else
1385
printf("Usage: dump start_address_in_hex count_in_decimal\n");
1386
1387
return;
1388
}
1389
1390
if (*Line == 'i')
1391
{
1392
printf("Vectors:\n");
1393
sprintf(string, " 8 Bit 16 Bit ");
1394
debug_line_print(string);
1395
sprintf(string, "ABT $00:%04X|$00:%04X", S9xDebugGetWord(0xFFF8), S9xDebugGetWord(0xFFE8));
1396
debug_line_print(string);
1397
sprintf(string, "BRK $00:%04X|$00:%04X", S9xDebugGetWord(0xFFFE), S9xDebugGetWord(0xFFE6));
1398
debug_line_print(string);
1399
sprintf(string, "COP $00:%04X|$00:%04X", S9xDebugGetWord(0xFFF4), S9xDebugGetWord(0xFFE4));
1400
debug_line_print(string);
1401
sprintf(string, "IRQ $00:%04X|$00:%04X", S9xDebugGetWord(0xFFFE), S9xDebugGetWord(0xFFEE));
1402
debug_line_print(string);
1403
sprintf(string, "NMI $00:%04X|$00:%04X", S9xDebugGetWord(0xFFFA), S9xDebugGetWord(0xFFEA));
1404
debug_line_print(string);
1405
sprintf(string, "RES $00:%04X", S9xDebugGetWord(0xFFFC));
1406
debug_line_print(string);
1407
}
1408
1409
/*
1410
if (strncmp(Line, "ai", 2) == 0)
1411
{
1412
printf("APU vectors:");
1413
1414
for (int i = 0; i < 0x40; i += 2)
1415
{
1416
if (i % 16 == 0)
1417
printf("\n%04x ", 0xffc0 + i);
1418
1419
printf("%04x ", APU.ExtraRAM[i]);
1420
}
1421
1422
printf("\n");
1423
}
1424
*/
1425
1426
if (*Line == 's')
1427
{
1428
Registers.PCw += debug_cpu_op_print(string, Bank, Address);
1429
Bank = Registers.PB;
1430
Address = Registers.PCw;
1431
*Line = 'r';
1432
}
1433
1434
if (*Line == 'z')
1435
{
1436
uint16 *p = (uint16 *) &Memory.VRAM[PPU.BG[2].SCBase << 1];
1437
1438
for (int l = 0; l < 32; l++)
1439
{
1440
for (int c = 0; c < 32; c++, p++)
1441
printf("%04x,", *p++);
1442
1443
printf("\n");
1444
}
1445
}
1446
1447
if (*Line == 'c')
1448
{
1449
printf("Colours:\n");
1450
1451
for (int i = 0; i < 256; i++)
1452
printf("%02x%02x%02x ", PPU.CGDATA[i] & 0x1f, (PPU.CGDATA[i] >> 5) & 0x1f, (PPU.CGDATA[i] >> 10) & 0x1f);
1453
1454
printf("\n");
1455
}
1456
1457
if (*Line == 'S')
1458
{
1459
int SmallWidth, LargeWidth, SmallHeight, LargeHeight;
1460
1461
switch ((Memory.FillRAM[0x2101] >> 5) & 7)
1462
{
1463
1464
case 0:
1465
SmallWidth = SmallHeight = 8;
1466
LargeWidth = LargeHeight = 16;
1467
break;
1468
1469
case 1:
1470
SmallWidth = SmallHeight = 8;
1471
LargeWidth = LargeHeight = 32;
1472
break;
1473
1474
case 2:
1475
SmallWidth = SmallHeight = 8;
1476
LargeWidth = LargeHeight = 64;
1477
break;
1478
1479
case 3:
1480
SmallWidth = SmallHeight = 16;
1481
LargeWidth = LargeHeight = 32;
1482
break;
1483
1484
case 4:
1485
SmallWidth = SmallHeight = 16;
1486
LargeWidth = LargeHeight = 64;
1487
break;
1488
1489
default:
1490
case 5:
1491
SmallWidth = SmallHeight = 32;
1492
LargeWidth = LargeHeight = 64;
1493
break;
1494
1495
case 6:
1496
SmallWidth = 16;
1497
SmallHeight = 32;
1498
LargeWidth = 32;
1499
LargeHeight = 64;
1500
break;
1501
1502
case 7:
1503
SmallWidth = 16;
1504
SmallHeight = 32;
1505
LargeWidth = LargeHeight = 32;
1506
break;
1507
}
1508
1509
printf("Sprites: Small: %dx%d, Large: %dx%d, OAMAddr: 0x%04x, OBJNameBase: 0x%04x, OBJNameSelect: 0x%04x, First: %d\n",
1510
SmallWidth, SmallHeight, LargeWidth, LargeHeight, PPU.OAMAddr, PPU.OBJNameBase, PPU.OBJNameSelect, PPU.FirstSprite);
1511
1512
for (int i = 0; i < 128; i++)
1513
{
1514
printf("X:%3d Y:%3d %c%c%d%c ",
1515
PPU.OBJ[i].HPos,
1516
PPU.OBJ[i].VPos,
1517
PPU.OBJ[i].VFlip ? 'V' : 'v',
1518
PPU.OBJ[i].HFlip ? 'H' : 'h',
1519
PPU.OBJ[i].Priority,
1520
PPU.OBJ[i].Size ? 'S' : 's');
1521
1522
if (i % 4 == 3)
1523
printf("\n");
1524
}
1525
}
1526
1527
if (*Line == 'T')
1528
{
1529
if (Line[1] == 'S')
1530
{
1531
SA1.Flags ^= TRACE_FLAG;
1532
1533
if (SA1.Flags & TRACE_FLAG)
1534
{
1535
printf("SA1 CPU instruction tracing enabled.\n");
1536
ENSURE_TRACE_OPEN(trace2, "trace_sa1.log", "wb")
1537
}
1538
else
1539
{
1540
printf("SA1 CPU instruction tracing disabled.\n");
1541
fclose(trace2);
1542
trace2 = NULL;
1543
}
1544
}
1545
else
1546
{
1547
CPU.Flags ^= TRACE_FLAG;
1548
1549
if (CPU.Flags & TRACE_FLAG)
1550
{
1551
printf("CPU instruction tracing enabled.\n");
1552
ENSURE_TRACE_OPEN(trace, "trace.log", "wb")
1553
}
1554
else
1555
{
1556
printf("CPU instruction tracing disabled.\n");
1557
fclose(trace);
1558
trace = NULL;
1559
}
1560
}
1561
}
1562
1563
if (*Line == 'E')
1564
{
1565
Settings.TraceHCEvent = !Settings.TraceHCEvent;
1566
printf("HC event tracing %s.\n", Settings.TraceHCEvent ? "enabled" : "disabled");
1567
}
1568
1569
if (*Line == 'A')
1570
spc_core->debug_toggle_trace();
1571
1572
/*
1573
if (*Line == 'B')
1574
{
1575
Settings.TraceSoundDSP = !Settings.TraceSoundDSP;
1576
printf("Sound DSP register tracing %s.\n", Settings.TraceSoundDSP ? "enabled" : "disabled");
1577
}
1578
1579
if (*Line == 'x')
1580
S9xPrintSoundDSPState();
1581
1582
if (*Line == 'C')
1583
{
1584
printf("SPC700 sample addresses at 0x%04x:\n", APU.DSP[APU_DIR] << 8);
1585
1586
for (int i = 0; i < 256; i++)
1587
{
1588
uint8 *dir = IAPU.RAM + (((APU.DSP[APU_DIR] << 8) + i * 4) & 0xffff);
1589
int addr = *dir + (*(dir + 1) << 8);
1590
int addr2 = *(dir + 2) + (*(dir + 3) << 8);
1591
printf("%04X %04X;", addr, addr2);
1592
1593
if (i % 8 == 7)
1594
printf("\n");
1595
}
1596
}
1597
*/
1598
1599
if (*Line == 'R')
1600
{
1601
S9xReset();
1602
printf("SNES reset.\n");
1603
CPU.Flags |= DEBUG_MODE_FLAG;
1604
}
1605
1606
/*
1607
if (strncmp(Line, "ad", 2) == 0)
1608
{
1609
uint32 Count = 16;
1610
Address = 0;
1611
1612
if (sscanf(Line + 2, "%x,%x", &Address, &Count) != 2)
1613
{
1614
if (sscanf(Line + 2, "%x", &Address) == 1)
1615
Count = 16;
1616
}
1617
1618
printf("APU RAM dump:\n");
1619
1620
for (uint32 l = 0; l < Count; l += 16)
1621
{
1622
printf("%04X ", Address);
1623
1624
for (int i = 0; i < 16; i++)
1625
printf("%02X ", IAPU.RAM[Address++]);
1626
1627
printf("\n");
1628
}
1629
1630
*Line = 0;
1631
}
1632
1633
if (*Line == 'a')
1634
{
1635
printf("APU in-ports : %02X %02X %02X %02X\n", IAPU.RAM[0xF4], IAPU.RAM[0xF5], IAPU.RAM[0xF6], IAPU.RAM[0xF7]);
1636
printf("APU out-ports: %02X %02X %02X %02X\n", APU.OutPorts[0], APU.OutPorts[1], APU.OutPorts[2], APU.OutPorts[3]);
1637
printf("ROM/RAM switch: %s\n", (IAPU.RAM[0xf1] & 0x80) ? "ROM" : "RAM");
1638
1639
for (int i = 0; i < 3; i++)
1640
if (APU.TimerEnabled[i])
1641
printf("Timer%d enabled, Value: 0x%03X, 4-bit: 0x%02X, Target: 0x%03X\n",
1642
i, APU.Timer[i], IAPU.RAM[0xfd + i], APU.TimerTarget[i]);
1643
}
1644
1645
if (*Line == 'P')
1646
{
1647
Settings.TraceDSP = !Settings.TraceDSP;
1648
printf("DSP tracing %s.\n", Settings.TraceDSP ? "enabled" : "disabled");
1649
}
1650
*/
1651
1652
if (*Line == 'p')
1653
{
1654
S9xBreakpoint[5].Enabled = FALSE;
1655
Address += debug_cpu_op_print(string, Bank, Address);
1656
1657
if (strncmp(&string[18], "JMP", 3) != 0 &&
1658
strncmp(&string[18], "JML", 3) != 0 &&
1659
strncmp(&string[18], "RT" , 2) != 0 &&
1660
strncmp(&string[18], "BRA", 3))
1661
{
1662
S9xBreakpoint[5].Enabled = TRUE;
1663
S9xBreakpoint[5].Bank = Bank;
1664
S9xBreakpoint[5].Address = Address;
1665
}
1666
else
1667
{
1668
CPU.Flags |= SINGLE_STEP_FLAG;
1669
CPU.Flags &= ~DEBUG_MODE_FLAG;
1670
}
1671
}
1672
1673
if (*Line == 'b')
1674
{
1675
if (Line[1] == 's')
1676
{
1677
debug_get_number(Line + 2, &Hold);
1678
1679
if (Hold > 4)
1680
Hold = 0;
1681
1682
if (Hold < 5)
1683
{
1684
if (debug_get_start_address(Line + 5, &Bank, &Address) == -1)
1685
S9xBreakpoint[Hold].Enabled = FALSE;
1686
else
1687
{
1688
S9xBreakpoint[Hold].Enabled = TRUE;
1689
S9xBreakpoint[Hold].Bank = Bank;
1690
S9xBreakpoint[Hold].Address = Address;
1691
CPU.Flags |= BREAK_FLAG;
1692
}
1693
}
1694
1695
Line[1] = 'v';
1696
}
1697
1698
if (Line[1] == 'v')
1699
{
1700
Number = 0;
1701
1702
if (debug_get_number(Line + 2, &Number) == -1 && Number < 5)
1703
{
1704
debug_line_print("Breakpoints:");
1705
1706
for (Number = 0; Number != 5; Number++)
1707
{
1708
if (S9xBreakpoint[Number].Enabled)
1709
sprintf(string, "%i @ $%02X:%04X", Number, S9xBreakpoint[Number].Bank, S9xBreakpoint[Number].Address);
1710
else
1711
sprintf(string, "%i @ Disabled", Number);
1712
1713
debug_line_print(string);
1714
}
1715
}
1716
else
1717
{
1718
debug_line_print("Breakpoint:");
1719
1720
if (S9xBreakpoint[Number].Enabled)
1721
sprintf(string, "%i @ $%02X:%04X", Number, S9xBreakpoint[Number].Bank, S9xBreakpoint[Number].Address);
1722
else
1723
sprintf(string, "%i @ Disabled", Number);
1724
1725
debug_line_print(string);
1726
}
1727
}
1728
}
1729
1730
if (*Line == '?' || strcasecmp(Line, "help") == 0)
1731
{
1732
for (int i = 0; HelpMessage[i] != NULL; i++)
1733
debug_line_print(HelpMessage[i]);
1734
}
1735
1736
if (*Line == 't')
1737
{
1738
CPU.Flags |= SINGLE_STEP_FLAG;
1739
CPU.Flags &= ~DEBUG_MODE_FLAG;
1740
}
1741
1742
if (*Line == 'f')
1743
{
1744
CPU.Flags |= FRAME_ADVANCE_FLAG;
1745
CPU.Flags &= ~DEBUG_MODE_FLAG;
1746
1747
IPPU.RenderThisFrame = TRUE;
1748
IPPU.FrameSkip = 0;
1749
1750
if (sscanf(&Line[1], "%u", &ICPU.FrameAdvanceCount) != 1)
1751
ICPU.Frame = 0;
1752
}
1753
1754
if (*Line == 'g')
1755
{
1756
S9xBreakpoint[5].Enabled = FALSE;
1757
1758
bool8 found = FALSE;
1759
1760
for (int i = 0; i < 5; i++)
1761
{
1762
if (S9xBreakpoint[i].Enabled)
1763
{
1764
found = TRUE;
1765
1766
if (S9xBreakpoint[i].Bank == Registers.PB && S9xBreakpoint[i].Address == Registers.PCw)
1767
{
1768
S9xBreakpoint[i].Enabled = 2;
1769
break;
1770
}
1771
}
1772
}
1773
1774
if (!found)
1775
CPU.Flags &= ~BREAK_FLAG;
1776
1777
ErrorCode = debug_get_start_address(Line, &Bank, &Address);
1778
1779
if (ErrorCode == 1)
1780
{
1781
S9xBreakpoint[5].Enabled = TRUE;
1782
S9xBreakpoint[5].Bank = Bank;
1783
S9xBreakpoint[5].Address = Address;
1784
CPU.Flags |= BREAK_FLAG;
1785
}
1786
1787
CPU.Flags &= ~DEBUG_MODE_FLAG;
1788
}
1789
1790
if (*Line == 'D')
1791
{
1792
Settings.TraceDMA = !Settings.TraceDMA;
1793
printf("DMA tracing %s.\n", Settings.TraceDMA ? "enabled" : "disabled");
1794
}
1795
1796
if (*Line == 'V')
1797
{
1798
Settings.TraceVRAM = !Settings.TraceVRAM;
1799
printf("Non-DMA VRAM write tracing %s.\n", Settings.TraceVRAM ? "enabled" : "disabled");
1800
}
1801
1802
if (*Line == 'H')
1803
{
1804
Settings.TraceHDMA = !Settings.TraceHDMA;
1805
printf("HDMA tracing %s.\n", Settings.TraceHDMA ? "enabled" : "disabled");
1806
}
1807
1808
if (*Line == 'U')
1809
{
1810
Settings.TraceUnknownRegisters = !Settings.TraceUnknownRegisters;
1811
printf("Unknown registers read/write tracing %s.\n", Settings.TraceUnknownRegisters ? "enabled" : "disabled");
1812
}
1813
1814
if (*Line == 'd')
1815
{
1816
int CLine;
1817
int CByte;
1818
uint8 MemoryByte;
1819
1820
if (Debug.Dump.Bank != 0 || Debug.Dump.Address != 0)
1821
{
1822
Bank = Debug.Dump.Bank;
1823
Address = Debug.Dump.Address;
1824
}
1825
1826
ErrorCode = debug_get_start_address(Line, &Bank, &Address);
1827
1828
for (CLine = 0; CLine != 10; CLine++)
1829
{
1830
sprintf(string, "$%02X:%04X", Bank, Address);
1831
1832
for (CByte = 0; CByte != 16; CByte++)
1833
{
1834
if (Address + CByte == 0x2140 ||
1835
Address + CByte == 0x2141 ||
1836
Address + CByte == 0x2142 ||
1837
Address + CByte == 0x2143 ||
1838
Address + CByte == 0x4210)
1839
MemoryByte = 0;
1840
else
1841
MemoryByte = S9xDebugGetByte((Bank << 16) + Address + CByte);
1842
1843
sprintf(string, "%s %02X", string, MemoryByte);
1844
}
1845
1846
sprintf(string, "%s-", string);
1847
1848
for (CByte = 0; CByte != 16; CByte++)
1849
{
1850
if (Address + CByte == 0x2140 ||
1851
Address + CByte == 0x2141 ||
1852
Address + CByte == 0x2142 ||
1853
Address + CByte == 0x2143 ||
1854
Address + CByte == 0x4210)
1855
MemoryByte = 0;
1856
else
1857
MemoryByte = S9xDebugGetByte((Bank << 16) + Address + CByte);
1858
1859
if (MemoryByte < 32 || MemoryByte >= 127)
1860
MemoryByte = '?';
1861
1862
sprintf(string, "%s%c", string, MemoryByte);
1863
}
1864
1865
Address += 16;
1866
1867
debug_line_print(string);
1868
}
1869
1870
Debug.Dump.Bank = Bank;
1871
Debug.Dump.Address = Address;
1872
}
1873
1874
if (*Line == 'q')
1875
S9xExit();
1876
1877
if (*Line == 'W')
1878
debug_whats_missing();
1879
1880
if (*Line == 'w')
1881
debug_whats_used();
1882
1883
if (*Line == 'r')
1884
{
1885
debug_cpu_op_print(string, Bank, Address);
1886
debug_line_print(string);
1887
}
1888
1889
if (*Line == 'u')
1890
{
1891
if (Debug.Unassemble.Bank != 0 || Debug.Unassemble.Address != 0)
1892
{
1893
Bank = Debug.Unassemble.Bank;
1894
Address = Debug.Unassemble.Address;
1895
}
1896
1897
ErrorCode = debug_get_start_address(Line, &Bank, &Address);
1898
1899
for (int i = 0; i != 10; i++)
1900
{
1901
Address += debug_cpu_op_print(string, Bank, Address);
1902
debug_line_print(string);
1903
}
1904
1905
Debug.Unassemble.Bank = Bank;
1906
Debug.Unassemble.Address = Address;
1907
}
1908
1909
debug_line_print("");
1910
1911
return;
1912
}
1913
1914
static void debug_print_window (uint8 *window)
1915
{
1916
for (int i = 0; i < 6; i++)
1917
{
1918
if (window[i])
1919
{
1920
switch (i)
1921
{
1922
case 0:
1923
printf("Background 0, ");
1924
break;
1925
1926
case 1:
1927
printf("Background 1, ");
1928
break;
1929
1930
case 2:
1931
printf("Background 2, ");
1932
break;
1933
1934
case 3:
1935
printf("Background 3, ");
1936
break;
1937
1938
case 4:
1939
printf("Objects, ");
1940
break;
1941
1942
case 5:
1943
printf("Color window, ");
1944
break;
1945
}
1946
}
1947
}
1948
}
1949
1950
static const char * debug_clip_fn (int logic)
1951
{
1952
switch (logic)
1953
{
1954
case CLIP_OR:
1955
return ("OR");
1956
1957
case CLIP_AND:
1958
return ("AND");
1959
1960
case CLIP_XOR:
1961
return ("XOR");
1962
1963
case CLIP_XNOR:
1964
return ("XNOR");
1965
1966
default:
1967
return ("???");
1968
}
1969
}
1970
1971
static void debug_whats_used (void)
1972
{
1973
printf("V-line: %ld, H-Pos: %ld, \n", (long) CPU.V_Counter, (long) CPU.Cycles);
1974
1975
printf("Screen mode: %d, ", PPU.BGMode);
1976
1977
if (PPU.BGMode <= 1 && (Memory.FillRAM[0x2105] & 8))
1978
printf("(BG#2 Priority), ");
1979
1980
printf("Brightness: %d, ", PPU.Brightness);
1981
1982
if (Memory.FillRAM[0x2100] & 0x80)
1983
printf("(screen blanked), ");
1984
1985
printf("\n");
1986
1987
if (Memory.FillRAM[0x2133] & 1)
1988
printf("Interlace, ");
1989
1990
if (Memory.FillRAM[0x2133] & 4)
1991
printf("240 line visible, ");
1992
1993
if (Memory.FillRAM[0x2133] & 8)
1994
printf("Pseudo 512 pixels horizontal resolution, ");
1995
1996
if (Memory.FillRAM[0x2133] & 0x40)
1997
printf("Mode 7 priority per pixel, ");
1998
1999
printf("\n");
2000
2001
if (PPU.BGMode == 7 && (Memory.FillRAM[0x211a] & 3))
2002
printf("Mode 7 flipping, ");
2003
2004
if (PPU.BGMode == 7)
2005
printf("Mode 7 screen repeat: %d, ", (Memory.FillRAM[0x211a] & 0xc0) >> 6);
2006
2007
if (Memory.FillRAM[0x2130] & 1)
2008
printf("32K colour mode, ");
2009
2010
printf("\n");
2011
2012
if (PPU.BGMode == 7)
2013
{
2014
// Sign extend 13 bit values to 16 bit values...
2015
if (PPU.CentreX & (1 << 12))
2016
PPU.CentreX |= 0xe000;
2017
2018
if (PPU.CentreY & (1 << 12))
2019
PPU.CentreY |= 0xe000;
2020
2021
printf("Matrix A: %.3f, B: %.3f, C: %.3f, D: %.3f, Centre X: %d Y:%d, \n",
2022
(double) PPU.MatrixA / 256, (double) PPU.MatrixB / 256,
2023
(double) PPU.MatrixC / 256, (double) PPU.MatrixD / 256,
2024
PPU.CentreX, PPU.CentreY);
2025
}
2026
2027
if ((Memory.FillRAM[0x2106] & 0xf0) && (Memory.FillRAM[0x2106] & 0x0f))
2028
{
2029
printf("Mosaic effect(%d) on, ", PPU.Mosaic);
2030
2031
for (int i = 0; i < 4; i++)
2032
if (Memory.FillRAM[0x2106] & (1 << i))
2033
printf("BG%d, ", i);
2034
}
2035
2036
printf("\n");
2037
2038
if (PPU.HVBeamCounterLatched)
2039
printf("V and H beam pos latched, \n");
2040
2041
if (Memory.FillRAM[0x4200] & 0x20)
2042
printf("V-IRQ enabled at %d, \n", PPU.IRQVBeamPos);
2043
2044
if (Memory.FillRAM[0x4200] & 0x10)
2045
printf("H-IRQ enabled at %d, \n", PPU.IRQHBeamPos);
2046
2047
if (Memory.FillRAM[0x4200] & 0x80)
2048
printf("V-blank NMI enabled, \n");
2049
2050
for (int i = 0; i < 8; i++)
2051
{
2052
if (missing.hdma_this_frame & (1 << i))
2053
{
2054
printf("H-DMA %d [%d] 0x%02X%04X->0x21%02X %s %s 0x%02X%04X %s addressing, \n",
2055
i, DMA[i].TransferMode, DMA[i].ABank, DMA[i].AAddress, DMA[i].BAddress,
2056
DMA[i].AAddressDecrement ? "dec" : "inc",
2057
DMA[i].Repeat ? "repeat" : "continue",
2058
DMA[i].IndirectBank, DMA[i].IndirectAddress,
2059
DMA[i].HDMAIndirectAddressing ? "indirect" : "absolute");
2060
}
2061
}
2062
2063
for (int i = 0; i < 8; i++)
2064
{
2065
if (missing.dma_this_frame & (1 << i))
2066
{
2067
printf("DMA %d [%d] 0x%02X%04X->0x21%02X Num: %d %s, \n",
2068
i, DMA[i].TransferMode, DMA[i].ABank, DMA[i].AAddress, DMA[i].BAddress, DMA[i].TransferBytes,
2069
DMA[i].AAddressFixed ? "fixed" : (DMA[i].AAddressDecrement ? "dec" : "inc"));
2070
}
2071
}
2072
2073
printf("VRAM write address: 0x%04x(%s), Full Graphic: %d, Address inc: %d, \n",
2074
PPU.VMA.Address,
2075
PPU.VMA.High ? "Byte" : "Word",
2076
PPU.VMA.FullGraphicCount, PPU.VMA.Increment);
2077
2078
for (int i = 0; i < 4; i++)
2079
{
2080
printf("BG%d: VOffset:%d, HOffset:%d, W:%d, H:%d, TS:%d, BA:0x%04x, TA:0x%04X, \n",
2081
i, PPU.BG[i].VOffset, PPU.BG[i].HOffset,
2082
(PPU.BG[i].SCSize & 1) * 32 + 32,
2083
(PPU.BG[i].SCSize & 2) * 16 + 32,
2084
PPU.BG[i].BGSize * 8 + 8,
2085
PPU.BG[i].SCBase,
2086
PPU.BG[i].NameBase);
2087
}
2088
2089
const char *s = "";
2090
2091
switch ((Memory.FillRAM[0x2130] & 0xc0) >> 6)
2092
{
2093
case 0:
2094
s = "always on";
2095
break;
2096
2097
case 1:
2098
s = "inside";
2099
break;
2100
2101
case 2:
2102
s = "outside";
2103
break;
2104
2105
case 3:
2106
s = "always off";
2107
break;
2108
}
2109
2110
printf("Main screen (%s): ", s);
2111
2112
for (int i = 0; i < 5; i++)
2113
{
2114
if (Memory.FillRAM[0x212c] & (1 << i))
2115
{
2116
switch (i)
2117
{
2118
case 0:
2119
printf("BG0, ");
2120
break;
2121
2122
case 1:
2123
printf("BG1, ");
2124
break;
2125
2126
case 2:
2127
printf("BG2, ");
2128
break;
2129
2130
case 3:
2131
printf("BG3, ");
2132
break;
2133
2134
case 4:
2135
printf("OBJ, ");
2136
break;
2137
}
2138
}
2139
}
2140
2141
printf("\n");
2142
2143
switch ((Memory.FillRAM[0x2130] & 0x30) >> 4)
2144
{
2145
case 0:
2146
s = "always on";
2147
break;
2148
2149
case 1:
2150
s = "inside";
2151
break;
2152
2153
case 2:
2154
s = "outside";
2155
break;
2156
2157
case 3:
2158
s = "always off";
2159
break;
2160
}
2161
2162
printf("Subscreen (%s): ", s);
2163
2164
for (int i = 0; i < 5; i++)
2165
{
2166
if (Memory.FillRAM[0x212d] & (1 << i))
2167
{
2168
switch (i)
2169
{
2170
case 0:
2171
printf("BG0, ");
2172
break;
2173
2174
case 1:
2175
printf("BG1, ");
2176
break;
2177
2178
case 2:
2179
printf("BG2, ");
2180
break;
2181
2182
case 3:
2183
printf("BG3, ");
2184
break;
2185
2186
case 4:
2187
printf("OBJ, ");
2188
break;
2189
}
2190
}
2191
}
2192
2193
printf("\n");
2194
2195
if ((Memory.FillRAM[0x2131] & 0x3f))
2196
{
2197
if (Memory.FillRAM[0x2131] & 0x80)
2198
{
2199
if (Memory.FillRAM[0x2130] & 0x02)
2200
printf("Subscreen subtract");
2201
else
2202
printf("Fixed colour subtract");
2203
}
2204
else
2205
{
2206
if (Memory.FillRAM[0x2130] & 0x02)
2207
printf("Subscreen addition");
2208
else
2209
printf("Fixed colour addition");
2210
}
2211
2212
if (Memory.FillRAM[0x2131] & 0x40)
2213
printf("(half): ");
2214
else
2215
printf(": ");
2216
2217
for (int i = 0; i < 6; i++)
2218
{
2219
if (Memory.FillRAM[0x2131] & (1 << i))
2220
{
2221
switch (i)
2222
{
2223
case 0:
2224
printf("BG0, ");
2225
break;
2226
2227
case 1:
2228
printf("BG1, ");
2229
break;
2230
2231
case 2:
2232
printf("BG2, ");
2233
break;
2234
2235
case 3:
2236
printf("BG3, ");
2237
break;
2238
2239
case 4:
2240
printf("OBJ, ");
2241
break;
2242
2243
case 5:
2244
printf("BACK, ");
2245
break;
2246
}
2247
}
2248
}
2249
2250
printf("\n");
2251
}
2252
2253
printf("Window 1 (%d, %d, %02x, %02x): ", PPU.Window1Left, PPU.Window1Right, Memory.FillRAM[0x212e], Memory.FillRAM[0x212f]);
2254
2255
for (int i = 0; i < 6; i++)
2256
{
2257
if (PPU.ClipWindow1Enable[i])
2258
{
2259
switch (i)
2260
{
2261
case 0:
2262
printf("BG0(%s-%s), ", PPU.ClipWindow1Inside[0] ? "I" : "O", debug_clip_fn(PPU.ClipWindowOverlapLogic[0]));
2263
break;
2264
2265
case 1:
2266
printf("BG1(%s-%s), ", PPU.ClipWindow1Inside[1] ? "I" : "O", debug_clip_fn(PPU.ClipWindowOverlapLogic[1]));
2267
break;
2268
2269
case 2:
2270
printf("BG2(%s-%s), ", PPU.ClipWindow1Inside[2] ? "I" : "O", debug_clip_fn(PPU.ClipWindowOverlapLogic[2]));
2271
break;
2272
2273
case 3:
2274
printf("BG3(%s-%s), ", PPU.ClipWindow1Inside[3] ? "I" : "O", debug_clip_fn(PPU.ClipWindowOverlapLogic[3]));
2275
break;
2276
2277
case 4:
2278
printf("OBJ(%s-%s), ", PPU.ClipWindow1Inside[4] ? "I" : "O", debug_clip_fn(PPU.ClipWindowOverlapLogic[4]));
2279
break;
2280
2281
case 5:
2282
printf("COL(%s-%s), ", PPU.ClipWindow1Inside[5] ? "I" : "O", debug_clip_fn(PPU.ClipWindowOverlapLogic[5]));
2283
break;
2284
}
2285
}
2286
}
2287
2288
printf("\n");
2289
2290
printf("Window 2 (%d, %d): ", PPU.Window2Left, PPU.Window2Right);
2291
2292
for (int i = 0; i < 6; i++)
2293
{
2294
if (PPU.ClipWindow2Enable[i])
2295
{
2296
switch (i)
2297
{
2298
case 0:
2299
printf("BG0(%s), ", PPU.ClipWindow2Inside[0] ? "I" : "O");
2300
break;
2301
2302
case 1:
2303
printf("BG1(%s), ", PPU.ClipWindow2Inside[1] ? "I" : "O");
2304
break;
2305
2306
case 2:
2307
printf("BG2(%s), ", PPU.ClipWindow2Inside[2] ? "I" : "O");
2308
break;
2309
2310
case 3:
2311
printf("BG3(%s), ", PPU.ClipWindow2Inside[3] ? "I" : "O");
2312
break;
2313
2314
case 4:
2315
printf("OBJ(%s), ", PPU.ClipWindow2Inside[4] ? "I" : "O");
2316
break;
2317
2318
case 5:
2319
printf("COL(%s), " , PPU.ClipWindow2Inside[5] ? "I" : "O");
2320
break;
2321
}
2322
}
2323
}
2324
2325
printf("\n");
2326
2327
printf("Fixed colour: %02x%02x%02x, \n", PPU.FixedColourRed, PPU.FixedColourGreen, PPU.FixedColourBlue);
2328
}
2329
2330
static void debug_whats_missing (void)
2331
{
2332
printf("Processor: ");
2333
2334
if (missing.emulate6502)
2335
printf("emulation mode, ");
2336
2337
if (missing.decimal_mode)
2338
printf("decimal mode, ");
2339
2340
if (missing.mv_8bit_index)
2341
printf("MVP/MVN with 8bit index registers and XH or YH > 0, ");
2342
2343
if (missing.mv_8bit_acc)
2344
printf("MVP/MVN with 8bit accumulator > 255, ");
2345
2346
printf("\n");
2347
2348
printf("Screen modes used: ");
2349
2350
for (int i = 0; i < 8; i++)
2351
if (missing.modes[i])
2352
printf("%d, ", i);
2353
2354
printf("\n");
2355
2356
if (missing.interlace)
2357
printf("Interlace, ");
2358
2359
if (missing.pseudo_512)
2360
printf("Pseudo 512 pixels horizontal resolution, ");
2361
2362
if (missing.lines_239)
2363
printf("240 lines visible, ");
2364
2365
if (missing.sprite_double_height)
2366
printf("double-hight sprites, ");
2367
2368
printf("\n");
2369
2370
if (missing.mode7_fx)
2371
printf("Mode 7 rotation/scaling, ");
2372
2373
if (missing.matrix_read)
2374
printf("Mode 7 read matrix registers, ");
2375
2376
if (missing.mode7_flip)
2377
printf("Mode 7 flipping, ");
2378
2379
if (missing.mode7_bgmode)
2380
printf("Mode 7 priority per pixel, ");
2381
2382
if (missing.direct)
2383
printf("Direct 32000 colour mode, ");
2384
2385
printf("\n");
2386
2387
if (missing.mosaic)
2388
printf("Mosaic effect, ");
2389
2390
if (missing.subscreen)
2391
printf("Subscreen enabled, ");
2392
2393
if (missing.subscreen_add)
2394
printf("Subscreen colour add, ");
2395
2396
if (missing.subscreen_sub)
2397
printf("Subscreen colour subtract, ");
2398
2399
if (missing.fixed_colour_add)
2400
printf("Fixed colour add, ");
2401
2402
if (missing.fixed_colour_sub)
2403
printf("Fixed colour subtract, ");
2404
2405
printf("\n");
2406
2407
printf("Window 1 enabled on: ");
2408
debug_print_window(missing.window1);
2409
2410
printf("\n");
2411
2412
printf("Window 2 enabled on: ");
2413
debug_print_window(missing.window2);
2414
2415
printf("\n");
2416
2417
if (missing.bg_offset_read)
2418
printf("BG offset read, ");
2419
2420
if (missing.oam_address_read)
2421
printf("OAM address read, ");
2422
2423
if (missing.sprite_priority_rotation)
2424
printf("Sprite priority rotation, ");
2425
2426
if (missing.fast_rom)
2427
printf("Fast 3.58MHz ROM access enabled, ");
2428
2429
if (missing.matrix_multiply)
2430
printf("Matrix multiply 16bit by 8bit used, ");
2431
2432
printf("\n");
2433
2434
if (missing.virq)
2435
printf("V-IRQ used at line %d, ", missing.virq_pos);
2436
2437
if (missing.hirq)
2438
printf("H-IRQ used at position %d, ", missing.hirq_pos);
2439
2440
printf("\n");
2441
2442
if (missing.h_v_latch)
2443
printf("H and V-Pos latched, ");
2444
2445
if (missing.h_counter_read)
2446
printf("H-Pos read, ");
2447
2448
if (missing.v_counter_read)
2449
printf("V-Pos read, ");
2450
2451
printf("\n");
2452
2453
if (missing.oam_read)
2454
printf("OAM read, ");
2455
2456
if (missing.vram_read)
2457
printf("VRAM read, ");
2458
2459
if (missing.cgram_read)
2460
printf("CG-RAM read, ");
2461
2462
if (missing.wram_read)
2463
printf("WRAM read, ");
2464
2465
if (missing.dma_read)
2466
printf("DMA read, ");
2467
2468
if (missing.vram_inc)
2469
printf("VRAM inc: %d, ", missing.vram_inc);
2470
2471
if (missing.vram_full_graphic_inc)
2472
printf("VRAM full graphic inc: %d, ", missing.vram_full_graphic_inc);
2473
2474
printf("\n");
2475
2476
for (int i = 0; i < 8; i++)
2477
{
2478
if (missing.hdma[i].used)
2479
{
2480
printf("HDMA %d 0x%02X%04X->0x21%02X %s, ",
2481
i, missing.hdma[i].abus_bank, missing.hdma[i].abus_address, missing.hdma[i].bbus_address,
2482
missing.hdma[i].indirect_address ? "indirect" : "absolute");
2483
2484
if (missing.hdma[i].force_table_address_write)
2485
printf("Forced address write, ");
2486
2487
if (missing.hdma[i].force_table_address_read)
2488
printf("Current address read, ");
2489
2490
if (missing.hdma[i].line_count_write)
2491
printf("Line count write, ");
2492
2493
if (missing.hdma[i].line_count_read)
2494
printf("Line count read, ");
2495
2496
printf("\n");
2497
}
2498
}
2499
2500
for (int i = 0; i < 8; i++)
2501
{
2502
if (missing.dma_channels & (1 << i))
2503
{
2504
printf("DMA %d [%d] 0x%02X%04X->0x21%02X Num: %d %s, \n",
2505
i, DMA[i].TransferMode, DMA[i].ABank, DMA[i].AAddress, DMA[i].BAddress, DMA[i].TransferBytes,
2506
DMA[i].AAddressFixed ? "fixed" : (DMA[i].AAddressDecrement ? "dec" : "inc"));
2507
}
2508
}
2509
2510
if (missing.unknownppu_read)
2511
printf("Read from unknown PPU register: $%04X, \n", missing.unknownppu_read);
2512
2513
if (missing.unknownppu_write)
2514
printf("Write to unknown PPU register: $%04X, \n", missing.unknownppu_write);
2515
2516
if (missing.unknowncpu_read)
2517
printf("Read from unknown CPU register: $%04X, \n", missing.unknowncpu_read);
2518
2519
if (missing.unknowncpu_write)
2520
printf("Write to unknown CPU register: $%04X, \n", missing.unknowncpu_write);
2521
2522
if (missing.unknowndsp_read)
2523
printf("Read from unknown DSP register: $%04X, \n", missing.unknowndsp_read);
2524
2525
if (missing.unknowndsp_write)
2526
printf("Write to unknown DSP register: $%04X, \n", missing.unknowndsp_write);
2527
}
2528
2529
void S9xDoDebug (void)
2530
{
2531
char Line[513];
2532
2533
Debug.Dump.Bank = 0;
2534
Debug.Dump.Address = 0;
2535
Debug.Unassemble.Bank = 0;
2536
Debug.Unassemble.Address = 0;
2537
2538
S9xTextMode();
2539
2540
strcpy(Line, "r");
2541
debug_process_command(Line);
2542
2543
while (CPU.Flags & DEBUG_MODE_FLAG)
2544
{
2545
int32 Cycles;
2546
char *p;
2547
2548
printf("> ");
2549
fflush(stdout);
2550
2551
p = fgets(Line, sizeof(Line) - 1, stdin);
2552
Line[strlen(Line) - 1] = 0;
2553
2554
Cycles = CPU.Cycles;
2555
debug_process_command(Line);
2556
CPU.Cycles = Cycles;
2557
}
2558
2559
if (!(CPU.Flags & SINGLE_STEP_FLAG))
2560
S9xGraphicsMode();
2561
}
2562
2563
void S9xTrace (void)
2564
{
2565
char msg[512];
2566
2567
ENSURE_TRACE_OPEN(trace, "trace.log", "a")
2568
2569
debug_cpu_op_print(msg, Registers.PB, Registers.PCw);
2570
fprintf(trace, "%s\n", msg);
2571
}
2572
2573
void S9xSA1Trace (void)
2574
{
2575
char msg[512];
2576
2577
ENSURE_TRACE_OPEN(trace2, "trace_sa1.log", "a")
2578
2579
debug_sa1_op_print(msg, SA1Registers.PB, SA1Registers.PCw);
2580
fprintf(trace2, "%s\n", msg);
2581
}
2582
2583
void S9xTraceMessage (const char *s)
2584
{
2585
if (s)
2586
{
2587
if (trace)
2588
fprintf(trace, "%s\n", s);
2589
else
2590
if (trace2)
2591
fprintf(trace2, "%s\n", s);
2592
}
2593
}
2594
2595
void S9xTraceFormattedMessage (const char *s, ...)
2596
{
2597
char msg[512];
2598
2599
if (s)
2600
{
2601
va_list argptr;
2602
2603
va_start(argptr, s);
2604
vsprintf(msg, s, argptr);
2605
va_end(argptr);
2606
2607
S9xTraceMessage(msg);
2608
}
2609
}
2610
2611
void S9xPrintHVPosition (char *s)
2612
{
2613
sprintf(s, "HC:%04ld VC:%03ld FC:%02d", (long) CPU.Cycles, (long) CPU.V_Counter, IPPU.FrameCount);
2614
}
2615
2616
#endif
2617
2618