]> git.unchartedbackwaters.co.uk Git - francis/winuae.git/commitdiff
Implement AGA 32/64-pixel wide sprite undocumented size behavior when FMODE is changed.
authorToni Wilen <twilen@winuae.net>
Sat, 6 Oct 2018 15:40:56 +0000 (18:40 +0300)
committerToni Wilen <twilen@winuae.net>
Sat, 6 Oct 2018 15:40:56 +0000 (18:40 +0300)
custom.cpp
drawing.cpp
include/drawing.h

index 7e9085fa15f42545b36b9779527d238dff5cc864..e82f44e0f9ae3a87362cb9adef16dc990a819ac9 100644 (file)
@@ -150,6 +150,7 @@ static bool graphicsbuffer_retry;
 static int scanlinecount;
 static int cia_hsync;
 static bool toscr_scanline_complex_bplcon1;
+static bool spr_width_64_seen;
 
 #define LOF_TOGGLES_NEEDED 3
 //#define NLACE_CNT_NEEDED 50
@@ -233,6 +234,14 @@ struct sprite {
        int ptxhpos;
        int ptxhpos2, ptxvpos2;
        bool ignoreverticaluntilnextline;
+       int width;
+
+       uae_u16 ctl, pos;
+#ifdef AGA
+       uae_u16 data[4], datb[4];
+#else
+       uae_u16 data[1], datb[1];
+#endif
 };
 
 static struct sprite spr[MAX_SPRITES];
@@ -246,13 +255,6 @@ static uae_u8 magic_sprite_mask = 0xff;
 
 static int sprite_vblank_endline = VBLANK_SPRITE_PAL;
 
-static uae_u16 sprctl[MAX_SPRITES], sprpos[MAX_SPRITES];
-#ifdef AGA
-static uae_u16 sprdata[MAX_SPRITES][4], sprdatb[MAX_SPRITES][4];
-#else
-static uae_u16 sprdata[MAX_SPRITES][1], sprdatb[MAX_SPRITES][1];
-#endif
-static int sprite_last_drawn_at[MAX_SPRITES];
 static int last_sprite_point, nr_armed;
 static int sprite_width, sprres;
 static int sprite_sprctlmask;
@@ -858,6 +860,7 @@ static void finish_playfield_line (void)
 #endif
 #ifdef AGA
                || line_decisions[next_lineno].bplcon4 != thisline_decision.bplcon4
+               || line_decisions[next_lineno].fmode != thisline_decision.fmode
 #endif
                )
 #endif /* SMART_UPDATE */
