preliminary irq10 support
authornotaz <notasas@gmail.com>
Mon, 4 Sep 2023 20:09:05 +0000 (23:09 +0300)
committernotaz <notasas@gmail.com>
Mon, 4 Sep 2023 20:30:07 +0000 (23:30 +0300)
libretro/pcsx_rearmed#723

libpcsxcore/cdrom.c
libpcsxcore/new_dynarec/events.c
libpcsxcore/new_dynarec/pcsxmem.c
libpcsxcore/psxbios.c
libpcsxcore/psxcounters.c
libpcsxcore/psxcounters.h
libpcsxcore/psxhw.c
libpcsxcore/r3000a.c
libpcsxcore/r3000a.h

index 90ec0d3..28358bf 100644 (file)
@@ -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) {
index 2a06c1f..b1d427c 100644 (file)
@@ -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,
 };
index 87aa17c..8f79c50 100644 (file)
@@ -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);
 
index 03d6aea..c899ed8 100644 (file)
@@ -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;
 }
 
index 18bd6a4..388fb89 100644 (file)
 
 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;
 }
index 4b7b6b4..03cd468 100644 (file)
@@ -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);
 
index 8397f39..fb365c0 100644 (file)
@@ -175,7 +175,7 @@ u16 psxHwRead16(u32 add) {
                        return 0x80;\r
 
                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
index 4888106..9b47936 100644 (file)
@@ -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;
+}
index fb5e1db..3a903b1 100644 (file)
@@ -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