Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
alexbevi
GitHub Repository: alexbevi/BizHawk
Path: blob/master/libsnes/bsnes/snes/smp/memory/memory.cpp
2 views
1
#ifdef SMP_CPP
2
3
alwaysinline uint8 SMP::ram_read(uint16 addr) {
4
if(addr >= 0xffc0 && status.iplrom_enable) return iplrom[addr & 0x3f];
5
if(status.ram_disable) return 0x5a; //0xff on mini-SNES
6
return apuram[addr];
7
}
8
9
alwaysinline void SMP::ram_write(uint16 addr, uint8 data) {
10
//writes to $ffc0-$ffff always go to apuram, even if the iplrom is enabled
11
if(status.ram_writable && !status.ram_disable) apuram[addr] = data;
12
}
13
14
uint8 SMP::port_read(uint2 port) const {
15
return apuram[0xf4 + port];
16
}
17
18
void SMP::port_write(uint2 port, uint8 data) {
19
apuram[0xf4 + port] = data;
20
}
21
22
uint8 SMP::op_busread(uint16 addr) {
23
unsigned result;
24
25
switch(addr) {
26
case 0xf0: //TEST -- write-only register
27
return 0x00;
28
29
case 0xf1: //CONTROL -- write-only register
30
return 0x00;
31
32
case 0xf2: //DSPADDR
33
return status.dsp_addr;
34
35
case 0xf3: //DSPDATA
36
//0x80-0xff are read-only mirrors of 0x00-0x7f
37
return dsp.read(status.dsp_addr & 0x7f);
38
39
case 0xf4: //CPUIO0
40
case 0xf5: //CPUIO1
41
case 0xf6: //CPUIO2
42
case 0xf7: //CPUIO3
43
synchronize_cpu_force();
44
return cpu.port_read(addr);
45
46
case 0xf8: //RAM0
47
return status.ram00f8;
48
49
case 0xf9: //RAM1
50
return status.ram00f9;
51
52
case 0xfa: //T0TARGET
53
case 0xfb: //T1TARGET
54
case 0xfc: //T2TARGET -- write-only registers
55
return 0x00;
56
57
case 0xfd: //T0OUT -- 4-bit counter value
58
result = timer0.stage3_ticks;
59
timer0.stage3_ticks = 0;
60
return result;
61
62
case 0xfe: //T1OUT -- 4-bit counter value
63
result = timer1.stage3_ticks;
64
timer1.stage3_ticks = 0;
65
return result;
66
67
case 0xff: //T2OUT -- 4-bit counter value
68
result = timer2.stage3_ticks;
69
timer2.stage3_ticks = 0;
70
return result;
71
}
72
73
cdlInfo.set(eCDLog_AddrType_APURAM, addr);
74
return ram_read(addr);
75
}
76
77
void SMP::op_buswrite(uint16 addr, uint8 data) {
78
switch(addr) {
79
case 0xf0: //TEST
80
if(regs.p.p) break; //writes only valid when P flag is clear
81
82
status.clock_speed = (data >> 6) & 3;
83
status.timer_speed = (data >> 4) & 3;
84
status.timers_enable = data & 0x08;
85
status.ram_disable = data & 0x04;
86
status.ram_writable = data & 0x02;
87
status.timers_disable = data & 0x01;
88
89
status.timer_step = (1 << status.clock_speed) + (2 << status.timer_speed);
90
91
timer0.synchronize_stage1();
92
timer1.synchronize_stage1();
93
timer2.synchronize_stage1();
94
break;
95
96
case 0xf1: //CONTROL
97
status.iplrom_enable = data & 0x80;
98
99
if(data & 0x30) {
100
//one-time clearing of APU port read registers,
101
//emulated by simulating CPU writes of 0x00
102
synchronize_cpu_force();
103
if(data & 0x20) {
104
cpu.port_write(2, 0x00);
105
cpu.port_write(3, 0x00);
106
}
107
if(data & 0x10) {
108
cpu.port_write(0, 0x00);
109
cpu.port_write(1, 0x00);
110
}
111
}
112
113
//0->1 transistion resets timers
114
if(timer2.enable == false && (data & 0x04)) {
115
timer2.stage2_ticks = 0;
116
timer2.stage3_ticks = 0;
117
}
118
timer2.enable = data & 0x04;
119
120
if(timer1.enable == false && (data & 0x02)) {
121
timer1.stage2_ticks = 0;
122
timer1.stage3_ticks = 0;
123
}
124
timer1.enable = data & 0x02;
125
126
if(timer0.enable == false && (data & 0x01)) {
127
timer0.stage2_ticks = 0;
128
timer0.stage3_ticks = 0;
129
}
130
timer0.enable = data & 0x01;
131
break;
132
133
case 0xf2: //DSPADDR
134
status.dsp_addr = data;
135
break;
136
137
case 0xf3: //DSPDATA
138
if(status.dsp_addr & 0x80) break; //0x80-0xff are read-only mirrors of 0x00-0x7f
139
dsp.write(status.dsp_addr & 0x7f, data);
140
break;
141
142
case 0xf4: //CPUIO0
143
case 0xf5: //CPUIO1
144
case 0xf6: //CPUIO2
145
case 0xf7: //CPUIO3
146
synchronize_cpu_force();
147
port_write(addr, data);
148
break;
149
150
case 0xf8: //RAM0
151
status.ram00f8 = data;
152
break;
153
154
case 0xf9: //RAM1
155
status.ram00f9 = data;
156
break;
157
158
case 0xfa: //T0TARGET
159
timer0.target = data;
160
break;
161
162
case 0xfb: //T1TARGET
163
timer1.target = data;
164
break;
165
166
case 0xfc: //T2TARGET
167
timer2.target = data;
168
break;
169
170
case 0xfd: //T0OUT
171
case 0xfe: //T1OUT
172
case 0xff: //T2OUT -- read-only registers
173
break;
174
}
175
176
ram_write(addr, data); //all writes, even to MMIO registers, appear on bus
177
}
178
179
void SMP::op_io() {
180
add_clocks(24);
181
cycle_edge();
182
}
183
184
uint8 SMP::op_read(uint16 addr, eCDLog_Flags flags) {
185
debugger.op_read(addr);
186
187
add_clocks(12);
188
cdlInfo.currFlags = flags;
189
uint8 r = op_busread(addr);
190
add_clocks(12);
191
cycle_edge();
192
return r;
193
}
194
195
void SMP::op_write(uint16 addr, uint8 data) {
196
debugger.op_write(addr, data);
197
198
add_clocks(24);
199
op_buswrite(addr, data);
200
cycle_edge();
201
}
202
203
#endif
204
205