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