]> git.unchartedbackwaters.co.uk Git - francis/winuae.git/commitdiff
Custom emulation update WIP.
authorToni Wilen <twilen@winuae.net>
Sun, 16 May 2021 17:23:16 +0000 (20:23 +0300)
committerToni Wilen <twilen@winuae.net>
Sun, 16 May 2021 17:23:16 +0000 (20:23 +0300)
blitter.cpp
custom.cpp
include/blitter.h
include/custom.h

index 1f8b5970db851ca9943e730e686efa09f4bf3905..bd5fd1691fa54dea7acbd8e61ccfead96980efe9 100644 (file)
@@ -49,6 +49,7 @@ int bltptxpos, bltptxc;
 static int blinea_shift;
 static uae_u16 blinea, blineb;
 static int blitline, blitfc, blitfill, blitife, blitsing, blitdesc, blit_ovf;
+static bool blitfill_idle;
 static int blitline_started;
 static int blitonedot, blitsign, blitlinepixel;
 static int blit_add;
@@ -86,7 +87,7 @@ static int blit_linecycles, blit_extracycles;
 static int blit_faulty;
 static int blt_delayed_irq;
 static uae_u16 ddat1;
-static int ddat1use;
+static int ddat1use, ddat2use;
 
 static int last_blitter_hpos;
 
@@ -99,7 +100,10 @@ static int debug_bltcop;
 static uae_u16 debug_bltsizev, debug_bltsizeh;
 static uae_u16 debug_bltadat, debug_bltbdat, debug_bltcdat;
 
-#define BLITTER_STARTUP_CYCLES 2
+#define BLITTER_MAX_PIPELINED_CYCLES 4
+
+#define CYCLECOUNT_FINISHED -1000
+#define CYCLECOUNT_START 3
 
 /*
 Blitter Idle Cycle:
@@ -349,19 +353,11 @@ void blitter_debugdump(void)
        blitter_dump();
 }
 
-static int canblit(int hpos)
+static void markidlecycle(int hpos)
 {
-       if (!dmaen(DMA_BLITTER))
-               return -1;
-       if (blitter_cant_access(hpos))
-               return 0;
-       return 1;
-}
-
-static void markidlecycle (int hpos)
-{
-       if (debug_dma)
-               record_dma_event (DMA_EVENT_BLITSTARTFINISH, hpos, vpos);
+       if (debug_dma) {
+               record_dma_event(DMA_EVENT_BLITSTARTFINISH, hpos, vpos);
+       }
 }
 
 static void reset_channel_mods (void)
@@ -412,7 +408,7 @@ static void check_channel_mods (int hpos, int ch)
 // (or cycle where last D write would have been if
 // ONEDOT was active)
 
-static bool blitter_interrupt(int hpos, int done)
+static bool blitter_interrupt(int done)
 {
        blt_info.blit_main = 0;
        if (blt_info.blit_interrupt) {
@@ -424,21 +420,16 @@ static bool blitter_interrupt(int hpos, int done)
        blt_info.blit_interrupt = 1;
        send_interrupt(6, (4 + 1) * CYCLE_UNIT);
        if (debug_dma) {
-               record_dma_event(DMA_EVENT_BLITIRQ, hpos, vpos);
+               record_dma_event(DMA_EVENT_BLITIRQ, current_hpos(), vpos);
        }
        blitter_done_notify(blitline);
        return true;
 }
 
-static void blitter_done(int hpos)
+static void blitter_done(void)
 {
-       ddat1use = 0;
-       if (blt_info.blit_finald) {
-               if (debug_dma)
-                       record_dma_event(DMA_EVENT_BLITFINALD, hpos, vpos);
-       }
        blt_info.blit_finald = 0;
-       if (!blitter_interrupt(hpos, 1)) {
+       if (!blitter_interrupt(1)) {
                blitter_done_notify(blitline);
        }
        event2_remevent(ev2_blitter);
@@ -450,35 +441,17 @@ static void blitter_done(int hpos)
        blt_info.blitter_dangerous_bpl = 0;
 }
 
-static void blitter_maybe_done_early(int hpos)
+static void blitter_done_except_d(void)
 {
-       if (currprefs.chipset_mask & CSMASK_AGA) {
-               if (!(bltcon0 & 0x100) || blitline) {
-                       // immediately done if D disabled or line mode.
-                       blitter_done(hpos);
-                       return;
-               }
-       }
-       // busy cleared, interrupt generated.
-       // last D write still pending if not linemode and D channel active
-       if (blitline) {
-               blitter_done(hpos);
-       } else {
-               if (ddat1use && (bltcon0 & 0x100)) {
-                       blt_info.blit_finald = 1 + 2;
-                       blitter_interrupt(hpos, 0);
-               } else {
-                       blitter_done(hpos);
-               }
-       }
+       blitter_interrupt(1);
 }
 
 STATIC_INLINE void chipmem_agnus_wput2 (uaecptr addr, uae_u32 w)
 {
-       //last_custom_value1 = w; blitter writes are not stored
        if (!(log_blitter & 4)) {
                debug_putpeekdma_chipram(addr, w, MW_MASK_BLITTER_D_N, 0x000, 0x054);
                chipmem_wput_indirect (addr, w);
+               last_custom_value1 = w;
        }
 }
 
@@ -692,6 +665,7 @@ static void blitter_write (void)
        /* D-channel state has no effect on linedraw, but C must be enabled or nothing is drawn! */
        if (bltcon0 & 0x200) {
                chipmem_wput_indirect(bltdpt, blt_info.bltddat);
+               last_custom_value1 = blt_info.bltddat;
        }
 }
 
@@ -808,11 +782,11 @@ static void actually_do_blit (void)
 static void blitter_doit (void)
 {
        if (blt_info.vblitsize == 0 || (blitline && blt_info.hblitsize != 2)) {
-               blitter_done (current_hpos());
+               blitter_done();
                return;
        }
        actually_do_blit();
-       blitter_done (current_hpos());
+       blitter_done();
 }
 
 static int makebliteventtime(int delay)
@@ -850,9 +824,29 @@ void blitter_handler (uae_u32 data)
 
 #ifdef CPUEMU_13
 
+static bool blitshifterdebug(uae_u16 con0, bool check)
+{
+       int cnt = 0;
+       for (int i = 0; i < 4; i++) {
+               if (shifter[i]) {
+                       cnt++;
+               }
+       }
+       if (cnt != 1 || !check) {
+               write_log(_T("Blitter shifter bits %d: CH=%c%c%c%c (%d-%d-%d-%d O=%d) PC=%08x\n"),
+                       cnt,
+                       ((con0 >> 11) & 1) ? 'A' : '-', ((con0 >> 10) & 1) ? 'B' : '-', ((con0 >> 9) & 1) ? 'C' : '-', ((con0 >> 8) & 1) ? 'D' : '-',
+                       shifter[0], shifter[1], shifter[2], shifter[3], shifter_out, M68K_GETPC);
+               return true;
+       }
+       return false;
+}
+
 static void blit_bltset(int con)
 {
        static int blit_warned = 100;
+       bool blit_changed = false;
+       uae_u16 con0_old = bltcon0_old;
 
        if (con & 2) {
                blitdesc = bltcon1 & 2;
@@ -860,11 +854,19 @@ static void blit_bltset(int con)
                blt_info.blitdownbshift = 16 - blt_info.blitbshift;
                if (blit_warned > 0) {
                        if ((bltcon1 & 1) && !blitline_started) {
-                               write_log(_T("BLITTER: linedraw enabled when blitter was already active! %08x\n"), M68K_GETPC);
+                               write_log(_T("BLITTER: linedraw enabled when blitter is active! %08x\n"), M68K_GETPC);
+                               blit_warned--;
                        } else if (!(bltcon1 & 1) && blitline_started) {
-                               write_log(_T("BLITTER: linedraw disabled when blitter was already active! %08x\n"), M68K_GETPC);
+                               write_log(_T("BLITTER: linedraw disabled when blitter is active! %08x\n"), M68K_GETPC);
+                               blit_warned--;
+                       }
+                       if ((bltcon1 & 0x18) && !(bltcon1_old & 0x18)) {
+                               write_log(_T("BLITTER: fill enabled when blitter is active! %08x\n"), M68K_GETPC);
+                               blit_warned--;
+                       } else if (!(bltcon1 & 0x18) && (bltcon1_old & 0x18)) {
+                               write_log(_T("BLITTER: fill disabled when blitter is active! %08x\n"), M68K_GETPC);
+                               blit_warned--;
                        }
-                       blit_warned--;
                }
        }
 
@@ -874,23 +876,30 @@ static void blit_bltset(int con)
        }
 
        if (!savestate_state && blt_info.blit_main && (bltcon0_old != bltcon0 || bltcon1_old != bltcon1)) {
+               blit_changed = true;
                if (blit_warned > 0) {
-                       write_log(_T("BLITTER: BLTCON0 %04x -> %04x BLTCON1 %04x -> %04x PC=%08x\n"), bltcon0_old, bltcon0, bltcon1_old, bltcon1, M68K_GETPC);
+                       write_log(_T("BLITTER: BLTCON0 %04x -> %04x BLTCON1 %04x -> %04x PC=%08x (%d %d)\n"), bltcon0_old, bltcon0, bltcon1_old, bltcon1, M68K_GETPC, current_hpos(), vpos);
+                       blitshifterdebug(bltcon0_old, false);
                        blit_warned--;
+                       //activate_debugger();
                }
                bltcon0_old = bltcon0;
                bltcon1_old = bltcon1;
+               //activate_debugger();
        }
 
        blit_ch = (bltcon0 & 0x0f00) >> 8;
        blitline = bltcon1 & 1;
        blit_ovf = (bltcon1 & 0x20) != 0;
 
+       blitfill_idle = false;
        shifter_skip_b = (bltcon0 & 0x400) == 0;
        if (blitline) {
                shifter_skip_y = true;
                blitfill = 0;
+               shifter_out = shifter_skip_y ? shifter[2] : shifter[3];
        } else {
+               int oldfill = blitfill;
                blitfill = (bltcon1 & 0x18) != 0;
                blitfc = !!(bltcon1 & 0x4);
                blitife = !!(bltcon1 & 0x8);
@@ -900,16 +909,20 @@ static void blit_bltset(int con)
                }
                if (blitfill && !blitdesc) {
                        debugtest(DEBUGTEST_BLITTER, _T("fill without desc\n"));
-                       if (log_blitter & 16)
+                       if (log_blitter & 16) {
                                activate_debugger();
+                       }
                }
+
                shifter_skip_y = (bltcon0 & (0x100 | 0x200)) != 0x300;
-               // fill mode idle cycle needed?
+               // fill mode idle cycle needed? (D enabled but C not enabled)
                if (blitfill && (bltcon0 & (0x100 | 0x200)) == 0x100) {
                        shifter_skip_y = false;
+                       blitfill_idle = true;
                }
+
+               shifter_out = shifter_skip_y ? shifter[2] : shifter[3];
        }
-       shifter_out = shifter_skip_y ? shifter[2] : shifter[3];
 
        blit_cyclecount = 4 - (shifter_skip_b + shifter_skip_y);
        blit_dmacount = ((bltcon0 & 0x800) ? 1 : 0) + ((bltcon0 & 0x400) ? 1 : 0) +
@@ -920,41 +933,29 @@ static void blit_bltset(int con)
                if (log_blitter & 16)
                        activate_debugger();
        }
+
+       if (blit_changed && blit_warned > 0) {
+               blitshifterdebug(bltcon0, false);
+       }
+
 }
 