@@ -3882,12 +3885,12 @@ superhires pixels (if AGA).  */
 static void record_sprite (int line, int num, int sprxp, uae_u16 *data, uae_u16 *datb, unsigned int ctl)
 {
        struct sprite_entry *e = curr_sprite_entries + next_sprite_entry;
-       int i;
        int word_offs;
        uae_u32 collision_mask;
        int width, dbl, half;
        unsigned int mask = 0;
        int attachment;
+       int spr_width;
 
        half = 0;
        dbl = sprite_buffer_res - sprres;
@@ -3896,11 +3899,13 @@ static void record_sprite (int line, int num, int sprxp, uae_u16 *data, uae_u16
                dbl = 0;
                mask = 1 << half;
        }
-       width = (sprite_width << sprite_buffer_res) >> sprres;
-       attachment = sprctl[num | 1] & 0x80;
+       spr_width = spr[num].width;
+       width = (spr_width << sprite_buffer_res) >> sprres;
+       attachment = spr[num | 1].ctl & 0x80;
 
        /* Try to coalesce entries if they aren't too far apart  */
-       if (!next_sprite_forced && e[-1].max + sprite_width >= sprxp) {
+       /* Don't coelesce 64-bit wide sprites, needed to support FMODE change tricks */
+       if (!next_sprite_forced && e[-1].max + spr_width >= sprxp) {
                e--;
        } else {
                next_sprite_entry++;
@@ -3918,7 +3923,7 @@ static void record_sprite (int line, int num, int sprxp, uae_u16 *data, uae_u16
        collision_mask = clxmask[clxcon >> 12];
        word_offs = e->first_pixel + sprxp - e->pos;
 
-       for (i = 0; i < sprite_width; i += 16) {
+       for (int i = 0; i < spr_width; i += 16) {
                unsigned int da = *data;
                unsigned int db = *datb;
                uae_u32 datab = ((sprtaba[da & 0xFF] << 16) | sprtaba[da >> 8]
@@ -3937,8 +3942,8 @@ static void record_sprite (int line, int num, int sprxp, uae_u16 *data, uae_u16
        low order bit records whether the attach bit was set for this pair.  */
        if (attachment && !ecsshres ()) {
                uae_u32 state = 0x01010101 << (num & ~1);
-               uae_u8 *stb1 = spixstate.bytes + word_offs;
-               for (i = 0; i < width; i += 8) {
+               uae_u8 *stb1 = spixstate.stb + word_offs;
+               for (int i = 0; i < width; i += 8) {
                        stb1[0] |= state;
                        stb1[1] |= state;
                        stb1[2] |= state;
@@ -3951,6 +3956,25 @@ static void record_sprite (int line, int num, int sprxp, uae_u16 *data, uae_u16
                }
                e->has_attached = 1;
        }
+       /* 64 pixel wide sprites' first 32 pixels work differently than
+        * last 32 pixels if FMODE is changed when sprite is being drawn
+        */
+       if (spr_width == 64) {
+               uae_u16 *stbfm = spixstate.stbfm + word_offs;
+               uae_u16 state = (3 << (2 * num));
+               for (int i = 0; i < width / 2; i += 8) {
+                       stbfm[0] |= state;
+                       stbfm[1] |= state;
+                       stbfm[2] |= state;
+                       stbfm[3] |= state;
+                       stbfm[4] |= state;
+                       stbfm[5] |= state;
+                       stbfm[6] |= state;
+                       stbfm[7] |= state;
+                       stbfm += 8;
+               }
+               spr_width_64_seen = true;
+       }
 }
 
 static void add_sprite (int *countp, int num, int sprxp, int posns[], int nrs[])
@@ -4021,7 +4045,6 @@ static void decide_sprites(int spnr, int hpos, bool usepointx, bool quick)
        int nrs[MAX_SPRITES * 2], posns[MAX_SPRITES * 2];
        int count, i;
        int point;
-       int width = sprite_width;
        int sscanmask = 0x100 << sprite_buffer_res;
        int gotdata = 0;
        int startnr = 0, endnr = MAX_SPRITES - 1;
@@ -4050,10 +4073,11 @@ static void decide_sprites(int spnr, int hpos, bool usepointx, bool quick)
 
        count = 0;
        for (i = startnr; i <= endnr; i++) {
+               struct sprite *s = &spr[i];
                int xpos = spr[i].xpos;
                int sprxp = (fmode & 0x8000) ? (xpos & ~sscanmask) : xpos;
                int hw_xp = sprxp >> sprite_buffer_res;
-               int pointx = usepointx && (sprctl[i] & sprite_sprctlmask) ? 0 : 1;
+               int pointx = usepointx && (s->ctl & sprite_sprctlmask) ? 0 : 1;
 
                if (xpos < 0)
                        continue;
@@ -4088,14 +4112,15 @@ static void decide_sprites(int spnr, int hpos, bool usepointx, bool quick)
 
        for (i = 0; i < count; i++) {
                int nr = nrs[i] & (MAX_SPRITES - 1);
-               record_sprite (next_lineno, nr, posns[i], sprdata[nr], sprdatb[nr], sprctl[nr]);
+               struct sprite *s = &spr[nr];
+               record_sprite (next_lineno, nr, posns[i], s->data, s->datb, s->ctl);
                /* get left and right sprite edge if brdsprt enabled */
 #if AUTOSCALE_SPRITES
                if (dmaen (DMA_SPRITE) && (bplcon0 & 1) && (bplcon3 & 0x02) && !(bplcon3 & 0x20) && nr > 0) {
                        int j, jj;
                        for (j = 0, jj = 0; j < sprite_width; j+= 16, jj++) {
                                int nx = fromspritexdiw (posns[i] + j);
-                               if (sprdata[nr][jj] || sprdatb[nr][jj]) {
+                               if (s->data[jj] || s->datb[jj]) {
                                        if (diwfirstword_total > nx && nx >= (48 << currprefs.gfx_resolution))
                                                diwfirstword_total = nx;
                                        if (diwlastword_total < nx + 16 && nx <= (448 << currprefs.gfx_resolution))
@@ -4128,9 +4153,10 @@ static void decide_sprites(int spnr, int hpos)
 }
 static void maybe_decide_sprites(int spnr, int hpos)
 {
-       if (!spr[spnr].armed)
+       struct sprite *s = &spr[spnr];
+       if (!s->armed)
                return;
-       if (!sprdata[spnr] && !sprdatb[spnr])
+       if (!s->data && !s->datb)
                return;
        decide_sprites(spnr, hpos, true, true);
 }
@@ -4160,7 +4186,7 @@ static int sprites_differ (struct draw_info *dip, struct draw_info *dip_old)
        if (memcmp (spixels + this_first->first_pixel, spixels + prev_first->first_pixel,
                npixels * sizeof (uae_u16)) != 0)
                return 1;
-       if (memcmp (spixstate.bytes + this_first->first_pixel, spixstate.bytes + prev_first->first_pixel, npixels) != 0)
+       if (memcmp (spixstate.stb + this_first->first_pixel, spixstate.stb + prev_first->first_pixel, npixels) != 0)
                return 1;
        return 0;
 }
@@ -4418,6 +4444,7 @@ static void reset_decisions (void)
 #endif
 #ifdef AGA
        thisline_decision.bplcon4 = bplcon4;
+       thisline_decision.fmode = fmode;
 #endif
        bplcon0d_old = -1;
        toscr_res_old = -1;
@@ -6228,6 +6255,7 @@ static void FMODE (int hpos, uae_u16 v)
        fmode_saved = v;
        set_chipset_mode();
        bpldmainitdelay (hpos);
+       record_register_change(hpos, 0x1fc, fmode);
 }
 
 static void FNULL (uae_u16 v)
@@ -6440,45 +6468,45 @@ static void SPRxCTLPOS(int num)
        struct sprite *s = &spr[num];
 
        sprstartstop (s);
-       sprxp = (sprpos[num] & 0xFF) * 2 + (sprctl[num] & 1);
+       sprxp = (s->pos & 0xFF) * 2 + (s->ctl & 1);
        sprxp <<= sprite_buffer_res;
        /* Quite a bit salad in this register... */
        if (0) {
        }
 #ifdef AGA
        else if (currprefs.chipset_mask & CSMASK_AGA) {
-               sprxp |= ((sprctl[num] >> 3) & 3) >> (RES_MAX - sprite_buffer_res);
-               s->dblscan = sprpos[num] & 0x80;
+               sprxp |= ((s->ctl >> 3) & 3) >> (RES_MAX - sprite_buffer_res);
+               s->dblscan = s->pos & 0x80;
        }
 #endif
 #ifdef ECS_DENISE
        else if (currprefs.chipset_mask & CSMASK_ECS_DENISE) {
-               sprxp |= ((sprctl[num] >> 3) & 2) >> (RES_MAX - sprite_buffer_res);
+               sprxp |= ((s->ctl >> 3) & 2) >> (RES_MAX - sprite_buffer_res);
        }
 #endif
        s->xpos = sprxp;
-       s->vstart = sprpos[num] >> 8;
-       s->vstart |= (sprctl[num] & 0x04) ? 0x0100 : 0;
-       s->vstop = sprctl[num] >> 8;
-       s->vstop |= (sprctl[num] & 0x02) ? 0x100 : 0;
+       s->vstart = s->pos >> 8;
+       s->vstart |= (s->ctl & 0x04) ? 0x0100 : 0;
+       s->vstop = s->ctl >> 8;
+       s->vstop |= (s->ctl & 0x02) ? 0x100 : 0;
        if (currprefs.chipset_mask & CSMASK_ECS_AGNUS) {
-               s->vstart |= (sprctl[num] & 0x40) ? 0x0200 : 0;
-               s->vstop |= (sprctl[num] & 0x20) ? 0x0200 : 0;
+               s->vstart |= (s->ctl & 0x40) ? 0x0200 : 0;
+               s->vstop |= (s->ctl & 0x20) ? 0x0200 : 0;
        }
        sprstartstop (s);
 }
 
 static void SPRxCTL_1(uae_u16 v, int num, int hpos)
 {
-       if (hpos >= maxhpos - 2 && sprctl[num] != v && vpos < maxvpos - 1) {
-               struct sprite *s = &spr[num];
+       struct sprite *s = &spr[num];
+       if (hpos >= maxhpos - 2 && s->ctl != v && vpos < maxvpos - 1) {
                vpos++;
                sprstartstop(s);
                vpos--;
                s->ignoreverticaluntilnextline = true;
                sprite_ignoreverticaluntilnextline = true;
        }
-       sprctl[num] = v;
+       s->ctl = v;
        spr_arm (num, 0);
        SPRxCTLPOS (num);
 
@@ -6493,18 +6521,17 @@ static void SPRxCTL_1(uae_u16 v, int num, int hpos)
 }
 static void SPRxPOS_1(uae_u16 v, int num, int hpos)
 {
-       if (hpos >= maxhpos - 2 && sprpos[num] != v && vpos < maxvpos - 1) {
-               struct sprite *s = &spr[num];
+       struct sprite *s = &spr[num];
+       if (hpos >= maxhpos - 2 && s->pos != v && vpos < maxvpos - 1) {
                vpos++;
                sprstartstop(s);
                vpos--;
                s->ignoreverticaluntilnextline = true;
                sprite_ignoreverticaluntilnextline = true;
        }
-       sprpos[num] = v;
+       s->pos = v;
        SPRxCTLPOS (num);
 #if SPRITE_DEBUG > 0
-       struct sprite *s = &spr[num];
        if (vpos >= SPRITE_DEBUG_MINY && vpos <= SPRITE_DEBUG_MAXY && (SPRITE_DEBUG & (1 << num))) {
                write_log (_T("%d:%d:SPR%dPOS %04X P=%06X VSTRT=%d VSTOP=%d HSTRT=%d D=%d A=%d CP=%x PC=%x\n"),
                        vpos, hpos, num, v, s->pt, s->vstart, s->vstop, s->xpos, spr[num].dmastate, spr[num].armed, cop_state.ip, M68K_GETPC);
@@ -6513,11 +6540,13 @@ static void SPRxPOS_1(uae_u16 v, int num, int hpos)
 }
 static void SPRxDATA_1(uae_u16 v, int num, int hpos)
 {
-       sprdata[num][0] = v;
+       struct sprite *s = &spr[num];
+       s->data[0] = v;
 #ifdef AGA
-       sprdata[num][1] = v;
-       sprdata[num][2] = v;
-       sprdata[num][3] = v;
+       s->data[1] = v;
+       s->data[2] = v;
+       s->data[3] = v;
+       s->width = sprite_width;
 #endif
        spr_arm (num, 1);
 #if SPRITE_DEBUG >= 256
@@ -6529,11 +6558,13 @@ static void SPRxDATA_1(uae_u16 v, int num, int hpos)
 }
 static void SPRxDATB_1(uae_u16 v, int num, int hpos)
 {
-       sprdatb[num][0] = v;
+       struct sprite *s = &spr[num];
+       s->datb[0] = v;
 #ifdef AGA
-       sprdatb[num][1] = v;
-       sprdatb[num][2] = v;
-       sprdatb[num][3] = v;
+       s->datb[1] = v;
+       s->datb[2] = v;
+       s->datb[3] = v;
+       s->width = sprite_width;
 #endif
 #if SPRITE_DEBUG >= 256
        if (vpos >= SPRITE_DEBUG_MINY && vpos <= SPRITE_DEBUG_MAXY && (SPRITE_DEBUG & (1 << num))) {
@@ -7583,20 +7614,25 @@ static void do_sprites_1(int num, int cycle, int hpos)
                {
                case 64:
                        if (cycle == 0) {
-                               sprdata[num][1] = data321;
-                               sprdata[num][2] = data322 >> 16;
-                               sprdata[num][3] = data322;
+                               s->data[1] = data321;
+                               s->data[2] = data322 >> 16;
+                               s->data[3] = data322;
                        } else {
-                               sprdatb[num][1] = data321;
-                               sprdatb[num][2] = data322 >> 16;
-                               sprdatb[num][3] = data322;
+                               s->datb[1] = data321;
+                               s->datb[2] = data322 >> 16;
+                               s->datb[3] = data322;
                        }
                        break;
                case 32:
-                       if (cycle == 0)
-                               sprdata[num][1] = data321;
-                       else
-                               sprdatb[num][1] = data321;
+                       if (cycle == 0) {
+                               s->data[1] = data321;
+                               s->data[2] = data;
+                               s->data[3] = data321;
+                       } else {
+                               s->datb[1] = data321;
+                               s->datb[2] = data;
+                               s->datb[3] = data321;
+                       }
                        break;
                }
 #endif
@@ -7652,8 +7688,11 @@ static void do_sprites (int hpos)
 
 static void init_sprites (void)
 {
-       memset (sprpos, 0, sizeof sprpos);
-       memset (sprctl, 0, sizeof sprctl);
+       for (int i = 0; i < MAX_SPRITES; i++) {
+               struct sprite *s = &spr[i];
+               s->pos = 0;
+               s->ctl = 0;
+       }
 }
 
 static void init_hardware_frame (void)
@@ -7715,7 +7754,11 @@ void init_hardware_for_drawing_frame (void)
                int first_pixel = prev_sprite_entries[0].first_pixel;
                int npixels = prev_sprite_entries[prev_next_sprite_entry].first_pixel - first_pixel;
                memset (spixels + first_pixel, 0, npixels * sizeof *spixels);
-               memset (spixstate.bytes + first_pixel, 0, npixels * sizeof *spixstate.bytes);
+               memset(spixstate.stb + first_pixel, 0, npixels * sizeof *spixstate.stb);
+               if (spr_width_64_seen) {
+                       memset(spixstate.stbfm + first_pixel, 0, npixels * sizeof *spixstate.stbfm);
+                       spr_width_64_seen = false;
+               }
        }
        prev_next_sprite_entry = next_sprite_entry;
 
@@ -9824,6 +9867,9 @@ void custom_reset (bool hardreset, bool keyboardreset)
                CLXCON2 (0);
                setup_fmodes (0);
                sprite_width = GET_SPRITEWIDTH (fmode);
+               for (int i = 0; i < MAX_SPRITES; i++) {
+                       spr[i].width = sprite_width;
+               }
                beamcon0 = new_beamcon0 = currprefs.ntscmode ? 0x00 : 0x20;
                bltstate = BLT_done;
                blit_interrupt = 1;
@@ -10810,10 +10856,11 @@ uae_u8 *save_custom (int *len, uae_u8 *dstptr, int full)
                        SL (spr[i].pt); /* 120-13E SPRxPT */
                }
                for (i = 0; i < 8; i++) {
-                       SW (sprpos[i]); /* 1x0 SPRxPOS */
-                       SW (sprctl[i]); /* 1x2 SPRxPOS */
-                       SW (sprdata[i][0]);     /* 1x4 SPRxDATA */
-                       SW (sprdatb[i][0]);     /* 1x6 SPRxDATB */
+                       struct sprite *s = &spr[i];
+                       SW (s->pos);    /* 1x0 SPRxPOS */
+                       SW (s->ctl);    /* 1x2 SPRxPOS */
+                       SW (s->data[0]);        /* 1x4 SPRxDATA */
+                       SW (s->datb[0]);        /* 1x6 SPRxDATB */
                }
        }
        for (i = 0; i < 32; i++) {
@@ -10912,42 +10959,44 @@ uae_u8 *save_custom_agacolors (int *len, uae_u8 *dstptr)
 
 uae_u8 *restore_custom_sprite (int num, uae_u8 *src)
 {
-       memset (&spr[num], 0, sizeof (struct sprite));
-       spr[num].pt = RL;               /* 120-13E SPRxPT */
-       sprpos[num] = RW;               /* 1x0 SPRxPOS */
-       sprctl[num] = RW;               /* 1x2 SPRxPOS */
-       sprdata[num][0] = RW;   /* 1x4 SPRxDATA */
-       sprdatb[num][0] = RW;   /* 1x6 SPRxDATB */
-       sprdata[num][1] = RW;
-       sprdatb[num][1] = RW;
-       sprdata[num][2] = RW;
-       sprdatb[num][2] = RW;
-       sprdata[num][3] = RW;
-       sprdatb[num][3] = RW;
-       spr[num].armed = RB & 1;
+       struct sprite *s = &spr[num];
+       memset (s, 0, sizeof (struct sprite));
+       s->pt = RL;             /* 120-13E SPRxPT */
+       s->pos = RW;            /* 1x0 SPRxPOS */
+       s->ctl = RW;            /* 1x2 SPRxPOS */
+       s->data[0] = RW;        /* 1x4 SPRxDATA */
+       s->datb[0] = RW;        /* 1x6 SPRxDATB */
+       s->data[1] = RW;
+       s->datb[1] = RW;
+       s->data[2] = RW;
+       s->datb[2] = RW;
+       s->data[3] = RW;
+       s->datb[3] = RW;
+       s->armed = RB & 1;
        return src;
 }
 
 uae_u8 *save_custom_sprite (int num, int *len, uae_u8 *dstptr)
 {
        uae_u8 *dstbak, *dst;
+       struct sprite *s = &spr[num];
 
        if (dstptr)
                dstbak = dst = dstptr;
        else
                dstbak = dst = xmalloc (uae_u8, 30);
-       SL (spr[num].pt);               /* 120-13E SPRxPT */
-       SW (sprpos[num]);               /* 1x0 SPRxPOS */
-       SW (sprctl[num]);               /* 1x2 SPRxPOS */
-       SW (sprdata[num][0]);   /* 1x4 SPRxDATA */
-       SW (sprdatb[num][0]);   /* 1x6 SPRxDATB */
-       SW (sprdata[num][1]);
-       SW (sprdatb[num][1]);
-       SW (sprdata[num][2]);
-       SW (sprdatb[num][2]);
-       SW (sprdata[num][3]);
-       SW (sprdatb[num][3]);
-       SB (spr[num].armed ? 1 : 0);
+       SL (s->pt);             /* 120-13E SPRxPT */
+       SW (s->pos);            /* 1x0 SPRxPOS */
+       SW (s->ctl);            /* 1x2 SPRxPOS */
+       SW (s->data[0]);        /* 1x4 SPRxDATA */
+       SW (s->datb[0]);        /* 1x6 SPRxDATB */
+       SW (s->data[1]);
+       SW (s->datb[1]);
+       SW (s->data[2]);
+       SW (s->datb[2]);
+       SW (s->data[3]);
+       SW (s->datb[3]);
+       SB (s->armed ? 1 : 0);
        *len = dst - dstbak;
        return dstbak;
 }
index 6d346a2fb4844654c4c27ff9e4cd37766f129847..c57954565deb5809d76e974471ff96fd098c9a18 100644 (file)
@@ -149,8 +149,9 @@ static uae_u32 clxtab[256];
 xcolnr xcolors[4096];
 
 struct spritepixelsbuf {
-       uae_u8 attach;
+       bool attach;
        uae_u8 stdata;
+       uae_u16 stfmdata;
        uae_u16 data;
 };
 static struct spritepixelsbuf spritepixels_buffer[MAX_PIXELS_PER_LINE];
@@ -194,8 +195,7 @@ uae_u16 *spixels;
 uae_u16 spixels[2 * MAX_SPR_PIXELS];
 #endif
 
-/* Eight bits for every pixel.  */
-union sps_union spixstate;
+struct sprite_stb spixstate;
 
 static uae_u32 ham_linebuf[MAX_PIXELS_PER_LINE * 2];
 static uae_u8 *real_bplpt[8];
@@ -274,6 +274,7 @@ static bool ecs_genlock_features_active;
 static uae_u8 ecs_genlock_features_mask;
 static bool ecs_genlock_features_colorkey;
 static int hsync_shift_hack;
+static bool sprite_smaller_than_64;
 
 uae_sem_t gui_sem;
 
@@ -1283,6 +1284,13 @@ static uae_u8 render_sprites (int pos, int dualpf, uae_u8 apixel, int aga)
        int *shift_lookup = dualpf ? (bpldualpfpri ? dblpf_ms2 : dblpf_ms1) : dblpf_ms;
        int maskshift, plfmask;
 
+       // If 64 pixel wide sprite and FMODE gets lowered when sprite's
+       // first 32 pixels are being drawn: matching pixel(s) in second
+       // 32 pixel part gets blanked.
+       if (aga && spb->stfmdata && sprite_smaller_than_64) {
+               spb[32 << currprefs.gfx_resolution].data &= ~spb->stfmdata;
+       }
+
        // shdelay hack, above &spritepixels[pos] is correct. 
        pos += sprite_shdelay;
        /* The value in the shift lookup table is _half_ the shift count we
@@ -2240,13 +2248,15 @@ that many of the if statements will go away completely after inlining.  */
 STATIC_INLINE void draw_sprites_1 (struct sprite_entry *e, int dualpf, int has_attach)
 {
        uae_u16 *buf = spixels + e->first_pixel;
-       uae_u8 *stbuf = spixstate.bytes + e->first_pixel;
+       uae_u8 *stbuf = spixstate.stb + e->first_pixel;
+       uae_u16 *stfmbuf = spixstate.stbfm + e->first_pixel;
        int spr_pos, pos;
        int epos = e->pos;
        int emax = e->max;
 
        buf -= epos;
        stbuf -= epos;
+       stfmbuf -= epos;
 
        spr_pos = epos + ((DIW_DDF_OFFSET - DISPLAY_LEFT_SHIFT) << sprite_buffer_res);
 
@@ -2257,6 +2267,7 @@ STATIC_INLINE void draw_sprites_1 (struct sprite_entry *e, int dualpf, int has_a
                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;
                }
        }
@@ -2777,6 +2788,7 @@ static void pfield_expand_dp_bplcon (void)
                bpldelay_sh = sh;
                pfield_mode_changed = true;
        }
+       sprite_smaller_than_64 = (dp_for_drawing->fmode & 0x0c) != 0x0c;
 #endif
        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) {
@@ -2843,6 +2855,9 @@ static void pfield_expand_dp_bplconx (int regno, int v)
        case 0x10c: // BPLCON4
                dp_for_drawing->bplcon4 = v;
                break;
+       case 0x1fc: // FMODE
+               dp_for_drawing->fmode = v;
+               break;
 #endif
        }
        pfield_expand_dp_bplcon ();
@@ -3137,6 +3152,7 @@ static void pfield_draw_line (struct vidbuffer *vb, int lineno, int gfx_ypos, in
                        uae_u16 b2 = dp_for_drawing->bplcon2;
                        uae_u16 b3 = dp_for_drawing->bplcon3;
                        uae_u16 b4 = dp_for_drawing->bplcon4;
+                       uae_u16 fm = dp_for_drawing->fmode;
                        init_ham_decoding ();
                        do_color_changes (dummy_worker, decode_ham, lineno);
                        if (have_color_changes) {
@@ -3146,6 +3162,7 @@ static void pfield_draw_line (struct vidbuffer *vb, int lineno, int gfx_ypos, in
                                dp_for_drawing->bplcon2 = b2;
                                dp_for_drawing->bplcon3 = b3;
                                dp_for_drawing->bplcon4 = b4;
+                               dp_for_drawing->fmode = fm;
                                pfield_expand_dp_bplcon ();
                        }
                        hposblank = ohposblank;
index 1dce48aa73253b9bdd7526bc273948e99c71e7aa..1f9961d2cc4cf18f23ae779a70bc9c74f9e503e4 100644 (file)
@@ -232,11 +232,15 @@ struct sprite_entry
        bool has_attached;
 };
 
-union sps_union {
-       uae_u8 bytes[2 * MAX_SPR_PIXELS];
-       uae_u32 words[2 * MAX_SPR_PIXELS / 4];
+struct sprite_stb
+{
+       /* Eight bits for every pixel for attachment
+        * Another eight for 64/32 status
+        */
+       uae_u8 stb[2 * MAX_SPR_PIXELS];
+       uae_u16 stbfm[2 * MAX_SPR_PIXELS];
 };
-extern union sps_union spixstate;
+extern struct sprite_stb spixstate;
 
 #ifdef OS_WITHOUT_MEMORY_MANAGEMENT
 extern uae_u16 *spixels;
@@ -265,6 +269,7 @@ struct decision {
        uae_u16 bplcon0, bplcon2;
 #ifdef AGA
        uae_u16 bplcon3, bplcon4;
+       uae_u16 fmode;
 #endif
        uae_u8 nr_planes;
        uae_u8 bplres;