region detection, cd states wip, fixes, stuff
[picodrive.git] / Pico / cd / Memory.c
CommitLineData
cc68a136 1// This is part of Pico Library\r
2\r
3// (c) Copyright 2004 Dave, All rights reserved.\r
b837b69b 4// (c) Copyright 2007 notaz, All rights reserved.\r
cc68a136 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
cb4a513a 19#include "gfx_cd.h"\r
20\r
cc68a136 21typedef unsigned char u8;\r
22typedef unsigned short u16;\r
23typedef unsigned int u32;\r
24\r
25//#define __debug_io\r
26//#define __debug_io2\r
d1df8786 27//#define rdprintf dprintf\r
28#define rdprintf(...)\r
cc68a136 29\r
30// -----------------------------------------------------------------\r
31\r
8c1952f0 32// extern m68ki_cpu_core m68ki_cpu;\r
cc68a136 33\r
cc68a136 34\r
cb4a513a 35static u32 m68k_reg_read16(u32 a)\r
cc68a136 36{\r
37 u32 d=0;\r
38 a &= 0x3e;\r
672ad671 39 // dprintf("m68k_regs r%2i: [%02x] @%06x", realsize&~1, a+(realsize&1), SekPc);\r
cc68a136 40\r
41 switch (a) {\r
672ad671 42 case 0:\r
c459aefd 43 d = ((Pico_mcd->s68k_regs[0x33]<<13)&0x8000) | Pico_mcd->m.busreq; // here IFL2 is always 0, just like in Gens\r
672ad671 44 goto end;\r
cc68a136 45 case 2:\r
672ad671 46 d = (Pico_mcd->s68k_regs[a]<<8) | (Pico_mcd->s68k_regs[a+1]&0xc7);\r
bf098bc5 47 dprintf("m68k_regs r3: %02x @%06x", (u8)d, SekPc);\r
cc68a136 48 goto end;\r
c459aefd 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
cc68a136 55 case 8:\r
cc68a136 56 d = Read_CDC_Host(0);\r
57 goto end;\r
c459aefd 58 case 0xA:\r
59 dprintf("m68k reserved read");\r
60 goto end;\r
cc68a136 61 case 0xC:\r
d1df8786 62 dprintf("m68k stopwatch timer read");\r
cc68a136 63 break;\r
64 }\r
65\r
cc68a136 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
74end:\r
75\r
672ad671 76 // dprintf("ret = %04x", d);\r
cc68a136 77 return d;\r
78}\r
79\r
cb4a513a 80static void m68k_reg_write8(u32 a, u32 d)\r
cc68a136 81{\r
82 a &= 0x3f;\r
672ad671 83 // dprintf("m68k_regs w%2i: [%02x] %02x @%06x", realsize, a, d, SekPc);\r
cc68a136 84\r
85 switch (a) {\r
86 case 0:\r
672ad671 87 d &= 1;\r
cc68a136 88 if ((d&1) && (Pico_mcd->s68k_regs[0x33]&(1<<2))) { dprintf("m68k: s68k irq 2"); SekInterruptS68k(2); }\r
c459aefd 89 return;\r
cc68a136 90 case 1:\r
672ad671 91 d &= 3;\r
51a902ae 92 if (!(d&1)) Pico_mcd->m.state_flags |= 1; // reset pending, needed to be sure we fetch the right vectors on reset\r
c459aefd 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
51a902ae 95 if ((Pico_mcd->m.state_flags&1) && (d&3)==1) {\r
cc68a136 96 SekResetS68k(); // S68k comes out of RESET or BRQ state\r
51a902ae 97 Pico_mcd->m.state_flags&=~1;\r
672ad671 98 dprintf("m68k: resetting s68k, cycles=%i", SekCyclesLeft);\r
cc68a136 99 }\r
c459aefd 100 Pico_mcd->m.busreq = d;\r
101 return;\r
672ad671 102 case 2:\r
103 Pico_mcd->s68k_regs[2] = d; // really use s68k side register\r
104 return;\r
cc68a136 105 case 3:\r
bf098bc5 106 dprintf("m68k_regs w3: %02x @%06x", (u8)d, SekPc);\r
672ad671 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
d0d47c5b 114 if (!(d & 4) && (d & 2)) d &= ~1; // return word RAM to s68k in 2M mode\r
672ad671 115 Pico_mcd->s68k_regs[3] = d; // really use s68k side register\r
116 return;\r
c459aefd 117 case 6:\r
118 *((char *)&Pico_mcd->m.hint_vector+1) = d;\r
d1df8786 119 Pico_mcd->bios[0x72 + 1] = d; // simple hint vector changer\r
c459aefd 120 return;\r
121 case 7:\r
122 *(char *)&Pico_mcd->m.hint_vector = d;\r
d1df8786 123 Pico_mcd->bios[0x72] = d;\r
c459aefd 124 return;\r
cc68a136 125 case 0xe:\r
672ad671 126 //dprintf("m68k: comm flag: %02x", d);\r
cc68a136 127\r
672ad671 128 //dprintf("s68k @ %06x", SekPcS68k);\r
cc68a136 129\r
130 Pico_mcd->s68k_regs[0xe] = d;\r
c459aefd 131 return;\r
672ad671 132 }\r
133\r
134 if ((a&0xf0) == 0x10) {\r
cc68a136 135 Pico_mcd->s68k_regs[a] = d;\r
672ad671 136 return;\r
cc68a136 137 }\r
138\r
c459aefd 139 dprintf("m68k: invalid write? [%02x] %02x", a, d);\r
cc68a136 140}\r
141\r
142\r
143\r
cb4a513a 144static u32 s68k_reg_read16(u32 a)\r
cc68a136 145{\r
146 u32 d=0;\r
cc68a136 147\r
672ad671 148 // dprintf("s68k_regs r%2i: [%02x] @ %06x", realsize&~1, a+(realsize&1), SekPcS68k);\r
cc68a136 149\r
150 switch (a) {\r
151 case 0:\r
cb4a513a 152 d = ((Pico_mcd->s68k_regs[0]&3)<<8) | 1; // ver = 0, not in reset state\r
c459aefd 153 goto end;\r
672ad671 154 case 2:\r
155 d = (Pico_mcd->s68k_regs[a]<<8) | (Pico_mcd->s68k_regs[a+1]&0x1f);\r
bf098bc5 156 dprintf("s68k_regs r3: %02x @%06x", (u8)d, SekPc);\r
672ad671 157 goto end;\r
cc68a136 158 case 6:\r
159 d = CDC_Read_Reg();\r
160 goto end;\r
161 case 8:\r
cb4a513a 162 d = Read_CDC_Host(1); // Gens returns 0 here on byte reads\r
cc68a136 163 goto end;\r
164 case 0xC:\r
d1df8786 165 dprintf("s68k stopwatch timer read");\r
166 break;\r
167 case 0x30:\r
168 dprintf("s68k int3 timer read");\r
cc68a136 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
177end:\r
178\r
672ad671 179 // dprintf("ret = %04x", d);\r
cc68a136 180\r
181 return d;\r
182}\r
183\r
cb4a513a 184static void s68k_reg_write8(u32 a, u32 d)\r
cc68a136 185{\r
672ad671 186 //dprintf("s68k_regs w%2i: [%02x] %02x @ %06x", realsize, a, d, SekPcS68k);\r
cc68a136 187\r
188 // TODO: review against Gens\r
189 switch (a) {\r
672ad671 190 case 2:\r
191 return; // only m68k can change WP\r
192 case 3:\r
bf098bc5 193 dprintf("s68k_regs w3: %02x @%06x", (u8)d, SekPc);\r
672ad671 194 d &= 0x1d;\r
d0d47c5b 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
672ad671 202 break;\r
cc68a136 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
c459aefd 208 //dprintf("s68k CDC reg addr: %x", d&0xf);\r
cc68a136 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
d1df8786 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
cc68a136 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
cc68a136 226 }\r
227 break;\r
228 case 0x34: // fader\r
229 Pico_mcd->s68k_regs[a] = (u8) d & 0x7f;\r
230 return;\r
672ad671 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
cc68a136 237 CDD_Export_Status();\r
cc68a136 238 }\r
672ad671 239 return;\r
240 }\r
cc68a136 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
260static 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
292static 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
321static 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
332static 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
672ad671 357 if ((a&0xffffc0)==0xa12000) {\r
cb4a513a 358 d=m68k_reg_read16(a);\r
672ad671 359 goto end;\r
360 }\r
cc68a136 361\r
362 d = UnusualRead16(a, realsize);\r
363\r
364end:\r
365 return d;\r
366}\r
367\r
368//extern UINT32 mz80GetRegisterValue(void *, UINT32);\r
369\r
370static 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
cb4a513a 420 if ((a&0xffffc0)==0xa12000) { m68k_reg_write8(a, d); return; }\r
cc68a136 421\r
422 dprintf("strange w%i: %06x, %08x @%06x", realsize, a&0xffffff, d, SekPc);\r
423}\r
424\r
425static 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
456u8 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
672ad671 468 u8 *prg_bank = Pico_mcd->prg_ram_b[Pico_mcd->s68k_regs[3]>>6];\r
cc68a136 469 d = *(prg_bank+((a^1)&0x1ffff));\r
470 goto end;\r
471 }\r
472\r
b837b69b 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
d0d47c5b 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
bf098bc5 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
d0d47c5b 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
cc68a136 508 if ((a&0xff4000)==0xa00000) { d=z80Read8(a); goto end; } // Z80 Ram\r
509\r
c459aefd 510 if ((a&0xffffc0)==0xa12000)\r
511 rdprintf("m68k_regs r8: [%02x] @%06x", a&0x3f, SekPc);\r
672ad671 512\r
cc68a136 513 d=OtherRead16(a&~1, 8|(a&1)); if ((a&1)==0) d>>=8;\r
514\r
c459aefd 515 if ((a&0xffffc0)==0xa12000)\r
516 rdprintf("ret = %02x", (u8)d);\r
672ad671 517\r
cc68a136 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
ab0607f7 526\r
cc68a136 527u16 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
672ad671 539 u8 *prg_bank = Pico_mcd->prg_ram_b[Pico_mcd->s68k_regs[3]>>6];\r
cc68a136 540 d = *(u16 *)(prg_bank+(a&0x1fffe));\r
541 goto end;\r
542 }\r
543\r
d0d47c5b 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
bf098bc5 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
d0d47c5b 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
c459aefd 563 if ((a&0xffffc0)==0xa12000)\r
564 rdprintf("m68k_regs r16: [%02x] @%06x", a&0x3f, SekPc);\r
672ad671 565\r
cc68a136 566 d = (u16)OtherRead16(a, 16);\r
567\r
c459aefd 568 if ((a&0xffffc0)==0xa12000)\r
569 rdprintf("ret = %04x", d);\r
672ad671 570\r
cc68a136 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
ab0607f7 579\r
cc68a136 580u32 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
672ad671 592 u8 *prg_bank = Pico_mcd->prg_ram_b[Pico_mcd->s68k_regs[3]>>6];\r
cc68a136 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
d0d47c5b 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
bf098bc5 602 if (a >= 0x220000) {\r
603 dprintf("cell");\r
604 } else {\r
bf098bc5 605 a=((a&0x1fffe)<<1);\r
606 if (Pico_mcd->s68k_regs[3]&1) a+=2;\r
ab0607f7 607 d = *(u16 *)(Pico_mcd->word_ram+a) << 16;\r
608 d |= *(u16 *)(Pico_mcd->word_ram+a+4);\r
bf098bc5 609 }\r
d0d47c5b 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
c459aefd 618 if ((a&0xffffc0)==0xa12000)\r
619 rdprintf("m68k_regs r32: [%02x] @%06x", a&0x3f, SekPc);\r
672ad671 620\r
cc68a136 621 d = (OtherRead16(a, 32)<<16)|OtherRead16(a+2, 32);\r
622\r
c459aefd 623 if ((a&0xffffc0)==0xa12000)\r
624 rdprintf("ret = %08x", d);\r
672ad671 625\r
cc68a136 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
ab0607f7 633\r
cc68a136 634// -----------------------------------------------------------------\r
635// Write Ram\r
636\r
637void 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
ab0607f7 646 if ((a&0xe00000)==0xe00000) { // Ram\r
647 *(u8 *)(Pico.ram+((a^1)&0xffff)) = d;\r
648 return;\r
649 }\r
cc68a136 650\r
651 a&=0xffffff;\r
652\r
653 // prg RAM\r
654 if ((a&0xfe0000)==0x020000) {\r
672ad671 655 u8 *prg_bank = Pico_mcd->prg_ram_b[Pico_mcd->s68k_regs[3]>>6];\r
bf098bc5 656 *(u8 *)(prg_bank+((a^1)&0x1ffff))=d;\r
cc68a136 657 return;\r
658 }\r
659\r
d0d47c5b 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
bf098bc5 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
d0d47c5b 671 } else {\r
672 // allow access in any mode, like Gens does\r
bf098bc5 673 *(u8 *)(Pico_mcd->word_ram+((a^1)&0x3ffff))=d;\r
d0d47c5b 674 }\r
675 return;\r
676 }\r
677\r
c459aefd 678 if ((a&0xffffc0)==0xa12000)\r
679 rdprintf("m68k_regs w8: [%02x] %02x @%06x", a&0x3f, d, SekPc);\r
672ad671 680\r
cc68a136 681 OtherWrite8(a,d,8);\r
682}\r
683\r
ab0607f7 684\r
cc68a136 685void 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
cc68a136 690 // dprintf("w16: %06x, %04x @%06x", a&0xffffff, d, SekPc);\r
691\r
ab0607f7 692 if ((a&0xe00000)==0xe00000) { // Ram\r
693 *(u16 *)(Pico.ram+(a&0xfffe))=d;\r
694 return;\r
695 }\r
cc68a136 696\r
697 a&=0xfffffe;\r
698\r
699 // prg RAM\r
700 if ((a&0xfe0000)==0x020000) {\r
672ad671 701 u8 *prg_bank = Pico_mcd->prg_ram_b[Pico_mcd->s68k_regs[3]>>6];\r
cc68a136 702 *(u16 *)(prg_bank+(a&0x1fffe))=d;\r
703 return;\r
704 }\r
705\r
d0d47c5b 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
bf098bc5 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
d0d47c5b 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
c459aefd 724 if ((a&0xffffc0)==0xa12000)\r
725 rdprintf("m68k_regs w16: [%02x] %04x @%06x", a&0x3f, d, SekPc);\r
cc68a136 726\r
727 OtherWrite16(a,d);\r
728}\r
729\r
ab0607f7 730\r
cc68a136 731void 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
672ad671 749 u8 *prg_bank = Pico_mcd->prg_ram_b[Pico_mcd->s68k_regs[3]>>6];\r
cc68a136 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
672ad671 755 // word RAM\r
d0d47c5b 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
bf098bc5 760 if (a >= 0x220000) {\r
761 dprintf("cell");\r
762 } else {\r
bf098bc5 763 a=((a&0x1fffe)<<1);\r
764 if (Pico_mcd->s68k_regs[3]&1) a+=2;\r
ab0607f7 765 *(u16 *)(Pico_mcd->word_ram+a) = d>>16;\r
766 *(u16 *)(Pico_mcd->word_ram+a+4) = d;\r
bf098bc5 767 }\r
d0d47c5b 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
672ad671 773 return;\r
d0d47c5b 774 }\r
672ad671 775\r
c459aefd 776 if ((a&0xffffc0)==0xa12000)\r
777 rdprintf("m68k_regs w32: [%02x] %08x @%06x", a&0x3f, d, SekPc);\r
cc68a136 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
787u8 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
cb4a513a 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
c459aefd 807 rdprintf("ret = %02x", (u8)d);\r
cc68a136 808 goto end;\r
809 }\r
810\r
d0d47c5b 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
bf098bc5 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
d0d47c5b 832 goto end;\r
833 }\r
834\r
ab0607f7 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
cc68a136 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
ab0607f7 851\r
cc68a136 852u16 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
cb4a513a 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
c459aefd 871 rdprintf("ret = %04x", d);\r
cc68a136 872 goto end;\r
873 }\r
874\r
d0d47c5b 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
ab0607f7 885 dprintf("ret = %04x", d);\r
d0d47c5b 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
bf098bc5 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
ab0607f7 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
d0d47c5b 906 goto end;\r
907 }\r
908\r
cc68a136 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
ab0607f7 919\r
cc68a136 920u32 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
cb4a513a 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
c459aefd 940 rdprintf("ret = %08x", d);\r
cc68a136 941 goto end;\r
942 }\r
943\r
d0d47c5b 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
ab0607f7 954 dprintf("ret = %08x", d);\r
d0d47c5b 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
ab0607f7 960 dprintf("s68k_wram1M r32: [%06x] @%06x", a, SekPc);\r
bf098bc5 961 a=((a&0x1fffe)<<1);\r
962 if (!(Pico_mcd->s68k_regs[3]&1)) a+=2;\r
ab0607f7 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
d0d47c5b 978 goto end;\r
979 }\r
980\r
cc68a136 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
ab0607f7 991\r
cc68a136 992// -----------------------------------------------------------------\r
993\r
994void 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
672ad671 1009 if (a != 0xff0011 && (a&0xff8000) == 0xff0000) // PCM hack\r
1010 return;\r
1011\r
cc68a136 1012 // regs\r
1013 if ((a&0xfffe00) == 0xff8000) {\r
cb4a513a 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
cc68a136 1019 return;\r
1020 }\r
1021\r
d0d47c5b 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
bf098bc5 1030 *(u8 *)(Pico_mcd->word_ram+((a^1)&0x3ffff))=d;\r
d0d47c5b 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
bf098bc5 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
d0d47c5b 1042 return;\r
1043 }\r
1044\r
ab0607f7 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
cc68a136 1052 dprintf("s68k w8 : %06x, %02x @%06x", a&0xffffff, d, SekPcS68k);\r
1053}\r
1054\r
ab0607f7 1055\r
cc68a136 1056void 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
cb4a513a 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
cc68a136 1080 return;\r
1081 }\r
1082\r
d0d47c5b 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
bf098bc5 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
d0d47c5b 1103 return;\r
1104 }\r
1105\r
ab0607f7 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
cc68a136 1116 dprintf("s68k w16: %06x, %04x @%06x", a&0xffffff, d, SekPcS68k);\r
1117}\r
1118\r
ab0607f7 1119\r
cc68a136 1120void 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
cb4a513a 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
cc68a136 1148 return;\r
1149 }\r
1150\r
d0d47c5b 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
bf098bc5 1169 a=((a&0x1fffe)<<1);\r
1170 if (!(Pico_mcd->s68k_regs[3]&1)) a+=2;\r
ab0607f7 1171 *(u16 *)(Pico_mcd->word_ram+a) = d>>16;\r
1172 *(u16 *)(Pico_mcd->word_ram+a+4) = d;\r
d0d47c5b 1173 return;\r
1174 }\r
ab0607f7 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
cc68a136 1188 dprintf("s68k w32: %06x, %08x @%06x", a&0xffffff, d, SekPcS68k);\r
1189}\r
1190\r
1191\r
1192\r
1193// -----------------------------------------------------------------\r
1194\r
b837b69b 1195\r
1196#if defined(EMU_C68K)\r
1197static __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
1224static 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
1235static __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
1250static 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
1262void 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
cc68a136 1286#ifdef EMU_M68K\r
1287unsigned char PicoReadCD8w (unsigned int a) {\r
1288 return m68ki_cpu_p == &PicoS68kCPU ? PicoReadS68k8(a) : PicoReadM68k8(a);\r
1289}\r
1290unsigned short PicoReadCD16w(unsigned int a) {\r
1291 return m68ki_cpu_p == &PicoS68kCPU ? PicoReadS68k16(a) : PicoReadM68k16(a);\r
1292}\r
1293unsigned int PicoReadCD32w(unsigned int a) {\r
1294 return m68ki_cpu_p == &PicoS68kCPU ? PicoReadS68k32(a) : PicoReadM68k32(a);\r
1295}\r
1296void PicoWriteCD8w (unsigned int a, unsigned char d) {\r
1297 if (m68ki_cpu_p == &PicoS68kCPU) PicoWriteS68k8(a, d); else PicoWriteM68k8(a, d);\r
1298}\r
1299void PicoWriteCD16w(unsigned int a, unsigned short d) {\r
1300 if (m68ki_cpu_p == &PicoS68kCPU) PicoWriteS68k16(a, d); else PicoWriteM68k16(a, d);\r
1301}\r
1302void 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
1307unsigned 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
b837b69b 1311 dprintf("s68k_read_pcrelative_CD8: can't handle %06x", a);\r
cc68a136 1312 } else {\r
b837b69b 1313 if(a<0x20000) return *(u8 *)(Pico.rom+(a^1)); // Bios\r
cc68a136 1314 if((a&0xe00000)==0xe00000) return *(u8 *)(Pico.ram+((a^1)&0xffff)); // Ram\r
b837b69b 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
cc68a136 1318 }\r
1319 return 0;//(u8) lastread_d;\r
1320}\r
1321unsigned 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
b837b69b 1325 dprintf("s68k_read_pcrelative_CD16: can't handle %06x", a);\r
cc68a136 1326 } else {\r
b837b69b 1327 if(a<0x20000) return *(u16 *)(Pico.rom+(a&~1)); // Bios\r
cc68a136 1328 if((a&0xe00000)==0xe00000) return *(u16 *)(Pico.ram+(a&0xfffe)); // Ram\r
b837b69b 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
cc68a136 1332 }\r
b837b69b 1333 return 0;\r
cc68a136 1334}\r
1335unsigned 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
b837b69b 1339 dprintf("s68k_read_pcrelative_CD32: can't handle %06x", a);\r
cc68a136 1340 } else {\r
b837b69b 1341 if(a<0x20000) { u16 *pm=(u16 *)(Pico.rom+(a&~1)); return (pm[0]<<16)|pm[1]; }\r
cc68a136 1342 if((a&0xe00000)==0xe00000) { u16 *pm=(u16 *)(Pico.ram+(a&0xfffe)); return (pm[0]<<16)|pm[1]; } // Ram\r
b837b69b 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
cc68a136 1346 }\r
b837b69b 1347 return 0;\r
cc68a136 1348}\r
1349#endif // EMU_M68K\r
1350\r