Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
alexbevi
GitHub Repository: alexbevi/BizHawk
Path: blob/master/libsnes/bsnes/snes/cpu/mmio/mmio.cpp
2 views
1
#ifdef CPU_CPP
2
3
uint8 CPU::pio() { return status.pio; }
4
bool CPU::joylatch() { return status.joypad_strobe_latch; }
5
6
//WMDATA
7
uint8 CPU::mmio_r2180() {
8
return bus.read(0x7e0000 | status.wram_addr++);
9
}
10
11
//WMDATA
12
void CPU::mmio_w2180(uint8 data) {
13
bus.write(0x7e0000 | status.wram_addr++, data);
14
}
15
16
//WMADDL
17
void CPU::mmio_w2181(uint8 data) {
18
status.wram_addr = (status.wram_addr & 0x01ff00) | (data << 0);
19
}
20
21
//WMADDM
22
void CPU::mmio_w2182(uint8 data) {
23
status.wram_addr = (status.wram_addr & 0x0100ff) | (data << 8);
24
}
25
26
//WMADDH
27
void CPU::mmio_w2183(uint8 data) {
28
status.wram_addr = (status.wram_addr & 0x00ffff) | (data << 16);
29
}
30
31
//JOYSER0
32
//bit 0 is shared between JOYSER0 and JOYSER1, therefore
33
//strobing $4016.d0 affects both controller port latches.
34
//$4017 bit 0 writes are ignored.
35
void CPU::mmio_w4016(uint8 data) {
36
input.port1->latch(data & 1);
37
input.port2->latch(data & 1);
38
interface()->inputNotify(data & 1);
39
}
40
41
//JOYSER0
42
//7-2 = MDR
43
//1-0 = Joypad serial data
44
uint8 CPU::mmio_r4016() {
45
uint8 r = regs.mdr & 0xfc;
46
r |= input.port1->data();
47
if (!status.auto_joypad_poll) interface()->inputNotify(0x4016);
48
return r;
49
}
50
51
//JOYSER1
52
//7-5 = MDR
53
//4-2 = Always 1 (pins are connected to GND)
54
//1-0 = Joypad serial data
55
uint8 CPU::mmio_r4017() {
56
uint8 r = (regs.mdr & 0xe0) | 0x1c;
57
r |= input.port2->data();
58
if (!status.auto_joypad_poll) interface()->inputNotify(0x4017);
59
return r;
60
}
61
62
//NMITIMEN
63
void CPU::mmio_w4200(uint8 data) {
64
status.auto_joypad_poll = data & 1;
65
nmitimen_update(data);
66
}
67
68
//WRIO
69
void CPU::mmio_w4201(uint8 data) {
70
if((status.pio & 0x80) && !(data & 0x80)) ppu.latch_counters();
71
status.pio = data;
72
}
73
74
//WRMPYA
75
void CPU::mmio_w4202(uint8 data) {
76
status.wrmpya = data;
77
}
78
79
//WRMPYB
80
void CPU::mmio_w4203(uint8 data) {
81
status.rdmpy = 0;
82
if(alu.mpyctr || alu.divctr) return;
83
84
status.wrmpyb = data;
85
status.rddiv = (status.wrmpyb << 8) | status.wrmpya;
86
87
alu.mpyctr = 8; //perform multiplication over the next eight cycles
88
alu.shift = status.wrmpyb;
89
}
90
91
//WRDIVL
92
void CPU::mmio_w4204(uint8 data) {
93
status.wrdiva = (status.wrdiva & 0xff00) | (data << 0);
94
}
95
96
//WRDIVH
97
void CPU::mmio_w4205(uint8 data) {
98
status.wrdiva = (status.wrdiva & 0x00ff) | (data << 8);
99
}
100
101
//WRDIVB
102
void CPU::mmio_w4206(uint8 data) {
103
status.rdmpy = status.wrdiva;
104
if(alu.mpyctr || alu.divctr) return;
105
106
status.wrdivb = data;
107
108
alu.divctr = 16; //perform division over the next sixteen cycles
109
alu.shift = status.wrdivb << 16;
110
}
111
112
//HTIMEL
113
void CPU::mmio_w4207(uint8 data) {
114
status.hirq_pos = (status.hirq_pos & 0x0100) | (data << 0);
115
}
116
117
//HTIMEH
118
void CPU::mmio_w4208(uint8 data) {
119
status.hirq_pos = (status.hirq_pos & 0x00ff) | (data << 8);
120
}
121
122
//VTIMEL
123
void CPU::mmio_w4209(uint8 data) {
124
status.virq_pos = (status.virq_pos & 0x0100) | (data << 0);
125
}
126
127
//VTIMEH
128
void CPU::mmio_w420a(uint8 data) {
129
status.virq_pos = (status.virq_pos & 0x00ff) | (data << 8);
130
}
131
132
//DMAEN
133
void CPU::mmio_w420b(uint8 data) {
134
for(unsigned i = 0; i < 8; i++) {
135
channel[i].dma_enabled = data & (1 << i);
136
}
137
if(data) status.dma_pending = true;
138
}
139
140
//HDMAEN
141
void CPU::mmio_w420c(uint8 data) {
142
for(unsigned i = 0; i < 8; i++) {
143
channel[i].hdma_enabled = data & (1 << i);
144
}
145
}
146
147
//MEMSEL
148
void CPU::mmio_w420d(uint8 data) {
149
status.rom_speed = (data & 1 ? 6 : 8);
150
}
151
152
//RDNMI
153
//7 = NMI acknowledge
154
//6-4 = MDR
155
//3-0 = CPU (5a22) version
156
uint8 CPU::mmio_r4210() {
157
uint8 r = (regs.mdr & 0x70);
158
r |= (uint8)(rdnmi()) << 7;
159
r |= (cpu_version & 0x0f);
160
return r;
161
}
162
163
//TIMEUP
164
//7 = IRQ acknowledge
165
//6-0 = MDR
166
uint8 CPU::mmio_r4211() {
167
uint8 r = (regs.mdr & 0x7f);
168
r |= (uint8)(timeup()) << 7;
169
return r;
170
}
171
172
//HVBJOY
173
//7 = VBLANK acknowledge
174
//6 = HBLANK acknowledge
175
//5-1 = MDR
176
//0 = JOYPAD acknowledge
177
uint8 CPU::mmio_r4212() {
178
uint8 r = (regs.mdr & 0x3e);
179
if(status.auto_joypad_active) r |= 0x01;
180
if(hcounter() <= 2 || hcounter() >= 1096) r |= 0x40; //hblank
181
if(vcounter() >= (ppu.overscan() == false ? 225 : 240)) r |= 0x80; //vblank
182
return r;
183
}
184
185
//RDIO
186
uint8 CPU::mmio_r4213() {
187
// interface()->inputNotify(0x4213); // if there are lag counter issues with super scope, uncomment this
188
return status.pio;
189
}
190
191
//RDDIVL
192
uint8 CPU::mmio_r4214() {
193
return status.rddiv >> 0;
194
}
195
196
//RDDIVH
197
uint8 CPU::mmio_r4215() {
198
return status.rddiv >> 8;
199
}
200
201
//RDMPYL
202
uint8 CPU::mmio_r4216() {
203
return status.rdmpy >> 0;
204
}
205
206
//RDMPYH
207
uint8 CPU::mmio_r4217() {
208
return status.rdmpy >> 8;
209
}
210
211
uint8 CPU::mmio_r4218() { interface()->inputNotify(0x4218); return status.joy1 >> 0; } //JOY1L
212
uint8 CPU::mmio_r4219() { interface()->inputNotify(0x4219); return status.joy1 >> 8; } //JOY1H
213
uint8 CPU::mmio_r421a() { interface()->inputNotify(0x421a); return status.joy2 >> 0; } //JOY2L
214
uint8 CPU::mmio_r421b() { interface()->inputNotify(0x421b); return status.joy2 >> 8; } //JOY2H
215
uint8 CPU::mmio_r421c() { interface()->inputNotify(0x421c); return status.joy3 >> 0; } //JOY3L
216
uint8 CPU::mmio_r421d() { interface()->inputNotify(0x421d); return status.joy3 >> 8; } //JOY3H
217
uint8 CPU::mmio_r421e() { interface()->inputNotify(0x421e); return status.joy4 >> 0; } //JOY4L
218
uint8 CPU::mmio_r421f() { interface()->inputNotify(0x421f); return status.joy4 >> 8; } //JOY4H
219
220
//DMAPx
221
uint8 CPU::mmio_r43x0(uint8 i) {
222
return (channel[i].direction << 7)
223
| (channel[i].indirect << 6)
224
| (channel[i].unused << 5)
225
| (channel[i].reverse_transfer << 4)
226
| (channel[i].fixed_transfer << 3)
227
| (channel[i].transfer_mode << 0);
228
}
229
230
//BBADx
231
uint8 CPU::mmio_r43x1(uint8 i) {
232
return channel[i].dest_addr;
233
}
234
235
//A1TxL
236
uint8 CPU::mmio_r43x2(uint8 i) {
237
return channel[i].source_addr >> 0;
238
}
239
240
//A1TxH
241
uint8 CPU::mmio_r43x3(uint8 i) {
242
return channel[i].source_addr >> 8;
243
}
244
245
//A1Bx
246
uint8 CPU::mmio_r43x4(uint8 i) {
247
return channel[i].source_bank;
248
}
249
250
//DASxL
251
//union { uint16 transfer_size; uint16 indirect_addr; };
252
uint8 CPU::mmio_r43x5(uint8 i) {
253
return channel[i].transfer_size >> 0;
254
}
255
256
//DASxH
257
//union { uint16 transfer_size; uint16 indirect_addr; };
258
uint8 CPU::mmio_r43x6(uint8 i) {
259
return channel[i].transfer_size >> 8;
260
}
261
262
//DASBx
263
uint8 CPU::mmio_r43x7(uint8 i) {
264
return channel[i].indirect_bank;
265
}
266
267
//A2AxL
268
uint8 CPU::mmio_r43x8(uint8 i) {
269
return channel[i].hdma_addr >> 0;
270
}
271
272
//A2AxH
273
uint8 CPU::mmio_r43x9(uint8 i) {
274
return channel[i].hdma_addr >> 8;
275
}
276
277
//NTRLx
278
uint8 CPU::mmio_r43xa(uint8 i) {
279
return channel[i].line_counter;
280
}
281
282
//???
283
uint8 CPU::mmio_r43xb(uint8 i) {
284
return channel[i].unknown;
285
}
286
287
//DMAPx
288
void CPU::mmio_w43x0(uint8 i, uint8 data) {
289
channel[i].direction = data & 0x80;
290
channel[i].indirect = data & 0x40;
291
channel[i].unused = data & 0x20;
292
channel[i].reverse_transfer = data & 0x10;
293
channel[i].fixed_transfer = data & 0x08;
294
channel[i].transfer_mode = data & 0x07;
295
}
296
297
//DDBADx
298
void CPU::mmio_w43x1(uint8 i, uint8 data) {
299
channel[i].dest_addr = data;
300
}
301
302
//A1TxL
303
void CPU::mmio_w43x2(uint8 i, uint8 data) {
304
channel[i].source_addr = (channel[i].source_addr & 0xff00) | (data << 0);
305
}
306
307
//A1TxH
308
void CPU::mmio_w43x3(uint8 i, uint8 data) {
309
channel[i].source_addr = (channel[i].source_addr & 0x00ff) | (data << 8);
310
}
311
312
//A1Bx
313
void CPU::mmio_w43x4(uint8 i, uint8 data) {
314
channel[i].source_bank = data;
315
}
316
317
//DASxL
318
//union { uint16 transfer_size; uint16 indirect_addr; };
319
void CPU::mmio_w43x5(uint8 i, uint8 data) {
320
channel[i].transfer_size = (channel[i].transfer_size & 0xff00) | (data << 0);
321
}
322
323
//DASxH
324
//union { uint16 transfer_size; uint16 indirect_addr; };
325
void CPU::mmio_w43x6(uint8 i, uint8 data) {
326
channel[i].transfer_size = (channel[i].transfer_size & 0x00ff) | (data << 8);
327
}
328
329
//DASBx
330
void CPU::mmio_w43x7(uint8 i, uint8 data) {
331
channel[i].indirect_bank = data;
332
}
333
334
//A2AxL
335
void CPU::mmio_w43x8(uint8 i, uint8 data) {
336
channel[i].hdma_addr = (channel[i].hdma_addr & 0xff00) | (data << 0);
337
}
338
339
//A2AxH
340
void CPU::mmio_w43x9(uint8 i, uint8 data) {
341
channel[i].hdma_addr = (channel[i].hdma_addr & 0x00ff) | (data << 8);
342
}
343
344
//NTRLx
345
void CPU::mmio_w43xa(uint8 i, uint8 data) {
346
channel[i].line_counter = data;
347
}
348
349
//???
350
void CPU::mmio_w43xb(uint8 i, uint8 data) {
351
channel[i].unknown = data;
352
}
353
354
void CPU::mmio_power() {
355
}
356
357
void CPU::mmio_reset() {
358
//$2140-217f
359
for(auto &port : status.port) port = 0x00;
360
361
//$2181-$2183
362
status.wram_addr = 0x000000;
363
364
//$4016-$4017
365
status.joypad_strobe_latch = 0;
366
status.joypad1_bits = ~0;
367
status.joypad2_bits = ~0;
368
369
//$4200
370
status.nmi_enabled = false;
371
status.hirq_enabled = false;
372
status.virq_enabled = false;
373
status.auto_joypad_poll = false;
374
375
//$4201
376
status.pio = 0xff;
377
378
//$4202-$4203
379
status.wrmpya = 0xff;
380
status.wrmpyb = 0xff;
381
382
//$4204-$4206
383
status.wrdiva = 0xffff;
384
status.wrdivb = 0xff;
385
386
//$4207-$420a
387
status.hirq_pos = 0x01ff;
388
status.virq_pos = 0x01ff;
389
390
//$420d
391
status.rom_speed = 8;
392
393
//$4214-$4217
394
status.rddiv = 0x0000;
395
status.rdmpy = 0x0000;
396
397
//$4218-$421f
398
status.joy1 = 0x0000;
399
status.joy2 = 0x0000;
400
status.joy3 = 0x0000;
401
status.joy4 = 0x0000;
402
403
//ALU
404
alu.mpyctr = 0;
405
alu.divctr = 0;
406
alu.shift = 0;
407
}
408
409
uint8 CPU::mmio_read(unsigned addr) {
410
addr &= 0xffff;
411
412
//APU
413
if((addr & 0xffc0) == 0x2140) { //$2140-$217f
414
synchronize_smp();
415
return smp.port_read(addr);
416
}
417
418
//DMA
419
if((addr & 0xff80) == 0x4300) { //$4300-$437f
420
unsigned i = (addr >> 4) & 7;
421
switch(addr & 0xf) {
422
case 0x0: return mmio_r43x0(i);
423
case 0x1: return mmio_r43x1(i);
424
case 0x2: return mmio_r43x2(i);
425
case 0x3: return mmio_r43x3(i);
426
case 0x4: return mmio_r43x4(i);
427
case 0x5: return mmio_r43x5(i);
428
case 0x6: return mmio_r43x6(i);
429
case 0x7: return mmio_r43x7(i);
430
case 0x8: return mmio_r43x8(i);
431
case 0x9: return mmio_r43x9(i);
432
case 0xa: return mmio_r43xa(i);
433
case 0xb: return mmio_r43xb(i);
434
case 0xc: return regs.mdr; //unmapped
435
case 0xd: return regs.mdr; //unmapped
436
case 0xe: return regs.mdr; //unmapped
437
case 0xf: return mmio_r43xb(i); //mirror of $43xb
438
}
439
}
440
441
switch(addr) {
442
case 0x2180: return mmio_r2180();
443
case 0x4016: return mmio_r4016();
444
case 0x4017: return mmio_r4017();
445
case 0x4210: return mmio_r4210();
446
case 0x4211: return mmio_r4211();
447
case 0x4212: return mmio_r4212();
448
case 0x4213: return mmio_r4213();
449
case 0x4214: return mmio_r4214();
450
case 0x4215: return mmio_r4215();
451
case 0x4216: return mmio_r4216();
452
case 0x4217: return mmio_r4217();
453
case 0x4218: return mmio_r4218();
454
case 0x4219: return mmio_r4219();
455
case 0x421a: return mmio_r421a();
456
case 0x421b: return mmio_r421b();
457
case 0x421c: return mmio_r421c();
458
case 0x421d: return mmio_r421d();
459
case 0x421e: return mmio_r421e();
460
case 0x421f: return mmio_r421f();
461
}
462
463
return regs.mdr;
464
}
465
466
void CPU::mmio_write(unsigned addr, uint8 data) {
467
addr &= 0xffff;
468
469
//APU
470
if((addr & 0xffc0) == 0x2140) { //$2140-$217f
471
synchronize_smp();
472
port_write(addr, data);
473
return;
474
}
475
476
//DMA
477
if((addr & 0xff80) == 0x4300) { //$4300-$437f
478
unsigned i = (addr >> 4) & 7;
479
switch(addr & 0xf) {
480
case 0x0: mmio_w43x0(i, data); return;
481
case 0x1: mmio_w43x1(i, data); return;
482
case 0x2: mmio_w43x2(i, data); return;
483
case 0x3: mmio_w43x3(i, data); return;
484
case 0x4: mmio_w43x4(i, data); return;
485
case 0x5: mmio_w43x5(i, data); return;
486
case 0x6: mmio_w43x6(i, data); return;
487
case 0x7: mmio_w43x7(i, data); return;
488
case 0x8: mmio_w43x8(i, data); return;
489
case 0x9: mmio_w43x9(i, data); return;
490
case 0xa: mmio_w43xa(i, data); return;
491
case 0xb: mmio_w43xb(i, data); return;
492
case 0xc: return; //unmapped
493
case 0xd: return; //unmapped
494
case 0xe: return; //unmapped
495
case 0xf: mmio_w43xb(i, data); return; //mirror of $43xb
496
}
497
}
498
499
switch(addr) {
500
case 0x2180: mmio_w2180(data); return;
501
case 0x2181: mmio_w2181(data); return;
502
case 0x2182: mmio_w2182(data); return;
503
case 0x2183: mmio_w2183(data); return;
504
case 0x4016: mmio_w4016(data); return;
505
case 0x4017: return; //unmapped
506
case 0x4200: mmio_w4200(data); return;
507
case 0x4201: mmio_w4201(data); return;
508
case 0x4202: mmio_w4202(data); return;
509
case 0x4203: mmio_w4203(data); return;
510
case 0x4204: mmio_w4204(data); return;
511
case 0x4205: mmio_w4205(data); return;
512
case 0x4206: mmio_w4206(data); return;
513
case 0x4207: mmio_w4207(data); return;
514
case 0x4208: mmio_w4208(data); return;
515
case 0x4209: mmio_w4209(data); return;
516
case 0x420a: mmio_w420a(data); return;
517
case 0x420b: mmio_w420b(data); return;
518
case 0x420c: mmio_w420c(data); return;
519
case 0x420d: mmio_w420d(data); return;
520
}
521
}
522
523
#endif
524
525