From d3d414551a4b76a1a0bfcfabc4c669d1d3f31872 Mon Sep 17 00:00:00 2001 From: notaz Date: Mon, 4 Sep 2023 23:09:05 +0300 Subject: [PATCH] preliminary irq10 support libretro/pcsx_rearmed#723 --- libpcsxcore/cdrom.c | 2 - libpcsxcore/new_dynarec/events.c | 6 +-- libpcsxcore/new_dynarec/pcsxmem.c | 28 ++++++----- libpcsxcore/psxbios.c | 10 ++-- libpcsxcore/psxcounters.c | 80 ++++++++++++++++++++++++++----- libpcsxcore/psxcounters.h | 4 +- libpcsxcore/psxhw.c | 12 ++--- libpcsxcore/r3000a.c | 45 +++++++++++++++++ libpcsxcore/r3000a.h | 5 +- 9 files changed, 151 insertions(+), 41 deletions(-) diff --git a/libpcsxcore/cdrom.c b/libpcsxcore/cdrom.c index 90ec0d30..28358bf6 100644 --- a/libpcsxcore/cdrom.c +++ b/libpcsxcore/cdrom.c @@ -1711,8 +1711,6 @@ int cdrFreeze(void *f, int Mode) { Find_CurTrack(cdr.SetSectorPlay); if (!Config.Cdda) CDR_play(cdr.SetSectorPlay); - if (psxRegs.interrupt & (1 << PSXINT_CDRPLAY_OLD)) - CDRPLAYREAD_INT((cdr.Mode & MODE_SPEED) ? (cdReadTime / 2) : cdReadTime, 1); } if ((cdr.freeze_ver & 0xffffff00) != 0x63647200) { diff --git a/libpcsxcore/new_dynarec/events.c b/libpcsxcore/new_dynarec/events.c index 2a06c1f9..b1d427c9 100644 --- a/libpcsxcore/new_dynarec/events.c +++ b/libpcsxcore/new_dynarec/events.c @@ -30,10 +30,6 @@ void schedule_timeslice(void) next_interupt = c + min; } -static void unusedInterrupt() -{ -} - typedef void (irq_func)(); static irq_func * const irq_funcs[] = { @@ -47,7 +43,7 @@ static irq_func * const irq_funcs[] = { [PSXINT_GPUOTCDMA] = gpuotcInterrupt, [PSXINT_CDRDMA] = cdrDmaInterrupt, [PSXINT_CDRLID] = cdrLidSeekInterrupt, - [PSXINT_CDRPLAY_OLD] = unusedInterrupt, + [PSXINT_IRQ10] = irq10Interrupt, [PSXINT_SPU_UPDATE] = spuUpdate, [PSXINT_RCNT] = psxRcntUpdate, }; diff --git a/libpcsxcore/new_dynarec/pcsxmem.c b/libpcsxcore/new_dynarec/pcsxmem.c index 87aa17c5..8f79c50a 100644 --- a/libpcsxcore/new_dynarec/pcsxmem.c +++ b/libpcsxcore/new_dynarec/pcsxmem.c @@ -101,7 +101,11 @@ static void io_write_sio32(u32 value) static void map_rcnt_rcount0(u32 mode) { - if (mode & 0x100) { // pixel clock + if (mode & 0x001) { // sync mode + map_item(&mem_iortab[IOMEM32(0x1100)], psxRcntRcount0, 1); + map_item(&mem_iortab[IOMEM16(0x1100)], psxRcntRcount0, 1); + } + else if (mode & 0x100) { // pixel clock map_item(&mem_iortab[IOMEM32(0x1100)], rcnt0_read_count_m1, 1); map_item(&mem_iortab[IOMEM16(0x1100)], rcnt0_read_count_m1, 1); } @@ -113,7 +117,11 @@ static void map_rcnt_rcount0(u32 mode) static void map_rcnt_rcount1(u32 mode) { - if (mode & 0x100) { // hcnt + if (mode & 0x001) { // sync mode + map_item(&mem_iortab[IOMEM32(0x1110)], psxRcntRcount1, 1); + map_item(&mem_iortab[IOMEM16(0x1110)], psxRcntRcount1, 1); + } + else if (mode & 0x100) { // hcnt map_item(&mem_iortab[IOMEM32(0x1110)], rcnt1_read_count_m1, 1); map_item(&mem_iortab[IOMEM16(0x1110)], rcnt1_read_count_m1, 1); } @@ -125,7 +133,7 @@ static void map_rcnt_rcount1(u32 mode) static void map_rcnt_rcount2(u32 mode) { - if (mode & 0x01) { // gate + if ((mode & 7) == 1 || (mode & 7) == 7) { // sync mode map_item(&mem_iortab[IOMEM32(0x1120)], &psxH[0x1000], 0); map_item(&mem_iortab[IOMEM16(0x1120)], &psxH[0x1000], 0); } @@ -146,7 +154,6 @@ static void map_rcnt_rcount2(u32 mode) #endif #define make_rcnt_funcs(i) \ -static u32 io_rcnt_read_count##i() { return psxRcntRcount(i); } \ static u32 io_rcnt_read_mode##i() { return psxRcntRmode(i); } \ static u32 io_rcnt_read_target##i() { return psxRcntRtarget(i); } \ static void io_rcnt_write_count##i(u32 val) { psxRcntWcount(i, val & 0xffff); } \ @@ -348,14 +355,13 @@ void new_dyna_pcsx_mem_init(void) } map_item(&mem_iortab[IOMEM32(0x1040)], io_read_sio32, 1); - map_item(&mem_iortab[IOMEM16(0x1044)], sioReadStat16, 1); - map_item(&mem_iortab[IOMEM32(0x1100)], io_rcnt_read_count0, 1); + map_item(&mem_iortab[IOMEM32(0x1100)], psxRcntRcount0, 1); map_item(&mem_iortab[IOMEM32(0x1104)], io_rcnt_read_mode0, 1); map_item(&mem_iortab[IOMEM32(0x1108)], io_rcnt_read_target0, 1); - map_item(&mem_iortab[IOMEM32(0x1110)], io_rcnt_read_count1, 1); + map_item(&mem_iortab[IOMEM32(0x1110)], psxRcntRcount1, 1); map_item(&mem_iortab[IOMEM32(0x1114)], io_rcnt_read_mode1, 1); map_item(&mem_iortab[IOMEM32(0x1118)], io_rcnt_read_target1, 1); - map_item(&mem_iortab[IOMEM32(0x1120)], io_rcnt_read_count2, 1); + map_item(&mem_iortab[IOMEM32(0x1120)], psxRcntRcount2, 1); map_item(&mem_iortab[IOMEM32(0x1124)], io_rcnt_read_mode2, 1); map_item(&mem_iortab[IOMEM32(0x1128)], io_rcnt_read_target2, 1); // map_item(&mem_iortab[IOMEM32(0x1810)], GPU_readData, 1); @@ -368,13 +374,13 @@ void new_dyna_pcsx_mem_init(void) map_item(&mem_iortab[IOMEM16(0x1048)], sioReadMode16, 1); map_item(&mem_iortab[IOMEM16(0x104a)], sioReadCtrl16, 1); map_item(&mem_iortab[IOMEM16(0x104e)], sioReadBaud16, 1); - map_item(&mem_iortab[IOMEM16(0x1100)], io_rcnt_read_count0, 1); + map_item(&mem_iortab[IOMEM16(0x1100)], psxRcntRcount0, 1); map_item(&mem_iortab[IOMEM16(0x1104)], io_rcnt_read_mode0, 1); map_item(&mem_iortab[IOMEM16(0x1108)], io_rcnt_read_target0, 1); - map_item(&mem_iortab[IOMEM16(0x1110)], io_rcnt_read_count1, 1); + map_item(&mem_iortab[IOMEM16(0x1110)], psxRcntRcount1, 1); map_item(&mem_iortab[IOMEM16(0x1114)], io_rcnt_read_mode1, 1); map_item(&mem_iortab[IOMEM16(0x1118)], io_rcnt_read_target1, 1); - map_item(&mem_iortab[IOMEM16(0x1120)], io_rcnt_read_count2, 1); + map_item(&mem_iortab[IOMEM16(0x1120)], psxRcntRcount2, 1); map_item(&mem_iortab[IOMEM16(0x1124)], io_rcnt_read_mode2, 1); map_item(&mem_iortab[IOMEM16(0x1128)], io_rcnt_read_target2, 1); diff --git a/libpcsxcore/psxbios.c b/libpcsxcore/psxbios.c index 03d6aea2..c899ed80 100644 --- a/libpcsxcore/psxbios.c +++ b/libpcsxcore/psxbios.c @@ -1869,9 +1869,13 @@ void psxBios_GetRCnt() { // 03 PSXBIOS_LOG("psxBios_%s\n", biosB0n[0x03]); #endif - a0&= 0x3; - if (a0 != 3) v0 = psxRcntRcount(a0); - else v0 = 0; + switch (a0 & 0x3) + { + case 0: v0 = psxRcntRcount0(); break; + case 1: v0 = psxRcntRcount1(); break; + case 2: v0 = psxRcntRcount2(); break; + case 3: v0 = 0; break; + } pc0 = ra; } diff --git a/libpcsxcore/psxcounters.c b/libpcsxcore/psxcounters.c index 18bd6a4e..388fb89d 100644 --- a/libpcsxcore/psxcounters.c +++ b/libpcsxcore/psxcounters.c @@ -30,11 +30,12 @@ enum { - Rc0Gate = 0x0001, // 0 not implemented - Rc1Gate = 0x0001, // 0 not implemented - Rc2Disable = 0x0001, // 0 partially implemented - RcUnknown1 = 0x0002, // 1 ? - RcUnknown2 = 0x0004, // 2 ? + RcSyncModeEnable = 0x0001, // 0 + Rc01BlankPause = 0 << 1, // 1,2 + Rc01UnblankReset = 1 << 1, // 1,2 + Rc01UnblankReset2 = 2 << 1, // 1,2 + Rc2Stop = 0 << 1, // 1,2 + Rc2Stop2 = 3 << 1, // 1,2 RcCountToTarget = 0x0008, // 3 RcIrqOnTarget = 0x0010, // 4 RcIrqOnOverflow = 0x0020, // 5 @@ -187,7 +188,8 @@ void _psxRcntWmode( u32 index, u32 value ) } // TODO: wcount must work. - if( value & Rc2Disable ) + if( (value & 7) == (RcSyncModeEnable | Rc2Stop) || + (value & 7) == (RcSyncModeEnable | Rc2Stop2) ) { rcnts[index].rate = 0xffffffff; } @@ -315,14 +317,26 @@ static void scheduleRcntBase(void) void psxRcntUpdate() { - u32 cycle; + u32 cycle, cycles_passed; cycle = psxRegs.cycle; // rcnt 0. - while( cycle - rcnts[0].cycleStart >= rcnts[0].cycle ) + cycles_passed = cycle - rcnts[0].cycleStart; + while( cycles_passed >= rcnts[0].cycle ) { - psxRcntReset( 0 ); + if (((rcnts[0].mode & 7) == (RcSyncModeEnable | Rc01UnblankReset) || + (rcnts[0].mode & 7) == (RcSyncModeEnable | Rc01UnblankReset2)) + && cycles_passed > PSXCLK / 60 / 263) + { + u32 q = cycles_passed / (PSXCLK / 60 / 263 + 1u); + rcnts[0].cycleStart += q * (PSXCLK / 60) / 263u; + break; + } + else + psxRcntReset( 0 ); + + cycles_passed = cycle - rcnts[0].cycleStart; } // rcnt 1. @@ -361,7 +375,7 @@ void psxRcntUpdate() // Update lace. if( hSyncCount >= HSyncTotal[Config.PsxType] ) { - u32 status, field = 0; + u32 status, field = 0, i; rcnts[3].cycleStart += Config.PsxType ? PSXCLK / 50 : PSXCLK / 60; hSyncCount = 0; frame_counter++; @@ -375,6 +389,15 @@ void psxRcntUpdate() } HW_GPU_STATUS = SWAP32(status); GPU_vBlank(0, field); + + for (i = 0; i < 2; i++) + { + if ((rcnts[i].mode & 7) == (RcSyncModeEnable | Rc01UnblankReset) || + (rcnts[i].mode & 7) == (RcSyncModeEnable | Rc01UnblankReset2)) + { + rcnts[i].cycleStart = rcnts[3].cycleStart; + } + } } scheduleRcntBase(); @@ -420,13 +443,46 @@ void psxRcntWtarget( u32 index, u32 value ) /******************************************************************************/ -u32 psxRcntRcount( u32 index ) +u32 psxRcntRcount0() +{ + u32 index = 0; + u32 count; + + if ((rcnts[0].mode & 7) == (RcSyncModeEnable | Rc01UnblankReset) || + (rcnts[0].mode & 7) == (RcSyncModeEnable | Rc01UnblankReset2)) + { + count = psxRegs.cycle - rcnts[index].cycleStart; + count = ((16u * count) % (16u * PSXCLK / 60 / 263)) / 16u; + rcnts[index].cycleStart = psxRegs.cycle - count; + } + else + count = _psxRcntRcount( index ); + + verboseLog( 2, "[RCNT 0] rcount: %04x m: %04x\n", count, rcnts[index].mode); + + return count; +} + +u32 psxRcntRcount1() +{ + u32 index = 1; + u32 count; + + count = _psxRcntRcount( index ); + + verboseLog( 2, "[RCNT 1] rcount: %04x m: %04x\n", count, rcnts[index].mode); + + return count; +} + +u32 psxRcntRcount2() { + u32 index = 2; u32 count; count = _psxRcntRcount( index ); - verboseLog( 2, "[RCNT %i] rcount: %x\n", index, count ); + verboseLog( 2, "[RCNT 2] rcount: %04x m: %04x\n", count, rcnts[index].mode); return count; } diff --git a/libpcsxcore/psxcounters.h b/libpcsxcore/psxcounters.h index 4b7b6b41..03cd4684 100644 --- a/libpcsxcore/psxcounters.h +++ b/libpcsxcore/psxcounters.h @@ -48,7 +48,9 @@ void psxRcntWcount(u32 index, u32 value); void psxRcntWmode(u32 index, u32 value); void psxRcntWtarget(u32 index, u32 value); -u32 psxRcntRcount(u32 index); +u32 psxRcntRcount0(); +u32 psxRcntRcount1(); +u32 psxRcntRcount2(); u32 psxRcntRmode(u32 index); u32 psxRcntRtarget(u32 index); diff --git a/libpcsxcore/psxhw.c b/libpcsxcore/psxhw.c index 8397f391..fb365c07 100644 --- a/libpcsxcore/psxhw.c +++ b/libpcsxcore/psxhw.c @@ -175,7 +175,7 @@ u16 psxHwRead16(u32 add) { return 0x80; case 0x1f801100: - hard = psxRcntRcount(0); + hard = psxRcntRcount0(); #ifdef PSXHW_LOG PSXHW_LOG("T0 count read16: %x\n", hard); #endif @@ -193,7 +193,7 @@ u16 psxHwRead16(u32 add) { #endif return hard; case 0x1f801110: - hard = psxRcntRcount(1); + hard = psxRcntRcount1(); #ifdef PSXHW_LOG PSXHW_LOG("T1 count read16: %x\n", hard); #endif @@ -211,7 +211,7 @@ u16 psxHwRead16(u32 add) { #endif return hard; case 0x1f801120: - hard = psxRcntRcount(2); + hard = psxRcntRcount2(); #ifdef PSXHW_LOG PSXHW_LOG("T2 count read16: %x\n", hard); #endif @@ -346,7 +346,7 @@ u32 psxHwRead32(u32 add) { // time for rootcounters :) case 0x1f801100: - hard = psxRcntRcount(0); + hard = psxRcntRcount0(); #ifdef PSXHW_LOG PSXHW_LOG("T0 count read32: %x\n", hard); #endif @@ -364,7 +364,7 @@ u32 psxHwRead32(u32 add) { #endif return hard; case 0x1f801110: - hard = psxRcntRcount(1); + hard = psxRcntRcount1(); #ifdef PSXHW_LOG PSXHW_LOG("T1 count read32: %x\n", hard); #endif @@ -382,7 +382,7 @@ u32 psxHwRead32(u32 add) { #endif return hard; case 0x1f801120: - hard = psxRcntRcount(2); + hard = psxRcntRcount2(); #ifdef PSXHW_LOG PSXHW_LOG("T2 count read32: %x\n", hard); #endif diff --git a/libpcsxcore/r3000a.c b/libpcsxcore/r3000a.c index 48881068..9b479362 100644 --- a/libpcsxcore/r3000a.c +++ b/libpcsxcore/r3000a.c @@ -191,6 +191,12 @@ void psxBranchTest() { cdrLidSeekInterrupt(); } } + if (psxRegs.interrupt & (1 << PSXINT_IRQ10)) { // irq10 - controller port pin8 + if ((psxRegs.cycle - psxRegs.intCycle[PSXINT_IRQ10].sCycle) >= psxRegs.intCycle[PSXINT_IRQ10].cycle) { + psxRegs.interrupt &= ~(1 << PSXINT_IRQ10); + irq10Interrupt(); + } + } if (psxRegs.interrupt & (1 << PSXINT_SPU_UPDATE)) { // scheduled spu update if ((psxRegs.cycle - psxRegs.intCycle[PSXINT_SPU_UPDATE].sCycle) >= psxRegs.intCycle[PSXINT_SPU_UPDATE].cycle) { psxRegs.interrupt &= ~(1 << PSXINT_SPU_UPDATE); @@ -248,3 +254,42 @@ void psxExecuteBios() { SysPrintf("non-standard BIOS detected (%d, %08x)\n", i, psxRegs.pc); } +// irq10 stuff, very preliminary +static int irq10count; + +static void psxScheduleIrq10One(u32 cycles_abs) { + // schedule relative to frame start + u32 c = cycles_abs - rcnts[3].cycleStart; + assert((s32)c >= 0); + psxRegs.interrupt |= 1 << PSXINT_IRQ10; + psxRegs.intCycle[PSXINT_IRQ10].cycle = c; + psxRegs.intCycle[PSXINT_IRQ10].sCycle = rcnts[3].cycleStart; + new_dyna_set_event(PSXINT_IRQ10, c); +} + +void irq10Interrupt() { + u32 prevc = psxRegs.intCycle[PSXINT_IRQ10].sCycle + + psxRegs.intCycle[PSXINT_IRQ10].cycle; + + psxHu32ref(0x1070) |= SWAPu32(0x400); + +#if 0 + s32 framec = psxRegs.cycle - rcnts[3].cycleStart; + printf("%d:%03d irq10 #%d %3d m=%d,%d\n", frame_counter, + (s32)((float)framec / (PSXCLK / 60 / 263.0f)), + irq10count, psxRegs.cycle - prevc, + (psxRegs.CP0.n.SR & 0x401) != 0x401, !(psxHu32(0x1074) & 0x400)); +#endif + if (--irq10count > 0) + psxScheduleIrq10One(prevc + PSXCLK / 60 / 263); +} + +void psxScheduleIrq10(int irq_count, int x_cycles, int y) { + //printf("%s %d, %d, %d\n", __func__, irq_count, x_cycles, y); + u32 cycles_per_frame = Config.PsxType ? PSXCLK / 50 : PSXCLK / 60; + u32 cycles = rcnts[3].cycleStart + cycles_per_frame; + cycles += y * cycles_per_frame / (Config.PsxType ? 314 : 263); + cycles += x_cycles; + psxScheduleIrq10One(cycles); + irq10count = irq_count; +} diff --git a/libpcsxcore/r3000a.h b/libpcsxcore/r3000a.h index fb5e1db6..3a903b1a 100644 --- a/libpcsxcore/r3000a.h +++ b/libpcsxcore/r3000a.h @@ -180,7 +180,7 @@ enum { PSXINT_NEWDRC_CHECK, PSXINT_RCNT, PSXINT_CDRLID, - PSXINT_CDRPLAY_OLD, /* unused */ + PSXINT_IRQ10, PSXINT_SPU_UPDATE, PSXINT_COUNT }; @@ -257,6 +257,9 @@ void psxBranchTest(); void psxExecuteBios(); void psxJumpTest(); +void irq10Interrupt(); +void psxScheduleIrq10(int irq_count, int x_cycles, int y); + #ifdef __cplusplus } #endif -- 2.39.5