#define POLL_CYCLES 124\r
unsigned int s68k_poll_adclk, s68k_poll_cnt;\r
\r
+void m68k_comm_check(u32 a)\r
+{\r
+ pcd_sync_s68k(SekCyclesDone());\r
+ /*if (Pico_mcd->m.m68k_comm_dirty & (1 << a/2)) {\r
+ Pico_mcd->m.m68k_comm_dirty &= ~(1 << a/2);\r
+ Pico_mcd->m.m68k_poll_a = Pico_mcd->m.m68k_poll_cnt = 0;\r
+ return;\r
+ }\r
+ if (a != Pico_mcd->m.m68k_poll_a) {\r
+ Pico_mcd->m.m68k_poll_a = a;\r
+ Pico_mcd->m.m68k_poll_cnt = 0;\r
+ return;\r
+ }\r
+ if (++Pico_mcd->m.m68k_poll_cnt > 5)\r
+ SekCyclesBurnRun(122);\r
+\r
+ elprintf(EL_CDPOLL, "m68k poll [%02x] %d %u", a,\r
+ Pico_mcd->m.m68k_poll_cnt, SekCyclesDone());*/\r
+}\r
+\r
#ifndef _ASM_CD_MEMORY_C\r
static u32 m68k_reg_read16(u32 a)\r
{\r
d = ((Pico_mcd->s68k_regs[0x33]<<13)&0x8000) | Pico_mcd->m.busreq; // here IFL2 is always 0, just like in Gens\r
goto end;\r
case 2:\r
+ m68k_comm_check(a);\r
d = (Pico_mcd->s68k_regs[a]<<8) | (Pico_mcd->s68k_regs[a+1]&0xc7);\r
elprintf(EL_CDREG3, "m68k_regs r3: %02x @%06x", (u8)d, SekPc);\r
goto end;\r
\r
if (a < 0x30) {\r
// comm flag/cmd/status (0xE-0x2F)\r
+ m68k_comm_check(a);\r
d = (Pico_mcd->s68k_regs[a]<<8) | Pico_mcd->s68k_regs[a+1];\r
goto end;\r
}\r
u32 dold;\r
a &= 0x3f;\r
\r
+ Pico_mcd->m.m68k_poll_a = 0;\r
+\r
switch (a) {\r
case 0:\r
d &= 1;\r
return;\r
case 1:\r
d &= 3;\r
- if (!(d&1)) Pico_mcd->m.state_flags |= 1; // reset pending, needed to be sure we fetch the right vectors on reset\r
- if ( (Pico_mcd->m.busreq&1) != (d&1)) elprintf(EL_INTSW, "m68k: s68k reset %i", !(d&1));\r
- if ( (Pico_mcd->m.busreq&2) != (d&2)) elprintf(EL_INTSW, "m68k: s68k brq %i", (d&2)>>1);\r
- if ((Pico_mcd->m.state_flags&1) && (d&3)==1) {\r
- SekResetS68k(); // S68k comes out of RESET or BRQ state\r
- Pico_mcd->m.state_flags&=~1;\r
- elprintf(EL_CDREGS, "m68k: resetting s68k, cycles=%i", SekCyclesLeft);\r
+ elprintf(EL_CDREGS, "d m.busreq %u %u", d, Pico_mcd->m.busreq);\r
+ if (d == Pico_mcd->m.busreq)\r
+ return;\r
+ pcd_sync_s68k(SekCyclesDone());\r
+\r
+ if ((Pico_mcd->m.busreq ^ d) & 1) {\r
+ elprintf(EL_INTSW, "m68k: s68k reset %i", !(d&1));\r
+ if (!(d & 1))\r
+ d |= 2; // verified: reset also gives bus\r
+ else {\r
+ elprintf(EL_CDREGS, "m68k: resetting s68k");\r
+ SekResetS68k();\r
+ }\r
}\r
- if (!(d & 1))\r
- d |= 2; // verified: reset also gives bus\r
- if ((d ^ Pico_mcd->m.busreq) & 2)\r
+ if ((Pico_mcd->m.busreq ^ d) & 2) {\r
+ elprintf(EL_INTSW, "m68k: s68k brq %i", d >> 1);\r
remap_prg_window();\r
+ }\r
Pico_mcd->m.busreq = d;\r
return;\r
case 2:\r
case 0xf:\r
d = (d << 1) | ((d >> 7) & 1); // rol8 1 (special case)\r
case 0xe:\r
- //dprintf("m68k: comm flag: %02x", d);\r
- Pico_mcd->s68k_regs[0xe] = d;\r
+ if (d != Pico_mcd->s68k_regs[0xe]) {\r
+ pcd_sync_s68k(SekCyclesDone());\r
+ Pico_mcd->s68k_regs[0xe] = d;\r
+ }\r
#ifdef USE_POLL_DETECT\r
if ((s68k_poll_adclk&0xfe) == 0xe && s68k_poll_cnt > POLL_LIMIT) {\r
SekSetStopS68k(0); s68k_poll_adclk = 0;\r
Pico_mcd->m.stopwatch_base_c = SekCyclesDoneS68k();\r
return;\r
case 0xe:\r
- Pico_mcd->s68k_regs[0xf] = (d>>1) | (d<<7); // ror8 1, Gens note: Dragons lair\r
- return;\r
+ d = (d>>1) | (d<<7); // ror8 1, Gens note: Dragons lair\r
+ break;\r
case 0x31: // 384 cycle int3 timer\r
d &= 0xff;\r
elprintf(EL_CDREGS|EL_CD, "s68k set int3 timer: %02x", d);\r
return;\r
}\r
\r
+ if (a < 0x30)\r
+ Pico_mcd->m.m68k_comm_dirty |= (1 << a/2);\r
+\r
Pico_mcd->s68k_regs[a] = (u8) d;\r
}\r
\r
sprintf(dstrp, "pend int: v:%i, h:%i, vdp status: %04x\n", bit(pv->pending_ints,5), bit(pv->pending_ints,4), pv->status); MVP;
sprintf(dstrp, "pal: %i, hw: %02x, frame#: %i, cycles: %i\n", Pico.m.pal, Pico.m.hardware, Pico.m.frame_count, SekCyclesDone()); MVP;
sprintf(dstrp, "M68k: PC: %06x, SR: %04x, irql: %i\n", SekPc, SekSr, SekIrqLevel); MVP;
-#if defined(EMU_C68K)
- sprintf(dstrp - 1, ", st_flg: %x\n", PicoCpuCM68k.state_flags); MVP;
-#endif
for (r = 0; r < 8; r++) {
sprintf(dstrp, "d%i=%08x, a%i=%08x\n", r, SekDar(r), r, SekDar(r+8)); MVP;
}
\r
// burn cycles while not in SekRun() and while in\r
#define SekCyclesBurn(c) SekCycleCnt += c\r
-#define SekCyclesBurnRun(c) SekCyclesLeft -= c\r
+#define SekCyclesBurnRun(c) { \\r
+ SekCyclesLeft -= c; \\r
+ if (SekCyclesLeft < 0) \\r
+ SekCyclesLeft = 0; \\r
+}\r
\r
// note: sometimes may extend timeslice to delay an irq\r
#define SekEndRun(after) { \\r
unsigned short hint_vector;\r
unsigned char busreq;\r
unsigned char s68k_pend_ints;\r
- unsigned int state_flags; // 04: emu state: reset_pending\r
+ unsigned int state_flags; // 04\r
unsigned int stopwatch_base_c;\r
- unsigned int pad[3];\r
+ unsigned int m68k_comm_dirty;\r
+ unsigned short m68k_poll_a;\r
+ unsigned short m68k_poll_cnt;\r
+ unsigned int pad;\r
unsigned char bcram_reg; // 18: battery-backed RAM cart register\r
unsigned char pad2;\r
unsigned short pad3;\r
void pcd_event_schedule(unsigned int now, enum pcd_event event, int after);\r
void pcd_event_schedule_s68k(enum pcd_event event, int after);\r
unsigned int pcd_cycles_m68k_to_s68k(unsigned int c);\r
+void pcd_sync_s68k(unsigned int m68k_target);\r
void pcd_state_loaded(void);\r
\r
// pico/pico.c\r