]> git.unchartedbackwaters.co.uk Git - francis/winuae.git/commitdiff
Custom emulation update WIP.
authorToni Wilen <twilen@winuae.net>
Tue, 15 Jun 2021 18:33:18 +0000 (21:33 +0300)
committerToni Wilen <twilen@winuae.net>
Tue, 15 Jun 2021 18:33:18 +0000 (21:33 +0300)
cfgfile.cpp
custom.cpp
drawing.cpp
include/custom.h
include/options.h
od-win32/resources/resource.h
od-win32/resources/winuae.rc
od-win32/win32gfx.cpp
od-win32/win32gui.cpp

index 115ce0e352f81319bd324b22809bcb18418fb11a..53b51531124f815da6a87260b5d7c9575f15b5d2 100644 (file)
@@ -205,6 +205,7 @@ static const TCHAR *vsyncmodes[] = { _T("false"), _T("true"), _T("autoswitch"),
 static const TCHAR *vsyncmodes2[] = { _T("normal"), _T("busywait"), 0 };
 static const TCHAR *filterapi[] = { _T("directdraw"), _T("direct3d"), _T("direct3d11"), 0 };
 static const TCHAR *filterapiopts[] = { _T("hardware"), _T("software"), 0 };
+static const TCHAR *overscanmodes[] = { _T("tv_narrow"), _T("tv_standard"), _T("tv_wide"), _T("overscan"), _T("broadcast"), _T("extreme"), NULL };
 static const TCHAR *dongles[] =
 {
        _T("none"),
@@ -2270,6 +2271,8 @@ void cfgfile_save_options (struct zfile *f, struct uae_prefs *p, int type)
        cfgfile_dwrite(f, _T("gfx_vertical_extra"), _T("%d"), p->gfx_extraheight);
        cfgfile_dwrite(f, _T("gfx_frame_slices"), _T("%d"), p->gfx_display_sections);
        cfgfile_dwrite_bool(f, _T("gfx_vrr_monitor"), p->gfx_variable_sync != 0);
+       cfgfile_dwrite_str(f, _T("gfx_overscanmode"), overscanmodes[p->gfx_overscanmode]);
+       
 
 #ifdef GFXFILTER
        for (int j = 0; j < 2; j++) {
@@ -3504,6 +3507,7 @@ static int cfgfile_parse_host (struct uae_prefs *p, TCHAR *option, TCHAR *value)
                || cfgfile_strval(option, value, _T("gfx_api"), &p->gfx_api, filterapi, 0)
                || cfgfile_strval(option, value, _T("gfx_api_options"), &p->gfx_api_options, filterapiopts, 0)
                || cfgfile_strval(option, value, _T("gfx_atari_palette_fix"), &p->gfx_threebitcolors, threebitcolors, 0)
+               || cfgfile_strval(option, value, _T("gfx_overscanmode"), &p->gfx_overscanmode, overscanmodes, 0)
                || cfgfile_strval(option, value, _T("magic_mousecursor"), &p->input_magic_mouse_cursor, magiccursors, 0)
                || cfgfile_strval (option, value, _T("absolute_mouse"), &p->input_tablet, abspointers, 0))
                return 1;
@@ -7958,6 +7962,7 @@ void default_prefs (struct uae_prefs *p, bool reset, int type)
        p->gfx_display_sections = 4;
        p->gfx_variable_sync = 0;
        p->gfx_windowed_resize = true;
+       p->gfx_overscanmode = 3;
 
        p->immediate_blits = 0;
        p->waiting_blits = 0;
index 833c3cc78fffcd9f39ccfb2656de21656d3f8fc9..a56eb0424fd520ec1cd6f5d8f0de2348d0f685d3 100644 (file)
 
 #define SPRBORDER 0
 
+#define EXTRAWIDTH_BROADCAST 7
+#define EXTRAHEIGHT_BROADCAST 2
+#define EXTRAWIDTH_EXTREME 32
+#define EXTRAHEIGHT_EXTREME 24
+
 extern uae_u16 serper;
 
 STATIC_INLINE bool nocustom (void)
@@ -409,6 +414,7 @@ enum diw_states
 
 static int plffirstline, plflastline;
 int plffirstline_total, plflastline_total;
+int vblank_firstline_hw, vblank_lastline_hw;
 static int autoscale_bordercolors;
 static int plfstrt, plfstop;
 static int sprite_minx;
@@ -3321,17 +3327,16 @@ static void decide_bpl_fetch(int endhpos)
 
 static void decide_vline(void)
 {
+       bool forceoff = (vb_start_line == 1 && !harddis_v);
+
        /* Take care of the vertical DIW.  */
-       if (vpos == plffirstline) {
-               // Following line after VB start has bitplane DMA start inhibited (if HARDDIS=0)
-               if (vb_start_line != 2 || harddis_v) {
-                       diwstate = DIW_waiting_stop;
-                       diwstate_vpos = vpos;
-                       SET_LINE_CYCLEBASED;
-               }
+       if (vpos == plffirstline && !forceoff) {
+               diwstate = DIW_waiting_stop;
+               diwstate_vpos = vpos;
+               SET_LINE_CYCLEBASED;
        }
        // VB start line forces vertical display window off (if HARDDIS=0)
-       if (vpos == plflastline || (vb_start_line == 1 && !harddis_v)) {
+       if (vpos == plflastline || forceoff) {
                diwstate = DIW_waiting_start;
                diwstate_vpos = vpos;
                SET_LINE_CYCLEBASED;
@@ -4262,7 +4267,7 @@ static void reset_decisions_hsync_start(void)
        bpldmawasactive = false;
        bpl1mod_hpos = -1;
        bpl2mod_hpos = -1;
-       //plane0 = false;
+       plane0 = false;
 
        delay_cycles_right_offset = 0;
        toscr_right_edge_offset = 0;
@@ -4713,7 +4718,7 @@ void compute_framesync(void)
        vidinfo->drawbuffer.inyoffset = -1;
        updateextblk();
 
-       if (beamcon0 & 0x80) {
+       if (new_beamcon0 & 0x80) {
                int res = GET_RES_AGNUS (bplcon0);
                int vres = islace ? 1 : 0;
                int res2, vres2;
@@ -4748,8 +4753,17 @@ void compute_framesync(void)
        } else {
 
                vidinfo->drawbuffer.inwidth = maxhpos_display << currprefs.gfx_resolution;
-               vidinfo->drawbuffer.extrawidth = currprefs.gfx_extrawidth ? currprefs.gfx_extrawidth : -1;
-               vidinfo->drawbuffer.extraheight = currprefs.gfx_extraheight ? currprefs.gfx_extraheight : -1;
+               vidinfo->drawbuffer.extrawidth = -2;
+               if (currprefs.gfx_extrawidth > 0) {
+                       vidinfo->drawbuffer.extrawidth = currprefs.gfx_extrawidth;
+               }
+               vidinfo->drawbuffer.extraheight = -2;
+               if (currprefs.gfx_extraheight > 0) {
+                       vidinfo->drawbuffer.extraheight = currprefs.gfx_extraheight;
+               }
+               if (vidinfo->drawbuffer.extrawidth == -2 && ((new_beamcon0 & (0x1000 | 0x0200 | 0x0010)) || currprefs.gfx_overscanmode == OVERSCANMODE_EXTREME)) {
+                       vidinfo->drawbuffer.extrawidth = -1;
+               }
                vidinfo->drawbuffer.inwidth2 = vidinfo->drawbuffer.inwidth;
                vidinfo->drawbuffer.inheight = (maxvpos_display - minfirstline + maxvpos_display_vsync) << currprefs.gfx_vresolution;
                vidinfo->drawbuffer.inheight2 = vidinfo->drawbuffer.inheight;
@@ -4838,6 +4852,10 @@ static void init_hz(bool checkvposw)
        if (beamcon0 != new_beamcon0) {
                vpos_count_diff = vpos_count = 0;
        }
+       if ((beamcon0 & (0x1000 | 0x0200 | 0x0010)) != (new_beamcon0 & (0x1000 | 0x0200 | 0x0010))) {
+               hzc = 1;
+       }
+
        beamcon0 = new_beamcon0;
        isntsc = (beamcon0 & 0x20) ? 0 : 1;
        islace = (interlace_seen) ? 1 : 0;
@@ -4883,12 +4901,34 @@ static void init_hz(bool checkvposw)
        }
        if (currprefs.gfx_extrawidth > 0) {
                maxhpos_display += currprefs.gfx_extrawidth;
+       } else if (currprefs.gfx_overscanmode == OVERSCANMODE_EXTREME) {
+               maxhpos_display += EXTRAWIDTH_EXTREME;
+       } else if (currprefs.gfx_overscanmode == OVERSCANMODE_BROADCAST) {
+               maxhpos_display += EXTRAWIDTH_BROADCAST;
        }
+
        // A1000/OCS Denise has topmost line "almost" blanked
        if (!ecs_denise) {
                minfirstline--;
        }
        vblank_extraline = !currprefs.cs_dipagnus && !ecs_denise ? 1 : 0;
+
+       vblank_lastline_hw = maxvpos + maxvpos_display_vsync + vblank_extraline;
+       vblank_firstline_hw = minfirstline;
+
+       int maxvpos_display_vsync_hw = maxvpos_display_vsync;
+       int minfirstline_hw = minfirstline;
+       if (currprefs.gfx_overscanmode == OVERSCANMODE_EXTREME) {
+               minfirstline_hw -= EXTRAHEIGHT_EXTREME / 2;
+               maxvpos_display_vsync_hw += EXTRAHEIGHT_EXTREME / 2;
+       } else if (currprefs.gfx_overscanmode == OVERSCANMODE_BROADCAST) {
+               minfirstline_hw -= EXTRAHEIGHT_BROADCAST / 2;
+               maxvpos_display_vsync_hw += EXTRAHEIGHT_BROADCAST / 2;
+       }
+       if (beamcon0 & 0x0080) {
+               minfirstline_hw = 0;
+       }
+
        if (vpos_count > 0) {
                // we come here if vpos_count != maxvpos and beamcon0 didn't change
                // (someone poked VPOSW)
@@ -4931,19 +4971,21 @@ static void init_hz(bool checkvposw)
                maxvpos_display_vsync = 4;
        }
 
-       if (currprefs.gfx_extraheight > 0) {
+       int eh = currprefs.gfx_extraheight;
+       if (eh <= 0) {
+               if (currprefs.gfx_overscanmode == OVERSCANMODE_EXTREME) {
+                       eh = EXTRAHEIGHT_EXTREME;
+               } else if (currprefs.gfx_overscanmode == OVERSCANMODE_BROADCAST) {
+                       eh = EXTRAHEIGHT_BROADCAST;
+               }
+       }
+       if (eh > 0) {
                if (beamcon0 & (0x0200 | 0x0010)) {
-                       maxvpos_display_vsync += currprefs.gfx_extraheight / 2;
-                       minfirstline -= currprefs.gfx_extraheight / 2;
-                       if (maxvpos_display_vsync >= vsstop) {
-                               maxvpos_display_vsync = vsstop - 1;
-                       }
-                       if (minfirstline <= vsstop) {
-                               minfirstline = vsstop + 1;
-                       }
+                       maxvpos_display_vsync += eh / 2;
+                       minfirstline -= eh / 2;
                } else {
                        maxvpos_display_vsync = 3;
-                       minfirstline -= currprefs.gfx_extraheight / 2;
+                       minfirstline -= eh / 2;
                        if (minfirstline < 8) {
                                minfirstline = 8;
                        }
@@ -4957,7 +4999,7 @@ static void init_hz(bool checkvposw)
        if (minfirstline < 1) {
                minfirstline = 1;
        }
-       if (!(beamcon0 & 0x80) && minfirstline < 8 && !currprefs.gfx_extraheight) {
+       if (!(beamcon0 & 0x80) && minfirstline < 8 && !eh) {
                minfirstline = 8;
        }
 
@@ -4969,6 +5011,22 @@ static void init_hz(bool checkvposw)
                firstblankedline = maxvpos + 1;
        }
 
+       if (minfirstline < minfirstline_hw) {
+               minfirstline = minfirstline_hw;
+       }
+       if (maxvpos_display_vsync > maxvpos_display_vsync_hw) {
+               maxvpos_display_vsync = maxvpos_display_vsync_hw;
+       }
+
+       if (beamcon0 & (0x0200 | 0x0010)) {
+               if (maxvpos_display_vsync >= vsstop) {
+                       maxvpos_display_vsync = vsstop - 1;
+               }
+               if (minfirstline <= vsstop) {
+                       minfirstline = vsstop + 1;
+               }
+       }
+
        if (beamcon0 & 0x80) {
                // programmable scanrates (ECS Agnus)
                if (vtotal >= MAXVPOS) {
@@ -5928,9 +5986,6 @@ static void BEAMCON0(int hpos, uae_u16 v)
                                dumpsync();
                        }
                }
-               if ((beamcon0 & (0x10 | 0x20 | 0x80 | 0x100 | 0x200 | 0x1000 | 0x4000)) != (new_beamcon0 & (0x10 | 0x20 | 0x80 | 0x100 | 0x200 | 0x1000 | 0x4000))) {
-                       varsync_changed = 2;
-               }
                beamcon0_saved = v;
                record_register_change(hpos, 0x1dc, new_beamcon0);
                check_harddis();
@@ -5951,9 +6006,6 @@ static void varsync(void)
        }
 #endif
        updateextblk();
-       if (!(beamcon0 & (0x80 | 0x1000 | 0x0200 | 0x0100 | 0x4000)))
-               return;
-       varsync_changed = 2;
 }
 
 #ifdef PICASSO96
@@ -6325,7 +6377,7 @@ static void DIWHIGH(int hpos, uae_u16 v)
        if (!aga_mode) {
                v &= ~(0x0008 | 0x0010 | 0x1000 | 0x0800);
        }
-       v &= ~(0x08000 | 0x4000 | 0x0080 | 0x0040);
+       v &= ~(0x8000 | 0x4000 | 0x0080 | 0x0040);
        if (diwhigh_written && diwhigh == v) {
                return;
        }
@@ -6898,12 +6950,15 @@ static void checkautoscalecol0(void)
        // autoscale if copper changes COLOR00 on top or bottom of screen
        if (vpos >= minfirstline) {
                int vpos2 = autoscale_bordercolors ? minfirstline : vpos;
-               if (first_planes_vpos == 0)
+               if (first_planes_vpos == 0) {
                        first_planes_vpos = vpos2 - 2;
-               if (plffirstline_total == current_maxvpos ())
+               }
+               if (plffirstline_total == current_maxvpos()) {
                        plffirstline_total = vpos2 - 2;
-               if (vpos2 > last_planes_vpos || vpos2 > plflastline_total)
+               }
+               if (vpos2 > last_planes_vpos || vpos2 > plflastline_total) {
                        plflastline_total = last_planes_vpos = vpos2 + 3;
+               }
                autoscale_bordercolors = 0;
        } else {
                autoscale_bordercolors++;
@@ -8284,48 +8339,15 @@ static void init_sprites(void)
        }
 }
 
+// line=0
 static void init_hardware_frame(void)
 {
-       first_bpl_vpos = -1;
        if (!harddis_v) {
                diwstate = DIW_waiting_start;
        }
-
-       if (first_bplcon0 != first_bplcon0_old) {
-               vertical_changed = horizontal_changed = true;
-       }
-       first_bplcon0_old = first_bplcon0;
-
-       if (first_planes_vpos != first_planes_vpos_old ||
-               last_planes_vpos != last_planes_vpos_old) {
-               vertical_changed = true;
-       }
-       first_planes_vpos_old = first_planes_vpos;
-       last_planes_vpos_old = last_planes_vpos;
-       
-       if (diwfirstword_total != diwfirstword_total_old ||
-               diwlastword_total != diwlastword_total_old ||
-               ddffirstword_total != ddffirstword_total_old ||
-               ddflastword_total != ddflastword_total_old) {
-               horizontal_changed = true;
-       }
-       diwfirstword_total_old = diwfirstword_total;
-       diwlastword_total_old = diwlastword_total;
-       ddffirstword_total_old = ddffirstword_total;
-       ddflastword_total_old = ddflastword_total;
-
-       first_planes_vpos = 0;
-       last_planes_vpos = 0;
-       diwfirstword_total = max_diwlastword;
-       diwlastword_total = 0;
-       ddffirstword_total = max_diwlastword;
-       ddflastword_total = 0;
-       plflastline_total = 0;
-       plffirstline_total = current_maxvpos();
-       first_bplcon0 = 0;
-       autoscale_bordercolors = 0;
 }
 
+// vsync start
 void init_hardware_for_drawing_frame(void)
 {
        /* Avoid this code in the first frame after a customreset.  */
@@ -8939,6 +8961,11 @@ static void vsync_handler_post(void)
 
        devices_vsync_post();
 
+       if ((beamcon0 & (0x10 | 0x20 | 0x80 | 0x100 | 0x200 | 0x1000 | 0x4000)) != (new_beamcon0 & (0x10 | 0x20 | 0x80 | 0x100 | 0x200 | 0x1000 | 0x4000))) {
+               if (!varsync_changed) {
+                       varsync_changed = 2;
+               }
+       }
        vsync_check_vsyncmode();
 
        lof_changed = 0;
@@ -9242,6 +9269,104 @@ static bool do_display_slice(void)
        return true;
 }
 
+static void reset_autoscale(void)
+{
+       first_bpl_vpos = -1;
+       if (first_bplcon0 != first_bplcon0_old) {
+               vertical_changed = horizontal_changed = true;
+       }
+       first_bplcon0_old = first_bplcon0;
+
+       if (first_planes_vpos != first_planes_vpos_old ||
+               last_planes_vpos != last_planes_vpos_old) {
+               vertical_changed = true;
+       }
+       first_planes_vpos_old = first_planes_vpos;
+       last_planes_vpos_old = last_planes_vpos;
+
+       if (diwfirstword_total != diwfirstword_total_old ||
+               diwlastword_total != diwlastword_total_old ||
+               ddffirstword_total != ddffirstword_total_old ||
+               ddflastword_total != ddflastword_total_old) {
+               horizontal_changed = true;
+       }
+       diwfirstword_total_old = diwfirstword_total;
+       diwlastword_total_old = diwlastword_total;
+       ddffirstword_total_old = ddffirstword_total;
+       ddflastword_total_old = ddflastword_total;
+
+       first_planes_vpos = 0;
+       last_planes_vpos = 0;
+       diwfirstword_total = max_diwlastword;
+       diwlastword_total = 0;
+       ddffirstword_total = max_diwlastword;
+       ddflastword_total = 0;
+       plflastline_total = 0;
+       plffirstline_total = current_maxvpos();
+       first_bplcon0 = 0;
+       autoscale_bordercolors = 0;
+}
+
+static void hautoscale_check(void)
+{
+       // border detection/autoscale
+       if (GET_PLANES(bplcon0) > 0 && dmaen(DMA_BITPLANE)) {
+               if (first_bplcon0 == 0) {
+                       first_bplcon0 = bplcon0;
+               }
+               if (vpos > last_planes_vpos) {
+                       last_planes_vpos = vpos;
+               }
+               if (vpos >= minfirstline && first_planes_vpos == 0) {
+                       first_planes_vpos = vpos > minfirstline ? vpos - 1 : vpos;
+               } else if (vpos >= current_maxvpos() - 1) {
+                       last_planes_vpos = current_maxvpos();
+               }
+       }
+       if (diw_change == 0) {
+               if (vpos >= first_planes_vpos && vpos <= last_planes_vpos) {
+                       int diwlastword_lores = diwlastword;
+                       int diwfirstword_lores = diwfirstword;
+                       if (diwlastword_lores > diwlastword_total) {
+                               diwlastword_total = diwlastword_lores;
+                               if (diwlastword_total > coord_diw_shres_to_window_x(hsyncstartpos)) {
+                                       diwlastword_total = coord_diw_shres_to_window_x(hsyncstartpos);
+                               }
+                       }
+                       if (diwfirstword_lores < diwfirstword_total) {
+                               diwfirstword_total = diwfirstword_lores;
+                               if (diwfirstword_total < coord_diw_shres_to_window_x(hsyncendpos)) {
+                                       diwfirstword_total = coord_diw_shres_to_window_x(hsyncendpos);
+                               }
+                               firstword_bplcon1 = bplcon1;
+                       }
+               }
+               if (diwstate == DIW_waiting_stop) {
+                       int f = 8 << fetchmode;
+                       if (plfstrt + f < ddffirstword_total + f) {
+                               ddffirstword_total = plfstrt + f;
+                       }
+                       if (plfstop + 2 * f > ddflastword_total + 2 * f) {
+                               ddflastword_total = plfstop + 2 * f;
+                       }
+               }
+               if ((plffirstline < plffirstline_total || (plffirstline_total == minfirstline && vpos > minfirstline)) && plffirstline < maxvpos / 2) {
+                       firstword_bplcon1 = bplcon1;
+                       if (plffirstline < minfirstline) {
+                               plffirstline_total = minfirstline;
+                       } else {
+                               plffirstline_total = plffirstline;
+                       }
+               }
+               if (plflastline > plflastline_total && plflastline > plffirstline_total && plflastline > maxvpos / 2) {
+                       plflastline_total = plflastline;
+               }
+       }
+       if (diw_change > 0) {
+               diw_change--;
+       }
+}
+
 static void hsync_handlerh(bool onvsync)
 {
        int hpos = current_hpos();
@@ -9258,6 +9383,8 @@ static void hsync_handlerh(bool onvsync)
 
                notice_resolution_seen(GET_RES_AGNUS(bplcon0), interlace_seen != 0);
 
+               hautoscale_check();
+
                int lineno = vposh;
                if (lineno >= MAXVPOS) {
                        lineno %= MAXVPOS;
@@ -10153,7 +10280,7 @@ static void hsync_handler_post (bool onvsync)
 #endif
        } else if (currprefs.cs_ciaatod == 0 && ciavsyncs) {
                // CIA-A TOD counter increases when vsync pulse ends
-               if (beamcon0 & 0x200) {
+               if (beamcon0 & 0x0200) {
                        if (vpos == vsstop && vs_state == true) {
                                CIAA_tod_inc(lof_store ? hsstop : hsstop + hcenter);
                        }
@@ -10187,8 +10314,6 @@ static void hsync_handler_post (bool onvsync)
                lof_lastline = lof_store != 0;
        }
 
-       decide_vline();
-
        vb_end_next_line = false;
        if (vb_start_line) {
                vb_start_line++;
@@ -10198,6 +10323,7 @@ static void hsync_handler_post (bool onvsync)
                vb_end_line = false;
                vb_end_next_line = true;
        }
+
        if (ecs_agnus) {
                if (vsstrt_m == vpos) {
                        vsstrt_m = -1;
@@ -10282,6 +10408,8 @@ static void hsync_handler_post (bool onvsync)
                }
        }
 
+       decide_vline();
+
        int hp = REFRESH_FIRST_HPOS;
        for (int i = 0; i < 4; i++) {
                alloc_cycle(hp, i == 0 ? CYCLE_STROBE : CYCLE_REFRESH); /* strobe */
@@ -10457,62 +10585,7 @@ static void hsync_handler_post (bool onvsync)
        compute_spcflag_copper();
 
 
-       // border detection/autoscale
-       if (GET_PLANES (bplcon0) > 0 && dmaen(DMA_BITPLANE)) {
-               if (first_bplcon0 == 0) {
-                       first_bplcon0 = bplcon0;
-               }
-               if (vpos > last_planes_vpos) {
-                       last_planes_vpos = vpos;
-               }
-               if (vpos >= minfirstline && first_planes_vpos == 0) {
-                       first_planes_vpos = vpos > minfirstline ? vpos - 1 : vpos;
-               } else if (vpos >= current_maxvpos() - 1) {
-                       last_planes_vpos = current_maxvpos();
-               }
-       }
-       if (diw_change == 0) {
-               if (vpos >= first_planes_vpos && vpos <= last_planes_vpos) {
-                       int diwlastword_lores = diwlastword;
-                       int diwfirstword_lores = diwfirstword;
-                       if (diwlastword_lores > diwlastword_total) {
-                               diwlastword_total = diwlastword_lores;
-                               if (diwlastword_total > coord_diw_shres_to_window_x(hsyncstartpos)) {
-                                       diwlastword_total = coord_diw_shres_to_window_x(hsyncstartpos);
-                               }
-                       }
-                       if (diwfirstword_lores < diwfirstword_total) {
-                               diwfirstword_total = diwfirstword_lores;
-                               if (diwfirstword_total < coord_diw_shres_to_window_x(hsyncendpos)) {
-                                       diwfirstword_total = coord_diw_shres_to_window_x(hsyncendpos);
-                               }
-                               firstword_bplcon1 = bplcon1;
-                       }
-               }
-               if (diwstate == DIW_waiting_stop) {
-                       int f = 8 << fetchmode;
-                       if (plfstrt + f < ddffirstword_total + f) {
-                               ddffirstword_total = plfstrt + f;
-                       }
-                       if (plfstop + 2 * f > ddflastword_total + 2 * f) {
-                               ddflastword_total = plfstop + 2 * f;
-                       }
-               }
-               if ((plffirstline < plffirstline_total || (plffirstline_total == minfirstline && vpos > minfirstline)) && plffirstline < maxvpos / 2) {
-                       firstword_bplcon1 = bplcon1;
-                       if (plffirstline < minfirstline) {
-                               plffirstline_total = minfirstline;
-                       } else {
-                               plffirstline_total = plffirstline;
-                       }
-               }
-               if (plflastline > plflastline_total && plflastline > plffirstline_total && plflastline > maxvpos / 2) {
-                       plflastline_total = plflastline;
-               }
-       }
-       if (diw_change > 0) {
-               diw_change--;
-       }
+
 
 #if 0
        /* fastest possible + last line and no vflip wait: render the frame as early as possible */
@@ -10565,6 +10638,7 @@ static void hsync_handler(void)
        if (vpos == maxvpos_display_vsync) {
                vsync_display_render();
                vsync_display_rendered = false;
+               reset_autoscale();
        }
        vsync_line = vs;
        hsync_handler_post(vs);
@@ -11374,7 +11448,6 @@ static int REGPARAM2 custom_wput_1 (int hpos, uaecptr addr, uae_u32 value, int n
        case 0x1C2:
                if (hsstop != value) {
                        hsstop = value & (MAXHPOS_ROWS - 1);
-                       //record_register_change(hpos, 0x1c2, hsstop);
                        varsync();
                }
                break;
@@ -11383,7 +11456,9 @@ static int REGPARAM2 custom_wput_1 (int hpos, uaecptr addr, uae_u32 value, int n
                        hbstrt = value & 0x7ff;
                        varsync();
                        updateextblk();
-                       //record_register_change(hpos, 0x1c4, hbstrt);
+                       if (exthblank) {
+                               record_color_change2(hpos, 0xffff, 0);
+                       }
                }
                break;
        case 0x1C6:
@@ -11391,7 +11466,9 @@ static int REGPARAM2 custom_wput_1 (int hpos, uaecptr addr, uae_u32 value, int n
                        hbstop = value & 0x7ff;
                        varsync();
                        updateextblk();
-                       //record_register_change(hpos, 0x1c6, hbstop);
+                       if (exthblank) {
+                               record_color_change2(hpos, 0xffff, 0);
+                       }
                }
                break;
        case 0x1C8:
@@ -11421,7 +11498,6 @@ static int REGPARAM2 custom_wput_1 (int hpos, uaecptr addr, uae_u32 value, int n
        case 0x1DE:
                if (hsstrt != value) {
                        hsstrt = value & (MAXHPOS_ROWS - 1);
-                       //record_register_change(hpos, 0x1de, hsstrt);
                        varsync();
                }
                break;
@@ -12449,6 +12525,8 @@ uae_u32 wait_cpu_cycle_read_ce020(uaecptr addr, int mode)
        peekdma_data.mask = 0;
 #endif
 
+       x_do_cycles_pre(CYCLE_UNIT);
+
        switch (mode) {
                case -1:
                v = get_long(addr);
@@ -12473,9 +12551,6 @@ uae_u32 wait_cpu_cycle_read_ce020(uaecptr addr, int mode)
        }
 #endif
 
-       x_do_cycles_pre(CYCLE_UNIT);
-
-
        regs.chipset_latch_rw = regs.chipset_latch_read = v;
        SETIFCHIP;
                
index 21e1f041883f7d063db8f5122289760ac65d6f98..08cefa831dc316b8ea63adaf6022dea1d06ce662 100644 (file)
@@ -250,7 +250,8 @@ int visible_left_border, visible_right_border;
 /* Pixels outside of visible_start and visible_stop are always black */
 static int visible_left_start, visible_right_stop;
 static int visible_top_start, visible_bottom_stop;
-/* same for hblank */
+/* same for blank */
+static int vblank_top_start, vblank_bottom_stop;
 static int hblank_left_start, hblank_right_stop;
 static bool exthblank;
 
@@ -475,31 +476,76 @@ static void set_blanking_limits(void)
 {
        hblank_left_start = visible_left_start;
        hblank_right_stop = visible_right_stop;
+       vblank_top_start = visible_top_start;
+       vblank_bottom_stop = visible_bottom_stop;
+
        if (hblank_left_start < visible_left_border) {
                hblank_left_start = visible_left_border;
        }
        if (hblank_right_stop > visible_right_border) {
                hblank_right_stop = visible_right_border;
        }
+       if (vblank_top_start < visible_top_start) {
+               vblank_top_start = visible_top_start;
+       }
+       if (vblank_bottom_stop > visible_bottom_stop) {
+               vblank_bottom_stop = visible_bottom_stop;
+       }
 
-       int hbstrt = 0;
-       int hbstop = 0;
-       int offset = -1;
-
-       if (!dp_for_drawing || !ce_is_extblankset(colors_for_drawing.extra) || !ce_is_extblankmode(colors_for_drawing.extra)) {
+       if (!dp_for_drawing || !ce_is_extblankset(colors_for_drawing.extra) || !ce_is_extblankmode(colors_for_drawing.extra) || (currprefs.gfx_overscanmode <= OVERSCANMODE_OVERSCAN && !(new_beamcon0 & 0x80))) {
                // hardwired blanking
-               // has 1.5 hires pixel offset
-               offset = 3;
-               hbstrt = hsyncstartpos_hw;
-               hbstop = hsyncendpos_hw;
-               exthblank = false;
-       }
-       if (offset >= 0) {
-               if (hblank_left_start < coord_hw_to_window_x_shres(hbstop - offset)) {
-                       hblank_left_start = coord_hw_to_window_x_shres(hbstop - offset);
+               int hbstrt = (235 << CCK_SHRES_SHIFT) - 3;
+               int hbstop = (47 << CCK_SHRES_SHIFT) - 7;
+
+               if (currprefs.gfx_overscanmode < OVERSCANMODE_OVERSCAN) {
+                       int mult = (OVERSCANMODE_OVERSCAN - currprefs.gfx_overscanmode) * 4;
+                       hbstrt -= mult << CCK_SHRES_SHIFT;
+                       hbstop += mult << CCK_SHRES_SHIFT;
+                       if (currprefs.gfx_overscanmode == 0) {
+                               hbstrt += 2 << CCK_SHRES_SHIFT;
+                               hbstop -= 2 << CCK_SHRES_SHIFT;
+                       }
+               }
+               if (!dp_for_drawing || !ce_is_extblankset(colors_for_drawing.extra) || !ce_is_extblankmode(colors_for_drawing.extra)) {
+                       exthblank = false;
+               } else if (currprefs.gfx_overscanmode <= OVERSCANMODE_OVERSCAN) {
+                       if ((new_beamcon0 & 0x0110) && !(new_beamcon0 & 0x80)) {
+                               extern uae_u16 hsstrt;
+                               hbstrt += (hsstrt - 13) << CCK_SHRES_SHIFT;
+                               hbstop += (hsstrt - 13) << CCK_SHRES_SHIFT;
+                       }
+               }
+               if (currprefs.chipset_hr) {
+                       hbstrt &= ~(3 >> currprefs.gfx_resolution);
+                       hbstop &= ~(3 >> currprefs.gfx_resolution);
+               } else {
+                       hbstrt &= ~3;
+                       hbstop &= ~3;
                }
-               if (hblank_right_stop > coord_hw_to_window_x_shres(hbstrt - offset)) {
-                       hblank_right_stop = coord_hw_to_window_x_shres(hbstrt - offset);
+               if (hblank_left_start < coord_hw_to_window_x_shres(hbstop)) {
+                       hblank_left_start = coord_hw_to_window_x_shres(hbstop);
+               }
+               if (hblank_right_stop > coord_hw_to_window_x_shres(hbstrt)) {
+                       hblank_right_stop = coord_hw_to_window_x_shres(hbstrt);
+               }
+       }
+       if (!(new_beamcon0 & 0x1000) || (currprefs.gfx_overscanmode <= OVERSCANMODE_OVERSCAN && !(new_beamcon0 & 0x80))) {
+               int vbstrt = vblank_firstline_hw;
+               int vbstop = vblank_lastline_hw;
+
+               if (currprefs.gfx_overscanmode < OVERSCANMODE_OVERSCAN) {
+                       int mult = (OVERSCANMODE_OVERSCAN - currprefs.gfx_overscanmode) * 5;
+                       vbstrt += mult;
+                       vbstop -= mult;
+               }
+
+               vbstrt <<= currprefs.gfx_vresolution;
+               vbstop <<= currprefs.gfx_vresolution;
+               if (vblank_top_start < vbstrt) {
+                       vblank_top_start = vbstrt;
+               }
+               if (vblank_bottom_stop > vbstop) {
+                       vblank_bottom_stop = vbstop;
                }
        }
 }
@@ -670,8 +716,8 @@ int get_custom_limits (int *pw, int *ph, int *pdx, int *pdy, int *prealh)
        ddflastword_total = coord_hw_to_window_x_lores(ddflastword_total * 2 + DIW_DDF_OFFSET);
 
        if (doublescan <= 0 && !programmedmode) {
-               int min = coord_diw_lores_to_window_x (92);
-               int max = coord_diw_lores_to_window_x (460);
+               int min = coord_diw_lores_to_window_x(92);
+               int max = coord_diw_lores_to_window_x(460);
                if (diwfirstword_total < min)
                        diwfirstword_total = min;
                if (diwlastword_total > max)
@@ -1326,7 +1372,7 @@ static void fill_line_border(int lineno)
        int endpos = visible_right_border;
        int w = endpos - lastpos;
 
-       if (lineno < visible_top_start || lineno >= visible_bottom_stop) {
+       if (lineno < visible_top_start || lineno < vblank_top_start || lineno >= visible_bottom_stop || lineno >= vblank_bottom_stop) {
                int b = hposblank;
                hposblank = 3;
                fill_line2(lastpos, w);
@@ -3134,7 +3180,7 @@ static void do_color_changes(line_draw_func worker_border, line_draw_func worker
                }
 
                // vblank + extblanken: blanked
-               if (!(vb_state & 1) && ce_is_extblankset(colors_for_drawing.extra)) {
+               if (!(vb_state & 1) && ce_is_extblankset(colors_for_drawing.extra) || vp < vblank_top_start || vp >= vblank_bottom_stop) {
 
                        if (nextpos_in_range > lastpos && lastpos < playfield_end) {
                                int t = nextpos_in_range <= playfield_end ? nextpos_in_range : playfield_end;
@@ -3251,11 +3297,11 @@ static void do_color_changes(line_draw_func worker_border, line_draw_func worker
                }
        }
 #if 1
-       if (vp < visible_top_start || vp >= visible_bottom_stop) {
+       if (vp < visible_top_start || vp >= visible_bottom_stop || vp < vblank_top_start || vp >= vblank_bottom_stop) {
                // outside of visible area
                // Just overwrite with black. Above code needs to run because of custom registers,
                // not worth the trouble for separate code path just for max 10 lines or so
-               (*worker_border)(visible_left_border, visible_left_border + vidinfo->drawbuffer.inwidth, 1);
+               (*worker_border)(visible_left_border, visible_right_border - visible_left_border, 1);
        }
 #endif
        if (hsync_shift_hack > 0) {
@@ -3263,7 +3309,7 @@ static void do_color_changes(line_draw_func worker_border, line_draw_func worker
                int shift = (hsync_shift_hack << lores_shift) * vidinfo->drawbuffer.pixbytes;
                if (shift) {
                        int firstpos = visible_left_border * vidinfo->drawbuffer.pixbytes;
-                       int lastpos = (visible_left_border + vidinfo->drawbuffer.inwidth) * vidinfo->drawbuffer.pixbytes;
+                       int lastpos = (visible_right_border - visible_left_border) * vidinfo->drawbuffer.pixbytes;
                        memmove(xlinebuffer + firstpos, xlinebuffer + firstpos + shift, lastpos - firstpos - shift);
                        memset(xlinebuffer + lastpos - shift, 0, shift);
                }
@@ -3528,7 +3574,7 @@ static void center_image (void)
 
        int w = vidinfo->drawbuffer.inwidth;
        int ew = vidinfo->drawbuffer.extrawidth;
-       if (currprefs.gfx_xcenter && !currprefs.gf[0].gfx_filter_autoscale && max_diwstop > 0) {
+       if (currprefs.gfx_overscanmode <= OVERSCANMODE_OVERSCAN && currprefs.gfx_xcenter && !currprefs.gf[0].gfx_filter_autoscale && max_diwstop > 0) {
 
                if (max_diwstop - min_diwstart < w && currprefs.gfx_xcenter == 2)
                        /* Try to center. */
@@ -3545,7 +3591,8 @@ static void center_image (void)
                        }
                }
 #endif
-       } else if (vidinfo->drawbuffer.extrawidth) {
+       } else if (vidinfo->drawbuffer.extrawidth > 0 || ew == -1 || currprefs.gfx_overscanmode == OVERSCANMODE_EXTREME) {
+               // wide mode
                visible_left_border = (hsync_end_left_border * 2) << currprefs.gfx_resolution;
                if (visible_left_border + w < max_diwlastword) {
                        visible_left_border += (max_diwlastword - (visible_left_border + w)) / 2;
@@ -3556,6 +3603,9 @@ static void center_image (void)
                if (visible_left_border < ((hsync_end_left_border * 2) << currprefs.gfx_resolution)) {
                        visible_left_border = (hsync_end_left_border * 2) << currprefs.gfx_resolution;
                }
+       } else if (ew < -1) {
+               // normal
+               visible_left_border = max_diwlastword - w;
        } else {
                if (vidinfo->drawbuffer.inxoffset < 0) {
                        visible_left_border = 0;
index 764b1507b5b13c4e757c6b6eaec8a57789d6fe50..6f76e3a520d732c623cb42fcbacdd5eef007edb4 100644 (file)
@@ -135,6 +135,7 @@ extern float vblank_hz, fake_vblank_hz;
 extern float hblank_hz;
 extern int vblank_skip, doublescan;
 extern bool programmedmode;
+extern int vblank_firstline_hw, vblank_lastline_hw;
 
 #define DMA_AUD0      0x0001
 #define DMA_AUD1      0x0002
@@ -161,7 +162,7 @@ extern bool programmedmode;
 #define CYCLE_MASK 0x0f
 
 extern unsigned long frametime, timeframes;
-extern uae_u16 htotal, vtotal, beamcon0;
+extern uae_u16 htotal, vtotal, beamcon0, new_beamcon0;
 
 // 100 words give you 1600 horizontal pixels. Should be more than enough for superhires. 
 // must be divisible by 8
index 33f09021aa265dcddecff74e0e66416a7fbae3ca..bd8377e043c942c7524dce02e013715b8975d2b8 100644 (file)
@@ -292,6 +292,10 @@ enum { CP_GENERIC = 1, CP_CDTV, CP_CDTVCR, CP_CD32, CP_A500, CP_A500P, CP_A600,
 #define MONITOREMU_OPALVISION 11
 #define MONITOREMU_COLORBURST 12
 
+#define OVERSCANMODE_OVERSCAN 3
+#define OVERSCANMODE_BROADCAST 4
+#define OVERSCANMODE_EXTREME 5
+
 #define MAX_FILTERSHADERS 4
 
 #define MAX_CHIPSET_REFRESH 10
@@ -573,6 +577,7 @@ struct uae_prefs {
        int gfx_display_sections;
        int gfx_variable_sync;
        bool gfx_windowed_resize;
+       int gfx_overscanmode;
 
        struct gfx_filterdata gf[2];
 
index 1f48eda36356e5ed74585ee46f6cb035ebe15def..dcb81a24fc4ae85b9769301277583ad4dd822f4b 100644 (file)
 #define IDC_AUTORESOLUTIONVGA           1181
 #define IDC_RATE2ENABLE                 1182
 #define IDC_GRAYSCALE                   1183
+#define IDC_OVERSCANMODE                1184
 #define IDC_FRAMERATE                   1185
 #define IDC_XSIZE                       1187
 #define IDC_YSIZE                       1188
index 9d1ce25ac988dc472f61d061a978262cd1fbb86a..426dfdbcc4e6970bfa1b87bf618f02fc32a2d418 100644 (file)
@@ -182,17 +182,17 @@ BEGIN
     CONTROL         "VGA mode resolution autoswitch [] Automatically selects between hires and superhires in programmed display modes, keeping correct aspect ratio.",IDC_AUTORESOLUTIONVGA,
                     "Button",BS_AUTOCHECKBOX | WS_TABSTOP,155,158,124,10
     CONTROL         "Monochrome video out",IDC_GRAYSCALE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,11,171,139,10
-    RTEXT           "Resolution:",IDC_STATIC,24,196,110,8,SS_CENTERIMAGE
-    COMBOBOX        IDC_LORES,142,195,127,150,CBS_DROPDOWNLIST | CBS_HASSTRINGS | WS_VSCROLL | WS_TABSTOP
+    RTEXT           "Resolution:",IDC_STATIC,6,196,44,8,SS_CENTERIMAGE
+    COMBOBOX        IDC_LORES,57,195,77,150,CBS_DROPDOWNLIST | CBS_HASSTRINGS | WS_VSCROLL | WS_TABSTOP
     RTEXT           "Resolution autoswitch:",IDC_STATIC,92,216,110,8,SS_CENTERIMAGE
-    COMBOBOX        IDC_AUTORESOLUTIONSELECT,210,215,59,150,CBS_DROPDOWNLIST | CBS_HASSTRINGS | WS_VSCROLL | WS_TABSTOP
+    COMBOBOX        IDC_AUTORESOLUTIONSELECT,214,215,63,150,CBS_DROPDOWNLIST | CBS_HASSTRINGS | WS_VSCROLL | WS_TABSTOP
     RTEXT           "Refresh:",IDC_REFRESHTEXT,11,235,57,8
     CONTROL         "Slider1",IDC_FRAMERATE,"msctls_trackbar32",TBS_AUTOTICKS | TBS_TOP | WS_TABSTOP,71,230,99,20
-    COMBOBOX        IDC_RATE2BOX,210,235,60,150,CBS_DROPDOWNLIST | CBS_HASSTRINGS | WS_VSCROLL | WS_TABSTOP
+    COMBOBOX        IDC_RATE2BOX,213,235,64,150,CBS_DROPDOWNLIST | CBS_HASSTRINGS | WS_VSCROLL | WS_TABSTOP
     RTEXT           "FPS adj.:",IDC_REFRESH2TEXT,9,256,61,8
     CONTROL         "",IDC_FRAMERATE2,"msctls_trackbar32",TBS_AUTOTICKS | TBS_TOP | WS_TABSTOP,71,251,99,20
-    EDITTEXT        IDC_RATE2TEXT,210,255,46,12,ES_AUTOHSCROLL
-    CONTROL         "",IDC_RATE2ENABLE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,261,256,8,10
+    EDITTEXT        IDC_RATE2TEXT,212,255,46,12,ES_AUTOHSCROLL
+    CONTROL         "",IDC_RATE2ENABLE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,265,256,8,10
     COMBOBOX        IDC_DA_MODE,15,280,71,150,CBS_DROPDOWNLIST | CBS_HASSTRINGS | WS_VSCROLL | WS_TABSTOP
     CONTROL         "",IDC_DA_SLIDER,"msctls_trackbar32",TBS_AUTOTICKS | TBS_TOP | WS_TABSTOP,96,276,96,20
     EDITTEXT        IDC_DA_TEXT,205,280,56,12,ES_AUTOHSCROLL | ES_READONLY
@@ -214,6 +214,8 @@ BEGIN
     CONTROL         "VRR monitor. Do not tick!",IDC_DISPLAY_VARSYNC,"Button",BS_AUTOCHECKBOX | NOT WS_VISIBLE | WS_TABSTOP,58,71,112,10
     COMBOBOX        IDC_SCREENMODE_NATIVE3,246,102,31,150,CBS_DROPDOWNLIST | CBS_HASSTRINGS | WS_VSCROLL | WS_TABSTOP
     CONTROL         "Window resize",IDC_DISPLAY_RESIZE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,161,55,92,10
+    COMBOBOX        IDC_OVERSCANMODE,197,194,80,150,CBS_DROPDOWNLIST | CBS_HASSTRINGS | WS_VSCROLL | WS_TABSTOP
+    RTEXT           "Overscan:",IDC_STATIC,145,196,43,8,SS_CENTERIMAGE
 END
 
 IDD_MEMORY DIALOGEX 0, 0, 396, 316
index 023a2b6a8ae2be0513d298e94c352db68d3306b2..63704845eff085964651db89d004c7b3ba80f808 100644 (file)
@@ -2386,6 +2386,7 @@ int check_prefs_changed_gfx (void)
        c |= _tcsicmp(currprefs.genlock_video_file, changed_prefs.genlock_video_file) ? (2 | 8) : 0;
 
        c |= currprefs.gfx_lores_mode != changed_prefs.gfx_lores_mode ? (2 | 8) : 0;
+       c |= currprefs.gfx_overscanmode != changed_prefs.gfx_overscanmode ? (2 | 8) : 0;
        c |= currprefs.gfx_scandoubler != changed_prefs.gfx_scandoubler ? (2 | 8) : 0;
        c |= currprefs.gfx_threebitcolors != changed_prefs.gfx_threebitcolors ? (256) : 0;
        c |= currprefs.gfx_grayscale != changed_prefs.gfx_grayscale ? (512) : 0;
@@ -2486,6 +2487,7 @@ int check_prefs_changed_gfx (void)
                _tcscpy(currprefs.genlock_video_file, changed_prefs.genlock_video_file);
 
                currprefs.gfx_lores_mode = changed_prefs.gfx_lores_mode;
+               currprefs.gfx_overscanmode = changed_prefs.gfx_overscanmode;
                currprefs.gfx_scandoubler = changed_prefs.gfx_scandoubler;
                currprefs.gfx_threebitcolors = changed_prefs.gfx_threebitcolors;
                currprefs.gfx_grayscale = changed_prefs.gfx_grayscale;
index c9afa58d8cbadbd6e24ef17cb35dec4841e9f6f6..41fed9878490ad6c58ac1da285ea4d3d91af4e29 100644 (file)
@@ -7600,12 +7600,13 @@ static void enable_for_displaydlg (HWND hDlg)
 #ifndef PICASSO96
        rtg = FALSE;
 #endif
-       ew (hDlg, IDC_SCREENMODE_RTG, rtg);
-       ew (hDlg, IDC_SCREENMODE_RTG2, rtg);
-       ew (hDlg, IDC_XCENTER, TRUE);
-       ew (hDlg, IDC_YCENTER, TRUE);
-       ew (hDlg, IDC_FRAMERATE, !workprefs.cpu_memory_cycle_exact);
-       ew (hDlg, IDC_LORES, !workprefs.gfx_autoresolution);
+       ew(hDlg, IDC_SCREENMODE_RTG, rtg);
+       ew(hDlg, IDC_SCREENMODE_RTG2, rtg);
+       ew(hDlg, IDC_XCENTER, TRUE);
+       ew(hDlg, IDC_YCENTER, TRUE);
+       ew(hDlg, IDC_FRAMERATE, !workprefs.cpu_memory_cycle_exact);
+       ew(hDlg, IDC_LORES, !workprefs.gfx_autoresolution);
+       ew(hDlg, IDC_OVERSCANMODE, TRUE);
 
        ew(hDlg, IDC_AUTORESOLUTIONVGA, workprefs.gfx_resolution >= RES_HIRES && workprefs.gfx_vresolution >= VRES_DOUBLE);
        if (workprefs.gfx_resolution < RES_HIRES || workprefs.gfx_vresolution < VRES_DOUBLE) {
@@ -8160,9 +8161,16 @@ static void values_to_displaydlg (HWND hDlg)
        SendDlgItemMessage(hDlg, IDC_LORES, CB_ADDSTRING, 0, (LPARAM)buffer);
        SendDlgItemMessage (hDlg, IDC_LORES, CB_SETCURSEL, workprefs.gfx_resolution, 0);
 
-       SendDlgItemMessage(hDlg, IDC_AUTORESOLUTIONSELECT, CB_RESETCONTENT, 0, 0);
-
+       SendDlgItemMessage(hDlg, IDC_OVERSCANMODE, CB_RESETCONTENT, 0, 0);
+       SendDlgItemMessage(hDlg, IDC_OVERSCANMODE, CB_ADDSTRING, 0, (LPARAM)_T("TV (narrow)"));
+       SendDlgItemMessage(hDlg, IDC_OVERSCANMODE, CB_ADDSTRING, 0, (LPARAM)_T("TV (standard"));
+       SendDlgItemMessage(hDlg, IDC_OVERSCANMODE, CB_ADDSTRING, 0, (LPARAM)_T("TV (wide)"));
+       SendDlgItemMessage(hDlg, IDC_OVERSCANMODE, CB_ADDSTRING, 0, (LPARAM)_T("Overscan"));
+       SendDlgItemMessage(hDlg, IDC_OVERSCANMODE, CB_ADDSTRING, 0, (LPARAM)_T("Overscan+"));
+       SendDlgItemMessage(hDlg, IDC_OVERSCANMODE, CB_ADDSTRING, 0, (LPARAM)_T("Extreme"));
+       SendDlgItemMessage(hDlg, IDC_OVERSCANMODE, CB_SETCURSEL, workprefs.gfx_overscanmode, 0);
 
+       SendDlgItemMessage(hDlg, IDC_AUTORESOLUTIONSELECT, CB_RESETCONTENT, 0, 0);
        WIN32GUI_LoadUIString(IDS_DISABLED, buffer, sizeof buffer / sizeof (TCHAR));
        SendDlgItemMessage(hDlg, IDC_AUTORESOLUTIONSELECT, CB_ADDSTRING, 0, (LPARAM)buffer);
        WIN32GUI_LoadUIString(IDS_ALWAYS_ON, buffer, sizeof buffer / sizeof (TCHAR));
@@ -8517,10 +8525,14 @@ static void values_from_displaydlg (HWND hDlg, UINT msg, WPARAM wParam, LPARAM l
                        init_resolution_combo (hDlg);
                        init_display_mode (hDlg);
                        return;
-               } else if (LOWORD (wParam) == IDC_LORES) {
-                       posn = SendDlgItemMessage (hDlg, IDC_LORES, CB_GETCURSEL, 0, 0);
+               } else if (LOWORD(wParam) == IDC_LORES) {
+                       posn = SendDlgItemMessage(hDlg, IDC_LORES, CB_GETCURSEL, 0, 0);
                        if (posn != CB_ERR)
                                workprefs.gfx_resolution = posn;
+               } else if (LOWORD(wParam) == IDC_OVERSCANMODE) {
+                       posn = SendDlgItemMessage(hDlg, IDC_OVERSCANMODE, CB_GETCURSEL, 0, 0);
+                       if (posn != CB_ERR)
+                               workprefs.gfx_overscanmode = posn;
                } else if ((LOWORD (wParam) == IDC_RESOLUTION || LOWORD(wParam) == IDC_RESOLUTIONDEPTH) && dmode >= 0) {
                        workprefs.gfx_monitor[0].gfx_size_fs.width  = md->DisplayModes[dmode].res.width;
                        workprefs.gfx_monitor[0].gfx_size_fs.height = md->DisplayModes[dmode].res.height;