+#define BLITTER_PIPELINE_BLIT 0x0008
+#define BLITTER_PIPELINE_ADDMOD 0x0010
+#define BLITTER_PIPELINE_LINE 0x0020
+#define BLITTER_PIPELINE_PROCESS 0x0200
+#define BLITTER_PIPELINE_FINISHED 0x0400
+#define BLITTER_PIPELINE_LASTDTODO 0x0800
+#define BLITTER_PIPELINE_LASTD 0x1000
+#define BLITTER_PIPELINE_FIRST 0x2000
+#define BLITTER_PIPELINE_LAST 0x4000
+
 static int get_current_channel(void)
 {
-       static int blit_warned = 100;
-
        if (blit_cyclecounter < 0) {
                return 0;
        }
 
-       if (!blit_faulty && blit_cyclecounter > 0) {
-               int cnt = 0;
-               for (int i = 0; i < 4; i++) {
-                       if (shifter[i])
-                               cnt++;
-               }
-               if (cnt == 0) {
-                       if (blit_warned > 0) {
-                               write_log(_T("Blitter stopped. Shift register empty! PC=%08x\n"), M68K_GETPC);
-                               blit_warned--;
-                       }
-                       blit_faulty = 1;
-               }
-               if (cnt > 1) {
-                       if (blit_warned > 0) {
-                               write_log(_T("Blitter shifter register number of bits %d! CH=%c%c%c%c (%d-%d-%d-%d) PC=%08x\n"),
-                                       cnt,
-                                       ((bltcon0 >> 11) & 1) ? 'A' : '-', ((bltcon0 >> 10) & 1) ? 'B' : '-', ((bltcon0 >> 9) & 1) ? 'C' : '-', ((bltcon0 >> 8) & 1) ? 'D' : '-',
-                                       shifter[0], shifter[1], shifter[2], shifter[3], M68K_GETPC);
-                               blit_warned--;
-                       }
-                       blit_faulty = 1;
-               }
-       }
-
        if (blitline) {
                if (shifter[0]) {
                        // A or idle
@@ -995,34 +996,49 @@ static int get_current_channel(void)
                }
                // D only if A, B and C is not currently active
                if (ddat1use) {
-                       // if stage 3 and C disabled and D enabled: D
-                       if (shifter[2] && !(bltcon0 & 0x200) && (bltcon0 & 0x100)) {
-                               return 4;
-                       }
-                       // if stage 4 and C enabled and D enabled: D
-                       if (shifter[3] && (bltcon0 & 0x200) && (bltcon0 & 0x100)) {
-                               return 4;
+                       // idle fill cycle: 3 = D, 4 = idle
+                       if (blitfill_idle) {
+                               // if stage 4: idle
+                               if (shifter[3]) {
+                                       return 0;
+                               }
+                               // if stage 3: D
+                               if (shifter[2] && (bltcon0 & 0x100)) {
+                                       return 4;
+                               }
+                       } else {
+                               // if stage 3 and C disabled and D enabled: D
+                               if (shifter[2] && !(bltcon0 & 0x200) && (bltcon0 & 0x100)) {
+                                       return 4;
+                               }
+                               // if stage 4 and C enabled and D enabled: D
+                               if (shifter[3] && (bltcon0 & 0x200) && (bltcon0 & 0x100)) {
+                                       return 4;
+                               }
                        }
                }
        }
        return 0;
 }
 
-static uae_u16 blitter_doblit (void)
+static uae_u16 blitter_doblit(uae_u16 dat)
 {
        uae_u32 blitahold;
        uae_u16 bltadat, ddat;
        uae_u8 mt = bltcon0 & 0xFF;
 
        bltadat = blt_info.bltadat;
-       if (blitter_hcounter == 0)
+       if (dat & BLITTER_PIPELINE_FIRST) {
                bltadat &= blt_info.bltafwm;
-       if (blitter_hcounter == blt_info.hblitsize - 1)
+       }
+       if (dat & BLITTER_PIPELINE_LAST) {
                bltadat &= blt_info.bltalwm;
-       if (blitdesc)
+       }
+       if (blitdesc) {
                blitahold = (((uae_u32)bltadat << 16) | blt_info.bltaold) >> blt_info.blitdownashift;
-       else
+       } else {
                blitahold = (((uae_u32)blt_info.bltaold << 16) | bltadat) >> blt_info.blitashift;
+       }
        blt_info.bltaold = bltadat;
 
        ddat = blit_func (blitahold, blt_info.bltbhold, blt_info.bltcdat, mt) & 0xFFFF;
@@ -1036,16 +1052,19 @@ static uae_u16 blitter_doblit (void)
                blitfc = blit_filltable[d >> 8][ifemode + fc1][1];
        }
 
-       if (ddat)
+       if (ddat) {
                blt_info.blitzero = 0;
+       }
 
        return ddat;
 }
 
-static void blitter_next_cycle(void)
+static int blitter_next_cycle(void)
 {
        bool tmp[4];
        bool out = false;
+       bool blitchanged = false;
+       bool dodat = false;
 
        memcpy(tmp, shifter, sizeof(shifter));
        memset(shifter, 0, sizeof(shifter));
@@ -1055,26 +1074,30 @@ static void blitter_next_cycle(void)
                tmp[1] = tmp[0];
                tmp[2] = tmp[0];
                shifter_skip_b_old = shifter_skip_b;
+               blitchanged = true;
        } else if (!shifter_skip_b_old && shifter_skip_b) {
                // if B skip was enabled: A goes nowhere
                tmp[0] = false;
                shifter_skip_b_old = shifter_skip_b;
+               blitchanged = true;
        }
 
        if (shifter_skip_y_old && !shifter_skip_y) {
-               // if Y skip was disbled: X goes both to Y and OUT
+               // if Y skip was disabled: X goes both to Y and OUT
                tmp[3] = tmp[2];
                shifter_skip_y_old = shifter_skip_y;
+               blitchanged = true;
        } else if (!shifter_skip_y_old && shifter_skip_y) {
                // if Y skip was enabled: X goes nowhere
                tmp[2] = false;
                shifter_out = false;
                shifter_skip_y_old = shifter_skip_y;
+               blitchanged = true;
        }
 
        if (shifter_out) {
+               dodat = true;
                if (!blitline) {
-                       ddat1 = blitter_doblit();
                        if (bltcon0 & 0x100) {
                                ddat1use = true;
                        }
@@ -1083,11 +1106,19 @@ static void blitter_next_cycle(void)
                if (blitter_hcounter == blt_info.hblitsize) {
                        blitter_hcounter = 0;
                        blitter_vcounter++;
-                       blitfc = !!(bltcon1 & 0x4);
                        if (blitter_vcounter == blt_info.vblitsize) {
                                shifter_out = false;
-                               blit_cyclecounter = 0;
-                               blitter_maybe_done_early(last_blitter_hpos);
+                               blit_cyclecounter = CYCLECOUNT_FINISHED;
+                               if (!blitline) {
+                                       // do we need final D write?
+                                       if (ddat1use && (bltcon0 & 0x0100)) {
+                                               if (blt_info.blit_finald) {
+                                                       write_log(_T("blit finald already set!?\n"));
+                                               }
+                                               blt_info.blit_finald = 1 + 2;
+                                               blt_info.blit_queued = BLITTER_MAX_PIPELINED_CYCLES;
+                                       }
+                               }
                        }
                }
                shifter[0] = shifter_out;
@@ -1112,10 +1143,21 @@ static void blitter_next_cycle(void)
                }
        }
        shifter_out = out;
+
+       if (blit_cyclecounter > 0 && blitchanged) {
+               static int blit_warned = 100;
+               if (blit_warned > 0) {
+                       if (blitshifterdebug(bltcon0, true)) {
+                               blit_faulty = 1;
+                       }
+                       blit_warned--;
+               }
+       }
+       return dodat;
 }
 
 
