From bc3c13d3291c1f7093f89d086b7082169f3c6077 Mon Sep 17 00:00:00 2001 From: notaz Date: Mon, 26 Aug 2013 03:46:27 +0300 Subject: [PATCH] cd sync improvements --- pico/cd/memory.c | 63 ++++++++++++++++++++++++++++++++++---------- pico/cd/memory_arm.s | 3 +++ pico/cd/pico.c | 4 +-- pico/debug.c | 3 --- pico/pico_int.h | 14 +++++++--- 5 files changed, 65 insertions(+), 22 deletions(-) diff --git a/pico/cd/memory.c b/pico/cd/memory.c index 2c6eadc5..743568ec 100644 --- a/pico/cd/memory.c +++ b/pico/cd/memory.c @@ -73,6 +73,26 @@ static void remap_word_ram(int r3); #define POLL_CYCLES 124 unsigned int s68k_poll_adclk, s68k_poll_cnt; +void m68k_comm_check(u32 a) +{ + pcd_sync_s68k(SekCyclesDone()); + /*if (Pico_mcd->m.m68k_comm_dirty & (1 << a/2)) { + Pico_mcd->m.m68k_comm_dirty &= ~(1 << a/2); + Pico_mcd->m.m68k_poll_a = Pico_mcd->m.m68k_poll_cnt = 0; + return; + } + if (a != Pico_mcd->m.m68k_poll_a) { + Pico_mcd->m.m68k_poll_a = a; + Pico_mcd->m.m68k_poll_cnt = 0; + return; + } + if (++Pico_mcd->m.m68k_poll_cnt > 5) + SekCyclesBurnRun(122); + + elprintf(EL_CDPOLL, "m68k poll [%02x] %d %u", a, + Pico_mcd->m.m68k_poll_cnt, SekCyclesDone());*/ +} + #ifndef _ASM_CD_MEMORY_C static u32 m68k_reg_read16(u32 a) { @@ -84,6 +104,7 @@ static u32 m68k_reg_read16(u32 a) d = ((Pico_mcd->s68k_regs[0x33]<<13)&0x8000) | Pico_mcd->m.busreq; // here IFL2 is always 0, just like in Gens goto end; case 2: + m68k_comm_check(a); d = (Pico_mcd->s68k_regs[a]<<8) | (Pico_mcd->s68k_regs[a+1]&0xc7); elprintf(EL_CDREG3, "m68k_regs r3: %02x @%06x", (u8)d, SekPc); goto end; @@ -110,6 +131,7 @@ static u32 m68k_reg_read16(u32 a) if (a < 0x30) { // comm flag/cmd/status (0xE-0x2F) + m68k_comm_check(a); d = (Pico_mcd->s68k_regs[a]<<8) | Pico_mcd->s68k_regs[a+1]; goto end; } @@ -130,6 +152,8 @@ void m68k_reg_write8(u32 a, u32 d) u32 dold; a &= 0x3f; + Pico_mcd->m.m68k_poll_a = 0; + switch (a) { case 0: d &= 1; @@ -137,18 +161,24 @@ void m68k_reg_write8(u32 a, u32 d) return; case 1: d &= 3; - if (!(d&1)) Pico_mcd->m.state_flags |= 1; // reset pending, needed to be sure we fetch the right vectors on reset - if ( (Pico_mcd->m.busreq&1) != (d&1)) elprintf(EL_INTSW, "m68k: s68k reset %i", !(d&1)); - if ( (Pico_mcd->m.busreq&2) != (d&2)) elprintf(EL_INTSW, "m68k: s68k brq %i", (d&2)>>1); - if ((Pico_mcd->m.state_flags&1) && (d&3)==1) { - SekResetS68k(); // S68k comes out of RESET or BRQ state - Pico_mcd->m.state_flags&=~1; - elprintf(EL_CDREGS, "m68k: resetting s68k, cycles=%i", SekCyclesLeft); + elprintf(EL_CDREGS, "d m.busreq %u %u", d, Pico_mcd->m.busreq); + if (d == Pico_mcd->m.busreq) + return; + pcd_sync_s68k(SekCyclesDone()); + + if ((Pico_mcd->m.busreq ^ d) & 1) { + elprintf(EL_INTSW, "m68k: s68k reset %i", !(d&1)); + if (!(d & 1)) + d |= 2; // verified: reset also gives bus + else { + elprintf(EL_CDREGS, "m68k: resetting s68k"); + SekResetS68k(); + } } - if (!(d & 1)) - d |= 2; // verified: reset also gives bus - if ((d ^ Pico_mcd->m.busreq) & 2) + if ((Pico_mcd->m.busreq ^ d) & 2) { + elprintf(EL_INTSW, "m68k: s68k brq %i", d >> 1); remap_prg_window(); + } Pico_mcd->m.busreq = d; return; case 2: @@ -193,8 +223,10 @@ void m68k_reg_write8(u32 a, u32 d) case 0xf: d = (d << 1) | ((d >> 7) & 1); // rol8 1 (special case) case 0xe: - //dprintf("m68k: comm flag: %02x", d); - Pico_mcd->s68k_regs[0xe] = d; + if (d != Pico_mcd->s68k_regs[0xe]) { + pcd_sync_s68k(SekCyclesDone()); + Pico_mcd->s68k_regs[0xe] = d; + } #ifdef USE_POLL_DETECT if ((s68k_poll_adclk&0xfe) == 0xe && s68k_poll_cnt > POLL_LIMIT) { SekSetStopS68k(0); s68k_poll_adclk = 0; @@ -374,8 +406,8 @@ void s68k_reg_write8(u32 a, u32 d) Pico_mcd->m.stopwatch_base_c = SekCyclesDoneS68k(); return; case 0xe: - Pico_mcd->s68k_regs[0xf] = (d>>1) | (d<<7); // ror8 1, Gens note: Dragons lair - return; + d = (d>>1) | (d<<7); // ror8 1, Gens note: Dragons lair + break; case 0x31: // 384 cycle int3 timer d &= 0xff; elprintf(EL_CDREGS|EL_CD, "s68k set int3 timer: %02x", d); @@ -418,6 +450,9 @@ void s68k_reg_write8(u32 a, u32 d) return; } + if (a < 0x30) + Pico_mcd->m.m68k_comm_dirty |= (1 << a/2); + Pico_mcd->s68k_regs[a] = (u8) d; } diff --git a/pico/cd/memory_arm.s b/pico/cd/memory_arm.s index b9bbaec8..598bcd7d 100644 --- a/pico/cd/memory_arm.s +++ b/pico/cd/memory_arm.s @@ -216,6 +216,9 @@ m_m68k_read8_r0d: mov r0, r0, lsr #16 bx lr m_m68k_read8_hi: + push {r0,r1,lr} + bl m68k_comm_check + pop {r0,r1,lr} cmp r0, #0x30 movge r0, #0 bxeq lr diff --git a/pico/cd/pico.c b/pico/cd/pico.c index 0b6b943c..eabd2ea9 100644 --- a/pico/cd/pico.c +++ b/pico/cd/pico.c @@ -45,7 +45,7 @@ PICO_INTERNAL int PicoResetMCD(void) memset(&Pico_mcd->m, 0, sizeof(Pico_mcd->m)); memset(Pico_mcd->bios + 0x70, 0xff, 4); // reset hint vector (simplest way to implement reg6) - Pico_mcd->m.state_flags |= 1; // s68k reset pending + Pico_mcd->m.state_flags = 0; Pico_mcd->s68k_regs[3] = 1; // 2M word RAM mode with m68k access after reset Reset_CD(); @@ -219,7 +219,7 @@ static void pcd_run_events(unsigned int until) oldest, event_time_next); } -static void pcd_sync_s68k(unsigned int m68k_target) +void pcd_sync_s68k(unsigned int m68k_target) { #define now SekCycleCntS68k unsigned int s68k_target = diff --git a/pico/debug.c b/pico/debug.c index 26b63936..959331f8 100644 --- a/pico/debug.c +++ b/pico/debug.c @@ -45,9 +45,6 @@ char *PDebugMain(void) 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; } diff --git a/pico/pico_int.h b/pico/pico_int.h index ef49295f..c23705b6 100644 --- a/pico/pico_int.h +++ b/pico/pico_int.h @@ -132,7 +132,11 @@ extern unsigned int SekCycleAim; // burn cycles while not in SekRun() and while in #define SekCyclesBurn(c) SekCycleCnt += c -#define SekCyclesBurnRun(c) SekCyclesLeft -= c +#define SekCyclesBurnRun(c) { \ + SekCyclesLeft -= c; \ + if (SekCyclesLeft < 0) \ + SekCyclesLeft = 0; \ +} // note: sometimes may extend timeslice to delay an irq #define SekEndRun(after) { \ @@ -383,9 +387,12 @@ struct mcd_misc unsigned short hint_vector; unsigned char busreq; unsigned char s68k_pend_ints; - unsigned int state_flags; // 04: emu state: reset_pending + unsigned int state_flags; // 04 unsigned int stopwatch_base_c; - unsigned int pad[3]; + unsigned int m68k_comm_dirty; + unsigned short m68k_poll_a; + unsigned short m68k_poll_cnt; + unsigned int pad; unsigned char bcram_reg; // 18: battery-backed RAM cart register unsigned char pad2; unsigned short pad3; @@ -624,6 +631,7 @@ extern unsigned int pcd_event_times[PCD_EVENT_COUNT]; void pcd_event_schedule(unsigned int now, enum pcd_event event, int after); void pcd_event_schedule_s68k(enum pcd_event event, int after); unsigned int pcd_cycles_m68k_to_s68k(unsigned int c); +void pcd_sync_s68k(unsigned int m68k_target); void pcd_state_loaded(void); // pico/pico.c -- 2.39.5