]> git.unchartedbackwaters.co.uk Git - francis/winuae.git/commitdiff
Bitplane shifter update, new undocumented active bitplane count/bplcon1 feature support.
authorToni Wilen <twilen@winuae.net>
Sun, 21 Nov 2021 17:14:48 +0000 (19:14 +0200)
committerToni Wilen <twilen@winuae.net>
Sun, 21 Nov 2021 17:14:48 +0000 (19:14 +0200)
custom.cpp

index 5e3fef1c625f6cb5d41abecc5e802a6afbd0d011..953d1a03ba3eaa073c6f7a37a2a41772eb4c1a30 100644 (file)
@@ -399,6 +399,7 @@ static struct color_entry current_colors;
 uae_u16 bplcon0;
 static uae_u16 bplcon1, bplcon2, bplcon3, bplcon4;
 static int bplcon0d, bplcon0d_old;
+static bool bplcon0d_change;
 static uae_u32 bplcon0_res, bplcon0_planes, bplcon0_planes_limit;
 static int diwstrt, diwstop, diwhigh;
 static int diwhigh_written;
@@ -565,6 +566,7 @@ static uae_u16 fetched[MAX_PLANES];
 static uae_u16 todisplay_fetched;
 #ifdef AGA
 static uae_u64 todisplay_aga[MAX_PLANES], todisplay2_aga[MAX_PLANES];
+static bool todisplay2_lastbit[MAX_PLANES];
 static uae_u64 fetched_aga[MAX_PLANES];
 static uae_u32 fetched_aga_spr[MAX_PLANES];
 #endif
@@ -574,7 +576,8 @@ static int toscr_res2p, toscr_res_mult;
 static int toscr_res, toscr_res_old;
 static int toscr_res_pixels, toscr_res_pixels_shift;
 static int toscr_res_pixels_hr, toscr_res_pixels_shift_hr, toscr_res_pixels_mask_hr;
-static int toscr_nr_planes, toscr_nr_planes2, toscr_nr_planes_agnus;
+static int toscr_nr_planes, toscr_nr_planes2, toscr_nr_planes3, toscr_nr_planes_agnus;
+static bool toscr_nr_changed;
 static int toscr_nr_planes_shifter, toscr_nr_planes_shifter_new;
 static int fetchwidth;
 static int toscr_delay_adjusted[2], toscr_delay_sh[2];
