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