region detection, cd states wip, fixes, stuff
[picodrive.git] / Pico / cd / Memory.c
1 // This is part of Pico Library\r
2 \r
3 // (c) Copyright 2004 Dave, All rights reserved.\r
4 // (c) Copyright 2007 notaz, All rights reserved.\r
5 // Free for non-commercial use.\r
6 \r
7 // For commercial use, separate licencing terms must be obtained.\r
8 \r
9 // A68K no longer supported here\r
10 \r
11 //#define __debug_io\r
12 \r
13 #include "../PicoInt.h"\r
14 \r
15 #include "../sound/sound.h"\r
16 #include "../sound/ym2612.h"\r
17 #include "../sound/sn76496.h"\r
18 \r
19 #include "gfx_cd.h"\r
20 \r
21 typedef unsigned char  u8;\r
22 typedef unsigned short u16;\r
23 typedef unsigned int   u32;\r
24 \r
25 //#define __debug_io\r
26 //#define __debug_io2\r
27 //#define rdprintf dprintf\r
28 #define rdprintf(...)\r
29 \r
30 // -----------------------------------------------------------------\r
31 \r
32 // extern m68ki_cpu_core m68ki_cpu;\r
33 \r
34 \r
35 static u32 m68k_reg_read16(u32 a)\r
36 {\r
37   u32 d=0;\r
38   a &= 0x3e;\r
39   // dprintf("m68k_regs r%2i: [%02x] @%06x", realsize&~1, a+(realsize&1), SekPc);\r
40 \r
41   switch (a) {\r
42     case 0:\r
43       d = ((Pico_mcd->s68k_regs[0x33]<<13)&0x8000) | Pico_mcd->m.busreq; // here IFL2 is always 0, just like in Gens\r
44       goto end;\r
45     case 2:\r
46       d = (Pico_mcd->s68k_regs[a]<<8) | (Pico_mcd->s68k_regs[a+1]&0xc7);\r
47       dprintf("m68k_regs r3: %02x @%06x", (u8)d, SekPc);\r
48       goto end;\r
49     case 4:\r
50       d = Pico_mcd->s68k_regs[4]<<8;\r
51       goto end;\r
52     case 6:\r
53       d = Pico_mcd->m.hint_vector;\r
54       goto end;\r
55     case 8:\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 timer 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)\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)) Pico_mcd->m.state_flags |= 1; // 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 ((Pico_mcd->m.state_flags&1) && (d&3)==1) {\r
96         SekResetS68k(); // S68k comes out of RESET or BRQ state\r
97         Pico_mcd->m.state_flags&=~1;\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       Pico_mcd->bios[0x72 + 1] = d; // simple hint vector changer\r
120       return;\r
121     case 7:\r
122       *(char *)&Pico_mcd->m.hint_vector = d;\r
123       Pico_mcd->bios[0x72] = d;\r
124       return;\r
125     case 0xe:\r
126       //dprintf("m68k: comm flag: %02x", d);\r
127 \r
128       //dprintf("s68k @ %06x", SekPcS68k);\r
129 \r
130       Pico_mcd->s68k_regs[0xe] = d;\r
131       return;\r
132   }\r
133 \r
134   if ((a&0xf0) == 0x10) {\r
135       Pico_mcd->s68k_regs[a] = d;\r
136       return;\r
137   }\r
138 \r
139   dprintf("m68k: invalid write? [%02x] %02x", a, d);\r
140 }\r
141 \r
142 \r
143 \r
144 static u32 s68k_reg_read16(u32 a)\r
145 {\r
146   u32 d=0;\r
147 \r
148   // dprintf("s68k_regs r%2i: [%02x] @ %06x", realsize&~1, a+(realsize&1), SekPcS68k);\r
149 \r
150   switch (a) {\r
151     case 0:\r
152       d = ((Pico_mcd->s68k_regs[0]&3)<<8) | 1; // ver = 0, not in reset state\r
153       goto end;\r
154     case 2:\r
155       d = (Pico_mcd->s68k_regs[a]<<8) | (Pico_mcd->s68k_regs[a+1]&0x1f);\r
156       dprintf("s68k_regs r3: %02x @%06x", (u8)d, SekPc);\r
157       goto end;\r
158     case 6:\r
159       d = CDC_Read_Reg();\r
160       goto end;\r
161     case 8:\r
162       d = Read_CDC_Host(1); // Gens returns 0 here on byte reads\r
163       goto end;\r
164     case 0xC:\r
165       dprintf("s68k stopwatch timer read");\r
166       break;\r
167     case 0x30:\r
168       dprintf("s68k int3 timer read");\r
169       break;\r
170     case 0x34: // fader\r
171       d = 0; // no busy bit\r
172       goto end;\r
173   }\r
174 \r
175   d = (Pico_mcd->s68k_regs[a]<<8) | Pico_mcd->s68k_regs[a+1];\r
176 \r
177 end:\r
178 \r
179   // dprintf("ret = %04x", d);\r
180 \r
181   return d;\r
182 }\r
183 \r
184 static void s68k_reg_write8(u32 a, u32 d)\r
185 {\r
186   //dprintf("s68k_regs w%2i: [%02x] %02x @ %06x", realsize, a, d, SekPcS68k);\r
187 \r
188   // TODO: review against Gens\r
189   switch (a) {\r
190     case 2:\r
191       return; // only m68k can change WP\r
192     case 3:\r
193       dprintf("s68k_regs w3: %02x @%06x", (u8)d, SekPc);\r
194       d &= 0x1d;\r
195       if (d&4) {\r
196         d |= Pico_mcd->s68k_regs[3]&0xc2;\r
197         if ((d ^ Pico_mcd->s68k_regs[3]) & 5) d &= ~2; // in case of mode or bank change we clear DMNA (m68k req) bit\r
198       } else {\r
199         d |= Pico_mcd->s68k_regs[3]&0xc3;\r
200         if (d&1) d &= ~2; // return word RAM to m68k in 2M mode\r
201       }\r
202       break;\r
203     case 4:\r
204       dprintf("s68k CDC dest: %x", d&7);\r
205       Pico_mcd->s68k_regs[4] = (Pico_mcd->s68k_regs[4]&0xC0) | (d&7); // CDC mode\r
206       return;\r
207     case 5:\r
208       //dprintf("s68k CDC reg addr: %x", d&0xf);\r
209       break;\r
210     case 7:\r
211       CDC_Write_Reg(d);\r
212       return;\r
213     case 0xa:\r
214       dprintf("s68k set CDC dma addr");\r
215       break;\r
216     case 0xc:\r
217       dprintf("s68k set stopwatch timer");\r
218       break;\r
219     case 0x31:\r
220       dprintf("s68k set int3 timer");\r
221       break;\r
222     case 0x33: // IRQ mask\r
223       dprintf("s68k irq mask: %02x", d);\r
224       if ((d&(1<<4)) && (Pico_mcd->s68k_regs[0x37]&4) && !(Pico_mcd->s68k_regs[0x33]&(1<<4))) {\r
225         CDD_Export_Status();\r
226       }\r
227       break;\r
228     case 0x34: // fader\r
229       Pico_mcd->s68k_regs[a] = (u8) d & 0x7f;\r
230       return;\r
231     case 0x36:\r
232       return; // d/m bit is unsetable\r
233     case 0x37: {\r
234       u32 d_old = Pico_mcd->s68k_regs[0x37];\r
235       Pico_mcd->s68k_regs[0x37] = d&7;\r
236       if ((d&4) && !(d_old&4)) {\r
237         CDD_Export_Status();\r
238       }\r
239       return;\r
240     }\r
241     case 0x4b:\r
242       Pico_mcd->s68k_regs[a] = (u8) d;\r
243       CDD_Import_Command();\r
244       return;\r
245   }\r
246 \r
247   if ((a&0x1f0) == 0x10 || a == 0x0e || (a >= 0x38 && a < 0x42))\r
248   {\r
249     dprintf("m68k: invalid write @ %02x?", a);\r
250     return;\r
251   }\r
252 \r
253   Pico_mcd->s68k_regs[a] = (u8) d;\r
254 }\r
255 \r
256 \r
257 \r
258 \r
259 \r
260 static int PadRead(int i)\r
261 {\r
262   int pad=0,value=0,TH;\r
263   pad=~PicoPad[i]; // Get inverse of pad MXYZ SACB RLDU\r
264   TH=Pico.ioports[i+1]&0x40;\r
265 \r
266   if(PicoOpt & 0x20) { // 6 button gamepad enabled\r
267     int phase = Pico.m.padTHPhase[i];\r
268 \r
269     if(phase == 2 && !TH) {\r
270       value=(pad&0xc0)>>2;              // ?0SA 0000\r
271       goto end;\r
272     } else if(phase == 3 && TH) {\r
273       value=(pad&0x30)|((pad>>8)&0xf);  // ?1CB MXYZ\r
274       goto end;\r
275     } else if(phase == 3 && !TH) {\r
276       value=((pad&0xc0)>>2)|0x0f;       // ?0SA 1111\r
277       goto end;\r
278     }\r
279   }\r
280 \r
281   if(TH) value=(pad&0x3f);              // ?1CB RLDU\r
282   else   value=((pad&0xc0)>>2)|(pad&3); // ?0SA 00DU\r
283 \r
284   end:\r
285 \r
286   // orr the bits, which are set as output\r
287   value |= Pico.ioports[i+1]&Pico.ioports[i+4];\r
288 \r
289   return value; // will mirror later\r
290 }\r
291 \r
292 static u8 z80Read8(u32 a)\r
293 {\r
294   if(Pico.m.z80Run&1) return 0;\r
295 \r
296   a&=0x1fff;\r
297 \r
298   if(!(PicoOpt&4)) {\r
299     // Z80 disabled, do some faking\r
300     static u8 zerosent = 0;\r
301     if(a == Pico.m.z80_lastaddr) { // probably polling something\r
302       u8 d = Pico.m.z80_fakeval;\r
303       if((d & 0xf) == 0xf && !zerosent) {\r
304         d = 0; zerosent = 1;\r
305       } else {\r
306         Pico.m.z80_fakeval++;\r
307         zerosent = 0;\r
308       }\r
309       return d;\r
310     } else {\r
311       Pico.m.z80_fakeval = 0;\r
312     }\r
313   }\r
314 \r
315   Pico.m.z80_lastaddr = (u16) a;\r
316   return Pico.zram[a];\r
317 }\r
318 \r
319 \r
320 // for nonstandard reads\r
321 static u32 UnusualRead16(u32 a, int realsize)\r
322 {\r
323   u32 d=0;\r
324 \r
325   dprintf("unusual r%i: %06x @%06x", realsize&~1, (a&0xfffffe)+(realsize&1), SekPc);\r
326 \r
327 \r
328   dprintf("ret = %04x", d);\r
329   return d;\r
330 }\r
331 \r
332 static u32 OtherRead16(u32 a, int realsize)\r
333 {\r
334   u32 d=0;\r
335 \r
336   if ((a&0xff0000)==0xa00000) {\r
337     if ((a&0x4000)==0x0000) { d=z80Read8(a); d|=d<<8; goto end; } // Z80 ram (not byteswaped)\r
338     if ((a&0x6000)==0x4000) { if(PicoOpt&1) d=YM2612Read(); else d=Pico.m.rotate++&3; goto end; } // 0x4000-0x5fff, Fudge if disabled\r
339         d=0xffff; goto end;\r
340   }\r
341   if ((a&0xffffe0)==0xa10000) { // I/O ports\r
342     a=(a>>1)&0xf;\r
343     switch(a) {\r
344       case 0:  d=Pico.m.hardware; break; // Hardware value (Version register)\r
345       case 1:  d=PadRead(0); d|=Pico.ioports[1]&0x80; break;\r
346       case 2:  d=PadRead(1); d|=Pico.ioports[2]&0x80; break;\r
347       default: d=Pico.ioports[a]; break; // IO ports can be used as RAM\r
348     }\r
349     d|=d<<8;\r
350     goto end;\r
351   }\r
352   // |=0x80 for Shadow of the Beast & Super Offroad; rotate fakes next fetched instruction for Time Killers\r
353   if (a==0xa11100) { d=((Pico.m.z80Run&1)<<8)|0x8000|Pico.m.rotate++; goto end; }\r
354 \r
355   if ((a&0xe700e0)==0xc00000) { d=PicoVideoRead(a); goto end; }\r
356 \r
357   if ((a&0xffffc0)==0xa12000) {\r
358     d=m68k_reg_read16(a);\r
359     goto end;\r
360   }\r
361 \r
362   d = UnusualRead16(a, realsize);\r
363 \r
364 end:\r
365   return d;\r
366 }\r
367 \r
368 //extern UINT32 mz80GetRegisterValue(void *, UINT32);\r
369 \r
370 static void OtherWrite8(u32 a,u32 d,int realsize)\r
371 {\r
372   if ((a&0xe700f9)==0xc00011||(a&0xff7ff9)==0xa07f11) { if(PicoOpt&2) SN76496Write(d); return; } // PSG Sound\r
373   if ((a&0xff4000)==0xa00000)  { if(!(Pico.m.z80Run&1)) Pico.zram[a&0x1fff]=(u8)d; return; } // Z80 ram\r
374   if ((a&0xff6000)==0xa04000)  { if(PicoOpt&1) emustatus|=YM2612Write(a&3, d); return; } // FM Sound\r
375   if ((a&0xffffe0)==0xa10000)  { // I/O ports\r
376     a=(a>>1)&0xf;\r
377     // 6 button gamepad: if TH went from 0 to 1, gamepad changes state\r
378     if(PicoOpt&0x20) {\r
379       if(a==1) {\r
380         Pico.m.padDelay[0] = 0;\r
381         if(!(Pico.ioports[1]&0x40) && (d&0x40)) Pico.m.padTHPhase[0]++;\r
382       }\r
383       else if(a==2) {\r
384         Pico.m.padDelay[1] = 0;\r
385         if(!(Pico.ioports[2]&0x40) && (d&0x40)) Pico.m.padTHPhase[1]++;\r
386       }\r
387     }\r
388     Pico.ioports[a]=(u8)d; // IO ports can be used as RAM\r
389     return;\r
390   }\r
391   if (a==0xa11100) {\r
392     extern int z80startCycle, z80stopCycle;\r
393     //int lineCycles=(488-SekCyclesLeft)&0x1ff;\r
394     d&=1; d^=1;\r
395         if(!d) {\r
396           // hack: detect a nasty situation where Z80 was enabled and disabled in the same 68k timeslice (Golden Axe III)\r
397       if((PicoOpt&4) && Pico.m.z80Run==1) z80_run(20);\r
398           z80stopCycle = SekCyclesDone();\r
399           //z80ExtraCycles += (lineCycles>>1)-(lineCycles>>5); // only meaningful in PicoFrameHints()\r
400         } else {\r
401           z80startCycle = SekCyclesDone();\r
402           //if(Pico.m.scanline != -1)\r
403           //z80ExtraCycles -= (lineCycles>>1)-(lineCycles>>5)+16;\r
404         }\r
405     //dprintf("set_zrun: %i [%i|%i] zPC=%04x @%06x", d, Pico.m.scanline, SekCyclesDone(), mz80GetRegisterValue(NULL, 0), SekPc);\r
406         Pico.m.z80Run=(u8)d; return;\r
407   }\r
408   if (a==0xa11200) { if(!(d&1)) z80_reset(); return; }\r
409 \r
410   if ((a&0xff7f00)==0xa06000) // Z80 BANK register\r
411   {\r
412     Pico.m.z80_bank68k>>=1;\r
413     Pico.m.z80_bank68k|=(d&1)<<8;\r
414     Pico.m.z80_bank68k&=0x1ff; // 9 bits and filled in the new top one\r
415     return;\r
416   }\r
417 \r
418   if ((a&0xe700e0)==0xc00000) { PicoVideoWrite(a,(u16)(d|(d<<8))); return; } // Byte access gets mirrored\r
419 \r
420   if ((a&0xffffc0)==0xa12000) { m68k_reg_write8(a, d); return; }\r
421 \r
422   dprintf("strange w%i: %06x, %08x @%06x", realsize, a&0xffffff, d, SekPc);\r
423 }\r
424 \r
425 static void OtherWrite16(u32 a,u32 d)\r
426 {\r
427   if ((a&0xe700e0)==0xc00000) { PicoVideoWrite(a,(u16)d); return; }\r
428   if ((a&0xff4000)==0xa00000) { if(!(Pico.m.z80Run&1)) Pico.zram[a&0x1fff]=(u8)(d>>8); return; } // Z80 ram (MSB only)\r
429 \r
430   if ((a&0xffffe0)==0xa10000) { // I/O ports\r
431     a=(a>>1)&0xf;\r
432     // 6 button gamepad: if TH went from 0 to 1, gamepad changes state\r
433     if(PicoOpt&0x20) {\r
434       if(a==1) {\r
435         Pico.m.padDelay[0] = 0;\r
436         if(!(Pico.ioports[1]&0x40) && (d&0x40)) Pico.m.padTHPhase[0]++;\r
437       }\r
438       else if(a==2) {\r
439         Pico.m.padDelay[1] = 0;\r
440         if(!(Pico.ioports[2]&0x40) && (d&0x40)) Pico.m.padTHPhase[1]++;\r
441       }\r
442     }\r
443     Pico.ioports[a]=(u8)d; // IO ports can be used as RAM\r
444     return;\r
445   }\r
446   if (a==0xa11100) { OtherWrite8(a, d>>8, 16); return; }\r
447   if (a==0xa11200) { if(!(d&0x100)) z80_reset(); return; }\r
448 \r
449   OtherWrite8(a,  d>>8, 16);\r
450   OtherWrite8(a+1,d&0xff, 16);\r
451 }\r
452 \r
453 // -----------------------------------------------------------------\r
454 //                     Read Rom and read Ram\r
455 \r
456 u8 PicoReadM68k8(u32 a)\r
457 {\r
458   u32 d=0;\r
459 \r
460   if ((a&0xe00000)==0xe00000) { d = *(u8 *)(Pico.ram+((a^1)&0xffff)); goto end; } // Ram\r
461 \r
462   a&=0xffffff;\r
463 \r
464   if (a < 0x20000) { d = *(u8 *)(Pico_mcd->bios+(a^1)); goto end; } // bios\r
465 \r
466   // prg RAM\r
467   if ((a&0xfe0000)==0x020000) {\r
468     u8 *prg_bank = Pico_mcd->prg_ram_b[Pico_mcd->s68k_regs[3]>>6];\r
469     d = *(prg_bank+((a^1)&0x1ffff));\r
470     goto end;\r
471   }\r
472 \r
473 #if 0\r
474   if (a == 0x200000 && SekPc == 0xff0b66 && Pico.m.frame_count > 1000)\r
475   {\r
476           int i;\r
477           FILE *ff;\r
478           unsigned short *ram = (unsigned short *) Pico.ram;\r
479           // unswap and dump RAM\r
480           for (i = 0; i < 0x10000/2; i++)\r
481                   ram[i] = (ram[i]>>8) | (ram[i]<<8);\r
482           ff = fopen("ram.bin", "wb");\r
483           fwrite(ram, 1, 0x10000, ff);\r
484           fclose(ff);\r
485           exit(0);\r
486   }\r
487 #endif\r
488 \r
489   // word RAM\r
490   if ((a&0xfc0000)==0x200000) {\r
491     dprintf("m68k_wram r8: [%06x] @%06x", a, SekPc);\r
492     if (Pico_mcd->s68k_regs[3]&4) { // 1M mode?\r
493       if (a >= 0x220000) {\r
494         dprintf("cell");\r
495       } else {\r
496         a=((a&0x1fffe)<<1)|(a&1);\r
497         if (Pico_mcd->s68k_regs[3]&1) a+=2;\r
498         d = Pico_mcd->word_ram[a^1];\r
499       }\r
500     } else {\r
501       // allow access in any mode, like Gens does\r
502       d = Pico_mcd->word_ram[(a^1)&0x3ffff];\r
503     }\r
504     dprintf("ret = %02x", (u8)d);\r
505     goto end;\r
506   }\r
507 \r
508   if ((a&0xff4000)==0xa00000) { d=z80Read8(a); goto end; } // Z80 Ram\r
509 \r
510   if ((a&0xffffc0)==0xa12000)\r
511     rdprintf("m68k_regs r8: [%02x] @%06x", a&0x3f, SekPc);\r
512 \r
513   d=OtherRead16(a&~1, 8|(a&1)); if ((a&1)==0) d>>=8;\r
514 \r
515   if ((a&0xffffc0)==0xa12000)\r
516     rdprintf("ret = %02x", (u8)d);\r
517 \r
518   end:\r
519 \r
520 #ifdef __debug_io\r
521   dprintf("r8 : %06x,   %02x @%06x", a&0xffffff, (u8)d, SekPc);\r
522 #endif\r
523   return (u8)d;\r
524 }\r
525 \r
526 \r
527 u16 PicoReadM68k16(u32 a)\r
528 {\r
529   u16 d=0;\r
530 \r
531   if ((a&0xe00000)==0xe00000) { d=*(u16 *)(Pico.ram+(a&0xfffe)); goto end; } // Ram\r
532 \r
533   a&=0xfffffe;\r
534 \r
535   if (a < 0x20000) { d = *(u16 *)(Pico_mcd->bios+a); goto end; } // bios\r
536 \r
537   // prg RAM\r
538   if ((a&0xfe0000)==0x020000) {\r
539     u8 *prg_bank = Pico_mcd->prg_ram_b[Pico_mcd->s68k_regs[3]>>6];\r
540     d = *(u16 *)(prg_bank+(a&0x1fffe));\r
541     goto end;\r
542   }\r
543 \r
544   // word RAM\r
545   if ((a&0xfc0000)==0x200000) {\r
546     dprintf("m68k_wram r16: [%06x] @%06x", a, SekPc);\r
547     if (Pico_mcd->s68k_regs[3]&4) { // 1M mode?\r
548       if (a >= 0x220000) {\r
549         dprintf("cell");\r
550       } else {\r
551         a=((a&0x1fffe)<<1);\r
552         if (Pico_mcd->s68k_regs[3]&1) a+=2;\r
553         d = *(u16 *)(Pico_mcd->word_ram+a);\r
554       }\r
555     } else {\r
556       // allow access in any mode, like Gens does\r
557       d = *(u16 *)(Pico_mcd->word_ram+(a&0x3fffe));\r
558     }\r
559     dprintf("ret = %04x", d);\r
560     goto end;\r
561   }\r
562 \r
563   if ((a&0xffffc0)==0xa12000)\r
564     rdprintf("m68k_regs r16: [%02x] @%06x", a&0x3f, SekPc);\r
565 \r
566   d = (u16)OtherRead16(a, 16);\r
567 \r
568   if ((a&0xffffc0)==0xa12000)\r
569     rdprintf("ret = %04x", d);\r
570 \r
571   end:\r
572 \r
573 #ifdef __debug_io\r
574   dprintf("r16: %06x, %04x  @%06x", a&0xffffff, d, SekPc);\r
575 #endif\r
576   return d;\r
577 }\r
578 \r
579 \r
580 u32 PicoReadM68k32(u32 a)\r
581 {\r
582   u32 d=0;\r
583 \r
584   if ((a&0xe00000)==0xe00000) { u16 *pm=(u16 *)(Pico.ram+(a&0xfffe)); d = (pm[0]<<16)|pm[1]; goto end; } // Ram\r
585 \r
586   a&=0xfffffe;\r
587 \r
588   if (a < 0x20000) { u16 *pm=(u16 *)(Pico_mcd->bios+a); d = (pm[0]<<16)|pm[1]; goto end; } // bios\r
589 \r
590   // prg RAM\r
591   if ((a&0xfe0000)==0x020000) {\r
592     u8 *prg_bank = Pico_mcd->prg_ram_b[Pico_mcd->s68k_regs[3]>>6];\r
593     u16 *pm=(u16 *)(prg_bank+(a&0x1fffe));\r
594     d = (pm[0]<<16)|pm[1];\r
595     goto end;\r
596   }\r
597 \r
598   // word RAM\r
599   if ((a&0xfc0000)==0x200000) {\r
600     dprintf("m68k_wram r32: [%06x] @%06x", a, SekPc);\r
601     if (Pico_mcd->s68k_regs[3]&4) { // 1M mode?\r
602       if (a >= 0x220000) {\r
603         dprintf("cell");\r
604       } else {\r
605         a=((a&0x1fffe)<<1);\r
606         if (Pico_mcd->s68k_regs[3]&1) a+=2;\r
607         d  = *(u16 *)(Pico_mcd->word_ram+a) << 16;\r
608         d |= *(u16 *)(Pico_mcd->word_ram+a+4);\r
609       }\r
610     } else {\r
611       // allow access in any mode, like Gens does\r
612       u16 *pm=(u16 *)(Pico_mcd->word_ram+(a&0x3fffe)); d = (pm[0]<<16)|pm[1];\r
613     }\r
614     dprintf("ret = %08x", d);\r
615     goto end;\r
616   }\r
617 \r
618   if ((a&0xffffc0)==0xa12000)\r
619     rdprintf("m68k_regs r32: [%02x] @%06x", a&0x3f, SekPc);\r
620 \r
621   d = (OtherRead16(a, 32)<<16)|OtherRead16(a+2, 32);\r
622 \r
623   if ((a&0xffffc0)==0xa12000)\r
624     rdprintf("ret = %08x", d);\r
625 \r
626   end:\r
627 #ifdef __debug_io\r
628   dprintf("r32: %06x, %08x @%06x", a&0xffffff, d, SekPc);\r
629 #endif\r
630   return d;\r
631 }\r
632 \r
633 \r
634 // -----------------------------------------------------------------\r
635 //                            Write Ram\r
636 \r
637 void PicoWriteM68k8(u32 a,u8 d)\r
638 {\r
639 #ifdef __debug_io\r
640   dprintf("w8 : %06x,   %02x @%06x", a&0xffffff, d, SekPc);\r
641 #endif\r
642   //if ((a&0xe0ffff)==0xe0a9ba+0x69c)\r
643   //  dprintf("w8 : %06x,   %02x @%06x", a&0xffffff, d, SekPc);\r
644 \r
645 \r
646   if ((a&0xe00000)==0xe00000) { // Ram\r
647     *(u8 *)(Pico.ram+((a^1)&0xffff)) = d;\r
648     return;\r
649   }\r
650 \r
651   a&=0xffffff;\r
652 \r
653   // prg RAM\r
654   if ((a&0xfe0000)==0x020000) {\r
655     u8 *prg_bank = Pico_mcd->prg_ram_b[Pico_mcd->s68k_regs[3]>>6];\r
656     *(u8 *)(prg_bank+((a^1)&0x1ffff))=d;\r
657     return;\r
658   }\r
659 \r
660   // word RAM\r
661   if ((a&0xfc0000)==0x200000) {\r
662     dprintf("m68k_wram w8: [%06x] %02x @%06x", a, d, SekPc);\r
663     if (Pico_mcd->s68k_regs[3]&4) { // 1M mode?\r
664       if (a >= 0x220000) {\r
665         dprintf("cell");\r
666       } else {\r
667         a=((a&0x1fffe)<<1)|(a&1);\r
668         if (Pico_mcd->s68k_regs[3]&1) a+=2;\r
669         *(u8 *)(Pico_mcd->word_ram+(a^1))=d;\r
670       }\r
671     } else {\r
672       // allow access in any mode, like Gens does\r
673       *(u8 *)(Pico_mcd->word_ram+((a^1)&0x3ffff))=d;\r
674     }\r
675     return;\r
676   }\r
677 \r
678   if ((a&0xffffc0)==0xa12000)\r
679     rdprintf("m68k_regs w8: [%02x] %02x @%06x", a&0x3f, d, SekPc);\r
680 \r
681   OtherWrite8(a,d,8);\r
682 }\r
683 \r
684 \r
685 void PicoWriteM68k16(u32 a,u16 d)\r
686 {\r
687 #ifdef __debug_io\r
688   dprintf("w16: %06x, %04x", a&0xffffff, d);\r
689 #endif\r
690   //  dprintf("w16: %06x, %04x  @%06x", a&0xffffff, d, SekPc);\r
691 \r
692   if ((a&0xe00000)==0xe00000) { // Ram\r
693     *(u16 *)(Pico.ram+(a&0xfffe))=d;\r
694     return;\r
695   }\r
696 \r
697   a&=0xfffffe;\r
698 \r
699   // prg RAM\r
700   if ((a&0xfe0000)==0x020000) {\r
701     u8 *prg_bank = Pico_mcd->prg_ram_b[Pico_mcd->s68k_regs[3]>>6];\r
702     *(u16 *)(prg_bank+(a&0x1fffe))=d;\r
703     return;\r
704   }\r
705 \r
706   // word RAM\r
707   if ((a&0xfc0000)==0x200000) {\r
708     dprintf("m68k_wram w16: [%06x] %04x @%06x", a, d, SekPc);\r
709     if (Pico_mcd->s68k_regs[3]&4) { // 1M mode?\r
710       if (a >= 0x220000) {\r
711         dprintf("cell");\r
712       } else {\r
713         a=((a&0x1fffe)<<1);\r
714         if (Pico_mcd->s68k_regs[3]&1) a+=2;\r
715         *(u16 *)(Pico_mcd->word_ram+a)=d;\r
716       }\r
717     } else {\r
718       // allow access in any mode, like Gens does\r
719       *(u16 *)(Pico_mcd->word_ram+(a&0x3fffe))=d;\r
720     }\r
721     return;\r
722   }\r
723 \r
724   if ((a&0xffffc0)==0xa12000)\r
725     rdprintf("m68k_regs w16: [%02x] %04x @%06x", a&0x3f, d, SekPc);\r
726 \r
727   OtherWrite16(a,d);\r
728 }\r
729 \r
730 \r
731 void PicoWriteM68k32(u32 a,u32 d)\r
732 {\r
733 #ifdef __debug_io\r
734   dprintf("w32: %06x, %08x", a&0xffffff, d);\r
735 #endif\r
736 \r
737   if ((a&0xe00000)==0xe00000)\r
738   {\r
739     // Ram:\r
740     u16 *pm=(u16 *)(Pico.ram+(a&0xfffe));\r
741     pm[0]=(u16)(d>>16); pm[1]=(u16)d;\r
742     return;\r
743   }\r
744 \r
745   a&=0xfffffe;\r
746 \r
747   // prg RAM\r
748   if ((a&0xfe0000)==0x020000) {\r
749     u8 *prg_bank = Pico_mcd->prg_ram_b[Pico_mcd->s68k_regs[3]>>6];\r
750     u16 *pm=(u16 *)(prg_bank+(a&0x1fffe));\r
751     pm[0]=(u16)(d>>16); pm[1]=(u16)d;\r
752     return;\r
753   }\r
754 \r
755   // word RAM\r
756   if ((a&0xfc0000)==0x200000) {\r
757     if (d != 0) // don't log clears\r
758       dprintf("m68k_wram w32: [%06x] %08x @%06x", a, d, SekPc);\r
759     if (Pico_mcd->s68k_regs[3]&4) { // 1M mode?\r
760       if (a >= 0x220000) {\r
761         dprintf("cell");\r
762       } else {\r
763         a=((a&0x1fffe)<<1);\r
764         if (Pico_mcd->s68k_regs[3]&1) a+=2;\r
765         *(u16 *)(Pico_mcd->word_ram+a) = d>>16;\r
766         *(u16 *)(Pico_mcd->word_ram+a+4) = d;\r
767       }\r
768     } else {\r
769       // allow access in any mode, like Gens does\r
770       u16 *pm=(u16 *)(Pico_mcd->word_ram+(a&0x3fffe));\r
771       pm[0]=(u16)(d>>16); pm[1]=(u16)d;\r
772     }\r
773     return;\r
774   }\r
775 \r
776   if ((a&0xffffc0)==0xa12000)\r
777     rdprintf("m68k_regs w32: [%02x] %08x @%06x", a&0x3f, d, SekPc);\r
778 \r
779   OtherWrite16(a,  (u16)(d>>16));\r
780   OtherWrite16(a+2,(u16)d);\r
781 }\r
782 \r
783 \r
784 // -----------------------------------------------------------------\r
785 \r
786 \r
787 u8 PicoReadS68k8(u32 a)\r
788 {\r
789   u32 d=0;\r
790 \r
791   a&=0xffffff;\r
792 \r
793   // prg RAM\r
794   if (a < 0x80000) {\r
795     d = *(Pico_mcd->prg_ram+(a^1));\r
796     goto end;\r
797   }\r
798 \r
799   // regs\r
800   if ((a&0xfffe00) == 0xff8000) {\r
801     a &= 0x1ff;\r
802     rdprintf("s68k_regs r8: [%02x] @ %06x", a, SekPcS68k);\r
803     if (a >= 0x50 && a < 0x68)\r
804          d = gfx_cd_read(a&~1);\r
805     else d = s68k_reg_read16(a&~1);\r
806     if ((a&1)==0) d>>=8;\r
807     rdprintf("ret = %02x", (u8)d);\r
808     goto end;\r
809   }\r
810 \r
811   // word RAM (2M area)\r
812   if ((a&0xfc0000)==0x080000) { // 080000-0bffff\r
813     dprintf("s68k_wram2M r8: [%06x] @%06x", a, SekPc);\r
814     if (Pico_mcd->s68k_regs[3]&4) { // 1M mode?\r
815       // TODO (decode)\r
816       dprintf("(decode)");\r
817     } else {\r
818       // allow access in any mode, like Gens does\r
819       d = Pico_mcd->word_ram[(a^1)&0x3ffff];\r
820     }\r
821     dprintf("ret = %02x", (u8)d);\r
822     goto end;\r
823   }\r
824 \r
825   // word RAM (1M area)\r
826   if ((a&0xfe0000)==0x0c0000 && (Pico_mcd->s68k_regs[3]&4)) { // 0c0000-0dffff\r
827     dprintf("s68k_wram1M r8: [%06x] @%06x", a, SekPc);\r
828     a=((a&0x1fffe)<<1)|(a&1);\r
829     if (!(Pico_mcd->s68k_regs[3]&1)) a+=2;\r
830     d = Pico_mcd->word_ram[a^1];\r
831     dprintf("ret = %02x", (u8)d);\r
832     goto end;\r
833   }\r
834 \r
835   // bram\r
836   if ((a&0xff0000)==0xfe0000) {\r
837     d = Pico_mcd->bram[(a>>1)&0x1fff];\r
838     goto end;\r
839   }\r
840 \r
841   dprintf("s68k r8 : %06x,   %02x @%06x", a&0xffffff, (u8)d, SekPcS68k);\r
842 \r
843   end:\r
844 \r
845 #ifdef __debug_io2\r
846   dprintf("s68k r8 : %06x,   %02x @%06x", a&0xffffff, (u8)d, SekPcS68k);\r
847 #endif\r
848   return (u8)d;\r
849 }\r
850 \r
851 \r
852 u16 PicoReadS68k16(u32 a)\r
853 {\r
854   u16 d=0;\r
855 \r
856   a&=0xfffffe;\r
857 \r
858   // prg RAM\r
859   if (a < 0x80000) {\r
860     d = *(u16 *)(Pico_mcd->prg_ram+a);\r
861     goto end;\r
862   }\r
863 \r
864   // regs\r
865   if ((a&0xfffe00) == 0xff8000) {\r
866     a &= 0x1fe;\r
867     rdprintf("s68k_regs r16: [%02x] @ %06x", a, SekPcS68k);\r
868     if (a >= 0x50 && a < 0x68)\r
869          d = gfx_cd_read(a);\r
870     else d = s68k_reg_read16(a);\r
871     rdprintf("ret = %04x", d);\r
872     goto end;\r
873   }\r
874 \r
875   // word RAM (2M area)\r
876   if ((a&0xfc0000)==0x080000) { // 080000-0bffff\r
877     dprintf("s68k_wram2M r16: [%06x] @%06x", a, SekPc);\r
878     if (Pico_mcd->s68k_regs[3]&4) { // 1M mode?\r
879       // TODO (decode)\r
880       dprintf("(decode)");\r
881     } else {\r
882       // allow access in any mode, like Gens does\r
883       d = *(u16 *)(Pico_mcd->word_ram+(a&0x3fffe));\r
884     }\r
885     dprintf("ret = %04x", d);\r
886     goto end;\r
887   }\r
888 \r
889   // word RAM (1M area)\r
890   if ((a&0xfe0000)==0x0c0000 && (Pico_mcd->s68k_regs[3]&4)) { // 0c0000-0dffff\r
891     dprintf("s68k_wram1M r16: [%06x] @%06x", a, SekPc);\r
892     a=((a&0x1fffe)<<1);\r
893     if (!(Pico_mcd->s68k_regs[3]&1)) a+=2;\r
894     d = *(u16 *)(Pico_mcd->word_ram+a);\r
895     dprintf("ret = %04x", d);\r
896     goto end;\r
897   }\r
898 \r
899   // bram\r
900   if ((a&0xff0000)==0xfe0000) {\r
901     dprintf("s68k_bram r16: [%06x] @%06x", a, SekPc);\r
902     a = (a>>1)&0x1fff;\r
903     d = Pico_mcd->bram[a++];            // Gens does little endian here, an so do we..\r
904     d|= Pico_mcd->bram[a++] << 8;\r
905     dprintf("ret = %04x", d);\r
906     goto end;\r
907   }\r
908 \r
909   dprintf("s68k r16: %06x, %04x  @%06x", a&0xffffff, d, SekPcS68k);\r
910 \r
911   end:\r
912 \r
913 #ifdef __debug_io2\r
914   dprintf("s68k r16: %06x, %04x  @%06x", a&0xffffff, d, SekPcS68k);\r
915 #endif\r
916   return d;\r
917 }\r
918 \r
919 \r
920 u32 PicoReadS68k32(u32 a)\r
921 {\r
922   u32 d=0;\r
923 \r
924   a&=0xfffffe;\r
925 \r
926   // prg RAM\r
927   if (a < 0x80000) {\r
928     u16 *pm=(u16 *)(Pico_mcd->prg_ram+a);\r
929     d = (pm[0]<<16)|pm[1];\r
930     goto end;\r
931   }\r
932 \r
933   // regs\r
934   if ((a&0xfffe00) == 0xff8000) {\r
935     a &= 0x1fe;\r
936     rdprintf("s68k_regs r32: [%02x] @ %06x", a, SekPcS68k);\r
937     if (a >= 0x50 && a < 0x68)\r
938          d = (gfx_cd_read(a)<<16)|gfx_cd_read(a+2);\r
939     else d = (s68k_reg_read16(a)<<16)|s68k_reg_read16(a+2);\r
940     rdprintf("ret = %08x", d);\r
941     goto end;\r
942   }\r
943 \r
944   // word RAM (2M area)\r
945   if ((a&0xfc0000)==0x080000) { // 080000-0bffff\r
946     dprintf("s68k_wram2M r32: [%06x] @%06x", a, SekPc);\r
947     if (Pico_mcd->s68k_regs[3]&4) { // 1M mode?\r
948       // TODO (decode)\r
949       dprintf("(decode)");\r
950     } else {\r
951       // allow access in any mode, like Gens does\r
952       u16 *pm=(u16 *)(Pico_mcd->word_ram+(a&0x3fffe)); d = (pm[0]<<16)|pm[1];\r
953     }\r
954     dprintf("ret = %08x", d);\r
955     goto end;\r
956   }\r
957 \r
958   // word RAM (1M area)\r
959   if ((a&0xfe0000)==0x0c0000 && (Pico_mcd->s68k_regs[3]&4)) { // 0c0000-0dffff\r
960     dprintf("s68k_wram1M r32: [%06x] @%06x", a, SekPc);\r
961     a=((a&0x1fffe)<<1);\r
962     if (!(Pico_mcd->s68k_regs[3]&1)) a+=2;\r
963     d  = *(u16 *)(Pico_mcd->word_ram+a) << 16;\r
964     d |= *(u16 *)(Pico_mcd->word_ram+a+4);\r
965     dprintf("ret = %08x", d);\r
966     goto end;\r
967   }\r
968 \r
969   // bram\r
970   if ((a&0xff0000)==0xfe0000) {\r
971     dprintf("s68k_bram r32: [%06x] @%06x", a, SekPc);\r
972     a = (a>>1)&0x1fff;\r
973     d = Pico_mcd->bram[a++] << 16;              // middle endian? TODO: verify against Fusion..\r
974     d|= Pico_mcd->bram[a++] << 24;\r
975     d|= Pico_mcd->bram[a++];\r
976     d|= Pico_mcd->bram[a++] << 8;\r
977     dprintf("ret = %08x", d);\r
978     goto end;\r
979   }\r
980 \r
981   dprintf("s68k r32: %06x, %08x @%06x", a&0xffffff, d, SekPcS68k);\r
982 \r
983   end:\r
984 \r
985 #ifdef __debug_io2\r
986   dprintf("s68k r32: %06x, %08x @%06x", a&0xffffff, d, SekPcS68k);\r
987 #endif\r
988   return d;\r
989 }\r
990 \r
991 \r
992 // -----------------------------------------------------------------\r
993 \r
994 void PicoWriteS68k8(u32 a,u8 d)\r
995 {\r
996 #ifdef __debug_io2\r
997   dprintf("s68k w8 : %06x,   %02x @%06x", a&0xffffff, d, SekPcS68k);\r
998 #endif\r
999 \r
1000   a&=0xffffff;\r
1001 \r
1002   // prg RAM\r
1003   if (a < 0x80000) {\r
1004     u8 *pm=(u8 *)(Pico_mcd->prg_ram+(a^1));\r
1005     *pm=d;\r
1006     return;\r
1007   }\r
1008 \r
1009   if (a != 0xff0011 && (a&0xff8000) == 0xff0000) // PCM hack\r
1010     return;\r
1011 \r
1012   // regs\r
1013   if ((a&0xfffe00) == 0xff8000) {\r
1014     a &= 0x1ff;\r
1015     rdprintf("s68k_regs w8: [%02x] %02x @ %06x", a, d, SekPcS68k);\r
1016     if (a >= 0x50 && a < 0x68)\r
1017          gfx_cd_write(a&~1, (d<<8)|d);\r
1018     else s68k_reg_write8(a,d);\r
1019     return;\r
1020   }\r
1021 \r
1022   // word RAM (2M area)\r
1023   if ((a&0xfc0000)==0x080000) { // 080000-0bffff\r
1024     dprintf("s68k_wram2M w8: [%06x] %02x @%06x", a, d, SekPc);\r
1025     if (Pico_mcd->s68k_regs[3]&4) { // 1M mode?\r
1026       // TODO (decode)\r
1027       dprintf("(decode)");\r
1028     } else {\r
1029       // allow access in any mode, like Gens does\r
1030       *(u8 *)(Pico_mcd->word_ram+((a^1)&0x3ffff))=d;\r
1031     }\r
1032     return;\r
1033   }\r
1034 \r
1035   // word RAM (1M area)\r
1036   if ((a&0xfe0000)==0x0c0000 && (Pico_mcd->s68k_regs[3]&4)) { // 0c0000-0dffff\r
1037     if (d)\r
1038       dprintf("s68k_wram1M w8: [%06x] %02x @%06x", a, d, SekPc);\r
1039     a=((a&0x1fffe)<<1)|(a&1);\r
1040     if (!(Pico_mcd->s68k_regs[3]&1)) a+=2;\r
1041     *(u8 *)(Pico_mcd->word_ram+(a^1))=d;\r
1042     return;\r
1043   }\r
1044 \r
1045   // bram\r
1046   if ((a&0xff0000)==0xfe0000) {\r
1047     Pico_mcd->bram[(a>>1)&0x1fff] = d;\r
1048     SRam.changed = 1;\r
1049     return;\r
1050   }\r
1051 \r
1052   dprintf("s68k w8 : %06x,   %02x @%06x", a&0xffffff, d, SekPcS68k);\r
1053 }\r
1054 \r
1055 \r
1056 void PicoWriteS68k16(u32 a,u16 d)\r
1057 {\r
1058 #ifdef __debug_io2\r
1059   dprintf("s68k w16: %06x, %04x @%06x", a&0xffffff, d, SekPcS68k);\r
1060 #endif\r
1061 \r
1062   a&=0xfffffe;\r
1063 \r
1064   // prg RAM\r
1065   if (a < 0x80000) {\r
1066     *(u16 *)(Pico_mcd->prg_ram+a)=d;\r
1067     return;\r
1068   }\r
1069 \r
1070   // regs\r
1071   if ((a&0xfffe00) == 0xff8000) {\r
1072     a &= 0x1fe;\r
1073     rdprintf("s68k_regs w16: [%02x] %04x @ %06x", a, d, SekPcS68k);\r
1074     if (a >= 0x50 && a < 0x68)\r
1075       gfx_cd_write(a, d);\r
1076     else {\r
1077       s68k_reg_write8(a,  d>>8);\r
1078       s68k_reg_write8(a+1,d&0xff);\r
1079     }\r
1080     return;\r
1081   }\r
1082 \r
1083   // word RAM (2M area)\r
1084   if ((a&0xfc0000)==0x080000) { // 080000-0bffff\r
1085     dprintf("s68k_wram2M w16: [%06x] %04x @%06x", a, d, SekPc);\r
1086     if (Pico_mcd->s68k_regs[3]&4) { // 1M mode?\r
1087       // TODO (decode)\r
1088       dprintf("(decode)");\r
1089     } else {\r
1090       // allow access in any mode, like Gens does\r
1091       *(u16 *)(Pico_mcd->word_ram+(a&0x3fffe))=d;\r
1092     }\r
1093     return;\r
1094   }\r
1095 \r
1096   // word RAM (1M area)\r
1097   if ((a&0xfe0000)==0x0c0000 && (Pico_mcd->s68k_regs[3]&4)) { // 0c0000-0dffff\r
1098     if (d)\r
1099       dprintf("s68k_wram1M w16: [%06x] %04x @%06x", a, d, SekPc);\r
1100     a=((a&0x1fffe)<<1);\r
1101     if (!(Pico_mcd->s68k_regs[3]&1)) a+=2;\r
1102     *(u16 *)(Pico_mcd->word_ram+a)=d;\r
1103     return;\r
1104   }\r
1105 \r
1106   // bram\r
1107   if ((a&0xff0000)==0xfe0000) {\r
1108     dprintf("s68k_bram w16: [%06x] %04x @%06x", a, d, SekPc);\r
1109     a = (a>>1)&0x1fff;\r
1110     Pico_mcd->bram[a++] = d;            // Gens does little endian here, an so do we..\r
1111     Pico_mcd->bram[a++] = d >> 8;\r
1112     SRam.changed = 1;\r
1113     return;\r
1114   }\r
1115 \r
1116   dprintf("s68k w16: %06x, %04x @%06x", a&0xffffff, d, SekPcS68k);\r
1117 }\r
1118 \r
1119 \r
1120 void PicoWriteS68k32(u32 a,u32 d)\r
1121 {\r
1122 #ifdef __debug_io2\r
1123   dprintf("s68k w32: %06x, %08x @%06x", a&0xffffff, d, SekPcS68k);\r
1124 #endif\r
1125 \r
1126   a&=0xfffffe;\r
1127 \r
1128   // prg RAM\r
1129   if (a < 0x80000) {\r
1130     u16 *pm=(u16 *)(Pico_mcd->prg_ram+a);\r
1131     pm[0]=(u16)(d>>16); pm[1]=(u16)d;\r
1132     return;\r
1133   }\r
1134 \r
1135   // regs\r
1136   if ((a&0xfffe00) == 0xff8000) {\r
1137     a &= 0x1fe;\r
1138     rdprintf("s68k_regs w32: [%02x] %08x @ %06x", a, d, SekPcS68k);\r
1139     if (a >= 0x50 && a < 0x68) {\r
1140       gfx_cd_write(a,   d>>16);\r
1141       gfx_cd_write(a+2, d&0xffff);\r
1142     } else {\r
1143       s68k_reg_write8(a,   d>>24);\r
1144       s68k_reg_write8(a+1,(d>>16)&0xff);\r
1145       s68k_reg_write8(a+2,(d>>8) &0xff);\r
1146       s68k_reg_write8(a+3, d     &0xff);\r
1147     }\r
1148     return;\r
1149   }\r
1150 \r
1151   // word RAM (2M area)\r
1152   if ((a&0xfc0000)==0x080000) { // 080000-0bffff\r
1153     dprintf("s68k_wram2M w32: [%06x] %08x @%06x", a, d, SekPc);\r
1154     if (Pico_mcd->s68k_regs[3]&4) { // 1M mode?\r
1155       // TODO (decode)\r
1156       dprintf("(decode)");\r
1157     } else {\r
1158       // allow access in any mode, like Gens does\r
1159       u16 *pm=(u16 *)(Pico_mcd->word_ram+(a&0x3fffe));\r
1160       pm[0]=(u16)(d>>16); pm[1]=(u16)d;\r
1161     }\r
1162     return;\r
1163   }\r
1164 \r
1165   // word RAM (1M area)\r
1166   if ((a&0xfe0000)==0x0c0000 && (Pico_mcd->s68k_regs[3]&4)) { // 0c0000-0dffff\r
1167     if (d)\r
1168       dprintf("s68k_wram1M w32: [%06x] %08x @%06x", a, d, SekPc);\r
1169     a=((a&0x1fffe)<<1);\r
1170     if (!(Pico_mcd->s68k_regs[3]&1)) a+=2;\r
1171     *(u16 *)(Pico_mcd->word_ram+a) = d>>16;\r
1172     *(u16 *)(Pico_mcd->word_ram+a+4) = d;\r
1173     return;\r
1174   }\r
1175 \r
1176   // bram\r
1177   if ((a&0xff0000)==0xfe0000) {\r
1178     dprintf("s68k_bram w32: [%06x] %08x @%06x", a, d, SekPc);\r
1179     a = (a>>1)&0x1fff;\r
1180     Pico_mcd->bram[a++] = d >> 16;              // middle endian? verify?\r
1181     Pico_mcd->bram[a++] = d >> 24;\r
1182     Pico_mcd->bram[a++] = d;\r
1183     Pico_mcd->bram[a++] = d >> 8;\r
1184     SRam.changed = 1;\r
1185     return;\r
1186   }\r
1187 \r
1188   dprintf("s68k w32: %06x, %08x @%06x", a&0xffffff, d, SekPcS68k);\r
1189 }\r
1190 \r
1191 \r
1192 \r
1193 // -----------------------------------------------------------------\r
1194 \r
1195 \r
1196 #if defined(EMU_C68K)\r
1197 static __inline int PicoMemBaseM68k(u32 pc)\r
1198 {\r
1199   int membase=0;\r
1200 \r
1201   if (pc < 0x20000)\r
1202   {\r
1203     membase=(int)Pico_mcd->bios; // Program Counter in BIOS\r
1204   }\r
1205   else if ((pc&0xe00000)==0xe00000)\r
1206   {\r
1207     membase=(int)Pico.ram-(pc&0xff0000); // Program Counter in Ram\r
1208   }\r
1209   else if ((pc&0xfc0000)==0x200000 && !(Pico_mcd->s68k_regs[3]&4))\r
1210   {\r
1211     membase=(int)Pico_mcd->word_ram-0x200000; // Program Counter in Word Ram\r
1212   }\r
1213   else\r
1214   {\r
1215     // Error - Program Counter is invalid\r
1216     dprintf("m68k: unhandled jump to %06x", pc);\r
1217     membase=(int)Pico.rom;\r
1218   }\r
1219 \r
1220   return membase;\r
1221 }\r
1222 \r
1223 \r
1224 static u32 PicoCheckPcM68k(u32 pc)\r
1225 {\r
1226   pc-=PicoCpu.membase; // Get real pc\r
1227   pc&=0xfffffe;\r
1228 \r
1229   PicoCpu.membase=PicoMemBaseM68k(pc);\r
1230 \r
1231   return PicoCpu.membase+pc;\r
1232 }\r
1233 \r
1234 \r
1235 static __inline int PicoMemBaseS68k(u32 pc)\r
1236 {\r
1237   int membase;\r
1238 \r
1239   membase=(int)Pico_mcd->prg_ram; // Program Counter in Prg RAM\r
1240   if (pc >= 0x80000)\r
1241   {\r
1242     // Error - Program Counter is invalid\r
1243     dprintf("s68k: unhandled jump to %06x", pc);\r
1244   }\r
1245 \r
1246   return membase;\r
1247 }\r
1248 \r
1249 \r
1250 static u32 PicoCheckPcS68k(u32 pc)\r
1251 {\r
1252   pc-=PicoCpuS68k.membase; // Get real pc\r
1253   pc&=0xfffffe;\r
1254 \r
1255   PicoCpuS68k.membase=PicoMemBaseS68k(pc);\r
1256 \r
1257   return PicoCpuS68k.membase+pc;\r
1258 }\r
1259 #endif\r
1260 \r
1261 \r
1262 void PicoMemSetupCD()\r
1263 {\r
1264   dprintf("PicoMemSetupCD()");\r
1265 #ifdef EMU_C68K\r
1266   // Setup m68k memory callbacks:\r
1267   PicoCpu.checkpc=PicoCheckPcM68k;\r
1268   PicoCpu.fetch8 =PicoCpu.read8 =PicoReadM68k8;\r
1269   PicoCpu.fetch16=PicoCpu.read16=PicoReadM68k16;\r
1270   PicoCpu.fetch32=PicoCpu.read32=PicoReadM68k32;\r
1271   PicoCpu.write8 =PicoWriteM68k8;\r
1272   PicoCpu.write16=PicoWriteM68k16;\r
1273   PicoCpu.write32=PicoWriteM68k32;\r
1274   // s68k\r
1275   PicoCpuS68k.checkpc=PicoCheckPcS68k;\r
1276   PicoCpuS68k.fetch8 =PicoCpuS68k.read8 =PicoReadS68k8;\r
1277   PicoCpuS68k.fetch16=PicoCpuS68k.read16=PicoReadS68k16;\r
1278   PicoCpuS68k.fetch32=PicoCpuS68k.read32=PicoReadS68k32;\r
1279   PicoCpuS68k.write8 =PicoWriteS68k8;\r
1280   PicoCpuS68k.write16=PicoWriteS68k16;\r
1281   PicoCpuS68k.write32=PicoWriteS68k32;\r
1282 #endif\r
1283 }\r
1284 \r
1285 \r
1286 #ifdef EMU_M68K\r
1287 unsigned char  PicoReadCD8w (unsigned int a) {\r
1288         return m68ki_cpu_p == &PicoS68kCPU ? PicoReadS68k8(a) : PicoReadM68k8(a);\r
1289 }\r
1290 unsigned short PicoReadCD16w(unsigned int a) {\r
1291         return m68ki_cpu_p == &PicoS68kCPU ? PicoReadS68k16(a) : PicoReadM68k16(a);\r
1292 }\r
1293 unsigned int   PicoReadCD32w(unsigned int a) {\r
1294         return m68ki_cpu_p == &PicoS68kCPU ? PicoReadS68k32(a) : PicoReadM68k32(a);\r
1295 }\r
1296 void PicoWriteCD8w (unsigned int a, unsigned char d) {\r
1297         if (m68ki_cpu_p == &PicoS68kCPU) PicoWriteS68k8(a, d); else PicoWriteM68k8(a, d);\r
1298 }\r
1299 void PicoWriteCD16w(unsigned int a, unsigned short d) {\r
1300         if (m68ki_cpu_p == &PicoS68kCPU) PicoWriteS68k16(a, d); else PicoWriteM68k16(a, d);\r
1301 }\r
1302 void PicoWriteCD32w(unsigned int a, unsigned int d) {\r
1303         if (m68ki_cpu_p == &PicoS68kCPU) PicoWriteS68k32(a, d); else PicoWriteM68k32(a, d);\r
1304 }\r
1305 \r
1306 // these are allowed to access RAM\r
1307 unsigned int  m68k_read_pcrelative_CD8 (unsigned int a) {\r
1308   a&=0xffffff;\r
1309   if(m68ki_cpu_p == &PicoS68kCPU) {\r
1310     if (a < 0x80000) return *(u8 *)(Pico_mcd->prg_ram+(a^1)); // PRG Ram\r
1311     dprintf("s68k_read_pcrelative_CD8: can't handle %06x", a);\r
1312   } else {\r
1313     if(a<0x20000)              return *(u8 *)(Pico.rom+(a^1)); // Bios\r
1314     if((a&0xe00000)==0xe00000) return *(u8 *)(Pico.ram+((a^1)&0xffff)); // Ram\r
1315     if(!(Pico_mcd->s68k_regs[3]&4) && (a&0xfc0000)==0x200000)\r
1316       return Pico_mcd->word_ram[(a^1)&0x3fffe];\r
1317     dprintf("m68k_read_pcrelative_CD8: can't handle %06x", a);\r
1318   }\r
1319   return 0;//(u8)  lastread_d;\r
1320 }\r
1321 unsigned int  m68k_read_pcrelative_CD16(unsigned int a) {\r
1322   a&=0xffffff;\r
1323   if(m68ki_cpu_p == &PicoS68kCPU) {\r
1324     if (a < 0x80000) return *(u16 *)(Pico_mcd->prg_ram+(a&~1)); // PRG Ram\r
1325     dprintf("s68k_read_pcrelative_CD16: can't handle %06x", a);\r
1326   } else {\r
1327     if(a<0x20000)              return *(u16 *)(Pico.rom+(a&~1)); // Bios\r
1328     if((a&0xe00000)==0xe00000) return *(u16 *)(Pico.ram+(a&0xfffe)); // Ram\r
1329     if(!(Pico_mcd->s68k_regs[3]&4) && (a&0xfc0000)==0x200000)\r
1330       return *(u16 *)(Pico_mcd->word_ram+(a&0x3fffe));\r
1331     dprintf("m68k_read_pcrelative_CD16: can't handle %06x", a);\r
1332   }\r
1333   return 0;\r
1334 }\r
1335 unsigned int  m68k_read_pcrelative_CD32(unsigned int a) {\r
1336   a&=0xffffff;\r
1337   if(m68ki_cpu_p == &PicoS68kCPU) {\r
1338     if (a < 0x80000) { u16 *pm=(u16 *)(Pico_mcd->prg_ram+(a&~1)); return (pm[0]<<16)|pm[1]; } // PRG Ram\r
1339     dprintf("s68k_read_pcrelative_CD32: can't handle %06x", a);\r
1340   } else {\r
1341     if(a<0x20000)              { u16 *pm=(u16 *)(Pico.rom+(a&~1));     return (pm[0]<<16)|pm[1]; }\r
1342     if((a&0xe00000)==0xe00000) { u16 *pm=(u16 *)(Pico.ram+(a&0xfffe)); return (pm[0]<<16)|pm[1]; } // Ram\r
1343     if(!(Pico_mcd->s68k_regs[3]&4) && (a&0xfc0000)==0x200000)\r
1344       { u16 *pm=(u16 *)(Pico_mcd->word_ram+(a&0x3fffe)); return (pm[0]<<16)|pm[1]; }\r
1345     dprintf("m68k_read_pcrelative_CD32: can't handle %06x", a);\r
1346   }\r
1347   return 0;\r
1348 }\r
1349 #endif // EMU_M68K\r
1350 \r