]> git.unchartedbackwaters.co.uk Git - francis/winuae.git/commitdiff
Blanking/no signal/mode change improvements
authorToni Wilen <twilen@winuae.net>
Mon, 13 Apr 2026 17:46:25 +0000 (20:46 +0300)
committerToni Wilen <twilen@winuae.net>
Mon, 13 Apr 2026 17:46:25 +0000 (20:46 +0300)
custom.cpp
drawing.cpp

index bdbc7c06f50fdf56eb6084ec6972d78c38e3a467..793abd262b9c48abb718fd2c12a42c9747cb046c 100644 (file)
@@ -120,6 +120,7 @@ static bool dmal_next;
 static int fast_lines_cnt;
 static bool lineoptimizations_draw_always;
 static int agnus_trigger_cck;
+static int init_beamcon_delay;
 
 static uae_u32 scandoubled_bpl_ptr[MAX_SCANDOUBLED_LINES + 1][2][MAX_PLANES];
 static bool scandoubled_bpl_ena[MAX_SCANDOUBLED_LINES + 1];
@@ -569,7 +570,7 @@ static uae_u32 cop1lc, cop2lc, copcon;
 */
 
 static bool agnus_phsync, agnus_phblank;
-static uae_u32 agnus_phblank_start_tmp, agnus_phblank_start, agnus_phblank_end, agnus_hsync_start;
+static uae_u32 agnus_phblank_start_tmp, agnus_phblank_start, agnus_phblank_end, agnus_hsync_start, agnus_vsync_start;
 static int hsync_ccks;
 static int current_linear_hs_hb_dist;
 static uae_u32 agnus_hsstrt_cck, agnus_hsstop_cck;
@@ -779,7 +780,6 @@ uae_u32 hsync_counter, vsync_counter;
 frame_time_t idletime;
 int bogusframe;
 static int display_vsync_counter, display_hsync_counter;
-static evt_t display_last_hsync, display_last_vsync;
 
 static bool ddf_limit_in, ddf_limit_out, ddf_limit, ddfstrt_match, hwi_old;
 static int ddf_stopping, ddf_enable_on;
@@ -1596,29 +1596,31 @@ static void update_display_vars(void)
                hpixels *= 2;
        }
        int vpixels = vsync_lines - minfirstline;
