From 82416cb055c20e1908c87553548f1a6e44187b4c Mon Sep 17 00:00:00 2001 From: Toni Wilen Date: Sat, 17 May 2025 16:53:20 +0300 Subject: [PATCH] Remove interlace artifacts fix --- custom.cpp | 94 +++++++++++++++++++++++++++++++++++++++-------- drawing.cpp | 33 +++++++++++++++++ include/drawing.h | 1 + 3 files changed, 112 insertions(+), 16 deletions(-) diff --git a/custom.cpp b/custom.cpp index 82d56d53..342628b7 100644 --- a/custom.cpp +++ b/custom.cpp @@ -4187,13 +4187,13 @@ static void CLXCON2(uae_u16 v) clxcon2 = v; } -static void draw_line(int, bool); +static void draw_line(int, bool, bool); static uae_u16 CLXDAT(void) { // draw line up to current horizontal position to get accurate collision state if (currprefs.cpu_memory_cycle_exact && currprefs.m68k_speed >= 0 && !doflickerfix_active()) { int ldvpos = linear_display_vpos + draw_line_next_line; - draw_line(ldvpos, false); + draw_line(ldvpos, false, false); } draw_denise_line_queue_flush(); uae_u16 v = clxdat | 0x8000; @@ -10861,12 +10861,37 @@ static bool checkprevfieldlinestateequal(void) // no match but same parameters: do quick BPL emulation storelinestate(); int planes = GET_PLANES(l->bplcon0); + + // first line after accurate -> fast switch + if (doflickerfix_active() && custom_fastmode == 1 && lvpos >= 2) { + scandoubled_line = 1; + lof_display ^= 1; + int lvpos2 = lvpos - 1; + struct linestate *l2 = &lines[lvpos2][lof_display]; + uaecptr bplptx[MAX_PLANES]; + bool skip = false; + for (int i = 0; i < planes; i++) { + uaecptr li1 = scandoubled_bpl_ptr[lvpos2][lof_store][i]; + uaecptr li2 = scandoubled_bpl_ptr[lvpos2][lof_store ^ 1][i]; + skip = !li1 || !li2 || li1 == 0xffffffff || li2 == 0xffffffff; + bplptx[i] = scandoubled_bpl_ptr[lvpos2 - 1][lof_store][i] - li1 + li2; + } + if (skip) { + draw_border_fast(l2, linear_display_vpos + 0); + } else { + draw_line_fast(l2, linear_display_vpos + 0, bplptx, false); + } + lof_display ^= 1; + scandoubled_line = 0; + } + r = draw_line_fast(l, linear_display_vpos + 1, bplpt, true); + if (doflickerfix_active()) { if (scandoubled_bpl_ena[lvpos]) { + scandoubled_line = 1; lof_display ^= 1; struct linestate *l2 = &lines[lvpos][lof_display]; - scandoubled_line = 1; uaecptr bplptx[MAX_PLANES]; bool skip = false; for (int i = 0; i < planes; i++) { @@ -10876,14 +10901,15 @@ static bool checkprevfieldlinestateequal(void) bplptx[i] = bplpt[i] - li1 + li2; } if (skip) { - draw_border_fast(l, linear_display_vpos + 2); + draw_border_fast(l2, linear_display_vpos + 2); } else { draw_line_fast(l2, linear_display_vpos + 2, bplptx, false); } - scandoubled_line = 0; lof_display ^= 1; + scandoubled_line = 0; } } + } ret = r > 0; } @@ -10892,12 +10918,15 @@ static bool checkprevfieldlinestateequal(void) return ret; } -static void draw_line(int ldvpos, bool finalseg) +static void draw_line(int ldvpos, bool finalseg, bool blank) { int dvp = calculate_linetype(ldvpos); int wclks = draw_line_wclks; int maxv = maxvpos_display + maxvpos_display_vsync - vsync_startline + lof_store; - if (!programmedmode && (ldvpos >= maxv || ldvpos + 1 < minfirstline - vsync_startline)) { + if (ldvpos >= maxv || ldvpos + 1 < minfirstline - vsync_startline) { + wclks = -1; + } + if (blank) { wclks = -1; } @@ -10962,20 +10991,23 @@ static void do_draw_line(void) draw_line_wclks = linear_hpos - (display_hstart_cyclewait_skip - display_hstart_cyclewait_skip2); if (custom_fastmode >= 0) { if (doflickerfix_active() && scandoubled_bpl_ena[linear_vpos]) { - draw_denise_line_queue_flush(); - denise_store_registers(); - draw_line(linear_display_vpos, true); + // if odd or even line is blanked, make both lines blanked to prevent flickering last line + int dvp = calculate_linetype(linear_display_vpos); + int maxv = maxvpos_display - vsync_startline; + bool blank = linear_display_vpos >= maxv; + denise_store_restore_registers_queue(true, rga_denise_cycle_line); + draw_line(linear_display_vpos, true, blank); draw_denise_line_queue_flush(); do_scandouble(); - denise_restore_registers(); + denise_store_restore_registers_queue(false, rga_denise_cycle_line); lof_display ^= 1; scandoubled_line = 1; rga_denise_cycle_count_start = 0; - draw_line(linear_display_vpos, true); + draw_line(linear_display_vpos, true, blank); scandoubled_line = 0; lof_display ^= 1; } else { - draw_line(linear_display_vpos, true); + draw_line(linear_display_vpos, true, false); } } @@ -11367,8 +11399,8 @@ static void custom_trigger_start(void) bool same = checkprevfieldlinestateequal(); if (same) { start_sync_equalline_handler(); - if (custom_fastmode > 0) { - custom_fastmode = 2; + if (custom_fastmode >= 1) { + custom_fastmode++; } else { custom_fastmode = 1; do_imm_dmal(); @@ -12248,9 +12280,39 @@ static void sync_equalline_handler(void) int rdc = rga_denise_cycle; do_draw_line(); rga_denise_cycle = rdc; + +#if 0 + + if (doflickerfix_active()) { + int lvpos = linear_vpos - 1; + struct linestate *l = &lines[lvpos][lof_display]; + if (scandoubled_bpl_ena[lvpos]) { + int planes = GET_PLANES(l->bplcon0); + lof_display ^= 1; + struct linestate *l2 = &lines[lvpos][lof_display]; + scandoubled_line = 1; + uaecptr bplptx[MAX_PLANES]; + bool skip = false; + for (int i = 0; i < planes; i++) { + uaecptr li1 = scandoubled_bpl_ptr[lvpos][lof_store][i]; + uaecptr li2 = scandoubled_bpl_ptr[lvpos][lof_store ^ 1][i]; + skip = !li1 || !li2 || li1 == 0xffffffff || li2 == 0xffffffff; + bplptx[i] = bplpt[i] - li1 + li2; + } + if (skip) { + draw_border_fast(l, linear_display_vpos + 1); + } else { + draw_line_fast(l2, linear_display_vpos + 1, bplptx, false); + } + scandoubled_line = 0; + lof_display ^= 1; + } + } + +#endif + } else { denise_handle_quick_strobe_queue(str, display_hstart_fastmode, rga_denise_cycle); - //denise_handle_quick_strobe(str, display_hstart_fastmode); next_denise_rga(); decide_line_end(); } diff --git a/drawing.cpp b/drawing.cpp index c89f47de..ddb2fe46 100644 --- a/drawing.cpp +++ b/drawing.cpp @@ -176,6 +176,12 @@ static void read_denise_line_queue(void) } else if (q->type == 6) { denise_update_reg(q->reg, q->val, q->linecnt); nolock = true; + } else if (q->type == 7) { + if (q->val) { + denise_store_registers(); + } else { + denise_restore_registers(); + } } if (!nolock) { @@ -7330,6 +7336,33 @@ void denise_update_reg_queue(uae_u16 reg, uae_u16 v, uae_u32 linecnt) } } +void denise_store_restore_registers_queue(bool store, uae_u32 linecnt) +{ + if (MULTITHREADED_DENISE) { + + if (!waitqueue()) { + return; + } + struct denise_rga_queue *q = &rga_queue[rga_queue_write & DENISE_RGA_SLOT_CHUNKS_MASK]; + q->type = 7; + q->vpos = vpos; + q->linear_vpos = linear_vpos; + q->val = store ? 1 : 0; + q->linecnt = linecnt; + + addtowritequeue(); + + } else { + + updatelinedata(); + if (store) { + denise_store_registers(); + } else { + denise_restore_registers(); + } + } +} + void draw_denise_line_queue_flush(void) { if (MULTITHREADED_DENISE) { diff --git a/include/drawing.h b/include/drawing.h index 49fb0d24..228a1b16 100644 --- a/include/drawing.h +++ b/include/drawing.h @@ -197,5 +197,6 @@ bool drawing_can_lineoptimizations(void); void set_drawbuffer(void); int gethresolution(void); void denise_update_reg_queue(uae_u16 reg, uae_u16 v, uae_u32 linecnt); +void denise_store_restore_registers_queue(bool store, uae_u32 linecnt); #endif /* UAE_DRAWING_H */ -- 2.47.3