32x: famec support
[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       break;
581     case 0x114:
582       elprintf(EL_32X, "%csh2 divide %08x%08x / %08x @%08x",
583         id ? 's' : 'm', r[0x110 / 4], d, r[0x100 / 4], sh2_pc(id));
584       if (r[0x100 / 4]) {
585         signed long long divident = (signed long long)r[0x110 / 4] << 32 | d;
586         signed int divisor = r[0x100 / 4];
587         // XXX: undocumented mirroring to 0x118,0x11c?
588         r[0x118 / 4] = r[0x110 / 4] = divident % divisor;
589         r[0x11c / 4] = r[0x114 / 4] = divident / divisor;
590       }
591       break;
592   }
593
594   if ((a == 0x1b0 || a == 0x18c) && (dmac0->chcr0 & 3) == 1 && (dmac0->dmaor & 1)) {
595     elprintf(EL_32X, "sh2 DMA %08x -> %08x, cnt %d, chcr %04x @%06x",
596       dmac0->sar0, dmac0->dar0, dmac0->tcr0, dmac0->chcr0, sh2_pc(id));
597     dmac0->tcr0 &= 0xffffff;
598
599     // HACK: assume 68k starts writing soon and end the timeslice
600     ash2_end_run(16);
601
602     // DREQ is only sent after first 4 words are written.
603     // we do multiple of 4 words to avoid messing up alignment
604     if (dmac0->sar0 == 0x20004012 && Pico32x.dmac_ptr && (Pico32x.dmac_ptr & 3) == 0) {
605       elprintf(EL_32X, "68k -> sh2 DMA");
606       dma_68k2sh2_do();
607     }
608   }
609 }
610
611 // ------------------------------------------------------------------
612 // 32x handlers
613
614 // after ADEN
615 static u32 PicoRead8_32x_on(u32 a)
616 {
617   u32 d = 0;
618   if ((a & 0xffc0) == 0x5100) { // a15100
619     d = p32x_reg_read16(a);
620     goto out_16to8;
621   }
622
623   if ((a & 0xfc00) != 0x5000)
624     return PicoRead8_io(a);
625
626   if ((a & 0xfff0) == 0x5180) { // a15180
627     d = p32x_vdp_read16(a);
628     goto out_16to8;
629   }
630
631   if ((a & 0xfe00) == 0x5200) { // a15200
632     d = Pico32xMem->pal[(a & 0x1ff) / 2];
633     goto out_16to8;
634   }
635
636   if ((a & 0xfffc) == 0x30ec) { // a130ec
637     d = str_mars[a & 3];
638     goto out;
639   }
640
641   elprintf(EL_UIO, "m68k unmapped r8  [%06x] @%06x", a, SekPc);
642   return d;
643
644 out_16to8:
645   if (a & 1)
646     d &= 0xff;
647   else
648     d >>= 8;
649
650 out:
651   elprintf(EL_32X, "m68k 32x r8  [%06x]   %02x @%06x", a, d, SekPc);
652   return d;
653 }
654
655 static u32 PicoRead16_32x_on(u32 a)
656 {
657   u32 d = 0;
658   if ((a & 0xffc0) == 0x5100) { // a15100
659     d = p32x_reg_read16(a);
660     goto out;
661   }
662
663   if ((a & 0xfc00) != 0x5000)
664     return PicoRead16_io(a);
665
666   if ((a & 0xfff0) == 0x5180) { // a15180
667     d = p32x_vdp_read16(a);
668     goto out;
669   }
670
671   if ((a & 0xfe00) == 0x5200) { // a15200
672     d = Pico32xMem->pal[(a & 0x1ff) / 2];
673     goto out;
674   }
675
676   if ((a & 0xfffc) == 0x30ec) { // a130ec
677     d = !(a & 2) ? ('M'<<8)|'A' : ('R'<<8)|'S';
678     goto out;
679   }
680
681   elprintf(EL_UIO, "m68k unmapped r16 [%06x] @%06x", a, SekPc);
682   return d;
683
684 out:
685   elprintf(EL_32X, "m68k 32x r16 [%06x] %04x @%06x", a, d, SekPc);
686   return d;
687 }
688
689 static void PicoWrite8_32x_on(u32 a, u32 d)
690 {
691   if ((a & 0xfc00) == 0x5000)
692     elprintf(EL_32X, "m68k 32x w8  [%06x]   %02x @%06x", a, d & 0xff, SekPc);
693
694   if ((a & 0xffc0) == 0x5100) { // a15100
695     p32x_reg_write8(a, d);
696     return;
697   }
698
699   if ((a & 0xfc00) != 0x5000) {
700     PicoWrite8_io(a, d);
701     return;
702   }
703
704   if ((a & 0xfff0) == 0x5180) { // a15180
705     p32x_vdp_write8(a, d);
706     return;
707   }
708
709   // TODO: verify
710   if ((a & 0xfe00) == 0x5200) { // a15200
711     elprintf(EL_32X|EL_ANOMALY, "m68k 32x PAL w8  [%06x]   %02x @%06x", a, d & 0xff, SekPc);
712     ((u8 *)Pico32xMem->pal)[(a & 0x1ff) ^ 1] = d;
713     Pico32x.dirty_pal = 1;
714     return;
715   }
716
717   elprintf(EL_UIO, "m68k unmapped w8  [%06x]   %02x @%06x", a, d & 0xff, SekPc);
718 }
719
720 static void PicoWrite16_32x_on(u32 a, u32 d)
721 {
722   if ((a & 0xfc00) == 0x5000)
723     elprintf(EL_UIO, "m68k 32x w16 [%06x] %04x @%06x", a, d & 0xffff, SekPc);
724
725   if ((a & 0xffc0) == 0x5100) { // a15100
726     p32x_reg_write16(a, d);
727     return;
728   }
729
730   if ((a & 0xfc00) != 0x5000) {
731     PicoWrite16_io(a, d);
732     return;
733   }
734
735   if ((a & 0xfff0) == 0x5180) { // a15180
736     p32x_vdp_write16(a, d);
737     return;
738   }
739
740   if ((a & 0xfe00) == 0x5200) { // a15200
741     Pico32xMem->pal[(a & 0x1ff) / 2] = d;
742     Pico32x.dirty_pal = 1;
743     return;
744   }
745
746   elprintf(EL_UIO, "m68k unmapped w16 [%06x] %04x @%06x", a, d & 0xffff, SekPc);
747 }
748
749 // before ADEN
750 u32 PicoRead8_32x(u32 a)
751 {
752   u32 d = 0;
753   if ((a & 0xffc0) == 0x5100) { // a15100
754     // regs are always readable
755     d = ((u8 *)Pico32x.regs)[(a & 0x3f) ^ 1];
756     goto out;
757   }
758
759   if ((a & 0xfffc) == 0x30ec) { // a130ec
760     d = str_mars[a & 3];
761     goto out;
762   }
763
764   elprintf(EL_UIO, "m68k unmapped r8  [%06x] @%06x", a, SekPc);
765   return d;
766
767 out:
768   elprintf(EL_32X, "m68k 32x r8  [%06x]   %02x @%06x", a, d, SekPc);
769   return d;
770 }
771
772 u32 PicoRead16_32x(u32 a)
773 {
774   u32 d = 0;
775   if ((a & 0xffc0) == 0x5100) { // a15100
776     d = Pico32x.regs[(a & 0x3f) / 2];
777     goto out;
778   }
779
780   if ((a & 0xfffc) == 0x30ec) { // a130ec
781     d = !(a & 2) ? ('M'<<8)|'A' : ('R'<<8)|'S';
782     goto out;
783   }
784
785   elprintf(EL_UIO, "m68k unmapped r16 [%06x] @%06x", a, SekPc);
786   return d;
787
788 out:
789   elprintf(EL_32X, "m68k 32x r16 [%06x] %04x @%06x", a, d, SekPc);
790   return d;
791 }
792
793 void PicoWrite8_32x(u32 a, u32 d)
794 {
795   if ((a & 0xffc0) == 0x5100) { // a15100
796     u16 *r = Pico32x.regs;
797
798     elprintf(EL_32X, "m68k 32x w8  [%06x]   %02x @%06x", a, d & 0xff, SekPc);
799     a &= 0x3f;
800     if (a == 1) {
801       if ((d ^ r[0]) & d & P32XS_ADEN) {
802         Pico32xStartup();
803         r[0] &= ~P32XS_nRES; // causes reset if specified by this write
804         r[0] |= P32XS_ADEN;
805         p32x_reg_write8(a, d); // forward for reset processing
806       }
807       return;
808     }
809
810     // allow only COMM for now
811     if ((a & 0x30) == 0x20) {
812       u8 *r8 = (u8 *)r;
813       r8[a ^ 1] = d;
814     }
815     return;
816   }
817
818   elprintf(EL_UIO, "m68k unmapped w8  [%06x]   %02x @%06x", a, d & 0xff, SekPc);
819 }
820
821 void PicoWrite16_32x(u32 a, u32 d)
822 {
823   if ((a & 0xffc0) == 0x5100) { // a15100
824     u16 *r = Pico32x.regs;
825
826     elprintf(EL_UIO, "m68k 32x w16 [%06x] %04x @%06x", a, d & 0xffff, SekPc);
827     a &= 0x3e;
828     if (a == 0) {
829       if ((d ^ r[0]) & d & P32XS_ADEN) {
830         Pico32xStartup();
831         r[0] &= ~P32XS_nRES; // causes reset if specified by this write
832         r[0] |= P32XS_ADEN;
833         p32x_reg_write16(a, d); // forward for reset processing
834       }
835       return;
836     }
837
838     // allow only COMM for now
839     if ((a & 0x30) == 0x20)
840       r[a / 2] = d;
841     return;
842   }
843
844   elprintf(EL_UIO, "m68k unmapped w16 [%06x] %04x @%06x", a, d & 0xffff, SekPc);
845 }
846
847 // -----------------------------------------------------------------
848
849 // hint vector is writeable
850 static void PicoWrite8_hint(u32 a, u32 d)
851 {
852   if ((a & 0xfffc) == 0x0070) {
853     Pico32xMem->m68k_rom[a ^ 1] = d;
854     return;
855   }
856
857   elprintf(EL_UIO, "m68k unmapped w8  [%06x]   %02x @%06x", a, d & 0xff, SekPc);
858 }
859
860 static void PicoWrite16_hint(u32 a, u32 d)
861 {
862   if ((a & 0xfffc) == 0x0070) {
863     ((u16 *)Pico32xMem->m68k_rom)[a/2] = d;
864     return;
865   }
866
867   elprintf(EL_UIO, "m68k unmapped w16 [%06x] %04x @%06x", a, d & 0xffff, SekPc);
868 }
869
870 void Pico32xSwapDRAM(int b)
871 {
872   cpu68k_map_set(m68k_read8_map,   0x840000, 0x85ffff, Pico32xMem->dram[b], 0);
873   cpu68k_map_set(m68k_read16_map,  0x840000, 0x85ffff, Pico32xMem->dram[b], 0);
874   cpu68k_map_set(m68k_write8_map,  0x840000, 0x85ffff, Pico32xMem->dram[b], 0);
875   cpu68k_map_set(m68k_write16_map, 0x840000, 0x85ffff, Pico32xMem->dram[b], 0);
876 }
877
878 static void bank_switch(int b)
879 {
880   unsigned int rs, bank;
881
882   bank = b << 20;
883   if (bank >= Pico.romsize) {
884     elprintf(EL_32X|EL_ANOMALY, "missing bank @ %06x", bank);
885     return;
886   }
887
888   // 32X ROM (unbanked, XXX: consider mirroring?)
889   rs = (Pico.romsize + M68K_BANK_MASK) & ~M68K_BANK_MASK;
890   rs -= bank;
891   if (rs > 0x100000)
892     rs = 0x100000;
893   cpu68k_map_set(m68k_read8_map,   0x900000, 0x900000 + rs - 1, Pico.rom + bank, 0);
894   cpu68k_map_set(m68k_read16_map,  0x900000, 0x900000 + rs - 1, Pico.rom + bank, 0);
895
896   elprintf(EL_32X, "bank %06x-%06x -> %06x", 0x900000, 0x900000 + rs - 1, bank);
897
898 #ifdef EMU_F68K
899   // setup FAME fetchmap
900   for (rs = 0x90; rs < 0xa0; rs++)
901     PicoCpuFM68k.Fetch[rs] = (u32)Pico.rom + bank - 0x900000;
902 #endif
903 }
904
905 // -----------------------------------------------------------------
906 //                              SH2  
907 // -----------------------------------------------------------------
908
909 u32 p32x_sh2_read8(u32 a, int id)
910 {
911   u32 d = 0;
912
913   if (id == 0 && a < sizeof(Pico32xMem->sh2_rom_m))
914     return Pico32xMem->sh2_rom_m[a ^ 1];
915   if (id == 1 && a < sizeof(Pico32xMem->sh2_rom_s))
916     return Pico32xMem->sh2_rom_s[a ^ 1];
917
918   if ((a & 0xdffc0000) == 0x06000000)
919     return Pico32xMem->sdram[(a & 0x3ffff) ^ 1];
920
921   if ((a & 0xdfc00000) == 0x02000000)
922     if ((a & 0x003fffff) < Pico.romsize)
923       return Pico.rom[(a & 0x3fffff) ^ 1];
924
925   if ((a & ~0xfff) == 0xc0000000)
926     return Pico32xMem->data_array[id][(a & 0xfff) ^ 1];
927
928   if ((a & 0xdffc0000) == 0x04000000) {
929     /* XXX: overwrite readable as normal? */
930     u8 *dram = (u8 *)Pico32xMem->dram[(Pico32x.vdp_regs[0x0a/2] & P32XV_FS) ^ 1];
931     return dram[(a & 0x1ffff) ^ 1];
932   }
933
934   if ((a & 0xdfffff00) == 0x4000) {
935     d = p32x_sh2reg_read16(a, id);
936     goto out_16to8;
937   }
938
939   if ((a & 0xdfffff00) == 0x4100) {
940     d = p32x_vdp_read16(a);
941     if (p32x_poll_detect(&sh2_poll[id], a, ash2_cycles_done(), 1))
942       ash2_end_run(8);
943     goto out_16to8;
944   }
945
946   if ((a & 0xdfffff00) == 0x4200) {
947     d = Pico32xMem->pal[(a & 0x1ff) / 2];
948     goto out_16to8;
949   }
950
951   if ((a & 0xfffffe00) == 0xfffffe00)
952     return sh2_peripheral_read8(a, id);
953
954   elprintf(EL_UIO, "%csh2 unmapped r8  [%08x]       %02x @%06x",
955     id ? 's' : 'm', a, d, sh2_pc(id));
956   return d;
957
958 out_16to8:
959   if (a & 1)
960     d &= 0xff;
961   else
962     d >>= 8;
963
964   elprintf(EL_32X, "%csh2 r8  [%08x]       %02x @%06x",
965     id ? 's' : 'm', a, d, sh2_pc(id));
966   return d;
967 }
968
969 u32 p32x_sh2_read16(u32 a, int id)
970 {
971   u32 d = 0;
972
973   if (id == 0 && a < sizeof(Pico32xMem->sh2_rom_m))
974     return *(u16 *)(Pico32xMem->sh2_rom_m + a);
975   if (id == 1 && a < sizeof(Pico32xMem->sh2_rom_s))
976     return *(u16 *)(Pico32xMem->sh2_rom_s + a);
977
978   if ((a & 0xdffc0000) == 0x06000000)
979     return ((u16 *)Pico32xMem->sdram)[(a & 0x3ffff) / 2];
980
981   if ((a & 0xdfc00000) == 0x02000000)
982     if ((a & 0x003fffff) < Pico.romsize)
983       return ((u16 *)Pico.rom)[(a & 0x3fffff) / 2];
984
985   if ((a & ~0xfff) == 0xc0000000)
986     return ((u16 *)Pico32xMem->data_array[id])[(a & 0xfff) / 2];
987
988   if ((a & 0xdffe0000) == 0x04000000)
989     return Pico32xMem->dram[(Pico32x.vdp_regs[0x0a/2] & P32XV_FS) ^ 1][(a & 0x1ffff) / 2];
990
991   if ((a & 0xdfffff00) == 0x4000) {
992     d = p32x_sh2reg_read16(a, id);
993     if (!(EL_LOGMASK & EL_PWM) && (a & 0x30) == 0x30) // hide PWM
994       return d;
995     goto out;
996   }
997
998   if ((a & 0xdfffff00) == 0x4100) {
999     d = p32x_vdp_read16(a);
1000     if (p32x_poll_detect(&sh2_poll[id], a, ash2_cycles_done(), 1))
1001       ash2_end_run(8);
1002     goto out;
1003   }
1004
1005   if ((a & 0xdfffff00) == 0x4200) {
1006     d = Pico32xMem->pal[(a & 0x1ff) / 2];
1007     goto out;
1008   }
1009
1010   if ((a & 0xfffffe00) == 0xfffffe00)
1011     return sh2_peripheral_read16(a, id);
1012
1013   elprintf(EL_UIO, "%csh2 unmapped r16 [%08x]     %04x @%06x",
1014     id ? 's' : 'm', a, d, sh2_pc(id));
1015   return d;
1016
1017 out:
1018   elprintf(EL_32X, "%csh2 r16 [%08x]     %04x @%06x",
1019     id ? 's' : 'm', a, d, sh2_pc(id));
1020   return d;
1021 }
1022
1023 u32 p32x_sh2_read32(u32 a, int id)
1024 {
1025   if ((a & 0xfffffe00) == 0xfffffe00)
1026     return sh2_peripheral_read32(a, id);
1027
1028 //  elprintf(EL_UIO, "sh2 r32 [%08x] %08x @%06x", a, d, ash2_pc());
1029   return (p32x_sh2_read16(a, id) << 16) | p32x_sh2_read16(a + 2, id);
1030 }
1031
1032 void p32x_sh2_write8(u32 a, u32 d, int id)
1033 {
1034   if ((a & 0xdffffc00) == 0x4000)
1035     elprintf(EL_32X, "%csh2 w8  [%08x]       %02x @%06x",
1036       id ? 's' : 'm', a, d & 0xff, sh2_pc(id));
1037
1038   if ((a & 0xdffc0000) == 0x06000000) {
1039     Pico32xMem->sdram[(a & 0x3ffff) ^ 1] = d;
1040     return;
1041   }
1042
1043   if ((a & 0xdffc0000) == 0x04000000) {
1044     u8 *dram;
1045     if (!(a & 0x20000) || d) {
1046       dram = (u8 *)Pico32xMem->dram[(Pico32x.vdp_regs[0x0a/2] & P32XV_FS) ^ 1];
1047       dram[(a & 0x1ffff) ^ 1] = d;
1048     }
1049     return;
1050   }
1051
1052   if ((a & ~0xfff) == 0xc0000000) {
1053     Pico32xMem->data_array[id][(a & 0xfff) ^ 1] = d;
1054     return;
1055   }
1056
1057   if ((a & 0xdfffff00) == 0x4100) {
1058     p32x_vdp_write8(a, d);
1059     return;
1060   }
1061
1062   if ((a & 0xdfffff00) == 0x4000) {
1063     p32x_sh2reg_write8(a, d, id);
1064     return;
1065   }
1066
1067   if ((a & 0xfffffe00) == 0xfffffe00) {
1068     sh2_peripheral_write8(a, d, id);
1069     return;
1070   }
1071
1072   elprintf(EL_UIO, "%csh2 unmapped w8  [%08x]       %02x @%06x",
1073     id ? 's' : 'm', a, d & 0xff, sh2_pc(id));
1074 }
1075
1076 void p32x_sh2_write16(u32 a, u32 d, int id)
1077 {
1078   if ((a & 0xdffffc00) == 0x4000 && ((EL_LOGMASK & EL_PWM) || (a & 0x30) != 0x30)) // hide PWM
1079     elprintf(EL_32X, "%csh2 w16 [%08x]     %04x @%06x",
1080       id ? 's' : 'm', a, d & 0xffff, sh2_pc(id));
1081
1082   // ignore "Associative purge space"
1083   if ((a & 0xf8000000) == 0x40000000)
1084     return;
1085
1086   if ((a & 0xdffc0000) == 0x06000000) {
1087     ((u16 *)Pico32xMem->sdram)[(a & 0x3ffff) / 2] = d;
1088     return;
1089   }
1090
1091   if ((a & ~0xfff) == 0xc0000000) {
1092     ((u16 *)Pico32xMem->data_array[id])[(a & 0xfff) / 2] = d;
1093     return;
1094   }
1095
1096   if ((a & 0xdffc0000) == 0x04000000) {
1097     u16 *pd = &Pico32xMem->dram[(Pico32x.vdp_regs[0x0a/2] & P32XV_FS) ^ 1][(a & 0x1ffff) / 2];
1098     if (!(a & 0x20000)) {
1099       *pd = d;
1100       return;
1101     }
1102     // overwrite
1103     if (!(d & 0xff00)) d |= *pd & 0xff00;
1104     if (!(d & 0x00ff)) d |= *pd & 0x00ff;
1105     *pd = d;
1106     return;
1107   }
1108
1109   if ((a & 0xdfffff00) == 0x4100) {
1110     sh2_poll[id].cnt = 0; // for poll before VDP accesses
1111     p32x_vdp_write16(a, d);
1112     return;
1113   }
1114
1115   if ((a & 0xdffffe00) == 0x4200) {
1116     Pico32xMem->pal[(a & 0x1ff) / 2] = d;
1117     Pico32x.dirty_pal = 1;
1118     return;
1119   }
1120
1121   if ((a & 0xdfffff00) == 0x4000) {
1122     p32x_sh2reg_write16(a, d, id);
1123     return;
1124   }
1125
1126   if ((a & 0xfffffe00) == 0xfffffe00) {
1127     sh2_peripheral_write16(a, d, id);
1128     return;
1129   }
1130
1131   elprintf(EL_UIO, "%csh2 unmapped w16 [%08x]     %04x @%06x",
1132     id ? 's' : 'm', a, d & 0xffff, sh2_pc(id));
1133 }
1134
1135 void p32x_sh2_write32(u32 a, u32 d, int id)
1136 {
1137   if ((a & 0xfffffe00) == 0xfffffe00) {
1138     sh2_peripheral_write32(a, d, id);
1139     return;
1140   }
1141
1142   p32x_sh2_write16(a, d >> 16, id);
1143   p32x_sh2_write16(a + 2, d, id);
1144 }
1145
1146 static const u16 msh2_code[] = {
1147   // trap instructions
1148   0xaffe, // bra <self>
1149   0x0009, // nop
1150   // have to wait a bit until m68k initial program finishes clearing stuff
1151   // to avoid races with game SH2 code, like in Tempo
1152   0xd004, // mov.l   @(_m_ok,pc), r0
1153   0xd105, // mov.l   @(_cnt,pc), r1
1154   0xd205, // mov.l   @(_start,pc), r2
1155   0x71ff, // add     #-1, r1
1156   0x4115, // cmp/pl  r1
1157   0x89fc, // bt      -2
1158   0xc208, // mov.l   r0, @(h'20,gbr)
1159   0x6822, // mov.l   @r2, r8
1160   0x482b, // jmp     @r8
1161   0x0009, // nop
1162   ('M'<<8)|'_', ('O'<<8)|'K',
1163   0x0001, 0x0000,
1164   0x2200, 0x03e0  // master start pointer in ROM
1165 };
1166
1167 static const u16 ssh2_code[] = {
1168   0xaffe, // bra <self>
1169   0x0009, // nop
1170   // code to wait for master, in case authentic master BIOS is used
1171   0xd104, // mov.l   @(_m_ok,pc), r1
1172   0xd206, // mov.l   @(_start,pc), r2
1173   0xc608, // mov.l   @(h'20,gbr), r0
1174   0x3100, // cmp/eq  r0, r1
1175   0x8bfc, // bf      #-2
1176   0xd003, // mov.l   @(_s_ok,pc), r0
1177   0xc209, // mov.l   r0, @(h'24,gbr)
1178   0x6822, // mov.l   @r2, r8
1179   0x482b, // jmp     @r8
1180   0x0009, // nop
1181   ('M'<<8)|'_', ('O'<<8)|'K',
1182   ('S'<<8)|'_', ('O'<<8)|'K',
1183   0x2200, 0x03e4  // slave start pointer in ROM
1184 };
1185
1186 #define HWSWAP(x) (((x) << 16) | ((x) >> 16))
1187 static void get_bios(void)
1188 {
1189   u16 *ps;
1190   u32 *pl;
1191   int i;
1192
1193   // M68K ROM
1194   if (p32x_bios_g != NULL) {
1195     elprintf(EL_STATUS|EL_32X, "32x: using supplied 68k BIOS");
1196     Byteswap(Pico32xMem->m68k_rom, p32x_bios_g, 0x100);
1197   }
1198   else {
1199     // generate 68k ROM
1200     ps = (u16 *)Pico32xMem->m68k_rom;
1201     pl = (u32 *)ps;
1202     for (i = 1; i < 0xc0/4; i++)
1203       pl[i] = HWSWAP(0x880200 + (i - 1) * 6);
1204
1205     // fill with nops
1206     for (i = 0xc0/2; i < 0x100/2; i++)
1207       ps[i] = 0x4e71;
1208
1209 #if 0
1210     ps[0xc0/2] = 0x46fc;
1211     ps[0xc2/2] = 0x2700; // move #0x2700,sr
1212     ps[0xfe/2] = 0x60fe; // jump to self
1213 #else
1214     ps[0xfe/2] = 0x4e75; // rts
1215 #endif
1216   }
1217   // fill remaining m68k_rom page with game ROM
1218   memcpy(Pico32xMem->m68k_rom + 0x100, Pico.rom + 0x100, sizeof(Pico32xMem->m68k_rom) - 0x100);
1219
1220   // MSH2
1221   if (p32x_bios_m != NULL) {
1222     elprintf(EL_STATUS|EL_32X, "32x: using supplied master SH2 BIOS");
1223     Byteswap(Pico32xMem->sh2_rom_m, p32x_bios_m, sizeof(Pico32xMem->sh2_rom_m));
1224   }
1225   else {
1226     pl = (u32 *)Pico32xMem->sh2_rom_m;
1227
1228     // fill exception vector table to our trap address
1229     for (i = 0; i < 128; i++)
1230       pl[i] = HWSWAP(0x200);
1231
1232     // startup code
1233     memcpy(Pico32xMem->sh2_rom_m + 0x200, msh2_code, sizeof(msh2_code));
1234
1235     // reset SP
1236     pl[1] = pl[3] = HWSWAP(0x6040000);
1237     // start
1238     pl[0] = pl[2] = HWSWAP(0x204);
1239   }
1240
1241   // SSH2
1242   if (p32x_bios_s != NULL) {
1243     elprintf(EL_STATUS|EL_32X, "32x: using supplied slave SH2 BIOS");
1244     Byteswap(Pico32xMem->sh2_rom_s, p32x_bios_s, sizeof(Pico32xMem->sh2_rom_s));
1245   }
1246   else {
1247     pl = (u32 *)Pico32xMem->sh2_rom_s;
1248
1249     // fill exception vector table to our trap address
1250     for (i = 0; i < 128; i++)
1251       pl[i] = HWSWAP(0x200);
1252
1253     // startup code
1254     memcpy(Pico32xMem->sh2_rom_s + 0x200, ssh2_code, sizeof(ssh2_code));
1255
1256     // reset SP
1257     pl[1] = pl[3] = HWSWAP(0x603f800);
1258     // start
1259     pl[0] = pl[2] = HWSWAP(0x204);
1260   }
1261 }
1262
1263 void PicoMemSetup32x(void)
1264 {
1265   unsigned int rs;
1266
1267   Pico32xMem = calloc(1, sizeof(*Pico32xMem));
1268   if (Pico32xMem == NULL) {
1269     elprintf(EL_STATUS, "OOM");
1270     return;
1271   }
1272
1273   dmac0 = (void *)&Pico32xMem->sh2_peri_regs[0][0x180 / 4];
1274
1275   get_bios();
1276
1277   // cartridge area becomes unmapped
1278   // XXX: we take the easy way and don't unmap ROM,
1279   // so that we can avoid handling the RV bit.
1280   // m68k_map_unmap(0x000000, 0x3fffff);
1281
1282   // MD ROM area
1283   rs = sizeof(Pico32xMem->m68k_rom);
1284   cpu68k_map_set(m68k_read8_map,   0x000000, rs - 1, Pico32xMem->m68k_rom, 0);
1285   cpu68k_map_set(m68k_read16_map,  0x000000, rs - 1, Pico32xMem->m68k_rom, 0);
1286   cpu68k_map_set(m68k_write8_map,  0x000000, rs - 1, PicoWrite8_hint, 1); // TODO verify
1287   cpu68k_map_set(m68k_write16_map, 0x000000, rs - 1, PicoWrite16_hint, 1);
1288
1289   // DRAM area
1290   Pico32xSwapDRAM(1);
1291
1292   // 32X ROM (unbanked, XXX: consider mirroring?)
1293   rs = (Pico.romsize + M68K_BANK_MASK) & ~M68K_BANK_MASK;
1294   if (rs > 0x80000)
1295     rs = 0x80000;
1296   cpu68k_map_set(m68k_read8_map,   0x880000, 0x880000 + rs - 1, Pico.rom, 0);
1297   cpu68k_map_set(m68k_read16_map,  0x880000, 0x880000 + rs - 1, Pico.rom, 0);
1298 #ifdef EMU_F68K
1299   // setup FAME fetchmap
1300   PicoCpuFM68k.Fetch[0] = (u32)Pico32xMem->m68k_rom;
1301   for (rs = 0x88; rs < 0x90; rs++)
1302     PicoCpuFM68k.Fetch[rs] = (u32)Pico.rom - 0x880000;
1303 #endif
1304
1305   // 32X ROM (banked)
1306   bank_switch(0);
1307
1308   // SYS regs
1309   cpu68k_map_set(m68k_read8_map,   0xa10000, 0xa1ffff, PicoRead8_32x_on, 1);
1310   cpu68k_map_set(m68k_read16_map,  0xa10000, 0xa1ffff, PicoRead16_32x_on, 1);
1311   cpu68k_map_set(m68k_write8_map,  0xa10000, 0xa1ffff, PicoWrite8_32x_on, 1);
1312   cpu68k_map_set(m68k_write16_map, 0xa10000, 0xa1ffff, PicoWrite16_32x_on, 1);
1313
1314   // setup poll detector
1315   m68k_poll.flag = P32XF_68KPOLL;
1316   m68k_poll.cyc_max = 64;
1317   sh2_poll[0].flag = P32XF_MSH2POLL;
1318   sh2_poll[0].cyc_max = 21;
1319   sh2_poll[1].flag = P32XF_SSH2POLL;
1320   sh2_poll[1].cyc_max = 16;
1321 }
1322