1 From 6bd069191d29ad70d38c82d59dd72cd0996fc45c Mon Sep 17 00:00:00 2001
2 From: Ilari Liusvaara <ilari.liusvaara@elisanet.fi>
3 Date: Mon, 31 Mar 2014 20:17:46 +0300
4 Subject: [PATCH 18/27] Support VRAM, OAM, CGRAM and APURAM breakpoints
7 snes/alt/ppu-compatibility/memory/memory.cpp | 44 +++++++++++++++++++++--
8 snes/alt/ppu-compatibility/ppu.hpp | 6 ++++
9 snes/cartridge/cartridge.hpp | 4 +++
10 snes/smp/core/core.hpp | 2 +-
11 snes/smp/core/memory.hpp | 6 ++--
12 snes/smp/core/opcodes.cpp | 36 +++++++++----------
13 snes/smp/debugger/debugger.cpp | 4 +--
14 snes/smp/debugger/debugger.hpp | 2 +-
15 snes/smp/memory/memory.cpp | 54 +++++++++++++++++++---------
16 snes/smp/memory/memory.hpp | 4 +--
17 snes/smp/smp.hpp | 4 +++
19 12 files changed, 122 insertions(+), 45 deletions(-)
21 diff --git a/snes/alt/ppu-compatibility/memory/memory.cpp b/snes/alt/ppu-compatibility/memory/memory.cpp
22 index 3f120d84..e47cf201 100755
23 --- a/snes/alt/ppu-compatibility/memory/memory.cpp
24 +++ b/snes/alt/ppu-compatibility/memory/memory.cpp
25 @@ -47,20 +47,31 @@ uint8 PPU::vram_mmio_read(uint16 addr) {
30 + if(__builtin_expect(vram_debugflags[addr] & 0x1, 0)) {
31 + debug_read(13, addr, data);
36 void PPU::vram_mmio_write(uint16 addr, uint8 data) {
37 if(regs.display_disabled == true) {
38 + if(__builtin_expect(vram_debugflags[addr] & 0x2, 0)) {
39 + debug_write(13, addr, data);
43 uint16 v = cpu.vcounter();
44 uint16 h = cpu.hcounter();
47 + if(__builtin_expect(vram_debugflags[addr] & 0x2, 0)) {
48 + debug_write(13, addr, data);
52 + if(__builtin_expect(vram_debugflags[addr] & 0x2, 0)) {
53 + debug_write(13, addr, cpu.regs.mdr);
55 vram[addr] = cpu.regs.mdr;
58 @@ -71,9 +82,15 @@ void PPU::vram_mmio_write(uint16 addr, uint8 data) {
62 + if(__builtin_expect(vram_debugflags[addr] & 0x2, 0)) {
63 + debug_write(13, addr, data);
68 + if(__builtin_expect(vram_debugflags[addr] & 0x2, 0)) {
69 + debug_write(13, addr, data);
74 @@ -93,7 +110,9 @@ uint8 PPU::oam_mmio_read(uint16 addr) {
79 + if(__builtin_expect(oam_debugflags[addr] & 0x1, 0)) {
80 + debug_read(14, addr, data);
85 @@ -104,13 +123,22 @@ void PPU::oam_mmio_write(uint16 addr, uint8 data) {
86 sprite_list_valid = false;
88 if(regs.display_disabled == true) {
89 + if(__builtin_expect(oam_debugflags[addr] & 0x2, 0)) {
90 + debug_write(14, addr, data);
93 update_sprite_list(addr, data);
95 if(cpu.vcounter() < (!overscan() ? 225 : 240)) {
96 + if(__builtin_expect(oam_debugflags[regs.ioamaddr] & 0x2, 0)) {
97 + debug_write(14, regs.ioamaddr, data);
99 oam[regs.ioamaddr] = data;
100 update_sprite_list(regs.ioamaddr, data);
102 + if(__builtin_expect(oam_debugflags[addr] & 0x2, 0)) {
103 + debug_write(14, addr, data);
106 update_sprite_list(addr, data);
108 @@ -134,6 +162,9 @@ uint8 PPU::cgram_mmio_read(uint16 addr) {
111 if(addr & 1) data &= 0x7f;
112 + if(__builtin_expect(cgram_debugflags[addr] & 0x1, 0)) {
113 + debug_read(15, addr, data);
118 @@ -142,13 +173,22 @@ void PPU::cgram_mmio_write(uint16 addr, uint8 data) {
119 if(addr & 1) data &= 0x7f;
121 if(1 || regs.display_disabled == true) {
122 + if(__builtin_expect(cgram_debugflags[addr] & 0x2, 0)) {
123 + debug_write(15, addr, data);
127 uint16 v = cpu.vcounter();
128 uint16 h = cpu.hcounter();
129 if(v < (!overscan() ? 225 : 240) && h >= 128 && h < 1096) {
130 + if(__builtin_expect(cgram_debugflags[regs.icgramaddr] & 0x2, 0)) {
131 + debug_write(15, regs.icgramaddr, data & 0x7f);
133 cgram[regs.icgramaddr] = data & 0x7f;
135 + if(__builtin_expect(cgram_debugflags[addr] & 0x2, 0)) {
136 + debug_write(15, addr, data);
141 diff --git a/snes/alt/ppu-compatibility/ppu.hpp b/snes/alt/ppu-compatibility/ppu.hpp
142 index cccaabba..4adac4c4 100755
143 --- a/snes/alt/ppu-compatibility/ppu.hpp
144 +++ b/snes/alt/ppu-compatibility/ppu.hpp
145 @@ -3,6 +3,12 @@ public:
146 uint8 vram[128 * 1024];
149 + //4 is read, 2 is write.
150 + uint8 vram_debugflags[128 * 1024];
151 + uint8 oam_debugflags[544];
152 + uint8 cgram_debugflags[512];
153 + function<void (uint8, unsigned, uint8)> debug_read;
154 + function<void (uint8, unsigned, uint8)> debug_write;
156 enum : bool { Threaded = true };
157 alwaysinline void step(unsigned clocks);
158 diff --git a/snes/cartridge/cartridge.hpp b/snes/cartridge/cartridge.hpp
159 index 82e73c4c..2358c088 100755
160 --- a/snes/cartridge/cartridge.hpp
161 +++ b/snes/cartridge/cartridge.hpp
162 @@ -26,6 +26,10 @@ struct Cartridge : property<Cartridge> {
163 SUFAMITURBO_RAMA = 10,
164 SUFAMITURBO_RAMB = 11,
172 enum class Slot : unsigned {
173 diff --git a/snes/smp/core/core.hpp b/snes/smp/core/core.hpp
174 index 13d69364..03f9ac66 100755
175 --- a/snes/smp/core/core.hpp
176 +++ b/snes/smp/core/core.hpp
179 virtual void op_io() = 0;
180 - virtual uint8 op_read(uint16 addr) = 0;
181 + virtual uint8 op_read(uint16 addr, bool exec) = 0;
182 virtual void op_write(uint16 addr, uint8 data) = 0;
183 virtual void op_step();
185 diff --git a/snes/smp/core/memory.hpp b/snes/smp/core/memory.hpp
186 index c4b6d99f..c297962f 100755
187 --- a/snes/smp/core/memory.hpp
188 +++ b/snes/smp/core/memory.hpp
190 alwaysinline uint8 op_readpc() {
191 - return op_read(regs.pc++);
192 + return op_read(regs.pc++, true);
195 alwaysinline uint8 op_readsp() {
196 - return op_read(0x0100 | ++regs.s);
197 + return op_read(0x0100 | ++regs.s, false);
200 alwaysinline void op_writesp(uint8 data) {
201 @@ -11,7 +11,7 @@ alwaysinline void op_writesp(uint8 data) {
204 alwaysinline uint8 op_readdp(uint8 addr) {
205 - return op_read((regs.p.p << 8) + addr);
206 + return op_read((regs.p.p << 8) + addr, false);
209 alwaysinline void op_writedp(uint8 addr, uint8 data) {
210 diff --git a/snes/smp/core/opcodes.cpp b/snes/smp/core/opcodes.cpp
211 index 95b9844f..43db081d 100755
212 --- a/snes/smp/core/opcodes.cpp
213 +++ b/snes/smp/core/opcodes.cpp
214 @@ -11,7 +11,7 @@ template<uint8 (SMPcore::*op)(uint8)>
215 void SMPcore::op_adjust_addr() {
219 + rd = op_read(dp, false);
223 @@ -78,7 +78,7 @@ template<uint8 (SMPcore::*op)(uint8, uint8)>
224 void SMPcore::op_read_addr(uint8 &r) {
228 + rd = op_read(dp, false);
232 @@ -87,7 +87,7 @@ void SMPcore::op_read_addri(uint8 &r) {
236 - rd = op_read(dp + r);
237 + rd = op_read(dp + r, false);
238 regs.a = call(regs.a, rd);
241 @@ -127,7 +127,7 @@ void SMPcore::op_read_idpx() {
243 sp.l = op_readdp(dp++);
244 sp.h = op_readdp(dp++);
246 + rd = op_read(sp, false);
247 regs.a = call(regs.a, rd);
250 @@ -137,7 +137,7 @@ void SMPcore::op_read_idpy() {
252 sp.l = op_readdp(dp++);
253 sp.h = op_readdp(dp++);
254 - rd = op_read(sp + regs.y);
255 + rd = op_read(sp + regs.y, false);
256 regs.a = call(regs.a, rd);
259 @@ -153,7 +153,7 @@ void SMPcore::op_set_addr_bit() {
264 + rd = op_read(dp, false);
265 switch(opcode >> 5) {
266 case 0: //orc addr:bit
267 case 1: //orc !addr:bit
268 @@ -198,10 +198,10 @@ void SMPcore::op_set_flag(bool &flag, bool data) {
269 void SMPcore::op_test_addr(bool set) {
273 + rd = op_read(dp, false);
274 regs.p.n = (regs.a - rd) & 0x80;
275 regs.p.z = (regs.a - rd) == 0;
277 + op_read(dp, false);
278 op_write(dp, set ? rd | regs.a : rd & ~regs.a);
281 @@ -216,7 +216,7 @@ void SMPcore::op_transfer(uint8 &from, uint8 &to) {
282 void SMPcore::op_write_addr(uint8 &r) {
286 + op_read(dp, false);
290 @@ -225,7 +225,7 @@ void SMPcore::op_write_addri(uint8 &i) {
295 + op_read(dp, false);
296 op_write(dp, regs.a);
299 @@ -317,8 +317,8 @@ void SMPcore::op_bne_ydec() {
302 void SMPcore::op_brk() {
303 - rd.l = op_read(0xffde);
304 - rd.h = op_read(0xffdf);
305 + rd.l = op_read(0xffde, false);
306 + rd.h = op_read(0xffdf, false);
309 op_writesp(regs.pc.h);
310 @@ -411,8 +411,8 @@ void SMPcore::op_jmp_iaddrx() {
314 - rd.l = op_read(dp++);
315 - rd.h = op_read(dp++);
316 + rd.l = op_read(dp++, false);
317 + rd.h = op_read(dp++, false);
321 @@ -438,8 +438,8 @@ void SMPcore::op_jsr_addr() {
323 void SMPcore::op_jst() {
324 dp = 0xffde - ((opcode >> 4) << 1);
325 - rd.l = op_read(dp++);
326 - rd.h = op_read(dp++);
327 + rd.l = op_read(dp++, false);
328 + rd.h = op_read(dp++, false);
332 @@ -505,7 +505,7 @@ void SMPcore::op_sta_idpx() {
334 dp.l = op_readdp(sp++);
335 dp.h = op_readdp(sp++);
337 + op_read(dp, false);
338 op_write(dp, regs.a);
341 @@ -515,7 +515,7 @@ void SMPcore::op_sta_idpy() {
342 dp.h = op_readdp(sp++);
346 + op_read(dp, false);
347 op_write(dp, regs.a);
350 diff --git a/snes/smp/debugger/debugger.cpp b/snes/smp/debugger/debugger.cpp
351 index 9546c118..894fdac9 100755
352 --- a/snes/smp/debugger/debugger.cpp
353 +++ b/snes/smp/debugger/debugger.cpp
354 @@ -18,8 +18,8 @@ void SMPDebugger::op_step() {
358 -uint8 SMPDebugger::op_read(uint16 addr) {
359 - uint8 data = SMP::op_read(addr);
360 +uint8 SMPDebugger::op_read(uint16 addr, bool exec) {
361 + uint8 data = SMP::op_read(addr, exec);
362 usage[addr] |= UsageRead;
363 debugger.breakpoint_test(Debugger::Breakpoint::Source::APURAM, Debugger::Breakpoint::Mode::Read, addr, data);
365 diff --git a/snes/smp/debugger/debugger.hpp b/snes/smp/debugger/debugger.hpp
366 index d5d28e53..26bc7af9 100755
367 --- a/snes/smp/debugger/debugger.hpp
368 +++ b/snes/smp/debugger/debugger.hpp
369 @@ -14,7 +14,7 @@ public:
373 - uint8 op_read(uint16 addr);
374 + uint8 op_read(uint16 addr, bool exec);
375 void op_write(uint16 addr, uint8 data);
378 diff --git a/snes/smp/memory/memory.cpp b/snes/smp/memory/memory.cpp
379 index 391324c4..58c11915 100755
380 --- a/snes/smp/memory/memory.cpp
381 +++ b/snes/smp/memory/memory.cpp
382 @@ -19,61 +19,83 @@ void SMP::port_write(uint2 port, uint8 data) {
383 apuram[0xf4 + port] = data;
386 -alwaysinline uint8 SMP::op_busread(uint16 addr) {
387 +alwaysinline uint8 SMP::op_busread(uint16 addr, bool exec) {
392 case 0xf0: //TEST -- write-only register
397 case 0xf1: //CONTROL -- write-only register
403 - return status.dsp_addr;
404 + data = status.dsp_addr;
408 //0x80-0xff are read-only mirrors of 0x00-0x7f
409 - return dsp.read(status.dsp_addr & 0x7f);
410 + data = dsp.read(status.dsp_addr & 0x7f);
418 - return cpu.port_read(addr);
419 + data = cpu.port_read(addr);
423 - return status.ram00f8;
424 + data = status.ram00f8;
428 - return status.ram00f9;
429 + data = status.ram00f9;
432 case 0xfa: //T0TARGET
433 case 0xfb: //T1TARGET
434 case 0xfc: //T2TARGET -- write-only registers
439 case 0xfd: //T0OUT -- 4-bit counter value
440 result = timer0.stage3_ticks;
441 timer0.stage3_ticks = 0;
446 case 0xfe: //T1OUT -- 4-bit counter value
447 result = timer1.stage3_ticks;
448 timer1.stage3_ticks = 0;
453 case 0xff: //T2OUT -- 4-bit counter value
454 result = timer2.stage3_ticks;
455 timer2.stage3_ticks = 0;
460 + data = ram_read(addr);
464 - return ram_read(addr);
465 + uint8 flag = exec ? 0x04 : 0x01;
466 + if(__builtin_expect(debugflags[addr] & flag, 0)) {
467 + debug_read(16, addr, data, exec);
472 alwaysinline void SMP::op_buswrite(uint16 addr, uint8 data) {
473 + if(__builtin_expect(debugflags[addr] & 0x2, 0)) {
474 + debug_write(16, addr, data);
479 if(regs.p.p) break; //writes only valid when P flag is clear
480 @@ -180,9 +202,9 @@ void SMP::op_io() {
484 -uint8 SMP::op_read(uint16 addr) {
485 +uint8 SMP::op_read(uint16 addr, bool exec) {
487 - uint8 r = op_busread(addr);
488 + uint8 r = op_busread(addr, exec);
492 diff --git a/snes/smp/memory/memory.hpp b/snes/smp/memory/memory.hpp
493 index 1a07445d..faa28daa 100755
494 --- a/snes/smp/memory/memory.hpp
495 +++ b/snes/smp/memory/memory.hpp
497 uint8 ram_read(uint16 addr);
498 void ram_write(uint16 addr, uint8 data);
500 -uint8 op_busread(uint16 addr);
501 +uint8 op_busread(uint16 addr, bool exec);
502 void op_buswrite(uint16 addr, uint8 data);
505 -debugvirtual uint8 op_read(uint16 addr);
506 +debugvirtual uint8 op_read(uint16 addr, bool exec);
507 debugvirtual void op_write(uint16 addr, uint8 data);
508 diff --git a/snes/smp/smp.hpp b/snes/smp/smp.hpp
509 index 6b387cba..6b6ae837 100755
510 --- a/snes/smp/smp.hpp
511 +++ b/snes/smp/smp.hpp
513 struct SMP : public Processor, public SMPcore {
514 static const uint8 iplrom[64];
515 uint8 apuram[64 * 1024];
516 + uint8 debugflags[64 * 1024];
518 + function<void (uint8, unsigned, uint8, bool)> debug_read;
519 + function<void (uint8, unsigned, uint8)> debug_write;
521 enum : bool { Threaded = true };
522 alwaysinline void step(unsigned clocks);
523 diff --git a/snes/snes.hpp b/snes/snes.hpp
524 index 9589db9b..27632bff 100755
530 #define BSNES_SUPPORTS_ADV_BREAKPOINTS
531 +#define BSNES_SUPPORTS_ADV_BREAKPOINTS_PPU
532 #define BSNES_SUPPORTS_ALT_TIMINGS