ISO loading, menus, LEDs
[picodrive.git] / Pico / cd / Memory.c
1 // This is part of Pico Library\r
2 \r
3 // (c) Copyright 2004 Dave, All rights reserved.\r
4 // (c) Copyright 2006 notaz, All rights reserved.\r
5 // Free for non-commercial use.\r
6 \r
7 // For commercial use, separate licencing terms must be obtained.\r
8 \r
9 // A68K no longer supported here\r
10 \r
11 //#define __debug_io\r
12 \r
13 #include "../PicoInt.h"\r
14 \r
15 #include "../sound/sound.h"\r
16 #include "../sound/ym2612.h"\r
17 #include "../sound/sn76496.h"\r
18 \r
19 typedef unsigned char  u8;\r
20 typedef unsigned short u16;\r
21 typedef unsigned int   u32;\r
22 \r
23 //#define __debug_io\r
24 //#define __debug_io2\r
25 \r
26 // -----------------------------------------------------------------\r
27 \r
28 // extern m68ki_cpu_core m68ki_cpu;\r
29 \r
30 extern int counter75hz;\r
31 \r
32 \r
33 static u32 m68k_reg_read16(u32 a, int realsize)\r
34 {\r
35   u32 d=0;\r
36   a &= 0x3e;\r
37   // dprintf("m68k_regs r%2i: [%02x] @%06x", realsize&~1, a+(realsize&1), SekPc);\r
38 \r
39   switch (a) {\r
40     case 0:\r
41       d = ((Pico_mcd->s68k_regs[0x33]<<13)&0x8000) | Pico_mcd->m68k_regs[1]; // here IFL2 is always 0, just like in Gens\r
42       goto end;\r
43     case 2:\r
44       d = (Pico_mcd->s68k_regs[a]<<8) | (Pico_mcd->s68k_regs[a+1]&0xc7);\r
45       dprintf("m68k_regs r3: %02x @%06x", (u8)d, SekPc);\r
46       goto end;\r
47     case 8:\r
48       dprintf("m68k host data read");\r
49       d = Read_CDC_Host(0);\r
50       goto end;\r
51     case 0xC:\r
52       dprintf("m68k stopwatch read");\r
53       break;\r
54   }\r
55 \r
56   if (a < 0xE) {\r
57     d = (Pico_mcd->m68k_regs[a]<<8) | Pico_mcd->m68k_regs[a+1];\r
58     goto end;\r
59   }\r
60 \r
61   if (a < 0x30) {\r
62     // comm flag/cmd/status (0xE-0x2F)\r
63     d = (Pico_mcd->s68k_regs[a]<<8) | Pico_mcd->s68k_regs[a+1];\r
64     goto end;\r
65   }\r
66 \r
67   dprintf("m68k_regs invalid read @ %02x", a);\r
68 \r
69 end:\r
70 \r
71   // dprintf("ret = %04x", d);\r
72   return d;\r
73 }\r
74 \r
75 static void m68k_reg_write8(u32 a, u32 d, int realsize)\r
76 {\r
77   a &= 0x3f;\r
78   // dprintf("m68k_regs w%2i: [%02x] %02x @%06x", realsize, a, d, SekPc);\r
79 \r
80   switch (a) {\r
81     case 0:\r
82       d &= 1;\r
83       if ((d&1) && (Pico_mcd->s68k_regs[0x33]&(1<<2))) { dprintf("m68k: s68k irq 2"); SekInterruptS68k(2); }\r
84       break;\r
85     case 1:\r
86       d &= 3;\r
87       if (!(d&1)) PicoMCD |= 2; // reset pending, needed to be sure we fetch the right vectors on reset\r
88       if ( (Pico_mcd->m68k_regs[1]&1) != (d&1)) dprintf("m68k: s68k reset %i", !(d&1));\r
89       if ( (Pico_mcd->m68k_regs[1]&2) != (d&2)) dprintf("m68k: s68k brq %i", (d&2)>>1);\r
90       if (/*!(Pico_mcd->m68k_regs[1]&1) &&*/ (PicoMCD&2) && (d&3)==1) {\r
91         SekResetS68k(); // S68k comes out of RESET or BRQ state\r
92         PicoMCD&=~2;\r
93         dprintf("m68k: resetting s68k, cycles=%i", SekCyclesLeft);\r
94       }\r
95       break;\r
96     case 2:\r
97       Pico_mcd->s68k_regs[2] = d; // really use s68k side register\r
98       return;\r
99     case 3:\r
100       dprintf("m68k_regs w3: %02x @%06x", (u8)d, SekPc);\r
101       d &= 0xc2;\r
102       if ((Pico_mcd->s68k_regs[3]>>6) != ((d>>6)&3))\r
103         dprintf("m68k: prg bank: %i -> %i", (Pico_mcd->s68k_regs[a]>>6), ((d>>6)&3));\r
104       //if ((Pico_mcd->s68k_regs[3]&4) != (d&4)) dprintf("m68k: ram mode %i mbit", (d&4) ? 1 : 2);\r
105       //if ((Pico_mcd->s68k_regs[3]&2) != (d&2)) dprintf("m68k: %s", (d&4) ? ((d&2) ? "word swap req" : "noop?") :\r
106       //                                             ((d&2) ? "word ram to s68k" : "word ram to m68k"));\r
107       d |= Pico_mcd->s68k_regs[3]&0x1d;\r
108       if (!(d & 4) && (d & 2)) d &= ~1; // return word RAM to s68k in 2M mode\r
109       Pico_mcd->s68k_regs[3] = d; // really use s68k side register\r
110       return;\r
111     case 0xe:\r
112       //dprintf("m68k: comm flag: %02x", d);\r
113 \r
114       //dprintf("s68k @ %06x", SekPcS68k);\r
115 \r
116       Pico_mcd->s68k_regs[0xe] = d;\r
117       break;\r
118   }\r
119 \r
120   if (a < 0x10) {\r
121     Pico_mcd->m68k_regs[a] = (u8) d;\r
122     return;\r
123   }\r
124 \r
125   if ((a&0xf0) == 0x10) {\r
126       Pico_mcd->s68k_regs[a] = d;\r
127       return;\r
128   }\r
129 \r
130   if (a >= 0x20 || (a >= 0xa && a <= 0xd) || a == 0x0f)\r
131     dprintf("m68k: invalid write?");\r
132 }\r
133 \r
134 \r
135 \r
136 static u32 s68k_reg_read16(u32 a, int realsize)\r
137 {\r
138   u32 d=0;\r
139   a &= 0x1fe;\r
140 \r
141   // dprintf("s68k_regs r%2i: [%02x] @ %06x", realsize&~1, a+(realsize&1), SekPcS68k);\r
142 \r
143   switch (a) {\r
144     case 0:\r
145       d = 1; goto end; // ver = 0, not in reset state\r
146     case 2:\r
147       d = (Pico_mcd->s68k_regs[a]<<8) | (Pico_mcd->s68k_regs[a+1]&0x1f);\r
148       dprintf("s68k_regs r3: %02x @%06x", (u8)d, SekPc);\r
149       goto end;\r
150     case 6:\r
151       d = CDC_Read_Reg();\r
152       goto end;\r
153     case 8:\r
154       dprintf("s68k host data read");\r
155       d = Read_CDC_Host(1);\r
156       goto end;\r
157     case 0xC:\r
158       dprintf("s68k stopwatch read");\r
159       break;\r
160     case 0x34: // fader\r
161       d = 0; // no busy bit\r
162       goto end;\r
163   }\r
164 \r
165   d = (Pico_mcd->s68k_regs[a]<<8) | Pico_mcd->s68k_regs[a+1];\r
166 \r
167 end:\r
168 \r
169   // dprintf("ret = %04x", d);\r
170 \r
171   return d;\r
172 }\r
173 \r
174 static void s68k_reg_write8(u32 a, u32 d, int realsize)\r
175 {\r
176   a &= 0x1ff;\r
177   //dprintf("s68k_regs w%2i: [%02x] %02x @ %06x", realsize, a, d, SekPcS68k);\r
178 \r
179   // TODO: review against Gens\r
180   switch (a) {\r
181     case 2:\r
182       return; // only m68k can change WP\r
183     case 3:\r
184       dprintf("s68k_regs w3: %02x @%06x", (u8)d, SekPc);\r
185       d &= 0x1d;\r
186       if (d&4) {\r
187         d |= Pico_mcd->s68k_regs[3]&0xc2;\r
188         if ((d ^ Pico_mcd->s68k_regs[3]) & 5) d &= ~2; // in case of mode or bank change we clear DMNA (m68k req) bit\r
189       } else {\r
190         d |= Pico_mcd->s68k_regs[3]&0xc3;\r
191         if (d&1) d &= ~2; // return word RAM to m68k in 2M mode\r
192       }\r
193       break;\r
194     case 4:\r
195       dprintf("s68k CDC dest: %x", d&7);\r
196       Pico_mcd->s68k_regs[4] = (Pico_mcd->s68k_regs[4]&0xC0) | (d&7); // CDC mode\r
197       return;\r
198     case 5:\r
199       dprintf("s68k CDC reg addr: %x", d&0xf);\r
200       break;\r
201     case 7:\r
202       CDC_Write_Reg(d);\r
203       return;\r
204     case 0xa:\r
205       dprintf("s68k set CDC dma addr");\r
206       break;\r
207     case 0x33: // IRQ mask\r
208       dprintf("s68k irq mask: %02x", d);\r
209       if ((d&(1<<4)) && (Pico_mcd->s68k_regs[0x37]&4) && !(Pico_mcd->s68k_regs[0x33]&(1<<4))) {\r
210         CDD_Export_Status();\r
211         // counter75hz = 0; // ???\r
212       }\r
213       break;\r
214     case 0x34: // fader\r
215       Pico_mcd->s68k_regs[a] = (u8) d & 0x7f;\r
216       return;\r
217     case 0x36:\r
218       return; // d/m bit is unsetable\r
219     case 0x37: {\r
220       u32 d_old = Pico_mcd->s68k_regs[0x37];\r
221       Pico_mcd->s68k_regs[0x37] = d&7;\r
222       if ((d&4) && !(d_old&4)) {\r
223         CDD_Export_Status();\r
224         // counter75hz = 0; // ???\r
225       }\r
226       return;\r
227     }\r
228     case 0x4b:\r
229       Pico_mcd->s68k_regs[a] = (u8) d;\r
230       CDD_Import_Command();\r
231       return;\r
232   }\r
233 \r
234   if ((a&0x1f0) == 0x10 || a == 0x0e || (a >= 0x38 && a < 0x42))\r
235   {\r
236     dprintf("m68k: invalid write @ %02x?", a);\r
237     return;\r
238   }\r
239 \r
240   Pico_mcd->s68k_regs[a] = (u8) d;\r
241 }\r
242 \r
243 \r
244 \r
245 \r
246 \r
247 static int PadRead(int i)\r
248 {\r
249   int pad=0,value=0,TH;\r
250   pad=~PicoPad[i]; // Get inverse of pad MXYZ SACB RLDU\r
251   TH=Pico.ioports[i+1]&0x40;\r
252 \r
253   if(PicoOpt & 0x20) { // 6 button gamepad enabled\r
254     int phase = Pico.m.padTHPhase[i];\r
255 \r
256     if(phase == 2 && !TH) {\r
257       value=(pad&0xc0)>>2;              // ?0SA 0000\r
258       goto end;\r
259     } else if(phase == 3 && TH) {\r
260       value=(pad&0x30)|((pad>>8)&0xf);  // ?1CB MXYZ\r
261       goto end;\r
262     } else if(phase == 3 && !TH) {\r
263       value=((pad&0xc0)>>2)|0x0f;       // ?0SA 1111\r
264       goto end;\r
265     }\r
266   }\r
267 \r
268   if(TH) value=(pad&0x3f);              // ?1CB RLDU\r
269   else   value=((pad&0xc0)>>2)|(pad&3); // ?0SA 00DU\r
270 \r
271   end:\r
272 \r
273   // orr the bits, which are set as output\r
274   value |= Pico.ioports[i+1]&Pico.ioports[i+4];\r
275 \r
276   return value; // will mirror later\r
277 }\r
278 \r
279 static u8 z80Read8(u32 a)\r
280 {\r
281   if(Pico.m.z80Run&1) return 0;\r
282 \r
283   a&=0x1fff;\r
284 \r
285   if(!(PicoOpt&4)) {\r
286     // Z80 disabled, do some faking\r
287     static u8 zerosent = 0;\r
288     if(a == Pico.m.z80_lastaddr) { // probably polling something\r
289       u8 d = Pico.m.z80_fakeval;\r
290       if((d & 0xf) == 0xf && !zerosent) {\r
291         d = 0; zerosent = 1;\r
292       } else {\r
293         Pico.m.z80_fakeval++;\r
294         zerosent = 0;\r
295       }\r
296       return d;\r
297     } else {\r
298       Pico.m.z80_fakeval = 0;\r
299     }\r
300   }\r
301 \r
302   Pico.m.z80_lastaddr = (u16) a;\r
303   return Pico.zram[a];\r
304 }\r
305 \r
306 \r
307 // for nonstandard reads\r
308 static u32 UnusualRead16(u32 a, int realsize)\r
309 {\r
310   u32 d=0;\r
311 \r
312   dprintf("unusual r%i: %06x @%06x", realsize&~1, (a&0xfffffe)+(realsize&1), SekPc);\r
313 \r
314 \r
315   dprintf("ret = %04x", d);\r
316   return d;\r
317 }\r
318 \r
319 static u32 OtherRead16(u32 a, int realsize)\r
320 {\r
321   u32 d=0;\r
322 \r
323   if ((a&0xff0000)==0xa00000) {\r
324     if ((a&0x4000)==0x0000) { d=z80Read8(a); d|=d<<8; goto end; } // Z80 ram (not byteswaped)\r
325     if ((a&0x6000)==0x4000) { if(PicoOpt&1) d=YM2612Read(); else d=Pico.m.rotate++&3; goto end; } // 0x4000-0x5fff, Fudge if disabled\r
326         d=0xffff; goto end;\r
327   }\r
328   if ((a&0xffffe0)==0xa10000) { // I/O ports\r
329     a=(a>>1)&0xf;\r
330     switch(a) {\r
331       case 0:  d=Pico.m.hardware; break; // Hardware value (Version register)\r
332       case 1:  d=PadRead(0); d|=Pico.ioports[1]&0x80; break;\r
333       case 2:  d=PadRead(1); d|=Pico.ioports[2]&0x80; break;\r
334       default: d=Pico.ioports[a]; break; // IO ports can be used as RAM\r
335     }\r
336     d|=d<<8;\r
337     goto end;\r
338   }\r
339   // |=0x80 for Shadow of the Beast & Super Offroad; rotate fakes next fetched instruction for Time Killers\r
340   if (a==0xa11100) { d=((Pico.m.z80Run&1)<<8)|0x8000|Pico.m.rotate++; goto end; }\r
341 \r
342   if ((a&0xe700e0)==0xc00000) { d=PicoVideoRead(a); goto end; }\r
343 \r
344   if ((a&0xffffc0)==0xa12000) {\r
345     d=m68k_reg_read16(a, realsize);\r
346     goto end;\r
347   }\r
348 \r
349   d = UnusualRead16(a, realsize);\r
350 \r
351 end:\r
352   return d;\r
353 }\r
354 \r
355 //extern UINT32 mz80GetRegisterValue(void *, UINT32);\r
356 \r
357 static void OtherWrite8(u32 a,u32 d,int realsize)\r
358 {\r
359   if ((a&0xe700f9)==0xc00011||(a&0xff7ff9)==0xa07f11) { if(PicoOpt&2) SN76496Write(d); return; } // PSG Sound\r
360   if ((a&0xff4000)==0xa00000)  { if(!(Pico.m.z80Run&1)) Pico.zram[a&0x1fff]=(u8)d; return; } // Z80 ram\r
361   if ((a&0xff6000)==0xa04000)  { if(PicoOpt&1) emustatus|=YM2612Write(a&3, d); return; } // FM Sound\r
362   if ((a&0xffffe0)==0xa10000)  { // I/O ports\r
363     a=(a>>1)&0xf;\r
364     // 6 button gamepad: if TH went from 0 to 1, gamepad changes state\r
365     if(PicoOpt&0x20) {\r
366       if(a==1) {\r
367         Pico.m.padDelay[0] = 0;\r
368         if(!(Pico.ioports[1]&0x40) && (d&0x40)) Pico.m.padTHPhase[0]++;\r
369       }\r
370       else if(a==2) {\r
371         Pico.m.padDelay[1] = 0;\r
372         if(!(Pico.ioports[2]&0x40) && (d&0x40)) Pico.m.padTHPhase[1]++;\r
373       }\r
374     }\r
375     Pico.ioports[a]=(u8)d; // IO ports can be used as RAM\r
376     return;\r
377   }\r
378   if (a==0xa11100) {\r
379     extern int z80startCycle, z80stopCycle;\r
380     //int lineCycles=(488-SekCyclesLeft)&0x1ff;\r
381     d&=1; d^=1;\r
382         if(!d) {\r
383           // hack: detect a nasty situation where Z80 was enabled and disabled in the same 68k timeslice (Golden Axe III)\r
384       if((PicoOpt&4) && Pico.m.z80Run==1) z80_run(20);\r
385           z80stopCycle = SekCyclesDone();\r
386           //z80ExtraCycles += (lineCycles>>1)-(lineCycles>>5); // only meaningful in PicoFrameHints()\r
387         } else {\r
388           z80startCycle = SekCyclesDone();\r
389           //if(Pico.m.scanline != -1)\r
390           //z80ExtraCycles -= (lineCycles>>1)-(lineCycles>>5)+16;\r
391         }\r
392     //dprintf("set_zrun: %i [%i|%i] zPC=%04x @%06x", d, Pico.m.scanline, SekCyclesDone(), mz80GetRegisterValue(NULL, 0), SekPc);\r
393         Pico.m.z80Run=(u8)d; return;\r
394   }\r
395   if (a==0xa11200) { if(!(d&1)) z80_reset(); return; }\r
396 \r
397   if ((a&0xff7f00)==0xa06000) // Z80 BANK register\r
398   {\r
399     Pico.m.z80_bank68k>>=1;\r
400     Pico.m.z80_bank68k|=(d&1)<<8;\r
401     Pico.m.z80_bank68k&=0x1ff; // 9 bits and filled in the new top one\r
402     return;\r
403   }\r
404 \r
405   if ((a&0xe700e0)==0xc00000) { PicoVideoWrite(a,(u16)(d|(d<<8))); return; } // Byte access gets mirrored\r
406 \r
407   if ((a&0xffffc0)==0xa12000) { m68k_reg_write8(a, d, realsize); return; }\r
408 \r
409   dprintf("strange w%i: %06x, %08x @%06x", realsize, a&0xffffff, d, SekPc);\r
410 }\r
411 \r
412 static void OtherWrite16(u32 a,u32 d)\r
413 {\r
414   if ((a&0xe700e0)==0xc00000) { PicoVideoWrite(a,(u16)d); return; }\r
415   if ((a&0xff4000)==0xa00000) { if(!(Pico.m.z80Run&1)) Pico.zram[a&0x1fff]=(u8)(d>>8); return; } // Z80 ram (MSB only)\r
416 \r
417   if ((a&0xffffe0)==0xa10000) { // I/O ports\r
418     a=(a>>1)&0xf;\r
419     // 6 button gamepad: if TH went from 0 to 1, gamepad changes state\r
420     if(PicoOpt&0x20) {\r
421       if(a==1) {\r
422         Pico.m.padDelay[0] = 0;\r
423         if(!(Pico.ioports[1]&0x40) && (d&0x40)) Pico.m.padTHPhase[0]++;\r
424       }\r
425       else if(a==2) {\r
426         Pico.m.padDelay[1] = 0;\r
427         if(!(Pico.ioports[2]&0x40) && (d&0x40)) Pico.m.padTHPhase[1]++;\r
428       }\r
429     }\r
430     Pico.ioports[a]=(u8)d; // IO ports can be used as RAM\r
431     return;\r
432   }\r
433   if (a==0xa11100) { OtherWrite8(a, d>>8, 16); return; }\r
434   if (a==0xa11200) { if(!(d&0x100)) z80_reset(); return; }\r
435 \r
436   OtherWrite8(a,  d>>8, 16);\r
437   OtherWrite8(a+1,d&0xff, 16);\r
438 }\r
439 \r
440 // -----------------------------------------------------------------\r
441 //                     Read Rom and read Ram\r
442 \r
443 u8 PicoReadM68k8(u32 a)\r
444 {\r
445   u32 d=0;\r
446 \r
447   if ((a&0xe00000)==0xe00000) { d = *(u8 *)(Pico.ram+((a^1)&0xffff)); goto end; } // Ram\r
448 \r
449   a&=0xffffff;\r
450 \r
451   if (a < 0x20000) { d = *(u8 *)(Pico_mcd->bios+(a^1)); goto end; } // bios\r
452 \r
453   // prg RAM\r
454   if ((a&0xfe0000)==0x020000) {\r
455     u8 *prg_bank = Pico_mcd->prg_ram_b[Pico_mcd->s68k_regs[3]>>6];\r
456     d = *(prg_bank+((a^1)&0x1ffff));\r
457     goto end;\r
458   }\r
459 \r
460   // word RAM\r
461   if ((a&0xfc0000)==0x200000) {\r
462     dprintf("m68k_wram r8: [%06x] @%06x", a, SekPc);\r
463     if (Pico_mcd->s68k_regs[3]&4) { // 1M mode?\r
464       if (a >= 0x220000) {\r
465         dprintf("cell");\r
466       } else {\r
467         a=((a&0x1fffe)<<1)|(a&1);\r
468         if (Pico_mcd->s68k_regs[3]&1) a+=2;\r
469         d = Pico_mcd->word_ram[a^1];\r
470       }\r
471     } else {\r
472       // allow access in any mode, like Gens does\r
473       d = Pico_mcd->word_ram[(a^1)&0x3ffff];\r
474     }\r
475     dprintf("ret = %02x", (u8)d);\r
476     goto end;\r
477   }\r
478 \r
479   if ((a&0xff4000)==0xa00000) { d=z80Read8(a); goto end; } // Z80 Ram\r
480 \r
481   //if ((a&0xffffc0)==0xa12000)\r
482   //  dprintf("m68k_regs r8: [%02x] @%06x", a&0x3f, SekPc);\r
483 \r
484   d=OtherRead16(a&~1, 8|(a&1)); if ((a&1)==0) d>>=8;\r
485 \r
486   //if ((a&0xffffc0)==0xa12000)\r
487   //  dprintf("ret = %02x", (u8)d);\r
488 \r
489   end:\r
490 \r
491 #ifdef __debug_io\r
492   dprintf("r8 : %06x,   %02x @%06x", a&0xffffff, (u8)d, SekPc);\r
493 #endif\r
494   return (u8)d;\r
495 }\r
496 \r
497 u16 PicoReadM68k16(u32 a)\r
498 {\r
499   u16 d=0;\r
500 \r
501   if ((a&0xe00000)==0xe00000) { d=*(u16 *)(Pico.ram+(a&0xfffe)); goto end; } // Ram\r
502 \r
503   a&=0xfffffe;\r
504 \r
505   if (a < 0x20000) { d = *(u16 *)(Pico_mcd->bios+a); goto end; } // bios\r
506 \r
507   // prg RAM\r
508   if ((a&0xfe0000)==0x020000) {\r
509     u8 *prg_bank = Pico_mcd->prg_ram_b[Pico_mcd->s68k_regs[3]>>6];\r
510     d = *(u16 *)(prg_bank+(a&0x1fffe));\r
511     goto end;\r
512   }\r
513 \r
514   // word RAM\r
515   if ((a&0xfc0000)==0x200000) {\r
516     dprintf("m68k_wram r16: [%06x] @%06x", a, SekPc);\r
517     if (Pico_mcd->s68k_regs[3]&4) { // 1M mode?\r
518       if (a >= 0x220000) {\r
519         dprintf("cell");\r
520       } else {\r
521         a=((a&0x1fffe)<<1);\r
522         if (Pico_mcd->s68k_regs[3]&1) a+=2;\r
523         d = *(u16 *)(Pico_mcd->word_ram+a);\r
524       }\r
525     } else {\r
526       // allow access in any mode, like Gens does\r
527       d = *(u16 *)(Pico_mcd->word_ram+(a&0x3fffe));\r
528     }\r
529     dprintf("ret = %04x", d);\r
530     goto end;\r
531   }\r
532 \r
533   //if ((a&0xffffc0)==0xa12000)\r
534   //  dprintf("m68k_regs r16: [%02x] @%06x", a&0x3f, SekPc);\r
535 \r
536   d = (u16)OtherRead16(a, 16);\r
537 \r
538   //if ((a&0xffffc0)==0xa12000)\r
539   //  dprintf("ret = %04x", d);\r
540 \r
541   end:\r
542 \r
543 #ifdef __debug_io\r
544   dprintf("r16: %06x, %04x  @%06x", a&0xffffff, d, SekPc);\r
545 #endif\r
546   return d;\r
547 }\r
548 \r
549 u32 PicoReadM68k32(u32 a)\r
550 {\r
551   u32 d=0;\r
552 \r
553   if ((a&0xe00000)==0xe00000) { u16 *pm=(u16 *)(Pico.ram+(a&0xfffe)); d = (pm[0]<<16)|pm[1]; goto end; } // Ram\r
554 \r
555   a&=0xfffffe;\r
556 \r
557   if (a < 0x20000) { u16 *pm=(u16 *)(Pico_mcd->bios+a); d = (pm[0]<<16)|pm[1]; goto end; } // bios\r
558 \r
559   // prg RAM\r
560   if ((a&0xfe0000)==0x020000) {\r
561     u8 *prg_bank = Pico_mcd->prg_ram_b[Pico_mcd->s68k_regs[3]>>6];\r
562     u16 *pm=(u16 *)(prg_bank+(a&0x1fffe));\r
563     d = (pm[0]<<16)|pm[1];\r
564     goto end;\r
565   }\r
566 \r
567   // word RAM\r
568   if ((a&0xfc0000)==0x200000) {\r
569     dprintf("m68k_wram r32: [%06x] @%06x", a, SekPc);\r
570     if (Pico_mcd->s68k_regs[3]&4) { // 1M mode?\r
571       if (a >= 0x220000) {\r
572         dprintf("cell");\r
573       } else {\r
574         u16 *pm;\r
575         a=((a&0x1fffe)<<1);\r
576         if (Pico_mcd->s68k_regs[3]&1) a+=2;\r
577         pm=(u16 *)(Pico_mcd->word_ram+a);\r
578         d = (pm[0]<<16)|pm[1];\r
579       }\r
580     } else {\r
581       // allow access in any mode, like Gens does\r
582       u16 *pm=(u16 *)(Pico_mcd->word_ram+(a&0x3fffe)); d = (pm[0]<<16)|pm[1];\r
583     }\r
584     dprintf("ret = %08x", d);\r
585     goto end;\r
586   }\r
587 \r
588   //if ((a&0xffffc0)==0xa12000)\r
589   //  dprintf("m68k_regs r32: [%02x] @%06x", a&0x3f, SekPc);\r
590 \r
591   d = (OtherRead16(a, 32)<<16)|OtherRead16(a+2, 32);\r
592 \r
593   //if ((a&0xffffc0)==0xa12000)\r
594   //  dprintf("ret = %08x", d);\r
595 \r
596   end:\r
597 #ifdef __debug_io\r
598   dprintf("r32: %06x, %08x @%06x", a&0xffffff, d, SekPc);\r
599 #endif\r
600   return d;\r
601 }\r
602 \r
603 // -----------------------------------------------------------------\r
604 //                            Write Ram\r
605 \r
606 void PicoWriteM68k8(u32 a,u8 d)\r
607 {\r
608 #ifdef __debug_io\r
609   dprintf("w8 : %06x,   %02x @%06x", a&0xffffff, d, SekPc);\r
610 #endif\r
611   //if ((a&0xe0ffff)==0xe0a9ba+0x69c)\r
612   //  dprintf("w8 : %06x,   %02x @%06x", a&0xffffff, d, SekPc);\r
613 \r
614 \r
615   if ((a&0xe00000)==0xe00000) { u8 *pm=(u8 *)(Pico.ram+((a^1)&0xffff)); pm[0]=d; return; } // Ram\r
616 \r
617   a&=0xffffff;\r
618 \r
619   // prg RAM\r
620   if ((a&0xfe0000)==0x020000) {\r
621     u8 *prg_bank = Pico_mcd->prg_ram_b[Pico_mcd->s68k_regs[3]>>6];\r
622     *(u8 *)(prg_bank+((a^1)&0x1ffff))=d;\r
623     return;\r
624   }\r
625 \r
626   // word RAM\r
627   if ((a&0xfc0000)==0x200000) {\r
628     dprintf("m68k_wram w8: [%06x] %02x @%06x", a, d, SekPc);\r
629     if (Pico_mcd->s68k_regs[3]&4) { // 1M mode?\r
630       if (a >= 0x220000) {\r
631         dprintf("cell");\r
632       } else {\r
633         a=((a&0x1fffe)<<1)|(a&1);\r
634         if (Pico_mcd->s68k_regs[3]&1) a+=2;\r
635         *(u8 *)(Pico_mcd->word_ram+(a^1))=d;\r
636       }\r
637     } else {\r
638       // allow access in any mode, like Gens does\r
639       *(u8 *)(Pico_mcd->word_ram+((a^1)&0x3ffff))=d;\r
640     }\r
641     return;\r
642   }\r
643 \r
644   //if ((a&0xffffc0)==0xa12000)\r
645   //  dprintf("m68k_regs w8: [%02x] %02x @%06x", a&0x3f, d, SekPc);\r
646 \r
647   OtherWrite8(a,d,8);\r
648 }\r
649 \r
650 void PicoWriteM68k16(u32 a,u16 d)\r
651 {\r
652 #ifdef __debug_io\r
653   dprintf("w16: %06x, %04x", a&0xffffff, d);\r
654 #endif\r
655   //  dprintf("w16: %06x, %04x  @%06x", a&0xffffff, d, SekPc);\r
656 \r
657   if ((a&0xe00000)==0xe00000) { *(u16 *)(Pico.ram+(a&0xfffe))=d; return; } // Ram\r
658 \r
659   a&=0xfffffe;\r
660 \r
661   // prg RAM\r
662   if ((a&0xfe0000)==0x020000) {\r
663     u8 *prg_bank = Pico_mcd->prg_ram_b[Pico_mcd->s68k_regs[3]>>6];\r
664     *(u16 *)(prg_bank+(a&0x1fffe))=d;\r
665     return;\r
666   }\r
667 \r
668   // word RAM\r
669   if ((a&0xfc0000)==0x200000) {\r
670     dprintf("m68k_wram w16: [%06x] %04x @%06x", a, d, SekPc);\r
671     if (Pico_mcd->s68k_regs[3]&4) { // 1M mode?\r
672       if (a >= 0x220000) {\r
673         dprintf("cell");\r
674       } else {\r
675         a=((a&0x1fffe)<<1);\r
676         if (Pico_mcd->s68k_regs[3]&1) a+=2;\r
677         *(u16 *)(Pico_mcd->word_ram+a)=d;\r
678       }\r
679     } else {\r
680       // allow access in any mode, like Gens does\r
681       *(u16 *)(Pico_mcd->word_ram+(a&0x3fffe))=d;\r
682     }\r
683     return;\r
684   }\r
685 \r
686   //if ((a&0xffffc0)==0xa12000)\r
687   //  dprintf("m68k_regs w16: [%02x] %04x @%06x", a&0x3f, d, SekPc);\r
688 \r
689   OtherWrite16(a,d);\r
690 }\r
691 \r
692 void PicoWriteM68k32(u32 a,u32 d)\r
693 {\r
694 #ifdef __debug_io\r
695   dprintf("w32: %06x, %08x", a&0xffffff, d);\r
696 #endif\r
697 \r
698   if ((a&0xe00000)==0xe00000)\r
699   {\r
700     // Ram:\r
701     u16 *pm=(u16 *)(Pico.ram+(a&0xfffe));\r
702     pm[0]=(u16)(d>>16); pm[1]=(u16)d;\r
703     return;\r
704   }\r
705 \r
706   a&=0xfffffe;\r
707 \r
708   // prg RAM\r
709   if ((a&0xfe0000)==0x020000) {\r
710     u8 *prg_bank = Pico_mcd->prg_ram_b[Pico_mcd->s68k_regs[3]>>6];\r
711     u16 *pm=(u16 *)(prg_bank+(a&0x1fffe));\r
712     pm[0]=(u16)(d>>16); pm[1]=(u16)d;\r
713     return;\r
714   }\r
715 \r
716   // word RAM\r
717   if ((a&0xfc0000)==0x200000) {\r
718     if (d != 0) // don't log clears\r
719       dprintf("m68k_wram w32: [%06x] %08x @%06x", a, d, SekPc);\r
720     if (Pico_mcd->s68k_regs[3]&4) { // 1M mode?\r
721       if (a >= 0x220000) {\r
722         dprintf("cell");\r
723       } else {\r
724         u16 *pm;\r
725         a=((a&0x1fffe)<<1);\r
726         if (Pico_mcd->s68k_regs[3]&1) a+=2;\r
727         pm=(u16 *)(Pico_mcd->word_ram+a);\r
728         pm[0]=(u16)(d>>16); pm[1]=(u16)d;\r
729       }\r
730     } else {\r
731       // allow access in any mode, like Gens does\r
732       u16 *pm=(u16 *)(Pico_mcd->word_ram+(a&0x3fffe));\r
733       pm[0]=(u16)(d>>16); pm[1]=(u16)d;\r
734     }\r
735     return;\r
736   }\r
737 \r
738   //if ((a&0xffffc0)==0xa12000)\r
739   //  dprintf("m68k_regs w32: [%02x] %08x @%06x", a&0x3f, d, SekPc);\r
740 \r
741   OtherWrite16(a,  (u16)(d>>16));\r
742   OtherWrite16(a+2,(u16)d);\r
743 }\r
744 \r
745 \r
746 // -----------------------------------------------------------------\r
747 \r
748 \r
749 u8 PicoReadS68k8(u32 a)\r
750 {\r
751   u32 d=0;\r
752 \r
753   a&=0xffffff;\r
754 \r
755   // prg RAM\r
756   if (a < 0x80000) {\r
757     d = *(Pico_mcd->prg_ram+(a^1));\r
758     goto end;\r
759   }\r
760 \r
761   // regs\r
762   if ((a&0xfffe00) == 0xff8000) {\r
763     //dprintf("s68k_regs r8: [%02x] @ %06x", a&0x1ff, SekPcS68k);\r
764     d = s68k_reg_read16(a&~1, 8|(a&1)); if ((a&1)==0) d>>=8;\r
765     //dprintf("ret = %02x", (u8)d);\r
766     goto end;\r
767   }\r
768 \r
769   // word RAM (2M area)\r
770   if ((a&0xfc0000)==0x080000) { // 080000-0bffff\r
771     dprintf("s68k_wram2M r8: [%06x] @%06x", a, SekPc);\r
772     if (Pico_mcd->s68k_regs[3]&4) { // 1M mode?\r
773       // TODO (decode)\r
774       dprintf("(decode)");\r
775     } else {\r
776       // allow access in any mode, like Gens does\r
777       d = Pico_mcd->word_ram[(a^1)&0x3ffff];\r
778     }\r
779     dprintf("ret = %02x", (u8)d);\r
780     goto end;\r
781   }\r
782 \r
783   // word RAM (1M area)\r
784   if ((a&0xfe0000)==0x0c0000 && (Pico_mcd->s68k_regs[3]&4)) { // 0c0000-0dffff\r
785     dprintf("s68k_wram1M r8: [%06x] @%06x", a, SekPc);\r
786     a=((a&0x1fffe)<<1)|(a&1);\r
787     if (!(Pico_mcd->s68k_regs[3]&1)) a+=2;\r
788     d = Pico_mcd->word_ram[a^1];\r
789     dprintf("ret = %02x", (u8)d);\r
790     goto end;\r
791   }\r
792 \r
793   dprintf("s68k r8 : %06x,   %02x @%06x", a&0xffffff, (u8)d, SekPcS68k);\r
794 \r
795   end:\r
796 \r
797 #ifdef __debug_io2\r
798   dprintf("s68k r8 : %06x,   %02x @%06x", a&0xffffff, (u8)d, SekPcS68k);\r
799 #endif\r
800   return (u8)d;\r
801 }\r
802 \r
803 u16 PicoReadS68k16(u32 a)\r
804 {\r
805   u16 d=0;\r
806 \r
807   a&=0xfffffe;\r
808 \r
809   // prg RAM\r
810   if (a < 0x80000) {\r
811     d = *(u16 *)(Pico_mcd->prg_ram+a);\r
812     goto end;\r
813   }\r
814 \r
815   // regs\r
816   if ((a&0xfffe00) == 0xff8000) {\r
817     //dprintf("s68k_regs r16: [%02x] @ %06x", a&0x1fe, SekPcS68k);\r
818     d = s68k_reg_read16(a, 16);\r
819     //dprintf("ret = %04x", d);\r
820     goto end;\r
821   }\r
822 \r
823   // word RAM (2M area)\r
824   if ((a&0xfc0000)==0x080000) { // 080000-0bffff\r
825     dprintf("s68k_wram2M r16: [%06x] @%06x", a, SekPc);\r
826     if (Pico_mcd->s68k_regs[3]&4) { // 1M mode?\r
827       // TODO (decode)\r
828       dprintf("(decode)");\r
829     } else {\r
830       // allow access in any mode, like Gens does\r
831       d = *(u16 *)(Pico_mcd->word_ram+(a&0x3fffe));\r
832     }\r
833     dprintf("ret = %04x", (u8)d);\r
834     goto end;\r
835   }\r
836 \r
837   // word RAM (1M area)\r
838   if ((a&0xfe0000)==0x0c0000 && (Pico_mcd->s68k_regs[3]&4)) { // 0c0000-0dffff\r
839     dprintf("s68k_wram1M r16: [%06x] @%06x", a, SekPc);\r
840     a=((a&0x1fffe)<<1);\r
841     if (!(Pico_mcd->s68k_regs[3]&1)) a+=2;\r
842     d = *(u16 *)(Pico_mcd->word_ram+a);\r
843     dprintf("ret = %04x", (u8)d);\r
844     goto end;\r
845   }\r
846 \r
847   dprintf("s68k r16: %06x, %04x  @%06x", a&0xffffff, d, SekPcS68k);\r
848 \r
849   end:\r
850 \r
851 #ifdef __debug_io2\r
852   dprintf("s68k r16: %06x, %04x  @%06x", a&0xffffff, d, SekPcS68k);\r
853 #endif\r
854   return d;\r
855 }\r
856 \r
857 u32 PicoReadS68k32(u32 a)\r
858 {\r
859   u32 d=0;\r
860 \r
861   a&=0xfffffe;\r
862 \r
863   // prg RAM\r
864   if (a < 0x80000) {\r
865     u16 *pm=(u16 *)(Pico_mcd->prg_ram+a);\r
866     d = (pm[0]<<16)|pm[1];\r
867     goto end;\r
868   }\r
869 \r
870   // regs\r
871   if ((a&0xfffe00) == 0xff8000) {\r
872     //dprintf("s68k_regs r32: [%02x] @ %06x", a&0x1fe, SekPcS68k);\r
873     d = (s68k_reg_read16(a, 32)<<16)|s68k_reg_read16(a+2, 32);\r
874     //dprintf("ret = %08x", d);\r
875     goto end;\r
876   }\r
877 \r
878   // word RAM (2M area)\r
879   if ((a&0xfc0000)==0x080000) { // 080000-0bffff\r
880     dprintf("s68k_wram2M r32: [%06x] @%06x", a, SekPc);\r
881     if (Pico_mcd->s68k_regs[3]&4) { // 1M mode?\r
882       // TODO (decode)\r
883       dprintf("(decode)");\r
884     } else {\r
885       // allow access in any mode, like Gens does\r
886       u16 *pm=(u16 *)(Pico_mcd->word_ram+(a&0x3fffe)); d = (pm[0]<<16)|pm[1];\r
887     }\r
888     dprintf("ret = %08x", (u8)d);\r
889     goto end;\r
890   }\r
891 \r
892   // word RAM (1M area)\r
893   if ((a&0xfe0000)==0x0c0000 && (Pico_mcd->s68k_regs[3]&4)) { // 0c0000-0dffff\r
894     u16 *pm;\r
895     dprintf("s68k_wram1M 32: [%06x] @%06x", a, SekPc);\r
896     a=((a&0x1fffe)<<1);\r
897     if (!(Pico_mcd->s68k_regs[3]&1)) a+=2;\r
898     pm=(u16 *)(Pico_mcd->word_ram+a);\r
899     d  = (pm[0]<<16)|pm[1];\r
900     dprintf("ret = %08x", (u8)d);\r
901     goto end;\r
902   }\r
903 \r
904   dprintf("s68k r32: %06x, %08x @%06x", a&0xffffff, d, SekPcS68k);\r
905 \r
906   end:\r
907 \r
908 #ifdef __debug_io2\r
909   dprintf("s68k r32: %06x, %08x @%06x", a&0xffffff, d, SekPcS68k);\r
910 #endif\r
911   return d;\r
912 }\r
913 \r
914 // -----------------------------------------------------------------\r
915 \r
916 void PicoWriteS68k8(u32 a,u8 d)\r
917 {\r
918 #ifdef __debug_io2\r
919   dprintf("s68k w8 : %06x,   %02x @%06x", a&0xffffff, d, SekPcS68k);\r
920 #endif\r
921 \r
922   a&=0xffffff;\r
923 \r
924   // prg RAM\r
925   if (a < 0x80000) {\r
926     u8 *pm=(u8 *)(Pico_mcd->prg_ram+(a^1));\r
927     *pm=d;\r
928     return;\r
929   }\r
930 \r
931   if (a != 0xff0011 && (a&0xff8000) == 0xff0000) // PCM hack\r
932     return;\r
933 \r
934   // regs\r
935   if ((a&0xfffe00) == 0xff8000) {\r
936     //dprintf("s68k_regs w8: [%02x] %02x @ %06x", a&0x1ff, d, SekPcS68k);\r
937     s68k_reg_write8(a,d,8);\r
938     return;\r
939   }\r
940 \r
941   // word RAM (2M area)\r
942   if ((a&0xfc0000)==0x080000) { // 080000-0bffff\r
943     dprintf("s68k_wram2M w8: [%06x] %02x @%06x", a, d, SekPc);\r
944     if (Pico_mcd->s68k_regs[3]&4) { // 1M mode?\r
945       // TODO (decode)\r
946       dprintf("(decode)");\r
947     } else {\r
948       // allow access in any mode, like Gens does\r
949       *(u8 *)(Pico_mcd->word_ram+((a^1)&0x3ffff))=d;\r
950     }\r
951     return;\r
952   }\r
953 \r
954   // word RAM (1M area)\r
955   if ((a&0xfe0000)==0x0c0000 && (Pico_mcd->s68k_regs[3]&4)) { // 0c0000-0dffff\r
956     if (d)\r
957       dprintf("s68k_wram1M w8: [%06x] %02x @%06x", a, d, SekPc);\r
958     a=((a&0x1fffe)<<1)|(a&1);\r
959     if (!(Pico_mcd->s68k_regs[3]&1)) a+=2;\r
960     *(u8 *)(Pico_mcd->word_ram+(a^1))=d;\r
961     return;\r
962   }\r
963 \r
964   dprintf("s68k w8 : %06x,   %02x @%06x", a&0xffffff, d, SekPcS68k);\r
965 }\r
966 \r
967 void PicoWriteS68k16(u32 a,u16 d)\r
968 {\r
969 #ifdef __debug_io2\r
970   dprintf("s68k w16: %06x, %04x @%06x", a&0xffffff, d, SekPcS68k);\r
971 #endif\r
972 \r
973   a&=0xfffffe;\r
974 \r
975   // prg RAM\r
976   if (a < 0x80000) {\r
977     *(u16 *)(Pico_mcd->prg_ram+a)=d;\r
978     return;\r
979   }\r
980 \r
981   // regs\r
982   if ((a&0xfffe00) == 0xff8000) {\r
983     //dprintf("s68k_regs w16: [%02x] %04x @ %06x", a&0x1ff, d, SekPcS68k);\r
984     s68k_reg_write8(a,  d>>8, 16);\r
985     s68k_reg_write8(a+1,d&0xff, 16);\r
986     return;\r
987   }\r
988 \r
989   // word RAM (2M area)\r
990   if ((a&0xfc0000)==0x080000) { // 080000-0bffff\r
991     dprintf("s68k_wram2M w16: [%06x] %04x @%06x", a, d, SekPc);\r
992     if (Pico_mcd->s68k_regs[3]&4) { // 1M mode?\r
993       // TODO (decode)\r
994       dprintf("(decode)");\r
995     } else {\r
996       // allow access in any mode, like Gens does\r
997       *(u16 *)(Pico_mcd->word_ram+(a&0x3fffe))=d;\r
998     }\r
999     return;\r
1000   }\r
1001 \r
1002   // word RAM (1M area)\r
1003   if ((a&0xfe0000)==0x0c0000 && (Pico_mcd->s68k_regs[3]&4)) { // 0c0000-0dffff\r
1004     if (d)\r
1005       dprintf("s68k_wram1M w16: [%06x] %04x @%06x", a, d, SekPc);\r
1006     a=((a&0x1fffe)<<1);\r
1007     if (!(Pico_mcd->s68k_regs[3]&1)) a+=2;\r
1008     *(u16 *)(Pico_mcd->word_ram+a)=d;\r
1009     return;\r
1010   }\r
1011 \r
1012   dprintf("s68k w16: %06x, %04x @%06x", a&0xffffff, d, SekPcS68k);\r
1013 }\r
1014 \r
1015 void PicoWriteS68k32(u32 a,u32 d)\r
1016 {\r
1017 #ifdef __debug_io2\r
1018   dprintf("s68k w32: %06x, %08x @%06x", a&0xffffff, d, SekPcS68k);\r
1019 #endif\r
1020 \r
1021   a&=0xfffffe;\r
1022 \r
1023   // prg RAM\r
1024   if (a < 0x80000) {\r
1025     u16 *pm=(u16 *)(Pico_mcd->prg_ram+a);\r
1026     pm[0]=(u16)(d>>16); pm[1]=(u16)d;\r
1027     return;\r
1028   }\r
1029 \r
1030   // regs\r
1031   if ((a&0xfffe00) == 0xff8000) {\r
1032     //dprintf("s68k_regs w32: [%02x] %08x @ %06x", a&0x1ff, d, SekPcS68k);\r
1033     s68k_reg_write8(a,   d>>24, 32);\r
1034     s68k_reg_write8(a+1,(d>>16)&0xff, 32);\r
1035     s68k_reg_write8(a+2,(d>>8) &0xff, 32);\r
1036     s68k_reg_write8(a+3, d     &0xff, 32);\r
1037     return;\r
1038   }\r
1039 \r
1040   // word RAM (2M area)\r
1041   if ((a&0xfc0000)==0x080000) { // 080000-0bffff\r
1042     dprintf("s68k_wram2M w32: [%06x] %08x @%06x", a, d, SekPc);\r
1043     if (Pico_mcd->s68k_regs[3]&4) { // 1M mode?\r
1044       // TODO (decode)\r
1045       dprintf("(decode)");\r
1046     } else {\r
1047       // allow access in any mode, like Gens does\r
1048       u16 *pm=(u16 *)(Pico_mcd->word_ram+(a&0x3fffe));\r
1049       pm[0]=(u16)(d>>16); pm[1]=(u16)d;\r
1050     }\r
1051     return;\r
1052   }\r
1053 \r
1054   // word RAM (1M area)\r
1055   if ((a&0xfe0000)==0x0c0000 && (Pico_mcd->s68k_regs[3]&4)) { // 0c0000-0dffff\r
1056     u16 *pm;\r
1057     if (d)\r
1058       dprintf("s68k_wram1M w32: [%06x] %08x @%06x", a, d, SekPc);\r
1059     a=((a&0x1fffe)<<1);\r
1060     if (!(Pico_mcd->s68k_regs[3]&1)) a+=2;\r
1061     pm=(u16 *)(Pico_mcd->word_ram+a);\r
1062     pm[0]=(u16)(d>>16); pm[1]=(u16)d;\r
1063     return;\r
1064   }\r
1065   dprintf("s68k w32: %06x, %08x @%06x", a&0xffffff, d, SekPcS68k);\r
1066 }\r
1067 \r
1068 \r
1069 \r
1070 // -----------------------------------------------------------------\r
1071 \r
1072 #ifdef EMU_M68K\r
1073 unsigned char  PicoReadCD8w (unsigned int a) {\r
1074         return m68ki_cpu_p == &PicoS68kCPU ? PicoReadS68k8(a) : PicoReadM68k8(a);\r
1075 }\r
1076 unsigned short PicoReadCD16w(unsigned int a) {\r
1077         return m68ki_cpu_p == &PicoS68kCPU ? PicoReadS68k16(a) : PicoReadM68k16(a);\r
1078 }\r
1079 unsigned int   PicoReadCD32w(unsigned int a) {\r
1080         return m68ki_cpu_p == &PicoS68kCPU ? PicoReadS68k32(a) : PicoReadM68k32(a);\r
1081 }\r
1082 void PicoWriteCD8w (unsigned int a, unsigned char d) {\r
1083         if (m68ki_cpu_p == &PicoS68kCPU) PicoWriteS68k8(a, d); else PicoWriteM68k8(a, d);\r
1084 }\r
1085 void PicoWriteCD16w(unsigned int a, unsigned short d) {\r
1086         if (m68ki_cpu_p == &PicoS68kCPU) PicoWriteS68k16(a, d); else PicoWriteM68k16(a, d);\r
1087 }\r
1088 void PicoWriteCD32w(unsigned int a, unsigned int d) {\r
1089         if (m68ki_cpu_p == &PicoS68kCPU) PicoWriteS68k32(a, d); else PicoWriteM68k32(a, d);\r
1090 }\r
1091 \r
1092 // these are allowed to access RAM\r
1093 unsigned int  m68k_read_pcrelative_CD8 (unsigned int a) {\r
1094   a&=0xffffff;\r
1095   if(m68ki_cpu_p == &PicoS68kCPU) {\r
1096     if (a < 0x80000) return *(u8 *)(Pico_mcd->prg_ram+(a^1)); // PRG Ram\r
1097     else dprintf("s68k read_pcrel8 @ %06x", a);\r
1098   } else {\r
1099     if(a<Pico.romsize)         return *(u8 *)(Pico.rom+(a^1)); // Rom\r
1100     if((a&0xe00000)==0xe00000) return *(u8 *)(Pico.ram+((a^1)&0xffff)); // Ram\r
1101   }\r
1102   return 0;//(u8)  lastread_d;\r
1103 }\r
1104 unsigned int  m68k_read_pcrelative_CD16(unsigned int a) {\r
1105   a&=0xffffff;\r
1106   if(m68ki_cpu_p == &PicoS68kCPU) {\r
1107     if (a < 0x80000) return *(u16 *)(Pico_mcd->prg_ram+(a&~1)); // PRG Ram\r
1108     else dprintf("s68k read_pcrel16 @ %06x", a);\r
1109   } else {\r
1110     if(a<Pico.romsize)         return *(u16 *)(Pico.rom+(a&~1)); // Rom\r
1111     if((a&0xe00000)==0xe00000) return *(u16 *)(Pico.ram+(a&0xfffe)); // Ram\r
1112   }\r
1113   return 0;//(u16) lastread_d;\r
1114 }\r
1115 unsigned int  m68k_read_pcrelative_CD32(unsigned int a) {\r
1116   a&=0xffffff;\r
1117   if(m68ki_cpu_p == &PicoS68kCPU) {\r
1118     if (a < 0x80000) { u16 *pm=(u16 *)(Pico_mcd->prg_ram+(a&~1)); return (pm[0]<<16)|pm[1]; } // PRG Ram\r
1119     else dprintf("s68k read_pcrel32 @ %06x", a);\r
1120   } else {\r
1121     if(a<Pico.romsize)         { u16 *pm=(u16 *)(Pico.rom+(a&~1));     return (pm[0]<<16)|pm[1]; }\r
1122     if((a&0xe00000)==0xe00000) { u16 *pm=(u16 *)(Pico.ram+(a&0xfffe)); return (pm[0]<<16)|pm[1]; } // Ram\r
1123   }\r
1124   return 0; //lastread_d;\r
1125 }\r
1126 #endif // EMU_M68K\r
1127 \r