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