mcd: text shows up
[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 & 2) d &= ~1; // returning word RAM to s68k\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       d |= Pico_mcd->s68k_regs[3]&0xc2;\r
183       if (d&1) d &= ~2; // returning word RAM to m68k\r
184       break;\r
185     case 4:\r
186       dprintf("s68k CDC dest: %x", d&7);\r
187       Pico_mcd->s68k_regs[4] = (Pico_mcd->s68k_regs[4]&0xC0) | (d&7); // CDC mode\r
188       return;\r
189     case 5:\r
190       dprintf("s68k CDC reg addr: %x", d&0xf);\r
191       break;\r
192     case 7:\r
193       CDC_Write_Reg(d);\r
194       return;\r
195     case 0xa:\r
196       dprintf("s68k set CDC dma addr");\r
197       break;\r
198     case 0x33: // IRQ mask\r
199       dprintf("s68k irq mask: %02x", d);\r
200       if ((d&(1<<4)) && (Pico_mcd->s68k_regs[0x37]&4) && !(Pico_mcd->s68k_regs[0x33]&(1<<4))) {\r
201         CDD_Export_Status();\r
202         // counter75hz = 0; // ???\r
203       }\r
204       break;\r
205     case 0x34: // fader\r
206       Pico_mcd->s68k_regs[a] = (u8) d & 0x7f;\r
207       return;\r
208     case 0x36:\r
209       return; // d/m bit is unsetable\r
210     case 0x37: {\r
211       u32 d_old = Pico_mcd->s68k_regs[0x37];\r
212       Pico_mcd->s68k_regs[0x37] = d&7;\r
213       if ((d&4) && !(d_old&4)) {\r
214         CDD_Export_Status();\r
215         // counter75hz = 0; // ???\r
216       }\r
217       return;\r
218     }\r
219     case 0x4b:\r
220       Pico_mcd->s68k_regs[a] = (u8) d;\r
221       CDD_Import_Command();\r
222       return;\r
223   }\r
224 \r
225   if ((a&0x1f0) == 0x10 || a == 0x0e || (a >= 0x38 && a < 0x42))\r
226   {\r
227     dprintf("m68k: invalid write @ %02x?", a);\r
228     return;\r
229   }\r
230 \r
231   Pico_mcd->s68k_regs[a] = (u8) d;\r
232 }\r
233 \r
234 \r
235 \r
236 \r
237 \r
238 static int PadRead(int i)\r
239 {\r
240   int pad=0,value=0,TH;\r
241   pad=~PicoPad[i]; // Get inverse of pad MXYZ SACB RLDU\r
242   TH=Pico.ioports[i+1]&0x40;\r
243 \r
244   if(PicoOpt & 0x20) { // 6 button gamepad enabled\r
245     int phase = Pico.m.padTHPhase[i];\r
246 \r
247     if(phase == 2 && !TH) {\r
248       value=(pad&0xc0)>>2;              // ?0SA 0000\r
249       goto end;\r
250     } else if(phase == 3 && TH) {\r
251       value=(pad&0x30)|((pad>>8)&0xf);  // ?1CB MXYZ\r
252       goto end;\r
253     } else if(phase == 3 && !TH) {\r
254       value=((pad&0xc0)>>2)|0x0f;       // ?0SA 1111\r
255       goto end;\r
256     }\r
257   }\r
258 \r
259   if(TH) value=(pad&0x3f);              // ?1CB RLDU\r
260   else   value=((pad&0xc0)>>2)|(pad&3); // ?0SA 00DU\r
261 \r
262   end:\r
263 \r
264   // orr the bits, which are set as output\r
265   value |= Pico.ioports[i+1]&Pico.ioports[i+4];\r
266 \r
267   return value; // will mirror later\r
268 }\r
269 \r
270 static u8 z80Read8(u32 a)\r
271 {\r
272   if(Pico.m.z80Run&1) return 0;\r
273 \r
274   a&=0x1fff;\r
275 \r
276   if(!(PicoOpt&4)) {\r
277     // Z80 disabled, do some faking\r
278     static u8 zerosent = 0;\r
279     if(a == Pico.m.z80_lastaddr) { // probably polling something\r
280       u8 d = Pico.m.z80_fakeval;\r
281       if((d & 0xf) == 0xf && !zerosent) {\r
282         d = 0; zerosent = 1;\r
283       } else {\r
284         Pico.m.z80_fakeval++;\r
285         zerosent = 0;\r
286       }\r
287       return d;\r
288     } else {\r
289       Pico.m.z80_fakeval = 0;\r
290     }\r
291   }\r
292 \r
293   Pico.m.z80_lastaddr = (u16) a;\r
294   return Pico.zram[a];\r
295 }\r
296 \r
297 \r
298 // for nonstandard reads\r
299 static u32 UnusualRead16(u32 a, int realsize)\r
300 {\r
301   u32 d=0;\r
302 \r
303   dprintf("unusual r%i: %06x @%06x", realsize&~1, (a&0xfffffe)+(realsize&1), SekPc);\r
304 \r
305 \r
306   dprintf("ret = %04x", d);\r
307   return d;\r
308 }\r
309 \r
310 static u32 OtherRead16(u32 a, int realsize)\r
311 {\r
312   u32 d=0;\r
313 \r
314   if ((a&0xff0000)==0xa00000) {\r
315     if ((a&0x4000)==0x0000) { d=z80Read8(a); d|=d<<8; goto end; } // Z80 ram (not byteswaped)\r
316     if ((a&0x6000)==0x4000) { if(PicoOpt&1) d=YM2612Read(); else d=Pico.m.rotate++&3; goto end; } // 0x4000-0x5fff, Fudge if disabled\r
317         d=0xffff; goto end;\r
318   }\r
319   if ((a&0xffffe0)==0xa10000) { // I/O ports\r
320     a=(a>>1)&0xf;\r
321     switch(a) {\r
322       case 0:  d=Pico.m.hardware; break; // Hardware value (Version register)\r
323       case 1:  d=PadRead(0); d|=Pico.ioports[1]&0x80; break;\r
324       case 2:  d=PadRead(1); d|=Pico.ioports[2]&0x80; break;\r
325       default: d=Pico.ioports[a]; break; // IO ports can be used as RAM\r
326     }\r
327     d|=d<<8;\r
328     goto end;\r
329   }\r
330   // |=0x80 for Shadow of the Beast & Super Offroad; rotate fakes next fetched instruction for Time Killers\r
331   if (a==0xa11100) { d=((Pico.m.z80Run&1)<<8)|0x8000|Pico.m.rotate++; goto end; }\r
332 \r
333   if ((a&0xe700e0)==0xc00000) { d=PicoVideoRead(a); goto end; }\r
334 \r
335   if ((a&0xffffc0)==0xa12000) {\r
336     d=m68k_reg_read16(a, realsize);\r
337     goto end;\r
338   }\r
339 \r
340   d = UnusualRead16(a, realsize);\r
341 \r
342 end:\r
343   return d;\r
344 }\r
345 \r
346 //extern UINT32 mz80GetRegisterValue(void *, UINT32);\r
347 \r
348 static void OtherWrite8(u32 a,u32 d,int realsize)\r
349 {\r
350   if ((a&0xe700f9)==0xc00011||(a&0xff7ff9)==0xa07f11) { if(PicoOpt&2) SN76496Write(d); return; } // PSG Sound\r
351   if ((a&0xff4000)==0xa00000)  { if(!(Pico.m.z80Run&1)) Pico.zram[a&0x1fff]=(u8)d; return; } // Z80 ram\r
352   if ((a&0xff6000)==0xa04000)  { if(PicoOpt&1) emustatus|=YM2612Write(a&3, d); return; } // FM Sound\r
353   if ((a&0xffffe0)==0xa10000)  { // I/O ports\r
354     a=(a>>1)&0xf;\r
355     // 6 button gamepad: if TH went from 0 to 1, gamepad changes state\r
356     if(PicoOpt&0x20) {\r
357       if(a==1) {\r
358         Pico.m.padDelay[0] = 0;\r
359         if(!(Pico.ioports[1]&0x40) && (d&0x40)) Pico.m.padTHPhase[0]++;\r
360       }\r
361       else if(a==2) {\r
362         Pico.m.padDelay[1] = 0;\r
363         if(!(Pico.ioports[2]&0x40) && (d&0x40)) Pico.m.padTHPhase[1]++;\r
364       }\r
365     }\r
366     Pico.ioports[a]=(u8)d; // IO ports can be used as RAM\r
367     return;\r
368   }\r
369   if (a==0xa11100) {\r
370     extern int z80startCycle, z80stopCycle;\r
371     //int lineCycles=(488-SekCyclesLeft)&0x1ff;\r
372     d&=1; d^=1;\r
373         if(!d) {\r
374           // hack: detect a nasty situation where Z80 was enabled and disabled in the same 68k timeslice (Golden Axe III)\r
375       if((PicoOpt&4) && Pico.m.z80Run==1) z80_run(20);\r
376           z80stopCycle = SekCyclesDone();\r
377           //z80ExtraCycles += (lineCycles>>1)-(lineCycles>>5); // only meaningful in PicoFrameHints()\r
378         } else {\r
379           z80startCycle = SekCyclesDone();\r
380           //if(Pico.m.scanline != -1)\r
381           //z80ExtraCycles -= (lineCycles>>1)-(lineCycles>>5)+16;\r
382         }\r
383     //dprintf("set_zrun: %i [%i|%i] zPC=%04x @%06x", d, Pico.m.scanline, SekCyclesDone(), mz80GetRegisterValue(NULL, 0), SekPc);\r
384         Pico.m.z80Run=(u8)d; return;\r
385   }\r
386   if (a==0xa11200) { if(!(d&1)) z80_reset(); return; }\r
387 \r
388   if ((a&0xff7f00)==0xa06000) // Z80 BANK register\r
389   {\r
390     Pico.m.z80_bank68k>>=1;\r
391     Pico.m.z80_bank68k|=(d&1)<<8;\r
392     Pico.m.z80_bank68k&=0x1ff; // 9 bits and filled in the new top one\r
393     return;\r
394   }\r
395 \r
396   if ((a&0xe700e0)==0xc00000) { PicoVideoWrite(a,(u16)(d|(d<<8))); return; } // Byte access gets mirrored\r
397 \r
398   if ((a&0xffffc0)==0xa12000) { m68k_reg_write8(a, d, realsize); return; }\r
399 \r
400   dprintf("strange w%i: %06x, %08x @%06x", realsize, a&0xffffff, d, SekPc);\r
401 }\r
402 \r
403 static void OtherWrite16(u32 a,u32 d)\r
404 {\r
405   if ((a&0xe700e0)==0xc00000) { PicoVideoWrite(a,(u16)d); return; }\r
406   if ((a&0xff4000)==0xa00000) { if(!(Pico.m.z80Run&1)) Pico.zram[a&0x1fff]=(u8)(d>>8); return; } // Z80 ram (MSB only)\r
407 \r
408   if ((a&0xffffe0)==0xa10000) { // I/O ports\r
409     a=(a>>1)&0xf;\r
410     // 6 button gamepad: if TH went from 0 to 1, gamepad changes state\r
411     if(PicoOpt&0x20) {\r
412       if(a==1) {\r
413         Pico.m.padDelay[0] = 0;\r
414         if(!(Pico.ioports[1]&0x40) && (d&0x40)) Pico.m.padTHPhase[0]++;\r
415       }\r
416       else if(a==2) {\r
417         Pico.m.padDelay[1] = 0;\r
418         if(!(Pico.ioports[2]&0x40) && (d&0x40)) Pico.m.padTHPhase[1]++;\r
419       }\r
420     }\r
421     Pico.ioports[a]=(u8)d; // IO ports can be used as RAM\r
422     return;\r
423   }\r
424   if (a==0xa11100) { OtherWrite8(a, d>>8, 16); return; }\r
425   if (a==0xa11200) { if(!(d&0x100)) z80_reset(); return; }\r
426 \r
427   OtherWrite8(a,  d>>8, 16);\r
428   OtherWrite8(a+1,d&0xff, 16);\r
429 }\r
430 \r
431 // -----------------------------------------------------------------\r
432 //                     Read Rom and read Ram\r
433 \r
434 u8 PicoReadM68k8(u32 a)\r
435 {\r
436   u32 d=0;\r
437 \r
438   if ((a&0xe00000)==0xe00000) { d = *(u8 *)(Pico.ram+((a^1)&0xffff)); goto end; } // Ram\r
439 \r
440   a&=0xffffff;\r
441 \r
442   if (a < 0x20000) { d = *(u8 *)(Pico_mcd->bios+(a^1)); goto end; } // bios\r
443 \r
444   // prg RAM\r
445   if ((a&0xfe0000)==0x020000) {\r
446     u8 *prg_bank = Pico_mcd->prg_ram_b[Pico_mcd->s68k_regs[3]>>6];\r
447     d = *(prg_bank+((a^1)&0x1ffff));\r
448     goto end;\r
449   }\r
450 \r
451   if ((a&0xff4000)==0xa00000) { d=z80Read8(a); goto end; } // Z80 Ram\r
452 \r
453   if ((a&0xffffc0)==0xa12000)\r
454     dprintf("m68k_regs r8: [%02x] @%06x", a&0x3f, SekPc);\r
455 \r
456   d=OtherRead16(a&~1, 8|(a&1)); if ((a&1)==0) d>>=8;\r
457 \r
458   if ((a&0xffffc0)==0xa12000)\r
459     dprintf("ret = %02x", (u8)d);\r
460 \r
461   end:\r
462 \r
463 #ifdef __debug_io\r
464   dprintf("r8 : %06x,   %02x @%06x", a&0xffffff, (u8)d, SekPc);\r
465 #endif\r
466   return (u8)d;\r
467 }\r
468 \r
469 u16 PicoReadM68k16(u32 a)\r
470 {\r
471   u16 d=0;\r
472 \r
473   if ((a&0xe00000)==0xe00000) { d=*(u16 *)(Pico.ram+(a&0xfffe)); goto end; } // Ram\r
474 \r
475   a&=0xfffffe;\r
476 \r
477   if (a < 0x20000) { d = *(u16 *)(Pico_mcd->bios+a); goto end; } // bios\r
478 \r
479   // prg RAM\r
480   if ((a&0xfe0000)==0x020000) {\r
481     u8 *prg_bank = Pico_mcd->prg_ram_b[Pico_mcd->s68k_regs[3]>>6];\r
482     d = *(u16 *)(prg_bank+(a&0x1fffe));\r
483     goto end;\r
484   }\r
485 \r
486   if ((a&0xffffc0)==0xa12000)\r
487     dprintf("m68k_regs r16: [%02x] @%06x", a&0x3f, SekPc);\r
488 \r
489   d = (u16)OtherRead16(a, 16);\r
490 \r
491   if ((a&0xffffc0)==0xa12000)\r
492     dprintf("ret = %04x", d);\r
493 \r
494   end:\r
495 \r
496 #ifdef __debug_io\r
497   dprintf("r16: %06x, %04x  @%06x", a&0xffffff, d, SekPc);\r
498 #endif\r
499   return d;\r
500 }\r
501 \r
502 u32 PicoReadM68k32(u32 a)\r
503 {\r
504   u32 d=0;\r
505 \r
506   if ((a&0xe00000)==0xe00000) { u16 *pm=(u16 *)(Pico.ram+(a&0xfffe)); d = (pm[0]<<16)|pm[1]; goto end; } // Ram\r
507 \r
508   a&=0xfffffe;\r
509 \r
510   if (a < 0x20000) { u16 *pm=(u16 *)(Pico_mcd->bios+a); d = (pm[0]<<16)|pm[1]; goto end; } // bios\r
511 \r
512   // prg RAM\r
513   if ((a&0xfe0000)==0x020000) {\r
514     u8 *prg_bank = Pico_mcd->prg_ram_b[Pico_mcd->s68k_regs[3]>>6];\r
515     u16 *pm=(u16 *)(prg_bank+(a&0x1fffe));\r
516     d = (pm[0]<<16)|pm[1];\r
517     goto end;\r
518   }\r
519 \r
520   if ((a&0xffffc0)==0xa12000)\r
521     dprintf("m68k_regs r32: [%02x] @%06x", a&0x3f, SekPc);\r
522 \r
523   d = (OtherRead16(a, 32)<<16)|OtherRead16(a+2, 32);\r
524 \r
525   if ((a&0xffffc0)==0xa12000)\r
526     dprintf("ret = %08x", d);\r
527 \r
528   end:\r
529 #ifdef __debug_io\r
530   dprintf("r32: %06x, %08x @%06x", a&0xffffff, d, SekPc);\r
531 #endif\r
532   return d;\r
533 }\r
534 \r
535 // -----------------------------------------------------------------\r
536 //                            Write Ram\r
537 \r
538 void PicoWriteM68k8(u32 a,u8 d)\r
539 {\r
540 #ifdef __debug_io\r
541   dprintf("w8 : %06x,   %02x @%06x", a&0xffffff, d, SekPc);\r
542 #endif\r
543   //if ((a&0xe0ffff)==0xe0a9ba+0x69c)\r
544   //  dprintf("w8 : %06x,   %02x @%06x", a&0xffffff, d, SekPc);\r
545 \r
546 \r
547   if ((a&0xe00000)==0xe00000) { u8 *pm=(u8 *)(Pico.ram+((a^1)&0xffff)); pm[0]=d; return; } // Ram\r
548 \r
549   a&=0xffffff;\r
550 \r
551   // prg RAM\r
552   if ((a&0xfe0000)==0x020000) {\r
553     u8 *prg_bank = Pico_mcd->prg_ram_b[Pico_mcd->s68k_regs[3]>>6];\r
554     u8 *pm=(u8 *)(prg_bank+((a^1)&0x1ffff));\r
555     *pm=d;\r
556     return;\r
557   }\r
558 \r
559   if ((a&0xffffc0)==0xa12000)\r
560     dprintf("m68k_regs w8: [%02x] %02x @%06x", a&0x3f, d, SekPc);\r
561 \r
562   OtherWrite8(a,d,8);\r
563 }\r
564 \r
565 void PicoWriteM68k16(u32 a,u16 d)\r
566 {\r
567 #ifdef __debug_io\r
568   dprintf("w16: %06x, %04x", a&0xffffff, d);\r
569 #endif\r
570   //if ((a&0xe0ffff)==0xe0AF0E+0x69c||(a&0xe0ffff)==0xe0A9A8+0x69c||(a&0xe0ffff)==0xe0A9AA+0x69c||(a&0xe0ffff)==0xe0A9AC+0x69c)\r
571   //  dprintf("w16: %06x, %04x  @%06x", a&0xffffff, d, SekPc);\r
572 \r
573   if ((a&0xe00000)==0xe00000) { *(u16 *)(Pico.ram+(a&0xfffe))=d; return; } // Ram\r
574 \r
575   a&=0xfffffe;\r
576 \r
577   // prg RAM\r
578   if ((a&0xfe0000)==0x020000) {\r
579     u8 *prg_bank = Pico_mcd->prg_ram_b[Pico_mcd->s68k_regs[3]>>6];\r
580     *(u16 *)(prg_bank+(a&0x1fffe))=d;\r
581     return;\r
582   }\r
583 \r
584   if ((a&0xffffc0)==0xa12000)\r
585     dprintf("m68k_regs w16: [%02x] %04x @%06x", a&0x3f, d, SekPc);\r
586 \r
587   OtherWrite16(a,d);\r
588 }\r
589 \r
590 void PicoWriteM68k32(u32 a,u32 d)\r
591 {\r
592 #ifdef __debug_io\r
593   dprintf("w32: %06x, %08x", a&0xffffff, d);\r
594 #endif\r
595 \r
596   if ((a&0xe00000)==0xe00000)\r
597   {\r
598     // Ram:\r
599     u16 *pm=(u16 *)(Pico.ram+(a&0xfffe));\r
600     pm[0]=(u16)(d>>16); pm[1]=(u16)d;\r
601     return;\r
602   }\r
603 \r
604   a&=0xfffffe;\r
605 \r
606   // prg RAM\r
607   if ((a&0xfe0000)==0x020000) {\r
608     u8 *prg_bank = Pico_mcd->prg_ram_b[Pico_mcd->s68k_regs[3]>>6];\r
609     u16 *pm=(u16 *)(prg_bank+(a&0x1fffe));\r
610     pm[0]=(u16)(d>>16); pm[1]=(u16)d;\r
611     return;\r
612   }\r
613 \r
614   // word RAM\r
615   if (a!=0x200000 && (a&0xfc0000)==0x200000) // tmp hack\r
616     return;\r
617 \r
618 \r
619   if ((a&0xffffc0)==0xa12000)\r
620     dprintf("m68k_regs w32: [%02x] %08x @%06x", a&0x3f, d, SekPc);\r
621 \r
622   OtherWrite16(a,  (u16)(d>>16));\r
623   OtherWrite16(a+2,(u16)d);\r
624 }\r
625 \r
626 \r
627 // -----------------------------------------------------------------\r
628 \r
629 \r
630 u8 PicoReadS68k8(u32 a)\r
631 {\r
632   u32 d=0;\r
633 \r
634   a&=0xffffff;\r
635 \r
636   // prg RAM\r
637   if (a < 0x80000) {\r
638     d = *(Pico_mcd->prg_ram+(a^1));\r
639     goto end;\r
640   }\r
641 \r
642   // regs\r
643   if ((a&0xfffe00) == 0xff8000) {\r
644     dprintf("s68k_regs r8: [%02x] @ %06x", a&0x1ff, SekPcS68k);\r
645     d = s68k_reg_read16(a&~1, 8|(a&1)); if ((a&1)==0) d>>=8;\r
646     dprintf("ret = %02x", (u8)d);\r
647     goto end;\r
648   }\r
649 \r
650   dprintf("s68k r8 : %06x,   %02x @%06x", a&0xffffff, (u8)d, SekPcS68k);\r
651 \r
652   end:\r
653 \r
654 #ifdef __debug_io2\r
655   dprintf("s68k r8 : %06x,   %02x @%06x", a&0xffffff, (u8)d, SekPcS68k);\r
656 #endif\r
657   return (u8)d;\r
658 }\r
659 \r
660 u16 PicoReadS68k16(u32 a)\r
661 {\r
662   u16 d=0;\r
663 \r
664   a&=0xfffffe;\r
665 \r
666   // prg RAM\r
667   if (a < 0x80000) {\r
668     d = *(u16 *)(Pico_mcd->prg_ram+a);\r
669     goto end;\r
670   }\r
671 \r
672   // regs\r
673   if ((a&0xfffe00) == 0xff8000) {\r
674     dprintf("s68k_regs r16: [%02x] @ %06x", a&0x1fe, SekPcS68k);\r
675     d = s68k_reg_read16(a, 16);\r
676     dprintf("ret = %04x", d);\r
677     goto end;\r
678   }\r
679 \r
680   dprintf("s68k r16: %06x, %04x  @%06x", a&0xffffff, d, SekPcS68k);\r
681 \r
682   end:\r
683 \r
684 #ifdef __debug_io2\r
685   dprintf("s68k r16: %06x, %04x  @%06x", a&0xffffff, d, SekPcS68k);\r
686 #endif\r
687   return d;\r
688 }\r
689 \r
690 u32 PicoReadS68k32(u32 a)\r
691 {\r
692   u32 d=0;\r
693 \r
694   a&=0xfffffe;\r
695 \r
696   // prg RAM\r
697   if (a < 0x80000) {\r
698     u16 *pm=(u16 *)(Pico_mcd->prg_ram+a);\r
699     d = (pm[0]<<16)|pm[1];\r
700     goto end;\r
701   }\r
702 \r
703   // regs\r
704   if ((a&0xfffe00) == 0xff8000) {\r
705     dprintf("s68k_regs r32: [%02x] @ %06x", a&0x1fe, SekPcS68k);\r
706     d = (s68k_reg_read16(a, 32)<<16)|s68k_reg_read16(a+2, 32);\r
707     dprintf("ret = %08x", d);\r
708     goto end;\r
709   }\r
710 \r
711   dprintf("s68k r32: %06x, %08x @%06x", a&0xffffff, d, SekPcS68k);\r
712 \r
713   end:\r
714 \r
715 #ifdef __debug_io2\r
716   dprintf("s68k r32: %06x, %08x @%06x", a&0xffffff, d, SekPcS68k);\r
717 #endif\r
718   return d;\r
719 }\r
720 \r
721 // -----------------------------------------------------------------\r
722 \r
723 void PicoWriteS68k8(u32 a,u8 d)\r
724 {\r
725 #ifdef __debug_io2\r
726   dprintf("s68k w8 : %06x,   %02x @%06x", a&0xffffff, d, SekPcS68k);\r
727 #endif\r
728 \r
729   a&=0xffffff;\r
730 \r
731   // prg RAM\r
732   if (a < 0x80000) {\r
733     u8 *pm=(u8 *)(Pico_mcd->prg_ram+(a^1));\r
734     *pm=d;\r
735     return;\r
736   }\r
737 \r
738   if (a != 0xff0011 && (a&0xff8000) == 0xff0000) // PCM hack\r
739     return;\r
740 \r
741   // regs\r
742   if ((a&0xfffe00) == 0xff8000) {\r
743     dprintf("s68k_regs w8: [%02x] %02x @ %06x", a&0x1ff, d, SekPcS68k);\r
744     s68k_reg_write8(a,d,8);\r
745     return;\r
746   }\r
747 \r
748   dprintf("s68k w8 : %06x,   %02x @%06x", a&0xffffff, d, SekPcS68k);\r
749 }\r
750 \r
751 void PicoWriteS68k16(u32 a,u16 d)\r
752 {\r
753 #ifdef __debug_io2\r
754   dprintf("s68k w16: %06x, %04x @%06x", a&0xffffff, d, SekPcS68k);\r
755 #endif\r
756 \r
757   a&=0xfffffe;\r
758 \r
759   // prg RAM\r
760   if (a < 0x80000) {\r
761     *(u16 *)(Pico_mcd->prg_ram+a)=d;\r
762     return;\r
763   }\r
764 \r
765   // regs\r
766   if ((a&0xfffe00) == 0xff8000) {\r
767     dprintf("s68k_regs w16: [%02x] %04x @ %06x", a&0x1ff, d, SekPcS68k);\r
768     s68k_reg_write8(a,  d>>8, 16);\r
769     s68k_reg_write8(a+1,d&0xff, 16);\r
770     return;\r
771   }\r
772 \r
773   dprintf("s68k w16: %06x, %04x @%06x", a&0xffffff, d, SekPcS68k);\r
774 }\r
775 \r
776 void PicoWriteS68k32(u32 a,u32 d)\r
777 {\r
778 #ifdef __debug_io2\r
779   dprintf("s68k w32: %06x, %08x @%06x", a&0xffffff, d, SekPcS68k);\r
780 #endif\r
781 \r
782   a&=0xfffffe;\r
783 \r
784   // prg RAM\r
785   if (a < 0x80000) {\r
786     u16 *pm=(u16 *)(Pico_mcd->prg_ram+a);\r
787     pm[0]=(u16)(d>>16); pm[1]=(u16)d;\r
788     return;\r
789   }\r
790 \r
791   // regs\r
792   if ((a&0xfffe00) == 0xff8000) {\r
793     dprintf("s68k_regs w32: [%02x] %08x @ %06x", a&0x1ff, d, SekPcS68k);\r
794     s68k_reg_write8(a,   d>>24, 32);\r
795     s68k_reg_write8(a+1,(d>>16)&0xff, 32);\r
796     s68k_reg_write8(a+2,(d>>8) &0xff, 32);\r
797     s68k_reg_write8(a+3, d     &0xff, 32);\r
798     return;\r
799   }\r
800 \r
801   dprintf("s68k w32: %06x, %08x @%06x", a&0xffffff, d, SekPcS68k);\r
802 }\r
803 \r
804 \r
805 \r
806 // -----------------------------------------------------------------\r
807 \r
808 #ifdef EMU_M68K\r
809 unsigned char  PicoReadCD8w (unsigned int a) {\r
810         return m68ki_cpu_p == &PicoS68kCPU ? PicoReadS68k8(a) : PicoReadM68k8(a);\r
811 }\r
812 unsigned short PicoReadCD16w(unsigned int a) {\r
813         return m68ki_cpu_p == &PicoS68kCPU ? PicoReadS68k16(a) : PicoReadM68k16(a);\r
814 }\r
815 unsigned int   PicoReadCD32w(unsigned int a) {\r
816         return m68ki_cpu_p == &PicoS68kCPU ? PicoReadS68k32(a) : PicoReadM68k32(a);\r
817 }\r
818 void PicoWriteCD8w (unsigned int a, unsigned char d) {\r
819         if (m68ki_cpu_p == &PicoS68kCPU) PicoWriteS68k8(a, d); else PicoWriteM68k8(a, d);\r
820 }\r
821 void PicoWriteCD16w(unsigned int a, unsigned short d) {\r
822         if (m68ki_cpu_p == &PicoS68kCPU) PicoWriteS68k16(a, d); else PicoWriteM68k16(a, d);\r
823 }\r
824 void PicoWriteCD32w(unsigned int a, unsigned int d) {\r
825         if (m68ki_cpu_p == &PicoS68kCPU) PicoWriteS68k32(a, d); else PicoWriteM68k32(a, d);\r
826 }\r
827 \r
828 // these are allowed to access RAM\r
829 unsigned int  m68k_read_pcrelative_CD8 (unsigned int a) {\r
830   a&=0xffffff;\r
831   if(m68ki_cpu_p == &PicoS68kCPU) {\r
832     if (a < 0x80000) return *(u8 *)(Pico_mcd->prg_ram+(a^1)); // PRG Ram\r
833     else dprintf("s68k read_pcrel8 @ %06x", a);\r
834   } else {\r
835     if(a<Pico.romsize)         return *(u8 *)(Pico.rom+(a^1)); // Rom\r
836     if((a&0xe00000)==0xe00000) return *(u8 *)(Pico.ram+((a^1)&0xffff)); // Ram\r
837   }\r
838   return 0;//(u8)  lastread_d;\r
839 }\r
840 unsigned int  m68k_read_pcrelative_CD16(unsigned int a) {\r
841   a&=0xffffff;\r
842   if(m68ki_cpu_p == &PicoS68kCPU) {\r
843     if (a < 0x80000) return *(u16 *)(Pico_mcd->prg_ram+(a&~1)); // PRG Ram\r
844     else dprintf("s68k read_pcrel16 @ %06x", a);\r
845   } else {\r
846     if(a<Pico.romsize)         return *(u16 *)(Pico.rom+(a&~1)); // Rom\r
847     if((a&0xe00000)==0xe00000) return *(u16 *)(Pico.ram+(a&0xfffe)); // Ram\r
848   }\r
849   return 0;//(u16) lastread_d;\r
850 }\r
851 unsigned int  m68k_read_pcrelative_CD32(unsigned int a) {\r
852   a&=0xffffff;\r
853   if(m68ki_cpu_p == &PicoS68kCPU) {\r
854     if (a < 0x80000) { u16 *pm=(u16 *)(Pico_mcd->prg_ram+(a&~1)); return (pm[0]<<16)|pm[1]; } // PRG Ram\r
855     else dprintf("s68k read_pcrel32 @ %06x", a);\r
856   } else {\r
857     if(a<Pico.romsize)         { u16 *pm=(u16 *)(Pico.rom+(a&~1));     return (pm[0]<<16)|pm[1]; }\r
858     if((a&0xe00000)==0xe00000) { u16 *pm=(u16 *)(Pico.ram+(a&0xfffe)); return (pm[0]<<16)|pm[1]; } // Ram\r
859   }\r
860   return 0; //lastread_d;\r
861 }\r
862 #endif // EMU_M68K\r
863 \r