]> git.unchartedbackwaters.co.uk Git - francis/winuae.git/commitdiff
Optional CPU slowdown when CIA timers/VHPOSR is accessed.
authorToni Wilen <twilen@winuae.net>
Sat, 29 Nov 2025 11:14:22 +0000 (13:14 +0200)
committerToni Wilen <twilen@winuae.net>
Sat, 29 Nov 2025 11:14:22 +0000 (13:14 +0200)
cia.cpp
custom.cpp
include/events.h
include/newcpu.h
newcpu.cpp
od-win32/win32.cpp

diff --git a/cia.cpp b/cia.cpp
index 2257c24b6fa4f7e2be426ec2ba0071b192f8050d..430a3acfc13a6299c7db84e00c2722d6dc40b3fa 100644 (file)
--- a/cia.cpp
+++ b/cia.cpp
@@ -136,6 +136,7 @@ struct CIATimer
        uae_u32 loaddelay;
        uae_u8 preovfl;
        uae_u8 cr;
+       uae_u32 timerval_prev;
 };
 
 struct CIA
@@ -403,6 +404,7 @@ static void compute_passed_time(void)
 static void timer_reset(struct CIATimer *t)
 {
        t->timer = t->latch;
+       t->timerval_prev = 0xffffffff;
        if (acc_mode()) {
                if (t->cr & CR_RUNMODE) {
                        t->inputpipe &= ~CIA_PIPE_CLR1;
@@ -529,6 +531,7 @@ static void CIA_update_check(void)
                                if (t->loaddelay & 0x00000001) {
                                        t->timer = t->latch;
                                        t->inputpipe &= ~CIA_PIPE_CLR1;
+                                       t->timerval_prev = 0xffffffff;
                                }
 
                                // timer=0 special cases. TODO: better way to do this..
@@ -562,6 +565,7 @@ static void CIA_update_check(void)
                        c->t[0].timer -= cc;
                        c->t[0].timer &= 0xffff;
                        if (c->t[0].timer == 0) {
+                               c->t[0].timerval_prev = 0xffffffff;
                                // SP in output mode (data sent can be ignored if CIA-A)
                                if ((c->t[0].cr & (CR_SPMODE | CR_RUNMODE)) == CR_SPMODE && c->sdr_cnt > 0) {
                                        c->sdr_cnt--;
@@ -590,11 +594,13 @@ static void CIA_update_check(void)
                if (cc > 0) {
                        if ((c->t[1].timer == 0 && (c->t[1].cr & (CR_INMODE | CR_INMODE1)))) {
                                ovfl[1] = 2;
+                               c->t[1].timerval_prev = 0xffffffff;
                        } else {
                                c->t[1].timer -= cc;
                                c->t[1].timer &= 0xffff;
                                if ((c->t[1].timer == 0 && !(c->t[1].cr & (CR_INMODE | CR_INMODE1)))) {
                                        ovfl[1] = 2;
+                                       c->t[1].timerval_prev = 0xffffffff;
                                }
                        }
                }
@@ -615,6 +621,7 @@ static void CIA_update_check(void)
                                                icr |= 1 << num;
                                        }
                                        t->timer = t->latch;
+                                       t->timerval_prev = 0xffffffff;
                                }
                                if (!loaded[tn]) {
                                        if (t->cr & CR_RUNMODE) {
@@ -1484,17 +1491,34 @@ static uae_u8 ReadCIAReg(int num, int reg)
        case 7:
        {
                uae_u16 tval = t->timer - t->passed;
+               bool timer_prev = true;
                // fast CPU timer hack
-               if ((t->cr & CR_START) && !(t->cr & CR_INMODE1) && !(t->cr & CR_INMODE) && t->latch == t->timer) {
-                       if (currprefs.cachesize || currprefs.m68k_speed < 0) {
-                               uae_u16 adj = cia_timer_hack_adjust;
-                               if (adj >= tval && tval > 1) {
-                                       adj = tval - 1;
+               if ((t->cr & CR_START) && !(t->cr & CR_INMODE1) && !(t->cr & CR_INMODE)) {
+                       if (t->latch == t->timer) {
+                               if (currprefs.cachesize || currprefs.m68k_speed < 0) {
+                                       uae_u16 adj = cia_timer_hack_adjust;
+                                       if (adj >= tval && (tval > 1 || !(t->cr & CR_RUNMODE))) {
+                                               adj = tval - 1;
+                                       }
+                                       tval -= adj;
+                               }
+                       }
+                       if ((slow_cpu_access & 1) && (reg == 4 || reg == 6) && tval == t->timerval_prev) {
+                               if (currprefs.cachesize || currprefs.m68k_speed < 0) {
+                                       uae_u16 adj = cia_timer_hack_adjust;
+                                       if (adj > 0 && ((tval > 1) || !(t->cr & CR_RUNMODE))) {
+                                               tval -= adj;
+                                       }
+                                       set_special(SPCFLAG_CPU_SLOW);
+                                       timer_prev = false;
+                                       t->timerval_prev = 0xffffffff;
                                }
-                               tval -= adj;
                        }
                }
                if (reg == 4 || reg == 6) {
+                       if (timer_prev) {
+                               t->timerval_prev = tval;
+                       }
                        return tval & 0xff;
                }
                return tval >> 8;
@@ -1591,6 +1615,7 @@ static void CIA_thi_write(int num, int tnum, uae_u8 val)
 
                if (!(t->cr & CR_START) || (t->cr & CR_RUNMODE)) {
                        t->timer = t->latch;
+                       t->timerval_prev = 0xffffffff;
                }
 
                if (t->cr & CR_RUNMODE) {
@@ -1655,9 +1680,11 @@ static void CIA_cr_write(int num, int tnum, uae_u8 val)
                if (val & CR_LOAD) {
                        val &= ~CR_LOAD;
                        t->timer = t->latch;
+                       t->timerval_prev = 0xffffffff;
                }
 
                if (val & CR_START) {
+                       t->timerval_prev = 0xffffffff;
                        if (!CIA_timer_inmode(tnum, val)) {
                                t->inputpipe = CIA_PIPE_ALL_MASK;
                                if (t->timer <= 1) {
@@ -1718,10 +1745,12 @@ static void WriteCIAReg(int num, int reg, uae_u8 val)
        switch (reg) {
        case 4:
        case 6:
+               t->timerval_prev = 0xffffffff;
                t->latch = (t->latch & 0xff00) | val;
                break;
        case 5:
        case 7:
+               t->timerval_prev = 0xffffffff;
                CIA_thi_write(num, tnum, val);
                break;
        case 8:
index ae8dd89ff5e7042b643117469ad1690930cb4380..4314f548d60e53d1db159d28c028fc97675762ba 100644 (file)
@@ -435,6 +435,7 @@ static int plffirstline, plflastline;
 * worth the trouble..
 */
 static int vpos_lpen, hpos_lpen, hhpos_lpen, lightpen_triggered;
+static uae_u32 vhposr_prev;
 int lightpen_x[2], lightpen_y[2];
 int lightpen_cx[2], lightpen_cy[2], lightpen_active, lightpen_enabled, lightpen_enabled2;
 
@@ -2631,6 +2632,16 @@ static uae_u16 VHPOSR(void)
        if (0 || M68K_GETPC < 0x00f00000 || M68K_GETPC >= 0x10000000)
                write_log (_T("VHPOSR %04x at %08x %04x\n"), vp, M68K_GETPC, bplcon0);
 #endif
+
+       if (slow_cpu_access & 2) {
+               if (vp == vhposr_prev) {
+                       if (currprefs.cachesize || currprefs.m68k_speed < 0) {
+                               set_special(SPCFLAG_CPU_SLOW);
+                       }
+               }
+               vhposr_prev = vp;
+       }
+
        return vp;
 }
 
@@ -5394,6 +5405,7 @@ static void vsync_handler_post(void)
        vsync_handle_check();
 
        vsync_cycles = get_cycles();
+       vhposr_prev = 0xffffffff;
 }
 
 static void copper_check(int n)
index 0ba788a8be8a775bd894acb28a54fea9e72e56e5..48ffce0f314d0a60b1783ff3190d843bc3ea47bd 100644 (file)
@@ -27,6 +27,7 @@ extern void reset_frame_rate_hack(void);
 extern evt_t vsync_cycles;
 extern evt_t start_cycles;
 extern bool event_wait;
+extern int slow_cpu_access;
 
 extern void event_init(void);
 extern void compute_vsynctime(void);
index 3bd8cbac74367fec63f0eeb37ca3afaa701a511c..85fedd894179169d5b953ca80a5a7b8e4a38204c 100644 (file)
@@ -332,6 +332,7 @@ extern bool m68k_interrupt_delay;
 extern void safe_interrupt_set(int, int, bool);
 
 #define SPCFLAG_CPUINRESET 2
+#define SPCFLAG_CPU_SLOW 4
 #define SPCFLAG_INT 8
 #define SPCFLAG_BRK 16
 #define SPCFLAG_UAEINT 32
index d1b7eed59957fa5d04c21db4ac785cb14d1bd646..94161e5bc92ab9fb3337acc838b4dcf46f79a1cb 100644 (file)
@@ -94,6 +94,7 @@ int hardware_bus_error;
 static int baseclock;
 int m68k_pc_indirect;
 bool m68k_interrupt_delay;
+int slow_cpu_access;
 static bool m68k_accurate_ipl;
 static bool m68k_reset_delay;
 static bool ismoves_nommu;
@@ -4774,6 +4775,16 @@ static int do_specialties (int cycles)
 #endif
        }
 
+       if (spcflags & SPCFLAG_CPU_SLOW) {
+               evt_t c = get_cck_cycles();
+               int cnt = 0;
+               while(regs.spcflags == SPCFLAG_CPU_SLOW && c == get_cck_cycles()) {
+                       x_do_cycles(4 * CYCLE_UNIT);
+                       cnt++;
+               }
+               unset_special(SPCFLAG_CPU_SLOW);
+       }
+
        if (spcflags & SPCFLAG_MMURESTART) {
                // can't have interrupt when 040/060 CPU reruns faulted instruction
                unset_special(SPCFLAG_MMURESTART);
index 49fe75b3e20af24e5742fc4f74e779fe81dd66a9..d13b5c3b71645f439b771dd7c0209fbcf819cb82 100644 (file)
@@ -6559,6 +6559,7 @@ extern int logitech_lcd;
 extern uae_s64 max_avi_size;
 extern int floppy_writemode;
 extern int cia_timer_hack_adjust;
+extern int slow_cpu_access;
 
 extern DWORD_PTR cpu_affinity, cpu_paffinity;
 static DWORD_PTR original_affinity = -1;
@@ -7212,6 +7213,11 @@ static int parseargs(const TCHAR *argx, const TCHAR *np, const TCHAR *np2)
                cia_timer_hack_adjust = getval(np);
                return 2;
        }
+       if (!_tcscmp(arg, _T("slow_cpu_access"))) {
+               slow_cpu_access = getval(np);
+               return 2;
+       }
+
 
 #endif
        return 0;