-       int hpixelsd = hpixels * 85 / 100;
-       if (hpixelsd < vpixels) {
-               doublescan = 1;
-               if (programmedmode == 2) {
-                       programmedmode = 1;
-               }
-               hpixelsd *= 2;
-       }
-       if (currprefs.gfx_keep_aspect) {
-               bool dbl = line_is_doubled();
-               if (dbl) {
-                       vpixels *= 2;
-               }
+       if (vpixels > 0 && minfirstline > 0) {
+               int hpixelsd = hpixels * 85 / 100;
                if (hpixelsd < vpixels) {
-                       doublescan2x = 1;
+                       doublescan = 1;
+                       if (programmedmode == 2) {
+                               programmedmode = 1;
+                       }
                        hpixelsd *= 2;
-                       if (hpixelsd < vpixels) {
-                               doublescan2x = 2;
+               }
+               if (currprefs.gfx_keep_aspect) {
+                       bool dbl = line_is_doubled();
+                       if (dbl) {
+                               vpixels *= 2;
                        }
-               } else if (hpixelsd > vpixels * 2) {
-                       doublescan2x = -1;
-                       if (hpixelsd > vpixels * 4) {
-                               doublescan2x = -2;
+                       if (hpixelsd < vpixels) {
+                               doublescan2x = 1;
+                               hpixelsd *= 2;
+                               if (hpixelsd < vpixels) {
+                                       doublescan2x = 2;
+                               }
+                       } else if (hpixelsd > vpixels * 2) {
+                               doublescan2x = -1;
+                               if (hpixelsd > vpixels * 4) {
+                                       doublescan2x = -2;
+                               }
                        }
                }
        }
@@ -1844,6 +1846,22 @@ void compute_framesync(void)
        );
 }
 
+// do not switch to H/V sync cable mode if required programmed mode registers are uninitialized
+static bool valid_programmed_mode(void)
+{
+       if ((beamcon0 & (BEAMCON0_VARHSYEN | BEAMCON0_VARCSYEN)) && programmed_register_accessed_h) {
+               if (hsstrt == 0xffff || hsstop == 0xffff) {
+                       return false;
+               }
+       }
+       if ((beamcon0 & (BEAMCON0_VARVSYEN | BEAMCON0_VARCSYEN)) && programmed_register_accessed_v) {
+               if (vsstrt == 0xffff || vsstop == 0xffff) {
+                       return false;
+               }
+       }
+       return true;
+}
+
 /* set PAL/NTSC or custom timing variables */
 static void init_beamcon0(void)
 {
@@ -1863,15 +1881,15 @@ static void init_beamcon0(void)
        }
        beamcon0_pal = !isntsc;
 
-       if (currprefs.cs_hvcsync == HVSYNC_COMBINED || currprefs.cs_hvcsync == HVSYNC_COMBINED_SYNC) {
+       if ((currprefs.cs_hvcsync == HVSYNC_COMBINED || currprefs.cs_hvcsync == HVSYNC_COMBINED_SYNC) && valid_programmed_mode()) {
                bemcon0_hsync_mask = BEAMCON0_VARHSYEN | BEAMCON0_VARCSYEN;
                bemcon0_vsync_mask = BEAMCON0_VARVSYEN | BEAMCON0_VARCSYEN;
-       } else if (currprefs.cs_hvcsync == HVSYNC_CSYNC || currprefs.cs_hvcsync == HVSYNC_CSYNC_SYNC) {
-               bemcon0_hsync_mask = BEAMCON0_VARCSYEN;
-               bemcon0_vsync_mask = BEAMCON0_VARCSYEN;
-       } else {
+       } else if (currprefs.cs_hvcsync == HVSYNC_HVSYNC || currprefs.cs_hvcsync == HVSYNC_HVSYNC_SYNC) {
                bemcon0_hsync_mask = BEAMCON0_VARHSYEN;
                bemcon0_vsync_mask = BEAMCON0_VARVSYEN;
+       } else {
+               bemcon0_hsync_mask = BEAMCON0_VARCSYEN;
+               bemcon0_vsync_mask = BEAMCON0_VARCSYEN;
        }
        beamcon0_has_hsync = (beamcon0 & bemcon0_hsync_mask) != 0;
        beamcon0_has_vsync = (beamcon0 & bemcon0_vsync_mask) != 0;
@@ -2054,6 +2072,7 @@ static void init_beamcon0(void)
        display_hstart_cyclewait_start = size;
        resetfulllinestate();
        updatehwhpostable();
+       init_beamcon_delay = -1;
 }
 
 static void init_hz_reset(void)
@@ -4989,16 +5008,29 @@ static void vsync_check_vsyncmode(void)
                        }
                        if ((current_linear_hblen != current_linear_hblen_temp || denise_get_hbstate(true)) && currprefs.cs_hvcsync < HVSYNC_SYNCPOS) {
                                current_linear_hblen = current_linear_hblen_temp;
-                               init_beamcon0();
                                framesync = true;
+                               init_beamcon0();
                                display_redraw = true;
                        }
                }
        }
 
