From: Toni Wilen Date: Mon, 13 Apr 2026 17:46:25 +0000 (+0300) Subject: Blanking/no signal/mode change improvements X-Git-Url: https://git.unchartedbackwaters.co.uk/w/?a=commitdiff_plain;h=fb64e77297f98ad7f7f4dbd7c0945c65118c874c;p=francis%2Fwinuae.git Blanking/no signal/mode change improvements --- diff --git a/custom.cpp b/custom.cpp index bdbc7c06..793abd26 100644 --- a/custom.cpp +++ b/custom.cpp @@ -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; diff --git a/drawing.cpp b/drawing.cpp index 05caa274..eec6dff0 100644 --- a/drawing.cpp +++ b/drawing.cpp @@ -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_u8* b = 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; } }