-static void blitter_doddma_new(int hpos)
+static void blitter_doddma_new(int hpos, bool addmod)
 {
        record_dma_blit(0x00, ddat1, bltdpt, hpos);
        chipmem_agnus_wput2(bltdpt, ddat1);
@@ -1123,13 +1165,13 @@ static void blitter_doddma_new(int hpos)
 
        if (!blitline) {
                bltdpt += blit_add;
-               if (blitter_hcounter == 0) {
+               if (addmod) {
                        bltdpt += blit_modaddd;
                }
        }
 }
 
-static void blitter_dodma_new(int ch, int hpos)
+static void blitter_dodma_new(int ch, int hpos, bool addmod)
 {
        uae_u16 dat, reg;
        uae_u32 *addr;
@@ -1137,7 +1179,7 @@ static void blitter_dodma_new(int ch, int hpos)
 
        switch (ch)
        {
-       case 1:
+       case 1: // A
                reg = 0x74;
                record_dma_blit(reg, 0, bltapt, hpos);
                blt_info.bltadat = dat = chipmem_wget_indirect(bltapt);
@@ -1147,7 +1189,7 @@ static void blitter_dodma_new(int ch, int hpos)
                mod = blit_modadda;
                alloc_cycle_blitter(hpos, &bltapt, 1);
                break;
-       case 2:
+       case 2: // B
                reg = 0x72;
                record_dma_blit(reg, 0, bltbpt, hpos);
                blt_info.bltbdat = dat = chipmem_wget_indirect(bltbpt);
@@ -1162,7 +1204,7 @@ static void blitter_dodma_new(int ch, int hpos)
                blt_info.bltbold = blt_info.bltbdat;
                alloc_cycle_blitter(hpos, &bltbpt, 2);
                break;
-       case 3:
+       case 3: // C
                reg = 0x70;
                record_dma_blit(reg, 0, bltcpt, hpos);
                blt_info.bltcdat = dat = chipmem_wget_indirect(bltcpt);
@@ -1178,19 +1220,22 @@ static void blitter_dodma_new(int ch, int hpos)
 
        if (!blitline) {
                (*addr) += blit_add;
-               if (blitter_hcounter + 1 == blt_info.hblitsize) {
+               if (addmod) {
                        (*addr) += mod;
                }
        }
 }
 
 
-static bool blitter_idle_cycle_register_write(uaecptr addr, uae_u16 v)
+static bool blitter_idle_cycle_register_write(uaecptr addr, uae_u32 v)
 {
        addrbank *ab = &get_mem_bank(addr);
        if (ab != &custom_bank)
                return false;
        addr &= 0x1fe;
+       if (v == 0xffffffff) {
+               v = last_custom_value1;
+       }
        if (addr == 0x40) {
                bltcon0 = v;
                blit_bltset(1);
@@ -1203,7 +1248,7 @@ static bool blitter_idle_cycle_register_write(uaecptr addr, uae_u16 v)
        return false;
 }
 
-static bool decide_blitter_idle(int lasthpos, int hpos, uaecptr addr, uae_u16 value)
+static bool decide_blitter_idle(int lasthpos, int hpos, uaecptr addr, uae_u32 value)
 {
        markidlecycle(last_blitter_hpos);
        if (addr != 0xffffffff && lasthpos + 1 == hpos) {
@@ -1214,12 +1259,9 @@ static bool decide_blitter_idle(int lasthpos, int hpos, uaecptr addr, uae_u16 va
        return false;
 }
 
-void decide_blitter(int until_hpos)
-{
-       decide_blitter_maybe_write(until_hpos, 0xffffffff, 0xffff);
-}
+uae_u16 blitter_pipe[256];
 
-bool decide_blitter_maybe_write(int until_hpos, uaecptr addr, uae_u16 value)
+static bool decide_blitter_maybe_write2(int until_hpos, uaecptr addr, uae_u32 value)
 {
        bool written = false;
        int hsync = until_hpos < 0;
@@ -1248,10 +1290,6 @@ bool decide_blitter_maybe_write(int until_hpos, uaecptr addr, uae_u16 value)
                return false;
        }
 
-       if (!blt_info.blit_main && !blt_info.blit_finald) {
-               goto end;
-       }
-
        if (log_blitter && blitter_delayed_debug) {
                blitter_delayed_debug = 0;
                blitter_dump();
@@ -1261,110 +1299,252 @@ bool decide_blitter_maybe_write(int until_hpos, uaecptr addr, uae_u16 value)
                return false;
        }
 
-       while (hpos < until_hpos) {
 
-               int c = get_current_channel();
+       while (hpos < until_hpos) {
+               bool cycle_allocated = false;
 
+               // dma transfers and processing
                for (;;) {
-                       int v = canblit(hpos);
-
-                       // final D idle cycle
-                       // does not need free bus
-                       if (blt_info.blit_finald > 1) {
-                               blt_info.blit_finald--;
+                       if (blt_info.blit_queued > 0) {
+                               blt_info.blit_queued--;
                        }
-
-                       // copper bltsize write needs one cycle (any cycle) delay
-                       // does not need free bus
-                       if (blit_waitcyclecounter) {
-                               blit_waitcyclecounter = 0;
-                               break;
+                       uae_u16 dat = blitter_pipe[hpos];
+                       if (dat) {
+                               blitter_pipe[hpos] = 0;
                        }
-
-                       if (v <= 0) {
-                               blit_misscyclecounter++;
+                       if (!(dat & CYCLE_PIPE_BLITTER)) {
                                break;
                        }
+                       cycle_line_pipe[hpos] = 0;
 
-                       if (blt_info.blit_finald == 1) {
-                               // final D write
-                               blitter_doddma_new(hpos);
-                               blitter_done(hpos);
+                       if (dat & CYCLE_PIPE_CPUSTEAL) {
+                               if (debug_dma) {
+                                       record_dma_event(DMA_EVENT_CPUBLITTERSTOLEN, hpos, vpos);
+                               }
                                break;
                        }
 
-                       if (blt_info.blit_main) {
-                               blit_totalcyclecounter++;
-                               blit_cyclecounter++;
-                               if (blit_cyclecounter == 0) {
-                                       shifter_first = true;
+                       int c = dat & 7;
+                       bool line = (dat & BLITTER_PIPELINE_LINE) != 0;
+
+                       // last D write?
+                       if (dat & BLITTER_PIPELINE_LASTD) {
+                               if (debug_dma) {
+                                       record_dma_event(DMA_EVENT_BLITFINALD, hpos, vpos);
+                               }
+                               if (cycle_line_slot[hpos]) {
+                                       write_log("Blitter cycle allocated by %d!?\n", cycle_line_slot[hpos]);
                                }
+                               //activate_debugger();
+                       }
 
-                               blt_info.got_cycle = 1;
+                       // finished?
+                       if (dat & BLITTER_PIPELINE_FINISHED) {
+                               if (line) {
+                                       if (debug_dma) {
+                                               record_dma_event(DMA_EVENT_BLITFINALD, hpos, vpos);
+                                               //activate_debugger();
+                                       }
+                               }
+                       }
 
-                               if (c == 0) {
+                       bool addmod = (dat & BLITTER_PIPELINE_ADDMOD) != 0;
 
-                                       written = decide_blitter_idle(hpos, until_hpos, addr, value);
+                       blit_totalcyclecounter++;
 
-                               } else if (c == 1 && blitline) { // line 1/4 (A, free)
+                       if (c == 0) {
 
-                                       written = decide_blitter_idle(hpos, until_hpos, addr, value);
+                               written = decide_blitter_idle(hpos, until_hpos, addr, value);
 
-                               } else if (c == 3 && blitline) { // line 2/4 (C)
+                       } else if (c == 1 && line) { // line 1/4 (A, free)
 
-                                       record_dma_blit(0x70, 0, bltcpt, hpos);
-                                       blt_info.bltcdat = chipmem_wget_indirect(bltcpt);
-                                       last_custom_value1 = blt_info.bltcdat;
-                                       record_dma_blit_val(blt_info.bltcdat);
-                                       alloc_cycle_blitter(hpos, &bltcpt, 3);
+                               written = decide_blitter_idle(hpos, until_hpos, addr, value);
 
-                               } else if (c == 5 && blitline) { // line 3/4 (free)
+                       } else if (c == 3 && line) { // line 2/4 (C)
 
-                                       blitter_line();
+                               record_dma_blit(0x70, 0, bltcpt, hpos);
+                               blt_info.bltcdat = chipmem_wget_indirect(bltcpt);
+                               last_custom_value1 = blt_info.bltcdat;
+                               record_dma_blit_val(blt_info.bltcdat);
+                               alloc_cycle_blitter(hpos, &bltcpt, 3);
 
-                                       written = decide_blitter_idle(hpos, until_hpos, addr, value);
+                       } else if (c == 5 && line) { // line 3/4 (free)
 
-                               } else if (c == 4 && blitline) { // line 4/4 (D)
+                               blitter_line();
 
-                                       if (ddat1use)
-                                               bltdpt = bltcpt;
-                                       ddat1use = 1;
+                               written = decide_blitter_idle(hpos, until_hpos, addr, value);
 
-                                       blitter_line_proc();
-                                       blitter_nxline();
+                       } else if (c == 4 && line) { // line 4/4 (D)
 
-                                       /* onedot mode and no pixel = bus write access is skipped */
-                                       if (blitlinepixel) {
-                                               record_dma_blit(0x00, blt_info.bltddat, bltdpt, hpos);
-                                               if (blt_info.bltddat)
-                                                       blt_info.blitzero = 0;
-                                               chipmem_wput_indirect(bltdpt, blt_info.bltddat);
-                                               alloc_cycle_blitter(hpos, &bltdpt, 4);
-                                               blitlinepixel = 0;
-                                       }
+                               if (ddat2use) {
                                        bltdpt = bltcpt;
+                               }
+                               ddat2use = 1;
+
+                               blitter_line_proc();
+                               blitter_nxline();
 
+                               /* onedot mode and no pixel = bus write access is skipped */
+                               if (blitlinepixel) {
+                                       record_dma_blit(0x00, blt_info.bltddat, bltdpt, hpos);
+                                       if (blt_info.bltddat) {
+                                               blt_info.blitzero = 0;
+                                       }
+                                       chipmem_wput_indirect(bltdpt, blt_info.bltddat);
+                                       last_custom_value1 = blt_info.bltddat;
+                                       alloc_cycle_blitter(hpos, &bltdpt, 4);
+                                       blitlinepixel = 0;
                                } else {
-                                       // normal mode A to D
+                                       markidlecycle(hpos);
+                               }
+                               bltdpt = bltcpt;
+
+                       } else {
 
-                                       if (c == 4) {
-                                               blitter_doddma_new(hpos);
-                                       } else {
-                                               blitter_dodma_new(c, hpos);
+                               // normal mode channels
+                               if (c == 4) {
+                                       blitter_doddma_new(hpos, addmod);
+                               } else {
+                                       if (c == 5) {
+                                               c = 1;
                                        }
+                                       blitter_dodma_new(c, hpos, addmod);
                                }
+                       }
 
-                               blitter_next_cycle();
+                       if ((dat & BLITTER_PIPELINE_BLIT) && !blitline) {
+                               ddat1 = blitter_doblit(dat);
+                       }
 
-                               // check this after end check because last D write won't cause any problems.
-                               check_channel_mods(hpos, c);
+                       if (dat & BLITTER_PIPELINE_PROCESS) {
+                               blitfc = !!(bltcon1 & 0x4);
                        }
+
+                       // check this after end check because last D write won't cause any problems.
+                       check_channel_mods(hpos, c);
                        break;
                }
 
+               if (blt_info.blit_finald || blt_info.blit_main) {
+
+                       blt_info.blit_queued++;
+
+                       // copper bltsize write needs one cycle (any cycle) delay
+                       // does not need free bus
+                       if (blit_waitcyclecounter > 0) {
+                               blit_waitcyclecounter--;
+                               markidlecycle(hpos);
+                               break;
+                       }
+
+                       // final D idle cycle
+                       // does not need free bus
+                       if (blt_info.blit_finald > 1) {
+                               blt_info.blit_finald--;
+                       }
+
+                       // cycle allocations
+                       for (;;) {
+                               bool cant = blitter_cant_access(hpos);
+                               if (cant) {
+                                       blit_misscyclecounter++;
+                                       break;
+                               }
+
+                               // CPU steals the cycle if CPU has waited long enough and current cyle is not free.
+                               if (!(dmacon & DMA_BLITPRI) && blt_info.nasty_cnt >= BLIT_NASTY_CPU_STEAL_CYCLE_COUNT && ((cycle_line_slot[hpos] & CYCLE_MASK) != 0 || bitplane_dma_access(hpos, 0) != 0)) {
+                                       int offset = get_rga_pipeline(hpos, RGA_PIPELINE_OFFSET_BLITTER);
+                                       cycle_line_pipe[offset] = CYCLE_PIPE_BLITTER | CYCLE_PIPE_CPUSTEAL;
+                                       blitter_pipe[offset] = cycle_line_pipe[offset];
+                                       blt_info.nasty_cnt = -1;
+                                       break;
+                               }
+
+                               if (blt_info.blit_finald == 1) {
+                                       // final D write
+                                       int offset = get_rga_pipeline(hpos, RGA_PIPELINE_OFFSET_BLITTER);
+                                       cycle_line_pipe[offset] = CYCLE_PIPE_BLITTER;
+                                       blitter_pipe[offset] = cycle_line_pipe[offset] | 4 | BLITTER_PIPELINE_ADDMOD | BLITTER_PIPELINE_LASTD;
+                                       blitter_done();
+                                       break;
+                               }
+
+                               if (blt_info.blit_main) {
+                                       blit_cyclecounter++;
+                                       if (blit_cyclecounter == 0) {
+                                               shifter_first = true;
+                                               blitter_next_cycle();
+                                       }
+                                       int c = get_current_channel();
+                                       blt_info.got_cycle = 1;
+
+                                       bool addmod = false;
+                                       if (c == 1 || c == 2 || c == 3) {
+                                               if (blitter_hcounter + 1 == blt_info.hblitsize) {
+                                                       addmod = true;
+                                               }
+                                       } else if (c == 4) {
+                                               if (blitter_hcounter == 0) {
+                                                       addmod = true;
+                                               }
+                                       }
+
+                                       uae_u16 v = CYCLE_PIPE_BLITTER | c | (addmod ? BLITTER_PIPELINE_ADDMOD : 0);
+
+                                       if (blitter_hcounter == 0) {
+                                               v |= BLITTER_PIPELINE_FIRST;
+                                       }
+                                       if (blitter_hcounter == blt_info.hblitsize - 1) {
+                                               v |= BLITTER_PIPELINE_LAST;
+                                       }
+                                       if (blitline) {
+                                               v |= BLITTER_PIPELINE_LINE;
+                                       }
+
+                                       bool doddat = false;
+                                       if (blit_cyclecounter >= 0) {
+                                               doddat = blitter_next_cycle();
+                                       }
+
+                                       int offset = get_rga_pipeline(hpos, RGA_PIPELINE_OFFSET_BLITTER);
+                                       if (cycle_line_pipe[offset]) {
+                                               write_log("Blitter cycle conflict %d\n", cycle_line_pipe[offset]);
+                                       }
+
+                                       if (doddat) {
+                                               v |= BLITTER_PIPELINE_BLIT;
+                                               if (blitter_hcounter == 0) {
+                                                       v |= BLITTER_PIPELINE_PROCESS;
+                                               }
+                                       }
+
+                                       // finished?
+                                       uae_u16 clv = CYCLE_PIPE_BLITTER;
+                                       if (blit_cyclecounter < -CYCLECOUNT_START) {
+                                               v |= BLITTER_PIPELINE_FINISHED;
+                                               if (!blt_info.blit_main) {
+                                                       write_log(_T("blitter blit_main already cleared!?\n"));
+                                               }
+                                               // has final D write?
+                                               if (blt_info.blit_finald) {
+                                                       v |= BLITTER_PIPELINE_LASTDTODO;
+                                                       blitter_done_except_d();
+                                               } else {
+                                                       blitter_done();
+                                               }
+                                       }
+
+                                       cycle_line_pipe[offset] = clv;
+                                       blitter_pipe[offset] = v;
+                               }
+                               break;
+                       }
+
+               }
+
                hpos++;
        }
-end:
+
        last_blitter_hpos = until_hpos;
        reset_channel_mods();
        if (hsync) {
@@ -1373,6 +1553,25 @@ end:
 
        return written;
 }
+
+bool decide_blitter_maybe_write(int until_hpos, uaecptr addr, uae_u32 value)
+{
+       int reg = addr & 0x1fe;
+       // early exit check
+       if (reg != 0x40 && reg != 0x42) {
+               addr = 0xffffffff;
+       } else {
+               return decide_blitter_maybe_write2(until_hpos, addr, value);
+       }
+       return decide_blitter_maybe_write2(until_hpos, addr, value);
+}
+
+void decide_blitter(int until_hpos)
+{
+       decide_blitter_maybe_write2(until_hpos, 0xffffffff, 0xffffffff);
+}
+
+
 #else
 void decide_blitter (int hpos) { }
 #endif
@@ -1401,7 +1600,7 @@ static void blitter_force_finish(bool state)
        } else {
                actually_do_blit();
        }
-       blitter_done(current_hpos());
+       blitter_done();
        dmacon = odmacon;
 }
 
@@ -1459,6 +1658,7 @@ static bool waitingblits (void)
 
 static void blitter_start_init (void)
 {
+       blt_info.blit_queued = 0;
        blit_faulty = 0;
        blt_info.blitzero = 1;
        blitline_started = bltcon1 & 1;
@@ -1468,6 +1668,7 @@ static void blitter_start_init (void)
        shifter_skip_y_old = shifter_skip_y;
        blit_modset();
        ddat1use = 0;
+       ddat2use = 0;
        blt_info.blit_interrupt = 0;
 
        blt_info.bltaold = 0;
@@ -1571,18 +1772,23 @@ void do_blitter(int hpos, int copper, uaecptr pc)
                } else {
                        blitter_hcounter = 0;
                        blitter_vcounter = 0;
-                       blit_cyclecounter = -BLITTER_STARTUP_CYCLES;
-                       blit_waitcyclecounter = copper;
+                       blit_cyclecounter = -CYCLECOUNT_START;
+                       if (copper) {
+                               blit_waitcyclecounter = 2;
+                       } else {
+                               blit_waitcyclecounter = 0;
+                       }
                        blit_maxcyclecounter = blt_info.hblitsize * blt_info.vblitsize + 2;
                        blt_info.blit_pending = 0;
                        blt_info.blit_main = 1;
+                       blt_info.blit_queued = BLITTER_MAX_PIPELINED_CYCLES;
                }
                return;
        }
 
        if (blt_info.vblitsize == 0 || (blitline && blt_info.hblitsize != 2)) {
                if (dmaen(DMA_BLITTER)) {
-                       blitter_done(hpos);
+                       blitter_done();
                }
                return;
        }
@@ -1749,6 +1955,8 @@ void restore_blitter_finish (void)
 {
        record_dma_reset();
        record_dma_reset();
+       blitter_cycle_exact = currprefs.blitter_cycle_exact;
+       immediate_blits = currprefs.immediate_blits;
        if (blt_statefile_type == 0) {
                blt_info.blit_interrupt = 1;
                if (blt_info.blit_pending) {
index 47a0449c88467d49f249af2a87c425c62992dc40..22cab6ea262734b9b4bf43cd7cc651ad5c3d211a 100644 (file)
@@ -311,6 +311,7 @@ uae_u16 vtotal = MAXVPOS_PAL, htotal = MAXHPOS_PAL;
 static int maxvpos_stored, maxhpos_stored;
 static uae_u16 hsstop, hbstrt, hbstop, vsstop, vbstrt, vbstop, hsstrt, vsstrt, hcenter;
 static uae_u16 sprhstrt, sprhstop, bplhstrt, bplhstop, hhpos, hhpos_hpos;
+static uae_u16 sprhstrt_v, sprhstop_v, bplhstrt_v, bplhstop_v;
 static int hhbpl, hhspr;
 static int ciavsyncmode;
 static int diw_hstrt, diw_hstop;
@@ -329,7 +330,6 @@ struct sprite {
        int armed;
        int dmastate;
        int dmacycle;
-       int ptxhpos2, ptxvpos2;
        bool ignoreverticaluntilnextline;
        int width;
 
@@ -358,7 +358,7 @@ static int sprite_sprctlmask;
 int sprite_buffer_res;
 
 uae_u8 cycle_line_slot[MAX_CHIPSETSLOTS + RGA_PIPELINE_ADJUST];
-uae_u8 cycle_line_pipe[MAX_CHIPSETSLOTS + RGA_PIPELINE_ADJUST];
+uae_u16 cycle_line_pipe[MAX_CHIPSETSLOTS + RGA_PIPELINE_ADJUST];
 
 static bool bpldmawasactive;
 static uae_s16 bpl1mod, bpl2mod, bpl1mod_prev, bpl2mod_prev;
@@ -451,6 +451,7 @@ struct copper {
        // following move does not enable COPRS
        int ignore_next;
        int vcmp, hcmp;
+       bool wakecond;
 
        int strobe; /* COPJMP1 / COPJMP2 accessed */
        int last_strobe;
@@ -511,11 +512,12 @@ static int bprun_cycle;
 static int bprun_pipeline_flush_delay;
 static bool plane0;
 static bool harddis;
+static uae_u16 dmal_alloc_mask;
 
 #define RGA_PIPELINE_OFFSET_BPL_WRITE 3
 #define RGA_PIPELINE_OFFSET_COPPER 2
 #define RGA_PIPELINE_OFFSET_SPRITE 3
-#define RGA_PIPELINE_OFFSET_BLITTER 2
+#define RGA_PIPELINE_OFFSET_DMAL 2
 
 struct custom_store custom_storage[256];
 
@@ -577,8 +579,8 @@ static void alloc_cycle(int hpos, int type)
 {
 #ifdef CPUEMU_13
 #if CYCLE_CONFLICT_LOGGING
-       if (cycle_line_slot[hpos]) {
-               write_log(_T("alloc cycle conflict %d: %02x -> %02x\n"), hpos, type, cycle_line_slot[hpos]);
+       if (cycle_line_slot[hpos] && cycle_line_slot[hpos] != type) {
+               write_log(_T("alloc cycle conflict %d: %02x <- %02x\n"), hpos, type, cycle_line_slot[hpos]);
        }
 #endif
        cycle_line_slot[hpos] = type;
@@ -818,7 +820,7 @@ static void add_modulo(int hpos, int nr)
                m2 = bpl2mod_prev;
        }
        if (fmode & 0x4000) {
-               if (((diwstrt >> 8) ^ vposh) & 1) {
+               if (((diwstrt >> 8) ^ (vposh ^ 1)) & 1) {
                        mod = m2;
                } else {
                        mod = m1;
@@ -836,7 +838,7 @@ static void add_modulos(void)
        uae_s16 m1, m2;
 
        if (fmode & 0x4000) {
-               if (((diwstrt >> 8) ^ vposh) & 1) {
+               if (((diwstrt >> 8) ^ (vposh ^ 1)) & 1) {
                        m1 = m2 = bpl2mod;
                } else {
                        m1 = m2 = bpl1mod;
@@ -965,16 +967,16 @@ static void clear_bitplane_pipeline(int type)
        if (type) {
                for (int i = 0; i < maxhpos + RGA_PIPELINE_ADJUST; i++) {
                        if (i < safepos || i >= safepos + count) {
-                               uae_u8 v = cycle_line_pipe[i];
-                               if (v & 0x20) {
+                               uae_u16 v = cycle_line_pipe[i];
+                               if (v & CYCLE_PIPE_BITPLANE) {
                                        cycle_line_pipe[i] = 0;
                                }
                        }
                }
        } else {
                for (int i = safepos; i < safepos + count; i++) {
-                       uae_u8 v = cycle_line_pipe[i];
-                       if (v & 0x20) {
+                       uae_u16 v = cycle_line_pipe[i];
+                       if (v & CYCLE_PIPE_BITPLANE) {
                                cycle_line_pipe[i] = 0;
                        }
                }
@@ -1309,16 +1311,11 @@ STATIC_INLINE int isocs7planes(void)
        return !aga_mode && bplcon0_res == 0 && bplcon0_planes == 7;
 }
 
-STATIC_INLINE int get_rga_pipeline(int hpos, int off)
-{
-       return (hpos + off) % maxhpos;
-}
-
 int get_sprite_dma_rel(int hpos, int off)
 {
        int offset = get_rga_pipeline(hpos, off);
-       uae_u8 v = cycle_line_pipe[offset];
-       if (v & 0x40) {
+       uae_u16 v = cycle_line_pipe[offset];
+       if (v & CYCLE_PIPE_SPRITE) {
                return v & 7;
        }
        return -1;
@@ -1327,8 +1324,8 @@ int get_sprite_dma_rel(int hpos, int off)
 int get_bitplane_dma_rel(int hpos, int off)
 {
        int offset = get_rga_pipeline(hpos, off);
-       uae_u8 v = cycle_line_pipe[offset];
-       if (v & 0x20) {
+       uae_u16 v = cycle_line_pipe[offset];
+       if (v & CYCLE_PIPE_BITPLANE) {
                return v & 0x0f;
        }
        return 0;
@@ -1512,7 +1509,7 @@ static int fetch_warn(int nr, int hpos)
        int add = fetchmode_bytes;
        if (cycle_line_slot[hpos] == CYCLE_REFRESH) {
                if (warned1 >= 0) {
-                       write_log(_T("WARNING: BPL fetch conflicts with strobe refresh slot, hpos %02X!\n"), hpos);
+                       write_log(_T("WARNING: BPL fetch conflictconflicts with strobe refresh slot, hpos %02X!\n"), hpos);
                        warned1--;
                }
                add = refptr_val;
@@ -2403,7 +2400,10 @@ static void update_denise_vars(void)
 static void update_denise(int hpos)
 {
        update_denise_vars();
-       delay_cycles = (((hpos + hpos_hsync_extra) * 2 - DDF_OFFSET) << (toscr_res + toscr_res_mult)) - delay_cycles_right_offset;
+       // FIXME: this assumes we are in cycle-by-cycle mode after denise/lisa hpos=0 condition.
+       if (!delay_cycles_right_offset) {
+               delay_cycles = ((hpos + hpos_hsync_extra) * 2 - DDF_OFFSET) << (toscr_res + toscr_res_mult);
+       }
        if (bplcon0d_old != bplcon0d) {
                bplcon0d_old = bplcon0d;
                record_color_change2(hpos, 0x100 + 0x1000, bplcon0d);
@@ -2473,10 +2473,15 @@ static void beginning_of_plane_block(int hpos, int fm)
 
 #if SPEEDUP
 
+#define MAX_FETCH_TEMP 128
+static uae_u32 fetch_tmp[MAX_FETCH_TEMP];
+
 /* The usual inlining tricks - don't touch unless you know what you are doing. */
 STATIC_INLINE void long_fetch_16(int plane, int nwords, int weird_number_of_bits)
 {
-       uae_u16 *real_pt = (uae_u16*)pfield_xlateptr(bplpt[plane], nwords * 2);
+       uaecptr bpladdr = bplpt[plane];
+       int bploffset = 0;
+       uae_u16 *real_pt = (uae_u16*)pfield_xlateptr(bpladdr, nwords * 2);
        int delay = toscr_delay_adjusted[plane & 1];
        int tmp_nbits = out_nbits;
        uae_u32 shiftbuffer;
@@ -2487,9 +2492,14 @@ STATIC_INLINE void long_fetch_16(int plane, int nwords, int weird_number_of_bits
        bplpt[plane] += nwords * 2;
        bplptx[plane] += nwords * 2;
 
-       if (real_pt == 0) {
-               /* @@@ Don't do this, fall back on chipmem_wget instead.  */
-               return;
+       if (real_pt == NULL) {
+               if (nwords > MAX_FETCH_TEMP) {
+                       return;
+               }
+               for (int i = 0; i < nwords; i++) {
+                       fetch_tmp[i] = chipmem_wget_indirect(bpladdr);
+                       bpladdr += 2;
+               }
        }
 
        shiftbuffer = todisplay2[plane] << delay;
@@ -2521,8 +2531,13 @@ STATIC_INLINE void long_fetch_16(int plane, int nwords, int weird_number_of_bits
                }
                shiftbuffer <<= 16;
                nwords--;
-               fetchval = do_get_mem_word(real_pt);
-               real_pt++;
+               if (real_pt) {
+                       fetchval = do_get_mem_word(real_pt);
+                       real_pt++;
+               } else {
+                       fetchval = fetch_tmp[bploffset];
+                       bploffset++;
+               }
        }
        fetched[plane] = fetchval;
        todisplay2[plane] = shiftbuffer >> delay;
@@ -2532,7 +2547,9 @@ STATIC_INLINE void long_fetch_16(int plane, int nwords, int weird_number_of_bits
 #ifdef AGA
 STATIC_INLINE void long_fetch_32 (int plane, int nwords, int weird_number_of_bits)
 {
-       uae_u32 *real_pt = (uae_u32*)pfield_xlateptr(bplpt[plane] & ~3, nwords * 2);
+       uaecptr bpladdr = bplpt[plane] & ~3;
+       int bploffset = 0;
+       uae_u32 *real_pt = (uae_u32*)pfield_xlateptr(bpladdr, nwords * 2);
        int delay = toscr_delay_adjusted[plane & 1];
        int tmp_nbits = out_nbits;
        uae_u64 shiftbuffer;
@@ -2544,9 +2561,14 @@ STATIC_INLINE void long_fetch_32 (int plane, int nwords, int weird_number_of_bit
        bplpt[plane] += nwords * 2;
        bplptx[plane] += nwords * 2;
 
-       if (real_pt == 0) {
-               /* @@@ Don't do this, fall back on chipmem_wget instead.  */
-               return;
+       if (real_pt == NULL) {
+               if (nwords > MAX_FETCH_TEMP) {
+                       return;
+               }
+               for (int i = 0; i < nwords; i++) {
+                       fetch_tmp[i] = chipmem_lget_indirect(bpladdr);
+                       bpladdr += 4;
+               }
        }
 
        shiftbuffer = todisplay2_aga[plane] << delay;
@@ -2582,7 +2604,13 @@ STATIC_INLINE void long_fetch_32 (int plane, int nwords, int weird_number_of_bit
                        shiftbuffer <<= 16;
                }
                nwords -= 2;
-               fetchval = do_get_mem_long(real_pt);
+               if (real_pt) {
+                       fetchval = do_get_mem_long(real_pt);
+                       real_pt++;
+               } else {
+                       fetchval = fetch_tmp[bploffset];
+                       bploffset++;
+               }
                if (unaligned) {
                        fetchval &= 0x0000ffff;
                        fetchval |= fetchval << 16;
@@ -2590,7 +2618,6 @@ STATIC_INLINE void long_fetch_32 (int plane, int nwords, int weird_number_of_bit
                        fetchval &= 0xffff0000;
                        fetchval |= fetchval >> 16;
                }
-               real_pt++;
 
        }
        fetched_aga[plane] = fetchval;
@@ -2636,7 +2663,9 @@ STATIC_INLINE void aga_shift_n(uae_u64 *p, int n)
 
 STATIC_INLINE void long_fetch_64(int plane, int nwords, int weird_number_of_bits)
 {
-       uae_u32 *real_pt = (uae_u32*)pfield_xlateptr(bplpt[plane] & ~7, nwords * 2);
+       uaecptr bpladdr = bplpt[plane] & ~7;
+       int bploffset = 0;
+       uae_u32 *real_pt = (uae_u32*)pfield_xlateptr(bpladdr, nwords * 2);
        int delay = toscr_delay_adjusted[plane & 1];
        int tmp_nbits = out_nbits;
 #ifdef HAVE_UAE_U128
@@ -2654,9 +2683,14 @@ STATIC_INLINE void long_fetch_64(int plane, int nwords, int weird_number_of_bits
        bplpt[plane] += nwords * 2;
        bplptx[plane] += nwords * 2;
 
-       if (real_pt == 0) {
-               /* @@@ Don't do this, fall back on chipmem_wget instead.  */
-               return;
+       if (real_pt == NULL) {
+               if (nwords * 2 > MAX_FETCH_TEMP) {
+                       return;
+               }
+               for (int i = 0; i < nwords * 2; i++) {
+                       fetch_tmp[i] = chipmem_lget_indirect(bpladdr);
+                       bpladdr += 4;
+               }
        }
 
 #ifdef HAVE_UAE_U128
@@ -2711,39 +2745,43 @@ STATIC_INLINE void long_fetch_64(int plane, int nwords, int weird_number_of_bits
 #ifdef HAVE_UAE_U128
                        shiftbuffer <<= 16;
 #else
-                       aga_shift (shiftbuffer, 16);
+                       aga_shift(shiftbuffer, 16);
 #endif
                }
 
                nwords -= 4;
 
-               uae_u32 *real_pt1, *real_pt2;
+               int offset1 = 0;
+               int offset2 = 1;
                if (unaligned4) {
-                       real_pt1 = real_pt + 1;
-                       real_pt2 = real_pt + 1;
+                       offset1 = 1;
+               }
+               uae_u32 v1, v2;
+               if (real_pt) {
+                       v1 = do_get_mem_long(real_pt + offset1);
+                       v2 = do_get_mem_long(real_pt + offset2);
+                       real_pt += 2;
                } else {
-                       real_pt1 = real_pt;
-                       real_pt2 = real_pt + 1;
+                       v1 = fetch_tmp[bploffset + offset1];
+                       v2 = fetch_tmp[bploffset + offset2];
+                       bploffset += 2;
                }
                if (unaligned2) {
-                       uae_u32 v1 = do_get_mem_long(real_pt1);
-                       uae_u32 v2 = do_get_mem_long(real_pt2);
                        v1 &= 0x0000ffff;
                        v1 |= v1 << 16;
                        v2 &= 0x0000ffff;
                        v2 |= v2 << 16;
                        fetchval = (((uae_u64)v1) << 32) | v2;
                } else {
-                       fetchval = ((uae_u64)do_get_mem_long(real_pt1)) << 32;
-                       fetchval |= do_get_mem_long(real_pt2);
+                       fetchval = ((uae_u64)v1) << 32;
+                       fetchval |= v2;
                }
-               real_pt += 2;
        }
        fetched_aga[plane] = fetchval;
 #ifdef HAVE_UAE_U128
        todisplay2_aga[plane] = shiftbuffer >> delay;
 #else
-       aga_shift_n (shiftbuffer, delay);
+       aga_shift_n(shiftbuffer, delay);
        todisplay2_aga[plane] = shiftbuffer[0];
 #endif
        outword[plane] = outval;
@@ -2877,7 +2915,7 @@ STATIC_INLINE int bpl_select_plane(int hpos, int plane, bool modulo)
                        write_log(_T("bitplane slot already allocated by %04x!\n"), cycle_line_pipe[offset]);
                }
 #endif
-               cycle_line_pipe[offset] = plane | (modulo ? 0x10 : 0) | 0x20;
+               cycle_line_pipe[offset] = plane | (modulo ? CYCLE_PIPE_MODULO : 0) | CYCLE_PIPE_BITPLANE;
                return true;
        }
        return false;
@@ -2941,11 +2979,11 @@ STATIC_INLINE void one_fetch_cycle_0(int hpos, int fm)
                        ddf_stopping = 2;
                }
        }
-       int datreg = cycle_line_pipe[hpos];
+       uae_u16 datreg = cycle_line_pipe[hpos];
        plane0 = false;
-       if (datreg & 0x20) {
-               plane0 = fetch((datreg - 1) & 7, fm, hpos, (datreg & 0x10) != 0);
-       } else if (datreg & 0x80) {
+       if (datreg & CYCLE_PIPE_BITPLANE) {
+               plane0 = fetch((datreg - 1) & 7, fm, hpos, (datreg & CYCLE_PIPE_MODULO) != 0);
+       } else if (datreg & CYCLE_PIPE_COPPER) {
                do_copper_fetch(hpos, datreg);
                cycle_line_pipe[hpos] = 0;
        }
@@ -4011,8 +4049,8 @@ static void reset_decisions_scanline_start(void)
 
        // clear sprite allocations
        for (int i = 0; i < maxhpos; i++) {
-               uae_u8 v = cycle_line_pipe[i];
-               if (v & 0x40) {
+               uae_u16 v = cycle_line_pipe[i];
+               if (v & CYCLE_PIPE_SPRITE) {
                        cycle_line_pipe[i] = 0;
                }
        }
@@ -4639,6 +4677,8 @@ static void init_hz(bool checkvposw)
                minfirstline = maxvpos - 1;
        }
 
+       sprite_vblank_endline = minfirstline - 1;
+
        if (beamcon0 & 0x80) {
                // programmable scanrates (ECS Agnus)
                if (vtotal >= MAXVPOS) {
@@ -4659,7 +4699,6 @@ static void init_hz(bool checkvposw)
                        firstblankedline = maxvpos + 1;
                }
 
-               sprite_vblank_endline = minfirstline - 1;
                maxvpos_nom = maxvpos;
                maxvpos_display = maxvpos;
                equ_vblank_endline = -1;
@@ -4878,13 +4917,13 @@ static bool blit_busy(void)
                if (blt_info.blit_pending)
                        return true;
                // Blitter is considered finished even if last D has not yet been written
-               if (!blt_info.blit_main && blt_info.blit_finald)
+               if (!blt_info.blit_main && blt_info.blit_finald < 2)
                        return false;
        } else if (!aga_mode) {
                if (blt_info.blit_pending)
                        return true;
                // Blitter is considered finished even if last D has not yet been written
-               if (!blt_info.blit_main && blt_info.blit_finald)
+               if (!blt_info.blit_main && blt_info.blit_finald < 2)
                        return false;
 #if 0
                // Blitter busy bug: Blitter nasty off, CPU attempting to steal cycle, Copper started blitter,
@@ -5134,6 +5173,34 @@ static uae_u16 HHPOSR(void)
        return v;
 }
 
+static void HHPOS(int hpos, uae_u16 v)
+{
+       hhpos = v & (MAXHPOS_ROWS - 1);
+       hhpos_hpos = hpos;
+}
+
+static void SPRHSTRT(int hpos, uae_u16 v)
+{
+       sprhstrt = v;
+       sprhstrt_v = v & (MAXVPOS_LINES_ECS - 1);
+}
+static void SPRHSTOP(int hpos, uae_u16 v)
+{
+       sprhstop = v;
+       sprhstop_v = v & (MAXVPOS_LINES_ECS - 1);
+}
+static void BPLHSTRT(int hpos, uae_u16 v)
+{
+       bplhstrt = v;
+       bplhstrt_v = v & (MAXVPOS_LINES_ECS - 1);
+}
+static void BPLHSTOP(int hpos, uae_u16 v)
+{
+       bplhstop = v;
+       bplhstop_v = v & (MAXVPOS_LINES_ECS - 1);
+}
+
+
 static void REFPTR(uae_u16 v)
 {
        /*
@@ -5373,7 +5440,7 @@ static void DMACON(int hpos, uae_u16 v)
        }
 #endif
 
-       if ((dmacon & DMA_BLITPRI) > (oldcon & DMA_BLITPRI) && (blt_info.blit_main || blt_info.blit_finald))
+       if ((dmacon & DMA_BLITPRI) > (oldcon & DMA_BLITPRI) && (blt_info.blit_main || blt_info.blit_finald || blt_info.blit_queued))
                set_special(SPCFLAG_BLTNASTY);
 
        if (dmaen (DMA_BLITTER) && blt_info.blit_pending) {
@@ -5573,14 +5640,16 @@ static void BEAMCON0(uae_u16 v)
 static void varsync(void)
 {
        struct amigadisplay *ad = &adisplays[0];
-       if (!ecs_agnus)
+       if (!ecs_agnus) {
                return;
+       }
 #ifdef PICASSO96
        if (ad->picasso_on && p96refresh_active) {
                vtotal = p96refresh_active;
                return;
        }
 #endif
+       updateextblk();
        if (!(beamcon0 & 0x80))
                return;
        varsync_changed = true;
@@ -5684,8 +5753,13 @@ static void bpldmainitdelay(int hpos)
        setup_fmodes(hpos);
 }
 
+static void BPLCON0(int hpos, uae_u16 v);
 static void bplcon0_denise_change(int hpos, uae_u16 con0)
 {
+       // CHECKME!
+       if (bprun_cycle == 1 && !aga_mode) {
+               BPLCON0(hpos, con0);
+       }
        int np = GET_PLANES(con0);
        if (np == toscr_nr_planes_shifter_new) {
                toscr_nr_planes_shifter = np;
@@ -6065,10 +6139,22 @@ static void BLTCON0L(int hpos, uae_u16 v)
        maybe_blit(hpos, 2); bltcon0 = (bltcon0 & 0xFF00) | (v & 0xFF);
        reset_blit(1);
 }
-static void BLTCON1(int hpos, uae_u16 v) { maybe_blit(hpos, 2); bltcon1 = v; reset_blit(2); }
+static void BLTCON1(int hpos, uae_u16 v) {
+       maybe_blit(hpos, 2);
+       bltcon1 = v;
+       reset_blit(2);
+}
 
-static void BLTAFWM(int hpos, uae_u16 v) { maybe_blit(hpos, 2); blt_info.bltafwm = v; reset_blit(0); }
-static void BLTALWM(int hpos, uae_u16 v) { maybe_blit(hpos, 2); blt_info.bltalwm = v; reset_blit(0); }
+static void BLTAFWM(int hpos, uae_u16 v) {
+       maybe_blit(hpos, 2);
+       blt_info.bltafwm = v;
+       reset_blit(0);
+}
+static void BLTALWM(int hpos, uae_u16 v) {
+       maybe_blit(hpos, 2);
+       blt_info.bltalwm = v;
+       reset_blit(0);
+}
 
 static void BLTAPTH(int hpos, uae_u16 v)
 {
@@ -6164,32 +6250,38 @@ static void BLTSIZE(int hpos, uae_u16 v)
        maybe_blit(hpos, 0);
        blt_info.vblitsize = v >> 6;
        blt_info.hblitsize = v & 0x3F;
-       if (!blt_info.vblitsize)
+       if (!blt_info.vblitsize) {
                blt_info.vblitsize = 1024;
-       if (!blt_info.hblitsize)
+       }
+       if (!blt_info.hblitsize) {
                blt_info.hblitsize = 64;
+       }
        do_blitter(hpos, copper_access, copper_access ? cop_state.ip : M68K_GETPC);
        dcheck_is_blit_dangerous();
 }
 
 static void BLTSIZV(int hpos, uae_u16 v)
 {
-       if (!ecs_agnus)
+       if (!ecs_agnus) {
                return;
+       }
        maybe_blit(hpos, 0);
        blt_info.vblitsize = v & 0x7FFF;
 }
 
 static void BLTSIZH(int hpos, uae_u16 v)
 {
-       if (!ecs_agnus)
+       if (!ecs_agnus) {
                return;
+       }
        maybe_blit(hpos, 0);
        blt_info.hblitsize = v & 0x7FF;
-       if (!blt_info.vblitsize)
+       if (!blt_info.vblitsize) {
                blt_info.vblitsize = 0x8000;
-       if (!blt_info.hblitsize)
+       }
+       if (!blt_info.hblitsize) {
                blt_info.hblitsize = 0x0800;
+       }
        do_blitter(hpos, copper_access, copper_access ? cop_state.ip : M68K_GETPC);
 }
 
@@ -6427,22 +6519,19 @@ static void SPRxPOS(int hpos, uae_u16 v, int num)
        decide_sprites(hpos);
        oldvpos = s->vstart;
        SPRxPOS_1(v, num, hpos);
-       // Superfrog flashing intro bees fix.
-       // if SPRxPOS is written one cycle before sprite's first DMA slot and sprite's vstart matches after
-       // SPRxPOS write, current line's DMA slot's stay idle. DMA decision seems to be done 4 cycles earlier.
-       if (hpos >= SPR_FIRST_HPOS + num * 4 - 4 && hpos <= SPR_FIRST_HPOS + num * 4 - 1 && oldvpos != vpos && (copper_access || currprefs.cpu_memory_cycle_exact)) {
-               s->ptxvpos2 = vpos;
-               s->ptxhpos2 = hpos + 4;
-       }
 }
 
 static void SPRxPTH(int hpos, uae_u16 v, int num)
 {
        decide_fetch_safe(hpos);
        decide_sprites(hpos);
-       if (get_sprite_dma_rel(hpos, -1) != num || (!copper_access && !currprefs.cpu_memory_cycle_exact)) {
+       if (get_sprite_dma_rel(hpos, 1) != num || (!copper_access && !currprefs.cpu_memory_cycle_exact)) {
                spr[num].pt &= 0xffff;
                spr[num].pt |= (uae_u32)v << 16;
+#if 0
+       } else {
+               write_log(_T("SPRxPTH %d\n"), num);
+#endif
        }
 #if SPRITE_DEBUG > 0
        if (vpos >= SPRITE_DEBUG_MINY && vpos <= SPRITE_DEBUG_MAXY && (SPRITE_DEBUG & (1 << num))) {
@@ -6454,9 +6543,13 @@ static void SPRxPTL(int hpos, uae_u16 v, int num)
 {
        decide_fetch_safe(hpos);
        decide_sprites(hpos);
-       if (get_sprite_dma_rel(hpos, -1) != num || (!copper_access && !currprefs.cpu_memory_cycle_exact)) {
+       if (get_sprite_dma_rel(hpos, 1) != num || (!copper_access && !currprefs.cpu_memory_cycle_exact)) {
                spr[num].pt &= ~0xffff;
                spr[num].pt |= v & ~1;
+#if 0
+       } else {
+               write_log(_T("SPRxPTL %d\n"), num);
+#endif
        }
 #if SPRITE_DEBUG > 0
        if (vpos >= SPRITE_DEBUG_MINY && vpos <= SPRITE_DEBUG_MAXY && (SPRITE_DEBUG & (1 << num))) {
@@ -6631,7 +6724,7 @@ static void COLOR_WRITE(int hpos, uae_u16 v, int num)
 }
 
 #if ESTIMATED_FETCH_MODE
-STATIC_INLINE bool bitplane_dma_access(int hpos, int offset)
+bool bitplane_dma_access(int hpos, int offset)
 {
        hpos += offset;
        if (hpos >= maxhpos) {
@@ -6643,7 +6736,7 @@ STATIC_INLINE bool bitplane_dma_access(int hpos, int offset)
        return false;
 }
 #else
-STATIC_INLINE bool bitplane_dma_access(int hpos, int offset)
+bool bitplane_dma_access(int hpos, int offset)
 {
        hpos += offset;
        if (hpos >= maxhpos) {
@@ -6687,16 +6780,40 @@ STATIC_INLINE bool bitplane_dma_access(int hpos, int offset)
 
 bool blitter_cant_access(int hpos)
 {
-       if (bitplane_dma_access(hpos, 0)) {
+       if (!dmaen(DMA_BLITTER)) {
+               return true;
+       }
+       // bitplane dma check
+       int coffset = RGA_PIPELINE_OFFSET_BLITTER;
+       if (bitplane_dma_access(hpos, coffset)) {
                return true;
        }
-       uae_u8 v = cycle_line_slot[hpos];
-       if (v & CYCLE_MASK){
+       // other DMA channel check
+       int offset = get_rga_pipeline(hpos, coffset);
+       if (cycle_line_pipe[offset] != 0 || blitter_pipe[offset] != 0) {
                return true;
        }
+       // static cycles are not in cycle_line_pipe
+       uae_u8 v = cycle_line_slot[offset];
+       if (v == CYCLE_REFRESH || v == CYCLE_STROBE) {
+               return true;
+       }
+       // DMAL is not in cycle_line_pipe
+       if (!dmal_alloc_mask || (hpos & 1) != ((DMAL_FIRST_HPOS - RGA_PIPELINE_OFFSET_BLITTER) & 1)) {
+               return false;
+       }
+       int dmaloffset = hpos - (DMAL_FIRST_HPOS - RGA_PIPELINE_OFFSET_BLITTER);
+       // 3 disk + 4 audio
+       if (dmaloffset >= 0 && dmaloffset < 3 * 2 + 4 * 2) {
+               if (dmal_alloc_mask & (3 << dmaloffset)) {
+                       return true;
+               }
+       }
        return false;
 }
 
+#define COPPER_CYCLE_IDLE 0x8f
+
 static bool copper_cant_read(int hpos, uae_u16 alloc)
 {
        if (!dmaen(DMA_COPPER)) {
@@ -6720,6 +6837,10 @@ static bool copper_cant_read(int hpos, uae_u16 alloc)
 
        if (alloc) {
                cycle_line_pipe[offset] = alloc;
+               // Keep copper cycles, without it blitter would
+               // think copper cycles are free cycles because they
+               // are cleared after copper has processed them
+               blitter_pipe[offset] = CYCLE_PIPE_COPPER;
        }
 
        return false;
@@ -6752,8 +6873,8 @@ static void decide_line(int endhpos)
                                custom_wput_copper(hpos, cop_state.moveptr, cop_state.moveaddr, cop_state.movedata, 0);
                        }
                }
-               uae_u8 datreg = cycle_line_pipe[hpos];
-               if (datreg & 0x80) {
+               uae_u16 datreg = cycle_line_pipe[hpos];
+               if (datreg & CYCLE_PIPE_COPPER) {
                        do_copper_fetch(hpos, datreg);
                        cycle_line_pipe[hpos] = 0;
                }
@@ -6996,7 +7117,7 @@ static int customdelay[]= {
 
 static void do_copper_fetch(int hpos, uae_u8 id)
 {
-       if (id == 0x8f) {
+       if (id == COPPER_CYCLE_IDLE) {
                // copper allocated cycle without DMA request
                switch (cop_state.state)
                {
@@ -7017,6 +7138,7 @@ static void do_copper_fetch(int hpos, uae_u8 id)
 #endif
                        break;
                }
+               alloc_cycle(hpos, CYCLE_COPPER);
                return;
        }
 
@@ -7340,9 +7462,9 @@ static void update_copper(int until_hpos)
                // NOTE: can use odd cycles if DMA request was done during last cycle of line and it was even cycle (always in PAL).
                // request cycle 226 (even), request always completes in 2 cycles = cycle 1 (odd).
                // pipelined copper DMA read?
-               bool copper_dma = (cycle_line_pipe[hpos] & 0x80) != 0;
+               bool copper_dma = (cycle_line_pipe[hpos] & CYCLE_PIPE_COPPER) != 0;
                if (copper_dma) {
-                       uae_u8 v = cycle_line_pipe[hpos];
+                       uae_u16 v = cycle_line_pipe[hpos];
                        do_copper_fetch(hpos, v);
                        cycle_line_pipe[hpos] = 0;
                }
@@ -7437,40 +7559,44 @@ static void update_copper(int until_hpos)
                        break;
 
                        // WAIT: Got IR2, first idle cycle.
-                       // Need free cycle, cycle allocated.
+                       // Need free cycle, cycle not allocated.
                case COP_wait_in2:
                        {
-                               if (copper_cant_read(hpos, 0x8f)) {
+                               if (copper_cant_read(hpos, 0)) {
                                        goto next;
                                }
                                cop_state.state = COP_wait1;
+                               cop_state.wakecond = false;
                        }
                        break;
 
                        // WAIT: Second idle cycle. Wait until comparison matches.
-                       // Need free cycle, cycle allocated.
+                       // Need free cycle, cycle not allocated.
                case COP_wait1:
                        {
-                               int comp = coppercomp(hpos, true);
-                               if (comp < 0) {
-                                       // If we need to wait for later scanline or blitter: no need to emulate copper cycle-by-cycle
-                                       if (cop_state.ir[0] == 0xFFFF && cop_state.ir[1] == 0xFFFE) {
-                                               cop_state.state = COP_waitforever;
+                               if (!cop_state.wakecond) {
+                                       int comp = coppercomp(hpos, true);
+                                       if (comp < 0) {
+                                               // If we need to wait for later scanline or blitter: no need to emulate copper cycle-by-cycle
+                                               if (cop_state.ir[0] == 0xFFFF && cop_state.ir[1] == 0xFFFE) {
+                                                       cop_state.state = COP_waitforever;
+                                               }
+                                               copper_enabled_thisline = 0;
+                                               unset_special(SPCFLAG_COPPER);
+                                               goto next;
                                        }
-                                       copper_enabled_thisline = 0;
-                                       unset_special(SPCFLAG_COPPER);
-                                       goto next;
-                               }
-                       
-                               if (comp) {
-                                       goto next;
+
+                                       if (comp) {
+                                               goto next;
+                                       }
+
+                                       cop_state.wakecond = true;
                                }
 
                                if (copper_cant_read(hpos, 0)) {
                                        goto next;
                                }
 
-                               copper_cant_read(hpos, 0x8f);
                                cop_state.state = COP_wait;
                        }
                        break;
@@ -7487,24 +7613,22 @@ static void update_copper(int until_hpos)
                        break;
 
                        // SKIP: Got IR2. First idle cycle.
-                       // Free cycle needed, cycle allocated.
+                       // Free cycle needed, cycle not allocated.
                case COP_skip_in2:
 
-                       if (copper_cant_read(hpos, 0x8f)) {
+                       if (copper_cant_read(hpos, 0)) {
                                goto next;
                        }
                        cop_state.state = COP_skip1;
                        break;
 
                        // SKIP: Second idle cycle. Check comparison.
-                       // Free cycle needed, cycle allocated.
+                       // Free cycle needed, cycle not allocated.
                case COP_skip1:
                        if (copper_cant_read(hpos, 0)) {
                                goto next;
                        }
 
-                       copper_cant_read(hpos, 0x8f);
-
                        if (!coppercomp(hpos, false)) {
                                cop_state.ignore_next = 1;
                        } else {
@@ -7547,8 +7671,9 @@ static void compute_spcflag_copper(void)
                return;
        if (cop_state.state == COP_wait1) {
                int vp = vpos & (((cop_state.ir[1] >> 8) & 0x7F) | 0x80);
-               if (vp < cop_state.vcmp)
+               if (vp < cop_state.vcmp) {
                        return;
+               }
        }
        last_copper_hpos = current_hpos();
        copper_enabled_thisline = 1;
@@ -7562,15 +7687,17 @@ static void blitter_done_notify_wakeup(uae_u32 temp)
        }
        cop_state.state = COP_wait1;
        compute_spcflag_copper();
+#ifdef DEBUGGER
        if (copper_enabled_thisline) {
                int hpos = current_hpos();
-#ifdef DEBUGGER
-               if (debug_dma)
+               if (debug_dma) {
                        record_dma_event(DMA_EVENT_COPPERWAKE, hpos, vpos);
-               if (debug_copper)
+               }
+               if (debug_copper) {
                        record_copper_blitwait(cop_state.ip - 4, hpos, vpos);
-#endif
+               }
        }
+#endif
 }
 
 void blitter_done_notify(int blitline)
@@ -7578,7 +7705,8 @@ void blitter_done_notify(int blitline)
        if (cop_state.state != COP_bltwait) {
                return;
        }
-       event2_newevent_xx(-1, 2 * CYCLE_UNIT, 0, blitter_done_notify_wakeup);
+       int wait = 1;
+       event2_newevent_xx(-1, wait * CYCLE_UNIT, 0, blitter_done_notify_wakeup);
 }
 
 void do_copper(void)
@@ -7799,9 +7927,9 @@ static void decide_sprite_fetch(int endhpos)
        while (hpos < endhpos) {
                if (hpos >= SPR_FIRST_HPOS - RGA_SPRITE_PIPELINE_DEPTH && hpos < SPR_FIRST_HPOS + MAX_SPRITES * 4) {
 
-                       bool sprite_dma = (cycle_line_pipe[hpos] & 0x40) != 0;
+                       bool sprite_dma = (cycle_line_pipe[hpos] & CYCLE_PIPE_SPRITE) != 0;
                        if (sprite_dma) {
-                               uae_u8 dat = cycle_line_pipe[hpos];
+                               uae_u16 dat = cycle_line_pipe[hpos];
                                do_sprite_fetch(hpos, dat);
                        }
 
@@ -7817,8 +7945,6 @@ static void decide_sprite_fetch(int endhpos)
                                                if (vpos == s->vstart) {
                                                        s->dmastate = 1;
                                                        s->dmacycle = 1;
-                                                       if (s->ptxvpos2 == vpos && hpos < s->ptxhpos2)
-                                                               return;
                                                        if (num == 0 && slot == 0) {
                                                                cursorsprite();
                                                        }
@@ -7842,7 +7968,7 @@ static void decide_sprite_fetch(int endhpos)
 #endif
                                                if (dodma) {
                                                        int offset = get_rga_pipeline(hpos, RGA_PIPELINE_OFFSET_SPRITE);
-                                                       uae_u8 dat = 0x40 | (s->dmastate ? 0x10 : 0x00) | (s->dmacycle == 1 ? 0 : 8) | num;
+                                                       uae_u8 dat = CYCLE_PIPE_SPRITE | (s->dmastate ? 0x10 : 0x00) | (s->dmacycle == 1 ? 0 : 8) | num;
 #if 0
                                                        if (cycle_line_pipe[offset]) {
                                                                write_log(_T("sprite cycle already allocated! %02x\n"), cycle_line_pipe[offset]);
@@ -7878,8 +8004,6 @@ static void init_sprites(void)
 
 static void init_hardware_frame(void)
 {
-       int i;
-
        first_bpl_vpos = -1;
        next_lineno = 0;
        prev_lineno = -1;
@@ -7919,10 +8043,6 @@ static void init_hardware_frame(void)
        plffirstline_total = current_maxvpos();
        first_bplcon0 = 0;
        autoscale_bordercolors = 0;
-
-       for (i = 0; i < MAX_SPRITES; i++) {
-               spr[i].ptxvpos2 = -1;
-       }
 }
 
 void init_hardware_for_drawing_frame(void)
@@ -8757,16 +8877,18 @@ static void events_dmal(int hpos)
 
 static void events_dmal_hsync(void)
 {
+       // 3 disk + 4 audio
        if (dmal)
                write_log (_T("DMAL error!? %04x\n"), dmal);
        dmal = audio_dmal();
-       dmal <<= 6;
+       dmal <<= (3 * 2);
        dmal |= disk_dmal();
+       dmal_alloc_mask = dmal;
        if (!dmal)
                return;
        dmal_hpos = 0;
        if (currprefs.cpu_memory_cycle_exact) {
-               for (int i = 0; i < 6 + 8; i += 2) {
+               for (int i = 0; i < 3 * 2 + 4 * 2; i += 2) {
                        if (dmal & (3 << i)) {
                                alloc_cycle_ext(i + DMAL_FIRST_HPOS, CYCLE_MISC);
                        }
@@ -9759,16 +9881,16 @@ static void hsync_handler_post (bool onvsync)
        decide_vline();
 
        if (ecs_agnus) {
-               if (vpos == sprhstrt) {
+               if (vpos == sprhstrt_v) {
                        hhspr = 1;
                }
-               if (vpos == sprhstop) {
+               if (vpos == sprhstop_v) {
                        hhspr = 0;
                }
-               if (vpos == bplhstrt) {
+               if (vpos == bplhstrt_v) {
                        hhbpl = 1;
                }
-               if (vpos == bplhstop) {
+               if (vpos == bplhstop_v) {
                        hhbpl = 0;
                }
                uae_u16 add = maxhpos - 1;
@@ -10207,6 +10329,7 @@ void custom_reset(bool hardreset, bool keyboardreset)
                blt_info.blit_finald = 0;
                blt_info.blit_pending = 0;
                blt_info.blit_interrupt = 1;
+               blt_info.blit_queued = 0;
                init_sprites();
 
                maxhpos = MAXHPOS_PAL;
@@ -10562,6 +10685,7 @@ writeonly:
                        }
                        decide_line(hpos);
                        decide_fetch_safe(hpos);
+                       decide_blitter(hpos);
                        debug_wputpeek(0xdff000 + addr, l);
                        r = custom_wput_1(hpos, addr, l, 1);
                        
@@ -10848,7 +10972,12 @@ static int REGPARAM2 custom_wput_1 (int hpos, uaecptr addr, uae_u32 value, int n
        case 0x1DE: if (hsstrt != value) { hsstrt = value & (MAXHPOS_ROWS - 1); varsync(); } break;
        case 0x1E0: if (vsstrt != value) { vsstrt = value & (MAXVPOS_LINES_ECS - 1); varsync(); } break;
        case 0x1E2: if (hcenter != value) { hcenter = value & (MAXHPOS_ROWS - 1); varsync(); } break;
-       case 0x1D8: hhpos = value & (MAXHPOS_ROWS - 1); hhpos_hpos = current_hpos();  break;
+
+       case 0x1D0: SPRHSTRT(hpos, value); break;
+       case 0x1D2: SPRHSTOP(hpos, value); break;
+       case 0x1D4: BPLHSTRT(hpos, value); break;
+       case 0x1D6: BPLHSTOP(hpos, value); break;
+       case 0x1D8: HHPOS(hpos, value); break;
 
 #ifdef AGA
        case 0x1FC: FMODE(hpos, value); break;
@@ -11058,11 +11187,11 @@ uae_u8 *restore_custom(uae_u8 *src)
        vsstop = RW;                    /* 1CA VSSTOP */
        vbstrt = RW;                    /* 1CC VBSTRT */
        vbstop = RW;                    /* 1CE VBSTOP */
-       RW;                                             /* 1D0 ? */
-       RW;                                             /* 1D2 ? */
-       RW;                                             /* 1D4 ? */
-       RW;                                             /* 1D6 ? */
-       RW;                                             /* 1D8 ? */
+       SPRHSTRT(-1, RW);               /* 1D0 SPRHSTART */
+       SPRHSTOP(-1, RW);               /* 1D2 SPRHSTOP */
+       BPLHSTRT(-1, RW);               /* 1D4 BPLHSTRT */
+       BPLHSTOP(-1, RW);               /* 1D6 BPLHSTOP */
+       hhpos = RW;                             /* 1D8 HHPOS */
        RW;                                             /* 1DA ? */
        new_beamcon0 = RW;              /* 1DC BEAMCON0 */
        hsstrt = RW;                    /* 1DE HSSTRT */
@@ -11707,52 +11836,45 @@ STATIC_INLINE void decide_fetch_ce(int hpos)
 // blitter idle cycles do count!)
 
 extern int cpu_tracer;
-static int dma_cycle(uaecptr addr, uae_u16 v, int *mode)
+static int dma_cycle(uaecptr addr, uae_u32 value, int *mode)
 {
-       int hpos, hpos_old;
+       int hpos_next, hpos_old;
 
        blt_info.nasty_cnt = 1;
        blt_info.wait_nasty = 0;
-       if (cpu_tracer < 0)
+       if (cpu_tracer < 0) {
                return current_hpos_safe();
-       if (!currprefs.cpu_memory_cycle_exact)
+       }
+       if (!currprefs.cpu_memory_cycle_exact) {
                return current_hpos_safe();
+       }
        while (currprefs.cpu_memory_cycle_exact) {
-               int blitpri = dmacon & DMA_BLITPRI;
                hpos_old = current_hpos_safe();
-               hpos = hpos_old + 1;
-               decide_line(hpos);
-               sync_copper(hpos);
-               decide_fetch_ce(hpos);
+               hpos_next = hpos_old + 1;
+               decide_line(hpos_next);
+               sync_copper(hpos_next);
+               decide_fetch_ce(hpos_next);
                int bpldma = bitplane_dma_access(hpos_old, 0);
-               if (blt_info.blit_main || blt_info.blit_finald) {
-                       if (blt_info.blit_main && !blitpri && blt_info.nasty_cnt >= BLIT_NASTY_CPU_STEAL_CYCLE_COUNT && (cycle_line_slot[hpos_old] & CYCLE_MASK) == 0 && !bpldma) {
-                               alloc_cycle(hpos_old, CYCLE_CPUNASTY);
-                               if (debug_dma && blt_info.nasty_cnt >= BLIT_NASTY_CPU_STEAL_CYCLE_COUNT) {
-                                       record_dma_event(DMA_EVENT_CPUBLITTERSTOLEN, hpos_old, vpos);
-                               }
-                               break;
-                       }
+               if (blt_info.blit_queued) {
 #if 0
-                       decide_blitter(hpos);
+                       decide_blitter(hpos_next);
 #else
                        // CPU write must be done at the same time with blitter idle cycles
-                       if (decide_blitter_maybe_write(hpos, addr, v)) {
+                       if (decide_blitter_maybe_write(hpos_next, addr, value)) {
                                // inform caller that write was already done
-                               *mode = -2;
+                               *mode = -3;
                        }
 #endif
                        // copper may have been waiting for the blitter
-                       sync_copper(hpos);
+                       sync_copper(hpos_next);
                }
                if ((cycle_line_slot[hpos_old] & CYCLE_MASK) == 0 && !bpldma) {
                        alloc_cycle(hpos_old, CYCLE_CPU);
                        break;
                }
-               if (debug_dma && !blitpri && (blt_info.blit_main || blt_info.blit_finald) && blt_info.nasty_cnt >= BLIT_NASTY_CPU_STEAL_CYCLE_COUNT) {
-                       record_dma_event(DMA_EVENT_CPUBLITTERSTEAL, hpos_old, vpos);
+               if (blt_info.nasty_cnt > 0) {
+                       blt_info.nasty_cnt++;
                }
-               blt_info.nasty_cnt++;
                do_cycles(1 * CYCLE_UNIT);
                /* bus was allocated to dma channel, wait for next cycle.. */
        }
@@ -11760,16 +11882,16 @@ static int dma_cycle(uaecptr addr, uae_u16 v, int *mode)
        return hpos_old;
 }
 
-static void sync_ce020 (void)
+static void sync_ce020(void)
 {
        unsigned long c;
        int extra;
 
-       c = get_cycles ();
+       c = get_cycles();
        extra = c & (CYCLE_UNIT - 1);
        if (extra) {
                extra = CYCLE_UNIT - extra;
-               do_cycles (extra);
+               do_cycles(extra);
        }
 }
 
@@ -11782,17 +11904,21 @@ uae_u32 wait_cpu_cycle_read(uaecptr addr, int mode)
        uae_u32 v = 0;
        int hpos;
 
-       hpos = dma_cycle(0xffffffff, 0xffff, NULL);
+       hpos = dma_cycle(addr, 0xffffffff, &mode);
 
 #ifdef DEBUGGER
        if (debug_dma) {
                int reg = 0x1000;
-               if (mode < 0)
+               if (mode == -3) {
+                       reg |= 2;
+                       v = last_custom_value1;
+               } else if (mode < 0) {
                        reg |= 4;
-               else if (mode > 0)
+               } else if (mode > 0) {
                        reg |= 2;
-               else
+               } else {
                        reg |= 1;
+               }
                record_dma_read(reg, addr, hpos, vpos, DMARECORD_CPU, mode == -2 || mode == 2 ? 0 : 1);
        }
        peekdma_data.mask = 0;
@@ -11825,30 +11951,32 @@ uae_u32 wait_cpu_cycle_read(uaecptr addr, int mode)
        }
 #endif
 
+       regs.chipset_latch_rw = regs.chipset_latch_read = v;
+       SETIFCHIP;
+               
        x_do_cycles_post(CYCLE_UNIT, v);
 
-       regs.chipset_latch_rw = regs.chipset_latch_read = v;
-       SETIFCHIP
        return v;
 }
 
-uae_u32 wait_cpu_cycle_read_ce020 (uaecptr addr, int mode)
+uae_u32 wait_cpu_cycle_read_ce020(uaecptr addr, int mode)
 {
        uae_u32 v = 0;
        int hpos;
 
-       sync_ce020 ();
+       sync_ce020();
        hpos = dma_cycle(0xffffffff, 0xffff, NULL);
 
 #ifdef DEBUGGER
        if (debug_dma) {
                int reg = 0x1000;
-               if (mode < 0)
+               if (mode < 0) {
                        reg |= 4;
-               else if (mode > 0)
+               } else if (mode > 0) {
                        reg |= 2;
-               else
+               } else {
                        reg |= 1;
+               }
                record_dma_read(reg, addr, hpos, vpos, DMARECORD_CPU, mode == -2 || mode == 2 ? 0 : 1);
        }
        peekdma_data.mask = 0;
@@ -11880,14 +12008,15 @@ uae_u32 wait_cpu_cycle_read_ce020 (uaecptr addr, int mode)
        }
 #endif
        
+       regs.chipset_latch_rw = regs.chipset_latch_read = v;
+       SETIFCHIP;
+               
        x_do_cycles_post (CYCLE_UNIT, v);
 
-       regs.chipset_latch_rw = regs.chipset_latch_read = v;
-       SETIFCHIP
        return v;
 }
 
-void wait_cpu_cycle_write (uaecptr addr, int mode, uae_u32 v)
+void wait_cpu_cycle_write(uaecptr addr, int mode, uae_u32 v)
 {
        int hpos;
 
@@ -11896,12 +12025,15 @@ void wait_cpu_cycle_write (uaecptr addr, int mode, uae_u32 v)
 #ifdef DEBUGGER
        if (debug_dma) {
                int reg = 0x1100;
-               if (mode < 0)
+               if (mode == -3) {
+                       reg |= 2;
+               } else if (mode < 0) {
                        reg |= 4;
-               else if (mode > 0)
+               } else if (mode > 0) {
                        reg |= 2;
-               else
+               } else {
                        reg |= 1;
+               }
                record_dma_write(reg, v, addr, hpos, vpos, DMARECORD_CPU, 1);
        }
        peekdma_data.mask = 0;
@@ -11910,25 +12042,27 @@ void wait_cpu_cycle_write (uaecptr addr, int mode, uae_u32 v)
        x_do_cycles_pre(CYCLE_UNIT);
 
        if (mode > -2) {
-               if (mode < 0)
+               if (mode < 0) {
                        put_long(addr, v);
-               else if (mode > 0)
+               } else if (mode > 0) {
                        put_word(addr, v);
-               else if (mode == 0)
+               } else if (mode == 0) {
                        put_byte(addr, v);
+               }
        }
 
+       regs.chipset_latch_rw = regs.chipset_latch_write = v;
+       SETIFCHIP;
+               
        x_do_cycles_post (CYCLE_UNIT, v);
 
-       regs.chipset_latch_rw = regs.chipset_latch_write = v;
-       SETIFCHIP
 }
 
-void wait_cpu_cycle_write_ce020 (uaecptr addr, int mode, uae_u32 v)
+void wait_cpu_cycle_write_ce020(uaecptr addr, int mode, uae_u32 v)
 {
        int hpos;
 
-       sync_ce020 ();
+       sync_ce020();
        hpos = dma_cycle(0xffffffff, 0xffff, NULL);
 
 #ifdef DEBUGGER
@@ -11947,19 +12081,21 @@ void wait_cpu_cycle_write_ce020 (uaecptr addr, int mode, uae_u32 v)
 
        x_do_cycles_pre(CYCLE_UNIT);
 
-       if (mode < 0)
-               put_long (addr, v);
-       else if (mode > 0)
-               put_word (addr, v);
-       else if (mode == 0)
-               put_byte (addr, v);
+       if (mode < 0) {
+               put_long(addr, v);
+       } else if (mode > 0) {
+               put_word(addr, v);
+       } else if (mode == 0) {
+               put_byte(addr, v);
+       }
 
+       regs.chipset_latch_rw = regs.chipset_latch_write = v;
+       SETIFCHIP;
+               
        // chipset buffer latches the write, CPU does
        // not need to wait for the chipset cycle to finish.
        x_do_cycles_post(cpucycleunit, v);
 
-       regs.chipset_latch_rw = regs.chipset_latch_write = v;
-       SETIFCHIP
 }
 
 void do_cycles_ce(unsigned long cycles)
@@ -11970,7 +12106,7 @@ void do_cycles_ce(unsigned long cycles)
                decide_line(hpos);
                sync_copper(hpos);
                decide_fetch_ce(hpos);
-               if (blt_info.blit_main || blt_info.blit_finald) {
+               if (blt_info.blit_queued) {
                        decide_blitter(hpos);
                }
                do_cycles(1 * CYCLE_UNIT);
@@ -12004,7 +12140,7 @@ void do_cycles_ce020(unsigned long cycles)
                decide_line(hpos);
                sync_copper(hpos);
                decide_fetch_ce(hpos);
-               if (blt_info.blit_main || blt_info.blit_finald) {
+               if (blt_info.blit_queued) {
                        decide_blitter(hpos);
                }
                if (c < CYCLE_UNIT) {
index 6a6fb00b86cfee5dbbda269aa61a967a8d1a4314..8ef4afc01293a57a9c777d2a47bbf1c9e83ce514 100644 (file)
@@ -24,6 +24,7 @@ struct bltinfo {
     // blitter is active and D may write to visible bitplane addresses
     int blitter_dangerous_bpl;
     int blit_main, blit_finald, blit_pending;
+    int blit_queued;
 };
 
 extern struct bltinfo blt_info;
@@ -43,12 +44,15 @@ extern void blitter_handler (uae_u32);
 extern void build_blitfilltable (void);
 extern void do_blitter (int, int, uaecptr);
 extern void decide_blitter(int hpos);
-extern bool decide_blitter_maybe_write(int hpos, uaecptr addr, uae_u16 v);
-extern void blitter_done_notify (int hpos);
+extern bool decide_blitter_maybe_write(int hpos, uaecptr addr, uae_u32 v);
+extern void blitter_done_notify (int);
 extern void blitter_slowdown (int, int, int, int);
 extern void blitter_check_start (void);
 extern void blitter_reset (void);
 extern void blitter_debugdump(void);
+extern bool blit_steal_cycle(int hpos);
+
+extern uae_u16 blitter_pipe[256];
 
 typedef void blitter_func(uaecptr, uaecptr, uaecptr, uaecptr, struct bltinfo *);
 
index 897e8095c00f4778cbebb74e1c07b8ec24ff5e7a..ced0c4bd6a17c7a4bad6d010802ca29aba738b4e 100644 (file)
@@ -27,7 +27,7 @@
 #define MAXVPOS_LINES_OCS 512
 #define HPOS_SHIFT 3
 
-#define BLIT_NASTY_CPU_STEAL_CYCLE_COUNT 4
+#define BLIT_NASTY_CPU_STEAL_CYCLE_COUNT 3
 
 uae_u32 get_copper_address(int copno);
 
@@ -153,7 +153,6 @@ extern bool programmedmode;
 #define CYCLE_COPPER   6
 #define CYCLE_BLITTER  7
 #define CYCLE_CPU              8
-#define CYCLE_CPUNASTY 9
 #define CYCLE_COPPER_SPECIAL 0x10
 
 #define CYCLE_MASK 0x0f
@@ -241,16 +240,31 @@ extern void compute_framesync(void);
 extern void getsyncregisters(uae_u16 *phsstrt, uae_u16 *phsstop, uae_u16 *pvsstrt, uae_u16 *pvsstop);
 bool blitter_cant_access(int hpos);
 void custom_cpuchange(void);
+bool bitplane_dma_access(int hpos, int offset);
 
 #define RGA_PIPELINE_ADJUST 4
 #define MAX_CHIPSETSLOTS 256
 extern uae_u8 cycle_line_slot[MAX_CHIPSETSLOTS + RGA_PIPELINE_ADJUST];
-extern uae_u8 cycle_line_pipe[MAX_CHIPSETSLOTS + RGA_PIPELINE_ADJUST];
+extern uae_u16 cycle_line_pipe[MAX_CHIPSETSLOTS + RGA_PIPELINE_ADJUST];
+
+#define CYCLE_PIPE_CPUSTEAL 0x8000
+#define CYCLE_PIPE_BLITTER 0x100
+#define CYCLE_PIPE_COPPER 0x80
+#define CYCLE_PIPE_SPRITE 0x40
+#define CYCLE_PIPE_BITPLANE 0x20
+#define CYCLE_PIPE_MODULO 0x10
 
 #define RGA_PIPELINE_MASK 255
 
+#define RGA_PIPELINE_OFFSET_BLITTER 1
+
 extern int rga_pipeline_blitter;
 
+STATIC_INLINE int get_rga_pipeline(int hpos, int off)
+{
+       return (hpos + off) % maxhpos;
+}
+
 struct custom_store
 {
        uae_u16 value;