static void blitter_doddma_new(int hpos, bool addmod)
{
- check_channel_mods(hpos, 4, &bltdpt);
+ uaecptr *hpt = NULL;
- record_dma_blit(0x00, ddat1, bltdpt, hpos);
- blit_chipmem_agnus_wput(bltdpt, ddat1, MW_MASK_BLITTER_D_N);
- alloc_cycle_blitter(hpos, &bltdpt, 4);
+ check_channel_mods(hpos, 4, &bltdpt);
+ uaecptr orptr = alloc_cycle_blitter_conflict_or();
+ record_dma_blit(0x00, ddat1, bltdpt | orptr, hpos);
+ blit_chipmem_agnus_wput(bltdpt | orptr, ddat1, MW_MASK_BLITTER_D_N);
+ bool skipadd = alloc_cycle_blitter(hpos, &bltdpt, 4, addmod ? blit_modaddd : 0);
- if (!blitline) {
+ if (!blitline && !skipadd) {
bltdpt += blit_add;
}
if (addmod) {
{
uae_u16 dat, reg;
uae_u32 *addr;
+ bool skipadd = false;
int mod;
+ uaecptr orptr = alloc_cycle_blitter_conflict_or();
+
switch (ch)
{
case 1: // A
{
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(reg, 0, bltapt | orptr, hpos);
+ blt_info.bltadat = dat = chipmem_wget_indirect(bltapt | orptr);
record_dma_blit_val(dat);
regs.chipset_latch_rw = blt_info.bltadat;
addr = &bltapt;
mod = blit_modadda;
- alloc_cycle_blitter(hpos, &bltapt, 1);
+ skipadd = alloc_cycle_blitter(hpos, &bltapt, 1, addmod ? mod : 0);
break;
}
case 2: // B
int bshift = bltcon1 >> 12;
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(reg, 0, bltbpt | orptr, hpos);
+ blt_info.bltbdat = dat = chipmem_wget_indirect(bltbpt | orptr);
record_dma_blit_val(dat);
regs.chipset_latch_rw = blt_info.bltbdat;
addr = &bltbpt;
blt_info.bltbhold = (((uae_u32)blt_info.bltbold << 16) | blt_info.bltbdat) >> bshift;
blineb = blt_info.bltbhold;
blt_info.bltbold = blt_info.bltbdat;
- alloc_cycle_blitter(hpos, &bltbpt, 2);
+ skipadd = alloc_cycle_blitter(hpos, &bltbpt, 2, addmod ? mod : 0);
break;
}
case 3: // C
{
reg = 0x70;
check_channel_mods(hpos, 3, &bltcpt);
- record_dma_blit(reg, 0, bltcpt, hpos);
- blt_info.bltcdat = dat = chipmem_wget_indirect(bltcpt);
+ record_dma_blit(reg, 0, bltcpt | orptr, hpos);
+ blt_info.bltcdat = dat = chipmem_wget_indirect(bltcpt | orptr);
record_dma_blit_val(dat);
regs.chipset_latch_rw = blt_info.bltcdat;
addr = &bltcpt;
mod = blit_modaddc;
- alloc_cycle_blitter(hpos, &bltcpt, 3);
+ skipadd = alloc_cycle_blitter(hpos, &bltcpt, 3, addmod ? mod : 0);
break;
}
default:
abort();
}
- if (!blitline) {
+ if (!blitline && !skipadd) {
(*addr) += blit_add;
}
if (addmod) {
blitter_line_proc_cpt_y();
blitlineloop = 0;
}
-
- record_dma_blit(0x70, 0, bltcpt, hpos);
+ uaecptr orptr = alloc_cycle_blitter_conflict_or();
+ record_dma_blit(0x70, 0, bltcpt | orptr, hpos);
check_channel_mods(hpos, 3, &bltcpt);
- blt_info.bltcdat = chipmem_wget_indirect(bltcpt);
+ 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);
+ alloc_cycle_blitter(hpos, &bltcpt, 3, 0);
if (dat & BLITTER_PIPELINE_FIRST) {
blitter_line_minterm(dat);
/* onedot mode and no pixel = bus write access is skipped */
if (blitlinepixel && c == 4) {
- record_dma_blit(0x00, blt_info.bltddat, bltdpt, hpos);
+ uaecptr orptr = alloc_cycle_blitter_conflict_or();
+ record_dma_blit(0x00, blt_info.bltddat, bltdpt | orptr, hpos);
check_channel_mods(hpos, 4, &bltdpt);
- blit_chipmem_agnus_wput(bltdpt, blt_info.bltddat, MW_MASK_BLITTER_D_L);
- alloc_cycle_blitter(hpos, &bltdpt, 4);
+ blit_chipmem_agnus_wput(bltdpt | orptr, blt_info.bltddat, MW_MASK_BLITTER_D_L);
+ alloc_cycle_blitter(hpos, &bltdpt, 4, 0);
} else {
markidlecycle(hpos);
}
bltdpt = bltcpt;
blitter_line_minterm(dat);
-
+#if 0
+ if (blt_info.hblitsize == 1) {
+ blitter_line_proc_cpt_x();
+ blitter_line_proc_cpt_y();
+ }
+#endif
} else {
// normal mode channels
static struct copper cop_state;
static int copper_enabled_thisline;
+static evt_t copper_bad_cycle;
+static uaecptr copper_bad_cycle_pc_old;
+static evt_t copper_bad_cycle_start;
+static uaecptr copper_bad_cycle_pc_new;
/*
* Statistics
alloc_cycle(hpos, type);
}
-void alloc_cycle_blitter(int hpos, uaecptr *ptr, int chnum)
+uaecptr alloc_cycle_blitter_conflict_or(void)
{
- if (cycle_line_slot[hpos] & CYCLE_COPPER_SPECIAL) {
- if ((currprefs.cs_hacks & 1) && currprefs.cpu_model == 68000) {
- uaecptr srcptr = cop_state.strobe == 1 ? cop1lc : cop2lc;
- //if (currprefs.cpu_model == 68000 && currprefs.cpu_cycle_exact && currprefs.blitter_cycle_exact) {
- // batman group / batman vuelve triggers this incorrectly. More testing needed.
- *ptr = srcptr;
- //activate_debugger();
- }
+ uaecptr orptr = 0;
+ if (get_cycles() == copper_bad_cycle) {
+ orptr = copper_bad_cycle_pc_old;
+ }
+ return orptr;
+}
+
+bool alloc_cycle_blitter(int hpos, uaecptr *ptr, int chnum, int add)
+{
+ bool skipadd = false;
+ if (get_cycles() == copper_bad_cycle) {
+ write_log("Copper PT=%08x %08x. Blitter CH=%d PT=%08x bug!\n", copper_bad_cycle_pc_old, copper_bad_cycle_pc_new, chnum, *ptr);
+ cop_state.ip += add;
+ *ptr = copper_bad_cycle_pc_new;
+ skipadd = true;
+ //activate_debugger();
}
alloc_cycle(hpos, CYCLE_BLITTER);
+ return skipadd;
}
static int expand_sprres(uae_u16 con0, uae_u16 con3)
warned--;
}
}
- if (current_hpos() & 1) {
- cop_state.state = COP_strobe_delay1x; // CPU unaligned COPJMP while waiting
+ int hp = current_hpos();
+ if ((hp & 1) && currprefs.cpu_model == 68000 && currprefs.cpu_cycle_exact) {
+ // CPU unaligned COPJMP while waiting
+ cop_state.state = COP_strobe_delay1x;
+ copper_bad_cycle_start = get_cycles();
} else {
cop_state.state = COP_strobe_delay1;
}
if (scandoubled_line) {
return;
}
- if (id == COPPER_CYCLE_IDLE) {
- // copper allocated cycle without DMA request
+
+ if (id & CYCLE_PIPE_NONE) {
alloc_cycle(hpos, CYCLE_COPPER);
return;
}
}
break;
case COP_strobe_delay2x:
- if (debug_dma) {
- record_dma_event(DMA_EVENT_SPECIAL, hpos, vpos);
- }
#ifdef DEBUGGER
{
if (debug_dma) {
cop_state.ip = cop2lc;
}
cop_state.strobe = 0;
-
alloc_cycle(hpos, CYCLE_COPPER);
- cycle_line_slot[hpos] |= CYCLE_COPPER_SPECIAL;
break;
case COP_start_delay:
cop_state.state = COP_read1;
case COP_strobe_delay2x:
// Second cycle fetches following word and tosses it away.
// Cycle can be free and copper won't allocate it.
- // If Blitter uses this cycle = Copper's PC gets copied to blitter DMA pointer..
- copper_cant_read(hpos, CYCLE_PIPE_COPPER | 0x09);
- break;
+ // If Blitter uses this cycle = Copper's new PC gets copied to blitter DMA pointer..
+ if (!copper_cant_read(hpos, CYCLE_PIPE_COPPER | 0x09)) {
+ copper_bad_cycle = get_cycles();
+ // conflict also does not happen if previous cycle was used by bitplane
+ // (if bitplane DMA is allocated, copper internal operations are also stopped)
+ int bpl = 0;// get_bitplane_dma_rel(hpos, -1);
+ if (copper_bad_cycle - copper_bad_cycle_start != 3 * CYCLE_UNIT || bpl) {
+ copper_bad_cycle = 0;
+ } else {
+ if (debug_dma) {
+ record_dma_event(DMA_EVENT_SPECIAL, hpos, vpos);
+ }
+ // early COPJMP processing
+ cop_state.state = COP_read1;
+ copper_bad_cycle_pc_old = cop_state.ip;
+ if (cop_state.strobe == 1) {
+ cop_state.ip = cop1lc;
+ } else {
+ cop_state.ip = cop2lc;
+ }
+ copper_bad_cycle_pc_new = cop_state.ip;
+ cop_state.strobe = 0;
+ }
+ }
+ break;
case COP_start_delay:
// cycle after vblank strobe fetches word from old pointer first
hcenter_v2 = 0;
set_hcenter();
display_reset = 1;
+ copper_bad_cycle = 0;
if (hardreset || savestate_state) {
maxhpos = ntsc ? MAXHPOS_NTSC : MAXHPOS_PAL;
toscr_delay_sh[0] = 0;
toscr_delay_sh[1] = 0;
+ memset(&cop_state, 0, sizeof(cop_state));
cop_state.state = COP_stop;
- cop_state.movedelay = 0;
- cop_state.strobe = 0;
- cop_state.ignore_next = 0;
+
vdiwstate = diw_states::DIW_waiting_start;
vdiw_change(0);
check_harddis();