]> git.unchartedbackwaters.co.uk Git - francis/winuae.git/commitdiff
Interlace LOF change update, scandoubler mode last line blanking
authorToni Wilen <twilen@winuae.net>
Sat, 27 Nov 2021 18:51:51 +0000 (20:51 +0200)
committerToni Wilen <twilen@winuae.net>
Sat, 27 Nov 2021 18:51:51 +0000 (20:51 +0200)
custom.cpp
drawing.cpp
include/custom.h
od-win32/screenshot.cpp

index 9f2da1ea2000cb823dd22b59402ba4ed62566409..f1f42fcd62bf369c9ec48ac6375ef9bf062c42bc 100644 (file)
@@ -129,7 +129,7 @@ int vpos, vpos_prev, vposh;
 static int hpos_hsync_extra;
 static int vpos_count, vpos_count_diff;
 int lof_store; // real bit in custom registers
-static int lof_current; // what display device thinks
+int lof_display; // what display device thinks
 static bool lof_lastline, lof_prev_lastline;
 static int lol, lol_prev;
 static int next_lineno;
@@ -635,10 +635,14 @@ STATIC_INLINE int hpos_to_diw(int pos)
        return ((pos + hpos_hsync_extra) * 2 - DDF_OFFSET) * 4;
 }
 
-static int doflickerfix(void)
+static bool doflickerfix_possible(void)
 {
        return currprefs.gfx_vresolution && doublescan < 0 && vpos < MAXVPOS;
 }
+static bool doflickerfix_active(void)
+{
+       return interlace_seen > 0 && doflickerfix_possible();
+}
 
 uae_u32 get_copper_address(int copno)
 {
@@ -851,7 +855,7 @@ static void remember_ctable_for_border(void)
 // This does not need start line check because only OCS Denise modes use this.
 static int get_equ_vblank_endline(void)
 {
-       return equ_vblank_endline + (equ_vblank_toggle ? (lof_current ? 1 : 0) : 0);
+       return equ_vblank_endline + (equ_vblank_toggle ? (lof_store ? 1 : 0) : 0);
 }
 
 static int output_res(int res)
@@ -927,7 +931,7 @@ static void record_color_change2(int hpos, int regno, uae_u32 value)
        }
 
        // HCENTER blanking
