Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
alexbevi
GitHub Repository: alexbevi/BizHawk
Path: blob/master/libsnes/bsnes/snes/ppu/mmio/mmio.cpp
2 views
1
#ifdef PPU_CPP
2
3
bool PPU::interlace() const {
4
return display.interlace;
5
}
6
7
bool PPU::overscan() const {
8
return display.overscan;
9
}
10
11
bool PPU::hires() const {
12
return true;
13
}
14
15
void PPU::latch_counters() {
16
cpu.synchronize_ppu();
17
regs.hcounter = hdot();
18
regs.vcounter = vcounter();
19
regs.counters_latched = true;
20
}
21
22
uint16 PPU::get_vram_address() {
23
uint16 addr = regs.vram_addr;
24
switch(regs.vram_mapping) {
25
case 0: break; //direct mapping
26
case 1: addr = (addr & 0xff00) | ((addr & 0x001f) << 3) | ((addr >> 5) & 7); break;
27
case 2: addr = (addr & 0xfe00) | ((addr & 0x003f) << 3) | ((addr >> 6) & 7); break;
28
case 3: addr = (addr & 0xfc00) | ((addr & 0x007f) << 3) | ((addr >> 7) & 7); break;
29
}
30
return (addr << 1);
31
}
32
33
uint8 PPU::vram_read(unsigned addr) {
34
debugger.vram_read(addr);
35
36
if(regs.display_disable || vcounter() >= (!regs.overscan ? 225 : 240)) {
37
return vram[addr];
38
}
39
return 0x00;
40
}
41
42
void PPU::vram_write(unsigned addr, uint8 data) {
43
debugger.vram_write(addr, data);
44
45
if(regs.display_disable || vcounter() >= (!regs.overscan ? 225 : 240)) {
46
vram[addr] = data;
47
}
48
}
49
50
uint8 PPU::oam_read(unsigned addr) {
51
debugger.oam_read(addr);
52
53
return oam[addr];
54
}
55
56
void PPU::oam_write(unsigned addr, uint8 data) {
57
debugger.oam_write(addr, data);
58
59
oam[addr] = data;
60
sprite.update(addr, data);
61
}
62
63
uint8 PPU::cgram_read(unsigned addr) {
64
debugger.cgram_read(addr);
65
66
return cgram[addr];
67
}
68
69
void PPU::cgram_write(unsigned addr, uint8 data) {
70
debugger.cgram_write(addr, data);
71
72
cgram[addr] = data;
73
}
74
75
void PPU::mmio_update_video_mode() {
76
switch(regs.bgmode) {
77
case 0: {
78
bg1.regs.mode = Background::Mode::BPP2; bg1.regs.priority0 = 8; bg1.regs.priority1 = 11;
79
bg2.regs.mode = Background::Mode::BPP2; bg2.regs.priority0 = 7; bg2.regs.priority1 = 10;
80
bg3.regs.mode = Background::Mode::BPP2; bg3.regs.priority0 = 2; bg3.regs.priority1 = 5;
81
bg4.regs.mode = Background::Mode::BPP2; bg4.regs.priority0 = 1; bg4.regs.priority1 = 4;
82
sprite.regs.priority0 = 3; sprite.regs.priority1 = 6; sprite.regs.priority2 = 9; sprite.regs.priority3 = 12;
83
} break;
84
85
case 1: {
86
bg1.regs.mode = Background::Mode::BPP4;
87
bg2.regs.mode = Background::Mode::BPP4;
88
bg3.regs.mode = Background::Mode::BPP2;
89
bg4.regs.mode = Background::Mode::Inactive;
90
if(regs.bg3_priority) {
91
bg1.regs.priority0 = 5; bg1.regs.priority1 = 8;
92
bg2.regs.priority0 = 4; bg2.regs.priority1 = 7;
93
bg3.regs.priority0 = 1; bg3.regs.priority1 = 10;
94
sprite.regs.priority0 = 2; sprite.regs.priority1 = 3; sprite.regs.priority2 = 6; sprite.regs.priority3 = 9;
95
} else {
96
bg1.regs.priority0 = 6; bg1.regs.priority1 = 9;
97
bg2.regs.priority0 = 5; bg2.regs.priority1 = 8;
98
bg3.regs.priority0 = 1; bg3.regs.priority1 = 3;
99
sprite.regs.priority0 = 2; sprite.regs.priority1 = 4; sprite.regs.priority2 = 7; sprite.regs.priority3 = 10;
100
}
101
} break;
102
103
case 2: {
104
bg1.regs.mode = Background::Mode::BPP4;
105
bg2.regs.mode = Background::Mode::BPP4;
106
bg3.regs.mode = Background::Mode::Inactive;
107
bg4.regs.mode = Background::Mode::Inactive;
108
bg1.regs.priority0 = 3; bg1.regs.priority1 = 7;
109
bg2.regs.priority0 = 1; bg2.regs.priority1 = 5;
110
sprite.regs.priority0 = 2; sprite.regs.priority1 = 4; sprite.regs.priority2 = 6; sprite.regs.priority3 = 8;
111
} break;
112
113
case 3: {
114
bg1.regs.mode = Background::Mode::BPP8;
115
bg2.regs.mode = Background::Mode::BPP4;
116
bg3.regs.mode = Background::Mode::Inactive;
117
bg4.regs.mode = Background::Mode::Inactive;
118
bg1.regs.priority0 = 3; bg1.regs.priority1 = 7;
119
bg2.regs.priority0 = 1; bg2.regs.priority1 = 5;
120
sprite.regs.priority0 = 2; sprite.regs.priority1 = 4; sprite.regs.priority2 = 6; sprite.regs.priority3 = 8;
121
} break;
122
123
case 4: {
124
bg1.regs.mode = Background::Mode::BPP8;
125
bg2.regs.mode = Background::Mode::BPP2;
126
bg3.regs.mode = Background::Mode::Inactive;
127
bg4.regs.mode = Background::Mode::Inactive;
128
bg1.regs.priority0 = 3; bg1.regs.priority1 = 7;
129
bg2.regs.priority0 = 1; bg2.regs.priority1 = 5;
130
sprite.regs.priority0 = 2; sprite.regs.priority1 = 4; sprite.regs.priority2 = 6; sprite.regs.priority3 = 8;
131
} break;
132
133
case 5: {
134
bg1.regs.mode = Background::Mode::BPP4;
135
bg2.regs.mode = Background::Mode::BPP2;
136
bg3.regs.mode = Background::Mode::Inactive;
137
bg4.regs.mode = Background::Mode::Inactive;
138
bg1.regs.priority0 = 3; bg1.regs.priority1 = 7;
139
bg2.regs.priority0 = 1; bg2.regs.priority1 = 5;
140
sprite.regs.priority0 = 2; sprite.regs.priority1 = 4; sprite.regs.priority2 = 6; sprite.regs.priority3 = 8;
141
} break;
142
143
case 6: {
144
bg1.regs.mode = Background::Mode::BPP4;
145
bg2.regs.mode = Background::Mode::Inactive;
146
bg3.regs.mode = Background::Mode::Inactive;
147
bg4.regs.mode = Background::Mode::Inactive;
148
bg1.regs.priority0 = 2; bg1.regs.priority1 = 5;
149
sprite.regs.priority0 = 1; sprite.regs.priority1 = 3; sprite.regs.priority2 = 4; sprite.regs.priority3 = 6;
150
} break;
151
152
case 7: {
153
if(regs.mode7_extbg == false) {
154
bg1.regs.mode = Background::Mode::Mode7;
155
bg2.regs.mode = Background::Mode::Inactive;
156
bg3.regs.mode = Background::Mode::Inactive;
157
bg4.regs.mode = Background::Mode::Inactive;
158
bg1.regs.priority0 = 2; bg1.regs.priority1 = 2;
159
sprite.regs.priority0 = 1; sprite.regs.priority1 = 3; sprite.regs.priority2 = 4; sprite.regs.priority3 = 5;
160
} else {
161
bg1.regs.mode = Background::Mode::Mode7;
162
bg2.regs.mode = Background::Mode::Mode7;
163
bg3.regs.mode = Background::Mode::Inactive;
164
bg4.regs.mode = Background::Mode::Inactive;
165
bg1.regs.priority0 = 3; bg1.regs.priority1 = 3;
166
bg2.regs.priority0 = 1; bg2.regs.priority1 = 5;
167
sprite.regs.priority0 = 2; sprite.regs.priority1 = 4; sprite.regs.priority2 = 6; sprite.regs.priority3 = 7;
168
}
169
} break;
170
}
171
}
172
173
//INIDISP
174
void PPU::mmio_w2100(uint8 data) {
175
if(regs.display_disable && vcounter() == (!regs.overscan ? 225 : 240)) sprite.address_reset();
176
regs.display_disable = data & 0x80;
177
regs.display_brightness = data & 0x0f;
178
}
179
180
//OBSEL
181
void PPU::mmio_w2101(uint8 data) {
182
sprite.regs.base_size = (data >> 5) & 7;
183
sprite.regs.nameselect = (data >> 3) & 3;
184
sprite.regs.tiledata_addr = (data & 3) << 14;
185
}
186
187
//OAMADDL
188
void PPU::mmio_w2102(uint8 data) {
189
regs.oam_baseaddr = (regs.oam_baseaddr & 0x0200) | (data << 1);
190
sprite.address_reset();
191
}
192
193
//OAMADDH
194
void PPU::mmio_w2103(uint8 data) {
195
regs.oam_priority = data & 0x80;
196
regs.oam_baseaddr = ((data & 0x01) << 9) | (regs.oam_baseaddr & 0x01fe);
197
sprite.address_reset();
198
}
199
200
//OAMDATA
201
void PPU::mmio_w2104(uint8 data) {
202
bool latch = regs.oam_addr & 1;
203
uint10 addr = regs.oam_addr++;
204
if(regs.display_disable == false && vcounter() < (!regs.overscan ? 225 : 240)) addr = regs.oam_iaddr;
205
if(addr & 0x0200) addr &= 0x021f;
206
207
if(latch == 0) regs.oam_latchdata = data;
208
if(addr & 0x0200) {
209
oam_write(addr, data);
210
} else if(latch == 1) {
211
oam_write((addr & ~1) + 0, regs.oam_latchdata);
212
oam_write((addr & ~1) + 1, data);
213
}
214
sprite.set_first_sprite();
215
}
216
217
//BGMODE
218
void PPU::mmio_w2105(uint8 data) {
219
bg4.regs.tile_size = (data & 0x80);
220
bg3.regs.tile_size = (data & 0x40);
221
bg2.regs.tile_size = (data & 0x20);
222
bg1.regs.tile_size = (data & 0x10);
223
regs.bg3_priority = (data & 0x08);
224
regs.bgmode = (data & 0x07);
225
mmio_update_video_mode();
226
}
227
228
//MOSAIC
229
void PPU::mmio_w2106(uint8 data) {
230
unsigned mosaic_size = (data >> 4) & 15;
231
bg4.regs.mosaic = (data & 0x08 ? mosaic_size : 0);
232
bg3.regs.mosaic = (data & 0x04 ? mosaic_size : 0);
233
bg2.regs.mosaic = (data & 0x02 ? mosaic_size : 0);
234
bg1.regs.mosaic = (data & 0x01 ? mosaic_size : 0);
235
}
236
237
//BG1SC
238
void PPU::mmio_w2107(uint8 data) {
239
bg1.regs.screen_addr = (data & 0x7c) << 9;
240
bg1.regs.screen_size = data & 3;
241
}
242
243
//BG2SC
244
void PPU::mmio_w2108(uint8 data) {
245
bg2.regs.screen_addr = (data & 0x7c) << 9;
246
bg2.regs.screen_size = data & 3;
247
}
248
249
//BG3SC
250
void PPU::mmio_w2109(uint8 data) {
251
bg3.regs.screen_addr = (data & 0x7c) << 9;
252
bg3.regs.screen_size = data & 3;
253
}
254
255
//BG4SC
256
void PPU::mmio_w210a(uint8 data) {
257
bg4.regs.screen_addr = (data & 0x7c) << 9;
258
bg4.regs.screen_size = data & 3;
259
}
260
261
//BG12NBA
262
void PPU::mmio_w210b(uint8 data) {
263
bg1.regs.tiledata_addr = (data & 0x07) << 13;
264
bg2.regs.tiledata_addr = (data & 0x70) << 9;
265
}
266
267
//BG34NBA
268
void PPU::mmio_w210c(uint8 data) {
269
bg3.regs.tiledata_addr = (data & 0x07) << 13;
270
bg4.regs.tiledata_addr = (data & 0x70) << 9;
271
}
272
273
//BG1HOFS
274
void PPU::mmio_w210d(uint8 data) {
275
regs.mode7_hoffset = (data << 8) | regs.mode7_latchdata;
276
regs.mode7_latchdata = data;
277
278
bg1.regs.hoffset = (data << 8) | (regs.bgofs_latchdata & ~7) | ((bg1.regs.hoffset >> 8) & 7);
279
regs.bgofs_latchdata = data;
280
}
281
282
//BG1VOFS
283
void PPU::mmio_w210e(uint8 data) {
284
regs.mode7_voffset = (data << 8) | regs.mode7_latchdata;
285
regs.mode7_latchdata = data;
286
287
bg1.regs.voffset = (data << 8) | regs.bgofs_latchdata;
288
regs.bgofs_latchdata = data;
289
}
290
291
//BG2HOFS
292
void PPU::mmio_w210f(uint8 data) {
293
bg2.regs.hoffset = (data << 8) | (regs.bgofs_latchdata & ~7) | ((bg2.regs.hoffset >> 8) & 7);
294
regs.bgofs_latchdata = data;
295
}
296
297
//BG2VOFS
298
void PPU::mmio_w2110(uint8 data) {
299
bg2.regs.voffset = (data << 8) | regs.bgofs_latchdata;
300
regs.bgofs_latchdata = data;
301
}
302
303
//BG3HOFS
304
void PPU::mmio_w2111(uint8 data) {
305
bg3.regs.hoffset = (data << 8) | (regs.bgofs_latchdata & ~7) | ((bg3.regs.hoffset >> 8) & 7);
306
regs.bgofs_latchdata = data;
307
}
308
309
//BG3VOFS
310
void PPU::mmio_w2112(uint8 data) {
311
bg3.regs.voffset = (data << 8) | regs.bgofs_latchdata;
312
regs.bgofs_latchdata = data;
313
}
314
315
//BG4HOFS
316
void PPU::mmio_w2113(uint8 data) {
317
bg4.regs.hoffset = (data << 8) | (regs.bgofs_latchdata & ~7) | ((bg4.regs.hoffset >> 8) & 7);
318
regs.bgofs_latchdata = data;
319
}
320
321
//BG4VOFS
322
void PPU::mmio_w2114(uint8 data) {
323
bg4.regs.voffset = (data << 8) | regs.bgofs_latchdata;
324
regs.bgofs_latchdata = data;
325
}
326
327
//VMAIN
328
void PPU::mmio_w2115(uint8 data) {
329
regs.vram_incmode = data & 0x80;
330
regs.vram_mapping = (data >> 2) & 3;
331
switch(data & 3) {
332
case 0: regs.vram_incsize = 1; break;
333
case 1: regs.vram_incsize = 32; break;
334
case 2: regs.vram_incsize = 128; break;
335
case 3: regs.vram_incsize = 128; break;
336
}
337
}
338
339
//VMADDL
340
void PPU::mmio_w2116(uint8 data) {
341
regs.vram_addr &= 0xff00;
342
regs.vram_addr |= (data << 0);
343
uint16 addr = get_vram_address();
344
regs.vram_readbuffer = vram_read(addr + 0) << 0;
345
regs.vram_readbuffer |= vram_read(addr + 1) << 8;
346
}
347
348
//VMADDH
349
void PPU::mmio_w2117(uint8 data) {
350
regs.vram_addr &= 0x00ff;
351
regs.vram_addr |= (data << 8);
352
uint16 addr = get_vram_address();
353
regs.vram_readbuffer = vram_read(addr + 0) << 0;
354
regs.vram_readbuffer |= vram_read(addr + 1) << 8;
355
}
356
357
//VMDATAL
358
void PPU::mmio_w2118(uint8 data) {
359
uint16 addr = get_vram_address() + 0;
360
vram_write(addr, data);
361
if(regs.vram_incmode == 0) regs.vram_addr += regs.vram_incsize;
362
}
363
364
//VMDATAH
365
void PPU::mmio_w2119(uint8 data) {
366
uint16 addr = get_vram_address() + 1;
367
vram_write(addr, data);
368
if(regs.vram_incmode == 1) regs.vram_addr += regs.vram_incsize;
369
}
370
371
//M7SEL
372
void PPU::mmio_w211a(uint8 data) {
373
regs.mode7_repeat = (data >> 6) & 3;
374
regs.mode7_vflip = data & 0x02;
375
regs.mode7_hflip = data & 0x01;
376
}
377
378
//M7A
379
void PPU::mmio_w211b(uint8 data) {
380
regs.m7a = (data << 8) | regs.mode7_latchdata;
381
regs.mode7_latchdata = data;
382
}
383
384
//M7B
385
void PPU::mmio_w211c(uint8 data) {
386
regs.m7b = (data << 8) | regs.mode7_latchdata;
387
regs.mode7_latchdata = data;
388
}
389
390
//M7C
391
void PPU::mmio_w211d(uint8 data) {
392
regs.m7c = (data << 8) | regs.mode7_latchdata;
393
regs.mode7_latchdata = data;
394
}
395
396
//M7D
397
void PPU::mmio_w211e(uint8 data) {
398
regs.m7d = (data << 8) | regs.mode7_latchdata;
399
regs.mode7_latchdata = data;
400
}
401
402
//M7X
403
void PPU::mmio_w211f(uint8 data) {
404
regs.m7x = (data << 8) | regs.mode7_latchdata;
405
regs.mode7_latchdata = data;
406
}
407
408
//M7Y
409
void PPU::mmio_w2120(uint8 data) {
410
regs.m7y = (data << 8) | regs.mode7_latchdata;
411
regs.mode7_latchdata = data;
412
}
413
414
//CGADD
415
void PPU::mmio_w2121(uint8 data) {
416
regs.cgram_addr = data << 1;
417
}
418
419
//CGDATA
420
void PPU::mmio_w2122(uint8 data) {
421
bool latch = regs.cgram_addr & 1;
422
uint9 addr = regs.cgram_addr++;
423
if(regs.display_disable == false
424
&& vcounter() > 0 && vcounter() < (!regs.overscan ? 225 : 240)
425
&& hcounter() >= 88 && hcounter() < 1096
426
) addr = regs.cgram_iaddr;
427
428
if(latch == 0) {
429
regs.cgram_latchdata = data;
430
} else {
431
cgram_write((addr & ~1) + 0, regs.cgram_latchdata);
432
cgram_write((addr & ~1) + 1, data & 0x7f);
433
}
434
}
435
436
//W12SEL
437
void PPU::mmio_w2123(uint8 data) {
438
window.regs.bg2_two_enable = data & 0x80;
439
window.regs.bg2_two_invert = data & 0x40;
440
window.regs.bg2_one_enable = data & 0x20;
441
window.regs.bg2_one_invert = data & 0x10;
442
window.regs.bg1_two_enable = data & 0x08;
443
window.regs.bg1_two_invert = data & 0x04;
444
window.regs.bg1_one_enable = data & 0x02;
445
window.regs.bg1_one_invert = data & 0x01;
446
}
447
448
//W34SEL
449
void PPU::mmio_w2124(uint8 data) {
450
window.regs.bg4_two_enable = data & 0x80;
451
window.regs.bg4_two_invert = data & 0x40;
452
window.regs.bg4_one_enable = data & 0x20;
453
window.regs.bg4_one_invert = data & 0x10;
454
window.regs.bg3_two_enable = data & 0x08;
455
window.regs.bg3_two_invert = data & 0x04;
456
window.regs.bg3_one_enable = data & 0x02;
457
window.regs.bg3_one_invert = data & 0x01;
458
}
459
460
//WOBJSEL
461
void PPU::mmio_w2125(uint8 data) {
462
window.regs.col_two_enable = data & 0x80;
463
window.regs.col_two_invert = data & 0x40;
464
window.regs.col_one_enable = data & 0x20;
465
window.regs.col_one_invert = data & 0x10;
466
window.regs.oam_two_enable = data & 0x08;
467
window.regs.oam_two_invert = data & 0x04;
468
window.regs.oam_one_enable = data & 0x02;
469
window.regs.oam_one_invert = data & 0x01;
470
}
471
472
//WH0
473
void PPU::mmio_w2126(uint8 data) {
474
window.regs.one_left = data;
475
}
476
477
//WH1
478
void PPU::mmio_w2127(uint8 data) {
479
window.regs.one_right = data;
480
}
481
482
//WH2
483
void PPU::mmio_w2128(uint8 data) {
484
window.regs.two_left = data;
485
}
486
487
//WH3
488
void PPU::mmio_w2129(uint8 data) {
489
window.regs.two_right = data;
490
}
491
492
//WBGLOG
493
void PPU::mmio_w212a(uint8 data) {
494
window.regs.bg4_mask = (data >> 6) & 3;
495
window.regs.bg3_mask = (data >> 4) & 3;
496
window.regs.bg2_mask = (data >> 2) & 3;
497
window.regs.bg1_mask = (data >> 0) & 3;
498
}
499
500
//WOBJLOG
501
void PPU::mmio_w212b(uint8 data) {
502
window.regs.col_mask = (data >> 2) & 3;
503
window.regs.oam_mask = (data >> 0) & 3;
504
}
505
506
//TM
507
void PPU::mmio_w212c(uint8 data) {
508
sprite.regs.main_enable = data & 0x10;
509
bg4.regs.main_enable = data & 0x08;
510
bg3.regs.main_enable = data & 0x04;
511
bg2.regs.main_enable = data & 0x02;
512
bg1.regs.main_enable = data & 0x01;
513
}
514
515
//TS
516
void PPU::mmio_w212d(uint8 data) {
517
sprite.regs.sub_enable = data & 0x10;
518
bg4.regs.sub_enable = data & 0x08;
519
bg3.regs.sub_enable = data & 0x04;
520
bg2.regs.sub_enable = data & 0x02;
521
bg1.regs.sub_enable = data & 0x01;
522
}
523
524
//TMW
525
void PPU::mmio_w212e(uint8 data) {
526
window.regs.oam_main_enable = data & 0x10;
527
window.regs.bg4_main_enable = data & 0x08;
528
window.regs.bg3_main_enable = data & 0x04;
529
window.regs.bg2_main_enable = data & 0x02;
530
window.regs.bg1_main_enable = data & 0x01;
531
}
532
533
//TSW
534
void PPU::mmio_w212f(uint8 data) {
535
window.regs.oam_sub_enable = data & 0x10;
536
window.regs.bg4_sub_enable = data & 0x08;
537
window.regs.bg3_sub_enable = data & 0x04;
538
window.regs.bg2_sub_enable = data & 0x02;
539
window.regs.bg1_sub_enable = data & 0x01;
540
}
541
542
//CGWSEL
543
void PPU::mmio_w2130(uint8 data) {
544
window.regs.col_main_mask = (data >> 6) & 3;
545
window.regs.col_sub_mask = (data >> 4) & 3;
546
screen.regs.addsub_mode = data & 0x02;
547
screen.regs.direct_color = data & 0x01;
548
}
549
550
//CGADDSUB
551
void PPU::mmio_w2131(uint8 data) {
552
screen.regs.color_mode = data & 0x80;
553
screen.regs.color_halve = data & 0x40;
554
screen.regs.back_color_enable = data & 0x20;
555
screen.regs.oam_color_enable = data & 0x10;
556
screen.regs.bg4_color_enable = data & 0x08;
557
screen.regs.bg3_color_enable = data & 0x04;
558
screen.regs.bg2_color_enable = data & 0x02;
559
screen.regs.bg1_color_enable = data & 0x01;
560
}
561
562
//COLDATA
563
void PPU::mmio_w2132(uint8 data) {
564
if(data & 0x80) screen.regs.color_b = data & 0x1f;
565
if(data & 0x40) screen.regs.color_g = data & 0x1f;
566
if(data & 0x20) screen.regs.color_r = data & 0x1f;
567
}
568
569
//SETINI
570
void PPU::mmio_w2133(uint8 data) {
571
regs.mode7_extbg = data & 0x40;
572
regs.pseudo_hires = data & 0x08;
573
regs.overscan = data & 0x04;
574
sprite.regs.interlace = data & 0x02;
575
regs.interlace = data & 0x01;
576
mmio_update_video_mode();
577
}
578
579
//MPYL
580
uint8 PPU::mmio_r2134() {
581
unsigned result = ((int16)regs.m7a * (int8)(regs.m7b >> 8));
582
regs.ppu1_mdr = (result >> 0);
583
return regs.ppu1_mdr;
584
}
585
586
//MPYM
587
uint8 PPU::mmio_r2135() {
588
unsigned result = ((int16)regs.m7a * (int8)(regs.m7b >> 8));
589
regs.ppu1_mdr = (result >> 8);
590
return regs.ppu1_mdr;
591
}
592
593
//MPYH
594
uint8 PPU::mmio_r2136() {
595
unsigned result = ((int16)regs.m7a * (int8)(regs.m7b >> 8));
596
regs.ppu1_mdr = (result >> 16);
597
return regs.ppu1_mdr;
598
}
599
600
//SLHV
601
uint8 PPU::mmio_r2137() {
602
if(cpu.pio() & 0x80) latch_counters();
603
return cpu.regs.mdr;
604
}
605
606
//OAMDATAREAD
607
uint8 PPU::mmio_r2138() {
608
uint10 addr = regs.oam_addr++;
609
if(regs.display_disable == false && vcounter() < (!regs.overscan ? 225 : 240)) addr = regs.oam_iaddr;
610
if(addr & 0x0200) addr &= 0x021f;
611
612
regs.ppu1_mdr = oam_read(addr);
613
sprite.set_first_sprite();
614
return regs.ppu1_mdr;
615
}
616
617
//VMDATALREAD
618
uint8 PPU::mmio_r2139() {
619
uint16 addr = get_vram_address() + 0;
620
regs.ppu1_mdr = regs.vram_readbuffer >> 0;
621
if(regs.vram_incmode == 0) {
622
addr &= ~1;
623
regs.vram_readbuffer = vram_read(addr + 0) << 0;
624
regs.vram_readbuffer |= vram_read(addr + 1) << 8;
625
regs.vram_addr += regs.vram_incsize;
626
}
627
return regs.ppu1_mdr;
628
}
629
630
//VMDATAHREAD
631
uint8 PPU::mmio_r213a() {
632
uint16 addr = get_vram_address() + 1;
633
regs.ppu1_mdr = regs.vram_readbuffer >> 8;
634
if(regs.vram_incmode == 1) {
635
addr &= ~1;
636
regs.vram_readbuffer = vram_read(addr + 0) << 0;
637
regs.vram_readbuffer |= vram_read(addr + 1) << 8;
638
regs.vram_addr += regs.vram_incsize;
639
}
640
return regs.ppu1_mdr;
641
}
642
643
//CGDATAREAD
644
uint8 PPU::mmio_r213b() {
645
bool latch = regs.cgram_addr & 1;
646
uint9 addr = regs.cgram_addr++;
647
if(regs.display_disable == false
648
&& vcounter() > 0 && vcounter() < (!regs.overscan ? 225 : 240)
649
&& hcounter() >= 88 && hcounter() < 1096
650
) addr = regs.cgram_iaddr;
651
652
if(latch == 0) {
653
regs.ppu2_mdr = cgram_read(addr);
654
} else {
655
regs.ppu2_mdr &= 0x80;
656
regs.ppu2_mdr |= cgram_read(addr);
657
}
658
return regs.ppu2_mdr;
659
}
660
661
//OPHCT
662
uint8 PPU::mmio_r213c() {
663
if(regs.latch_hcounter == 0) {
664
regs.ppu2_mdr = (regs.hcounter >> 0);
665
} else {
666
regs.ppu2_mdr &= 0xfe;
667
regs.ppu2_mdr |= (regs.hcounter >> 8) & 1;
668
}
669
regs.latch_hcounter ^= 1;
670
return regs.ppu2_mdr;
671
}
672
673
//OPVCT
674
uint8 PPU::mmio_r213d() {
675
if(regs.latch_vcounter == 0) {
676
regs.ppu2_mdr = (regs.vcounter >> 0);
677
} else {
678
regs.ppu2_mdr &= 0xfe;
679
regs.ppu2_mdr |= (regs.vcounter >> 8) & 1;
680
}
681
regs.latch_vcounter ^= 1;
682
return regs.ppu2_mdr;
683
}
684
685
//STAT77
686
uint8 PPU::mmio_r213e() {
687
regs.ppu1_mdr &= 0x10;
688
regs.ppu1_mdr |= sprite.regs.time_over << 7;
689
regs.ppu1_mdr |= sprite.regs.range_over << 6;
690
regs.ppu1_mdr |= ppu1_version & 0x0f;
691
return regs.ppu1_mdr;
692
}
693
694
//STAT78
695
uint8 PPU::mmio_r213f() {
696
regs.latch_hcounter = 0;
697
regs.latch_vcounter = 0;
698
699
regs.ppu2_mdr &= 0x20;
700
regs.ppu2_mdr |= field() << 7;
701
if((cpu.pio() & 0x80) == 0) {
702
regs.ppu2_mdr |= 0x40;
703
} else if(regs.counters_latched) {
704
regs.ppu2_mdr |= 0x40;
705
regs.counters_latched = false;
706
}
707
regs.ppu2_mdr |= (system.region() == System::Region::NTSC ? 0 : 1) << 4;
708
regs.ppu2_mdr |= ppu2_version & 0x0f;
709
return regs.ppu2_mdr;
710
}
711
712
void PPU::mmio_reset() {
713
regs.ppu1_mdr = random(0xff);
714
regs.ppu2_mdr = random(0xff);
715
716
regs.vram_readbuffer = random(0x0000);
717
regs.oam_latchdata = random(0x00);
718
regs.cgram_latchdata = random(0x00);
719
regs.bgofs_latchdata = random(0x00);
720
regs.mode7_latchdata = random(0x00);
721
regs.counters_latched = false;
722
regs.latch_hcounter = 0;
723
regs.latch_vcounter = 0;
724
725
regs.oam_iaddr = 0x0000;
726
regs.cgram_iaddr = 0x00;
727
728
//$2100 INIDISP
729
regs.display_disable = true;
730
regs.display_brightness = 0;
731
732
//$2102 OAMADDL
733
//$2103 OAMADDH
734
regs.oam_baseaddr = random(0x0000);
735
regs.oam_addr = random(0x0000);
736
regs.oam_priority = random(false);
737
738
//$2105 BGMODE
739
regs.bg3_priority = false;
740
regs.bgmode = 0;
741
742
//$210d BG1HOFS
743
regs.mode7_hoffset = random(0x0000);
744
745
//$210e BG1VOFS
746
regs.mode7_voffset = random(0x0000);
747
748
//$2115 VMAIN
749
regs.vram_incmode = random(1);
750
regs.vram_mapping = random(0);
751
regs.vram_incsize = 1;
752
753
//$2116 VMADDL
754
//$2117 VMADDH
755
regs.vram_addr = random(0x0000);
756
757
//$211a M7SEL
758
regs.mode7_repeat = random(0);
759
regs.mode7_vflip = random(false);
760
regs.mode7_hflip = random(false);
761
762
//$211b M7A
763
regs.m7a = random(0x0000);
764
765
//$211c M7B
766
regs.m7b = random(0x0000);
767
768
//$211d M7C
769
regs.m7c = random(0x0000);
770
771
//$211e M7D
772
regs.m7d = random(0x0000);
773
774
//$211f M7X
775
regs.m7x = random(0x0000);
776
777
//$2120 M7Y
778
regs.m7y = random(0x0000);
779
780
//$2121 CGADD
781
regs.cgram_addr = random(0x0000);
782
783
//$2133 SETINI
784
regs.mode7_extbg = random(false);
785
regs.pseudo_hires = random(false);
786
regs.overscan = false;
787
regs.interlace = false;
788
789
//$213c OPHCT
790
regs.hcounter = 0;
791
792
//$213d OPVCT
793
regs.vcounter = 0;
794
}
795
796
uint8 PPU::mmio_read(unsigned addr) {
797
cpu.synchronize_ppu();
798
799
switch(addr & 0xffff) {
800
case 0x2104:
801
case 0x2105:
802
case 0x2106:
803
case 0x2108:
804
case 0x2109:
805
case 0x210a:
806
case 0x2114:
807
case 0x2115:
808
case 0x2116:
809
case 0x2118:
810
case 0x2119:
811
case 0x211a:
812
case 0x2124:
813
case 0x2125:
814
case 0x2126:
815
case 0x2128:
816
case 0x2129:
817
case 0x212a: return regs.ppu1_mdr;
818
case 0x2134: return mmio_r2134(); //MPYL
819
case 0x2135: return mmio_r2135(); //MPYM
820
case 0x2136: return mmio_r2136(); //MYPH
821
case 0x2137: return mmio_r2137(); //SLHV
822
case 0x2138: return mmio_r2138(); //OAMDATAREAD
823
case 0x2139: return mmio_r2139(); //VMDATALREAD
824
case 0x213a: return mmio_r213a(); //VMDATAHREAD
825
case 0x213b: return mmio_r213b(); //CGDATAREAD
826
case 0x213c: return mmio_r213c(); //OPHCT
827
case 0x213d: return mmio_r213d(); //OPVCT
828
case 0x213e: return mmio_r213e(); //STAT77
829
case 0x213f: return mmio_r213f(); //STAT78
830
}
831
832
return cpu.regs.mdr;
833
}
834
835
void PPU::mmio_write(unsigned addr, uint8 data) {
836
cpu.synchronize_ppu();
837
838
switch(addr & 0xffff) {
839
case 0x2100: return mmio_w2100(data); //INIDISP
840
case 0x2101: return mmio_w2101(data); //OBSEL
841
case 0x2102: return mmio_w2102(data); //OAMADDL
842
case 0x2103: return mmio_w2103(data); //OAMADDH
843
case 0x2104: return mmio_w2104(data); //OAMDATA
844
case 0x2105: return mmio_w2105(data); //BGMODE
845
case 0x2106: return mmio_w2106(data); //MOSAIC
846
case 0x2107: return mmio_w2107(data); //BG1SC
847
case 0x2108: return mmio_w2108(data); //BG2SC
848
case 0x2109: return mmio_w2109(data); //BG3SC
849
case 0x210a: return mmio_w210a(data); //BG4SC
850
case 0x210b: return mmio_w210b(data); //BG12NBA
851
case 0x210c: return mmio_w210c(data); //BG34NBA
852
case 0x210d: return mmio_w210d(data); //BG1HOFS
853
case 0x210e: return mmio_w210e(data); //BG1VOFS
854
case 0x210f: return mmio_w210f(data); //BG2HOFS
855
case 0x2110: return mmio_w2110(data); //BG2VOFS
856
case 0x2111: return mmio_w2111(data); //BG3HOFS
857
case 0x2112: return mmio_w2112(data); //BG3VOFS
858
case 0x2113: return mmio_w2113(data); //BG4HOFS
859
case 0x2114: return mmio_w2114(data); //BG4VOFS
860
case 0x2115: return mmio_w2115(data); //VMAIN
861
case 0x2116: return mmio_w2116(data); //VMADDL
862
case 0x2117: return mmio_w2117(data); //VMADDH
863
case 0x2118: return mmio_w2118(data); //VMDATAL
864
case 0x2119: return mmio_w2119(data); //VMDATAH
865
case 0x211a: return mmio_w211a(data); //M7SEL
866
case 0x211b: return mmio_w211b(data); //M7A
867
case 0x211c: return mmio_w211c(data); //M7B
868
case 0x211d: return mmio_w211d(data); //M7C
869
case 0x211e: return mmio_w211e(data); //M7D
870
case 0x211f: return mmio_w211f(data); //M7X
871
case 0x2120: return mmio_w2120(data); //M7Y
872
case 0x2121: return mmio_w2121(data); //CGADD
873
case 0x2122: return mmio_w2122(data); //CGDATA
874
case 0x2123: return mmio_w2123(data); //W12SEL
875
case 0x2124: return mmio_w2124(data); //W34SEL
876
case 0x2125: return mmio_w2125(data); //WOBJSEL
877
case 0x2126: return mmio_w2126(data); //WH0
878
case 0x2127: return mmio_w2127(data); //WH1
879
case 0x2128: return mmio_w2128(data); //WH2
880
case 0x2129: return mmio_w2129(data); //WH3
881
case 0x212a: return mmio_w212a(data); //WBGLOG
882
case 0x212b: return mmio_w212b(data); //WOBJLOG
883
case 0x212c: return mmio_w212c(data); //TM
884
case 0x212d: return mmio_w212d(data); //TS
885
case 0x212e: return mmio_w212e(data); //TMW
886
case 0x212f: return mmio_w212f(data); //TSW
887
case 0x2130: return mmio_w2130(data); //CGWSEL
888
case 0x2131: return mmio_w2131(data); //CGADDSUB
889
case 0x2132: return mmio_w2132(data); //COLDATA
890
case 0x2133: return mmio_w2133(data); //SETINI
891
}
892
}
893
894
#endif
895
896