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