12c3f737044e8044a1b504dd3b7980e74180a825
[picodrive.git] / pico / 32x / memory.c
1 /*
2  * PicoDrive
3  * (C) notaz, 2009,2010,2013
4  * (C) irixxxx, 2019-2024
5  *
6  * This work is licensed under the terms of MAME license.
7  * See COPYING file in the top-level directory.
8  *
9  * Register map:
10  * a15100 F....... R.....EA  F.....AC N...VHMP 4000 // Fm Ren nrEs Aden Cart heN V H cMd Pwm
11  * a15102 ........ ......SM  ?                 4002 // intS intM
12  * a15104 ........ ......10  ........ hhhhhhhh 4004 // bk1 bk0 Hint
13  * a15106 ........ F....SDR  UE...... .....SDR 4006 // Full 68S Dma Rv fUll[fb] Empt[fb]
14  * a15108           (32bit DREQ src)           4008
15  * a1510c           (32bit DREQ dst)           400c
16  * a15110          llllllll llllll00           4010 // DREQ Len
17  * a15112           (16bit FIFO reg)           4012
18  * a15114 0                  (16bit VRES clr)  4014
19  * a15116 0                  (16bit Vint clr)  4016
20  * a15118 0                  (16bit Hint clr)  4018
21  * a1511a .......? .......C  (16bit CMD clr)   401a // TV Cm
22  * a1511c 0                  (16bit PWM clr)   401c
23  * a1511e 0                  ?                 401e
24  * a15120            (16 bytes comm)           2020
25  * a15130                 (PWM)                2030
26  *
27  * SH2 addr lines:
28  * iii. .cc. ..xx *   // Internal, Cs, x
29  *
30  * sh2 map, wait/bus cycles (from docs):
31  *                             r    w
32  * rom      0000000-0003fff    1    -
33  * sys reg  0004000-00040ff    1    1
34  * vdp reg  0004100-00041ff    5    5
35  * vdp pal  0004200-00043ff    5    5
36  * cart     2000000-23fffff     6-15
37  * dram/fb  4000000-401ffff 5-12  1-3
38  * fb ovr   4020000-403ffff
39  * sdram    6000000-603ffff   12    2  (cycles)
40  * d.a.    c0000000-?
41  */
42 #include "../pico_int.h"
43 #include "../memory.h"
44
45 #include <cpu/sh2/compiler.h>
46 DRC_DECLARE_SR;
47
48 static const char str_mars[] = "MARS";
49
50 void *p32x_bios_g, *p32x_bios_m, *p32x_bios_s;
51 struct Pico32xMem *Pico32xMem;
52
53 static void bank_switch_rom_68k(int b);
54
55 static void (*m68k_write8_io)(u32 a, u32 d);
56 static void (*m68k_write16_io)(u32 a, u32 d);
57
58 // addressing byte in 16bit reg
59 #define REG8IN16(ptr, offs) ((u8 *)ptr)[MEM_BE2(offs)]
60
61 // poll detection
62 #define POLL_THRESHOLD 11  // Primal Rage speed, Blackthorne intro
63
64 static struct {
65   u32 addr1, addr2, cycles;
66   int cnt;
67 } m68k_poll;
68
69 static int m68k_poll_detect(u32 a, u32 cycles, u32 flags)
70 {
71   int ret = 0;
72   // support polling on 2 addresses - seen in Wolfenstein
73   int match = (a - m68k_poll.addr1 <= 3 || a - m68k_poll.addr2 <= 3);
74
75   if (match && CYCLES_GT(64, cycles - m68k_poll.cycles) && !SekNotPolling)
76   {
77     // detect split 32bit access by same cycle count, and ignore those
78     if (cycles != m68k_poll.cycles && ++m68k_poll.cnt >= POLL_THRESHOLD) {
79       if (!(Pico32x.emu_flags & flags)) {
80         elprintf(EL_32X, "m68k poll addr %08x, cyc %u",
81           a, cycles - m68k_poll.cycles);
82       }
83       Pico32x.emu_flags |= flags;
84       ret = 1;
85     }
86   }
87   else {
88     // reset poll state in case of restart by interrupt
89     Pico32x.emu_flags &= ~(P32XF_68KCPOLL|P32XF_68KVPOLL);
90     SekSetStop(0);
91     m68k_poll.cnt = 0;
92     if (!match) {
93       m68k_poll.addr2 = m68k_poll.addr1;
94       m68k_poll.addr1 = a & ~1;
95     }
96     SekNotPolling = 0;
97   }
98   m68k_poll.cycles = cycles;
99
100   return ret;
101 }
102
103 void p32x_m68k_poll_event(u32 a, u32 flags)
104 {
105   int match = (a - m68k_poll.addr1 <= 3 || a - m68k_poll.addr2 <= 3);
106
107   if ((Pico32x.emu_flags & flags) && match) {
108     elprintf(EL_32X, "m68k poll %02x -> %02x", Pico32x.emu_flags,
109       Pico32x.emu_flags & ~flags);
110     Pico32x.emu_flags &= ~flags;
111     SekSetStop(0);
112   }
113
114   if (!(Pico32x.emu_flags & (P32XF_68KCPOLL|P32XF_68KVPOLL)))
115     m68k_poll.addr1 = m68k_poll.addr2 = m68k_poll.cnt = 0;
116 }
117
118 void NOINLINE p32x_sh2_poll_detect(u32 a, SH2 *sh2, u32 flags, int maxcnt)
119 {
120   u32 cycles_done = sh2_cycles_done_t(sh2);
121   u32 cycles_diff = cycles_done - sh2->poll_cycles;
122
123   a &= ~0x20000000;
124   // reading 2 consecutive 16bit values is probably a 32bit access. detect this
125   // by checking address (max 2 bytes away) and cycles (max 2 cycles later).
126   // no polling if more than 20 cycles have passed since last detect call.
127   if (a - sh2->poll_addr <= 3 && CYCLES_GE(20, cycles_diff)) {
128     if (!sh2_not_polling(sh2) && CYCLES_GT(cycles_diff, 2) &&
129                 ++sh2->poll_cnt >= maxcnt) {
130       if (!(sh2->state & flags))
131         elprintf_sh2(sh2, EL_32X, "state: %02x->%02x",
132           sh2->state, sh2->state | flags);
133
134       sh2->state |= flags;
135       sh2_end_run(sh2, 0);
136       pevt_log_sh2(sh2, EVT_POLL_START);
137 #ifdef DRC_SH2
138       // mark this as an address used for polling if SDRAM
139       if ((a & 0xc6000000) == 0x06000000) {
140         unsigned char *p = sh2->p_drcblk_ram;
141         p[(a & 0x3ffff) >> SH2_DRCBLK_RAM_SHIFT] |= 0x80;
142         // mark next word too to enable poll fifo for 32bit access
143         p[((a+2) & 0x3ffff) >> SH2_DRCBLK_RAM_SHIFT] |= 0x80;
144       }
145 #endif
146     }
147   }
148   else if (!(sh2->state & (SH2_STATE_CPOLL|SH2_STATE_VPOLL|SH2_STATE_RPOLL))) {
149     sh2->poll_cnt = 0;
150     sh2->poll_addr = a & ~1;
151   }
152   sh2->poll_cycles = cycles_done;
153   sh2_set_polling(sh2);
154 }
155
156 void NOINLINE p32x_sh2_poll_event(u32 a, SH2 *sh2, u32 flags, u32 m68k_cycles)
157 {
158   a &= ~0x20000000;
159   if ((sh2->state & flags) && a - sh2->poll_addr <= 3) {
160     elprintf_sh2(sh2, EL_32X, "state: %02x->%02x", sh2->state,
161       sh2->state & ~flags);
162
163     if (CYCLES_GT(m68k_cycles, sh2->m68krcycles_done) && !(sh2->state & SH2_STATE_RUN))
164       sh2->m68krcycles_done = m68k_cycles;
165
166     pevt_log_sh2_o(sh2, EVT_POLL_END);
167     sh2->state &= ~flags;
168   }
169
170   if (!(sh2->state & (SH2_STATE_CPOLL|SH2_STATE_VPOLL|SH2_STATE_RPOLL)))
171     sh2->poll_addr = sh2->poll_cycles = sh2->poll_cnt = 0;
172 }
173
174 static NOINLINE void sh2s_sync_on_read(SH2 *sh2, unsigned cycles)
175 {
176   if (sh2->poll_cnt != 0)
177     return;
178
179   if (p32x_sh2_ready(sh2->other_sh2, cycles-250))
180     p32x_sync_other_sh2(sh2, cycles);
181 }
182
183 // poll fifo, stores writes to potential addresses used for polling.
184 // This is used to correctly deliver syncronisation data to the 3 cpus. The
185 // fifo stores 16 bit values, 8/32 bit accesses must be adapted accordingly.
186 #define PFIFO_SZ        4
187 #define PFIFO_CNT       8
188 struct sh2_poll_fifo {
189   u32 cycles;
190   u32 a;
191   u16 d;
192   int cpu;
193 } sh2_poll_fifo[PFIFO_CNT][PFIFO_SZ];
194 unsigned sh2_poll_rd[PFIFO_CNT], sh2_poll_wr[PFIFO_CNT]; // ringbuffer pointers
195
196 static NOINLINE u32 sh2_poll_read(u32 a, u32 d, unsigned int cycles, SH2* sh2)
197 {
198   int hix = (a >> 1) % PFIFO_CNT;
199   struct sh2_poll_fifo *fifo = sh2_poll_fifo[hix];
200   struct sh2_poll_fifo *p;
201   int cpu = sh2 ? sh2->is_slave : -1;
202   unsigned idx;
203
204   a &= ~0x20000000; // ignore writethrough bit
205   // fetch oldest write to address from fifo, but stop when reaching the present
206   idx = sh2_poll_rd[hix];
207   while (idx != sh2_poll_wr[hix] && CYCLES_GE(cycles, fifo[idx].cycles)) {
208     p = &fifo[idx];
209     idx = (idx+1) % PFIFO_SZ;
210
211     if (cpu != p->cpu) {
212       if (CYCLES_GT(cycles, p->cycles+60)) { // ~180 sh2 cycles, Spiderman
213         // drop older fifo stores that may cause synchronisation problems.
214         p->a = -1;
215       } else if (p->a == a) {
216         // replace current data with fifo value and discard fifo entry
217         d = p->d;
218         p->a = -1;
219         break;
220       }
221     }
222   }
223   return d;
224 }
225
226 static NOINLINE void sh2_poll_write(u32 a, u32 d, unsigned int cycles, SH2 *sh2)
227 {
228   int hix = (a >> 1) % PFIFO_CNT;
229   struct sh2_poll_fifo *fifo = sh2_poll_fifo[hix];
230   struct sh2_poll_fifo *q;
231   int cpu = sh2 ? sh2->is_slave : -1;
232   unsigned rd = sh2_poll_rd[hix], wr = sh2_poll_wr[hix];
233   unsigned idx, nrd;
234
235   a &= ~0x20000000; // ignore writethrough bit
236
237   // throw out any values written by other cpus, plus heading cancelled stuff
238   for (idx = nrd = wr; idx != rd; ) {
239     idx = (idx-1) % PFIFO_SZ;
240     q = &fifo[idx];
241     if (q->a == a && q->cpu != cpu)     { q->a = -1; }
242     if (q->a != -1)                     { nrd = idx; }
243   }
244   rd = nrd;
245
246   // fold 2 consecutive writes to the same address to avoid reading of
247   // intermediate values that may cause synchronisation problems.
248   // NB this can take an eternity on m68k: mov.b <addr1.l>,<addr2.l> needs
249   // 28 m68k-cycles (~80 sh2-cycles) to complete (observed in Metal Head)
250   q = &fifo[(sh2_poll_wr[hix]-1) % PFIFO_SZ];
251   if (rd != wr && q->a == a && !CYCLES_GT(cycles,q->cycles + (cpu<0 ? 30:4))) {
252     q->d = d;
253   } else {
254     // store write to poll address in fifo
255     fifo[wr] =
256         (struct sh2_poll_fifo){ .cycles = cycles, .a = a, .d = d, .cpu = cpu };
257     wr = (wr+1) % PFIFO_SZ;
258     if (wr == rd)
259       // fifo overflow, discard oldest value
260       rd = (rd+1) % PFIFO_SZ;
261   }
262
263   sh2_poll_rd[hix] = rd; sh2_poll_wr[hix] = wr;
264 }
265
266 u32 REGPARM(3) p32x_sh2_poll_memory8(u32 a, u32 d, SH2 *sh2)
267 {
268   int shift = (a & 1 ? 0 : 8);
269   d = (s8)(p32x_sh2_poll_memory16(a & ~1, d << shift, sh2) >> shift);
270   return d;
271 }
272
273 u32 REGPARM(3) p32x_sh2_poll_memory16(u32 a, u32 d, SH2 *sh2)
274 {
275   unsigned char *p = sh2->p_drcblk_ram;
276   unsigned int cycles;
277
278   DRC_SAVE_SR(sh2);
279   // is this a synchronisation address?
280   if(p[(a & 0x3ffff) >> SH2_DRCBLK_RAM_SHIFT] & 0x80) {
281     cycles = sh2_cycles_done_m68k(sh2);
282     sh2s_sync_on_read(sh2, cycles);
283     // check poll fifo and sign-extend the result correctly
284     d = (s16)sh2_poll_read(a, d, cycles, sh2);
285   }
286
287   p32x_sh2_poll_detect(a, sh2, SH2_STATE_RPOLL, 7);
288
289   DRC_RESTORE_SR(sh2);
290   return d;
291 }
292
293 u32 REGPARM(3) p32x_sh2_poll_memory32(u32 a, u32 d, SH2 *sh2)
294 {
295   unsigned char *p = sh2->p_drcblk_ram;
296   unsigned int cycles;
297
298   DRC_SAVE_SR(sh2);
299   // is this a synchronisation address?
300   if(p[(a & 0x3ffff) >> SH2_DRCBLK_RAM_SHIFT] & 0x80) {
301     cycles = sh2_cycles_done_m68k(sh2);
302     sh2s_sync_on_read(sh2, cycles);
303     // check poll fifo and sign-extend the result correctly
304     d = (sh2_poll_read(a, d >> 16, cycles, sh2) << 16) |
305         ((u16)sh2_poll_read(a+2, d, cycles, sh2));
306   }
307
308   p32x_sh2_poll_detect(a, sh2, SH2_STATE_RPOLL, 7);
309
310   DRC_RESTORE_SR(sh2);
311   return d;
312 }
313
314 // SH2 faking
315 //#define FAKE_SH2
316 #ifdef FAKE_SH2
317 static int p32x_csum_faked;
318 static const u16 comm_fakevals[] = {
319   0x4d5f, 0x4f4b, // M_OK
320   0x535f, 0x4f4b, // S_OK
321   0x4D41, 0x5346, // MASF - Brutal Unleashed
322   0x5331, 0x4d31, // Darxide
323   0x5332, 0x4d32,
324   0x5333, 0x4d33,
325   0x0000, 0x0000, // eq for doom
326   0x0002, // Mortal Kombat
327 //  0, // pad
328 };
329
330 static u32 sh2_comm_faker(u32 a)
331 {
332   static int f = 0;
333   if (a == 0x28 && !p32x_csum_faked) {
334     p32x_csum_faked = 1;
335     return *(u16 *)(Pico.rom + 0x18e);
336   }
337   if (f >= sizeof(comm_fakevals) / sizeof(comm_fakevals[0]))
338     f = 0;
339   return comm_fakevals[f++];
340 }
341 #endif
342
343 // ------------------------------------------------------------------
344 // 68k regs
345
346 static u32 p32x_reg_read16(u32 a)
347 {
348   a &= 0x3e;
349
350 #if 0
351   if ((a & 0x30) == 0x20)
352     return sh2_comm_faker(a);
353 #else
354   if ((a & 0x30) == 0x20) {
355     unsigned int cycles = SekCyclesDone();
356
357     if (CYCLES_GT(cycles - msh2.m68krcycles_done, 244))
358       p32x_sync_sh2s(cycles);
359
360     if (m68k_poll_detect(a, cycles, P32XF_68KCPOLL))
361       SekSetStop(1);
362     return sh2_poll_read(a, Pico32x.regs[a / 2], cycles, NULL);
363   }
364 #endif
365
366   if (a == 2) { // INTM, INTS
367     unsigned int cycles = SekCyclesDone();
368     if (CYCLES_GT(cycles - msh2.m68krcycles_done, 64))
369       p32x_sync_sh2s(cycles);
370     goto out;
371   }
372
373   if ((a & 0x30) == 0x30)
374     return p32x_pwm_read16(a, NULL, SekCyclesDone());
375
376 out:
377   return Pico32x.regs[a / 2];
378 }
379
380 static void dreq0_write(u16 *r, u32 d)
381 {
382   if (!(r[6 / 2] & P32XS_68S)) {
383     elprintf(EL_32X|EL_ANOMALY, "DREQ FIFO w16 without 68S?");
384     return; // ignored - tested
385   }
386   if (Pico32x.dmac0_fifo_ptr < DMAC_FIFO_LEN) {
387     Pico32x.dmac_fifo[Pico32x.dmac0_fifo_ptr++] = d;
388     if (Pico32x.dmac0_fifo_ptr == DMAC_FIFO_LEN)
389       r[6 / 2] |= P32XS_FULL;
390     // tested: len register decrements and 68S clears
391     // even if SH2s/DMAC aren't active..
392     r[0x10 / 2]--;
393     if (r[0x10 / 2] == 0)
394       r[6 / 2] &= ~P32XS_68S;
395
396     if ((Pico32x.dmac0_fifo_ptr & 3) == 0) {
397       p32x_sync_sh2s(SekCyclesDone());
398       p32x_dreq0_trigger();
399     }
400   }
401   else
402     elprintf(EL_32X|EL_ANOMALY, "DREQ FIFO overflow!");
403 }
404
405 // writable bits tested
406 static void p32x_reg_write8(u32 a, u32 d)
407 {
408   u16 *r = Pico32x.regs;
409   a &= 0x3f;
410
411   // for things like bset on comm port
412   m68k_poll.cnt = 0;
413
414   switch (a) {
415     case 0x00: // adapter ctl: FM writable
416       REG8IN16(r, 0x00) = d & 0x80;
417       return;
418     case 0x01: // adapter ctl: RES and ADEN writable
419       if ((d ^ r[0]) & ~d & P32XS_ADEN) {
420         d |= P32XS_nRES;
421         Pico32xShutdown();
422       } else if ((d ^ r[0]) & d & P32XS_nRES)
423         p32x_reset_sh2s();
424       REG8IN16(r, 0x01) &= ~(P32XS_nRES|P32XS_ADEN);
425       REG8IN16(r, 0x01) |= d & (P32XS_nRES|P32XS_ADEN);
426       return;
427     case 0x02: // ignored, always 0
428       return;
429     case 0x03: // irq ctl
430       if ((d ^ r[0x02 / 2]) & 3) {
431         unsigned int cycles = SekCyclesDone();
432         p32x_sync_sh2s(cycles);
433         r[0x02 / 2] = d & 3;
434         p32x_update_cmd_irq(NULL, cycles);
435       }
436       return;
437     case 0x04: // ignored, always 0
438       return;
439     case 0x05: // bank
440       d &= 3;
441       if (r[0x04 / 2] != d) {
442         r[0x04 / 2] = d;
443         bank_switch_rom_68k(d);
444       }
445       return;
446     case 0x06: // ignored, always 0
447       return;
448     case 0x07: // DREQ ctl
449       REG8IN16(r, 0x07) &= ~(P32XS_68S|P32XS_DMA|P32XS_RV);
450       if (!(d & P32XS_68S)) {
451         Pico32x.dmac0_fifo_ptr = 0;
452         REG8IN16(r, 0x07) &= ~P32XS_FULL;
453       }
454       REG8IN16(r, 0x07) |= d & (P32XS_68S|P32XS_DMA|P32XS_RV);
455       return;
456     case 0x08: // ignored, always 0
457       return;
458     case 0x09: // DREQ src
459       REG8IN16(r, 0x09) = d;
460       return;
461     case 0x0a:
462       REG8IN16(r, 0x0a) = d;
463       return;
464     case 0x0b:
465       REG8IN16(r, 0x0b) = d & 0xfe;
466       return;
467     case 0x0c: // ignored, always 0
468       return;
469     case 0x0d: // DREQ dest
470     case 0x0e:
471     case 0x0f:
472     case 0x10: // DREQ len
473       REG8IN16(r, a) = d;
474       return;
475     case 0x11:
476       REG8IN16(r, a) = d & 0xfc;
477       return;
478     // DREQ FIFO - writes to odd addr go to fifo
479     // do writes to even work? Reads return 0
480     case 0x12:
481       REG8IN16(r, a) = d;
482       return;
483     case 0x13:
484       d = (REG8IN16(r, 0x12) << 8) | (d & 0xff);
485       REG8IN16(r, 0x12) = 0;
486       dreq0_write(r, d);
487       return;
488     case 0x14: // ignored, always 0
489     case 0x15:
490     case 0x16:
491     case 0x17:
492     case 0x18:
493     case 0x19:
494       return;
495     case 0x1a: // what's this?
496       elprintf(EL_32X|EL_ANOMALY, "mystery w8 %02x %02x", a, d);
497       REG8IN16(r, a) = d & 0x01;
498       return;
499     case 0x1b: // TV
500       REG8IN16(r, a) = d & 0x01;
501       return;
502     case 0x1c: // ignored, always 0
503     case 0x1d:
504     case 0x1e:
505     case 0x1f:
506       return;
507     case 0x20: // comm port
508     case 0x21:
509     case 0x22:
510     case 0x23:
511     case 0x24:
512     case 0x25:
513     case 0x26:
514     case 0x27:
515     case 0x28:
516     case 0x29:
517     case 0x2a:
518     case 0x2b:
519     case 0x2c:
520     case 0x2d:
521     case 0x2e:
522     case 0x2f:
523       { unsigned int cycles = SekCyclesDone();
524
525         if (CYCLES_GT(cycles - msh2.m68krcycles_done, 64))
526           p32x_sync_sh2s(cycles);
527
528         if (REG8IN16(r, a) != (u8)d) {
529           REG8IN16(r, a) = d;
530           p32x_sh2_poll_event(a, &sh2s[0], SH2_STATE_CPOLL, cycles);
531           p32x_sh2_poll_event(a, &sh2s[1], SH2_STATE_CPOLL, cycles);
532           sh2_poll_write(a & ~1, r[a / 2], cycles, NULL);
533         }
534       }
535       return;
536     case 0x30:
537       return;
538     case 0x31: // PWM control
539       REG8IN16(r, a) &= ~0x0f;
540       REG8IN16(r, a) |= d & 0x0f;
541       d = r[0x30 / 2];
542       goto pwm_write;
543     case 0x32: // PWM cycle
544       REG8IN16(r, a) = d & 0x0f;
545       d = r[0x32 / 2];
546       goto pwm_write;
547     case 0x33:
548       REG8IN16(r, a) = d;
549       d = r[0x32 / 2];
550       goto pwm_write;
551     // PWM pulse regs.. Only writes to odd address send a value
552     // to FIFO; reads are 0 (except status bits)
553     case 0x34:
554     case 0x36:
555     case 0x38:
556       REG8IN16(r, a) = d;
557       return;
558     case 0x35:
559     case 0x37:
560     case 0x39:
561       d = (REG8IN16(r, a ^ 1) << 8) | (d & 0xff);
562       REG8IN16(r, a ^ 1) = 0;
563       goto pwm_write;
564     case 0x3a: // ignored, always 0
565     case 0x3b:
566     case 0x3c:
567     case 0x3d:
568     case 0x3e:
569     case 0x3f:
570       return;
571     pwm_write:
572       p32x_pwm_write16(a & ~1, d, NULL, SekCyclesDone());
573       return;
574   }
575 }
576
577 static void p32x_reg_write16(u32 a, u32 d)
578 {
579   u16 *r = Pico32x.regs;
580   a &= 0x3e;
581
582   // for things like bset on comm port
583   m68k_poll.cnt = 0;
584
585   switch (a/2) {
586     case 0x00/2: // adapter ctl
587       if ((d ^ r[0]) & ~d & P32XS_ADEN) {
588         d |= P32XS_nRES;
589         Pico32xShutdown();
590       } else if ((d ^ r[0]) & d & P32XS_nRES)
591         p32x_reset_sh2s();
592       r[0] &= ~(P32XS_FM|P32XS_nRES|P32XS_ADEN);
593       r[0] |= d & (P32XS_FM|P32XS_nRES|P32XS_ADEN);
594       return;
595     case 0x08/2: // DREQ src
596       r[a / 2] = d & 0xff;
597       return;
598     case 0x0a/2:
599       r[a / 2] = d & ~1;
600       return;
601     case 0x0c/2: // DREQ dest
602       r[a / 2] = d & 0xff;
603       return;
604     case 0x0e/2:
605       r[a / 2] = d;
606       return;
607     case 0x10/2: // DREQ len
608       r[a / 2] = d & ~3;
609       return;
610     case 0x12/2: // FIFO reg
611       dreq0_write(r, d);
612       return;
613     case 0x1a/2: // TV + mystery bit
614       r[a / 2] = d & 0x0101;
615       return;
616     case 0x20/2: // comm port
617     case 0x22/2:
618     case 0x24/2:
619     case 0x26/2:
620     case 0x28/2:
621     case 0x2a/2:
622     case 0x2c/2:
623     case 0x2e/2:
624       { unsigned int cycles = SekCyclesDone();
625
626         if (CYCLES_GT(cycles - msh2.m68krcycles_done, 64))
627           p32x_sync_sh2s(cycles);
628
629         if (r[a / 2] != (u16)d) {
630           r[a / 2] = d;
631           p32x_sh2_poll_event(a, &sh2s[0], SH2_STATE_CPOLL, cycles);
632           p32x_sh2_poll_event(a, &sh2s[1], SH2_STATE_CPOLL, cycles);
633           sh2_poll_write(a, (u16)d, cycles, NULL);
634         }
635       }
636       return;
637     case 0x30/2: // PWM control
638       d = (r[a / 2] & ~0x0f) | (d & 0x0f);
639       r[a / 2] = d;
640       p32x_pwm_write16(a, d, NULL, SekCyclesDone());
641       return;
642     case 0x32/2:
643     case 0x34/2:
644     case 0x36/2:
645     case 0x38/2:
646     case 0x3a/2:
647     case 0x3c/2:
648     case 0x3e/2:
649       p32x_pwm_write16(a, d, NULL, SekCyclesDone());
650       return;
651   }
652
653   p32x_reg_write8(a + 1, d);
654 }
655
656 // ------------------------------------------------------------------
657 // VDP regs
658 static u32 p32x_vdp_read16(u32 a)
659 {
660   u32 d;
661   a &= 0x0e;
662
663   d = Pico32x.vdp_regs[a / 2];
664   if (a == 0x0a) {
665     // tested: FEN seems to be randomly pulsing on hcnt 0x80-0xf0,
666     // most often at 0xb1-0xb5, even during vblank,
667     // what's the deal with that?
668     // we'll just fake it along with hblank for now
669     Pico32x.vdp_fbcr_fake++;
670     if (Pico32x.vdp_fbcr_fake & 4)
671       d |= P32XV_HBLK;
672     if ((Pico32x.vdp_fbcr_fake & 7) == 0)
673       d |= P32XV_nFEN;
674   }
675   return d;
676 }
677
678 static void p32x_vdp_write8(u32 a, u32 d, SH2 *sh2)
679 {
680   u16 *r = Pico32x.vdp_regs;
681   a &= 0x0f;
682
683   // TODO: verify what's writeable
684   switch (a) {
685     case 0x01:
686       // priority inversion is handled in palette
687       if ((r[0] ^ d) & P32XV_PRI) {
688         Pico32xDrawSync(sh2);
689         Pico32x.dirty_pal = 1;
690       }
691       r[0] = (r[0] & P32XV_nPAL) | (d & 0xff);
692       break;
693     case 0x03: // shift (for pp mode)
694       if ((r[2 / 2] ^ d) & P32XV_SFT)
695         Pico32xDrawSync(sh2);
696       r[2 / 2] = d & 1;
697       break;
698     case 0x05: // fill len
699       r[4 / 2] = d & 0xff;
700       break;
701     case 0x0b:
702       d &= P32XV_FS;
703       Pico32x.pending_fb = d;
704       // if we are blanking and FS bit is changing
705       if (((r[0x0a/2] & P32XV_VBLK) || (r[0] & P32XV_Mx) == 0) && ((r[0x0a/2] ^ d) & P32XV_FS)) {
706         r[0x0a/2] ^= P32XV_FS;
707         Pico32xSwapDRAM(d ^ P32XV_FS);
708         elprintf(EL_32X, "VDP FS: %d", r[0x0a/2] & P32XV_FS);
709       }
710       break;
711   }
712 }
713
714 static void p32x_vdp_write16(u32 a, u32 d, SH2 *sh2)
715 {
716   a &= 0x0e;
717   if (a == 6) { // fill start
718     Pico32x.vdp_regs[6 / 2] = d;
719     return;
720   }
721   if (a == 8) { // fill data
722     u16 *dram = Pico32xMem->dram[(Pico32x.vdp_regs[0x0a/2] & P32XV_FS) ^ 1];
723     int len = Pico32x.vdp_regs[4 / 2] + 1;
724     int len1 = len;
725     a = Pico32x.vdp_regs[6 / 2];
726     while (len1--) {
727       dram[a] = d;
728       a = (a & 0xff00) | ((a + 1) & 0xff);
729     }
730     Pico32x.vdp_regs[0x06 / 2] = a;
731     Pico32x.vdp_regs[0x08 / 2] = d;
732     if (sh2 != NULL && len > 8) {
733       Pico32x.vdp_regs[0x0a / 2] |= P32XV_nFEN;
734       // supposedly takes 3 bus/6 sh2 cycles? or 3 sh2 cycles?
735       p32x_event_schedule_sh2(sh2, P32X_EVENT_FILLEND, 3 + len);
736     }
737     return;
738   }
739
740   p32x_vdp_write8(a | 1, d, sh2);
741 }
742
743 // ------------------------------------------------------------------
744 // SH2 regs
745
746 static u32 p32x_sh2reg_read16(u32 a, SH2 *sh2)
747 {
748   u16 *r = Pico32x.regs;
749   unsigned cycles;
750   a &= 0x3e;
751
752   switch (a/2) {
753     case 0x00/2: // adapter/irq ctl
754       return (r[0] & P32XS_FM) | Pico32x.sh2_regs[0]
755         | Pico32x.sh2irq_mask[sh2->is_slave];
756     case 0x04/2: // H count (often as comm too)
757       p32x_sh2_poll_detect(a, sh2, SH2_STATE_CPOLL, 5);
758       cycles = sh2_cycles_done_m68k(sh2);
759       sh2s_sync_on_read(sh2, cycles);
760       return sh2_poll_read(a, Pico32x.sh2_regs[4 / 2], cycles, sh2);
761     case 0x06/2:
762       return (r[a / 2] & ~P32XS_FULL) | 0x4000;
763     case 0x08/2: // DREQ src
764     case 0x0a/2:
765     case 0x0c/2: // DREQ dst
766     case 0x0e/2:
767     case 0x10/2: // DREQ len
768       return r[a / 2];
769     case 0x12/2: // DREQ FIFO - does this work on hw?
770       if (Pico32x.dmac0_fifo_ptr > 0) {
771         Pico32x.dmac0_fifo_ptr--;
772         r[a / 2] = Pico32x.dmac_fifo[0];
773         memmove(&Pico32x.dmac_fifo[0], &Pico32x.dmac_fifo[1],
774           Pico32x.dmac0_fifo_ptr * 2);
775       }
776       return r[a / 2];
777     case 0x14/2:
778     case 0x16/2:
779     case 0x18/2:
780     case 0x1a/2:
781     case 0x1c/2:
782       return 0; // ?
783     case 0x20/2: // comm port
784     case 0x22/2:
785     case 0x24/2:
786     case 0x26/2:
787     case 0x28/2:
788     case 0x2a/2:
789     case 0x2c/2:
790     case 0x2e/2:
791       p32x_sh2_poll_detect(a, sh2, SH2_STATE_CPOLL, 9);
792       cycles = sh2_cycles_done_m68k(sh2);
793       sh2s_sync_on_read(sh2, cycles);
794       return sh2_poll_read(a, r[a / 2], cycles, sh2);
795     case 0x30/2: // PWM
796     case 0x32/2:
797     case 0x34/2:
798     case 0x36/2:
799     case 0x38/2:
800     case 0x3a/2:
801     case 0x3c/2:
802     case 0x3e/2:
803       return p32x_pwm_read16(a, sh2, sh2_cycles_done_m68k(sh2));
804   }
805
806   elprintf_sh2(sh2, EL_32X|EL_ANOMALY, 
807     "unhandled sysreg r16 [%02x] @%08x", a, sh2_pc(sh2));
808   return 0;
809 }
810
811 static void p32x_sh2reg_write8(u32 a, u32 d, SH2 *sh2)
812 {
813   u16 *r = Pico32x.regs;
814   u32 old;
815
816   a &= 0x3f;
817   sh2->poll_cnt = 0;
818
819   switch (a) {
820     case 0x00: // FM
821       r[0] &= ~P32XS_FM;
822       r[0] |= (d << 8) & P32XS_FM;
823       return;
824     case 0x01: // HEN/irq masks
825       old = Pico32x.sh2irq_mask[sh2->is_slave];
826       if ((d ^ old) & 1)
827         p32x_pwm_sync_to_sh2(sh2);
828
829       Pico32x.sh2irq_mask[sh2->is_slave] = d & 0x0f;
830       Pico32x.sh2_regs[0] &= ~0x80;
831       Pico32x.sh2_regs[0] |= d & 0x80;
832
833       if ((old ^ d) & 1)
834         p32x_pwm_schedule_sh2(sh2);
835       if ((old ^ d) & 2)
836         p32x_update_cmd_irq(sh2, 0);
837       if ((old ^ d) & 4)
838         p32x_schedule_hint(sh2, 0); 
839       return;
840     case 0x04: // ignored?
841       return;
842     case 0x05: // H count
843       d &= 0xff;
844       if (Pico32x.sh2_regs[4 / 2] != (u8)d) {
845         unsigned int cycles = sh2_cycles_done_m68k(sh2);
846         Pico32x.sh2_regs[4 / 2] = d;
847         p32x_sh2_poll_event(a, sh2->other_sh2, SH2_STATE_CPOLL, cycles);
848         if (p32x_sh2_ready(sh2->other_sh2, cycles+8))
849           sh2_end_run(sh2, 4);
850         sh2_poll_write(a & ~1, d, cycles, sh2);
851       }
852       return;
853     case 0x20: // comm port
854     case 0x21:
855     case 0x22:
856     case 0x23:
857     case 0x24:
858     case 0x25:
859     case 0x26:
860     case 0x27:
861     case 0x28:
862     case 0x29:
863     case 0x2a:
864     case 0x2b:
865     case 0x2c:
866     case 0x2d:
867     case 0x2e:
868     case 0x2f:
869       if (REG8IN16(r, a) != (u8)d) {
870         unsigned int cycles = sh2_cycles_done_m68k(sh2);
871
872         REG8IN16(r, a) = d;
873         p32x_m68k_poll_event(a, P32XF_68KCPOLL);
874         p32x_sh2_poll_event(a, sh2->other_sh2, SH2_STATE_CPOLL, cycles);
875         if (p32x_sh2_ready(sh2->other_sh2, cycles+8))
876           sh2_end_run(sh2, 0);
877         sh2_poll_write(a & ~1, r[a / 2], cycles, sh2);
878       }
879       return;
880     case 0x30:
881       REG8IN16(r, a) = d & 0x0f;
882       d = r[0x30 / 2];
883       goto pwm_write;
884     case 0x31: // PWM control
885       REG8IN16(r, a) = d & 0x8f;
886       d = r[0x30 / 2];
887       goto pwm_write;
888     case 0x32: // PWM cycle
889       REG8IN16(r, a) = d & 0x0f;
890       d = r[0x32 / 2];
891       goto pwm_write;
892     case 0x33:
893       REG8IN16(r, a) = d;
894       d = r[0x32 / 2];
895       goto pwm_write;
896     // PWM pulse regs.. Only writes to odd address send a value
897     // to FIFO; reads are 0 (except status bits)
898     case 0x34:
899     case 0x36:
900     case 0x38:
901       REG8IN16(r, a) = d;
902       return;
903     case 0x35:
904     case 0x37:
905     case 0x39:
906       d = (REG8IN16(r, a ^ 1) << 8) | (d & 0xff);
907       REG8IN16(r, a ^ 1) = 0;
908       goto pwm_write;
909     case 0x3a: // ignored, always 0?
910     case 0x3b:
911     case 0x3c:
912     case 0x3d:
913     case 0x3e:
914     case 0x3f:
915       return;
916     pwm_write:
917       p32x_pwm_write16(a & ~1, d, sh2, sh2_cycles_done_m68k(sh2));
918       return;
919   }
920
921   elprintf(EL_32X|EL_ANOMALY,
922     "unhandled sysreg w8  [%02x] %02x @%08x", a, d, sh2_pc(sh2));
923 }
924
925 static void p32x_sh2reg_write16(u32 a, u32 d, SH2 *sh2)
926 {
927   a &= 0x3e;
928
929   sh2->poll_cnt = 0;
930
931   switch (a/2) {
932     case 0x00/2: // FM
933       Pico32x.regs[0] &= ~P32XS_FM;
934       Pico32x.regs[0] |= d & P32XS_FM;
935       break;
936     case 0x14/2:
937       Pico32x.sh2irqi[sh2->is_slave] &= ~P32XI_VRES;
938       goto irls;
939     case 0x16/2:
940       Pico32x.sh2irqi[sh2->is_slave] &= ~P32XI_VINT;
941       goto irls;
942     case 0x18/2:
943       Pico32x.sh2irqi[sh2->is_slave] &= ~P32XI_HINT;
944       goto irls;
945     case 0x1a/2:
946       Pico32x.regs[2 / 2] &= ~(1 << sh2->is_slave);
947       p32x_update_cmd_irq(sh2, 0);
948       return;
949     case 0x1c/2:
950       p32x_pwm_sync_to_sh2(sh2);
951       Pico32x.sh2irqi[sh2->is_slave] &= ~P32XI_PWM;
952       p32x_pwm_schedule_sh2(sh2);
953       goto irls;
954     case 0x20/2: // comm port
955     case 0x22/2:
956     case 0x24/2:
957     case 0x26/2:
958     case 0x28/2:
959     case 0x2a/2:
960     case 0x2c/2:
961     case 0x2e/2:
962       if (Pico32x.regs[a / 2] != (u16)d) {
963         unsigned int cycles = sh2_cycles_done_m68k(sh2);
964
965         Pico32x.regs[a / 2] = d;
966         p32x_m68k_poll_event(a, P32XF_68KCPOLL);
967         p32x_sh2_poll_event(a, sh2->other_sh2, SH2_STATE_CPOLL, cycles);
968         if (p32x_sh2_ready(sh2->other_sh2, cycles+8))
969           sh2_end_run(sh2, 0);
970         sh2_poll_write(a, d, cycles, sh2);
971       }
972       return;
973     case 0x30/2: // PWM
974     case 0x32/2:
975     case 0x34/2:
976     case 0x36/2:
977     case 0x38/2:
978     case 0x3a/2:
979     case 0x3c/2:
980     case 0x3e/2:
981       p32x_pwm_write16(a, d, sh2, sh2_cycles_done_m68k(sh2));
982       return;
983   }
984
985   p32x_sh2reg_write8(a | 1, d, sh2);
986   return;
987
988 irls:
989   p32x_update_irls(sh2, 0);
990 }
991
992 // ------------------------------------------------------------------
993 // 32x 68k handlers
994
995 // after ADEN
996 static u32 PicoRead8_32x_on(u32 a)
997 {
998   u32 d = 0;
999   if ((a & 0xffc0) == 0x5100) { // a15100
1000     d = p32x_reg_read16(a);
1001     goto out_16to8;
1002   }
1003
1004   if ((a & 0xfc00) != 0x5000) {
1005     if (PicoIn.AHW & PAHW_MCD)
1006       return PicoRead8_mcd_io(a);
1007     else
1008       return PicoRead8_io(a);
1009   }
1010
1011   if ((a & 0xfff0) == 0x5180) { // a15180
1012     d = p32x_vdp_read16(a);
1013     goto out_16to8;
1014   }
1015
1016   if ((a & 0xfe00) == 0x5200) { // a15200
1017     d = Pico32xMem->pal[(a & 0x1ff) / 2];
1018     goto out_16to8;
1019   }
1020
1021   if ((a & 0xfffc) == 0x30ec) { // a130ec
1022     d = str_mars[a & 3];
1023     goto out;
1024   }
1025
1026   elprintf(EL_UIO, "m68k unmapped r8  [%06x] @%06x", a, SekPc);
1027   return d;
1028
1029 out_16to8:
1030   if (a & 1)
1031     d &= 0xff;
1032   else
1033     d >>= 8;
1034
1035 out:
1036   elprintf(EL_32X, "m68k 32x r8  [%06x]   %02x @%06x", a, d, SekPc);
1037   return d;
1038 }
1039
1040 static u32 PicoRead16_32x_on(u32 a)
1041 {
1042   u32 d = 0;
1043   if ((a & 0xffc0) == 0x5100) { // a15100
1044     d = p32x_reg_read16(a);
1045     goto out;
1046   }
1047
1048   if ((a & 0xfc00) != 0x5000) {
1049     if (PicoIn.AHW & PAHW_MCD)
1050       return PicoRead16_mcd_io(a);
1051     else
1052       return PicoRead16_io(a);
1053   }
1054
1055   if ((a & 0xfff0) == 0x5180) { // a15180
1056     d = p32x_vdp_read16(a);
1057     goto out;
1058   }
1059
1060   if ((a & 0xfe00) == 0x5200) { // a15200
1061     d = Pico32xMem->pal[(a & 0x1ff) / 2];
1062     goto out;
1063   }
1064
1065   if ((a & 0xfffc) == 0x30ec) { // a130ec
1066     d = !(a & 2) ? ('M'<<8)|'A' : ('R'<<8)|'S';
1067     goto out;
1068   }
1069
1070   elprintf(EL_UIO, "m68k unmapped r16 [%06x] @%06x", a, SekPc);
1071   return d;
1072
1073 out:
1074   elprintf(EL_32X, "m68k 32x r16 [%06x] %04x @%06x", a, d, SekPc);
1075   return d;
1076 }
1077
1078 static void PicoWrite8_32x_on(u32 a, u32 d)
1079 {
1080   if ((a & 0xfc00) == 0x5000)
1081     elprintf(EL_32X, "m68k 32x w8  [%06x]   %02x @%06x", a, d & 0xff, SekPc);
1082
1083   if ((a & 0xffc0) == 0x5100) { // a15100
1084     p32x_reg_write8(a, d);
1085     return;
1086   }
1087
1088   if ((a & 0xfc00) != 0x5000) {
1089     m68k_write8_io(a, d);
1090     return;
1091   }
1092
1093   if (!(Pico32x.regs[0] & P32XS_FM)) {
1094     if ((a & 0xfff0) == 0x5180) { // a15180
1095       p32x_vdp_write8(a, d, NULL);
1096       return;
1097     }
1098
1099     // TODO: verify
1100     if ((a & 0xfe00) == 0x5200) { // a15200
1101       elprintf(EL_32X|EL_ANOMALY, "m68k 32x PAL w8  [%06x]   %02x @%06x", a, d & 0xff, SekPc);
1102       if (((u8 *)Pico32xMem->pal)[MEM_BE2(a & 0x1ff)] != d)
1103         Pico32xDrawSync(NULL);
1104       ((u8 *)Pico32xMem->pal)[MEM_BE2(a & 0x1ff)] = d;
1105       Pico32x.dirty_pal = 1;
1106       return;
1107     }
1108   }
1109
1110   elprintf(EL_UIO, "m68k unmapped w8  [%06x]   %02x @%06x", a, d & 0xff, SekPc);
1111 }
1112
1113 static void PicoWrite8_32x_on_io(u32 a, u32 d)
1114 {
1115   PicoWrite8_io(a, d);
1116   if (a == 0xa130f1)
1117     bank_switch_rom_68k(Pico32x.regs[4 / 2]);
1118 }
1119
1120 static void PicoWrite8_32x_on_io_cd(u32 a, u32 d)
1121 {
1122   PicoWrite8_mcd_io(a, d);
1123   if (a == 0xa130f1)
1124     bank_switch_rom_68k(Pico32x.regs[4 / 2]);
1125 }
1126
1127 static void PicoWrite8_32x_on_io_ssf2(u32 a, u32 d)
1128 {
1129   carthw_ssf2_write8(a, d);
1130   if ((a & ~0x0e) == 0xa130f1)
1131     bank_switch_rom_68k(Pico32x.regs[4 / 2]);
1132 }
1133
1134 static void PicoWrite16_32x_on(u32 a, u32 d)
1135 {
1136   if ((a & 0xfc00) == 0x5000)
1137     elprintf(EL_32X, "m68k 32x w16 [%06x] %04x @%06x", a, d & 0xffff, SekPc);
1138
1139   if ((a & 0xffc0) == 0x5100) { // a15100
1140     p32x_reg_write16(a, d);
1141     return;
1142   }
1143
1144   if ((a & 0xfc00) != 0x5000) {
1145     m68k_write16_io(a, d);
1146     return;
1147   }
1148
1149   if (!(Pico32x.regs[0] & P32XS_FM)) {
1150     if ((a & 0xfff0) == 0x5180) { // a15180
1151       p32x_vdp_write16(a, d, NULL); // FIXME?
1152       return;
1153     }
1154
1155     if ((a & 0xfe00) == 0x5200) { // a15200
1156       if (Pico32xMem->pal[(a & 0x1ff) / 2] != d)
1157         Pico32xDrawSync(NULL);
1158       Pico32xMem->pal[(a & 0x1ff) / 2] = d;
1159       Pico32x.dirty_pal = 1;
1160       return;
1161     }
1162   }
1163
1164   elprintf(EL_UIO, "m68k unmapped w16 [%06x] %04x @%06x", a, d & 0xffff, SekPc);
1165 }
1166
1167 static void PicoWrite16_32x_on_io(u32 a, u32 d)
1168 {
1169   PicoWrite16_io(a, d);
1170   if (a == 0xa130f0)
1171     bank_switch_rom_68k(Pico32x.regs[4 / 2]);
1172 }
1173
1174 static void PicoWrite16_32x_on_io_cd(u32 a, u32 d)
1175 {
1176   PicoWrite16_mcd_io(a, d);
1177   if (a == 0xa130f0)
1178     bank_switch_rom_68k(Pico32x.regs[4 / 2]);
1179 }
1180
1181 static void PicoWrite16_32x_on_io_ssf2(u32 a, u32 d)
1182 {
1183   carthw_ssf2_write16(a, d);
1184   if (a == 0x130f0)
1185     bank_switch_rom_68k(Pico32x.regs[4 / 2]);
1186 }
1187
1188 // before ADEN
1189 u32 PicoRead8_32x(u32 a)
1190 {
1191   u32 d = 0;
1192
1193   if (PicoIn.opt & POPT_EN_32X) {
1194     if ((a & 0xffc0) == 0x5100) { // a15100
1195       // regs are always readable
1196       d = ((u8 *)Pico32x.regs)[MEM_BE2(a & 0x3f)];
1197       goto out;
1198     }
1199
1200     if ((a & 0xfffc) == 0x30ec) { // a130ec
1201       d = str_mars[a & 3];
1202       goto out;
1203     }
1204   }
1205
1206   elprintf(EL_UIO, "m68k unmapped r8  [%06x] @%06x", a, SekPc);
1207   return d;
1208
1209 out:
1210   elprintf(EL_32X, "m68k 32x r8  [%06x]   %02x @%06x", a, d, SekPc);
1211   return d;
1212 }
1213
1214 u32 PicoRead16_32x(u32 a)
1215 {
1216   u32 d = 0;
1217
1218   if (PicoIn.opt & POPT_EN_32X) {
1219     if ((a & 0xffc0) == 0x5100) { // a15100
1220       d = Pico32x.regs[(a & 0x3f) / 2];
1221       goto out;
1222     }
1223
1224     if ((a & 0xfffc) == 0x30ec) { // a130ec
1225       d = !(a & 2) ? ('M'<<8)|'A' : ('R'<<8)|'S';
1226       goto out;
1227     }
1228   }
1229
1230   elprintf(EL_UIO, "m68k unmapped r16 [%06x] @%06x", a, SekPc);
1231   return d;
1232
1233 out:
1234   elprintf(EL_32X, "m68k 32x r16 [%06x] %04x @%06x", a, d, SekPc);
1235   return d;
1236 }
1237
1238 void PicoWrite8_32x(u32 a, u32 d)
1239 {
1240   if ((PicoIn.opt & POPT_EN_32X) && (a & 0xffc0) == 0x5100) // a15100
1241   {
1242     u16 *r = Pico32x.regs;
1243     u8 *r8 = (u8 *)r;
1244
1245     elprintf(EL_32X, "m68k 32x w8  [%06x]   %02x @%06x", a, d & 0xff, SekPc);
1246     a &= 0x3f;
1247     switch (a) {
1248       case 0x00:
1249         r8[MEM_BE2(a)] = d & (P32XS_FM>>8);
1250         return;
1251       case 0x01:
1252         if ((d ^ r[0]) & d & P32XS_ADEN) {
1253           Pico32xStartup();
1254           r[0] &= ~P32XS_nRES; // causes reset if specified by this write
1255           r[0] |= P32XS_ADEN;
1256           p32x_reg_write8(a, d); // forward for reset processing
1257         }
1258         else {
1259           r[0] &= ~(P32XS_nRES|P32XS_ADEN);
1260           r[0] |= d & (P32XS_nRES|P32XS_ADEN);
1261         }
1262         return;
1263       case 0x03: r8[MEM_BE2(a)] = d &    3; return;
1264       case 0x05: r8[MEM_BE2(a)] = d &    3; return;
1265       case 0x07: r8[MEM_BE2(a)] = d &    7; return;
1266       case 0x09: r8[MEM_BE2(a)] = d       ; return;
1267       case 0x0a: r8[MEM_BE2(a)] = d       ; return;
1268       case 0x0b: r8[MEM_BE2(a)] = d & 0xfe; return;
1269       case 0x0d: r8[MEM_BE2(a)] = d       ; return;
1270       case 0x0e: r8[MEM_BE2(a)] = d       ; return;
1271       case 0x0f: r8[MEM_BE2(a)] = d       ; return;
1272       case 0x10: r8[MEM_BE2(a)] = d       ; return;
1273       case 0x11: r8[MEM_BE2(a)] = d & 0xfc; return;
1274       case 0x1a: r8[MEM_BE2(a)] = d &    1; return;
1275       case 0x1b: r8[MEM_BE2(a)] = d &    1; return;
1276       case 0x20: case 0x21: case 0x22: case 0x23: // COMM
1277       case 0x24: case 0x25: case 0x26: case 0x27:
1278       case 0x28: case 0x29: case 0x2a: case 0x2b:
1279       case 0x2c: case 0x2d: case 0x2e: case 0x2f:
1280         r8[MEM_BE2(a)] = d;
1281         return;
1282     }
1283   }
1284
1285   elprintf(EL_UIO, "m68k unmapped w8  [%06x]   %02x @%06x", a, d & 0xff, SekPc);
1286 }
1287
1288 void PicoWrite16_32x(u32 a, u32 d)
1289 {
1290   if ((PicoIn.opt & POPT_EN_32X) && (a & 0xffc0) == 0x5100) // a15100
1291   {
1292     u16 *r = Pico32x.regs;
1293
1294     elprintf(EL_32X, "m68k 32x w16 [%06x] %04x @%06x", a, d & 0xffff, SekPc);
1295     a &= 0x3e;
1296     switch (a) {
1297       case 0x00:
1298         if ((d ^ r[0]) & d & P32XS_ADEN) {
1299           Pico32xStartup();
1300           r[0] &= ~(P32XS_FM|P32XS_nRES|P32XS_ADEN);
1301           // causes reset if specified by this write
1302           r[0] |= d & (P32XS_FM|P32XS_ADEN);
1303           p32x_reg_write16(a, d); // forward for reset processing
1304         }
1305         else {
1306           r[0] &= ~(P32XS_FM|P32XS_nRES|P32XS_ADEN);
1307           r[0] |= d & (P32XS_FM|P32XS_nRES|P32XS_ADEN);
1308         }
1309         return;
1310       case 0x02: r[a / 2] = d &      3; return;
1311       case 0x04: r[a / 2] = d &      3; return;
1312       case 0x06: r[a / 2] = d &      7; return;
1313       case 0x08: r[a / 2] = d & 0x00ff; return;
1314       case 0x0a: r[a / 2] = d & 0xfffe; return;
1315       case 0x0c: r[a / 2] = d & 0x00ff; return;
1316       case 0x0e: r[a / 2] = d         ; return;
1317       case 0x10: r[a / 2] = d & 0xfffc; return;
1318       case 0x1a: r[a / 2] = d & 0x0101; return;
1319       case 0x20: case 0x22: // COMM
1320       case 0x24: case 0x26:
1321       case 0x28: case 0x2a:
1322       case 0x2c: case 0x2e:
1323         r[a / 2] = d;
1324         return;
1325     }
1326   }
1327
1328   elprintf(EL_UIO, "m68k unmapped w16 [%06x] %04x @%06x", a, d & 0xffff, SekPc);
1329 }
1330
1331 /* quirk: in both normal and overwrite areas only nonzero values go through */
1332 #define sh2_write8_dramN(p, a, d) \
1333   if ((d & 0xff) != 0) { \
1334     u8 *dram = (u8 *)p; \
1335     dram[MEM_BE2(a & 0x1ffff)] = d; \
1336   }
1337
1338 static void m68k_write8_dram0_ow(u32 a, u32 d)
1339 {
1340   sh2_write8_dramN(Pico32xMem->dram[0], a, d);
1341 }
1342
1343 static void m68k_write8_dram1_ow(u32 a, u32 d)
1344 {
1345   sh2_write8_dramN(Pico32xMem->dram[1], a, d);
1346 }
1347
1348 #define sh2_write16_dramN(p, a, d) \
1349   u16 *pd = &((u16 *)p)[(a & 0x1ffff) / 2]; \
1350   if (!(a & 0x20000)) { \
1351     *pd = d; \
1352   } else { \
1353     u16 v = *pd; /* overwrite */ \
1354     if (!(d & 0x00ff)) d |= v & 0x00ff; \
1355     if (!(d & 0xff00)) d |= v & 0xff00; \
1356     *pd = d; \
1357   }
1358
1359 static void m68k_write16_dram0_ow(u32 a, u32 d)
1360 {
1361   sh2_write16_dramN(Pico32xMem->dram[0], a, d);
1362 }
1363
1364 static void m68k_write16_dram1_ow(u32 a, u32 d)
1365 {
1366   sh2_write16_dramN(Pico32xMem->dram[1], a, d);
1367 }
1368
1369 // -----------------------------------------------------------------
1370
1371 // hint vector is writeable
1372 static void PicoWrite8_hint(u32 a, u32 d)
1373 {
1374   if ((a & 0xfffc) == 0x0070) {
1375     Pico32xMem->m68k_rom[MEM_BE2(a)] = d;
1376     return;
1377   }
1378
1379   elprintf(EL_UIO, "m68k unmapped w8  [%06x]   %02x @%06x",
1380     a, d & 0xff, SekPc);
1381 }
1382
1383 static void PicoWrite16_hint(u32 a, u32 d)
1384 {
1385   if ((a & 0xfffc) == 0x0070) {
1386     ((u16 *)Pico32xMem->m68k_rom)[a/2] = d;
1387     return;
1388   }
1389
1390   elprintf(EL_UIO, "m68k unmapped w16 [%06x] %04x @%06x",
1391     a, d & 0xffff, SekPc);
1392 }
1393
1394 // normally not writable, but somebody could make a RAM cart
1395 static void PicoWrite8_cart(u32 a, u32 d)
1396 {
1397   elprintf(EL_UIO, "m68k w8  [%06x]   %02x @%06x", a, d & 0xff, SekPc);
1398
1399   a &= 0xfffff;
1400   m68k_write8(a, d);
1401 }
1402
1403 static void PicoWrite16_cart(u32 a, u32 d)
1404 {
1405   elprintf(EL_UIO, "m68k w16 [%06x] %04x @%06x", a, d & 0xffff, SekPc);
1406
1407   a &= 0xfffff;
1408   m68k_write16(a, d);
1409 }
1410
1411 // same with bank, but save ram is sometimes here
1412 static u32 PicoRead8_bank(u32 a)
1413 {
1414   a = (Pico32x.regs[4 / 2] << 20) | (a & 0xfffff);
1415   return m68k_read8(a);
1416 }
1417
1418 static u32 PicoRead16_bank(u32 a)
1419 {
1420   a = (Pico32x.regs[4 / 2] << 20) | (a & 0xfffff);
1421   return m68k_read16(a);
1422 }
1423
1424 static void PicoWrite8_bank(u32 a, u32 d)
1425 {
1426   if (!(Pico.m.sram_reg & SRR_MAPPED))
1427     elprintf(EL_UIO, "m68k w8  [%06x]   %02x @%06x",
1428       a, d & 0xff, SekPc);
1429
1430   a = (Pico32x.regs[4 / 2] << 20) | (a & 0xfffff);
1431   m68k_write8(a, d);
1432 }
1433
1434 static void PicoWrite16_bank(u32 a, u32 d)
1435 {
1436   if (!(Pico.m.sram_reg & SRR_MAPPED))
1437     elprintf(EL_UIO, "m68k w16 [%06x] %04x @%06x",
1438       a, d & 0xffff, SekPc);
1439
1440   a = (Pico32x.regs[4 / 2] << 20) | (a & 0xfffff);
1441   m68k_write16(a, d);
1442 }
1443
1444 static void bank_map_handler(void)
1445 {
1446   cpu68k_map_read_funcs(0x900000, 0x9fffff, PicoRead8_bank, PicoRead16_bank, 0);
1447 }
1448
1449 static void bank_switch_rom_68k(int b)
1450 {
1451   unsigned int rs, bank, bank2;
1452
1453   if (Pico.m.ncart_in)
1454     return;
1455
1456   bank = b << 20;
1457   if ((Pico.m.sram_reg & SRR_MAPPED) && bank == Pico.sv.start) {
1458     bank_map_handler();
1459     return;
1460   }
1461
1462   if (bank >= Pico.romsize) {
1463     elprintf(EL_32X|EL_ANOMALY, "missing bank @ %06x", bank);
1464     bank_map_handler();
1465     return;
1466   }
1467
1468   // 32X ROM (XXX: consider mirroring?)
1469   rs = (Pico.romsize + M68K_BANK_MASK) & ~M68K_BANK_MASK;
1470   if (!carthw_ssf2_active) {
1471     rs -= bank;
1472     if (rs > 0x100000)
1473       rs = 0x100000;
1474     cpu68k_map_read_mem(0x900000, 0x900000 + rs - 1, Pico.rom + bank, 0);
1475     elprintf(EL_32X, "bank %06x-%06x -> %06x", 0x900000, 0x900000 + rs - 1, bank);
1476   }
1477   else {
1478     bank = bank >> 19;
1479     bank2 = carthw_ssf2_banks[bank + 0] << 19;
1480     cpu68k_map_read_mem(0x900000, 0x97ffff, Pico.rom + bank2, 0);
1481     bank2 = carthw_ssf2_banks[bank + 1] << 19;
1482     cpu68k_map_read_mem(0x980000, 0x9fffff, Pico.rom + bank2, 0);
1483   }
1484 }
1485
1486 // -----------------------------------------------------------------
1487 //                              SH2  
1488 // -----------------------------------------------------------------
1489
1490 // read8
1491 static REGPARM(2) u32 sh2_read8_unmapped(u32 a, SH2 *sh2)
1492 {
1493   elprintf_sh2(sh2, EL_32X, "unmapped r8  [%08x]       %02x @%06x",
1494     a, 0, sh2_pc(sh2));
1495   return 0;
1496 }
1497
1498 static u32 REGPARM(2) sh2_read8_cs0(u32 a, SH2 *sh2)
1499 {
1500   u32 d = 0;
1501   DRC_SAVE_SR(sh2);
1502
1503   sh2_burn_cycles(sh2, 1*2);
1504
1505   // 0x3ffc0 is verified
1506   if ((a & 0x3ffc0) == 0x4000) {
1507     d = p32x_sh2reg_read16(a, sh2);
1508     goto out_16to8;
1509   }
1510
1511   if ((a & 0x3fff0) == 0x4100) {
1512     d = p32x_vdp_read16(a);
1513     p32x_sh2_poll_detect(a, sh2, SH2_STATE_VPOLL, 9);
1514     goto out_16to8;
1515   }
1516
1517   if ((a & 0x3fe00) == 0x4200) {
1518     d = Pico32xMem->pal[(a & 0x1ff) / 2];
1519     goto out_16to8;
1520   }
1521
1522   // TODO: mirroring?
1523   if (!sh2->is_slave && a < sizeof(Pico32xMem->sh2_rom_m))
1524     d = Pico32xMem->sh2_rom_m.b[MEM_BE2(a)];
1525   else if (sh2->is_slave  && a < sizeof(Pico32xMem->sh2_rom_s))
1526     d = Pico32xMem->sh2_rom_s.b[MEM_BE2(a)];
1527   else
1528     d = sh2_read8_unmapped(a, sh2);
1529   goto out;
1530
1531 out_16to8:
1532   if (a & 1)
1533     d &= 0xff;
1534   else
1535     d >>= 8;
1536
1537 out:
1538   elprintf_sh2(sh2, EL_32X, "r8  [%08x]       %02x @%06x",
1539     a, d, sh2_pc(sh2));
1540   DRC_RESTORE_SR(sh2);
1541   return (s8)d;
1542 }
1543
1544 // for ssf2
1545 static u32 REGPARM(2) sh2_read8_rom(u32 a, SH2 *sh2)
1546 {
1547   u32 bank = carthw_ssf2_banks[(a >> 19) & 7] << 19;
1548   s8 *p = sh2->p_rom;
1549   return p[MEM_BE2(bank + (a & 0x7ffff))];
1550 }
1551
1552 // read16
1553 static u32 REGPARM(2) sh2_read16_unmapped(u32 a, SH2 *sh2)
1554 {
1555   elprintf_sh2(sh2, EL_32X, "unmapped r16 [%08x]     %04x @%06x",
1556     a, 0, sh2_pc(sh2));
1557   return 0;
1558 }
1559
1560 static u32 REGPARM(2) sh2_read16_cs0(u32 a, SH2 *sh2)
1561 {
1562   u32 d = 0;
1563   DRC_SAVE_SR(sh2);
1564
1565   sh2_burn_cycles(sh2, 1*2);
1566
1567   if ((a & 0x3ffc0) == 0x4000) {
1568     d = p32x_sh2reg_read16(a, sh2);
1569     if (!(EL_LOGMASK & EL_PWM) && (a & 0x30) == 0x30) // hide PWM
1570       goto out_noprint;
1571     goto out;
1572   }
1573
1574   if ((a & 0x3fff0) == 0x4100) {
1575     d = p32x_vdp_read16(a);
1576     p32x_sh2_poll_detect(a, sh2, SH2_STATE_VPOLL, 9);
1577     goto out;
1578   }
1579
1580   if ((a & 0x3fe00) == 0x4200) {
1581     d = Pico32xMem->pal[(a & 0x1ff) / 2];
1582     goto out;
1583   }
1584
1585   if (!sh2->is_slave && a < sizeof(Pico32xMem->sh2_rom_m))
1586     d = Pico32xMem->sh2_rom_m.w[a / 2];
1587   else if (sh2->is_slave  && a < sizeof(Pico32xMem->sh2_rom_s))
1588     d = Pico32xMem->sh2_rom_s.w[a / 2];
1589   else
1590     d = sh2_read16_unmapped(a, sh2);
1591
1592 out:
1593   elprintf_sh2(sh2, EL_32X, "r16 [%08x]     %04x @%06x",
1594     a, d, sh2_pc(sh2));
1595 out_noprint:
1596   DRC_RESTORE_SR(sh2);
1597   return (s16)d;
1598 }
1599
1600 static u32 REGPARM(2) sh2_read16_rom(u32 a, SH2 *sh2)
1601 {
1602   u32 bank = carthw_ssf2_banks[(a >> 19) & 7] << 19;
1603   s16 *p = sh2->p_rom;
1604   return p[(bank + (a & 0x7fffe)) / 2];
1605 }
1606
1607 static u32 REGPARM(2) sh2_read32_unmapped(u32 a, SH2 *sh2)
1608 {
1609   elprintf_sh2(sh2, EL_32X, "unmapped r32 [%08x]     %08x @%06x",
1610     a, 0, sh2_pc(sh2));
1611   return 0;
1612 }
1613
1614 static u32 REGPARM(2) sh2_read32_cs0(u32 a, SH2 *sh2)
1615 {
1616   u32 d1 = sh2_read16_cs0(a, sh2) << 16, d2 = sh2_read16_cs0(a + 2, sh2) << 16;
1617   return d1 | (d2 >> 16);
1618 }
1619
1620 static u32 REGPARM(2) sh2_read32_rom(u32 a, SH2 *sh2)
1621 {
1622   u32 bank = carthw_ssf2_banks[(a >> 19) & 7] << 19;
1623   u32 *p = sh2->p_rom;
1624   u32 d = p[(bank + (a & 0x7fffc)) / 4];
1625   return CPU_BE2(d);
1626 }
1627
1628 // writes
1629 #ifdef DRC_SH2
1630 static void sh2_sdram_poll(u32 a, u32 d, SH2 *sh2)
1631 {
1632   unsigned cycles;
1633
1634   DRC_SAVE_SR(sh2);
1635   cycles = sh2_cycles_done_m68k(sh2);
1636   sh2_poll_write(a, d, cycles, sh2);
1637   p32x_sh2_poll_event(a, sh2->other_sh2, SH2_STATE_RPOLL, cycles);
1638   if (p32x_sh2_ready(sh2->other_sh2, cycles+8))
1639     sh2_end_run(sh2, 0);
1640   DRC_RESTORE_SR(sh2);
1641 }
1642
1643 void NOINLINE sh2_sdram_checks(u32 a, u32 d, SH2 *sh2, u32 t)
1644 {
1645   if (t & 0x80)         sh2_sdram_poll(a, d, sh2);
1646   if (t & 0x7f)         sh2_drc_wcheck_ram(a, 2, sh2);
1647 }
1648
1649 void NOINLINE sh2_sdram_checks_l(u32 a, u32 d, SH2 *sh2, u32 t)
1650 {
1651   if (t & 0x000080)     sh2_sdram_poll(a, d>>16, sh2);
1652   if (t & 0x800000)     sh2_sdram_poll(a+2, d, sh2);
1653   if (t & ~0x800080)    sh2_drc_wcheck_ram(a, 4, sh2);
1654 }
1655
1656 #ifndef _ASM_32X_MEMORY_C
1657 static void sh2_da_checks(u32 a, u32 t, SH2 *sh2)
1658 {
1659   sh2_drc_wcheck_da(a, 2, sh2);
1660 }
1661
1662 static void sh2_da_checks_l(u32 a, u32 t, SH2 *sh2)
1663 {
1664   sh2_drc_wcheck_da(a, 4, sh2);
1665 }
1666 #endif
1667 #endif
1668
1669 static void REGPARM(3) sh2_write_ignore(u32 a, u32 d, SH2 *sh2)
1670 {
1671 }
1672
1673 // write8
1674 static void REGPARM(3) sh2_write8_unmapped(u32 a, u32 d, SH2 *sh2)
1675 {
1676   elprintf_sh2(sh2, EL_32X, "unmapped w8  [%08x]       %02x @%06x",
1677     a, d & 0xff, sh2_pc(sh2));
1678 }
1679
1680 static void REGPARM(3) sh2_write8_cs0(u32 a, u32 d, SH2 *sh2)
1681 {
1682   DRC_SAVE_SR(sh2);
1683   elprintf_sh2(sh2, EL_32X, "w8  [%08x]       %02x @%06x",
1684     a, d & 0xff, sh2_pc(sh2));
1685
1686   if ((a & 0x3ffc0) == 0x4000) {
1687     p32x_sh2reg_write8(a, d, sh2);
1688     goto out;
1689   }
1690
1691   if (Pico32x.regs[0] & P32XS_FM) {
1692     if ((a & 0x3fff0) == 0x4100) {
1693       sh2->poll_cnt = 0;
1694       p32x_vdp_write8(a, d, sh2);
1695       goto out;
1696     }
1697
1698     if ((a & 0x3fe00) == 0x4200) {
1699       sh2->poll_cnt = 0;
1700       if (((u8 *)Pico32xMem->pal)[MEM_BE2(a & 0x1ff)] != d)
1701         Pico32xDrawSync(sh2);
1702       ((u8 *)Pico32xMem->pal)[MEM_BE2(a & 0x1ff)] = d;
1703       Pico32x.dirty_pal = 1;
1704       goto out;
1705     }
1706   }
1707
1708   sh2_write8_unmapped(a, d, sh2);
1709 out:
1710   DRC_RESTORE_SR(sh2);
1711 }
1712
1713 #ifdef _ASM_32X_MEMORY_C
1714 extern void REGPARM(3) sh2_write8_dram(u32 a, u32 d, SH2 *sh2);
1715 extern void REGPARM(3) sh2_write8_sdram(u32 a, u32 d, SH2 *sh2);
1716 extern void REGPARM(3) sh2_write8_da(u32 a, u32 d, SH2 *sh2);
1717 #else
1718 static void REGPARM(3) sh2_write8_dram(u32 a, u32 d, SH2 *sh2)
1719 {
1720   sh2_write8_dramN(sh2->p_dram, a, d);
1721 }
1722
1723 static void REGPARM(3) sh2_write8_sdram(u32 a, u32 d, SH2 *sh2)
1724 {
1725   u32 a1 = MEM_BE2(a & 0x3ffff);
1726   ((u8 *)sh2->p_sdram)[a1] = d;
1727 #ifdef DRC_SH2
1728   u8 *p = sh2->p_drcblk_ram;
1729   u32 t = p[a1 >> SH2_DRCBLK_RAM_SHIFT];
1730   if (t)
1731     sh2_sdram_checks(a & ~1, ((u16 *)sh2->p_sdram)[a1 / 2], sh2, t);
1732 #endif
1733 }
1734
1735 static void REGPARM(3) sh2_write8_da(u32 a, u32 d, SH2 *sh2)
1736 {
1737   u32 a1 = MEM_BE2(a & 0xfff);
1738   sh2->data_array[a1] = d;
1739 #ifdef DRC_SH2
1740   u8 *p = sh2->p_drcblk_da;
1741   u32 t = p[a1 >> SH2_DRCBLK_DA_SHIFT];
1742   if (t)
1743     sh2_da_checks(a, t, sh2);
1744 #endif
1745 }
1746 #endif
1747
1748 // write16
1749 static void REGPARM(3) sh2_write16_unmapped(u32 a, u32 d, SH2 *sh2)
1750 {
1751   elprintf_sh2(sh2, EL_32X, "unmapped w16 [%08x]     %04x @%06x",
1752     a, d & 0xffff, sh2_pc(sh2));
1753 }
1754
1755 static void REGPARM(3) sh2_write16_cs0(u32 a, u32 d, SH2 *sh2)
1756 {
1757   DRC_SAVE_SR(sh2);
1758   if (((EL_LOGMASK & EL_PWM) || (a & 0x30) != 0x30)) // hide PWM
1759     elprintf_sh2(sh2, EL_32X, "w16 [%08x]     %04x @%06x",
1760       a, d & 0xffff, sh2_pc(sh2));
1761
1762   if ((a & 0x3ffc0) == 0x4000) {
1763     p32x_sh2reg_write16(a, d, sh2);
1764     goto out;
1765   }
1766
1767   if (Pico32x.regs[0] & P32XS_FM) {
1768     if ((a & 0x3fff0) == 0x4100) {
1769       sh2->poll_cnt = 0;
1770       p32x_vdp_write16(a, d, sh2);
1771       goto out;
1772     }
1773
1774     if ((a & 0x3fe00) == 0x4200) {
1775       sh2->poll_cnt = 0;
1776       if (Pico32xMem->pal[(a & 0x1ff) / 2] != d)
1777         Pico32xDrawSync(sh2);
1778       Pico32xMem->pal[(a & 0x1ff) / 2] = d;
1779       Pico32x.dirty_pal = 1;
1780       goto out;
1781     }
1782   }
1783
1784   sh2_write16_unmapped(a, d, sh2);
1785 out:
1786   DRC_RESTORE_SR(sh2);
1787 }
1788
1789 #ifdef _ASM_32X_MEMORY_C
1790 extern void REGPARM(3) sh2_write16_dram(u32 a, u32 d, SH2 *sh2);
1791 extern void REGPARM(3) sh2_write16_sdram(u32 a, u32 d, SH2 *sh2);
1792 extern void REGPARM(3) sh2_write16_da(u32 a, u32 d, SH2 *sh2);
1793 #else
1794 static void REGPARM(3) sh2_write16_dram(u32 a, u32 d, SH2 *sh2)
1795 {
1796   sh2_write16_dramN(sh2->p_dram, a, d);
1797 }
1798
1799 static void REGPARM(3) sh2_write16_sdram(u32 a, u32 d, SH2 *sh2)
1800 {
1801   u32 a1 = a & 0x3fffe;
1802   ((u16 *)sh2->p_sdram)[a1 / 2] = d;
1803 #ifdef DRC_SH2
1804   u8 *p = sh2->p_drcblk_ram;
1805   u32 t = p[a1 >> SH2_DRCBLK_RAM_SHIFT];
1806   if (t)
1807     sh2_sdram_checks(a, d, sh2, t);
1808 #endif
1809 }
1810
1811 static void REGPARM(3) sh2_write16_da(u32 a, u32 d, SH2 *sh2)
1812 {
1813   u32 a1 = a & 0xffe;
1814   ((u16 *)sh2->data_array)[a1 / 2] = d;
1815 #ifdef DRC_SH2
1816   u8 *p = sh2->p_drcblk_da;
1817   u32 t = p[a1 >> SH2_DRCBLK_DA_SHIFT];
1818   if (t)
1819     sh2_da_checks(a, t, sh2);
1820 #endif
1821 }
1822 #endif
1823
1824 static void REGPARM(3) sh2_write16_rom(u32 a, u32 d, SH2 *sh2)
1825 {
1826   u32 a1 = a & 0x3ffffe;
1827   // tweak for WWF Raw: does writes to ROM area, and it doesn't work without
1828   // allowing this.
1829   // Presumably the write goes to the CPU cache and is read back from there,
1830   // but it would be extremely costly to emulate cache behaviour. Just allow
1831   // writes to that region, hoping that the original ROM values are never used.
1832   if ((a1 & 0x3e0000) == 0x3e0000 && (PicoIn.quirks & PQUIRK_WWFRAW_HACK))
1833     ((u16 *)sh2->p_rom)[a1 / 2] = d;
1834   else
1835     sh2_write16_unmapped(a, d, sh2);
1836 }
1837
1838 static void REGPARM(3) sh2_write32_unmapped(u32 a, u32 d, SH2 *sh2)
1839 {
1840   elprintf_sh2(sh2, EL_32X, "unmapped w32 [%08x]     %08x @%06x",
1841       a, d, sh2_pc(sh2));
1842 }
1843
1844 static void REGPARM(3) sh2_write32_cs0(u32 a, u32 d, SH2 *sh2)
1845 {
1846   sh2_write16_cs0(a, d >> 16, sh2);
1847   sh2_write16_cs0(a + 2, d, sh2);
1848 }
1849
1850 #define sh2_write32_dramN(p, a, d) \
1851   u32 *pd = &((u32 *)p)[(a & 0x1ffff) / 4]; \
1852   if (!(a & 0x20000)) { \
1853     *pd = CPU_BE2(d); \
1854   } else { \
1855     /* overwrite */ \
1856     u32 v = *pd, m = 0; d = CPU_BE2(d); \
1857     if (!(d & 0x000000ff)) m |= 0x000000ff; \
1858     if (!(d & 0x0000ff00)) m |= 0x0000ff00; \
1859     if (!(d & 0x00ff0000)) m |= 0x00ff0000; \
1860     if (!(d & 0xff000000)) m |= 0xff000000; \
1861     *pd = d | (v&m); \
1862   }
1863
1864 #ifdef _ASM_32X_MEMORY_C
1865 extern void REGPARM(3) sh2_write32_dram(u32 a, u32 d, SH2 *sh2);
1866 extern void REGPARM(3) sh2_write32_sdram(u32 a, u32 d, SH2 *sh2);
1867 extern void REGPARM(3) sh2_write32_da(u32 a, u32 d, SH2 *sh2);
1868 #else
1869 static void REGPARM(3) sh2_write32_dram(u32 a, u32 d, SH2 *sh2)
1870 {
1871   sh2_write32_dramN(sh2->p_dram, a, d);
1872 }
1873
1874 static void REGPARM(3) sh2_write32_sdram(u32 a, u32 d, SH2 *sh2)
1875 {
1876   u32 a1 = a & 0x3fffc;
1877   *(u32 *)((char*)sh2->p_sdram + a1) = CPU_BE2(d);
1878 #ifdef DRC_SH2
1879   u8 *p = sh2->p_drcblk_ram;
1880   u32 t = p[a1 >> SH2_DRCBLK_RAM_SHIFT];
1881   u32 u = p[(a1+2) >> SH2_DRCBLK_RAM_SHIFT];
1882   if (t|(u<<16))
1883     sh2_sdram_checks_l(a, d, sh2, t|(u<<16));
1884 #endif
1885 }
1886
1887 static void REGPARM(3) sh2_write32_da(u32 a, u32 d, SH2 *sh2)
1888 {
1889   u32 a1 = a & 0xffc;
1890   *((u32 *)sh2->data_array + a1/4) = CPU_BE2(d);
1891 #ifdef DRC_SH2
1892   u8 *p = sh2->p_drcblk_da;
1893   u32 t = p[a1 >> SH2_DRCBLK_DA_SHIFT];
1894   u32 u = p[(a1+2) >> SH2_DRCBLK_DA_SHIFT];
1895   if (t|(u<<16))
1896     sh2_da_checks_l(a, t|(u<<16), sh2);
1897 #endif
1898 }
1899 #endif
1900
1901 static void REGPARM(3) sh2_write32_rom(u32 a, u32 d, SH2 *sh2)
1902 {
1903   sh2_write16_rom(a, d >> 16, sh2);
1904   sh2_write16_rom(a + 2, d, sh2);
1905 }
1906
1907 typedef u32 REGPARM(2) (sh2_read_handler)(u32 a, SH2 *sh2);
1908 typedef void REGPARM(3) (sh2_write_handler)(u32 a, u32 d, SH2 *sh2);
1909
1910 #define SH2MAP_ADDR2OFFS_R(a) \
1911   ((u32)(a) >> SH2_READ_SHIFT)
1912
1913 #define SH2MAP_ADDR2OFFS_W(a) \
1914   ((u32)(a) >> SH2_WRITE_SHIFT)
1915
1916 u32 REGPARM(2) p32x_sh2_read8(u32 a, SH2 *sh2)
1917 {
1918   const sh2_memmap *sh2_map = sh2->read8_map;
1919   uptr p;
1920
1921   sh2_map += SH2MAP_ADDR2OFFS_R(a);
1922   p = sh2_map->addr;
1923   if (!map_flag_set(p))
1924     return *(s8 *)((p << 1) + MEM_BE2(a & sh2_map->mask));
1925   else
1926     return ((sh2_read_handler *)(p << 1))(a, sh2);
1927 }
1928
1929 u32 REGPARM(2) p32x_sh2_read16(u32 a, SH2 *sh2)
1930 {
1931   const sh2_memmap *sh2_map = sh2->read16_map;
1932   uptr p;
1933
1934   sh2_map += SH2MAP_ADDR2OFFS_R(a);
1935   p = sh2_map->addr;
1936   if (!map_flag_set(p))
1937     return *(s16 *)((p << 1) + (a & sh2_map->mask));
1938   else
1939     return ((sh2_read_handler *)(p << 1))(a, sh2);
1940 }
1941
1942 u32 REGPARM(2) p32x_sh2_read32(u32 a, SH2 *sh2)
1943 {
1944   const sh2_memmap *sh2_map = sh2->read32_map;
1945   uptr p;
1946
1947   sh2_map += SH2MAP_ADDR2OFFS_R(a);
1948   p = sh2_map->addr;
1949   if (!map_flag_set(p)) {
1950     u32 *pd = (u32 *)((p << 1) + (a & sh2_map->mask));
1951     return CPU_BE2(*pd);
1952   } else
1953     return ((sh2_read_handler *)(p << 1))(a, sh2);
1954 }
1955
1956 void REGPARM(3) p32x_sh2_write8(u32 a, u32 d, SH2 *sh2)
1957 {
1958   const void **sh2_wmap = sh2->write8_tab;
1959   sh2_write_handler *wh;
1960
1961   wh = sh2_wmap[SH2MAP_ADDR2OFFS_W(a)];
1962   wh(a, d, sh2);
1963 }
1964
1965 void REGPARM(3) p32x_sh2_write16(u32 a, u32 d, SH2 *sh2)
1966 {
1967   const void **sh2_wmap = sh2->write16_tab;
1968   sh2_write_handler *wh;
1969
1970   wh = sh2_wmap[SH2MAP_ADDR2OFFS_W(a)];
1971   wh(a, d, sh2);
1972 }
1973
1974 void REGPARM(3) p32x_sh2_write32(u32 a, u32 d, SH2 *sh2)
1975 {
1976   const void **sh2_wmap = sh2->write32_tab;
1977   sh2_write_handler *wh;
1978
1979   wh = sh2_wmap[SH2MAP_ADDR2OFFS_W(a)];
1980   wh(a, d, sh2);
1981 }
1982
1983 void *p32x_sh2_get_mem_ptr(u32 a, u32 *mask, SH2 *sh2)
1984 {
1985   const sh2_memmap *mm = sh2->read8_map;
1986   void *ret = (void *)-1;
1987
1988   mm += SH2MAP_ADDR2OFFS_R(a);
1989   if (!map_flag_set(mm->addr)) {
1990     // directly mapped memory (SDRAM, ROM, data array)
1991     ret = (void *)(mm->addr << 1);
1992     *mask = mm->mask;
1993   } else if ((a & ~0x7ff) == 0) {
1994     // BIOS, has handler function since it shares its segment with I/O
1995     ret = sh2->p_bios;
1996     *mask = 0x7ff;
1997   } else if ((a & 0xc6000000) == 0x02000000) {
1998     // banked ROM. Return bank address
1999     u32 bank = carthw_ssf2_banks[(a >> 19) & 7] << 19;
2000     ret = (char*)sh2->p_rom + bank;
2001     *mask = 0x07ffff;
2002   }
2003
2004   return ret;
2005 }
2006
2007 int p32x_sh2_mem_is_rom(u32 a, SH2 *sh2)
2008 {
2009   if ((a & 0xc6000000) == 0x02000000) {
2010     // ROM, but mind tweak for WWF Raw
2011     return !(PicoIn.quirks & PQUIRK_WWFRAW_HACK) || (a & 0x3f0000) < 0x3e0000;
2012   }
2013
2014   return 0;
2015 }
2016
2017 int p32x_sh2_memcpy(u32 dst, u32 src, int count, int size, SH2 *sh2)
2018 {
2019   u32 mask;
2020   u8 *ps, *pd;
2021   int len, i;
2022
2023   // check if src and dst points to memory (rom/sdram/dram/da)
2024   if ((pd = p32x_sh2_get_mem_ptr(dst, &mask, sh2)) == (void *)-1)
2025     return 0;
2026   if ((ps = p32x_sh2_get_mem_ptr(src, &mask, sh2)) == (void *)-1)
2027     return 0;
2028   ps += src & mask;
2029   len = count * size;
2030
2031   // DRAM in byte access is always in overwrite mode
2032   if (pd == sh2->p_dram && size == 1)
2033     dst |= 0x20000;
2034
2035   // align dst to halfword
2036   if (dst & 1) {
2037     p32x_sh2_write8(dst, *(u8 *)MEM_BE2((uptr)ps), sh2);
2038     ps++, dst++, len --;
2039   }
2040
2041   // copy data
2042   if ((uptr)ps & 1) {
2043     // unaligned, use halfword copy mode to reduce memory bandwidth
2044     u16 *sp = (u16 *)(ps - 1);
2045     u16 dl, dh = *sp++;
2046     for (i = 0; i < (len & ~1); i += 2, dst += 2, sp++) {
2047       dl = dh, dh = *sp;
2048       p32x_sh2_write16(dst, (dh >> 8) | (dl << 8), sh2);
2049     }
2050     if (len & 1)
2051       p32x_sh2_write8(dst, dh, sh2);
2052   } else {
2053     // dst and src at least halfword aligned
2054     u16 *sp = (u16 *)ps;
2055     // align dst to word
2056     if ((dst & 2) && len >= 2) {
2057       p32x_sh2_write16(dst, *sp++, sh2);
2058       dst += 2, len -= 2;
2059     }
2060     if ((uptr)sp & 2) {
2061       // halfword copy, using word writes to reduce memory bandwidth
2062       u16 dl, dh;
2063       for (i = 0; i < (len & ~3); i += 4, dst += 4, sp += 2) {
2064         dl = sp[0], dh = sp[1];
2065         p32x_sh2_write32(dst, (dl << 16) | dh, sh2);
2066       }
2067     } else {
2068       // word copy
2069       u32 d;
2070       for (i = 0; i < (len & ~3); i += 4, dst += 4, sp += 2) {
2071         d = *(u32 *)sp;
2072         p32x_sh2_write32(dst, CPU_BE2(d), sh2);
2073       }
2074     }
2075     if (len & 2) {
2076       p32x_sh2_write16(dst, *sp++, sh2);
2077       dst += 2;
2078     }
2079     if (len & 1)
2080       p32x_sh2_write8(dst, *sp >> 8, sh2);
2081   }
2082
2083   return count;
2084 }
2085
2086 // -----------------------------------------------------------------
2087
2088 static void z80_md_bank_write_32x(u32 a, unsigned char d)
2089 {
2090   u32 addr68k;
2091
2092   addr68k = Pico.m.z80_bank68k << 15;
2093   addr68k += a & 0x7fff;
2094   if ((addr68k & 0xfff000) == 0xa15000)
2095     Pico32x.emu_flags |= P32XF_Z80_32X_IO;
2096
2097   elprintf(EL_Z80BNK, "z80->68k w8 [%06x] %02x", addr68k, d);
2098   m68k_write8(addr68k, d);
2099 }
2100
2101 // -----------------------------------------------------------------
2102
2103 static const u16 msh2_code[] = {
2104   // trap instructions
2105   0xaffe, // 200 bra <self>
2106   0x0009, // 202 nop
2107   // have to wait a bit until m68k initial program finishes clearing stuff
2108   // to avoid races with game SH2 code, like in Tempo
2109   0xd406, // 204 mov.l   @(_m_ok,pc), r4
2110   0xc400, // 206 mov.b   @(h'0,gbr),r0
2111   0xc801, // 208 tst     #1, r0
2112   0x8b0f, // 20a bf      cd_start
2113   0xd105, // 20c mov.l   @(_cnt,pc), r1
2114   0xd206, // 20e mov.l   @(_start,pc), r2
2115   0x71ff, // 210 add     #-1, r1
2116   0x4115, // 212 cmp/pl  r1
2117   0x89fc, // 214 bt      -2
2118   0x6043, // 216 mov     r4, r0
2119   0xc208, // 218 mov.l   r0, @(h'20,gbr)
2120   0x6822, // 21a mov.l   @r2, r8
2121   0x482b, // 21c jmp     @r8
2122   0x0009, // 21e nop
2123   ('M'<<8)|'_', ('O'<<8)|'K', // 220 _m_ok
2124   0x0001, 0x0000,             // 224 _cnt
2125   0x2200, 0x03e0, // master start pointer in ROM
2126   // cd_start:
2127   0xd20d, // 22c mov.l   @(__cd_,pc), r2
2128   0xc608, // 22e mov.l   @(h'20,gbr), r0
2129   0x3200, // 230 cmp/eq  r0, r2
2130   0x8bfc, // 232 bf      #-2
2131   0xe000, // 234 mov     #0, r0
2132   0xcf80, // 236 or.b    #0x80,@(r0,gbr)
2133   0xd80b, // 238 mov.l   @(_start_cd,pc), r8 // 24000018
2134   0xd30c, // 23a mov.l   @(_max_len,pc), r3
2135   0x5b84, // 23c mov.l   @(h'10,r8), r11     // master vbr
2136   0x5a82, // 23e mov.l   @(8,r8), r10        // entry
2137   0x5081, // 240 mov.l   @(4,r8), r0         // len
2138   0x5980, // 242 mov.l   @(0,r8), r9         // dst
2139   0x3036, // 244 cmp/hi  r3,r0
2140   0x8b00, // 246 bf      #1
2141   0x6033, // 248 mov     r3,r0
2142   0x7820, // 24a add     #0x20, r8
2143   // ipl_copy:
2144   0x6286, // 24c mov.l   @r8+, r2
2145   0x2922, // 24e mov.l   r2, @r9
2146   0x7904, // 250 add     #4, r9
2147   0x70fc, // 252 add     #-4, r0
2148   0x8800, // 254 cmp/eq  #0, r0
2149   0x8bf9, // 256 bf      #-5
2150   //
2151   0x4b2e, // 258 ldc     r11, vbr
2152   0x6043, // 25a mov     r4, r0              // M_OK
2153   0xc208, // 25c mov.l   r0, @(h'20,gbr)
2154   0x4a2b, // 25e jmp     @r10
2155   0x0009, // 260 nop
2156   0x0009, // 262 nop          //     pad
2157   ('_'<<8)|'C', ('D'<<8)|'_', // 264 __cd_
2158   0x2400, 0x0018,             // 268 _start_cd
2159   0x0001, 0xffe0,             // 26c _max_len
2160 };
2161
2162 static const u16 ssh2_code[] = {
2163   0xaffe, // 200 bra <self>
2164   0x0009, // 202 nop
2165   // code to wait for master, in case authentic master BIOS is used
2166   0xd106, // 204 mov.l   @(_m_ok,pc), r1
2167   0xd208, // 206 mov.l   @(_start,pc), r2
2168   0xc608, // 208 mov.l   @(h'20,gbr), r0
2169   0x3100, // 20a cmp/eq  r0, r1
2170   0x8bfc, // 20c bf      #-2
2171   0xc400, // 20e mov.b   @(h'0,gbr),r0
2172   0xc801, // 210 tst     #1, r0
2173   0xd004, // 212 mov.l   @(_s_ok,pc), r0
2174   0x8b0a, // 214 bf      cd_start
2175   0xc209, // 216 mov.l   r0, @(h'24,gbr)
2176   0x6822, // 218 mov.l   @r2, r8
2177   0x482b, // 21a jmp     @r8
2178   0x0009, // 21c nop
2179   0x0009, // 21e nop
2180   ('M'<<8)|'_', ('O'<<8)|'K', // 220
2181   ('S'<<8)|'_', ('O'<<8)|'K', // 224
2182   0x2200, 0x03e4,  // slave start pointer in ROM
2183   // cd_start:
2184   0xd803, // 22c mov.l   @(_start_cd,pc), r8 // 24000018
2185   0x5b85, // 22e mov.l   @(h'14,r8), r11     // slave vbr
2186   0x5a83, // 230 mov.l   @(h'0c,r8), r10     // entry
2187   0x4b2e, // 232 ldc     r11, vbr
2188   0xc209, // 234 mov.l   r0, @(h'24,gbr)     // write S_OK
2189   0x4a2b, // 236 jmp     @r10
2190   0x0009, // 238 nop
2191   0x0009, // 23a nop
2192   0x2400, 0x0018, // 23c _start_cd
2193 };
2194
2195 static void get_bios(void)
2196 {
2197   u16 *ps;
2198   u32 *pl;
2199   int i;
2200
2201   // M68K ROM
2202   if (p32x_bios_g != NULL) {
2203     elprintf(EL_STATUS|EL_32X, "32x: using supplied 68k BIOS");
2204     Byteswap(Pico32xMem->m68k_rom, p32x_bios_g, sizeof(Pico32xMem->m68k_rom));
2205   }
2206   else {
2207     static const u16 andb[] = { 0x0239, 0x00fe, 0x00a1, 0x5107 };
2208     static const u16 p_d4[] = {
2209       0x48e7, 0x8040,         //   movem.l d0/a1, -(sp)
2210       0x227c, 0x00a1, 0x30f1, //   movea.l #0xa130f1, a1
2211       0x7007,                 //   moveq.l #7, d0
2212       0x12d8,                 //0: move.b (a0)+, (a1)+
2213       0x5289,                 //   addq.l  #1, a1
2214       0x51c8, 0xfffa,         //   dbra   d0, 0b
2215       0x0239, 0x00fe, 0x00a1, //   and.b  #0xfe, (0xa15107).l
2216                       0x5107,
2217       0x4cdf, 0x0201          //   movem.l (sp)+, d0/a1
2218     };
2219
2220     // generate 68k ROM
2221     ps = (u16 *)Pico32xMem->m68k_rom;
2222     pl = (u32 *)ps;
2223     for (i = 1; i < 0xc0/4; i++)
2224       pl[i] = CPU_BE2(0x880200 + (i - 1) * 6);
2225     pl[0x70/4] = 0;
2226
2227     // fill with nops
2228     for (i = 0xc0/2; i < 0x100/2; i++)
2229       ps[i] = 0x4e71;
2230
2231     // c0: don't need to care about RV - not emulated
2232     ps[0xc8/2] = 0x1280;                     // move.b d0, (a1)
2233     memcpy(ps + 0xca/2, andb, sizeof(andb)); // and.b #0xfe, (a15107)
2234     ps[0xd2/2] = 0x4e75;                     // rts
2235     // d4:
2236     memcpy(ps + 0xd4/2, p_d4, sizeof(p_d4));
2237     ps[0xfe/2] = 0x4e75; // rts
2238   }
2239   // fill remaining m68k_rom page with game ROM
2240   memcpy(Pico32xMem->m68k_rom_bank + sizeof(Pico32xMem->m68k_rom),
2241     Pico.rom + sizeof(Pico32xMem->m68k_rom),
2242     sizeof(Pico32xMem->m68k_rom_bank) - sizeof(Pico32xMem->m68k_rom));
2243
2244   // MSH2
2245   if (p32x_bios_m != NULL) {
2246     elprintf(EL_STATUS|EL_32X, "32x: using supplied master SH2 BIOS");
2247     Byteswap(&Pico32xMem->sh2_rom_m, p32x_bios_m, sizeof(Pico32xMem->sh2_rom_m));
2248   }
2249   else {
2250     pl = (u32 *)&Pico32xMem->sh2_rom_m;
2251     ps = (u16 *)pl;
2252
2253     // fill exception vector table to our trap address
2254     for (i = 0; i < 80; i++)
2255       pl[i] = CPU_BE2(0x200);
2256     // CD titles by Digital Pictures jump to 0x140 for resetting ...
2257     for (i = 0x140/2; i < 0x1fc/2; i++)
2258       ps[i] = 0x0009; // nop         // ... so fill the remainder with nops
2259     ps[i++] = 0xa002; // bra 0x204   // ... and jump over the trap
2260     ps[i++] = 0x0009; // nop
2261
2262     // start
2263     pl[0] = pl[2] = CPU_BE2(0x204);
2264     // reset SP
2265     pl[1] = pl[3] = CPU_BE2(0x6040000);
2266
2267     // startup code
2268     memcpy(&Pico32xMem->sh2_rom_m.b[0x200], msh2_code, sizeof(msh2_code));
2269     if (!Pico.m.ncart_in && (PicoIn.AHW & PAHW_MCD))
2270       // hack for MSU games (adjust delay loop for copying the MSU code to sub)
2271       Pico32xMem->sh2_rom_m.w[0x224/2] = 0x0090;
2272   }
2273
2274   // SSH2
2275   if (p32x_bios_s != NULL) {
2276     elprintf(EL_STATUS|EL_32X, "32x: using supplied slave SH2 BIOS");
2277     Byteswap(&Pico32xMem->sh2_rom_s, p32x_bios_s, sizeof(Pico32xMem->sh2_rom_s));
2278   }
2279   else {
2280     pl = (u32 *)&Pico32xMem->sh2_rom_s;
2281
2282     // fill exception vector table to our trap address
2283     for (i = 0; i < 128; i++)
2284       pl[i] = CPU_BE2(0x200);
2285
2286     // start
2287     pl[0] = pl[2] = CPU_BE2(0x204);
2288     // reset SP
2289     pl[1] = pl[3] = CPU_BE2(0x603f800);
2290
2291     // startup code
2292     memcpy(&Pico32xMem->sh2_rom_s.b[0x200], ssh2_code, sizeof(ssh2_code));
2293   }
2294 }
2295
2296 #define MAP_MEMORY(m) ((uptr)(m) >> 1)
2297 #define MAP_HANDLER(h) ( ((uptr)(h) >> 1) | ((uptr)1 << (sizeof(uptr) * 8 - 1)) )
2298
2299 static sh2_memmap msh2_read8_map[0x80], msh2_read16_map[0x80],  msh2_read32_map[0x80];
2300 static sh2_memmap ssh2_read8_map[0x80], ssh2_read16_map[0x80],  ssh2_read32_map[0x80];
2301 // for writes we are using handlers only
2302 static sh2_write_handler *msh2_write8_map[0x80], *msh2_write16_map[0x80], *msh2_write32_map[0x80];
2303 static sh2_write_handler *ssh2_write8_map[0x80], *ssh2_write16_map[0x80], *ssh2_write32_map[0x80];
2304
2305 void Pico32xSwapDRAM(int b)
2306 {
2307   cpu68k_map_read_mem(0x840000, 0x85ffff, Pico32xMem->dram[b], 0);
2308   cpu68k_map_read_mem(0x860000, 0x87ffff, Pico32xMem->dram[b], 0);
2309   cpu68k_map_set(m68k_write8_map,  0x840000, 0x87ffff,
2310                  b ? m68k_write8_dram1_ow : m68k_write8_dram0_ow, 1);
2311   cpu68k_map_set(m68k_write16_map, 0x840000, 0x87ffff,
2312                  b ? m68k_write16_dram1_ow : m68k_write16_dram0_ow, 1);
2313
2314   // SH2
2315   msh2_read8_map[0x04/2].addr  = msh2_read8_map[0x24/2].addr  =
2316   msh2_read16_map[0x04/2].addr = msh2_read16_map[0x24/2].addr =
2317   msh2_read32_map[0x04/2].addr = msh2_read32_map[0x24/2].addr = MAP_MEMORY(Pico32xMem->dram[b]);
2318   ssh2_read8_map[0x04/2].addr  = ssh2_read8_map[0x24/2].addr  =
2319   ssh2_read16_map[0x04/2].addr = ssh2_read16_map[0x24/2].addr =
2320   ssh2_read32_map[0x04/2].addr = ssh2_read32_map[0x24/2].addr = MAP_MEMORY(Pico32xMem->dram[b]);
2321
2322   // convenience ptrs
2323   msh2.p_dram  = ssh2.p_dram  = Pico32xMem->dram[b];
2324 }
2325
2326 static void bank_switch_rom_sh2(void)
2327 {
2328   if (!carthw_ssf2_active) {
2329     // easy
2330     msh2_read8_map[0x02/2].addr  = msh2_read8_map[0x22/2].addr  =
2331     msh2_read16_map[0x02/2].addr = msh2_read16_map[0x22/2].addr =
2332     msh2_read32_map[0x02/2].addr = msh2_read32_map[0x22/2].addr = MAP_MEMORY(Pico.rom);
2333     ssh2_read8_map[0x02/2].addr  = ssh2_read8_map[0x22/2].addr  =
2334     ssh2_read16_map[0x02/2].addr = ssh2_read16_map[0x22/2].addr =
2335     ssh2_read32_map[0x02/2].addr = ssh2_read32_map[0x22/2].addr = MAP_MEMORY(Pico.rom);
2336   }
2337   else {
2338     msh2_read8_map[0x02/2].addr  = msh2_read8_map[0x22/2].addr  = MAP_HANDLER(sh2_read8_rom);
2339     msh2_read16_map[0x02/2].addr = msh2_read16_map[0x22/2].addr = MAP_HANDLER(sh2_read16_rom);
2340     msh2_read32_map[0x02/2].addr = msh2_read32_map[0x22/2].addr = MAP_HANDLER(sh2_read32_rom);
2341     ssh2_read8_map[0x02/2].addr  = ssh2_read8_map[0x22/2].addr  = MAP_HANDLER(sh2_read8_rom);
2342     ssh2_read16_map[0x02/2].addr = ssh2_read16_map[0x22/2].addr = MAP_HANDLER(sh2_read16_rom);
2343     ssh2_read32_map[0x02/2].addr = ssh2_read32_map[0x22/2].addr = MAP_HANDLER(sh2_read32_rom);
2344   }
2345 }
2346
2347 void PicoMemSetup32x(void)
2348 {
2349   unsigned int rs;
2350   int i;
2351
2352   get_bios();
2353
2354   // cartridge area becomes unmapped
2355   // XXX: we take the easy way and don't unmap ROM,
2356   // so that we can avoid handling the RV bit.
2357   // m68k_map_unmap(0x000000, 0x3fffff);
2358
2359   if (!Pico.m.ncart_in) {
2360     // MD ROM area
2361     rs = sizeof(Pico32xMem->m68k_rom_bank);
2362     cpu68k_map_set(m68k_read8_map,   0x000000, rs - 1, Pico32xMem->m68k_rom_bank, 0);
2363     cpu68k_map_set(m68k_read16_map,  0x000000, rs - 1, Pico32xMem->m68k_rom_bank, 0);
2364     cpu68k_map_set(m68k_write8_map,  0x000000, rs - 1, PicoWrite8_hint, 1); // TODO verify
2365     cpu68k_map_set(m68k_write16_map, 0x000000, rs - 1, PicoWrite16_hint, 1);
2366
2367     // 32X ROM (unbanked, XXX: consider mirroring?)
2368     rs = (Pico.romsize + M68K_BANK_MASK) & ~M68K_BANK_MASK;
2369     if (rs > 0x80000)
2370       rs = 0x80000;
2371     cpu68k_map_set(m68k_read8_map,   0x880000, 0x880000 + rs - 1, Pico.rom, 0);
2372     cpu68k_map_set(m68k_read16_map,  0x880000, 0x880000 + rs - 1, Pico.rom, 0);
2373     cpu68k_map_set(m68k_write8_map,  0x880000, 0x880000 + rs - 1, PicoWrite8_cart, 1);
2374     cpu68k_map_set(m68k_write16_map, 0x880000, 0x880000 + rs - 1, PicoWrite16_cart, 1);
2375
2376     // 32X ROM (banked)
2377     bank_switch_rom_68k(Pico32x.regs[4 / 2]);
2378     cpu68k_map_set(m68k_write8_map,  0x900000, 0x9fffff, PicoWrite8_bank, 1);
2379     cpu68k_map_set(m68k_write16_map, 0x900000, 0x9fffff, PicoWrite16_bank, 1);
2380   }
2381
2382   // SYS regs
2383   cpu68k_map_set(m68k_read8_map,   0xa10000, 0xa1ffff, PicoRead8_32x_on, 1);
2384   cpu68k_map_set(m68k_read16_map,  0xa10000, 0xa1ffff, PicoRead16_32x_on, 1);
2385   cpu68k_map_set(m68k_write8_map,  0xa10000, 0xa1ffff, PicoWrite8_32x_on, 1);
2386   cpu68k_map_set(m68k_write16_map, 0xa10000, 0xa1ffff, PicoWrite16_32x_on, 1);
2387
2388   // TODO: cd + carthw
2389   if (PicoIn.AHW & PAHW_MCD) {
2390     m68k_write8_io  = PicoWrite8_32x_on_io_cd;
2391     m68k_write16_io = PicoWrite16_32x_on_io_cd;
2392   }
2393   else if (carthw_ssf2_active) {
2394     m68k_write8_io  = PicoWrite8_32x_on_io_ssf2;
2395     m68k_write16_io = PicoWrite16_32x_on_io_ssf2;
2396   }
2397   else {
2398     m68k_write8_io  = PicoWrite8_32x_on_io;
2399     m68k_write16_io = PicoWrite16_32x_on_io;
2400   }
2401
2402   // SH2 maps: A31,A30,A29,CS1,CS0
2403   // all unmapped by default
2404   for (i = 0; i < ARRAY_SIZE(msh2_read8_map); i++) {
2405     msh2_read8_map[i].addr   = MAP_HANDLER(sh2_read8_unmapped);
2406     msh2_read16_map[i].addr  = MAP_HANDLER(sh2_read16_unmapped);
2407     msh2_read32_map[i].addr  = MAP_HANDLER(sh2_read32_unmapped);
2408   }
2409
2410   for (i = 0; i < ARRAY_SIZE(msh2_write8_map); i++) {
2411     msh2_write8_map[i]       = sh2_write8_unmapped;
2412     msh2_write16_map[i]      = sh2_write16_unmapped;
2413     msh2_write32_map[i]      = sh2_write32_unmapped;
2414   }
2415
2416   // "purge area"
2417   for (i = 0x40; i <= 0x5f; i++) {
2418     msh2_write8_map[i >> 1]  =
2419     msh2_write16_map[i >> 1] =
2420     msh2_write32_map[i >> 1] = sh2_write_ignore;
2421   }
2422
2423   // CS0
2424   msh2_read8_map[0x00/2].addr  = msh2_read8_map[0x20/2].addr  = MAP_HANDLER(sh2_read8_cs0);
2425   msh2_read16_map[0x00/2].addr = msh2_read16_map[0x20/2].addr = MAP_HANDLER(sh2_read16_cs0);
2426   msh2_read32_map[0x00/2].addr = msh2_read32_map[0x20/2].addr = MAP_HANDLER(sh2_read32_cs0);
2427   msh2_write8_map[0x00/2]  = msh2_write8_map[0x20/2]  = sh2_write8_cs0;
2428   msh2_write16_map[0x00/2] = msh2_write16_map[0x20/2] = sh2_write16_cs0;
2429   msh2_write32_map[0x00/2] = msh2_write32_map[0x20/2] = sh2_write32_cs0;
2430   // CS1 - ROM
2431   bank_switch_rom_sh2();
2432   for (rs = 0x8000; rs < Pico.romsize && rs < 0x400000; rs *= 2) ; 
2433   msh2_read8_map[0x02/2].mask  = msh2_read8_map[0x22/2].mask  = rs-1;
2434   msh2_read16_map[0x02/2].mask = msh2_read16_map[0x22/2].mask = rs-1;
2435   msh2_read32_map[0x02/2].mask = msh2_read32_map[0x22/2].mask = rs-1;
2436   msh2_write16_map[0x02/2] = msh2_write16_map[0x22/2] = sh2_write16_rom;
2437   msh2_write32_map[0x02/2] = msh2_write32_map[0x22/2] = sh2_write32_rom;
2438   // CS2 - DRAM 
2439   msh2_read8_map[0x04/2].mask  = msh2_read8_map[0x24/2].mask  = 0x01ffff;
2440   msh2_read16_map[0x04/2].mask = msh2_read16_map[0x24/2].mask = 0x01fffe;
2441   msh2_read32_map[0x04/2].mask = msh2_read32_map[0x24/2].mask = 0x01fffc;
2442   msh2_write8_map[0x04/2]  = msh2_write8_map[0x24/2]  = sh2_write8_dram;
2443   msh2_write16_map[0x04/2] = msh2_write16_map[0x24/2] = sh2_write16_dram;
2444   msh2_write32_map[0x04/2] = msh2_write32_map[0x24/2] = sh2_write32_dram;
2445
2446   // CS3 - SDRAM
2447   msh2_read8_map[0x06/2].addr   = msh2_read8_map[0x26/2].addr   =
2448   msh2_read16_map[0x06/2].addr  = msh2_read16_map[0x26/2].addr  =
2449   msh2_read32_map[0x06/2].addr  = msh2_read32_map[0x26/2].addr  = MAP_MEMORY(Pico32xMem->sdram);
2450   msh2_write8_map[0x06/2]       = msh2_write8_map[0x26/2]       = sh2_write8_sdram;
2451
2452   msh2_write16_map[0x06/2]      = msh2_write16_map[0x26/2]      = sh2_write16_sdram;
2453   msh2_write32_map[0x06/2]      = msh2_write32_map[0x26/2]      = sh2_write32_sdram;
2454   msh2_read8_map[0x06/2].mask   = msh2_read8_map[0x26/2].mask   = 0x03ffff;
2455   msh2_read16_map[0x06/2].mask  = msh2_read16_map[0x26/2].mask  = 0x03fffe;
2456   msh2_read32_map[0x06/2].mask  = msh2_read32_map[0x26/2].mask  = 0x03fffc;
2457   // SH2 data array
2458   msh2_read8_map[0xc0/2].mask  = 0x0fff;
2459   msh2_read16_map[0xc0/2].mask = 0x0ffe;
2460   msh2_read32_map[0xc0/2].mask = 0x0ffc;
2461   msh2_write8_map[0xc0/2]      = sh2_write8_da;
2462   msh2_write16_map[0xc0/2]     = sh2_write16_da;
2463   msh2_write32_map[0xc0/2]     = sh2_write32_da;
2464   // SH2 IO
2465   msh2_read8_map[0xff/2].addr  = MAP_HANDLER(sh2_peripheral_read8);
2466   msh2_read16_map[0xff/2].addr = MAP_HANDLER(sh2_peripheral_read16);
2467   msh2_read32_map[0xff/2].addr = MAP_HANDLER(sh2_peripheral_read32);
2468   msh2_write8_map[0xff/2]      = sh2_peripheral_write8;
2469   msh2_write16_map[0xff/2]     = sh2_peripheral_write16;
2470   msh2_write32_map[0xff/2]     = sh2_peripheral_write32;
2471
2472   memcpy(ssh2_read8_map,   msh2_read8_map,   sizeof(msh2_read8_map));
2473   memcpy(ssh2_read16_map,  msh2_read16_map,  sizeof(msh2_read16_map));
2474   memcpy(ssh2_read32_map,  msh2_read32_map,  sizeof(msh2_read32_map));
2475   memcpy(ssh2_write8_map,  msh2_write8_map,  sizeof(msh2_write8_map));
2476   memcpy(ssh2_write16_map, msh2_write16_map, sizeof(msh2_write16_map));
2477   memcpy(ssh2_write32_map, msh2_write32_map, sizeof(msh2_write32_map));
2478
2479   msh2_read8_map[0xc0/2].addr  =
2480   msh2_read16_map[0xc0/2].addr =
2481   msh2_read32_map[0xc0/2].addr = MAP_MEMORY(msh2.data_array);
2482   ssh2_read8_map[0xc0/2].addr  =
2483   ssh2_read16_map[0xc0/2].addr =
2484   ssh2_read32_map[0xc0/2].addr = MAP_MEMORY(ssh2.data_array);
2485
2486   // map DRAM area, both 68k and SH2
2487   Pico32xSwapDRAM((Pico32x.vdp_regs[0x0a / 2] & P32XV_FS) ^ P32XV_FS);
2488
2489   msh2.read8_map   = msh2_read8_map;  ssh2.read8_map   = ssh2_read8_map;
2490   msh2.read16_map  = msh2_read16_map; ssh2.read16_map  = ssh2_read16_map;
2491   msh2.read32_map  = msh2_read32_map; ssh2.read32_map  = ssh2_read32_map;
2492   msh2.write8_tab  = (const void **)(void *)msh2_write8_map;
2493   msh2.write16_tab = (const void **)(void *)msh2_write16_map;
2494   msh2.write32_tab = (const void **)(void *)msh2_write32_map;
2495   ssh2.write8_tab  = (const void **)(void *)ssh2_write8_map;
2496   ssh2.write16_tab = (const void **)(void *)ssh2_write16_map;
2497   ssh2.write32_tab = (const void **)(void *)ssh2_write32_map;
2498
2499   // convenience ptrs
2500   msh2.p_sdram = ssh2.p_sdram = Pico32xMem->sdram;
2501   msh2.p_rom   = ssh2.p_rom   = Pico.rom;
2502   msh2.p_bios  = Pico32xMem->sh2_rom_m.w; msh2.p_da = msh2.data_array;
2503   ssh2.p_bios  = Pico32xMem->sh2_rom_s.w; ssh2.p_da = ssh2.data_array;
2504
2505   sh2_drc_mem_setup(&msh2);
2506   sh2_drc_mem_setup(&ssh2);
2507   memset(sh2_poll_rd, 0, sizeof(sh2_poll_rd));
2508   memset(sh2_poll_wr, 0, sizeof(sh2_poll_wr));
2509   memset(sh2_poll_fifo, -1, sizeof(sh2_poll_fifo));
2510
2511   // z80 hack
2512   z80_map_set(z80_write_map, 0x8000, 0xffff, z80_md_bank_write_32x, 1);
2513 }
2514
2515 void p32x_update_banks(void)
2516 {
2517   bank_switch_rom_68k(Pico32x.regs[4 / 2]);
2518   bank_switch_rom_sh2();
2519   if (Pico32x.emu_flags & P32XF_DRC_ROM_C)
2520     sh2_drc_flush_all();
2521 }
2522
2523 void Pico32xMemStateLoaded(void)
2524 {
2525   bank_switch_rom_68k(Pico32x.regs[4 / 2]);
2526   Pico32xSwapDRAM((Pico32x.vdp_regs[0x0a / 2] & P32XV_FS) ^ P32XV_FS);
2527   memset(Pico32xMem->pwm, 0, sizeof(Pico32xMem->pwm));
2528   Pico32x.dirty_pal = 1;
2529
2530   memset(&m68k_poll, 0, sizeof(m68k_poll));
2531   msh2.state = 0;
2532   msh2.poll_addr = msh2.poll_cycles = msh2.poll_cnt = 0;
2533   ssh2.state = 0;
2534   ssh2.poll_addr = ssh2.poll_cycles = ssh2.poll_cnt = 0;
2535   memset(sh2_poll_fifo, 0, sizeof(sh2_poll_fifo));
2536
2537   sh2_drc_flush_all();
2538 }
2539
2540 // vim:shiftwidth=2:ts=2:expandtab