From 8e0840eaefc536d4525b2ac3bde6462ebf20610b Mon Sep 17 00:00:00 2001 From: Toni Wilen Date: Sun, 16 May 2021 20:23:16 +0300 Subject: [PATCH] Custom emulation update WIP. --- blitter.cpp | 578 +++++++++++++++++++++++++++++++--------------- custom.cpp | 538 ++++++++++++++++++++++++++---------------- include/blitter.h | 8 +- include/custom.h | 20 +- 4 files changed, 753 insertions(+), 391 deletions(-) diff --git a/blitter.cpp b/blitter.cpp index 1f8b5970..bd5fd169 100644 --- a/blitter.cpp +++ b/blitter.cpp @@ -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) { diff --git a/custom.cpp b/custom.cpp index 47a0449c..22cab6ea 100644 --- a/custom.cpp +++ b/custom.cpp @@ -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) { diff --git a/include/blitter.h b/include/blitter.h index 6a6fb00b..8ef4afc0 100644 --- a/include/blitter.h +++ b/include/blitter.h @@ -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 *); diff --git a/include/custom.h b/include/custom.h index 897e8095..ced0c4bd 100644 --- a/include/custom.h +++ b/include/custom.h @@ -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; -- 2.47.3