From 7a1f6e45c9f6a11152f62303b0203475a9fd431a Mon Sep 17 00:00:00 2001 From: notaz Date: Sat, 24 Mar 2007 18:25:17 +0000 Subject: [PATCH 1/1] bugfixes in cd/Memory.s, poll loop detection git-svn-id: file:///home/notaz/opt/svn/PicoDrive@77 be3aeb3a-fb24-0410-a615-afba39da0efa --- Pico/PicoInt.h | 17 +++++- Pico/cd/Memory.c | 106 ++++++++++++++++++++++++++--------- Pico/cd/Memory.s | 33 ++++++++++- platform/gp2x/emu.c | 7 ++- platform/gp2x/version.h | 2 +- platform/linux/port_config.h | 4 +- 6 files changed, 134 insertions(+), 35 deletions(-) diff --git a/Pico/PicoInt.h b/Pico/PicoInt.h index 18e779b..6caff48 100644 --- a/Pico/PicoInt.h +++ b/Pico/PicoInt.h @@ -27,12 +27,16 @@ extern struct Cyclone PicoCpu, PicoCpuS68k; #define SekCyclesLeftNoMCD PicoCpu.cycles // cycles left for this run #define SekCyclesLeft \ (((PicoMCD&1) && (PicoOpt & 0x2000)) ? (SekCycleAim-SekCycleCnt) : SekCyclesLeftNoMCD) +#define SekCyclesLeftS68k \ + ((PicoOpt & 0x2000) ? (SekCycleAimS68k-SekCycleCntS68k) : PicoCpuS68k.cycles) #define SekSetCyclesLeftNoMCD(c) PicoCpu.cycles=c #define SekSetCyclesLeft(c) { \ if ((PicoMCD&1) && (PicoOpt & 0x2000)) SekCycleCnt=SekCycleAim-(c); else SekSetCyclesLeftNoMCD(c); \ } #define SekPc (PicoCpu.pc-PicoCpu.membase) #define SekPcS68k (PicoCpuS68k.pc-PicoCpuS68k.membase) +#define SekSetStop(x) { PicoCpu.stopped=x; if (x) PicoCpu.cycles=0; } +#define SekSetStopS68k(x) { PicoCpuS68k.stopped=x; if (x) PicoCpuS68k.cycles=0; } #endif #ifdef EMU_A68K @@ -60,15 +64,25 @@ extern int m68k_ICount; extern m68ki_cpu_core PicoM68kCPU; // MD's CPU extern m68ki_cpu_core PicoS68kCPU; // Mega CD's CPU #ifndef SekCyclesLeft -#define SekCyclesLeftNoMCD m68k_cycles_remaining() +#define SekCyclesLeftNoMCD PicoM68kCPU.cyc_remaining_cycles #define SekCyclesLeft \ (((PicoMCD&1) && (PicoOpt & 0x2000)) ? (SekCycleAim-SekCycleCnt) : SekCyclesLeftNoMCD) +#define SekCyclesLeftS68k \ + ((PicoOpt & 0x2000) ? (SekCycleAimS68k-SekCycleCntS68k) : PicoS68kCPU.cyc_remaining_cycles) #define SekSetCyclesLeftNoMCD(c) SET_CYCLES(c) #define SekSetCyclesLeft(c) { \ if ((PicoMCD&1) && (PicoOpt & 0x2000)) SekCycleCnt=SekCycleAim-(c); else SET_CYCLES(c); \ } #define SekPc m68k_get_reg(&PicoM68kCPU, M68K_REG_PC) #define SekPcS68k m68k_get_reg(&PicoS68kCPU, M68K_REG_PC) +#define SekSetStop(x) { \ + if(x) { SET_CYCLES(0); PicoM68kCPU.stopped=STOP_LEVEL_STOP; } \ + else PicoM68kCPU.stopped=0; \ +} +#define SekSetStopS68k(x) { \ + if(x) { SET_CYCLES(0); PicoS68kCPU.stopped=STOP_LEVEL_STOP; } \ + else PicoS68kCPU.stopped=0; \ +} #endif #endif @@ -91,6 +105,7 @@ extern int SekCycleCntS68k; extern int SekCycleAimS68k; #define SekCyclesResetS68k() {SekCycleCntS68k=SekCycleAimS68k=0;} +#define SekCyclesDoneS68k() (SekCycleAimS68k-SekCyclesLeftS68k) // does not work as expected //extern int z80ExtraCycles; // extra z80 cycles, used when z80 is [en|dis]abled diff --git a/Pico/cd/Memory.c b/Pico/cd/Memory.c index 0b11e98..fdbf316 100644 --- a/Pico/cd/Memory.c +++ b/Pico/cd/Memory.c @@ -33,6 +33,12 @@ typedef unsigned int u32; // ----------------------------------------------------------------- +// poller detection +#define USE_POLL_DETECT +#define POLL_LIMIT 16 +#define POLL_CYCLES 124 +// int m68k_poll_addr, m68k_poll_cnt; +unsigned int s68k_poll_adclk, s68k_poll_cnt; #ifndef _ASM_CD_MEMORY_C static u32 m68k_reg_read16(u32 a) @@ -126,12 +132,12 @@ void m68k_reg_write8(u32 a, u32 d) if (d & 2) dold &= ~1; // return word RAM to s68k in 2M mode } Pico_mcd->s68k_regs[3] = d | dold; // really use s68k side register - -/* - d |= Pico_mcd->s68k_regs[3]&0x1d; - if (!(d & 4) && (d & 2)) d &= ~1; // return word RAM to s68k in 2M mode - Pico_mcd->s68k_regs[3] = d; // really use s68k side register -*/ +#ifdef USE_POLL_DETECT + if ((s68k_poll_adclk&0xfe) == 2 && s68k_poll_cnt > POLL_LIMIT) { + SekSetStopS68k(0); s68k_poll_adclk = 0; + //printf("%05i:%03i: s68k poll release, a=%02x\n", Pico.m.frame_count, Pico.m.scanline, a); + } +#endif return; } case 6: @@ -141,14 +147,28 @@ void m68k_reg_write8(u32 a, u32 d) Pico_mcd->bios[0x72] = d; dprintf("hint vector set to %08x", PicoRead32(0x70)); return; + 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; +#ifdef USE_POLL_DETECT + if ((s68k_poll_adclk&0xfe) == 0xe && s68k_poll_cnt > POLL_LIMIT) { + SekSetStopS68k(0); s68k_poll_adclk = 0; + //printf("%05i:%03i: s68k poll release, a=%02x\n", Pico.m.frame_count, Pico.m.scanline, a); + } +#endif return; } if ((a&0xf0) == 0x10) { Pico_mcd->s68k_regs[a] = d; +#ifdef USE_POLL_DETECT + if ((a&0xfe) == (s68k_poll_adclk&0xfe) && s68k_poll_cnt > POLL_LIMIT) { + SekSetStopS68k(0); s68k_poll_adclk = 0; + //printf("%05i:%03i: s68k poll release, a=%02x\n", Pico.m.frame_count, Pico.m.scanline, a); + } +#endif return; } @@ -178,48 +198,64 @@ u32 s68k_reg_read16(u32 a) switch (a) { case 0: - d = ((Pico_mcd->s68k_regs[0]&3)<<8) | 1; // ver = 0, not in reset state - goto end; + return ((Pico_mcd->s68k_regs[0]&3)<<8) | 1; // ver = 0, not in reset state case 2: d = (Pico_mcd->s68k_regs[a]<<8) | (Pico_mcd->s68k_regs[a+1]&0x1f); dprintf("s68k_regs r3: %02x @%06x", (u8)d, SekPcS68k); - goto end; + goto poll_detect; case 6: - d = CDC_Read_Reg(); - goto end; + return CDC_Read_Reg(); case 8: - d = Read_CDC_Host(1); // Gens returns 0 here on byte reads - goto end; + return Read_CDC_Host(1); // Gens returns 0 here on byte reads case 0xC: d = Pico_mcd->m.timer_stopwatch >> 16; dprintf("s68k stopwatch timer read (%04x)", d); - goto end; + return d; case 0x30: - dprintf("s68k int3 timer read (%02x%02x)", Pico_mcd->s68k_regs[30], Pico_mcd->s68k_regs[31]); - break; + dprintf("s68k int3 timer read (%02x)", Pico_mcd->s68k_regs[31]); + return Pico_mcd->s68k_regs[31]; case 0x34: // fader - d = 0; // no busy bit - goto end; + return 0; // no busy bit case 0x50: // font data (check: Lunar 2, Silpheed) READ_FONT_DATA(0x00100000); - goto end; + return d; case 0x52: READ_FONT_DATA(0x00010000); - goto end; + return d; case 0x54: READ_FONT_DATA(0x10000000); - goto end; + return d; case 0x56: READ_FONT_DATA(0x01000000); - goto end; + return d; } d = (Pico_mcd->s68k_regs[a]<<8) | Pico_mcd->s68k_regs[a+1]; -end: + if (a >= 0x0e && a < 0x30) goto poll_detect; - // dprintf("ret = %04x", d); + return d; +poll_detect: +#ifdef USE_POLL_DETECT + // polling detection + if (a == (s68k_poll_adclk&0xfe)) { + unsigned int clkdiff = SekCyclesDoneS68k() - (s68k_poll_adclk>>8); + if (clkdiff <= POLL_CYCLES) { + s68k_poll_cnt++; + //printf("-- diff: %u, cnt = %i\n", clkdiff, s68k_poll_cnt); + if (s68k_poll_cnt > POLL_LIMIT) { + SekSetStopS68k(1); + //printf("%05i:%03i: s68k poll detected @ %06x, a=%02x\n", Pico.m.frame_count, Pico.m.scanline, SekPcS68k, a); + } + s68k_poll_adclk = (SekCyclesDoneS68k() << 8) | a; + return d; + } + } + s68k_poll_adclk = (SekCyclesDoneS68k() << 8) | a; + s68k_poll_cnt = 0; + +#endif return d; } @@ -292,8 +328,7 @@ void s68k_reg_write8(u32 a, u32 d) Pico_mcd->m.timer_stopwatch = 0; return; case 0xe: - Pico_mcd->s68k_regs[0Xf] = (d>>1) | (d<<7); // ror8, Gens note: Dragons lair - Pico_mcd->m.timer_stopwatch = 0; + Pico_mcd->s68k_regs[0xf] = (d>>1) | (d<<7); // ror8 1, Gens note: Dragons lair return; case 0x31: dprintf("s68k set int3 timer: %02x", d); @@ -634,8 +669,23 @@ static void PicoWriteM68k16(u32 a,u16 d) return; } - if ((a&0xffffc0)==0xa12000) + // regs + if ((a&0xffffc0)==0xa12000) { rdprintf("m68k_regs w16: [%02x] %04x @%06x", a&0x3f, d, SekPc); + if (a == 0xe) { // special case, 2 byte writes would be handled differently + Pico_mcd->s68k_regs[0xe] = d >> 8; +#ifdef USE_POLL_DETECT + if ((s68k_poll_adclk&0xfe) == 0xe && s68k_poll_cnt > POLL_LIMIT) { + SekSetStopS68k(0); s68k_poll_adclk = -1; + //printf("%05i:%03i: s68k poll release, a=%02x\n", Pico.m.frame_count, Pico.m.scanline, a); + } +#endif + return; + } + m68k_reg_write8(a, d>>8); + m68k_reg_write8(a+1,d&0xff); + return; + } OtherWrite16(a,d); } @@ -1408,6 +1458,8 @@ void PicoMemSetupCD() PicoCpuS68k.write16=PicoWriteS68k16; PicoCpuS68k.write32=PicoWriteS68k32; #endif + // m68k_poll_addr = m68k_poll_cnt = 0; + s68k_poll_adclk = s68k_poll_cnt = 0; } diff --git a/Pico/cd/Memory.s b/Pico/cd/Memory.s index 6bdf3e5..8c360f8 100644 --- a/Pico/cd/Memory.s +++ b/Pico/cd/Memory.s @@ -7,6 +7,7 @@ .equiv PCM_STEP_SHIFT, 11 +.equiv POLL_LIMIT, 16 @ jump tables .data @@ -132,6 +133,8 @@ m_s68k_decode_write_table: .extern SRam .extern gfx_cd_write16 .extern s68k_reg_write8 +.extern s68k_poll_adclk +.extern PicoCpuS68k @ r0=reg3, r1-r3=temp @@ -665,7 +668,7 @@ m_m68k_read16_m68k_regs: .long m_m68k_read16_r0c m_m68k_read16_r00: add r1, r1, #0x110000 - ldr r0, [r1, #30] + ldr r0, [r1, #0x30] add r1, r1, #0x002200 ldrb r1, [r1, #2] @ Pico_mcd->m.busreq and r0, r0, #0x04000000 @ we need irq2 mask state @@ -1073,6 +1076,9 @@ m_m68k_write16_system_io: bne OtherWrite16 m_m68k_write16_m68k_regs: + and r0, r0, #0x3e + cmp r0, #0x0e + beq m_m68k_write16_regs_spec and r3, r1, #0xff add r2, r0, #1 stmfd sp!,{r2,r3,lr} @@ -1081,6 +1087,24 @@ m_m68k_write16_m68k_regs: ldmfd sp!,{r0,r1,lr} b m68k_reg_write8 +m_m68k_write16_regs_spec: @ special case + ldr r2, =(Pico+0x22200) + ldr r3, =s68k_poll_adclk + mov r0, #0x110000 + ldr r2, [r2] + add r0, r0, #0x00000e + mov r1, r1, lsr #8 + strb r1, [r2, r0] @ if (a == 0xe) s68k_regs[0x0e] = d >> 8; + ldr r2, [r3] + mov r1, #0 + and r2, r2, #0xfe + cmp r2, #0x0e + bxne lr + ldr r0, =PicoCpuS68k + str r1, [r0, #0x58] @ push s68k out of stopped state + str r1, [r3] + bx lr + m_m68k_write16_vdp: tst r0, #0x70000 @@ -1454,7 +1478,10 @@ m_s68k_read16_regs: sub r2, r0, #0x58 cmp r2, #0x10 blo gfx_cd_read - b s68k_reg_read16 + cmp r0, #8 + bne s68k_reg_read16 + mov r0, #1 + b Read_CDC_Host @ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@ -1664,7 +1691,7 @@ m_s68k_write8_backup: @ 0xfe0000 - 0xfe3fff (repeated?) strb r1, [r2, r0] ldr r1, =SRam mov r0, #1 - str r0, [r1, #0x0e] @ SRam.changed = 1 + strb r0, [r1, #0x0e] @ SRam.changed = 1 bx lr diff --git a/platform/gp2x/emu.c b/platform/gp2x/emu.c index 60907ff..f43f9b7 100644 --- a/platform/gp2x/emu.c +++ b/platform/gp2x/emu.c @@ -790,6 +790,9 @@ static void emu_msg_cb(const char *msg) } gettimeofday(¬iceMsgTime, 0); noticeMsgTime.tv_sec -= 2; + + /* assumption: emu_msg_cb gets called only when something slow is about to happen */ + reset_timing = 1; } static void emu_state_cb(const char *str) @@ -1168,7 +1171,9 @@ void emu_Loop(void) if (frames_shown > frames_done) frames_shown = frames_done; } } - +#if 0 + sprintf(fpsbuff, "%05i", Pico.m.frame_count); +#endif lim_time = (frames_done+1) * target_frametime; if(currentConfig.Frameskip >= 0) { // frameskip enabled for(i = 0; i < currentConfig.Frameskip; i++) { diff --git a/platform/gp2x/version.h b/platform/gp2x/version.h index db5382d..7bb0de2 100644 --- a/platform/gp2x/version.h +++ b/platform/gp2x/version.h @@ -1,2 +1,2 @@ -#define VERSION "1.201" +#define VERSION "1.30" diff --git a/platform/linux/port_config.h b/platform/linux/port_config.h index e5c88bb..a0a855a 100644 --- a/platform/linux/port_config.h +++ b/platform/linux/port_config.h @@ -12,8 +12,8 @@ // pico.c #define CAN_HANDLE_240_LINES 1 -#define dprintf(f,...) printf("%05i:%03i: " f "\n",Pico.m.frame_count,Pico.m.scanline,##__VA_ARGS__) -//#define dprintf(x...) +//#define dprintf(f,...) printf("%05i:%03i: " f "\n",Pico.m.frame_count,Pico.m.scanline,##__VA_ARGS__) +#define dprintf(x...) #endif //PORT_CONFIG_H -- 2.39.2