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