32x: move sh2 peripheral emu code to it's own file
[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 ?                  (16bit VRES clr)  4014
18  * a15116 ?                  (16bit Vint clr)  4016
19  * a15118 ?                  (16bit Hint clr)  4018
20  * a1511a ........ .......C  (16bit CMD clr)   401a // Cm
21  * a1511c ?                  (16bit PWM clr)   401c
22  * a1511e ?                  ?                 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  * rom      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(int b);
51
52 // poll detection
53 #define POLL_THRESHOLD 3
54
55 static struct {
56   u32 addr, cycles;
57   int cnt;
58 } m68k_poll;
59
60 static int m68k_poll_detect(u32 a, u32 cycles, u32 flags)
61 {
62   int ret = 0;
63
64   if (a - 2 <= m68k_poll.addr && m68k_poll.addr <= a + 2
65     && cycles - m68k_poll.cycles <= 64)
66   {
67     if (m68k_poll.cnt++ > POLL_THRESHOLD) {
68       if (!(Pico32x.emu_flags & flags)) {
69         elprintf(EL_32X, "m68k poll addr %08x, cyc %u",
70           a, cycles - m68k_poll.cycles);
71         ret = 1;
72       }
73       Pico32x.emu_flags |= flags;
74     }
75   }
76   else {
77     m68k_poll.cnt = 0;
78     m68k_poll.addr = a;
79   }
80   m68k_poll.cycles = cycles;
81
82   return ret;
83 }
84
85 void p32x_m68k_poll_event(u32 flags)
86 {
87   if (Pico32x.emu_flags & flags) {
88     elprintf(EL_32X, "m68k poll %02x -> %02x", Pico32x.emu_flags,
89       Pico32x.emu_flags & ~flags);
90     Pico32x.emu_flags &= ~flags;
91     SekSetStop(0);
92   }
93   m68k_poll.addr = m68k_poll.cnt = 0;
94 }
95
96 static void sh2_poll_detect(SH2 *sh2, u32 a, u32 flags)
97 {
98   int cycles_left = sh2_cycles_left(sh2);
99
100   if (a == sh2->poll_addr && sh2->poll_cycles - cycles_left <= 10) {
101     if (sh2->poll_cnt++ > 3) {
102       if (!(sh2->state & flags))
103         elprintf(EL_32X, "%csh2 state: %02x->%02x", sh2->is_slave?'s':'m',
104           sh2->state, sh2->state | flags);
105
106       sh2->state |= flags;
107       sh2_end_run(sh2, 1);
108       pevt_log_sh2(sh2, EVT_POLL_START);
109       return;
110     }
111   }
112   else
113     sh2->poll_cnt = 0;
114   sh2->poll_addr = a;
115   sh2->poll_cycles = cycles_left;
116 }
117
118 void p32x_sh2_poll_event(SH2 *sh2, u32 flags, u32 m68k_cycles)
119 {
120   if (sh2->state & flags) {
121     elprintf(EL_32X, "%csh2 state: %02x->%02x", sh2->is_slave?'s':'m',
122       sh2->state, sh2->state & ~flags);
123
124     if (sh2->m68krcycles_done < m68k_cycles)
125       sh2->m68krcycles_done = m68k_cycles;
126
127     pevt_log_sh2_o(sh2, EVT_POLL_END);
128   }
129
130   sh2->state &= ~flags;
131   sh2->poll_addr = sh2->poll_cycles = sh2->poll_cnt = 0;
132 }
133
134 static void sh2s_sync_on_read(SH2 *sh2)
135 {
136   int cycles;
137   if (sh2->poll_cnt != 0)
138     return;
139
140   cycles = sh2_cycles_done(sh2);
141   if (cycles > 600)
142     p32x_sync_other_sh2(sh2, sh2->m68krcycles_done + cycles / 3);
143 }
144
145 // SH2 faking
146 //#define FAKE_SH2
147 #ifdef FAKE_SH2
148 static int p32x_csum_faked;
149 static const u16 comm_fakevals[] = {
150   0x4d5f, 0x4f4b, // M_OK
151   0x535f, 0x4f4b, // S_OK
152   0x4D41, 0x5346, // MASF - Brutal Unleashed
153   0x5331, 0x4d31, // Darxide
154   0x5332, 0x4d32,
155   0x5333, 0x4d33,
156   0x0000, 0x0000, // eq for doom
157   0x0002, // Mortal Kombat
158 //  0, // pad
159 };
160
161 static u32 sh2_comm_faker(u32 a)
162 {
163   static int f = 0;
164   if (a == 0x28 && !p32x_csum_faked) {
165     p32x_csum_faked = 1;
166     return *(unsigned short *)(Pico.rom + 0x18e);
167   }
168   if (f >= sizeof(comm_fakevals) / sizeof(comm_fakevals[0]))
169     f = 0;
170   return comm_fakevals[f++];
171 }
172 #endif
173
174 // ------------------------------------------------------------------
175 // 68k regs
176
177 static u32 p32x_reg_read16(u32 a)
178 {
179   a &= 0x3e;
180
181 #if 0
182   if ((a & 0x30) == 0x20)
183     return sh2_comm_faker(a);
184 #else
185   if ((a & 0x30) == 0x20) {
186     static u32 dr2 = 0;
187     unsigned int cycles = SekCyclesDoneT();
188     int comreg = 1 << (a & 0x0f) / 2;
189
190     // evil X-Men proto polls in a dbra loop and expects it to expire..
191     if (SekDar(2) != dr2)
192       m68k_poll.cnt = 0;
193     dr2 = SekDar(2);
194
195     if (cycles - msh2.m68krcycles_done > 500)
196       p32x_sync_sh2s(cycles);
197     if (Pico32x.comm_dirty_sh2 & comreg)
198       Pico32x.comm_dirty_sh2 &= ~comreg;
199     else if (m68k_poll_detect(a, cycles, P32XF_68KCPOLL)) {
200       SekSetStop(1);
201       SekEndTimeslice(16);
202     }
203     dr2 = SekDar(2);
204     goto out;
205   }
206 #endif
207
208   if (a == 2) { // INTM, INTS
209     unsigned int cycles = SekCyclesDoneT();
210     if (cycles - msh2.m68krcycles_done > 64)
211       p32x_sync_sh2s(cycles);
212     return ((Pico32x.sh2irqi[0] & P32XI_CMD) >> 4) | ((Pico32x.sh2irqi[1] & P32XI_CMD) >> 3);
213   }
214
215   if ((a & 0x30) == 0x30)
216     return p32x_pwm_read16(a, SekCyclesDoneT());
217
218 out:
219   return Pico32x.regs[a / 2];
220 }
221
222 static void p32x_reg_write8(u32 a, u32 d)
223 {
224   u16 *r = Pico32x.regs;
225   a &= 0x3f;
226
227   // for things like bset on comm port
228   m68k_poll.cnt = 0;
229
230   switch (a) {
231     case 0: // adapter ctl
232       r[0] = (r[0] & ~P32XS_FM) | ((d << 8) & P32XS_FM);
233       return;
234     case 1: // adapter ctl, RES bit writeable
235       if ((d ^ r[0]) & d & P32XS_nRES)
236         p32x_reset_sh2s();
237       r[0] = (r[0] & ~P32XS_nRES) | (d & P32XS_nRES);
238       return;
239     case 3: // irq ctl
240       if ((d & 1) && !(Pico32x.sh2irqi[0] & P32XI_CMD)) {
241         p32x_sync_sh2s(SekCyclesDoneT());
242         Pico32x.sh2irqi[0] |= P32XI_CMD;
243         p32x_update_irls(NULL);
244       }
245       if ((d & 2) && !(Pico32x.sh2irqi[1] & P32XI_CMD)) {
246         p32x_sync_sh2s(SekCyclesDoneT());
247         Pico32x.sh2irqi[1] |= P32XI_CMD;
248         p32x_update_irls(NULL);
249       }
250       return;
251     case 5: // bank
252       d &= 7;
253       if (r[4 / 2] != d) {
254         r[4 / 2] = d;
255         bank_switch(d);
256       }
257       return;
258     case 7: // DREQ ctl
259       r[6 / 2] = (r[6 / 2] & P32XS_FULL) | (d & (P32XS_68S|P32XS_DMA|P32XS_RV));
260       return;
261     case 0x1b: // TV
262       r[0x1a / 2] = d;
263       return;
264   }
265
266   if ((a & 0x30) == 0x20) {
267     u8 *r8 = (u8 *)r;
268     int cycles = SekCyclesDoneT();
269     int comreg;
270     
271     if (r8[a ^ 1] == d)
272       return;
273
274     comreg = 1 << (a & 0x0f) / 2;
275     if (Pico32x.comm_dirty_68k & comreg)
276       p32x_sync_sh2s(cycles);
277
278     r8[a ^ 1] = d;
279     p32x_sh2_poll_event(&sh2s[0], SH2_STATE_CPOLL, cycles);
280     p32x_sh2_poll_event(&sh2s[1], SH2_STATE_CPOLL, cycles);
281     Pico32x.comm_dirty_68k |= comreg;
282
283     if (cycles - (int)msh2.m68krcycles_done > 120)
284       p32x_sync_sh2s(cycles);
285     return;
286   }
287 }
288
289 static void p32x_reg_write16(u32 a, u32 d)
290 {
291   u16 *r = Pico32x.regs;
292   a &= 0x3e;
293
294   // for things like bset on comm port
295   m68k_poll.cnt = 0;
296
297   switch (a) {
298     case 0x00: // adapter ctl
299       if ((d ^ r[0]) & d & P32XS_nRES)
300         p32x_reset_sh2s();
301       r[0] = (r[0] & ~(P32XS_FM|P32XS_nRES)) | (d & (P32XS_FM|P32XS_nRES));
302       return;
303     case 0x10: // DREQ len
304       r[a / 2] = d & ~3;
305       return;
306     case 0x12: // FIFO reg
307       if (!(r[6 / 2] & P32XS_68S)) {
308         elprintf(EL_32X|EL_ANOMALY, "DREQ FIFO w16 without 68S?");
309         return;
310       }
311       if (Pico32x.dmac0_fifo_ptr < DMAC_FIFO_LEN) {
312         Pico32x.dmac_fifo[Pico32x.dmac0_fifo_ptr++] = d;
313         if ((Pico32x.dmac0_fifo_ptr & 3) == 0)
314           p32x_dreq0_trigger();
315         if (Pico32x.dmac0_fifo_ptr == DMAC_FIFO_LEN)
316           r[6 / 2] |= P32XS_FULL;
317       }
318       break;
319   }
320
321   // DREQ src, dst
322   if      ((a & 0x38) == 0x08) {
323     r[a / 2] = d;
324     return;
325   }
326   // comm port
327   else if ((a & 0x30) == 0x20) {
328     int cycles = SekCyclesDoneT();
329     int comreg;
330     
331     if (r[a / 2] == d)
332       return;
333
334     comreg = 1 << (a & 0x0f) / 2;
335     if (Pico32x.comm_dirty_68k & comreg)
336       p32x_sync_sh2s(cycles);
337
338     r[a / 2] = d;
339     p32x_sh2_poll_event(&sh2s[0], SH2_STATE_CPOLL, cycles);
340     p32x_sh2_poll_event(&sh2s[1], SH2_STATE_CPOLL, cycles);
341     Pico32x.comm_dirty_68k |= comreg;
342
343     if (cycles - (int)msh2.m68krcycles_done > 120)
344       p32x_sync_sh2s(cycles);
345     return;
346   }
347   // PWM
348   else if ((a & 0x30) == 0x30) {
349     p32x_pwm_write16(a, d, SekCyclesDoneT());
350     return;
351   }
352
353   p32x_reg_write8(a + 1, d);
354 }
355
356 // ------------------------------------------------------------------
357 // VDP regs
358 static u32 p32x_vdp_read16(u32 a)
359 {
360   a &= 0x0e;
361
362   return Pico32x.vdp_regs[a / 2];
363 }
364
365 static void p32x_vdp_write8(u32 a, u32 d)
366 {
367   u16 *r = Pico32x.vdp_regs;
368   a &= 0x0f;
369
370   // TODO: verify what's writeable
371   switch (a) {
372     case 0x01:
373       // priority inversion is handled in palette
374       if ((r[0] ^ d) & P32XV_PRI)
375         Pico32x.dirty_pal = 1;
376       r[0] = (r[0] & P32XV_nPAL) | (d & 0xff);
377       break;
378     case 0x03: // shift (for pp mode)
379       r[2 / 2] = d & 1;
380       break;
381     case 0x05: // fill len
382       r[4 / 2] = d & 0xff;
383       break;
384     case 0x0b:
385       d &= 1;
386       Pico32x.pending_fb = d;
387       // if we are blanking and FS bit is changing
388       if (((r[0x0a/2] & P32XV_VBLK) || (r[0] & P32XV_Mx) == 0) && ((r[0x0a/2] ^ d) & P32XV_FS)) {
389         r[0x0a/2] ^= P32XV_FS;
390         Pico32xSwapDRAM(d ^ 1);
391         elprintf(EL_32X, "VDP FS: %d", r[0x0a/2] & P32XV_FS);
392       }
393       break;
394   }
395 }
396
397 static void p32x_vdp_write16(u32 a, u32 d, SH2 *sh2)
398 {
399   a &= 0x0e;
400   if (a == 6) { // fill start
401     Pico32x.vdp_regs[6 / 2] = d;
402     return;
403   }
404   if (a == 8) { // fill data
405     u16 *dram = Pico32xMem->dram[(Pico32x.vdp_regs[0x0a/2] & P32XV_FS) ^ 1];
406     int len = Pico32x.vdp_regs[4 / 2] + 1;
407     int len1 = len;
408     a = Pico32x.vdp_regs[6 / 2];
409     while (len1--) {
410       dram[a] = d;
411       a = (a & 0xff00) | ((a + 1) & 0xff);
412     }
413     Pico32x.vdp_regs[0x06 / 2] = a;
414     Pico32x.vdp_regs[0x08 / 2] = d;
415     if (sh2 != NULL && len > 4) {
416       Pico32x.vdp_regs[0x0a / 2] |= P32XV_nFEN;
417       // supposedly takes 3 bus/6 sh2 cycles? or 3 sh2 cycles?
418       p32x_event_schedule_sh2(sh2, P32X_EVENT_FILLEND, 3 + len);
419     }
420     return;
421   }
422
423   p32x_vdp_write8(a | 1, d);
424 }
425
426 // ------------------------------------------------------------------
427 // SH2 regs
428
429 static u32 p32x_sh2reg_read16(u32 a, int cpuid)
430 {
431   u16 *r = Pico32x.regs;
432   a &= 0xfe; // ?
433
434   switch (a) {
435     case 0x00: // adapter/irq ctl
436       return (r[0] & P32XS_FM) | Pico32x.sh2_regs[0] | Pico32x.sh2irq_mask[cpuid];
437     case 0x04: // H count (often as comm too)
438       sh2_poll_detect(&sh2s[cpuid], a, SH2_STATE_CPOLL);
439       sh2s_sync_on_read(&sh2s[cpuid]);
440       return Pico32x.sh2_regs[4 / 2];
441     case 0x10: // DREQ len
442       return r[a / 2];
443   }
444
445   // DREQ src, dst
446   if ((a & 0x38) == 0x08)
447     return r[a / 2];
448   // comm port
449   if ((a & 0x30) == 0x20) {
450     int comreg = 1 << (a & 0x0f) / 2;
451     if (Pico32x.comm_dirty_68k & comreg)
452       Pico32x.comm_dirty_68k &= ~comreg;
453     else
454       sh2_poll_detect(&sh2s[cpuid], a, SH2_STATE_CPOLL);
455     sh2s_sync_on_read(&sh2s[cpuid]);
456     return r[a / 2];
457   }
458   if ((a & 0x30) == 0x30) {
459     return p32x_pwm_read16(a, sh2_cycles_done_m68k(&sh2s[cpuid]));
460   }
461
462   return 0;
463 }
464
465 static void p32x_sh2reg_write8(u32 a, u32 d, int cpuid)
466 {
467   a &= 0xff;
468
469   sh2s[cpuid].poll_addr = 0;
470
471   switch (a) {
472     case 0: // FM
473       Pico32x.regs[0] &= ~P32XS_FM;
474       Pico32x.regs[0] |= (d << 8) & P32XS_FM;
475       return;
476     case 1: // HEN/irq masks
477       if ((d ^ Pico32x.sh2_regs[0]) & 0x80)
478         elprintf(EL_ANOMALY|EL_32X, "HEN");
479       Pico32x.sh2irq_mask[cpuid] = d & 0x8f;
480       Pico32x.sh2_regs[0] &= ~0x80;
481       Pico32x.sh2_regs[0] |= d & 0x80;
482       if (d & 1)
483         p32x_pwm_schedule_sh2(&sh2s[cpuid]);
484       p32x_update_irls(&sh2s[cpuid]);
485       return;
486     case 5: // H count
487       d &= 0xff;
488       if (Pico32x.sh2_regs[4 / 2] != d) {
489         Pico32x.sh2_regs[4 / 2] = d;
490         p32x_sh2_poll_event(&sh2s[cpuid ^ 1], SH2_STATE_CPOLL,
491           sh2_cycles_done_m68k(&sh2s[cpuid]));
492         sh2_end_run(&sh2s[cpuid], 4);
493       }
494       return;
495   }
496
497   if ((a & 0x30) == 0x20) {
498     u8 *r8 = (u8 *)Pico32x.regs;
499     int comreg;
500     if (r8[a ^ 1] == d)
501       return;
502
503     r8[a ^ 1] = d;
504     p32x_m68k_poll_event(P32XF_68KCPOLL);
505     p32x_sh2_poll_event(&sh2s[cpuid ^ 1], SH2_STATE_CPOLL,
506       sh2_cycles_done_m68k(&sh2s[cpuid]));
507     comreg = 1 << (a & 0x0f) / 2;
508     Pico32x.comm_dirty_sh2 |= comreg;
509     return;
510   }
511 }
512
513 static void p32x_sh2reg_write16(u32 a, u32 d, int cpuid)
514 {
515   a &= 0xfe;
516
517   sh2s[cpuid].poll_addr = 0;
518
519   // comm
520   if ((a & 0x30) == 0x20) {
521     int comreg;
522     if (Pico32x.regs[a / 2] == d)
523       return;
524
525     Pico32x.regs[a / 2] = d;
526     p32x_m68k_poll_event(P32XF_68KCPOLL);
527     p32x_sh2_poll_event(&sh2s[cpuid ^ 1], SH2_STATE_CPOLL,
528       sh2_cycles_done_m68k(&sh2s[cpuid]));
529     comreg = 1 << (a & 0x0f) / 2;
530     Pico32x.comm_dirty_sh2 |= comreg;
531     return;
532   }
533   // PWM
534   else if ((a & 0x30) == 0x30) {
535     p32x_pwm_write16(a, d, sh2_cycles_done_m68k(&sh2s[cpuid]));
536     return;
537   }
538
539   switch (a) {
540     case 0: // FM
541       Pico32x.regs[0] &= ~P32XS_FM;
542       Pico32x.regs[0] |= d & P32XS_FM;
543       break;
544     case 0x14: Pico32x.sh2irqs &= ~P32XI_VRES; goto irls;
545     case 0x16: Pico32x.sh2irqs &= ~P32XI_VINT; goto irls;
546     case 0x18: Pico32x.sh2irqs &= ~P32XI_HINT; goto irls;
547     case 0x1a: Pico32x.sh2irqi[cpuid] &= ~P32XI_CMD; goto irls;
548     case 0x1c:
549       Pico32x.sh2irqs &= ~P32XI_PWM;
550       p32x_pwm_schedule_sh2(&sh2s[cpuid]);
551       goto irls;
552   }
553
554   p32x_sh2reg_write8(a | 1, d, cpuid);
555   return;
556
557 irls:
558   p32x_update_irls(&sh2s[cpuid]);
559 }
560
561 // ------------------------------------------------------------------
562 // 32x handlers
563
564 // after ADEN
565 static u32 PicoRead8_32x_on(u32 a)
566 {
567   u32 d = 0;
568   if ((a & 0xffc0) == 0x5100) { // a15100
569     d = p32x_reg_read16(a);
570     goto out_16to8;
571   }
572
573   if ((a & 0xfc00) != 0x5000)
574     return PicoRead8_io(a);
575
576   if ((a & 0xfff0) == 0x5180) { // a15180
577     d = p32x_vdp_read16(a);
578     goto out_16to8;
579   }
580
581   if ((a & 0xfe00) == 0x5200) { // a15200
582     d = Pico32xMem->pal[(a & 0x1ff) / 2];
583     goto out_16to8;
584   }
585
586   if ((a & 0xfffc) == 0x30ec) { // a130ec
587     d = str_mars[a & 3];
588     goto out;
589   }
590
591   elprintf(EL_UIO, "m68k unmapped r8  [%06x] @%06x", a, SekPc);
592   return d;
593
594 out_16to8:
595   if (a & 1)
596     d &= 0xff;
597   else
598     d >>= 8;
599
600 out:
601   elprintf(EL_32X, "m68k 32x r8  [%06x]   %02x @%06x", a, d, SekPc);
602   return d;
603 }
604
605 static u32 PicoRead16_32x_on(u32 a)
606 {
607   u32 d = 0;
608   if ((a & 0xffc0) == 0x5100) { // a15100
609     d = p32x_reg_read16(a);
610     goto out;
611   }
612
613   if ((a & 0xfc00) != 0x5000)
614     return PicoRead16_io(a);
615
616   if ((a & 0xfff0) == 0x5180) { // a15180
617     d = p32x_vdp_read16(a);
618     goto out;
619   }
620
621   if ((a & 0xfe00) == 0x5200) { // a15200
622     d = Pico32xMem->pal[(a & 0x1ff) / 2];
623     goto out;
624   }
625
626   if ((a & 0xfffc) == 0x30ec) { // a130ec
627     d = !(a & 2) ? ('M'<<8)|'A' : ('R'<<8)|'S';
628     goto out;
629   }
630
631   elprintf(EL_UIO, "m68k unmapped r16 [%06x] @%06x", a, SekPc);
632   return d;
633
634 out:
635   elprintf(EL_32X, "m68k 32x r16 [%06x] %04x @%06x", a, d, SekPc);
636   return d;
637 }
638
639 static void PicoWrite8_32x_on(u32 a, u32 d)
640 {
641   if ((a & 0xfc00) == 0x5000)
642     elprintf(EL_32X, "m68k 32x w8  [%06x]   %02x @%06x", a, d & 0xff, SekPc);
643
644   if ((a & 0xffc0) == 0x5100) { // a15100
645     p32x_reg_write8(a, d);
646     return;
647   }
648
649   if ((a & 0xfc00) != 0x5000) {
650     PicoWrite8_io(a, d);
651     return;
652   }
653
654   if (!(Pico32x.regs[0] & P32XS_FM)) {
655     if ((a & 0xfff0) == 0x5180) { // a15180
656       p32x_vdp_write8(a, d);
657       return;
658     }
659
660     // TODO: verify
661     if ((a & 0xfe00) == 0x5200) { // a15200
662       elprintf(EL_32X|EL_ANOMALY, "m68k 32x PAL w8  [%06x]   %02x @%06x", a, d & 0xff, SekPc);
663       ((u8 *)Pico32xMem->pal)[(a & 0x1ff) ^ 1] = d;
664       Pico32x.dirty_pal = 1;
665       return;
666     }
667   }
668
669   elprintf(EL_UIO, "m68k unmapped w8  [%06x]   %02x @%06x", a, d & 0xff, SekPc);
670 }
671
672 static void PicoWrite16_32x_on(u32 a, u32 d)
673 {
674   if ((a & 0xfc00) == 0x5000)
675     elprintf(EL_32X, "m68k 32x w16 [%06x] %04x @%06x", a, d & 0xffff, SekPc);
676
677   if ((a & 0xffc0) == 0x5100) { // a15100
678     p32x_reg_write16(a, d);
679     return;
680   }
681
682   if ((a & 0xfc00) != 0x5000) {
683     PicoWrite16_io(a, d);
684     return;
685   }
686
687   if (!(Pico32x.regs[0] & P32XS_FM)) {
688     if ((a & 0xfff0) == 0x5180) { // a15180
689       p32x_vdp_write16(a, d, NULL); // FIXME?
690       return;
691     }
692
693     if ((a & 0xfe00) == 0x5200) { // a15200
694       Pico32xMem->pal[(a & 0x1ff) / 2] = d;
695       Pico32x.dirty_pal = 1;
696       return;
697     }
698   }
699
700   elprintf(EL_UIO, "m68k unmapped w16 [%06x] %04x @%06x", a, d & 0xffff, SekPc);
701 }
702
703 // before ADEN
704 u32 PicoRead8_32x(u32 a)
705 {
706   u32 d = 0;
707   if ((a & 0xffc0) == 0x5100) { // a15100
708     // regs are always readable
709     d = ((u8 *)Pico32x.regs)[(a & 0x3f) ^ 1];
710     goto out;
711   }
712
713   if ((a & 0xfffc) == 0x30ec) { // a130ec
714     d = str_mars[a & 3];
715     goto out;
716   }
717
718   elprintf(EL_UIO, "m68k unmapped r8  [%06x] @%06x", a, SekPc);
719   return d;
720
721 out:
722   elprintf(EL_32X, "m68k 32x r8  [%06x]   %02x @%06x", a, d, SekPc);
723   return d;
724 }
725
726 u32 PicoRead16_32x(u32 a)
727 {
728   u32 d = 0;
729   if ((a & 0xffc0) == 0x5100) { // a15100
730     d = Pico32x.regs[(a & 0x3f) / 2];
731     goto out;
732   }
733
734   if ((a & 0xfffc) == 0x30ec) { // a130ec
735     d = !(a & 2) ? ('M'<<8)|'A' : ('R'<<8)|'S';
736     goto out;
737   }
738
739   elprintf(EL_UIO, "m68k unmapped r16 [%06x] @%06x", a, SekPc);
740   return d;
741
742 out:
743   elprintf(EL_32X, "m68k 32x r16 [%06x] %04x @%06x", a, d, SekPc);
744   return d;
745 }
746
747 void PicoWrite8_32x(u32 a, u32 d)
748 {
749   if ((a & 0xffc0) == 0x5100) { // a15100
750     u16 *r = Pico32x.regs;
751
752     elprintf(EL_32X, "m68k 32x w8  [%06x]   %02x @%06x", a, d & 0xff, SekPc);
753     a &= 0x3f;
754     if (a == 1) {
755       if ((d ^ r[0]) & d & P32XS_ADEN) {
756         Pico32xStartup();
757         r[0] &= ~P32XS_nRES; // causes reset if specified by this write
758         r[0] |= P32XS_ADEN;
759         p32x_reg_write8(a, d); // forward for reset processing
760       }
761       return;
762     }
763
764     // allow only COMM for now
765     if ((a & 0x30) == 0x20) {
766       u8 *r8 = (u8 *)r;
767       r8[a ^ 1] = d;
768     }
769     return;
770   }
771
772   elprintf(EL_UIO, "m68k unmapped w8  [%06x]   %02x @%06x", a, d & 0xff, SekPc);
773 }
774
775 void PicoWrite16_32x(u32 a, u32 d)
776 {
777   if ((a & 0xffc0) == 0x5100) { // a15100
778     u16 *r = Pico32x.regs;
779
780     elprintf(EL_UIO, "m68k 32x w16 [%06x] %04x @%06x", a, d & 0xffff, SekPc);
781     a &= 0x3e;
782     if (a == 0) {
783       if ((d ^ r[0]) & d & P32XS_ADEN) {
784         Pico32xStartup();
785         r[0] &= ~P32XS_nRES; // causes reset if specified by this write
786         r[0] |= P32XS_ADEN;
787         p32x_reg_write16(a, d); // forward for reset processing
788       }
789       return;
790     }
791
792     // allow only COMM for now
793     if ((a & 0x30) == 0x20)
794       r[a / 2] = d;
795     return;
796   }
797
798   elprintf(EL_UIO, "m68k unmapped w16 [%06x] %04x @%06x", a, d & 0xffff, SekPc);
799 }
800
801 // -----------------------------------------------------------------
802
803 // hint vector is writeable
804 static void PicoWrite8_hint(u32 a, u32 d)
805 {
806   if ((a & 0xfffc) == 0x0070) {
807     Pico32xMem->m68k_rom[a ^ 1] = d;
808     return;
809   }
810
811   elprintf(EL_UIO, "m68k unmapped w8  [%06x]   %02x @%06x", a, d & 0xff, SekPc);
812 }
813
814 static void PicoWrite16_hint(u32 a, u32 d)
815 {
816   if ((a & 0xfffc) == 0x0070) {
817     ((u16 *)Pico32xMem->m68k_rom)[a/2] = d;
818     return;
819   }
820
821   elprintf(EL_UIO, "m68k unmapped w16 [%06x] %04x @%06x", a, d & 0xffff, SekPc);
822 }
823
824 static void bank_switch(int b)
825 {
826   unsigned int rs, bank;
827
828   bank = b << 20;
829   if (bank >= Pico.romsize) {
830     elprintf(EL_32X|EL_ANOMALY, "missing bank @ %06x", bank);
831     return;
832   }
833
834   // 32X ROM (unbanked, XXX: consider mirroring?)
835   rs = (Pico.romsize + M68K_BANK_MASK) & ~M68K_BANK_MASK;
836   rs -= bank;
837   if (rs > 0x100000)
838     rs = 0x100000;
839   cpu68k_map_set(m68k_read8_map,   0x900000, 0x900000 + rs - 1, Pico.rom + bank, 0);
840   cpu68k_map_set(m68k_read16_map,  0x900000, 0x900000 + rs - 1, Pico.rom + bank, 0);
841
842   elprintf(EL_32X, "bank %06x-%06x -> %06x", 0x900000, 0x900000 + rs - 1, bank);
843
844 #ifdef EMU_F68K
845   // setup FAME fetchmap
846   for (rs = 0x90; rs < 0xa0; rs++)
847     PicoCpuFM68k.Fetch[rs] = (unsigned long)Pico.rom + bank - 0x900000;
848 #endif
849 }
850
851 // -----------------------------------------------------------------
852 //                              SH2  
853 // -----------------------------------------------------------------
854
855 // read8
856 static u32 sh2_read8_unmapped(u32 a, int id)
857 {
858   elprintf(EL_UIO, "%csh2 unmapped r8  [%08x]       %02x @%06x",
859     id ? 's' : 'm', a, 0, sh2_pc(id));
860   return 0;
861 }
862
863 static u32 sh2_read8_cs0(u32 a, int id)
864 {
865   u32 d = 0;
866
867   // 0x3ff00 is veridied
868   if ((a & 0x3ff00) == 0x4000) {
869     d = p32x_sh2reg_read16(a, id);
870     goto out_16to8;
871   }
872
873   if ((a & 0x3ff00) == 0x4100) {
874     d = p32x_vdp_read16(a);
875     sh2_poll_detect(&sh2s[id], a, SH2_STATE_VPOLL);
876     goto out_16to8;
877   }
878
879   // TODO: mirroring?
880   if (id == 0 && a < sizeof(Pico32xMem->sh2_rom_m))
881     return Pico32xMem->sh2_rom_m[a ^ 1];
882   if (id == 1 && a < sizeof(Pico32xMem->sh2_rom_s))
883     return Pico32xMem->sh2_rom_s[a ^ 1];
884
885   if ((a & 0x3fe00) == 0x4200) {
886     d = Pico32xMem->pal[(a & 0x1ff) / 2];
887     goto out_16to8;
888   }
889
890   return sh2_read8_unmapped(a, id);
891
892 out_16to8:
893   if (a & 1)
894     d &= 0xff;
895   else
896     d >>= 8;
897
898   elprintf(EL_32X, "%csh2 r8  [%08x]       %02x @%06x",
899     id ? 's' : 'm', a, d, sh2_pc(id));
900   return d;
901 }
902
903 static u32 sh2_read8_da(u32 a, int id)
904 {
905   return Pico32xMem->data_array[id][(a & 0xfff) ^ 1];
906 }
907
908 // read16
909 static u32 sh2_read16_unmapped(u32 a, int id)
910 {
911   elprintf(EL_UIO, "%csh2 unmapped r16 [%08x]     %04x @%06x",
912     id ? 's' : 'm', a, 0, sh2_pc(id));
913   return 0;
914 }
915
916 static u32 sh2_read16_cs0(u32 a, int id)
917 {
918   u32 d = 0;
919
920   if ((a & 0x3ff00) == 0x4000) {
921     d = p32x_sh2reg_read16(a, id);
922     if (!(EL_LOGMASK & EL_PWM) && (a & 0x30) == 0x30) // hide PWM
923       return d;
924     goto out;
925   }
926
927   if ((a & 0x3ff00) == 0x4100) {
928     d = p32x_vdp_read16(a);
929     sh2_poll_detect(&sh2s[id], a, SH2_STATE_VPOLL);
930     goto out;
931   }
932
933   if (id == 0 && a < sizeof(Pico32xMem->sh2_rom_m))
934     return *(u16 *)(Pico32xMem->sh2_rom_m + a);
935   if (id == 1 && a < sizeof(Pico32xMem->sh2_rom_s))
936     return *(u16 *)(Pico32xMem->sh2_rom_s + a);
937
938   if ((a & 0x3fe00) == 0x4200) {
939     d = Pico32xMem->pal[(a & 0x1ff) / 2];
940     goto out;
941   }
942
943   return sh2_read16_unmapped(a, id);
944
945 out:
946   elprintf(EL_32X, "%csh2 r16 [%08x]     %04x @%06x",
947     id ? 's' : 'm', a, d, sh2_pc(id));
948   return d;
949 }
950
951 static u32 sh2_read16_da(u32 a, int id)
952 {
953   return ((u16 *)Pico32xMem->data_array[id])[(a & 0xfff) / 2];
954 }
955
956 static int REGPARM(3) sh2_write_ignore(u32 a, u32 d, int id)
957 {
958   return 0;
959 }
960
961 // write8
962 static int REGPARM(3) sh2_write8_unmapped(u32 a, u32 d, int id)
963 {
964   elprintf(EL_UIO, "%csh2 unmapped w8  [%08x]       %02x @%06x",
965     id ? 's' : 'm', a, d & 0xff, sh2_pc(id));
966   return 0;
967 }
968
969 static int REGPARM(3) sh2_write8_cs0(u32 a, u32 d, int id)
970 {
971   elprintf(EL_32X, "%csh2 w8  [%08x]       %02x @%06x",
972     id ? 's' : 'm', a, d & 0xff, sh2_pc(id));
973
974   if (Pico32x.regs[0] & P32XS_FM) {
975     if ((a & 0x3ff00) == 0x4100) {
976       sh2s[id].poll_addr = 0;
977       p32x_vdp_write8(a, d);
978       return 0;
979     }
980   }
981
982   if ((a & 0x3ff00) == 0x4000) {
983     p32x_sh2reg_write8(a, d, id);
984     return 1;
985   }
986
987   return sh2_write8_unmapped(a, d, id);
988 }
989
990 /* quirk: in both normal and overwrite areas only nonzero values go through */
991 #define sh2_write8_dramN(n) \
992   if ((d & 0xff) != 0) { \
993     u8 *dram = (u8 *)Pico32xMem->dram[n]; \
994     dram[(a & 0x1ffff) ^ 1] = d; \
995   } \
996   return 0;
997
998 static int REGPARM(3) sh2_write8_dram0(u32 a, u32 d, int id)
999 {
1000   sh2_write8_dramN(0);
1001 }
1002
1003 static int REGPARM(3) sh2_write8_dram1(u32 a, u32 d, int id)
1004 {
1005   sh2_write8_dramN(1);
1006 }
1007
1008 static int REGPARM(3) sh2_write8_sdram(u32 a, u32 d, int id)
1009 {
1010   u32 a1 = a & 0x3ffff;
1011 #ifdef DRC_SH2
1012   int t = Pico32xMem->drcblk_ram[a1 >> SH2_DRCBLK_RAM_SHIFT];
1013   if (t)
1014     sh2_drc_wcheck_ram(a, t, id);
1015 #endif
1016   Pico32xMem->sdram[a1 ^ 1] = d;
1017   return 0;
1018 }
1019
1020 static int REGPARM(3) sh2_write8_da(u32 a, u32 d, int id)
1021 {
1022   u32 a1 = a & 0xfff;
1023 #ifdef DRC_SH2
1024   int t = Pico32xMem->drcblk_da[id][a1 >> SH2_DRCBLK_DA_SHIFT];
1025   if (t)
1026     sh2_drc_wcheck_da(a, t, id);
1027 #endif
1028   Pico32xMem->data_array[id][a1 ^ 1] = d;
1029   return 0;
1030 }
1031
1032 // write16
1033 static int REGPARM(3) sh2_write16_unmapped(u32 a, u32 d, int id)
1034 {
1035   elprintf(EL_UIO, "%csh2 unmapped w16 [%08x]     %04x @%06x",
1036     id ? 's' : 'm', a, d & 0xffff, sh2_pc(id));
1037   return 0;
1038 }
1039
1040 static int REGPARM(3) sh2_write16_cs0(u32 a, u32 d, int id)
1041 {
1042   if (((EL_LOGMASK & EL_PWM) || (a & 0x30) != 0x30)) // hide PWM
1043     elprintf(EL_32X, "%csh2 w16 [%08x]     %04x @%06x",
1044       id ? 's' : 'm', a, d & 0xffff, sh2_pc(id));
1045
1046   if (Pico32x.regs[0] & P32XS_FM) {
1047     if ((a & 0x3ff00) == 0x4100) {
1048       sh2s[id].poll_addr = 0;
1049       p32x_vdp_write16(a, d, &sh2s[id]);
1050       return 0;
1051     }
1052
1053     if ((a & 0x3fe00) == 0x4200) {
1054       Pico32xMem->pal[(a & 0x1ff) / 2] = d;
1055       Pico32x.dirty_pal = 1;
1056       return 0;
1057     }
1058   }
1059
1060   if ((a & 0x3ff00) == 0x4000) {
1061     p32x_sh2reg_write16(a, d, id);
1062     return 1;
1063   }
1064
1065   return sh2_write16_unmapped(a, d, id);
1066 }
1067
1068 #define sh2_write16_dramN(n) \
1069   u16 *pd = &Pico32xMem->dram[n][(a & 0x1ffff) / 2]; \
1070   if (!(a & 0x20000)) { \
1071     *pd = d; \
1072     return 0; \
1073   } \
1074   /* overwrite */ \
1075   if (!(d & 0xff00)) d |= *pd & 0xff00; \
1076   if (!(d & 0x00ff)) d |= *pd & 0x00ff; \
1077   *pd = d; \
1078   return 0
1079
1080 static int REGPARM(3) sh2_write16_dram0(u32 a, u32 d, int id)
1081 {
1082   sh2_write16_dramN(0);
1083 }
1084
1085 static int REGPARM(3) sh2_write16_dram1(u32 a, u32 d, int id)
1086 {
1087   sh2_write16_dramN(1);
1088 }
1089
1090 static int REGPARM(3) sh2_write16_sdram(u32 a, u32 d, int id)
1091 {
1092   u32 a1 = a & 0x3ffff;
1093 #ifdef DRC_SH2
1094   int t = Pico32xMem->drcblk_ram[a1 >> SH2_DRCBLK_RAM_SHIFT];
1095   if (t)
1096     sh2_drc_wcheck_ram(a, t, id);
1097 #endif
1098   ((u16 *)Pico32xMem->sdram)[a1 / 2] = d;
1099   return 0;
1100 }
1101
1102 static int REGPARM(3) sh2_write16_da(u32 a, u32 d, int id)
1103 {
1104   u32 a1 = a & 0xfff;
1105 #ifdef DRC_SH2
1106   int t = Pico32xMem->drcblk_da[id][a1 >> SH2_DRCBLK_DA_SHIFT];
1107   if (t)
1108     sh2_drc_wcheck_da(a, t, id);
1109 #endif
1110   ((u16 *)Pico32xMem->data_array[id])[a1 / 2] = d;
1111   return 0;
1112 }
1113
1114
1115 typedef u32 (sh2_read_handler)(u32 a, int id);
1116 typedef int REGPARM(3) (sh2_write_handler)(u32 a, u32 d, int id);
1117
1118 #define SH2MAP_ADDR2OFFS_R(a) \
1119   ((((a) >> 25) & 3) | (((a) >> 27) & 0x1c))
1120
1121 #define SH2MAP_ADDR2OFFS_W(a) \
1122   ((u32)(a) >> SH2_WRITE_SHIFT)
1123
1124 u32 REGPARM(2) p32x_sh2_read8(u32 a, SH2 *sh2)
1125 {
1126   const sh2_memmap *sh2_map = sh2->read8_map;
1127   uptr p;
1128
1129   sh2_map += SH2MAP_ADDR2OFFS_R(a);
1130   p = sh2_map->addr;
1131   if (map_flag_set(p))
1132     return ((sh2_read_handler *)(p << 1))(a, sh2->is_slave);
1133   else
1134     return *(u8 *)((p << 1) + ((a & sh2_map->mask) ^ 1));
1135 }
1136
1137 u32 REGPARM(2) p32x_sh2_read16(u32 a, SH2 *sh2)
1138 {
1139   const sh2_memmap *sh2_map = sh2->read16_map;
1140   uptr p;
1141
1142   sh2_map += SH2MAP_ADDR2OFFS_R(a);
1143   p = sh2_map->addr;
1144   if (map_flag_set(p))
1145     return ((sh2_read_handler *)(p << 1))(a, sh2->is_slave);
1146   else
1147     return *(u16 *)((p << 1) + ((a & sh2_map->mask) & ~1));
1148 }
1149
1150 u32 REGPARM(2) p32x_sh2_read32(u32 a, SH2 *sh2)
1151 {
1152   const sh2_memmap *sh2_map = sh2->read16_map;
1153   sh2_read_handler *handler;
1154   u32 offs;
1155   uptr p;
1156
1157   offs = SH2MAP_ADDR2OFFS_R(a);
1158   sh2_map += offs;
1159   p = sh2_map->addr;
1160   if (!map_flag_set(p)) {
1161     // XXX: maybe 32bit access instead with ror?
1162     u16 *pd = (u16 *)((p << 1) + ((a & sh2_map->mask) & ~1));
1163     return (pd[0] << 16) | pd[1];
1164   }
1165
1166   if (offs == 0x1f)
1167     return sh2_peripheral_read32(a, sh2->is_slave);
1168
1169   handler = (sh2_read_handler *)(p << 1);
1170   return (handler(a, sh2->is_slave) << 16) | handler(a + 2, sh2->is_slave);
1171 }
1172
1173 // return nonzero if write potentially causes an interrupt (used by drc)
1174 int REGPARM(3) p32x_sh2_write8(u32 a, u32 d, SH2 *sh2)
1175 {
1176   const void **sh2_wmap = sh2->write8_tab;
1177   sh2_write_handler *wh;
1178
1179   wh = sh2_wmap[SH2MAP_ADDR2OFFS_W(a)];
1180   return wh(a, d, sh2->is_slave);
1181 }
1182
1183 int REGPARM(3) p32x_sh2_write16(u32 a, u32 d, SH2 *sh2)
1184 {
1185   const void **sh2_wmap = sh2->write16_tab;
1186   sh2_write_handler *wh;
1187
1188   wh = sh2_wmap[SH2MAP_ADDR2OFFS_W(a)];
1189   return wh(a, d, sh2->is_slave);
1190 }
1191
1192 int REGPARM(3) p32x_sh2_write32(u32 a, u32 d, SH2 *sh2)
1193 {
1194   const void **sh2_wmap = sh2->write16_tab;
1195   sh2_write_handler *handler;
1196   u32 offs;
1197
1198   offs = SH2MAP_ADDR2OFFS_W(a);
1199
1200   if (offs == SH2MAP_ADDR2OFFS_W(0xffffc000)) {
1201     sh2_peripheral_write32(a, d, sh2->is_slave);
1202     return 0;
1203   }
1204
1205   handler = sh2_wmap[offs];
1206   handler(a, d >> 16, sh2->is_slave);
1207   handler(a + 2, d, sh2->is_slave);
1208   return 0;
1209 }
1210
1211 // -----------------------------------------------------------------
1212
1213 static const u16 msh2_code[] = {
1214   // trap instructions
1215   0xaffe, // bra <self>
1216   0x0009, // nop
1217   // have to wait a bit until m68k initial program finishes clearing stuff
1218   // to avoid races with game SH2 code, like in Tempo
1219   0xd004, // mov.l   @(_m_ok,pc), r0
1220   0xd105, // mov.l   @(_cnt,pc), r1
1221   0xd205, // mov.l   @(_start,pc), r2
1222   0x71ff, // add     #-1, r1
1223   0x4115, // cmp/pl  r1
1224   0x89fc, // bt      -2
1225   0xc208, // mov.l   r0, @(h'20,gbr)
1226   0x6822, // mov.l   @r2, r8
1227   0x482b, // jmp     @r8
1228   0x0009, // nop
1229   ('M'<<8)|'_', ('O'<<8)|'K',
1230   0x0001, 0x0000,
1231   0x2200, 0x03e0  // master start pointer in ROM
1232 };
1233
1234 static const u16 ssh2_code[] = {
1235   0xaffe, // bra <self>
1236   0x0009, // nop
1237   // code to wait for master, in case authentic master BIOS is used
1238   0xd104, // mov.l   @(_m_ok,pc), r1
1239   0xd206, // mov.l   @(_start,pc), r2
1240   0xc608, // mov.l   @(h'20,gbr), r0
1241   0x3100, // cmp/eq  r0, r1
1242   0x8bfc, // bf      #-2
1243   0xd003, // mov.l   @(_s_ok,pc), r0
1244   0xc209, // mov.l   r0, @(h'24,gbr)
1245   0x6822, // mov.l   @r2, r8
1246   0x482b, // jmp     @r8
1247   0x0009, // nop
1248   ('M'<<8)|'_', ('O'<<8)|'K',
1249   ('S'<<8)|'_', ('O'<<8)|'K',
1250   0x2200, 0x03e4  // slave start pointer in ROM
1251 };
1252
1253 #define HWSWAP(x) (((u16)(x) << 16) | ((x) >> 16))
1254 static void get_bios(void)
1255 {
1256   u16 *ps;
1257   u32 *pl;
1258   int i;
1259
1260   // M68K ROM
1261   if (p32x_bios_g != NULL) {
1262     elprintf(EL_STATUS|EL_32X, "32x: using supplied 68k BIOS");
1263     Byteswap(Pico32xMem->m68k_rom, p32x_bios_g, sizeof(Pico32xMem->m68k_rom));
1264   }
1265   else {
1266     // generate 68k ROM
1267     ps = (u16 *)Pico32xMem->m68k_rom;
1268     pl = (u32 *)ps;
1269     for (i = 1; i < 0xc0/4; i++)
1270       pl[i] = HWSWAP(0x880200 + (i - 1) * 6);
1271
1272     // fill with nops
1273     for (i = 0xc0/2; i < 0x100/2; i++)
1274       ps[i] = 0x4e71;
1275
1276 #if 0
1277     ps[0xc0/2] = 0x46fc;
1278     ps[0xc2/2] = 0x2700; // move #0x2700,sr
1279     ps[0xfe/2] = 0x60fe; // jump to self
1280 #else
1281     ps[0xfe/2] = 0x4e75; // rts
1282 #endif
1283   }
1284   // fill remaining m68k_rom page with game ROM
1285   memcpy(Pico32xMem->m68k_rom_bank + sizeof(Pico32xMem->m68k_rom),
1286     Pico.rom + sizeof(Pico32xMem->m68k_rom),
1287     sizeof(Pico32xMem->m68k_rom_bank) - sizeof(Pico32xMem->m68k_rom));
1288
1289   // MSH2
1290   if (p32x_bios_m != NULL) {
1291     elprintf(EL_STATUS|EL_32X, "32x: using supplied master SH2 BIOS");
1292     Byteswap(Pico32xMem->sh2_rom_m, p32x_bios_m, sizeof(Pico32xMem->sh2_rom_m));
1293   }
1294   else {
1295     pl = (u32 *)Pico32xMem->sh2_rom_m;
1296
1297     // fill exception vector table to our trap address
1298     for (i = 0; i < 128; i++)
1299       pl[i] = HWSWAP(0x200);
1300
1301     // startup code
1302     memcpy(Pico32xMem->sh2_rom_m + 0x200, msh2_code, sizeof(msh2_code));
1303
1304     // reset SP
1305     pl[1] = pl[3] = HWSWAP(0x6040000);
1306     // start
1307     pl[0] = pl[2] = HWSWAP(0x204);
1308   }
1309
1310   // SSH2
1311   if (p32x_bios_s != NULL) {
1312     elprintf(EL_STATUS|EL_32X, "32x: using supplied slave SH2 BIOS");
1313     Byteswap(Pico32xMem->sh2_rom_s, p32x_bios_s, sizeof(Pico32xMem->sh2_rom_s));
1314   }
1315   else {
1316     pl = (u32 *)Pico32xMem->sh2_rom_s;
1317
1318     // fill exception vector table to our trap address
1319     for (i = 0; i < 128; i++)
1320       pl[i] = HWSWAP(0x200);
1321
1322     // startup code
1323     memcpy(Pico32xMem->sh2_rom_s + 0x200, ssh2_code, sizeof(ssh2_code));
1324
1325     // reset SP
1326     pl[1] = pl[3] = HWSWAP(0x603f800);
1327     // start
1328     pl[0] = pl[2] = HWSWAP(0x204);
1329   }
1330 }
1331
1332 #define MAP_MEMORY(m) ((uptr)(m) >> 1)
1333 #define MAP_HANDLER(h) ( ((uptr)(h) >> 1) | ((uptr)1 << (sizeof(uptr) * 8 - 1)) )
1334
1335 static sh2_memmap sh2_read8_map[0x20], sh2_read16_map[0x20];
1336 // for writes we are using handlers only
1337 static sh2_write_handler *sh2_write8_map[0x80], *sh2_write16_map[0x80];
1338
1339 void Pico32xSwapDRAM(int b)
1340 {
1341   cpu68k_map_set(m68k_read8_map,   0x840000, 0x85ffff, Pico32xMem->dram[b], 0);
1342   cpu68k_map_set(m68k_read16_map,  0x840000, 0x85ffff, Pico32xMem->dram[b], 0);
1343   cpu68k_map_set(m68k_write8_map,  0x840000, 0x85ffff, Pico32xMem->dram[b], 0);
1344   cpu68k_map_set(m68k_write16_map, 0x840000, 0x85ffff, Pico32xMem->dram[b], 0);
1345
1346   // SH2
1347   sh2_read8_map[2].addr   = sh2_read8_map[6].addr   =
1348   sh2_read16_map[2].addr  = sh2_read16_map[6].addr  = MAP_MEMORY(Pico32xMem->dram[b]);
1349
1350   sh2_write8_map[0x04/2]  = sh2_write8_map[0x24/2]  = b ? sh2_write8_dram1 : sh2_write8_dram0;
1351   sh2_write16_map[0x04/2] = sh2_write16_map[0x24/2] = b ? sh2_write16_dram1 : sh2_write16_dram0;
1352 }
1353
1354 void PicoMemSetup32x(void)
1355 {
1356   unsigned int rs;
1357   int i;
1358
1359   Pico32xMem = plat_mmap(0x06000000, sizeof(*Pico32xMem), 0, 0);
1360   if (Pico32xMem == NULL) {
1361     elprintf(EL_STATUS, "OOM");
1362     return;
1363   }
1364
1365   get_bios();
1366
1367   // cartridge area becomes unmapped
1368   // XXX: we take the easy way and don't unmap ROM,
1369   // so that we can avoid handling the RV bit.
1370   // m68k_map_unmap(0x000000, 0x3fffff);
1371
1372   // MD ROM area
1373   rs = sizeof(Pico32xMem->m68k_rom_bank);
1374   cpu68k_map_set(m68k_read8_map,   0x000000, rs - 1, Pico32xMem->m68k_rom_bank, 0);
1375   cpu68k_map_set(m68k_read16_map,  0x000000, rs - 1, Pico32xMem->m68k_rom_bank, 0);
1376   cpu68k_map_set(m68k_write8_map,  0x000000, rs - 1, PicoWrite8_hint, 1); // TODO verify
1377   cpu68k_map_set(m68k_write16_map, 0x000000, rs - 1, PicoWrite16_hint, 1);
1378
1379   // 32X ROM (unbanked, XXX: consider mirroring?)
1380   rs = (Pico.romsize + M68K_BANK_MASK) & ~M68K_BANK_MASK;
1381   if (rs > 0x80000)
1382     rs = 0x80000;
1383   cpu68k_map_set(m68k_read8_map,   0x880000, 0x880000 + rs - 1, Pico.rom, 0);
1384   cpu68k_map_set(m68k_read16_map,  0x880000, 0x880000 + rs - 1, Pico.rom, 0);
1385 #ifdef EMU_F68K
1386   // setup FAME fetchmap
1387   PicoCpuFM68k.Fetch[0] = (unsigned long)Pico32xMem->m68k_rom;
1388   for (rs = 0x88; rs < 0x90; rs++)
1389     PicoCpuFM68k.Fetch[rs] = (unsigned long)Pico.rom - 0x880000;
1390 #endif
1391
1392   // 32X ROM (banked)
1393   bank_switch(0);
1394
1395   // SYS regs
1396   cpu68k_map_set(m68k_read8_map,   0xa10000, 0xa1ffff, PicoRead8_32x_on, 1);
1397   cpu68k_map_set(m68k_read16_map,  0xa10000, 0xa1ffff, PicoRead16_32x_on, 1);
1398   cpu68k_map_set(m68k_write8_map,  0xa10000, 0xa1ffff, PicoWrite8_32x_on, 1);
1399   cpu68k_map_set(m68k_write16_map, 0xa10000, 0xa1ffff, PicoWrite16_32x_on, 1);
1400
1401   // SH2 maps: A31,A30,A29,CS1,CS0
1402   // all unmapped by default
1403   for (i = 0; i < ARRAY_SIZE(sh2_read8_map); i++) {
1404     sh2_read8_map[i].addr   = MAP_HANDLER(sh2_read8_unmapped);
1405     sh2_read16_map[i].addr  = MAP_HANDLER(sh2_read16_unmapped);
1406   }
1407
1408   for (i = 0; i < ARRAY_SIZE(sh2_write8_map); i++) {
1409     sh2_write8_map[i]       = sh2_write8_unmapped;
1410     sh2_write16_map[i]      = sh2_write16_unmapped;
1411   }
1412
1413   // "purge area"
1414   for (i = 0x40; i <= 0x5f; i++) {
1415     sh2_write8_map[i >> 1]  =
1416     sh2_write16_map[i >> 1] = sh2_write_ignore;
1417   }
1418
1419   // CS0
1420   sh2_read8_map[0].addr   = sh2_read8_map[4].addr   = MAP_HANDLER(sh2_read8_cs0);
1421   sh2_read16_map[0].addr  = sh2_read16_map[4].addr  = MAP_HANDLER(sh2_read16_cs0);
1422   sh2_write8_map[0x00/2]  = sh2_write8_map[0x20/2]  = sh2_write8_cs0;
1423   sh2_write16_map[0x00/2] = sh2_write16_map[0x20/2] = sh2_write16_cs0;
1424   // CS1 - ROM
1425   sh2_read8_map[1].addr   = sh2_read8_map[5].addr   =
1426   sh2_read16_map[1].addr  = sh2_read16_map[5].addr  = MAP_MEMORY(Pico.rom);
1427   sh2_read8_map[1].mask   = sh2_read8_map[5].mask   =
1428   sh2_read16_map[1].mask  = sh2_read16_map[5].mask  = 0x3fffff; // FIXME
1429   // CS2 - DRAM - done by Pico32xSwapDRAM()
1430   sh2_read8_map[2].mask   = sh2_read8_map[6].mask   =
1431   sh2_read16_map[2].mask  = sh2_read16_map[6].mask  = 0x01ffff;
1432   // CS3 - SDRAM
1433   sh2_read8_map[3].addr   = sh2_read8_map[7].addr   =
1434   sh2_read16_map[3].addr  = sh2_read16_map[7].addr  = MAP_MEMORY(Pico32xMem->sdram);
1435   sh2_write8_map[0x06/2]  = sh2_write8_map[0x26/2]  = sh2_write8_sdram;
1436   sh2_write16_map[0x06/2] = sh2_write16_map[0x26/2] = sh2_write16_sdram;
1437   sh2_read8_map[3].mask   = sh2_read8_map[7].mask   =
1438   sh2_read16_map[3].mask  = sh2_read16_map[7].mask  = 0x03ffff;
1439   // SH2 data array
1440   sh2_read8_map[0x18].addr   = MAP_HANDLER(sh2_read8_da);
1441   sh2_read16_map[0x18].addr  = MAP_HANDLER(sh2_read16_da);
1442   sh2_write8_map[0xc0/2]     = sh2_write8_da;
1443   sh2_write16_map[0xc0/2]    = sh2_write16_da;
1444   // SH2 IO
1445   sh2_read8_map[0x1f].addr   = MAP_HANDLER(sh2_peripheral_read8);
1446   sh2_read16_map[0x1f].addr  = MAP_HANDLER(sh2_peripheral_read16);
1447   sh2_write8_map[0xff/2]     = sh2_peripheral_write8;
1448   sh2_write16_map[0xff/2]    = sh2_peripheral_write16;
1449
1450   // map DRAM area, both 68k and SH2
1451   Pico32xSwapDRAM(1);
1452
1453   msh2.read8_map   = ssh2.read8_map   = sh2_read8_map;
1454   msh2.read16_map  = ssh2.read16_map  = sh2_read16_map;
1455   msh2.write8_tab  = ssh2.write8_tab  = (const void **)(void *)sh2_write8_map;
1456   msh2.write16_tab = ssh2.write16_tab = (const void **)(void *)sh2_write16_map;
1457
1458   sh2_drc_mem_setup(&msh2);
1459   sh2_drc_mem_setup(&ssh2);
1460 }
1461
1462 void Pico32xMemStateLoaded(void)
1463 {
1464   bank_switch(Pico32x.regs[4 / 2]);
1465   Pico32xSwapDRAM((Pico32x.vdp_regs[0x0a / 2] & P32XV_FS) ^ P32XV_FS);
1466   memset(Pico32xMem->pwm, 0, sizeof(Pico32xMem->pwm));
1467   Pico32x.dirty_pal = 1;
1468
1469   Pico32x.emu_flags &= ~(P32XF_68KCPOLL | P32XF_68KVPOLL);
1470   memset(&m68k_poll, 0, sizeof(m68k_poll));
1471   msh2.state = 0;
1472   msh2.poll_addr = msh2.poll_cycles = msh2.poll_cnt = 0;
1473   ssh2.state = 0;
1474   ssh2.poll_addr = ssh2.poll_cycles = ssh2.poll_cnt = 0;
1475
1476   sh2_drc_flush_all();
1477 }
1478
1479 // vim:shiftwidth=2:ts=2:expandtab