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