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