From: Toni Wilen Date: Thu, 10 Dec 2015 15:43:24 +0000 (+0200) Subject: AGA subpixel bitplane delay support rewritten. X-Git-Tag: 3220~22 X-Git-Url: https://git.unchartedbackwaters.co.uk/w/?a=commitdiff_plain;h=3313d6123d187230f0d9adc1d9e331ab227d1495;p=francis%2Fwinuae.git AGA subpixel bitplane delay support rewritten. --- diff --git a/custom.cpp b/custom.cpp index fd9dc961..00266f80 100644 --- a/custom.cpp +++ b/custom.cpp @@ -1723,6 +1723,27 @@ STATIC_INLINE void flush_display (int fm) toscr_nbits = 0; } +static void record_color_change(int hpos, int regno, unsigned long value); + +static void hack_shres_delay(int hpos) +{ + if (!(currprefs.chipset_mask & CSMASK_AGA) && !toscr_delay_sh[0] && !toscr_delay_sh[1]) + return; + int o0 = toscr_delay_sh[0]; + int o1 = toscr_delay_sh[1]; + int shdelay1 = (bplcon1 >> 8) & 3; + int shdelay2 = (bplcon1 >> 12) & 3; + toscr_delay_sh[0] = (shdelay1 & 3) >> toscr_res; + toscr_delay_sh[1] = (shdelay2 & 3) >> toscr_res; + if (hpos >= 0 && toscr_delay_sh[0] != o0 || toscr_delay_sh[1] != o1) { + record_color_change(hpos, 0, COLOR_CHANGE_SHRES_DELAY | toscr_delay_sh[0]); + current_colors.extra &= ~(1 << CE_SHRES_DELAY); + current_colors.extra &= ~(1 << (CE_SHRES_DELAY + 1)); + current_colors.extra |= toscr_delay_sh[0] << CE_SHRES_DELAY; + remembered_color_entry = -1; + } +} + static void update_denise_shifter_planes (int hpos) { int np = GET_PLANES (bplcon0d); @@ -1768,6 +1789,7 @@ static void update_denise (int hpos) toscr_nr_planes2 = toscr_nr_planes; } toscr_nr_planes_shifter = toscr_nr_planes2; + hack_shres_delay(hpos); } STATIC_INLINE void fetch_start (int hpos) @@ -2945,16 +2967,17 @@ static bool isbrdblank (int hpos, uae_u16 bplcon0, uae_u16 bplcon3) brdblank = false; brdntrans = false; #endif - if (hpos >= 0 && (current_colors.borderblank != brdblank || current_colors.borderntrans != brdntrans)) { - record_color_change (hpos, 0, COLOR_CHANGE_BRDBLANK | (brdblank ? 1 : 0) | (current_colors.bordersprite ? 2 : 0) | (brdntrans ? 4 : 0)); - current_colors.borderblank = brdblank; - current_colors.borderntrans = brdntrans; + if (hpos >= 0 && (ce_is_borderblank(current_colors.extra) != brdblank || ce_is_borderntrans(current_colors.extra) != brdntrans)) { + record_color_change (hpos, 0, COLOR_CHANGE_BRDBLANK | (brdblank ? 1 : 0) | (ce_is_bordersprite(current_colors.extra) ? 2 : 0) | (brdntrans ? 4 : 0)); + current_colors.extra &= ~(1 << CE_BORDERBLANK); + current_colors.extra &= ~(1 << CE_BORDERNTRANS); + current_colors.extra |= brdblank ? (1 << CE_BORDERBLANK) : 0; + current_colors.extra |= brdntrans ? (1 << CE_BORDERNTRANS) : 0; remembered_color_entry = -1; } return brdblank; } - static bool issprbrd (int hpos, uae_u16 bplcon0, uae_u16 bplcon3) { bool brdsprt; @@ -2963,14 +2986,15 @@ static bool issprbrd (int hpos, uae_u16 bplcon0, uae_u16 bplcon3) #else brdsprt = false; #endif - if (hpos >= 0 && current_colors.bordersprite != brdsprt) { - record_color_change (hpos, 0, COLOR_CHANGE_BRDBLANK | (current_colors.borderblank ? 1 : 0) | (current_colors.borderntrans ? 4 : 0) | (brdsprt ? 2 : 0)); - current_colors.bordersprite = brdsprt; + if (hpos >= 0 && ce_is_bordersprite(current_colors.extra) != brdsprt) { + record_color_change (hpos, 0, COLOR_CHANGE_BRDBLANK | (ce_is_borderblank(current_colors.extra) ? 1 : 0) | (ce_is_borderntrans(current_colors.extra) ? 4 : 0) | (brdsprt ? 2 : 0)); + current_colors.extra &= ~(1 << CE_BORDERSPRITE); + current_colors.extra |= brdsprt ? (1 << CE_BORDERSPRITE) : 0; remembered_color_entry = -1; - if (brdsprt && !current_colors.borderblank) + if (brdsprt && !ce_is_borderblank(current_colors.extra)) thisline_decision.bordersprite_seen = true; } - return brdsprt && !current_colors.borderblank; + return brdsprt && !ce_is_borderblank(current_colors.extra); } static void record_register_change (int hpos, int regno, uae_u16 value) @@ -5278,17 +5302,6 @@ static void BPLCON0 (int hpos, uae_u16 v) BPLCON0_Denise (hpos, v, true); } -static void hack_bplcon2(void) -{ - // AGA subpixel scrolling in lores/hires modes - int shdelay1 = (bplcon1 >> 8) & 3; - int shdelay2 = (bplcon1 >> 12) & 3; - toscr_delay_sh[0] = (shdelay1 & 3) >> toscr_res; - toscr_delay_sh[1] = (shdelay2 & 3) >> toscr_res; - bplcon2 &= ~0xc000; - bplcon2 |= toscr_delay_sh[0] << 14; -} - static void BPLCON1 (int hpos, uae_u16 v) { if (!(currprefs.chipset_mask & CSMASK_AGA)) @@ -5300,16 +5313,7 @@ static void BPLCON1 (int hpos, uae_u16 v) decide_fetch_safe (hpos); bplcon1_written = true; bplcon1 = v; - - if (currprefs.chipset_mask & CSMASK_AGA) { - int o0 = toscr_delay_sh[0]; - int o1 = toscr_delay_sh[1]; - hack_bplcon2(); - if (toscr_delay_sh[0] != o0 || toscr_delay_sh[1] != o1) { - // HACK: Use BPLCON2 unused bits to store sh shift - record_register_change(hpos, 0x104, bplcon2); - } - } + hack_shres_delay(hpos); } static void BPLCON2(int hpos, uae_u16 v) @@ -5320,8 +5324,6 @@ static void BPLCON2(int hpos, uae_u16 v) return; decide_line (hpos); bplcon2 = v; - if (currprefs.chipset_mask & CSMASK_AGA) - hack_bplcon2(); record_register_change (hpos, 0x104, bplcon2); } @@ -8411,6 +8413,8 @@ void custom_reset (bool hardreset, bool keyboardreset) sprite_entries[1][1].first_pixel = MAX_SPR_PIXELS; memset (spixels, 0, 2 * MAX_SPR_PIXELS * sizeof *spixels); memset (&spixstate, 0, sizeof spixstate); + toscr_delay_sh[0] = 0; + toscr_delay_sh[1] = 0; cop_state.state = COP_stop; cop_state.movedelay = 0; @@ -9225,10 +9229,17 @@ uae_u8 *restore_custom (uae_u8 *src) i = RW; /* 1FA ? */ if (i & 0x8000) currprefs.ntscmode = changed_prefs.ntscmode = i & 1; - fmode = RW; /* 1FC FMODE */ + fmode = fmode_saved = RW; /* 1FC FMODE */ last_custom_value1 = RW;/* 1FE ? */ - current_colors.borderblank = isbrdblank (-1, bplcon0, bplcon3); + current_colors.extra = 0; + if (isbrdblank (-1, bplcon0, bplcon3)) + current_colors.extra |= 1 << CE_BORDERBLANK; + if (issprbrd(-1, bplcon0, bplcon3)) + current_colors.extra |= 1 << CE_BORDERSPRITE; + if ((currprefs.chipset_mask & CSMASK_ECS_DENISE) && (bplcon0 & 1) && (bplcon3 & 0x10)) + current_colors.extra |= 1 << CE_BORDERNTRANS; + DISK_restore_custom (dskpt, dsklen, dskbytr); return src; diff --git a/drawing.cpp b/drawing.cpp index d618bd2e..3ff4eed2 100644 --- a/drawing.cpp +++ b/drawing.cpp @@ -243,7 +243,6 @@ static int bplehb, bplham, bpldualpf, bpldualpfpri, bpldualpf2of, bplplanecnt, e static bool issprites; static int bplres; static int plf1pri, plf2pri, bplxor, bpldelay_sh; -static bool enabled_sh; static uae_u32 plf_sprite_mask; static int sbasecol[2] = { 16, 16 }; static int hposblank; @@ -830,7 +829,7 @@ STATIC_INLINE xcolnr getbgc (bool blank) //return colors_for_drawing.acolors[0]; return xcolors[0xf0f]; #endif - return (blank || hposblank || colors_for_drawing.borderblank) ? 0 : colors_for_drawing.acolors[0]; + return (blank || hposblank || ce_is_borderblank(colors_for_drawing.extra)) ? 0 : colors_for_drawing.acolors[0]; } @@ -902,7 +901,7 @@ static void pfield_init_linetoscr (bool border) // before first bitplane pixel appears. // This means "bordersprite" condition is possible under OCS/ECS too. Argh! if (dip_for_drawing->nr_sprites) { - if (!colors_for_drawing.borderblank) { + if (!ce_is_borderblank(colors_for_drawing.extra)) { /* bordersprite off or not supported: sprites are visible until diw_end */ if (playfield_end < linetoscr_diw_end && hblank_right_stop > playfield_end) { playfield_end = linetoscr_diw_end; @@ -923,7 +922,7 @@ static void pfield_init_linetoscr (bool border) #ifdef AGA may_require_hard_way = false; - if (dp_for_drawing->bordersprite_seen && !colors_for_drawing.borderblank && dip_for_drawing->nr_sprites) { + if (dp_for_drawing->bordersprite_seen && !ce_is_borderblank(colors_for_drawing.extra) && dip_for_drawing->nr_sprites) { int min = visible_right_border, max = visible_left_border, i; for (i = 0; i < dip_for_drawing->nr_sprites; i++) { int x; @@ -957,7 +956,7 @@ static void pfield_init_linetoscr (bool border) int first_x = sprite_first_x; int last_x = sprite_last_x; if (first_x < last_x) { - if (dp_for_drawing->bordersprite_seen && !colors_for_drawing.borderblank) { + if (dp_for_drawing->bordersprite_seen && !ce_is_borderblank(colors_for_drawing.extra)) { if (first_x > visible_left_border) first_x = visible_left_border; if (last_x < visible_right_border) @@ -1276,7 +1275,7 @@ static uae_u8 render_sprites (int pos, int dualpf, uae_u8 apixel, int aga) static bool get_genlock_very_rare_and_complex_case(uae_u8 v) { // border color without BRDNTRAN bit set = transparent - if (v == 0 && !colors_for_drawing.borderntrans) + if (v == 0 && !ce_is_borderntrans(colors_for_drawing.extra)) return false; if (ecs_genlock_features_colorkey) { // color key match? @@ -1666,6 +1665,10 @@ static int pfield_do_linetoscr_normal_shdelay(int spix, int dpix, int dpix_end) { int add = get_shdelay_add(); int add2 = add * gfxvidinfo.drawbuffer.pixbytes; + if (add) { + // Clear skipped pixel(s). + pfield_do_linetoscr_shdelay_sprite(spix, dpix, dpix + add); + } xlinebuffer += add2; int out = pfield_do_linetoscr_shdelay_normal(spix, dpix, dpix_end); xlinebuffer -= add2; @@ -1673,12 +1676,28 @@ static int pfield_do_linetoscr_normal_shdelay(int spix, int dpix, int dpix_end) } static int pfield_do_linetoscr_sprite_shdelay(int spix, int dpix, int dpix_end) { + int out = spix; + if (dpix < real_playfield_start && dpix_end > real_playfield_start) { + // Crosses real_playfield_start. + // Render only from dpix to real_playfield_start. + int len = real_playfield_start - dpix; + out = pfield_do_linetoscr_spriteonly(out, dpix, dpix + len); + dpix = real_playfield_start; + } else if (dpix_end <= real_playfield_start) { + // Does not cross real_playfield_start, nothing special needed. + out = pfield_do_linetoscr_spriteonly(out, dpix, dpix_end); + return out; + } + // Render bitplane with subpixel scroll, from real_playfield_start to end. int add = get_shdelay_add(); int add2 = add * gfxvidinfo.drawbuffer.pixbytes; + if (add) { + pfield_do_linetoscr_shdelay_sprite(out, dpix, dpix + add); + } sprite_shdelay = add; spritepixels += add; xlinebuffer += add2; - int out = pfield_do_linetoscr_shdelay_sprite(spix, dpix, dpix_end); + out = pfield_do_linetoscr_shdelay_sprite(out, dpix, dpix_end); xlinebuffer -= add2; spritepixels -= add; sprite_shdelay = 0; @@ -1688,7 +1707,6 @@ static int pfield_do_linetoscr_sprite_shdelay(int spix, int dpix, int dpix_end) static void pfield_set_linetoscr (void) { xlinecheck(start, stop); - enabled_sh = false; spritepixels = spritepixels_buffer; pfield_do_linetoscr_spriteonly = pfield_do_nothing; #ifdef AGA @@ -1794,7 +1812,6 @@ static void pfield_set_linetoscr (void) pfield_do_linetoscr_shdelay_sprite = pfield_do_linetoscr_sprite; pfield_do_linetoscr_normal = pfield_do_linetoscr_normal_shdelay; pfield_do_linetoscr_sprite = pfield_do_linetoscr_sprite_shdelay; - enabled_sh = true; } } #endif @@ -1932,7 +1949,7 @@ static void pfield_do_linetoscr_bordersprite_aga (int start, int stop, bool blan pfield_do_fill_line (start, stop, blank); return; } - src_pixel = pfield_do_linetoscr_spriteonly(src_pixel, start, stop); + pfield_do_linetoscr_spriteonly(src_pixel, start, stop); } static void dummy_worker (int start, int stop, bool blank) @@ -2564,12 +2581,13 @@ static void pfield_expand_dp_bplcon (void) sbasecol[0] = ((dp_for_drawing->bplcon4 >> 4) & 15) << 4; sbasecol[1] = ((dp_for_drawing->bplcon4 >> 0) & 15) << 4; bplxor = dp_for_drawing->bplcon4 >> 8; - int obpldelay_sh = bpldelay_sh; - bpldelay_sh = dp_for_drawing->bplcon2 >> 14; - if ((bpldelay_sh && !obpldelay_sh) || (!bpldelay_sh && obpldelay_sh)) + int sh = (colors_for_drawing.extra >> CE_SHRES_DELAY) & 3; + if (sh != bpldelay_sh) { + bpldelay_sh = sh; pfield_mode_changed = true; + } #endif - ecs_genlock_features_active = (currprefs.chipset_mask & CSMASK_ECS_DENISE) && ((dp_for_drawing->bplcon2 & 0x0c00) || colors_for_drawing.borderntrans) ? 1 : 0; + ecs_genlock_features_active = (currprefs.chipset_mask & CSMASK_ECS_DENISE) && ((dp_for_drawing->bplcon2 & 0x0c00) || ce_is_borderntrans(colors_for_drawing.extra)) ? 1 : 0; if (ecs_genlock_features_active) { ecs_genlock_features_colorkey = false; ecs_genlock_features_mask = 0; @@ -2650,8 +2668,7 @@ static void adjust_drawing_colors (int ctable, int need_full) } else { memcpy (colors_for_drawing.acolors, curr_color_tables[ctable].acolors, sizeof colors_for_drawing.acolors); - colors_for_drawing.borderblank = curr_color_tables[ctable].borderblank; - colors_for_drawing.bordersprite = curr_color_tables[ctable].bordersprite; + colors_for_drawing.extra = curr_color_tables[ctable].extra; color_match_type = color_match_acolors; } drawing_color_matches = ctable; @@ -2742,9 +2759,17 @@ static void do_color_changes (line_draw_func worker_border, line_draw_func worke pfield_expand_dp_bplconx (regno, value); } else if (regno >= 0) { if (regno == 0 && (value & COLOR_CHANGE_BRDBLANK)) { - colors_for_drawing.borderblank = (value & 1) != 0; - colors_for_drawing.bordersprite = (value & 3) == 2; - colors_for_drawing.borderntrans = (value & 5) == 4; + colors_for_drawing.extra &= ~(1 << CE_BORDERBLANK); + colors_for_drawing.extra &= ~(1 << CE_BORDERNTRANS); + colors_for_drawing.extra &= ~(1 << CE_BORDERSPRITE); + colors_for_drawing.extra |= (value & 1) != 0 ? (1 << CE_BORDERBLANK) : 0; + colors_for_drawing.extra |= (value & 3) == 2 ? (1 << CE_BORDERSPRITE) : 0; + colors_for_drawing.extra |= (value & 5) == 4 ? (1 << CE_BORDERNTRANS) : 0; + } else if (regno == 0 && (value & COLOR_CHANGE_SHRES_DELAY)) { + colors_for_drawing.extra &= ~(1 << CE_SHRES_DELAY); + colors_for_drawing.extra &= ~(1 << (CE_SHRES_DELAY + 1)); + colors_for_drawing.extra |= (value & 3) << CE_SHRES_DELAY; + pfield_expand_dp_bplcon(); } else { color_reg_set (&colors_for_drawing, regno, value); colors_for_drawing.acolors[regno] = getxcolor (value); @@ -2873,7 +2898,7 @@ static void pfield_draw_line (struct vidbuffer *vb, int lineno, int gfx_ypos, in if (dip_for_drawing->nr_sprites) { int i; #ifdef AGA - if (colors_for_drawing.bordersprite && dp_for_drawing->bordersprite_seen && !colors_for_drawing.borderblank) + if (ce_is_bordersprite(colors_for_drawing.extra) && dp_for_drawing->bordersprite_seen && !ce_is_borderblank(colors_for_drawing.extra)) clear_bitplane_border_aga (); #endif @@ -2888,7 +2913,7 @@ static void pfield_draw_line (struct vidbuffer *vb, int lineno, int gfx_ypos, in } #ifdef AGA - if (dip_for_drawing->nr_sprites && colors_for_drawing.bordersprite && !colors_for_drawing.borderblank && dp_for_drawing->bordersprite_seen) + if (dip_for_drawing->nr_sprites && ce_is_bordersprite(colors_for_drawing.extra) && !ce_is_borderblank(colors_for_drawing.extra) && dp_for_drawing->bordersprite_seen) do_color_changes (pfield_do_linetoscr_bordersprite_aga, pfield_do_linetoscr_spr, lineno); else #endif @@ -2918,7 +2943,7 @@ static void pfield_draw_line (struct vidbuffer *vb, int lineno, int gfx_ypos, in adjust_drawing_colors (dp_for_drawing->ctable, 0); #ifdef AGA /* this makes things complex.. */ - if (dp_for_drawing->bordersprite_seen && !colors_for_drawing.borderblank && dip_for_drawing->nr_sprites) { + if (dp_for_drawing->bordersprite_seen && !ce_is_borderblank(colors_for_drawing.extra) && dip_for_drawing->nr_sprites) { dosprites = true; pfield_expand_dp_bplcon (); pfield_init_linetoscr (true); diff --git a/genlinetoscr.cpp b/genlinetoscr.cpp index 05695b4f..43f40f5a 100644 --- a/genlinetoscr.cpp +++ b/genlinetoscr.cpp @@ -190,8 +190,10 @@ static void out_linetoscr_do_dstpix (DEPTH_T bpp, HMODE_T hmode, int aga, CMODE_ static void out_linetoscr_do_incspix (DEPTH_T bpp, HMODE_T hmode, int aga, CMODE_T cmode, int spr) { - if (spr < 0) + if (spr < 0) { + outln(" spix++;"); return; + } if (hmode == HMODE_HALVE1F) { outln ( " {"); outln ( " uae_u32 tmp_val;"); diff --git a/include/drawing.h b/include/drawing.h index a7863bc6..9f25ef44 100644 --- a/include/drawing.h +++ b/include/drawing.h @@ -83,6 +83,24 @@ extern int custom_frame_redraw_necessary; * * !!! See color_reg_xxx functions below before touching !!! */ +#define CE_BORDERBLANK 0 +#define CE_BORDERNTRANS 1 +#define CE_BORDERSPRITE 2 +#define CE_SHRES_DELAY 4 + +STATIC_INLINE bool ce_is_borderblank(uae_u8 data) +{ + return (data & (1 << CE_BORDERBLANK)) != 0; +} +STATIC_INLINE bool ce_is_bordersprite(uae_u8 data) +{ + return (data & (1 << CE_BORDERSPRITE)) != 0; +} +STATIC_INLINE bool ce_is_borderntrans(uae_u8 data) +{ + return (data & (1 << CE_BORDERNTRANS)) != 0; +} + struct color_entry { uae_u16 color_regs_ecs[32]; #ifndef AGA @@ -91,7 +109,7 @@ struct color_entry { xcolnr acolors[256]; uae_u32 color_regs_aga[256]; #endif - bool borderblank, borderntrans, bordersprite; + uae_u8 extra; }; #ifdef AGA @@ -146,14 +164,14 @@ STATIC_INLINE int color_reg_cmp (struct color_entry *ce1, struct color_entry *ce else #endif v = memcmp (ce1->color_regs_ecs, ce2->color_regs_ecs, sizeof (uae_u16) * 32); - if (!v && ce1->borderblank == ce2->borderblank) + if (!v && ce1->extra == ce2->extra) return 0; return 1; } /* ugly copy hack, is there better solution? */ STATIC_INLINE void color_reg_cpy (struct color_entry *dst, struct color_entry *src) { - dst->borderblank = src->borderblank; + dst->extra = src->extra; #ifdef AGA if (aga_mode) /* copy acolors and color_regs_aga */ @@ -174,6 +192,7 @@ STATIC_INLINE void color_reg_cpy (struct color_entry *dst, struct color_entry *s */ #define COLOR_CHANGE_BRDBLANK 0x80000000 +#define COLOR_CHANGE_SHRES_DELAY 0x40000000 struct color_change { int linepos; int regno;