32x: memhandler improvements
[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, SH2 *sh2)
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]
443         | Pico32x.sh2irq_mask[sh2->is_slave];
444     case 0x04: // H count (often as comm too)
445       sh2_poll_detect(sh2, a, SH2_STATE_CPOLL);
446       sh2s_sync_on_read(sh2);
447       return Pico32x.sh2_regs[4 / 2];
448     case 0x10: // DREQ len
449       return r[a / 2];
450   }
451
452   // DREQ src, dst
453   if ((a & 0x38) == 0x08)
454     return r[a / 2];
455   // comm port
456   if ((a & 0x30) == 0x20) {
457     int comreg = 1 << (a & 0x0f) / 2;
458     if (Pico32x.comm_dirty_68k & comreg)
459       Pico32x.comm_dirty_68k &= ~comreg;
460     else
461       sh2_poll_detect(sh2, a, SH2_STATE_CPOLL);
462     sh2s_sync_on_read(sh2);
463     return r[a / 2];
464   }
465   if ((a & 0x30) == 0x30) {
466     return p32x_pwm_read16(a, sh2, sh2_cycles_done_m68k(sh2));
467   }
468
469   return 0;
470 }
471
472 static void p32x_sh2reg_write8(u32 a, u32 d, SH2 *sh2)
473 {
474   a &= 0xff;
475
476   sh2->poll_addr = 0;
477
478   switch (a) {
479     case 0: // FM
480       Pico32x.regs[0] &= ~P32XS_FM;
481       Pico32x.regs[0] |= (d << 8) & P32XS_FM;
482       return;
483     case 1: // HEN/irq masks
484       if ((d ^ Pico32x.sh2_regs[0]) & 0x80)
485         elprintf(EL_ANOMALY|EL_32X, "HEN");
486       Pico32x.sh2irq_mask[sh2->is_slave] = d & 0x8f;
487       Pico32x.sh2_regs[0] &= ~0x80;
488       Pico32x.sh2_regs[0] |= d & 0x80;
489       if (d & 1)
490         p32x_pwm_schedule_sh2(sh2);
491       p32x_update_irls(sh2, 0);
492       return;
493     case 5: // H count
494       d &= 0xff;
495       if (Pico32x.sh2_regs[4 / 2] != d) {
496         Pico32x.sh2_regs[4 / 2] = d;
497         p32x_sh2_poll_event(sh2->other_sh2, SH2_STATE_CPOLL,
498           sh2_cycles_done_m68k(sh2));
499         sh2_end_run(sh2, 4);
500       }
501       return;
502   }
503
504   if ((a & 0x30) == 0x20) {
505     u8 *r8 = (u8 *)Pico32x.regs;
506     int comreg;
507     if (r8[a ^ 1] == d)
508       return;
509
510     r8[a ^ 1] = d;
511     p32x_m68k_poll_event(P32XF_68KCPOLL);
512     p32x_sh2_poll_event(sh2->other_sh2, SH2_STATE_CPOLL,
513       sh2_cycles_done_m68k(sh2));
514     comreg = 1 << (a & 0x0f) / 2;
515     Pico32x.comm_dirty_sh2 |= comreg;
516     return;
517   }
518 }
519
520 static void p32x_sh2reg_write16(u32 a, u32 d, SH2 *sh2)
521 {
522   a &= 0xfe;
523
524   sh2->poll_addr = 0;
525
526   // comm
527   if ((a & 0x30) == 0x20) {
528     int comreg;
529     if (Pico32x.regs[a / 2] == d)
530       return;
531
532     Pico32x.regs[a / 2] = d;
533     p32x_m68k_poll_event(P32XF_68KCPOLL);
534     p32x_sh2_poll_event(sh2->other_sh2, SH2_STATE_CPOLL,
535       sh2_cycles_done_m68k(sh2));
536     comreg = 1 << (a & 0x0f) / 2;
537     Pico32x.comm_dirty_sh2 |= comreg;
538     return;
539   }
540   // PWM
541   else if ((a & 0x30) == 0x30) {
542     p32x_pwm_write16(a, d, sh2, sh2_cycles_done_m68k(sh2));
543     return;
544   }
545
546   switch (a) {
547     case 0: // FM
548       Pico32x.regs[0] &= ~P32XS_FM;
549       Pico32x.regs[0] |= d & P32XS_FM;
550       break;
551     case 0x14: Pico32x.sh2irqs &= ~P32XI_VRES; goto irls;
552     case 0x16: Pico32x.sh2irqs &= ~P32XI_VINT; goto irls;
553     case 0x18: Pico32x.sh2irqs &= ~P32XI_HINT; goto irls;
554     case 0x1a: Pico32x.sh2irqi[sh2->is_slave] &= ~P32XI_CMD; goto irls;
555     case 0x1c:
556       Pico32x.sh2irqs &= ~P32XI_PWM;
557       p32x_pwm_schedule_sh2(sh2);
558       goto irls;
559   }
560
561   p32x_sh2reg_write8(a | 1, d, sh2);
562   return;
563
564 irls:
565   p32x_update_irls(sh2, 0);
566 }
567
568 // ------------------------------------------------------------------
569 // 32x 68k handlers
570
571 // after ADEN
572 static u32 PicoRead8_32x_on(u32 a)
573 {
574   u32 d = 0;
575   if ((a & 0xffc0) == 0x5100) { // a15100
576     d = p32x_reg_read16(a);
577     goto out_16to8;
578   }
579
580   if ((a & 0xfc00) != 0x5000)
581     return PicoRead8_io(a);
582
583   if ((a & 0xfff0) == 0x5180) { // a15180
584     d = p32x_vdp_read16(a);
585     goto out_16to8;
586   }
587
588   if ((a & 0xfe00) == 0x5200) { // a15200
589     d = Pico32xMem->pal[(a & 0x1ff) / 2];
590     goto out_16to8;
591   }
592
593   if ((a & 0xfffc) == 0x30ec) { // a130ec
594     d = str_mars[a & 3];
595     goto out;
596   }
597
598   elprintf(EL_UIO, "m68k unmapped r8  [%06x] @%06x", a, SekPc);
599   return d;
600
601 out_16to8:
602   if (a & 1)
603     d &= 0xff;
604   else
605     d >>= 8;
606
607 out:
608   elprintf(EL_32X, "m68k 32x r8  [%06x]   %02x @%06x", a, d, SekPc);
609   return d;
610 }
611
612 static u32 PicoRead16_32x_on(u32 a)
613 {
614   u32 d = 0;
615   if ((a & 0xffc0) == 0x5100) { // a15100
616     d = p32x_reg_read16(a);
617     goto out;
618   }
619
620   if ((a & 0xfc00) != 0x5000)
621     return PicoRead16_io(a);
622
623   if ((a & 0xfff0) == 0x5180) { // a15180
624     d = p32x_vdp_read16(a);
625     goto out;
626   }
627
628   if ((a & 0xfe00) == 0x5200) { // a15200
629     d = Pico32xMem->pal[(a & 0x1ff) / 2];
630     goto out;
631   }
632
633   if ((a & 0xfffc) == 0x30ec) { // a130ec
634     d = !(a & 2) ? ('M'<<8)|'A' : ('R'<<8)|'S';
635     goto out;
636   }
637
638   elprintf(EL_UIO, "m68k unmapped r16 [%06x] @%06x", a, SekPc);
639   return d;
640
641 out:
642   elprintf(EL_32X, "m68k 32x r16 [%06x] %04x @%06x", a, d, SekPc);
643   return d;
644 }
645
646 static void PicoWrite8_32x_on(u32 a, u32 d)
647 {
648   if ((a & 0xfc00) == 0x5000)
649     elprintf(EL_32X, "m68k 32x w8  [%06x]   %02x @%06x", a, d & 0xff, SekPc);
650
651   if ((a & 0xffc0) == 0x5100) { // a15100
652     p32x_reg_write8(a, d);
653     return;
654   }
655
656   if ((a & 0xfc00) != 0x5000) {
657     PicoWrite8_io(a, d);
658     return;
659   }
660
661   if (!(Pico32x.regs[0] & P32XS_FM)) {
662     if ((a & 0xfff0) == 0x5180) { // a15180
663       p32x_vdp_write8(a, d);
664       return;
665     }
666
667     // TODO: verify
668     if ((a & 0xfe00) == 0x5200) { // a15200
669       elprintf(EL_32X|EL_ANOMALY, "m68k 32x PAL w8  [%06x]   %02x @%06x", a, d & 0xff, SekPc);
670       ((u8 *)Pico32xMem->pal)[(a & 0x1ff) ^ 1] = d;
671       Pico32x.dirty_pal = 1;
672       return;
673     }
674   }
675
676   elprintf(EL_UIO, "m68k unmapped w8  [%06x]   %02x @%06x", a, d & 0xff, SekPc);
677 }
678
679 static void PicoWrite16_32x_on(u32 a, u32 d)
680 {
681   if ((a & 0xfc00) == 0x5000)
682     elprintf(EL_32X, "m68k 32x w16 [%06x] %04x @%06x", a, d & 0xffff, SekPc);
683
684   if ((a & 0xffc0) == 0x5100) { // a15100
685     p32x_reg_write16(a, d);
686     return;
687   }
688
689   if ((a & 0xfc00) != 0x5000) {
690     PicoWrite16_io(a, d);
691     return;
692   }
693
694   if (!(Pico32x.regs[0] & P32XS_FM)) {
695     if ((a & 0xfff0) == 0x5180) { // a15180
696       p32x_vdp_write16(a, d, NULL); // FIXME?
697       return;
698     }
699
700     if ((a & 0xfe00) == 0x5200) { // a15200
701       Pico32xMem->pal[(a & 0x1ff) / 2] = d;
702       Pico32x.dirty_pal = 1;
703       return;
704     }
705   }
706
707   elprintf(EL_UIO, "m68k unmapped w16 [%06x] %04x @%06x", a, d & 0xffff, SekPc);
708 }
709
710 // before ADEN
711 u32 PicoRead8_32x(u32 a)
712 {
713   u32 d = 0;
714   if ((a & 0xffc0) == 0x5100) { // a15100
715     // regs are always readable
716     d = ((u8 *)Pico32x.regs)[(a & 0x3f) ^ 1];
717     goto out;
718   }
719
720   if ((a & 0xfffc) == 0x30ec) { // a130ec
721     d = str_mars[a & 3];
722     goto out;
723   }
724
725   elprintf(EL_UIO, "m68k unmapped r8  [%06x] @%06x", a, SekPc);
726   return d;
727
728 out:
729   elprintf(EL_32X, "m68k 32x r8  [%06x]   %02x @%06x", a, d, SekPc);
730   return d;
731 }
732
733 u32 PicoRead16_32x(u32 a)
734 {
735   u32 d = 0;
736   if ((a & 0xffc0) == 0x5100) { // a15100
737     d = Pico32x.regs[(a & 0x3f) / 2];
738     goto out;
739   }
740
741   if ((a & 0xfffc) == 0x30ec) { // a130ec
742     d = !(a & 2) ? ('M'<<8)|'A' : ('R'<<8)|'S';
743     goto out;
744   }
745
746   elprintf(EL_UIO, "m68k unmapped r16 [%06x] @%06x", a, SekPc);
747   return d;
748
749 out:
750   elprintf(EL_32X, "m68k 32x r16 [%06x] %04x @%06x", a, d, SekPc);
751   return d;
752 }
753
754 void PicoWrite8_32x(u32 a, u32 d)
755 {
756   if ((a & 0xffc0) == 0x5100) { // a15100
757     u16 *r = Pico32x.regs;
758
759     elprintf(EL_32X, "m68k 32x w8  [%06x]   %02x @%06x", a, d & 0xff, SekPc);
760     a &= 0x3f;
761     if (a == 1) {
762       if ((d ^ r[0]) & d & P32XS_ADEN) {
763         Pico32xStartup();
764         r[0] &= ~P32XS_nRES; // causes reset if specified by this write
765         r[0] |= P32XS_ADEN;
766         p32x_reg_write8(a, d); // forward for reset processing
767       }
768       return;
769     }
770
771     // allow only COMM for now
772     if ((a & 0x30) == 0x20) {
773       u8 *r8 = (u8 *)r;
774       r8[a ^ 1] = d;
775     }
776     return;
777   }
778
779   elprintf(EL_UIO, "m68k unmapped w8  [%06x]   %02x @%06x", a, d & 0xff, SekPc);
780 }
781
782 void PicoWrite16_32x(u32 a, u32 d)
783 {
784   if ((a & 0xffc0) == 0x5100) { // a15100
785     u16 *r = Pico32x.regs;
786
787     elprintf(EL_UIO, "m68k 32x w16 [%06x] %04x @%06x", a, d & 0xffff, SekPc);
788     a &= 0x3e;
789     if (a == 0) {
790       if ((d ^ r[0]) & d & P32XS_ADEN) {
791         Pico32xStartup();
792         r[0] &= ~P32XS_nRES; // causes reset if specified by this write
793         r[0] |= P32XS_ADEN;
794         p32x_reg_write16(a, d); // forward for reset processing
795       }
796       return;
797     }
798
799     // allow only COMM for now
800     if ((a & 0x30) == 0x20)
801       r[a / 2] = d;
802     return;
803   }
804
805   elprintf(EL_UIO, "m68k unmapped w16 [%06x] %04x @%06x", a, d & 0xffff, SekPc);
806 }
807
808 /* quirk: in both normal and overwrite areas only nonzero values go through */
809 #define sh2_write8_dramN(n) \
810   if ((d & 0xff) != 0) { \
811     u8 *dram = (u8 *)Pico32xMem->dram[n]; \
812     dram[(a & 0x1ffff) ^ 1] = d; \
813   }
814
815 static void m68k_write8_dram0_ow(u32 a, u32 d)
816 {
817   sh2_write8_dramN(0);
818 }
819
820 static void m68k_write8_dram1_ow(u32 a, u32 d)
821 {
822   sh2_write8_dramN(1);
823 }
824
825 #define sh2_write16_dramN(n) \
826   u16 *pd = &Pico32xMem->dram[n][(a & 0x1ffff) / 2]; \
827   if (!(a & 0x20000)) { \
828     *pd = d; \
829     return; \
830   } \
831   /* overwrite */ \
832   if (!(d & 0xff00)) d |= *pd & 0xff00; \
833   if (!(d & 0x00ff)) d |= *pd & 0x00ff; \
834   *pd = d;
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, SH2 *sh2)
902 {
903   elprintf(EL_UIO, "%csh2 unmapped r8  [%08x]       %02x @%06x",
904     sh2->is_slave ? 's' : 'm', a, 0, sh2_pc(sh2));
905   return 0;
906 }
907
908 static u32 sh2_read8_cs0(u32 a, SH2 *sh2)
909 {
910   u32 d = 0;
911
912   // 0x3ff00 is veridied
913   if ((a & 0x3ff00) == 0x4000) {
914     d = p32x_sh2reg_read16(a, sh2);
915     goto out_16to8;
916   }
917
918   if ((a & 0x3ff00) == 0x4100) {
919     d = p32x_vdp_read16(a);
920     sh2_poll_detect(sh2, a, SH2_STATE_VPOLL);
921     goto out_16to8;
922   }
923
924   // TODO: mirroring?
925   if (!sh2->is_slave && a < sizeof(Pico32xMem->sh2_rom_m))
926     return Pico32xMem->sh2_rom_m[a ^ 1];
927   if (sh2->is_slave  && 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, sh2);
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     sh2->is_slave ? 's' : 'm', a, d, sh2_pc(sh2));
945   return d;
946 }
947
948 static u32 sh2_read8_da(u32 a, SH2 *sh2)
949 {
950   return sh2->data_array[(a & 0xfff) ^ 1];
951 }
952
953 // read16
954 static u32 sh2_read16_unmapped(u32 a, SH2 *sh2)
955 {
956   elprintf(EL_UIO, "%csh2 unmapped r16 [%08x]     %04x @%06x",
957     sh2->is_slave ? 's' : 'm', a, 0, sh2_pc(sh2));
958   return 0;
959 }
960
961 static u32 sh2_read16_cs0(u32 a, SH2 *sh2)
962 {
963   u32 d = 0;
964
965   if ((a & 0x3ff00) == 0x4000) {
966     d = p32x_sh2reg_read16(a, sh2);
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(sh2, a, SH2_STATE_VPOLL);
975     goto out;
976   }
977
978   if (!sh2->is_slave && a < sizeof(Pico32xMem->sh2_rom_m))
979     return *(u16 *)(Pico32xMem->sh2_rom_m + a);
980   if (sh2->is_slave  && 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, sh2);
989
990 out:
991   elprintf(EL_32X, "%csh2 r16 [%08x]     %04x @%06x",
992     sh2->is_slave ? 's' : 'm', a, d, sh2_pc(sh2));
993   return d;
994 }
995
996 static u32 sh2_read16_da(u32 a, SH2 *sh2)
997 {
998   return ((u16 *)sh2->data_array)[(a & 0xfff) / 2];
999 }
1000
1001 // writes
1002 static void REGPARM(3) sh2_write_ignore(u32 a, u32 d, SH2 *sh2)
1003 {
1004 }
1005
1006 // write8
1007 static void REGPARM(3) sh2_write8_unmapped(u32 a, u32 d, SH2 *sh2)
1008 {
1009   elprintf(EL_UIO, "%csh2 unmapped w8  [%08x]       %02x @%06x",
1010     sh2->is_slave ? 's' : 'm', a, d & 0xff, sh2_pc(sh2));
1011 }
1012
1013 static void REGPARM(3) sh2_write8_cs0(u32 a, u32 d, SH2 *sh2)
1014 {
1015   elprintf(EL_32X, "%csh2 w8  [%08x]       %02x @%06x",
1016     sh2->is_slave ? 's' : 'm', a, d & 0xff, sh2_pc(sh2));
1017
1018   if (Pico32x.regs[0] & P32XS_FM) {
1019     if ((a & 0x3ff00) == 0x4100) {
1020       sh2->poll_addr = 0;
1021       p32x_vdp_write8(a, d);
1022       return;
1023     }
1024   }
1025
1026   if ((a & 0x3ff00) == 0x4000) {
1027     p32x_sh2reg_write8(a, d, sh2);
1028     return;
1029   }
1030
1031   sh2_write8_unmapped(a, d, sh2);
1032 }
1033
1034 static void REGPARM(3) sh2_write8_dram0(u32 a, u32 d, SH2 *sh2)
1035 {
1036   sh2_write8_dramN(0);
1037 }
1038
1039 static void REGPARM(3) sh2_write8_dram1(u32 a, u32 d, SH2 *sh2)
1040 {
1041   sh2_write8_dramN(1);
1042 }
1043
1044 static void REGPARM(3) sh2_write8_sdram(u32 a, u32 d, SH2 *sh2)
1045 {
1046   u32 a1 = a & 0x3ffff;
1047 #ifdef DRC_SH2
1048   int t = Pico32xMem->drcblk_ram[a1 >> SH2_DRCBLK_RAM_SHIFT];
1049   if (t)
1050     sh2_drc_wcheck_ram(a, t, sh2->is_slave);
1051 #endif
1052   Pico32xMem->sdram[a1 ^ 1] = d;
1053 }
1054
1055 static void REGPARM(3) sh2_write8_da(u32 a, u32 d, SH2 *sh2)
1056 {
1057   u32 a1 = a & 0xfff;
1058 #ifdef DRC_SH2
1059   int id = sh2->is_slave;
1060   int t = Pico32xMem->drcblk_da[id][a1 >> SH2_DRCBLK_DA_SHIFT];
1061   if (t)
1062     sh2_drc_wcheck_da(a, t, id);
1063 #endif
1064   sh2->data_array[a1 ^ 1] = d;
1065 }
1066
1067 // write16
1068 static void REGPARM(3) sh2_write16_unmapped(u32 a, u32 d, SH2 *sh2)
1069 {
1070   elprintf(EL_UIO, "%csh2 unmapped w16 [%08x]     %04x @%06x",
1071     sh2->is_slave ? 's' : 'm', a, d & 0xffff, sh2_pc(sh2));
1072 }
1073
1074 static void REGPARM(3) sh2_write16_cs0(u32 a, u32 d, SH2 *sh2)
1075 {
1076   if (((EL_LOGMASK & EL_PWM) || (a & 0x30) != 0x30)) // hide PWM
1077     elprintf(EL_32X, "%csh2 w16 [%08x]     %04x @%06x",
1078       sh2->is_slave ? 's' : 'm', a, d & 0xffff, sh2_pc(sh2));
1079
1080   if (Pico32x.regs[0] & P32XS_FM) {
1081     if ((a & 0x3ff00) == 0x4100) {
1082       sh2->poll_addr = 0;
1083       p32x_vdp_write16(a, d, sh2);
1084       return;
1085     }
1086
1087     if ((a & 0x3fe00) == 0x4200) {
1088       Pico32xMem->pal[(a & 0x1ff) / 2] = d;
1089       Pico32x.dirty_pal = 1;
1090       return;
1091     }
1092   }
1093
1094   if ((a & 0x3ff00) == 0x4000) {
1095     p32x_sh2reg_write16(a, d, sh2);
1096     return;
1097   }
1098
1099   sh2_write16_unmapped(a, d, sh2);
1100 }
1101
1102 static void REGPARM(3) sh2_write16_dram0(u32 a, u32 d, SH2 *sh2)
1103 {
1104   sh2_write16_dramN(0);
1105 }
1106
1107 static void REGPARM(3) sh2_write16_dram1(u32 a, u32 d, SH2 *sh2)
1108 {
1109   sh2_write16_dramN(1);
1110 }
1111
1112 static void REGPARM(3) sh2_write16_sdram(u32 a, u32 d, SH2 *sh2)
1113 {
1114   u32 a1 = a & 0x3ffff;
1115 #ifdef DRC_SH2
1116   int t = Pico32xMem->drcblk_ram[a1 >> SH2_DRCBLK_RAM_SHIFT];
1117   if (t)
1118     sh2_drc_wcheck_ram(a, t, sh2->is_slave);
1119 #endif
1120   ((u16 *)Pico32xMem->sdram)[a1 / 2] = d;
1121 }
1122
1123 static void REGPARM(3) sh2_write16_da(u32 a, u32 d, SH2 *sh2)
1124 {
1125   u32 a1 = a & 0xfff;
1126 #ifdef DRC_SH2
1127   int id = sh2->is_slave;
1128   int t = Pico32xMem->drcblk_da[id][a1 >> SH2_DRCBLK_DA_SHIFT];
1129   if (t)
1130     sh2_drc_wcheck_da(a, t, id);
1131 #endif
1132   ((u16 *)sh2->data_array)[a1 / 2] = d;
1133 }
1134
1135
1136 typedef u32 (sh2_read_handler)(u32 a, SH2 *sh2);
1137 typedef void REGPARM(3) (sh2_write_handler)(u32 a, u32 d, SH2 *sh2);
1138
1139 #define SH2MAP_ADDR2OFFS_R(a) \
1140   ((u32)(a) >> SH2_READ_SHIFT)
1141
1142 #define SH2MAP_ADDR2OFFS_W(a) \
1143   ((u32)(a) >> SH2_WRITE_SHIFT)
1144
1145 u32 REGPARM(2) p32x_sh2_read8(u32 a, SH2 *sh2)
1146 {
1147   const sh2_memmap *sh2_map = sh2->read8_map;
1148   uptr p;
1149
1150   sh2_map += SH2MAP_ADDR2OFFS_R(a);
1151   p = sh2_map->addr;
1152   if (map_flag_set(p))
1153     return ((sh2_read_handler *)(p << 1))(a, sh2);
1154   else
1155     return *(u8 *)((p << 1) + ((a & sh2_map->mask) ^ 1));
1156 }
1157
1158 u32 REGPARM(2) p32x_sh2_read16(u32 a, SH2 *sh2)
1159 {
1160   const sh2_memmap *sh2_map = sh2->read16_map;
1161   uptr p;
1162
1163   sh2_map += SH2MAP_ADDR2OFFS_R(a);
1164   p = sh2_map->addr;
1165   if (map_flag_set(p))
1166     return ((sh2_read_handler *)(p << 1))(a, sh2);
1167   else
1168     return *(u16 *)((p << 1) + ((a & sh2_map->mask) & ~1));
1169 }
1170
1171 u32 REGPARM(2) p32x_sh2_read32(u32 a, SH2 *sh2)
1172 {
1173   const sh2_memmap *sh2_map = sh2->read16_map;
1174   sh2_read_handler *handler;
1175   u32 offs;
1176   uptr p;
1177
1178   offs = SH2MAP_ADDR2OFFS_R(a);
1179   sh2_map += offs;
1180   p = sh2_map->addr;
1181   if (!map_flag_set(p)) {
1182     // XXX: maybe 32bit access instead with ror?
1183     u16 *pd = (u16 *)((p << 1) + ((a & sh2_map->mask) & ~1));
1184     return (pd[0] << 16) | pd[1];
1185   }
1186
1187   if (offs == 0x1f)
1188     return sh2_peripheral_read32(a, sh2);
1189
1190   handler = (sh2_read_handler *)(p << 1);
1191   return (handler(a, sh2) << 16) | handler(a + 2, sh2);
1192 }
1193
1194 void REGPARM(3) p32x_sh2_write8(u32 a, u32 d, SH2 *sh2)
1195 {
1196   const void **sh2_wmap = sh2->write8_tab;
1197   sh2_write_handler *wh;
1198
1199   wh = sh2_wmap[SH2MAP_ADDR2OFFS_W(a)];
1200   wh(a, d, sh2);
1201 }
1202
1203 void REGPARM(3) p32x_sh2_write16(u32 a, u32 d, SH2 *sh2)
1204 {
1205   const void **sh2_wmap = sh2->write16_tab;
1206   sh2_write_handler *wh;
1207
1208   wh = sh2_wmap[SH2MAP_ADDR2OFFS_W(a)];
1209   wh(a, d, sh2);
1210 }
1211
1212 void REGPARM(3) p32x_sh2_write32(u32 a, u32 d, SH2 *sh2)
1213 {
1214   const void **sh2_wmap = sh2->write16_tab;
1215   sh2_write_handler *wh;
1216   u32 offs;
1217
1218   offs = SH2MAP_ADDR2OFFS_W(a);
1219
1220   if (offs == SH2MAP_ADDR2OFFS_W(0xffffc000)) {
1221     sh2_peripheral_write32(a, d, sh2);
1222     return;
1223   }
1224
1225   wh = sh2_wmap[offs];
1226   wh(a, d >> 16, sh2);
1227   wh(a + 2, d, sh2);
1228 }
1229
1230 // -----------------------------------------------------------------
1231
1232 static const u16 msh2_code[] = {
1233   // trap instructions
1234   0xaffe, // bra <self>
1235   0x0009, // nop
1236   // have to wait a bit until m68k initial program finishes clearing stuff
1237   // to avoid races with game SH2 code, like in Tempo
1238   0xd004, // mov.l   @(_m_ok,pc), r0
1239   0xd105, // mov.l   @(_cnt,pc), r1
1240   0xd205, // mov.l   @(_start,pc), r2
1241   0x71ff, // add     #-1, r1
1242   0x4115, // cmp/pl  r1
1243   0x89fc, // bt      -2
1244   0xc208, // mov.l   r0, @(h'20,gbr)
1245   0x6822, // mov.l   @r2, r8
1246   0x482b, // jmp     @r8
1247   0x0009, // nop
1248   ('M'<<8)|'_', ('O'<<8)|'K',
1249   0x0001, 0x0000,
1250   0x2200, 0x03e0  // master start pointer in ROM
1251 };
1252
1253 static const u16 ssh2_code[] = {
1254   0xaffe, // bra <self>
1255   0x0009, // nop
1256   // code to wait for master, in case authentic master BIOS is used
1257   0xd104, // mov.l   @(_m_ok,pc), r1
1258   0xd206, // mov.l   @(_start,pc), r2
1259   0xc608, // mov.l   @(h'20,gbr), r0
1260   0x3100, // cmp/eq  r0, r1
1261   0x8bfc, // bf      #-2
1262   0xd003, // mov.l   @(_s_ok,pc), r0
1263   0xc209, // mov.l   r0, @(h'24,gbr)
1264   0x6822, // mov.l   @r2, r8
1265   0x482b, // jmp     @r8
1266   0x0009, // nop
1267   ('M'<<8)|'_', ('O'<<8)|'K',
1268   ('S'<<8)|'_', ('O'<<8)|'K',
1269   0x2200, 0x03e4  // slave start pointer in ROM
1270 };
1271
1272 #define HWSWAP(x) (((u16)(x) << 16) | ((x) >> 16))
1273 static void get_bios(void)
1274 {
1275   u16 *ps;
1276   u32 *pl;
1277   int i;
1278
1279   // M68K ROM
1280   if (p32x_bios_g != NULL) {
1281     elprintf(EL_STATUS|EL_32X, "32x: using supplied 68k BIOS");
1282     Byteswap(Pico32xMem->m68k_rom, p32x_bios_g, sizeof(Pico32xMem->m68k_rom));
1283   }
1284   else {
1285     // generate 68k ROM
1286     ps = (u16 *)Pico32xMem->m68k_rom;
1287     pl = (u32 *)ps;
1288     for (i = 1; i < 0xc0/4; i++)
1289       pl[i] = HWSWAP(0x880200 + (i - 1) * 6);
1290
1291     // fill with nops
1292     for (i = 0xc0/2; i < 0x100/2; i++)
1293       ps[i] = 0x4e71;
1294
1295 #if 0
1296     ps[0xc0/2] = 0x46fc;
1297     ps[0xc2/2] = 0x2700; // move #0x2700,sr
1298     ps[0xfe/2] = 0x60fe; // jump to self
1299 #else
1300     ps[0xfe/2] = 0x4e75; // rts
1301 #endif
1302   }
1303   // fill remaining m68k_rom page with game ROM
1304   memcpy(Pico32xMem->m68k_rom_bank + sizeof(Pico32xMem->m68k_rom),
1305     Pico.rom + sizeof(Pico32xMem->m68k_rom),
1306     sizeof(Pico32xMem->m68k_rom_bank) - sizeof(Pico32xMem->m68k_rom));
1307
1308   // MSH2
1309   if (p32x_bios_m != NULL) {
1310     elprintf(EL_STATUS|EL_32X, "32x: using supplied master SH2 BIOS");
1311     Byteswap(Pico32xMem->sh2_rom_m, p32x_bios_m, sizeof(Pico32xMem->sh2_rom_m));
1312   }
1313   else {
1314     pl = (u32 *)Pico32xMem->sh2_rom_m;
1315
1316     // fill exception vector table to our trap address
1317     for (i = 0; i < 128; i++)
1318       pl[i] = HWSWAP(0x200);
1319
1320     // startup code
1321     memcpy(Pico32xMem->sh2_rom_m + 0x200, msh2_code, sizeof(msh2_code));
1322
1323     // reset SP
1324     pl[1] = pl[3] = HWSWAP(0x6040000);
1325     // start
1326     pl[0] = pl[2] = HWSWAP(0x204);
1327   }
1328
1329   // SSH2
1330   if (p32x_bios_s != NULL) {
1331     elprintf(EL_STATUS|EL_32X, "32x: using supplied slave SH2 BIOS");
1332     Byteswap(Pico32xMem->sh2_rom_s, p32x_bios_s, sizeof(Pico32xMem->sh2_rom_s));
1333   }
1334   else {
1335     pl = (u32 *)Pico32xMem->sh2_rom_s;
1336
1337     // fill exception vector table to our trap address
1338     for (i = 0; i < 128; i++)
1339       pl[i] = HWSWAP(0x200);
1340
1341     // startup code
1342     memcpy(Pico32xMem->sh2_rom_s + 0x200, ssh2_code, sizeof(ssh2_code));
1343
1344     // reset SP
1345     pl[1] = pl[3] = HWSWAP(0x603f800);
1346     // start
1347     pl[0] = pl[2] = HWSWAP(0x204);
1348   }
1349 }
1350
1351 #define MAP_MEMORY(m) ((uptr)(m) >> 1)
1352 #define MAP_HANDLER(h) ( ((uptr)(h) >> 1) | ((uptr)1 << (sizeof(uptr) * 8 - 1)) )
1353
1354 static sh2_memmap sh2_read8_map[0x80], sh2_read16_map[0x80];
1355 // for writes we are using handlers only
1356 static sh2_write_handler *sh2_write8_map[0x80], *sh2_write16_map[0x80];
1357
1358 void Pico32xSwapDRAM(int b)
1359 {
1360   cpu68k_map_set(m68k_read8_map,   0x840000, 0x85ffff, Pico32xMem->dram[b], 0);
1361   cpu68k_map_set(m68k_read16_map,  0x840000, 0x85ffff, Pico32xMem->dram[b], 0);
1362   cpu68k_map_set(m68k_read8_map,   0x860000, 0x87ffff, Pico32xMem->dram[b], 0);
1363   cpu68k_map_set(m68k_read16_map,  0x860000, 0x87ffff, Pico32xMem->dram[b], 0);
1364   cpu68k_map_set(m68k_write8_map,  0x840000, 0x87ffff,
1365                  b ? m68k_write8_dram1_ow : m68k_write8_dram0_ow, 1);
1366   cpu68k_map_set(m68k_write16_map, 0x840000, 0x87ffff,
1367                  b ? m68k_write16_dram1_ow : m68k_write16_dram0_ow, 1);
1368
1369   // SH2
1370   sh2_read8_map[0x04/2].addr  = sh2_read8_map[0x24/2].addr  =
1371   sh2_read16_map[0x04/2].addr = sh2_read16_map[0x24/2].addr = MAP_MEMORY(Pico32xMem->dram[b]);
1372
1373   sh2_write8_map[0x04/2]  = sh2_write8_map[0x24/2]  = b ? sh2_write8_dram1 : sh2_write8_dram0;
1374   sh2_write16_map[0x04/2] = sh2_write16_map[0x24/2] = b ? sh2_write16_dram1 : sh2_write16_dram0;
1375 }
1376
1377 void PicoMemSetup32x(void)
1378 {
1379   unsigned int rs;
1380   int i;
1381
1382   Pico32xMem = plat_mmap(0x06000000, sizeof(*Pico32xMem), 0, 0);
1383   if (Pico32xMem == NULL) {
1384     elprintf(EL_STATUS, "OOM");
1385     return;
1386   }
1387
1388   get_bios();
1389
1390   // cartridge area becomes unmapped
1391   // XXX: we take the easy way and don't unmap ROM,
1392   // so that we can avoid handling the RV bit.
1393   // m68k_map_unmap(0x000000, 0x3fffff);
1394
1395   // MD ROM area
1396   rs = sizeof(Pico32xMem->m68k_rom_bank);
1397   cpu68k_map_set(m68k_read8_map,   0x000000, rs - 1, Pico32xMem->m68k_rom_bank, 0);
1398   cpu68k_map_set(m68k_read16_map,  0x000000, rs - 1, Pico32xMem->m68k_rom_bank, 0);
1399   cpu68k_map_set(m68k_write8_map,  0x000000, rs - 1, PicoWrite8_hint, 1); // TODO verify
1400   cpu68k_map_set(m68k_write16_map, 0x000000, rs - 1, PicoWrite16_hint, 1);
1401
1402   // 32X ROM (unbanked, XXX: consider mirroring?)
1403   rs = (Pico.romsize + M68K_BANK_MASK) & ~M68K_BANK_MASK;
1404   if (rs > 0x80000)
1405     rs = 0x80000;
1406   cpu68k_map_set(m68k_read8_map,   0x880000, 0x880000 + rs - 1, Pico.rom, 0);
1407   cpu68k_map_set(m68k_read16_map,  0x880000, 0x880000 + rs - 1, Pico.rom, 0);
1408 #ifdef EMU_F68K
1409   // setup FAME fetchmap
1410   PicoCpuFM68k.Fetch[0] = (unsigned long)Pico32xMem->m68k_rom;
1411   for (rs = 0x88; rs < 0x90; rs++)
1412     PicoCpuFM68k.Fetch[rs] = (unsigned long)Pico.rom - 0x880000;
1413 #endif
1414
1415   // 32X ROM (banked)
1416   bank_switch(0);
1417
1418   // SYS regs
1419   cpu68k_map_set(m68k_read8_map,   0xa10000, 0xa1ffff, PicoRead8_32x_on, 1);
1420   cpu68k_map_set(m68k_read16_map,  0xa10000, 0xa1ffff, PicoRead16_32x_on, 1);
1421   cpu68k_map_set(m68k_write8_map,  0xa10000, 0xa1ffff, PicoWrite8_32x_on, 1);
1422   cpu68k_map_set(m68k_write16_map, 0xa10000, 0xa1ffff, PicoWrite16_32x_on, 1);
1423
1424   // SH2 maps: A31,A30,A29,CS1,CS0
1425   // all unmapped by default
1426   for (i = 0; i < ARRAY_SIZE(sh2_read8_map); i++) {
1427     sh2_read8_map[i].addr   = MAP_HANDLER(sh2_read8_unmapped);
1428     sh2_read16_map[i].addr  = MAP_HANDLER(sh2_read16_unmapped);
1429   }
1430
1431   for (i = 0; i < ARRAY_SIZE(sh2_write8_map); i++) {
1432     sh2_write8_map[i]       = sh2_write8_unmapped;
1433     sh2_write16_map[i]      = sh2_write16_unmapped;
1434   }
1435
1436   // "purge area"
1437   for (i = 0x40; i <= 0x5f; i++) {
1438     sh2_write8_map[i >> 1]  =
1439     sh2_write16_map[i >> 1] = sh2_write_ignore;
1440   }
1441
1442   // CS0
1443   sh2_read8_map[0x00/2].addr  = sh2_read8_map[0x20/2].addr  = MAP_HANDLER(sh2_read8_cs0);
1444   sh2_read16_map[0x00/2].addr = sh2_read16_map[0x20/2].addr = MAP_HANDLER(sh2_read16_cs0);
1445   sh2_write8_map[0x00/2]  = sh2_write8_map[0x20/2]  = sh2_write8_cs0;
1446   sh2_write16_map[0x00/2] = sh2_write16_map[0x20/2] = sh2_write16_cs0;
1447   // CS1 - ROM
1448   sh2_read8_map[0x02/2].addr  = sh2_read8_map[0x22/2].addr  =
1449   sh2_read16_map[0x02/2].addr = sh2_read16_map[0x22/2].addr = MAP_MEMORY(Pico.rom);
1450   sh2_read8_map[0x02/2].mask  = sh2_read8_map[0x22/2].mask  =
1451   sh2_read16_map[0x02/2].mask = sh2_read16_map[0x22/2].mask = 0x3fffff; // FIXME
1452   // CS2 - DRAM - done by Pico32xSwapDRAM()
1453   sh2_read8_map[0x04/2].mask  = sh2_read8_map[0x24/2].mask  =
1454   sh2_read16_map[0x04/2].mask = sh2_read16_map[0x24/2].mask = 0x01ffff;
1455   // CS3 - SDRAM
1456   sh2_read8_map[0x06/2].addr   = sh2_read8_map[0x26/2].addr   =
1457   sh2_read16_map[0x06/2].addr  = sh2_read16_map[0x26/2].addr  = MAP_MEMORY(Pico32xMem->sdram);
1458   sh2_write8_map[0x06/2]       = sh2_write8_map[0x26/2]       = sh2_write8_sdram;
1459   sh2_write16_map[0x06/2]      = sh2_write16_map[0x26/2]      = sh2_write16_sdram;
1460   sh2_read8_map[0x06/2].mask   = sh2_read8_map[0x26/2].mask   =
1461   sh2_read16_map[0x06/2].mask  = sh2_read16_map[0x26/2].mask  = 0x03ffff;
1462   // SH2 data array
1463   sh2_read8_map[0xc0/2].addr  = MAP_HANDLER(sh2_read8_da);
1464   sh2_read16_map[0xc0/2].addr = MAP_HANDLER(sh2_read16_da);
1465   sh2_write8_map[0xc0/2]      = sh2_write8_da;
1466   sh2_write16_map[0xc0/2]     = sh2_write16_da;
1467   // SH2 IO
1468   sh2_read8_map[0xff/2].addr  = MAP_HANDLER(sh2_peripheral_read8);
1469   sh2_read16_map[0xff/2].addr = MAP_HANDLER(sh2_peripheral_read16);
1470   sh2_write8_map[0xff/2]      = sh2_peripheral_write8;
1471   sh2_write16_map[0xff/2]     = sh2_peripheral_write16;
1472
1473   // map DRAM area, both 68k and SH2
1474   Pico32xSwapDRAM(1);
1475
1476   msh2.read8_map   = ssh2.read8_map   = sh2_read8_map;
1477   msh2.read16_map  = ssh2.read16_map  = sh2_read16_map;
1478   msh2.write8_tab  = ssh2.write8_tab  = (const void **)(void *)sh2_write8_map;
1479   msh2.write16_tab = ssh2.write16_tab = (const void **)(void *)sh2_write16_map;
1480
1481   sh2_drc_mem_setup(&msh2);
1482   sh2_drc_mem_setup(&ssh2);
1483 }
1484
1485 void Pico32xMemStateLoaded(void)
1486 {
1487   bank_switch(Pico32x.regs[4 / 2]);
1488   Pico32xSwapDRAM((Pico32x.vdp_regs[0x0a / 2] & P32XV_FS) ^ P32XV_FS);
1489   memset(Pico32xMem->pwm, 0, sizeof(Pico32xMem->pwm));
1490   Pico32x.dirty_pal = 1;
1491
1492   Pico32x.emu_flags &= ~(P32XF_68KCPOLL | P32XF_68KVPOLL);
1493   memset(&m68k_poll, 0, sizeof(m68k_poll));
1494   msh2.state = 0;
1495   msh2.poll_addr = msh2.poll_cycles = msh2.poll_cnt = 0;
1496   ssh2.state = 0;
1497   ssh2.poll_addr = ssh2.poll_cycles = ssh2.poll_cnt = 0;
1498
1499   sh2_drc_flush_all();
1500 }
1501
1502 // vim:shiftwidth=2:ts=2:expandtab