-       if (hcenter_v2 && vs_state_on && vpos < maxvpos_display_vsync && lof_current) {
+       if (hcenter_v2 && vs_state_on && vpos < maxvpos_display_vsync && lof_display) {
                int chpos = pos;
                if (hcenter_v2_end == 0xffff && hcenter_v2 < chpos && hcenter_v2 >= last_recorded_diw_hpos) {
                        cc = &curr_color_changes[next_color_change];
@@ -1064,7 +1068,7 @@ static void sync_color_changes(int hpos)
 // erase (color0 or bblank) area between previous end and new start
 static void hdiw_restart(int diw_last, int diw_current)
 {
-       if (diw_last >= diw_current || line_hidden()) {
+       if (diw_last >= diw_current || line_hidden() || nocustom()) {
                return;
        }
        // update state
@@ -3395,6 +3399,12 @@ static void finish_final_fetch(int hpos)
        clear_bitplane_pipeline(1);
 
        if (thisline_decision.plfleft < 0) {
+               // registers that affect programmed vblank must be checked even if line is blank
+               if (line_decisions[next_lineno].bplcon3 != thisline_decision.bplcon3
+                       || (line_decisions[next_lineno].bplcon0 & 1) != (thisline_decision.bplcon0 & 1)
+                       || line_decisions[next_lineno].vb != thisline_decision.vb
+               )
+                       thisline_changed = 1;
                return;
        }
 
@@ -3453,8 +3463,8 @@ static void do_sprite_fetch(int hpos, uae_u8 dat);
 
 static void scandoubler_bpl_dma_start(void)
 {
-       if (!scandoubled_line && doflickerfix() && interlace_seen > 0) {
-               int lof = 1 - lof_current;
+       if (!scandoubled_line && doflickerfix_active()) {
+               int lof = 1 - lof_display;
                for (int i = 0; i < MAX_PLANES; i++) {
                        prevbpl[lof][vpos][i] = bplptx[i];
                        if (!lof && (bplcon0 & 4)) {
@@ -3758,11 +3768,6 @@ static void decide_vline(void)
 {
        bool forceoff = (vb_start_line == 1 && !harddis_v);
 
-       // if scandoubler mode: stop display before possible last non-paired line
-       if (doflickerfix() && interlace_seen > 0 && vpos + 1 >= maxvpos && lof_current && diwstate == DIW_waiting_stop) {
-               forceoff = true;
-       }
-
        /* Take care of the vertical DIW.  */
        if (vpos == plffirstline && !forceoff) {
                diwstate = DIW_waiting_stop;
@@ -4739,9 +4744,18 @@ static void reset_decisions_hsync_start(void)
                thisline_decision.vb = vb_start_line > 1 + vblank_extraline ? 0 : 1;
        }
        // if programmed vblank
-       if (!thisline_decision.vb && (beamcon0 & 0x1000) && ecs_agnus) {
-               thisline_decision.vb |= 2;
+       if ((beamcon0 & 0x1000) && ecs_agnus) {
+               if (!thisline_decision.vb) {
+                       thisline_decision.vb |= 2;
+               }
+       }
+       // doublescan last line garbage workaround
+       if (doflickerfix_active()) {
+               if (vpos < maxvpos_display_vsync || (!lof_display && vpos >= maxvpos - 1) || (lof_display && vpos >= maxvpos - 1)) {
+                       thisline_decision.vb |= 4;
+               }
        }
+
        if (!ecs_denise && vb_end_line) {
                thisline_decision.vb = 1;
        }
@@ -4780,7 +4794,7 @@ static void reset_decisions_hsync_start(void)
        delay_cycles2 = delay_cycles;
        set_delay_lastcycle();
 
-       if (1 && fetchmode >= 2 && !doflickerfix()) {
+       if (1 && fetchmode >= 2 && !doflickerfix_active()) {
                // handle bitplane data wrap around
                bool toshift = false;
                if ((exthblank || (beamcon0 & 0x0110)) && (thisline_decision.bplres == 0 || currprefs.chipset_hr)) {
@@ -4912,7 +4926,7 @@ void compute_vsynctime(void)
        }
        if (interlace_seen) {
                svpos += 0.5;
-       } else if (lof_current) {
+       } else if (lof_display) {
                svpos += 1.0;
        }
        if (currprefs.produce_sound > 1) {
@@ -5202,7 +5216,7 @@ void compute_framesync(void)
 
        if (islace) {
                vblank_hz = vblank_hz_lace;
-       } else if (lof_current) {
+       } else if (lof_store) {
                vblank_hz = vblank_hz_lof;
        } else {
                vblank_hz = vblank_hz_shf;
@@ -5526,7 +5540,7 @@ static void init_hz(bool checkvposw)
                }
                vblank_hz = (isntsc ? 15734.0 : 15625.0) / vpos_count;
                vblank_hz_nom = vblank_hz_shf = vblank_hz_lof = vblank_hz_lace = (float)vblank_hz;
-               maxvpos_nom = vpos_count - (lof_current ? 1 : 0);
+               maxvpos_nom = vpos_count - (lof_store ? 1 : 0);
                if ((maxvpos_nom >= 256 && maxvpos_nom <= 313) || (beamcon0 & 0x80)) {
                        maxvpos_display = maxvpos_nom;
                } else if (maxvpos_nom < 256) {
@@ -6698,7 +6712,7 @@ static void BPLCON0_Denise(int hpos, uae_u16 v)
 {
        v = BPLCON0_Denise_mask(v);
 
-       if (bplcon0d == v || bplcon0d_change) {
+       if (bplcon0d == v && !bplcon0d_change) {
                return;
        }
        bplcon0d_change = false;
@@ -9037,7 +9051,7 @@ static void decide_sprites_fetch(int endhpos)
        if (hpos >= endhpos) {
                return;
        }
-       if (vb_state || (doflickerfix() && interlace_seen && (next_lineno & 1))) {
+       if (vb_state || (doflickerfix_active() && (next_lineno & 1))) {
                last_decide_sprite_hpos = endhpos;
                return;
        }
@@ -9130,7 +9144,7 @@ static int calculate_lineno(int vp)
                lineno %= MAXVPOS;
        }
        nextline_how = nln_normal;
-       if (doflickerfix() && interlace_seen > 0) {
+       if (doflickerfix_active()) {
                lineno *= 2;
        }
        else if (!interlace_seen && doublescan <= 0 && currprefs.gfx_vresolution && currprefs.gfx_pscanlines > 1) {
@@ -9144,7 +9158,7 @@ static int calculate_lineno(int vp)
        } else if ((doublescan <= 0 || interlace_seen > 0) && currprefs.gfx_vresolution && currprefs.gfx_iscanlines) {
                lineno *= 2;
                if (interlace_seen) {
-                       if (!lof_current) {
+                       if (!lof_display) {
                                lineno++;
                                nextline_how = currprefs.gfx_iscanlines == 2 ? nln_lower_black_always : nln_lower_black;
                        } else {
@@ -9156,7 +9170,7 @@ static int calculate_lineno(int vp)
        } else if (currprefs.gfx_vresolution && (doublescan <= 0 || interlace_seen > 0)) {
                lineno *= 2;
                if (interlace_seen) {
-                       if (!lof_current) {
+                       if (!lof_display) {
                                lineno++;
                                nextline_how = nln_lower;
                        } else {
@@ -9185,11 +9199,11 @@ void init_hardware_for_drawing_frame(void)
                }
        }
        prev_next_sprite_entry = next_sprite_entry;
+       next_sprite_entry = 0;
 
        next_lineno = calculate_lineno(vpos);
        last_color_change = 0;
        next_color_change = 0;
-       next_sprite_entry = 0;
        next_color_entry = 0;
        remembered_color_entry = -1;
 
@@ -9731,7 +9745,6 @@ static void vsync_handler_post(void)
 #endif
        }
        lof_prev_lastline = lof_lastline;
-       lof_current = lof_store;
        if (lof_togglecnt_lace >= LOF_TOGGLES_NEEDED) {
                interlace_changed = notice_interlace_seen(true);
                if (interlace_changed) {
@@ -9867,7 +9880,7 @@ static void hsync_scandoubler(int hpos)
                return;
        }
 
-       int lof = lof_store;
+       int lof = lof_display;
        next_lineno++;
        scandoubled_line = 1;
        last_hdiw = 0 - 1;
@@ -9889,7 +9902,6 @@ static void hsync_scandoubler(int hpos)
                                } else {
                                        bplpt[i] = bplpt[i] - diff;
                                }
-
                        }
                }
        }
@@ -10242,12 +10254,13 @@ static void hsync_handlerh(bool onvsync)
 
        if (!nocustom()) {
 
-               finish_decisions(hpos);
-
-               hsync_record_line_state(next_lineno, nextline_how, thisline_changed);
-
-               if (doflickerfix() && interlace_seen > 0) {
+               if (doflickerfix_active()) {
+                       finish_decisions(hpos);
+                       hsync_record_line_state(next_lineno, nextline_how, thisline_changed);
                        hsync_scandoubler(hpos);
+               } else {
+                       finish_decisions(hpos);
+                       hsync_record_line_state(next_lineno, nextline_how, thisline_changed);
                }
 
                notice_resolution_seen(GET_RES_AGNUS(bplcon0), interlace_seen != 0);
@@ -11230,10 +11243,10 @@ static void hsync_handler_post(bool onvsync)
        }
 
        if (beamcon0 & 0x20) {
-               if (vpos == 2 && !lof_current) {
+               if (vpos == 2 && !lof_store) {
                        vs_state_hw = true;
                }
-               if (vpos == 3 && lof_current) {
+               if (vpos == 3 && lof_store) {
                        vs_state_hw = true;
                }
                if (vpos == 5) {
@@ -11297,7 +11310,7 @@ static void hsync_handler_post(bool onvsync)
                if (diwstate == DIW_waiting_stop) {
                        record_dma_event(DMA_EVENT_VDIW, REFRESH_FIRST_HPOS, vpos);
                }
-               if (lof_current) {
+               if (lof_store) {
                        record_dma_event(DMA_EVENT_LOF, REFRESH_FIRST_HPOS + 2, vpos);
                }
                if (lol) {
@@ -11509,6 +11522,7 @@ static void hsync_handler(void)
        if (vpos == maxvpos_display_vsync) {
                vsync_display_render();
                vsync_display_rendered = false;
+               lof_display = lof_store;
                reset_autoscale();
        }
        vsync_line = vs;
@@ -11663,7 +11677,7 @@ void custom_reset(bool hardreset, bool keyboardreset)
                                }
        #endif
                        }
-                       lof_store = lof_current = 0;
+                       lof_store = lof_display = 0;
                        lof_lace = false;
                        setextblank();
                }
@@ -11864,7 +11878,7 @@ void dumpcustom(void)
                (unsigned int)diwstrt, (unsigned int)diwstop, (unsigned int)ddfstrt, (unsigned int)ddfstop);
        console_out_f(_T("BPLCON 0: %04x 1: %04x 2: %04x 3: %04x 4: %04x LOF=%d/%d HDIW=%d VDIW=%d\n"),
                bplcon0, bplcon1, bplcon2, bplcon3, bplcon4,
-               lof_current, lof_store,
+               lof_display, lof_store,
                hdiwstate == DIW_waiting_start ? 0 : 1, diwstate == DIW_waiting_start ? 0 : 1);
        if (timeframes) {
                console_out_f(_T("Average frame time: %.2f ms [frames: %d time: %d]\n"),
@@ -12541,7 +12555,7 @@ uae_u8 *restore_custom(uae_u8 *src)
        dsklen = RW;                    /* 024 DSKLEN */
        RW;                                             /* 026 DSKDAT */
        refptr = RW;                    /* 028 REFPTR */
-       i = RW; lof_store = lof_current = (i & 0x8000) ? 1 : 0; lol = (i & 0x0080) ? 1 : 0; /* 02A VPOSW */
+       i = RW; lof_store = lof_display = (i & 0x8000) ? 1 : 0; lol = (i & 0x0080) ? 1 : 0; /* 02A VPOSW */
        RW;                                             /* 02C VHPOSW */
        COPCON(RW);                     /* 02E COPCON */
        RW;                                             /* 030 SERDAT* */
index 7ea0c12dc0d762b05fe909b83f600ca6af3704e0..ac3e8d7edace1b4aaaa67219b14552989ced8f66 100644 (file)
@@ -429,7 +429,7 @@ extern int diwfirstword_total, diwlastword_total;
 extern int ddffirstword_total, ddflastword_total;
 extern bool vertical_changed, horizontal_changed;
 extern int firstword_bplcon1;
-extern int lof_store;
+extern int lof_display;
 
 #define MIN_DISPLAY_W 256
 #define MIN_DISPLAY_H 192
@@ -490,7 +490,7 @@ static void get_vblanking_limits(int *vbstrtp, int *vbstopp, bool overscanonly)
        if (!ecs_denise) {
                vbstrt--;
        }
-       int vbstop = maxvpos + lof_store;
+       int vbstop = maxvpos + lof_display;
        if (!ecs_denise && !ecs_agnus) {
                vbstop++;
        } else if (ecs_agnus && !ecs_denise) {
@@ -772,13 +772,13 @@ int get_custom_limits (int *pw, int *ph, int *pdx, int *pdy, int *prealh)
        if (interlace_seen) {
                static int interlace_count;
                // interlace = only use long frames
-               if (lof_store && (interlace_count & 1) == 0)
+               if (lof_display && (interlace_count & 1) == 0)
                        interlace_count++;
-               if (!lof_store && (interlace_count & 1) != 0)
+               if (!lof_display && (interlace_count & 1) != 0)
                        interlace_count++;
                if (interlace_count < 3)
                        return ret;
-               if (!lof_store)
+               if (!lof_display)
                        return ret;
                interlace_count = 0;
                /* program may have set last visible line as last possible line (CD32 boot screen) */
@@ -1447,7 +1447,7 @@ static void fill_line_border(int lineno)
        int endpos = visible_left_border + vidinfo->drawbuffer.inwidth;
        int w = endpos - lastpos;
 
-       if (lineno < visible_top_start || lineno < vblank_top_start || lineno >= visible_bottom_stop || lineno >= vblank_bottom_stop) {
+       if (lineno < visible_top_start || lineno < vblank_top_start || lineno >= visible_bottom_stop || lineno >= vblank_bottom_stop || vb_state >= 4) {
                int b = hposblank;
                hposblank = 3;
                fill_line2(lastpos, w);
@@ -3299,8 +3299,11 @@ static void do_color_changes(line_draw_func worker_border, line_draw_func worker
                        }
 
                        // vblank + programmed vblank / hardwired vblank
-                       if (vb_state == 2 || vbarea) {
+                       if (vb_state == 2 || vb_state >= 4 || vbarea) {
 
+                               if (vbarea || vb_state >= 4) {
+                                       hposblank = 3;
+                               }
                                if (nextpos_in_range > lastpos && lastpos < playfield_end) {
                                        int t = nextpos_in_range <= playfield_end ? nextpos_in_range : playfield_end;
                                        (*worker_border)(lastpos, t, 1);
@@ -4772,6 +4775,8 @@ void hsync_record_line_state (int lineno, enum nln_how how, int changed)
        if (ad->framecnt != 0)
                return;
 
+       //write_log("%d:%d:%d ", lineno, how, lof_display);
+
        state = linestate + lineno;
        changed |= ad->frame_redraw_necessary != 0 || refresh_indicator_buffer != NULL ||
                ((lineno >= lightpen_y1[0] && lineno < lightpen_y2[0]) ||
@@ -4794,7 +4799,7 @@ void hsync_record_line_state (int lineno, enum nln_how how, int changed)
                }
                break;
        case nln_lower:
-               if (lineno > 0 && state[-1] == LINE_UNDECIDED) {
+               if (state[-1] == LINE_UNDECIDED) {
                        state[-1] = LINE_DECIDED; //LINE_BLACK;
                }
                *state = changed ? LINE_DECIDED : LINE_DONE;
@@ -4809,34 +4814,20 @@ void hsync_record_line_state (int lineno, enum nln_how how, int changed)
        case nln_lower_black_always:
                state[1] = LINE_BLACK;
                *state = LINE_DECIDED;
-//             if (lineno == (maxvpos + lof_store) * 2 - 1)
-//                     *state = LINE_BLACK;
                break;
        case nln_lower_black:
                changed |= state[0] != LINE_DONE;
-               state[1] = LINE_DONE;
                *state = changed ? LINE_DECIDED : LINE_DONE;
-//             if (lineno == (maxvpos + lof_store) * 2 - 1)
-//                     *state = LINE_BLACK;
+               state[1] = LINE_DONE;
                break;
        case nln_upper_black_always:
                *state = LINE_DECIDED;
-               if (lineno > 0) {
-                       state[-1] = LINE_BLACK;
-               }
-               if (!interlace_seen && lineno == (maxvpos + lof_store) * 2 - 2) {
-                       state[1] = LINE_BLACK;
-               }
+               state[-1] = LINE_BLACK;
                break;
        case nln_upper_black:
                changed |= state[0] != LINE_DONE;
                *state = changed ? LINE_DECIDED : LINE_DONE;
-               if (lineno > 0) {
-                       state[-1] = LINE_DONE;
-               }
-               if (!interlace_seen && lineno == (maxvpos + lof_store) * 2 - 2) {
-                       state[1] = LINE_DONE;
-               }
+               state[-1] = LINE_DONE;
                break;
        }
 }
index 9f0a8c26033779368c791a1044a9ac05a7bd6696..f6d49a245bd2831bd11280f72d52126052632a13 100644 (file)
@@ -56,7 +56,7 @@ extern unsigned long int hsync_counter, vsync_counter;
 extern uae_u16 dmacon;
 extern uae_u16 intena, intreq, intreqr;
 
-extern int vpos, lof_store;
+extern int vpos, lof_store, lof_display;
 
 extern int n_frames;
 
index 8df06841a84f4e528b3db2fd9be72eeba94a395f..b5c77708a9addfb5cb3e4b80d98941b4ab3d4dfe 100644 (file)
@@ -959,7 +959,7 @@ uae_u8 *save_screenshot(int monid, int *len)
        int w = avidinfo->drawbuffer.inwidth;
        int h = avidinfo->drawbuffer.inheight;
        if (!programmedmode) {
-               h = (maxvpos + lof_store - minfirstline) << currprefs.gfx_vresolution;
+               h = (maxvpos + lof_display - minfirstline) << currprefs.gfx_vresolution;
        }
        if (interlace_seen && currprefs.gfx_vresolution > 0) {
                h -= 1 << (currprefs.gfx_vresolution - 1);