switch DMNA Silpheed hack to timeslice hack
[picodrive.git] / pico / cd / memory.c
1 // Memory I/O handlers for Sega/Mega CD.\r
2 // Loosely based on Gens code.\r
3 // (c) Copyright 2007, Grazvydas "notaz" Ignotas\r
4 \r
5 \r
6 #include "../pico_int.h"\r
7 \r
8 #include "../sound/ym2612.h"\r
9 #include "../sound/sn76496.h"\r
10 \r
11 #include "gfx_cd.h"\r
12 #include "pcm.h"\r
13 \r
14 #ifndef UTYPES_DEFINED\r
15 typedef unsigned char  u8;\r
16 typedef unsigned short u16;\r
17 typedef unsigned int   u32;\r
18 #define UTYPES_DEFINED\r
19 #endif\r
20 \r
21 #ifdef _MSC_VER\r
22 #define rdprintf\r
23 #define wrdprintf\r
24 #define r3printf\r
25 #else\r
26 //#define rdprintf dprintf\r
27 #define rdprintf(...)\r
28 //#define wrdprintf dprintf\r
29 #define wrdprintf(...)\r
30 //#define r3printf elprintf\r
31 #define r3printf(...)\r
32 #endif\r
33 \r
34 #ifdef EMU_CORE_DEBUG\r
35 extern u32 lastread_a, lastread_d[16], lastwrite_cyc_d[16];\r
36 extern int lrp_cyc, lwp_cyc;\r
37 #undef USE_POLL_DETECT\r
38 #endif\r
39 \r
40 // -----------------------------------------------------------------\r
41 \r
42 // poller detection\r
43 #define POLL_LIMIT 16\r
44 #define POLL_CYCLES 124\r
45 // int m68k_poll_addr, m68k_poll_cnt;\r
46 unsigned int s68k_poll_adclk, s68k_poll_cnt;\r
47 \r
48 #ifndef _ASM_CD_MEMORY_C\r
49 static u32 m68k_reg_read16(u32 a)\r
50 {\r
51   u32 d=0;\r
52   a &= 0x3e;\r
53   // dprintf("m68k_regs r%2i: [%02x] @%06x", realsize&~1, a+(realsize&1), SekPc);\r
54 \r
55   switch (a) {\r
56     case 0:\r
57       d = ((Pico_mcd->s68k_regs[0x33]<<13)&0x8000) | Pico_mcd->m.busreq; // here IFL2 is always 0, just like in Gens\r
58       goto end;\r
59     case 2:\r
60       d = (Pico_mcd->s68k_regs[a]<<8) | (Pico_mcd->s68k_regs[a+1]&0xc7);\r
61       r3printf(EL_STATUS, "m68k_regs r3: %02x @%06x", (u8)d, SekPc);\r
62       goto end;\r
63     case 4:\r
64       d = Pico_mcd->s68k_regs[4]<<8;\r
65       goto end;\r
66     case 6:\r
67       d = *(u16 *)(Pico_mcd->bios + 0x72);\r
68       goto end;\r
69     case 8:\r
70       d = Read_CDC_Host(0);\r
71       goto end;\r
72     case 0xA:\r
73       elprintf(EL_UIO, "m68k FIXME: reserved read");\r
74       goto end;\r
75     case 0xC:\r
76       d = Pico_mcd->m.timer_stopwatch >> 16;\r
77       dprintf("m68k stopwatch timer read (%04x)", d);\r
78       goto end;\r
79   }\r
80 \r
81   if (a < 0x30) {\r
82     // comm flag/cmd/status (0xE-0x2F)\r
83     d = (Pico_mcd->s68k_regs[a]<<8) | Pico_mcd->s68k_regs[a+1];\r
84     goto end;\r
85   }\r
86 \r
87   elprintf(EL_UIO, "m68k_regs FIXME invalid read @ %02x", a);\r
88 \r
89 end:\r
90 \r
91   return d;\r
92 }\r
93 #endif\r
94 \r
95 #ifndef _ASM_CD_MEMORY_C\r
96 static\r
97 #endif\r
98 void m68k_reg_write8(u32 a, u32 d)\r
99 {\r
100   a &= 0x3f;\r
101   // dprintf("m68k_regs w%2i: [%02x] %02x @%06x", realsize, a, d, SekPc);\r
102 \r
103   switch (a) {\r
104     case 0:\r
105       d &= 1;\r
106       if ((d&1) && (Pico_mcd->s68k_regs[0x33]&(1<<2))) { elprintf(EL_INTS, "m68k: s68k irq 2"); SekInterruptS68k(2); }\r
107       return;\r
108     case 1:\r
109       d &= 3;\r
110       if (!(d&1)) Pico_mcd->m.state_flags |= 1; // reset pending, needed to be sure we fetch the right vectors on reset\r
111       if ( (Pico_mcd->m.busreq&1) != (d&1)) elprintf(EL_INTSW, "m68k: s68k reset %i", !(d&1));\r
112       if ( (Pico_mcd->m.busreq&2) != (d&2)) elprintf(EL_INTSW, "m68k: s68k brq %i", (d&2)>>1);\r
113       if ((Pico_mcd->m.state_flags&1) && (d&3)==1) {\r
114         SekResetS68k(); // S68k comes out of RESET or BRQ state\r
115         Pico_mcd->m.state_flags&=~1;\r
116         dprintf("m68k: resetting s68k, cycles=%i", SekCyclesLeft);\r
117       }\r
118       Pico_mcd->m.busreq = d;\r
119       return;\r
120     case 2:\r
121       dprintf("m68k: prg wp=%02x", d);\r
122       Pico_mcd->s68k_regs[2] = d; // really use s68k side register\r
123       return;\r
124     case 3: {\r
125       u32 dold = Pico_mcd->s68k_regs[3]&0x1f;\r
126       r3printf(EL_STATUS, "m68k_regs w3: %02x @%06x", (u8)d, SekPc);\r
127       d &= 0xc2;\r
128       if ((dold>>6) != ((d>>6)&3))\r
129         dprintf("m68k: prg bank: %i -> %i", (Pico_mcd->s68k_regs[a]>>6), ((d>>6)&3));\r
130       //if ((Pico_mcd->s68k_regs[3]&4) != (d&4)) dprintf("m68k: ram mode %i mbit", (d&4) ? 1 : 2);\r
131       //if ((Pico_mcd->s68k_regs[3]&2) != (d&2)) dprintf("m68k: %s", (d&4) ? ((d&2) ? "word swap req" : "noop?") :\r
132       //                                             ((d&2) ? "word ram to s68k" : "word ram to m68k"));\r
133       if (dold & 4) {   // 1M mode\r
134         d ^= 2;         // writing 0 to DMNA actually sets it, 1 does nothing\r
135       } else {\r
136         if ((d ^ dold) & d & 2) { // DMNA is being set\r
137           dold &= ~1;   // return word RAM to s68k\r
138           /* Silpheed hack: bset(w3), r3, btst, bne, r3 */\r
139           SekEndRun(20+16+10+12+16);\r
140         }\r
141       }\r
142       Pico_mcd->s68k_regs[3] = d | dold; // really use s68k side register\r
143 #ifdef USE_POLL_DETECT\r
144       if ((s68k_poll_adclk&0xfe) == 2 && s68k_poll_cnt > POLL_LIMIT) {\r
145         SekSetStopS68k(0); s68k_poll_adclk = 0;\r
146         elprintf(EL_CDPOLL, "s68k poll release, a=%02x", a);\r
147       }\r
148 #endif\r
149       return;\r
150     }\r
151     case 6:\r
152       Pico_mcd->bios[0x72 + 1] = d; // simple hint vector changer\r
153       return;\r
154     case 7:\r
155       Pico_mcd->bios[0x72] = d;\r
156       dprintf("hint vector set to %08x", PicoRead32(0x70));\r
157       return;\r
158     case 0xf:\r
159       d = (d << 1) | ((d >> 7) & 1); // rol8 1 (special case)\r
160     case 0xe:\r
161       //dprintf("m68k: comm flag: %02x", d);\r
162       Pico_mcd->s68k_regs[0xe] = d;\r
163 #ifdef USE_POLL_DETECT\r
164       if ((s68k_poll_adclk&0xfe) == 0xe && s68k_poll_cnt > POLL_LIMIT) {\r
165         SekSetStopS68k(0); s68k_poll_adclk = 0;\r
166         elprintf(EL_CDPOLL, "s68k poll release, a=%02x", a);\r
167       }\r
168 #endif\r
169       return;\r
170   }\r
171 \r
172   if ((a&0xf0) == 0x10) {\r
173       Pico_mcd->s68k_regs[a] = d;\r
174 #ifdef USE_POLL_DETECT\r
175       if ((a&0xfe) == (s68k_poll_adclk&0xfe) && s68k_poll_cnt > POLL_LIMIT) {\r
176         SekSetStopS68k(0); s68k_poll_adclk = 0;\r
177         elprintf(EL_CDPOLL, "s68k poll release, a=%02x", a);\r
178       }\r
179 #endif\r
180       return;\r
181   }\r
182 \r
183   elprintf(EL_UIO, "m68k FIXME: invalid write? [%02x] %02x", a, d);\r
184 }\r
185 \r
186 #ifndef _ASM_CD_MEMORY_C\r
187 static\r
188 #endif\r
189 u32 s68k_poll_detect(u32 a, u32 d)\r
190 {\r
191 #ifdef USE_POLL_DETECT\r
192   // needed mostly for Cyclone, which doesn't always check it's cycle counter\r
193   if (SekIsStoppedS68k()) return d;\r
194   // polling detection\r
195   if (a == (s68k_poll_adclk&0xff)) {\r
196     unsigned int clkdiff = SekCyclesDoneS68k() - (s68k_poll_adclk>>8);\r
197     if (clkdiff <= POLL_CYCLES) {\r
198       s68k_poll_cnt++;\r
199       //printf("-- diff: %u, cnt = %i\n", clkdiff, s68k_poll_cnt);\r
200       if (s68k_poll_cnt > POLL_LIMIT) {\r
201         SekSetStopS68k(1);\r
202         elprintf(EL_CDPOLL, "s68k poll detected @ %06x, a=%02x", SekPcS68k, a);\r
203       }\r
204       s68k_poll_adclk = (SekCyclesDoneS68k() << 8) | a;\r
205       return d;\r
206     }\r
207   }\r
208   s68k_poll_adclk = (SekCyclesDoneS68k() << 8) | a;\r
209   s68k_poll_cnt = 0;\r
210 #endif\r
211   return d;\r
212 }\r
213 \r
214 #define READ_FONT_DATA(basemask) \\r
215 { \\r
216       unsigned int fnt = *(unsigned int *)(Pico_mcd->s68k_regs + 0x4c); \\r
217       unsigned int col0 = (fnt >> 8) & 0x0f, col1 = (fnt >> 12) & 0x0f;   \\r
218       if (fnt & (basemask << 0)) d  = col1      ; else d  = col0;       \\r
219       if (fnt & (basemask << 1)) d |= col1 <<  4; else d |= col0 <<  4; \\r
220       if (fnt & (basemask << 2)) d |= col1 <<  8; else d |= col0 <<  8; \\r
221       if (fnt & (basemask << 3)) d |= col1 << 12; else d |= col0 << 12; \\r
222 }\r
223 \r
224 \r
225 #ifndef _ASM_CD_MEMORY_C\r
226 static\r
227 #endif\r
228 u32 s68k_reg_read16(u32 a)\r
229 {\r
230   u32 d=0;\r
231 \r
232   // dprintf("s68k_regs r%2i: [%02x] @ %06x", realsize&~1, a+(realsize&1), SekPcS68k);\r
233 \r
234   switch (a) {\r
235     case 0:\r
236       return ((Pico_mcd->s68k_regs[0]&3)<<8) | 1; // ver = 0, not in reset state\r
237     case 2:\r
238       d = (Pico_mcd->s68k_regs[2]<<8) | (Pico_mcd->s68k_regs[3]&0x1f);\r
239       r3printf(EL_STATUS, "s68k_regs r3: %02x @%06x", (u8)d, SekPcS68k);\r
240       return s68k_poll_detect(a, d);\r
241     case 6:\r
242       return CDC_Read_Reg();\r
243     case 8:\r
244       return Read_CDC_Host(1); // Gens returns 0 here on byte reads\r
245     case 0xC:\r
246       d = Pico_mcd->m.timer_stopwatch >> 16;\r
247       dprintf("s68k stopwatch timer read (%04x)", d);\r
248       return d;\r
249     case 0x30:\r
250       dprintf("s68k int3 timer read (%02x)", Pico_mcd->s68k_regs[31]);\r
251       return Pico_mcd->s68k_regs[31];\r
252     case 0x34: // fader\r
253       return 0; // no busy bit\r
254     case 0x50: // font data (check: Lunar 2, Silpheed)\r
255       READ_FONT_DATA(0x00100000);\r
256       return d;\r
257     case 0x52:\r
258       READ_FONT_DATA(0x00010000);\r
259       return d;\r
260     case 0x54:\r
261       READ_FONT_DATA(0x10000000);\r
262       return d;\r
263     case 0x56:\r
264       READ_FONT_DATA(0x01000000);\r
265       return d;\r
266   }\r
267 \r
268   d = (Pico_mcd->s68k_regs[a]<<8) | Pico_mcd->s68k_regs[a+1];\r
269 \r
270   if (a >= 0x0e && a < 0x30)\r
271     return s68k_poll_detect(a, d);\r
272 \r
273   return d;\r
274 }\r
275 \r
276 #ifndef _ASM_CD_MEMORY_C\r
277 static\r
278 #endif\r
279 void s68k_reg_write8(u32 a, u32 d)\r
280 {\r
281   //dprintf("s68k_regs w%2i: [%02x] %02x @ %06x", realsize, a, d, SekPcS68k);\r
282 \r
283   // Warning: d might have upper bits set\r
284   switch (a) {\r
285     case 2:\r
286       return; // only m68k can change WP\r
287     case 3: {\r
288       int dold = Pico_mcd->s68k_regs[3];\r
289       r3printf(EL_STATUS, "s68k_regs w3: %02x @%06x", (u8)d, SekPcS68k);\r
290       d &= 0x1d;\r
291       d |= dold&0xc2;\r
292       if (d&4)\r
293       {\r
294         if ((d ^ dold) & 5) {\r
295           d &= ~2; // in case of mode or bank change we clear DMNA (m68k req) bit\r
296           PicoMemResetCD(d);\r
297         }\r
298 #ifdef _ASM_CD_MEMORY_C\r
299         if ((d ^ dold) & 0x1d)\r
300           PicoMemResetCDdecode(d);\r
301 #endif\r
302         if (!(dold & 4)) {\r
303           r3printf(EL_STATUS, "wram mode 2M->1M");\r
304           wram_2M_to_1M(Pico_mcd->word_ram2M);\r
305         }\r
306       }\r
307       else\r
308       {\r
309         if (dold & 4) {\r
310           r3printf(EL_STATUS, "wram mode 1M->2M");\r
311           if (!(d&1)) { // it didn't set the ret bit, which means it doesn't want to give WRAM to m68k\r
312             d &= ~3;\r
313             d |= (dold&1) ? 2 : 1; // then give it to the one which had bank0 in 1M mode\r
314           }\r
315           wram_1M_to_2M(Pico_mcd->word_ram2M);\r
316           PicoMemResetCD(d);\r
317         }\r
318         else\r
319           d |= dold&1;\r
320         // s68k can only set RET, writing 0 has no effect\r
321         if (d&1) d &= ~2; // return word RAM to m68k in 2M mode\r
322       }\r
323       break;\r
324     }\r
325     case 4:\r
326       dprintf("s68k CDC dest: %x", d&7);\r
327       Pico_mcd->s68k_regs[4] = (Pico_mcd->s68k_regs[4]&0xC0) | (d&7); // CDC mode\r
328       return;\r
329     case 5:\r
330       //dprintf("s68k CDC reg addr: %x", d&0xf);\r
331       break;\r
332     case 7:\r
333       CDC_Write_Reg(d);\r
334       return;\r
335     case 0xa:\r
336       dprintf("s68k set CDC dma addr");\r
337       break;\r
338     case 0xc:\r
339     case 0xd:\r
340       dprintf("s68k set stopwatch timer");\r
341       Pico_mcd->m.timer_stopwatch = 0;\r
342       return;\r
343     case 0xe:\r
344       Pico_mcd->s68k_regs[0xf] = (d>>1) | (d<<7); // ror8 1, Gens note: Dragons lair\r
345       return;\r
346     case 0x31:\r
347       dprintf("s68k set int3 timer: %02x", d);\r
348       Pico_mcd->m.timer_int3 = (d & 0xff) << 16;\r
349       break;\r
350     case 0x33: // IRQ mask\r
351       dprintf("s68k irq mask: %02x", d);\r
352       if ((d&(1<<4)) && (Pico_mcd->s68k_regs[0x37]&4) && !(Pico_mcd->s68k_regs[0x33]&(1<<4))) {\r
353         CDD_Export_Status();\r
354       }\r
355       break;\r
356     case 0x34: // fader\r
357       Pico_mcd->s68k_regs[a] = (u8) d & 0x7f;\r
358       return;\r
359     case 0x36:\r
360       return; // d/m bit is unsetable\r
361     case 0x37: {\r
362       u32 d_old = Pico_mcd->s68k_regs[0x37];\r
363       Pico_mcd->s68k_regs[0x37] = d&7;\r
364       if ((d&4) && !(d_old&4)) {\r
365         CDD_Export_Status();\r
366       }\r
367       return;\r
368     }\r
369     case 0x4b:\r
370       Pico_mcd->s68k_regs[a] = (u8) d;\r
371       CDD_Import_Command();\r
372       return;\r
373   }\r
374 \r
375   if ((a&0x1f0) == 0x10 || (a >= 0x38 && a < 0x42))\r
376   {\r
377     elprintf(EL_UIO, "s68k FIXME: invalid write @ %02x?", a);\r
378     return;\r
379   }\r
380 \r
381   Pico_mcd->s68k_regs[a] = (u8) d;\r
382 }\r
383 \r
384 \r
385 static u32 OtherRead16End(u32 a, int realsize)\r
386 {\r
387   u32 d=0;\r
388 \r
389 #ifndef _ASM_CD_MEMORY_C\r
390   if ((a&0xffffc0)==0xa12000) {\r
391     d=m68k_reg_read16(a);\r
392     goto end;\r
393   }\r
394 \r
395   if (a==0x400000) {\r
396     if (SRam.data != NULL) d=3; // 64k cart\r
397     goto end;\r
398   }\r
399 \r
400   if ((a&0xfe0000)==0x600000) {\r
401     if (SRam.data != NULL) {\r
402       d=SRam.data[((a>>1)&0xffff)+0x2000];\r
403       if (realsize == 8) d|=d<<8;\r
404     }\r
405     goto end;\r
406   }\r
407 \r
408   if (a==0x7ffffe) {\r
409     d=Pico_mcd->m.bcram_reg;\r
410     goto end;\r
411   }\r
412 #endif\r
413 \r
414   elprintf(EL_UIO, "m68k FIXME: unusual r%i: %06x @%06x", realsize&~1, (a&0xfffffe)+(realsize&1), SekPc);\r
415 \r
416 #ifndef _ASM_CD_MEMORY_C\r
417 end:\r
418 #endif\r
419   return d;\r
420 }\r
421 \r
422 \r
423 static void OtherWrite8End(u32 a, u32 d, int realsize)\r
424 {\r
425 #ifndef _ASM_CD_MEMORY_C\r
426   if ((a&0xffffc0)==0xa12000) { m68k_reg_write8(a, d); return; }\r
427 \r
428   if ((a&0xfe0000)==0x600000) {\r
429     if (SRam.data != NULL && (Pico_mcd->m.bcram_reg&1)) {\r
430       SRam.data[((a>>1)&0xffff)+0x2000]=d;\r
431       SRam.changed = 1;\r
432     }\r
433     return;\r
434   }\r
435 \r
436   if (a==0x7fffff) {\r
437     Pico_mcd->m.bcram_reg=d;\r
438     return;\r
439   }\r
440 #endif\r
441 \r
442   elprintf(EL_UIO, "m68k FIXME: strange w%i: [%06x], %08x @%06x", realsize, a&0xffffff, d, SekPc);\r
443 }\r
444 \r
445 #ifndef _ASM_CD_MEMORY_C\r
446 #define _CD_MEMORY_C\r
447 #undef _ASM_MEMORY_C\r
448 #include "../memory_cmn.c"\r
449 #include "cell_map.c"\r
450 #endif\r
451 \r
452 \r
453 // -----------------------------------------------------------------\r
454 //                     Read Rom and read Ram\r
455 \r
456 #ifdef _ASM_CD_MEMORY_C\r
457 u32 PicoReadM68k8(u32 a);\r
458 #else\r
459 u32 PicoReadM68k8(u32 a)\r
460 {\r
461   u32 d=0;\r
462 \r
463   a&=0xffffff;\r
464 \r
465   switch (a >> 17)\r
466   {\r
467     case 0x00>>1: // BIOS: 000000 - 020000\r
468       d = *(u8 *)(Pico_mcd->bios+(a^1));\r
469       break;\r
470     case 0x02>>1: // prg RAM\r
471       if ((Pico_mcd->m.busreq&3)!=1) {\r
472         u8 *prg_bank = Pico_mcd->prg_ram_b[Pico_mcd->s68k_regs[3]>>6];\r
473         d = *(prg_bank+((a^1)&0x1ffff));\r
474       }\r
475       break;\r
476     case 0x20>>1: // word RAM: 200000 - 220000\r
477       wrdprintf("m68k_wram r8: [%06x] @%06x", a, SekPc);\r
478       a &= 0x1ffff;\r
479       if (Pico_mcd->s68k_regs[3]&4) { // 1M mode?\r
480         int bank = Pico_mcd->s68k_regs[3]&1;\r
481         d = Pico_mcd->word_ram1M[bank][a^1];\r
482       } else {\r
483         // allow access in any mode, like Gens does\r
484         d = Pico_mcd->word_ram2M[a^1];\r
485       }\r
486       wrdprintf("ret = %02x", (u8)d);\r
487       break;\r
488     case 0x22>>1: // word RAM: 220000 - 240000\r
489       wrdprintf("m68k_wram r8: [%06x] @%06x", a, SekPc);\r
490       if (Pico_mcd->s68k_regs[3]&4) { // 1M mode?\r
491         int bank = Pico_mcd->s68k_regs[3]&1;\r
492         a = (a&3) | (cell_map(a >> 2) << 2); // cell arranged\r
493         d = Pico_mcd->word_ram1M[bank][a^1];\r
494       } else {\r
495         // allow access in any mode, like Gens does\r
496         d = Pico_mcd->word_ram2M[(a^1)&0x3ffff];\r
497       }\r
498       wrdprintf("ret = %02x", (u8)d);\r
499       break;\r
500     case 0xc0>>1: case 0xc2>>1: case 0xc4>>1: case 0xc6>>1:\r
501     case 0xc8>>1: case 0xca>>1: case 0xcc>>1: case 0xce>>1:\r
502     case 0xd0>>1: case 0xd2>>1: case 0xd4>>1: case 0xd6>>1:\r
503     case 0xd8>>1: case 0xda>>1: case 0xdc>>1: case 0xde>>1:\r
504       // VDP\r
505       if ((a&0xe700e0)==0xc00000)\r
506         d=PicoVideoRead8(a);\r
507       break;\r
508     case 0xe0>>1: case 0xe2>>1: case 0xe4>>1: case 0xe6>>1:\r
509     case 0xe8>>1: case 0xea>>1: case 0xec>>1: case 0xee>>1:\r
510     case 0xf0>>1: case 0xf2>>1: case 0xf4>>1: case 0xf6>>1:\r
511     case 0xf8>>1: case 0xfa>>1: case 0xfc>>1: case 0xfe>>1:\r
512       // RAM:\r
513       d = *(u8 *)(Pico.ram+((a^1)&0xffff));\r
514       break;\r
515     default:\r
516       if ((a&0xff4000)==0xa00000) { d=z80Read8(a); break; } // Z80 Ram\r
517       if ((a&0xffffc0)==0xa12000)\r
518         rdprintf("m68k_regs r8: [%02x] @%06x", a&0x3f, SekPc);\r
519 \r
520       d=OtherRead16(a&~1, 8|(a&1)); if ((a&1)==0) d>>=8;\r
521 \r
522       if ((a&0xffffc0)==0xa12000)\r
523         rdprintf("ret = %02x", (u8)d);\r
524       break;\r
525   }\r
526 \r
527 \r
528   elprintf(EL_IO, "r8 : %06x,   %02x @%06x", a&0xffffff, (u8)d, SekPc);\r
529 #ifdef EMU_CORE_DEBUG\r
530   if (a>=Pico.romsize) {\r
531     lastread_a = a;\r
532     lastread_d[lrp_cyc++&15] = d;\r
533   }\r
534 #endif\r
535   return d;\r
536 }\r
537 #endif\r
538 \r
539 \r
540 #ifdef _ASM_CD_MEMORY_C\r
541 u32 PicoReadM68k16(u32 a);\r
542 #else\r
543 static u32 PicoReadM68k16(u32 a)\r
544 {\r
545   u32 d=0;\r
546 \r
547   a&=0xfffffe;\r
548 \r
549   switch (a >> 17)\r
550   {\r
551     case 0x00>>1: // BIOS: 000000 - 020000\r
552       d = *(u16 *)(Pico_mcd->bios+a);\r
553       break;\r
554     case 0x02>>1: // prg RAM\r
555       if ((Pico_mcd->m.busreq&3)!=1) {\r
556         u8 *prg_bank = Pico_mcd->prg_ram_b[Pico_mcd->s68k_regs[3]>>6];\r
557         wrdprintf("m68k_prgram r16: [%i,%06x] @%06x", Pico_mcd->s68k_regs[3]>>6, a, SekPc);\r
558         d = *(u16 *)(prg_bank+(a&0x1fffe));\r
559         wrdprintf("ret = %04x", d);\r
560       }\r
561       break;\r
562     case 0x20>>1: // word RAM: 200000 - 220000\r
563       wrdprintf("m68k_wram r16: [%06x] @%06x", a, SekPc);\r
564       a &= 0x1fffe;\r
565       if (Pico_mcd->s68k_regs[3]&4) { // 1M mode?\r
566         int bank = Pico_mcd->s68k_regs[3]&1;\r
567         d = *(u16 *)(Pico_mcd->word_ram1M[bank]+a);\r
568       } else {\r
569         // allow access in any mode, like Gens does\r
570         d = *(u16 *)(Pico_mcd->word_ram2M+a);\r
571       }\r
572       wrdprintf("ret = %04x", d);\r
573       break;\r
574     case 0x22>>1: // word RAM: 220000 - 240000\r
575       wrdprintf("m68k_wram r16: [%06x] @%06x", a, SekPc);\r
576       if (Pico_mcd->s68k_regs[3]&4) { // 1M mode?\r
577         int bank = Pico_mcd->s68k_regs[3]&1;\r
578         a = (a&2) | (cell_map(a >> 2) << 2); // cell arranged\r
579         d = *(u16 *)(Pico_mcd->word_ram1M[bank]+a);\r
580       } else {\r
581         // allow access in any mode, like Gens does\r
582         d = *(u16 *)(Pico_mcd->word_ram2M+(a&0x3fffe));\r
583       }\r
584       wrdprintf("ret = %04x", d);\r
585       break;\r
586     case 0xc0>>1: case 0xc2>>1: case 0xc4>>1: case 0xc6>>1:\r
587     case 0xc8>>1: case 0xca>>1: case 0xcc>>1: case 0xce>>1:\r
588     case 0xd0>>1: case 0xd2>>1: case 0xd4>>1: case 0xd6>>1:\r
589     case 0xd8>>1: case 0xda>>1: case 0xdc>>1: case 0xde>>1:\r
590       // VDP\r
591       if ((a&0xe700e0)==0xc00000)\r
592         d=PicoVideoRead(a);\r
593       break;\r
594     case 0xe0>>1: case 0xe2>>1: case 0xe4>>1: case 0xe6>>1:\r
595     case 0xe8>>1: case 0xea>>1: case 0xec>>1: case 0xee>>1:\r
596     case 0xf0>>1: case 0xf2>>1: case 0xf4>>1: case 0xf6>>1:\r
597     case 0xf8>>1: case 0xfa>>1: case 0xfc>>1: case 0xfe>>1:\r
598       // RAM:\r
599       d=*(u16 *)(Pico.ram+(a&0xfffe));\r
600       break;\r
601     default:\r
602       if ((a&0xffffc0)==0xa12000)\r
603         rdprintf("m68k_regs r16: [%02x] @%06x", a&0x3f, SekPc);\r
604 \r
605       d = OtherRead16(a, 16);\r
606 \r
607       if ((a&0xffffc0)==0xa12000)\r
608         rdprintf("ret = %04x", d);\r
609       break;\r
610   }\r
611 \r
612 \r
613   elprintf(EL_IO, "r16: %06x, %04x  @%06x", a&0xffffff, d, SekPc);\r
614 #ifdef EMU_CORE_DEBUG\r
615   if (a>=Pico.romsize) {\r
616     lastread_a = a;\r
617     lastread_d[lrp_cyc++&15] = d;\r
618   }\r
619 #endif\r
620   return d;\r
621 }\r
622 #endif\r
623 \r
624 \r
625 #ifdef _ASM_CD_MEMORY_C\r
626 u32 PicoReadM68k32(u32 a);\r
627 #else\r
628 static u32 PicoReadM68k32(u32 a)\r
629 {\r
630   u32 d=0;\r
631 \r
632   a&=0xfffffe;\r
633 \r
634   switch (a >> 17)\r
635   {\r
636     case 0x00>>1: { // BIOS: 000000 - 020000\r
637       u16 *pm=(u16 *)(Pico_mcd->bios+a);\r
638       d = (pm[0]<<16)|pm[1];\r
639       break;\r
640     }\r
641     case 0x02>>1: // prg RAM\r
642       if ((Pico_mcd->m.busreq&3)!=1) {\r
643         u8 *prg_bank = Pico_mcd->prg_ram_b[Pico_mcd->s68k_regs[3]>>6];\r
644         u16 *pm=(u16 *)(prg_bank+(a&0x1fffe));\r
645         d = (pm[0]<<16)|pm[1];\r
646       }\r
647       break;\r
648     case 0x20>>1: // word RAM: 200000 - 220000\r
649       wrdprintf("m68k_wram r32: [%06x] @%06x", a, SekPc);\r
650       a&=0x1fffe;\r
651       if (Pico_mcd->s68k_regs[3]&4) { // 1M mode?\r
652         int bank = Pico_mcd->s68k_regs[3]&1;\r
653         u16 *pm=(u16 *)(Pico_mcd->word_ram1M[bank]+a);\r
654         d = (pm[0]<<16)|pm[1];\r
655       } else {\r
656         // allow access in any mode, like Gens does\r
657         u16 *pm=(u16 *)(Pico_mcd->word_ram2M+a);\r
658         d = (pm[0]<<16)|pm[1];\r
659       }\r
660       wrdprintf("ret = %08x", d);\r
661       break;\r
662     case 0x22>>1: // word RAM: 220000 - 240000\r
663       wrdprintf("m68k_wram r32: [%06x] @%06x", a, SekPc);\r
664       if (Pico_mcd->s68k_regs[3]&4) { // 1M mode, cell arranged?\r
665         u32 a1, a2;\r
666         int bank = Pico_mcd->s68k_regs[3]&1;\r
667         a1 = (a&2) | (cell_map(a >> 2) << 2);\r
668         if (a&2) a2 = cell_map((a+2) >> 2) << 2;\r
669         else     a2 = a1 + 2;\r
670         d  = *(u16 *)(Pico_mcd->word_ram1M[bank]+a1) << 16;\r
671         d |= *(u16 *)(Pico_mcd->word_ram1M[bank]+a2);\r
672       } else {\r
673         // allow access in any mode, like Gens does\r
674         u16 *pm=(u16 *)(Pico_mcd->word_ram2M+(a&0x3fffe));\r
675         d = (pm[0]<<16)|pm[1];\r
676       }\r
677       wrdprintf("ret = %08x", d);\r
678       break;\r
679     case 0xc0>>1: case 0xc2>>1: case 0xc4>>1: case 0xc6>>1:\r
680     case 0xc8>>1: case 0xca>>1: case 0xcc>>1: case 0xce>>1:\r
681     case 0xd0>>1: case 0xd2>>1: case 0xd4>>1: case 0xd6>>1:\r
682     case 0xd8>>1: case 0xda>>1: case 0xdc>>1: case 0xde>>1:\r
683       // VDP\r
684       d = (PicoVideoRead(a)<<16)|PicoVideoRead(a+2);\r
685       break;\r
686     case 0xe0>>1: case 0xe2>>1: case 0xe4>>1: case 0xe6>>1:\r
687     case 0xe8>>1: case 0xea>>1: case 0xec>>1: case 0xee>>1:\r
688     case 0xf0>>1: case 0xf2>>1: case 0xf4>>1: case 0xf6>>1:\r
689     case 0xf8>>1: case 0xfa>>1: case 0xfc>>1: case 0xfe>>1: {\r
690       // RAM:\r
691       u16 *pm=(u16 *)(Pico.ram+(a&0xfffe));\r
692       d = (pm[0]<<16)|pm[1];\r
693       break;\r
694     }\r
695     default:\r
696       if ((a&0xffffc0)==0xa12000)\r
697         rdprintf("m68k_regs r32: [%02x] @%06x", a&0x3f, SekPc);\r
698 \r
699       d = (OtherRead16(a, 32)<<16)|OtherRead16(a+2, 32);\r
700 \r
701       if ((a&0xffffc0)==0xa12000)\r
702         rdprintf("ret = %08x", d);\r
703       break;\r
704   }\r
705 \r
706 \r
707   elprintf(EL_IO, "r32: %06x, %08x @%06x", a&0xffffff, d, SekPc);\r
708 #ifdef EMU_CORE_DEBUG\r
709   if (a>=Pico.romsize) {\r
710     lastread_a = a;\r
711     lastread_d[lrp_cyc++&15] = d;\r
712   }\r
713 #endif\r
714   return d;\r
715 }\r
716 #endif\r
717 \r
718 \r
719 // -----------------------------------------------------------------\r
720 \r
721 #ifdef _ASM_CD_MEMORY_C\r
722 void PicoWriteM68k8(u32 a,u8 d);\r
723 #else\r
724 void PicoWriteM68k8(u32 a,u8 d)\r
725 {\r
726   elprintf(EL_IO, "w8 : %06x,   %02x @%06x", a&0xffffff, d, SekPc);\r
727 #ifdef EMU_CORE_DEBUG\r
728   lastwrite_cyc_d[lwp_cyc++&15] = d;\r
729 #endif\r
730 \r
731   if ((a&0xe00000)==0xe00000) { // Ram\r
732     *(u8 *)(Pico.ram+((a^1)&0xffff)) = d;\r
733     return;\r
734   }\r
735 \r
736   // prg RAM\r
737   if ((a&0xfe0000)==0x020000 && (Pico_mcd->m.busreq&3)!=1) {\r
738     u8 *prg_bank = Pico_mcd->prg_ram_b[Pico_mcd->s68k_regs[3]>>6];\r
739     *(u8 *)(prg_bank+((a^1)&0x1ffff))=d;\r
740     return;\r
741   }\r
742 \r
743   a&=0xffffff;\r
744 \r
745   // word RAM\r
746   if ((a&0xfc0000)==0x200000) {\r
747     wrdprintf("m68k_wram w8: [%06x] %02x @%06x", a, d, SekPc);\r
748     if (Pico_mcd->s68k_regs[3]&4) { // 1M mode?\r
749       int bank = Pico_mcd->s68k_regs[3]&1;\r
750       if (a >= 0x220000)\r
751            a = (a&3) | (cell_map(a >> 2) << 2); // cell arranged\r
752       else a &= 0x1ffff;\r
753       *(u8 *)(Pico_mcd->word_ram1M[bank]+(a^1))=d;\r
754     } else {\r
755       // allow access in any mode, like Gens does\r
756       *(u8 *)(Pico_mcd->word_ram2M+((a^1)&0x3ffff))=d;\r
757     }\r
758     return;\r
759   }\r
760 \r
761   if ((a&0xffffc0)==0xa12000) {\r
762     rdprintf("m68k_regs w8: [%02x] %02x @%06x", a&0x3f, d, SekPc);\r
763     m68k_reg_write8(a, d);\r
764     return;\r
765   }\r
766 \r
767   OtherWrite8(a,d);\r
768 }\r
769 #endif\r
770 \r
771 \r
772 #ifdef _ASM_CD_MEMORY_C\r
773 void PicoWriteM68k16(u32 a,u16 d);\r
774 #else\r
775 static void PicoWriteM68k16(u32 a,u16 d)\r
776 {\r
777   elprintf(EL_IO, "w16: %06x, %04x", a&0xffffff, d);\r
778 #ifdef EMU_CORE_DEBUG\r
779   lastwrite_cyc_d[lwp_cyc++&15] = d;\r
780 #endif\r
781 \r
782   if ((a&0xe00000)==0xe00000) { // Ram\r
783     *(u16 *)(Pico.ram+(a&0xfffe))=d;\r
784     return;\r
785   }\r
786 \r
787   // prg RAM\r
788   if ((a&0xfe0000)==0x020000 && (Pico_mcd->m.busreq&3)!=1) {\r
789     u8 *prg_bank = Pico_mcd->prg_ram_b[Pico_mcd->s68k_regs[3]>>6];\r
790     wrdprintf("m68k_prgram w16: [%i,%06x] %04x @%06x", Pico_mcd->s68k_regs[3]>>6, a, d, SekPc);\r
791     *(u16 *)(prg_bank+(a&0x1fffe))=d;\r
792     return;\r
793   }\r
794 \r
795   a&=0xfffffe;\r
796 \r
797   // word RAM\r
798   if ((a&0xfc0000)==0x200000) {\r
799     wrdprintf("m68k_wram w16: [%06x] %04x @%06x", a, d, SekPc);\r
800     if (Pico_mcd->s68k_regs[3]&4) { // 1M mode?\r
801       int bank = Pico_mcd->s68k_regs[3]&1;\r
802       if (a >= 0x220000)\r
803            a = (a&2) | (cell_map(a >> 2) << 2); // cell arranged\r
804       else a &= 0x1fffe;\r
805       *(u16 *)(Pico_mcd->word_ram1M[bank]+a)=d;\r
806     } else {\r
807       // allow access in any mode, like Gens does\r
808       *(u16 *)(Pico_mcd->word_ram2M+(a&0x3fffe))=d;\r
809     }\r
810     return;\r
811   }\r
812 \r
813   // regs\r
814   if ((a&0xffffc0)==0xa12000) {\r
815     rdprintf("m68k_regs w16: [%02x] %04x @%06x", a&0x3f, d, SekPc);\r
816     if (a == 0xe) { // special case, 2 byte writes would be handled differently\r
817       Pico_mcd->s68k_regs[0xe] = d >> 8;\r
818 #ifdef USE_POLL_DETECT\r
819       if ((s68k_poll_adclk&0xfe) == 0xe && s68k_poll_cnt > POLL_LIMIT) {\r
820         SekSetStopS68k(0); s68k_poll_adclk = 0;\r
821         elprintf(EL_CDPOLL, "s68k poll release, a=%02x", a);\r
822       }\r
823 #endif\r
824       return;\r
825     }\r
826     m68k_reg_write8(a,  d>>8);\r
827     m68k_reg_write8(a+1,d&0xff);\r
828     return;\r
829   }\r
830 \r
831   // VDP\r
832   if ((a&0xe700e0)==0xc00000) {\r
833     PicoVideoWrite(a,(u16)d);\r
834     return;\r
835   }\r
836 \r
837   OtherWrite16(a,d);\r
838 }\r
839 #endif\r
840 \r
841 \r
842 #ifdef _ASM_CD_MEMORY_C\r
843 void PicoWriteM68k32(u32 a,u32 d);\r
844 #else\r
845 static void PicoWriteM68k32(u32 a,u32 d)\r
846 {\r
847   elprintf(EL_IO, "w32: %06x, %08x", a&0xffffff, d);\r
848 #ifdef EMU_CORE_DEBUG\r
849   lastwrite_cyc_d[lwp_cyc++&15] = d;\r
850 #endif\r
851 \r
852   if ((a&0xe00000)==0xe00000)\r
853   {\r
854     // Ram:\r
855     u16 *pm=(u16 *)(Pico.ram+(a&0xfffe));\r
856     pm[0]=(u16)(d>>16); pm[1]=(u16)d;\r
857     return;\r
858   }\r
859 \r
860   // prg RAM\r
861   if ((a&0xfe0000)==0x020000 && (Pico_mcd->m.busreq&3)!=1) {\r
862     u8 *prg_bank = Pico_mcd->prg_ram_b[Pico_mcd->s68k_regs[3]>>6];\r
863     u16 *pm=(u16 *)(prg_bank+(a&0x1fffe));\r
864     pm[0]=(u16)(d>>16); pm[1]=(u16)d;\r
865     return;\r
866   }\r
867 \r
868   a&=0xfffffe;\r
869 \r
870   // word RAM\r
871   if ((a&0xfc0000)==0x200000) {\r
872     if (d != 0) // don't log clears\r
873       wrdprintf("m68k_wram w32: [%06x] %08x @%06x", a, d, SekPc);\r
874     if (Pico_mcd->s68k_regs[3]&4) { // 1M mode?\r
875       int bank = Pico_mcd->s68k_regs[3]&1;\r
876       if (a >= 0x220000) { // cell arranged\r
877         u32 a1, a2;\r
878         a1 = (a&2) | (cell_map(a >> 2) << 2);\r
879         if (a&2) a2 = cell_map((a+2) >> 2) << 2;\r
880         else     a2 = a1 + 2;\r
881         *(u16 *)(Pico_mcd->word_ram1M[bank]+a1) = d >> 16;\r
882         *(u16 *)(Pico_mcd->word_ram1M[bank]+a2) = d;\r
883       } else {\r
884         u16 *pm=(u16 *)(Pico_mcd->word_ram1M[bank]+(a&0x1fffe));\r
885         pm[0]=(u16)(d>>16); pm[1]=(u16)d;\r
886       }\r
887     } else {\r
888       // allow access in any mode, like Gens does\r
889       u16 *pm=(u16 *)(Pico_mcd->word_ram2M+(a&0x3fffe));\r
890       pm[0]=(u16)(d>>16); pm[1]=(u16)d;\r
891     }\r
892     return;\r
893   }\r
894 \r
895   if ((a&0xffffc0)==0xa12000) {\r
896     rdprintf("m68k_regs w32: [%02x] %08x @%06x", a&0x3f, d, SekPc);\r
897     if ((a&0x3e) == 0xe) dprintf("m68k FIXME: w32 [%02x]", a&0x3f);\r
898   }\r
899 \r
900   // VDP\r
901   if ((a&0xe700e0)==0xc00000)\r
902   {\r
903     PicoVideoWrite(a,  (u16)(d>>16));\r
904     PicoVideoWrite(a+2,(u16)d);\r
905     return;\r
906   }\r
907 \r
908   OtherWrite16(a,  (u16)(d>>16));\r
909   OtherWrite16(a+2,(u16)d);\r
910 }\r
911 #endif\r
912 \r
913 \r
914 // -----------------------------------------------------------------\r
915 //                            S68k\r
916 // -----------------------------------------------------------------\r
917 \r
918 #ifdef _ASM_CD_MEMORY_C\r
919 u32 PicoReadS68k8(u32 a);\r
920 #else\r
921 static u32 PicoReadS68k8(u32 a)\r
922 {\r
923   u32 d=0;\r
924 \r
925 #ifdef EMU_CORE_DEBUG\r
926   u32 ab=a&0xfffffe;\r
927 #endif\r
928   a&=0xffffff;\r
929 \r
930   // prg RAM\r
931   if (a < 0x80000) {\r
932     d = *(Pico_mcd->prg_ram+(a^1));\r
933     goto end;\r
934   }\r
935 \r
936   // regs\r
937   if ((a&0xfffe00) == 0xff8000) {\r
938     a &= 0x1ff;\r
939     rdprintf("s68k_regs r8: [%02x] @ %06x", a, SekPcS68k);\r
940     if (a >= 0x0e && a < 0x30) {\r
941       d = Pico_mcd->s68k_regs[a];\r
942       s68k_poll_detect(a, d);\r
943       rdprintf("ret = %02x", (u8)d);\r
944       goto end;\r
945     }\r
946     else if (a >= 0x58 && a < 0x68)\r
947          d = gfx_cd_read(a&~1);\r
948     else d = s68k_reg_read16(a&~1);\r
949     if ((a&1)==0) d>>=8;\r
950     rdprintf("ret = %02x", (u8)d);\r
951     goto end;\r
952   }\r
953 \r
954   // word RAM (2M area)\r
955   if ((a&0xfc0000)==0x080000) { // 080000-0bffff\r
956     // test: batman returns\r
957     wrdprintf("s68k_wram2M r8: [%06x] @%06x", a, SekPcS68k);\r
958     if (Pico_mcd->s68k_regs[3]&4) { // 1M decode mode?\r
959       int bank = (Pico_mcd->s68k_regs[3]&1)^1;\r
960       d = Pico_mcd->word_ram1M[bank][((a>>1)^1)&0x1ffff];\r
961       if (a&1) d &= 0x0f;\r
962       else d >>= 4;\r
963     } else {\r
964       // allow access in any mode, like Gens does\r
965       d = Pico_mcd->word_ram2M[(a^1)&0x3ffff];\r
966     }\r
967     wrdprintf("ret = %02x", (u8)d);\r
968     goto end;\r
969   }\r
970 \r
971   // word RAM (1M area)\r
972   if ((a&0xfe0000)==0x0c0000 && (Pico_mcd->s68k_regs[3]&4)) { // 0c0000-0dffff\r
973     int bank;\r
974     wrdprintf("s68k_wram1M r8: [%06x] @%06x", a, SekPcS68k);\r
975 //    if (!(Pico_mcd->s68k_regs[3]&4))\r
976 //      dprintf("s68k_wram1M FIXME: wrong mode");\r
977     bank = (Pico_mcd->s68k_regs[3]&1)^1;\r
978     d = Pico_mcd->word_ram1M[bank][(a^1)&0x1ffff];\r
979     wrdprintf("ret = %02x", (u8)d);\r
980     goto end;\r
981   }\r
982 \r
983   // PCM\r
984   if ((a&0xff8000)==0xff0000) {\r
985     elprintf(EL_IO, "s68k_pcm r8: [%06x] @%06x", a, SekPcS68k);\r
986     a &= 0x7fff;\r
987     if (a >= 0x2000)\r
988       d = Pico_mcd->pcm_ram_b[Pico_mcd->pcm.bank][(a>>1)&0xfff];\r
989     else if (a >= 0x20) {\r
990       a &= 0x1e;\r
991       d = Pico_mcd->pcm.ch[a>>2].addr >> PCM_STEP_SHIFT;\r
992       if (a & 2) d >>= 8;\r
993     }\r
994     elprintf(EL_IO, "ret = %02x", (u8)d);\r
995     goto end;\r
996   }\r
997 \r
998   // bram\r
999   if ((a&0xff0000)==0xfe0000) {\r
1000     d = Pico_mcd->bram[(a>>1)&0x1fff];\r
1001     goto end;\r
1002   }\r
1003 \r
1004   elprintf(EL_UIO, "s68k r8 : %06x,   %02x @%06x", a&0xffffff, (u8)d, SekPcS68k);\r
1005 \r
1006   end:\r
1007 \r
1008   elprintf(EL_IO, "s68k r8 : %06x,   %02x @%06x", a&0xffffff, (u8)d, SekPcS68k);\r
1009 #ifdef EMU_CORE_DEBUG\r
1010   lastread_a = ab;\r
1011   lastread_d[lrp_cyc++&15] = d;\r
1012 #endif\r
1013   return d;\r
1014 }\r
1015 #endif\r
1016 \r
1017 \r
1018 #ifdef _ASM_CD_MEMORY_C\r
1019 u32 PicoReadS68k16(u32 a);\r
1020 #else\r
1021 static u32 PicoReadS68k16(u32 a)\r
1022 {\r
1023   u32 d=0;\r
1024 \r
1025 #ifdef EMU_CORE_DEBUG\r
1026   u32 ab=a&0xfffffe;\r
1027 #endif\r
1028   a&=0xfffffe;\r
1029 \r
1030   // prg RAM\r
1031   if (a < 0x80000) {\r
1032     wrdprintf("s68k_prgram r16: [%06x] @%06x", a, SekPcS68k);\r
1033     d = *(u16 *)(Pico_mcd->prg_ram+a);\r
1034     wrdprintf("ret = %04x", d);\r
1035     goto end;\r
1036   }\r
1037 \r
1038   // regs\r
1039   if ((a&0xfffe00) == 0xff8000) {\r
1040     a &= 0x1fe;\r
1041     rdprintf("s68k_regs r16: [%02x] @ %06x", a, SekPcS68k);\r
1042     if (a >= 0x58 && a < 0x68)\r
1043          d = gfx_cd_read(a);\r
1044     else d = s68k_reg_read16(a);\r
1045     rdprintf("ret = %04x", d);\r
1046     goto end;\r
1047   }\r
1048 \r
1049   // word RAM (2M area)\r
1050   if ((a&0xfc0000)==0x080000) { // 080000-0bffff\r
1051     wrdprintf("s68k_wram2M r16: [%06x] @%06x", a, SekPcS68k);\r
1052     if (Pico_mcd->s68k_regs[3]&4) { // 1M decode mode?\r
1053       int bank = (Pico_mcd->s68k_regs[3]&1)^1;\r
1054       d = Pico_mcd->word_ram1M[bank][((a>>1)^1)&0x1ffff];\r
1055       d |= d << 4; d &= ~0xf0;\r
1056     } else {\r
1057       // allow access in any mode, like Gens does\r
1058       d = *(u16 *)(Pico_mcd->word_ram2M+(a&0x3fffe));\r
1059     }\r
1060     wrdprintf("ret = %04x", d);\r
1061     goto end;\r
1062   }\r
1063 \r
1064   // word RAM (1M area)\r
1065   if ((a&0xfe0000)==0x0c0000 && (Pico_mcd->s68k_regs[3]&4)) { // 0c0000-0dffff\r
1066     int bank;\r
1067     wrdprintf("s68k_wram1M r16: [%06x] @%06x", a, SekPcS68k);\r
1068 //    if (!(Pico_mcd->s68k_regs[3]&4))\r
1069 //      dprintf("s68k_wram1M FIXME: wrong mode");\r
1070     bank = (Pico_mcd->s68k_regs[3]&1)^1;\r
1071     d = *(u16 *)(Pico_mcd->word_ram1M[bank]+(a&0x1fffe));\r
1072     wrdprintf("ret = %04x", d);\r
1073     goto end;\r
1074   }\r
1075 \r
1076   // bram\r
1077   if ((a&0xff0000)==0xfe0000) {\r
1078     dprintf("FIXME: s68k_bram r16: [%06x] @%06x", a, SekPcS68k);\r
1079     a = (a>>1)&0x1fff;\r
1080     d = Pico_mcd->bram[a++];            // Gens does little endian here, and so do we..\r
1081     d|= Pico_mcd->bram[a++] << 8;       // This is most likely wrong\r
1082     dprintf("ret = %04x", d);\r
1083     goto end;\r
1084   }\r
1085 \r
1086   // PCM\r
1087   if ((a&0xff8000)==0xff0000) {\r
1088     dprintf("FIXME: s68k_pcm r16: [%06x] @%06x", a, SekPcS68k);\r
1089     a &= 0x7fff;\r
1090     if (a >= 0x2000)\r
1091       d = Pico_mcd->pcm_ram_b[Pico_mcd->pcm.bank][(a>>1)&0xfff];\r
1092     else if (a >= 0x20) {\r
1093       a &= 0x1e;\r
1094       d = Pico_mcd->pcm.ch[a>>2].addr >> PCM_STEP_SHIFT;\r
1095       if (a & 2) d >>= 8;\r
1096     }\r
1097     dprintf("ret = %04x", d);\r
1098     goto end;\r
1099   }\r
1100 \r
1101   elprintf(EL_UIO, "s68k r16: %06x, %04x  @%06x", a&0xffffff, d, SekPcS68k);\r
1102 \r
1103   end:\r
1104 \r
1105   elprintf(EL_IO, "s68k r16: %06x, %04x  @%06x", a&0xffffff, d, SekPcS68k);\r
1106 #ifdef EMU_CORE_DEBUG\r
1107   lastread_a = ab;\r
1108   lastread_d[lrp_cyc++&15] = d;\r
1109 #endif\r
1110   return d;\r
1111 }\r
1112 #endif\r
1113 \r
1114 \r
1115 #ifdef _ASM_CD_MEMORY_C\r
1116 u32 PicoReadS68k32(u32 a);\r
1117 #else\r
1118 static u32 PicoReadS68k32(u32 a)\r
1119 {\r
1120   u32 d=0;\r
1121 \r
1122 #ifdef EMU_CORE_DEBUG\r
1123   u32 ab=a&0xfffffe;\r
1124 #endif\r
1125   a&=0xfffffe;\r
1126 \r
1127   // prg RAM\r
1128   if (a < 0x80000) {\r
1129     u16 *pm=(u16 *)(Pico_mcd->prg_ram+a);\r
1130     d = (pm[0]<<16)|pm[1];\r
1131     goto end;\r
1132   }\r
1133 \r
1134   // regs\r
1135   if ((a&0xfffe00) == 0xff8000) {\r
1136     a &= 0x1fe;\r
1137     rdprintf("s68k_regs r32: [%02x] @ %06x", a, SekPcS68k);\r
1138     if (a >= 0x58 && a < 0x68)\r
1139          d = (gfx_cd_read(a)<<16)|gfx_cd_read(a+2);\r
1140     else d = (s68k_reg_read16(a)<<16)|s68k_reg_read16(a+2);\r
1141     rdprintf("ret = %08x", d);\r
1142     goto end;\r
1143   }\r
1144 \r
1145   // word RAM (2M area)\r
1146   if ((a&0xfc0000)==0x080000) { // 080000-0bffff\r
1147     wrdprintf("s68k_wram2M r32: [%06x] @%06x", a, SekPcS68k);\r
1148     if (Pico_mcd->s68k_regs[3]&4) { // 1M decode mode?\r
1149       int bank = (Pico_mcd->s68k_regs[3]&1)^1;\r
1150       a >>= 1;\r
1151       d  = Pico_mcd->word_ram1M[bank][((a+0)^1)&0x1ffff] << 16;\r
1152       d |= Pico_mcd->word_ram1M[bank][((a+1)^1)&0x1ffff];\r
1153       d |= d << 4; d &= 0x0f0f0f0f;\r
1154     } else {\r
1155       // allow access in any mode, like Gens does\r
1156       u16 *pm=(u16 *)(Pico_mcd->word_ram2M+(a&0x3fffe)); d = (pm[0]<<16)|pm[1];\r
1157     }\r
1158     wrdprintf("ret = %08x", d);\r
1159     goto end;\r
1160   }\r
1161 \r
1162   // word RAM (1M area)\r
1163   if ((a&0xfe0000)==0x0c0000 && (Pico_mcd->s68k_regs[3]&4)) { // 0c0000-0dffff\r
1164     int bank;\r
1165     u16 *pm;\r
1166     wrdprintf("s68k_wram1M r32: [%06x] @%06x", a, SekPcS68k);\r
1167 //    if (!(Pico_mcd->s68k_regs[3]&4))\r
1168 //      dprintf("s68k_wram1M FIXME: wrong mode");\r
1169     bank = (Pico_mcd->s68k_regs[3]&1)^1;\r
1170     pm=(u16 *)(Pico_mcd->word_ram1M[bank]+(a&0x1fffe)); d = (pm[0]<<16)|pm[1];\r
1171     wrdprintf("ret = %08x", d);\r
1172     goto end;\r
1173   }\r
1174 \r
1175   // PCM\r
1176   if ((a&0xff8000)==0xff0000) {\r
1177     dprintf("s68k_pcm r32: [%06x] @%06x", a, SekPcS68k);\r
1178     a &= 0x7fff;\r
1179     if (a >= 0x2000) {\r
1180       a >>= 1;\r
1181       d  = Pico_mcd->pcm_ram_b[Pico_mcd->pcm.bank][a&0xfff] << 16;\r
1182       d |= Pico_mcd->pcm_ram_b[Pico_mcd->pcm.bank][(a+1)&0xfff];\r
1183     } else if (a >= 0x20) {\r
1184       a &= 0x1e;\r
1185       if (a & 2) {\r
1186         a >>= 2;\r
1187         d  = (Pico_mcd->pcm.ch[a].addr >> (PCM_STEP_SHIFT-8)) & 0xff0000;\r
1188         d |= (Pico_mcd->pcm.ch[(a+1)&7].addr >> PCM_STEP_SHIFT)   & 0xff;\r
1189       } else {\r
1190         d = Pico_mcd->pcm.ch[a>>2].addr >> PCM_STEP_SHIFT;\r
1191         d = ((d<<16)&0xff0000) | ((d>>8)&0xff); // PCM chip is LE\r
1192       }\r
1193     }\r
1194     dprintf("ret = %08x", d);\r
1195     goto end;\r
1196   }\r
1197 \r
1198   // bram\r
1199   if ((a&0xff0000)==0xfe0000) {\r
1200     dprintf("FIXME: s68k_bram r32: [%06x] @%06x", a, SekPcS68k);\r
1201     a = (a>>1)&0x1fff;\r
1202     d = Pico_mcd->bram[a++] << 16;              // middle endian? TODO: verify against Fusion..\r
1203     d|= Pico_mcd->bram[a++] << 24;\r
1204     d|= Pico_mcd->bram[a++];\r
1205     d|= Pico_mcd->bram[a++] << 8;\r
1206     dprintf("ret = %08x", d);\r
1207     goto end;\r
1208   }\r
1209 \r
1210   elprintf(EL_UIO, "s68k r32: %06x, %08x @%06x", a&0xffffff, d, SekPcS68k);\r
1211 \r
1212   end:\r
1213 \r
1214   elprintf(EL_IO, "s68k r32: %06x, %08x @%06x", a&0xffffff, d, SekPcS68k);\r
1215 #ifdef EMU_CORE_DEBUG\r
1216   if (ab > 0x78) { // not vectors and stuff\r
1217     lastread_a = ab;\r
1218     lastread_d[lrp_cyc++&15] = d;\r
1219   }\r
1220 #endif\r
1221   return d;\r
1222 }\r
1223 #endif\r
1224 \r
1225 \r
1226 #ifndef _ASM_CD_MEMORY_C\r
1227 /* check: jaguar xj 220 (draws entire world using decode) */\r
1228 static void decode_write8(u32 a, u8 d, int r3)\r
1229 {\r
1230   u8 *pd = Pico_mcd->word_ram1M[(r3 & 1)^1] + (((a>>1)^1)&0x1ffff);\r
1231   u8 oldmask = (a&1) ? 0xf0 : 0x0f;\r
1232 \r
1233   r3 &= 0x18;\r
1234   d  &= 0x0f;\r
1235   if (!(a&1)) d <<= 4;\r
1236 \r
1237   if (r3 == 8) {\r
1238     if ((!(*pd & (~oldmask))) && d) goto do_it;\r
1239   } else if (r3 > 8) {\r
1240     if (d) goto do_it;\r
1241   } else {\r
1242     goto do_it;\r
1243   }\r
1244 \r
1245   return;\r
1246 do_it:\r
1247   *pd = d | (*pd & oldmask);\r
1248 }\r
1249 \r
1250 \r
1251 static void decode_write16(u32 a, u16 d, int r3)\r
1252 {\r
1253   u8 *pd = Pico_mcd->word_ram1M[(r3 & 1)^1] + (((a>>1)^1)&0x1ffff);\r
1254 \r
1255   //if ((a & 0x3ffff) < 0x28000) return;\r
1256 \r
1257   r3 &= 0x18;\r
1258   d  &= 0x0f0f;\r
1259   d  |= d >> 4;\r
1260 \r
1261   if (r3 == 8) {\r
1262     u8 dold = *pd;\r
1263     if (!(dold & 0xf0)) dold |= d & 0xf0;\r
1264     if (!(dold & 0x0f)) dold |= d & 0x0f;\r
1265     *pd = dold;\r
1266   } else if (r3 > 8) {\r
1267     u8 dold = *pd;\r
1268     if (!(d & 0xf0)) d |= dold & 0xf0;\r
1269     if (!(d & 0x0f)) d |= dold & 0x0f;\r
1270     *pd = d;\r
1271   } else {\r
1272     *pd = d;\r
1273   }\r
1274 }\r
1275 #endif\r
1276 \r
1277 // -----------------------------------------------------------------\r
1278 \r
1279 #ifdef _ASM_CD_MEMORY_C\r
1280 void PicoWriteS68k8(u32 a,u8 d);\r
1281 #else\r
1282 static void PicoWriteS68k8(u32 a,u8 d)\r
1283 {\r
1284   elprintf(EL_IO, "s68k w8 : %06x,   %02x @%06x", a&0xffffff, d, SekPcS68k);\r
1285 \r
1286   a&=0xffffff;\r
1287 \r
1288 #ifdef EMU_CORE_DEBUG\r
1289   lastwrite_cyc_d[lwp_cyc++&15] = d;\r
1290 #endif\r
1291 \r
1292   // prg RAM\r
1293   if (a < 0x80000) {\r
1294     u8 *pm=(u8 *)(Pico_mcd->prg_ram+(a^1));\r
1295     if (a >= (Pico_mcd->s68k_regs[2]<<8)) *pm=d;\r
1296     return;\r
1297   }\r
1298 \r
1299   // regs\r
1300   if ((a&0xfffe00) == 0xff8000) {\r
1301     a &= 0x1ff;\r
1302     rdprintf("s68k_regs w8: [%02x] %02x @ %06x", a, d, SekPcS68k);\r
1303     if (a >= 0x58 && a < 0x68)\r
1304          gfx_cd_write16(a&~1, (d<<8)|d);\r
1305     else s68k_reg_write8(a,d);\r
1306     return;\r
1307   }\r
1308 \r
1309   // word RAM (2M area)\r
1310   if ((a&0xfc0000)==0x080000) { // 080000-0bffff\r
1311     int r3 = Pico_mcd->s68k_regs[3];\r
1312     wrdprintf("s68k_wram2M w8: [%06x] %02x @%06x", a, d, SekPcS68k);\r
1313     if (r3 & 4) { // 1M decode mode?\r
1314       decode_write8(a, d, r3);\r
1315     } else {\r
1316       // allow access in any mode, like Gens does\r
1317       *(u8 *)(Pico_mcd->word_ram2M+((a^1)&0x3ffff))=d;\r
1318     }\r
1319     return;\r
1320   }\r
1321 \r
1322   // word RAM (1M area)\r
1323   if ((a&0xfe0000)==0x0c0000 && (Pico_mcd->s68k_regs[3]&4)) { // 0c0000-0dffff\r
1324     // Wing Commander tries to write here in wrong mode\r
1325     int bank;\r
1326     if (d)\r
1327       wrdprintf("s68k_wram1M w8: [%06x] %02x @%06x", a, d, SekPcS68k);\r
1328 //    if (!(Pico_mcd->s68k_regs[3]&4))\r
1329 //      dprintf("s68k_wram1M FIXME: wrong mode");\r
1330     bank = (Pico_mcd->s68k_regs[3]&1)^1;\r
1331     *(u8 *)(Pico_mcd->word_ram1M[bank]+((a^1)&0x1ffff))=d;\r
1332     return;\r
1333   }\r
1334 \r
1335   // PCM\r
1336   if ((a&0xff8000)==0xff0000) {\r
1337     a &= 0x7fff;\r
1338     if (a >= 0x2000)\r
1339       Pico_mcd->pcm_ram_b[Pico_mcd->pcm.bank][(a>>1)&0xfff] = d;\r
1340     else if (a < 0x12)\r
1341       pcm_write(a>>1, d);\r
1342     return;\r
1343   }\r
1344 \r
1345   // bram\r
1346   if ((a&0xff0000)==0xfe0000) {\r
1347     Pico_mcd->bram[(a>>1)&0x1fff] = d;\r
1348     SRam.changed = 1;\r
1349     return;\r
1350   }\r
1351 \r
1352   elprintf(EL_UIO, "s68k w8 : %06x,   %02x @%06x", a&0xffffff, d, SekPcS68k);\r
1353 }\r
1354 #endif\r
1355 \r
1356 \r
1357 #ifdef _ASM_CD_MEMORY_C\r
1358 void PicoWriteS68k16(u32 a,u16 d);\r
1359 #else\r
1360 static void PicoWriteS68k16(u32 a,u16 d)\r
1361 {\r
1362   elprintf(EL_IO, "s68k w16: %06x, %04x @%06x", a&0xffffff, d, SekPcS68k);\r
1363 \r
1364   a&=0xfffffe;\r
1365 \r
1366 #ifdef EMU_CORE_DEBUG\r
1367   lastwrite_cyc_d[lwp_cyc++&15] = d;\r
1368 #endif\r
1369 \r
1370   // prg RAM\r
1371   if (a < 0x80000) {\r
1372     wrdprintf("s68k_prgram w16: [%06x] %04x @%06x", a, d, SekPcS68k);\r
1373     if (a >= (Pico_mcd->s68k_regs[2]<<8)) // needed for Dungeon Explorer\r
1374       *(u16 *)(Pico_mcd->prg_ram+a)=d;\r
1375     return;\r
1376   }\r
1377 \r
1378   // regs\r
1379   if ((a&0xfffe00) == 0xff8000) {\r
1380     a &= 0x1fe;\r
1381     rdprintf("s68k_regs w16: [%02x] %04x @ %06x", a, d, SekPcS68k);\r
1382     if (a >= 0x58 && a < 0x68)\r
1383       gfx_cd_write16(a, d);\r
1384     else {\r
1385       if (a == 0xe) { // special case, 2 byte writes would be handled differently\r
1386         Pico_mcd->s68k_regs[0xf] = d;\r
1387         return;\r
1388       }\r
1389       s68k_reg_write8(a,  d>>8);\r
1390       s68k_reg_write8(a+1,d&0xff);\r
1391     }\r
1392     return;\r
1393   }\r
1394 \r
1395   // word RAM (2M area)\r
1396   if ((a&0xfc0000)==0x080000) { // 080000-0bffff\r
1397     int r3 = Pico_mcd->s68k_regs[3];\r
1398     wrdprintf("s68k_wram2M w16: [%06x] %04x @%06x", a, d, SekPcS68k);\r
1399     if (r3 & 4) { // 1M decode mode?\r
1400       decode_write16(a, d, r3);\r
1401     } else {\r
1402       // allow access in any mode, like Gens does\r
1403       *(u16 *)(Pico_mcd->word_ram2M+(a&0x3fffe))=d;\r
1404     }\r
1405     return;\r
1406   }\r
1407 \r
1408   // word RAM (1M area)\r
1409   if ((a&0xfe0000)==0x0c0000 && (Pico_mcd->s68k_regs[3]&4)) { // 0c0000-0dffff\r
1410     int bank;\r
1411     if (d)\r
1412       wrdprintf("s68k_wram1M w16: [%06x] %04x @%06x", a, d, SekPcS68k);\r
1413 //    if (!(Pico_mcd->s68k_regs[3]&4))\r
1414 //      dprintf("s68k_wram1M FIXME: wrong mode");\r
1415     bank = (Pico_mcd->s68k_regs[3]&1)^1;\r
1416     *(u16 *)(Pico_mcd->word_ram1M[bank]+(a&0x1fffe))=d;\r
1417     return;\r
1418   }\r
1419 \r
1420   // PCM\r
1421   if ((a&0xff8000)==0xff0000) {\r
1422     a &= 0x7fff;\r
1423     if (a >= 0x2000)\r
1424       Pico_mcd->pcm_ram_b[Pico_mcd->pcm.bank][(a>>1)&0xfff] = d;\r
1425     else if (a < 0x12)\r
1426       pcm_write(a>>1, d & 0xff);\r
1427     return;\r
1428   }\r
1429 \r
1430   // bram\r
1431   if ((a&0xff0000)==0xfe0000) {\r
1432     dprintf("s68k_bram w16: [%06x] %04x @%06x", a, d, SekPcS68k);\r
1433     a = (a>>1)&0x1fff;\r
1434     Pico_mcd->bram[a++] = d;            // Gens does little endian here, an so do we..\r
1435     Pico_mcd->bram[a++] = d >> 8;\r
1436     SRam.changed = 1;\r
1437     return;\r
1438   }\r
1439 \r
1440   elprintf(EL_UIO, "s68k w16: %06x, %04x @%06x", a&0xffffff, d, SekPcS68k);\r
1441 }\r
1442 #endif\r
1443 \r
1444 \r
1445 #ifdef _ASM_CD_MEMORY_C\r
1446 void PicoWriteS68k32(u32 a,u32 d);\r
1447 #else\r
1448 static void PicoWriteS68k32(u32 a,u32 d)\r
1449 {\r
1450   elprintf(EL_IO, "s68k w32: %06x, %08x @%06x", a&0xffffff, d, SekPcS68k);\r
1451 \r
1452   a&=0xfffffe;\r
1453 \r
1454 #ifdef EMU_CORE_DEBUG\r
1455   lastwrite_cyc_d[lwp_cyc++&15] = d;\r
1456 #endif\r
1457 \r
1458   // prg RAM\r
1459   if (a < 0x80000) {\r
1460     if (a >= (Pico_mcd->s68k_regs[2]<<8)) {\r
1461       u16 *pm=(u16 *)(Pico_mcd->prg_ram+a);\r
1462       pm[0]=(u16)(d>>16); pm[1]=(u16)d;\r
1463     }\r
1464     return;\r
1465   }\r
1466 \r
1467   // regs\r
1468   if ((a&0xfffe00) == 0xff8000) {\r
1469     a &= 0x1fe;\r
1470     rdprintf("s68k_regs w32: [%02x] %08x @ %06x", a, d, SekPcS68k);\r
1471     if (a >= 0x58 && a < 0x68) {\r
1472       gfx_cd_write16(a,   d>>16);\r
1473       gfx_cd_write16(a+2, d&0xffff);\r
1474     } else {\r
1475       if ((a&0x1fe) == 0xe) dprintf("s68k FIXME: w32 [%02x]", a&0x3f);\r
1476       s68k_reg_write8(a,   d>>24);\r
1477       s68k_reg_write8(a+1,(d>>16)&0xff);\r
1478       s68k_reg_write8(a+2,(d>>8) &0xff);\r
1479       s68k_reg_write8(a+3, d     &0xff);\r
1480     }\r
1481     return;\r
1482   }\r
1483 \r
1484   // word RAM (2M area)\r
1485   if ((a&0xfc0000)==0x080000) { // 080000-0bffff\r
1486     int r3 = Pico_mcd->s68k_regs[3];\r
1487     wrdprintf("s68k_wram2M w32: [%06x] %08x @%06x", a, d, SekPcS68k);\r
1488     if (r3 & 4) { // 1M decode mode?\r
1489       decode_write16(a  , d >> 16, r3);\r
1490       decode_write16(a+2, d      , r3);\r
1491     } else {\r
1492       // allow access in any mode, like Gens does\r
1493       u16 *pm=(u16 *)(Pico_mcd->word_ram2M+(a&0x3fffe));\r
1494       pm[0]=(u16)(d>>16); pm[1]=(u16)d;\r
1495     }\r
1496     return;\r
1497   }\r
1498 \r
1499   // word RAM (1M area)\r
1500   if ((a&0xfe0000)==0x0c0000 && (Pico_mcd->s68k_regs[3]&4)) { // 0c0000-0dffff\r
1501     int bank;\r
1502     u16 *pm;\r
1503     if (d)\r
1504       wrdprintf("s68k_wram1M w32: [%06x] %08x @%06x", a, d, SekPcS68k);\r
1505 //    if (!(Pico_mcd->s68k_regs[3]&4))\r
1506 //      dprintf("s68k_wram1M FIXME: wrong mode");\r
1507     bank = (Pico_mcd->s68k_regs[3]&1)^1;\r
1508     pm=(u16 *)(Pico_mcd->word_ram1M[bank]+(a&0x1fffe));\r
1509     pm[0]=(u16)(d>>16); pm[1]=(u16)d;\r
1510     return;\r
1511   }\r
1512 \r
1513   // PCM\r
1514   if ((a&0xff8000)==0xff0000) {\r
1515     a &= 0x7fff;\r
1516     if (a >= 0x2000) {\r
1517       a >>= 1;\r
1518       Pico_mcd->pcm_ram_b[Pico_mcd->pcm.bank][a&0xfff] = (d >> 16);\r
1519       Pico_mcd->pcm_ram_b[Pico_mcd->pcm.bank][(a+1)&0xfff] = d;\r
1520     } else if (a < 0x12) {\r
1521       a >>= 1;\r
1522       pcm_write(a,  (d>>16) & 0xff);\r
1523       pcm_write(a+1, d & 0xff);\r
1524     }\r
1525     return;\r
1526   }\r
1527 \r
1528   // bram\r
1529   if ((a&0xff0000)==0xfe0000) {\r
1530     dprintf("s68k_bram w32: [%06x] %08x @%06x", a, d, SekPcS68k);\r
1531     a = (a>>1)&0x1fff;\r
1532     Pico_mcd->bram[a++] = d >> 16;              // middle endian? verify?\r
1533     Pico_mcd->bram[a++] = d >> 24;\r
1534     Pico_mcd->bram[a++] = d;\r
1535     Pico_mcd->bram[a++] = d >> 8;\r
1536     SRam.changed = 1;\r
1537     return;\r
1538   }\r
1539 \r
1540   elprintf(EL_UIO, "s68k w32: %06x, %08x @%06x", a&0xffffff, d, SekPcS68k);\r
1541 }\r
1542 #endif\r
1543 \r
1544 \r
1545 // -----------------------------------------------------------------\r
1546 \r
1547 \r
1548 #ifdef EMU_C68K\r
1549 static __inline int PicoMemBaseM68k(u32 pc)\r
1550 {\r
1551   if ((pc&0xe00000)==0xe00000)\r
1552     return (int)Pico.ram-(pc&0xff0000); // Program Counter in Ram\r
1553 \r
1554   if (pc < 0x20000)\r
1555     return (int)Pico_mcd->bios; // Program Counter in BIOS\r
1556 \r
1557   if ((pc&0xfc0000)==0x200000)\r
1558   {\r
1559     if (!(Pico_mcd->s68k_regs[3]&4))\r
1560       return (int)Pico_mcd->word_ram2M - 0x200000; // Program Counter in Word Ram\r
1561     if (pc < 0x220000) {\r
1562       int bank = Pico_mcd->s68k_regs[3]&1;\r
1563       return (int)Pico_mcd->word_ram1M[bank] - 0x200000;\r
1564     }\r
1565   }\r
1566 \r
1567   // Error - Program Counter is invalid\r
1568   elprintf(EL_ANOMALY, "m68k FIXME: unhandled jump to %06x", pc);\r
1569 \r
1570   return (int)Pico_mcd->bios;\r
1571 }\r
1572 \r
1573 \r
1574 static u32 PicoCheckPcM68k(u32 pc)\r
1575 {\r
1576   pc-=PicoCpuCM68k.membase; // Get real pc\r
1577   pc&=0xfffffe;\r
1578 \r
1579   PicoCpuCM68k.membase=PicoMemBaseM68k(pc);\r
1580 \r
1581   return PicoCpuCM68k.membase+pc;\r
1582 }\r
1583 \r
1584 \r
1585 static __inline int PicoMemBaseS68k(u32 pc)\r
1586 {\r
1587   if (pc < 0x80000)                     // PRG RAM\r
1588     return (int)Pico_mcd->prg_ram;\r
1589 \r
1590   if ((pc&0xfc0000)==0x080000)          // WORD RAM 2M area (assume we are in the right mode..)\r
1591     return (int)Pico_mcd->word_ram2M - 0x080000;\r
1592 \r
1593   if ((pc&0xfe0000)==0x0c0000) {        // word RAM 1M area\r
1594     int bank = (Pico_mcd->s68k_regs[3]&1)^1;\r
1595     return (int)Pico_mcd->word_ram1M[bank] - 0x0c0000;\r
1596   }\r
1597 \r
1598   // Error - Program Counter is invalid\r
1599   elprintf(EL_ANOMALY, "s68k FIXME: unhandled jump to %06x", pc);\r
1600 \r
1601   return (int)Pico_mcd->prg_ram;\r
1602 }\r
1603 \r
1604 \r
1605 static u32 PicoCheckPcS68k(u32 pc)\r
1606 {\r
1607   pc-=PicoCpuCS68k.membase; // Get real pc\r
1608   pc&=0xfffffe;\r
1609 \r
1610   PicoCpuCS68k.membase=PicoMemBaseS68k(pc);\r
1611 \r
1612   return PicoCpuCS68k.membase+pc;\r
1613 }\r
1614 #endif\r
1615 \r
1616 #ifndef _ASM_CD_MEMORY_C\r
1617 void PicoMemResetCD(int r3)\r
1618 {\r
1619 #ifdef EMU_F68K\r
1620   // update fetchmap..\r
1621   int i;\r
1622   if (!(r3 & 4))\r
1623   {\r
1624     for (i = M68K_FETCHBANK1*2/16; (i<<(24-FAMEC_FETCHBITS)) < 0x240000; i++)\r
1625       PicoCpuFM68k.Fetch[i] = (unsigned int)Pico_mcd->word_ram2M - 0x200000;\r
1626   }\r
1627   else\r
1628   {\r
1629     for (i = M68K_FETCHBANK1*2/16; (i<<(24-FAMEC_FETCHBITS)) < 0x220000; i++)\r
1630       PicoCpuFM68k.Fetch[i] = (unsigned int)Pico_mcd->word_ram1M[r3 & 1] - 0x200000;\r
1631     for (i = M68K_FETCHBANK1*0x0c/0x100; (i<<(24-FAMEC_FETCHBITS)) < 0x0e0000; i++)\r
1632       PicoCpuFS68k.Fetch[i] = (unsigned int)Pico_mcd->word_ram1M[(r3&1)^1] - 0x0c0000;\r
1633   }\r
1634 #endif\r
1635 }\r
1636 #endif\r
1637 \r
1638 #ifdef EMU_M68K\r
1639 static void m68k_mem_setup_cd(void);\r
1640 #endif\r
1641 \r
1642 PICO_INTERNAL void PicoMemSetupCD(void)\r
1643 {\r
1644   // additional handlers for common code\r
1645   PicoRead16Hook = OtherRead16End;\r
1646   PicoWrite8Hook = OtherWrite8End;\r
1647 \r
1648 #ifdef EMU_C68K\r
1649   // Setup m68k memory callbacks:\r
1650   PicoCpuCM68k.checkpc=PicoCheckPcM68k;\r
1651   PicoCpuCM68k.fetch8 =PicoCpuCM68k.read8 =PicoReadM68k8;\r
1652   PicoCpuCM68k.fetch16=PicoCpuCM68k.read16=PicoReadM68k16;\r
1653   PicoCpuCM68k.fetch32=PicoCpuCM68k.read32=PicoReadM68k32;\r
1654   PicoCpuCM68k.write8 =PicoWriteM68k8;\r
1655   PicoCpuCM68k.write16=PicoWriteM68k16;\r
1656   PicoCpuCM68k.write32=PicoWriteM68k32;\r
1657   // s68k\r
1658   PicoCpuCS68k.checkpc=PicoCheckPcS68k;\r
1659   PicoCpuCS68k.fetch8 =PicoCpuCS68k.read8 =PicoReadS68k8;\r
1660   PicoCpuCS68k.fetch16=PicoCpuCS68k.read16=PicoReadS68k16;\r
1661   PicoCpuCS68k.fetch32=PicoCpuCS68k.read32=PicoReadS68k32;\r
1662   PicoCpuCS68k.write8 =PicoWriteS68k8;\r
1663   PicoCpuCS68k.write16=PicoWriteS68k16;\r
1664   PicoCpuCS68k.write32=PicoWriteS68k32;\r
1665 #endif\r
1666 #ifdef EMU_F68K\r
1667   // m68k\r
1668   PicoCpuFM68k.read_byte =PicoReadM68k8;\r
1669   PicoCpuFM68k.read_word =PicoReadM68k16;\r
1670   PicoCpuFM68k.read_long =PicoReadM68k32;\r
1671   PicoCpuFM68k.write_byte=PicoWriteM68k8;\r
1672   PicoCpuFM68k.write_word=PicoWriteM68k16;\r
1673   PicoCpuFM68k.write_long=PicoWriteM68k32;\r
1674   // s68k\r
1675   PicoCpuFS68k.read_byte =PicoReadS68k8;\r
1676   PicoCpuFS68k.read_word =PicoReadS68k16;\r
1677   PicoCpuFS68k.read_long =PicoReadS68k32;\r
1678   PicoCpuFS68k.write_byte=PicoWriteS68k8;\r
1679   PicoCpuFS68k.write_word=PicoWriteS68k16;\r
1680   PicoCpuFS68k.write_long=PicoWriteS68k32;\r
1681 \r
1682   // setup FAME fetchmap\r
1683   {\r
1684     int i;\r
1685     // M68k\r
1686     // by default, point everything to fitst 64k of ROM (BIOS)\r
1687     for (i = 0; i < M68K_FETCHBANK1; i++)\r
1688       PicoCpuFM68k.Fetch[i] = (unsigned int)Pico.rom - (i<<(24-FAMEC_FETCHBITS));\r
1689     // now real ROM (BIOS)\r
1690     for (i = 0; i < M68K_FETCHBANK1 && (i<<(24-FAMEC_FETCHBITS)) < Pico.romsize; i++)\r
1691       PicoCpuFM68k.Fetch[i] = (unsigned int)Pico.rom;\r
1692     // .. and RAM\r
1693     for (i = M68K_FETCHBANK1*14/16; i < M68K_FETCHBANK1; i++)\r
1694       PicoCpuFM68k.Fetch[i] = (unsigned int)Pico.ram - (i<<(24-FAMEC_FETCHBITS));\r
1695     // S68k\r
1696     // PRG RAM is default\r
1697     for (i = 0; i < M68K_FETCHBANK1; i++)\r
1698       PicoCpuFS68k.Fetch[i] = (unsigned int)Pico_mcd->prg_ram - (i<<(24-FAMEC_FETCHBITS));\r
1699     // real PRG RAM\r
1700     for (i = 0; i < M68K_FETCHBANK1 && (i<<(24-FAMEC_FETCHBITS)) < 0x80000; i++)\r
1701       PicoCpuFS68k.Fetch[i] = (unsigned int)Pico_mcd->prg_ram;\r
1702     // WORD RAM 2M area\r
1703     for (i = M68K_FETCHBANK1*0x08/0x100; i < M68K_FETCHBANK1 && (i<<(24-FAMEC_FETCHBITS)) < 0xc0000; i++)\r
1704       PicoCpuFS68k.Fetch[i] = (unsigned int)Pico_mcd->word_ram2M - 0x80000;\r
1705     // PicoMemResetCD() will setup word ram for both\r
1706   }\r
1707 #endif\r
1708 #ifdef EMU_M68K\r
1709   m68k_mem_setup_cd();\r
1710 #endif\r
1711 \r
1712   // m68k_poll_addr = m68k_poll_cnt = 0;\r
1713   s68k_poll_adclk = s68k_poll_cnt = 0;\r
1714 }\r
1715 \r
1716 \r
1717 #ifdef EMU_M68K\r
1718 static unsigned int PicoReadCD8w (unsigned int a) {\r
1719         return m68ki_cpu_p == &PicoCpuMS68k ? PicoReadS68k8(a) : PicoReadM68k8(a);\r
1720 }\r
1721 static unsigned int PicoReadCD16w(unsigned int a) {\r
1722         return m68ki_cpu_p == &PicoCpuMS68k ? PicoReadS68k16(a) : PicoReadM68k16(a);\r
1723 }\r
1724 static unsigned int PicoReadCD32w(unsigned int a) {\r
1725         return m68ki_cpu_p == &PicoCpuMS68k ? PicoReadS68k32(a) : PicoReadM68k32(a);\r
1726 }\r
1727 static void PicoWriteCD8w (unsigned int a, unsigned char d) {\r
1728         if (m68ki_cpu_p == &PicoCpuMS68k) PicoWriteS68k8(a, d); else PicoWriteM68k8(a, d);\r
1729 }\r
1730 static void PicoWriteCD16w(unsigned int a, unsigned short d) {\r
1731         if (m68ki_cpu_p == &PicoCpuMS68k) PicoWriteS68k16(a, d); else PicoWriteM68k16(a, d);\r
1732 }\r
1733 static void PicoWriteCD32w(unsigned int a, unsigned int d) {\r
1734         if (m68ki_cpu_p == &PicoCpuMS68k) PicoWriteS68k32(a, d); else PicoWriteM68k32(a, d);\r
1735 }\r
1736 \r
1737 // these are allowed to access RAM\r
1738 static unsigned int  m68k_read_pcrelative_CD8 (unsigned int a)\r
1739 {\r
1740   a&=0xffffff;\r
1741   if(m68ki_cpu_p == &PicoCpuMS68k) {\r
1742     if (a < 0x80000) return *(u8 *)(Pico_mcd->prg_ram+(a^1)); // PRG Ram\r
1743     if ((a&0xfc0000)==0x080000 && !(Pico_mcd->s68k_regs[3]&4)) // word RAM (2M area: 080000-0bffff)\r
1744       return *(u8 *)(Pico_mcd->word_ram2M+((a^1)&0x3ffff));\r
1745     if ((a&0xfe0000)==0x0c0000 &&  (Pico_mcd->s68k_regs[3]&4)) { // word RAM (1M area: 0c0000-0dffff)\r
1746       int bank = (Pico_mcd->s68k_regs[3]&1)^1;\r
1747       return *(u8 *)(Pico_mcd->word_ram1M[bank]+((a^1)&0x1ffff));\r
1748     }\r
1749     elprintf(EL_ANOMALY, "s68k_read_pcrelative_CD8 FIXME: can't handle %06x", a);\r
1750   } else {\r
1751     if((a&0xe00000)==0xe00000) return *(u8 *)(Pico.ram+((a^1)&0xffff)); // Ram\r
1752     if(a<0x20000)              return *(u8 *)(Pico.rom+(a^1)); // Bios\r
1753     if((a&0xfc0000)==0x200000) { // word RAM\r
1754       if(!(Pico_mcd->s68k_regs[3]&4)) // 2M?\r
1755         return *(u8 *)(Pico_mcd->word_ram2M+((a^1)&0x3ffff));\r
1756       else if (a < 0x220000) {\r
1757         int bank = Pico_mcd->s68k_regs[3]&1;\r
1758         return *(u8 *)(Pico_mcd->word_ram1M[bank]+((a^1)&0x1ffff));\r
1759       }\r
1760     }\r
1761     elprintf(EL_ANOMALY, "m68k_read_pcrelative_CD8 FIXME: can't handle %06x", a);\r
1762   }\r
1763   return 0;//(u8)  lastread_d;\r
1764 }\r
1765 static unsigned int  m68k_read_pcrelative_CD16(unsigned int a)\r
1766 {\r
1767   a&=0xffffff;\r
1768   if(m68ki_cpu_p == &PicoCpuMS68k) {\r
1769     if (a < 0x80000) return *(u16 *)(Pico_mcd->prg_ram+(a&~1)); // PRG Ram\r
1770     if ((a&0xfc0000)==0x080000 && !(Pico_mcd->s68k_regs[3]&4)) // word RAM (2M area: 080000-0bffff)\r
1771       return *(u16 *)(Pico_mcd->word_ram2M+(a&0x3fffe));\r
1772     if ((a&0xfe0000)==0x0c0000 &&  (Pico_mcd->s68k_regs[3]&4)) { // word RAM (1M area: 0c0000-0dffff)\r
1773       int bank = (Pico_mcd->s68k_regs[3]&1)^1;\r
1774       return *(u16 *)(Pico_mcd->word_ram1M[bank]+(a&0x1fffe));\r
1775     }\r
1776     elprintf(EL_ANOMALY, "s68k_read_pcrelative_CD16 FIXME: can't handle %06x", a);\r
1777   } else {\r
1778     if((a&0xe00000)==0xe00000) return *(u16 *)(Pico.ram+(a&0xfffe)); // Ram\r
1779     if(a<0x20000)              return *(u16 *)(Pico.rom+(a&~1)); // Bios\r
1780     if((a&0xfc0000)==0x200000) { // word RAM\r
1781       if(!(Pico_mcd->s68k_regs[3]&4)) // 2M?\r
1782         return *(u16 *)(Pico_mcd->word_ram2M+(a&0x3fffe));\r
1783       else if (a < 0x220000) {\r
1784         int bank = Pico_mcd->s68k_regs[3]&1;\r
1785         return *(u16 *)(Pico_mcd->word_ram1M[bank]+(a&0x1fffe));\r
1786       }\r
1787     }\r
1788     elprintf(EL_ANOMALY, "m68k_read_pcrelative_CD16 FIXME: can't handle %06x", a);\r
1789   }\r
1790   return 0;\r
1791 }\r
1792 static unsigned int  m68k_read_pcrelative_CD32(unsigned int a)\r
1793 {\r
1794   u16 *pm;\r
1795   a&=0xffffff;\r
1796   if(m68ki_cpu_p == &PicoCpuMS68k) {\r
1797     if (a < 0x80000) { u16 *pm=(u16 *)(Pico_mcd->prg_ram+(a&~1)); return (pm[0]<<16)|pm[1]; } // PRG Ram\r
1798     if ((a&0xfc0000)==0x080000 && !(Pico_mcd->s68k_regs[3]&4)) // word RAM (2M area: 080000-0bffff)\r
1799       { pm=(u16 *)(Pico_mcd->word_ram2M+(a&0x3fffe)); return (pm[0]<<16)|pm[1]; }\r
1800     if ((a&0xfe0000)==0x0c0000 &&  (Pico_mcd->s68k_regs[3]&4)) { // word RAM (1M area: 0c0000-0dffff)\r
1801       int bank = (Pico_mcd->s68k_regs[3]&1)^1;\r
1802       pm=(u16 *)(Pico_mcd->word_ram1M[bank]+(a&0x1fffe));\r
1803       return (pm[0]<<16)|pm[1];\r
1804     }\r
1805     elprintf(EL_ANOMALY, "s68k_read_pcrelative_CD32 FIXME: can't handle %06x", a);\r
1806   } else {\r
1807     if((a&0xe00000)==0xe00000) { u16 *pm=(u16 *)(Pico.ram+(a&0xfffe)); return (pm[0]<<16)|pm[1]; } // Ram\r
1808     if(a<0x20000)              { u16 *pm=(u16 *)(Pico.rom+(a&~1));     return (pm[0]<<16)|pm[1]; }\r
1809     if((a&0xfc0000)==0x200000) { // word RAM\r
1810       if(!(Pico_mcd->s68k_regs[3]&4)) // 2M?\r
1811         { pm=(u16 *)(Pico_mcd->word_ram2M+(a&0x3fffe)); return (pm[0]<<16)|pm[1]; }\r
1812       else if (a < 0x220000) {\r
1813         int bank = Pico_mcd->s68k_regs[3]&1;\r
1814         pm=(u16 *)(Pico_mcd->word_ram1M[bank]+(a&0x1fffe));\r
1815         return (pm[0]<<16)|pm[1];\r
1816       }\r
1817     }\r
1818     elprintf(EL_ANOMALY, "m68k_read_pcrelative_CD32 FIXME: can't handle %06x", a);\r
1819   }\r
1820   return 0;\r
1821 }\r
1822 \r
1823 extern unsigned int (*pm68k_read_memory_8) (unsigned int address);\r
1824 extern unsigned int (*pm68k_read_memory_16)(unsigned int address);\r
1825 extern unsigned int (*pm68k_read_memory_32)(unsigned int address);\r
1826 extern void (*pm68k_write_memory_8) (unsigned int address, unsigned char  value);\r
1827 extern void (*pm68k_write_memory_16)(unsigned int address, unsigned short value);\r
1828 extern void (*pm68k_write_memory_32)(unsigned int address, unsigned int   value);\r
1829 extern unsigned int (*pm68k_read_memory_pcr_8) (unsigned int address);\r
1830 extern unsigned int (*pm68k_read_memory_pcr_16)(unsigned int address);\r
1831 extern unsigned int (*pm68k_read_memory_pcr_32)(unsigned int address);\r
1832 \r
1833 static void m68k_mem_setup_cd(void)\r
1834 {\r
1835   pm68k_read_memory_8  = PicoReadCD8w;\r
1836   pm68k_read_memory_16 = PicoReadCD16w;\r
1837   pm68k_read_memory_32 = PicoReadCD32w;\r
1838   pm68k_write_memory_8  = PicoWriteCD8w;\r
1839   pm68k_write_memory_16 = PicoWriteCD16w;\r
1840   pm68k_write_memory_32 = PicoWriteCD32w;\r
1841   pm68k_read_memory_pcr_8  = m68k_read_pcrelative_CD8;\r
1842   pm68k_read_memory_pcr_16 = m68k_read_pcrelative_CD16;\r
1843   pm68k_read_memory_pcr_32 = m68k_read_pcrelative_CD32;\r
1844 }\r
1845 #endif // EMU_M68K\r
1846 \r