From 555bf99c0875d4cd3766809762ae74865d176aa7 Mon Sep 17 00:00:00 2001 From: Toni Wilen Date: Mon, 23 Jul 2018 21:55:51 +0300 Subject: [PATCH] DIWHIGH H0/H1 support. AGA borderblank update. BPLCON1 updates. --- custom.cpp | 55 +++++++++++++++++-------------------- drawing.cpp | 70 +++++++++++++++++++++++++++++++++-------------- include/drawing.h | 11 ++++++-- 3 files changed, 83 insertions(+), 53 deletions(-) diff --git a/custom.cpp b/custom.cpp index c5b2e11d..d7dda90c 100644 --- a/custom.cpp +++ b/custom.cpp @@ -2126,29 +2126,19 @@ static int flush_plane_data_hr(int fm) { int i = 0; - while (out_nbits) { + if (out_nbits) { int m = 64 - out_nbits; - if (m > 16) - m = 16; toscr_1_hr(m, fm); i += m; } - i += 32; - toscr_1_hr(16, fm); - toscr_1_hr(16, fm); - i += 32; - toscr_1_hr(16, fm); - toscr_1_hr(16, fm); + i += 64; + toscr_1_hr(64, fm); if (fm == 2) { /* flush AGA full 64-bit shift register + possible data in todisplay */ - i += 32; - toscr_1_hr(16, fm); - toscr_1_hr(16, fm); - i += 32; - toscr_1_hr(16, fm); - toscr_1_hr(16, fm); + i += 64; + toscr_1_hr(64, fm); } return i >> (1 + toscr_res); @@ -4980,12 +4970,12 @@ void init_hz_normal (void) static void calcdiw (void) { - int hstrt = diwstrt & 0xFF; - int hstop = diwstop & 0xFF; + int hstrt = (diwstrt & 0xFF) << 2; + int hstop = (diwstop & 0xFF) << 2; int vstrt = diwstrt >> 8; int vstop = diwstop >> 8; - // vertical in ECS Agnus + // ECS Agnus/AGA: DIWHIGH vertical high bits. if (diwhigh_written && (currprefs.chipset_mask & CSMASK_ECS_AGNUS)) { vstrt |= (diwhigh & 7) << 8; vstop |= ((diwhigh >> 8) & 7) << 8; @@ -4993,19 +4983,24 @@ static void calcdiw (void) if ((vstop & 0x80) == 0) vstop |= 0x100; } - // horizontal in ECS Denise + // ECS Denise/AGA: horizontal DIWHIGH high bit. if (diwhigh_written && (currprefs.chipset_mask & CSMASK_ECS_DENISE)) { - hstrt |= ((diwhigh >> 5) & 1) << 8; - hstop |= ((diwhigh >> 13) & 1) << 8; + hstrt |= ((diwhigh >> 5) & 1) << (8 + 2); + hstop |= ((diwhigh >> 13) & 1) << (8 + 2); } else { - hstop += 0x100; + hstop |= 0x100 << 2; + } + // AGA only: horizontal DIWHIGH hires/shres bits. + if (currprefs.chipset_hr && diwhigh_written && (currprefs.chipset_mask & CSMASK_AGA)) { + hstrt |= (diwhigh >> 3) & 3; + hstop |= (diwhigh >> 11) & 3; } - diw_hstrt = hstrt; - diw_hstop = hstop; + diw_hstrt = hstrt >> 2; + diw_hstop = hstop >> 2; - diwfirstword = coord_diw_to_window_x (hstrt); - diwlastword = coord_diw_to_window_x (hstop); + diwfirstword = coord_diw_shres_to_window_x(hstrt); + diwlastword = coord_diw_shres_to_window_x(hstop); if (diwfirstword >= diwlastword) { diwfirstword = min_diwlastword; @@ -9571,13 +9566,13 @@ static void hsync_handler_post (bool onvsync) if (vpos >= first_planes_vpos && vpos <= last_planes_vpos) { if (diwlastword > diwlastword_total) { diwlastword_total = diwlastword; - if (diwlastword_total > coord_diw_to_window_x (hsyncstartpos * 2)) - diwlastword_total = coord_diw_to_window_x (hsyncstartpos * 2); + if (diwlastword_total > coord_diw_lores_to_window_x(hsyncstartpos * 2)) + diwlastword_total = coord_diw_lores_to_window_x(hsyncstartpos * 2); } if (diwfirstword < diwfirstword_total) { diwfirstword_total = diwfirstword; - if (diwfirstword_total < coord_diw_to_window_x (hsyncendpos * 2)) - diwfirstword_total = coord_diw_to_window_x (hsyncendpos * 2); + if (diwfirstword_total < coord_diw_lores_to_window_x(hsyncendpos * 2)) + diwfirstword_total = coord_diw_lores_to_window_x(hsyncendpos * 2); firstword_bplcon1 = bplcon1; } } diff --git a/drawing.cpp b/drawing.cpp index a75715ba..fd3c98e6 100644 --- a/drawing.cpp +++ b/drawing.cpp @@ -69,7 +69,7 @@ typedef enum extern int sprite_buffer_res; static int lores_factor; -int lores_shift; +int lores_shift, shres_shift; static void pfield_set_linetoscr(void); @@ -79,8 +79,10 @@ static void lores_set(int lores) { int old = lores_shift; lores_shift = lores; - if (lores_shift != old) + if (lores_shift != old) { + shres_shift = RES_MAX - lores; pfield_set_linetoscr(); + } } static void lores_reset (void) @@ -629,8 +631,8 @@ int get_custom_limits (int *pw, int *ph, int *pdx, int *pdy, int *prealh) ddflastword_total = coord_hw_to_window_x (ddflastword_total * 2 + DIW_DDF_OFFSET); if (doublescan <= 0 && !programmedmode) { - int min = coord_diw_to_window_x (92); - int max = coord_diw_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) @@ -841,7 +843,7 @@ STATIC_INLINE int get_shdelay_add(void) where do we start drawing the playfield, where do we start drawing the right border. All of these are forced into the visible window (VISIBLE_LEFT_BORDER .. VISIBLE_RIGHT_BORDER). PLAYFIELD_START and PLAYFIELD_END are in window coordinates. */ -static int playfield_start_pre; +static int playfield_start_pre, playfield_end_pre; static int playfield_start, playfield_end; static int real_playfield_start, real_playfield_end; static int sprite_playfield_start; @@ -1001,10 +1003,12 @@ static void pfield_init_linetoscr (bool border) } #endif - // AGA borderblank starts horizontally 1 hires pixel before bitplanes start, leaving 1 hires background color gap + // AGA borderblank starts horizontally 1 hires pixel before bitplanes start, leaving 1 hires pixel background color gap playfield_start_pre = playfield_start; - if (currprefs.chipset_hr && (currprefs.chipset_mask & CSMASK_AGA) && currprefs.gfx_resolution > 0) { - playfield_start_pre -= 2; + playfield_end_pre = playfield_end; + if (currprefs.chipset_hr && (currprefs.chipset_mask & CSMASK_AGA) && bplres > 0) { + playfield_start_pre -= bplres; + playfield_end_pre -= bplres; } unpainted = visible_left_border < playfield_start ? 0 : visible_left_border - playfield_start; @@ -2805,42 +2809,65 @@ static void do_color_changes (line_draw_func worker_border, line_draw_func worke lastpos = t; } + // normal if (playfield_start_pre >= playfield_start || !ce_is_borderblank(colors_for_drawing.extra)) { + // normal left border (hblank end to playfield start) if (nextpos_in_range > lastpos && lastpos < playfield_start) { int t = nextpos_in_range <= playfield_start ? nextpos_in_range : playfield_start; (*worker_border) (lastpos, t, 0); lastpos = t; } + + // playfield + if (nextpos_in_range > lastpos && lastpos >= playfield_start && lastpos < playfield_end) { + int t = nextpos_in_range <= playfield_end ? nextpos_in_range : playfield_end; + if ((plf2pri >= 5 || plf1pri >= 5) && !(currprefs.chipset_mask & CSMASK_AGA)) + weird_bitplane_fix(lastpos, t); + if (bplxor && may_require_hard_way && worker_pfield != pfield_do_linetoscr_bordersprite_aga) + playfield_hard_way(worker_pfield, lastpos, t); + else + (*worker_pfield) (lastpos, t, 0); + lastpos = t; + } + } else { + // special AGA borderblank 1 hires pixel delay + // borderblank left border (hblank end to playfield_start_pre) if (nextpos_in_range > lastpos && lastpos < playfield_start_pre) { int t = nextpos_in_range <= playfield_start_pre ? nextpos_in_range : playfield_start_pre; (*worker_border) (lastpos, t, 0); lastpos = t; } - // AGA "buggy" borderblank, real background color visible. + // AGA "buggy" borderblank, real background color visible, single hires pixel wide. if (nextpos_in_range > lastpos && lastpos < playfield_start) { int t = nextpos_in_range <= playfield_start ? nextpos_in_range : playfield_start; (*worker_border) (lastpos, t, -1); lastpos = t; } - } - // playfield - if (nextpos_in_range > lastpos && lastpos >= playfield_start && lastpos < playfield_end) { - int t = nextpos_in_range <= playfield_end ? nextpos_in_range : playfield_end; - if ((plf2pri >= 5 || plf1pri >= 5) && !(currprefs.chipset_mask & CSMASK_AGA)) - weird_bitplane_fix (lastpos, t); - if (bplxor && may_require_hard_way && worker_pfield != pfield_do_linetoscr_bordersprite_aga) - playfield_hard_way(worker_pfield, lastpos, t); - else - (*worker_pfield) (lastpos, t, 0); - lastpos = t; + // playfield with last hires pixel not drawn. + if (nextpos_in_range > lastpos && lastpos >= playfield_start && lastpos < playfield_end_pre) { + int t = nextpos_in_range <= playfield_end_pre ? nextpos_in_range : playfield_end_pre; + if (bplxor && may_require_hard_way && worker_pfield != pfield_do_linetoscr_bordersprite_aga) + playfield_hard_way(worker_pfield, lastpos, t); + else + (*worker_pfield) (lastpos, t, 0); + lastpos = t; + } + + // last 1 hires pixel of playfield blanked + if (nextpos_in_range > lastpos && lastpos >= playfield_end_pre && lastpos < playfield_end) { + int t = nextpos_in_range <= playfield_end ? nextpos_in_range : playfield_end; + (*worker_border) (lastpos, t, 0); + lastpos = t; + } + } // right border (playfield end to hblank start) - if (nextpos_in_range > lastpos && lastpos >= playfield_end) { + if (nextpos_in_range > lastpos && lastpos >= playfield_end_pre) { int t = nextpos_in_range <= hblank_right_stop ? nextpos_in_range : hblank_right_stop; (*worker_border) (lastpos, t, 0); lastpos = t; @@ -3110,6 +3137,7 @@ static void pfield_draw_line (struct vidbuffer *vb, int lineno, int gfx_ypos, in playfield_start = visible_right_border; playfield_end = visible_right_border; playfield_start_pre = playfield_start; + playfield_end_pre = playfield_end; do_color_changes (pfield_do_fill_line, pfield_do_fill_line, lineno); } diff --git a/include/drawing.h b/include/drawing.h index 5e35a8e6..1dce48aa 100644 --- a/include/drawing.h +++ b/include/drawing.h @@ -36,11 +36,13 @@ /* According to the HRM, pixel data spends a couple of cycles somewhere in the chips before it appears on-screen. (TW: display emulation now does this automatically) */ #define DIW_DDF_OFFSET 1 +#define DIW_DDF_OFFSET_SHRES (DIW_DDF_OFFSET << 2) /* this many cycles starting from hpos=0 are visible on right border */ #define HBLANK_OFFSET 9 /* We ignore that many lores pixels at the start of the display. These are * invisible anyway due to hardware DDF limits. */ #define DISPLAY_LEFT_SHIFT 0x38 +#define DISPLAY_LEFT_SHIFT_SHRES (DISPLAY_LEFT_SHIFT << 2) #endif #define PIXEL_XPOS(HPOS) (((HPOS)*2 - DISPLAY_LEFT_SHIFT + DIW_DDF_OFFSET - 1) << lores_shift) @@ -48,7 +50,7 @@ before it appears on-screen. (TW: display emulation now does this automatically) #define min_diwlastword (0) #define max_diwlastword (PIXEL_XPOS(0x1d4 >> 1)) -extern int lores_shift, interlace_seen; +extern int lores_shift, shres_shift, interlace_seen; extern bool aga_mode, direct_rgb; extern int visible_left_border, visible_right_border; extern int detected_screen_resolution; @@ -73,11 +75,16 @@ STATIC_INLINE int coord_window_to_hw_x (int x) return x + DISPLAY_LEFT_SHIFT; } -STATIC_INLINE int coord_diw_to_window_x (int x) +STATIC_INLINE int coord_diw_lores_to_window_x(int x) { return (x - DISPLAY_LEFT_SHIFT + DIW_DDF_OFFSET - 1) << lores_shift; } +STATIC_INLINE int coord_diw_shres_to_window_x (int x) +{ + return (x - DISPLAY_LEFT_SHIFT_SHRES + DIW_DDF_OFFSET_SHRES - (1 << 2)) >> shres_shift; +} + STATIC_INLINE int coord_window_to_diw_x (int x) { x = coord_window_to_hw_x (x); -- 2.47.3