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