1 #include <../base.hpp>
2
3 #define SA1_CPP
4 namespace SNES {
5
6 SA1 sa1;
7
8 #include "serialization.cpp"
9 #include "bus/bus.cpp"
10 #include "dma/dma.cpp"
11 #include "memory/memory.cpp"
12 #include "mmio/mmio.cpp"
13
enter()14 void SA1::enter() {
15 while(true) {
16 while(scheduler.sync == Scheduler::SyncAll) {
17 scheduler.exit(Scheduler::SynchronizeEvent);
18 }
19
20 if(mmio.sa1_rdyb || mmio.sa1_resb) {
21 //SA-1 co-processor is asleep
22 tick();
23 scheduler.sync_copcpu();
24 continue;
25 }
26
27 if(status.interrupt_pending) {
28 status.interrupt_pending = false;
29 interrupt(status.interrupt_vector);
30 }
31
32 (this->*opcode_table[op_readpc()])();
33 }
34 }
35
last_cycle()36 void SA1::last_cycle() {
37 if(mmio.sa1_nmi && !mmio.sa1_nmicl) {
38 status.interrupt_pending = true;
39 status.interrupt_vector = mmio.cnv;
40 mmio.sa1_nmifl = true;
41 mmio.sa1_nmicl = 1;
42 regs.wai = false;
43 } else if(!regs.p.i) {
44 if(mmio.timer_irqen && !mmio.timer_irqcl) {
45 status.interrupt_pending = true;
46 status.interrupt_vector = mmio.civ;
47 mmio.timer_irqfl = true;
48 regs.wai = false;
49 } else if(mmio.dma_irqen && !mmio.dma_irqcl) {
50 status.interrupt_pending = true;
51 status.interrupt_vector = mmio.civ;
52 mmio.dma_irqfl = true;
53 regs.wai = false;
54 } else if(mmio.sa1_irq && !mmio.sa1_irqcl) {
55 status.interrupt_pending = true;
56 status.interrupt_vector = mmio.civ;
57 mmio.sa1_irqfl = true;
58 regs.wai = false;
59 }
60 }
61 }
62
interrupt(uint16 vector)63 void SA1::interrupt(uint16 vector) {
64 op_read(regs.pc.d);
65 op_io();
66 if(!regs.e) op_writestack(regs.pc.b);
67 op_writestack(regs.pc.h);
68 op_writestack(regs.pc.l);
69 op_writestack(regs.e ? (regs.p & ~0x10) : regs.p);
70 regs.pc.w = vector;
71 regs.pc.b = 0x00;
72 regs.p.i = 1;
73 regs.p.d = 0;
74 }
75
interrupt_pending()76 bool SA1::interrupt_pending() {
77 return status.interrupt_pending;
78 }
79
tick()80 void SA1::tick() {
81 scheduler.addclocks_cop(2);
82 if(++status.tick_counter == 0) scheduler.sync_copcpu();
83
84 //adjust counters:
85 //note that internally, status counters are in clocks;
86 //whereas MMIO register counters are in dots (4 clocks = 1 dot)
87 if(mmio.hvselb == 0) {
88 //HV timer
89 status.hcounter += 2;
90 if(status.hcounter >= 1364) {
91 status.hcounter = 0;
92 if(++status.vcounter >= status.scanlines) status.vcounter = 0;
93 }
94 } else {
95 //linear timer
96 status.hcounter += 2;
97 status.vcounter += (status.hcounter >> 11);
98 status.hcounter &= 0x07ff;
99 status.vcounter &= 0x01ff;
100 }
101
102 //test counters for timer IRQ
103 switch((mmio.ven << 1) + (mmio.hen << 0)) {
104 case 0: break;
105 case 1: if(status.hcounter == (mmio.hcnt << 2)) trigger_irq(); break;
106 case 2: if(status.vcounter == mmio.vcnt && status.hcounter == 0) trigger_irq(); break;
107 case 3: if(status.vcounter == mmio.hcnt && status.hcounter == (mmio.hcnt << 2)) trigger_irq(); break;
108 }
109 }
110
trigger_irq()111 void SA1::trigger_irq() {
112 mmio.timer_irqfl = true;
113 if(mmio.timer_irqen) mmio.timer_irqcl = 0;
114 }
115
init()116 void SA1::init() {
117 }
118
enable()119 void SA1::enable() {
120 }
121
power()122 void SA1::power() {
123 regs.a = regs.x = regs.y = 0x0000;
124 regs.s = 0x01ff;
125
126 reset();
127 }
128
reset()129 void SA1::reset() {
130 memory::vectorsp.access = 0;
131 memory::cc1bwram.dma = false;
132 for(unsigned addr = 0; addr < memory::iram.size(); addr++) {
133 memory::iram.write(addr, 0x00);
134 }
135 vbrbus.init();
136 sa1bus.init();
137
138 regs.pc.d = 0x000000;
139 regs.x.h = 0x00;
140 regs.y.h = 0x00;
141 regs.s.h = 0x01;
142 regs.d = 0x0000;
143 regs.db = 0x00;
144 regs.p = 0x34;
145 regs.e = 1;
146 regs.mdr = 0x00;
147 regs.wai = false;
148 CPUcore::update_table();
149
150 status.tick_counter = 0;
151
152 status.interrupt_pending = false;
153 status.interrupt_vector = 0x0000;
154
155 status.scanlines = (system.region() == System::NTSC ? 262 : 312);
156 status.vcounter = 0;
157 status.hcounter = 0;
158
159 dma.line = 0;
160
161 //$2200 CCNT
162 mmio.sa1_irq = false;
163 mmio.sa1_rdyb = false;
164 mmio.sa1_resb = true;
165 mmio.sa1_nmi = false;
166 mmio.smeg = 0;
167
168 //$2201 SIE
169 mmio.cpu_irqen = false;
170 mmio.chdma_irqen = false;
171
172 //$2202 SIC
173 mmio.cpu_irqcl = false;
174 mmio.chdma_irqcl = false;
175
176 //$2203,$2204 CRV
177 mmio.crv = 0x0000;
178
179 //$2205,$2206 CNV
180 mmio.cnv = 0x0000;
181
182 //$2207,$2208 CIV
183 mmio.civ = 0x0000;
184
185 //$2209 SCNT
186 mmio.cpu_irq = false;
187 mmio.cpu_ivsw = false;
188 mmio.cpu_nvsw = false;
189 mmio.cmeg = 0;
190
191 //$220a CIE
192 mmio.sa1_irqen = false;
193 mmio.timer_irqen = false;
194 mmio.dma_irqen = false;
195 mmio.sa1_nmien = false;
196
197 //$220b CIC
198 mmio.sa1_irqcl = false;
199 mmio.timer_irqcl = false;
200 mmio.dma_irqcl = false;
201 mmio.sa1_nmicl = false;
202
203 //$220c,$220d SNV
204 mmio.snv = 0x0000;
205
206 //$220e,$220f SIV
207 mmio.siv = 0x0000;
208
209 //$2210
210 mmio.hvselb = false;
211 mmio.ven = false;
212 mmio.hen = false;
213
214 //$2212,$2213 HCNT
215 mmio.hcnt = 0x0000;
216
217 //$2214,$2215 VCNT
218 mmio.vcnt = 0x0000;
219
220 //$2220-2223 CXB, DXB, EXB, FXB
221 mmio.cbmode = 0;
222 mmio.dbmode = 0;
223 mmio.ebmode = 0;
224 mmio.fbmode = 0;
225
226 mmio.cb = 0x00;
227 mmio.db = 0x01;
228 mmio.eb = 0x02;
229 mmio.fb = 0x03;
230
231 //$2224 BMAPS
232 mmio.sbm = 0x00;
233
234 //$2225 BMAP
235 mmio.sw46 = false;
236 mmio.cbm = 0x00;
237
238 //$2226 SWBE
239 mmio.swen = false;
240
241 //$2227 CWBE
242 mmio.cwen = false;
243
244 //$2228 BWPA
245 mmio.bwp = 0x0f;
246
247 //$2229 SIWP
248 mmio.siwp = 0x00;
249
250 //$222a CIWP
251 mmio.ciwp = 0x00;
252
253 //$2230 DCNT
254 mmio.dmaen = false;
255 mmio.dprio = false;
256 mmio.cden = false;
257 mmio.cdsel = false;
258 mmio.dd = 0;
259 mmio.sd = 0;
260
261 //$2231 CDMA
262 mmio.chdend = false;
263 mmio.dmasize = 0;
264 mmio.dmacb = 0;
265
266 //$2232-$2234 SDA
267 mmio.dsa = 0x000000;
268
269 //$2235-$2237 DDA
270 mmio.dda = 0x000000;
271
272 //$2238,$2239 DTC
273 mmio.dtc = 0x0000;
274
275 //$223f BBF
276 mmio.bbf = 0;
277
278 //$2240-$224f BRF
279 for(unsigned i = 0; i < 16; i++) {
280 mmio.brf[i] = 0x00;
281 }
282
283 //$2250 MCNT
284 mmio.acm = 0;
285 mmio.md = 0;
286
287 //$2251,$2252 MA
288 mmio.ma = 0x0000;
289
290 //$2253,$2254 MB
291 mmio.mb = 0x0000;
292
293 //$2258 VBD
294 mmio.hl = false;
295 mmio.vb = 16;
296
297 //$2259-$225b
298 mmio.va = 0x000000;
299 mmio.vbit = 0;
300
301 //$2300 SFR
302 mmio.cpu_irqfl = false;
303 mmio.chdma_irqfl = false;
304
305 //$2301 CFR
306 mmio.sa1_irqfl = false;
307 mmio.timer_irqfl = false;
308 mmio.dma_irqfl = false;
309 mmio.sa1_nmifl = false;
310
311 //$2302,$2303 HCR
312 mmio.hcr = 0x0000;
313
314 //$2304,$2305 VCR
315 mmio.vcr = 0x0000;
316
317 //$2306-$230a MR
318 mmio.mr = 0;
319
320 //$230b
321 mmio.overflow = false;
322 }
323
SA1()324 SA1::SA1() {
325 }
326
327 };
328