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