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