From: Toni Wilen Date: Sun, 6 Dec 2020 13:58:13 +0000 (+0200) Subject: Blitter rewrite to match real hardware behavior. Reverted earlier copper changes. X-Git-Tag: 4900~240 X-Git-Url: https://git.unchartedbackwaters.co.uk/w/?a=commitdiff_plain;h=ef48a30d00eba86f408d523517bdeb382090706c;p=francis%2Fwinuae.git Blitter rewrite to match real hardware behavior. Reverted earlier copper changes. --- diff --git a/blitter.cpp b/blitter.cpp index 988715f3..49a1afa6 100644 --- a/blitter.cpp +++ b/blitter.cpp @@ -46,18 +46,19 @@ uae_u32 bltapt, bltbpt, bltcpt, bltdpt; uae_u32 bltptx; int bltptxpos, bltptxc; -static int original_ch, original_fill, original_line; - static int blinea_shift; static uae_u16 blinea, blineb; -static int blitline, blitfc, blitfill, blitife, blitsing, blitdesc; +static int blitline, blitfc, blitfill, blitife, blitsing, blitdesc, blit_ovf; static int blitline_started; static int blitonedot, blitsign, blitlinepixel; static int blit_add; static int blit_modadda, blit_modaddb, blit_modaddc, blit_modaddd; static int blit_ch; +static bool shifter_skip_b, shifter_skip_y; +static bool shifter_skip_b_old, shifter_skip_y_old; +static uae_u16 bltcon0_old, bltcon1_old; +static bool shifter[4], shifter_out, shifter_first; -static int blitter_dontdo; static int blitter_delayed_debug; #ifdef BLITTER_SLOWDOWNDEBUG static int blitter_slowdowndebug; @@ -67,27 +68,26 @@ struct bltinfo blt_info; static uae_u8 blit_filltable[256][4][2]; uae_u32 blit_masktable[BLITTER_MAX_WORDS]; -enum blitter_states bltstate; static int blit_cyclecounter, blit_waitcyclecounter; -static uaecptr blit_waitpc; static int blit_maxcyclecounter, blit_slowdown, blit_totalcyclecounter; -static int blit_startcycles, blit_misscyclecounter; +static int blit_misscyclecounter; #ifdef CPUEMU_13 extern uae_u8 cycle_line[256]; +static int blitter_cyclecounter; +static int blitter_hcounter; +static int blitter_vcounter; #endif static long blit_firstline_cycles; static long blit_first_cycle; -static int blit_last_cycle, blit_dmacount, blit_dmacount2; -static int blit_linecycles, blit_extracycles, blit_nod; -static const int *blit_diag; -static int blit_frozen, blit_faulty; -static int blit_final; +static int blit_last_cycle, blit_dmacount, blit_cyclecount; +static int blit_linecycles, blit_extracycles; +static int blit_faulty; static int blt_delayed_irq; -static uae_u16 ddat1, ddat2; -static int ddat1use, ddat2use; +static uae_u16 ddat1; +static int ddat1use; static int last_blitter_hpos; @@ -115,8 +115,8 @@ same in both block and line modes number of cycles, initial cycle, main cycle */ +#if 0 #define DIAGSIZE 10 - static const int blit_cycle_diagram[][DIAGSIZE] = { { 2, 0,0, 0,0 }, /* 0 -- */ @@ -136,33 +136,42 @@ static const int blit_cycle_diagram[][DIAGSIZE] = { 3, 1,2,3, 1,2,3 }, /* E ABC */ { 4, 1,2,3,0, 1,2,3,4 } /* F ABCD */ }; +#endif /* following 4 channel combinations in fill mode have extra idle cycle added (still requires free bus cycle) +Condition: If D without C: Add extra cycle. + */ +#if 0 + +// Cycle sequences are now generated using same +// logic as real blitter. Tables are not used anymore. + static const int blit_cycle_diagram_fill[][DIAGSIZE] = { - { 0 }, /* 0 */ - { 3, 0,0,0, 0,4,0 }, /* 1 */ - { 0 }, /* 2 */ - { 0 }, /* 3 */ - { 0 }, /* 4 */ - { 4, 0,2,0,0, 0,2,4,0 }, /* 5 */ - { 0 }, /* 6 */ - { 0 }, /* 7 */ - { 0 }, /* 8 */ - { 3, 1,0,0, 1,4,0 }, /* 9 */ - { 0 }, /* A */ - { 0 }, /* B */ - { 0 }, /* C */ - { 4, 1,2,0,0, 1,2,4,0 }, /* D */ - { 0 }, /* E */ - { 0 }, /* F */ + { 0 }, /* 0 -- */ + { 3, 0,0,0, 0,4,0 }, /* 1 -D */ + { 0 }, /* 2 -C */ + { 0 }, /* 3 -CD */ + { 0 }, /* 4 -B- */ + { 4, 0,2,0,0, 0,2,4,0 }, /* 5 -BD */ + { 0 }, /* 6 -BC */ + { 0 }, /* 7 -BCD */ + { 0 }, /* 8 A- */ + { 3, 1,0,0, 1,4,0 }, /* 9 AD */ + { 0 }, /* A AC */ + { 0 }, /* B ACD */ + { 0 }, /* C AB- */ + { 4, 1,2,0,0, 1,2,4,0 }, /* D ABD */ + { 0 }, /* E ABC */ + { 0 }, /* F ABCD */ }; +#endif /* -C-D C-D- ... C-D- -- @@ -213,53 +222,6 @@ There is at least one demo that does this.. */ -// 5 = internal "processing cycle" -static const int blit_cycle_diagram_line[] = -{ - 4, 0,3,5,4, 0,3,5,4 -}; - -static const int blit_cycle_diagram_finald[] = -{ - 2, 0,4, 0,4 -}; - -static const int blit_cycle_diagram_finalld[] = -{ - 2, 0,0, 0,0 -}; - -static int get_cycle_diagram_type (const int *diag) -{ - for (int i = 0; i < 16; i++) { - if (diag == &blit_cycle_diagram[i][0]) - return i; - if (diag == &blit_cycle_diagram_fill[i][0]) - return i + 0x40; - } - if (diag == blit_cycle_diagram_line) - return 0x80; - if (diag == blit_cycle_diagram_finald) - return 0x81; - if (diag == blit_cycle_diagram_finalld) - return 0x82; - return 0xff; -} -static const int *set_cycle_diagram_type (uae_u8 diag) -{ - if (diag >= 0x00 && diag <= 0x0f) - return &blit_cycle_diagram[diag][0]; - if (diag >= 0x40 && diag <= 0x4f) - return &blit_cycle_diagram_fill[diag][0]; - if (diag == 0x80) - return blit_cycle_diagram_line; - if (diag == 0x81) - return blit_cycle_diagram_finald; - if (diag == 0x82) - return blit_cycle_diagram_finalld; - return NULL; -} - void build_blitfilltable (void) { unsigned int d, fillmask; @@ -381,56 +343,13 @@ void blitter_debugdump(void) blitter_dump(); } -STATIC_INLINE const int *get_ch (void) -{ - if (blit_faulty) - return &blit_diag[0]; - if (blit_final) - return blitline || blit_nod ? blit_cycle_diagram_finalld : blit_cycle_diagram_finald; - return blit_diag; -} - -STATIC_INLINE int channel_state (int cycles) -{ - const int *diag; - if (cycles < 0) - return 0; - diag = get_ch (); - if (cycles < diag[0]) - return diag[1 + cycles]; - cycles -= diag[0]; - cycles %= diag[0]; - return diag[1 + diag[0] + cycles]; -} -STATIC_INLINE int channel_pos (int cycles) -{ - const int *diag; - if (cycles < 0) - return 0; - diag = get_ch (); - if (cycles < diag[0]) - return cycles; - cycles -= diag[0]; - cycles %= diag[0]; - return cycles; -} - -int blitter_channel_state (void) -{ - return channel_state (blit_cyclecounter); -} - -STATIC_INLINE int canblit (int hpos) +static int canblit (int hpos) { if (!dmaen (DMA_BLITTER)) return -1; if (is_bitplane_dma (hpos)) return 0; if (cycle_line[hpos] & CYCLE_MASK) { -#if 0 - if ((dmacon & DMA_BLITPRI) && (cycle_line[hpos] & CYCLE_MASK) == CYCLE_CPU) - write_log (_T("BLITTER: CPU stole cycle from blitter without nasty!?\n")); -#endif return 0; } return 1; @@ -466,12 +385,15 @@ static void reset_channel_mods (void) static void check_channel_mods (int hpos, int ch) { + static int blit_warned = 100; if (bltptxpos != hpos) return; if (ch == bltptxc) { bltptxpos = -1; - write_log (_T("BLITTER: %08X write to %cPT ignored! %08x\n"), bltptx, ch + 'A' - 1, m68k_getpc ()); - //activate_debugger(); + if (blit_warned > 0) { + write_log(_T("BLITTER: %08X write to %cPT ignored! %08x\n"), bltptx, ch + 'A' - 1, m68k_getpc()); + blit_warned--; + } } } @@ -486,6 +408,7 @@ static void check_channel_mods (int hpos, int ch) static void blitter_interrupt (int hpos, int done) { + blt_info.blit_main = 0; if (blt_info.blit_interrupt) return; if (!done && (!blitter_cycle_exact || immediate_blits || currprefs.cpu_model >= 68030 || currprefs.cachesize || currprefs.m68k_speed < 0)) @@ -498,11 +421,9 @@ static void blitter_interrupt (int hpos, int done) static void blitter_done (int hpos) { - ddat1use = ddat2use = 0; - bltstate = blit_startcycles == 0 || !blitter_cycle_exact || immediate_blits ? BLT_done : BLT_init; + ddat1use = 0; blitter_interrupt (hpos, 1); blitter_done_notify (hpos); - markidlecycle (hpos); event2_remevent (ev2_blitter); unset_special (SPCFLAG_BLTNASTY); if (log_blitter & 1) @@ -615,8 +536,7 @@ static void blitter_dofast (void) } blit_masktable[0] = 0xFFFF; blit_masktable[blt_info.hblitsize - 1] = 0xFFFF; - - bltstate = BLT_done; + blt_info.blit_main = 0; } static void blitter_dofast_desc (void) @@ -713,11 +633,10 @@ static void blitter_dofast_desc (void) } blit_masktable[0] = 0xFFFF; blit_masktable[blt_info.hblitsize - 1] = 0xFFFF; - - bltstate = BLT_done; + blt_info.blit_main = 0; } -STATIC_INLINE void blitter_read (void) +static void blitter_read (void) { if (bltcon0 & 0x200) { if (!dmaen (DMA_BLITTER)) @@ -725,10 +644,9 @@ STATIC_INLINE void blitter_read (void) blt_info.bltcdat = chipmem_wget_indirect (bltcpt); last_custom_value1 = blt_info.bltcdat; } - bltstate = BLT_work; } -STATIC_INLINE void blitter_write (void) +static void blitter_write (void) { if (blt_info.bltddat) blt_info.blitzero = 0; @@ -738,10 +656,9 @@ STATIC_INLINE void blitter_write (void) return; chipmem_wput_indirect (bltdpt, blt_info.bltddat); } - bltstate = BLT_next; } -STATIC_INLINE void blitter_line_incx (void) +static void blitter_line_incx (void) { if (++blinea_shift == 16) { blinea_shift = 0; @@ -749,7 +666,7 @@ STATIC_INLINE void blitter_line_incx (void) } } -STATIC_INLINE void blitter_line_decx (void) +static void blitter_line_decx (void) { if (blinea_shift-- == 0) { blinea_shift = 15; @@ -757,13 +674,13 @@ STATIC_INLINE void blitter_line_decx (void) } } -STATIC_INLINE void blitter_line_decy (void) +static void blitter_line_decy (void) { bltcpt -= blt_info.bltcmod; blitonedot = 0; } -STATIC_INLINE void blitter_line_incy (void) +static void blitter_line_incy (void) { bltcpt += blt_info.bltcmod; blitonedot = 0; @@ -788,164 +705,68 @@ static void blitter_line_proc (void) else bltapt += (uae_s16)blt_info.bltamod; } + blitsign = 0 > (uae_s16)bltapt; if (!blitsign) { if (bltcon1 & 0x10) { if (bltcon1 & 0x8) - blitter_line_decy (); + blitter_line_decy(); else - blitter_line_incy (); + blitter_line_incy(); } else { if (bltcon1 & 0x8) - blitter_line_decx (); + blitter_line_decx(); else - blitter_line_incx (); + blitter_line_incx(); } } if (bltcon1 & 0x10) { if (bltcon1 & 0x4) - blitter_line_decx (); + blitter_line_decx(); else - blitter_line_incx (); + blitter_line_incx(); } else { if (bltcon1 & 0x4) - blitter_line_decy (); + blitter_line_decy(); else - blitter_line_incy (); + blitter_line_incy(); } - blitsign = 0 > (uae_s16)bltapt; - bltstate = BLT_write; } -STATIC_INLINE void blitter_nxline (void) +static void blitter_nxline (void) { blineb = (blineb << 1) | (blineb >> 15); blt_info.vblitsize--; - bltstate = BLT_read; -} - -#ifdef CPUEMU_13 - -static int blitter_cyclecounter; -static int blitter_hcounter1, blitter_hcounter2; -static int blitter_vcounter1, blitter_vcounter2; - -static void decide_blitter_line (int hsync, int hpos) -{ - if (blit_final && blt_info.vblitsize) - blit_final = 0; - while (last_blitter_hpos < hpos) { - int c = channel_state (blit_cyclecounter); - - for (;;) { - int v = canblit (last_blitter_hpos); - - if (blit_waitcyclecounter) { - blit_waitcyclecounter = 0; - break; - } - - // final 2 idle cycles? does not need free bus - if (blit_final) { - blit_cyclecounter++; - blit_totalcyclecounter++; - if (blit_cyclecounter >= 2) { - blitter_done(last_blitter_hpos); - return; - } - break; - } - - if (v <= 0) { - blit_misscyclecounter++; - break; - } - - blit_cyclecounter++; - blit_totalcyclecounter++; - - check_channel_mods (last_blitter_hpos, c); - - if (c == 3) { - - record_dma_blit(0x70, 0, bltcpt, last_blitter_hpos); - blitter_read(); - record_dma_blit_val(blt_info.bltcdat); - alloc_cycle_blitter (last_blitter_hpos, &bltcpt, 3); - - } else if (c == 5) { - - if (ddat1use) { - bltdpt = bltcpt; - } - ddat1use = 1; - blitter_line (); - blitter_line_proc (); - blitter_nxline (); - - } else if (c == 4) { - - /* onedot mode and no pixel = bus write access is skipped */ - if (blitlinepixel) { - record_dma_blit(0x00, blt_info.bltddat, bltdpt, last_blitter_hpos); - blitter_write (); - alloc_cycle_blitter (last_blitter_hpos, &bltdpt, 4); - blitlinepixel = 0; - } - if (blt_info.vblitsize == 0) { - bltdpt = bltcpt; - blit_final = 1; - blit_cyclecounter = 0; - blit_waitcyclecounter = 0; - // blit finished bit is set and interrupt triggered - // immediately after last D write - blitter_interrupt (last_blitter_hpos, 0); - break; - } - - } - - break; - } - last_blitter_hpos++; - } - if (hsync) - last_blitter_hpos = 0; - reset_channel_mods (); } -#endif - static void actually_do_blit (void) { if (blitline) { do { record_dma_blit(0x70, 0, bltcpt, last_blitter_hpos); - blitter_read (); + blitter_read(); record_dma_blit_val(blt_info.bltcdat); if (ddat1use) bltdpt = bltcpt; ddat1use = 1; - blitter_line (); - blitter_line_proc (); - blitter_nxline (); + blitter_line(); + blitter_line_proc(); + blitter_nxline(); if (blitlinepixel) { record_dma_blit(0x00, blt_info.bltddat, bltdpt, last_blitter_hpos); - blitter_write (); + blitter_write(); blitlinepixel = 0; } - if (blt_info.vblitsize == 0) - bltstate = BLT_done; - } while (bltstate != BLT_done); + } while (blt_info.vblitsize != 0); bltdpt = bltcpt; } else { if (blitdesc) - blitter_dofast_desc (); + blitter_dofast_desc(); else - blitter_dofast (); - bltstate = BLT_done; + blitter_dofast(); } + blt_info.blit_main = 0; } static void blitter_doit (void) @@ -954,15 +775,8 @@ 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) @@ -995,21 +809,158 @@ void blitter_handler (uae_u32 data) blit_slowdown = -1; return; } - blitter_doit (); + blitter_doit(); } #ifdef CPUEMU_13 -STATIC_INLINE uae_u16 blitter_doblit (void) +static void blit_bltset(int con) +{ + static int blit_warned = 100; + + if (con & 2) { + blitdesc = bltcon1 & 2; + blt_info.blitbshift = bltcon1 >> 12; + 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); + } else if (!(bltcon1 & 1) && blitline_started) { + write_log(_T("BLITTER: linedraw disabled when blitter was already active! %08x\n"), M68K_GETPC); + } + blit_warned--; + } + } + + if (con & 1) { + blt_info.blitashift = bltcon0 >> 12; + blt_info.blitdownashift = 16 - blt_info.blitashift; + } + + if (!savestate_state && blt_info.blit_main && (bltcon0_old != bltcon0 || bltcon1_old != bltcon1)) { + 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); + blit_warned--; + } + bltcon0_old = bltcon0; + bltcon1_old = bltcon1; + } + + blit_ch = (bltcon0 & 0x0f00) >> 8; + blitline = bltcon1 & 1; + blitfill = (bltcon1 & 0x18) != 0; + blit_ovf = (bltcon1 & 0x20) != 0; + + shifter_skip_b = (bltcon0 & 0x400) == 0; + if (blitline) { + shifter_skip_y = true; + } else { + shifter_skip_y = (bltcon0 & (0x100 | 0x200)) != 0x300; + // fill mode idle cycle needed? + if (blitfill && (bltcon0 & (0x100 | 0x200)) == 0x100) { + shifter_skip_y = false; + } + } + 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) + + ((bltcon0 & 0x200) ? 1 : 0) + ((bltcon0 & 0x100) ? 1 : 0); + + if ((bltcon1 & 0x80) && (currprefs.chipset_mask & CSMASK_ECS_AGNUS)) { + debugtest(DEBUGTEST_BLITTER, _T("ECS BLTCON1 DOFF-bit set\n")); + if (log_blitter & 16) + activate_debugger(); + } +} + +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]) { + if (blitter_hcounter + 1 == blt_info.hblitsize) + return 5; + if (bltcon0 & 0x800) + return 1; + return 0; + } + if (shifter[1] && (bltcon0 & 0x400)) { + return 2; + } + if (shifter[2] && (bltcon0 & 0x200)) { + if (blitter_hcounter + 1 == blt_info.hblitsize) + return 4; + return 3; + } + } else { + // order is important when multiple bits in shift register + // C + if (shifter[2] && (bltcon0 & 0x200)) { + return 3; + } + // Shift stage 4 active, C enabled and other stage(s) also active: + // normally would be D but becomes C. + if (shifter[3] && (bltcon0 & 0x200) && (shifter[0] || shifter[1])) { + return 3; + } + // A + if (shifter[0] && (bltcon0 & 0x800)) { + return 1; + } + // B + if (shifter[1] && (bltcon0 & 0x400)) { + return 2; + } + // D only if A, B and C is not currently active + if (shifter_out) { + if ((bltcon0 & 0x100) && ddat1use) { + return 4; + } + } + } + return 0; +} + +static 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) + if (blitter_hcounter == 0) bltadat &= blt_info.bltafwm; - if (blitter_hcounter1 == blt_info.hblitsize - 1) + if (blitter_hcounter == blt_info.hblitsize - 1) bltadat &= blt_info.bltalwm; if (blitdesc) blitahold = (((uae_u32)bltadat << 16) | blt_info.bltaold) >> blt_info.blitdownashift; @@ -1034,155 +985,188 @@ STATIC_INLINE uae_u16 blitter_doblit (void) return ddat; } - -STATIC_INLINE void blitter_doddma (int hpos) +static void blitter_next_cycle(void) { - uae_u16 d; - - if (blit_dmacount2 == 0) { - d = blitter_doblit (); - } else if (ddat2use) { - d = ddat2; - ddat2use = 0; - } else if (ddat1use) { - d = ddat1; - ddat1use = 0; + bool tmp[4]; + bool out = false; + + memcpy(tmp, shifter, sizeof(shifter)); + memset(shifter, 0, sizeof(shifter)); + + if (shifter_skip_b_old && !shifter_skip_b) { + // if B skip was disabled: A goes both to B and C + tmp[1] = tmp[0]; + tmp[2] = tmp[0]; + shifter_skip_b_old = shifter_skip_b; + } 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; + } + + if (shifter_skip_y_old && !shifter_skip_y) { + // if Y skip was disbled: X goes both to Y and OUT + tmp[3] = tmp[2]; + shifter_skip_y_old = shifter_skip_y; + } 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; + } + + if (shifter_out) { + if (!blitline) { + ddat1 = blitter_doblit(); + ddat1use = true; + } + blitter_hcounter++; + 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; + if (!blitline) { + blt_info.blit_finald = 3; + blitter_interrupt(last_blitter_hpos, 0); + } else { + blitter_done(last_blitter_hpos); + } + } + } + shifter[0] = shifter_out; + } + + if (shifter_first) { + shifter_first = false; + shifter[0] = true; + blitfc = !!(bltcon1 & 0x4); } else { - static int warn = 10; - if (warn > 0) { - warn--; - write_log (_T("BLITTER: D-channel without nothing to do?\n")); + if (shifter_skip_b) { + shifter[2] = tmp[0]; + } else { + shifter[1] = tmp[0]; + shifter[2] = tmp[1]; + } + if (shifter_skip_y) { + out = shifter[2]; + } else { + shifter[3] = tmp[2]; + out = shifter[3]; } - return; } - record_dma_blit(0x00, d, bltdpt, hpos); - chipmem_agnus_wput2 (bltdpt, d); + shifter_out = out; +} + + +static void blitter_doddma_new(int hpos) +{ + record_dma_blit(0x00, ddat1, bltdpt, hpos); + chipmem_agnus_wput2 (bltdpt, ddat1); 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; + if (!blitline) { + bltdpt += blit_add; + if (blitter_hcounter == 0) { + bltdpt += blit_modaddd; + } + } } -STATIC_INLINE void blitter_dodma (int ch, int hpos) +static void blitter_dodma_new(int ch, int hpos) { uae_u16 dat, reg; - uae_u32 addr; + uae_u32 *addr; + int mod; switch (ch) { case 1: reg = 0x74; record_dma_blit(reg, 0, bltapt, hpos); - blt_info.bltadat = dat = chipmem_wget_indirect (bltapt); + blt_info.bltadat = dat = chipmem_wget_indirect(bltapt); record_dma_blit_val(dat); last_custom_value1 = blt_info.bltadat; - addr = bltapt; - bltapt += blit_add; - alloc_cycle_blitter (hpos, &bltapt, 1); + addr = &bltapt; + mod = blit_modadda; + alloc_cycle_blitter(hpos, &bltapt, 1); break; case 2: reg = 0x72; record_dma_blit(reg, 0, bltbpt, hpos); - blt_info.bltbdat = dat = chipmem_wget_indirect (bltbpt); + blt_info.bltbdat = dat = chipmem_wget_indirect(bltbpt); record_dma_blit_val(dat); last_custom_value1 = blt_info.bltbdat; - addr = bltbpt; - bltbpt += blit_add; + addr = &bltbpt; + mod = blit_modaddb; 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; - alloc_cycle_blitter (hpos, &bltbpt, 2); + alloc_cycle_blitter(hpos, &bltbpt, 2); break; case 3: reg = 0x70; record_dma_blit(reg, 0, bltcpt, hpos); - blt_info.bltcdat = dat = chipmem_wget_indirect (bltcpt); + blt_info.bltcdat = dat = chipmem_wget_indirect(bltcpt); record_dma_blit_val(dat); last_custom_value1 = blt_info.bltcdat; - addr = bltcpt; - bltcpt += blit_add; - alloc_cycle_blitter (hpos, &bltcpt, 3); + addr = &bltcpt; + mod = blit_modaddc; + alloc_cycle_blitter(hpos, &bltcpt, 3); break; default: - abort (); + 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); + if (!blitline) { + (*addr) += blit_add; + if (blitter_hcounter + 1 == blt_info.hblitsize) { + (*addr) += mod; } } } -int blitter_need (int hpos) + +static bool blitter_idle_cycle_register_write(uaecptr addr, uae_u16 v) { - int c; - if (bltstate == BLT_done) - return 0; - if (!dmaen (DMA_BLITTER)) - return 0; - c = channel_state (blit_cyclecounter); - return c; + addrbank *ab = &get_mem_bank(addr); + if (ab != &custom_bank) + return false; + addr &= 0x1fe; + if (addr == 0x40) { + bltcon0 = v; + blit_bltset(1); + return true; + } else if (addr == 0x42) { + bltcon1 = v; + blit_bltset(2); + return true; + } + return false; } -static void do_startcycles (int hpos) +static bool decide_blitter_idle(int lasthpos, int hpos, uaecptr addr, uae_u16 value) { - 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); - } + markidlecycle(last_blitter_hpos); + if (addr != 0xffffffff && lasthpos + 1 == hpos) { + shifter_skip_b_old = shifter_skip_b; + shifter_skip_y_old = shifter_skip_y; + return blitter_idle_cycle_register_write(addr, value); } + return false; } -void decide_blitter (int hpos) +void decide_blitter(int hpos) { + decide_blitter_maybe_write(hpos, 0xffffffff, 0xffff); +} + +bool decide_blitter_maybe_write(int hpos, uaecptr addr, uae_u16 value) +{ + bool written = false; int hsync = hpos < 0; if (hsync && blt_delayed_irq) { @@ -1195,133 +1179,165 @@ void decide_blitter (int hpos) } if (immediate_blits) { - if (bltstate == BLT_done) - return; - if (dmaen (DMA_BLITTER)) + if (!blt_info.blit_main) + return false; + if (dmaen(DMA_BLITTER)) blitter_doit(); - return; + return false; } - if (blit_startcycles > 0) - do_startcycles (hpos); - - if (bltstate == BLT_done) - return; + if (!blt_info.blit_main && !blt_info.blit_finald) { + return false; + } if (log_blitter && blitter_delayed_debug) { blitter_delayed_debug = 0; - blitter_dump (); + blitter_dump(); } - if (!blitter_cycle_exact) - return; + if (!blitter_cycle_exact) { + return false; + } - if (hpos < 0) + if (hpos < 0) { hpos = maxhpos; - - 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); + int c = get_current_channel(); for (;;) { - int v; - - v = canblit (last_blitter_hpos); + int v = canblit(last_blitter_hpos); // copper bltsize write needs one cycle (any cycle) delay if (blit_waitcyclecounter) { blit_waitcyclecounter = 0; - markidlecycle (last_blitter_hpos); + 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)) { + + if (v <= 0) { blit_misscyclecounter++; 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++; - break; + + if (blt_info.blit_finald) { + blt_info.blit_finald--; + if (blt_info.blit_finald == 1) { + blitter_doddma_new(last_blitter_hpos); + blitter_done(hpos); } } -#endif - if (blit_frozen) { - blit_misscyclecounter++; - break; - } - if (c == 0) { - blt_info.got_cycle = 1; - blit_cyclecounter++; - if (blit_cyclecounter == 0) - blit_final = 0; + if (blt_info.blit_main) { blit_totalcyclecounter++; - /* check if blit with zero channels has ended */ - if (blit_ch == 0 && blit_cyclecounter >= blit_maxcyclecounter) { - blitter_done (last_blitter_hpos); - return; + blit_cyclecounter++; + if (blit_cyclecounter == 0) { + shifter_first = true; } - markidlecycle (last_blitter_hpos); - break; - } - if (v <= 0) { - blit_misscyclecounter++; - break; - } + blt_info.got_cycle = 1; - 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 (c == 0) { - if (blitter_vcounter1 >= blt_info.vblitsize && blitter_vcounter2 >= blt_info.vblitsize) { - if (!ddat1use && !ddat2use) { - blitter_done (last_blitter_hpos); - return; + written = decide_blitter_idle(last_blitter_hpos, hpos, addr, value); + + } else if (c == 1 && blitline) { // line 1 (A, free) + + if (blitsign) + bltapt += (uae_s16)blt_info.bltbmod; + else + bltapt += (uae_s16)blt_info.bltamod; + + written = decide_blitter_idle(last_blitter_hpos, hpos, addr, value); + + } else if (c == 3 && blitline) { // line 2 (C) + + record_dma_blit(0x70, 0, bltcpt, last_blitter_hpos); + blt_info.bltcdat = chipmem_wget_indirect(bltcpt); + last_custom_value1 = blt_info.bltcdat; + record_dma_blit_val(blt_info.bltcdat); + alloc_cycle_blitter(last_blitter_hpos, &bltcpt, 3); + + blitter_line(); + + if (!blitsign) { + if (bltcon1 & 0x10) { + if (bltcon1 & 0x8) + blitter_line_decy(); + else + blitter_line_incy(); + } + } + if (!(bltcon1 & 0x10)) { + if (bltcon1 & 0x4) + blitter_line_decy(); + else + blitter_line_incy(); + } + + blitsign = 0 > (uae_s16)bltapt; + + blineb = (blineb << 1) | (blineb >> 15); + + } else if (c == 5 && blitline) { // line 3 (free) + + if (!blitsign) { + if (!(bltcon1 & 0x10)) { + if (bltcon1 & 0x8) + blitter_line_decx(); + else + blitter_line_incx(); + } + } + if (bltcon1 & 0x10) { + if (bltcon1 & 0x4) + blitter_line_decx(); + else + blitter_line_incx(); + } + + written = decide_blitter_idle(last_blitter_hpos, hpos, addr, value); + + } else if (c == 4 && blitline) { // line 4 (D) + + /* onedot mode and no pixel = bus write access is skipped */ + if (blitlinepixel) { + record_dma_blit(0x00, blt_info.bltddat, bltdpt, last_blitter_hpos); + if (blt_info.bltddat) + blt_info.blitzero = 0; + chipmem_wput_indirect(bltdpt, blt_info.bltddat); + alloc_cycle_blitter(last_blitter_hpos, &bltdpt, 4); + blitlinepixel = 0; + } + bltdpt = bltcpt; + + } else { + // normal mode A to D + + if (c == 4) { + blitter_doddma_new(last_blitter_hpos); + } else { + blitter_dodma_new(c, last_blitter_hpos); + } } + + blitter_next_cycle(); + + // check this after end check because last D write won't cause any problems. + check_channel_mods(last_blitter_hpos, c); } - // 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 (); + reset_channel_mods(); if (hsync) last_blitter_hpos = 0; + + return written; } #else void decide_blitter (int hpos) { } @@ -1330,171 +1346,29 @@ void decide_blitter (int hpos) { } static void blitter_force_finish(bool state) { uae_u16 odmacon; - if (bltstate == BLT_done) + if (!blt_info.blit_main && !blt_info.blit_finald) return; - if (bltstate != BLT_done) { - /* blitter is currently running - * force finish (no blitter state support yet) - */ - 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); - rounds--; - } - if (rounds == 0) - write_log (_T("blitter froze!?\n")); - blit_startcycles = 0; - } else { - actually_do_blit (); + /* blitter is currently running + * force finish (no blitter state support yet) + */ + 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 (blt_info.blit_main || blt_info.blit_finald && rounds > 0) { + memset(cycle_line, 0, sizeof cycle_line); + decide_blitter(-1); + rounds--; } - blitter_done (current_hpos ()); - dmacon = odmacon; - } -} - -static bool invstate (void) -{ - return bltstate != BLT_done && bltstate != BLT_init; -} - -static void blit_bltset (int con) -{ - int i; - const int *olddiag = blit_diag; - - if (con & 2) { - blitdesc = bltcon1 & 2; - blt_info.blitbshift = bltcon1 >> 12; - blt_info.blitdownbshift = 16 - blt_info.blitbshift; - if ((bltcon1 & 1) && !blitline_started) { - write_log (_T("BLITTER: linedraw enabled after starting normal blit! %08x\n"), M68K_GETPC); - return; - } - } - - if (con & 1) { - blt_info.blitashift = bltcon0 >> 12; - blt_info.blitdownashift = 16 - blt_info.blitashift; - } - - blit_ch = (bltcon0 & 0x0f00) >> 8; - blitline = bltcon1 & 1; - blitfill = !!(bltcon1 & 0x18); - - // disable line draw if bltcon0 is written while it is active - if (!savestate_state && bltstate != BLT_done && bltstate != BLT_init && blitline && blitline_started) { - blitline = 0; - bltstate = BLT_done; - blt_info.blit_interrupt = 1; - write_log (_T("BLITTER: register modification during linedraw! %08x\n"), M68K_GETPC); - if (log_blitter & 16) - activate_debugger (); - } - - if (blitline) { - if (blt_info.hblitsize != 2) { - debugtest (DEBUGTEST_BLITTER, _T("weird blt_info.hblitsize in linemode: %d vsize=%d\n"), - blt_info.hblitsize, blt_info.vblitsize); - if (log_blitter & 16) - activate_debugger (); - } - blit_diag = blit_cycle_diagram_line; + if (rounds == 0) + write_log(_T("blitter froze!?\n")); } else { - if (con & 2) { - blitfc = !!(bltcon1 & 0x4); - blitife = !!(bltcon1 & 0x8); - if ((bltcon1 & 0x18) == 0x18) { - debugtest (DEBUGTEST_BLITTER, _T("weird fill mode\n")); - blitife = 0; - } - } - if (blitfill && !blitdesc) { - debugtest (DEBUGTEST_BLITTER, _T("fill without desc\n")); - if (log_blitter & 16) - activate_debugger (); - } - blit_diag = blitfill && blit_cycle_diagram_fill[blit_ch][0] ? blit_cycle_diagram_fill[blit_ch] : blit_cycle_diagram[blit_ch]; - } - if ((bltcon1 & 0x80) && (currprefs.chipset_mask & CSMASK_ECS_AGNUS)) { - debugtest (DEBUGTEST_BLITTER, _T("ECS BLTCON1 DOFF-bit set\n")); - if (log_blitter & 16) - activate_debugger (); - } - - // 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; - } - } - - if (blit_faulty) { - blit_ch = 0; - blit_diag = blit_cycle_diagram[blit_ch]; - } - - blit_dmacount = blit_dmacount2 = 0; - blit_nod = 1; - for (i = 0; i < blit_diag[0]; i++) { - int v = blit_diag[1 + blit_diag[0] + i]; - if (v <= 4) - blit_dmacount++; - if (v > 0 && v < 4) - blit_dmacount2++; - if (v == 4) - blit_nod = 0; - } - if (blit_dmacount2 == 0) { - ddat2use = 0; - ddat1use = 0; + actually_do_blit(); } + blitter_done(current_hpos()); + dmacon = odmacon; } static void blit_modset (void) @@ -1515,11 +1389,11 @@ void reset_blit (int bltcon) blinea_shift = bltcon0 >> 12; if (bltcon & 2) blitsign = bltcon1 & 0x40; - if (bltstate == BLT_done) + if (!blt_info.blit_main) return; if (bltcon) blit_bltset (bltcon); - blit_modset (); + blit_modset(); } static bool waitingblits (void) @@ -1536,7 +1410,7 @@ static bool waitingblits (void) } bool waited = false; - while (bltstate != BLT_done && dmaen (DMA_BLITTER)) { + while ((blt_info.blit_main || blt_info.blit_finald) && dmaen (DMA_BLITTER)) { waited = true; x_do_cycles (8 * CYCLE_UNIT); } @@ -1544,20 +1418,22 @@ static bool waitingblits (void) warned--; write_log (_T("waiting_blits detected PC=%08x\n"), M68K_GETPC); } - if (bltstate == BLT_done) + if (!blt_info.blit_main && !blt_info.blit_finald) return true; return false; } static void blitter_start_init (void) { + blit_faulty = 0; blt_info.blitzero = 1; - blit_frozen = 0; blitline_started = bltcon1 & 1; blit_bltset (1 | 2); - blit_modset (); - ddat1use = ddat2use = 0; + shifter_skip_b_old = shifter_skip_b; + shifter_skip_y_old = shifter_skip_y; + blit_modset(); + ddat1use = 0; blt_info.blit_interrupt = 0; blt_info.bltaold = 0; @@ -1578,60 +1454,45 @@ static void blitter_start_init (void) } } -static void do_blitter2(int hpos, int copper, uaecptr pc) +void do_blitter(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(); - } + if (blt_info.blit_main) { + write_log (_T("blitter was already active! PC=%08x\n"), M68K_GETPC); } } - cleanstart = 0; - if (bltstate == BLT_done) { - if (blit_faulty > 0) - blit_faulty = 0; - cleanstart = 1; - } - - bltstate = BLT_done; + bltcon0_old = bltcon0; + bltcon1_old = bltcon1; blitter_cycle_exact = currprefs.blitter_cycle_exact; immediate_blits = currprefs.immediate_blits; blt_info.got_cycle = 0; last_blitter_hpos = hpos + 1; - blit_firstline_cycles = blit_first_cycle = get_cycles (); + blit_firstline_cycles = blit_first_cycle = get_cycles(); blit_misscyclecounter = 0; blit_last_cycle = 0; blit_maxcyclecounter = 0; blit_cyclecounter = 0; blit_totalcyclecounter = 0; + blt_info.blit_pending = 1; - blitter_start_init (); + blitter_start_init(); if (blitline) { cycles = blt_info.vblitsize; } else { cycles = blt_info.vblitsize * blt_info.hblitsize; - blit_firstline_cycles = blit_first_cycle + (blit_diag[0] * blt_info.hblitsize) * CYCLE_UNIT + cpu_cycles; + blit_firstline_cycles = blit_first_cycle + (blit_cyclecount * blt_info.hblitsize) * CYCLE_UNIT + cpu_cycles; } - if (cleanstart) { - original_ch = blit_ch; - original_fill = blitfill; - original_line = blitline; - } - - if (memwatch_enabled) + if (memwatch_enabled) { blitter_debugsave(copper, pc); + } if ((log_blitter & 1) || ((log_blitter & 32) && !blitline)) { - blitter_dontdo = 0; if (1) { int ch = 0; if (blit_ch & 1) @@ -1642,62 +1503,54 @@ static void do_blitter2(int hpos, int copper, uaecptr pc) ch++; if (blit_ch & 8) ch++; - write_log (_T("blitstart: %dx%d ch=%d %d*%d=%d d=%d f=%02x n=%d pc=%08x l=%d dma=%04x %s\n"), - blt_info.hblitsize, blt_info.vblitsize, ch, blit_diag[0], cycles, blit_diag[0] * cycles, + write_log (_T("blitstart: %dx%d ch=%d %d d=%d f=%02x n=%d pc=%08x l=%d dma=%04x %s\n"), + blt_info.hblitsize, blt_info.vblitsize, ch, cycles, blitdesc ? 1 : 0, blitfill, dmaen (DMA_BLITPRI) ? 1 : 0, M68K_GETPC, blitline, dmacon, ((dmacon & (DMA_MASTER | DMA_BLITTER)) == (DMA_MASTER | DMA_BLITTER)) ? _T("") : _T(" off!")); - blitter_dump (); + blitter_dump(); } } - bltstate = BLT_init; blit_slowdown = 0; unset_special (SPCFLAG_BLTNASTY); - if (dmaen (DMA_BLITPRI)) - set_special (SPCFLAG_BLTNASTY); - -#if 0 - if (M68K_GETPC >= 0x00070554 && M68K_GETPC <= 0x000706B0) { - blitter_done (); - return; - } - if (M68K_GETPC >= 0x00070838) { - blitter_done (); - return; + if (dmaen(DMA_BLITPRI)) { + set_special(SPCFLAG_BLTNASTY); } -#endif - if (dmaen (DMA_BLITTER)) - bltstate = BLT_work; + if (dmaen(DMA_BLITTER)) { + blt_info.blit_main = 1; + blt_info.blit_pending = 0; + } blit_maxcyclecounter = 0x7fffffff; blit_waitcyclecounter = 0; if (blitter_cycle_exact) { if (immediate_blits) { - if (dmaen (DMA_BLITTER)) - blitter_doit (); + 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; + blitter_hcounter = 0; + blitter_vcounter = 0; blit_cyclecounter = -BLITTER_STARTUP_CYCLES; blit_waitcyclecounter = copper; - blit_startcycles = 0; blit_maxcyclecounter = blt_info.hblitsize * blt_info.vblitsize + 2; + blt_info.blit_pending = 0; + blt_info.blit_main = 1; } return; } if (blt_info.vblitsize == 0 || (blitline && blt_info.hblitsize != 2)) { - if (dmaen (DMA_BLITTER)) - blitter_done (hpos); + if (dmaen(DMA_BLITTER)) { + blitter_done(hpos); + } return; } @@ -1706,53 +1559,35 @@ static void do_blitter2(int hpos, int copper, uaecptr pc) } if (immediate_blits) { - if (dmaen (DMA_BLITTER)) - blitter_doit (); + if (dmaen(DMA_BLITTER)) { + blitter_doit(); + } return; } - blit_cyclecounter = cycles * (blit_dmacount2 + (blit_nod ? 0 : 1)); + blit_cyclecounter = cycles * blit_cyclecount; event2_newevent (ev2_blitter, makebliteventtime(blit_cyclecounter), 0); } void blitter_check_start (void) { - if (bltstate != BLT_init) - return; - blitter_start_init (); - bltstate = BLT_work; - if (immediate_blits) { - blitter_doit (); - } -} - -void do_blitter(int hpos, int copper, uaecptr pc) -{ - if (bltstate == BLT_done || !blitter_cycle_exact) { - do_blitter2(hpos, copper, pc); - return; - } - - if (dmaen(DMA_BLITTER) && (log_blitter & 16)) { - activate_debugger(); + if (blt_info.blit_pending && !blt_info.blit_main) { + blt_info.blit_pending = 0; + blt_info.blit_main = 1; + blitter_start_init(); + if (immediate_blits) { + blitter_doit(); + } } - - 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 (); + reset_channel_mods(); - if (bltstate == BLT_done) + if (!blt_info.blit_main) return; if (savestate_state) @@ -1763,16 +1598,16 @@ void maybe_blit (int hpos, int hack) 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)) + if (blit_dmacount == blit_cyclecount && (regs.spcflags & SPCFLAG_BLTNASTY)) doit = true; } else if (currprefs.waiting_blits == 1) { // automatic - if (blit_dmacount == blit_diag[0] && (regs.spcflags & SPCFLAG_BLTNASTY)) + if (blit_dmacount == blit_cyclecount && (regs.spcflags & SPCFLAG_BLTNASTY)) doit = true; else if (currprefs.m68k_speed < 0) doit = true; } if (doit) { - if (waitingblits ()) + if (waitingblits()) return; } } @@ -1785,7 +1620,7 @@ void maybe_blit (int hpos, int hack) if (log_blitter & 2) { warned = 10; write_log (_T("program does not wait for blitter PC=%08x\n"), M68K_GETPC); - //activate_debugger (); + //activate_debugger(); //blitter_done (hpos); } } @@ -1807,7 +1642,7 @@ end:; void check_is_blit_dangerous (uaecptr *bplpt, int planes, int words) { blt_info.blitter_dangerous_bpl = 0; - if (bltstate == BLT_done || !blitter_cycle_exact) + if ((!blt_info.blit_main && !blt_info.blit_finald) || !blitter_cycle_exact) return; // too simple but better than nothing for (int i = 0; i < planes; i++) { @@ -1823,22 +1658,21 @@ void check_is_blit_dangerous (uaecptr *bplpt, int planes, int words) int blitnasty (void) { int cycles, ccnt; - if (bltstate == BLT_done) + if (!blt_info.blit_main) return 0; - if (!dmaen (DMA_BLITTER)) + 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]) + if (blit_last_cycle >= blit_cyclecount && blit_dmacount == blit_cyclecount) return 0; - cycles = (get_cycles () - blit_first_cycle) / CYCLE_UNIT; + cycles = (get_cycles() - blit_first_cycle) / CYCLE_UNIT; ccnt = 0; - while (blit_last_cycle < cycles) { - int c = channel_state (blit_last_cycle++); - if (!c) - ccnt++; + while (blit_last_cycle + blit_cyclecount < cycles) { + ccnt += blit_dmacount; + blit_last_cycle += blit_cyclecount; } return ccnt; } @@ -1854,7 +1688,7 @@ void blitter_slowdown (int ddfstrt, int ddfstop, int totalcycles, int freecycles if (ddfstrt != oddfstrt || ddfstop != oddfstop || totalcycles != ototal || ofree != freecycles) { int linecycles = ((ddfstop - ddfstrt + totalcycles - 1) / totalcycles) * totalcycles; int freelinecycles = ((ddfstop - ddfstrt + totalcycles - 1) / totalcycles) * freecycles; - int dmacycles = (linecycles * blit_dmacount) / blit_diag[0]; + int dmacycles = (linecycles * blit_dmacount) / blit_cyclecount; oddfstrt = ddfstrt; oddfstop = ddfstop; ototal = totalcycles; @@ -1878,11 +1712,11 @@ void blitter_reset (void) void restore_blitter_finish (void) { - record_dma_reset (); - record_dma_reset (); + record_dma_reset(); + record_dma_reset(); if (blt_statefile_type == 0) { blt_info.blit_interrupt = 1; - if (bltstate == BLT_init) { + if (blt_info.blit_pending) { write_log (_T("blitter was started but DMA was inactive during save\n")); //do_blitter (0); } @@ -1893,7 +1727,7 @@ void restore_blitter_finish (void) } } else { last_blitter_hpos = 0; - blit_modset (); + blit_modset(); } } @@ -1903,9 +1737,13 @@ uae_u8 *restore_blitter (uae_u8 *src) blt_statefile_type = 0; blt_delayed_irq = 0; - bltstate = BLT_done; + blt_info.blit_pending = 0; + blt_info.blit_finald = 0; + blt_info.blit_main = 0; if (flags & 4) { - bltstate = (flags & 1) ? BLT_done : BLT_init; + if (!(flags & 1)) { + blt_info.blit_pending = 1; + } } if (flags & 2) { write_log (_T("blitter was force-finished when this statefile was saved\n")); @@ -1924,7 +1762,7 @@ uae_u8 *save_blitter (int *len, uae_u8 *dstptr) int forced; forced = 0; - if (bltstate != BLT_done && bltstate != BLT_init) { + if (blt_info.blit_main || blt_info.blit_finald) { 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(true); @@ -1934,7 +1772,7 @@ uae_u8 *save_blitter (int *len, uae_u8 *dstptr) dstbak = dst = dstptr; else dstbak = dst = xmalloc (uae_u8, 16); - save_u32 (((bltstate != BLT_done) ? 0 : 1) | forced | 4); + save_u32 (((blt_info.blit_main || blt_info.blit_finald) ? 0 : 1) | forced | 4); *len = dst - dstbak; return dstbak; @@ -1944,79 +1782,99 @@ uae_u8 *save_blitter (int *len, uae_u8 *dstptr) uae_u8 *restore_blitter_new (uae_u8 *src) { - uae_u8 state; + uae_u8 state, tmp; + 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 (); - - blt_info.blitbshift = restore_u8 (); - blt_info.blitdownbshift = restore_u8 (); - blt_info.blitashift = restore_u8 (); - blt_info.blitdownashift = restore_u8 (); - - ddat1use = restore_u8 (); - ddat2use = restore_u8 (); - ddat1 = restore_u16 (); - ddat2 = restore_u16 (); - - blitline = restore_u8 (); - blitfill = restore_u8 (); - blinea = restore_u16 (); - blineb = restore_u16 (); - blinea_shift = restore_u8 (); - blitonedot = restore_u8 (); - blitlinepixel = restore_u8 (); - blitsing = restore_u8 (); - blitlinepixel = restore_u8 (); - blt_info.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 ()); - - if (restore_u16 () != 0x1234) + blitter_cycle_exact = restore_u8(); + if (blitter_cycle_exact == 3) { + blt_statefile_type = 2; + blitter_cycle_exact = 1; + } + + state = restore_u8(); + + blit_first_cycle = restore_u32(); + blit_last_cycle = restore_u32(); + blit_waitcyclecounter = restore_u32(); + restore_u32(); + blit_maxcyclecounter = restore_u32(); + blit_firstline_cycles = restore_u32(); + blit_cyclecounter = restore_u32(); + blit_slowdown = restore_u32(); + blit_misscyclecounter = restore_u32(); + + blitter_hcounter = restore_u16(); + restore_u16(); + blitter_vcounter = restore_u16(); + restore_u16(); + blit_ch = restore_u8(); + restore_u8(); + restore_u8(); + restore_u8(); + blt_info.blit_finald = restore_u8(); + blitfc = restore_u8(); + blitife = restore_u8(); + + blt_info.blitbshift = restore_u8(); + blt_info.blitdownbshift = restore_u8(); + blt_info.blitashift = restore_u8(); + blt_info.blitdownashift = restore_u8(); + + ddat1use = restore_u8(); + restore_u8(); + ddat1 = restore_u16(); + restore_u16(); + + blitline = restore_u8(); + blitfill = restore_u8(); + blinea = restore_u16(); + blineb = restore_u16(); + blinea_shift = restore_u8(); + blitonedot = restore_u8(); + blitlinepixel = restore_u8(); + blitsing = restore_u8(); + blitlinepixel = restore_u8(); + blt_info.blit_interrupt = restore_u8(); + blt_delayed_irq = restore_u8(); + blt_info.blitzero = restore_u8(); + blt_info.got_cycle = restore_u8(); + + restore_u8(); + blit_faulty = restore_u8(); + restore_u8(); + restore_u8(); + restore_u8(); + + if (restore_u16() != 0x1234) write_log (_T("error\n")); - blt_info.blitter_nasty = restore_u8 (); + blt_info.blitter_nasty = restore_u8(); + tmp = restore_u8(); + shifter[0] = (tmp & 1) != 0; + shifter[1] = (tmp & 2) != 0; + shifter[2] = (tmp & 4) != 0; + shifter[3] = (tmp & 8) != 0; + blt_info.blit_finald = restore_u8(); + blit_ovf = restore_u8(); + + blt_info.blit_main = 0; + blt_info.blit_finald = 0; + blt_info.blit_pending = 0; - bltstate = BLT_done; if (!blitter_cycle_exact) { if (state > 0) do_blitter(0, 0, 0); } else { if (state == 1) - bltstate = BLT_init; + blt_info.blit_pending = 1; else if (state == 2) - bltstate = BLT_work; + blt_info.blit_main = 1; + if (blt_info.blit_finald) { + blt_info.blit_main = 0; + } + if (blt_statefile_type == 2) { + blit_bltset(0); + } } return src; } @@ -2030,77 +1888,80 @@ 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) + save_u8 (blitter_cycle_exact ? 3 : 0); + if (!blt_info.blit_main && !blt_info.blit_finald) state = 0; - else if (bltstate == BLT_init) + else if (blt_info.blit_pending) state = 1; else state = 2; save_u8 (state); - if (bltstate != BLT_done) { + if (blt_info.blit_main || blt_info.blit_finald) { write_log (_T("BLITTER active while saving state\n")); if (log_blitter) - blitter_dump (); - } - - 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); - - save_u8 (blt_info.blitbshift); - save_u8 (blt_info.blitdownbshift); - save_u8 (blt_info.blitashift); - save_u8 (blt_info.blitdownashift); - - save_u8 (ddat1use); - save_u8 (ddat2use); - save_u16 (ddat1); - save_u16 (ddat2); - - save_u8 (blitline); - save_u8 (blitfill); - save_u16 (blinea); - save_u16 (blineb); - save_u8 (blinea_shift); - save_u8 (blitonedot); - save_u8 (blitlinepixel); - save_u8 (blitsing); - save_u8 (blitlinepixel); - save_u8 (blt_info.blit_interrupt); - save_u8 (blt_delayed_irq); - save_u8 (blt_info.blitzero); - save_u8 (blt_info.got_cycle); + blitter_dump(); + } + + save_u32(blit_first_cycle); + save_u32(blit_last_cycle); + save_u32(blit_waitcyclecounter); + save_u32(0); //(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_hcounter); + save_u16(0); //(blitter_hcounter2); + save_u16(blitter_vcounter); + save_u16(0); //(blitter_vcounter2); + save_u8(blit_ch); + save_u8(blit_dmacount); + save_u8(blit_cyclecount); + save_u8(0); //(blit_nod); + save_u8(blt_info.blit_finald); + save_u8(blitfc); + save_u8(blitife); + + save_u8(blt_info.blitbshift); + save_u8(blt_info.blitdownbshift); + save_u8(blt_info.blitashift); + save_u8(blt_info.blitdownashift); + + save_u8(ddat1use); + save_u8(0); //(ddat2use); + save_u16(ddat1); + save_u16(0); //(ddat2); + + save_u8(blitline); + save_u8(blitfill); + save_u16(blinea); + save_u16(blineb); + save_u8(blinea_shift); + save_u8(blitonedot); + save_u8(blitlinepixel); + save_u8(blitsing); + save_u8(blitlinepixel); + save_u8(blt_info.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); - - save_u8 (blt_info.blitter_nasty); + save_u8(0); //(blit_frozen); + save_u8(blit_faulty); + save_u8(0); //original_ch); + save_u8(0); //original_fill); + save_u8(0); //original_line); + save_u8(0); //get_cycle_diagram_type (blit_diag)); + + save_u16(0x1234); + + save_u8(blt_info.blitter_nasty); + save_u8(shifter[0] | (shifter[1] << 1) | (shifter[2] << 2) | (shifter[3] << 3)); + save_u8(blt_info.blit_finald); + save_u8(blit_ovf); *len = dst - dstbak; return dstbak; diff --git a/custom.cpp b/custom.cpp index 14f372cc..6ce61d5c 100644 --- a/custom.cpp +++ b/custom.cpp @@ -366,7 +366,6 @@ struct copper { int strobe; /* COPJMP1 / COPJMP2 accessed */ int last_strobe; int moveaddr, movedata, movedelay; - int blitbusy; }; static struct copper cop_state; @@ -5206,16 +5205,25 @@ static uae_u16 DENISEID (int *missing) static bool blit_busy(void) { - if (blt_info.blit_interrupt) + if (!blt_info.blit_main && !blt_info.blit_finald) return false; + // AGA apparently fixes both bugs. if (currprefs.cs_agnusbltbusybug) { // Blitter busy bug: A1000 Agnus only sets busy-bit when blitter gets first DMA slot. - if (!blt_info.blit_interrupt && !blt_info.got_cycle) + if (!blt_info.got_cycle) + return false; + 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) return false; - // A1000 Agnus also has below bug but it does not need separate check because of above bug. } else if (!(currprefs.chipset_mask & CSMASK_AGA)) { + 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) + return false; #if 0 - // AGA apparently does not have this bug. // Blitter busy bug: Blitter nasty off, CPU attempting to steal cycle, Copper started blitter, // Copper WAITing for blitter finished: busy is not set until CPU gets the cycle. // NOT CORRECT YET @@ -5601,7 +5609,7 @@ static void COPJMP (int num, int vblank) if (!oldstrobe) cop_state.state_prev = cop_state.state; if ((cop_state.state == COP_wait || cop_state.state == COP_waitforever) && !vblank && dmaen(DMA_COPPER)) { - if (bltstate == BLT_work) { + if (blt_info.blit_main) { static int warned = 100; if (warned > 0) { write_log(_T("possible buggy copper cycle conflict with blitter PC=%08x\n"), M68K_GETPC); @@ -5712,10 +5720,10 @@ static void DMACON (int hpos, uae_u16 v) } #endif - if ((dmacon & DMA_BLITPRI) > (oldcon & DMA_BLITPRI) && bltstate != BLT_done) + if ((dmacon & DMA_BLITPRI) > (oldcon & DMA_BLITPRI) && (blt_info.blit_main || blt_info.blit_finald)) set_special (SPCFLAG_BLTNASTY); - if (dmaen (DMA_BLITTER) && bltstate == BLT_init) { + if (dmaen (DMA_BLITTER) && (blt_info.blit_pending || blt_info.blit_main || blt_info.blit_finald)) { blitter_check_start (); } @@ -6414,7 +6422,7 @@ static void BLTALWM (int hpos, uae_u16 v) { maybe_blit (hpos, 2); blt_info.bltal static void BLTAPTH (int hpos, uae_u16 v) { maybe_blit (hpos, 0); - if (bltstate != BLT_done && currprefs.blitter_cycle_exact && currprefs.cpu_memory_cycle_exact) { + if (blt_info.blit_main && currprefs.blitter_cycle_exact && currprefs.cpu_memory_cycle_exact) { bltptx = (bltapt & 0xffff) | ((uae_u32)v << 16); bltptxpos = hpos; bltptxc = 1; @@ -6425,7 +6433,7 @@ static void BLTAPTH (int hpos, uae_u16 v) static void BLTAPTL (int hpos, uae_u16 v) { maybe_blit (hpos, 0); - if (bltstate != BLT_done && currprefs.blitter_cycle_exact && currprefs.cpu_memory_cycle_exact) { + if (blt_info.blit_main && currprefs.blitter_cycle_exact && currprefs.cpu_memory_cycle_exact) { bltptx = (bltapt & ~0xffff) | (v & 0xFFFE); bltptxpos = hpos; bltptxc = 1; @@ -6436,7 +6444,7 @@ static void BLTAPTL (int hpos, uae_u16 v) static void BLTBPTH (int hpos, uae_u16 v) { maybe_blit (hpos, 0); - if (bltstate != BLT_done && currprefs.blitter_cycle_exact && currprefs.cpu_memory_cycle_exact) { + if (blt_info.blit_main && currprefs.blitter_cycle_exact && currprefs.cpu_memory_cycle_exact) { bltptx = (bltbpt & 0xffff) | ((uae_u32)v << 16); bltptxpos = hpos; bltptxc = 2; @@ -6447,7 +6455,7 @@ static void BLTBPTH (int hpos, uae_u16 v) static void BLTBPTL (int hpos, uae_u16 v) { maybe_blit (hpos, 0); - if (bltstate != BLT_done && currprefs.blitter_cycle_exact && currprefs.cpu_memory_cycle_exact) { + if (blt_info.blit_main && currprefs.blitter_cycle_exact && currprefs.cpu_memory_cycle_exact) { bltptx = (bltbpt & ~0xffff) | (v & 0xFFFE); bltptxpos = hpos; bltptxc = 2; @@ -6458,7 +6466,7 @@ static void BLTBPTL (int hpos, uae_u16 v) static void BLTCPTH (int hpos, uae_u16 v) { maybe_blit (hpos, 0); - if (bltstate != BLT_done && currprefs.blitter_cycle_exact && currprefs.cpu_memory_cycle_exact) { + if (blt_info.blit_main && currprefs.blitter_cycle_exact && currprefs.cpu_memory_cycle_exact) { bltptx = (bltcpt & 0xffff) | ((uae_u32)v << 16); bltptxpos = hpos; bltptxc = 3; @@ -6469,7 +6477,7 @@ static void BLTCPTH (int hpos, uae_u16 v) static void BLTCPTL (int hpos, uae_u16 v) { maybe_blit (hpos, 0); - if (bltstate != BLT_done && currprefs.blitter_cycle_exact && currprefs.cpu_memory_cycle_exact) { + if (blt_info.blit_main && currprefs.blitter_cycle_exact && currprefs.cpu_memory_cycle_exact) { bltptx = (bltcpt & ~0xffff) | (v & 0xFFFE); bltptxpos = hpos; bltptxc = 3; @@ -6480,7 +6488,7 @@ static void BLTCPTL (int hpos, uae_u16 v) static void BLTDPTH (int hpos, uae_u16 v) { maybe_blit (hpos, 0); - if (bltstate != BLT_done && currprefs.blitter_cycle_exact && currprefs.cpu_memory_cycle_exact) { + if ((blt_info.blit_main || blt_info.blit_finald) && currprefs.blitter_cycle_exact && currprefs.cpu_memory_cycle_exact) { bltptx = (bltdpt & 0xffff) | ((uae_u32)v << 16); bltptxpos = hpos; bltptxc = 4; @@ -6491,7 +6499,7 @@ static void BLTDPTH (int hpos, uae_u16 v) static void BLTDPTL (int hpos, uae_u16 v) { maybe_blit (hpos, 0); - if (bltstate != BLT_done && currprefs.blitter_cycle_exact && currprefs.cpu_memory_cycle_exact) { + if ((blt_info.blit_main || blt_info.blit_finald) && currprefs.blitter_cycle_exact && currprefs.cpu_memory_cycle_exact) { bltptx = (bltdpt & ~0xffff) | (v & 0xFFFE); bltptxpos = hpos; bltptxc = 4; @@ -7147,23 +7155,11 @@ static void update_copper (int until_hpos) if (copper_cant_read (old_hpos, 0)) continue; cop_state.state = COP_wait1; - // check blitter status early - cop_state.blitbusy = 0; - if ((cop_state.saved_i2 & 0x8000) == 0) { - decide_blitter(old_hpos); - cop_state.blitbusy = blit_busy(); - } break; case COP_skip_in2: if (copper_cant_read (old_hpos, 0)) continue; cop_state.state = COP_skip1; - // check blitter status early - cop_state.blitbusy = 0; - if ((cop_state.saved_i2 & 0x8000) == 0) { - decide_blitter(old_hpos); - cop_state.blitbusy = blit_busy(); - } break; case COP_strobe_extra: @@ -7495,13 +7491,7 @@ static void update_copper (int until_hpos) */ if ((cop_state.saved_i2 & 0x8000) == 0) { decide_blitter(old_hpos); - if (cop_state.blitbusy) { - if (!blit_busy()) { - // if blitter was actually finished - // check again next copper cycle. - cop_state.state = COP_wait_in2; - continue; - } + if (blit_busy()) { /* We need to wait for the blitter. */ cop_state.state = COP_bltwait; copper_enabled_thisline = 0; @@ -7532,6 +7522,9 @@ static void update_copper (int until_hpos) { unsigned int vcmp, hcmp, vp1, hp1; + if (c_hpos >= (maxhpos & ~1) || (c_hpos & 1)) + break; + if (copper_cant_read (old_hpos, 0)) continue; @@ -7544,8 +7537,9 @@ static void update_copper (int until_hpos) vp1 = vpos & (((cop_state.saved_i2 >> 8) & 0x7F) | 0x80); hp1 = ch_comp & (cop_state.saved_i2 & 0xFE); - if ((vp1 > vcmp || (vp1 == vcmp && hp1 >= hcmp)) && ((cop_state.saved_i2 & 0x8000) != 0 || !cop_state.blitbusy)) + if ((vp1 > vcmp || (vp1 == vcmp && hp1 >= hcmp)) && ((cop_state.saved_i2 & 0x8000) != 0 || !blit_busy())) { cop_state.ignore_next = 1; + } cop_state.state = COP_read1; @@ -9722,7 +9716,7 @@ static void hsync_handler_post (bool onvsync) } if (!nocustom ()) { - if (!currprefs.blitter_cycle_exact && bltstate != BLT_done && dmaen (DMA_BITPLANE) && diwstate == DIW_waiting_stop) { + if (!currprefs.blitter_cycle_exact && blt_info.blit_main && dmaen (DMA_BITPLANE) && diwstate == DIW_waiting_stop) { blitter_slowdown (thisline_decision.plfleft, thisline_decision.plfright - (16 << fetchmode), cycle_diagram_total_cycles[fetchmode][GET_RES_AGNUS (bplcon0)][GET_PLANES_LIMIT (bplcon0)], cycle_diagram_free_cycles[fetchmode][GET_RES_AGNUS (bplcon0)][GET_PLANES_LIMIT (bplcon0)]); @@ -10216,7 +10210,9 @@ void custom_reset (bool hardreset, bool keyboardreset) CLXCON2 (0); setup_fmodes (0); beamcon0 = new_beamcon0 = beamcon0_saved = currprefs.ntscmode ? 0x00 : 0x20; - bltstate = BLT_done; + blt_info.blit_main = 0; + blt_info.blit_finald = 0; + blt_info.blit_pending = 0; blt_info.blit_interrupt = 1; init_sprites (); } @@ -11704,7 +11700,7 @@ STATIC_INLINE void decide_fetch_ce (int hpos) // blitter idle cycles do count!) extern int cpu_tracer; -static int dma_cycle (void) +static int dma_cycle(uaecptr addr, uae_u16 v, int *mode) { int hpos, hpos_old; @@ -11723,15 +11719,19 @@ static int dma_cycle (void) sync_copper (hpos); decide_fetch_ce (hpos); bpldma = is_bitplane_dma (hpos_old); - if (bltstate != BLT_done) { - if (!blitpri && blt_info.nasty_cnt >= BLIT_NASTY_CPU_STEAL_CYCLE_COUNT && (cycle_line[hpos_old] & CYCLE_MASK) == 0 && !bpldma) { + 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[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; } - decide_blitter (hpos); + // CPU write must be done at the same time with blitter idle cycles + if (decide_blitter_maybe_write(hpos, addr, v)) { + // inform caller that write was already done + *mode = -2; + } // copper may have been waiting for the blitter sync_copper (hpos); } @@ -11779,7 +11779,7 @@ uae_u32 wait_cpu_cycle_read (uaecptr addr, int mode) uae_u32 v = 0; int hpos; - hpos = dma_cycle (); + hpos = dma_cycle(0xffffffff, 0xffff, NULL); x_do_cycles_pre (CYCLE_UNIT); #ifdef DEBUGGER @@ -11834,7 +11834,7 @@ uae_u32 wait_cpu_cycle_read_ce020 (uaecptr addr, int mode) int hpos; sync_ce020 (); - hpos = dma_cycle (); + hpos = dma_cycle(0xffffffff, 0xffff, NULL); x_do_cycles_pre (CYCLE_UNIT); #ifdef DEBUGGER @@ -11886,7 +11886,7 @@ void wait_cpu_cycle_write (uaecptr addr, int mode, uae_u32 v) { int hpos; - hpos = dma_cycle (); + hpos = dma_cycle(addr, v, &mode); x_do_cycles_pre (CYCLE_UNIT); #ifdef DEBUGGER @@ -11904,12 +11904,14 @@ void wait_cpu_cycle_write (uaecptr addr, int mode, uae_u32 v) peekdma_data.mask = 0; #endif - 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 > -2) { + if (mode < 0) + put_long(addr, v); + else if (mode > 0) + put_word(addr, v); + else if (mode == 0) + put_byte(addr, v); + } x_do_cycles_post (CYCLE_UNIT, v); @@ -11922,7 +11924,7 @@ void wait_cpu_cycle_write_ce020 (uaecptr addr, int mode, uae_u32 v) int hpos; sync_ce020 (); - hpos = dma_cycle (); + hpos = dma_cycle(0xffffffff, 0xffff, NULL); x_do_cycles_pre (CYCLE_UNIT); #ifdef DEBUGGER @@ -11963,7 +11965,7 @@ void do_cycles_ce (unsigned long cycles) decide_line (hpos); sync_copper (hpos); decide_fetch_ce (hpos); - if (bltstate != BLT_done) { + if (blt_info.blit_main || blt_info.blit_finald) { decide_blitter(hpos); } do_cycles (1 * CYCLE_UNIT); @@ -11996,7 +11998,7 @@ void do_cycles_ce020 (unsigned long cycles) decide_line (hpos); sync_copper (hpos); decide_fetch_ce (hpos); - if (bltstate != BLT_done) + if (blt_info.blit_main || blt_info.blit_finald) decide_blitter (hpos); if (c < CYCLE_UNIT) break; diff --git a/include/blitter.h b/include/blitter.h index 8275463e..6a6fb00b 100644 --- a/include/blitter.h +++ b/include/blitter.h @@ -23,12 +23,9 @@ struct bltinfo { int blitter_nasty, blit_interrupt; // blitter is active and D may write to visible bitplane addresses int blitter_dangerous_bpl; + int blit_main, blit_finald, blit_pending; }; -extern enum blitter_states { - BLT_done, BLT_init, BLT_read, BLT_work, BLT_write, BLT_next -} bltstate; - extern struct bltinfo blt_info; extern void check_is_blit_dangerous (uaecptr *bplpt, int planes, int words); @@ -38,7 +35,6 @@ extern uae_u16 bltcon0, bltcon1; extern uae_u32 bltapt, bltbpt, bltcpt, bltdpt; extern uae_u32 bltptx; extern int bltptxpos, bltptxc; -extern int blit_singlechannel; extern void maybe_blit (int, int); extern void reset_blit (int); @@ -46,11 +42,10 @@ extern int blitnasty (void); 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 int blitter_need (int hpos); +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 void blitter_slowdown (int, int, int, int); -extern int blitter_channel_state (void); extern void blitter_check_start (void); extern void blitter_reset (void); extern void blitter_debugdump(void); @@ -63,9 +58,4 @@ extern blitter_func * const blitfunc_dofast[256]; extern blitter_func * const blitfunc_dofast_desc[256]; extern uae_u32 blit_masktable[BLITTER_MAX_WORDS]; -#define BLIT_MODE_IMMEDIATE -1 -#define BLIT_MODE_APPROXIMATE 0 -#define BLIT_MODE_COMPATIBLE 1 -#define BLIT_MODE_EXACT 2 - #endif /* UAE_BLITTER_H */