Lua: Fix type confusion between signed and unsigned
[lsnes.git] / bsnes-patches / v085 / 0018-Support-VRAM-OAM-CGRAM-and-APURAM-breakpoints.patch
blob718708e6eeb88169dd13d076590978f6de7ff758
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/26] Support VRAM, OAM, CGRAM and APURAM breakpoints
6 ---
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 +++
18 snes/snes.hpp | 1 +
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 3f120d8..e47cf20 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) {
26 data = vram[addr];
30 + if(__builtin_expect(vram_debugflags[addr] & 0x1, 0)) {
31 + debug_read(13, addr, data);
32 + }
33 return 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);
40 + }
41 vram[addr] = data;
42 } else {
43 uint16 v = cpu.vcounter();
44 uint16 h = cpu.hcounter();
45 if(v == 0) {
46 if(h <= 4) {
47 + if(__builtin_expect(vram_debugflags[addr] & 0x2, 0)) {
48 + debug_write(13, addr, data);
49 + }
50 vram[addr] = data;
51 } else if(h == 6) {
52 + if(__builtin_expect(vram_debugflags[addr] & 0x2, 0)) {
53 + debug_write(13, addr, cpu.regs.mdr);
54 + }
55 vram[addr] = cpu.regs.mdr;
56 } else {
57 //no write
58 @@ -71,9 +82,15 @@ void PPU::vram_mmio_write(uint16 addr, uint8 data) {
59 if(h <= 4) {
60 //no write
61 } else {
62 + if(__builtin_expect(vram_debugflags[addr] & 0x2, 0)) {
63 + debug_write(13, addr, data);
64 + }
65 vram[addr] = data;
67 } else {
68 + if(__builtin_expect(vram_debugflags[addr] & 0x2, 0)) {
69 + debug_write(13, addr, data);
70 + }
71 vram[addr] = data;
74 @@ -93,7 +110,9 @@ uint8 PPU::oam_mmio_read(uint16 addr) {
75 data = oam[addr];
79 + if(__builtin_expect(oam_debugflags[addr] & 0x1, 0)) {
80 + debug_read(14, addr, data);
81 + }
82 return 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);
91 + }
92 oam[addr] = data;
93 update_sprite_list(addr, data);
94 } else {
95 if(cpu.vcounter() < (!overscan() ? 225 : 240)) {
96 + if(__builtin_expect(oam_debugflags[regs.ioamaddr] & 0x2, 0)) {
97 + debug_write(14, regs.ioamaddr, data);
98 + }
99 oam[regs.ioamaddr] = data;
100 update_sprite_list(regs.ioamaddr, data);
101 } else {
102 + if(__builtin_expect(oam_debugflags[addr] & 0x2, 0)) {
103 + debug_write(14, addr, data);
105 oam[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);
115 return 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);
125 cgram[addr] = data;
126 } else {
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;
134 } else {
135 + if(__builtin_expect(cgram_debugflags[addr] & 0x2, 0)) {
136 + debug_write(15, addr, data);
138 cgram[addr] = data;
141 diff --git a/snes/alt/ppu-compatibility/ppu.hpp b/snes/alt/ppu-compatibility/ppu.hpp
142 index cccaabb..4adac4c 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];
147 uint8 oam[544];
148 uint8 cgram[512];
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 82e73c4..2358c08 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,
165 BSXFLASH = 12,
166 + VRAM = 13,
167 + OAM = 14,
168 + CGRAM = 15,
169 + APURAM = 16,
172 enum class Slot : unsigned {
173 diff --git a/snes/smp/core/core.hpp b/snes/smp/core/core.hpp
174 index 13d6936..03f9ac6 100755
175 --- a/snes/smp/core/core.hpp
176 +++ b/snes/smp/core/core.hpp
177 @@ -1,6 +1,6 @@
178 struct SMPcore {
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 c4b6d99..c297962 100755
187 --- a/snes/smp/core/memory.hpp
188 +++ b/snes/smp/core/memory.hpp
189 @@ -1,9 +1,9 @@
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 95b9844..43db081 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() {
216 dp.l = op_readpc();
217 dp.h = op_readpc();
218 - rd = op_read(dp);
219 + rd = op_read(dp, false);
220 rd = call(rd);
221 op_write(dp, rd);
223 @@ -78,7 +78,7 @@ template<uint8 (SMPcore::*op)(uint8, uint8)>
224 void SMPcore::op_read_addr(uint8 &r) {
225 dp.l = op_readpc();
226 dp.h = op_readpc();
227 - rd = op_read(dp);
228 + rd = op_read(dp, false);
229 r = call(r, rd);
232 @@ -87,7 +87,7 @@ void SMPcore::op_read_addri(uint8 &r) {
233 dp.l = op_readpc();
234 dp.h = op_readpc();
235 op_io();
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() {
242 op_io();
243 sp.l = op_readdp(dp++);
244 sp.h = op_readdp(dp++);
245 - rd = op_read(sp);
246 + rd = op_read(sp, false);
247 regs.a = call(regs.a, rd);
250 @@ -137,7 +137,7 @@ void SMPcore::op_read_idpy() {
251 op_io();
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() {
260 dp.h = op_readpc();
261 bit = dp >> 13;
262 dp &= 0x1fff;
263 - rd = op_read(dp);
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) {
270 dp.l = op_readpc();
271 dp.h = op_readpc();
272 - rd = op_read(dp);
273 + rd = op_read(dp, false);
274 regs.p.n = (regs.a - rd) & 0x80;
275 regs.p.z = (regs.a - rd) == 0;
276 - op_read(dp);
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) {
283 dp.l = op_readpc();
284 dp.h = op_readpc();
285 - op_read(dp);
286 + op_read(dp, false);
287 op_write(dp, r);
290 @@ -225,7 +225,7 @@ void SMPcore::op_write_addri(uint8 &i) {
291 dp.h = op_readpc();
292 op_io();
293 dp += i;
294 - op_read(dp);
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);
307 op_io();
308 op_io();
309 op_writesp(regs.pc.h);
310 @@ -411,8 +411,8 @@ void SMPcore::op_jmp_iaddrx() {
311 dp.h = op_readpc();
312 op_io();
313 dp += regs.x;
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);
318 regs.pc = rd;
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);
329 op_io();
330 op_io();
331 op_io();
332 @@ -505,7 +505,7 @@ void SMPcore::op_sta_idpx() {
333 op_io();
334 dp.l = op_readdp(sp++);
335 dp.h = op_readdp(sp++);
336 - op_read(dp);
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++);
343 op_io();
344 dp += regs.y;
345 - op_read(dp);
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 9546c11..894fdac 100755
352 --- a/snes/smp/debugger/debugger.cpp
353 +++ b/snes/smp/debugger/debugger.cpp
354 @@ -18,8 +18,8 @@ void SMPDebugger::op_step() {
355 synchronize_cpu();
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);
364 return data;
365 diff --git a/snes/smp/debugger/debugger.hpp b/snes/smp/debugger/debugger.hpp
366 index d5d28e5..26bc7af 100755
367 --- a/snes/smp/debugger/debugger.hpp
368 +++ b/snes/smp/debugger/debugger.hpp
369 @@ -14,7 +14,7 @@ public:
370 bool opcode_edge;
372 void op_step();
373 - uint8 op_read(uint16 addr);
374 + uint8 op_read(uint16 addr, bool exec);
375 void op_write(uint16 addr, uint8 data);
377 SMPDebugger();
378 diff --git a/snes/smp/memory/memory.cpp b/snes/smp/memory/memory.cpp
379 index 391324c..58c1191 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) {
388 unsigned result;
389 + uint8 data;
391 switch(addr) {
392 case 0xf0: //TEST -- write-only register
393 - return 0x00;
394 + data = 0x00;
395 + break;
397 case 0xf1: //CONTROL -- write-only register
398 - return 0x00;
399 + data = 0x00;
400 + break;
402 case 0xf2: //DSPADDR
403 - return status.dsp_addr;
404 + data = status.dsp_addr;
405 + break;
407 case 0xf3: //DSPDATA
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);
411 + break;
413 case 0xf4: //CPUIO0
414 case 0xf5: //CPUIO1
415 case 0xf6: //CPUIO2
416 case 0xf7: //CPUIO3
417 synchronize_cpu();
418 - return cpu.port_read(addr);
419 + data = cpu.port_read(addr);
420 + break;
422 case 0xf8: //RAM0
423 - return status.ram00f8;
424 + data = status.ram00f8;
425 + break;
427 case 0xf9: //RAM1
428 - return status.ram00f9;
429 + data = status.ram00f9;
430 + break;
432 case 0xfa: //T0TARGET
433 case 0xfb: //T1TARGET
434 case 0xfc: //T2TARGET -- write-only registers
435 - return 0x00;
436 + data = 0x00;
437 + break;
439 case 0xfd: //T0OUT -- 4-bit counter value
440 result = timer0.stage3_ticks;
441 timer0.stage3_ticks = 0;
442 - return result;
443 + data = result;
444 + break;
446 case 0xfe: //T1OUT -- 4-bit counter value
447 result = timer1.stage3_ticks;
448 timer1.stage3_ticks = 0;
449 - return result;
450 + data = result;
451 + break;
453 case 0xff: //T2OUT -- 4-bit counter value
454 result = timer2.stage3_ticks;
455 timer2.stage3_ticks = 0;
456 - return result;
457 + data = result;
458 + break;
459 + default:
460 + data = ram_read(addr);
461 + break;
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);
469 + return data;
472 alwaysinline void SMP::op_buswrite(uint16 addr, uint8 data) {
473 + if(__builtin_expect(debugflags[addr] & 0x2, 0)) {
474 + debug_write(16, addr, data);
477 switch(addr) {
478 case 0xf0: //TEST
479 if(regs.p.p) break; //writes only valid when P flag is clear
480 @@ -180,9 +202,9 @@ void SMP::op_io() {
481 cycle_edge();
484 -uint8 SMP::op_read(uint16 addr) {
485 +uint8 SMP::op_read(uint16 addr, bool exec) {
486 add_clocks(12);
487 - uint8 r = op_busread(addr);
488 + uint8 r = op_busread(addr, exec);
489 add_clocks(12);
490 cycle_edge();
491 return r;
492 diff --git a/snes/smp/memory/memory.hpp b/snes/smp/memory/memory.hpp
493 index 1a07445..faa28da 100755
494 --- a/snes/smp/memory/memory.hpp
495 +++ b/snes/smp/memory/memory.hpp
496 @@ -1,9 +1,9 @@
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);
504 void op_io();
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 6b387cb..6b6ae83 100755
510 --- a/snes/smp/smp.hpp
511 +++ b/snes/smp/smp.hpp
512 @@ -1,6 +1,10 @@
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 9589db9..27632bf 100755
525 --- a/snes/snes.hpp
526 +++ b/snes/snes.hpp
527 @@ -1,6 +1,7 @@
528 #ifndef SNES_HPP
529 #define SNES_HPP
530 #define BSNES_SUPPORTS_ADV_BREAKPOINTS
531 +#define BSNES_SUPPORTS_ADV_BREAKPOINTS_PPU
532 #define BSNES_SUPPORTS_ALT_TIMINGS
534 namespace SNES {
536 2.8.1