-       if (framesync) {
-               compute_framesync();
-               devices_syncchange();
+       // if no sync condition, wait until sync is back before recalculating display
+       if (!nosignal_cnt && !nosignal_trigger) {
+               if (framesync) {
+                       compute_framesync();
+                       devices_syncchange();
+                       init_beamcon_delay = 0;
+               }
+               if (init_beamcon_delay < 0) {
+                       init_beamcon_delay = 2;
+               } else if (init_beamcon_delay > 0) {
+                       init_beamcon_delay--;
+                       if (init_beamcon_delay == 0) {
+                               compute_framesync();
+                               devices_syncchange();
+                       }
+               }
        }
 
        if (agnus_afterreset > 0) {
@@ -5108,46 +5140,6 @@ static void check_interlace(void)
        prevlofs[0] = lof_display;
 }
 
-static void check_no_signal(void)
-{
-       evt_t c = get_cycles();
-       if (issyncstopped(bplcon0)) {
-               nosignal_trigger = true;
-       }
-       // Missing vsync
-       if (c > display_last_vsync + (CHIPSET_CLOCK_PAL / 10) * CYCLE_UNIT) {
-               nosignal_trigger = true;
-       }
-       // Missing hsync
-       if (c > display_last_hsync + (CHIPSET_CLOCK_PAL / 100) * CYCLE_UNIT) {
-               nosignal_trigger = true;
-       }
-       // Inverted CSYNC
-       if ((beamcon0 & BEAMCON0_CSYTRUE) && (currprefs.cs_hvcsync == HVSYNC_CSYNC || currprefs.cs_hvcsync == HVSYNC_CSYNC_SYNC)) {
-               nosignal_trigger = true;
-       }
-       // BLANKEN set: horizontal blanking is merged with CSYNC
-       if ((beamcon0 & BEAMCON0_BLANKEN) && (currprefs.cs_hvcsync == HVSYNC_CSYNC || currprefs.cs_hvcsync == HVSYNC_CSYNC_SYNC)) {
-               nosignal_trigger = true;
-       }
-       if ((beamcon0 & BEAMCON0_CSCBEN) && (currprefs.cs_hvcsync == HVSYNC_HVSYNC || currprefs.cs_hvcsync == HVSYNC_HVSYNC_SYNC)) {
-               nosignal_trigger = true;
-       }
-       if (beamcon0 & BEAMCON0_VARBEAMEN) {
-               if (htotal < 50 || htotal >= 255) {
-                       nosignal_trigger = true;
-               }
-               if (vtotal < 100 || vtotal > 1000) {
-                       nosignal_trigger = true;
-               }
-               // CSY output is invalid (no vsync part included) if HTOTAL is too small + hardwired CSYNC.
-               int csyh = (beamcon0 & 0x20) ? 0x8c : 0x8d;
-               if (htotal < csyh && !(beamcon0 & BEAMCON0_VARCSYEN) && (currprefs.cs_hvcsync == HVSYNC_CSYNC || currprefs.cs_hvcsync == HVSYNC_CSYNC_SYNC)) {
-                       nosignal_trigger = true;
-               }
-       }
-}
-
 static void handle_nosignal(void)
 {
        if (nosignal_status < 0) {
@@ -5165,13 +5157,15 @@ static void handle_nosignal(void)
                struct amigadisplay *ad = &adisplays[0];
                nosignal_trigger = false;
                resetfulllinestate();
-               denise_clearbuffers();
+               if (!nosignal_cnt) {
+                       denise_clearbuffers();
+               }
                if (!ad->specialmonitoron) {
                        if (currprefs.gfx_monitorblankdelay > 0) {
                                nosignal_status = 1;
                                nosignal_cnt = (int)(currprefs.gfx_monitorblankdelay / (1000.0f / vblank_hz));
                                if (nosignal_cnt <= 0) {
-                                       nosignal_cnt = 1;
+                                       nosignal_cnt = 2;
                                }
                        } else {
                                nosignal_status = 2;
@@ -5181,6 +5175,50 @@ static void handle_nosignal(void)
        }
 }
 
+static void check_no_signal(void)
+{
+       if (!nosignal_trigger) {
+
+               evt_t c = get_cycles();
+               uae_u32 cck = get_cck_cycles();
+
+               if (issyncstopped(bplcon0)) {
+                       nosignal_trigger = true;
+               }
+               // Missing vsync
+               if (cck > agnus_vsync_start + 256 * 1000) {
+                       nosignal_trigger = true;
+               }
+               // Missing hsync
+               if (cck > agnus_hsync_start + 400) {
+                       nosignal_trigger = true;
+               }
+               // Inverted CSYNC
+               if ((beamcon0 & BEAMCON0_CSYTRUE) && (currprefs.cs_hvcsync == HVSYNC_CSYNC || currprefs.cs_hvcsync == HVSYNC_CSYNC_SYNC)) {
+                       nosignal_trigger = true;
+               }
+               // BLANKEN set: horizontal blanking is merged with CSYNC
+               if ((beamcon0 & BEAMCON0_BLANKEN) && (currprefs.cs_hvcsync == HVSYNC_CSYNC || currprefs.cs_hvcsync == HVSYNC_CSYNC_SYNC)) {
+                       nosignal_trigger = true;
+               }
+               if ((beamcon0 & BEAMCON0_CSCBEN) && (currprefs.cs_hvcsync == HVSYNC_HVSYNC || currprefs.cs_hvcsync == HVSYNC_HVSYNC_SYNC)) {
+                       nosignal_trigger = true;
+               }
+               if (beamcon0 & BEAMCON0_VARBEAMEN) {
+                       // CSY output is invalid (no vsync part included) if HTOTAL is too small + hardwired CSYNC.
+                       int csyh = (beamcon0 & 0x20) ? 0x8c : 0x8d;
+                       if (htotal < csyh && !(beamcon0 & BEAMCON0_VARCSYEN) && (currprefs.cs_hvcsync == HVSYNC_CSYNC || currprefs.cs_hvcsync == HVSYNC_CSYNC_SYNC)) {
+                               nosignal_trigger = true;
+                       }
+               }
+
+               if (nosignal_trigger && !nosignal_cnt) {
+                       handle_nosignal();
+               }
+       }
+
+}
+
 static void virtual_vsync_check(void)
 {
        check_display_mode_change();
@@ -5211,8 +5249,6 @@ static void vsync_handler_post(void)
        uae_lua_run_handler("on_uae_vsync");
 #endif
 
-       check_no_signal();
-
 #ifdef DEBUGGER
        if (debug_copper) {
                record_copper_reset();
@@ -6430,8 +6466,6 @@ static bool uae_quit_check(void)
 // executed at start of scanline
 static void hsync_handler(bool vs)
 {
-       display_last_hsync = get_cycles();
-
        hsync_handler_pre(vs);
        if (vs) {
                devices_vsync_pre();
@@ -6447,20 +6481,20 @@ static void hsync_handler(bool vs)
                inputdevice_read_msg(true);
                vsync_display_render();
                vsync_display_rendered = false;
-               if ((currprefs.cs_hvcsync == HVSYNC_COMBINED || currprefs.cs_hvcsync == HVSYNC_COMBINED_SYNC)) {
+               if ((currprefs.cs_hvcsync == HVSYNC_COMBINED || currprefs.cs_hvcsync == HVSYNC_COMBINED_SYNC) && valid_programmed_mode()) {
                        if (beamcon0 & (BEAMCON0_VARVSYEN | BEAMCON0_VARCSYEN)) {
                                lof_display = lof_pdetect;
                        } else {
                                lof_display = lof_detect;
                        }
-               } else if (currprefs.cs_hvcsync == HVSYNC_CSYNC || currprefs.cs_hvcsync == HVSYNC_CSYNC_SYNC) {
-                       if (beamcon0 & BEAMCON0_VARCSYEN) {
+               } else if (currprefs.cs_hvcsync == HVSYNC_HVSYNC || currprefs.cs_hvcsync == HVSYNC_HVSYNC_SYNC) {
+                       if (beamcon0 & BEAMCON0_VARVSYEN) {
                                lof_display = lof_pdetect;
                        } else {
                                lof_display = lof_detect;
                        }
-               } else if (currprefs.cs_hvcsync == HVSYNC_HVSYNC || currprefs.cs_hvcsync == HVSYNC_HVSYNC_SYNC) {
-                       if (beamcon0 & BEAMCON0_VARVSYEN) {
+               } else {
+                       if (beamcon0 & BEAMCON0_VARCSYEN) {
                                lof_display = lof_pdetect;
                        } else {
                                lof_display = lof_detect;
@@ -6472,7 +6506,6 @@ static void hsync_handler(bool vs)
                display_vsync_counter++;
                maxvpos_display_vsync_next = true;
                display_hsync_counter = 0;
-               display_last_vsync = get_cycles();
                vsync_start_check();
        } else if (vpos != vsync_startline + 1 && maxvpos_display_vsync_next) {
                // protect against weird VPOSW writes causing continuous vblanks
@@ -6598,8 +6631,7 @@ void custom_reset(bool hardreset, bool keyboardreset)
        vsync_counter = 0;
        display_vsync_counter = 0;
        display_hsync_counter = 0;
-       display_last_hsync = get_cycles();
-       display_last_vsync = get_cycles();
+       agnus_vsync_start = get_cck_cycles();
        agnus_hsync_start = get_cck_cycles();
        next_lineno = 0;
 
@@ -9857,6 +9889,7 @@ static void vsync_mark(void)
 {
        if (vsync_linecnt) {
                vsync_lines = vsync_linecnt;
+               agnus_vsync_start = get_cck_cycles();
                vsync_linecnt = 0;
                linear_vpos_prev[2] = linear_vpos_prev[1];
                linear_vpos_prev[1] = linear_vpos_prev[0];
@@ -10961,6 +10994,8 @@ static void custom_trigger_start(void)
                }
        }
 
+       check_no_signal();
+
        if (!(new_beamcon0 & BEAMCON0_PAL) && !(new_beamcon0 & BEAMCON0_LOLDIS)) {
                lol = lol ? false : true;
                linetoggle = true;
index 05caa274cce78b7bcda6a7a15e3e0328710811f1..eec6dff0e549aefd08066d85a8aa7decf63fa279 100644 (file)
@@ -5670,7 +5670,7 @@ static void get_line(int monid, int gfx_ypos, enum nln_how how, int lol_shift_pr
                struct vidbuf_description* vidinfo = &adisplays[0].gfxvidinfo;
                int l = 0;
                while (l < vb->inheight) {
-                       uae_u8b = get_row(monid, l);
+                       uae_u8 *b = get_row(monid, l);
                        memset(b, 0, vb->inwidth * vb->pixbytes);
                        l++;
                }
@@ -6134,41 +6134,42 @@ static void draw_denise_line(int gfx_ypos, enum nln_how how, uae_u32 linecnt, in
                ls->lol = lol;
        }
 
-       frame_internal_pixel_cnt = internal_pixel_cnt;
-
-       // detect horizontal blanking
-       if (!denise_vblank_active) {
-               int ipc = internal_pixel_cnt + (denise_strlong_seen ? lol * 8 : 0);
-               linear_denise_frame_hbstrt = hbstrt_offset + (denise_strlong_seen ? lol * 8 : 0);
-               linear_denise_frame_hbstop = hbstop_offset;
-               //write_log("%d %d\n", linear_denise_frame_hbstrt, linear_denise_frame_hbstop);
-
-               if (linear_denise_frame_hbstrt == linear_denise_frame_hbstrt_tmp && linear_denise_frame_hbstop == linear_denise_frame_hbstop_tmp) {
-                       denise_hbstrt_relative_cnt++;
-                       if (denise_hbstrt_relative_cnt > maxvpos_display / 2) {
-                               int ss = linear_denise_frame_hbstrt_sel;
-                               int ee = linear_denise_frame_hbstop_sel;
-                               linear_denise_frame_hbstrt_sel = linear_denise_frame_hbstrt_tmp;
-                               linear_denise_frame_hbstop_sel = linear_denise_frame_hbstop_tmp;
-                               if (linear_denise_frame_hbstrt_sel < 0 || linear_denise_frame_hbstop_sel < 0) {
-                                       linear_denise_frame_hbstrt_sel = -1;
-                                       linear_denise_frame_hbstop_sel = -1;
-                               } else {
-                                       if (linear_denise_frame_hbstrt_sel > linear_denise_frame_hbstop_sel) {
-                                               linear_denise_frame_hbstrt_sel -= ipc;
+       if (internal_pixel_cnt > 0) {
+               frame_internal_pixel_cnt = internal_pixel_cnt;
+               // detect horizontal blanking
+               if (!denise_vblank_active) {
+                       int ipc = internal_pixel_cnt + (denise_strlong_seen ? lol * 8 : 0);
+                       linear_denise_frame_hbstrt = hbstrt_offset + (denise_strlong_seen ? lol * 8 : 0);
+                       linear_denise_frame_hbstop = hbstop_offset;
+                       //write_log("%d %d\n", linear_denise_frame_hbstrt, linear_denise_frame_hbstop);
+
+                       if (linear_denise_frame_hbstrt == linear_denise_frame_hbstrt_tmp && linear_denise_frame_hbstop == linear_denise_frame_hbstop_tmp) {
+                               denise_hbstrt_relative_cnt++;
+                               if (denise_hbstrt_relative_cnt > maxvpos_display / 2) {
+                                       int ss = linear_denise_frame_hbstrt_sel;
+                                       int ee = linear_denise_frame_hbstop_sel;
+                                       linear_denise_frame_hbstrt_sel = linear_denise_frame_hbstrt_tmp;
+                                       linear_denise_frame_hbstop_sel = linear_denise_frame_hbstop_tmp;
+                                       if (linear_denise_frame_hbstrt_sel < 0 || linear_denise_frame_hbstop_sel < 0) {
+                                               linear_denise_frame_hbstrt_sel = -1;
+                                               linear_denise_frame_hbstop_sel = -1;
+                                       } else {
+                                               if (linear_denise_frame_hbstrt_sel > linear_denise_frame_hbstop_sel) {
+                                                       linear_denise_frame_hbstrt_sel -= ipc;
+                                               }
+                                       }
+                                       linear_denise_frame_hbstrt_sel += linear_denise_strobe_offset + 2 * 8;
+                                       linear_denise_frame_hbstop_sel += linear_denise_strobe_offset + 2 * 8;
+                                       denise_hbstrt_relative_cnt = 0;
+                                       if (ss != linear_denise_frame_hbstrt_sel || ee != linear_denise_frame_hbstop_sel) {
+                                               denise_blanking_changed = true;
                                        }
                                }
-                               linear_denise_frame_hbstrt_sel += linear_denise_strobe_offset + 2 * 8;
-                               linear_denise_frame_hbstop_sel += linear_denise_strobe_offset + 2 * 8;
+                       } else {
+                               linear_denise_frame_hbstrt_tmp = linear_denise_frame_hbstrt;
+                               linear_denise_frame_hbstop_tmp = linear_denise_frame_hbstop;
                                denise_hbstrt_relative_cnt = 0;
-                               if (ss != linear_denise_frame_hbstrt_sel || ee != linear_denise_frame_hbstop_sel) {
-                                       denise_blanking_changed = true;
-                               }
                        }
-               } else {
-                       linear_denise_frame_hbstrt_tmp = linear_denise_frame_hbstrt;
-                       linear_denise_frame_hbstop_tmp = linear_denise_frame_hbstop;
-                       denise_hbstrt_relative_cnt = 0;
                }
        }