diff --git a/src/blitter.cpp b/src/blitter.cpp index 82ee4b75..9b8b1454 100644 --- a/src/blitter.cpp +++ b/src/blitter.cpp @@ -11,12 +11,28 @@ #include "sysdeps.h" #include "options.h" +#include "uae.h" #include "memory.h" #include "custom.h" +#include "events.h" #include "newcpu.h" #include "blitter.h" #include "blit.h" #include "savestate.h" +//#include "debug.h" + +// 1 = logging +// 2 = no wait detection +// 4 = no D +// 8 = instant +// 16 = activate debugger if weird things +// 32 = logging (no line) + +#if BLITTER_DEBUG +int log_blitter = 1 | 16; +#else +int log_blitter = 0; +#endif /* we must not change ce-mode while blitter is running.. */ static int blitter_cycle_exact, immediate_blits; @@ -274,6 +290,82 @@ void build_blitfilltable (void) } } +STATIC_INLINE void record_dma_blit (uae_u16 reg, uae_u16 dat, uae_u32 addr, int hpos) +{ +#ifdef DEBUGGER + if (debug_dma) + record_dma (reg, dat, addr, hpos, vpos, DMARECORD_BLITTER, blitline ? 2 : (blitfill ? 1 : 0)); + if (memwatch_enabled) { + if (reg == 0) { + uae_u32 mask = MW_MASK_BLITTER_D_N; + if (blitfill) + mask = MW_MASK_BLITTER_D_F; + if (blitline) + mask = MW_MASK_BLITTER_D_L; + debug_wputpeekdma_chipram(addr, dat, mask, reg, 0x054); + } else if (reg == 0x70) { + debug_wgetpeekdma_chipram(addr, dat, MW_MASK_BLITTER_C, reg, 0x48); + } else if (reg == 0x72) { + debug_wgetpeekdma_chipram(addr, dat, MW_MASK_BLITTER_B, reg, 0x4c); + } else if (reg == 0x74) { + debug_wgetpeekdma_chipram(addr, dat, MW_MASK_BLITTER_A, reg, 0x52); + } + } +#endif +} + +static void blitter_debugsave(int copper, uaecptr pc) +{ + debug_bltcon0 = bltcon0; + debug_bltcon1 = bltcon1; + debug_bltsizev = blt_info.vblitsize; + debug_bltsizeh = blt_info.hblitsize; + debug_bltapt = bltapt; + debug_bltbpt = bltbpt; + debug_bltcpt = bltcpt; + debug_bltdpt = bltdpt; + debug_bltadat = blt_info.bltadat; + debug_bltbdat = blt_info.bltbdat; + debug_bltcdat = blt_info.bltcdat; + debug_bltamod = blt_info.bltamod; + debug_bltbmod = blt_info.bltbmod; + debug_bltcmod = blt_info.bltcmod; + debug_bltdmod = blt_info.bltdmod; + debug_bltafwm = blt_info.bltafwm; + debug_bltalwm = blt_info.bltalwm; + debug_bltpc = pc; + debug_bltcop = copper; +} + +static void blitter_dump (void) +{ + //int chipsize = currprefs.chipmem_size; + //console_out_f(_T("PT A=%08X B=%08X C=%08X D=%08X\n"), bltapt, bltbpt, bltcpt, bltdpt); + //console_out_f(_T("CON0=%04X CON1=%04X DAT A=%04X B=%04X C=%04X\n"), + // bltcon0, bltcon1, blt_info.bltadat, blt_info.bltbdat, blt_info.bltcdat); + //console_out_f(_T("AFWM=%04X ALWM=%04X MOD A=%04X B=%04X C=%04X D=%04X\n"), + // blt_info.bltafwm, blt_info.bltalwm, + // blt_info.bltamod & 0xffff, blt_info.bltbmod & 0xffff, blt_info.bltcmod & 0xffff, blt_info.bltdmod & 0xffff); + //console_out_f(_T("PC=%08X DMA=%d\n"), m68k_getpc(), dmaen (DMA_BLITTER)); + + //if (((bltcon0 & 0x800) && bltapt >= chipsize) || ((bltcon0 & 0x400) && bltbpt >= chipsize) || + // ((bltcon0 & 0x200) && bltcpt >= chipsize) || ((bltcon0 & 0x100) && bltdpt >= chipsize)) + // console_out_f(_T("PT outside of chipram\n")); +} + +void blitter_debugdump(void) +{ + //console_out(_T("Blitter registers at start:\n")); + //console_out_f(_T("PT A=%08X B=%08X C=%08X D=%08X\n"), debug_bltapt, debug_bltbpt, debug_bltcpt, debug_bltdpt); + //console_out_f(_T("CON0=%04X CON1=%04X DAT A=%04X B=%04X C=%04X\n"), + // debug_bltcon0, debug_bltcon1, debug_bltadat, debug_bltbdat, debug_bltcdat); + //console_out_f(_T("AFWM=%04X ALWM=%04X MOD A=%04X B=%04X C=%04X D=%04X\n"), + // debug_bltafwm, debug_bltalwm, debug_bltamod, debug_bltbmod, debug_bltcmod, debug_bltdmod); + //console_out_f(_T("COP=%d PC=%08X\n"), debug_bltcop, debug_bltpc); + //console_out(_T("Blitter registers now:\n")); + //blitter_dump(); +} + STATIC_INLINE const int *get_ch (void) { if (blit_faulty) @@ -325,6 +417,12 @@ STATIC_INLINE int canblit (int hpos) return 1; } +static void markidlecycle (int hpos) +{ + //if (debug_dma) + //record_dma_event (DMA_EVENT_BLITSTARTFINISH, hpos, vpos); +} + static void reset_channel_mods (void) { if (bltptxpos < 0) @@ -367,22 +465,23 @@ static void check_channel_mods (int hpos, int ch) // (or cycle where last D write would have been if // ONEDOT was active) -static void blitter_interrupt (int done) +static void blitter_interrupt (int hpos, int done) { if (blit_interrupt) return; if (!done && (!blitter_cycle_exact || immediate_blits || currprefs.cpu_model >= 68030 || currprefs.cachesize || currprefs.m68k_speed < 0)) return; blit_interrupt = 1; - send_interrupt (6); + send_interrupt (6, 4 * CYCLE_UNIT); } static void blitter_done (int hpos) { ddat1use = ddat2use = 0; bltstate = blit_startcycles == 0 || !blitter_cycle_exact || immediate_blits ? BLT_done : BLT_init; - blitter_interrupt (1); + blitter_interrupt (hpos, 1); blitter_done_notify (hpos); + markidlecycle (hpos); event2_remevent (ev2_blitter); unset_special (SPCFLAG_BLTNASTY); blitter_dangerous_bpl = 0; @@ -590,6 +689,8 @@ static void blitter_dofast_desc (void) STATIC_INLINE void blitter_read (void) { if (bltcon0 & 0x200) { + if (!dmaen (DMA_BLITTER)) + return; blt_info.bltcdat = chipmem_wget_indirect (bltcpt); last_custom_value1 = blt_info.bltcdat; } @@ -602,6 +703,9 @@ STATIC_INLINE void blitter_write (void) blt_info.blitzero = 0; /* D-channel state has no effect on linedraw, but C must be enabled or nothing is drawn! */ if (bltcon0 & 0x200) { + if (!dmaen (DMA_BLITTER)) + return; + //last_custom_value1 = blt_info.bltddat; blitter writes are not stored chipmem_wput_indirect (bltdpt, blt_info.bltddat); } bltstate = BLT_next; @@ -691,7 +795,7 @@ STATIC_INLINE void blitter_nxline (void) bltstate = BLT_read; } -#ifdef CPUEMU_13 +//#ifdef CPUEMU_13 static int blitter_cyclecounter; static int blitter_hcounter1, blitter_hcounter2; @@ -783,7 +887,7 @@ static void decide_blitter_line (int hsync, int hpos) reset_channel_mods (); } -#endif +//#endif static void actually_do_blit (void) { @@ -819,10 +923,25 @@ static void blitter_doit (void) blitter_done (current_hpos()); return; } + if (log_blitter) { + if (!blitter_dontdo) + actually_do_blit (); + else + bltstate = BLT_done; + } else { + actually_do_blit (); + } + blitter_done (current_hpos ()); +} - actually_do_blit(); - - blitter_done(current_hpos()); +static int makebliteventtime(int delay) +{ + if (delay) { + delay += delay - (int)(delay * (1 + currprefs.blitter_speed_throttle) + 0.5); + if (delay <= 0) + delay = 1; + } + return delay; } void blitter_handler (uae_u32 data) @@ -840,13 +959,192 @@ void blitter_handler (uae_u32 data) } blitter_stuck = 0; if (blit_slowdown > 0 && !immediate_blits) { - event2_newevent (ev2_blitter, blit_slowdown, 0); + event2_newevent (ev2_blitter, makebliteventtime(blit_slowdown), 0); blit_slowdown = -1; return; } blitter_doit (); } +//#ifdef CPUEMU_13 + +STATIC_INLINE uae_u16 blitter_doblit (void) +{ + uae_u32 blitahold; + uae_u16 bltadat, ddat; + uae_u8 mt = bltcon0 & 0xFF; + + bltadat = blt_info.bltadat; + if (blitter_hcounter1 == 0) + bltadat &= blt_info.bltafwm; + if (blitter_hcounter1 == blt_info.hblitsize - 1) + bltadat &= blt_info.bltalwm; + if (blitdesc) + blitahold = (((uae_u32)bltadat << 16) | blt_info.bltaold) >> blt_info.blitdownashift; + 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; + + if ((bltcon1 & 0x18)) { + uae_u16 d = ddat; + int ifemode = blitife ? 2 : 0; + int fc1 = blit_filltable[d & 255][ifemode + blitfc][1]; + ddat = (blit_filltable[d & 255][ifemode + blitfc][0] + + (blit_filltable[d >> 8][ifemode + fc1][0] << 8)); + blitfc = blit_filltable[d >> 8][ifemode + fc1][1]; + } + + if (ddat) + blt_info.blitzero = 0; + + return ddat; +} + + +STATIC_INLINE void blitter_doddma (int hpos) +{ + uae_u16 d; + + if (blit_dmacount2 == 0) { + d = blitter_doblit (); + } else if (ddat2use) { + d = ddat2; + ddat2use = 0; + } else if (ddat1use) { + d = ddat1; + ddat1use = 0; + } else { + static int warn = 10; + if (warn > 0) { + warn--; + write_log (_T("BLITTER: D-channel without nothing to do?\n")); + } + return; + } + record_dma_blit (0x00, d, bltdpt, hpos); + //last_custom_value1 = d; blitter writes are not stored + chipmem_agnus_wput2 (bltdpt, d); + alloc_cycle_blitter (hpos, &bltdpt, 4); + bltdpt += blit_add; + blitter_hcounter2++; + if (blitter_hcounter2 == blt_info.hblitsize) { + blitter_hcounter2 = 0; + bltdpt += blit_modaddd; + blitter_vcounter2++; + if (blit_dmacount2 == 0) // d-only + blitter_vcounter1++; + if (blitter_vcounter2 > blitter_vcounter1) + blitter_vcounter1 = blitter_vcounter2; + } + if (blit_ch == 1) + blitter_hcounter1 = blitter_hcounter2; +} + +STATIC_INLINE void blitter_dodma (int ch, int hpos) +{ + uae_u16 dat, reg; + uae_u32 addr; + + switch (ch) + { + case 1: + blt_info.bltadat = dat = chipmem_wget_indirect (bltapt); + last_custom_value1 = blt_info.bltadat; + addr = bltapt; + bltapt += blit_add; + reg = 0x74; + alloc_cycle_blitter (hpos, &bltapt, 1); + break; + case 2: + blt_info.bltbdat = dat = chipmem_wget_indirect (bltbpt); + last_custom_value1 = blt_info.bltbdat; + addr = bltbpt; + bltbpt += blit_add; + if (blitdesc) + blt_info.bltbhold = (((uae_u32)blt_info.bltbdat << 16) | blt_info.bltbold) >> blt_info.blitdownbshift; + else + blt_info.bltbhold = (((uae_u32)blt_info.bltbold << 16) | blt_info.bltbdat) >> blt_info.blitbshift; + blt_info.bltbold = blt_info.bltbdat; + reg = 0x72; + alloc_cycle_blitter (hpos, &bltbpt, 2); + break; + case 3: + blt_info.bltcdat = dat = chipmem_wget_indirect (bltcpt); + last_custom_value1 = blt_info.bltcdat; + addr = bltcpt; + bltcpt += blit_add; + reg = 0x70; + alloc_cycle_blitter (hpos, &bltcpt, 3); + break; + default: + abort (); + } + + blitter_cyclecounter++; + if (blitter_cyclecounter >= blit_dmacount2) { + blitter_cyclecounter = 0; + ddat2 = ddat1; + ddat2use = ddat1use; + ddat1use = 0; + ddat1 = blitter_doblit (); + if (bltcon0 & 0x100) + ddat1use = 1; + blitter_hcounter1++; + if (blitter_hcounter1 == blt_info.hblitsize) { + blitter_hcounter1 = 0; + if (bltcon0 & 0x800) + bltapt += blit_modadda; + if (bltcon0 & 0x400) + bltbpt += blit_modaddb; + if (bltcon0 & 0x200) + bltcpt += blit_modaddc; + blitter_vcounter1++; + blitfc = !!(bltcon1 & 0x4); + } + } + record_dma_blit (reg, dat, addr, hpos); +} + +int blitter_need (int hpos) +{ + int c; + if (bltstate == BLT_done) + return 0; + if (!dmaen (DMA_BLITTER)) + return 0; + c = channel_state (blit_cyclecounter); + return c; +} + +static void do_startcycles (int hpos) +{ + int vhpos = last_blitter_hpos; + while (vhpos < hpos) { + int v = canblit (vhpos); + vhpos++; + if (v > 0) { + blit_startcycles--; + if (blit_startcycles == 0) { + if (blit_faulty) + blit_faulty = -1; + bltstate = BLT_done; + blit_final = 0; + do_blitter(vhpos, 0, blit_waitpc); + blit_startcycles = 0; + blit_cyclecounter = 0; + blit_waitcyclecounter = 0; + if (blit_faulty) + blit_faulty = 1; + return; + } + } else { + markidlecycle (hpos); + } + } +} + void decide_blitter (int hpos) { int hsync = hpos < 0; @@ -856,7 +1154,7 @@ void decide_blitter (int hpos) blt_delayed_irq--; if (blt_delayed_irq <= 0) { blt_delayed_irq = 0; - send_interrupt(6); + send_interrupt(6, 2 * CYCLE_UNIT); } } @@ -868,6 +1166,9 @@ void decide_blitter (int hpos) return; } + if (blit_startcycles > 0) + do_startcycles (hpos); + if (bltstate == BLT_done) return; @@ -876,9 +1177,120 @@ void decide_blitter (int hpos) if (hpos < 0) hpos = maxhpos; -} -static void blitter_force_finish(void) + if (blitline) { + blt_info.got_cycle = 1; + decide_blitter_line (hsync, hpos); + return; + } + + while (last_blitter_hpos < hpos) { + int c; + + c = channel_state (blit_cyclecounter); + + for (;;) { + int v; + + v = canblit (last_blitter_hpos); + + // copper bltsize write needs one cycle (any cycle) delay + if (blit_waitcyclecounter) { + blit_waitcyclecounter = 0; + markidlecycle (last_blitter_hpos); + break; + } + // idle cycles require free bus. + // Final empty cycle does not, unless it is fill mode that requires extra idle cycle + // (CPU can still use this cycle) +#if 1 + if ((blit_cyclecounter < 0 || !blit_final || (blitfill && blit_cycle_diagram_fill[blit_ch][0])) && ((c == 0 && v == 0) || v < 0)) { + blit_misscyclecounter++; + blitter_nasty++; + break; + } +#else + if ((c == 0 && v == 0) || v < 0) { + if (blit_cyclecounter < 0 || !blit_final) { + blit_misscyclecounter++; + break; + } + if (blitfill && blit_cycle_diagram_fill[blit_ch][0]) { + blit_misscyclecounter++; + blitter_nasty++; + break; + } + } +#endif + if (blit_frozen) { + blit_misscyclecounter++; + break; + } + + if (c == 0) { + blt_info.got_cycle = 1; + blit_cyclecounter++; + if (blit_cyclecounter == 0) + blit_final = 0; + blit_totalcyclecounter++; + /* check if blit with zero channels has ended */ + if (blit_ch == 0 && blit_cyclecounter >= blit_maxcyclecounter) { + blitter_done (last_blitter_hpos); + return; + } + markidlecycle (last_blitter_hpos); + break; + } + + blitter_nasty++; + + if (v <= 0) { + blit_misscyclecounter++; + break; + } + + blt_info.got_cycle = 1; + if (c == 4) { + blitter_doddma (last_blitter_hpos); + blit_cyclecounter++; + blit_totalcyclecounter++; + } else { + if (blitter_vcounter1 < blt_info.vblitsize) { + blitter_dodma (c, last_blitter_hpos); + } + blit_cyclecounter++; + blit_totalcyclecounter++; + } + + if (blitter_vcounter1 >= blt_info.vblitsize && blitter_vcounter2 >= blt_info.vblitsize) { + if (!ddat1use && !ddat2use) { + blitter_done (last_blitter_hpos); + return; + } + } + // check this after end check because last D write won't cause any problems. + check_channel_mods (last_blitter_hpos, c); + break; + } + + if (dmaen (DMA_BLITTER) && !blit_final && (blitter_vcounter1 == blt_info.vblitsize || (blitter_vcounter1 == blt_info.vblitsize - 1 && blitter_hcounter1 == blt_info.hblitsize - 1 && blit_dmacount2 == 0))) { + if (channel_pos (blit_cyclecounter - 1) == blit_diag[0] - 1) { + blitter_interrupt (last_blitter_hpos, 0); + blit_cyclecounter = 0; + blit_final = 1; + } + } + last_blitter_hpos++; + } + reset_channel_mods (); + if (hsync) + last_blitter_hpos = 0; +} +//#else +//void decide_blitter (int hpos) { } +//#endif + +static void blitter_force_finish(bool state) { uae_u16 odmacon; if (bltstate == BLT_done) @@ -889,21 +1301,22 @@ static void blitter_force_finish(void) */ odmacon = dmacon; dmacon |= DMA_MASTER | DMA_BLITTER; + if (state) + write_log (_T("forcing blitter finish\n")); if (blitter_cycle_exact && !immediate_blits) { int rounds = 10000; while (bltstate != BLT_done && rounds > 0) { - memset(cycle_line, 0, sizeof cycle_line); - decide_blitter(-1); + memset (cycle_line, 0, sizeof cycle_line); + decide_blitter (-1); rounds--; } if (rounds == 0) - write_log(_T("blitter froze!?\n")); + write_log (_T("blitter froze!?\n")); blit_startcycles = 0; + } else { + actually_do_blit (); } - else { - actually_do_blit(); - } - blitter_done(current_hpos()); + blitter_done (current_hpos ()); dmacon = odmacon; } } @@ -916,6 +1329,7 @@ static bool invstate (void) static void blit_bltset (int con) { int i; + const int *olddiag = blit_diag; if (con & 2) { blitdesc = bltcon1 & 2; @@ -957,9 +1371,49 @@ static void blit_bltset (int con) blit_diag = blitfill && blit_cycle_diagram_fill[blit_ch][0] ? blit_cycle_diagram_fill[blit_ch] : blit_cycle_diagram[blit_ch]; } + // on the fly switching fillmode from extra cycle to non-extra: blitter freezes + // non-extra cycle to extra cycle: does not freeze but cycle diagram goes weird, + // extra free cycle changes to another D write.. + // (Absolute Inebriation vector cube inside semi-filled vector object requires freezing blitter.) + if (!savestate_state && invstate ()) { + static int freezes = 10; + int isen = blit_diag >= &blit_cycle_diagram_fill[0][0] && blit_diag <= &blit_cycle_diagram_fill[15][0]; + int iseo = olddiag >= &blit_cycle_diagram_fill[0][0] && olddiag <= &blit_cycle_diagram_fill[15][0]; + if (iseo != isen) { + if (freezes > 0) { + write_log (_T("BLITTER: on the fly %d (%d) -> %d (%d) switch! PC=%08x\n"), original_ch, iseo, blit_ch, isen, M68K_GETPC); + freezes--; + } + } + if (original_fill == isen) { + blit_frozen = 0; // switched back to original fill mode? unfreeze + } else if (iseo && !isen) { + blit_frozen = 1; + write_log (_T("BLITTER: frozen! %d (%d) -> %d (%d) %08X\n"), original_ch, iseo, blit_ch, isen, M68K_GETPC); + //if (log_blitter & 16) + //activate_debugger (); + } else if (!iseo && isen) { + if (!dmaen (DMA_BLITTER)) // subtle shades / nuance bootblock bug + blit_frozen = 1; + //if (log_blitter) + //write_log (_T("BLITTER: on the fly %d (%d) -> %d (%d) switch\n"), original_ch, iseo, blit_ch, isen); + } + } + // on the fly switching from CH=1 to CH=D -> blitter stops writing (Rampage/TEK) // currently just switch to no-channels mode, better than crashing the demo.. if (!savestate_state && invstate ()) { + static uae_u8 changetable[32 * 32]; + int o = original_ch + (original_fill ? 16 : 0); + int n = blit_ch + (blitfill ? 16 : 0); + if (o != n) { + if (changetable[o * 32 + n] < 10) { + changetable[o * 32 + n]++; + write_log (_T("BLITTER: channel mode changed while active (%02X->%02X) PC=%08x\n"), o, n, M68K_GETPC); + //if (log_blitter & 16) + //activate_debugger (); + } + } if (blit_ch == 13 && original_ch == 1) { blit_faulty = 1; } @@ -1062,11 +1516,20 @@ static void blitter_start_init (void) } } -void do_blitter (int hpos) +static void do_blitter2(int hpos, int copper, uaecptr pc) { int cycles; int cleanstart; + if ((log_blitter & 2)) { + if (bltstate != BLT_done) { + if (blit_final) { + write_log (_T("blitter was already active! PC=%08x\n"), M68K_GETPC); + //activate_debugger(); + } + } + } + cleanstart = 0; if (bltstate == BLT_done) { if (blit_faulty > 0) @@ -1105,9 +1568,9 @@ void do_blitter (int hpos) bltstate = BLT_init; blit_slowdown = 0; - unset_special(SPCFLAG_BLTNASTY); - if (dmaen(DMA_BLITPRI)) - set_special(SPCFLAG_BLTNASTY); + unset_special (SPCFLAG_BLTNASTY); + if (dmaen (DMA_BLITPRI)) + set_special (SPCFLAG_BLTNASTY); if (dmaen (DMA_BLITTER)) bltstate = BLT_work; @@ -1115,6 +1578,27 @@ void do_blitter (int hpos) blit_maxcyclecounter = 0x7fffffff; blit_waitcyclecounter = 0; + if (blitter_cycle_exact) { + if (immediate_blits) { + if (dmaen (DMA_BLITTER)) + blitter_doit (); + return; + } + if (log_blitter & 8) { + blitter_handler (0); + } else { + blitter_hcounter1 = blitter_hcounter2 = 0; + blitter_vcounter1 = blitter_vcounter2 = 0; + if (blit_nod) + blitter_vcounter2 = blt_info.vblitsize; + blit_cyclecounter = -BLITTER_STARTUP_CYCLES; + blit_waitcyclecounter = copper; + blit_startcycles = 0; + blit_maxcyclecounter = blt_info.hblitsize * blt_info.vblitsize + 2; + } + return; + } + if (blt_info.vblitsize == 0 || (blitline && blt_info.hblitsize != 2)) { if (dmaen (DMA_BLITTER)) blitter_done (hpos); @@ -1132,7 +1616,7 @@ void do_blitter (int hpos) } blit_cyclecounter = cycles * (blit_dmacount2 + (blit_nod ? 0 : 1)); - event2_newevent (ev2_blitter, blit_cyclecounter, 0); + event2_newevent (ev2_blitter, makebliteventtime(blit_cyclecounter), 0); } void blitter_check_start (void) @@ -1146,11 +1630,41 @@ void blitter_check_start (void) } } -void maybe_blit2 (int hack) +void do_blitter(int hpos, int copper, uaecptr pc) { - if (dmaen (DMA_BLITTER)) { + if (bltstate == BLT_done || !blitter_cycle_exact) { + do_blitter2(hpos, copper, pc); + return; + } + if (!dmaen (DMA_BLITTER) || !blt_info.got_cycle) + return; + // previous blit may have last write cycle left + // and we must let it finish + blit_startcycles = BLITTER_STARTUP_CYCLES; + blit_waitcyclecounter = copper; + blit_waitpc = pc; +} + +void maybe_blit (int hpos, int hack) +{ + static int warned = 10; + + reset_channel_mods (); + + if (bltstate == BLT_done) + return; + + if (savestate_state) + return; + + if (dmaen (DMA_BLITTER) && (currprefs.cpu_model >= 68020 || !currprefs.cpu_memory_cycle_exact)) { bool doit = false; - if (currprefs.waiting_blits) { // automatic + if (currprefs.waiting_blits == 3) { // always + doit = true; + } else if (currprefs.waiting_blits == 2) { // noidle + if (blit_dmacount == blit_diag[0] && (regs.spcflags & SPCFLAG_BLTNASTY)) + doit = true; + } else if (currprefs.waiting_blits == 1) { // automatic if (blit_dmacount == blit_diag[0] && (regs.spcflags & SPCFLAG_BLTNASTY)) doit = true; else if (currprefs.m68k_speed < 0) @@ -1162,10 +1676,28 @@ void maybe_blit2 (int hack) } } - if (hack == 1 && (int)get_cycles() - (int)blit_firstline_cycles < 0) - return; + if (warned && dmaen (DMA_BLITTER) && blt_info.got_cycle) { + warned--; + //debugtest (DEBUGTEST_BLITTER, _T("program does not wait for blitter tc=%d\n"), blit_cyclecounter); + if (log_blitter) + warned = 0; + if (log_blitter & 2) { + warned = 10; + write_log (_T("program does not wait for blitter PC=%08x\n"), M68K_GETPC); + //activate_debugger (); + //blitter_done (hpos); + } + } - blitter_handler (0); + if (blitter_cycle_exact) { + decide_blitter (hpos); + return; + } + + if (hack == 1 && (int)get_cycles() - (int)blit_firstline_cycles < 0) + return; + + blitter_handler (0); } void check_is_blit_dangerous (uaecptr *bplpt, int planes, int words) @@ -1191,6 +1723,10 @@ int blitnasty (void) return 0; if (!dmaen (DMA_BLITTER)) return 0; + if (blitter_cycle_exact) { + blitter_force_finish(false); + return -1; + } if (blit_last_cycle >= blit_diag[0] && blit_dmacount == blit_diag[0]) return 0; cycles = (get_cycles () - blit_first_cycle) / CYCLE_UNIT; @@ -1238,6 +1774,8 @@ void blitter_reset (void) void restore_blitter_finish (void) { + //record_dma_reset (); + //record_dma_reset (); if (blt_statefile_type == 0) { blit_interrupt = 1; if (bltstate == BLT_init) { @@ -1248,6 +1786,9 @@ void restore_blitter_finish (void) blt_delayed_irq = 3; intreq &= ~0x0040; } + } else { + last_blitter_hpos = 0; + blit_modset (); } } @@ -1281,7 +1822,7 @@ uae_u8 *save_blitter (int *len, uae_u8 *dstptr) if (bltstate != BLT_done && bltstate != BLT_init) { write_log (_T("blitter is active, forcing immediate finish\n")); /* blitter is active just now but we don't have blitter state support yet */ - blitter_force_finish(); + blitter_force_finish(true); forced = 2; } if (dstptr) @@ -1300,18 +1841,28 @@ uae_u8 *restore_blitter_new (uae_u8 *src) { uae_u8 state; blt_statefile_type = 1; + blitter_cycle_exact = restore_u8 (); state = restore_u8 (); blit_first_cycle = restore_u32 (); blit_last_cycle = restore_u32 (); + blit_waitcyclecounter = restore_u32 (); + blit_startcycles = restore_u32 (); + blit_maxcyclecounter = restore_u32 (); blit_firstline_cycles = restore_u32 (); blit_cyclecounter = restore_u32 (); blit_slowdown = restore_u32 (); + blit_misscyclecounter = restore_u32 (); + blitter_hcounter1 = restore_u16 (); + blitter_hcounter2 = restore_u16 (); + blitter_vcounter1 = restore_u16 (); + blitter_vcounter2 = restore_u16 (); blit_ch = restore_u8 (); blit_dmacount = restore_u8 (); blit_dmacount2 = restore_u8 (); blit_nod = restore_u8 (); + blit_final = restore_u8 (); blitfc = restore_u8 (); blitife = restore_u8 (); @@ -1321,6 +1872,9 @@ uae_u8 *restore_blitter_new (uae_u8 *src) blt_info.blitdownashift = restore_u8 (); ddat1use = restore_u8 (); + ddat2use = restore_u8 (); + ddat1 = restore_u16 (); + ddat2 = restore_u16 (); blitline = restore_u8 (); blitfill = restore_u8 (); @@ -1328,13 +1882,19 @@ uae_u8 *restore_blitter_new (uae_u8 *src) blineb = restore_u16 (); blinea_shift = restore_u8 (); blitonedot = restore_u8 (); + blitlinepixel = restore_u8 (); blitsing = restore_u8 (); + blitlinepixel = restore_u8 (); blit_interrupt = restore_u8 (); blt_delayed_irq = restore_u8 (); blt_info.blitzero = restore_u8 (); + blt_info.got_cycle = restore_u8 (); + blit_frozen = restore_u8 (); blit_faulty = restore_u8 (); original_ch = restore_u8 (); + original_fill = restore_u8 (); + original_line = restore_u8 (); blit_diag = set_cycle_diagram_type (restore_u8 ()); @@ -1344,8 +1904,15 @@ uae_u8 *restore_blitter_new (uae_u8 *src) blitter_nasty = restore_u8 (); bltstate = BLT_done; - if (state > 0) - do_blitter (0); + if (!blitter_cycle_exact) { + if (state > 0) + do_blitter(0, 0, 0); + } else { + if (state == 1) + bltstate = BLT_init; + else if (state == 2) + bltstate = BLT_work; + } return src; } @@ -1358,6 +1925,7 @@ uae_u8 *save_blitter_new (int *len, uae_u8 *dstptr) dstbak = dst = xmalloc (uae_u8, 1000); uae_u8 state; + save_u8 (blitter_cycle_exact ? 1 : 0); if (bltstate == BLT_done) state = 0; else if (bltstate == BLT_init) @@ -1372,14 +1940,23 @@ uae_u8 *save_blitter_new (int *len, uae_u8 *dstptr) save_u32 (blit_first_cycle); save_u32 (blit_last_cycle); + save_u32 (blit_waitcyclecounter); + save_u32 (blit_startcycles); + save_u32 (blit_maxcyclecounter); save_u32 (blit_firstline_cycles); save_u32 (blit_cyclecounter); save_u32 (blit_slowdown); + save_u32 (blit_misscyclecounter); + save_u16 (blitter_hcounter1); + save_u16 (blitter_hcounter2); + save_u16 (blitter_vcounter1); + save_u16 (blitter_vcounter2); save_u8 (blit_ch); save_u8 (blit_dmacount); save_u8 (blit_dmacount2); save_u8 (blit_nod); + save_u8 (blit_final); save_u8 (blitfc); save_u8 (blitife); @@ -1389,6 +1966,9 @@ uae_u8 *save_blitter_new (int *len, uae_u8 *dstptr) save_u8 (blt_info.blitdownashift); save_u8 (ddat1use); + save_u8 (ddat2use); + save_u16 (ddat1); + save_u16 (ddat2); save_u8 (blitline); save_u8 (blitfill); @@ -1396,13 +1976,19 @@ uae_u8 *save_blitter_new (int *len, uae_u8 *dstptr) save_u16 (blineb); save_u8 (blinea_shift); save_u8 (blitonedot); + save_u8 (blitlinepixel); save_u8 (blitsing); + save_u8 (blitlinepixel); save_u8 (blit_interrupt); save_u8 (blt_delayed_irq); save_u8 (blt_info.blitzero); + save_u8 (blt_info.got_cycle); + save_u8 (blit_frozen); save_u8 (blit_faulty); save_u8 (original_ch); + save_u8 (original_fill); + save_u8 (original_line); save_u8 (get_cycle_diagram_type (blit_diag)); save_u16 (0x1234); diff --git a/src/custom.cpp b/src/custom.cpp index f43e0806..a60f3495 100644 --- a/src/custom.cpp +++ b/src/custom.cpp @@ -17,13 +17,15 @@ #include "options.h" #include "uae.h" +#include "gensound.h" #include "audio.h" +#include "sounddep/sound.h" +#include "events.h" #include "memory.h" #include "custom.h" #include "newcpu.h" #include "cia.h" #include "disk.h" -#include "savestate.h" #include "blitter.h" #include "xwin.h" #include "inputdevice.h" @@ -4249,6 +4251,7 @@ void compute_vsynctime (void) } if (currprefs.produce_sound > 1) { double clk = svpos * shpos * fake_vblank_hz; + write_log (_T("SNDRATE %.1f*%.1f*%.6f=%.6f\n"), svpos, shpos, fake_vblank_hz, clk); devices_update_sound(clk, syncadjust); } devices_update_sync(svpos, syncadjust); @@ -4327,11 +4330,9 @@ void compute_framesync(void) if (islace) { vblank_hz = vblank_hz_lace; - } - else if (lof_current) { + } else if (lof_current) { vblank_hz = vblank_hz_lof; - } - else { + } else { vblank_hz = vblank_hz_shf; } @@ -4374,9 +4375,9 @@ void compute_framesync(void) v = cr->rate; if (v > 0) { changed_prefs.chipset_refreshrate = currprefs.chipset_refreshrate = v; - cfgfile_parse_lines(&changed_prefs, cr->commands, -1); + cfgfile_parse_lines (&changed_prefs, cr->commands, -1); if (cr->commands[0]) - write_log(_T("CMD2: '%s'\n"), cr->commands); + write_log (_T("CMD2: '%s'\n"), cr->commands); } } else { if (cr->locked == false) @@ -4403,7 +4404,7 @@ void compute_framesync(void) vidinfo->drawbuffer.inyoffset = -1; if (beamcon0 & 0x80) { - int res = GET_RES_AGNUS(bplcon0); + int res = GET_RES_AGNUS (bplcon0); int vres = islace ? 1 : 0; int res2, vres2; @@ -4434,8 +4435,7 @@ void compute_framesync(void) vidinfo->drawbuffer.inheight = ((firstblankedline < maxvpos ? firstblankedline : maxvpos) - minfirstline + 1) << vres2; vidinfo->drawbuffer.inheight2 = vidinfo->drawbuffer.inheight; - } - else { + } else { vidinfo->drawbuffer.inwidth = AMIGA_WIDTH_MAX << currprefs.gfx_resolution; vidinfo->drawbuffer.extrawidth = currprefs.gfx_extrawidth ? currprefs.gfx_extrawidth : -1; @@ -4857,7 +4857,7 @@ STATIC_INLINE uae_u16 DMACONR (int hpos) decide_line (hpos); decide_fetch_safe (hpos); dmacon &= ~(0x4000 | 0x2000); - dmacon |= ((blit_interrupt || (!blit_interrupt && currprefs.cs_agnusbltbusybug)) ? 0 : 0x4000) + dmacon |= ((blit_interrupt || (!blit_interrupt && currprefs.cs_agnusbltbusybug && !blt_info.got_cycle)) ? 0 : 0x4000) | (blt_info.blitzero ? 0x2000 : 0); return dmacon; } @@ -4865,10 +4865,10 @@ STATIC_INLINE uae_u16 INTENAR (void) { return intena; } -//uae_u16 INTREQR (void) -//{ -// return intreq; -//} +uae_u16 INTREQR (void) +{ + return intreq; +} STATIC_INLINE uae_u16 ADKCONR (void) { return adkcon; @@ -5444,10 +5444,13 @@ bool INTREQ_0 (uae_u16 v) uae_u16 old = intreq; setclr (&intreq, v); - if ((old & 0x0800) && !(intreq & 0x0800)) - return false; - if ((v & 0x8000) && old != v) + if ((old & 0x0800) && !(intreq & 0x0800)) { + //serial_rbf_clear(); + } + + if ((v & 0x8000) && old != v) { doint_delay(); + } return true; } @@ -5466,6 +5469,8 @@ static void ADKCON (int hpos, uae_u16 v) DISK_update_adkcon (hpos, v); setclr (&adkcon, v); audio_update_adkmasks (); + //if ((v >> 11) & 1) + //serial_uartbreak ((adkcon >> 11) & 1); } static void BEAMCON0 (uae_u16 v) @@ -5910,7 +5915,7 @@ static void FNULL (uae_u16 v) static void BLTADAT (int hpos, uae_u16 v) { - maybe_blit (0); + maybe_blit (hpos, 0); blt_info.bltadat = v; } @@ -5921,7 +5926,7 @@ static void BLTADAT (int hpos, uae_u16 v) */ static void BLTBDAT (int hpos, uae_u16 v) { - maybe_blit(0); + maybe_blit (hpos, 0); int shift = bltcon1 >> 12; @@ -5933,72 +5938,120 @@ static void BLTBDAT (int hpos, uae_u16 v) blt_info.bltbdat = v; blt_info.bltbold = v; } -static void BLTCDAT (int hpos, uae_u16 v) { maybe_blit (0); blt_info.bltcdat = v; reset_blit(0); } +static void BLTCDAT (int hpos, uae_u16 v) { maybe_blit (hpos, 0); blt_info.bltcdat = v; reset_blit (0); } -static void BLTAMOD (int hpos, uae_u16 v) { maybe_blit (1); blt_info.bltamod = uae_s16(v & 0xFFFE); reset_blit (0); } -static void BLTBMOD (int hpos, uae_u16 v) { maybe_blit (1); blt_info.bltbmod = uae_s16(v & 0xFFFE); reset_blit (0); } -static void BLTCMOD (int hpos, uae_u16 v) { maybe_blit (1); blt_info.bltcmod = uae_s16(v & 0xFFFE); reset_blit (0); } -static void BLTDMOD (int hpos, uae_u16 v) { maybe_blit (1); blt_info.bltdmod = uae_s16(v & 0xFFFE); reset_blit (0); } +static void BLTAMOD (int hpos, uae_u16 v) { maybe_blit (hpos, 1); blt_info.bltamod = (uae_s16)(v & 0xFFFE); reset_blit (0); } +static void BLTBMOD (int hpos, uae_u16 v) { maybe_blit (hpos, 1); blt_info.bltbmod = (uae_s16)(v & 0xFFFE); reset_blit (0); } +static void BLTCMOD (int hpos, uae_u16 v) { maybe_blit (hpos, 1); blt_info.bltcmod = (uae_s16)(v & 0xFFFE); reset_blit (0); } +static void BLTDMOD (int hpos, uae_u16 v) { maybe_blit (hpos, 1); blt_info.bltdmod = (uae_s16)(v & 0xFFFE); reset_blit (0); } -static void BLTCON0 (int hpos, uae_u16 v) { maybe_blit (2); bltcon0 = v; reset_blit(1); } +static void BLTCON0 (int hpos, uae_u16 v) { maybe_blit (hpos, 2); bltcon0 = v; reset_blit (1); } /* The next category is "Most useless hardware register". * And the winner is... */ static void BLTCON0L (int hpos, uae_u16 v) { - if (!(currprefs.chipset_mask & CSMASK_ECS_AGNUS)) + if (! (currprefs.chipset_mask & CSMASK_ECS_AGNUS)) return; // ei voittoa. - maybe_blit (2); bltcon0 = (bltcon0 & 0xFF00) | (v & 0xFF); + maybe_blit (hpos, 2); bltcon0 = (bltcon0 & 0xFF00) | (v & 0xFF); reset_blit (1); } -static void BLTCON1 (int hpos, uae_u16 v) { maybe_blit (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 (2); blt_info.bltafwm = v; reset_blit (0); } -static void BLTALWM (int hpos, uae_u16 v) { maybe_blit (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 (0); - bltapt = (bltapt & 0xffff) | ((uae_u32)v << 16); + maybe_blit (hpos, 0); + if (bltstate != BLT_done && currprefs.blitter_cycle_exact && currprefs.cpu_memory_cycle_exact) { + bltptx = (bltapt & 0xffff) | ((uae_u32)v << 16); + bltptxpos = hpos; + bltptxc = 1; + } else { + bltapt = (bltapt & 0xffff) | ((uae_u32)v << 16); + } } static void BLTAPTL (int hpos, uae_u16 v) { - maybe_blit (0); - bltapt = (bltapt & ~0xffff) | (v & 0xFFFE); + maybe_blit (hpos, 0); + if (bltstate != BLT_done && currprefs.blitter_cycle_exact && currprefs.cpu_memory_cycle_exact) { + bltptx = (bltapt & ~0xffff) | (v & 0xFFFE); + bltptxpos = hpos; + bltptxc = 1; + } else { + bltapt = (bltapt & ~0xffff) | (v & 0xFFFE); + } } static void BLTBPTH (int hpos, uae_u16 v) { - maybe_blit (0); - bltbpt = (bltbpt & 0xffff) | ((uae_u32)v << 16); + maybe_blit (hpos, 0); + if (bltstate != BLT_done && currprefs.blitter_cycle_exact && currprefs.cpu_memory_cycle_exact) { + bltptx = (bltbpt & 0xffff) | ((uae_u32)v << 16); + bltptxpos = hpos; + bltptxc = 2; + } else { + bltbpt = (bltbpt & 0xffff) | ((uae_u32)v << 16); + } } static void BLTBPTL (int hpos, uae_u16 v) { - maybe_blit (0); - bltbpt = (bltbpt & ~0xffff) | (v & 0xFFFE); + maybe_blit (hpos, 0); + if (bltstate != BLT_done && currprefs.blitter_cycle_exact && currprefs.cpu_memory_cycle_exact) { + bltptx = (bltbpt & ~0xffff) | (v & 0xFFFE); + bltptxpos = hpos; + bltptxc = 2; + } else { + bltbpt = (bltbpt & ~0xffff) | (v & 0xFFFE); + } } static void BLTCPTH (int hpos, uae_u16 v) { - maybe_blit (0); - bltcpt = (bltcpt & 0xffff) | ((uae_u32)v << 16); + maybe_blit (hpos, 0); + if (bltstate != BLT_done && currprefs.blitter_cycle_exact && currprefs.cpu_memory_cycle_exact) { + bltptx = (bltcpt & 0xffff) | ((uae_u32)v << 16); + bltptxpos = hpos; + bltptxc = 3; + } else { + bltcpt = (bltcpt & 0xffff) | ((uae_u32)v << 16); + } } static void BLTCPTL (int hpos, uae_u16 v) { - maybe_blit (0); - bltcpt = (bltcpt & ~0xffff) | (v & 0xFFFE); + maybe_blit (hpos, 0); + if (bltstate != BLT_done && currprefs.blitter_cycle_exact && currprefs.cpu_memory_cycle_exact) { + bltptx = (bltcpt & ~0xffff) | (v & 0xFFFE); + bltptxpos = hpos; + bltptxc = 3; + } else { + bltcpt = (bltcpt & ~0xffff) | (v & 0xFFFE); + } } static void BLTDPTH (int hpos, uae_u16 v) { - maybe_blit (0); - bltdpt = (bltdpt & 0xffff) | ((uae_u32)v << 16); + maybe_blit (hpos, 0); + if (bltstate != BLT_done && currprefs.blitter_cycle_exact && currprefs.cpu_memory_cycle_exact) { + bltptx = (bltdpt & 0xffff) | ((uae_u32)v << 16); + bltptxpos = hpos; + bltptxc = 4; + } else { + bltdpt = (bltdpt & 0xffff) | ((uae_u32)v << 16); + } } static void BLTDPTL (int hpos, uae_u16 v) { - maybe_blit (0); - bltdpt = (bltdpt & ~0xffff) | (v & 0xFFFE); + maybe_blit (hpos, 0); + if (bltstate != BLT_done && currprefs.blitter_cycle_exact && currprefs.cpu_memory_cycle_exact) { + bltptx = (bltdpt & ~0xffff) | (v & 0xFFFE); + bltptxpos = hpos; + bltptxc = 4; + } else { + bltdpt = (bltdpt & ~0xffff) | (v & 0xFFFE); + } } static void BLTSIZE (int hpos, uae_u16 v) { - maybe_blit (0); + maybe_blit (hpos, 0); blt_info.vblitsize = v >> 6; blt_info.hblitsize = v & 0x3F; @@ -6006,7 +6059,7 @@ static void BLTSIZE (int hpos, uae_u16 v) blt_info.vblitsize = 1024; if (!blt_info.hblitsize) blt_info.hblitsize = 64; - do_blitter(hpos); + do_blitter(hpos, copper_access, copper_access ? cop_state.ip : M68K_GETPC); dcheck_is_blit_dangerous (); } @@ -6014,7 +6067,7 @@ static void BLTSIZV (int hpos, uae_u16 v) { if (! (currprefs.chipset_mask & CSMASK_ECS_AGNUS)) return; - maybe_blit (0); + maybe_blit (hpos, 0); blt_info.vblitsize = v & 0x7FFF; } @@ -6022,13 +6075,13 @@ static void BLTSIZH (int hpos, uae_u16 v) { if (! (currprefs.chipset_mask & CSMASK_ECS_AGNUS)) return; - maybe_blit (0); + maybe_blit (hpos, 0); blt_info.hblitsize = v & 0x7FF; if (!blt_info.vblitsize) blt_info.vblitsize = 0x8000; if (!blt_info.hblitsize) blt_info.hblitsize = 0x0800; - do_blitter(hpos); + do_blitter(hpos, copper_access, copper_access ? cop_state.ip : M68K_GETPC); } STATIC_INLINE void spr_arm (int num, int state) diff --git a/src/include/blitter.h b/src/include/blitter.h index e5756d86..f508c546 100644 --- a/src/include/blitter.h +++ b/src/include/blitter.h @@ -9,7 +9,6 @@ #ifndef UAE_BLITTER_H #define UAE_BLITTER_H -#include "savestate.h" #include "uae/types.h" struct bltinfo { @@ -39,23 +38,13 @@ extern uae_u32 bltptx; extern int bltptxpos, bltptxc; extern int blit_singlechannel; -extern void maybe_blit2 (int); -STATIC_INLINE void maybe_blit(int hack) -{ - if (bltstate == BLT_done) - return; - - if (savestate_state) - return; - - maybe_blit2(hack); -} +extern void maybe_blit (int, int); extern void reset_blit (int); extern int blitnasty (void); extern int blitnnasty (int); extern void blitter_handler (uae_u32); extern void build_blitfilltable (void); -extern void do_blitter (int); +extern void do_blitter (int, int, uaecptr); extern void decide_blitter (int hpos); extern int blitter_need (int hpos); extern void blitter_done_notify (int hpos); diff --git a/src/include/custom.h b/src/include/custom.h index e7ab6d0c..81fddfde 100644 --- a/src/include/custom.h +++ b/src/include/custom.h @@ -85,19 +85,11 @@ extern uae_u16 adkcon; extern unsigned int joy0dir, joy1dir; extern int joy0button, joy1button; -extern void INTREQ (uae_u16); -extern bool INTREQ_0 (uae_u16); -extern void INTREQ_f (uae_u16); -STATIC_INLINE void send_interrupt (int num) -{ - INTREQ_0 (0x8000 | (1 << num)); -} +extern void INTREQ(uae_u16); +extern bool INTREQ_0(uae_u16); +extern void INTREQ_f(uae_u16); +extern void send_interrupt(int num, int delay); extern void rethink_uae_int(void); -STATIC_INLINE uae_u16 INTREQR(void) -{ - return intreq; -} - STATIC_INLINE void safe_interrupt_set(bool i6) { uae_u16 v = i6 ? 0x2000 : 0x0008; @@ -105,6 +97,7 @@ STATIC_INLINE void safe_interrupt_set(bool i6) INTREQ_0(0x8000 | v); } } +extern uae_u16 INTREQR(void); /* maximums for statically allocated tables */ #ifdef UAE_MINI