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