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