32x: some timing hacks..
[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(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   sh2_burn_cycles(sh2, 1*2);
1067
1068   // 0x3ff00 is veridied
1069   if ((a & 0x3ff00) == 0x4000) {
1070     d = p32x_sh2reg_read16(a, sh2);
1071     goto out_16to8;
1072   }
1073
1074   if ((a & 0x3ff00) == 0x4100) {
1075     d = p32x_vdp_read16(a);
1076     sh2_poll_detect(sh2, a, SH2_STATE_VPOLL, 7);
1077     goto out_16to8;
1078   }
1079
1080   // TODO: mirroring?
1081   if (!sh2->is_slave && a < sizeof(Pico32xMem->sh2_rom_m))
1082     return Pico32xMem->sh2_rom_m[a ^ 1];
1083   if (sh2->is_slave  && a < sizeof(Pico32xMem->sh2_rom_s))
1084     return Pico32xMem->sh2_rom_s[a ^ 1];
1085
1086   if ((a & 0x3fe00) == 0x4200) {
1087     d = Pico32xMem->pal[(a & 0x1ff) / 2];
1088     goto out_16to8;
1089   }
1090
1091   return sh2_read8_unmapped(a, sh2);
1092
1093 out_16to8:
1094   if (a & 1)
1095     d &= 0xff;
1096   else
1097     d >>= 8;
1098
1099   elprintf(EL_32X, "%csh2 r8  [%08x]       %02x @%06x",
1100     sh2->is_slave ? 's' : 'm', a, d, sh2_pc(sh2));
1101   return d;
1102 }
1103
1104 static u32 sh2_read8_da(u32 a, SH2 *sh2)
1105 {
1106   return sh2->data_array[(a & 0xfff) ^ 1];
1107 }
1108
1109 // read16
1110 static u32 sh2_read16_unmapped(u32 a, SH2 *sh2)
1111 {
1112   elprintf(EL_UIO, "%csh2 unmapped r16 [%08x]     %04x @%06x",
1113     sh2->is_slave ? 's' : 'm', a, 0, sh2_pc(sh2));
1114   return 0;
1115 }
1116
1117 static u32 sh2_read16_cs0(u32 a, SH2 *sh2)
1118 {
1119   u32 d = 0;
1120
1121   sh2_burn_cycles(sh2, 1*2);
1122
1123   if ((a & 0x3ff00) == 0x4000) {
1124     d = p32x_sh2reg_read16(a, sh2);
1125     if (!(EL_LOGMASK & EL_PWM) && (a & 0x30) == 0x30) // hide PWM
1126       return d;
1127     goto out;
1128   }
1129
1130   if ((a & 0x3ff00) == 0x4100) {
1131     d = p32x_vdp_read16(a);
1132     sh2_poll_detect(sh2, a, SH2_STATE_VPOLL, 7);
1133     goto out;
1134   }
1135
1136   if (!sh2->is_slave && a < sizeof(Pico32xMem->sh2_rom_m))
1137     return *(u16 *)(Pico32xMem->sh2_rom_m + a);
1138   if (sh2->is_slave  && a < sizeof(Pico32xMem->sh2_rom_s))
1139     return *(u16 *)(Pico32xMem->sh2_rom_s + a);
1140
1141   if ((a & 0x3fe00) == 0x4200) {
1142     d = Pico32xMem->pal[(a & 0x1ff) / 2];
1143     goto out;
1144   }
1145
1146   return sh2_read16_unmapped(a, sh2);
1147
1148 out:
1149   elprintf(EL_32X, "%csh2 r16 [%08x]     %04x @%06x",
1150     sh2->is_slave ? 's' : 'm', a, d, sh2_pc(sh2));
1151   return d;
1152 }
1153
1154 static u32 sh2_read16_da(u32 a, SH2 *sh2)
1155 {
1156   return ((u16 *)sh2->data_array)[(a & 0xfff) / 2];
1157 }
1158
1159 // writes
1160 static void REGPARM(3) sh2_write_ignore(u32 a, u32 d, SH2 *sh2)
1161 {
1162 }
1163
1164 // write8
1165 static void REGPARM(3) sh2_write8_unmapped(u32 a, u32 d, SH2 *sh2)
1166 {
1167   elprintf(EL_UIO, "%csh2 unmapped w8  [%08x]       %02x @%06x",
1168     sh2->is_slave ? 's' : 'm', a, d & 0xff, sh2_pc(sh2));
1169 }
1170
1171 static void REGPARM(3) sh2_write8_cs0(u32 a, u32 d, SH2 *sh2)
1172 {
1173   elprintf(EL_32X, "%csh2 w8  [%08x]       %02x @%06x",
1174     sh2->is_slave ? 's' : 'm', a, d & 0xff, sh2_pc(sh2));
1175
1176   if (Pico32x.regs[0] & P32XS_FM) {
1177     if ((a & 0x3ff00) == 0x4100) {
1178       sh2->poll_addr = 0;
1179       p32x_vdp_write8(a, d);
1180       return;
1181     }
1182   }
1183
1184   if ((a & 0x3ff00) == 0x4000) {
1185     p32x_sh2reg_write8(a, d, sh2);
1186     return;
1187   }
1188
1189   sh2_write8_unmapped(a, d, sh2);
1190 }
1191
1192 static void REGPARM(3) sh2_write8_dram0(u32 a, u32 d, SH2 *sh2)
1193 {
1194   sh2_write8_dramN(0);
1195 }
1196
1197 static void REGPARM(3) sh2_write8_dram1(u32 a, u32 d, SH2 *sh2)
1198 {
1199   sh2_write8_dramN(1);
1200 }
1201
1202 static void REGPARM(3) sh2_write8_sdram(u32 a, u32 d, SH2 *sh2)
1203 {
1204   u32 a1 = a & 0x3ffff;
1205 #ifdef DRC_SH2
1206   int t = Pico32xMem->drcblk_ram[a1 >> SH2_DRCBLK_RAM_SHIFT];
1207   if (t)
1208     sh2_drc_wcheck_ram(a, t, sh2->is_slave);
1209 #endif
1210   Pico32xMem->sdram[a1 ^ 1] = d;
1211 }
1212
1213 static void REGPARM(3) sh2_write8_sdram_wt(u32 a, u32 d, SH2 *sh2)
1214 {
1215   // xmen sync hack..
1216   if (a < 0x26000200)
1217     sh2_end_run(sh2, 32);
1218
1219   sh2_write8_sdram(a, d, sh2);
1220 }
1221
1222 static void REGPARM(3) sh2_write8_da(u32 a, u32 d, SH2 *sh2)
1223 {
1224   u32 a1 = a & 0xfff;
1225 #ifdef DRC_SH2
1226   int id = sh2->is_slave;
1227   int t = Pico32xMem->drcblk_da[id][a1 >> SH2_DRCBLK_DA_SHIFT];
1228   if (t)
1229     sh2_drc_wcheck_da(a, t, id);
1230 #endif
1231   sh2->data_array[a1 ^ 1] = d;
1232 }
1233
1234 // write16
1235 static void REGPARM(3) sh2_write16_unmapped(u32 a, u32 d, SH2 *sh2)
1236 {
1237   elprintf(EL_UIO, "%csh2 unmapped w16 [%08x]     %04x @%06x",
1238     sh2->is_slave ? 's' : 'm', a, d & 0xffff, sh2_pc(sh2));
1239 }
1240
1241 static void REGPARM(3) sh2_write16_cs0(u32 a, u32 d, SH2 *sh2)
1242 {
1243   if (((EL_LOGMASK & EL_PWM) || (a & 0x30) != 0x30)) // hide PWM
1244     elprintf(EL_32X, "%csh2 w16 [%08x]     %04x @%06x",
1245       sh2->is_slave ? 's' : 'm', a, d & 0xffff, sh2_pc(sh2));
1246
1247   if (Pico32x.regs[0] & P32XS_FM) {
1248     if ((a & 0x3ff00) == 0x4100) {
1249       sh2->poll_addr = 0;
1250       p32x_vdp_write16(a, d, sh2);
1251       return;
1252     }
1253
1254     if ((a & 0x3fe00) == 0x4200) {
1255       Pico32xMem->pal[(a & 0x1ff) / 2] = d;
1256       Pico32x.dirty_pal = 1;
1257       return;
1258     }
1259   }
1260
1261   if ((a & 0x3ff00) == 0x4000) {
1262     p32x_sh2reg_write16(a, d, sh2);
1263     return;
1264   }
1265
1266   sh2_write16_unmapped(a, d, sh2);
1267 }
1268
1269 static void REGPARM(3) sh2_write16_dram0(u32 a, u32 d, SH2 *sh2)
1270 {
1271   sh2_write16_dramN(0);
1272 }
1273
1274 static void REGPARM(3) sh2_write16_dram1(u32 a, u32 d, SH2 *sh2)
1275 {
1276   sh2_write16_dramN(1);
1277 }
1278
1279 static void REGPARM(3) sh2_write16_sdram(u32 a, u32 d, SH2 *sh2)
1280 {
1281   u32 a1 = a & 0x3ffff;
1282 #ifdef DRC_SH2
1283   int t = Pico32xMem->drcblk_ram[a1 >> SH2_DRCBLK_RAM_SHIFT];
1284   if (t)
1285     sh2_drc_wcheck_ram(a, t, sh2->is_slave);
1286 #endif
1287   ((u16 *)Pico32xMem->sdram)[a1 / 2] = d;
1288 }
1289
1290 static void REGPARM(3) sh2_write16_da(u32 a, u32 d, SH2 *sh2)
1291 {
1292   u32 a1 = a & 0xfff;
1293 #ifdef DRC_SH2
1294   int id = sh2->is_slave;
1295   int t = Pico32xMem->drcblk_da[id][a1 >> SH2_DRCBLK_DA_SHIFT];
1296   if (t)
1297     sh2_drc_wcheck_da(a, t, id);
1298 #endif
1299   ((u16 *)sh2->data_array)[a1 / 2] = d;
1300 }
1301
1302
1303 typedef u32 (sh2_read_handler)(u32 a, SH2 *sh2);
1304 typedef void REGPARM(3) (sh2_write_handler)(u32 a, u32 d, SH2 *sh2);
1305
1306 #define SH2MAP_ADDR2OFFS_R(a) \
1307   ((u32)(a) >> SH2_READ_SHIFT)
1308
1309 #define SH2MAP_ADDR2OFFS_W(a) \
1310   ((u32)(a) >> SH2_WRITE_SHIFT)
1311
1312 u32 REGPARM(2) p32x_sh2_read8(u32 a, SH2 *sh2)
1313 {
1314   const sh2_memmap *sh2_map = sh2->read8_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 *(u8 *)((p << 1) + ((a & sh2_map->mask) ^ 1));
1323 }
1324
1325 u32 REGPARM(2) p32x_sh2_read16(u32 a, SH2 *sh2)
1326 {
1327   const sh2_memmap *sh2_map = sh2->read16_map;
1328   uptr p;
1329
1330   sh2_map += SH2MAP_ADDR2OFFS_R(a);
1331   p = sh2_map->addr;
1332   if (map_flag_set(p))
1333     return ((sh2_read_handler *)(p << 1))(a, sh2);
1334   else
1335     return *(u16 *)((p << 1) + ((a & sh2_map->mask) & ~1));
1336 }
1337
1338 u32 REGPARM(2) p32x_sh2_read32(u32 a, SH2 *sh2)
1339 {
1340   const sh2_memmap *sh2_map = sh2->read16_map;
1341   sh2_read_handler *handler;
1342   u32 offs;
1343   uptr p;
1344
1345   offs = SH2MAP_ADDR2OFFS_R(a);
1346   sh2_map += offs;
1347   p = sh2_map->addr;
1348   if (!map_flag_set(p)) {
1349     // XXX: maybe 32bit access instead with ror?
1350     u16 *pd = (u16 *)((p << 1) + ((a & sh2_map->mask) & ~1));
1351     return (pd[0] << 16) | pd[1];
1352   }
1353
1354   if (offs == 0x1f)
1355     return sh2_peripheral_read32(a, sh2);
1356
1357   handler = (sh2_read_handler *)(p << 1);
1358   return (handler(a, sh2) << 16) | handler(a + 2, sh2);
1359 }
1360
1361 void REGPARM(3) p32x_sh2_write8(u32 a, u32 d, SH2 *sh2)
1362 {
1363   const void **sh2_wmap = sh2->write8_tab;
1364   sh2_write_handler *wh;
1365
1366   wh = sh2_wmap[SH2MAP_ADDR2OFFS_W(a)];
1367   wh(a, d, sh2);
1368 }
1369
1370 void REGPARM(3) p32x_sh2_write16(u32 a, u32 d, SH2 *sh2)
1371 {
1372   const void **sh2_wmap = sh2->write16_tab;
1373   sh2_write_handler *wh;
1374
1375   wh = sh2_wmap[SH2MAP_ADDR2OFFS_W(a)];
1376   wh(a, d, sh2);
1377 }
1378
1379 void REGPARM(3) p32x_sh2_write32(u32 a, u32 d, SH2 *sh2)
1380 {
1381   const void **sh2_wmap = sh2->write16_tab;
1382   sh2_write_handler *wh;
1383   u32 offs;
1384
1385   offs = SH2MAP_ADDR2OFFS_W(a);
1386
1387   if (offs == SH2MAP_ADDR2OFFS_W(0xffffc000)) {
1388     sh2_peripheral_write32(a, d, sh2);
1389     return;
1390   }
1391
1392   wh = sh2_wmap[offs];
1393   wh(a, d >> 16, sh2);
1394   wh(a + 2, d, sh2);
1395 }
1396
1397 // -----------------------------------------------------------------
1398
1399 static const u16 msh2_code[] = {
1400   // trap instructions
1401   0xaffe, // bra <self>
1402   0x0009, // nop
1403   // have to wait a bit until m68k initial program finishes clearing stuff
1404   // to avoid races with game SH2 code, like in Tempo
1405   0xd004, // mov.l   @(_m_ok,pc), r0
1406   0xd105, // mov.l   @(_cnt,pc), r1
1407   0xd205, // mov.l   @(_start,pc), r2
1408   0x71ff, // add     #-1, r1
1409   0x4115, // cmp/pl  r1
1410   0x89fc, // bt      -2
1411   0xc208, // mov.l   r0, @(h'20,gbr)
1412   0x6822, // mov.l   @r2, r8
1413   0x482b, // jmp     @r8
1414   0x0009, // nop
1415   ('M'<<8)|'_', ('O'<<8)|'K',
1416   0x0001, 0x0000,
1417   0x2200, 0x03e0  // master start pointer in ROM
1418 };
1419
1420 static const u16 ssh2_code[] = {
1421   0xaffe, // bra <self>
1422   0x0009, // nop
1423   // code to wait for master, in case authentic master BIOS is used
1424   0xd104, // mov.l   @(_m_ok,pc), r1
1425   0xd206, // mov.l   @(_start,pc), r2
1426   0xc608, // mov.l   @(h'20,gbr), r0
1427   0x3100, // cmp/eq  r0, r1
1428   0x8bfc, // bf      #-2
1429   0xd003, // mov.l   @(_s_ok,pc), r0
1430   0xc209, // mov.l   r0, @(h'24,gbr)
1431   0x6822, // mov.l   @r2, r8
1432   0x482b, // jmp     @r8
1433   0x0009, // nop
1434   ('M'<<8)|'_', ('O'<<8)|'K',
1435   ('S'<<8)|'_', ('O'<<8)|'K',
1436   0x2200, 0x03e4  // slave start pointer in ROM
1437 };
1438
1439 #define HWSWAP(x) (((u16)(x) << 16) | ((x) >> 16))
1440 static void get_bios(void)
1441 {
1442   u16 *ps;
1443   u32 *pl;
1444   int i;
1445
1446   // M68K ROM
1447   if (p32x_bios_g != NULL) {
1448     elprintf(EL_STATUS|EL_32X, "32x: using supplied 68k BIOS");
1449     Byteswap(Pico32xMem->m68k_rom, p32x_bios_g, sizeof(Pico32xMem->m68k_rom));
1450   }
1451   else {
1452     // generate 68k ROM
1453     ps = (u16 *)Pico32xMem->m68k_rom;
1454     pl = (u32 *)ps;
1455     for (i = 1; i < 0xc0/4; i++)
1456       pl[i] = HWSWAP(0x880200 + (i - 1) * 6);
1457
1458     // fill with nops
1459     for (i = 0xc0/2; i < 0x100/2; i++)
1460       ps[i] = 0x4e71;
1461
1462 #if 0
1463     ps[0xc0/2] = 0x46fc;
1464     ps[0xc2/2] = 0x2700; // move #0x2700,sr
1465     ps[0xfe/2] = 0x60fe; // jump to self
1466 #else
1467     ps[0xfe/2] = 0x4e75; // rts
1468 #endif
1469   }
1470   // fill remaining m68k_rom page with game ROM
1471   memcpy(Pico32xMem->m68k_rom_bank + sizeof(Pico32xMem->m68k_rom),
1472     Pico.rom + sizeof(Pico32xMem->m68k_rom),
1473     sizeof(Pico32xMem->m68k_rom_bank) - sizeof(Pico32xMem->m68k_rom));
1474
1475   // MSH2
1476   if (p32x_bios_m != NULL) {
1477     elprintf(EL_STATUS|EL_32X, "32x: using supplied master SH2 BIOS");
1478     Byteswap(Pico32xMem->sh2_rom_m, p32x_bios_m, sizeof(Pico32xMem->sh2_rom_m));
1479   }
1480   else {
1481     pl = (u32 *)Pico32xMem->sh2_rom_m;
1482
1483     // fill exception vector table to our trap address
1484     for (i = 0; i < 128; i++)
1485       pl[i] = HWSWAP(0x200);
1486
1487     // startup code
1488     memcpy(Pico32xMem->sh2_rom_m + 0x200, msh2_code, sizeof(msh2_code));
1489
1490     // reset SP
1491     pl[1] = pl[3] = HWSWAP(0x6040000);
1492     // start
1493     pl[0] = pl[2] = HWSWAP(0x204);
1494   }
1495
1496   // SSH2
1497   if (p32x_bios_s != NULL) {
1498     elprintf(EL_STATUS|EL_32X, "32x: using supplied slave SH2 BIOS");
1499     Byteswap(Pico32xMem->sh2_rom_s, p32x_bios_s, sizeof(Pico32xMem->sh2_rom_s));
1500   }
1501   else {
1502     pl = (u32 *)Pico32xMem->sh2_rom_s;
1503
1504     // fill exception vector table to our trap address
1505     for (i = 0; i < 128; i++)
1506       pl[i] = HWSWAP(0x200);
1507
1508     // startup code
1509     memcpy(Pico32xMem->sh2_rom_s + 0x200, ssh2_code, sizeof(ssh2_code));
1510
1511     // reset SP
1512     pl[1] = pl[3] = HWSWAP(0x603f800);
1513     // start
1514     pl[0] = pl[2] = HWSWAP(0x204);
1515   }
1516 }
1517
1518 #define MAP_MEMORY(m) ((uptr)(m) >> 1)
1519 #define MAP_HANDLER(h) ( ((uptr)(h) >> 1) | ((uptr)1 << (sizeof(uptr) * 8 - 1)) )
1520
1521 static sh2_memmap sh2_read8_map[0x80], sh2_read16_map[0x80];
1522 // for writes we are using handlers only
1523 static sh2_write_handler *sh2_write8_map[0x80], *sh2_write16_map[0x80];
1524
1525 void Pico32xSwapDRAM(int b)
1526 {
1527   cpu68k_map_set(m68k_read8_map,   0x840000, 0x85ffff, Pico32xMem->dram[b], 0);
1528   cpu68k_map_set(m68k_read16_map,  0x840000, 0x85ffff, Pico32xMem->dram[b], 0);
1529   cpu68k_map_set(m68k_read8_map,   0x860000, 0x87ffff, Pico32xMem->dram[b], 0);
1530   cpu68k_map_set(m68k_read16_map,  0x860000, 0x87ffff, Pico32xMem->dram[b], 0);
1531   cpu68k_map_set(m68k_write8_map,  0x840000, 0x87ffff,
1532                  b ? m68k_write8_dram1_ow : m68k_write8_dram0_ow, 1);
1533   cpu68k_map_set(m68k_write16_map, 0x840000, 0x87ffff,
1534                  b ? m68k_write16_dram1_ow : m68k_write16_dram0_ow, 1);
1535
1536   // SH2
1537   sh2_read8_map[0x04/2].addr  = sh2_read8_map[0x24/2].addr  =
1538   sh2_read16_map[0x04/2].addr = sh2_read16_map[0x24/2].addr = MAP_MEMORY(Pico32xMem->dram[b]);
1539
1540   sh2_write8_map[0x04/2]  = sh2_write8_map[0x24/2]  = b ? sh2_write8_dram1 : sh2_write8_dram0;
1541   sh2_write16_map[0x04/2] = sh2_write16_map[0x24/2] = b ? sh2_write16_dram1 : sh2_write16_dram0;
1542 }
1543
1544 void PicoMemSetup32x(void)
1545 {
1546   unsigned int rs;
1547   int i;
1548
1549   Pico32xMem = plat_mmap(0x06000000, sizeof(*Pico32xMem), 0, 0);
1550   if (Pico32xMem == NULL) {
1551     elprintf(EL_STATUS, "OOM");
1552     return;
1553   }
1554
1555   get_bios();
1556
1557   // cartridge area becomes unmapped
1558   // XXX: we take the easy way and don't unmap ROM,
1559   // so that we can avoid handling the RV bit.
1560   // m68k_map_unmap(0x000000, 0x3fffff);
1561
1562   // MD ROM area
1563   rs = sizeof(Pico32xMem->m68k_rom_bank);
1564   cpu68k_map_set(m68k_read8_map,   0x000000, rs - 1, Pico32xMem->m68k_rom_bank, 0);
1565   cpu68k_map_set(m68k_read16_map,  0x000000, rs - 1, Pico32xMem->m68k_rom_bank, 0);
1566   cpu68k_map_set(m68k_write8_map,  0x000000, rs - 1, PicoWrite8_hint, 1); // TODO verify
1567   cpu68k_map_set(m68k_write16_map, 0x000000, rs - 1, PicoWrite16_hint, 1);
1568
1569   // 32X ROM (unbanked, XXX: consider mirroring?)
1570   rs = (Pico.romsize + M68K_BANK_MASK) & ~M68K_BANK_MASK;
1571   if (rs > 0x80000)
1572     rs = 0x80000;
1573   cpu68k_map_set(m68k_read8_map,   0x880000, 0x880000 + rs - 1, Pico.rom, 0);
1574   cpu68k_map_set(m68k_read16_map,  0x880000, 0x880000 + rs - 1, Pico.rom, 0);
1575 #ifdef EMU_F68K
1576   // setup FAME fetchmap
1577   PicoCpuFM68k.Fetch[0] = (unsigned long)Pico32xMem->m68k_rom;
1578   for (rs = 0x88; rs < 0x90; rs++)
1579     PicoCpuFM68k.Fetch[rs] = (unsigned long)Pico.rom - 0x880000;
1580 #endif
1581
1582   // 32X ROM (banked)
1583   bank_switch(0);
1584
1585   // SYS regs
1586   cpu68k_map_set(m68k_read8_map,   0xa10000, 0xa1ffff, PicoRead8_32x_on, 1);
1587   cpu68k_map_set(m68k_read16_map,  0xa10000, 0xa1ffff, PicoRead16_32x_on, 1);
1588   cpu68k_map_set(m68k_write8_map,  0xa10000, 0xa1ffff, PicoWrite8_32x_on, 1);
1589   cpu68k_map_set(m68k_write16_map, 0xa10000, 0xa1ffff, PicoWrite16_32x_on, 1);
1590
1591   // SH2 maps: A31,A30,A29,CS1,CS0
1592   // all unmapped by default
1593   for (i = 0; i < ARRAY_SIZE(sh2_read8_map); i++) {
1594     sh2_read8_map[i].addr   = MAP_HANDLER(sh2_read8_unmapped);
1595     sh2_read16_map[i].addr  = MAP_HANDLER(sh2_read16_unmapped);
1596   }
1597
1598   for (i = 0; i < ARRAY_SIZE(sh2_write8_map); i++) {
1599     sh2_write8_map[i]       = sh2_write8_unmapped;
1600     sh2_write16_map[i]      = sh2_write16_unmapped;
1601   }
1602
1603   // "purge area"
1604   for (i = 0x40; i <= 0x5f; i++) {
1605     sh2_write8_map[i >> 1]  =
1606     sh2_write16_map[i >> 1] = sh2_write_ignore;
1607   }
1608
1609   // CS0
1610   sh2_read8_map[0x00/2].addr  = sh2_read8_map[0x20/2].addr  = MAP_HANDLER(sh2_read8_cs0);
1611   sh2_read16_map[0x00/2].addr = sh2_read16_map[0x20/2].addr = MAP_HANDLER(sh2_read16_cs0);
1612   sh2_write8_map[0x00/2]  = sh2_write8_map[0x20/2]  = sh2_write8_cs0;
1613   sh2_write16_map[0x00/2] = sh2_write16_map[0x20/2] = sh2_write16_cs0;
1614   // CS1 - ROM
1615   sh2_read8_map[0x02/2].addr  = sh2_read8_map[0x22/2].addr  =
1616   sh2_read16_map[0x02/2].addr = sh2_read16_map[0x22/2].addr = MAP_MEMORY(Pico.rom);
1617   sh2_read8_map[0x02/2].mask  = sh2_read8_map[0x22/2].mask  =
1618   sh2_read16_map[0x02/2].mask = sh2_read16_map[0x22/2].mask = 0x3fffff; // FIXME
1619   // CS2 - DRAM - done by Pico32xSwapDRAM()
1620   sh2_read8_map[0x04/2].mask  = sh2_read8_map[0x24/2].mask  =
1621   sh2_read16_map[0x04/2].mask = sh2_read16_map[0x24/2].mask = 0x01ffff;
1622   // CS3 - SDRAM
1623   sh2_read8_map[0x06/2].addr   = sh2_read8_map[0x26/2].addr   =
1624   sh2_read16_map[0x06/2].addr  = sh2_read16_map[0x26/2].addr  = MAP_MEMORY(Pico32xMem->sdram);
1625   sh2_write8_map[0x06/2]       = sh2_write8_sdram;
1626   sh2_write8_map[0x26/2]       = sh2_write8_sdram_wt;
1627   sh2_write16_map[0x06/2]      = sh2_write16_map[0x26/2]      = sh2_write16_sdram;
1628   sh2_read8_map[0x06/2].mask   = sh2_read8_map[0x26/2].mask   =
1629   sh2_read16_map[0x06/2].mask  = sh2_read16_map[0x26/2].mask  = 0x03ffff;
1630   // SH2 data array
1631   sh2_read8_map[0xc0/2].addr  = MAP_HANDLER(sh2_read8_da);
1632   sh2_read16_map[0xc0/2].addr = MAP_HANDLER(sh2_read16_da);
1633   sh2_write8_map[0xc0/2]      = sh2_write8_da;
1634   sh2_write16_map[0xc0/2]     = sh2_write16_da;
1635   // SH2 IO
1636   sh2_read8_map[0xff/2].addr  = MAP_HANDLER(sh2_peripheral_read8);
1637   sh2_read16_map[0xff/2].addr = MAP_HANDLER(sh2_peripheral_read16);
1638   sh2_write8_map[0xff/2]      = sh2_peripheral_write8;
1639   sh2_write16_map[0xff/2]     = sh2_peripheral_write16;
1640
1641   // map DRAM area, both 68k and SH2
1642   Pico32xSwapDRAM(1);
1643
1644   msh2.read8_map   = ssh2.read8_map   = sh2_read8_map;
1645   msh2.read16_map  = ssh2.read16_map  = sh2_read16_map;
1646   msh2.write8_tab  = ssh2.write8_tab  = (const void **)(void *)sh2_write8_map;
1647   msh2.write16_tab = ssh2.write16_tab = (const void **)(void *)sh2_write16_map;
1648
1649   sh2_drc_mem_setup(&msh2);
1650   sh2_drc_mem_setup(&ssh2);
1651 }
1652
1653 void Pico32xMemStateLoaded(void)
1654 {
1655   bank_switch(Pico32x.regs[4 / 2]);
1656   Pico32xSwapDRAM((Pico32x.vdp_regs[0x0a / 2] & P32XV_FS) ^ P32XV_FS);
1657   memset(Pico32xMem->pwm, 0, sizeof(Pico32xMem->pwm));
1658   Pico32x.dirty_pal = 1;
1659
1660   Pico32x.emu_flags &= ~(P32XF_68KCPOLL | P32XF_68KVPOLL);
1661   memset(&m68k_poll, 0, sizeof(m68k_poll));
1662   msh2.state = 0;
1663   msh2.poll_addr = msh2.poll_cycles = msh2.poll_cnt = 0;
1664   ssh2.state = 0;
1665   ssh2.poll_addr = ssh2.poll_cycles = ssh2.poll_cnt = 0;
1666
1667   sh2_drc_flush_all();
1668 }
1669
1670 // vim:shiftwidth=2:ts=2:expandtab