From 8ac15d30777f411758d577c4668b970c72214abd Mon Sep 17 00:00:00 2001 From: Toni Wilen Date: Sat, 11 Feb 2023 10:52:32 +0200 Subject: [PATCH] Ultra extreme overscan blanking and sync modes. --- cfgfile.cpp | 2 +- custom.cpp | 328 +++++++++++++++++++++++----------- drawing.cpp | 165 ++++++++++++++--- include/drawing.h | 2 + od-win32/resources/resource.h | 1 - od-win32/win32gui.cpp | 2 + 6 files changed, 368 insertions(+), 132 deletions(-) diff --git a/cfgfile.cpp b/cfgfile.cpp index 28b7693c..696a6db1 100644 --- a/cfgfile.cpp +++ b/cfgfile.cpp @@ -205,7 +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"), _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"), _T("ultra"), NULL}; +static const TCHAR *overscanmodes[] = { _T("tv_narrow"), _T("tv_standard"), _T("tv_wide"), _T("overscan"), _T("broadcast"), _T("extreme"), _T("ultra"), _T("ultra_hv"), _T("ultra_csync"), NULL}; static const TCHAR *dongles[] = { _T("none"), diff --git a/custom.cpp b/custom.cpp index 38e4b325..d877436a 100644 --- a/custom.cpp +++ b/custom.cpp @@ -193,22 +193,30 @@ static bool dmacon_bpl, vdiwstate_bpl; static uae_u32 cop1lc, cop2lc, copcon; /* -* horizontal defaults +* Horizontal defaults +* * 0x00 0 HCB * 0x01 1 HC1 (HSTART) * 0x09 9 VR1 (HBLANK start) * 0x12 18 SHS (Horizontal sync start) -* 0x1a 26 VER1 PAL +* 0x1a 26 VER1 PAL * 0x1b 27 VER1 NTSC * 0x23 35 RHS (Horizontal sync end) * 0x73 115 VR2 * 0x84 132 CEN (HCENTER) -* 0x8c 140 VER2 PAL +* 0x8c 140 VER2 PAL (CEN->VER2 = CSYNC qualising pulse 2) * 0x8d 141 VER2 NTSC * 0xe2 226 HC226 (short line, selected if LOL=1, NTSC only) * 0xe3 227 HC227 (NTSC long line/PAL) * -* vertical defaults +* SHS->VER1 = CSYNC equalising pulse 1 +* CEN->VER2 = CSYNC equalising pulse 2 +* +* HC1->SHS = Inactivate part of CSYNC Vsync+Hsync pulse 1 +* VR2->CEN = Inactivate part of CSYNC Vsync+HSync pulse 2 +* +* +* Vertical defaults * * PAL * @@ -287,11 +295,6 @@ static uae_u32 cop1lc, cop2lc, copcon; * Switch DMACON BPLEN off, wait value to DDFSTRT that matches during current scanline, * switch BPLEN on: if OCS, bitplane DMA won't start, ECS/AGA: bitplane DMA starts. * -* -* -* -* -* */ @@ -342,10 +345,12 @@ static int hsstop_detect, hsstop_detect2; static uae_u16 vsstop, vsstrt; static uae_u16 vbstop, vbstrt; static uae_u16 hcenter, hcenter_v2, hcenter_v2_end; +static bool hcenter_active; static uae_u16 hbstop_v, hbstrt_v, hbstop_v2, hbstrt_v2; +static uae_u16 hsstrt_v2, hsstop_v2; static int vsstrt_m, vsstop_m, vbstrt_m, vbstop_m; static bool vb_state, vb_end_line; -static bool vs_state, vs_state_on, vs_state_hw; +static bool vs_state, vs_state_on, vs_state_on_old, vs_state_on_old2, vs_state_hw; static bool vb_end_next_line, vb_end_next_line2; static int vb_start_line; static bool ocs_blanked; @@ -454,6 +459,7 @@ static int last_hdiw; static diw_states vdiwstate, hdiwstate, hdiwstate_conflict; static int bpl_hstart; static bool exthblank, exthblank_state, hcenterblank_state; +static int hsyncdebug; static int last_diw_hpos, last_diw_hpos2; static int last_recorded_diw_hpos; static int last_hblank_start; @@ -990,10 +996,84 @@ static void hblank_reset(int hblankpos) hb_last_diwlastword = hblankpos + 4; } -static void record_color_change2(int hpos, int regno, uae_u32 value) +static void addcc(int pos, int reg, int v) { - color_change *cc; + color_change *cc = &curr_color_changes[next_color_change++]; + cc->linepos = pos; + cc->regno = reg; + cc->value = v; + cc++; + cc->regno = -1; +} + +static void addccmp(int pos, int reg, int v, int chpos) +{ + if (pos < chpos && pos >= last_recorded_diw_hpos) { + addcc(pos, reg, v); + } +} +static void syncdebugmarkers(int chpos) +{ + if (hsyncdebug == 3) { + int ver1 = (beamcon0 & BEAMCON0_PAL) ? 26 : 27; + int ver2 = (beamcon0 & BEAMCON0_PAL) ? 140 : 141; + // CSYNC + if (vpos >= 8 || (beamcon0 & BEAMCON0_VARHSYEN)) { + addccmp(hsstrt_v2, RECORDED_REGISTER_CHANGE_OFFSET + 0x202, 1, chpos); + addccmp(hsstop_v2, RECORDED_REGISTER_CHANGE_OFFSET + 0x202, 0, chpos); + } + addccmp(hbstrt_v2, RECORDED_REGISTER_CHANGE_OFFSET + 0x204, 1, chpos); + addccmp(hbstop_v2, RECORDED_REGISTER_CHANGE_OFFSET + 0x204, 0, chpos); + if (!(beamcon0 & BEAMCON0_VARHSYEN)) { + if (vpos == 0 || vpos == 1 || vpos == 5 || vpos == 6) { + addccmp(18 << CCK_SHRES_SHIFT, RECORDED_REGISTER_CHANGE_OFFSET + 0x202, 1, chpos); + addccmp(ver1 << CCK_SHRES_SHIFT, RECORDED_REGISTER_CHANGE_OFFSET + 0x202, 0, chpos); + addccmp(132 << CCK_SHRES_SHIFT, RECORDED_REGISTER_CHANGE_OFFSET + 0x202, 1, chpos); + addccmp(ver2 << CCK_SHRES_SHIFT, RECORDED_REGISTER_CHANGE_OFFSET + 0x202, 0, chpos); + } + if (vpos == 2) { + addccmp((12 + maxhpos) << CCK_SHRES_SHIFT, RECORDED_REGISTER_CHANGE_OFFSET + 0x202, 1, chpos); + addccmp(ver1 << CCK_SHRES_SHIFT, RECORDED_REGISTER_CHANGE_OFFSET + 0x202, 0, chpos); + addccmp(132 << CCK_SHRES_SHIFT, RECORDED_REGISTER_CHANGE_OFFSET + 0x202, 1, chpos); + } + if (vpos == 3 || vpos == 4) { + addccmp((1 + maxhpos) << CCK_SHRES_SHIFT, RECORDED_REGISTER_CHANGE_OFFSET + 0x202, 0, chpos); + addccmp(18 << CCK_SHRES_SHIFT, RECORDED_REGISTER_CHANGE_OFFSET + 0x202, 1, chpos); + addccmp(115 << CCK_SHRES_SHIFT, RECORDED_REGISTER_CHANGE_OFFSET + 0x202, 0, chpos); + addccmp(132 << CCK_SHRES_SHIFT, RECORDED_REGISTER_CHANGE_OFFSET + 0x202, 1, chpos); + } + if (vpos == 7) { + addccmp(18 << CCK_SHRES_SHIFT, RECORDED_REGISTER_CHANGE_OFFSET + 0x202, 1, chpos); + addccmp(ver1 << CCK_SHRES_SHIFT, RECORDED_REGISTER_CHANGE_OFFSET + 0x202, 0, chpos); + } + } + } else { + // H/V SYNC + if (hcenter_v2 < chpos && hcenter_v2 >= last_recorded_diw_hpos) { + if (beamcon0 & BEAMCON0_PAL) { + if (vs_state_on && !lof_display) { + addcc(hcenter_v2, RECORDED_REGISTER_CHANGE_OFFSET + 0x206, 0); + } else if (!vs_state_on && vs_state_on_old && lof_display) { + addcc(hcenter_v2, RECORDED_REGISTER_CHANGE_OFFSET + 0x206, 1); + } + } else { + if (vs_state_on && lof_display) { + addcc(hcenter_v2, RECORDED_REGISTER_CHANGE_OFFSET + 0x206, 0); + } else if (!vs_state_on && vs_state_on_old && lof_display) { + addcc(hcenter_v2, RECORDED_REGISTER_CHANGE_OFFSET + 0x206, 1); + } + } + } + addccmp(hsstrt_v2, RECORDED_REGISTER_CHANGE_OFFSET + 0x202, 1, chpos); + addccmp(hsstop_v2, RECORDED_REGISTER_CHANGE_OFFSET + 0x202, 0, chpos); + addccmp(hbstrt_v2, RECORDED_REGISTER_CHANGE_OFFSET + 0x204, 1, chpos); + addccmp(hbstop_v2, RECORDED_REGISTER_CHANGE_OFFSET + 0x204, 0, chpos); + } +} + +static void record_color_change2(int hpos, int regno, uae_u32 value) +{ if (line_disabled) { return; } @@ -1003,6 +1083,7 @@ static void record_color_change2(int hpos, int regno, uae_u32 value) } int pos = hpos < 0 ? -hpos : hpos_to_diwx(hpos); + int start_color_change = next_color_change; // AGA has extra hires pixel delay in color changes if ((regno < RECORDED_REGISTER_CHANGE_OFFSET || regno == RECORDED_REGISTER_CHANGE_OFFSET + 0x10c || regno == RECORDED_REGISTER_CHANGE_OFFSET + 0x201) && aga_mode) { @@ -1026,31 +1107,21 @@ static void record_color_change2(int hpos, int regno, uae_u32 value) pos += 2; if ((value & 0x00ff) != (bplcon4 & 0x00ff)) { // Sprite bank delay - cc = &curr_color_changes[next_color_change]; - cc->linepos = pos; - cc->regno = regno | 1; - cc->value = value; - next_color_change++; + addcc(pos, regno | 1, value); } pos += 2; } } // HCENTER blanking (ECS Denise only) - if (hcenter_v2 && vs_state_on && lof_display) { + if (hcenter_active && vs_state_on && lof_display) { int chpos = pos; if (!hcenterblank_state && hcenter_v2 < chpos && hcenter_v2 >= last_recorded_diw_hpos) { hcenterblank_state = true; if ((bplcon0 & 1) && (bplcon3 & 1)) { - cc = &curr_color_changes[next_color_change]; - cc->linepos = hcenter_v2; - cc->regno = RECORDED_REGISTER_CHANGE_OFFSET + 0x200; - cc->value = 1; - next_color_change++; - cc[1].regno = -1; - last_recorded_diw_hpos = cc->linepos; + addcc(hcenter_v2, RECORDED_REGISTER_CHANGE_OFFSET + 0x200, 1); if (debug_dma) { - record_dma_event(DMA_EVENT_HBS, diw_to_hpos(cc->linepos), vpos); + record_dma_event(DMA_EVENT_HBS, diw_to_hpos(hcenter_v2), vpos); } thisline_changed = 1; } @@ -1058,15 +1129,9 @@ static void record_color_change2(int hpos, int regno, uae_u32 value) if (hcenterblank_state && hcenter_v2_end < chpos && hcenter_v2_end >= last_recorded_diw_hpos) { hcenterblank_state = false; if ((bplcon0 & 1) && (bplcon3 & 1)) { - cc = &curr_color_changes[next_color_change]; - cc->linepos = hcenter_v2_end; - cc->regno = RECORDED_REGISTER_CHANGE_OFFSET + 0x200; - cc->value = 0; - next_color_change++; - cc[1].regno = -1; - last_recorded_diw_hpos = cc->linepos; + addcc(hcenter_v2_end, RECORDED_REGISTER_CHANGE_OFFSET + 0x200, 0); if (debug_dma) { - record_dma_event(DMA_EVENT_HBE, diw_to_hpos(cc->linepos), vpos); + record_dma_event(DMA_EVENT_HBE, diw_to_hpos(hcenter_v2), vpos); } thisline_changed = 1; } @@ -1078,93 +1143,89 @@ static void record_color_change2(int hpos, int regno, uae_u32 value) // inject programmed hblank start and end in color changes if (hbstrt_v2 <= hbstop_v2) { if (hbstrt_v2 < chpos && hbstrt_v2 >= last_recorded_diw_hpos) { - cc = &curr_color_changes[next_color_change]; - cc->linepos = hbstrt_v2; - cc->regno = RECORDED_REGISTER_CHANGE_OFFSET + 0x200; - cc->value = 1; - next_color_change++; - cc[1].regno = -1; + addcc(hbstrt_v2, RECORDED_REGISTER_CHANGE_OFFSET + 0x200, 1); hblank_reset(hbstrt_v2); exthblank_state = true; - last_recorded_diw_hpos = cc->linepos; - last_hblank_start = cc->linepos; + last_hblank_start = hbstrt_v2; if (debug_dma) { - record_dma_event(DMA_EVENT_HBS, diw_to_hpos(cc->linepos), vpos); + record_dma_event(DMA_EVENT_HBS, diw_to_hpos(hbstrt_v2), vpos); } } if (hbstop_v2 < chpos && hbstop_v2 >= last_recorded_diw_hpos) { // do_color_changes() HBLANK workaround if (next_color_change == last_color_change && exthblank_state) { - cc = &curr_color_changes[next_color_change]; - cc->linepos = 0; - cc->regno = RECORDED_REGISTER_CHANGE_OFFSET + 0x200; - cc->value = 1; - next_color_change++; - } - cc = &curr_color_changes[next_color_change]; - cc->linepos = hbstop_v2; - cc->regno = RECORDED_REGISTER_CHANGE_OFFSET + 0x200; - cc->value = 0; - next_color_change++; - cc[1].regno = -1; + addcc(0, RECORDED_REGISTER_CHANGE_OFFSET + 0x200, 1); + } + addcc(hbstop_v2, RECORDED_REGISTER_CHANGE_OFFSET + 0x200, 0); exthblank_state = false; - last_recorded_diw_hpos = cc->linepos; if (debug_dma) { - record_dma_event(DMA_EVENT_HBE, diw_to_hpos(cc->linepos), vpos); + record_dma_event(DMA_EVENT_HBE, diw_to_hpos(hbstop_v2), vpos); } } - } else if (hbstrt_v2 > hbstop_v2) { // equal: blank disable wins + } else if (hbstrt_v2 > hbstop_v2) { // equal: blank disable wins if (hbstop_v2 < chpos && hbstop_v2 >= last_recorded_diw_hpos) { if (next_color_change == last_color_change && exthblank_state) { - cc = &curr_color_changes[next_color_change]; - cc->linepos = 0; - cc->regno = RECORDED_REGISTER_CHANGE_OFFSET + 0x200; - cc->value = 1; - next_color_change++; - } - cc = &curr_color_changes[next_color_change]; - cc->linepos = hbstop_v2; - cc->regno = RECORDED_REGISTER_CHANGE_OFFSET + 0x200; - cc->value = 0; - next_color_change++; - cc[1].regno = -1; + addcc(0, RECORDED_REGISTER_CHANGE_OFFSET + 0x200, 1); + } + addcc(hbstop_v2, RECORDED_REGISTER_CHANGE_OFFSET + 0x200, 0); exthblank_state = false; - last_recorded_diw_hpos = cc->linepos; if (debug_dma) { - record_dma_event(DMA_EVENT_HBE, diw_to_hpos(cc->linepos), vpos); + record_dma_event(DMA_EVENT_HBE, diw_to_hpos(hbstop_v2), vpos); } } if (hbstrt_v2 < chpos && hbstrt_v2 >= last_recorded_diw_hpos) { - cc = &curr_color_changes[next_color_change]; - cc->linepos = hbstrt_v2; - cc->regno = RECORDED_REGISTER_CHANGE_OFFSET + 0x200; - cc->value = 1; - next_color_change++; - cc[1].regno = -1; + addcc(hbstrt_v2, RECORDED_REGISTER_CHANGE_OFFSET + 0x200, 1); hblank_reset(hbstrt_v2); exthblank_state = true; - last_recorded_diw_hpos = cc->linepos; - last_hblank_start = cc->linepos; + last_hblank_start = hbstrt_v2; if (debug_dma) { - record_dma_event(DMA_EVENT_HBS, diw_to_hpos(cc->linepos), vpos); + record_dma_event(DMA_EVENT_HBS, diw_to_hpos(hbstrt_v2), vpos); } } } } + // inject hsync and end in color changes (ultra mode debug) + if (hsyncdebug) { + syncdebugmarkers(pos); + } + if (regno != 0xffff) { - cc = &curr_color_changes[next_color_change]; - cc->linepos = pos; - cc->regno = regno; - cc->value = value; - next_color_change++; - cc[1].regno = -1; + addcc(pos, regno, value); } if (pos > last_recorded_diw_hpos) { last_recorded_diw_hpos = pos; } + int cchanges = next_color_change - start_color_change; + if (cchanges > 1 && hsyncdebug) { + if (cchanges == 2) { + color_change *cc1 = &curr_color_changes[start_color_change]; + color_change *cc2 = &curr_color_changes[start_color_change + 1]; + if (cc1->linepos > cc2->linepos) { + color_change cc = *cc2; + *cc2 = *cc1; + *cc1 = cc; + } + } else { + // debug only, can be slow + for (int i = 0; i < cchanges; i++) { + color_change *cc1 = &curr_color_changes[start_color_change + i]; + for(int j = i + 1; j < cchanges; j++) { + color_change *cc2 = &curr_color_changes[start_color_change + j]; + if (cc1->linepos > cc2->linepos) { + color_change cc = *cc2; + *cc2 = *cc1; + *cc1 = cc; + } + } + } + color_change *cc1 = &curr_color_changes[start_color_change]; + color_change *cc2 = &curr_color_changes[start_color_change]; + } + } + } static void sync_color_changes(int hpos) @@ -1947,6 +2008,10 @@ static void update_mirrors(void) sprite_sprctlmask = 0x01; } set_chipset_mode(); + hsyncdebug = 0; + if (currprefs.gfx_overscanmode >= OVERSCANMODE_ULTRA) { + hsyncdebug = currprefs.gfx_overscanmode - OVERSCANMODE_ULTRA + 1; + } } extern struct color_entry colors_for_drawing; @@ -5679,13 +5744,15 @@ static void reset_decisions_hsync_start(void) } } } - - if (!ecs_denise && vb_end_line) { - thisline_decision.vb = VB_NOVB; - } #endif - if (currprefs.gfx_overscanmode == OVERSCANMODE_ULTRA) { - thisline_decision.vb = VB_NOVB; + + if (currprefs.gfx_overscanmode >= OVERSCANMODE_ULTRA) { + if (thisline_decision.vb != VB_NOVB) { + thisline_decision.vb = VB_VB | VB_NOVB; + } + if (vs_state_on) { + thisline_decision.vb |= VB_VS; + } } if (nosignal_status == 1) { thisline_decision.vb = VB_XBLANK; @@ -5990,8 +6057,14 @@ static void set_hcenter(void) if (hcenter_v2_end >= maxhpos << CCK_SHRES_SHIFT) { hcenter_v2_end -= maxhpos << CCK_SHRES_SHIFT; } + hcenter_active = true; } else { - hcenter_v2 = 0; + if (beamcon0 & bemcon0_vsync_mask) { + hcenter_v2 = (hcenter & 0xff) << CCK_SHRES_SHIFT; + } else { + hcenter_v2 = 132 << CCK_SHRES_SHIFT; + } + hcenter_active = false; } } @@ -6051,6 +6124,13 @@ static void updateextblk(void) exthblank = (bplcon0 & 1) && (bplcon3 & 1); } + if (!exthblank) { + hbstrt_v2 = (8 << CCK_SHRES_SHIFT) - 3; + hbstop_v2 = (47 << CCK_SHRES_SHIFT) - 7; + hbstrt_v2 = adjust_hr(hbstrt_v2); + hbstop_v2 = adjust_hr(hbstop_v2); + } + if (new_beamcon0 & bemcon0_hsync_mask) { hsyncstartpos = hsstrt + 2; @@ -6076,6 +6156,9 @@ static void updateextblk(void) hsyncstartpos_start = REFRESH_FIRST_HPOS + 1; } + hsstrt_v2 = (hsstrt & 0xff) << CCK_SHRES_SHIFT; + hsstop_v2 = (hsstop & 0xff) << CCK_SHRES_SHIFT; + } else { hsyncstartpos_start = hsyncstartpos_start_hw; @@ -6083,8 +6166,14 @@ static void updateextblk(void) denisehtotal = 227 + 7; hsstop_detect2 = (35 + 9) * 2; + hsstrt_v2 = 18 << CCK_SHRES_SHIFT; + hsstop_v2 = 35 << CCK_SHRES_SHIFT; + } + hsstrt_v2 = adjust_hr(hsstrt_v2); + hsstop_v2 = adjust_hr(hsstop_v2); + // Out of range left. Denise/Lisa hcounter starts from 2 (skips first 2 lores pixels) if (hbstrt_v2 < (1 << CCK_SHRES_SHIFT)) { hbstrt_v2 = 0xffff; @@ -6146,7 +6235,7 @@ static void updateextblk(void) denisehtotal <<= CCK_SHRES_SHIFT; // ECS Denise has 1 extra lores pixel in right border - if (currprefs.gfx_overscanmode == OVERSCANMODE_ULTRA) { + if (currprefs.gfx_overscanmode >= OVERSCANMODE_ULTRA) { denisehtotal += 2 << (CCK_SHRES_SHIFT - 1); } else if (ecs_denise) { denisehtotal += 1 << (CCK_SHRES_SHIFT - 1); @@ -6510,8 +6599,11 @@ static void init_hz(bool checkvposw) // assume VGA-like monitor if VARBEAMEN if (currprefs.gfx_overscanmode >= OVERSCANMODE_ULTRA) { maxhpos_display = maxhpos; - hsstop_detect = 8 * 2; - maxvpos_display_vsync += 2; + hsstop_detect = hsstrt * 2; + if (hsstop_detect > maxhpos / 2 * 2 || hsstop_detect < 4 * 2) { + hsstop_detect = 4 * 2; + } + minfirstline = 0; } else { int hp2 = maxhpos * 2; if (exthblank) { @@ -6591,7 +6683,7 @@ static void init_hz(bool checkvposw) hsstop_detect += 7; } else if (currprefs.gfx_overscanmode == OVERSCANMODE_BROADCAST) { hsstop_detect += 5; - } else if (currprefs.gfx_overscanmode == OVERSCANMODE_ULTRA) { + } else if (currprefs.gfx_overscanmode >= OVERSCANMODE_ULTRA) { maxhpos_display += EXTRAWIDTH_ULTRA; maxvpos_display_vsync += 2; minfirstline = 0; @@ -6599,10 +6691,10 @@ static void init_hz(bool checkvposw) } } else { - if (currprefs.gfx_overscanmode == OVERSCANMODE_ULTRA) { + if (currprefs.gfx_overscanmode >= OVERSCANMODE_ULTRA) { maxhpos_display += EXTRAWIDTH_ULTRA; maxvpos_display_vsync += 2; - hsstop_detect = 16; + hsstop_detect = 18 * 2; minfirstline = 0; } } @@ -6633,11 +6725,14 @@ static void init_hz(bool checkvposw) if (hsstop_detect < 0) { hsstop_detect = 0; } + if (minfirstline < 0) { + minfirstline = 0; + } vblank_extraline = !currprefs.cs_dipagnus && !ecs_denise ? 1 : 0; int minfirstline_hw = minfirstline; - if (currprefs.gfx_overscanmode == OVERSCANMODE_ULTRA) { + if (currprefs.gfx_overscanmode >= OVERSCANMODE_ULTRA) { minfirstline = 0; minfirstline_hw = 0; } else if (currprefs.gfx_overscanmode == OVERSCANMODE_EXTREME) { @@ -6711,8 +6806,8 @@ static void init_hz(bool checkvposw) maxvpos_display_vsync = 0; } - if (minfirstline < 1) { - minfirstline = 1; + if (minfirstline < vsync_startline) { + minfirstline = vsync_startline; } if (minfirstline >= maxvpos) { @@ -6734,9 +6829,14 @@ static void init_hz(bool checkvposw) if (maxvpos_display_vsync < 0) { maxvpos_display_vsync = 0; } - if (minfirstline <= vsync_startline) { + if (minfirstline < vsync_startline) { minfirstline = vsync_startline; } + if (currprefs.gfx_overscanmode >= OVERSCANMODE_ULTRA) { + if (minfirstline > vsstrt + 1) { + minfirstline = vsstrt + 1; + } + } } if (beamcon0 & BEAMCON0_VARBEAMEN) { @@ -11980,7 +12080,18 @@ static void hsync_handlerh(bool onvsync) hpos_hsync_extra = 0; estimate_last_fetch_cycle(hpos); - if (vb_end_next_line && !ecs_denise && currprefs.gfx_overscanmode < OVERSCANMODE_ULTRA) { + if (currprefs.gfx_overscanmode >= OVERSCANMODE_ULTRA) { + if (beamcon0 & BEAMCON0_PAL) { + if (vs_state_on_old && !vs_state_on_old2 && !lof_display) { + record_color_change2(hpos, RECORDED_REGISTER_CHANGE_OFFSET + 0x206, 1); + } + } else { + if (vs_state_on_old && !vs_state_on_old2 && lof_display) { + record_color_change2(hpos, RECORDED_REGISTER_CHANGE_OFFSET + 0x206, 1); + } + } + } + if (vb_end_next_line && !ecs_denise) { record_color_change2(hpos, 0, COLOR_CHANGE_BLANK | 1); } @@ -13003,18 +13114,20 @@ static void hsync_handler_post(bool onvsync) if (vpos == 3 && lof_store) { vs_state_hw = true; } - if (vpos == 5) { + if (vpos == 5 + 1) { vs_state_hw = false; } } else { if (vpos == 3) { vs_state_hw = true; } - if (vpos == 6) { + if (vpos == 6 + 1) { vs_state_hw = false; } } + vs_state_on_old2 = vs_state_on_old; + vs_state_on_old = vs_state_on; if (new_beamcon0 & bemcon0_vsync_mask) { vs_state_on = vs_state; } else { @@ -13388,6 +13501,7 @@ void custom_reset(bool hardreset, bool keyboardreset) hbstrt_v2 = 0; hbstop_v2 = 0; hcenter_v2 = 0; + hcenter_active = false; set_hcenter(); display_reset = 1; copper_bad_cycle = 0; diff --git a/drawing.cpp b/drawing.cpp index 522a7d8f..f2ba63a9 100644 --- a/drawing.cpp +++ b/drawing.cpp @@ -255,8 +255,11 @@ static int visible_top_start, visible_bottom_stop; static int vblank_top_start, vblank_bottom_stop; static int hblank_left_start, hblank_right_stop; static int hblank_left_start_hard, hblank_right_stop_hard; -static bool exthblank, extborder, exthblanken, exthblankon; +static bool extborder, exthblanken, exthblankon; +static int exthblank; +static int exthblank_set; static bool ehb_enable; +static bool syncdebug; static int linetoscr_x_adjust_pixbytes, linetoscr_x_adjust_pixels; static int thisframe_y_adjust; @@ -289,6 +292,8 @@ static bool aga_genlock_features_zdclken; static int hsync_shift_hack; static bool sprite_smaller_than_64, sprite_smaller_than_64_inuse; static bool full_blank; +static bool hsync_debug, vsync_debug, hblank_debug, vblank_debug; +static int hcenter_debug; static uae_u8 vb_state; uae_sem_t gui_sem; @@ -480,16 +485,18 @@ static void reset_custom_limits(void) static void expand_vb_state(void) { full_blank = vb_state == VB_PRGVB || (vb_state >= VB_XBLANK && vb_state < VB_XBORDER) || (vb_state == VB_XBORDER); + vsync_debug = (vb_state & VB_VS) != 0; + vblank_debug = (vb_state & VB_VB) != 0; } static void extblankcheck(void) { exthblankon = dp_for_drawing && (dp_for_drawing->bplcon3 & 1) && (dp_for_drawing->bplcon0 & 1); if (exthblanken && exthblankon) { - exthblank = true; + exthblank = exthblank_set; } if (exthblanken && !exthblankon) { - exthblank = false; + exthblank = 0; } } @@ -553,7 +560,7 @@ static void set_vblanking_limits(void) vblank_bottom_stop = visible_bottom_stop; } - if (currprefs.gfx_overscanmode == OVERSCANMODE_ULTRA) { + if (syncdebug) { return; } @@ -596,7 +603,7 @@ int get_vertical_visible_height(bool useoldsize) if (interlace_seen && currprefs.gfx_vresolution > 0) { h -= 1 << (currprefs.gfx_vresolution - 1); } - if (currprefs.gfx_overscanmode < OVERSCANMODE_ULTRA) { + if (syncdebug) { bool hardwired = true; if (ecs_agnus) { hardwired = (new_beamcon0 & BEAMCON0_VARVBEN) == 0; @@ -614,7 +621,7 @@ int get_vertical_visible_height(bool useoldsize) static void set_hblanking_limits(void) { - if (currprefs.gfx_overscanmode == OVERSCANMODE_ULTRA) { + if (syncdebug) { hblank_left_start_hard = visible_left_start; hblank_right_stop_hard = visible_right_stop; return; @@ -654,6 +661,8 @@ static void set_hblanking_limits(void) } else if (currprefs.gfx_overscanmode == OVERSCANMODE_BROADCAST) { hbstrt = (239 << CCK_SHRES_SHIFT) - 3; doblank = true; + } else if (currprefs.gfx_overscanmode >= OVERSCANMODE_ULTRA) { + doblank = true; } if (doblank && programmedmode != 1) { @@ -1102,7 +1111,7 @@ static xcolnr getbgc(int blank) //return colors_for_drawing.acolors[0]; return xcolors[0xf0f]; #endif - if (exthblank) { + if (exthblank > 0) { return fullblack; } bool extblken = ce_is_extblankset(colors_for_drawing.extra); @@ -1541,6 +1550,84 @@ static void pfield_do_fill_line (int start, int stop, int blank) } } +static void pfield_do_darken_line(int start, int stop, int vp) +{ + struct vidbuf_description *vidinfo = &adisplays[0].gfxvidinfo; + if (stop <= start) + return; + if (currprefs.gfx_resolution) { + vp >>= 1; + } + bool brd = !vsync_debug && !hsync_debug && !vblank_debug && !hblank_debug && !hcenter_debug && ce_is_borderblank(colors_for_drawing.extra); + bool vs = vsync_debug; + if (hcenter_debug) { + vs = false; + + } + int c0 = 0x000; + int c1 = 0x136; + int c2 = 0x686; + bool csync = currprefs.gfx_overscanmode == OVERSCANMODE_ULTRA + 2; + bool trans = currprefs.gfx_overscanmode == OVERSCANMODE_ULTRA; + if (!csync) { + bool sync = hsync_debug || vs; + if (sync && currprefs.gfx_overscanmode > OVERSCANMODE_ULTRA) { + c0 = 0x831; + c1 = 0x000; + } + if (hcenter_debug && vsync_debug && currprefs.gfx_overscanmode > OVERSCANMODE_ULTRA) { + c0 = 0x381; + } + } else { + if (hsync_debug) { + c0 = 0x831; + c1 = 0x000; + } + } + if (!trans) { + vp = 0; + if (!c0) { + c0 = c1; + } else { + c1 = c0; + } + } + if (vidinfo->drawbuffer.pixbytes == 4) { + uae_u32 *b = (uae_u32 *)xlinebuffer; + for (int i = start; i < stop; i++) { + int s = (i ^ vp) & 3; + if (brd) { + if (playfield_start_pre >= playfield_start && (i < playfield_start || i >= playfield_end)) { + if (s == 1) { + b[i] = xcolors[c2]; + } else if (s == 3) { + b[i] = xcolors[c1]; + } + } else if (i < playfield_start_pre || i >= playfield_end_pre) { + if (s == 1) { + b[i] = xcolors[c2]; + } else if (s == 3) { + b[i] = xcolors[c1]; + } + } + } else { + if (s == 1) { + b[i] = xcolors[c0]; + } else if (s == 3) { + b[i] = xcolors[c1]; + } + if (!trans) { + if (s == 0) { + b[i] = xcolors[c0]; + } else if (s == 2) { + b[i] = xcolors[c1]; + } + } + } + } + } +} + static void fill_line2(int startpos, int len) { struct vidbuf_description *vidinfo = &adisplays[0].gfxvidinfo; @@ -1603,6 +1690,9 @@ static void fill_line_border(int lineno) int b = hposblank; hposblank = 3; fill_line2(lastpos, w); + if (syncdebug) { + pfield_do_darken_line(lastpos, endpos, lineno); + } if (need_genlock_data) { memset(xlinebuffer_genlock + lastpos, get_genlock_transparency_border(), w); } @@ -1614,11 +1704,15 @@ static void fill_line_border(int lineno) if (hposblank) { hposblank = 3; fill_line2(lastpos, w); + if (syncdebug) { + pfield_do_darken_line(lastpos, endpos, lineno); + } if (need_genlock_data) { memset(xlinebuffer_genlock + lastpos, get_genlock_transparency_border(), w); } return; } + // hblank not visible if (hblank_left <= lastpos && hblank_right >= endpos) { fill_line2(lastpos, w); @@ -2103,7 +2197,7 @@ static void pfield_do_linetoscr_spr(int start, int stop, int blank) bool bb = ce_is_borderblank(colors_for_drawing.extra); #endif pixel = pfield_do_linetoscr_sprite(src_pixel, start, stop); - pfield_do_fill_line(start, stop, bb || exthblank); + pfield_do_fill_line(start, stop, bb || exthblank > 0); } else { pixel = pfield_do_linetoscr_sprite(src_pixel, start, stop); if (exthblank) { @@ -2491,7 +2585,7 @@ static void pfield_set_linetoscr (void) // A1000 Denise right border bug: sprites have 1 extra lores pixel visible static void pfield_do_linetoscr_bordersprite_a1000(int start, int stop, int blank) { - if (blank || exthblank || extborder) { + if (blank || exthblank > 0 || extborder) { pfield_do_fill_line(start, stop, blank); return; } @@ -2511,7 +2605,7 @@ static void pfield_do_linetoscr_bordersprite_a1000(int start, int stop, int blan // left or right AGA border sprite static void pfield_do_linetoscr_bordersprite_aga(int start, int stop, int blank) { - if (blank || exthblank || extborder) { + if (blank || exthblank > 0 || extborder) { pfield_do_fill_line(start, stop, blank); return; } @@ -3407,19 +3501,26 @@ static void pfield_expand_dp_bplconx (int regno, int v, int hp, int vp) break; case 0x200: // hblank if (v) { - if (currprefs.gfx_overscanmode < OVERSCANMODE_ULTRA) { - exthblanken = true; - } + exthblanken = true; if (vp >= 0) { extblankcheck(); } else { - exthblank = true; + exthblank = exthblank_set; } } else { exthblanken = false; - exthblank = false; + exthblank = 0; } return; + case 0x202: // hsync (debug) + hsync_debug = v; + return; + case 0x204: // hblank (debug) + hblank_debug = v; + return; + case 0x206: // hcenter (denug) + hcenter_debug = v; + return; #endif } pfield_expand_dp_bplcon(); @@ -3494,18 +3595,19 @@ static void playfield_hard_way(line_draw_func worker_pfield, int first, int last static void do_color_changes(line_draw_func worker_border, line_draw_func worker_pfield, int vp) { struct vidbuf_description *vidinfo = &adisplays[0].gfxvidinfo; - int i; int lastpos = visible_left_border; + int lastpos2 = lastpos; int endpos = visible_left_border + vidinfo->drawbuffer.inwidth; bool vbarea = vp < vblank_top_start || vp >= vblank_bottom_stop; extborder = false; // reset here because it always have start and end in same scanline + hcenter_debug = 0; if (!ecs_denise) { // used for OCS Denise blanking bug when not ECS Denise or AGA. - exthblank = false; + exthblank = 0; } ehb_enable = true; - for (i = dip_for_drawing->first_color_change; i <= dip_for_drawing->last_color_change; i++) { + for (int i = dip_for_drawing->first_color_change; i <= dip_for_drawing->last_color_change; i++) { int regno = curr_color_changes[i].regno; uae_u32 value = curr_color_changes[i].value; int nextpos, nextpos_in_range; @@ -3517,7 +3619,7 @@ static void do_color_changes(line_draw_func worker_border, line_draw_func worker } nextpos_in_range = nextpos; - if (nextpos > endpos) { + if (nextpos_in_range > endpos) { nextpos_in_range = endpos; } @@ -3618,6 +3720,15 @@ static void do_color_changes(line_draw_func worker_border, line_draw_func worker lastpos = nextpos_in_range; } } + + if (syncdebug) { + if (hblank_debug || vblank_debug || hsync_debug || vsync_debug || hcenter_debug || exthblank || ce_is_borderblank(colors_for_drawing.extra)) { + pfield_do_darken_line(lastpos2, nextpos_in_range, vp); + } + if (nextpos_in_range > lastpos2) { + lastpos2 = nextpos_in_range; + } + } } if (i < dip_for_drawing->last_color_change) { @@ -3635,9 +3746,12 @@ static void do_color_changes(line_draw_func worker_border, line_draw_func worker } } else if (value & COLOR_CHANGE_BLANK) { if (value & 1) { - exthblank = true; + exthblank = exthblank_set; } else { - exthblank = false; + exthblank = 0; + // so that OCS Denise blanking bug is marked in debug mode + hblank_debug = false; + vblank_debug = false; } } else if (value & COLOR_CHANGE_BRDBLANK) { colors_for_drawing.extra &= ~(1 << CE_BORDERBLANK); @@ -3659,6 +3773,7 @@ static void do_color_changes(line_draw_func worker_border, line_draw_func worker } } } + if (vp >= 0 && hsync_shift_hack > 0) { // hpos shift hack int shift = (hsync_shift_hack << lores_shift) * vidinfo->drawbuffer.pixbytes; @@ -3867,7 +3982,7 @@ static void pfield_draw_line(struct vidbuffer *vb, int lineno, int gfx_ypos, int pfield_erase_vborder_sprites(); } #endif - if (!dosprites && !have_color_changes) { + if (!syncdebug && !dosprites && !have_color_changes) { if (dp_for_drawing->plfleft < -1) { // blanked border line int tmp = hposblank; @@ -5187,14 +5302,18 @@ void reset_drawing(void) struct amigadisplay *ad = &adisplays[monid]; struct vidbuf_description *vidinfo = &ad->gfxvidinfo; + syncdebug = currprefs.gfx_overscanmode >= OVERSCANMODE_ULTRA; max_diwstop = 0; vb_state = 0; - exthblank = false; + exthblank = 0; + exthblank_set = syncdebug ? -1 : 1; exthblanken = false; exthblankon = false; extborder = false; display_reset = 1; ehb_enable = true; + hblank_debug = vblank_debug = hsync_debug = vsync_debug = false; + hcenter_debug = 0; lores_reset (); diff --git a/include/drawing.h b/include/drawing.h index c303a8e5..9738be8f 100644 --- a/include/drawing.h +++ b/include/drawing.h @@ -142,6 +142,8 @@ STATIC_INLINE bool ce_is_borderntrans(uae_u16 data) return (data & (1 << CE_BORDERNTRANS)) != 0; } +#define VB_VB 0x20 // vblank +#define VB_VS 0x10 // vsync #define VB_XBORDER 0x08 // forced border color or bblank #define VB_XBLANK 0x04 // forced bblank #define VB_PRGVB 0x02 // programmed vblank diff --git a/od-win32/resources/resource.h b/od-win32/resources/resource.h index af9cde73..d4740013 100644 --- a/od-win32/resources/resource.h +++ b/od-win32/resources/resource.h @@ -777,7 +777,6 @@ #define IDC_SETTINGSTEXT3 1520 #define IDC_DISPLAY_VARSYNC 1520 #define IDC_ECS_AGNUS 1521 -#define IDC_DISPLAY_VARSYNC2 1521 #define IDC_DISPLAY_RESIZE 1521 #define IDC_ECS_DENISE 1522 #define IDC_ECS 1523 diff --git a/od-win32/win32gui.cpp b/od-win32/win32gui.cpp index 14788ec7..d66b43ec 100644 --- a/od-win32/win32gui.cpp +++ b/od-win32/win32gui.cpp @@ -8473,6 +8473,8 @@ static void values_to_displaydlg (HWND hDlg) xSendDlgItemMessage(hDlg, IDC_OVERSCANMODE, CB_ADDSTRING, 0, (LPARAM)_T("Overscan+")); xSendDlgItemMessage(hDlg, IDC_OVERSCANMODE, CB_ADDSTRING, 0, (LPARAM)_T("Extreme")); xSendDlgItemMessage(hDlg, IDC_OVERSCANMODE, CB_ADDSTRING, 0, (LPARAM)_T("Ultra extreme debug")); + xSendDlgItemMessage(hDlg, IDC_OVERSCANMODE, CB_ADDSTRING, 0, (LPARAM)_T("Ultra extreme debug (HV)")); + xSendDlgItemMessage(hDlg, IDC_OVERSCANMODE, CB_ADDSTRING, 0, (LPARAM)_T("Ultra extreme debug (C)")); xSendDlgItemMessage(hDlg, IDC_OVERSCANMODE, CB_SETCURSEL, workprefs.gfx_overscanmode, 0); xSendDlgItemMessage(hDlg, IDC_AUTORESOLUTIONSELECT, CB_RESETCONTENT, 0, 0); -- 2.47.3