6890b57611cd790d9e4a13d6bee36d5d407ac886
[picodrive.git] / pico / cd / memory.c
1 /*\r
2  * Memory I/O handlers for Sega/Mega CD.\r
3  * (C) notaz, 2007-2009\r
4  *\r
5  * This work is licensed under the terms of MAME license.\r
6  * See COPYING file in the top-level directory.\r
7  */\r
8 \r
9 #include "../pico_int.h"\r
10 #include "../memory.h"\r
11 \r
12 uptr s68k_read8_map  [0x1000000 >> M68K_MEM_SHIFT];\r
13 uptr s68k_read16_map [0x1000000 >> M68K_MEM_SHIFT];\r
14 uptr s68k_write8_map [0x1000000 >> M68K_MEM_SHIFT];\r
15 uptr s68k_write16_map[0x1000000 >> M68K_MEM_SHIFT];\r
16 \r
17 MAKE_68K_READ8(s68k_read8, s68k_read8_map)\r
18 MAKE_68K_READ16(s68k_read16, s68k_read16_map)\r
19 MAKE_68K_READ32(s68k_read32, s68k_read16_map)\r
20 MAKE_68K_WRITE8(s68k_write8, s68k_write8_map)\r
21 MAKE_68K_WRITE16(s68k_write16, s68k_write16_map)\r
22 MAKE_68K_WRITE32(s68k_write32, s68k_write16_map)\r
23 \r
24 // -----------------------------------------------------------------\r
25 \r
26 // provided by ASM code:\r
27 #ifdef _ASM_CD_MEMORY_C\r
28 u32 PicoReadS68k8_pr(u32 a);\r
29 u32 PicoReadS68k16_pr(u32 a);\r
30 void PicoWriteS68k8_pr(u32 a, u32 d);\r
31 void PicoWriteS68k16_pr(u32 a, u32 d);\r
32 \r
33 u32 PicoReadM68k8_cell0(u32 a);\r
34 u32 PicoReadM68k8_cell1(u32 a);\r
35 u32 PicoReadM68k16_cell0(u32 a);\r
36 u32 PicoReadM68k16_cell1(u32 a);\r
37 void PicoWriteM68k8_cell0(u32 a, u32 d);\r
38 void PicoWriteM68k8_cell1(u32 a, u32 d);\r
39 void PicoWriteM68k16_cell0(u32 a, u32 d);\r
40 void PicoWriteM68k16_cell1(u32 a, u32 d);\r
41 \r
42 u32 PicoReadS68k8_dec0(u32 a);\r
43 u32 PicoReadS68k8_dec1(u32 a);\r
44 u32 PicoReadS68k16_dec0(u32 a);\r
45 u32 PicoReadS68k16_dec1(u32 a);\r
46 void PicoWriteS68k8_dec_m0b0(u32 a, u32 d);\r
47 void PicoWriteS68k8_dec_m1b0(u32 a, u32 d);\r
48 void PicoWriteS68k8_dec_m2b0(u32 a, u32 d);\r
49 void PicoWriteS68k8_dec_m0b1(u32 a, u32 d);\r
50 void PicoWriteS68k8_dec_m1b1(u32 a, u32 d);\r
51 void PicoWriteS68k8_dec_m2b1(u32 a, u32 d);\r
52 void PicoWriteS68k16_dec_m0b0(u32 a, u32 d);\r
53 void PicoWriteS68k16_dec_m1b0(u32 a, u32 d);\r
54 void PicoWriteS68k16_dec_m2b0(u32 a, u32 d);\r
55 void PicoWriteS68k16_dec_m0b1(u32 a, u32 d);\r
56 void PicoWriteS68k16_dec_m1b1(u32 a, u32 d);\r
57 void PicoWriteS68k16_dec_m2b1(u32 a, u32 d);\r
58 #endif\r
59 \r
60 static void remap_prg_window(u32 r1, u32 r3);\r
61 static void remap_word_ram(u32 r3);\r
62 \r
63 // poller detection\r
64 #define POLL_LIMIT 16\r
65 #define POLL_CYCLES 64\r
66 \r
67 void m68k_comm_check(u32 a)\r
68 {\r
69   pcd_sync_s68k(SekCyclesDone(), 0);\r
70   if (a >= 0x0e && !Pico_mcd->m.need_sync) {\r
71     // there are cases when slave updates comm and only switches RAM\r
72     // over after that (mcd1b), so there must be a resync..\r
73     SekEndRun(64);\r
74     Pico_mcd->m.need_sync = 1;\r
75   }\r
76   if (SekNotPolling || a != Pico_mcd->m.m68k_poll_a) {\r
77     Pico_mcd->m.m68k_poll_a = a;\r
78     Pico_mcd->m.m68k_poll_cnt = 0;\r
79     SekNotPolling = 0;\r
80     return;\r
81   }\r
82   Pico_mcd->m.m68k_poll_cnt++;\r
83 }\r
84 \r
85 #ifndef _ASM_CD_MEMORY_C\r
86 static u32 m68k_reg_read16(u32 a)\r
87 {\r
88   u32 d = 0;\r
89   a &= 0x3e;\r
90 \r
91   switch (a) {\r
92     case 0:\r
93       // here IFL2 is always 0, just like in Gens\r
94       d = ((Pico_mcd->s68k_regs[0x33] << 13) & 0x8000)\r
95         | Pico_mcd->m.busreq;\r
96       goto end;\r
97     case 2:\r
98       m68k_comm_check(a);\r
99       d = (Pico_mcd->s68k_regs[a]<<8) | (Pico_mcd->s68k_regs[a+1]&0xc7);\r
100       elprintf(EL_CDREG3, "m68k_regs r3: %02x @%06x", (u8)d, SekPc);\r
101       goto end;\r
102     case 4:\r
103       d = Pico_mcd->s68k_regs[4]<<8;\r
104       goto end;\r
105     case 6:\r
106       d = *(u16 *)(Pico_mcd->bios + 0x72);\r
107       goto end;\r
108     case 8:\r
109       d = cdc_host_r();\r
110       goto end;\r
111     case 0xA:\r
112       elprintf(EL_UIO, "m68k FIXME: reserved read");\r
113       goto end;\r
114     case 0xC: // 384 cycle stopwatch timer\r
115       // ugh..\r
116       d = pcd_cycles_m68k_to_s68k(SekCyclesDone());\r
117       d = (d - Pico_mcd->m.stopwatch_base_c) / 384;\r
118       d &= 0x0fff;\r
119       elprintf(EL_CDREGS, "m68k stopwatch timer read (%04x)", d);\r
120       goto end;\r
121   }\r
122 \r
123   if (a < 0x30) {\r
124     // comm flag/cmd/status (0xE-0x2F)\r
125     m68k_comm_check(a);\r
126     d = (Pico_mcd->s68k_regs[a]<<8) | Pico_mcd->s68k_regs[a+1];\r
127     goto end;\r
128   }\r
129 \r
130   elprintf(EL_UIO, "m68k_regs FIXME invalid read @ %02x", a);\r
131 \r
132 end:\r
133   return d;\r
134 }\r
135 #endif\r
136 \r
137 #ifndef _ASM_CD_MEMORY_C\r
138 static\r
139 #endif\r
140 void m68k_reg_write8(u32 a, u32 d)\r
141 {\r
142   u32 dold;\r
143   a &= 0x3f;\r
144 \r
145   switch (a) {\r
146     case 0:\r
147       d &= 1;\r
148       if (d && (Pico_mcd->s68k_regs[0x33] & PCDS_IEN2)) {\r
149         elprintf(EL_INTS, "m68k: s68k irq 2");\r
150         pcd_sync_s68k(SekCyclesDone(), 0);\r
151         SekInterruptS68k(2);\r
152       }\r
153       return;\r
154     case 1:\r
155       d &= 3;\r
156       dold = Pico_mcd->m.busreq;\r
157       if (!(d & 1))\r
158         d |= 2; // verified: can't release bus on reset\r
159       if (dold == d)\r
160         return;\r
161 \r
162       pcd_sync_s68k(SekCyclesDone(), 0);\r
163 \r
164       if ((dold ^ d) & 1)\r
165         elprintf(EL_INTSW, "m68k: s68k reset %i", !(d&1));\r
166       if (!(d & 1))\r
167         Pico_mcd->m.state_flags |= PCD_ST_S68K_RST;\r
168       else if (d == 1 && (Pico_mcd->m.state_flags & PCD_ST_S68K_RST)) {\r
169         Pico_mcd->m.state_flags &= ~PCD_ST_S68K_RST;\r
170         elprintf(EL_CDREGS, "m68k: resetting s68k");\r
171         SekResetS68k();\r
172       }\r
173       if ((dold ^ d) & 2) {\r
174         elprintf(EL_INTSW, "m68k: s68k brq %i", d >> 1);\r
175         remap_prg_window(d, Pico_mcd->s68k_regs[3]);\r
176       }\r
177       Pico_mcd->m.busreq = d;\r
178       return;\r
179     case 2:\r
180       elprintf(EL_CDREGS, "m68k: prg wp=%02x", d);\r
181       Pico_mcd->s68k_regs[2] = d; // really use s68k side register\r
182       return;\r
183     case 3:\r
184       dold = Pico_mcd->s68k_regs[3];\r
185       elprintf(EL_CDREG3, "m68k_regs w3: %02x @%06x", (u8)d, SekPc);\r
186       if ((d ^ dold) & 0xc0) {\r
187         elprintf(EL_CDREGS, "m68k: prg bank: %i -> %i",\r
188           (Pico_mcd->s68k_regs[a]>>6), ((d>>6)&3));\r
189         remap_prg_window(Pico_mcd->m.busreq, d);\r
190       }\r
191 \r
192       // 2M mode state is tracked regardless of current mode\r
193       if (d & 2) {\r
194         Pico_mcd->m.dmna_ret_2m |= 2;\r
195         Pico_mcd->m.dmna_ret_2m &= ~1;\r
196       }\r
197       if (dold & 4) { // 1M mode\r
198         d ^= 2;       // 0 sets DMNA, 1 does nothing\r
199         d = (d & 0xc2) | (dold & 0x1f);\r
200       }\r
201       else\r
202         d = (d & 0xc0) | (dold & 0x1c) | Pico_mcd->m.dmna_ret_2m;\r
203 \r
204       goto write_comm;\r
205     case 6:\r
206       Pico_mcd->bios[0x72 + 1] = d; // simple hint vector changer\r
207       return;\r
208     case 7:\r
209       Pico_mcd->bios[0x72] = d;\r
210       elprintf(EL_CDREGS, "hint vector set to %04x%04x",\r
211         ((u16 *)Pico_mcd->bios)[0x70/2], ((u16 *)Pico_mcd->bios)[0x72/2]);\r
212       return;\r
213     case 0x0f:\r
214       a = 0x0e;\r
215     case 0x0e:\r
216       goto write_comm;\r
217   }\r
218 \r
219   if ((a&0xf0) == 0x10)\r
220     goto write_comm;\r
221 \r
222   elprintf(EL_UIO, "m68k FIXME: invalid write? [%02x] %02x", a, d);\r
223   return;\r
224 \r
225 write_comm:\r
226   if (d == Pico_mcd->s68k_regs[a])\r
227     return;\r
228 \r
229   pcd_sync_s68k(SekCyclesDone(), 0);\r
230   Pico_mcd->s68k_regs[a] = d;\r
231   if (Pico_mcd->m.s68k_poll_a == (a & ~1))\r
232   {\r
233     if (Pico_mcd->m.s68k_poll_cnt > POLL_LIMIT) {\r
234       elprintf(EL_CDPOLL, "s68k poll release, a=%02x", a);\r
235       SekSetStopS68k(0);\r
236     }\r
237     Pico_mcd->m.s68k_poll_a = 0;\r
238   }\r
239 }\r
240 \r
241 u32 s68k_poll_detect(u32 a, u32 d)\r
242 {\r
243 #ifdef USE_POLL_DETECT\r
244   u32 cycles, cnt = 0;\r
245   if (SekIsStoppedS68k())\r
246     return d;\r
247 \r
248   cycles = SekCyclesDoneS68k();\r
249   if (!SekNotPolling && a == Pico_mcd->m.s68k_poll_a) {\r
250     u32 clkdiff = cycles - Pico_mcd->m.s68k_poll_clk;\r
251     if (clkdiff <= POLL_CYCLES) {\r
252       cnt = Pico_mcd->m.s68k_poll_cnt + 1;\r
253       //printf("-- diff: %u, cnt = %i\n", clkdiff, cnt);\r
254       if (Pico_mcd->m.s68k_poll_cnt > POLL_LIMIT) {\r
255         SekSetStopS68k(1);\r
256         elprintf(EL_CDPOLL, "s68k poll detected @%06x, a=%02x",\r
257           SekPcS68k, a);\r
258       }\r
259     }\r
260   }\r
261   Pico_mcd->m.s68k_poll_a = a;\r
262   Pico_mcd->m.s68k_poll_clk = cycles;\r
263   Pico_mcd->m.s68k_poll_cnt = cnt;\r
264   SekNotPollingS68k = 0;\r
265 #endif\r
266   return d;\r
267 }\r
268 \r
269 #define READ_FONT_DATA(basemask) \\r
270 { \\r
271       unsigned int fnt = *(unsigned int *)(Pico_mcd->s68k_regs + 0x4c); \\r
272       unsigned int col0 = (fnt >> 8) & 0x0f, col1 = (fnt >> 12) & 0x0f;   \\r
273       if (fnt & (basemask << 0)) d  = col1      ; else d  = col0;       \\r
274       if (fnt & (basemask << 1)) d |= col1 <<  4; else d |= col0 <<  4; \\r
275       if (fnt & (basemask << 2)) d |= col1 <<  8; else d |= col0 <<  8; \\r
276       if (fnt & (basemask << 3)) d |= col1 << 12; else d |= col0 << 12; \\r
277 }\r
278 \r
279 \r
280 #ifndef _ASM_CD_MEMORY_C\r
281 static\r
282 #endif\r
283 u32 s68k_reg_read16(u32 a)\r
284 {\r
285   u32 d=0;\r
286 \r
287   switch (a) {\r
288     case 0:\r
289       return ((Pico_mcd->s68k_regs[0]&3)<<8) | 1; // ver = 0, not in reset state\r
290     case 2:\r
291       d = (Pico_mcd->s68k_regs[2]<<8) | (Pico_mcd->s68k_regs[3]&0x1f);\r
292       elprintf(EL_CDREG3, "s68k_regs r3: %02x @%06x", (u8)d, SekPcS68k);\r
293       return s68k_poll_detect(a, d);\r
294     case 6:\r
295       return cdc_reg_r();\r
296     case 8:\r
297       return cdc_host_r();\r
298     case 0xC:\r
299       d = SekCyclesDoneS68k() - Pico_mcd->m.stopwatch_base_c;\r
300       d /= 384;\r
301       d &= 0x0fff;\r
302       elprintf(EL_CDREGS, "s68k stopwatch timer read (%04x)", d);\r
303       return d;\r
304     case 0x30:\r
305       elprintf(EL_CDREGS, "s68k int3 timer read (%02x)", Pico_mcd->s68k_regs[31]);\r
306       return Pico_mcd->s68k_regs[31];\r
307     case 0x34: // fader\r
308       return 0; // no busy bit\r
309     case 0x50: // font data (check: Lunar 2, Silpheed)\r
310       READ_FONT_DATA(0x00100000);\r
311       return d;\r
312     case 0x52:\r
313       READ_FONT_DATA(0x00010000);\r
314       return d;\r
315     case 0x54:\r
316       READ_FONT_DATA(0x10000000);\r
317       return d;\r
318     case 0x56:\r
319       READ_FONT_DATA(0x01000000);\r
320       return d;\r
321   }\r
322 \r
323   d = (Pico_mcd->s68k_regs[a]<<8) | Pico_mcd->s68k_regs[a+1];\r
324 \r
325   if (a >= 0x0e && a < 0x30)\r
326     return s68k_poll_detect(a, d);\r
327 \r
328   return d;\r
329 }\r
330 \r
331 #ifndef _ASM_CD_MEMORY_C\r
332 static\r
333 #endif\r
334 void s68k_reg_write8(u32 a, u32 d)\r
335 {\r
336   // Warning: d might have upper bits set\r
337   switch (a) {\r
338     case 1:\r
339       if (!(d & 1))\r
340         pcd_soft_reset();\r
341       return;\r
342     case 2:\r
343       return; // only m68k can change WP\r
344     case 3: {\r
345       int dold = Pico_mcd->s68k_regs[3];\r
346       elprintf(EL_CDREG3, "s68k_regs w3: %02x @%06x", (u8)d, SekPcS68k);\r
347       d &= 0x1d;\r
348       d |= dold & 0xc2;\r
349 \r
350       // 2M mode state\r
351       if (d & 1) {\r
352         Pico_mcd->m.dmna_ret_2m |= 1;\r
353         Pico_mcd->m.dmna_ret_2m &= ~2; // DMNA clears\r
354       }\r
355 \r
356       if (d & 4)\r
357       {\r
358         if (!(dold & 4)) {\r
359           elprintf(EL_CDREG3, "wram mode 2M->1M");\r
360           wram_2M_to_1M(Pico_mcd->word_ram2M);\r
361         }\r
362 \r
363         if ((d ^ dold) & 0x1d)\r
364           remap_word_ram(d);\r
365 \r
366         if ((d ^ dold) & 0x05)\r
367           d &= ~2; // clear DMNA - swap complete\r
368       }\r
369       else\r
370       {\r
371         if (dold & 4) {\r
372           elprintf(EL_CDREG3, "wram mode 1M->2M");\r
373           wram_1M_to_2M(Pico_mcd->word_ram2M);\r
374           remap_word_ram(d);\r
375         }\r
376         d = (d & ~3) | Pico_mcd->m.dmna_ret_2m;\r
377       }\r
378       goto write_comm;\r
379     }\r
380     case 4:\r
381       elprintf(EL_CDREGS, "s68k CDC dest: %x", d&7);\r
382       Pico_mcd->s68k_regs[4] = (Pico_mcd->s68k_regs[4]&0xC0) | (d&7); // CDC mode\r
383       return;\r
384     case 5:\r
385       //dprintf("s68k CDC reg addr: %x", d&0xf);\r
386       break;\r
387     case 7:\r
388       cdc_reg_w(d & 0xff);\r
389       return;\r
390     case 0xa:\r
391       elprintf(EL_CDREGS, "s68k set CDC dma addr");\r
392       break;\r
393     case 0xc:\r
394     case 0xd: // 384 cycle stopwatch timer\r
395       elprintf(EL_CDREGS|EL_CD, "s68k clear stopwatch (%x)", d);\r
396       // does this also reset internal 384 cycle counter?\r
397       Pico_mcd->m.stopwatch_base_c = SekCyclesDoneS68k();\r
398       return;\r
399     case 0x0e:\r
400       a = 0x0f;\r
401     case 0x0f:\r
402       goto write_comm;\r
403     case 0x31: // 384 cycle int3 timer\r
404       d &= 0xff;\r
405       elprintf(EL_CDREGS|EL_CD, "s68k set int3 timer: %02x", d);\r
406       Pico_mcd->s68k_regs[a] = (u8) d;\r
407       if (d) // d or d+1??\r
408         pcd_event_schedule_s68k(PCD_EVENT_TIMER3, d * 384);\r
409       else\r
410         pcd_event_schedule(0, PCD_EVENT_TIMER3, 0);\r
411       break;\r
412     case 0x33: // IRQ mask\r
413       elprintf(EL_CDREGS|EL_CD, "s68k irq mask: %02x", d);\r
414       d &= 0x7e;\r
415       if ((d ^ Pico_mcd->s68k_regs[0x33]) & d & PCDS_IEN4) {\r
416         // XXX: emulate pending irq instead?\r
417         if (Pico_mcd->s68k_regs[0x37] & 4) {\r
418           elprintf(EL_INTS, "cdd export irq 4 (unmask)");\r
419           SekInterruptS68k(4);\r
420         }\r
421       }\r
422       break;\r
423     case 0x34: // fader\r
424       Pico_mcd->s68k_regs[a] = (u8) d & 0x7f;\r
425       return;\r
426     case 0x36:\r
427       return; // d/m bit is unsetable\r
428     case 0x37: {\r
429       u32 d_old = Pico_mcd->s68k_regs[0x37];\r
430       Pico_mcd->s68k_regs[0x37] = d & 7;\r
431       if ((d&4) && !(d_old&4)) {\r
432         // ??\r
433         pcd_event_schedule_s68k(PCD_EVENT_CDC, 12500000/75);\r
434 \r
435         if (Pico_mcd->s68k_regs[0x33] & PCDS_IEN4) {\r
436           elprintf(EL_INTS, "cdd export irq 4");\r
437           SekInterruptS68k(4);\r
438         }\r
439       }\r
440       return;\r
441     }\r
442     case 0x4b:\r
443       Pico_mcd->s68k_regs[a] = 0; // (u8) d; ?\r
444       cdd_process();\r
445       {\r
446         static const char *nm[] =\r
447           { "stat", "stop", "read_toc", "play",\r
448             "seek", "???",  "pause",    "resume",\r
449             "ff",   "fr",   "tjump",    "???",\r
450             "close","open", "???",      "???" };\r
451         u8 *c = &Pico_mcd->s68k_regs[0x42];\r
452         u8 *s = &Pico_mcd->s68k_regs[0x38];\r
453         elprintf(EL_CD,\r
454           "CDD command: %02x %02x %02x %02x %02x %02x %02x %02x %12s",\r
455           c[0], c[1], c[2], c[3], c[4], c[5], c[6], c[7], nm[c[0] & 0x0f]);\r
456         elprintf(EL_CD,\r
457           "CDD status:  %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x",\r
458           s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[8], s[9]);\r
459       }\r
460       return;\r
461     case 0x58:\r
462       return;\r
463   }\r
464 \r
465   if ((a&0x1f0) == 0x20)\r
466     goto write_comm;\r
467 \r
468   if ((a&0x1f0) == 0x10 || (a >= 0x38 && a < 0x42))\r
469   {\r
470     elprintf(EL_UIO, "s68k FIXME: invalid write @ %02x?", a);\r
471     return;\r
472   }\r
473 \r
474   Pico_mcd->s68k_regs[a] = (u8) d;\r
475   return;\r
476 \r
477 write_comm:\r
478   Pico_mcd->s68k_regs[a] = (u8) d;\r
479   if (Pico_mcd->m.m68k_poll_cnt)\r
480     SekEndRunS68k(0);\r
481   Pico_mcd->m.m68k_poll_cnt = 0;\r
482 }\r
483 \r
484 void s68k_reg_write16(u32 a, u32 d)\r
485 {\r
486   u8 *r = Pico_mcd->s68k_regs;\r
487 \r
488   if ((a & 0x1f0) == 0x20)\r
489     goto write_comm;\r
490 \r
491   switch (a) {\r
492     case 0x0e:\r
493       // special case, 2 byte writes would be handled differently\r
494       // TODO: verify\r
495       r[0xf] = d;\r
496       return;\r
497     case 0x58: // stamp data size\r
498       r[0x59] = d & 7;\r
499       return;\r
500     case 0x5a: // stamp map base address\r
501       r[0x5a] = d >> 8;\r
502       r[0x5b] = d & 0xe0;\r
503       return;\r
504     case 0x5c: // V cell size\r
505       r[0x5d] = d & 0x1f;\r
506       return;\r
507     case 0x5e: // image buffer start address\r
508       r[0x5e] = d >> 8;\r
509       r[0x5f] = d & 0xf8;\r
510       return;\r
511     case 0x60: // image buffer offset\r
512       r[0x61] = d & 0x3f;\r
513       return;\r
514     case 0x62: // h dot size\r
515       r[0x62] = (d >> 8) & 1;\r
516       r[0x63] = d;\r
517       return;\r
518     case 0x64: // v dot size\r
519       r[0x65] = d;\r
520       return;\r
521     case 0x66: // trace vector base address\r
522       d &= 0xfffe;\r
523       r[0x66] = d >> 8;\r
524       r[0x67] = d;\r
525       gfx_start(d);\r
526       return;\r
527     default:\r
528       break;\r
529   }\r
530 \r
531   s68k_reg_write8(a,     d >> 8);\r
532   s68k_reg_write8(a + 1, d & 0xff);\r
533   return;\r
534 \r
535 write_comm:\r
536   r[a] = d >> 8;\r
537   r[a + 1] = d;\r
538   if (Pico_mcd->m.m68k_poll_cnt)\r
539     SekEndRunS68k(0);\r
540   Pico_mcd->m.m68k_poll_cnt = 0;\r
541 }\r
542 \r
543 // -----------------------------------------------------------------\r
544 //                          Main 68k\r
545 // -----------------------------------------------------------------\r
546 \r
547 #ifndef _ASM_CD_MEMORY_C\r
548 #include "cell_map.c"\r
549 \r
550 // WORD RAM, cell aranged area (220000 - 23ffff)\r
551 static u32 PicoReadM68k8_cell0(u32 a)\r
552 {\r
553   a = (a&3) | (cell_map(a >> 2) << 2); // cell arranged\r
554   return Pico_mcd->word_ram1M[0][a ^ 1];\r
555 }\r
556 \r
557 static u32 PicoReadM68k8_cell1(u32 a)\r
558 {\r
559   a = (a&3) | (cell_map(a >> 2) << 2);\r
560   return Pico_mcd->word_ram1M[1][a ^ 1];\r
561 }\r
562 \r
563 static u32 PicoReadM68k16_cell0(u32 a)\r
564 {\r
565   a = (a&2) | (cell_map(a >> 2) << 2);\r
566   return *(u16 *)(Pico_mcd->word_ram1M[0] + a);\r
567 }\r
568 \r
569 static u32 PicoReadM68k16_cell1(u32 a)\r
570 {\r
571   a = (a&2) | (cell_map(a >> 2) << 2);\r
572   return *(u16 *)(Pico_mcd->word_ram1M[1] + a);\r
573 }\r
574 \r
575 static void PicoWriteM68k8_cell0(u32 a, u32 d)\r
576 {\r
577   a = (a&3) | (cell_map(a >> 2) << 2);\r
578   Pico_mcd->word_ram1M[0][a ^ 1] = d;\r
579 }\r
580 \r
581 static void PicoWriteM68k8_cell1(u32 a, u32 d)\r
582 {\r
583   a = (a&3) | (cell_map(a >> 2) << 2);\r
584   Pico_mcd->word_ram1M[1][a ^ 1] = d;\r
585 }\r
586 \r
587 static void PicoWriteM68k16_cell0(u32 a, u32 d)\r
588 {\r
589   a = (a&3) | (cell_map(a >> 2) << 2);\r
590   *(u16 *)(Pico_mcd->word_ram1M[0] + a) = d;\r
591 }\r
592 \r
593 static void PicoWriteM68k16_cell1(u32 a, u32 d)\r
594 {\r
595   a = (a&3) | (cell_map(a >> 2) << 2);\r
596   *(u16 *)(Pico_mcd->word_ram1M[1] + a) = d;\r
597 }\r
598 #endif\r
599 \r
600 // RAM cart (40000 - 7fffff, optional)\r
601 static u32 PicoReadM68k8_ramc(u32 a)\r
602 {\r
603   u32 d = 0;\r
604   if (a == 0x400001) {\r
605     if (Pico.sv.data != NULL)\r
606       d = 3; // 64k cart\r
607     return d;\r
608   }\r
609 \r
610   if ((a & 0xfe0000) == 0x600000) {\r
611     if (Pico.sv.data != NULL)\r
612       d = Pico.sv.data[((a >> 1) & 0xffff) + 0x2000];\r
613     return d;\r
614   }\r
615 \r
616   if (a == 0x7fffff)\r
617     return Pico_mcd->m.bcram_reg;\r
618 \r
619   elprintf(EL_UIO, "m68k unmapped r8  [%06x] @%06x", a, SekPc);\r
620   return d;\r
621 }\r
622 \r
623 static u32 PicoReadM68k16_ramc(u32 a)\r
624 {\r
625   elprintf(EL_ANOMALY, "ramcart r16: [%06x] @%06x", a, SekPcS68k);\r
626   return PicoReadM68k8_ramc(a + 1);\r
627 }\r
628 \r
629 static void PicoWriteM68k8_ramc(u32 a, u32 d)\r
630 {\r
631   if ((a & 0xfe0000) == 0x600000) {\r
632     if (Pico.sv.data != NULL && (Pico_mcd->m.bcram_reg & 1)) {\r
633       Pico.sv.data[((a>>1) & 0xffff) + 0x2000] = d;\r
634       Pico.sv.changed = 1;\r
635     }\r
636     return;\r
637   }\r
638 \r
639   if (a == 0x7fffff) {\r
640     Pico_mcd->m.bcram_reg = d;\r
641     return;\r
642   }\r
643 \r
644   elprintf(EL_UIO, "m68k unmapped w8  [%06x]   %02x @%06x",\r
645     a, d & 0xff, SekPc);\r
646 }\r
647 \r
648 static void PicoWriteM68k16_ramc(u32 a, u32 d)\r
649 {\r
650   elprintf(EL_ANOMALY, "ramcart w16: [%06x] %04x @%06x",\r
651     a, d, SekPcS68k);\r
652   PicoWriteM68k8_ramc(a + 1, d);\r
653 }\r
654 \r
655 // IO/control/cd registers (a10000 - ...)\r
656 #ifndef _ASM_CD_MEMORY_C\r
657 u32 PicoRead8_mcd_io(u32 a)\r
658 {\r
659   u32 d;\r
660   if ((a & 0xff00) == 0x2000) { // a12000 - a120ff\r
661     d = m68k_reg_read16(a); // TODO: m68k_reg_read8\r
662     if (!(a & 1))\r
663       d >>= 8;\r
664     d &= 0xff;\r
665     elprintf(EL_CDREGS, "m68k_regs r8:  [%02x]   %02x @%06x",\r
666       a & 0x3f, d, SekPc);\r
667     return d;\r
668   }\r
669 \r
670   // fallback to default MD handler\r
671   return PicoRead8_io(a);\r
672 }\r
673 \r
674 u32 PicoRead16_mcd_io(u32 a)\r
675 {\r
676   u32 d;\r
677   if ((a & 0xff00) == 0x2000) {\r
678     d = m68k_reg_read16(a);\r
679     elprintf(EL_CDREGS, "m68k_regs r16: [%02x] %04x @%06x",\r
680       a & 0x3f, d, SekPc);\r
681     return d;\r
682   }\r
683 \r
684   return PicoRead16_io(a);\r
685 }\r
686 \r
687 void PicoWrite8_mcd_io(u32 a, u32 d)\r
688 {\r
689   if ((a & 0xff00) == 0x2000) { // a12000 - a120ff\r
690     elprintf(EL_CDREGS, "m68k_regs w8:  [%02x]   %02x @%06x",\r
691       a & 0x3f, d, SekPc);\r
692     m68k_reg_write8(a, d);\r
693     return;\r
694   }\r
695 \r
696   PicoWrite8_io(a, d);\r
697 }\r
698 \r
699 void PicoWrite16_mcd_io(u32 a, u32 d)\r
700 {\r
701   if ((a & 0xff00) == 0x2000) { // a12000 - a120ff\r
702     elprintf(EL_CDREGS, "m68k_regs w16: [%02x] %04x @%06x",\r
703       a & 0x3f, d, SekPc);\r
704 \r
705     m68k_reg_write8(a, d >> 8);\r
706     if ((a & 0x3e) != 0x0e) // special case\r
707       m68k_reg_write8(a + 1, d & 0xff);\r
708     return;\r
709   }\r
710 \r
711   PicoWrite16_io(a, d);\r
712 }\r
713 #endif\r
714 \r
715 // -----------------------------------------------------------------\r
716 //                           Sub 68k\r
717 // -----------------------------------------------------------------\r
718 \r
719 static u32 s68k_unmapped_read8(u32 a)\r
720 {\r
721   elprintf(EL_UIO, "s68k unmapped r8  [%06x] @%06x", a, SekPc);\r
722   return 0;\r
723 }\r
724 \r
725 static u32 s68k_unmapped_read16(u32 a)\r
726 {\r
727   elprintf(EL_UIO, "s68k unmapped r16 [%06x] @%06x", a, SekPc);\r
728   return 0;\r
729 }\r
730 \r
731 static void s68k_unmapped_write8(u32 a, u32 d)\r
732 {\r
733   elprintf(EL_UIO, "s68k unmapped w8  [%06x]   %02x @%06x",\r
734     a, d & 0xff, SekPc);\r
735 }\r
736 \r
737 static void s68k_unmapped_write16(u32 a, u32 d)\r
738 {\r
739   elprintf(EL_UIO, "s68k unmapped w16 [%06x] %04x @%06x",\r
740     a, d & 0xffff, SekPc);\r
741 }\r
742 \r
743 // PRG RAM protected range (000000 - 01fdff)?\r
744 // XXX verify: ff00 or 1fe00 max?\r
745 static void PicoWriteS68k8_prgwp(u32 a, u32 d)\r
746 {\r
747   if (a >= (Pico_mcd->s68k_regs[2] << 9))\r
748     Pico_mcd->prg_ram[a ^ 1] = d;\r
749 }\r
750 \r
751 static void PicoWriteS68k16_prgwp(u32 a, u32 d)\r
752 {\r
753   if (a >= (Pico_mcd->s68k_regs[2] << 9))\r
754     *(u16 *)(Pico_mcd->prg_ram + a) = d;\r
755 }\r
756 \r
757 #ifndef _ASM_CD_MEMORY_C\r
758 \r
759 // decode (080000 - 0bffff, in 1M mode)\r
760 static u32 PicoReadS68k8_dec0(u32 a)\r
761 {\r
762   u32 d = Pico_mcd->word_ram1M[0][((a >> 1) ^ 1) & 0x1ffff];\r
763   if (a & 1)\r
764     d &= 0x0f;\r
765   else\r
766     d >>= 4;\r
767   return d;\r
768 }\r
769 \r
770 static u32 PicoReadS68k8_dec1(u32 a)\r
771 {\r
772   u32 d = Pico_mcd->word_ram1M[1][((a >> 1) ^ 1) & 0x1ffff];\r
773   if (a & 1)\r
774     d &= 0x0f;\r
775   else\r
776     d >>= 4;\r
777   return d;\r
778 }\r
779 \r
780 static u32 PicoReadS68k16_dec0(u32 a)\r
781 {\r
782   u32 d = Pico_mcd->word_ram1M[0][((a >> 1) ^ 1) & 0x1ffff];\r
783   d |= d << 4;\r
784   d &= ~0xf0;\r
785   return d;\r
786 }\r
787 \r
788 static u32 PicoReadS68k16_dec1(u32 a)\r
789 {\r
790   u32 d = Pico_mcd->word_ram1M[1][((a >> 1) ^ 1) & 0x1ffff];\r
791   d |= d << 4;\r
792   d &= ~0xf0;\r
793   return d;\r
794 }\r
795 \r
796 /* check: jaguar xj 220 (draws entire world using decode) */\r
797 #define mk_decode_w8(bank)                                        \\r
798 static void PicoWriteS68k8_dec_m0b##bank(u32 a, u32 d)            \\r
799 {                                                                 \\r
800   u8 *pd = &Pico_mcd->word_ram1M[bank][((a >> 1) ^ 1) & 0x1ffff]; \\r
801                                                                   \\r
802   if (!(a & 1))                                                   \\r
803     *pd = (*pd & 0x0f) | (d << 4);                                \\r
804   else                                                            \\r
805     *pd = (*pd & 0xf0) | (d & 0x0f);                              \\r
806 }                                                                 \\r
807                                                                   \\r
808 static void PicoWriteS68k8_dec_m1b##bank(u32 a, u32 d)            \\r
809 {                                                                 \\r
810   u8 *pd = &Pico_mcd->word_ram1M[bank][((a >> 1) ^ 1) & 0x1ffff]; \\r
811   u8 mask = (a & 1) ? 0x0f : 0xf0;                                \\r
812                                                                   \\r
813   if (!(*pd & mask) && (d & 0x0f)) /* underwrite */               \\r
814     PicoWriteS68k8_dec_m0b##bank(a, d);                           \\r
815 }                                                                 \\r
816                                                                   \\r
817 static void PicoWriteS68k8_dec_m2b##bank(u32 a, u32 d) /* ...and m3? */ \\r
818 {                                                                 \\r
819   if (d & 0x0f) /* overwrite */                                   \\r
820     PicoWriteS68k8_dec_m0b##bank(a, d);                           \\r
821 }\r
822 \r
823 mk_decode_w8(0)\r
824 mk_decode_w8(1)\r
825 \r
826 #define mk_decode_w16(bank)                                       \\r
827 static void PicoWriteS68k16_dec_m0b##bank(u32 a, u32 d)           \\r
828 {                                                                 \\r
829   u8 *pd = &Pico_mcd->word_ram1M[bank][((a >> 1) ^ 1) & 0x1ffff]; \\r
830                                                                   \\r
831   d &= 0x0f0f;                                                    \\r
832   *pd = d | (d >> 4);                                             \\r
833 }                                                                 \\r
834                                                                   \\r
835 static void PicoWriteS68k16_dec_m1b##bank(u32 a, u32 d)           \\r
836 {                                                                 \\r
837   u8 *pd = &Pico_mcd->word_ram1M[bank][((a >> 1) ^ 1) & 0x1ffff]; \\r
838                                                                   \\r
839   d &= 0x0f0f; /* underwrite */                                   \\r
840   if (!(*pd & 0xf0)) *pd |= d >> 4;                               \\r
841   if (!(*pd & 0x0f)) *pd |= d;                                    \\r
842 }                                                                 \\r
843                                                                   \\r
844 static void PicoWriteS68k16_dec_m2b##bank(u32 a, u32 d)           \\r
845 {                                                                 \\r
846   u8 *pd = &Pico_mcd->word_ram1M[bank][((a >> 1) ^ 1) & 0x1ffff]; \\r
847                                                                   \\r
848   d &= 0x0f0f; /* overwrite */                                    \\r
849   d |= d >> 4;                                                    \\r
850                                                                   \\r
851   if (!(d & 0xf0)) d |= *pd & 0xf0;                               \\r
852   if (!(d & 0x0f)) d |= *pd & 0x0f;                               \\r
853   *pd = d;                                                        \\r
854 }\r
855 \r
856 mk_decode_w16(0)\r
857 mk_decode_w16(1)\r
858 \r
859 #endif\r
860 \r
861 // backup RAM (fe0000 - feffff)\r
862 static u32 PicoReadS68k8_bram(u32 a)\r
863 {\r
864   return Pico_mcd->bram[(a>>1)&0x1fff];\r
865 }\r
866 \r
867 static u32 PicoReadS68k16_bram(u32 a)\r
868 {\r
869   u32 d;\r
870   elprintf(EL_ANOMALY, "FIXME: s68k_bram r16: [%06x] @%06x", a, SekPcS68k);\r
871   a = (a >> 1) & 0x1fff;\r
872   d = Pico_mcd->bram[a++];\r
873   d|= Pico_mcd->bram[a++] << 8; // probably wrong, TODO: verify\r
874   return d;\r
875 }\r
876 \r
877 static void PicoWriteS68k8_bram(u32 a, u32 d)\r
878 {\r
879   Pico_mcd->bram[(a >> 1) & 0x1fff] = d;\r
880   Pico.sv.changed = 1;\r
881 }\r
882 \r
883 static void PicoWriteS68k16_bram(u32 a, u32 d)\r
884 {\r
885   elprintf(EL_ANOMALY, "s68k_bram w16: [%06x] %04x @%06x", a, d, SekPcS68k);\r
886   a = (a >> 1) & 0x1fff;\r
887   Pico_mcd->bram[a++] = d;\r
888   Pico_mcd->bram[a++] = d >> 8; // TODO: verify..\r
889   Pico.sv.changed = 1;\r
890 }\r
891 \r
892 #ifndef _ASM_CD_MEMORY_C\r
893 \r
894 // PCM and registers (ff0000 - ffffff)\r
895 static u32 PicoReadS68k8_pr(u32 a)\r
896 {\r
897   u32 d = 0;\r
898 \r
899   // regs\r
900   if ((a & 0xfe00) == 0x8000) {\r
901     a &= 0x1ff;\r
902     if (a >= 0x0e && a < 0x30) {\r
903       d = Pico_mcd->s68k_regs[a];\r
904       s68k_poll_detect(a & ~1, d);\r
905       goto regs_done;\r
906     }\r
907     d = s68k_reg_read16(a & ~1);\r
908     if (!(a & 1))\r
909       d >>= 8;\r
910 \r
911 regs_done:\r
912     d &= 0xff;\r
913     elprintf(EL_CDREGS, "s68k_regs r8: [%02x] %02x @%06x",\r
914       a, d, SekPcS68k);\r
915     return d;\r
916   }\r
917 \r
918   // PCM\r
919   // XXX: verify: probably odd addrs only?\r
920   if ((a & 0x8000) == 0x0000) {\r
921     a &= 0x7fff;\r
922     if (a >= 0x2000)\r
923       d = Pico_mcd->pcm_ram_b[Pico_mcd->pcm.bank][(a >> 1) & 0xfff];\r
924     else if (a >= 0x20)\r
925       d = pcd_pcm_read(a >> 1);\r
926 \r
927     return d;\r
928   }\r
929 \r
930   return s68k_unmapped_read8(a);\r
931 }\r
932 \r
933 static u32 PicoReadS68k16_pr(u32 a)\r
934 {\r
935   u32 d = 0;\r
936 \r
937   // regs\r
938   if ((a & 0xfe00) == 0x8000) {\r
939     a &= 0x1fe;\r
940     d = s68k_reg_read16(a);\r
941 \r
942     elprintf(EL_CDREGS, "s68k_regs r16: [%02x] %04x @%06x",\r
943       a, d, SekPcS68k);\r
944     return d;\r
945   }\r
946 \r
947   // PCM\r
948   if ((a & 0x8000) == 0x0000) {\r
949     a &= 0x7fff;\r
950     if (a >= 0x2000)\r
951       d = Pico_mcd->pcm_ram_b[Pico_mcd->pcm.bank][(a >> 1) & 0xfff];\r
952     else if (a >= 0x20)\r
953       d = pcd_pcm_read(a >> 1);\r
954 \r
955     return d;\r
956   }\r
957 \r
958   return s68k_unmapped_read16(a);\r
959 }\r
960 \r
961 static void PicoWriteS68k8_pr(u32 a, u32 d)\r
962 {\r
963   // regs\r
964   if ((a & 0xfe00) == 0x8000) {\r
965     a &= 0x1ff;\r
966     elprintf(EL_CDREGS, "s68k_regs w8: [%02x] %02x @%06x", a, d, SekPcS68k);\r
967     if (0x59 <= a && a < 0x68) // word regs\r
968       s68k_reg_write16(a & ~1, (d << 8) | d);\r
969     else\r
970       s68k_reg_write8(a, d);\r
971     return;\r
972   }\r
973 \r
974   // PCM\r
975   if ((a & 0x8000) == 0x0000) {\r
976     a &= 0x7fff;\r
977     if (a >= 0x2000)\r
978       Pico_mcd->pcm_ram_b[Pico_mcd->pcm.bank][(a>>1)&0xfff] = d;\r
979     else if (a < 0x12)\r
980       pcd_pcm_write(a>>1, d);\r
981     return;\r
982   }\r
983 \r
984   s68k_unmapped_write8(a, d);\r
985 }\r
986 \r
987 static void PicoWriteS68k16_pr(u32 a, u32 d)\r
988 {\r
989   // regs\r
990   if ((a & 0xfe00) == 0x8000) {\r
991     a &= 0x1fe;\r
992     elprintf(EL_CDREGS, "s68k_regs w16: [%02x] %04x @%06x", a, d, SekPcS68k);\r
993     s68k_reg_write16(a, d);\r
994     return;\r
995   }\r
996 \r
997   // PCM\r
998   if ((a & 0x8000) == 0x0000) {\r
999     a &= 0x7fff;\r
1000     if (a >= 0x2000)\r
1001       Pico_mcd->pcm_ram_b[Pico_mcd->pcm.bank][(a>>1)&0xfff] = d;\r
1002     else if (a < 0x12)\r
1003       pcd_pcm_write(a>>1, d & 0xff);\r
1004     return;\r
1005   }\r
1006 \r
1007   s68k_unmapped_write16(a, d);\r
1008 }\r
1009 \r
1010 #endif\r
1011 \r
1012 static const void *m68k_cell_read8[]   = { PicoReadM68k8_cell0, PicoReadM68k8_cell1 };\r
1013 static const void *m68k_cell_read16[]  = { PicoReadM68k16_cell0, PicoReadM68k16_cell1 };\r
1014 static const void *m68k_cell_write8[]  = { PicoWriteM68k8_cell0, PicoWriteM68k8_cell1 };\r
1015 static const void *m68k_cell_write16[] = { PicoWriteM68k16_cell0, PicoWriteM68k16_cell1 };\r
1016 \r
1017 static const void *s68k_dec_read8[]   = { PicoReadS68k8_dec0, PicoReadS68k8_dec1 };\r
1018 static const void *s68k_dec_read16[]  = { PicoReadS68k16_dec0, PicoReadS68k16_dec1 };\r
1019 \r
1020 static const void *s68k_dec_write8[2][4] = {\r
1021   { PicoWriteS68k8_dec_m0b0, PicoWriteS68k8_dec_m1b0, PicoWriteS68k8_dec_m2b0, PicoWriteS68k8_dec_m2b0 },\r
1022   { PicoWriteS68k8_dec_m0b1, PicoWriteS68k8_dec_m1b1, PicoWriteS68k8_dec_m2b1, PicoWriteS68k8_dec_m2b1 },\r
1023 };\r
1024 \r
1025 static const void *s68k_dec_write16[2][4] = {\r
1026   { PicoWriteS68k16_dec_m0b0, PicoWriteS68k16_dec_m1b0, PicoWriteS68k16_dec_m2b0, PicoWriteS68k16_dec_m2b0 },\r
1027   { PicoWriteS68k16_dec_m0b1, PicoWriteS68k16_dec_m1b1, PicoWriteS68k16_dec_m2b1, PicoWriteS68k16_dec_m2b1 },\r
1028 };\r
1029 \r
1030 // -----------------------------------------------------------------\r
1031 \r
1032 static void remap_prg_window(u32 r1, u32 r3)\r
1033 {\r
1034   // PRG RAM\r
1035   if (r1 & 2) {\r
1036     void *bank = Pico_mcd->prg_ram_b[(r3 >> 6) & 3];\r
1037     cpu68k_map_all_ram(0x020000, 0x03ffff, bank, 0);\r
1038   }\r
1039   else {\r
1040     m68k_map_unmap(0x020000, 0x03ffff);\r
1041   }\r
1042 }\r
1043 \r
1044 static void remap_word_ram(u32 r3)\r
1045 {\r
1046   void *bank;\r
1047 \r
1048   // WORD RAM\r
1049   if (!(r3 & 4)) {\r
1050     // 2M mode. XXX: allowing access in all cases for simplicity\r
1051     bank = Pico_mcd->word_ram2M;\r
1052     cpu68k_map_all_ram(0x200000, 0x23ffff, bank, 0);\r
1053     cpu68k_map_all_ram(0x080000, 0x0bffff, bank, 1);\r
1054     // TODO: handle 0x0c0000\r
1055   }\r
1056   else {\r
1057     int b0 = r3 & 1;\r
1058     int m = (r3 & 0x18) >> 3;\r
1059     bank = Pico_mcd->word_ram1M[b0];\r
1060     cpu68k_map_all_ram(0x200000, 0x21ffff, bank, 0);\r
1061     bank = Pico_mcd->word_ram1M[b0 ^ 1];\r
1062     cpu68k_map_all_ram(0x0c0000, 0x0effff, bank, 1);\r
1063     // "cell arrange" on m68k\r
1064     cpu68k_map_set(m68k_read8_map,   0x220000, 0x23ffff, m68k_cell_read8[b0], 1);\r
1065     cpu68k_map_set(m68k_read16_map,  0x220000, 0x23ffff, m68k_cell_read16[b0], 1);\r
1066     cpu68k_map_set(m68k_write8_map,  0x220000, 0x23ffff, m68k_cell_write8[b0], 1);\r
1067     cpu68k_map_set(m68k_write16_map, 0x220000, 0x23ffff, m68k_cell_write16[b0], 1);\r
1068     // "decode format" on s68k\r
1069     cpu68k_map_set(s68k_read8_map,   0x080000, 0x0bffff, s68k_dec_read8[b0 ^ 1], 1);\r
1070     cpu68k_map_set(s68k_read16_map,  0x080000, 0x0bffff, s68k_dec_read16[b0 ^ 1], 1);\r
1071     cpu68k_map_set(s68k_write8_map,  0x080000, 0x0bffff, s68k_dec_write8[b0 ^ 1][m], 1);\r
1072     cpu68k_map_set(s68k_write16_map, 0x080000, 0x0bffff, s68k_dec_write16[b0 ^ 1][m], 1);\r
1073   }\r
1074 }\r
1075 \r
1076 void pcd_state_loaded_mem(void)\r
1077 {\r
1078   u32 r3 = Pico_mcd->s68k_regs[3];\r
1079 \r
1080   /* after load events */\r
1081   if (r3 & 4) // 1M mode?\r
1082     wram_2M_to_1M(Pico_mcd->word_ram2M);\r
1083   remap_word_ram(r3);\r
1084   remap_prg_window(Pico_mcd->m.busreq, r3);\r
1085   Pico_mcd->m.dmna_ret_2m &= 3;\r
1086 \r
1087   // restore hint vector\r
1088   *(unsigned short *)(Pico_mcd->bios + 0x72) = Pico_mcd->m.hint_vector;\r
1089 }\r
1090 \r
1091 #ifdef EMU_M68K\r
1092 static void m68k_mem_setup_cd(void);\r
1093 #endif\r
1094 \r
1095 PICO_INTERNAL void PicoMemSetupCD(void)\r
1096 {\r
1097   // setup default main68k map\r
1098   PicoMemSetup();\r
1099 \r
1100   // main68k map (BIOS mapped by PicoMemSetup()):\r
1101   // RAM cart\r
1102   if (PicoOpt & POPT_EN_MCD_RAMCART) {\r
1103     cpu68k_map_set(m68k_read8_map,   0x400000, 0x7fffff, PicoReadM68k8_ramc, 1);\r
1104     cpu68k_map_set(m68k_read16_map,  0x400000, 0x7fffff, PicoReadM68k16_ramc, 1);\r
1105     cpu68k_map_set(m68k_write8_map,  0x400000, 0x7fffff, PicoWriteM68k8_ramc, 1);\r
1106     cpu68k_map_set(m68k_write16_map, 0x400000, 0x7fffff, PicoWriteM68k16_ramc, 1);\r
1107   }\r
1108 \r
1109   // registers/IO:\r
1110   cpu68k_map_set(m68k_read8_map,   0xa10000, 0xa1ffff, PicoRead8_mcd_io, 1);\r
1111   cpu68k_map_set(m68k_read16_map,  0xa10000, 0xa1ffff, PicoRead16_mcd_io, 1);\r
1112   cpu68k_map_set(m68k_write8_map,  0xa10000, 0xa1ffff, PicoWrite8_mcd_io, 1);\r
1113   cpu68k_map_set(m68k_write16_map, 0xa10000, 0xa1ffff, PicoWrite16_mcd_io, 1);\r
1114 \r
1115   // sub68k map\r
1116   cpu68k_map_set(s68k_read8_map,   0x000000, 0xffffff, s68k_unmapped_read8, 1);\r
1117   cpu68k_map_set(s68k_read16_map,  0x000000, 0xffffff, s68k_unmapped_read16, 1);\r
1118   cpu68k_map_set(s68k_write8_map,  0x000000, 0xffffff, s68k_unmapped_write8, 1);\r
1119   cpu68k_map_set(s68k_write16_map, 0x000000, 0xffffff, s68k_unmapped_write16, 1);\r
1120 \r
1121   // PRG RAM\r
1122   cpu68k_map_set(s68k_read8_map,   0x000000, 0x07ffff, Pico_mcd->prg_ram, 0);\r
1123   cpu68k_map_set(s68k_read16_map,  0x000000, 0x07ffff, Pico_mcd->prg_ram, 0);\r
1124   cpu68k_map_set(s68k_write8_map,  0x000000, 0x07ffff, Pico_mcd->prg_ram, 0);\r
1125   cpu68k_map_set(s68k_write16_map, 0x000000, 0x07ffff, Pico_mcd->prg_ram, 0);\r
1126   cpu68k_map_set(s68k_write8_map,  0x000000, 0x01ffff, PicoWriteS68k8_prgwp, 1);\r
1127   cpu68k_map_set(s68k_write16_map, 0x000000, 0x01ffff, PicoWriteS68k16_prgwp, 1);\r
1128 \r
1129   // BRAM\r
1130   cpu68k_map_set(s68k_read8_map,   0xfe0000, 0xfeffff, PicoReadS68k8_bram, 1);\r
1131   cpu68k_map_set(s68k_read16_map,  0xfe0000, 0xfeffff, PicoReadS68k16_bram, 1);\r
1132   cpu68k_map_set(s68k_write8_map,  0xfe0000, 0xfeffff, PicoWriteS68k8_bram, 1);\r
1133   cpu68k_map_set(s68k_write16_map, 0xfe0000, 0xfeffff, PicoWriteS68k16_bram, 1);\r
1134 \r
1135   // PCM, regs\r
1136   cpu68k_map_set(s68k_read8_map,   0xff0000, 0xffffff, PicoReadS68k8_pr, 1);\r
1137   cpu68k_map_set(s68k_read16_map,  0xff0000, 0xffffff, PicoReadS68k16_pr, 1);\r
1138   cpu68k_map_set(s68k_write8_map,  0xff0000, 0xffffff, PicoWriteS68k8_pr, 1);\r
1139   cpu68k_map_set(s68k_write16_map, 0xff0000, 0xffffff, PicoWriteS68k16_pr, 1);\r
1140 \r
1141   // RAMs\r
1142   remap_word_ram(1);\r
1143 \r
1144 #ifdef EMU_C68K\r
1145   // s68k\r
1146   PicoCpuCS68k.read8  = (void *)s68k_read8_map;\r
1147   PicoCpuCS68k.read16 = (void *)s68k_read16_map;\r
1148   PicoCpuCS68k.read32 = (void *)s68k_read16_map;\r
1149   PicoCpuCS68k.write8  = (void *)s68k_write8_map;\r
1150   PicoCpuCS68k.write16 = (void *)s68k_write16_map;\r
1151   PicoCpuCS68k.write32 = (void *)s68k_write16_map;\r
1152   PicoCpuCS68k.checkpc = NULL; /* unused */\r
1153   PicoCpuCS68k.fetch8  = NULL;\r
1154   PicoCpuCS68k.fetch16 = NULL;\r
1155   PicoCpuCS68k.fetch32 = NULL;\r
1156 #endif\r
1157 #ifdef EMU_F68K\r
1158   // s68k\r
1159   PicoCpuFS68k.read_byte  = s68k_read8;\r
1160   PicoCpuFS68k.read_word  = s68k_read16;\r
1161   PicoCpuFS68k.read_long  = s68k_read32;\r
1162   PicoCpuFS68k.write_byte = s68k_write8;\r
1163   PicoCpuFS68k.write_word = s68k_write16;\r
1164   PicoCpuFS68k.write_long = s68k_write32;\r
1165 \r
1166   // setup FAME fetchmap\r
1167   {\r
1168 #ifdef __clang__\r
1169     volatile // prevent strange relocs from clang\r
1170 #endif\r
1171     unsigned long ptr_ram = (unsigned long)PicoMem.ram;\r
1172     int i;\r
1173 \r
1174     // M68k\r
1175     // by default, point everything to fitst 64k of ROM (BIOS)\r
1176     for (i = 0; i < M68K_FETCHBANK1; i++)\r
1177       PicoCpuFM68k.Fetch[i] = (unsigned long)Pico.rom - (i<<(24-FAMEC_FETCHBITS));\r
1178     // now real ROM (BIOS)\r
1179     for (i = 0; i < M68K_FETCHBANK1 && (i<<(24-FAMEC_FETCHBITS)) < Pico.romsize; i++)\r
1180       PicoCpuFM68k.Fetch[i] = (unsigned long)Pico.rom;\r
1181     // .. and RAM\r
1182     for (i = M68K_FETCHBANK1*14/16; i < M68K_FETCHBANK1; i++)\r
1183       PicoCpuFM68k.Fetch[i] = ptr_ram - (i<<(24-FAMEC_FETCHBITS));\r
1184     // S68k\r
1185     // PRG RAM is default\r
1186     for (i = 0; i < M68K_FETCHBANK1; i++)\r
1187       PicoCpuFS68k.Fetch[i] = (unsigned long)Pico_mcd->prg_ram - (i<<(24-FAMEC_FETCHBITS));\r
1188     // real PRG RAM\r
1189     for (i = 0; i < M68K_FETCHBANK1 && (i<<(24-FAMEC_FETCHBITS)) < 0x80000; i++)\r
1190       PicoCpuFS68k.Fetch[i] = (unsigned long)Pico_mcd->prg_ram;\r
1191     // WORD RAM 2M area\r
1192     for (i = M68K_FETCHBANK1*0x08/0x100; i < M68K_FETCHBANK1 && (i<<(24-FAMEC_FETCHBITS)) < 0xc0000; i++)\r
1193       PicoCpuFS68k.Fetch[i] = (unsigned long)Pico_mcd->word_ram2M - 0x80000;\r
1194     // remap_word_ram() will setup word ram for both\r
1195   }\r
1196 #endif\r
1197 #ifdef EMU_M68K\r
1198   m68k_mem_setup_cd();\r
1199 #endif\r
1200 }\r
1201 \r
1202 \r
1203 #ifdef EMU_M68K\r
1204 u32  m68k_read8(u32 a);\r
1205 u32  m68k_read16(u32 a);\r
1206 u32  m68k_read32(u32 a);\r
1207 void m68k_write8(u32 a, u8 d);\r
1208 void m68k_write16(u32 a, u16 d);\r
1209 void m68k_write32(u32 a, u32 d);\r
1210 \r
1211 static unsigned int PicoReadCD8w (unsigned int a) {\r
1212         return m68ki_cpu_p == &PicoCpuMS68k ? s68k_read8(a) : m68k_read8(a);\r
1213 }\r
1214 static unsigned int PicoReadCD16w(unsigned int a) {\r
1215         return m68ki_cpu_p == &PicoCpuMS68k ? s68k_read16(a) : m68k_read16(a);\r
1216 }\r
1217 static unsigned int PicoReadCD32w(unsigned int a) {\r
1218         return m68ki_cpu_p == &PicoCpuMS68k ? s68k_read32(a) : m68k_read32(a);\r
1219 }\r
1220 static void PicoWriteCD8w (unsigned int a, unsigned char d) {\r
1221         if (m68ki_cpu_p == &PicoCpuMS68k) s68k_write8(a, d); else m68k_write8(a, d);\r
1222 }\r
1223 static void PicoWriteCD16w(unsigned int a, unsigned short d) {\r
1224         if (m68ki_cpu_p == &PicoCpuMS68k) s68k_write16(a, d); else m68k_write16(a, d);\r
1225 }\r
1226 static void PicoWriteCD32w(unsigned int a, unsigned int d) {\r
1227         if (m68ki_cpu_p == &PicoCpuMS68k) s68k_write32(a, d); else m68k_write32(a, d);\r
1228 }\r
1229 \r
1230 extern unsigned int (*pm68k_read_memory_8) (unsigned int address);\r
1231 extern unsigned int (*pm68k_read_memory_16)(unsigned int address);\r
1232 extern unsigned int (*pm68k_read_memory_32)(unsigned int address);\r
1233 extern void (*pm68k_write_memory_8) (unsigned int address, unsigned char  value);\r
1234 extern void (*pm68k_write_memory_16)(unsigned int address, unsigned short value);\r
1235 extern void (*pm68k_write_memory_32)(unsigned int address, unsigned int   value);\r
1236 \r
1237 static void m68k_mem_setup_cd(void)\r
1238 {\r
1239   pm68k_read_memory_8  = PicoReadCD8w;\r
1240   pm68k_read_memory_16 = PicoReadCD16w;\r
1241   pm68k_read_memory_32 = PicoReadCD32w;\r
1242   pm68k_write_memory_8  = PicoWriteCD8w;\r
1243   pm68k_write_memory_16 = PicoWriteCD16w;\r
1244   pm68k_write_memory_32 = PicoWriteCD32w;\r
1245 }\r
1246 #endif // EMU_M68K\r
1247 \r
1248 // vim:shiftwidth=2:ts=2:expandtab\r