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