From 13c6583889f7d2351aa89c775681bc3bf06d4af6 Mon Sep 17 00:00:00 2001 From: Toni Wilen Date: Mon, 17 Apr 2023 19:54:53 +0300 Subject: [PATCH] Chipset updates (ECS superhires sprites, BPLxDAT border open edge cases) --- custom.cpp | 35 +++++++----- drawing.cpp | 145 ++++++++++++++++++++++++++++++----------------- include/custom.h | 2 + 3 files changed, 115 insertions(+), 67 deletions(-) diff --git a/custom.cpp b/custom.cpp index 68519b3f..33d3c1fd 100644 --- a/custom.cpp +++ b/custom.cpp @@ -4262,7 +4262,9 @@ static void beginning_of_plane_block(int hpos) // do not mistake end of bitplane as start of low value hblank programmed mode if (bpl_shifter <= 0 && hpos > REFRESH_FIRST_HPOS) { - start_noborder(hpos + hpos_hsync_extra); + if (ecs_denise || (!ecs_denise && hpos >= OCS_DENISE_HBLANK_DISABLE_HPOS + 1)) { + start_noborder(hpos + hpos_hsync_extra); + } } hbstrt_bordercheck(hpos, true); @@ -4927,6 +4929,7 @@ static void update_fetch(int until, int fm) // Unrolled simple version of the for loop below. if (bprun && !line_cyclebased && dmacon_bpl && !ddf_stopping && plane0 + && (ecs_denise || hpos >= OCS_DENISE_HBLANK_DISABLE_HPOS) && !currprefs.chipset_hr #ifdef DEBUGGER && !debug_dma @@ -5171,6 +5174,10 @@ static bool isbrdblank(int hpos, uae_u16 bplcon0, uae_u16 bplcon3) return brdblank; } +static bool brdblankactive(void) +{ + return (bplcon0 & 1) && (bplcon3 & 0x20); +} static bool brdspractive(void) { @@ -5669,24 +5676,17 @@ static void calcsprite(void) sprite_minx = tospritexdiw(thisline_decision.diwfirstword); } if (thisline_decision.diwlastword >= 0) { - sprite_maxx = tospritexdiw(thisline_decision.diwfirstword); + sprite_maxx = tospritexdiw(thisline_decision.diwlastword); } if (thisline_decision.plfleft >= 0) { - int min, max; - min = tospritexddf(thisline_decision.plfleft); - max = tospritexddf(thisline_decision.plfright); + int min = tospritexddf(thisline_decision.plfleft); + int max = tospritexddf(thisline_decision.plfright); if (min > sprite_minx && min < max) { /* min < max = full line ddf */ - if (ecs_denise) { - sprite_minx = min; - } else { - if (thisline_decision.plfleft >= 0x28) { - sprite_minx = min; - } - } + sprite_minx = min; } /* sprites are visible from first BPL1DAT write to end of line * ECS Denise/AGA: no limits - * OCS Denise: BPL1DAT write only enables sprite if hpos >= 0x28 or so. + * OCS Denise: BPL1DAT write only enables sprite if hpos >= 0x2e (OCS_DENISE_HBLANK_DISABLE_HPOS). * (undocumented feature) */ } @@ -5739,6 +5739,11 @@ static void decide_sprites(int hpos, bool usepointx, bool quick) continue; } + // ECS Denise and superhires resolution: sprites 4 to 7 are disabled. + if (!aga_mode && ecs_denise && GET_RES_AGNUS(bplcon0) == RES_SUPERHIRES && i >= 4) { + continue; + } + if (s->ecs_denise_hires && (bplcon0d & 0x0040)) { xpos |= 2 >> (RES_MAX - sprite_buffer_res); sprxp = xpos; @@ -9130,7 +9135,8 @@ static void BPLxDAT_next(uae_u32 vv) } if (num == 0) { - if (ecs_denise || (!ecs_denise && hpos >= 0x2e)) { + // ECS/AGA: HSYNC start - 1: $0C is first possible. + if ((ecs_denise && hpos != hsyncstartpos_start_cycles - 1) || (!ecs_denise && hpos >= OCS_DENISE_HBLANK_DISABLE_HPOS)) { beginning_of_plane_block(hpos); bprun_pipeline_flush_delay = maxhpos; if (bplcon0_planes_changed) { @@ -11199,7 +11205,6 @@ static void do_sprite_fetch(int hpos, uae_u16 dat) sprite_fetch_full(s, hpos, slot, dmastate, &data, &data321, &data322); - int sprxp = s->xpos >> (sprite_buffer_res + 1); if (dmastate) { if (!slot) { SPRxDATA_1(data, num, hpos); diff --git a/drawing.cpp b/drawing.cpp index 4909cef5..7c11f33c 100644 --- a/drawing.cpp +++ b/drawing.cpp @@ -164,7 +164,7 @@ static uae_u32 clxtab[256]; xcolnr xcolors[4096]; struct spritepixelsbuf { - bool attach; + uae_u8 flags; uae_u8 stdata; uae_u16 stfmdata; uae_u16 data; @@ -1232,6 +1232,24 @@ static void pfield_init_linetoscr (bool border) // This means "bordersprite" condition is possible under OCS/ECS too. Argh! if (dip_for_drawing->nr_sprites) { + int gap = 0; + // OCS Denise: no "bordersprite" + if (aga_mode) { + // If AGA: "bordersprite" starts 0.5 lores pixels earlier + if (currprefs.chipset_hr) { + // 1 lores pixel + gap = 1 << lores_shift; + // 1 lores -> 1 hires but don't round to zero. + if (gap >= 2) { + gap /= 2; + } + } else { + gap = 1 << lores_shift; + } + } else if (ecs_denise) { + // If ECS Denise: "bordersprite" starts 1 lores pixel earlier + gap = 1 << lores_shift; + } 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) { @@ -1243,24 +1261,27 @@ static void pfield_init_linetoscr (bool border) } int plfleft = dp_for_drawing->plfleft - DDF_OFFSET; int left = coord_hw_to_window_x_lores(plfleft); - if (aga_mode) { - // If AGA: "bordersprite" starts 0.5 lores pixels earlier - if (currprefs.chipset_hr) { - left -= lores_shift > 0 ? 1 : 0; - } else { - left -= 1 << lores_shift; + int total = left - dp_for_drawing->diwfirstword; + if (total > 0 && gap > 0) { + if (gap > total) { + gap = total; } - } else if (ecs_denise) { - // If ECS Denise: "bordersprite" starts 1 lores pixel earlier - left -= 1 << lores_shift; + left -= gap; } - if (left < visible_left_border) + if (left < visible_left_border) { left = visible_left_border; + } if (left < playfield_start && left >= linetoscr_diw_start) { playfield_start = left; } + sprite_playfield_start = playfield_start; } else { - sprite_playfield_start = 0; + if (!ce_is_bordersprite(colors_for_drawing.extra)) { + bool early = ((dp_for_drawing->plfleft >> 1) & 1) != 0; + int plfleft = dp_for_drawing->plfleft - DDF_OFFSET + (early ? 1 * 2 : 0); + sprite_playfield_start = coord_hw_to_window_x_lores(plfleft); + sprite_playfield_start -= gap; + } if (playfield_end < linetoscr_diw_end && hblank_right_stop > playfield_end) { playfield_end = linetoscr_diw_end; } @@ -1778,7 +1799,7 @@ static uae_u8 render_sprites(int pos, int dualpf, uae_u8 apixel, int aga) plfmask = (plf_sprite_mask >> maskshift) >> maskshift; v &= ~plfmask; /* Extra 1 sprite pixel at DDFSTRT is only possible if at least 1 plane is active */ - if ((bplplanecnt > 0 || pos >= sprite_playfield_start) && (pos < sprite_end) && (v != 0 || SPRITE_DEBUG)) { + if (pos >= sprite_playfield_start && pos < sprite_end && (v != 0 || SPRITE_DEBUG)) { unsigned int vlo, vhi, col; unsigned int v1 = v & 255; /* OFFS determines the sprite pair with the highest priority that has @@ -1800,7 +1821,7 @@ static uae_u8 render_sprites(int pos, int dualpf, uae_u8 apixel, int aga) #if SPRITE_DEBUG > 0 v ^= 8; #endif - if (spb->attach && (spb->stdata & (3 << offs))) { + if ((spb->flags & 1) && (spb->stdata & (3 << offs))) { col = v; if (aga) col += sbasecol[1]; @@ -1848,27 +1869,43 @@ static uae_u8 render_sprites(int pos, int dualpf, uae_u8 apixel, int aga) #define PUTBPIX(x) buf[dpix] = (x); -STATIC_INLINE uae_u32 shsprite (int dpix, uae_u32 spix_val, uae_u32 v, int spr) +STATIC_INLINE uae_u32 shsprite(int dpix, uae_u32 spix_val, uae_u32 v, int add, int spr) { - uae_u8 sprcol; + uae_u8 sprcol1, sprcol2, off; uae_u16 scol; - if (!spr) - return v; - sprcol = render_sprites (dpix, 0, spix_val, 0); - if (!sprcol) + if (!spr) { return v; - /* good enough for now.. */ - scol = colors_for_drawing.color_regs_ecs[sprcol] & 0xccc; + } + dpix &= ~1; + struct spritepixelsbuf *spb = &spritepixels[dpix]; + int sdpix = dpix; + if (spb->flags & 2) { + sdpix -= add; + } + sprcol1 = render_sprites(sdpix, bpldualpf, spix_val, 0) & 3; + sprcol2 = render_sprites(sdpix + add, bpldualpf, spix_val, 0) & 3; + off = sprcol2 * 4 + sprcol1 + 16; + if ((dpix & add)) { + if (!sprcol2) { + return v; + } + scol = (colors_for_drawing.color_regs_ecs[off] & 0x333) << 2; + } else { + if (!sprcol1) { + return v; + } + scol = (colors_for_drawing.color_regs_ecs[off] & 0xccc) << 0; + } scol |= scol >> 2; return xcolors[scol]; } -static int NOINLINE linetoscr_16_sh_func(int spix, int dpix, int stoppos, int spr) +static int NOINLINE linetoscr_32_sh_func(int spix, int dpix, int stoppos, int spr) { - uae_u16 *buf = (uae_u16 *) xlinebuffer; + uae_u32 *buf = (uae_u32 *)xlinebuffer; while (dpix < stoppos) { - uae_u16 spix_val1, spix_val2; + uae_u32 spix_val1, spix_val2; uae_u16 v; int off; spix_val1 = pixdata.apixels[spix++]; @@ -1876,29 +1913,30 @@ static int NOINLINE linetoscr_16_sh_func(int spix, int dpix, int stoppos, int sp off = ((spix_val2 & 3) * 4) + (spix_val1 & 3) + ((spix_val1 | spix_val2) & 16); v = (colors_for_drawing.color_regs_ecs[off] & 0xccc) << 0; v |= v >> 2; - PUTBPIX(shsprite (dpix, spix_val1, xcolors[v], spr)); + PUTBPIX(shsprite(dpix, spix_val1, xcolors[v], 2, spr)); dpix++; v = (colors_for_drawing.color_regs_ecs[off] & 0x333) << 2; v |= v >> 2; - PUTBPIX(shsprite (dpix, spix_val2, xcolors[v], spr)); + PUTBPIX(shsprite(dpix, spix_val2, xcolors[v], 2, spr)); dpix++; } return spix; } -static int linetoscr_16_sh_spr(int spix, int dpix, int stoppos) +static int linetoscr_32_sh_spr(int spix, int dpix, int stoppos) { - return linetoscr_16_sh_func(spix, dpix, stoppos, true); + return linetoscr_32_sh_func(spix, dpix, stoppos, true); } -static int linetoscr_16_sh(int spix, int dpix, int stoppos) +static int linetoscr_32_sh(int spix, int dpix, int stoppos) { - return linetoscr_16_sh_func(spix, dpix, stoppos, false); + return linetoscr_32_sh_func(spix, dpix, stoppos, false); } -static int NOINLINE linetoscr_32_sh_func(int spix, int dpix, int stoppos, int spr) + +static int NOINLINE linetoscr_16_sh_func(int spix, int dpix, int stoppos, int spr) { - uae_u32 *buf = (uae_u32 *) xlinebuffer; + uae_u16 *buf = (uae_u16 *) xlinebuffer; while (dpix < stoppos) { - uae_u32 spix_val1, spix_val2; + uae_u16 spix_val1, spix_val2; uae_u16 v; int off; spix_val1 = pixdata.apixels[spix++]; @@ -1906,22 +1944,22 @@ static int NOINLINE linetoscr_32_sh_func(int spix, int dpix, int stoppos, int sp off = ((spix_val2 & 3) * 4) + (spix_val1 & 3) + ((spix_val1 | spix_val2) & 16); v = (colors_for_drawing.color_regs_ecs[off] & 0xccc) << 0; v |= v >> 2; - PUTBPIX(shsprite (dpix, spix_val1, xcolors[v], spr)); + PUTBPIX(shsprite (dpix, spix_val1, xcolors[v], 2, spr)); dpix++; v = (colors_for_drawing.color_regs_ecs[off] & 0x333) << 2; v |= v >> 2; - PUTBPIX(shsprite (dpix, spix_val2, xcolors[v], spr)); + PUTBPIX(shsprite (dpix, spix_val2, xcolors[v], 2, spr)); dpix++; } return spix; } -static int linetoscr_32_sh_spr(int spix, int dpix, int stoppos) +static int linetoscr_16_sh_spr(int spix, int dpix, int stoppos) { - return linetoscr_32_sh_func(spix, dpix, stoppos, true); + return linetoscr_16_sh_func(spix, dpix, stoppos, true); } -static int linetoscr_32_sh(int spix, int dpix, int stoppos) +static int linetoscr_16_sh(int spix, int dpix, int stoppos) { - return linetoscr_32_sh_func(spix, dpix, stoppos, false); + return linetoscr_16_sh_func(spix, dpix, stoppos, false); } static int NOINLINE linetoscr_32_shrink1_sh_func(int spix, int dpix, int stoppos, int spr) { @@ -1936,7 +1974,7 @@ static int NOINLINE linetoscr_32_shrink1_sh_func(int spix, int dpix, int stoppos off = ((spix_val2 & 3) * 4) + (spix_val1 & 3) + ((spix_val1 | spix_val2) & 16); v = (colors_for_drawing.color_regs_ecs[off] & 0xccc) << 0; v |= v >> 2; - PUTBPIX(shsprite (dpix, spix_val1, xcolors[v], spr)); + PUTBPIX(shsprite (dpix, spix_val1, xcolors[v], 1, spr)); dpix++; } return spix; @@ -1966,7 +2004,7 @@ static int NOINLINE linetoscr_32_shrink1f_sh_func(int spix, int dpix, int stoppo v = (colors_for_drawing.color_regs_ecs[off] & 0x333) << 2; v |= v >> 2; dpix_val2 = xcolors[v]; - PUTBPIX(shsprite (dpix, spix_val1, merge_2pixel32 (dpix_val1, dpix_val2), spr)); + PUTBPIX(shsprite (dpix, spix_val1, merge_2pixel32 (dpix_val1, dpix_val2), 1, spr)); dpix++; } return spix; @@ -1992,7 +2030,7 @@ static int NOINLINE linetoscr_16_shrink1_sh_func(int spix, int dpix, int stoppos off = ((spix_val2 & 3) * 4) + (spix_val1 & 3) + ((spix_val1 | spix_val2) & 16); v = (colors_for_drawing.color_regs_ecs[off] & 0xccc) << 0; v |= v >> 2; - PUTBPIX(shsprite (dpix, spix_val1, xcolors[v], spr)); + PUTBPIX(shsprite (dpix, spix_val1, xcolors[v], 1, spr)); dpix++; } return spix; @@ -2022,7 +2060,7 @@ static int NOINLINE linetoscr_16_shrink1f_sh_func(int spix, int dpix, int stoppo v = (colors_for_drawing.color_regs_ecs[off] & 0x333) << 2; v |= v >> 2; dpix_val2 = xcolors[v]; - PUTBPIX(shsprite (dpix, spix_val1, merge_2pixel16 (dpix_val1, dpix_val2), spr)); + PUTBPIX(shsprite (dpix, spix_val1, merge_2pixel16 (dpix_val1, dpix_val2), 1, spr)); dpix++; } return spix; @@ -2048,7 +2086,7 @@ static int NOINLINE linetoscr_32_shrink2_sh_func(int spix, int dpix, int stoppos off = ((spix_val2 & 3) * 4) + (spix_val1 & 3) + ((spix_val1 | spix_val2) & 16); v = (colors_for_drawing.color_regs_ecs[off] & 0xccc) << 0; v |= v >> 2; - PUTBPIX(shsprite (dpix, spix_val1, xcolors[v], spr)); + PUTBPIX(shsprite (dpix, spix_val1, xcolors[v], 1, spr)); spix+=2; dpix++; } @@ -2090,7 +2128,7 @@ static int NOINLINE linetoscr_32_shrink2f_sh_func(int spix, int dpix, int stoppo v |= v >> 2; dpix_val2 = xcolors[v]; dpix_val4 = merge_2pixel32 (dpix_val1, dpix_val2); - PUTBPIX(shsprite (dpix, spix_val1, merge_2pixel32 (dpix_val3, dpix_val4), spr)); + PUTBPIX(shsprite (dpix, spix_val1, merge_2pixel32 (dpix_val3, dpix_val4), 1, spr)); dpix++; } return spix; @@ -2116,7 +2154,7 @@ static int NOINLINE linetoscr_16_shrink2_sh_func(int spix, int dpix, int stoppos off = ((spix_val2 & 3) * 4) + (spix_val1 & 3) + ((spix_val1 | spix_val2) & 16); v = (colors_for_drawing.color_regs_ecs[off] & 0xccc) << 0; v |= v >> 2; - PUTBPIX(shsprite (dpix, spix_val1, xcolors[v], spr)); + PUTBPIX(shsprite (dpix, spix_val1, xcolors[v], 1, spr)); spix+=2; dpix++; } @@ -2158,7 +2196,7 @@ static int NOINLINE linetoscr_16_shrink2f_sh_func (int spix, int dpix, int stopp v |= v >> 2; dpix_val2 = xcolors[v]; dpix_val4 = merge_2pixel32 (dpix_val1, dpix_val2); - PUTBPIX(shsprite (dpix, spix_val1, merge_2pixel16 (dpix_val3, dpix_val4), spr)); + PUTBPIX(shsprite (dpix, spix_val1, merge_2pixel16 (dpix_val3, dpix_val4), 1, spr)); dpix++; } return spix; @@ -2798,10 +2836,13 @@ STATIC_INLINE void draw_sprites_1(struct sprite_entry *e, int dualpf, int has_at for (pos = epos; pos < emax; pos++, spr_pos++) { if (spr_pos >= 0 && spr_pos < MAX_PIXELS_PER_LINE) { - spritepixels[spr_pos].data = buf[pos]; - spritepixels[spr_pos].stdata = stbuf[pos]; - spritepixels[spr_pos].stfmdata = stfmbuf[pos]; - spritepixels[spr_pos].attach = has_attach; + struct spritepixelsbuf *sp = &spritepixels[spr_pos]; + sp->data = buf[pos]; + sp->stdata = stbuf[pos]; + sp->stfmdata = stfmbuf[pos]; + sp->flags = has_attach ? 1 : 0; + // ECS superhires sprite odd/even bit + sp->flags |= (pos & 2) ? 2 : 0; } } diff --git a/include/custom.h b/include/custom.h index 7a259709..9e298677 100644 --- a/include/custom.h +++ b/include/custom.h @@ -144,6 +144,8 @@ extern uae_u16 INTREQR(void); #define EQU_ENDLINE_PAL 8 #define EQU_ENDLINE_NTSC 10 +#define OCS_DENISE_HBLANK_DISABLE_HPOS 0x2d + extern int maxhpos, maxhposm0, maxhpos_short; extern int maxvpos, maxvpos_nom, maxvpos_display, maxvpos_display_vsync; extern int hsyncstartpos_hw, hsyncendpos_hw; -- 2.47.3