32x: overflow handling for X-Men
[picodrive.git] / pico / 32x / memory.c
1 /*
2  * Register map:
3  * a15100 F....... R.....EA  F.....AC N...VHMP 4000 // Fm Ren nrEs Aden Cart heN V H cMd Pwm
4  * a15102 ........ ......SM  ?                 4002 // intS intM
5  * a15104 ........ ......10  ........ hhhhhhhh 4004 // bk1 bk0 Hint
6  * a15106 F....... .....SDR  UE...... .....SDR 4006 // Full 68S Dma Rv fUll[fb] Empt[fb]
7  * a15108           (32bit DREQ src)           4008
8  * a1510c           (32bit DREQ dst)           400c
9  * a15110          llllllll llllll00           4010 // DREQ Len
10  * a15112           (16bit FIFO reg)           4012
11  * a15114 ?                  (16bit VRES clr)  4014
12  * a15116 ?                  (16bit Vint clr)  4016
13  * a15118 ?                  (16bit Hint clr)  4018
14  * a1511a ........ .......C  (16bit CMD clr)   401a // Cm
15  * a1511c ?                  (16bit PWM clr)   401c
16  * a1511e ?                  ?                 401e
17  * a15120            (16 bytes comm)           2020
18  * a15130                 (PWM)                2030
19  */
20 #include "../pico_int.h"
21 #include "../memory.h"
22
23 #if 0
24 #undef ash2_end_run
25 #undef SekEndRun
26 #define ash2_end_run(x)
27 #define SekEndRun(x)
28 #endif
29
30 static const char str_mars[] = "MARS";
31
32 void *p32x_bios_g, *p32x_bios_m, *p32x_bios_s;
33 struct Pico32xMem *Pico32xMem;
34
35 static void bank_switch(int b);
36
37 // poll detection
38 #define POLL_THRESHOLD 6
39
40 struct poll_det {
41   u32 addr, cycles, cyc_max;
42   int cnt, flag;
43 };
44 static struct poll_det m68k_poll, sh2_poll[2];
45
46 static int p32x_poll_detect(struct poll_det *pd, u32 a, u32 cycles, int is_vdp)
47 {
48   int ret = 0, flag = pd->flag;
49
50   if (is_vdp)
51     flag <<= 3;
52
53   if (a - 2 <= pd->addr && pd->addr <= a + 2 && cycles - pd->cycles <= pd->cyc_max) {
54     pd->cnt++;
55     if (pd->cnt > POLL_THRESHOLD) {
56       if (!(Pico32x.emu_flags & flag)) {
57         elprintf(EL_32X, "%s poll addr %08x, cyc %u",
58           flag & (P32XF_68KPOLL|P32XF_68KVPOLL) ? "m68k" :
59           (flag & (P32XF_MSH2POLL|P32XF_MSH2VPOLL) ? "msh2" : "ssh2"), a, cycles - pd->cycles);
60         ret = 1;
61       }
62       Pico32x.emu_flags |= flag;
63     }
64   }
65   else {
66     pd->cnt = 0;
67     pd->addr = a;
68   }
69   pd->cycles = cycles;
70
71   return ret;
72 }
73
74 static int p32x_poll_undetect(struct poll_det *pd, int is_vdp)
75 {
76   int ret = 0, flag = pd->flag;
77   if (is_vdp)
78     flag <<= 3; // VDP only
79   else
80     flag |= flag << 3; // both
81   if (Pico32x.emu_flags & flag) {
82     elprintf(EL_32X, "poll %02x -> %02x", Pico32x.emu_flags, Pico32x.emu_flags & ~flag);
83     ret = 1;
84   }
85   Pico32x.emu_flags &= ~flag;
86   pd->addr = pd->cnt = 0;
87   return ret;
88 }
89
90 void p32x_poll_event(int cpu_mask, int is_vdp)
91 {
92   if (cpu_mask & 1)
93     p32x_poll_undetect(&sh2_poll[0], is_vdp);
94   if (cpu_mask & 2)
95     p32x_poll_undetect(&sh2_poll[1], is_vdp);
96 }
97
98 // SH2 faking
99 //#define FAKE_SH2
100 int p32x_csum_faked;
101 #ifdef FAKE_SH2
102 static const u16 comm_fakevals[] = {
103   0x4d5f, 0x4f4b, // M_OK
104   0x535f, 0x4f4b, // S_OK
105   0x4D41, 0x5346, // MASF - Brutal Unleashed
106   0x5331, 0x4d31, // Darxide
107   0x5332, 0x4d32,
108   0x5333, 0x4d33,
109   0x0000, 0x0000, // eq for doom
110   0x0002, // Mortal Kombat
111 //  0, // pad
112 };
113
114 static u32 sh2_comm_faker(u32 a)
115 {
116   static int f = 0;
117   if (a == 0x28 && !p32x_csum_faked) {
118     p32x_csum_faked = 1;
119     return *(unsigned short *)(Pico.rom + 0x18e);
120   }
121   if (f >= sizeof(comm_fakevals) / sizeof(comm_fakevals[0]))
122     f = 0;
123   return comm_fakevals[f++];
124 }
125 #endif
126
127 // DMAC handling
128 static struct {
129   unsigned int sar0, dar0, tcr0; // src addr, dst addr, transfer count
130   unsigned int chcr0; // chan ctl
131   unsigned int sar1, dar1, tcr1; // same for chan 1
132   unsigned int chcr1;
133   int pad[4];
134   unsigned int dmaor;
135 } * dmac0;
136
137 static void dma_68k2sh2_do(void)
138 {
139   unsigned short *dreqlen = &Pico32x.regs[0x10 / 2];
140   int i;
141
142   if (dmac0->tcr0 != *dreqlen)
143     elprintf(EL_32X|EL_ANOMALY, "tcr0 and dreq len differ: %d != %d", dmac0->tcr0, *dreqlen);
144
145   // HACK: assume bus is busy and SH2 is halted
146   // XXX: use different mechanism for this, not poll det
147   Pico32x.emu_flags |= P32XF_MSH2POLL; // id ? P32XF_SSH2POLL : P32XF_MSH2POLL;
148
149   for (i = 0; i < Pico32x.dmac_ptr && dmac0->tcr0 > 0; i++) {
150     extern void p32x_sh2_write16(u32 a, u32 d, int id);
151       elprintf(EL_32X, "dmaw [%08x] %04x, left %d", dmac0->dar0, Pico32x.dmac_fifo[i], *dreqlen);
152     p32x_sh2_write16(dmac0->dar0, Pico32x.dmac_fifo[i], 0);
153     dmac0->dar0 += 2;
154     dmac0->tcr0--;
155     (*dreqlen)--;
156   }
157
158   Pico32x.dmac_ptr = 0; // HACK
159   Pico32x.regs[6 / 2] &= ~P32XS_FULL;
160   if (*dreqlen == 0)
161     Pico32x.regs[6 / 2] &= ~P32XS_68S; // transfer complete
162   if (dmac0->tcr0 == 0) {
163     dmac0->chcr0 |= 2; // DMA has ended normally
164     p32x_poll_undetect(&sh2_poll[0], 0);
165   }
166 }
167
168 // ------------------------------------------------------------------
169 // 68k regs
170
171 static u32 p32x_reg_read16(u32 a)
172 {
173   a &= 0x3e;
174
175   if (a == 2) // INTM, INTS
176     return ((Pico32x.sh2irqi[0] & P32XI_CMD) >> 4) | ((Pico32x.sh2irqi[1] & P32XI_CMD) >> 3);
177 #if 0
178   if ((a & 0x30) == 0x20)
179     return sh2_comm_faker(a);
180 #else
181   if ((a & 0x30) == 0x20) {
182     // evil X-Men proto polls in a dbra loop and expects it to expire..
183     static u32 dr2 = 0;
184     if (SekDar(2) != dr2)
185       m68k_poll.cnt = 0;
186     dr2 = SekDar(2);
187
188     if (p32x_poll_detect(&m68k_poll, a, SekCyclesDoneT(), 0)) {
189       SekSetStop(1);
190       SekEndTimeslice(16);
191     }
192     dr2 = SekDar(2);
193   }
194 #endif
195
196   if ((a & 0x30) == 0x30)
197     return p32x_pwm_read16(a);
198
199   return Pico32x.regs[a / 2];
200 }
201
202 static void p32x_reg_write8(u32 a, u32 d)
203 {
204   u16 *r = Pico32x.regs;
205   a &= 0x3f;
206
207   // for things like bset on comm port
208   m68k_poll.cnt = 0;
209
210   switch (a) {
211     case 0: // adapter ctl
212       r[0] = (r[0] & ~P32XS_FM) | ((d << 8) & P32XS_FM);
213       return;
214     case 1: // adapter ctl, RES bit writeable
215       if ((d ^ r[0]) & d & P32XS_nRES)
216         p32x_reset_sh2s();
217       r[0] = (r[0] & ~P32XS_nRES) | (d & P32XS_nRES);
218       return;
219     case 3: // irq ctl
220       if ((d & 1) && !(Pico32x.sh2irqi[0] & P32XI_CMD)) {
221         Pico32x.sh2irqi[0] |= P32XI_CMD;
222         p32x_update_irls();
223         SekEndRun(16);
224       }
225       if ((d & 2) && !(Pico32x.sh2irqi[1] & P32XI_CMD)) {
226         Pico32x.sh2irqi[1] |= P32XI_CMD;
227         p32x_update_irls();
228         SekEndRun(16);
229       }
230       return;
231     case 5: // bank
232       d &= 7;
233       if (r[4 / 2] != d) {
234         r[4 / 2] = d;
235         bank_switch(d);
236       }
237       return;
238     case 7: // DREQ ctl
239       r[6 / 2] = (r[6 / 2] & P32XS_FULL) | (d & (P32XS_68S|P32XS_DMA|P32XS_RV));
240       return;
241     case 0x1b: // TV
242       r[0x1a / 2] = d;
243       return;
244   }
245
246   if ((a & 0x30) == 0x20) {
247     u8 *r8 = (u8 *)r;
248     r8[a ^ 1] = d;
249     p32x_poll_undetect(&sh2_poll[0], 0);
250     p32x_poll_undetect(&sh2_poll[1], 0);
251     // if some SH2 is busy waiting, it needs to see the result ASAP
252     if (SekCyclesLeftNoMCD > 32)
253       SekEndRun(32);
254     return;
255   }
256 }
257
258 static void p32x_reg_write16(u32 a, u32 d)
259 {
260   u16 *r = Pico32x.regs;
261   a &= 0x3e;
262
263   // for things like bset on comm port
264   m68k_poll.cnt = 0;
265
266   switch (a) {
267     case 0x00: // adapter ctl
268       if ((d ^ r[0]) & d & P32XS_nRES)
269         p32x_reset_sh2s();
270       r[0] = (r[0] & ~(P32XS_FM|P32XS_nRES)) | (d & (P32XS_FM|P32XS_nRES));
271       return;
272     case 0x10: // DREQ len
273       r[a / 2] = d & ~3;
274       return;
275     case 0x12: // FIFO reg
276       if (!(r[6 / 2] & P32XS_68S)) {
277         elprintf(EL_32X|EL_ANOMALY, "DREQ FIFO w16 without 68S?");
278         return;
279       }
280       if (Pico32x.dmac_ptr < DMAC_FIFO_LEN) {
281         Pico32x.dmac_fifo[Pico32x.dmac_ptr++] = d;
282         if ((Pico32x.dmac_ptr & 3) == 0 && (dmac0->chcr0 & 3) == 1 && (dmac0->dmaor & 1))
283           dma_68k2sh2_do();
284         if (Pico32x.dmac_ptr == DMAC_FIFO_LEN)
285           r[6 / 2] |= P32XS_FULL;
286       }
287       break;
288   }
289
290   // DREQ src, dst
291   if      ((a & 0x38) == 0x08) {
292     r[a / 2] = d;
293     return;
294   }
295   // comm port
296   else if ((a & 0x30) == 0x20 && r[a / 2] != d) {
297     r[a / 2] = d;
298     p32x_poll_undetect(&sh2_poll[0], 0);
299     p32x_poll_undetect(&sh2_poll[1], 0);
300     // same as for w8
301     if (SekCyclesLeftNoMCD > 32)
302       SekEndRun(32);
303     return;
304   }
305   // PWM
306   else if ((a & 0x30) == 0x30) {
307     p32x_pwm_write16(a, d);
308     return;
309   }
310
311   p32x_reg_write8(a + 1, d);
312 }
313
314 // ------------------------------------------------------------------
315 // VDP regs
316 static u32 p32x_vdp_read16(u32 a)
317 {
318   a &= 0x0e;
319
320   return Pico32x.vdp_regs[a / 2];
321 }
322
323 static void p32x_vdp_write8(u32 a, u32 d)
324 {
325   u16 *r = Pico32x.vdp_regs;
326   a &= 0x0f;
327
328   // for FEN checks between writes
329   sh2_poll[0].cnt = 0;
330
331   // TODO: verify what's writeable
332   switch (a) {
333     case 0x01:
334       // priority inversion is handled in palette
335       if ((r[0] ^ d) & P32XV_PRI)
336         Pico32x.dirty_pal = 1;
337       r[0] = (r[0] & P32XV_nPAL) | (d & 0xff);
338       break;
339     case 0x05: // fill len
340       r[4 / 2] = d & 0xff;
341       break;
342     case 0x0b:
343       d &= 1;
344       Pico32x.pending_fb = d;
345       // if we are blanking and FS bit is changing
346       if (((r[0x0a/2] & P32XV_VBLK) || (r[0] & P32XV_Mx) == 0) && ((r[0x0a/2] ^ d) & P32XV_FS)) {
347         r[0x0a/2] ^= 1;
348         Pico32xSwapDRAM(d ^ 1);
349         elprintf(EL_32X, "VDP FS: %d", r[0x0a/2] & P32XV_FS);
350       }
351       break;
352   }
353 }
354
355 static void p32x_vdp_write16(u32 a, u32 d)
356 {
357   a &= 0x0e;
358   if (a == 6) { // fill start
359     Pico32x.vdp_regs[6 / 2] = d;
360     return;
361   }
362   if (a == 8) { // fill data
363     u16 *dram = Pico32xMem->dram[(Pico32x.vdp_regs[0x0a/2] & P32XV_FS) ^ 1];
364     int len = Pico32x.vdp_regs[4 / 2] + 1;
365     a = Pico32x.vdp_regs[6 / 2];
366     while (len--) {
367       dram[a] = d;
368       a = (a & 0xff00) | ((a + 1) & 0xff);
369     }
370     Pico32x.vdp_regs[6 / 2] = a;
371     Pico32x.vdp_regs[8 / 2] = d;
372     return;
373   }
374
375   p32x_vdp_write8(a | 1, d);
376 }
377
378 // ------------------------------------------------------------------
379 // SH2 regs
380
381 static u32 p32x_sh2reg_read16(u32 a, int cpuid)
382 {
383   u16 *r = Pico32x.regs;
384   a &= 0xfe; // ?
385
386   switch (a) {
387     case 0x00: // adapter/irq ctl
388       return (r[0] & P32XS_FM) | Pico32x.sh2_regs[0] | Pico32x.sh2irq_mask[cpuid];
389     case 0x04: // H count (often as comm too)
390       if (p32x_poll_detect(&sh2_poll[cpuid], a, ash2_cycles_done(), 0))
391         ash2_end_run(8);
392       return Pico32x.sh2_regs[4 / 2];
393     case 0x10: // DREQ len
394       return r[a / 2];
395   }
396
397   // DREQ src, dst
398   if ((a & 0x38) == 0x08)
399     return r[a / 2];
400   // comm port
401   if ((a & 0x30) == 0x20) {
402     if (p32x_poll_detect(&sh2_poll[cpuid], a, ash2_cycles_done(), 0))
403       ash2_end_run(8);
404     return r[a / 2];
405   }
406   if ((a & 0x30) == 0x30) {
407     sh2_poll[cpuid].cnt = 0;
408     return p32x_pwm_read16(a);
409   }
410
411   return 0;
412 }
413
414 static void p32x_sh2reg_write8(u32 a, u32 d, int cpuid)
415 {
416   a &= 0xff;
417   switch (a) {
418     case 0: // FM
419       Pico32x.regs[0] &= ~P32XS_FM;
420       Pico32x.regs[0] |= (d << 8) & P32XS_FM;
421       return;
422     case 1: // 
423       Pico32x.sh2irq_mask[cpuid] = d & 0x8f;
424       Pico32x.sh2_regs[0] &= ~0x80;
425       Pico32x.sh2_regs[0] |= d & 0x80;
426       p32x_update_irls();
427       return;
428     case 5: // H count
429       Pico32x.sh2_regs[4 / 2] = d & 0xff;
430       p32x_poll_undetect(&sh2_poll[cpuid ^ 1], 0);
431       return;
432   }
433
434   if ((a & 0x30) == 0x20) {
435     u8 *r8 = (u8 *)Pico32x.regs;
436     r8[a ^ 1] = d;
437     if (p32x_poll_undetect(&m68k_poll, 0))
438       SekSetStop(0);
439     p32x_poll_undetect(&sh2_poll[cpuid ^ 1], 0);
440     return;
441   }
442 }
443
444 static void p32x_sh2reg_write16(u32 a, u32 d, int cpuid)
445 {
446   a &= 0xfe;
447
448   // comm
449   if ((a & 0x30) == 0x20 && Pico32x.regs[a/2] != d) {
450     Pico32x.regs[a / 2] = d;
451     if (p32x_poll_undetect(&m68k_poll, 0))
452       SekSetStop(0);
453     p32x_poll_undetect(&sh2_poll[cpuid ^ 1], 0);
454     return;
455   }
456   // PWM
457   else if ((a & 0x30) == 0x30) {
458     p32x_pwm_write16(a, d);
459     return;
460   }
461
462   switch (a) {
463     case 0: // FM
464       Pico32x.regs[0] &= ~P32XS_FM;
465       Pico32x.regs[0] |= d & P32XS_FM;
466       break;
467     case 0x14: Pico32x.sh2irqs &= ~P32XI_VRES; goto irls;
468     case 0x16: Pico32x.sh2irqs &= ~P32XI_VINT; goto irls;
469     case 0x18: Pico32x.sh2irqs &= ~P32XI_HINT; goto irls;
470     case 0x1a: Pico32x.sh2irqi[cpuid] &= ~P32XI_CMD; goto irls;
471     case 0x1c:
472       Pico32x.sh2irqs &= ~P32XI_PWM;
473       p32x_timers_do(0);
474       goto irls;
475   }
476
477   p32x_sh2reg_write8(a | 1, d, cpuid);
478   return;
479
480 irls:
481   p32x_update_irls();
482 }
483
484 // ------------------------------------------------------------------
485 // SH2 internal peripherals
486 // we keep them in little endian format
487 static u32 sh2_peripheral_read8(u32 a, int id)
488 {
489   u8 *r = (void *)Pico32xMem->sh2_peri_regs[id];
490   u32 d;
491
492   a &= 0x1ff;
493   d = PREG8(r, a);
494
495   elprintf(EL_32X, "%csh2 peri r8  [%08x]       %02x @%06x", id ? 's' : 'm', a | ~0x1ff, d, sh2_pc(id));
496   return d;
497 }
498
499 static u32 sh2_peripheral_read16(u32 a, int id)
500 {
501   u16 *r = (void *)Pico32xMem->sh2_peri_regs[id];
502   u32 d;
503
504   a &= 0x1ff;
505   d = r[(a / 2) ^ 1];
506
507   elprintf(EL_32X, "%csh2 peri r16 [%08x]     %04x @%06x", id ? 's' : 'm', a | ~0x1ff, d, sh2_pc(id));
508   return d;
509 }
510
511 static u32 sh2_peripheral_read32(u32 a, int id)
512 {
513   u32 d;
514   a &= 0x1fc;
515   d = Pico32xMem->sh2_peri_regs[id][a / 4];
516
517   elprintf(EL_32X, "%csh2 peri r32 [%08x] %08x @%06x", id ? 's' : 'm', a | ~0x1ff, d, sh2_pc(id));
518   return d;
519 }
520
521 static void sh2_peripheral_write8(u32 a, u32 d, int id)
522 {
523   u8 *r = (void *)Pico32xMem->sh2_peri_regs[id];
524   elprintf(EL_32X, "%csh2 peri w8  [%08x]       %02x @%06x", id ? 's' : 'm', a, d, sh2_pc(id));
525
526   a &= 0x1ff;
527   PREG8(r, a) = d;
528
529   // X-men SCI hack
530   if ((a == 2 &&  (d & 0x20)) || // transmiter enabled
531       (a == 4 && !(d & 0x80))) { // valid data in TDR
532     void *oregs = Pico32xMem->sh2_peri_regs[id ^ 1];
533     if ((PREG8(oregs, 2) & 0x50) == 0x50) { // receiver + irq enabled
534       int level = PREG8(oregs, 0x60) >> 4;
535       int vector = PREG8(oregs, 0x63) & 0x7f;
536       elprintf(EL_32X, "%csh2 SCI recv irq (%d, %d)", (id ^ 1) ? 's' : 'm', level, vector);
537       sh2_internal_irq(&sh2s[id ^ 1], level, vector);
538     }
539   }
540 }
541
542 static void sh2_peripheral_write16(u32 a, u32 d, int id)
543 {
544   u16 *r = (void *)Pico32xMem->sh2_peri_regs[id];
545   elprintf(EL_32X, "%csh2 peri w16 [%08x]     %04x @%06x", id ? 's' : 'm', a, d, sh2_pc(id));
546
547   a &= 0x1ff;
548
549   // evil WDT
550   if (a == 0x80) {
551     if ((d & 0xff00) == 0xa500) { // WTCSR
552       PREG8(r, 0x80) = d;
553       p32x_timers_recalc();
554     }
555     if ((d & 0xff00) == 0x5a00) // WTCNT
556       PREG8(r, 0x81) = d;
557     return;
558   }
559
560   r[(a / 2) ^ 1] = d;
561 }
562
563 static void sh2_peripheral_write32(u32 a, u32 d, int id)
564 {
565   u32 *r = Pico32xMem->sh2_peri_regs[id];
566   elprintf(EL_32X, "%csh2 peri w32 [%08x] %08x @%06x", id ? 's' : 'm', a, d, sh2_pc(id));
567
568   a &= 0x1fc;
569   r[a / 4] = d;
570
571   switch (a) {
572     // division unit (TODO: verify):
573     case 0x104: // DVDNT: divident L, starts divide
574       elprintf(EL_32X, "%csh2 divide %08x / %08x", id ? 's' : 'm', d, r[0x100 / 4]);
575       if (r[0x100 / 4]) {
576         signed int divisor = r[0x100 / 4];
577                        r[0x118 / 4] = r[0x110 / 4] = (signed int)d % divisor;
578         r[0x104 / 4] = r[0x11c / 4] = r[0x114 / 4] = (signed int)d / divisor;
579       }
580       else
581         r[0x110 / 4] = r[0x114 / 4] = r[0x118 / 4] = r[0x11c / 4] = 0; // ?
582       break;
583     case 0x114:
584       elprintf(EL_32X, "%csh2 divide %08x%08x / %08x @%08x",
585         id ? 's' : 'm', r[0x110 / 4], d, r[0x100 / 4], sh2_pc(id));
586       if (r[0x100 / 4]) {
587         signed long long divident = (signed long long)r[0x110 / 4] << 32 | d;
588         signed int divisor = r[0x100 / 4];
589         // XXX: undocumented mirroring to 0x118,0x11c?
590         r[0x118 / 4] = r[0x110 / 4] = divident % divisor;
591         divident /= divisor;
592         r[0x11c / 4] = r[0x114 / 4] = divident;
593         divident >>= 31;
594         if ((unsigned long long)divident + 1 > 1) {
595           //elprintf(EL_32X, "%csh2 divide overflow! @%08x", id ? 's' : 'm', sh2_pc(id));
596           r[0x11c / 4] = r[0x114 / 4] = divident > 0 ? 0x7fffffff : 0x80000000; // overflow
597         }
598       }
599       else
600         r[0x110 / 4] = r[0x114 / 4] = r[0x118 / 4] = r[0x11c / 4] = 0; // ?
601       break;
602   }
603
604   if ((a == 0x1b0 || a == 0x18c) && (dmac0->chcr0 & 3) == 1 && (dmac0->dmaor & 1)) {
605     elprintf(EL_32X, "sh2 DMA %08x -> %08x, cnt %d, chcr %04x @%06x",
606       dmac0->sar0, dmac0->dar0, dmac0->tcr0, dmac0->chcr0, sh2_pc(id));
607     dmac0->tcr0 &= 0xffffff;
608
609     // HACK: assume 68k starts writing soon and end the timeslice
610     ash2_end_run(16);
611
612     // DREQ is only sent after first 4 words are written.
613     // we do multiple of 4 words to avoid messing up alignment
614     if (dmac0->sar0 == 0x20004012 && Pico32x.dmac_ptr && (Pico32x.dmac_ptr & 3) == 0) {
615       elprintf(EL_32X, "68k -> sh2 DMA");
616       dma_68k2sh2_do();
617     }
618   }
619 }
620
621 // ------------------------------------------------------------------
622 // 32x handlers
623
624 // after ADEN
625 static u32 PicoRead8_32x_on(u32 a)
626 {
627   u32 d = 0;
628   if ((a & 0xffc0) == 0x5100) { // a15100
629     d = p32x_reg_read16(a);
630     goto out_16to8;
631   }
632
633   if ((a & 0xfc00) != 0x5000)
634     return PicoRead8_io(a);
635
636   if ((a & 0xfff0) == 0x5180) { // a15180
637     d = p32x_vdp_read16(a);
638     goto out_16to8;
639   }
640
641   if ((a & 0xfe00) == 0x5200) { // a15200
642     d = Pico32xMem->pal[(a & 0x1ff) / 2];
643     goto out_16to8;
644   }
645
646   if ((a & 0xfffc) == 0x30ec) { // a130ec
647     d = str_mars[a & 3];
648     goto out;
649   }
650
651   elprintf(EL_UIO, "m68k unmapped r8  [%06x] @%06x", a, SekPc);
652   return d;
653
654 out_16to8:
655   if (a & 1)
656     d &= 0xff;
657   else
658     d >>= 8;
659
660 out:
661   elprintf(EL_32X, "m68k 32x r8  [%06x]   %02x @%06x", a, d, SekPc);
662   return d;
663 }
664
665 static u32 PicoRead16_32x_on(u32 a)
666 {
667   u32 d = 0;
668   if ((a & 0xffc0) == 0x5100) { // a15100
669     d = p32x_reg_read16(a);
670     goto out;
671   }
672
673   if ((a & 0xfc00) != 0x5000)
674     return PicoRead16_io(a);
675
676   if ((a & 0xfff0) == 0x5180) { // a15180
677     d = p32x_vdp_read16(a);
678     goto out;
679   }
680
681   if ((a & 0xfe00) == 0x5200) { // a15200
682     d = Pico32xMem->pal[(a & 0x1ff) / 2];
683     goto out;
684   }
685
686   if ((a & 0xfffc) == 0x30ec) { // a130ec
687     d = !(a & 2) ? ('M'<<8)|'A' : ('R'<<8)|'S';
688     goto out;
689   }
690
691   elprintf(EL_UIO, "m68k unmapped r16 [%06x] @%06x", a, SekPc);
692   return d;
693
694 out:
695   elprintf(EL_32X, "m68k 32x r16 [%06x] %04x @%06x", a, d, SekPc);
696   return d;
697 }
698
699 static void PicoWrite8_32x_on(u32 a, u32 d)
700 {
701   if ((a & 0xfc00) == 0x5000)
702     elprintf(EL_32X, "m68k 32x w8  [%06x]   %02x @%06x", a, d & 0xff, SekPc);
703
704   if ((a & 0xffc0) == 0x5100) { // a15100
705     p32x_reg_write8(a, d);
706     return;
707   }
708
709   if ((a & 0xfc00) != 0x5000) {
710     PicoWrite8_io(a, d);
711     return;
712   }
713
714   if ((a & 0xfff0) == 0x5180) { // a15180
715     p32x_vdp_write8(a, d);
716     return;
717   }
718
719   // TODO: verify
720   if ((a & 0xfe00) == 0x5200) { // a15200
721     elprintf(EL_32X|EL_ANOMALY, "m68k 32x PAL w8  [%06x]   %02x @%06x", a, d & 0xff, SekPc);
722     ((u8 *)Pico32xMem->pal)[(a & 0x1ff) ^ 1] = d;
723     Pico32x.dirty_pal = 1;
724     return;
725   }
726
727   elprintf(EL_UIO, "m68k unmapped w8  [%06x]   %02x @%06x", a, d & 0xff, SekPc);
728 }
729
730 static void PicoWrite16_32x_on(u32 a, u32 d)
731 {
732   if ((a & 0xfc00) == 0x5000)
733     elprintf(EL_UIO, "m68k 32x w16 [%06x] %04x @%06x", a, d & 0xffff, SekPc);
734
735   if ((a & 0xffc0) == 0x5100) { // a15100
736     p32x_reg_write16(a, d);
737     return;
738   }
739
740   if ((a & 0xfc00) != 0x5000) {
741     PicoWrite16_io(a, d);
742     return;
743   }
744
745   if ((a & 0xfff0) == 0x5180) { // a15180
746     p32x_vdp_write16(a, d);
747     return;
748   }
749
750   if ((a & 0xfe00) == 0x5200) { // a15200
751     Pico32xMem->pal[(a & 0x1ff) / 2] = d;
752     Pico32x.dirty_pal = 1;
753     return;
754   }
755
756   elprintf(EL_UIO, "m68k unmapped w16 [%06x] %04x @%06x", a, d & 0xffff, SekPc);
757 }
758
759 // before ADEN
760 u32 PicoRead8_32x(u32 a)
761 {
762   u32 d = 0;
763   if ((a & 0xffc0) == 0x5100) { // a15100
764     // regs are always readable
765     d = ((u8 *)Pico32x.regs)[(a & 0x3f) ^ 1];
766     goto out;
767   }
768
769   if ((a & 0xfffc) == 0x30ec) { // a130ec
770     d = str_mars[a & 3];
771     goto out;
772   }
773
774   elprintf(EL_UIO, "m68k unmapped r8  [%06x] @%06x", a, SekPc);
775   return d;
776
777 out:
778   elprintf(EL_32X, "m68k 32x r8  [%06x]   %02x @%06x", a, d, SekPc);
779   return d;
780 }
781
782 u32 PicoRead16_32x(u32 a)
783 {
784   u32 d = 0;
785   if ((a & 0xffc0) == 0x5100) { // a15100
786     d = Pico32x.regs[(a & 0x3f) / 2];
787     goto out;
788   }
789
790   if ((a & 0xfffc) == 0x30ec) { // a130ec
791     d = !(a & 2) ? ('M'<<8)|'A' : ('R'<<8)|'S';
792     goto out;
793   }
794
795   elprintf(EL_UIO, "m68k unmapped r16 [%06x] @%06x", a, SekPc);
796   return d;
797
798 out:
799   elprintf(EL_32X, "m68k 32x r16 [%06x] %04x @%06x", a, d, SekPc);
800   return d;
801 }
802
803 void PicoWrite8_32x(u32 a, u32 d)
804 {
805   if ((a & 0xffc0) == 0x5100) { // a15100
806     u16 *r = Pico32x.regs;
807
808     elprintf(EL_32X, "m68k 32x w8  [%06x]   %02x @%06x", a, d & 0xff, SekPc);
809     a &= 0x3f;
810     if (a == 1) {
811       if ((d ^ r[0]) & d & P32XS_ADEN) {
812         Pico32xStartup();
813         r[0] &= ~P32XS_nRES; // causes reset if specified by this write
814         r[0] |= P32XS_ADEN;
815         p32x_reg_write8(a, d); // forward for reset processing
816       }
817       return;
818     }
819
820     // allow only COMM for now
821     if ((a & 0x30) == 0x20) {
822       u8 *r8 = (u8 *)r;
823       r8[a ^ 1] = d;
824     }
825     return;
826   }
827
828   elprintf(EL_UIO, "m68k unmapped w8  [%06x]   %02x @%06x", a, d & 0xff, SekPc);
829 }
830
831 void PicoWrite16_32x(u32 a, u32 d)
832 {
833   if ((a & 0xffc0) == 0x5100) { // a15100
834     u16 *r = Pico32x.regs;
835
836     elprintf(EL_UIO, "m68k 32x w16 [%06x] %04x @%06x", a, d & 0xffff, SekPc);
837     a &= 0x3e;
838     if (a == 0) {
839       if ((d ^ r[0]) & d & P32XS_ADEN) {
840         Pico32xStartup();
841         r[0] &= ~P32XS_nRES; // causes reset if specified by this write
842         r[0] |= P32XS_ADEN;
843         p32x_reg_write16(a, d); // forward for reset processing
844       }
845       return;
846     }
847
848     // allow only COMM for now
849     if ((a & 0x30) == 0x20)
850       r[a / 2] = d;
851     return;
852   }
853
854   elprintf(EL_UIO, "m68k unmapped w16 [%06x] %04x @%06x", a, d & 0xffff, SekPc);
855 }
856
857 // -----------------------------------------------------------------
858
859 // hint vector is writeable
860 static void PicoWrite8_hint(u32 a, u32 d)
861 {
862   if ((a & 0xfffc) == 0x0070) {
863     Pico32xMem->m68k_rom[a ^ 1] = d;
864     return;
865   }
866
867   elprintf(EL_UIO, "m68k unmapped w8  [%06x]   %02x @%06x", a, d & 0xff, SekPc);
868 }
869
870 static void PicoWrite16_hint(u32 a, u32 d)
871 {
872   if ((a & 0xfffc) == 0x0070) {
873     ((u16 *)Pico32xMem->m68k_rom)[a/2] = d;
874     return;
875   }
876
877   elprintf(EL_UIO, "m68k unmapped w16 [%06x] %04x @%06x", a, d & 0xffff, SekPc);
878 }
879
880 void Pico32xSwapDRAM(int b)
881 {
882   cpu68k_map_set(m68k_read8_map,   0x840000, 0x85ffff, Pico32xMem->dram[b], 0);
883   cpu68k_map_set(m68k_read16_map,  0x840000, 0x85ffff, Pico32xMem->dram[b], 0);
884   cpu68k_map_set(m68k_write8_map,  0x840000, 0x85ffff, Pico32xMem->dram[b], 0);
885   cpu68k_map_set(m68k_write16_map, 0x840000, 0x85ffff, Pico32xMem->dram[b], 0);
886 }
887
888 static void bank_switch(int b)
889 {
890   unsigned int rs, bank;
891
892   bank = b << 20;
893   if (bank >= Pico.romsize) {
894     elprintf(EL_32X|EL_ANOMALY, "missing bank @ %06x", bank);
895     return;
896   }
897
898   // 32X ROM (unbanked, XXX: consider mirroring?)
899   rs = (Pico.romsize + M68K_BANK_MASK) & ~M68K_BANK_MASK;
900   rs -= bank;
901   if (rs > 0x100000)
902     rs = 0x100000;
903   cpu68k_map_set(m68k_read8_map,   0x900000, 0x900000 + rs - 1, Pico.rom + bank, 0);
904   cpu68k_map_set(m68k_read16_map,  0x900000, 0x900000 + rs - 1, Pico.rom + bank, 0);
905
906   elprintf(EL_32X, "bank %06x-%06x -> %06x", 0x900000, 0x900000 + rs - 1, bank);
907
908 #ifdef EMU_F68K
909   // setup FAME fetchmap
910   for (rs = 0x90; rs < 0xa0; rs++)
911     PicoCpuFM68k.Fetch[rs] = (u32)Pico.rom + bank - 0x900000;
912 #endif
913 }
914
915 // -----------------------------------------------------------------
916 //                              SH2  
917 // -----------------------------------------------------------------
918
919 u32 p32x_sh2_read8(u32 a, int id)
920 {
921   u32 d = 0;
922
923   if (id == 0 && a < sizeof(Pico32xMem->sh2_rom_m))
924     return Pico32xMem->sh2_rom_m[a ^ 1];
925   if (id == 1 && a < sizeof(Pico32xMem->sh2_rom_s))
926     return Pico32xMem->sh2_rom_s[a ^ 1];
927
928   if ((a & 0xdffc0000) == 0x06000000)
929     return Pico32xMem->sdram[(a & 0x3ffff) ^ 1];
930
931   if ((a & 0xdfc00000) == 0x02000000)
932     if ((a & 0x003fffff) < Pico.romsize)
933       return Pico.rom[(a & 0x3fffff) ^ 1];
934
935   if ((a & ~0xfff) == 0xc0000000)
936     return Pico32xMem->data_array[id][(a & 0xfff) ^ 1];
937
938   if ((a & 0xdffc0000) == 0x04000000) {
939     /* XXX: overwrite readable as normal? */
940     u8 *dram = (u8 *)Pico32xMem->dram[(Pico32x.vdp_regs[0x0a/2] & P32XV_FS) ^ 1];
941     return dram[(a & 0x1ffff) ^ 1];
942   }
943
944   if ((a & 0xdfffff00) == 0x4000) {
945     d = p32x_sh2reg_read16(a, id);
946     goto out_16to8;
947   }
948
949   if ((a & 0xdfffff00) == 0x4100) {
950     d = p32x_vdp_read16(a);
951     if (p32x_poll_detect(&sh2_poll[id], a, ash2_cycles_done(), 1))
952       ash2_end_run(8);
953     goto out_16to8;
954   }
955
956   if ((a & 0xdfffff00) == 0x4200) {
957     d = Pico32xMem->pal[(a & 0x1ff) / 2];
958     goto out_16to8;
959   }
960
961   if ((a & 0xfffffe00) == 0xfffffe00)
962     return sh2_peripheral_read8(a, id);
963
964   elprintf(EL_UIO, "%csh2 unmapped r8  [%08x]       %02x @%06x",
965     id ? 's' : 'm', a, d, sh2_pc(id));
966   return d;
967
968 out_16to8:
969   if (a & 1)
970     d &= 0xff;
971   else
972     d >>= 8;
973
974   elprintf(EL_32X, "%csh2 r8  [%08x]       %02x @%06x",
975     id ? 's' : 'm', a, d, sh2_pc(id));
976   return d;
977 }
978
979 u32 p32x_sh2_read16(u32 a, int id)
980 {
981   u32 d = 0;
982
983   if (id == 0 && a < sizeof(Pico32xMem->sh2_rom_m))
984     return *(u16 *)(Pico32xMem->sh2_rom_m + a);
985   if (id == 1 && a < sizeof(Pico32xMem->sh2_rom_s))
986     return *(u16 *)(Pico32xMem->sh2_rom_s + a);
987
988   if ((a & 0xdffc0000) == 0x06000000)
989     return ((u16 *)Pico32xMem->sdram)[(a & 0x3ffff) / 2];
990
991   if ((a & 0xdfc00000) == 0x02000000)
992     if ((a & 0x003fffff) < Pico.romsize)
993       return ((u16 *)Pico.rom)[(a & 0x3fffff) / 2];
994
995   if ((a & ~0xfff) == 0xc0000000)
996     return ((u16 *)Pico32xMem->data_array[id])[(a & 0xfff) / 2];
997
998   if ((a & 0xdffe0000) == 0x04000000)
999     return Pico32xMem->dram[(Pico32x.vdp_regs[0x0a/2] & P32XV_FS) ^ 1][(a & 0x1ffff) / 2];
1000
1001   if ((a & 0xdfffff00) == 0x4000) {
1002     d = p32x_sh2reg_read16(a, id);
1003     if (!(EL_LOGMASK & EL_PWM) && (a & 0x30) == 0x30) // hide PWM
1004       return d;
1005     goto out;
1006   }
1007
1008   if ((a & 0xdfffff00) == 0x4100) {
1009     d = p32x_vdp_read16(a);
1010     if (p32x_poll_detect(&sh2_poll[id], a, ash2_cycles_done(), 1))
1011       ash2_end_run(8);
1012     goto out;
1013   }
1014
1015   if ((a & 0xdfffff00) == 0x4200) {
1016     d = Pico32xMem->pal[(a & 0x1ff) / 2];
1017     goto out;
1018   }
1019
1020   if ((a & 0xfffffe00) == 0xfffffe00)
1021     return sh2_peripheral_read16(a, id);
1022
1023   elprintf(EL_UIO, "%csh2 unmapped r16 [%08x]     %04x @%06x",
1024     id ? 's' : 'm', a, d, sh2_pc(id));
1025   return d;
1026
1027 out:
1028   elprintf(EL_32X, "%csh2 r16 [%08x]     %04x @%06x",
1029     id ? 's' : 'm', a, d, sh2_pc(id));
1030   return d;
1031 }
1032
1033 u32 p32x_sh2_read32(u32 a, int id)
1034 {
1035   if ((a & 0xfffffe00) == 0xfffffe00)
1036     return sh2_peripheral_read32(a, id);
1037
1038 //  elprintf(EL_UIO, "sh2 r32 [%08x] %08x @%06x", a, d, ash2_pc());
1039   return (p32x_sh2_read16(a, id) << 16) | p32x_sh2_read16(a + 2, id);
1040 }
1041
1042 void p32x_sh2_write8(u32 a, u32 d, int id)
1043 {
1044   if ((a & 0xdffffc00) == 0x4000)
1045     elprintf(EL_32X, "%csh2 w8  [%08x]       %02x @%06x",
1046       id ? 's' : 'm', a, d & 0xff, sh2_pc(id));
1047
1048   if ((a & 0xdffc0000) == 0x06000000) {
1049     Pico32xMem->sdram[(a & 0x3ffff) ^ 1] = d;
1050     return;
1051   }
1052
1053   if ((a & 0xdffc0000) == 0x04000000) {
1054     u8 *dram;
1055     if (!(a & 0x20000) || d) {
1056       dram = (u8 *)Pico32xMem->dram[(Pico32x.vdp_regs[0x0a/2] & P32XV_FS) ^ 1];
1057       dram[(a & 0x1ffff) ^ 1] = d;
1058     }
1059     return;
1060   }
1061
1062   if ((a & ~0xfff) == 0xc0000000) {
1063     Pico32xMem->data_array[id][(a & 0xfff) ^ 1] = d;
1064     return;
1065   }
1066
1067   if ((a & 0xdfffff00) == 0x4100) {
1068     p32x_vdp_write8(a, d);
1069     return;
1070   }
1071
1072   if ((a & 0xdfffff00) == 0x4000) {
1073     p32x_sh2reg_write8(a, d, id);
1074     return;
1075   }
1076
1077   if ((a & 0xfffffe00) == 0xfffffe00) {
1078     sh2_peripheral_write8(a, d, id);
1079     return;
1080   }
1081
1082   elprintf(EL_UIO, "%csh2 unmapped w8  [%08x]       %02x @%06x",
1083     id ? 's' : 'm', a, d & 0xff, sh2_pc(id));
1084 }
1085
1086 void p32x_sh2_write16(u32 a, u32 d, int id)
1087 {
1088   if ((a & 0xdffffc00) == 0x4000 && ((EL_LOGMASK & EL_PWM) || (a & 0x30) != 0x30)) // hide PWM
1089     elprintf(EL_32X, "%csh2 w16 [%08x]     %04x @%06x",
1090       id ? 's' : 'm', a, d & 0xffff, sh2_pc(id));
1091
1092   // ignore "Associative purge space"
1093   if ((a & 0xf8000000) == 0x40000000)
1094     return;
1095
1096   if ((a & 0xdffc0000) == 0x06000000) {
1097     ((u16 *)Pico32xMem->sdram)[(a & 0x3ffff) / 2] = d;
1098     return;
1099   }
1100
1101   if ((a & ~0xfff) == 0xc0000000) {
1102     ((u16 *)Pico32xMem->data_array[id])[(a & 0xfff) / 2] = d;
1103     return;
1104   }
1105
1106   if ((a & 0xdffc0000) == 0x04000000) {
1107     u16 *pd = &Pico32xMem->dram[(Pico32x.vdp_regs[0x0a/2] & P32XV_FS) ^ 1][(a & 0x1ffff) / 2];
1108     if (!(a & 0x20000)) {
1109       *pd = d;
1110       return;
1111     }
1112     // overwrite
1113     if (!(d & 0xff00)) d |= *pd & 0xff00;
1114     if (!(d & 0x00ff)) d |= *pd & 0x00ff;
1115     *pd = d;
1116     return;
1117   }
1118
1119   if ((a & 0xdfffff00) == 0x4100) {
1120     sh2_poll[id].cnt = 0; // for poll before VDP accesses
1121     p32x_vdp_write16(a, d);
1122     return;
1123   }
1124
1125   if ((a & 0xdffffe00) == 0x4200) {
1126     Pico32xMem->pal[(a & 0x1ff) / 2] = d;
1127     Pico32x.dirty_pal = 1;
1128     return;
1129   }
1130
1131   if ((a & 0xdfffff00) == 0x4000) {
1132     p32x_sh2reg_write16(a, d, id);
1133     return;
1134   }
1135
1136   if ((a & 0xfffffe00) == 0xfffffe00) {
1137     sh2_peripheral_write16(a, d, id);
1138     return;
1139   }
1140
1141   elprintf(EL_UIO, "%csh2 unmapped w16 [%08x]     %04x @%06x",
1142     id ? 's' : 'm', a, d & 0xffff, sh2_pc(id));
1143 }
1144
1145 void p32x_sh2_write32(u32 a, u32 d, int id)
1146 {
1147   if ((a & 0xfffffe00) == 0xfffffe00) {
1148     sh2_peripheral_write32(a, d, id);
1149     return;
1150   }
1151
1152   p32x_sh2_write16(a, d >> 16, id);
1153   p32x_sh2_write16(a + 2, d, id);
1154 }
1155
1156 static const u16 msh2_code[] = {
1157   // trap instructions
1158   0xaffe, // bra <self>
1159   0x0009, // nop
1160   // have to wait a bit until m68k initial program finishes clearing stuff
1161   // to avoid races with game SH2 code, like in Tempo
1162   0xd004, // mov.l   @(_m_ok,pc), r0
1163   0xd105, // mov.l   @(_cnt,pc), r1
1164   0xd205, // mov.l   @(_start,pc), r2
1165   0x71ff, // add     #-1, r1
1166   0x4115, // cmp/pl  r1
1167   0x89fc, // bt      -2
1168   0xc208, // mov.l   r0, @(h'20,gbr)
1169   0x6822, // mov.l   @r2, r8
1170   0x482b, // jmp     @r8
1171   0x0009, // nop
1172   ('M'<<8)|'_', ('O'<<8)|'K',
1173   0x0001, 0x0000,
1174   0x2200, 0x03e0  // master start pointer in ROM
1175 };
1176
1177 static const u16 ssh2_code[] = {
1178   0xaffe, // bra <self>
1179   0x0009, // nop
1180   // code to wait for master, in case authentic master BIOS is used
1181   0xd104, // mov.l   @(_m_ok,pc), r1
1182   0xd206, // mov.l   @(_start,pc), r2
1183   0xc608, // mov.l   @(h'20,gbr), r0
1184   0x3100, // cmp/eq  r0, r1
1185   0x8bfc, // bf      #-2
1186   0xd003, // mov.l   @(_s_ok,pc), r0
1187   0xc209, // mov.l   r0, @(h'24,gbr)
1188   0x6822, // mov.l   @r2, r8
1189   0x482b, // jmp     @r8
1190   0x0009, // nop
1191   ('M'<<8)|'_', ('O'<<8)|'K',
1192   ('S'<<8)|'_', ('O'<<8)|'K',
1193   0x2200, 0x03e4  // slave start pointer in ROM
1194 };
1195
1196 #define HWSWAP(x) (((x) << 16) | ((x) >> 16))
1197 static void get_bios(void)
1198 {
1199   u16 *ps;
1200   u32 *pl;
1201   int i;
1202
1203   // M68K ROM
1204   if (p32x_bios_g != NULL) {
1205     elprintf(EL_STATUS|EL_32X, "32x: using supplied 68k BIOS");
1206     Byteswap(Pico32xMem->m68k_rom, p32x_bios_g, 0x100);
1207   }
1208   else {
1209     // generate 68k ROM
1210     ps = (u16 *)Pico32xMem->m68k_rom;
1211     pl = (u32 *)ps;
1212     for (i = 1; i < 0xc0/4; i++)
1213       pl[i] = HWSWAP(0x880200 + (i - 1) * 6);
1214
1215     // fill with nops
1216     for (i = 0xc0/2; i < 0x100/2; i++)
1217       ps[i] = 0x4e71;
1218
1219 #if 0
1220     ps[0xc0/2] = 0x46fc;
1221     ps[0xc2/2] = 0x2700; // move #0x2700,sr
1222     ps[0xfe/2] = 0x60fe; // jump to self
1223 #else
1224     ps[0xfe/2] = 0x4e75; // rts
1225 #endif
1226   }
1227   // fill remaining m68k_rom page with game ROM
1228   memcpy(Pico32xMem->m68k_rom + 0x100, Pico.rom + 0x100, sizeof(Pico32xMem->m68k_rom) - 0x100);
1229
1230   // MSH2
1231   if (p32x_bios_m != NULL) {
1232     elprintf(EL_STATUS|EL_32X, "32x: using supplied master SH2 BIOS");
1233     Byteswap(Pico32xMem->sh2_rom_m, p32x_bios_m, sizeof(Pico32xMem->sh2_rom_m));
1234   }
1235   else {
1236     pl = (u32 *)Pico32xMem->sh2_rom_m;
1237
1238     // fill exception vector table to our trap address
1239     for (i = 0; i < 128; i++)
1240       pl[i] = HWSWAP(0x200);
1241
1242     // startup code
1243     memcpy(Pico32xMem->sh2_rom_m + 0x200, msh2_code, sizeof(msh2_code));
1244
1245     // reset SP
1246     pl[1] = pl[3] = HWSWAP(0x6040000);
1247     // start
1248     pl[0] = pl[2] = HWSWAP(0x204);
1249   }
1250
1251   // SSH2
1252   if (p32x_bios_s != NULL) {
1253     elprintf(EL_STATUS|EL_32X, "32x: using supplied slave SH2 BIOS");
1254     Byteswap(Pico32xMem->sh2_rom_s, p32x_bios_s, sizeof(Pico32xMem->sh2_rom_s));
1255   }
1256   else {
1257     pl = (u32 *)Pico32xMem->sh2_rom_s;
1258
1259     // fill exception vector table to our trap address
1260     for (i = 0; i < 128; i++)
1261       pl[i] = HWSWAP(0x200);
1262
1263     // startup code
1264     memcpy(Pico32xMem->sh2_rom_s + 0x200, ssh2_code, sizeof(ssh2_code));
1265
1266     // reset SP
1267     pl[1] = pl[3] = HWSWAP(0x603f800);
1268     // start
1269     pl[0] = pl[2] = HWSWAP(0x204);
1270   }
1271 }
1272
1273 void PicoMemSetup32x(void)
1274 {
1275   unsigned int rs;
1276
1277   Pico32xMem = calloc(1, sizeof(*Pico32xMem));
1278   if (Pico32xMem == NULL) {
1279     elprintf(EL_STATUS, "OOM");
1280     return;
1281   }
1282
1283   dmac0 = (void *)&Pico32xMem->sh2_peri_regs[0][0x180 / 4];
1284
1285   get_bios();
1286
1287   // cartridge area becomes unmapped
1288   // XXX: we take the easy way and don't unmap ROM,
1289   // so that we can avoid handling the RV bit.
1290   // m68k_map_unmap(0x000000, 0x3fffff);
1291
1292   // MD ROM area
1293   rs = sizeof(Pico32xMem->m68k_rom);
1294   cpu68k_map_set(m68k_read8_map,   0x000000, rs - 1, Pico32xMem->m68k_rom, 0);
1295   cpu68k_map_set(m68k_read16_map,  0x000000, rs - 1, Pico32xMem->m68k_rom, 0);
1296   cpu68k_map_set(m68k_write8_map,  0x000000, rs - 1, PicoWrite8_hint, 1); // TODO verify
1297   cpu68k_map_set(m68k_write16_map, 0x000000, rs - 1, PicoWrite16_hint, 1);
1298
1299   // DRAM area
1300   Pico32xSwapDRAM(1);
1301
1302   // 32X ROM (unbanked, XXX: consider mirroring?)
1303   rs = (Pico.romsize + M68K_BANK_MASK) & ~M68K_BANK_MASK;
1304   if (rs > 0x80000)
1305     rs = 0x80000;
1306   cpu68k_map_set(m68k_read8_map,   0x880000, 0x880000 + rs - 1, Pico.rom, 0);
1307   cpu68k_map_set(m68k_read16_map,  0x880000, 0x880000 + rs - 1, Pico.rom, 0);
1308 #ifdef EMU_F68K
1309   // setup FAME fetchmap
1310   PicoCpuFM68k.Fetch[0] = (u32)Pico32xMem->m68k_rom;
1311   for (rs = 0x88; rs < 0x90; rs++)
1312     PicoCpuFM68k.Fetch[rs] = (u32)Pico.rom - 0x880000;
1313 #endif
1314
1315   // 32X ROM (banked)
1316   bank_switch(0);
1317
1318   // SYS regs
1319   cpu68k_map_set(m68k_read8_map,   0xa10000, 0xa1ffff, PicoRead8_32x_on, 1);
1320   cpu68k_map_set(m68k_read16_map,  0xa10000, 0xa1ffff, PicoRead16_32x_on, 1);
1321   cpu68k_map_set(m68k_write8_map,  0xa10000, 0xa1ffff, PicoWrite8_32x_on, 1);
1322   cpu68k_map_set(m68k_write16_map, 0xa10000, 0xa1ffff, PicoWrite16_32x_on, 1);
1323
1324   // setup poll detector
1325   m68k_poll.flag = P32XF_68KPOLL;
1326   m68k_poll.cyc_max = 64;
1327   sh2_poll[0].flag = P32XF_MSH2POLL;
1328   sh2_poll[0].cyc_max = 21;
1329   sh2_poll[1].flag = P32XF_SSH2POLL;
1330   sh2_poll[1].cyc_max = 16;
1331 }
1332