runs code in 1M wram, cell arrange, decode (untested)
[picodrive.git] / Pico / cd / Memory.c
1 // This is part of Pico Library\r
2 \r
3 // (c) Copyright 2004 Dave, All rights reserved.\r
4 // (c) Copyright 2007 notaz, All rights reserved.\r
5 // Free for non-commercial use.\r
6 \r
7 // For commercial use, separate licencing terms must be obtained.\r
8 \r
9 // A68K no longer supported here\r
10 \r
11 //#define __debug_io\r
12 \r
13 #include "../PicoInt.h"\r
14 \r
15 #include "../sound/sound.h"\r
16 #include "../sound/ym2612.h"\r
17 #include "../sound/sn76496.h"\r
18 \r
19 #include "gfx_cd.h"\r
20 #include "pcm.h"\r
21 \r
22 #include "cell_map.c"\r
23 \r
24 typedef unsigned char  u8;\r
25 typedef unsigned short u16;\r
26 typedef unsigned int   u32;\r
27 \r
28 //#define __debug_io\r
29 //#define __debug_io2\r
30 //#define rdprintf dprintf\r
31 #define rdprintf(...)\r
32 \r
33 // -----------------------------------------------------------------\r
34 \r
35 \r
36 static u32 m68k_reg_read16(u32 a)\r
37 {\r
38   u32 d=0;\r
39   a &= 0x3e;\r
40   // dprintf("m68k_regs r%2i: [%02x] @%06x", realsize&~1, a+(realsize&1), SekPc);\r
41 \r
42   switch (a) {\r
43     case 0:\r
44       d = ((Pico_mcd->s68k_regs[0x33]<<13)&0x8000) | Pico_mcd->m.busreq; // here IFL2 is always 0, just like in Gens\r
45       goto end;\r
46     case 2:\r
47       d = (Pico_mcd->s68k_regs[a]<<8) | (Pico_mcd->s68k_regs[a+1]&0xc7);\r
48       dprintf("m68k_regs r3: %02x @%06x", (u8)d, SekPcS68k);\r
49       goto end;\r
50     case 4:\r
51       d = Pico_mcd->s68k_regs[4]<<8;\r
52       goto end;\r
53     case 6:\r
54       d = Pico_mcd->m.hint_vector;\r
55       goto end;\r
56     case 8:\r
57       d = Read_CDC_Host(0);\r
58       goto end;\r
59     case 0xA:\r
60       dprintf("m68k FIXME: reserved read");\r
61       goto end;\r
62     case 0xC:\r
63       dprintf("m68k stopwatch timer read");\r
64       d = Pico_mcd->m.timer_stopwatch >> 16;\r
65       goto end;\r
66   }\r
67 \r
68   if (a < 0x30) {\r
69     // comm flag/cmd/status (0xE-0x2F)\r
70     d = (Pico_mcd->s68k_regs[a]<<8) | Pico_mcd->s68k_regs[a+1];\r
71     goto end;\r
72   }\r
73 \r
74   dprintf("m68k_regs FIXME invalid read @ %02x", a);\r
75 \r
76 end:\r
77 \r
78   // dprintf("ret = %04x", d);\r
79   return d;\r
80 }\r
81 \r
82 static void m68k_reg_write8(u32 a, u32 d)\r
83 {\r
84   a &= 0x3f;\r
85   // dprintf("m68k_regs w%2i: [%02x] %02x @%06x", realsize, a, d, SekPc);\r
86 \r
87   switch (a) {\r
88     case 0:\r
89       d &= 1;\r
90       if ((d&1) && (Pico_mcd->s68k_regs[0x33]&(1<<2))) { dprintf("m68k: s68k irq 2"); SekInterruptS68k(2); }\r
91       return;\r
92     case 1:\r
93       d &= 3;\r
94       if (!(d&1)) Pico_mcd->m.state_flags |= 1; // reset pending, needed to be sure we fetch the right vectors on reset\r
95       if ( (Pico_mcd->m.busreq&1) != (d&1)) dprintf("m68k: s68k reset %i", !(d&1));\r
96       if ( (Pico_mcd->m.busreq&2) != (d&2)) dprintf("m68k: s68k brq %i", (d&2)>>1);\r
97       if ((Pico_mcd->m.state_flags&1) && (d&3)==1) {\r
98         SekResetS68k(); // S68k comes out of RESET or BRQ state\r
99         Pico_mcd->m.state_flags&=~1;\r
100         dprintf("m68k: resetting s68k, cycles=%i", SekCyclesLeft);\r
101       }\r
102       Pico_mcd->m.busreq = d;\r
103       return;\r
104     case 2:\r
105       Pico_mcd->s68k_regs[2] = d; // really use s68k side register\r
106       return;\r
107     case 3:\r
108       dprintf("m68k_regs w3: %02x @%06x", (u8)d, SekPc);\r
109       d &= 0xc2;\r
110       if ((Pico_mcd->s68k_regs[3]>>6) != ((d>>6)&3))\r
111         dprintf("m68k: prg bank: %i -> %i", (Pico_mcd->s68k_regs[a]>>6), ((d>>6)&3));\r
112       //if ((Pico_mcd->s68k_regs[3]&4) != (d&4)) dprintf("m68k: ram mode %i mbit", (d&4) ? 1 : 2);\r
113       //if ((Pico_mcd->s68k_regs[3]&2) != (d&2)) dprintf("m68k: %s", (d&4) ? ((d&2) ? "word swap req" : "noop?") :\r
114       //                                             ((d&2) ? "word ram to s68k" : "word ram to m68k"));\r
115       d |= Pico_mcd->s68k_regs[3]&0x1d;\r
116       if (!(d & 4) && (d & 2)) d &= ~1; // return word RAM to s68k in 2M mode\r
117       Pico_mcd->s68k_regs[3] = d; // really use s68k side register\r
118       return;\r
119     case 6:\r
120       dprintf("FIXME hint[2]: %02x @%06x", (u8)d, SekPc);\r
121       Pico_mcd->bios[0x72 + 1] = d; // simple hint vector changer\r
122       return;\r
123     case 7:\r
124       dprintf("FIXME hint[3]: %02x @%06x", (u8)d, SekPc);\r
125       Pico_mcd->bios[0x72] = d;\r
126       dprintf("vector is now %08x", PicoRead32(0x70));\r
127       return;\r
128     case 0xe:\r
129       //dprintf("m68k: comm flag: %02x", d);\r
130       Pico_mcd->s68k_regs[0xe] = d;\r
131       return;\r
132   }\r
133 \r
134   if ((a&0xf0) == 0x10) {\r
135       Pico_mcd->s68k_regs[a] = d;\r
136       return;\r
137   }\r
138 \r
139   dprintf("m68k FIXME: invalid write? [%02x] %02x", a, d);\r
140 }\r
141 \r
142 \r
143 \r
144 static u32 s68k_reg_read16(u32 a)\r
145 {\r
146   u32 d=0;\r
147 \r
148   // dprintf("s68k_regs r%2i: [%02x] @ %06x", realsize&~1, a+(realsize&1), SekPcS68k);\r
149 \r
150   switch (a) {\r
151     case 0:\r
152       d = ((Pico_mcd->s68k_regs[0]&3)<<8) | 1; // ver = 0, not in reset state\r
153       goto end;\r
154     case 2:\r
155       d = (Pico_mcd->s68k_regs[a]<<8) | (Pico_mcd->s68k_regs[a+1]&0x1f);\r
156       dprintf("s68k_regs r3: %02x @%06x", (u8)d, SekPc);\r
157       goto end;\r
158     case 6:\r
159       d = CDC_Read_Reg();\r
160       goto end;\r
161     case 8:\r
162       d = Read_CDC_Host(1); // Gens returns 0 here on byte reads\r
163       goto end;\r
164     case 0xC:\r
165       dprintf("s68k stopwatch timer read");\r
166       d = Pico_mcd->m.timer_stopwatch >> 16;\r
167       goto end;\r
168     case 0x30:\r
169       dprintf("s68k int3 timer read");\r
170       break;\r
171     case 0x34: // fader\r
172       d = 0; // no busy bit\r
173       goto end;\r
174   }\r
175 \r
176   d = (Pico_mcd->s68k_regs[a]<<8) | Pico_mcd->s68k_regs[a+1];\r
177 \r
178 end:\r
179 \r
180   // dprintf("ret = %04x", d);\r
181 \r
182   return d;\r
183 }\r
184 \r
185 static void s68k_reg_write8(u32 a, u32 d)\r
186 {\r
187   //dprintf("s68k_regs w%2i: [%02x] %02x @ %06x", realsize, a, d, SekPcS68k);\r
188 \r
189   // TODO: review against Gens\r
190   switch (a) {\r
191     case 2:\r
192       return; // only m68k can change WP\r
193     case 3: {\r
194       int dold = Pico_mcd->s68k_regs[3];\r
195       dprintf("s68k_regs w3: %02x @%06x", (u8)d, SekPc);\r
196       d &= 0x1d;\r
197       if (d&4) {\r
198         d |= dold&0xc2;\r
199         if ((d ^ dold) & 5) d &= ~2; // in case of mode or bank change we clear DMNA (m68k req) bit\r
200         if (!(dold & 4)) {\r
201           dprintf("wram mode 2M->1M");\r
202           wram_2M_to_1M(Pico_mcd->word_ram2M);\r
203         }\r
204       } else {\r
205         d |= Pico_mcd->s68k_regs[3]&0xc3;\r
206         if (d&1) d &= ~2; // return word RAM to m68k in 2M mode\r
207         if (dold & 4) {\r
208           dprintf("wram mode 1M->2M");\r
209           wram_1M_to_2M(Pico_mcd->word_ram2M);\r
210         }\r
211       }\r
212       break;\r
213     }\r
214     case 4:\r
215       dprintf("s68k CDC dest: %x", d&7);\r
216       Pico_mcd->s68k_regs[4] = (Pico_mcd->s68k_regs[4]&0xC0) | (d&7); // CDC mode\r
217       return;\r
218     case 5:\r
219       //dprintf("s68k CDC reg addr: %x", d&0xf);\r
220       break;\r
221     case 7:\r
222       CDC_Write_Reg(d);\r
223       return;\r
224     case 0xa:\r
225       dprintf("s68k set CDC dma addr");\r
226       break;\r
227     case 0xc:\r
228     case 0xd:\r
229       dprintf("s68k set stopwatch timer");\r
230       Pico_mcd->m.timer_stopwatch = 0;\r
231       return;\r
232     case 0xe:\r
233       Pico_mcd->s68k_regs[0Xf] = (d>>1) | (d<<7); // ror8, Gens note: Dragons lair\r
234       Pico_mcd->m.timer_stopwatch = 0;\r
235       return;\r
236     case 0x31:\r
237       dprintf("s68k set int3 timer: %02x", d);\r
238       Pico_mcd->m.timer_int3 = d << 16;\r
239       break;\r
240     case 0x33: // IRQ mask\r
241       dprintf("s68k irq mask: %02x", d);\r
242       if ((d&(1<<4)) && (Pico_mcd->s68k_regs[0x37]&4) && !(Pico_mcd->s68k_regs[0x33]&(1<<4))) {\r
243         CDD_Export_Status();\r
244       }\r
245       break;\r
246     case 0x34: // fader\r
247       Pico_mcd->s68k_regs[a] = (u8) d & 0x7f;\r
248       return;\r
249     case 0x36:\r
250       return; // d/m bit is unsetable\r
251     case 0x37: {\r
252       u32 d_old = Pico_mcd->s68k_regs[0x37];\r
253       Pico_mcd->s68k_regs[0x37] = d&7;\r
254       if ((d&4) && !(d_old&4)) {\r
255         CDD_Export_Status();\r
256       }\r
257       return;\r
258     }\r
259     case 0x4b:\r
260       Pico_mcd->s68k_regs[a] = (u8) d;\r
261       CDD_Import_Command();\r
262       return;\r
263   }\r
264 \r
265   if ((a&0x1f0) == 0x10 || (a >= 0x38 && a < 0x42))\r
266   {\r
267     dprintf("s68k FIXME: invalid write @ %02x?", a);\r
268     return;\r
269   }\r
270 \r
271   Pico_mcd->s68k_regs[a] = (u8) d;\r
272 }\r
273 \r
274 \r
275 \r
276 static u32 OtherRead16End(u32 a, int realsize)\r
277 {\r
278   u32 d=0;\r
279 \r
280   if ((a&0xffffc0)==0xa12000) {\r
281     d=m68k_reg_read16(a);\r
282     goto end;\r
283   }\r
284 \r
285   dprintf("m68k FIXME: unusual r%i: %06x @%06x", realsize&~1, (a&0xfffffe)+(realsize&1), SekPc);\r
286 \r
287 end:\r
288   return d;\r
289 }\r
290 \r
291 \r
292 static void OtherWrite8End(u32 a, u32 d, int realsize)\r
293 {\r
294   if ((a&0xffffc0)==0xa12000) { m68k_reg_write8(a, d); return; }\r
295 \r
296   dprintf("m68k FIXME: strange w%i: %06x, %08x @%06x", realsize, a&0xffffff, d, SekPc);\r
297 }\r
298 \r
299 \r
300 #undef _ASM_MEMORY_C\r
301 #include "../MemoryCmn.c"\r
302 \r
303 \r
304 // -----------------------------------------------------------------\r
305 //                     Read Rom and read Ram\r
306 \r
307 u8 PicoReadM68k8(u32 a)\r
308 {\r
309   u32 d=0;\r
310 \r
311   if ((a&0xe00000)==0xe00000) { d = *(u8 *)(Pico.ram+((a^1)&0xffff)); goto end; } // Ram\r
312 \r
313   a&=0xffffff;\r
314 \r
315   if (a < 0x20000) { d = *(u8 *)(Pico_mcd->bios+(a^1)); goto end; } // bios\r
316 \r
317   // prg RAM\r
318   if ((a&0xfe0000)==0x020000) {\r
319     u8 *prg_bank = Pico_mcd->prg_ram_b[Pico_mcd->s68k_regs[3]>>6];\r
320     d = *(prg_bank+((a^1)&0x1ffff));\r
321     goto end;\r
322   }\r
323 \r
324 #if 0\r
325   if (a == 0x200000 && SekPc == 0xff0b66 && Pico.m.frame_count > 1000)\r
326   {\r
327           int i;\r
328           FILE *ff;\r
329           unsigned short *ram = (unsigned short *) Pico.ram;\r
330           // unswap and dump RAM\r
331           for (i = 0; i < 0x10000/2; i++)\r
332                   ram[i] = (ram[i]>>8) | (ram[i]<<8);\r
333           ff = fopen("ram.bin", "wb");\r
334           fwrite(ram, 1, 0x10000, ff);\r
335           fclose(ff);\r
336           exit(0);\r
337   }\r
338 #endif\r
339 \r
340   // word RAM\r
341   if ((a&0xfc0000)==0x200000) {\r
342     dprintf("m68k_wram r8: [%06x] @%06x", a, SekPc);\r
343     if (Pico_mcd->s68k_regs[3]&4) { // 1M mode?\r
344       int bank = Pico_mcd->s68k_regs[3]&1;\r
345       if (a >= 0x220000)\r
346            a = (a&3) | (cell_map(a >> 2) << 2); // cell arranged\r
347       else a &= 0x1ffff;\r
348       d = Pico_mcd->word_ram1M[bank][a^1];\r
349     } else {\r
350       // allow access in any mode, like Gens does\r
351       d = Pico_mcd->word_ram2M[(a^1)&0x3ffff];\r
352     }\r
353     dprintf("ret = %02x", (u8)d);\r
354     goto end;\r
355   }\r
356 \r
357   if ((a&0xff4000)==0xa00000) { d=z80Read8(a); goto end; } // Z80 Ram\r
358 \r
359   if ((a&0xffffc0)==0xa12000)\r
360     rdprintf("m68k_regs r8: [%02x] @%06x", a&0x3f, SekPc);\r
361 \r
362   d=OtherRead16(a&~1, 8|(a&1)); if ((a&1)==0) d>>=8;\r
363 \r
364   if ((a&0xffffc0)==0xa12000)\r
365     rdprintf("ret = %02x", (u8)d);\r
366 \r
367   end:\r
368 \r
369 #ifdef __debug_io\r
370   dprintf("r8 : %06x,   %02x @%06x", a&0xffffff, (u8)d, SekPc);\r
371 #endif\r
372   return (u8)d;\r
373 }\r
374 \r
375 \r
376 u16 PicoReadM68k16(u32 a)\r
377 {\r
378   u16 d=0;\r
379 \r
380   if ((a&0xe00000)==0xe00000) { d=*(u16 *)(Pico.ram+(a&0xfffe)); goto end; } // Ram\r
381 \r
382   a&=0xfffffe;\r
383 \r
384   if (a < 0x20000) { d = *(u16 *)(Pico_mcd->bios+a); goto end; } // bios\r
385 \r
386   // prg RAM\r
387   if ((a&0xfe0000)==0x020000) {\r
388     u8 *prg_bank = Pico_mcd->prg_ram_b[Pico_mcd->s68k_regs[3]>>6];\r
389     d = *(u16 *)(prg_bank+(a&0x1fffe));\r
390     goto end;\r
391   }\r
392 \r
393   // word RAM\r
394   if ((a&0xfc0000)==0x200000) {\r
395     dprintf("m68k_wram r16: [%06x] @%06x", a, SekPc);\r
396     if (Pico_mcd->s68k_regs[3]&4) { // 1M mode?\r
397       int bank = Pico_mcd->s68k_regs[3]&1;\r
398       if (a >= 0x220000)\r
399            a = (a&2) | (cell_map(a >> 2) << 2); // cell arranged\r
400       else a &= 0x1fffe;\r
401       d = *(u16 *)(Pico_mcd->word_ram1M[bank]+a);\r
402     } else {\r
403       // allow access in any mode, like Gens does\r
404       d = *(u16 *)(Pico_mcd->word_ram2M+(a&0x3fffe));\r
405     }\r
406     dprintf("ret = %04x", d);\r
407     goto end;\r
408   }\r
409 \r
410   if ((a&0xffffc0)==0xa12000)\r
411     rdprintf("m68k_regs r16: [%02x] @%06x", a&0x3f, SekPc);\r
412 \r
413   d = (u16)OtherRead16(a, 16);\r
414 \r
415   if ((a&0xffffc0)==0xa12000)\r
416     rdprintf("ret = %04x", d);\r
417 \r
418   end:\r
419 \r
420 #ifdef __debug_io\r
421   dprintf("r16: %06x, %04x  @%06x", a&0xffffff, d, SekPc);\r
422 #endif\r
423   return d;\r
424 }\r
425 \r
426 \r
427 u32 PicoReadM68k32(u32 a)\r
428 {\r
429   u32 d=0;\r
430 \r
431   if ((a&0xe00000)==0xe00000) { u16 *pm=(u16 *)(Pico.ram+(a&0xfffe)); d = (pm[0]<<16)|pm[1]; goto end; } // Ram\r
432 \r
433   a&=0xfffffe;\r
434 \r
435   if (a < 0x20000) { u16 *pm=(u16 *)(Pico_mcd->bios+a); d = (pm[0]<<16)|pm[1]; goto end; } // bios\r
436 \r
437   // prg RAM\r
438   if ((a&0xfe0000)==0x020000) {\r
439     u8 *prg_bank = Pico_mcd->prg_ram_b[Pico_mcd->s68k_regs[3]>>6];\r
440     u16 *pm=(u16 *)(prg_bank+(a&0x1fffe));\r
441     d = (pm[0]<<16)|pm[1];\r
442     goto end;\r
443   }\r
444 \r
445   // word RAM\r
446   if ((a&0xfc0000)==0x200000) {\r
447     dprintf("m68k_wram r32: [%06x] @%06x", a, SekPc);\r
448     if (Pico_mcd->s68k_regs[3]&4) { // 1M mode?\r
449       int bank = Pico_mcd->s68k_regs[3]&1;\r
450       if (a >= 0x220000) { // cell arranged\r
451         u32 a1, a2;\r
452         a1 = (a&2) | (cell_map(a >> 2) << 2);\r
453         if (a&2) a2 = cell_map((a+2) >> 2) << 2;\r
454         else     a2 = a1 + 2;\r
455         d  = *(u16 *)(Pico_mcd->word_ram1M[bank]+a1) << 16;\r
456         d |= *(u16 *)(Pico_mcd->word_ram1M[bank]+a2);\r
457       } else {\r
458         u16 *pm=(u16 *)(Pico_mcd->word_ram1M[bank]+(a&0x1fffe)); d = (pm[0]<<16)|pm[1];\r
459       }\r
460     } else {\r
461       // allow access in any mode, like Gens does\r
462       u16 *pm=(u16 *)(Pico_mcd->word_ram2M+(a&0x3fffe)); d = (pm[0]<<16)|pm[1];\r
463     }\r
464     dprintf("ret = %08x", d);\r
465     goto end;\r
466   }\r
467 \r
468   if ((a&0xffffc0)==0xa12000)\r
469     rdprintf("m68k_regs r32: [%02x] @%06x", a&0x3f, SekPc);\r
470 \r
471   d = (OtherRead16(a, 32)<<16)|OtherRead16(a+2, 32);\r
472 \r
473   if ((a&0xffffc0)==0xa12000)\r
474     rdprintf("ret = %08x", d);\r
475 \r
476   end:\r
477 #ifdef __debug_io\r
478   dprintf("r32: %06x, %08x @%06x", a&0xffffff, d, SekPc);\r
479 #endif\r
480   return d;\r
481 }\r
482 \r
483 \r
484 // -----------------------------------------------------------------\r
485 //                            Write Ram\r
486 \r
487 void PicoWriteM68k8(u32 a,u8 d)\r
488 {\r
489 #ifdef __debug_io\r
490   dprintf("w8 : %06x,   %02x @%06x", a&0xffffff, d, SekPc);\r
491 #endif\r
492   //if ((a&0xe0ffff)==0xe0a9ba+0x69c)\r
493   //  dprintf("w8 : %06x,   %02x @%06x", a&0xffffff, d, SekPc);\r
494 \r
495 \r
496   if ((a&0xe00000)==0xe00000) { // Ram\r
497     *(u8 *)(Pico.ram+((a^1)&0xffff)) = d;\r
498     return;\r
499   }\r
500 \r
501   a&=0xffffff;\r
502 \r
503   // prg RAM\r
504   if ((a&0xfe0000)==0x020000) {\r
505     u8 *prg_bank = Pico_mcd->prg_ram_b[Pico_mcd->s68k_regs[3]>>6];\r
506     *(u8 *)(prg_bank+((a^1)&0x1ffff))=d;\r
507     return;\r
508   }\r
509 \r
510   // word RAM\r
511   if ((a&0xfc0000)==0x200000) {\r
512     dprintf("m68k_wram w8: [%06x] %02x @%06x", a, d, SekPc);\r
513     if (Pico_mcd->s68k_regs[3]&4) { // 1M mode?\r
514       int bank = Pico_mcd->s68k_regs[3]&1;\r
515       if (a >= 0x220000)\r
516            a = (a&3) | (cell_map(a >> 2) << 2); // cell arranged\r
517       else a &= 0x1ffff;\r
518       *(u8 *)(Pico_mcd->word_ram1M[bank]+(a^1))=d;\r
519     } else {\r
520       // allow access in any mode, like Gens does\r
521       *(u8 *)(Pico_mcd->word_ram2M+((a^1)&0x3ffff))=d;\r
522     }\r
523     return;\r
524   }\r
525 \r
526   if ((a&0xffffc0)==0xa12000)\r
527     rdprintf("m68k_regs w8: [%02x] %02x @%06x", a&0x3f, d, SekPc);\r
528 \r
529   OtherWrite8(a,d,8);\r
530 }\r
531 \r
532 \r
533 void PicoWriteM68k16(u32 a,u16 d)\r
534 {\r
535 #ifdef __debug_io\r
536   dprintf("w16: %06x, %04x", a&0xffffff, d);\r
537 #endif\r
538   //  dprintf("w16: %06x, %04x  @%06x", a&0xffffff, d, SekPc);\r
539 \r
540   if ((a&0xe00000)==0xe00000) { // Ram\r
541     *(u16 *)(Pico.ram+(a&0xfffe))=d;\r
542     return;\r
543   }\r
544 \r
545   a&=0xfffffe;\r
546 \r
547   // prg RAM\r
548   if ((a&0xfe0000)==0x020000) {\r
549     u8 *prg_bank = Pico_mcd->prg_ram_b[Pico_mcd->s68k_regs[3]>>6];\r
550     *(u16 *)(prg_bank+(a&0x1fffe))=d;\r
551     return;\r
552   }\r
553 \r
554   // word RAM\r
555   if ((a&0xfc0000)==0x200000) {\r
556     dprintf("m68k_wram w16: [%06x] %04x @%06x", a, d, SekPc);\r
557     if (Pico_mcd->s68k_regs[3]&4) { // 1M mode?\r
558       int bank = Pico_mcd->s68k_regs[3]&1;\r
559       if (a >= 0x220000)\r
560            a = (a&2) | (cell_map(a >> 2) << 2); // cell arranged\r
561       else a &= 0x1fffe;\r
562       *(u16 *)(Pico_mcd->word_ram1M[bank]+a)=d;\r
563     } else {\r
564       // allow access in any mode, like Gens does\r
565       *(u16 *)(Pico_mcd->word_ram2M+(a&0x3fffe))=d;\r
566     }\r
567     return;\r
568   }\r
569 \r
570   if ((a&0xffffc0)==0xa12000)\r
571     rdprintf("m68k_regs w16: [%02x] %04x @%06x", a&0x3f, d, SekPc);\r
572 \r
573   OtherWrite16(a,d);\r
574 }\r
575 \r
576 \r
577 void PicoWriteM68k32(u32 a,u32 d)\r
578 {\r
579 #ifdef __debug_io\r
580   dprintf("w32: %06x, %08x", a&0xffffff, d);\r
581 #endif\r
582 \r
583   if ((a&0xe00000)==0xe00000)\r
584   {\r
585     // Ram:\r
586     u16 *pm=(u16 *)(Pico.ram+(a&0xfffe));\r
587     pm[0]=(u16)(d>>16); pm[1]=(u16)d;\r
588     return;\r
589   }\r
590 \r
591   a&=0xfffffe;\r
592 \r
593   // prg RAM\r
594   if ((a&0xfe0000)==0x020000) {\r
595     u8 *prg_bank = Pico_mcd->prg_ram_b[Pico_mcd->s68k_regs[3]>>6];\r
596     u16 *pm=(u16 *)(prg_bank+(a&0x1fffe));\r
597     pm[0]=(u16)(d>>16); pm[1]=(u16)d;\r
598     return;\r
599   }\r
600 \r
601   // word RAM\r
602   if ((a&0xfc0000)==0x200000) {\r
603     if (d != 0) // don't log clears\r
604       dprintf("m68k_wram w32: [%06x] %08x @%06x", a, d, SekPc);\r
605     if (Pico_mcd->s68k_regs[3]&4) { // 1M mode?\r
606       int bank = Pico_mcd->s68k_regs[3]&1;\r
607       if (a >= 0x220000) { // cell arranged\r
608         u32 a1, a2;\r
609         a1 = (a&2) | (cell_map(a >> 2) << 2);\r
610         if (a&2) a2 = cell_map((a+2) >> 2) << 2;\r
611         else     a2 = a1 + 2;\r
612         *(u16 *)(Pico_mcd->word_ram1M[bank]+a1) = d >> 16;\r
613         *(u16 *)(Pico_mcd->word_ram1M[bank]+a2) = d;\r
614       } else {\r
615         u16 *pm=(u16 *)(Pico_mcd->word_ram1M[bank]+(a&0x1fffe));\r
616         pm[0]=(u16)(d>>16); pm[1]=(u16)d;\r
617       }\r
618     } else {\r
619       // allow access in any mode, like Gens does\r
620       u16 *pm=(u16 *)(Pico_mcd->word_ram2M+(a&0x3fffe));\r
621       pm[0]=(u16)(d>>16); pm[1]=(u16)d;\r
622     }\r
623     return;\r
624   }\r
625 \r
626   if ((a&0xffffc0)==0xa12000)\r
627     rdprintf("m68k_regs w32: [%02x] %08x @%06x", a&0x3f, d, SekPc);\r
628 \r
629   OtherWrite16(a,  (u16)(d>>16));\r
630   OtherWrite16(a+2,(u16)d);\r
631 }\r
632 \r
633 \r
634 // -----------------------------------------------------------------\r
635 \r
636 \r
637 u8 PicoReadS68k8(u32 a)\r
638 {\r
639   u32 d=0;\r
640 \r
641   a&=0xffffff;\r
642 \r
643   // prg RAM\r
644   if (a < 0x80000) {\r
645     d = *(Pico_mcd->prg_ram+(a^1));\r
646     goto end;\r
647   }\r
648 \r
649   // regs\r
650   if ((a&0xfffe00) == 0xff8000) {\r
651     a &= 0x1ff;\r
652     rdprintf("s68k_regs r8: [%02x] @ %06x", a, SekPcS68k);\r
653     if (a >= 0x50 && a < 0x68)\r
654          d = gfx_cd_read(a&~1);\r
655     else d = s68k_reg_read16(a&~1);\r
656     if ((a&1)==0) d>>=8;\r
657     rdprintf("ret = %02x", (u8)d);\r
658     goto end;\r
659   }\r
660 \r
661   // word RAM (2M area)\r
662   if ((a&0xfc0000)==0x080000) { // 080000-0bffff\r
663     // test: batman returns\r
664     dprintf("s68k_wram2M r8: [%06x] @%06x", a, SekPcS68k);\r
665     if (Pico_mcd->s68k_regs[3]&4) { // 1M decode mode?\r
666       int bank = !(Pico_mcd->s68k_regs[3]&1);\r
667       d = Pico_mcd->word_ram1M[bank][((a>>1)^1)&0x1ffff];\r
668       if (a&1) d &= 0x0f;\r
669       else d >>= 4;\r
670       dprintf("FIXME: decode");\r
671     } else {\r
672       // allow access in any mode, like Gens does\r
673       d = Pico_mcd->word_ram2M[(a^1)&0x3ffff];\r
674     }\r
675     dprintf("ret = %02x", (u8)d);\r
676     goto end;\r
677   }\r
678 \r
679   // word RAM (1M area)\r
680   if ((a&0xfe0000)==0x0c0000) { // 0c0000-0dffff\r
681     int bank;\r
682     dprintf("s68k_wram1M r8: [%06x] @%06x", a, SekPcS68k);\r
683     if (!(Pico_mcd->s68k_regs[3]&4))\r
684       dprintf("s68k_wram1M FIXME: wrong mode");\r
685     bank = !(Pico_mcd->s68k_regs[3]&1);\r
686     d = Pico_mcd->word_ram1M[bank][(a^1)&0x1ffff];\r
687     dprintf("ret = %02x", (u8)d);\r
688     goto end;\r
689   }\r
690 \r
691   // PCM\r
692   if ((a&0xff8000)==0xff0000) {\r
693     dprintf("s68k_pcm r8: [%06x] @%06x", a, SekPcS68k);\r
694     a &= 0x7fff;\r
695     if (a >= 0x2000)\r
696       d = Pico_mcd->pcm_ram_b[Pico_mcd->pcm.bank][(a>>1)&0xfff];\r
697     else if (a >= 0x20) {\r
698       a &= 0x1e;\r
699       d = Pico_mcd->pcm.ch[a>>2].addr >> PCM_STEP_SHIFT;\r
700       if (a & 2) d >>= 8;\r
701     }\r
702     dprintf("ret = %02x", (u8)d);\r
703     goto end;\r
704   }\r
705 \r
706   // bram\r
707   if ((a&0xff0000)==0xfe0000) {\r
708     d = Pico_mcd->bram[(a>>1)&0x1fff];\r
709     goto end;\r
710   }\r
711 \r
712   dprintf("s68k r8 : %06x,   %02x @%06x", a&0xffffff, (u8)d, SekPcS68k);\r
713 \r
714   end:\r
715 \r
716 #ifdef __debug_io2\r
717   dprintf("s68k r8 : %06x,   %02x @%06x", a&0xffffff, (u8)d, SekPcS68k);\r
718 #endif\r
719   return (u8)d;\r
720 }\r
721 \r
722 \r
723 u16 PicoReadS68k16(u32 a)\r
724 {\r
725   u32 d=0;\r
726 \r
727   a&=0xfffffe;\r
728 \r
729   // prg RAM\r
730   if (a < 0x80000) {\r
731     d = *(u16 *)(Pico_mcd->prg_ram+a);\r
732     goto end;\r
733   }\r
734 \r
735   // regs\r
736   if ((a&0xfffe00) == 0xff8000) {\r
737     a &= 0x1fe;\r
738     rdprintf("s68k_regs r16: [%02x] @ %06x", a, SekPcS68k);\r
739     if (a >= 0x50 && a < 0x68)\r
740          d = gfx_cd_read(a);\r
741     else d = s68k_reg_read16(a);\r
742     rdprintf("ret = %04x", d);\r
743     goto end;\r
744   }\r
745 \r
746   // word RAM (2M area)\r
747   if ((a&0xfc0000)==0x080000) { // 080000-0bffff\r
748     dprintf("s68k_wram2M r16: [%06x] @%06x", a, SekPcS68k);\r
749     if (Pico_mcd->s68k_regs[3]&4) { // 1M decode mode?\r
750       int bank = !(Pico_mcd->s68k_regs[3]&1);\r
751       d = Pico_mcd->word_ram1M[bank][((a>>1)^1)&0x1ffff];\r
752       d |= d << 4; d &= ~0xf0;\r
753       dprintf("FIXME: decode");\r
754     } else {\r
755       // allow access in any mode, like Gens does\r
756       d = *(u16 *)(Pico_mcd->word_ram2M+(a&0x3fffe));\r
757     }\r
758     dprintf("ret = %04x", d);\r
759     goto end;\r
760   }\r
761 \r
762   // word RAM (1M area)\r
763   if ((a&0xfe0000)==0x0c0000) { // 0c0000-0dffff\r
764     int bank;\r
765     dprintf("s68k_wram1M r16: [%06x] @%06x", a, SekPcS68k);\r
766     if (!(Pico_mcd->s68k_regs[3]&4))\r
767       dprintf("s68k_wram1M FIXME: wrong mode");\r
768     bank = !(Pico_mcd->s68k_regs[3]&1);\r
769     d = *(u16 *)(Pico_mcd->word_ram1M[bank]+(a&0x1fffe));\r
770     dprintf("ret = %04x", d);\r
771     goto end;\r
772   }\r
773 \r
774   // bram\r
775   if ((a&0xff0000)==0xfe0000) {\r
776     dprintf("s68k_bram r16: [%06x] @%06x", a, SekPcS68k);\r
777     a = (a>>1)&0x1fff;\r
778     d = Pico_mcd->bram[a++];            // Gens does little endian here, and so do we..\r
779     d|= Pico_mcd->bram[a++] << 8;\r
780     dprintf("ret = %04x", d);\r
781     goto end;\r
782   }\r
783 \r
784   // PCM\r
785   if ((a&0xff8000)==0xff0000) {\r
786     dprintf("s68k_pcm r16: [%06x] @%06x", a, SekPcS68k);\r
787     a &= 0x7fff;\r
788     if (a >= 0x2000)\r
789       d = Pico_mcd->pcm_ram_b[Pico_mcd->pcm.bank][(a>>1)&0xfff];\r
790     else if (a >= 0x20) {\r
791       a &= 0x1e;\r
792       d = Pico_mcd->pcm.ch[a>>2].addr >> PCM_STEP_SHIFT;\r
793       if (a & 2) d >>= 8;\r
794     }\r
795     dprintf("ret = %04x", d);\r
796     goto end;\r
797   }\r
798 \r
799   dprintf("s68k r16: %06x, %04x  @%06x", a&0xffffff, d, SekPcS68k);\r
800 \r
801   end:\r
802 \r
803 #ifdef __debug_io2\r
804   dprintf("s68k r16: %06x, %04x  @%06x", a&0xffffff, d, SekPcS68k);\r
805 #endif\r
806   return d;\r
807 }\r
808 \r
809 \r
810 u32 PicoReadS68k32(u32 a)\r
811 {\r
812   u32 d=0;\r
813 \r
814   a&=0xfffffe;\r
815 \r
816   // prg RAM\r
817   if (a < 0x80000) {\r
818     u16 *pm=(u16 *)(Pico_mcd->prg_ram+a);\r
819     d = (pm[0]<<16)|pm[1];\r
820     goto end;\r
821   }\r
822 \r
823   // regs\r
824   if ((a&0xfffe00) == 0xff8000) {\r
825     a &= 0x1fe;\r
826     rdprintf("s68k_regs r32: [%02x] @ %06x", a, SekPcS68k);\r
827     if (a >= 0x50 && a < 0x68)\r
828          d = (gfx_cd_read(a)<<16)|gfx_cd_read(a+2);\r
829     else d = (s68k_reg_read16(a)<<16)|s68k_reg_read16(a+2);\r
830     rdprintf("ret = %08x", d);\r
831     goto end;\r
832   }\r
833 \r
834   // word RAM (2M area)\r
835   if ((a&0xfc0000)==0x080000) { // 080000-0bffff\r
836     dprintf("s68k_wram2M r32: [%06x] @%06x", a, SekPcS68k);\r
837     if (Pico_mcd->s68k_regs[3]&4) { // 1M decode mode?\r
838       int bank = !(Pico_mcd->s68k_regs[3]&1);\r
839       a >>= 1;\r
840       d  = Pico_mcd->word_ram1M[bank][((a+0)^1)&0x1ffff] << 16;\r
841       d |= Pico_mcd->word_ram1M[bank][((a+1)^1)&0x1ffff];\r
842       d |= d << 4; d &= 0x0f0f0f0f;\r
843       dprintf("FIXME: decode");\r
844     } else {\r
845       // allow access in any mode, like Gens does\r
846       u16 *pm=(u16 *)(Pico_mcd->word_ram2M+(a&0x3fffe)); d = (pm[0]<<16)|pm[1];\r
847     }\r
848     dprintf("ret = %08x", d);\r
849     goto end;\r
850   }\r
851 \r
852   // word RAM (1M area)\r
853   if ((a&0xfe0000)==0x0c0000) { // 0c0000-0dffff\r
854     int bank;\r
855     dprintf("s68k_wram1M r32: [%06x] @%06x", a, SekPcS68k);\r
856     if (!(Pico_mcd->s68k_regs[3]&4))\r
857       dprintf("s68k_wram1M FIXME: wrong mode");\r
858     bank = !(Pico_mcd->s68k_regs[3]&1);\r
859     u16 *pm=(u16 *)(Pico_mcd->word_ram1M[bank]+(a&0x1fffe)); d = (pm[0]<<16)|pm[1];\r
860     dprintf("ret = %08x", d);\r
861     goto end;\r
862   }\r
863 \r
864   // PCM\r
865   if ((a&0xff8000)==0xff0000) {\r
866     dprintf("s68k_pcm r32: [%06x] @%06x", a, SekPcS68k);\r
867     a &= 0x7fff;\r
868     if (a >= 0x2000) {\r
869       a >>= 1;\r
870       d  = Pico_mcd->pcm_ram_b[Pico_mcd->pcm.bank][a&0xfff] << 16;\r
871       d |= Pico_mcd->pcm_ram_b[Pico_mcd->pcm.bank][(a+1)&0xfff];\r
872     } else if (a >= 0x20) {\r
873       a &= 0x1e;\r
874       if (a & 2) {\r
875         a >>= 2;\r
876         d  = (Pico_mcd->pcm.ch[a].addr >> (PCM_STEP_SHIFT-8)) & 0xff0000;\r
877         d |= (Pico_mcd->pcm.ch[(a+1)&7].addr >> PCM_STEP_SHIFT)   & 0xff;\r
878       } else {\r
879         d = Pico_mcd->pcm.ch[a>>2].addr >> PCM_STEP_SHIFT;\r
880         d = ((d<<16)&0xff0000) | ((d>>8)&0xff); // PCM chip is LE\r
881       }\r
882     }\r
883     dprintf("ret = %08x", d);\r
884     goto end;\r
885   }\r
886 \r
887   // bram\r
888   if ((a&0xff0000)==0xfe0000) {\r
889     dprintf("s68k_bram r32: [%06x] @%06x", a, SekPcS68k);\r
890     a = (a>>1)&0x1fff;\r
891     d = Pico_mcd->bram[a++] << 16;              // middle endian? TODO: verify against Fusion..\r
892     d|= Pico_mcd->bram[a++] << 24;\r
893     d|= Pico_mcd->bram[a++];\r
894     d|= Pico_mcd->bram[a++] << 8;\r
895     dprintf("ret = %08x", d);\r
896     goto end;\r
897   }\r
898 \r
899   dprintf("s68k r32: %06x, %08x @%06x", a&0xffffff, d, SekPcS68k);\r
900 \r
901   end:\r
902 \r
903 #ifdef __debug_io2\r
904   dprintf("s68k r32: %06x, %08x @%06x", a&0xffffff, d, SekPcS68k);\r
905 #endif\r
906   return d;\r
907 }\r
908 \r
909 \r
910 // -----------------------------------------------------------------\r
911 \r
912 void PicoWriteS68k8(u32 a,u8 d)\r
913 {\r
914 #ifdef __debug_io2\r
915   dprintf("s68k w8 : %06x,   %02x @%06x", a&0xffffff, d, SekPcS68k);\r
916 #endif\r
917 \r
918   a&=0xffffff;\r
919 \r
920   // prg RAM\r
921   if (a < 0x80000) {\r
922     u8 *pm=(u8 *)(Pico_mcd->prg_ram+(a^1));\r
923     *pm=d;\r
924     return;\r
925   }\r
926 \r
927   // regs\r
928   if ((a&0xfffe00) == 0xff8000) {\r
929     a &= 0x1ff;\r
930     rdprintf("s68k_regs w8: [%02x] %02x @ %06x", a, d, SekPcS68k);\r
931     if (a >= 0x50 && a < 0x68)\r
932          gfx_cd_write(a&~1, (d<<8)|d);\r
933     else s68k_reg_write8(a,d);\r
934     return;\r
935   }\r
936 \r
937   // word RAM (2M area)\r
938   if ((a&0xfc0000)==0x080000) { // 080000-0bffff\r
939     dprintf("s68k_wram2M w8: [%06x] %02x @%06x", a, d, SekPcS68k);\r
940     if (Pico_mcd->s68k_regs[3]&4) { // 1M decode mode?\r
941       int bank = !(Pico_mcd->s68k_regs[3]&1);\r
942       if (a&1) d &= 0x0f;\r
943       else d >>= 4;\r
944       Pico_mcd->word_ram1M[bank][((a>>1)^1)&0x1ffff]=d;\r
945       dprintf("FIXME: decode");\r
946     } else {\r
947       // allow access in any mode, like Gens does\r
948       *(u8 *)(Pico_mcd->word_ram2M+((a^1)&0x3ffff))=d;\r
949     }\r
950     return;\r
951   }\r
952 \r
953   // word RAM (1M area)\r
954   if ((a&0xfe0000)==0x0c0000) { // 0c0000-0dffff\r
955     int bank;\r
956     if (d)\r
957       dprintf("s68k_wram1M w8: [%06x] %02x @%06x", a, d, SekPcS68k);\r
958     if (!(Pico_mcd->s68k_regs[3]&4))\r
959       dprintf("s68k_wram1M FIXME: wrong mode");\r
960     bank = !(Pico_mcd->s68k_regs[3]&1);\r
961     *(u8 *)(Pico_mcd->word_ram1M[bank]+((a^1)&0x1ffff))=d;\r
962     return;\r
963   }\r
964 \r
965   // PCM\r
966   if ((a&0xff8000)==0xff0000) {\r
967     a &= 0x7fff;\r
968     if (a >= 0x2000)\r
969       Pico_mcd->pcm_ram_b[Pico_mcd->pcm.bank][(a>>1)&0xfff] = d;\r
970     else if (a < 0x12)\r
971       pcm_write(a>>1, d);\r
972     return;\r
973   }\r
974 \r
975   // bram\r
976   if ((a&0xff0000)==0xfe0000) {\r
977     Pico_mcd->bram[(a>>1)&0x1fff] = d;\r
978     SRam.changed = 1;\r
979     return;\r
980   }\r
981 \r
982   dprintf("s68k w8 : %06x,   %02x @%06x", a&0xffffff, d, SekPcS68k);\r
983 }\r
984 \r
985 \r
986 void PicoWriteS68k16(u32 a,u16 d)\r
987 {\r
988 #ifdef __debug_io2\r
989   dprintf("s68k w16: %06x, %04x @%06x", a&0xffffff, d, SekPcS68k);\r
990 #endif\r
991 \r
992   a&=0xfffffe;\r
993 \r
994   // prg RAM\r
995   if (a < 0x80000) {\r
996     *(u16 *)(Pico_mcd->prg_ram+a)=d;\r
997     return;\r
998   }\r
999 \r
1000   // regs\r
1001   if ((a&0xfffe00) == 0xff8000) {\r
1002     a &= 0x1fe;\r
1003     rdprintf("s68k_regs w16: [%02x] %04x @ %06x", a, d, SekPcS68k);\r
1004     if (a >= 0x50 && a < 0x68)\r
1005       gfx_cd_write(a, d);\r
1006     else {\r
1007       if (a == 0xe) { // special case, 2 byte writes would be handled differently\r
1008         Pico_mcd->s68k_regs[0xf] = d;\r
1009         return;\r
1010       }\r
1011       s68k_reg_write8(a,  d>>8);\r
1012       s68k_reg_write8(a+1,d&0xff);\r
1013     }\r
1014     return;\r
1015   }\r
1016 \r
1017   // word RAM (2M area)\r
1018   if ((a&0xfc0000)==0x080000) { // 080000-0bffff\r
1019     dprintf("s68k_wram2M w16: [%06x] %04x @%06x", a, d, SekPcS68k);\r
1020     if (Pico_mcd->s68k_regs[3]&4) { // 1M decode mode?\r
1021       int bank = !(Pico_mcd->s68k_regs[3]&1);\r
1022       d &= ~0xf0; d |= d >> 8;\r
1023       Pico_mcd->word_ram1M[bank][((a>>1)^1)&0x1ffff] = d;\r
1024       dprintf("FIXME: decode");\r
1025     } else {\r
1026       // allow access in any mode, like Gens does\r
1027       *(u16 *)(Pico_mcd->word_ram2M+(a&0x3fffe))=d;\r
1028     }\r
1029     return;\r
1030   }\r
1031 \r
1032   // word RAM (1M area)\r
1033   if ((a&0xfe0000)==0x0c0000) { // 0c0000-0dffff\r
1034     int bank;\r
1035     if (d)\r
1036       dprintf("s68k_wram1M w16: [%06x] %04x @%06x", a, d, SekPcS68k);\r
1037     if (!(Pico_mcd->s68k_regs[3]&4))\r
1038       dprintf("s68k_wram1M FIXME: wrong mode");\r
1039     bank = !(Pico_mcd->s68k_regs[3]&1);\r
1040     *(u16 *)(Pico_mcd->word_ram1M[bank]+(a&0x1fffe))=d;\r
1041     return;\r
1042   }\r
1043 \r
1044   // PCM\r
1045   if ((a&0xff8000)==0xff0000) {\r
1046     a &= 0x7fff;\r
1047     if (a >= 0x2000)\r
1048       Pico_mcd->pcm_ram_b[Pico_mcd->pcm.bank][(a>>1)&0xfff] = d;\r
1049     else if (a < 0x12)\r
1050       pcm_write(a>>1, d & 0xff);\r
1051     return;\r
1052   }\r
1053 \r
1054   // bram\r
1055   if ((a&0xff0000)==0xfe0000) {\r
1056     dprintf("s68k_bram w16: [%06x] %04x @%06x", a, d, SekPcS68k);\r
1057     a = (a>>1)&0x1fff;\r
1058     Pico_mcd->bram[a++] = d;            // Gens does little endian here, an so do we..\r
1059     Pico_mcd->bram[a++] = d >> 8;\r
1060     SRam.changed = 1;\r
1061     return;\r
1062   }\r
1063 \r
1064   dprintf("s68k w16: %06x, %04x @%06x", a&0xffffff, d, SekPcS68k);\r
1065 }\r
1066 \r
1067 \r
1068 void PicoWriteS68k32(u32 a,u32 d)\r
1069 {\r
1070 #ifdef __debug_io2\r
1071   dprintf("s68k w32: %06x, %08x @%06x", a&0xffffff, d, SekPcS68k);\r
1072 #endif\r
1073 \r
1074   a&=0xfffffe;\r
1075 \r
1076   // prg RAM\r
1077   if (a < 0x80000) {\r
1078     u16 *pm=(u16 *)(Pico_mcd->prg_ram+a);\r
1079     pm[0]=(u16)(d>>16); pm[1]=(u16)d;\r
1080     return;\r
1081   }\r
1082 \r
1083   // regs\r
1084   if ((a&0xfffe00) == 0xff8000) {\r
1085     a &= 0x1fe;\r
1086     rdprintf("s68k_regs w32: [%02x] %08x @ %06x", a, d, SekPcS68k);\r
1087     if (a >= 0x50 && a < 0x68) {\r
1088       gfx_cd_write(a,   d>>16);\r
1089       gfx_cd_write(a+2, d&0xffff);\r
1090     } else {\r
1091       s68k_reg_write8(a,   d>>24);\r
1092       s68k_reg_write8(a+1,(d>>16)&0xff);\r
1093       s68k_reg_write8(a+2,(d>>8) &0xff);\r
1094       s68k_reg_write8(a+3, d     &0xff);\r
1095     }\r
1096     return;\r
1097   }\r
1098 \r
1099   // word RAM (2M area)\r
1100   if ((a&0xfc0000)==0x080000) { // 080000-0bffff\r
1101     dprintf("s68k_wram2M w32: [%06x] %08x @%06x", a, d, SekPcS68k);\r
1102     if (Pico_mcd->s68k_regs[3]&4) { // 1M decode mode?\r
1103       int bank = !(Pico_mcd->s68k_regs[3]&1);\r
1104       a >>= 1;\r
1105       d &= 0x0f0f0f0f; d |= d >> 4;\r
1106       Pico_mcd->word_ram1M[bank][((a+0)^1)&0x1ffff] = d >> 16;\r
1107       Pico_mcd->word_ram1M[bank][((a+1)^1)&0x1ffff] = d;\r
1108       dprintf("FIXME: decode");\r
1109     } else {\r
1110       // allow access in any mode, like Gens does\r
1111       u16 *pm=(u16 *)(Pico_mcd->word_ram2M+(a&0x3fffe));\r
1112       pm[0]=(u16)(d>>16); pm[1]=(u16)d;\r
1113     }\r
1114     return;\r
1115   }\r
1116 \r
1117   // word RAM (1M area)\r
1118   if ((a&0xfe0000)==0x0c0000) { // 0c0000-0dffff\r
1119     int bank;\r
1120     u16 *pm;\r
1121     if (d)\r
1122       dprintf("s68k_wram1M w32: [%06x] %08x @%06x", a, d, SekPcS68k);\r
1123     if (!(Pico_mcd->s68k_regs[3]&4))\r
1124       dprintf("s68k_wram1M FIXME: wrong mode");\r
1125     bank = !(Pico_mcd->s68k_regs[3]&1);\r
1126     pm=(u16 *)(Pico_mcd->word_ram1M[bank]+(a&0x1fffe));\r
1127     pm[0]=(u16)(d>>16); pm[1]=(u16)d;\r
1128     return;\r
1129   }\r
1130 \r
1131   // PCM\r
1132   if ((a&0xff8000)==0xff0000) {\r
1133     a &= 0x7fff;\r
1134     if (a >= 0x2000) {\r
1135       a >>= 1;\r
1136       Pico_mcd->pcm_ram_b[Pico_mcd->pcm.bank][a&0xfff] = (d >> 16);\r
1137       Pico_mcd->pcm_ram_b[Pico_mcd->pcm.bank][(a+1)&0xfff] = d;\r
1138     } else if (a < 0x12) {\r
1139       a >>= 1;\r
1140       pcm_write(a,  (d>>16) & 0xff);\r
1141       pcm_write(a+1, d & 0xff);\r
1142     }\r
1143     return;\r
1144   }\r
1145 \r
1146   // bram\r
1147   if ((a&0xff0000)==0xfe0000) {\r
1148     dprintf("s68k_bram w32: [%06x] %08x @%06x", a, d, SekPcS68k);\r
1149     a = (a>>1)&0x1fff;\r
1150     Pico_mcd->bram[a++] = d >> 16;              // middle endian? verify?\r
1151     Pico_mcd->bram[a++] = d >> 24;\r
1152     Pico_mcd->bram[a++] = d;\r
1153     Pico_mcd->bram[a++] = d >> 8;\r
1154     SRam.changed = 1;\r
1155     return;\r
1156   }\r
1157 \r
1158   dprintf("s68k w32: %06x, %08x @%06x", a&0xffffff, d, SekPcS68k);\r
1159 }\r
1160 \r
1161 \r
1162 \r
1163 // -----------------------------------------------------------------\r
1164 \r
1165 \r
1166 #if defined(EMU_C68K)\r
1167 static __inline int PicoMemBaseM68k(u32 pc)\r
1168 {\r
1169   if ((pc&0xe00000)==0xe00000)\r
1170     return (int)Pico.ram-(pc&0xff0000); // Program Counter in Ram\r
1171 \r
1172   if (pc < 0x20000)\r
1173     return (int)Pico_mcd->bios; // Program Counter in BIOS\r
1174 \r
1175   if ((pc&0xfc0000)==0x200000)\r
1176   {\r
1177     if (!(Pico_mcd->s68k_regs[3]&4))\r
1178       return (int)Pico_mcd->word_ram2M - 0x200000; // Program Counter in Word Ram\r
1179     if (pc < 0x220000) {\r
1180       int bank = (Pico_mcd->s68k_regs[3]&1);\r
1181       return (int)Pico_mcd->word_ram1M[bank] - 0x200000;\r
1182     }\r
1183   }\r
1184 \r
1185   // Error - Program Counter is invalid\r
1186   dprintf("m68k FIXME: unhandled jump to %06x", pc);\r
1187 \r
1188   return (int)Pico_mcd->bios;\r
1189 }\r
1190 \r
1191 \r
1192 static u32 PicoCheckPcM68k(u32 pc)\r
1193 {\r
1194   pc-=PicoCpu.membase; // Get real pc\r
1195   pc&=0xfffffe;\r
1196 \r
1197   PicoCpu.membase=PicoMemBaseM68k(pc);\r
1198 \r
1199   return PicoCpu.membase+pc;\r
1200 }\r
1201 \r
1202 \r
1203 static __inline int PicoMemBaseS68k(u32 pc)\r
1204 {\r
1205   if (pc < 0x80000)                     // PRG RAM\r
1206     return (int)Pico_mcd->prg_ram;\r
1207 \r
1208   if ((pc&0xfc0000)==0x080000)          // WORD RAM 2M area (assume we are in the right mode..)\r
1209     return (int)Pico_mcd->word_ram2M - 0x080000;\r
1210 \r
1211   if ((pc&0xfe0000)==0x0c0000) {        // word RAM 1M area\r
1212     int bank = !(Pico_mcd->s68k_regs[3]&1);\r
1213     return (int)Pico_mcd->word_ram1M[bank] - 0x0c0000;\r
1214   }\r
1215 \r
1216   // Error - Program Counter is invalid\r
1217   dprintf("s68k FIXME: unhandled jump to %06x", pc);\r
1218 \r
1219   return (int)Pico_mcd->prg_ram;\r
1220 }\r
1221 \r
1222 \r
1223 static u32 PicoCheckPcS68k(u32 pc)\r
1224 {\r
1225   pc-=PicoCpuS68k.membase; // Get real pc\r
1226   pc&=0xfffffe;\r
1227 \r
1228   PicoCpuS68k.membase=PicoMemBaseS68k(pc);\r
1229 \r
1230   return PicoCpuS68k.membase+pc;\r
1231 }\r
1232 #endif\r
1233 \r
1234 \r
1235 void PicoMemSetupCD()\r
1236 {\r
1237   dprintf("PicoMemSetupCD()");\r
1238 #ifdef EMU_C68K\r
1239   // Setup m68k memory callbacks:\r
1240   PicoCpu.checkpc=PicoCheckPcM68k;\r
1241   PicoCpu.fetch8 =PicoCpu.read8 =PicoReadM68k8;\r
1242   PicoCpu.fetch16=PicoCpu.read16=PicoReadM68k16;\r
1243   PicoCpu.fetch32=PicoCpu.read32=PicoReadM68k32;\r
1244   PicoCpu.write8 =PicoWriteM68k8;\r
1245   PicoCpu.write16=PicoWriteM68k16;\r
1246   PicoCpu.write32=PicoWriteM68k32;\r
1247   // s68k\r
1248   PicoCpuS68k.checkpc=PicoCheckPcS68k;\r
1249   PicoCpuS68k.fetch8 =PicoCpuS68k.read8 =PicoReadS68k8;\r
1250   PicoCpuS68k.fetch16=PicoCpuS68k.read16=PicoReadS68k16;\r
1251   PicoCpuS68k.fetch32=PicoCpuS68k.read32=PicoReadS68k32;\r
1252   PicoCpuS68k.write8 =PicoWriteS68k8;\r
1253   PicoCpuS68k.write16=PicoWriteS68k16;\r
1254   PicoCpuS68k.write32=PicoWriteS68k32;\r
1255 #endif\r
1256 }\r
1257 \r
1258 \r
1259 #ifdef EMU_M68K\r
1260 unsigned char  PicoReadCD8w (unsigned int a) {\r
1261         return m68ki_cpu_p == &PicoS68kCPU ? PicoReadS68k8(a) : PicoReadM68k8(a);\r
1262 }\r
1263 unsigned short PicoReadCD16w(unsigned int a) {\r
1264         return m68ki_cpu_p == &PicoS68kCPU ? PicoReadS68k16(a) : PicoReadM68k16(a);\r
1265 }\r
1266 unsigned int   PicoReadCD32w(unsigned int a) {\r
1267         return m68ki_cpu_p == &PicoS68kCPU ? PicoReadS68k32(a) : PicoReadM68k32(a);\r
1268 }\r
1269 void PicoWriteCD8w (unsigned int a, unsigned char d) {\r
1270         if (m68ki_cpu_p == &PicoS68kCPU) PicoWriteS68k8(a, d); else PicoWriteM68k8(a, d);\r
1271 }\r
1272 void PicoWriteCD16w(unsigned int a, unsigned short d) {\r
1273         if (m68ki_cpu_p == &PicoS68kCPU) PicoWriteS68k16(a, d); else PicoWriteM68k16(a, d);\r
1274 }\r
1275 void PicoWriteCD32w(unsigned int a, unsigned int d) {\r
1276         if (m68ki_cpu_p == &PicoS68kCPU) PicoWriteS68k32(a, d); else PicoWriteM68k32(a, d);\r
1277 }\r
1278 \r
1279 // these are allowed to access RAM\r
1280 unsigned int  m68k_read_pcrelative_CD8 (unsigned int a) {\r
1281   a&=0xffffff;\r
1282   if(m68ki_cpu_p == &PicoS68kCPU) {\r
1283     if (a < 0x80000) return *(u8 *)(Pico_mcd->prg_ram+(a^1)); // PRG Ram\r
1284     if ((a&0xfc0000)==0x080000 && !(Pico_mcd->s68k_regs[3]&4)) // word RAM (2M area: 080000-0bffff)\r
1285       return *(u8 *)(Pico_mcd->word_ram2M+((a^1)&0x3ffff));\r
1286     if ((a&0xfe0000)==0x0c0000 &&  (Pico_mcd->s68k_regs[3]&4)) { // word RAM (1M area: 0c0000-0dffff)\r
1287       int bank = !(Pico_mcd->s68k_regs[3]&1);\r
1288       return *(u8 *)(Pico_mcd->word_ram1M[bank]+((a^1)&0x1ffff));\r
1289     }\r
1290     dprintf("s68k_read_pcrelative_CD8 FIXME: can't handle %06x", a);\r
1291   } else {\r
1292     if((a&0xe00000)==0xe00000) return *(u8 *)(Pico.ram+((a^1)&0xffff)); // Ram\r
1293     if(a<0x20000)              return *(u8 *)(Pico.rom+(a^1)); // Bios\r
1294     if((a&0xfc0000)==0x200000) { // word RAM\r
1295       if(!(Pico_mcd->s68k_regs[3]&4)) // 2M?\r
1296         return *(u8 *)(Pico_mcd->word_ram2M+((a^1)&0x3ffff));\r
1297       else if (a < 0x220000) {\r
1298         int bank = Pico_mcd->s68k_regs[3]&1;\r
1299         return *(u8 *)(Pico_mcd->word_ram1M[bank]+((a^1)&0x1ffff));\r
1300       }\r
1301     }\r
1302     dprintf("m68k_read_pcrelative_CD8 FIXME: can't handle %06x", a);\r
1303   }\r
1304   return 0;//(u8)  lastread_d;\r
1305 }\r
1306 unsigned int  m68k_read_pcrelative_CD16(unsigned int a) {\r
1307   a&=0xffffff;\r
1308   if(m68ki_cpu_p == &PicoS68kCPU) {\r
1309     if (a < 0x80000) return *(u16 *)(Pico_mcd->prg_ram+(a&~1)); // PRG Ram\r
1310     if ((a&0xfc0000)==0x080000 && !(Pico_mcd->s68k_regs[3]&4)) // word RAM (2M area: 080000-0bffff)\r
1311       return *(u16 *)(Pico_mcd->word_ram2M+(a&0x3fffe));\r
1312     if ((a&0xfe0000)==0x0c0000 &&  (Pico_mcd->s68k_regs[3]&4)) { // word RAM (1M area: 0c0000-0dffff)\r
1313       int bank = !(Pico_mcd->s68k_regs[3]&1);\r
1314       return *(u16 *)(Pico_mcd->word_ram1M[bank]+(a&0x1fffe));\r
1315     }\r
1316     dprintf("s68k_read_pcrelative_CD16 FIXME: can't handle %06x", a);\r
1317   } else {\r
1318     if((a&0xe00000)==0xe00000) return *(u16 *)(Pico.ram+(a&0xfffe)); // Ram\r
1319     if(a<0x20000)              return *(u16 *)(Pico.rom+(a&~1)); // Bios\r
1320     if((a&0xfc0000)==0x200000) { // word RAM\r
1321       if(!(Pico_mcd->s68k_regs[3]&4)) // 2M?\r
1322         return *(u16 *)(Pico_mcd->word_ram2M+(a&0x3fffe));\r
1323       else if (a < 0x220000) {\r
1324         int bank = Pico_mcd->s68k_regs[3]&1;\r
1325         return *(u16 *)(Pico_mcd->word_ram1M[bank]+(a&0x1fffe));\r
1326       }\r
1327     }\r
1328     dprintf("m68k_read_pcrelative_CD16 FIXME: can't handle %06x", a);\r
1329   }\r
1330   return 0;\r
1331 }\r
1332 unsigned int  m68k_read_pcrelative_CD32(unsigned int a) {\r
1333   u16 *pm;\r
1334   a&=0xffffff;\r
1335   if(m68ki_cpu_p == &PicoS68kCPU) {\r
1336     if (a < 0x80000) { u16 *pm=(u16 *)(Pico_mcd->prg_ram+(a&~1)); return (pm[0]<<16)|pm[1]; } // PRG Ram\r
1337     if ((a&0xfc0000)==0x080000 && !(Pico_mcd->s68k_regs[3]&4)) // word RAM (2M area: 080000-0bffff)\r
1338       { pm=(u16 *)(Pico_mcd->word_ram2M+(a&0x3fffe)); return (pm[0]<<16)|pm[1]; }\r
1339     if ((a&0xfe0000)==0x0c0000 &&  (Pico_mcd->s68k_regs[3]&4)) { // word RAM (1M area: 0c0000-0dffff)\r
1340       int bank = !(Pico_mcd->s68k_regs[3]&1);\r
1341       pm=(u16 *)(Pico_mcd->word_ram1M[bank]+(a&0x1fffe));\r
1342       return (pm[0]<<16)|pm[1];\r
1343     }\r
1344     dprintf("s68k_read_pcrelative_CD32 FIXME: can't handle %06x", a);\r
1345   } else {\r
1346     if((a&0xe00000)==0xe00000) { u16 *pm=(u16 *)(Pico.ram+(a&0xfffe)); return (pm[0]<<16)|pm[1]; } // Ram\r
1347     if(a<0x20000)              { u16 *pm=(u16 *)(Pico.rom+(a&~1));     return (pm[0]<<16)|pm[1]; }\r
1348     if((a&0xfc0000)==0x200000) { // word RAM\r
1349       if(!(Pico_mcd->s68k_regs[3]&4)) // 2M?\r
1350         { pm=(u16 *)(Pico_mcd->word_ram2M+(a&0x3fffe)); return (pm[0]<<16)|pm[1]; }\r
1351       else if (a < 0x220000) {\r
1352         int bank = Pico_mcd->s68k_regs[3]&1;\r
1353         pm=(u16 *)(Pico_mcd->word_ram1M[bank]+(a&0x1fffe));\r
1354         return (pm[0]<<16)|pm[1];\r
1355       }\r
1356     }\r
1357     dprintf("m68k_read_pcrelative_CD32 FIXME: can't handle %06x", a);\r
1358   }\r
1359   return 0;\r
1360 }\r
1361 #endif // EMU_M68K\r
1362 \r