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