]> git.unchartedbackwaters.co.uk Git - francis/winuae.git/commitdiff
Chipset updates (ECS superhires sprites, BPLxDAT border open edge cases)
authorToni Wilen <twilen@winuae.net>
Mon, 17 Apr 2023 16:54:53 +0000 (19:54 +0300)
committerToni Wilen <twilen@winuae.net>
Mon, 17 Apr 2023 16:54:53 +0000 (19:54 +0300)
custom.cpp
drawing.cpp
include/custom.h

index 68519b3fdd191878bac367fc7e5ace02231dd34b..33d3c1fdea394d36ef44ddd6c81087544d049627 100644 (file)
@@ -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);
index 4909cef50347598907f3dbe7242afd566835af87..7c11f33c3362e0a37af6d1cee87b896e8fa1228b 100644 (file)
@@ -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;
                }
        }
 
index 7a25970920b1473b6b76e43500040e02deded7e3..9e2986774e97941a0cfebacfb038b78f8b8f7343 100644 (file)
@@ -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;