From: Toni Wilen Date: Sun, 1 Jan 2023 15:16:39 +0000 (+0200) Subject: Copper, sprite and blitter DMA start/stop accuracy fix. New undocumented sprite DMA... X-Git-Tag: 41010~38 X-Git-Url: https://git.unchartedbackwaters.co.uk/w/?a=commitdiff_plain;h=5d4c3371bf91801843581f09ebe58e96689e2e9d;p=francis%2Fwinuae.git Copper, sprite and blitter DMA start/stop accuracy fix. New undocumented sprite DMA conflict emulation. --- diff --git a/blitter.cpp b/blitter.cpp index 3bc0bc1a..3a4e65a0 100644 --- a/blitter.cpp +++ b/blitter.cpp @@ -1331,29 +1331,35 @@ static int blitter_next_cycle(void) static void blitter_doddma_new(int hpos, bool addmod) { uaecptr *hpt = NULL; + bool skip = false; check_channel_mods(hpos, 4, &bltdpt); - bltdpt |= alloc_cycle_blitter_conflict_or(hpos); - record_dma_blit(0x00, ddat1, bltdpt, hpos); - blit_chipmem_agnus_wput(bltdpt, ddat1, MW_MASK_BLITTER_D_N); - bool skipadd = alloc_cycle_blitter(hpos, &bltdpt, 4, addmod ? blit_modaddd : 0); + bltdpt |= alloc_cycle_blitter_conflict_or(hpos, 4, &skip); + // alloc_cycle_blitter() can change modulo, old modulo is used during this cycle. + int mod = blit_modaddd; + if (!skip) { + record_dma_blit(0x00, ddat1, bltdpt, hpos); + blit_chipmem_agnus_wput(bltdpt, ddat1, MW_MASK_BLITTER_D_N); + } + bool skipadd = alloc_cycle_blitter(hpos, &bltdpt, 4, addmod ? mod : 0); if (!blitline && !skipadd) { bltdpt += blit_add; } if (addmod) { - bltdpt += blit_modaddd; + bltdpt += mod; } } static void blitter_dodma_new(int ch, int hpos, bool addmod) { - uae_u16 dat, reg; + uae_u16 dat; uae_u32 *addr; bool skipadd = false; int mod; + bool skip = false; - uaecptr orptr = alloc_cycle_blitter_conflict_or(hpos); + uaecptr orptr = alloc_cycle_blitter_conflict_or(hpos, ch, &skip); switch (ch) { @@ -1361,11 +1367,13 @@ static void blitter_dodma_new(int ch, int hpos, bool addmod) { bltapt |= orptr; check_channel_mods(hpos, 1, &bltapt); - reg = 0x74; - record_dma_blit(reg, 0, bltapt, hpos); - blt_info.bltadat = dat = chipmem_wget_indirect(bltapt); - record_dma_blit_val(dat); - regs.chipset_latch_rw = blt_info.bltadat; + if (!skip) { + uae_u16 reg = 0x74; + record_dma_blit(reg, 0, bltapt, hpos); + blt_info.bltadat = dat = chipmem_wget_indirect(bltapt); + record_dma_blit_val(dat); + regs.chipset_latch_rw = blt_info.bltadat; + } addr = &bltapt; mod = blit_modadda; skipadd = alloc_cycle_blitter(hpos, &bltapt, 1, addmod ? mod : 0); @@ -1376,11 +1384,13 @@ static void blitter_dodma_new(int ch, int hpos, bool addmod) int bshift = bltcon1 >> 12; bltbpt |= orptr; check_channel_mods(hpos, 2, &bltbpt); - reg = 0x72; - record_dma_blit(reg, 0, bltbpt, hpos); - blt_info.bltbdat = dat = chipmem_wget_indirect(bltbpt); - record_dma_blit_val(dat); - regs.chipset_latch_rw = blt_info.bltbdat; + if (!skip) { + uae_u16 reg = 0x72; + record_dma_blit(reg, 0, bltbpt, hpos); + blt_info.bltbdat = dat = chipmem_wget_indirect(bltbpt); + record_dma_blit_val(dat); + regs.chipset_latch_rw = blt_info.bltbdat; + } addr = &bltbpt; mod = blit_modaddb; if (blitdesc) @@ -1394,13 +1404,15 @@ static void blitter_dodma_new(int ch, int hpos, bool addmod) } case 3: // C { - reg = 0x70; bltcpt |= orptr; check_channel_mods(hpos, 3, &bltcpt); - record_dma_blit(reg, 0, bltcpt, hpos); - blt_info.bltcdat = dat = chipmem_wget_indirect(bltcpt); - record_dma_blit_val(dat); - regs.chipset_latch_rw = blt_info.bltcdat; + if (!skip) { + uae_u16 reg = 0x70; + record_dma_blit(reg, 0, bltcpt, hpos); + blt_info.bltcdat = dat = chipmem_wget_indirect(bltcpt); + record_dma_blit_val(dat); + regs.chipset_latch_rw = blt_info.bltcdat; + } addr = &bltcpt; mod = blit_modaddc; skipadd = alloc_cycle_blitter(hpos, &bltcpt, 3, addmod ? mod : 0); @@ -1572,12 +1584,15 @@ static bool decide_blitter_maybe_write2(int until_hpos, uaecptr addr, uae_u32 va blitter_line_proc_cpt_y(); blitlineloop = 0; } - uaecptr orptr = alloc_cycle_blitter_conflict_or(hpos); + bool skip = false; + uaecptr orptr = alloc_cycle_blitter_conflict_or(hpos, 3, &skip); record_dma_blit(0x70, 0, bltcpt | orptr, hpos); check_channel_mods(hpos, 3, &bltcpt); - blt_info.bltcdat = chipmem_wget_indirect(bltcpt | orptr); - regs.chipset_latch_rw = blt_info.bltcdat; - record_dma_blit_val(blt_info.bltcdat); + if (!skip) { + blt_info.bltcdat = chipmem_wget_indirect(bltcpt | orptr); + regs.chipset_latch_rw = blt_info.bltcdat; + record_dma_blit_val(blt_info.bltcdat); + } alloc_cycle_blitter(hpos, &bltcpt, 3, 0); if (dat & BLITTER_PIPELINE_FIRST) { @@ -1609,10 +1624,13 @@ static bool decide_blitter_maybe_write2(int until_hpos, uaecptr addr, uae_u32 va /* onedot mode and no pixel = bus write access is skipped */ if (blitlinepixel && c == 4) { - uaecptr orptr = alloc_cycle_blitter_conflict_or(hpos); + bool skip = false; + uaecptr orptr = alloc_cycle_blitter_conflict_or(hpos, 4, &skip); record_dma_blit(0x00, blt_info.bltddat, bltdpt | orptr, hpos); check_channel_mods(hpos, 4, &bltdpt); - blit_chipmem_agnus_wput(bltdpt | orptr, blt_info.bltddat, MW_MASK_BLITTER_D_L); + if (!skip) { + blit_chipmem_agnus_wput(bltdpt | orptr, blt_info.bltddat, MW_MASK_BLITTER_D_L); + } alloc_cycle_blitter(hpos, &bltdpt, 4, 0); } else { markidlecycle(hpos); diff --git a/custom.cpp b/custom.cpp index 8c036f9e..ba8e3604 100644 --- a/custom.cpp +++ b/custom.cpp @@ -66,7 +66,7 @@ #define ALL_SUBPIXEL 1 #define RGA_COPPER_PIPELINE_DEPTH 2 -#define RGA_SPRITE_PIPELINE_DEPTH 3 +#define RGA_SPRITE_PIPELINE_DEPTH 2 #define REFRESH_FIRST_HPOS 3 #define DMAL_FIRST_HPOS 11 #define SPR_FIRST_HPOS 25 @@ -391,6 +391,8 @@ struct sprite { static struct sprite spr[MAX_SPRITES]; static int plfstrt_sprite; static int sprbplconflict, sprbplconflict_hpos; +static int sprbplconflict2, sprbplconflict_hpos2; +static uae_u16 sprbplconflict_dat; uaecptr sprite_0; int sprite_0_width, sprite_0_height, sprite_0_doubled; uae_u32 sprite_0_colors[4]; @@ -519,6 +521,10 @@ static uaecptr copper_bad_cycle_pc_old; static evt_t copper_bad_cycle_start; static uaecptr copper_bad_cycle_pc_new; +static evt_t copper_dma_change_cycle; +static evt_t blitter_dma_change_cycle; +static evt_t sprite_dma_change_cycle_on, sprite_dma_change_cycle_off; + /* * Statistics */ @@ -576,7 +582,7 @@ static uae_u16 dmal_alloc_mask; #define RGA_PIPELINE_OFFSET_BPL_WRITE 3 #define RGA_PIPELINE_OFFSET_COPPER 2 -#define RGA_PIPELINE_OFFSET_SPRITE 3 +#define RGA_PIPELINE_OFFSET_SPRITE 2 #define RGA_PIPELINE_OFFSET_DMAL 2 struct custom_store custom_storage[256]; @@ -647,6 +653,11 @@ static int REGPARAM3 custom_wput_1(int, uaecptr, uae_u32, int) REGPARAM; * helper functions */ +static bool safecpu(void) +{ + return currprefs.cpu_model == 68000 && currprefs.cpu_cycle_exact && currprefs.blitter_cycle_exact && currprefs.m68k_speed == 0 && !(currprefs.cs_hacks & 16); +} + static void check_nocustom(void) { struct amigadisplay* ad = &adisplays[0]; @@ -778,11 +789,19 @@ void alloc_cycle_ext(int hpos, int type) alloc_cycle(hpos, type); } -uaecptr alloc_cycle_blitter_conflict_or(int hpos) +uaecptr alloc_cycle_blitter_conflict_or(int hpos, int chnum, bool *skip) { uaecptr orptr = 0; if (copper_bad_cycle && line_start_cycles + hpos * CYCLE_UNIT == copper_bad_cycle) { orptr = copper_bad_cycle_pc_old; + } else if (hpos == sprbplconflict_hpos2) { + uae_u16 bltdat = chnum == 4 ? 0x000 : (3 - chnum) * 2 + 0x70; + uae_u16 rga = bltdat & sprbplconflict2; + int spnum = (sprbplconflict2 - 0x140) / 8; + orptr = spr[spnum].pt; + if (rga != bltdat) { + *skip = true; + } } return orptr; } @@ -791,12 +810,26 @@ bool alloc_cycle_blitter(int hpos, uaecptr *ptr, int chnum, int add) { bool skipadd = false; if (copper_bad_cycle && line_start_cycles + hpos * CYCLE_UNIT == copper_bad_cycle) { - write_log("Copper PT=%08x/%08x. Blitter CH=%d PT=%08x. Conflict bug!\n", copper_bad_cycle_pc_old, copper_bad_cycle_pc_new, chnum, *ptr); + write_log("Copper PT=%08x/%08x. Blitter CH=%d MOD=%d PT=%08x. Conflict bug!\n", copper_bad_cycle_pc_old, copper_bad_cycle_pc_new, chnum, add, *ptr); cop_state.ip += add; *ptr = copper_bad_cycle_pc_old; skipadd = true; copper_bad_cycle = 0; - //activate_debugger(); + } else if (hpos == sprbplconflict_hpos2) { + uae_u16 v = chipmem_wget_indirect(*ptr); + uae_u16 bltdat = chnum == 4 ? 0x000 : (3 - chnum) * 2 + 0x70; + uae_u16 rga = bltdat & sprbplconflict2; + int spnum = (sprbplconflict2 - 0x140) / 8; + uaecptr pt = spr[spnum].pt; + spr[spnum].pt = *ptr + 2 + add; + custom_wput_1(hpos, rga, v, 1); +#ifdef DEBUGGER + if (debug_dma) { + record_dma_read_value(v); + record_dma_read(rga, *ptr, hpos, vpos, DMARECORD_SPRITE, spnum); + } +#endif + write_log("Sprite %d. Blitter CH=%d MOD=%d PT=%08x. Conflict bug!\n", spnum, chnum, add, *ptr); } alloc_cycle(hpos, CYCLE_BLITTER); return skipadd; @@ -5479,6 +5512,7 @@ static void reset_decisions_scanline_start(void) /* Default to no bitplane DMA overriding sprite DMA */ plfstrt_sprite = 0x100; sprbplconflict_hpos = -1; + sprbplconflict_hpos2 = -1; bprun_end = 0; // clear sprite allocations @@ -7461,6 +7495,24 @@ static int test_copper_dangerous(uaecptr address) return 0; } +// if DMA was changed during same cycle: previous value is used +static bool is_blitter_dma(void) +{ + bool dma = dmaen(DMA_BLITTER); + if (get_cycles() == blitter_dma_change_cycle) { + return dma == false; + } + return dma; +} +static bool is_copper_dma(void) +{ + bool dma = dmaen(DMA_COPPER); + if (get_cycles() == copper_dma_change_cycle) { + return dma == false; + } + return dma; +} + static void immediate_copper(int num) { int pos = 0; @@ -7473,7 +7525,7 @@ static void immediate_copper(int num) if (oldpos > pos) { pos = oldpos; } - if (!dmaen(DMA_COPPER)) { + if (!is_copper_dma()) { break; } if (cop_state.ip >= currprefs.chipmem.size && @@ -7542,7 +7594,7 @@ static void COPJMP(int num, int vblank) if (!oldstrobe) { cop_state.state_prev = cop_state.state; } - if ((cop_state.state == COP_wait1 || cop_state.state == COP_waitforever) && !vblank && dmaen(DMA_COPPER)) { + if ((cop_state.state == COP_wait1 || cop_state.state == COP_waitforever) && !vblank && is_copper_dma()) { if (blt_info.blit_main) { static int warned = 100; if (warned > 0) { @@ -7551,7 +7603,7 @@ static void COPJMP(int num, int vblank) } } int hp = current_hpos(); - if ((hp & 1) && currprefs.cpu_model == 68000 && currprefs.cpu_cycle_exact && currprefs.blitter_cycle_exact && currprefs.m68k_speed == 0 && !(currprefs.cs_hacks & 16)) { + if ((hp & 1) && safecpu()) { // CPU unaligned COPJMP while waiting cop_state.state = COP_strobe_delay1x; copper_bad_cycle_start = get_cycles(); @@ -7586,7 +7638,7 @@ static void COPJMP(int num, int vblank) return; } - if (dmaen(DMA_COPPER)) { + if (is_copper_dma()) { compute_spcflag_copper(); } else if (wasstopped || (oldstrobe > 0 && oldstrobe != num && cop_state.state_prev == COP_wait1)) { /* dma disabled, copper idle and accessed both COPxJMPs -> copper stops! */ @@ -7601,7 +7653,7 @@ STATIC_INLINE void COPCON(uae_u16 a) static void check_copper_stop(void) { - if (copper_enabled_thisline < 0 && !((dmacon & DMA_COPPER) && (dmacon & DMA_MASTER))) { + if (copper_enabled_thisline < 0 && !(is_copper_dma() && (dmacon & DMA_MASTER))) { copper_enabled_thisline = 0; unset_special(SPCFLAG_COPPER); } @@ -7620,9 +7672,7 @@ static void bitplane_dma_change(uae_u32 v) static void DMACON(int hpos, uae_u16 v) { - int oldcop, newcop; uae_u16 changed; - uae_u16 oldcon = dmacon; decide_line(hpos); @@ -7636,14 +7686,32 @@ static void DMACON(int hpos, uae_u16 v) if (changed) write_log(_T("%04x -> %04x %08x\n"), oldcon, dmacon, m68k_getpc ()); #endif - oldcop = (oldcon & DMA_COPPER) && (oldcon & DMA_MASTER); - newcop = (dmacon & DMA_COPPER) && (dmacon & DMA_MASTER); - if (oldcop != newcop) { - if (newcop && !oldcop) { - compute_spcflag_copper(); - } else if (!newcop) { - copper_stop(); + int oldcop = (oldcon & DMA_COPPER) && (oldcon & DMA_MASTER); + int newcop = (dmacon & DMA_COPPER) && (dmacon & DMA_MASTER); + if (oldcop != newcop && (copper_access || safecpu())) { + copper_dma_change_cycle = get_cycles(); + } + if (newcop && !oldcop) { + compute_spcflag_copper(); + } + + int oldblt = (oldcon & DMA_BLITTER) && (oldcon & DMA_MASTER); + int newblt = (dmacon & DMA_BLITTER) && (dmacon & DMA_MASTER); + if (oldblt != newblt && (copper_access || safecpu())) { + if (copper_access) { + blitter_dma_change_cycle = get_cycles(); + } else { + // because of CPU vs blitter emulation side-effect + blitter_dma_change_cycle = get_cycles() + CYCLE_UNIT; + } + } + + int oldspr = (oldcon & DMA_SPRITE) && (oldcon & DMA_MASTER); + int newspr = (dmacon & DMA_SPRITE) && (dmacon & DMA_MASTER); + if (!oldspr && newspr) { + if (copper_access || safecpu()) { + sprite_dma_change_cycle_on = get_cycles() + CYCLE_UNIT; } } @@ -7665,26 +7733,23 @@ static void DMACON(int hpos, uae_u16 v) } #endif - if ((dmacon & DMA_BLITPRI) > (oldcon & DMA_BLITPRI) && (blt_info.blit_main || blt_info.blit_finald || blt_info.blit_queued)) + if ((dmacon & DMA_BLITPRI) > (oldcon & DMA_BLITPRI) && (blt_info.blit_main || blt_info.blit_finald || blt_info.blit_queued)) { set_special(SPCFLAG_BLTNASTY); + } - if (dmaen (DMA_BLITTER) && blt_info.blit_pending) { + if (dmaen(DMA_BLITTER) && blt_info.blit_pending) { blitter_check_start(); } if ((dmacon & (DMA_BLITPRI | DMA_BLITTER | DMA_MASTER)) != (DMA_BLITPRI | DMA_BLITTER | DMA_MASTER)) unset_special(SPCFLAG_BLTNASTY); - if (changed & (DMA_MASTER | 0x0f)) + if (changed & (DMA_MASTER | DMA_AUD3 | DMA_AUD2 | DMA_AUD1 | DMA_AUD0)) { audio_state_machine(); + } if (changed & (DMA_MASTER | DMA_BITPLANE)) { - if (dmaen(DMA_BITPLANE)) { - bitplane_dma_change(dmacon); - } else { - bitplane_dma_change(dmacon); - //event2_newevent_xx(-1, CYCLE_UNIT, dmacon, bitplane_dma_change); - } + bitplane_dma_change(dmacon); SET_LINE_CYCLEBASED; } } @@ -9236,7 +9301,7 @@ bool bitplane_dma_access(int hpos, int offset) bool blitter_cant_access(int hpos) { - if (!dmaen(DMA_BLITTER)) { + if (!is_blitter_dma()) { return true; } // bitplane dma check @@ -9270,7 +9335,7 @@ bool blitter_cant_access(int hpos) static bool copper_cant_read(int hpos, uae_u16 alloc) { - if (!dmaen(DMA_COPPER)) { + if (!is_copper_dma()) { return true; } @@ -10220,7 +10285,7 @@ next: static void compute_spcflag_copper(void) { - if (!dmaen(DMA_COPPER) || cop_state.state == COP_stop || cop_state.state == COP_waitforever || cop_state.state == COP_bltwait || cop_state.state == COP_bltwait2 || custom_disabled) + if (!is_copper_dma() || cop_state.state == COP_stop || cop_state.state == COP_waitforever || cop_state.state == COP_bltwait || cop_state.state == COP_bltwait2 || custom_disabled) return; if (cop_state.state == COP_wait1) { int vp = vpos & (((cop_state.ir[1] >> 8) & 0x7F) | 0x80); @@ -10430,6 +10495,15 @@ static void do_sprite_fetch(int hpos, uae_u16 dat) decide_sprites(hpos, false, true); sprite_fetch_full(s, hpos, slot, dmastate, &data, &data321, &data322); + + // do pointer increase only + if (!(dat & CYCLE_PIPE_SPRITE)) { + if (debug_dma) { + record_dma_event(DMA_EVENT_SPECIAL, hpos, vpos); + } + return; + } + int sprxp = s->xpos >> (sprite_buffer_res + 1); if (dmastate) { if (!slot) { @@ -10509,12 +10583,6 @@ static void decide_sprites_fetch(int endhpos) while (hpos < endhpos) { if (hpos >= SPR_FIRST_HPOS - RGA_SPRITE_PIPELINE_DEPTH && hpos < SPR_FIRST_HPOS + MAX_SPRITES * 4) { - bool sprite_dma = (cycle_line_pipe[hpos] & CYCLE_PIPE_SPRITE) != 0; - if (sprite_dma) { - uae_u16 dat = cycle_line_pipe[hpos]; - do_sprite_fetch(hpos, dat); - } - if (hpos < SPR_FIRST_HPOS + MAX_SPRITES * 4 - RGA_SPRITE_PIPELINE_DEPTH) { int num = (hpos - (SPR_FIRST_HPOS - RGA_SPRITE_PIPELINE_DEPTH)) / 4; int slot = (hpos - (SPR_FIRST_HPOS - RGA_SPRITE_PIPELINE_DEPTH)) & 3; @@ -10563,9 +10631,17 @@ static void decide_sprites_fetch(int endhpos) write_log(_T("sprite cycle already allocated! %02x\n"), cycle_line_pipe[offset]); } #endif - if (bprun_end == hpos) { + evt_t t = line_start_cycles + hpos * CYCLE_UNIT; + if (t == sprite_dma_change_cycle_on) { + // if sprite DMA is switched on just when sprite DMA is decided, channel is still decided to it is not allocated! + sprbplconflict2 = 0x140 + num * 8 + slot + (s->dmacycle ? 4 : 0); + sprbplconflict_hpos = sprbplconflict_hpos2 = hpos + RGA_PIPELINE_OFFSET_SPRITE; + sprbplconflict_dat = dat & ~CYCLE_PIPE_SPRITE; + } else if (bprun_end == hpos) { + // last bitplane cycle is available for sprites (if bitplane ends before all sprites) sprbplconflict = 0x140 + num * 8 + slot + (s->dmacycle ? 4 : 0); sprbplconflict_hpos = hpos + RGA_PIPELINE_OFFSET_SPRITE; + sprbplconflict_dat = dat & ~CYCLE_PIPE_SPRITE; } else { cycle_line_pipe[offset] = dat; } @@ -10583,6 +10659,15 @@ static void decide_sprites_fetch(int endhpos) } } } + + bool sprite_dma = (cycle_line_pipe[hpos] & CYCLE_PIPE_SPRITE) != 0; + if (sprite_dma) { + uae_u16 dat = cycle_line_pipe[hpos]; + do_sprite_fetch(hpos, dat); + } + if (hpos == sprbplconflict_hpos2) { + do_sprite_fetch(hpos, sprbplconflict_dat); + } } hpos++; } @@ -13261,6 +13346,9 @@ void custom_reset(bool hardreset, bool keyboardreset) set_hcenter(); display_reset = 1; copper_bad_cycle = 0; + copper_dma_change_cycle = -1; + blitter_dma_change_cycle = -1; + sprite_dma_change_cycle_on = -1; if (hardreset || savestate_state) { maxhpos = ntsc ? MAXHPOS_NTSC : MAXHPOS_PAL; diff --git a/debug.cpp b/debug.cpp index 1823e69d..e7368cc5 100644 --- a/debug.cpp +++ b/debug.cpp @@ -2297,8 +2297,9 @@ static bool get_record_dma_info(struct dma_rec *dr, int hpos, int vpos, TCHAR *l chcnt = br + 1; } if (dr->cf_reg != 0xffff) { - _stprintf(srtext, _T("!%03x "), dr->cf_reg); + _stprintf(srtext, _T("!%03x"), dr->cf_reg); chcnt = -1; + regsize--; } else { _tcscpy(srtext, sr); } @@ -2355,13 +2356,17 @@ static bool get_record_dma_info(struct dma_rec *dr, int hpos, int vpos, TCHAR *l if (chcnt >= 0) { if (regsize == 3) _stprintf(l2, _T("%3s%d %03X"), srtext, chcnt, r); - else + else if (regsize == 2) _stprintf(l2, _T("%4s%d %02X"), srtext, chcnt, r); + else + _stprintf(l2, _T("%5s%d %02X"), srtext, chcnt, r); } else { if (regsize == 3) _stprintf(l2, _T("%4s %03X"), srtext, r); - else + else if (regsize == 2) _stprintf(l2, _T("%5s %02X"), srtext, r); + else + _stprintf(l2, _T("%6s %02X"), srtext, r); } } if (l3 && !noval) { diff --git a/include/custom.h b/include/custom.h index 031901f8..84b0e647 100644 --- a/include/custom.h +++ b/include/custom.h @@ -253,7 +253,7 @@ struct customhack { }; extern void alloc_cycle_ext(int, int); extern bool alloc_cycle_blitter(int hpos, uaecptr *ptr, int, int); -extern uaecptr alloc_cycle_blitter_conflict_or(int); +extern uaecptr alloc_cycle_blitter_conflict_or(int, int, bool*); extern bool ispal(int *lines); extern bool isvga(void); extern int current_maxvpos(void);