1 #ifdef BPPU_CPP
2
3 //INIDISP
mmio_w2100(uint8 value)4 void bPPU::mmio_w2100(uint8 value) {
5 if(regs.display_disabled == true && cpu.vcounter() == (!overscan() ? 225 : 240)) {
6 regs.oam_addr = regs.oam_baseaddr << 1;
7 regs.oam_firstsprite = (regs.oam_priority == false) ? 0 : (regs.oam_addr >> 2) & 127;
8 }
9
10 regs.display_disabled = !!(value & 0x80);
11 regs.display_brightness = value & 15;
12 }
13
14 //OBSEL
mmio_w2101(uint8 value)15 void bPPU::mmio_w2101(uint8 value) {
16 regs.oam_basesize = (value >> 5) & 7;
17 regs.oam_nameselect = (value >> 3) & 3;
18 regs.oam_tdaddr = (value & 3) << 14;
19 }
20
21 //OAMADDL
mmio_w2102(uint8 data)22 void bPPU::mmio_w2102(uint8 data) {
23 regs.oam_baseaddr = (regs.oam_baseaddr & ~0xff) | (data << 0);
24 regs.oam_baseaddr &= 0x01ff;
25 regs.oam_addr = regs.oam_baseaddr << 1;
26 regs.oam_firstsprite = (regs.oam_priority == false) ? 0 : (regs.oam_addr >> 2) & 127;
27 }
28
29 //OAMADDH
mmio_w2103(uint8 data)30 void bPPU::mmio_w2103(uint8 data) {
31 regs.oam_priority = !!(data & 0x80);
32 regs.oam_baseaddr = (regs.oam_baseaddr & 0xff) | (data << 8);
33 regs.oam_baseaddr &= 0x01ff;
34 regs.oam_addr = regs.oam_baseaddr << 1;
35 regs.oam_firstsprite = (regs.oam_priority == false) ? 0 : (regs.oam_addr >> 2) & 127;
36 }
37
38 //OAMDATA
mmio_w2104(uint8 data)39 void bPPU::mmio_w2104(uint8 data) {
40 if(regs.oam_addr & 0x0200) {
41 oam_mmio_write(regs.oam_addr, data);
42 } else if((regs.oam_addr & 1) == 0) {
43 regs.oam_latchdata = data;
44 } else {
45 oam_mmio_write((regs.oam_addr & ~1) + 0, regs.oam_latchdata);
46 oam_mmio_write((regs.oam_addr & ~1) + 1, data);
47 }
48
49 regs.oam_addr++;
50 regs.oam_addr &= 0x03ff;
51 regs.oam_firstsprite = (regs.oam_priority == false) ? 0 : (regs.oam_addr >> 2) & 127;
52 }
53
54 //BGMODE
mmio_w2105(uint8 value)55 void bPPU::mmio_w2105(uint8 value) {
56 regs.bg_tilesize[BG4] = !!(value & 0x80);
57 regs.bg_tilesize[BG3] = !!(value & 0x40);
58 regs.bg_tilesize[BG2] = !!(value & 0x20);
59 regs.bg_tilesize[BG1] = !!(value & 0x10);
60 regs.bg3_priority = !!(value & 0x08);
61 regs.bg_mode = (value & 7);
62 }
63
64 //MOSAIC
mmio_w2106(uint8 value)65 void bPPU::mmio_w2106(uint8 value) {
66 regs.mosaic_size = (value >> 4) & 15;
67 regs.mosaic_enabled[BG4] = !!(value & 0x08);
68 regs.mosaic_enabled[BG3] = !!(value & 0x04);
69 regs.mosaic_enabled[BG2] = !!(value & 0x02);
70 regs.mosaic_enabled[BG1] = !!(value & 0x01);
71 }
72
73 //BG1SC
mmio_w2107(uint8 value)74 void bPPU::mmio_w2107(uint8 value) {
75 regs.bg_scaddr[BG1] = (value & 0x7c) << 9;
76 regs.bg_scsize[BG1] = value & 3;
77 }
78
79 //BG2SC
mmio_w2108(uint8 value)80 void bPPU::mmio_w2108(uint8 value) {
81 regs.bg_scaddr[BG2] = (value & 0x7c) << 9;
82 regs.bg_scsize[BG2] = value & 3;
83 }
84
85 //BG3SC
mmio_w2109(uint8 value)86 void bPPU::mmio_w2109(uint8 value) {
87 regs.bg_scaddr[BG3] = (value & 0x7c) << 9;
88 regs.bg_scsize[BG3] = value & 3;
89 }
90
91 //BG4SC
mmio_w210a(uint8 value)92 void bPPU::mmio_w210a(uint8 value) {
93 regs.bg_scaddr[BG4] = (value & 0x7c) << 9;
94 regs.bg_scsize[BG4] = value & 3;
95 }
96
97 //BG12NBA
mmio_w210b(uint8 value)98 void bPPU::mmio_w210b(uint8 value) {
99 regs.bg_tdaddr[BG1] = (value & 0x07) << 13;
100 regs.bg_tdaddr[BG2] = (value & 0x70) << 9;
101 }
102
103 //BG34NBA
mmio_w210c(uint8 value)104 void bPPU::mmio_w210c(uint8 value) {
105 regs.bg_tdaddr[BG3] = (value & 0x07) << 13;
106 regs.bg_tdaddr[BG4] = (value & 0x70) << 9;
107 }
108
109 //BG1HOFS
mmio_w210d(uint8 value)110 void bPPU::mmio_w210d(uint8 value) {
111 regs.m7_hofs = (value << 8) | regs.m7_latch;
112 regs.m7_latch = value;
113
114 regs.bg_hofs[BG1] = (value << 8) | (regs.bg_ofslatch & ~7) | ((regs.bg_hofs[BG1] >> 8) & 7);
115 regs.bg_ofslatch = value;
116 }
117
118 //BG1VOFS
mmio_w210e(uint8 value)119 void bPPU::mmio_w210e(uint8 value) {
120 regs.m7_vofs = (value << 8) | regs.m7_latch;
121 regs.m7_latch = value;
122
123 regs.bg_vofs[BG1] = (value << 8) | (regs.bg_ofslatch);
124 regs.bg_ofslatch = value;
125 }
126
127 //BG2HOFS
mmio_w210f(uint8 value)128 void bPPU::mmio_w210f(uint8 value) {
129 regs.bg_hofs[BG2] = (value << 8) | (regs.bg_ofslatch & ~7) | ((regs.bg_hofs[BG2] >> 8) & 7);
130 regs.bg_ofslatch = value;
131 }
132
133 //BG2VOFS
mmio_w2110(uint8 value)134 void bPPU::mmio_w2110(uint8 value) {
135 regs.bg_vofs[BG2] = (value << 8) | (regs.bg_ofslatch);
136 regs.bg_ofslatch = value;
137 }
138
139 //BG3HOFS
mmio_w2111(uint8 value)140 void bPPU::mmio_w2111(uint8 value) {
141 regs.bg_hofs[BG3] = (value << 8) | (regs.bg_ofslatch & ~7) | ((regs.bg_hofs[BG3] >> 8) & 7);
142 regs.bg_ofslatch = value;
143 }
144
145 //BG3VOFS
mmio_w2112(uint8 value)146 void bPPU::mmio_w2112(uint8 value) {
147 regs.bg_vofs[BG3] = (value << 8) | (regs.bg_ofslatch);
148 regs.bg_ofslatch = value;
149 }
150
151 //BG4HOFS
mmio_w2113(uint8 value)152 void bPPU::mmio_w2113(uint8 value) {
153 regs.bg_hofs[BG4] = (value << 8) | (regs.bg_ofslatch & ~7) | ((regs.bg_hofs[BG4] >> 8) & 7);
154 regs.bg_ofslatch = value;
155 }
156
157 //BG4VOFS
mmio_w2114(uint8 value)158 void bPPU::mmio_w2114(uint8 value) {
159 regs.bg_vofs[BG4] = (value << 8) | (regs.bg_ofslatch);
160 regs.bg_ofslatch = value;
161 }
162
163 //VMAIN
mmio_w2115(uint8 value)164 void bPPU::mmio_w2115(uint8 value) {
165 regs.vram_incmode = !!(value & 0x80);
166 regs.vram_mapping = (value >> 2) & 3;
167 switch(value & 3) {
168 case 0: regs.vram_incsize = 1; break;
169 case 1: regs.vram_incsize = 32; break;
170 case 2: regs.vram_incsize = 128; break;
171 case 3: regs.vram_incsize = 128; break;
172 }
173 }
174
175 //VMADDL
mmio_w2116(uint8 value)176 void bPPU::mmio_w2116(uint8 value) {
177 regs.vram_addr = (regs.vram_addr & 0xff00) | value;
178 uint16 addr = get_vram_address();
179 regs.vram_readbuffer = vram_mmio_read(addr + 0);
180 regs.vram_readbuffer |= vram_mmio_read(addr + 1) << 8;
181 }
182
183 //VMADDH
mmio_w2117(uint8 value)184 void bPPU::mmio_w2117(uint8 value) {
185 regs.vram_addr = (value << 8) | (regs.vram_addr & 0x00ff);
186 uint16 addr = get_vram_address();
187 regs.vram_readbuffer = vram_mmio_read(addr + 0);
188 regs.vram_readbuffer |= vram_mmio_read(addr + 1) << 8;
189 }
190
191 //VMDATAL
mmio_w2118(uint8 value)192 void bPPU::mmio_w2118(uint8 value) {
193 uint16 addr = get_vram_address();
194 vram_mmio_write(addr, value);
195 bg_tiledata_state[TILE_2BIT][(addr >> 4)] = 1;
196 bg_tiledata_state[TILE_4BIT][(addr >> 5)] = 1;
197 bg_tiledata_state[TILE_8BIT][(addr >> 6)] = 1;
198
199 if(regs.vram_incmode == 0) {
200 regs.vram_addr += regs.vram_incsize;
201 }
202 }
203
204 //VMDATAH
mmio_w2119(uint8 value)205 void bPPU::mmio_w2119(uint8 value) {
206 uint16 addr = get_vram_address() + 1;
207 vram_mmio_write(addr, value);
208 bg_tiledata_state[TILE_2BIT][(addr >> 4)] = 1;
209 bg_tiledata_state[TILE_4BIT][(addr >> 5)] = 1;
210 bg_tiledata_state[TILE_8BIT][(addr >> 6)] = 1;
211
212 if(regs.vram_incmode == 1) {
213 regs.vram_addr += regs.vram_incsize;
214 }
215 }
216
217 //M7SEL
mmio_w211a(uint8 value)218 void bPPU::mmio_w211a(uint8 value) {
219 regs.mode7_repeat = (value >> 6) & 3;
220 regs.mode7_vflip = !!(value & 0x02);
221 regs.mode7_hflip = !!(value & 0x01);
222 }
223
224 //M7A
mmio_w211b(uint8 value)225 void bPPU::mmio_w211b(uint8 value) {
226 regs.m7a = (value << 8) | regs.m7_latch;
227 regs.m7_latch = value;
228 }
229
230 //M7B
mmio_w211c(uint8 value)231 void bPPU::mmio_w211c(uint8 value) {
232 regs.m7b = (value << 8) | regs.m7_latch;
233 regs.m7_latch = value;
234 }
235
236 //M7C
mmio_w211d(uint8 value)237 void bPPU::mmio_w211d(uint8 value) {
238 regs.m7c = (value << 8) | regs.m7_latch;
239 regs.m7_latch = value;
240 }
241
242 //M7D
mmio_w211e(uint8 value)243 void bPPU::mmio_w211e(uint8 value) {
244 regs.m7d = (value << 8) | regs.m7_latch;
245 regs.m7_latch = value;
246 }
247
248 //M7X
mmio_w211f(uint8 value)249 void bPPU::mmio_w211f(uint8 value) {
250 regs.m7x = (value << 8) | regs.m7_latch;
251 regs.m7_latch = value;
252 }
253
254 //M7Y
mmio_w2120(uint8 value)255 void bPPU::mmio_w2120(uint8 value) {
256 regs.m7y = (value << 8) | regs.m7_latch;
257 regs.m7_latch = value;
258 }
259
260 //CGADD
mmio_w2121(uint8 value)261 void bPPU::mmio_w2121(uint8 value) {
262 regs.cgram_addr = value << 1;
263 }
264
265 //CGDATA
266 //note: CGRAM palette data format is 15-bits
267 //(0,bbbbb,ggggg,rrrrr). Highest bit is ignored,
268 //as evidenced by $213b CGRAM data reads.
269 //
270 //anomie indicates writes to CGDATA work the same
271 //as writes to OAMDATA's low table. need to verify
272 //this on hardware.
mmio_w2122(uint8 value)273 void bPPU::mmio_w2122(uint8 value) {
274 if(!(regs.cgram_addr & 1)) {
275 regs.cgram_latchdata = value;
276 } else {
277 cgram_mmio_write((regs.cgram_addr & 0x01fe), regs.cgram_latchdata);
278 cgram_mmio_write((regs.cgram_addr & 0x01fe) + 1, value & 0x7f);
279 }
280 regs.cgram_addr++;
281 regs.cgram_addr &= 0x01ff;
282 }
283
284 //W12SEL
mmio_w2123(uint8 value)285 void bPPU::mmio_w2123(uint8 value) {
286 regs.window2_enabled[BG2] = !!(value & 0x80);
287 regs.window2_invert [BG2] = !!(value & 0x40);
288 regs.window1_enabled[BG2] = !!(value & 0x20);
289 regs.window1_invert [BG2] = !!(value & 0x10);
290 regs.window2_enabled[BG1] = !!(value & 0x08);
291 regs.window2_invert [BG1] = !!(value & 0x04);
292 regs.window1_enabled[BG1] = !!(value & 0x02);
293 regs.window1_invert [BG1] = !!(value & 0x01);
294 }
295
296 //W34SEL
mmio_w2124(uint8 value)297 void bPPU::mmio_w2124(uint8 value) {
298 regs.window2_enabled[BG4] = !!(value & 0x80);
299 regs.window2_invert [BG4] = !!(value & 0x40);
300 regs.window1_enabled[BG4] = !!(value & 0x20);
301 regs.window1_invert [BG4] = !!(value & 0x10);
302 regs.window2_enabled[BG3] = !!(value & 0x08);
303 regs.window2_invert [BG3] = !!(value & 0x04);
304 regs.window1_enabled[BG3] = !!(value & 0x02);
305 regs.window1_invert [BG3] = !!(value & 0x01);
306 }
307
308 //WOBJSEL
mmio_w2125(uint8 value)309 void bPPU::mmio_w2125(uint8 value) {
310 regs.window2_enabled[COL] = !!(value & 0x80);
311 regs.window2_invert [COL] = !!(value & 0x40);
312 regs.window1_enabled[COL] = !!(value & 0x20);
313 regs.window1_invert [COL] = !!(value & 0x10);
314 regs.window2_enabled[OAM] = !!(value & 0x08);
315 regs.window2_invert [OAM] = !!(value & 0x04);
316 regs.window1_enabled[OAM] = !!(value & 0x02);
317 regs.window1_invert [OAM] = !!(value & 0x01);
318 }
319
320 //WH0
mmio_w2126(uint8 value)321 void bPPU::mmio_w2126(uint8 value) {
322 regs.window1_left = value;
323 }
324
325 //WH1
mmio_w2127(uint8 value)326 void bPPU::mmio_w2127(uint8 value) {
327 regs.window1_right = value;
328 }
329
330 //WH2
mmio_w2128(uint8 value)331 void bPPU::mmio_w2128(uint8 value) {
332 regs.window2_left = value;
333 }
334
335 //WH3
mmio_w2129(uint8 value)336 void bPPU::mmio_w2129(uint8 value) {
337 regs.window2_right = value;
338 }
339
340 //WBGLOG
mmio_w212a(uint8 value)341 void bPPU::mmio_w212a(uint8 value) {
342 regs.window_mask[BG4] = (value >> 6) & 3;
343 regs.window_mask[BG3] = (value >> 4) & 3;
344 regs.window_mask[BG2] = (value >> 2) & 3;
345 regs.window_mask[BG1] = (value ) & 3;
346 }
347
348 //WOBJLOG
mmio_w212b(uint8 value)349 void bPPU::mmio_w212b(uint8 value) {
350 regs.window_mask[COL] = (value >> 2) & 3;
351 regs.window_mask[OAM] = (value ) & 3;
352 }
353
354 //TM
mmio_w212c(uint8 value)355 void bPPU::mmio_w212c(uint8 value) {
356 regs.bg_enabled[OAM] = !!(value & 0x10);
357 regs.bg_enabled[BG4] = !!(value & 0x08);
358 regs.bg_enabled[BG3] = !!(value & 0x04);
359 regs.bg_enabled[BG2] = !!(value & 0x02);
360 regs.bg_enabled[BG1] = !!(value & 0x01);
361 }
362
363 //TS
mmio_w212d(uint8 value)364 void bPPU::mmio_w212d(uint8 value) {
365 regs.bgsub_enabled[OAM] = !!(value & 0x10);
366 regs.bgsub_enabled[BG4] = !!(value & 0x08);
367 regs.bgsub_enabled[BG3] = !!(value & 0x04);
368 regs.bgsub_enabled[BG2] = !!(value & 0x02);
369 regs.bgsub_enabled[BG1] = !!(value & 0x01);
370 }
371
372 //TMW
mmio_w212e(uint8 value)373 void bPPU::mmio_w212e(uint8 value) {
374 regs.window_enabled[OAM] = !!(value & 0x10);
375 regs.window_enabled[BG4] = !!(value & 0x08);
376 regs.window_enabled[BG3] = !!(value & 0x04);
377 regs.window_enabled[BG2] = !!(value & 0x02);
378 regs.window_enabled[BG1] = !!(value & 0x01);
379 }
380
381 //TSW
mmio_w212f(uint8 value)382 void bPPU::mmio_w212f(uint8 value) {
383 regs.sub_window_enabled[OAM] = !!(value & 0x10);
384 regs.sub_window_enabled[BG4] = !!(value & 0x08);
385 regs.sub_window_enabled[BG3] = !!(value & 0x04);
386 regs.sub_window_enabled[BG2] = !!(value & 0x02);
387 regs.sub_window_enabled[BG1] = !!(value & 0x01);
388 }
389
390 //CGWSEL
mmio_w2130(uint8 value)391 void bPPU::mmio_w2130(uint8 value) {
392 regs.color_mask = (value >> 6) & 3;
393 regs.colorsub_mask = (value >> 4) & 3;
394 regs.addsub_mode = !!(value & 0x02);
395 regs.direct_color = !!(value & 0x01);
396 }
397
398 //CGADDSUB
mmio_w2131(uint8 value)399 void bPPU::mmio_w2131(uint8 value) {
400 regs.color_mode = !!(value & 0x80);
401 regs.color_halve = !!(value & 0x40);
402 regs.color_enabled[BACK] = !!(value & 0x20);
403 regs.color_enabled[OAM] = !!(value & 0x10);
404 regs.color_enabled[BG4] = !!(value & 0x08);
405 regs.color_enabled[BG3] = !!(value & 0x04);
406 regs.color_enabled[BG2] = !!(value & 0x02);
407 regs.color_enabled[BG1] = !!(value & 0x01);
408 }
409
410 //COLDATA
mmio_w2132(uint8 value)411 void bPPU::mmio_w2132(uint8 value) {
412 if(value & 0x80) regs.color_b = value & 0x1f;
413 if(value & 0x40) regs.color_g = value & 0x1f;
414 if(value & 0x20) regs.color_r = value & 0x1f;
415
416 regs.color_rgb = (regs.color_r)
417 | (regs.color_g << 5)
418 | (regs.color_b << 10);
419 }
420
421 //SETINI
mmio_w2133(uint8 value)422 void bPPU::mmio_w2133(uint8 value) {
423 regs.mode7_extbg = !!(value & 0x40);
424 regs.pseudo_hires = !!(value & 0x08);
425 regs.overscan = !!(value & 0x04);
426 regs.oam_interlace = !!(value & 0x02);
427 regs.interlace = !!(value & 0x01);
428
429 display.overscan = regs.overscan;
430 sprite_list_valid = false;
431 }
432
433 //MPYL
mmio_r2134()434 uint8 bPPU::mmio_r2134() {
435 uint32 r;
436 r = ((int16)regs.m7a * (int8)(regs.m7b >> 8));
437 regs.ppu1_mdr = r;
438 return regs.ppu1_mdr;
439 }
440
441 //MPYM
mmio_r2135()442 uint8 bPPU::mmio_r2135() {
443 uint32 r;
444 r = ((int16)regs.m7a * (int8)(regs.m7b >> 8));
445 regs.ppu1_mdr = r >> 8;
446 return regs.ppu1_mdr;
447 }
448
449 //MPYH
mmio_r2136()450 uint8 bPPU::mmio_r2136() {
451 uint32 r;
452 r = ((int16)regs.m7a * (int8)(regs.m7b >> 8));
453 regs.ppu1_mdr = r >> 16;
454 return regs.ppu1_mdr;
455 }
456
457 //SLHV
mmio_r2137()458 uint8 bPPU::mmio_r2137() {
459 if(cpu.pio() & 0x80) {
460 latch_counters();
461 }
462 return cpu.regs.mdr;
463 }
464
465 //OAMDATAREAD
mmio_r2138()466 uint8 bPPU::mmio_r2138() {
467 regs.ppu1_mdr = oam_mmio_read(regs.oam_addr);
468
469 regs.oam_addr++;
470 regs.oam_addr &= 0x03ff;
471 regs.oam_firstsprite = (regs.oam_priority == false) ? 0 : (regs.oam_addr >> 2) & 127;
472
473 return regs.ppu1_mdr;
474 }
475
476 //VMDATALREAD
mmio_r2139()477 uint8 bPPU::mmio_r2139() {
478 uint16 addr = get_vram_address();
479 regs.ppu1_mdr = regs.vram_readbuffer;
480 if(regs.vram_incmode == 0) {
481 addr &= 0xfffe;
482 regs.vram_readbuffer = vram_mmio_read(addr + 0);
483 regs.vram_readbuffer |= vram_mmio_read(addr + 1) << 8;
484 regs.vram_addr += regs.vram_incsize;
485 }
486 return regs.ppu1_mdr;
487 }
488
489 //VMDATAHREAD
mmio_r213a()490 uint8 bPPU::mmio_r213a() {
491 uint16 addr = get_vram_address() + 1;
492 regs.ppu1_mdr = regs.vram_readbuffer >> 8;
493 if(regs.vram_incmode == 1) {
494 addr &= 0xfffe;
495 regs.vram_readbuffer = vram_mmio_read(addr + 0);
496 regs.vram_readbuffer |= vram_mmio_read(addr + 1) << 8;
497 regs.vram_addr += regs.vram_incsize;
498 }
499 return regs.ppu1_mdr;
500 }
501
502 //CGDATAREAD
503 //note: CGRAM palette data is 15-bits (0,bbbbb,ggggg,rrrrr)
504 //therefore, the high byte read from each color does not
505 //update bit 7 of the PPU2 MDR.
mmio_r213b()506 uint8 bPPU::mmio_r213b() {
507 if(!(regs.cgram_addr & 1)) {
508 regs.ppu2_mdr = cgram_mmio_read(regs.cgram_addr) & 0xff;
509 } else {
510 regs.ppu2_mdr &= 0x80;
511 regs.ppu2_mdr |= cgram_mmio_read(regs.cgram_addr) & 0x7f;
512 }
513 regs.cgram_addr++;
514 regs.cgram_addr &= 0x01ff;
515 return regs.ppu2_mdr;
516 }
517
518 //OPHCT
mmio_r213c()519 uint8 bPPU::mmio_r213c() {
520 if(!regs.latch_hcounter) {
521 regs.ppu2_mdr = regs.hcounter & 0xff;
522 } else {
523 regs.ppu2_mdr &= 0xfe;
524 regs.ppu2_mdr |= (regs.hcounter >> 8) & 1;
525 }
526 regs.latch_hcounter ^= 1;
527 return regs.ppu2_mdr;
528 }
529
530 //OPVCT
mmio_r213d()531 uint8 bPPU::mmio_r213d() {
532 if(!regs.latch_vcounter) {
533 regs.ppu2_mdr = regs.vcounter & 0xff;
534 } else {
535 regs.ppu2_mdr &= 0xfe;
536 regs.ppu2_mdr |= (regs.vcounter >> 8) & 1;
537 }
538 regs.latch_vcounter ^= 1;
539 return regs.ppu2_mdr;
540 }
541
542 //STAT77
mmio_r213e()543 uint8 bPPU::mmio_r213e() {
544 uint8 r = 0x00;
545 r |= (regs.time_over) ? 0x80 : 0x00;
546 r |= (regs.range_over) ? 0x40 : 0x00;
547 r |= (regs.ppu1_mdr & 0x10);
548 r |= (ppu1_version & 0x0f);
549 regs.ppu1_mdr = r;
550 return regs.ppu1_mdr;
551 }
552
553 //STAT78
mmio_r213f()554 uint8 bPPU::mmio_r213f() {
555 uint8 r = 0x00;
556 regs.latch_hcounter = 0;
557 regs.latch_vcounter = 0;
558
559 r |= cpu.field() << 7;
560 if(!(cpu.pio() & 0x80)) {
561 r |= 0x40;
562 } else if(regs.counters_latched == true) {
563 r |= 0x40;
564 regs.counters_latched = false;
565 }
566 r |= (regs.ppu2_mdr & 0x20);
567 r |= (region << 4); //0 = NTSC, 1 = PAL
568 r |= (ppu2_version & 0x0f);
569 regs.ppu2_mdr = r;
570 return regs.ppu2_mdr;
571 }
572
mmio_read(unsigned addr)573 uint8 bPPU::mmio_read(unsigned addr) {
574 scheduler.sync_cpuppu();
575
576 switch(addr & 0xffff) {
577 case 0x2104:
578 case 0x2105:
579 case 0x2106:
580 case 0x2108:
581 case 0x2109:
582 case 0x210a:
583 case 0x2114:
584 case 0x2115:
585 case 0x2116:
586 case 0x2118:
587 case 0x2119:
588 case 0x211a:
589 case 0x2124:
590 case 0x2125:
591 case 0x2126:
592 case 0x2128:
593 case 0x2129:
594 case 0x212a: return regs.ppu1_mdr;
595 case 0x2134: return mmio_r2134(); //MPYL
596 case 0x2135: return mmio_r2135(); //MPYM
597 case 0x2136: return mmio_r2136(); //MPYH
598 case 0x2137: return mmio_r2137(); //SLHV
599 case 0x2138: return mmio_r2138(); //OAMDATAREAD
600 case 0x2139: return mmio_r2139(); //VMDATALREAD
601 case 0x213a: return mmio_r213a(); //VMDATAHREAD
602 case 0x213b: return mmio_r213b(); //CGDATAREAD
603 case 0x213c: return mmio_r213c(); //OPHCT
604 case 0x213d: return mmio_r213d(); //OPVCT
605 case 0x213e: return mmio_r213e(); //STAT77
606 case 0x213f: return mmio_r213f(); //STAT78
607 }
608
609 return cpu.regs.mdr;
610 }
611
mmio_write(unsigned addr,uint8 data)612 void bPPU::mmio_write(unsigned addr, uint8 data) {
613 scheduler.sync_cpuppu();
614
615 switch(addr & 0xffff) {
616 case 0x2100: return mmio_w2100(data); //INIDISP
617 case 0x2101: return mmio_w2101(data); //OBSEL
618 case 0x2102: return mmio_w2102(data); //OAMADDL
619 case 0x2103: return mmio_w2103(data); //OAMADDH
620 case 0x2104: return mmio_w2104(data); //OAMDATA
621 case 0x2105: return mmio_w2105(data); //BGMODE
622 case 0x2106: return mmio_w2106(data); //MOSAIC
623 case 0x2107: return mmio_w2107(data); //BG1SC
624 case 0x2108: return mmio_w2108(data); //BG2SC
625 case 0x2109: return mmio_w2109(data); //BG3SC
626 case 0x210a: return mmio_w210a(data); //BG4SC
627 case 0x210b: return mmio_w210b(data); //BG12NBA
628 case 0x210c: return mmio_w210c(data); //BG34NBA
629 case 0x210d: return mmio_w210d(data); //BG1HOFS
630 case 0x210e: return mmio_w210e(data); //BG1VOFS
631 case 0x210f: return mmio_w210f(data); //BG2HOFS
632 case 0x2110: return mmio_w2110(data); //BG2VOFS
633 case 0x2111: return mmio_w2111(data); //BG3HOFS
634 case 0x2112: return mmio_w2112(data); //BG3VOFS
635 case 0x2113: return mmio_w2113(data); //BG4HOFS
636 case 0x2114: return mmio_w2114(data); //BG4VOFS
637 case 0x2115: return mmio_w2115(data); //VMAIN
638 case 0x2116: return mmio_w2116(data); //VMADDL
639 case 0x2117: return mmio_w2117(data); //VMADDH
640 case 0x2118: return mmio_w2118(data); //VMDATAL
641 case 0x2119: return mmio_w2119(data); //VMDATAH
642 case 0x211a: return mmio_w211a(data); //M7SEL
643 case 0x211b: return mmio_w211b(data); //M7A
644 case 0x211c: return mmio_w211c(data); //M7B
645 case 0x211d: return mmio_w211d(data); //M7C
646 case 0x211e: return mmio_w211e(data); //M7D
647 case 0x211f: return mmio_w211f(data); //M7X
648 case 0x2120: return mmio_w2120(data); //M7Y
649 case 0x2121: return mmio_w2121(data); //CGADD
650 case 0x2122: return mmio_w2122(data); //CGDATA
651 case 0x2123: return mmio_w2123(data); //W12SEL
652 case 0x2124: return mmio_w2124(data); //W34SEL
653 case 0x2125: return mmio_w2125(data); //WOBJSEL
654 case 0x2126: return mmio_w2126(data); //WH0
655 case 0x2127: return mmio_w2127(data); //WH1
656 case 0x2128: return mmio_w2128(data); //WH2
657 case 0x2129: return mmio_w2129(data); //WH3
658 case 0x212a: return mmio_w212a(data); //WBGLOG
659 case 0x212b: return mmio_w212b(data); //WOBJLOG
660 case 0x212c: return mmio_w212c(data); //TM
661 case 0x212d: return mmio_w212d(data); //TS
662 case 0x212e: return mmio_w212e(data); //TMW
663 case 0x212f: return mmio_w212f(data); //TSW
664 case 0x2130: return mmio_w2130(data); //CGWSEL
665 case 0x2131: return mmio_w2131(data); //CGADDSUB
666 case 0x2132: return mmio_w2132(data); //COLDATA
667 case 0x2133: return mmio_w2133(data); //SETINI
668 }
669 }
670
671 #endif
672