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;
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;
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:
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)
// (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) {
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);
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;
}
}
/* 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;
}
}
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)
#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;
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--;
}
}
}
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);
}
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) +
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
}
// 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;
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));
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;
}
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;
}
}
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);
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;
switch (ch)
{
- case 1:
+ case 1: // A
reg = 0x74;
record_dma_blit(reg, 0, bltapt, hpos);
blt_info.bltadat = dat = chipmem_wget_indirect(bltapt);
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);
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);
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);
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) {
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;
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();
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) {
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
} else {
actually_do_blit();
}
- blitter_done(current_hpos());
+ blitter_done();
dmacon = odmacon;
}
static void blitter_start_init (void)
{
+ blt_info.blit_queued = 0;
blit_faulty = 0;
blt_info.blitzero = 1;
blitline_started = bltcon1 & 1;
shifter_skip_y_old = shifter_skip_y;
blit_modset();
ddat1use = 0;
+ ddat2use = 0;
blt_info.blit_interrupt = 0;
blt_info.bltaold = 0;
} 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;
}
{
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) {
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;
int armed;
int dmastate;
int dmacycle;
- int ptxhpos2, ptxvpos2;
bool ignoreverticaluntilnextline;
int width;
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;
// following move does not enable COPRS
int ignore_next;
int vcmp, hcmp;
+ bool wakecond;
int strobe; /* COPJMP1 / COPJMP2 accessed */
int last_strobe;
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];
{
#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;
m2 = bpl2mod_prev;
}
if (fmode & 0x4000) {
- if (((diwstrt >> 8) ^ vposh) & 1) {
+ if (((diwstrt >> 8) ^ (vposh ^ 1)) & 1) {
mod = m2;
} else {
mod = m1;
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;
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;
}
}
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;
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;
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;
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);
#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;
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;
}
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;
#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;
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;
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;
fetchval &= 0xffff0000;
fetchval |= fetchval >> 16;
}
- real_pt++;
}
fetched_aga[plane] = fetchval;
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
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
#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;
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;
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;
}
// 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;
}
}
minfirstline = maxvpos - 1;
}
+ sprite_vblank_endline = minfirstline - 1;
+
if (beamcon0 & 0x80) {
// programmable scanrates (ECS Agnus)
if (vtotal >= MAXVPOS) {
firstblankedline = maxvpos + 1;
}
- sprite_vblank_endline = minfirstline - 1;
maxvpos_nom = maxvpos;
maxvpos_display = maxvpos;
equ_vblank_endline = -1;
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,
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)
{
/*
}
#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) {
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;
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;
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)
{
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);
}
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))) {
{
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))) {
}
#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) {
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) {
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)) {
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;
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;
}
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)
{
#endif
break;
}
+ alloc_cycle(hpos, CYCLE_COPPER);
return;
}
// 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;
}
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;
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 {
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;
}
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)
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)
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);
}
if (vpos == s->vstart) {
s->dmastate = 1;
s->dmacycle = 1;
- if (s->ptxvpos2 == vpos && hpos < s->ptxhpos2)
- return;
if (num == 0 && slot == 0) {
cursorsprite();
}
#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]);
static void init_hardware_frame(void)
{
- int i;
-
first_bpl_vpos = -1;
next_lineno = 0;
prev_lineno = -1;
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)
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);
}
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;
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;
}
decide_line(hpos);
decide_fetch_safe(hpos);
+ decide_blitter(hpos);
debug_wputpeek(0xdff000 + addr, l);
r = custom_wput_1(hpos, addr, l, 1);
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;
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 */
// 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.. */
}
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);
}
}
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;
}
#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;
}
#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;
#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;
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
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)
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);
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) {