@@ -2134,12 +2137,8 @@ STATIC_INLINE void toscr_3_ecs(int oddeven, int step, int nbits)
 {
        int shift = 16 - nbits;
 
-       // if number of planes decrease (or go to zero), we still need to
-       // shift all possible remaining pixels out of Denise's shift register
-       for (int i = oddeven; i < thisline_decision.nr_planes; i += step) {
-               outword[i] <<= nbits;
-       }
        for (int i = oddeven; i < toscr_nr_planes2; i += step) {
+               outword[i] <<= nbits;
                outword[i] |= todisplay2[i] >> shift;
                todisplay2[i] <<= nbits;
        }
@@ -2152,15 +2151,14 @@ STATIC_INLINE void toscr_3_aga(int oddeven, int step, int nbits, int fm_size)
        uae_u32 mask = 0xFFFF >> (16 - nbits);
        int shift = fm_size - nbits;
 
-       for (int i = oddeven; i < thisline_decision.nr_planes; i += step) {
-               outword[i] <<= nbits;
-       }
        if (shift == 64) {
                for (int i = oddeven; i < toscr_nr_planes2; i += step) {
+                       outword[i] <<= nbits;
                        todisplay2_aga[i] <<= nbits;
                }
        } else {
                for (int i = oddeven; i < toscr_nr_planes2; i += step) {
+                       outword[i] <<= nbits;
                        outword[i] |= (todisplay2_aga[i] >> shift) & mask;
                        todisplay2_aga[i] <<= nbits;
                }
@@ -2170,9 +2168,7 @@ STATIC_INLINE void toscr_3_aga(int oddeven, int step, int nbits, int fm_size)
 // very, very slow and unoptimized..
 STATIC_INLINE void toscr_3_aga_hr(int oddeven, int step, int nbits, int fm_size_minusone)
 {
-       int i;
-
-       for (i = oddeven; i < toscr_nr_planes2; i += step) {
+       for (int i = oddeven; i < toscr_nr_planes2; i += step) {
                int subpix = out_subpix[oddeven];
                for (int j = 0; j < nbits; j++) {
                        uae_u32 bit = (todisplay2_aga[i] >> fm_size_minusone) & 1;
@@ -2185,10 +2181,6 @@ STATIC_INLINE void toscr_3_aga_hr(int oddeven, int step, int nbits, int fm_size_
                        }
                }
        }
-       while (i < thisline_decision.nr_planes) {
-               outword64[i] <<= nbits;
-               i += step;
-       }
        out_subpix[oddeven] += nbits;
 }
 
@@ -2327,6 +2319,8 @@ STATIC_INLINE void do_delays_3_aga(int nbits, int fm)
        }
 }
 
+static const uae_u64 firstpixel[] = { 0x8000, 0x80000000, 0x8000000000000000, 0x8000000000000000 };
+
 STATIC_INLINE void do_delays_fast_3_aga(int nbits, int fm)
 {
        int delaypos = delay_cycles;
@@ -2337,8 +2331,23 @@ STATIC_INLINE void do_delays_fast_3_aga(int nbits, int fm)
                do_tosrc(0, 1, diff, fm);
                nbits2 -= diff;
                if (todisplay_fetched) {
-                       memcpy(todisplay2_aga, todisplay_aga, toscr_nr_planes_shifter * sizeof(uae_u64));
+                       int i;
+                       for (i = 0; i < toscr_nr_planes_shifter; i++) {
+                               todisplay2_aga[i] = todisplay_aga[i];
+                               todisplay2_lastbit[i] = todisplay_aga[i] & 1;
+                       }
                        todisplay_fetched = 0;
+                       // Chipset bug. if bitplane gets disabled mid-scanline and its last pixel in shifter
+                       // is one, it gets duplicated.
+                       if (toscr_nr_changed) {
+                               while (i < toscr_nr_planes2) {
+                                       if (todisplay2_lastbit[i]) {
+                                               todisplay2_aga[i] = firstpixel[fm];
+                                               todisplay2_lastbit[i] = 0;
+                                       }
+                                       i++;
+                               }
+                       }
                }
        }
        if (nbits2) {
@@ -2357,11 +2366,22 @@ STATIC_INLINE void do_delays_3_aga_hr(int nbits, int fm)
                        do_tosrc_hr(oddeven, 2, diff, fm);
                        nbits2 -= diff;
                        if (todisplay_fetched & (oddeven + 1)) {
-                               for (int i = oddeven; i < toscr_nr_planes_shifter; i += 2) {
+                               int i;
+                               for (i = oddeven; i < toscr_nr_planes_shifter; i += 2) {
                                        todisplay2_aga[i] = todisplay_aga[i];
+                                       todisplay2_lastbit[i] = todisplay_aga[i] & 1;
                                }
                                todisplay_fetched -= oddeven + 1;
                                out_subpix[oddeven] = 0;
+                               if (toscr_nr_changed) {
+                                       while (i < toscr_nr_planes2) {
+                                               if (todisplay2_lastbit[i]) {
+                                                       todisplay2_aga[i] = firstpixel[fm];
+                                                       todisplay2_lastbit[i] = 0;
+                                               }
+                                               i += 2;
+                                       }
+                               }
                        }
                }
                if (nbits2) {
@@ -2620,7 +2640,7 @@ STATIC_INLINE void toscr_1(int nbits, int fm)
        if (out_nbits == 32) {
                if (out_offs < MAX_WORDS_PER_LINE * 2 / 4) {
                        uae_u8 *dataptr = line_data[next_lineno] + out_offs * 4;
-                       for (int i = 0; i < thisline_decision.nr_planes; i++) {
+                       for (int i = 0; i < toscr_nr_planes2; i++) {
                                uae_u32 *dataptr32 = (uae_u32*)dataptr;
                                if (*dataptr32 != outword[i]) {
                                        thisline_changed = 1;
@@ -2642,7 +2662,7 @@ STATIC_INLINE void toscr_1_hr(int nbits, int fm)
        if (out_nbits == 64) {
                if (out_offs < MAX_WORDS_PER_LINE * 2 / 4 - 1) {
                        uae_u8 *dataptr = line_data[next_lineno] + out_offs * 4;
-                       for (int i = 0; i < thisline_decision.nr_planes; i++) {
+                       for (int i = 0; i < toscr_nr_planes2; i++) {
                                uae_u64 *dataptr64 = (uae_u64*)dataptr;
                                uae_u64 v = (outword64[i] >> 32) | (outword64[i] << 32);
                                if (*dataptr64 != v) {
@@ -2856,25 +2876,13 @@ static void update_denise_vars(void)
        compute_shifter_mask();
 }
 
-static void update_planecount(void)
-{
-       toscr_nr_planes = GET_PLANES(bplcon0d);
-       if (isocs7planes()) {
-               if (toscr_nr_planes2 < 6) {
-                       toscr_nr_planes2 = 6;
-               }
-       } else {
-               toscr_nr_planes2 = toscr_nr_planes;
-       }
-}
-
 static void update_denise(int hpos)
 {
        update_denise_vars();
        if (bplcon0d_old != bplcon0d) {
                bplcon0d_old = bplcon0d;
                record_color_change2(hpos, 0x100 + RECORDED_REGISTER_CHANGE_OFFSET, bplcon0d);
-               update_planecount();
+               toscr_nr_planes = GET_PLANES(bplcon0d);
                hack_shres_delay(hpos);
        }
 }
@@ -2892,13 +2900,13 @@ STATIC_INLINE void clear_fetchbuffer(uae_u32* ptr, int nwords)
        memset(ptr, 0, nwords * 4);
 }
 
-static void update_toscr_planes(int fm)
+static void update_toscr_planes(int newplanes, int fm)
 {
        // This must be called just before new bitplane block starts,
        // not when depth value changes. Depth can change early and can leave
        // 16+ pixel horizontal line of old data visible.
        if (out_offs) {
-               for (int j = thisline_decision.nr_planes; j < toscr_nr_planes_agnus; j++) {
+               for (int j = toscr_nr_planes2; j < newplanes ; j++) {
                        clear_fetchbuffer((uae_u32 *)(line_data[next_lineno] + 2 * MAX_WORDS_PER_LINE * j), out_offs);
                        if (thisline_decision.plfleft >= 0) {
                                todisplay[j] = 0;
@@ -2910,7 +2918,6 @@ static void update_toscr_planes(int fm)
                        }
                }
        }
-       thisline_decision.nr_planes = toscr_nr_planes_agnus;
 }
 
 static void hbstrt_bordercheck(int hpos, bool early)
@@ -2995,7 +3002,7 @@ static void beginning_of_plane_block(int hpos)
 
        update_denise(hpos);
        if (toscr_nr_planes_agnus > thisline_decision.nr_planes) {
-               update_toscr_planes(fetchmode);
+               thisline_decision.nr_planes = toscr_nr_planes_agnus;
        }
 }
 
@@ -3544,7 +3551,7 @@ STATIC_INLINE void one_fetch_cycle_0(int hpos, int fm)
                bplcon1_written = false;
        }
 
-       // BPLCON0 modification immediate after BPL1DAT can affect BPL1DAT finished plane block
+       // BPLCON0 modification immediately after BPL1DAT can affect BPL1DAT finished plane block
        if (bplcon0_planes_changed) {
                if (((hpos - bpl_hstart) & fetchstart_mask) < fetchstart_mask) {
                        flush_display(fm);
@@ -4752,6 +4759,15 @@ static void reset_decisions_hsync_start(void)
        thisline_decision.xor_seen = (bplcon4 & 0xff00) != 0;
        thisline_decision.nr_planes = toscr_nr_planes_agnus;
 
+       toscr_nr_planes2 = GET_PLANES(bplcon0d);
+       if (isocs7planes()) {
+               if (toscr_nr_planes2 < 6) {
+                       toscr_nr_planes2 = 6;
+               }
+       }
+       toscr_nr_planes3 = toscr_nr_planes2;
+       toscr_nr_changed = false;
+
        hpos_hsync_extra = 0;
        int hpos = current_hpos();
        bool normalstart = true;
@@ -6662,7 +6678,7 @@ static void BPLxPTL(int hpos, uae_u16 v, int num)
        //write_log (_T("%d:%d:BPL%dPTL %08X COP=%08x\n"), hpos, vpos, num, bplpt[num], cop_state.ip);
 }
 
-static void BPLCON0_Denise(int hpos, uae_u16 v)
+static uae_u16 BPLCON0_Denise_mask(uae_u16 v)
 {
        if (!ecs_denise) {
                v &= ~0x00F1;
@@ -6674,10 +6690,17 @@ static void BPLCON0_Denise(int hpos, uae_u16 v)
 #if SPRBORDER
        v |= 1;
 #endif
+       return v;
+}
 
-       if (bplcon0d == v) {
+static void BPLCON0_Denise(int hpos, uae_u16 v)
+{
+       v = BPLCON0_Denise_mask(v);
+
+       if (bplcon0d == v || bplcon0d_change) {
                return;
        }
+       bplcon0d_change = false;
 
        // fake unused 0x0080 bit as an EHB bit (see below)
        if (isehb(bplcon0d, bplcon2)) {
@@ -6709,17 +6732,68 @@ static void bpldmainitdelay(int hpos)
 static void BPLCON0(int hpos, uae_u16 v);
 static void bplcon0_denise_change(int hpos, uae_u16 con0)
 {
+       con0 = BPLCON0_Denise_mask(con0);
        int np = GET_PLANES(con0);
+       if (bplcon0d != con0) {
+               bplcon0d = con0;
+               bplcon0d_change = true;
+       }
        if (np == toscr_nr_planes_shifter_new) {
                toscr_nr_planes_shifter = np;
-               return;
+       } else {
+               bplcon0_planes_changed = true;
        }
+       
        SET_LINE_CYCLEBASED;
        decide_diw(hpos);
        decide_line(hpos);
        decide_fetch_safe(hpos);
+
        toscr_nr_planes_shifter_new = np;
-       bplcon0_planes_changed = true;
+       if (ecs_denise || aga_mode) {
+               toscr_nr_changed = np != toscr_nr_planes3;
+       }
+       toscr_nr_planes3 = np;
+
+#if 0
+       // TODO: handle mid resolution switches pixel-accurately.
+       // OCS Denise, ECS Denise and AGA have different behavior
+       if (currprefs.chipset_hr) {
+               int res = GET_RES_DENISE(con0);
+               if (toscr_res != res && thisline_decision.plfleft >= 0) {
+                       flush_display(fetchmode);
+                       if (res == RES_HIRES) {
+                               for (int i = 0; i < toscr_nr_planes2; i++) {
+                                       uae_u64 v = todisplay2_aga[i];
+                                       todisplay2_aga[i] = 0;
+                                       for (int j = 0, k = 1; j < 16; j += 2, k++) {
+                                               if (v & (1 << k)) {
+                                                       todisplay2_aga[i] |= 1 << j;
+                                               }
+                                       }
+                               }
+                       } else if (res == RES_LORES) {
+                               for (int i = 0; i < toscr_nr_planes2; i++) {
+                                       uae_u64 v1 = todisplay2_aga[i];
+                                       uae_u32 v2 = todisplay2[i];
+                                       todisplay2[i] = 0;
+                                       for (int j = 0, k = 0; j < 16; j += 2, k++) {
+                                               if (v2 & (1 << j)) {
+                                                       todisplay2[i] |= 1 << k;
+                                               }
+                                       }
+                               }
+                       }
+               }
+       }
+#endif
+
+
+       if (np > toscr_nr_planes2) {
+               update_toscr_planes(np, fetchmode);
+               toscr_nr_planes2 = np;
+       }
+
        if (isocs7planes()) {
                if (toscr_nr_planes_shifter_new < 6) {
                        toscr_nr_planes_shifter_new = 6;