From 3a79ff114c86faaa0d3667e77d7f07d8b4f401df Mon Sep 17 00:00:00 2001 From: Toni Wilen Date: Tue, 15 Jun 2021 21:33:18 +0300 Subject: [PATCH] Custom emulation update WIP. --- cfgfile.cpp | 5 + custom.cpp | 343 +++++++++++++++++++++------------- drawing.cpp | 102 +++++++--- include/custom.h | 3 +- include/options.h | 5 + od-win32/resources/resource.h | 1 + od-win32/resources/winuae.rc | 14 +- od-win32/win32gfx.cpp | 2 + od-win32/win32gui.cpp | 32 +++- 9 files changed, 330 insertions(+), 177 deletions(-) diff --git a/cfgfile.cpp b/cfgfile.cpp index 115ce0e3..53b51531 100644 --- a/cfgfile.cpp +++ b/cfgfile.cpp @@ -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; diff --git a/custom.cpp b/custom.cpp index 833c3cc7..a56eb042 100644 --- a/custom.cpp +++ b/custom.cpp @@ -69,6 +69,11 @@ #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; diff --git a/drawing.cpp b/drawing.cpp index 21e1f041..08cefa83 100644 --- a/drawing.cpp +++ b/drawing.cpp @@ -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; diff --git a/include/custom.h b/include/custom.h index 764b1507..6f76e3a5 100644 --- a/include/custom.h +++ b/include/custom.h @@ -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 diff --git a/include/options.h b/include/options.h index 33f09021..bd8377e0 100644 --- a/include/options.h +++ b/include/options.h @@ -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]; diff --git a/od-win32/resources/resource.h b/od-win32/resources/resource.h index 1f48eda3..dcb81a24 100644 --- a/od-win32/resources/resource.h +++ b/od-win32/resources/resource.h @@ -510,6 +510,7 @@ #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 diff --git a/od-win32/resources/winuae.rc b/od-win32/resources/winuae.rc index 9d1ce25a..426dfdbc 100644 --- a/od-win32/resources/winuae.rc +++ b/od-win32/resources/winuae.rc @@ -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 diff --git a/od-win32/win32gfx.cpp b/od-win32/win32gfx.cpp index 023a2b6a..63704845 100644 --- a/od-win32/win32gfx.cpp +++ b/od-win32/win32gfx.cpp @@ -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; diff --git a/od-win32/win32gui.cpp b/od-win32/win32gui.cpp index c9afa58d..41fed987 100644 --- a/od-win32/win32gui.cpp +++ b/od-win32/win32gui.cpp @@ -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; -- 2.47.3