32x: implement standard/ssf2 mapper, part 2
[picodrive.git] / pico / 32x / memory.c
1 /*
2  * PicoDrive
3  * (C) notaz, 2009,2010,2013
4  *
5  * This work is licensed under the terms of MAME license.
6  * See COPYING file in the top-level directory.
7  *
8  * Register map:
9  * a15100 F....... R.....EA  F.....AC N...VHMP 4000 // Fm Ren nrEs Aden Cart heN V H cMd Pwm
10  * a15102 ........ ......SM  ?                 4002 // intS intM
11  * a15104 ........ ......10  ........ hhhhhhhh 4004 // bk1 bk0 Hint
12  * a15106 ........ F....SDR  UE...... .....SDR 4006 // Full 68S Dma Rv fUll[fb] Empt[fb]
13  * a15108           (32bit DREQ src)           4008
14  * a1510c           (32bit DREQ dst)           400c
15  * a15110          llllllll llllll00           4010 // DREQ Len
16  * a15112           (16bit FIFO reg)           4012
17  * a15114 0                  (16bit VRES clr)  4014
18  * a15116 0                  (16bit Vint clr)  4016
19  * a15118 0                  (16bit Hint clr)  4018
20  * a1511a .......? .......C  (16bit CMD clr)   401a // TV Cm
21  * a1511c 0                  (16bit PWM clr)   401c
22  * a1511e 0                  ?                 401e
23  * a15120            (16 bytes comm)           2020
24  * a15130                 (PWM)                2030
25  *
26  * SH2 addr lines:
27  * iii. .cc. ..xx *   // Internal, Cs, x
28  *
29  * sh2 map, wait/bus cycles (from docs):
30  *                             r    w
31  * rom      0000000-0003fff    1    -
32  * sys reg  0004000-00040ff    1    1
33  * vdp reg  0004100-00041ff    5    5
34  * vdp pal  0004200-00043ff    5    5
35  * cart     2000000-23fffff     6-15
36  * dram/fb  4000000-401ffff 5-12  1-3
37  * fb ovr   4020000-403ffff
38  * sdram    6000000-603ffff   12    2  (cycles)
39  * d.a.    c0000000-?
40  */
41 #include "../pico_int.h"
42 #include "../memory.h"
43 #include "../../cpu/sh2/compiler.h"
44
45 static const char str_mars[] = "MARS";
46
47 void *p32x_bios_g, *p32x_bios_m, *p32x_bios_s;
48 struct Pico32xMem *Pico32xMem;
49
50 static void bank_switch_rom_68k(int b);
51
52 static void (*m68k_write8_io)(u32 a, u32 d);
53 static void (*m68k_write16_io)(u32 a, u32 d);
54
55 // addressing byte in 16bit reg
56 #define REG8IN16(ptr, offs) ((u8 *)ptr)[(offs) ^ 1]
57
58 // poll detection
59 #define POLL_THRESHOLD 3
60
61 static struct {
62   u32 addr, cycles;
63   int cnt;
64 } m68k_poll;
65
66 static int m68k_poll_detect(u32 a, u32 cycles, u32 flags)
67 {
68   int ret = 0;
69
70   if (a - 2 <= m68k_poll.addr && m68k_poll.addr <= a + 2
71     && cycles - m68k_poll.cycles <= 64 && !SekNotPolling)
72   {
73     if (m68k_poll.cnt++ > POLL_THRESHOLD) {
74       if (!(Pico32x.emu_flags & flags)) {
75         elprintf(EL_32X, "m68k poll addr %08x, cyc %u",
76           a, cycles - m68k_poll.cycles);
77         ret = 1;
78       }
79       Pico32x.emu_flags |= flags;
80     }
81   }
82   else {
83     m68k_poll.cnt = 0;
84     m68k_poll.addr = a;
85     SekNotPolling = 0;
86   }
87   m68k_poll.cycles = cycles;
88
89   return ret;
90 }
91
92 void p32x_m68k_poll_event(u32 flags)
93 {
94   if (Pico32x.emu_flags & flags) {
95     elprintf(EL_32X, "m68k poll %02x -> %02x", Pico32x.emu_flags,
96       Pico32x.emu_flags & ~flags);
97     Pico32x.emu_flags &= ~flags;
98     SekSetStop(0);
99   }
100   m68k_poll.addr = m68k_poll.cnt = 0;
101 }
102
103 static void sh2_poll_detect(SH2 *sh2, u32 a, u32 flags, int maxcnt)
104 {
105   int cycles_left = sh2_cycles_left(sh2);
106
107   if (a == sh2->poll_addr && sh2->poll_cycles - cycles_left <= 10) {
108     if (sh2->poll_cnt++ > maxcnt) {
109       if (!(sh2->state & flags))
110         elprintf_sh2(sh2, EL_32X, "state: %02x->%02x",
111           sh2->state, sh2->state | flags);
112
113       sh2->state |= flags;
114       sh2_end_run(sh2, 1);
115       pevt_log_sh2(sh2, EVT_POLL_START);
116       return;
117     }
118   }
119   else
120     sh2->poll_cnt = 0;
121   sh2->poll_addr = a;
122   sh2->poll_cycles = cycles_left;
123 }
124
125 void p32x_sh2_poll_event(SH2 *sh2, u32 flags, u32 m68k_cycles)
126 {
127   if (sh2->state & flags) {
128     elprintf_sh2(sh2, EL_32X, "state: %02x->%02x", sh2->state,
129       sh2->state & ~flags);
130
131     if (sh2->m68krcycles_done < m68k_cycles)
132       sh2->m68krcycles_done = m68k_cycles;
133
134     pevt_log_sh2_o(sh2, EVT_POLL_END);
135   }
136
137   sh2->state &= ~flags;
138   sh2->poll_addr = sh2->poll_cycles = sh2->poll_cnt = 0;
139 }
140
141 static void sh2s_sync_on_read(SH2 *sh2)
142 {
143   int cycles;
144   if (sh2->poll_cnt != 0)
145     return;
146
147   cycles = sh2_cycles_done(sh2);
148   if (cycles > 600)
149     p32x_sync_other_sh2(sh2, sh2->m68krcycles_done + cycles / 3);
150 }
151
152 // SH2 faking
153 //#define FAKE_SH2
154 #ifdef FAKE_SH2
155 static int p32x_csum_faked;
156 static const u16 comm_fakevals[] = {
157   0x4d5f, 0x4f4b, // M_OK
158   0x535f, 0x4f4b, // S_OK
159   0x4D41, 0x5346, // MASF - Brutal Unleashed
160   0x5331, 0x4d31, // Darxide
161   0x5332, 0x4d32,
162   0x5333, 0x4d33,
163   0x0000, 0x0000, // eq for doom
164   0x0002, // Mortal Kombat
165 //  0, // pad
166 };
167
168 static u32 sh2_comm_faker(u32 a)
169 {
170   static int f = 0;
171   if (a == 0x28 && !p32x_csum_faked) {
172     p32x_csum_faked = 1;
173     return *(unsigned short *)(Pico.rom + 0x18e);
174   }
175   if (f >= sizeof(comm_fakevals) / sizeof(comm_fakevals[0]))
176     f = 0;
177   return comm_fakevals[f++];
178 }
179 #endif
180
181 // ------------------------------------------------------------------
182 // 68k regs
183
184 static u32 p32x_reg_read16(u32 a)
185 {
186   a &= 0x3e;
187
188 #if 0
189   if ((a & 0x30) == 0x20)
190     return sh2_comm_faker(a);
191 #else
192   if ((a & 0x30) == 0x20) {
193     unsigned int cycles = SekCyclesDone();
194     int comreg = 1 << (a & 0x0f) / 2;
195
196     if (cycles - msh2.m68krcycles_done > 244
197         || (Pico32x.comm_dirty & comreg))
198       p32x_sync_sh2s(cycles);
199
200     if (m68k_poll_detect(a, cycles, P32XF_68KCPOLL)) {
201       SekSetStop(1);
202       SekEndRun(16);
203     }
204     goto out;
205   }
206 #endif
207
208   if (a == 2) { // INTM, INTS
209     unsigned int cycles = SekCyclesDone();
210     if (cycles - msh2.m68krcycles_done > 64)
211       p32x_sync_sh2s(cycles);
212     goto out;
213   }
214
215   if ((a & 0x30) == 0x30)
216     return p32x_pwm_read16(a, NULL, SekCyclesDone());
217
218 out:
219   return Pico32x.regs[a / 2];
220 }
221
222 static void dreq0_write(u16 *r, u32 d)
223 {
224   if (!(r[6 / 2] & P32XS_68S)) {
225     elprintf(EL_32X|EL_ANOMALY, "DREQ FIFO w16 without 68S?");
226     return; // ignored - tested
227   }
228   if (Pico32x.dmac0_fifo_ptr < DMAC_FIFO_LEN) {
229     Pico32x.dmac_fifo[Pico32x.dmac0_fifo_ptr++] = d;
230     if (Pico32x.dmac0_fifo_ptr == DMAC_FIFO_LEN)
231       r[6 / 2] |= P32XS_FULL;
232     // tested: len register decrements and 68S clears
233     // even if SH2s/DMAC aren't active..
234     r[0x10 / 2]--;
235     if (r[0x10 / 2] == 0)
236       r[6 / 2] &= ~P32XS_68S;
237
238     if ((Pico32x.dmac0_fifo_ptr & 3) == 0) {
239       p32x_sync_sh2s(SekCyclesDone());
240       p32x_dreq0_trigger();
241     }
242   }
243   else
244     elprintf(EL_32X|EL_ANOMALY, "DREQ FIFO overflow!");
245 }
246
247 // writable bits tested
248 static void p32x_reg_write8(u32 a, u32 d)
249 {
250   u16 *r = Pico32x.regs;
251   a &= 0x3f;
252
253   // for things like bset on comm port
254   m68k_poll.cnt = 0;
255
256   switch (a) {
257     case 0x00: // adapter ctl: FM writable
258       REG8IN16(r, 0x00) = d & 0x80;
259       return;
260     case 0x01: // adapter ctl: RES and ADEN writable
261       if ((d ^ r[0]) & d & P32XS_nRES)
262         p32x_reset_sh2s();
263       REG8IN16(r, 0x01) &= ~(P32XS_nRES|P32XS_ADEN);
264       REG8IN16(r, 0x01) |= d & (P32XS_nRES|P32XS_ADEN);
265       return;
266     case 0x02: // ignored, always 0
267       return;
268     case 0x03: // irq ctl
269       if ((d ^ r[0x02 / 2]) & 3) {
270         int cycles = SekCyclesDone();
271         p32x_sync_sh2s(cycles);
272         r[0x02 / 2] = d & 3;
273         p32x_update_cmd_irq(NULL, cycles);
274       }
275       return;
276     case 0x04: // ignored, always 0
277       return;
278     case 0x05: // bank
279       d &= 3;
280       if (r[0x04 / 2] != d) {
281         r[0x04 / 2] = d;
282         bank_switch_rom_68k(d);
283       }
284       return;
285     case 0x06: // ignored, always 0
286       return;
287     case 0x07: // DREQ ctl
288       REG8IN16(r, 0x07) &= ~(P32XS_68S|P32XS_DMA|P32XS_RV);
289       if (!(d & P32XS_68S)) {
290         Pico32x.dmac0_fifo_ptr = 0;
291         REG8IN16(r, 0x07) &= ~P32XS_FULL;
292       }
293       REG8IN16(r, 0x07) |= d & (P32XS_68S|P32XS_DMA|P32XS_RV);
294       return;
295     case 0x08: // ignored, always 0
296       return;
297     case 0x09: // DREQ src
298       REG8IN16(r, 0x09) = d;
299       return;
300     case 0x0a:
301       REG8IN16(r, 0x0a) = d;
302       return;
303     case 0x0b:
304       REG8IN16(r, 0x0b) = d & 0xfe;
305       return;
306     case 0x0c: // ignored, always 0
307       return;
308     case 0x0d: // DREQ dest
309     case 0x0e:
310     case 0x0f:
311     case 0x10: // DREQ len
312       REG8IN16(r, a) = d;
313       return;
314     case 0x11:
315       REG8IN16(r, a) = d & 0xfc;
316       return;
317     // DREQ FIFO - writes to odd addr go to fifo
318     // do writes to even work? Reads return 0
319     case 0x12:
320       REG8IN16(r, a) = d;
321       return;
322     case 0x13:
323       d = (REG8IN16(r, 0x12) << 8) | (d & 0xff);
324       REG8IN16(r, 0x12) = 0;
325       dreq0_write(r, d);
326       return;
327     case 0x14: // ignored, always 0
328     case 0x15:
329     case 0x16:
330     case 0x17:
331     case 0x18:
332     case 0x19:
333       return;
334     case 0x1a: // what's this?
335       elprintf(EL_32X|EL_ANOMALY, "mystery w8 %02x %02x", a, d);
336       REG8IN16(r, a) = d & 0x01;
337       return;
338     case 0x1b: // TV
339       REG8IN16(r, a) = d & 0x01;
340       return;
341     case 0x1c: // ignored, always 0
342     case 0x1d:
343     case 0x1e:
344     case 0x1f:
345     case 0x30:
346       return;
347     case 0x31: // PWM control
348       REG8IN16(r, a) &= ~0x0f;
349       REG8IN16(r, a) |= d & 0x0f;
350       d = r[0x30 / 2];
351       goto pwm_write;
352     case 0x32: // PWM cycle
353       REG8IN16(r, a) = d & 0x0f;
354       d = r[0x32 / 2];
355       goto pwm_write;
356     case 0x33:
357       REG8IN16(r, a) = d;
358       d = r[0x32 / 2];
359       goto pwm_write;
360     // PWM pulse regs.. Only writes to odd address send a value
361     // to FIFO; reads are 0 (except status bits)
362     case 0x34:
363     case 0x36:
364     case 0x38:
365       REG8IN16(r, a) = d;
366       return;
367     case 0x35:
368     case 0x37:
369     case 0x39:
370       d = (REG8IN16(r, a ^ 1) << 8) | (d & 0xff);
371       REG8IN16(r, a ^ 1) = 0;
372       goto pwm_write;
373     case 0x3a: // ignored, always 0
374     case 0x3b:
375     case 0x3c:
376     case 0x3d:
377     case 0x3e:
378     case 0x3f:
379       return;
380     pwm_write:
381       p32x_pwm_write16(a & ~1, d, NULL, SekCyclesDone());
382       return;
383   }
384
385   if ((a & 0x30) == 0x20) {
386     int cycles = SekCyclesDone();
387     int comreg;
388     
389     if (REG8IN16(r, a) == d)
390       return;
391
392     p32x_sync_sh2s(cycles);
393
394     REG8IN16(r, a) = d;
395     p32x_sh2_poll_event(&sh2s[0], SH2_STATE_CPOLL, cycles);
396     p32x_sh2_poll_event(&sh2s[1], SH2_STATE_CPOLL, cycles);
397     comreg = 1 << (a & 0x0f) / 2;
398     Pico32x.comm_dirty |= comreg;
399
400     if (cycles - (int)msh2.m68krcycles_done > 120)
401       p32x_sync_sh2s(cycles);
402     return;
403   }
404 }
405
406 static void p32x_reg_write16(u32 a, u32 d)
407 {
408   u16 *r = Pico32x.regs;
409   a &= 0x3e;
410
411   // for things like bset on comm port
412   m68k_poll.cnt = 0;
413
414   switch (a) {
415     case 0x00: // adapter ctl
416       if ((d ^ r[0]) & d & P32XS_nRES)
417         p32x_reset_sh2s();
418       r[0] &= ~(P32XS_FM|P32XS_nRES|P32XS_ADEN);
419       r[0] |= d & (P32XS_FM|P32XS_nRES|P32XS_ADEN);
420       return;
421     case 0x08: // DREQ src
422       r[a / 2] = d & 0xff;
423       return;
424     case 0x0a:
425       r[a / 2] = d & ~1;
426       return;
427     case 0x0c: // DREQ dest
428       r[a / 2] = d & 0xff;
429       return;
430     case 0x0e:
431       r[a / 2] = d;
432       return;
433     case 0x10: // DREQ len
434       r[a / 2] = d & ~3;
435       return;
436     case 0x12: // FIFO reg
437       dreq0_write(r, d);
438       return;
439     case 0x1a: // TV + mystery bit
440       r[a / 2] = d & 0x0101;
441       return;
442     case 0x30: // PWM control
443       d = (r[a / 2] & ~0x0f) | (d & 0x0f);
444       r[a / 2] = d;
445       p32x_pwm_write16(a, d, NULL, SekCyclesDone());
446       return;
447   }
448
449   // comm port
450   if ((a & 0x30) == 0x20) {
451     int cycles = SekCyclesDone();
452     int comreg;
453     
454     p32x_sync_sh2s(cycles);
455
456     r[a / 2] = d;
457     p32x_sh2_poll_event(&sh2s[0], SH2_STATE_CPOLL, cycles);
458     p32x_sh2_poll_event(&sh2s[1], SH2_STATE_CPOLL, cycles);
459     comreg = 1 << (a & 0x0f) / 2;
460     Pico32x.comm_dirty |= comreg;
461     return;
462   }
463   // PWM
464   else if ((a & 0x30) == 0x30) {
465     p32x_pwm_write16(a, d, NULL, SekCyclesDone());
466     return;
467   }
468
469   p32x_reg_write8(a + 1, d);
470 }
471
472 // ------------------------------------------------------------------
473 // VDP regs
474 static u32 p32x_vdp_read16(u32 a)
475 {
476   u32 d;
477   a &= 0x0e;
478
479   d = Pico32x.vdp_regs[a / 2];
480   if (a == 0x0a) {
481     // tested: FEN seems to be randomly pulsing on hcnt 0x80-0xf0,
482     // most often at 0xb1-0xb5, even during vblank,
483     // what's the deal with that?
484     // we'll just fake it along with hblank for now
485     Pico32x.vdp_fbcr_fake++;
486     if (Pico32x.vdp_fbcr_fake & 4)
487       d |= P32XV_HBLK;
488     if ((Pico32x.vdp_fbcr_fake & 7) == 0)
489       d |= P32XV_nFEN;
490   }
491   return d;
492 }
493
494 static void p32x_vdp_write8(u32 a, u32 d)
495 {
496   u16 *r = Pico32x.vdp_regs;
497   a &= 0x0f;
498
499   // TODO: verify what's writeable
500   switch (a) {
501     case 0x01:
502       // priority inversion is handled in palette
503       if ((r[0] ^ d) & P32XV_PRI)
504         Pico32x.dirty_pal = 1;
505       r[0] = (r[0] & P32XV_nPAL) | (d & 0xff);
506       break;
507     case 0x03: // shift (for pp mode)
508       r[2 / 2] = d & 1;
509       break;
510     case 0x05: // fill len
511       r[4 / 2] = d & 0xff;
512       break;
513     case 0x0b:
514       d &= 1;
515       Pico32x.pending_fb = d;
516       // if we are blanking and FS bit is changing
517       if (((r[0x0a/2] & P32XV_VBLK) || (r[0] & P32XV_Mx) == 0) && ((r[0x0a/2] ^ d) & P32XV_FS)) {
518         r[0x0a/2] ^= P32XV_FS;
519         Pico32xSwapDRAM(d ^ 1);
520         elprintf(EL_32X, "VDP FS: %d", r[0x0a/2] & P32XV_FS);
521       }
522       break;
523   }
524 }
525
526 static void p32x_vdp_write16(u32 a, u32 d, SH2 *sh2)
527 {
528   a &= 0x0e;
529   if (a == 6) { // fill start
530     Pico32x.vdp_regs[6 / 2] = d;
531     return;
532   }
533   if (a == 8) { // fill data
534     u16 *dram = Pico32xMem->dram[(Pico32x.vdp_regs[0x0a/2] & P32XV_FS) ^ 1];
535     int len = Pico32x.vdp_regs[4 / 2] + 1;
536     int len1 = len;
537     a = Pico32x.vdp_regs[6 / 2];
538     while (len1--) {
539       dram[a] = d;
540       a = (a & 0xff00) | ((a + 1) & 0xff);
541     }
542     Pico32x.vdp_regs[0x06 / 2] = a;
543     Pico32x.vdp_regs[0x08 / 2] = d;
544     if (sh2 != NULL && len > 4) {
545       Pico32x.vdp_regs[0x0a / 2] |= P32XV_nFEN;
546       // supposedly takes 3 bus/6 sh2 cycles? or 3 sh2 cycles?
547       p32x_event_schedule_sh2(sh2, P32X_EVENT_FILLEND, 3 + len);
548     }
549     return;
550   }
551
552   p32x_vdp_write8(a | 1, d);
553 }
554
555 // ------------------------------------------------------------------
556 // SH2 regs
557
558 static u32 p32x_sh2reg_read16(u32 a, SH2 *sh2)
559 {
560   u16 *r = Pico32x.regs;
561   a &= 0x3e;
562
563   switch (a) {
564     case 0x00: // adapter/irq ctl
565       return (r[0] & P32XS_FM) | Pico32x.sh2_regs[0]
566         | Pico32x.sh2irq_mask[sh2->is_slave];
567     case 0x04: // H count (often as comm too)
568       sh2_poll_detect(sh2, a, SH2_STATE_CPOLL, 3);
569       sh2s_sync_on_read(sh2);
570       return Pico32x.sh2_regs[4 / 2];
571     case 0x06:
572       return (r[a / 2] & ~P32XS_FULL) | 0x4000;
573     case 0x08: // DREQ src
574     case 0x0a:
575     case 0x0c: // DREQ dst
576     case 0x0e:
577     case 0x10: // DREQ len
578       return r[a / 2];
579     case 0x12: // DREQ FIFO - does this work on hw?
580       if (Pico32x.dmac0_fifo_ptr > 0) {
581         Pico32x.dmac0_fifo_ptr--;
582         r[a / 2] = Pico32x.dmac_fifo[0];
583         memmove(&Pico32x.dmac_fifo[0], &Pico32x.dmac_fifo[1],
584           Pico32x.dmac0_fifo_ptr * 2);
585       }
586       return r[a / 2];
587     case 0x14:
588     case 0x16:
589     case 0x18:
590     case 0x1a:
591     case 0x1c:
592       return 0; // ?
593   }
594
595   // comm port
596   if ((a & 0x30) == 0x20) {
597     sh2_poll_detect(sh2, a, SH2_STATE_CPOLL, 3);
598     sh2s_sync_on_read(sh2);
599     return r[a / 2];
600   }
601   if ((a & 0x30) == 0x30)
602     return p32x_pwm_read16(a, sh2, sh2_cycles_done_m68k(sh2));
603
604   elprintf_sh2(sh2, EL_32X|EL_ANOMALY, 
605     "unhandled sysreg r16 [%02x] @%08x", a, sh2_pc(sh2));
606   return 0;
607 }
608
609 static void p32x_sh2reg_write8(u32 a, u32 d, SH2 *sh2)
610 {
611   u16 *r = Pico32x.regs;
612   u32 old;
613
614   a &= 0x3f;
615   sh2->poll_addr = 0;
616
617   switch (a) {
618     case 0x00: // FM
619       r[0] &= ~P32XS_FM;
620       r[0] |= (d << 8) & P32XS_FM;
621       return;
622     case 0x01: // HEN/irq masks
623       old = Pico32x.sh2irq_mask[sh2->is_slave];
624       if ((d ^ old) & 1)
625         p32x_pwm_sync_to_sh2(sh2);
626
627       Pico32x.sh2irq_mask[sh2->is_slave] = d & 0x0f;
628       Pico32x.sh2_regs[0] &= ~0x80;
629       Pico32x.sh2_regs[0] |= d & 0x80;
630
631       if ((d ^ old) & 1)
632         p32x_pwm_schedule_sh2(sh2);
633       if ((old ^ d) & 2)
634         p32x_update_cmd_irq(sh2, 0);
635       if ((old ^ d) & 4)
636         p32x_schedule_hint(sh2, 0); 
637       return;
638     case 0x04: // ignored?
639       return;
640     case 0x05: // H count
641       d &= 0xff;
642       if (Pico32x.sh2_regs[4 / 2] != d) {
643         Pico32x.sh2_regs[4 / 2] = d;
644         p32x_sh2_poll_event(sh2->other_sh2, SH2_STATE_CPOLL,
645           sh2_cycles_done_m68k(sh2));
646         sh2_end_run(sh2, 4);
647       }
648       return;
649     case 0x30:
650       REG8IN16(r, a) = d & 0x0f;
651       d = r[0x30 / 2];
652       goto pwm_write;
653     case 0x31: // PWM control
654       REG8IN16(r, a) = d & 0x8f;
655       d = r[0x30 / 2];
656       goto pwm_write;
657     case 0x32: // PWM cycle
658       REG8IN16(r, a) = d & 0x0f;
659       d = r[0x32 / 2];
660       goto pwm_write;
661     case 0x33:
662       REG8IN16(r, a) = d;
663       d = r[0x32 / 2];
664       goto pwm_write;
665     // PWM pulse regs.. Only writes to odd address send a value
666     // to FIFO; reads are 0 (except status bits)
667     case 0x34:
668     case 0x36:
669     case 0x38:
670       REG8IN16(r, a) = d;
671       return;
672     case 0x35:
673     case 0x37:
674     case 0x39:
675       d = (REG8IN16(r, a ^ 1) << 8) | (d & 0xff);
676       REG8IN16(r, a ^ 1) = 0;
677       goto pwm_write;
678     case 0x3a: // ignored, always 0?
679     case 0x3b:
680     case 0x3c:
681     case 0x3d:
682     case 0x3e:
683     case 0x3f:
684       return;
685     pwm_write:
686       p32x_pwm_write16(a & ~1, d, sh2, 0);
687       return;
688   }
689
690   if ((a & 0x30) == 0x20) {
691     int comreg;
692     if (REG8IN16(r, a) == d)
693       return;
694
695     REG8IN16(r, a) = d;
696     p32x_m68k_poll_event(P32XF_68KCPOLL);
697     p32x_sh2_poll_event(sh2->other_sh2, SH2_STATE_CPOLL,
698       sh2_cycles_done_m68k(sh2));
699     comreg = 1 << (a & 0x0f) / 2;
700     Pico32x.comm_dirty |= comreg;
701     return;
702   }
703
704   elprintf(EL_32X|EL_ANOMALY,
705     "unhandled sysreg w8  [%02x] %02x @%08x", a, d, sh2_pc(sh2));
706 }
707
708 static void p32x_sh2reg_write16(u32 a, u32 d, SH2 *sh2)
709 {
710   a &= 0x3e;
711
712   sh2->poll_addr = 0;
713
714   // comm
715   if ((a & 0x30) == 0x20) {
716     int comreg;
717     if (Pico32x.regs[a / 2] == d)
718       return;
719
720     Pico32x.regs[a / 2] = d;
721     p32x_m68k_poll_event(P32XF_68KCPOLL);
722     p32x_sh2_poll_event(sh2->other_sh2, SH2_STATE_CPOLL,
723       sh2_cycles_done_m68k(sh2));
724     comreg = 1 << (a & 0x0f) / 2;
725     Pico32x.comm_dirty |= comreg;
726     return;
727   }
728   // PWM
729   else if ((a & 0x30) == 0x30) {
730     p32x_pwm_write16(a, d, sh2, sh2_cycles_done_m68k(sh2));
731     return;
732   }
733
734   switch (a) {
735     case 0: // FM
736       Pico32x.regs[0] &= ~P32XS_FM;
737       Pico32x.regs[0] |= d & P32XS_FM;
738       break;
739     case 0x14:
740       Pico32x.sh2irqs &= ~P32XI_VRES;
741       goto irls;
742     case 0x16:
743       Pico32x.sh2irqi[sh2->is_slave] &= ~P32XI_VINT;
744       goto irls;
745     case 0x18:
746       Pico32x.sh2irqi[sh2->is_slave] &= ~P32XI_HINT;
747       goto irls;
748     case 0x1a:
749       Pico32x.regs[2 / 2] &= ~(1 << sh2->is_slave);
750       p32x_update_cmd_irq(sh2, 0);
751       return;
752     case 0x1c:
753       p32x_pwm_sync_to_sh2(sh2);
754       Pico32x.sh2irqi[sh2->is_slave] &= ~P32XI_PWM;
755       p32x_pwm_schedule_sh2(sh2);
756       goto irls;
757   }
758
759   p32x_sh2reg_write8(a | 1, d, sh2);
760   return;
761
762 irls:
763   p32x_update_irls(sh2, 0);
764 }
765
766 // ------------------------------------------------------------------
767 // 32x 68k handlers
768
769 // after ADEN
770 static u32 PicoRead8_32x_on(u32 a)
771 {
772   u32 d = 0;
773   if ((a & 0xffc0) == 0x5100) { // a15100
774     d = p32x_reg_read16(a);
775     goto out_16to8;
776   }
777
778   if ((a & 0xfc00) != 0x5000) {
779     if (PicoIn.AHW & PAHW_MCD)
780       return PicoRead8_mcd_io(a);
781     else
782       return PicoRead8_io(a);
783   }
784
785   if ((a & 0xfff0) == 0x5180) { // a15180
786     d = p32x_vdp_read16(a);
787     goto out_16to8;
788   }
789
790   if ((a & 0xfe00) == 0x5200) { // a15200
791     d = Pico32xMem->pal[(a & 0x1ff) / 2];
792     goto out_16to8;
793   }
794
795   if ((a & 0xfffc) == 0x30ec) { // a130ec
796     d = str_mars[a & 3];
797     goto out;
798   }
799
800   elprintf(EL_UIO, "m68k unmapped r8  [%06x] @%06x", a, SekPc);
801   return d;
802
803 out_16to8:
804   if (a & 1)
805     d &= 0xff;
806   else
807     d >>= 8;
808
809 out:
810   elprintf(EL_32X, "m68k 32x r8  [%06x]   %02x @%06x", a, d, SekPc);
811   return d;
812 }
813
814 static u32 PicoRead16_32x_on(u32 a)
815 {
816   u32 d = 0;
817   if ((a & 0xffc0) == 0x5100) { // a15100
818     d = p32x_reg_read16(a);
819     goto out;
820   }
821
822   if ((a & 0xfc00) != 0x5000) {
823     if (PicoIn.AHW & PAHW_MCD)
824       return PicoRead16_mcd_io(a);
825     else
826       return PicoRead16_io(a);
827   }
828
829   if ((a & 0xfff0) == 0x5180) { // a15180
830     d = p32x_vdp_read16(a);
831     goto out;
832   }
833
834   if ((a & 0xfe00) == 0x5200) { // a15200
835     d = Pico32xMem->pal[(a & 0x1ff) / 2];
836     goto out;
837   }
838
839   if ((a & 0xfffc) == 0x30ec) { // a130ec
840     d = !(a & 2) ? ('M'<<8)|'A' : ('R'<<8)|'S';
841     goto out;
842   }
843
844   elprintf(EL_UIO, "m68k unmapped r16 [%06x] @%06x", a, SekPc);
845   return d;
846
847 out:
848   elprintf(EL_32X, "m68k 32x r16 [%06x] %04x @%06x", a, d, SekPc);
849   return d;
850 }
851
852 static void PicoWrite8_32x_on(u32 a, u32 d)
853 {
854   if ((a & 0xfc00) == 0x5000)
855     elprintf(EL_32X, "m68k 32x w8  [%06x]   %02x @%06x", a, d & 0xff, SekPc);
856
857   if ((a & 0xffc0) == 0x5100) { // a15100
858     p32x_reg_write8(a, d);
859     return;
860   }
861
862   if ((a & 0xfc00) != 0x5000) {
863     m68k_write8_io(a, d);
864     return;
865   }
866
867   if (!(Pico32x.regs[0] & P32XS_FM)) {
868     if ((a & 0xfff0) == 0x5180) { // a15180
869       p32x_vdp_write8(a, d);
870       return;
871     }
872
873     // TODO: verify
874     if ((a & 0xfe00) == 0x5200) { // a15200
875       elprintf(EL_32X|EL_ANOMALY, "m68k 32x PAL w8  [%06x]   %02x @%06x", a, d & 0xff, SekPc);
876       ((u8 *)Pico32xMem->pal)[(a & 0x1ff) ^ 1] = d;
877       Pico32x.dirty_pal = 1;
878       return;
879     }
880   }
881
882   elprintf(EL_UIO, "m68k unmapped w8  [%06x]   %02x @%06x", a, d & 0xff, SekPc);
883 }
884
885 static void PicoWrite8_32x_on_io(u32 a, u32 d)
886 {
887   PicoWrite8_io(a, d);
888   if (a == 0xa130f1)
889     bank_switch_rom_68k(Pico32x.regs[4 / 2]);
890 }
891
892 static void PicoWrite8_32x_on_io_cd(u32 a, u32 d)
893 {
894   PicoWrite8_mcd_io(a, d);
895   if (a == 0xa130f1)
896     bank_switch_rom_68k(Pico32x.regs[4 / 2]);
897 }
898
899 static void PicoWrite8_32x_on_io_ssf2(u32 a, u32 d)
900 {
901   carthw_ssf2_write8(a, d);
902   if ((a & ~0x0e) == 0xa130f1)
903     bank_switch_rom_68k(Pico32x.regs[4 / 2]);
904 }
905
906 static void PicoWrite16_32x_on(u32 a, u32 d)
907 {
908   if ((a & 0xfc00) == 0x5000)
909     elprintf(EL_32X, "m68k 32x w16 [%06x] %04x @%06x", a, d & 0xffff, SekPc);
910
911   if ((a & 0xffc0) == 0x5100) { // a15100
912     p32x_reg_write16(a, d);
913     return;
914   }
915
916   if ((a & 0xfc00) != 0x5000) {
917     m68k_write16_io(a, d);
918     return;
919   }
920
921   if (!(Pico32x.regs[0] & P32XS_FM)) {
922     if ((a & 0xfff0) == 0x5180) { // a15180
923       p32x_vdp_write16(a, d, NULL); // FIXME?
924       return;
925     }
926
927     if ((a & 0xfe00) == 0x5200) { // a15200
928       Pico32xMem->pal[(a & 0x1ff) / 2] = d;
929       Pico32x.dirty_pal = 1;
930       return;
931     }
932   }
933
934   elprintf(EL_UIO, "m68k unmapped w16 [%06x] %04x @%06x", a, d & 0xffff, SekPc);
935 }
936
937 static void PicoWrite16_32x_on_io(u32 a, u32 d)
938 {
939   PicoWrite16_io(a, d);
940   if (a == 0xa130f0)
941     bank_switch_rom_68k(Pico32x.regs[4 / 2]);
942 }
943
944 static void PicoWrite16_32x_on_io_cd(u32 a, u32 d)
945 {
946   PicoWrite16_mcd_io(a, d);
947   if (a == 0xa130f0)
948     bank_switch_rom_68k(Pico32x.regs[4 / 2]);
949 }
950
951 static void PicoWrite16_32x_on_io_ssf2(u32 a, u32 d)
952 {
953   PicoWrite16_io(a, d);
954   if ((a & ~0x0f) == 0xa130f0) {
955     carthw_ssf2_write8(a + 1, d);
956     bank_switch_rom_68k(Pico32x.regs[4 / 2]);
957   }
958 }
959
960 // before ADEN
961 u32 PicoRead8_32x(u32 a)
962 {
963   u32 d = 0;
964
965   if (PicoIn.opt & POPT_EN_32X) {
966     if ((a & 0xffc0) == 0x5100) { // a15100
967       // regs are always readable
968       d = ((u8 *)Pico32x.regs)[(a & 0x3f) ^ 1];
969       goto out;
970     }
971
972     if ((a & 0xfffc) == 0x30ec) { // a130ec
973       d = str_mars[a & 3];
974       goto out;
975     }
976   }
977
978   elprintf(EL_UIO, "m68k unmapped r8  [%06x] @%06x", a, SekPc);
979   return d;
980
981 out:
982   elprintf(EL_32X, "m68k 32x r8  [%06x]   %02x @%06x", a, d, SekPc);
983   return d;
984 }
985
986 u32 PicoRead16_32x(u32 a)
987 {
988   u32 d = 0;
989
990   if (PicoIn.opt & POPT_EN_32X) {
991     if ((a & 0xffc0) == 0x5100) { // a15100
992       d = Pico32x.regs[(a & 0x3f) / 2];
993       goto out;
994     }
995
996     if ((a & 0xfffc) == 0x30ec) { // a130ec
997       d = !(a & 2) ? ('M'<<8)|'A' : ('R'<<8)|'S';
998       goto out;
999     }
1000   }
1001
1002   elprintf(EL_UIO, "m68k unmapped r16 [%06x] @%06x", a, SekPc);
1003   return d;
1004
1005 out:
1006   elprintf(EL_32X, "m68k 32x r16 [%06x] %04x @%06x", a, d, SekPc);
1007   return d;
1008 }
1009
1010 void PicoWrite8_32x(u32 a, u32 d)
1011 {
1012   if ((PicoIn.opt & POPT_EN_32X) && (a & 0xffc0) == 0x5100) // a15100
1013   {
1014     u16 *r = Pico32x.regs;
1015
1016     elprintf(EL_32X, "m68k 32x w8  [%06x]   %02x @%06x", a, d & 0xff, SekPc);
1017     a &= 0x3f;
1018     if (a == 1) {
1019       if ((d ^ r[0]) & d & P32XS_ADEN) {
1020         Pico32xStartup();
1021         r[0] &= ~P32XS_nRES; // causes reset if specified by this write
1022         r[0] |= P32XS_ADEN;
1023         p32x_reg_write8(a, d); // forward for reset processing
1024       }
1025       return;
1026     }
1027
1028     // allow only COMM for now
1029     if ((a & 0x30) == 0x20) {
1030       u8 *r8 = (u8 *)r;
1031       r8[a ^ 1] = d;
1032     }
1033     return;
1034   }
1035
1036   elprintf(EL_UIO, "m68k unmapped w8  [%06x]   %02x @%06x", a, d & 0xff, SekPc);
1037 }
1038
1039 void PicoWrite16_32x(u32 a, u32 d)
1040 {
1041   if ((PicoIn.opt & POPT_EN_32X) && (a & 0xffc0) == 0x5100) // a15100
1042   {
1043     u16 *r = Pico32x.regs;
1044
1045     elprintf(EL_UIO, "m68k 32x w16 [%06x] %04x @%06x", a, d & 0xffff, SekPc);
1046     a &= 0x3e;
1047     if (a == 0) {
1048       if ((d ^ r[0]) & d & P32XS_ADEN) {
1049         Pico32xStartup();
1050         r[0] &= ~P32XS_nRES; // causes reset if specified by this write
1051         r[0] |= P32XS_ADEN;
1052         p32x_reg_write16(a, d); // forward for reset processing
1053       }
1054       return;
1055     }
1056
1057     // allow only COMM for now
1058     if ((a & 0x30) == 0x20)
1059       r[a / 2] = d;
1060     return;
1061   }
1062
1063   elprintf(EL_UIO, "m68k unmapped w16 [%06x] %04x @%06x", a, d & 0xffff, SekPc);
1064 }
1065
1066 /* quirk: in both normal and overwrite areas only nonzero values go through */
1067 #define sh2_write8_dramN(n) \
1068   if ((d & 0xff) != 0) { \
1069     u8 *dram = (u8 *)Pico32xMem->dram[n]; \
1070     dram[(a & 0x1ffff) ^ 1] = d; \
1071   }
1072
1073 static void m68k_write8_dram0_ow(u32 a, u32 d)
1074 {
1075   sh2_write8_dramN(0);
1076 }
1077
1078 static void m68k_write8_dram1_ow(u32 a, u32 d)
1079 {
1080   sh2_write8_dramN(1);
1081 }
1082
1083 #define sh2_write16_dramN(n) \
1084   u16 *pd = &Pico32xMem->dram[n][(a & 0x1ffff) / 2]; \
1085   if (!(a & 0x20000)) { \
1086     *pd = d; \
1087     return; \
1088   } \
1089   /* overwrite */ \
1090   if (!(d & 0xff00)) d |= *pd & 0xff00; \
1091   if (!(d & 0x00ff)) d |= *pd & 0x00ff; \
1092   *pd = d;
1093
1094 static void m68k_write16_dram0_ow(u32 a, u32 d)
1095 {
1096   sh2_write16_dramN(0);
1097 }
1098
1099 static void m68k_write16_dram1_ow(u32 a, u32 d)
1100 {
1101   sh2_write16_dramN(1);
1102 }
1103
1104 // -----------------------------------------------------------------
1105
1106 // hint vector is writeable
1107 static void PicoWrite8_hint(u32 a, u32 d)
1108 {
1109   if ((a & 0xfffc) == 0x0070) {
1110     Pico32xMem->m68k_rom[a ^ 1] = d;
1111     return;
1112   }
1113
1114   elprintf(EL_UIO, "m68k unmapped w8  [%06x]   %02x @%06x",
1115     a, d & 0xff, SekPc);
1116 }
1117
1118 static void PicoWrite16_hint(u32 a, u32 d)
1119 {
1120   if ((a & 0xfffc) == 0x0070) {
1121     ((u16 *)Pico32xMem->m68k_rom)[a/2] = d;
1122     return;
1123   }
1124
1125   elprintf(EL_UIO, "m68k unmapped w16 [%06x] %04x @%06x",
1126     a, d & 0xffff, SekPc);
1127 }
1128
1129 // normally not writable, but somebody could make a RAM cart
1130 static void PicoWrite8_cart(u32 a, u32 d)
1131 {
1132   elprintf(EL_UIO, "m68k w8  [%06x]   %02x @%06x", a, d & 0xff, SekPc);
1133
1134   a &= 0xfffff;
1135   m68k_write8(a, d);
1136 }
1137
1138 static void PicoWrite16_cart(u32 a, u32 d)
1139 {
1140   elprintf(EL_UIO, "m68k w16 [%06x] %04x @%06x", a, d & 0xffff, SekPc);
1141
1142   a &= 0xfffff;
1143   m68k_write16(a, d);
1144 }
1145
1146 // same with bank, but save ram is sometimes here
1147 static u32 PicoRead8_bank(u32 a)
1148 {
1149   a = (Pico32x.regs[4 / 2] << 20) | (a & 0xfffff);
1150   return m68k_read8(a);
1151 }
1152
1153 static u32 PicoRead16_bank(u32 a)
1154 {
1155   a = (Pico32x.regs[4 / 2] << 20) | (a & 0xfffff);
1156   return m68k_read16(a);
1157 }
1158
1159 static void PicoWrite8_bank(u32 a, u32 d)
1160 {
1161   if (!(Pico.m.sram_reg & SRR_MAPPED))
1162     elprintf(EL_UIO, "m68k w8  [%06x]   %02x @%06x",
1163       a, d & 0xff, SekPc);
1164
1165   a = (Pico32x.regs[4 / 2] << 20) | (a & 0xfffff);
1166   m68k_write8(a, d);
1167 }
1168
1169 static void PicoWrite16_bank(u32 a, u32 d)
1170 {
1171   if (!(Pico.m.sram_reg & SRR_MAPPED))
1172     elprintf(EL_UIO, "m68k w16 [%06x] %04x @%06x",
1173       a, d & 0xffff, SekPc);
1174
1175   a = (Pico32x.regs[4 / 2] << 20) | (a & 0xfffff);
1176   m68k_write16(a, d);
1177 }
1178
1179 static void bank_map_handler(void)
1180 {
1181   cpu68k_map_set(m68k_read8_map,   0x900000, 0x9fffff, PicoRead8_bank, 1);
1182   cpu68k_map_set(m68k_read16_map,  0x900000, 0x9fffff, PicoRead16_bank, 1);
1183 }
1184
1185 static void bank_switch_rom_68k(int b)
1186 {
1187   unsigned int rs, bank, bank2;
1188
1189   if (Pico.m.ncart_in)
1190     return;
1191
1192   bank = b << 20;
1193   if ((Pico.m.sram_reg & SRR_MAPPED) && bank == Pico.sv.start) {
1194     bank_map_handler();
1195     return;
1196   }
1197
1198   if (bank >= Pico.romsize) {
1199     elprintf(EL_32X|EL_ANOMALY, "missing bank @ %06x", bank);
1200     bank_map_handler();
1201     return;
1202   }
1203
1204   // 32X ROM (XXX: consider mirroring?)
1205   rs = (Pico.romsize + M68K_BANK_MASK) & ~M68K_BANK_MASK;
1206   if (!carthw_ssf2_active) {
1207     rs -= bank;
1208     if (rs > 0x100000)
1209       rs = 0x100000;
1210     cpu68k_map_set(m68k_read8_map,  0x900000, 0x900000 + rs - 1, Pico.rom + bank, 0);
1211     cpu68k_map_set(m68k_read16_map, 0x900000, 0x900000 + rs - 1, Pico.rom + bank, 0);
1212     elprintf(EL_32X, "bank %06x-%06x -> %06x", 0x900000, 0x900000 + rs - 1, bank);
1213   }
1214   else {
1215     bank = bank >> 19;
1216     bank2 = carthw_ssf2_banks[bank + 0] << 19;
1217     cpu68k_map_set(m68k_read8_map,  0x900000, 0x97ffff, Pico.rom + bank2, 0);
1218     cpu68k_map_set(m68k_read16_map, 0x900000, 0x97ffff, Pico.rom + bank2, 0);
1219     bank2 = carthw_ssf2_banks[bank + 1] << 19;
1220     cpu68k_map_set(m68k_read8_map,  0x980000, 0x9fffff, Pico.rom + bank2, 0);
1221     cpu68k_map_set(m68k_read16_map, 0x980000, 0x9fffff, Pico.rom + bank2, 0);
1222   }
1223 }
1224
1225 // -----------------------------------------------------------------
1226 //                              SH2  
1227 // -----------------------------------------------------------------
1228
1229 // read8
1230 static u32 sh2_read8_unmapped(u32 a, SH2 *sh2)
1231 {
1232   elprintf_sh2(sh2, EL_32X, "unmapped r8  [%08x]       %02x @%06x",
1233     a, 0, sh2_pc(sh2));
1234   return 0;
1235 }
1236
1237 static u32 sh2_read8_cs0(u32 a, SH2 *sh2)
1238 {
1239   u32 d = 0;
1240
1241   sh2_burn_cycles(sh2, 1*2);
1242
1243   // 0x3ffc0 is veridied
1244   if ((a & 0x3ffc0) == 0x4000) {
1245     d = p32x_sh2reg_read16(a, sh2);
1246     goto out_16to8;
1247   }
1248
1249   if ((a & 0x3fff0) == 0x4100) {
1250     d = p32x_vdp_read16(a);
1251     sh2_poll_detect(sh2, a, SH2_STATE_VPOLL, 7);
1252     goto out_16to8;
1253   }
1254
1255   // TODO: mirroring?
1256   if (!sh2->is_slave && a < sizeof(Pico32xMem->sh2_rom_m))
1257     return Pico32xMem->sh2_rom_m.b[a ^ 1];
1258   if (sh2->is_slave  && a < sizeof(Pico32xMem->sh2_rom_s))
1259     return Pico32xMem->sh2_rom_s.b[a ^ 1];
1260
1261   if ((a & 0x3fe00) == 0x4200) {
1262     d = Pico32xMem->pal[(a & 0x1ff) / 2];
1263     goto out_16to8;
1264   }
1265
1266   return sh2_read8_unmapped(a, sh2);
1267
1268 out_16to8:
1269   if (a & 1)
1270     d &= 0xff;
1271   else
1272     d >>= 8;
1273
1274   elprintf_sh2(sh2, EL_32X, "r8  [%08x]       %02x @%06x",
1275     a, d, sh2_pc(sh2));
1276   return d;
1277 }
1278
1279 static u32 sh2_read8_da(u32 a, SH2 *sh2)
1280 {
1281   return sh2->data_array[(a & 0xfff) ^ 1];
1282 }
1283
1284 // for ssf2
1285 static u32 sh2_read8_rom(u32 a, SH2 *sh2)
1286 {
1287   u32 bank = carthw_ssf2_banks[(a >> 19) & 7] << 19;
1288   return Pico.rom[(bank + (a & 0x7ffff)) ^ 1];
1289 }
1290
1291 // read16
1292 static u32 sh2_read16_unmapped(u32 a, SH2 *sh2)
1293 {
1294   elprintf_sh2(sh2, EL_32X, "unmapped r16 [%08x]     %04x @%06x",
1295     a, 0, sh2_pc(sh2));
1296   return 0;
1297 }
1298
1299 static u32 sh2_read16_cs0(u32 a, SH2 *sh2)
1300 {
1301   u32 d = 0;
1302
1303   sh2_burn_cycles(sh2, 1*2);
1304
1305   if ((a & 0x3ffc0) == 0x4000) {
1306     d = p32x_sh2reg_read16(a, sh2);
1307     if (!(EL_LOGMASK & EL_PWM) && (a & 0x30) == 0x30) // hide PWM
1308       return d;
1309     goto out;
1310   }
1311
1312   if ((a & 0x3fff0) == 0x4100) {
1313     d = p32x_vdp_read16(a);
1314     sh2_poll_detect(sh2, a, SH2_STATE_VPOLL, 7);
1315     goto out;
1316   }
1317
1318   if (!sh2->is_slave && a < sizeof(Pico32xMem->sh2_rom_m))
1319     return Pico32xMem->sh2_rom_m.w[a / 2];
1320   if (sh2->is_slave  && a < sizeof(Pico32xMem->sh2_rom_s))
1321     return Pico32xMem->sh2_rom_s.w[a / 2];
1322
1323   if ((a & 0x3fe00) == 0x4200) {
1324     d = Pico32xMem->pal[(a & 0x1ff) / 2];
1325     goto out;
1326   }
1327
1328   return sh2_read16_unmapped(a, sh2);
1329
1330 out:
1331   elprintf_sh2(sh2, EL_32X, "r16 [%08x]     %04x @%06x",
1332     a, d, sh2_pc(sh2));
1333   return d;
1334 }
1335
1336 static u32 sh2_read16_da(u32 a, SH2 *sh2)
1337 {
1338   return ((u16 *)sh2->data_array)[(a & 0xfff) / 2];
1339 }
1340
1341 static u32 sh2_read16_rom(u32 a, SH2 *sh2)
1342 {
1343   u32 bank = carthw_ssf2_banks[(a >> 19) & 7] << 19;
1344   return *(u16 *)(Pico.rom + bank + (a & 0x7fffe));
1345 }
1346
1347 // writes
1348 static void REGPARM(3) sh2_write_ignore(u32 a, u32 d, SH2 *sh2)
1349 {
1350 }
1351
1352 // write8
1353 static void REGPARM(3) sh2_write8_unmapped(u32 a, u32 d, SH2 *sh2)
1354 {
1355   elprintf_sh2(sh2, EL_32X, "unmapped w8  [%08x]       %02x @%06x",
1356     a, d & 0xff, sh2_pc(sh2));
1357 }
1358
1359 static void REGPARM(3) sh2_write8_cs0(u32 a, u32 d, SH2 *sh2)
1360 {
1361   elprintf_sh2(sh2, EL_32X, "w8  [%08x]       %02x @%06x",
1362     a, d & 0xff, sh2_pc(sh2));
1363
1364   if (Pico32x.regs[0] & P32XS_FM) {
1365     if ((a & 0x3fff0) == 0x4100) {
1366       sh2->poll_addr = 0;
1367       p32x_vdp_write8(a, d);
1368       return;
1369     }
1370   }
1371
1372   if ((a & 0x3ffc0) == 0x4000) {
1373     p32x_sh2reg_write8(a, d, sh2);
1374     return;
1375   }
1376
1377   sh2_write8_unmapped(a, d, sh2);
1378 }
1379
1380 static void REGPARM(3) sh2_write8_dram0(u32 a, u32 d, SH2 *sh2)
1381 {
1382   sh2_write8_dramN(0);
1383 }
1384
1385 static void REGPARM(3) sh2_write8_dram1(u32 a, u32 d, SH2 *sh2)
1386 {
1387   sh2_write8_dramN(1);
1388 }
1389
1390 static void REGPARM(3) sh2_write8_sdram(u32 a, u32 d, SH2 *sh2)
1391 {
1392   u32 a1 = a & 0x3ffff;
1393 #ifdef DRC_SH2
1394   int t = Pico32xMem->drcblk_ram[a1 >> SH2_DRCBLK_RAM_SHIFT];
1395   if (t)
1396     sh2_drc_wcheck_ram(a, t, sh2->is_slave);
1397 #endif
1398   Pico32xMem->sdram[a1 ^ 1] = d;
1399 }
1400
1401 static void REGPARM(3) sh2_write8_sdram_wt(u32 a, u32 d, SH2 *sh2)
1402 {
1403   // xmen sync hack..
1404   if (a < 0x26000200)
1405     sh2_end_run(sh2, 32);
1406
1407   sh2_write8_sdram(a, d, sh2);
1408 }
1409
1410 static void REGPARM(3) sh2_write8_da(u32 a, u32 d, SH2 *sh2)
1411 {
1412   u32 a1 = a & 0xfff;
1413 #ifdef DRC_SH2
1414   int id = sh2->is_slave;
1415   int t = Pico32xMem->drcblk_da[id][a1 >> SH2_DRCBLK_DA_SHIFT];
1416   if (t)
1417     sh2_drc_wcheck_da(a, t, id);
1418 #endif
1419   sh2->data_array[a1 ^ 1] = d;
1420 }
1421
1422 // write16
1423 static void REGPARM(3) sh2_write16_unmapped(u32 a, u32 d, SH2 *sh2)
1424 {
1425   elprintf_sh2(sh2, EL_32X, "unmapped w16 [%08x]     %04x @%06x",
1426     a, d & 0xffff, sh2_pc(sh2));
1427 }
1428
1429 static void REGPARM(3) sh2_write16_cs0(u32 a, u32 d, SH2 *sh2)
1430 {
1431   if (((EL_LOGMASK & EL_PWM) || (a & 0x30) != 0x30)) // hide PWM
1432     elprintf_sh2(sh2, EL_32X, "w16 [%08x]     %04x @%06x",
1433       a, d & 0xffff, sh2_pc(sh2));
1434
1435   if (Pico32x.regs[0] & P32XS_FM) {
1436     if ((a & 0x3fff0) == 0x4100) {
1437       sh2->poll_addr = 0;
1438       p32x_vdp_write16(a, d, sh2);
1439       return;
1440     }
1441
1442     if ((a & 0x3fe00) == 0x4200) {
1443       Pico32xMem->pal[(a & 0x1ff) / 2] = d;
1444       Pico32x.dirty_pal = 1;
1445       return;
1446     }
1447   }
1448
1449   if ((a & 0x3ffc0) == 0x4000) {
1450     p32x_sh2reg_write16(a, d, sh2);
1451     return;
1452   }
1453
1454   sh2_write16_unmapped(a, d, sh2);
1455 }
1456
1457 static void REGPARM(3) sh2_write16_dram0(u32 a, u32 d, SH2 *sh2)
1458 {
1459   sh2_write16_dramN(0);
1460 }
1461
1462 static void REGPARM(3) sh2_write16_dram1(u32 a, u32 d, SH2 *sh2)
1463 {
1464   sh2_write16_dramN(1);
1465 }
1466
1467 static void REGPARM(3) sh2_write16_sdram(u32 a, u32 d, SH2 *sh2)
1468 {
1469   u32 a1 = a & 0x3ffff;
1470 #ifdef DRC_SH2
1471   int t = Pico32xMem->drcblk_ram[a1 >> SH2_DRCBLK_RAM_SHIFT];
1472   if (t)
1473     sh2_drc_wcheck_ram(a, t, sh2->is_slave);
1474 #endif
1475   ((u16 *)Pico32xMem->sdram)[a1 / 2] = d;
1476 }
1477
1478 static void REGPARM(3) sh2_write16_da(u32 a, u32 d, SH2 *sh2)
1479 {
1480   u32 a1 = a & 0xfff;
1481 #ifdef DRC_SH2
1482   int id = sh2->is_slave;
1483   int t = Pico32xMem->drcblk_da[id][a1 >> SH2_DRCBLK_DA_SHIFT];
1484   if (t)
1485     sh2_drc_wcheck_da(a, t, id);
1486 #endif
1487   ((u16 *)sh2->data_array)[a1 / 2] = d;
1488 }
1489
1490
1491 typedef u32 (sh2_read_handler)(u32 a, SH2 *sh2);
1492 typedef void REGPARM(3) (sh2_write_handler)(u32 a, u32 d, SH2 *sh2);
1493
1494 #define SH2MAP_ADDR2OFFS_R(a) \
1495   ((u32)(a) >> SH2_READ_SHIFT)
1496
1497 #define SH2MAP_ADDR2OFFS_W(a) \
1498   ((u32)(a) >> SH2_WRITE_SHIFT)
1499
1500 u32 REGPARM(2) p32x_sh2_read8(u32 a, SH2 *sh2)
1501 {
1502   const sh2_memmap *sh2_map = sh2->read8_map;
1503   uptr p;
1504
1505   sh2_map += SH2MAP_ADDR2OFFS_R(a);
1506   p = sh2_map->addr;
1507   if (map_flag_set(p))
1508     return ((sh2_read_handler *)(p << 1))(a, sh2);
1509   else
1510     return *(u8 *)((p << 1) + ((a & sh2_map->mask) ^ 1));
1511 }
1512
1513 u32 REGPARM(2) p32x_sh2_read16(u32 a, SH2 *sh2)
1514 {
1515   const sh2_memmap *sh2_map = sh2->read16_map;
1516   uptr p;
1517
1518   sh2_map += SH2MAP_ADDR2OFFS_R(a);
1519   p = sh2_map->addr;
1520   if (map_flag_set(p))
1521     return ((sh2_read_handler *)(p << 1))(a, sh2);
1522   else
1523     return *(u16 *)((p << 1) + ((a & sh2_map->mask) & ~1));
1524 }
1525
1526 u32 REGPARM(2) p32x_sh2_read32(u32 a, SH2 *sh2)
1527 {
1528   const sh2_memmap *sh2_map = sh2->read16_map;
1529   sh2_read_handler *handler;
1530   u32 offs;
1531   uptr p;
1532
1533   offs = SH2MAP_ADDR2OFFS_R(a);
1534   sh2_map += offs;
1535   p = sh2_map->addr;
1536   if (!map_flag_set(p)) {
1537     // XXX: maybe 32bit access instead with ror?
1538     u16 *pd = (u16 *)((p << 1) + ((a & sh2_map->mask) & ~1));
1539     return (pd[0] << 16) | pd[1];
1540   }
1541
1542   if (offs == SH2MAP_ADDR2OFFS_R(0xffffc000))
1543     return sh2_peripheral_read32(a, sh2);
1544
1545   handler = (sh2_read_handler *)(p << 1);
1546   return (handler(a, sh2) << 16) | handler(a + 2, sh2);
1547 }
1548
1549 void REGPARM(3) p32x_sh2_write8(u32 a, u32 d, SH2 *sh2)
1550 {
1551   const void **sh2_wmap = sh2->write8_tab;
1552   sh2_write_handler *wh;
1553
1554   wh = sh2_wmap[SH2MAP_ADDR2OFFS_W(a)];
1555   wh(a, d, sh2);
1556 }
1557
1558 void REGPARM(3) p32x_sh2_write16(u32 a, u32 d, SH2 *sh2)
1559 {
1560   const void **sh2_wmap = sh2->write16_tab;
1561   sh2_write_handler *wh;
1562
1563   wh = sh2_wmap[SH2MAP_ADDR2OFFS_W(a)];
1564   wh(a, d, sh2);
1565 }
1566
1567 void REGPARM(3) p32x_sh2_write32(u32 a, u32 d, SH2 *sh2)
1568 {
1569   const void **sh2_wmap = sh2->write16_tab;
1570   sh2_write_handler *wh;
1571   u32 offs;
1572
1573   offs = SH2MAP_ADDR2OFFS_W(a);
1574
1575   if (offs == SH2MAP_ADDR2OFFS_W(0xffffc000)) {
1576     sh2_peripheral_write32(a, d, sh2);
1577     return;
1578   }
1579
1580   wh = sh2_wmap[offs];
1581   wh(a, d >> 16, sh2);
1582   wh(a + 2, d, sh2);
1583 }
1584
1585 // -----------------------------------------------------------------
1586
1587 static void z80_md_bank_write_32x(unsigned int a, unsigned char d)
1588 {
1589   unsigned int addr68k;
1590
1591   addr68k = Pico.m.z80_bank68k << 15;
1592   addr68k += a & 0x7fff;
1593   if ((addr68k & 0xfff000) == 0xa15000)
1594     Pico32x.emu_flags |= P32XF_Z80_32X_IO;
1595
1596   elprintf(EL_Z80BNK, "z80->68k w8 [%06x] %02x", addr68k, d);
1597   m68k_write8(addr68k, d);
1598 }
1599
1600 // -----------------------------------------------------------------
1601
1602 static const u16 msh2_code[] = {
1603   // trap instructions
1604   0xaffe, // 200 bra <self>
1605   0x0009, // 202 nop
1606   // have to wait a bit until m68k initial program finishes clearing stuff
1607   // to avoid races with game SH2 code, like in Tempo
1608   0xd406, // 204 mov.l   @(_m_ok,pc), r4
1609   0xc400, // 206 mov.b   @(h'0,gbr),r0
1610   0xc801, // 208 tst     #1, r0
1611   0x8b0f, // 20a bf      cd_start
1612   0xd105, // 20c mov.l   @(_cnt,pc), r1
1613   0xd206, // 20e mov.l   @(_start,pc), r2
1614   0x71ff, // 210 add     #-1, r1
1615   0x4115, // 212 cmp/pl  r1
1616   0x89fc, // 214 bt      -2
1617   0x6043, // 216 mov     r4, r0
1618   0xc208, // 218 mov.l   r0, @(h'20,gbr)
1619   0x6822, // 21a mov.l   @r2, r8
1620   0x482b, // 21c jmp     @r8
1621   0x0009, // 21e nop
1622   ('M'<<8)|'_', ('O'<<8)|'K', // 220 _m_ok
1623   0x0001, 0x0000,             // 224 _cnt
1624   0x2200, 0x03e0, // master start pointer in ROM
1625   // cd_start:
1626   0xd20d, // 22c mov.l   @(__cd_,pc), r2
1627   0xc608, // 22e mov.l   @(h'20,gbr), r0
1628   0x3200, // 230 cmp/eq  r0, r2
1629   0x8bfc, // 232 bf      #-2
1630   0xe000, // 234 mov     #0, r0
1631   0xcf80, // 236 or.b    #0x80,@(r0,gbr)
1632   0xd80b, // 238 mov.l   @(_start_cd,pc), r8 // 24000018
1633   0xd30c, // 23a mov.l   @(_max_len,pc), r3
1634   0x5b84, // 23c mov.l   @(h'10,r8), r11     // master vbr
1635   0x5a82, // 23e mov.l   @(8,r8), r10        // entry
1636   0x5081, // 240 mov.l   @(4,r8), r0         // len
1637   0x5980, // 242 mov.l   @(0,r8), r9         // dst
1638   0x3036, // 244 cmp/hi  r3,r0
1639   0x8b00, // 246 bf      #1
1640   0x6033, // 248 mov     r3,r0
1641   0x7820, // 24a add     #0x20, r8
1642   // ipl_copy:
1643   0x6286, // 24c mov.l   @r8+, r2
1644   0x2922, // 24e mov.l   r2, @r9
1645   0x7904, // 250 add     #4, r9
1646   0x70fc, // 252 add     #-4, r0
1647   0x8800, // 254 cmp/eq  #0, r0
1648   0x8bf9, // 256 bf      #-5
1649   //
1650   0x4b2e, // 258 ldc     r11, vbr
1651   0x6043, // 25a mov     r4, r0              // M_OK
1652   0xc208, // 25c mov.l   r0, @(h'20,gbr)
1653   0x4a2b, // 25e jmp     @r10
1654   0x0009, // 260 nop
1655   0x0009, // 262 nop          //     pad
1656   ('_'<<8)|'C', ('D'<<8)|'_', // 264 __cd_
1657   0x2400, 0x0018,             // 268 _start_cd
1658   0x0001, 0xffe0,             // 26c _max_len
1659 };
1660
1661 static const u16 ssh2_code[] = {
1662   0xaffe, // 200 bra <self>
1663   0x0009, // 202 nop
1664   // code to wait for master, in case authentic master BIOS is used
1665   0xd106, // 204 mov.l   @(_m_ok,pc), r1
1666   0xd208, // 206 mov.l   @(_start,pc), r2
1667   0xc608, // 208 mov.l   @(h'20,gbr), r0
1668   0x3100, // 20a cmp/eq  r0, r1
1669   0x8bfc, // 20c bf      #-2
1670   0xc400, // 20e mov.b   @(h'0,gbr),r0
1671   0xc801, // 210 tst     #1, r0
1672   0xd004, // 212 mov.l   @(_s_ok,pc), r0
1673   0x8b0a, // 214 bf      cd_start
1674   0xc209, // 216 mov.l   r0, @(h'24,gbr)
1675   0x6822, // 218 mov.l   @r2, r8
1676   0x482b, // 21a jmp     @r8
1677   0x0009, // 21c nop
1678   0x0009, // 21e nop
1679   ('M'<<8)|'_', ('O'<<8)|'K', // 220
1680   ('S'<<8)|'_', ('O'<<8)|'K', // 224
1681   0x2200, 0x03e4,  // slave start pointer in ROM
1682   // cd_start:
1683   0xd803, // 22c mov.l   @(_start_cd,pc), r8 // 24000018
1684   0x5b85, // 22e mov.l   @(h'14,r8), r11     // slave vbr
1685   0x5a83, // 230 mov.l   @(h'0c,r8), r10     // entry
1686   0x4b2e, // 232 ldc     r11, vbr
1687   0xc209, // 234 mov.l   r0, @(h'24,gbr)     // write S_OK
1688   0x4a2b, // 236 jmp     @r10
1689   0x0009, // 238 nop
1690   0x0009, // 23a nop
1691   0x2400, 0x0018, // 23c _start_cd
1692 };
1693
1694 #define HWSWAP(x) (((u16)(x) << 16) | ((x) >> 16))
1695 static void get_bios(void)
1696 {
1697   u16 *ps;
1698   u32 *pl;
1699   int i;
1700
1701   // M68K ROM
1702   if (p32x_bios_g != NULL) {
1703     elprintf(EL_STATUS|EL_32X, "32x: using supplied 68k BIOS");
1704     Byteswap(Pico32xMem->m68k_rom, p32x_bios_g, sizeof(Pico32xMem->m68k_rom));
1705   }
1706   else {
1707     static const u16 andb[] = { 0x0239, 0x00fe, 0x00a1, 0x5107 };
1708     static const u16 p_d4[] = {
1709       0x48e7, 0x8040,         //   movem.l d0/a1, -(sp)
1710       0x227c, 0x00a1, 0x30f1, //   movea.l #0xa130f1, a1
1711       0x7007,                 //   moveq.l #7, d0
1712       0x12d8,                 //0: move.b (a0)+, (a1)+
1713       0x5289,                 //   addq.l  #1, a1
1714       0x51c8, 0xfffa,         //   dbra   d0, 0b
1715       0x0239, 0x00fe, 0x00a1, //   and.b  #0xfe, (0xa15107).l
1716                       0x5107,
1717       0x4cdf, 0x0201          //   movem.l (sp)+, d0/a1
1718     };
1719
1720     // generate 68k ROM
1721     ps = (u16 *)Pico32xMem->m68k_rom;
1722     pl = (u32 *)ps;
1723     for (i = 1; i < 0xc0/4; i++)
1724       pl[i] = HWSWAP(0x880200 + (i - 1) * 6);
1725     pl[0x70/4] = 0;
1726
1727     // fill with nops
1728     for (i = 0xc0/2; i < 0x100/2; i++)
1729       ps[i] = 0x4e71;
1730
1731     // c0: don't need to care about RV - not emulated
1732     ps[0xc8/2] = 0x1280;                     // move.b d0, (a1)
1733     memcpy(ps + 0xca/2, andb, sizeof(andb)); // and.b #0xfe, (a15107)
1734     ps[0xd2/2] = 0x4e75;                     // rts
1735     // d4:
1736     memcpy(ps + 0xd4/2, p_d4, sizeof(p_d4));
1737     ps[0xfe/2] = 0x4e75; // rts
1738   }
1739   // fill remaining m68k_rom page with game ROM
1740   memcpy(Pico32xMem->m68k_rom_bank + sizeof(Pico32xMem->m68k_rom),
1741     Pico.rom + sizeof(Pico32xMem->m68k_rom),
1742     sizeof(Pico32xMem->m68k_rom_bank) - sizeof(Pico32xMem->m68k_rom));
1743
1744   // MSH2
1745   if (p32x_bios_m != NULL) {
1746     elprintf(EL_STATUS|EL_32X, "32x: using supplied master SH2 BIOS");
1747     Byteswap(&Pico32xMem->sh2_rom_m, p32x_bios_m, sizeof(Pico32xMem->sh2_rom_m));
1748   }
1749   else {
1750     pl = (u32 *)&Pico32xMem->sh2_rom_m;
1751
1752     // fill exception vector table to our trap address
1753     for (i = 0; i < 128; i++)
1754       pl[i] = HWSWAP(0x200);
1755
1756     // start
1757     pl[0] = pl[2] = HWSWAP(0x204);
1758     // reset SP
1759     pl[1] = pl[3] = HWSWAP(0x6040000);
1760
1761     // startup code
1762     memcpy(&Pico32xMem->sh2_rom_m.b[0x200], msh2_code, sizeof(msh2_code));
1763   }
1764
1765   // SSH2
1766   if (p32x_bios_s != NULL) {
1767     elprintf(EL_STATUS|EL_32X, "32x: using supplied slave SH2 BIOS");
1768     Byteswap(&Pico32xMem->sh2_rom_s, p32x_bios_s, sizeof(Pico32xMem->sh2_rom_s));
1769   }
1770   else {
1771     pl = (u32 *)&Pico32xMem->sh2_rom_s;
1772
1773     // fill exception vector table to our trap address
1774     for (i = 0; i < 128; i++)
1775       pl[i] = HWSWAP(0x200);
1776
1777     // start
1778     pl[0] = pl[2] = HWSWAP(0x204);
1779     // reset SP
1780     pl[1] = pl[3] = HWSWAP(0x603f800);
1781
1782     // startup code
1783     memcpy(&Pico32xMem->sh2_rom_s.b[0x200], ssh2_code, sizeof(ssh2_code));
1784   }
1785 }
1786
1787 #define MAP_MEMORY(m) ((uptr)(m) >> 1)
1788 #define MAP_HANDLER(h) ( ((uptr)(h) >> 1) | ((uptr)1 << (sizeof(uptr) * 8 - 1)) )
1789
1790 static sh2_memmap sh2_read8_map[0x80], sh2_read16_map[0x80];
1791 // for writes we are using handlers only
1792 static sh2_write_handler *sh2_write8_map[0x80], *sh2_write16_map[0x80];
1793
1794 void Pico32xSwapDRAM(int b)
1795 {
1796   cpu68k_map_set(m68k_read8_map,   0x840000, 0x85ffff, Pico32xMem->dram[b], 0);
1797   cpu68k_map_set(m68k_read16_map,  0x840000, 0x85ffff, Pico32xMem->dram[b], 0);
1798   cpu68k_map_set(m68k_read8_map,   0x860000, 0x87ffff, Pico32xMem->dram[b], 0);
1799   cpu68k_map_set(m68k_read16_map,  0x860000, 0x87ffff, Pico32xMem->dram[b], 0);
1800   cpu68k_map_set(m68k_write8_map,  0x840000, 0x87ffff,
1801                  b ? m68k_write8_dram1_ow : m68k_write8_dram0_ow, 1);
1802   cpu68k_map_set(m68k_write16_map, 0x840000, 0x87ffff,
1803                  b ? m68k_write16_dram1_ow : m68k_write16_dram0_ow, 1);
1804
1805   // SH2
1806   sh2_read8_map[0x04/2].addr  = sh2_read8_map[0x24/2].addr  =
1807   sh2_read16_map[0x04/2].addr = sh2_read16_map[0x24/2].addr = MAP_MEMORY(Pico32xMem->dram[b]);
1808
1809   sh2_write8_map[0x04/2]  = sh2_write8_map[0x24/2]  = b ? sh2_write8_dram1 : sh2_write8_dram0;
1810   sh2_write16_map[0x04/2] = sh2_write16_map[0x24/2] = b ? sh2_write16_dram1 : sh2_write16_dram0;
1811 }
1812
1813 static void bank_switch_rom_sh2(void)
1814 {
1815   if (!carthw_ssf2_active) {
1816     // easy
1817     sh2_read8_map[0x02/2].addr  = sh2_read8_map[0x22/2].addr  =
1818     sh2_read16_map[0x02/2].addr = sh2_read16_map[0x22/2].addr = MAP_MEMORY(Pico.rom);
1819   }
1820   else {
1821     sh2_read8_map[0x02/2].addr  = sh2_read8_map[0x22/2].addr  = MAP_HANDLER(sh2_read8_rom);
1822     sh2_read16_map[0x02/2].addr = sh2_read16_map[0x22/2].addr = MAP_HANDLER(sh2_read16_rom);
1823   }
1824 }
1825
1826 void PicoMemSetup32x(void)
1827 {
1828   unsigned int rs;
1829   int i;
1830
1831   Pico32xMem = plat_mmap(0x06000000, sizeof(*Pico32xMem), 0, 0);
1832   if (Pico32xMem == NULL) {
1833     elprintf(EL_STATUS, "OOM");
1834     return;
1835   }
1836
1837   get_bios();
1838
1839   // cartridge area becomes unmapped
1840   // XXX: we take the easy way and don't unmap ROM,
1841   // so that we can avoid handling the RV bit.
1842   // m68k_map_unmap(0x000000, 0x3fffff);
1843
1844   if (!Pico.m.ncart_in) {
1845     // MD ROM area
1846     rs = sizeof(Pico32xMem->m68k_rom_bank);
1847     cpu68k_map_set(m68k_read8_map,   0x000000, rs - 1, Pico32xMem->m68k_rom_bank, 0);
1848     cpu68k_map_set(m68k_read16_map,  0x000000, rs - 1, Pico32xMem->m68k_rom_bank, 0);
1849     cpu68k_map_set(m68k_write8_map,  0x000000, rs - 1, PicoWrite8_hint, 1); // TODO verify
1850     cpu68k_map_set(m68k_write16_map, 0x000000, rs - 1, PicoWrite16_hint, 1);
1851
1852     // 32X ROM (unbanked, XXX: consider mirroring?)
1853     rs = (Pico.romsize + M68K_BANK_MASK) & ~M68K_BANK_MASK;
1854     if (rs > 0x80000)
1855       rs = 0x80000;
1856     cpu68k_map_set(m68k_read8_map,   0x880000, 0x880000 + rs - 1, Pico.rom, 0);
1857     cpu68k_map_set(m68k_read16_map,  0x880000, 0x880000 + rs - 1, Pico.rom, 0);
1858     cpu68k_map_set(m68k_write8_map,  0x880000, 0x880000 + rs - 1, PicoWrite8_cart, 1);
1859     cpu68k_map_set(m68k_write16_map, 0x880000, 0x880000 + rs - 1, PicoWrite16_cart, 1);
1860
1861     // 32X ROM (banked)
1862     bank_switch_rom_68k(0);
1863     cpu68k_map_set(m68k_write8_map,  0x900000, 0x9fffff, PicoWrite8_bank, 1);
1864     cpu68k_map_set(m68k_write16_map, 0x900000, 0x9fffff, PicoWrite16_bank, 1);
1865   }
1866
1867   // SYS regs
1868   cpu68k_map_set(m68k_read8_map,   0xa10000, 0xa1ffff, PicoRead8_32x_on, 1);
1869   cpu68k_map_set(m68k_read16_map,  0xa10000, 0xa1ffff, PicoRead16_32x_on, 1);
1870   cpu68k_map_set(m68k_write8_map,  0xa10000, 0xa1ffff, PicoWrite8_32x_on, 1);
1871   cpu68k_map_set(m68k_write16_map, 0xa10000, 0xa1ffff, PicoWrite16_32x_on, 1);
1872
1873   // TODO: cd + carthw
1874   if (PicoIn.AHW & PAHW_MCD) {
1875     m68k_write8_io  = PicoWrite8_32x_on_io_cd;
1876     m68k_write16_io = PicoWrite16_32x_on_io_cd;
1877   }
1878   else if (carthw_ssf2_active) {
1879     m68k_write8_io  = PicoWrite8_32x_on_io_ssf2;
1880     m68k_write16_io = PicoWrite16_32x_on_io_ssf2;
1881   }
1882   else {
1883     m68k_write8_io  = PicoWrite8_32x_on_io;
1884     m68k_write16_io = PicoWrite16_32x_on_io;
1885   }
1886
1887   // SH2 maps: A31,A30,A29,CS1,CS0
1888   // all unmapped by default
1889   for (i = 0; i < ARRAY_SIZE(sh2_read8_map); i++) {
1890     sh2_read8_map[i].addr   = MAP_HANDLER(sh2_read8_unmapped);
1891     sh2_read16_map[i].addr  = MAP_HANDLER(sh2_read16_unmapped);
1892   }
1893
1894   for (i = 0; i < ARRAY_SIZE(sh2_write8_map); i++) {
1895     sh2_write8_map[i]       = sh2_write8_unmapped;
1896     sh2_write16_map[i]      = sh2_write16_unmapped;
1897   }
1898
1899   // "purge area"
1900   for (i = 0x40; i <= 0x5f; i++) {
1901     sh2_write8_map[i >> 1]  =
1902     sh2_write16_map[i >> 1] = sh2_write_ignore;
1903   }
1904
1905   // CS0
1906   sh2_read8_map[0x00/2].addr  = sh2_read8_map[0x20/2].addr  = MAP_HANDLER(sh2_read8_cs0);
1907   sh2_read16_map[0x00/2].addr = sh2_read16_map[0x20/2].addr = MAP_HANDLER(sh2_read16_cs0);
1908   sh2_write8_map[0x00/2]  = sh2_write8_map[0x20/2]  = sh2_write8_cs0;
1909   sh2_write16_map[0x00/2] = sh2_write16_map[0x20/2] = sh2_write16_cs0;
1910   // CS1 - ROM
1911   bank_switch_rom_sh2();
1912   sh2_read8_map[0x02/2].mask  = sh2_read8_map[0x22/2].mask  =
1913   sh2_read16_map[0x02/2].mask = sh2_read16_map[0x22/2].mask = 0x3fffff; // FIXME
1914   // CS2 - DRAM - done by Pico32xSwapDRAM()
1915   sh2_read8_map[0x04/2].mask  = sh2_read8_map[0x24/2].mask  =
1916   sh2_read16_map[0x04/2].mask = sh2_read16_map[0x24/2].mask = 0x01ffff;
1917   // CS3 - SDRAM
1918   sh2_read8_map[0x06/2].addr   = sh2_read8_map[0x26/2].addr   =
1919   sh2_read16_map[0x06/2].addr  = sh2_read16_map[0x26/2].addr  = MAP_MEMORY(Pico32xMem->sdram);
1920   sh2_write8_map[0x06/2]       = sh2_write8_sdram;
1921   sh2_write8_map[0x26/2]       = sh2_write8_sdram_wt;
1922   sh2_write16_map[0x06/2]      = sh2_write16_map[0x26/2]      = sh2_write16_sdram;
1923   sh2_read8_map[0x06/2].mask   = sh2_read8_map[0x26/2].mask   =
1924   sh2_read16_map[0x06/2].mask  = sh2_read16_map[0x26/2].mask  = 0x03ffff;
1925   // SH2 data array
1926   sh2_read8_map[0xc0/2].addr  = MAP_HANDLER(sh2_read8_da);
1927   sh2_read16_map[0xc0/2].addr = MAP_HANDLER(sh2_read16_da);
1928   sh2_write8_map[0xc0/2]      = sh2_write8_da;
1929   sh2_write16_map[0xc0/2]     = sh2_write16_da;
1930   // SH2 IO
1931   sh2_read8_map[0xff/2].addr  = MAP_HANDLER(sh2_peripheral_read8);
1932   sh2_read16_map[0xff/2].addr = MAP_HANDLER(sh2_peripheral_read16);
1933   sh2_write8_map[0xff/2]      = sh2_peripheral_write8;
1934   sh2_write16_map[0xff/2]     = sh2_peripheral_write16;
1935
1936   // map DRAM area, both 68k and SH2
1937   Pico32xSwapDRAM(1);
1938
1939   msh2.read8_map   = ssh2.read8_map   = sh2_read8_map;
1940   msh2.read16_map  = ssh2.read16_map  = sh2_read16_map;
1941   msh2.write8_tab  = ssh2.write8_tab  = (const void **)(void *)sh2_write8_map;
1942   msh2.write16_tab = ssh2.write16_tab = (const void **)(void *)sh2_write16_map;
1943
1944   sh2_drc_mem_setup(&msh2);
1945   sh2_drc_mem_setup(&ssh2);
1946
1947   // z80 hack
1948   z80_map_set(z80_write_map, 0x8000, 0xffff, z80_md_bank_write_32x, 1);
1949 }
1950
1951 void p32x_update_banks(void)
1952 {
1953   bank_switch_rom_68k(Pico32x.regs[4 / 2]);
1954   bank_switch_rom_sh2();
1955   if (Pico32x.emu_flags & P32XF_DRC_ROM_C)
1956     sh2_drc_flush_all();
1957 }
1958
1959 void Pico32xMemStateLoaded(void)
1960 {
1961   bank_switch_rom_68k(Pico32x.regs[4 / 2]);
1962   Pico32xSwapDRAM((Pico32x.vdp_regs[0x0a / 2] & P32XV_FS) ^ P32XV_FS);
1963   memset(Pico32xMem->pwm, 0, sizeof(Pico32xMem->pwm));
1964   Pico32x.dirty_pal = 1;
1965
1966   Pico32x.emu_flags &= ~(P32XF_68KCPOLL | P32XF_68KVPOLL);
1967   memset(&m68k_poll, 0, sizeof(m68k_poll));
1968   msh2.state = 0;
1969   msh2.poll_addr = msh2.poll_cycles = msh2.poll_cnt = 0;
1970   ssh2.state = 0;
1971   ssh2.poll_addr = ssh2.poll_cycles = ssh2.poll_cnt = 0;
1972
1973   sh2_drc_flush_all();
1974 }
1975
1976 // vim:shiftwidth=2:ts=2:expandtab