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