COP_skip1,
COP_strobe_delay1,
COP_strobe_delay2,
+ COP_strobe_delay3,
+ COP_strobe_delay4,
COP_strobe_delay1x,
COP_strobe_delay2x,
COP_strobe_extra, // just to skip current cycle when CPU wrote to COPJMP
{
uae_u16 hp = *hpp;
uae_u16 vp = *vpp;
+
hp++;
if (hp == maxhpos) {
hp = 0;
- }
- if (hp <= 1) {
+ } else if (hp == 1) {
// HP=0-1: VP = previous line.
vp = vpos_prev;
}
+
*hpp = hp;
*vpp = vp;
}
cop_state.state = COP_strobe_delay1;
}
} else {
- cop_state.state = vblank ? COP_strobe_delay2 : (copper_access ? COP_strobe_delay1 : COP_strobe_extra);
+ if (vblank) {
+ cop_state.state = COP_strobe_delay2;
+ switch (cop_state.state_prev)
+ {
+ case copper_states::COP_read2:
+ case copper_states::COP_read1:
+ // Wake up is delayed by 1 copper cycle if copper is currently loading words
+ cop_state.state = COP_strobe_delay3;
+ break;
+
+ }
+ } else {
+ cop_state.state = copper_access ? COP_strobe_delay1 : COP_strobe_extra;
+ }
}
cop_state.vblankip = cop1lc;
copper_enabled_thisline = 0;
break;
}
case COP_strobe_delay2:
+ case COP_strobe_delay3:
{
// fake MOVE phase 2
#ifdef DEBUGGER
record_dma_read_value(cop_state.ir[1]);
}
#endif
- cop_state.state = COP_read1;
+ if (cop_state.state == COP_strobe_delay3) {
+ cop_state.state = COP_strobe_delay4;
+ } else {
+ cop_state.state = COP_read1;
+ }
// Next cycle finally reads from new pointer
if (cop_state.strobe == 1) {
cop_state.ip = cop1lc;
alloc_cycle(hpos, CYCLE_COPPER);
}
break;
+ case COP_strobe_delay4:
+ {
+ // COPJMP when previous instruction is mid-cycle
+ cop_state.state = COP_read1;
+ alloc_cycle(hpos, CYCLE_COPPER);
+ }
+ break;
case COP_strobe_delay2x:
if (debug_dma) {
record_dma_event(DMA_EVENT_SPECIAL, hpos, vpos);
int hpos_cmp = hpos;
int vpos_cmp = vpos;
+ // If waiting for last cycle of line and last cycle is even cycle:
+ // Horizontal counter has already wrapped around to zero.
if (hpos_cmp == maxhposm1 && maxhposeven == COPPER_CYCLE_POLARITY) {
hpos_cmp = 0;
}
return -1;
}
+ // Cycle 0: copper can't wake up
+ if (hpos == 0) {
+ return 1;
+ }
+
if ((cop_state.ir[1] & 0x8000) == 0) {
decide_blitter(hpos);
if (blit_busy(-1, false)) {
}
break;
case COP_strobe_delay2:
+ case COP_strobe_delay3:
+ case COP_strobe_delay4:
// Second cycle after COPJMP does basically skipped MOVE (MOVE to 1FE)
// Cycle is used and needs to be free.
copper_cant_read(hpos, CYCLE_PIPE_COPPER);
}
}
-static void delayed_copjmp(uae_u32 v)
+static void check_vblank_copjmp(uae_u32 v)
{
COPJMP(1, 1);
}
static void delayed_framestart(uae_u32 v)
{
- COPJMP(1, 1);
+ check_vblank_copjmp(0);
send_interrupt(5, 2 * CYCLE_UNIT); // total REFRESH_FIRST_HPOS + 1
}
} else if (vb_start_line == 1) {
send_interrupt(5, (REFRESH_FIRST_HPOS + 1) * CYCLE_UNIT);
} else if (vpos == 0) {
- event2_newevent_xx(-1, 2 * CYCLE_UNIT, 0, delayed_copjmp);
+ event2_newevent_xx(-1, 2 * CYCLE_UNIT, 0, check_vblank_copjmp);
}
// lastline - 1?