static int hpos_hsync_extra;
static int vpos_count, vpos_count_diff;
int lof_store; // real bit in custom registers
-static int lof_current; // what display device thinks
+int lof_display; // what display device thinks
static bool lof_lastline, lof_prev_lastline;
static int lol, lol_prev;
static int next_lineno;
return ((pos + hpos_hsync_extra) * 2 - DDF_OFFSET) * 4;
}
-static int doflickerfix(void)
+static bool doflickerfix_possible(void)
{
return currprefs.gfx_vresolution && doublescan < 0 && vpos < MAXVPOS;
}
+static bool doflickerfix_active(void)
+{
+ return interlace_seen > 0 && doflickerfix_possible();
+}
uae_u32 get_copper_address(int copno)
{
// This does not need start line check because only OCS Denise modes use this.
static int get_equ_vblank_endline(void)
{
- return equ_vblank_endline + (equ_vblank_toggle ? (lof_current ? 1 : 0) : 0);
+ return equ_vblank_endline + (equ_vblank_toggle ? (lof_store ? 1 : 0) : 0);
}
static int output_res(int res)
}
// HCENTER blanking
- if (hcenter_v2 && vs_state_on && vpos < maxvpos_display_vsync && lof_current) {
+ if (hcenter_v2 && vs_state_on && vpos < maxvpos_display_vsync && lof_display) {
int chpos = pos;
if (hcenter_v2_end == 0xffff && hcenter_v2 < chpos && hcenter_v2 >= last_recorded_diw_hpos) {
cc = &curr_color_changes[next_color_change];
// erase (color0 or bblank) area between previous end and new start
static void hdiw_restart(int diw_last, int diw_current)
{
- if (diw_last >= diw_current || line_hidden()) {
+ if (diw_last >= diw_current || line_hidden() || nocustom()) {
return;
}
// update state
clear_bitplane_pipeline(1);
if (thisline_decision.plfleft < 0) {
+ // registers that affect programmed vblank must be checked even if line is blank
+ if (line_decisions[next_lineno].bplcon3 != thisline_decision.bplcon3
+ || (line_decisions[next_lineno].bplcon0 & 1) != (thisline_decision.bplcon0 & 1)
+ || line_decisions[next_lineno].vb != thisline_decision.vb
+ )
+ thisline_changed = 1;
return;
}
static void scandoubler_bpl_dma_start(void)
{
- if (!scandoubled_line && doflickerfix() && interlace_seen > 0) {
- int lof = 1 - lof_current;
+ if (!scandoubled_line && doflickerfix_active()) {
+ int lof = 1 - lof_display;
for (int i = 0; i < MAX_PLANES; i++) {
prevbpl[lof][vpos][i] = bplptx[i];
if (!lof && (bplcon0 & 4)) {
{
bool forceoff = (vb_start_line == 1 && !harddis_v);
- // if scandoubler mode: stop display before possible last non-paired line
- if (doflickerfix() && interlace_seen > 0 && vpos + 1 >= maxvpos && lof_current && diwstate == DIW_waiting_stop) {
- forceoff = true;
- }
-
/* Take care of the vertical DIW. */
if (vpos == plffirstline && !forceoff) {
diwstate = DIW_waiting_stop;
thisline_decision.vb = vb_start_line > 1 + vblank_extraline ? 0 : 1;
}
// if programmed vblank
- if (!thisline_decision.vb && (beamcon0 & 0x1000) && ecs_agnus) {
- thisline_decision.vb |= 2;
+ if ((beamcon0 & 0x1000) && ecs_agnus) {
+ if (!thisline_decision.vb) {
+ thisline_decision.vb |= 2;
+ }
+ }
+ // doublescan last line garbage workaround
+ if (doflickerfix_active()) {
+ if (vpos < maxvpos_display_vsync || (!lof_display && vpos >= maxvpos - 1) || (lof_display && vpos >= maxvpos - 1)) {
+ thisline_decision.vb |= 4;
+ }
}
+
if (!ecs_denise && vb_end_line) {
thisline_decision.vb = 1;
}
delay_cycles2 = delay_cycles;
set_delay_lastcycle();
- if (1 && fetchmode >= 2 && !doflickerfix()) {
+ if (1 && fetchmode >= 2 && !doflickerfix_active()) {
// handle bitplane data wrap around
bool toshift = false;
if ((exthblank || (beamcon0 & 0x0110)) && (thisline_decision.bplres == 0 || currprefs.chipset_hr)) {
}
if (interlace_seen) {
svpos += 0.5;
- } else if (lof_current) {
+ } else if (lof_display) {
svpos += 1.0;
}
if (currprefs.produce_sound > 1) {
if (islace) {
vblank_hz = vblank_hz_lace;
- } else if (lof_current) {
+ } else if (lof_store) {
vblank_hz = vblank_hz_lof;
} else {
vblank_hz = vblank_hz_shf;
}
vblank_hz = (isntsc ? 15734.0 : 15625.0) / vpos_count;
vblank_hz_nom = vblank_hz_shf = vblank_hz_lof = vblank_hz_lace = (float)vblank_hz;
- maxvpos_nom = vpos_count - (lof_current ? 1 : 0);
+ maxvpos_nom = vpos_count - (lof_store ? 1 : 0);
if ((maxvpos_nom >= 256 && maxvpos_nom <= 313) || (beamcon0 & 0x80)) {
maxvpos_display = maxvpos_nom;
} else if (maxvpos_nom < 256) {
{
v = BPLCON0_Denise_mask(v);
- if (bplcon0d == v || bplcon0d_change) {
+ if (bplcon0d == v && !bplcon0d_change) {
return;
}
bplcon0d_change = false;
if (hpos >= endhpos) {
return;
}
- if (vb_state || (doflickerfix() && interlace_seen && (next_lineno & 1))) {
+ if (vb_state || (doflickerfix_active() && (next_lineno & 1))) {
last_decide_sprite_hpos = endhpos;
return;
}
lineno %= MAXVPOS;
}
nextline_how = nln_normal;
- if (doflickerfix() && interlace_seen > 0) {
+ if (doflickerfix_active()) {
lineno *= 2;
}
else if (!interlace_seen && doublescan <= 0 && currprefs.gfx_vresolution && currprefs.gfx_pscanlines > 1) {
} else if ((doublescan <= 0 || interlace_seen > 0) && currprefs.gfx_vresolution && currprefs.gfx_iscanlines) {
lineno *= 2;
if (interlace_seen) {
- if (!lof_current) {
+ if (!lof_display) {
lineno++;
nextline_how = currprefs.gfx_iscanlines == 2 ? nln_lower_black_always : nln_lower_black;
} else {
} else if (currprefs.gfx_vresolution && (doublescan <= 0 || interlace_seen > 0)) {
lineno *= 2;
if (interlace_seen) {
- if (!lof_current) {
+ if (!lof_display) {
lineno++;
nextline_how = nln_lower;
} else {
}
}
prev_next_sprite_entry = next_sprite_entry;
+ next_sprite_entry = 0;
next_lineno = calculate_lineno(vpos);
last_color_change = 0;
next_color_change = 0;
- next_sprite_entry = 0;
next_color_entry = 0;
remembered_color_entry = -1;
#endif
}
lof_prev_lastline = lof_lastline;
- lof_current = lof_store;
if (lof_togglecnt_lace >= LOF_TOGGLES_NEEDED) {
interlace_changed = notice_interlace_seen(true);
if (interlace_changed) {
return;
}
- int lof = lof_store;
+ int lof = lof_display;
next_lineno++;
scandoubled_line = 1;
last_hdiw = 0 - 1;
} else {
bplpt[i] = bplpt[i] - diff;
}
-
}
}
}
if (!nocustom()) {
- finish_decisions(hpos);
-
- hsync_record_line_state(next_lineno, nextline_how, thisline_changed);
-
- if (doflickerfix() && interlace_seen > 0) {
+ if (doflickerfix_active()) {
+ finish_decisions(hpos);
+ hsync_record_line_state(next_lineno, nextline_how, thisline_changed);
hsync_scandoubler(hpos);
+ } else {
+ finish_decisions(hpos);
+ hsync_record_line_state(next_lineno, nextline_how, thisline_changed);
}
notice_resolution_seen(GET_RES_AGNUS(bplcon0), interlace_seen != 0);
}
if (beamcon0 & 0x20) {
- if (vpos == 2 && !lof_current) {
+ if (vpos == 2 && !lof_store) {
vs_state_hw = true;
}
- if (vpos == 3 && lof_current) {
+ if (vpos == 3 && lof_store) {
vs_state_hw = true;
}
if (vpos == 5) {
if (diwstate == DIW_waiting_stop) {
record_dma_event(DMA_EVENT_VDIW, REFRESH_FIRST_HPOS, vpos);
}
- if (lof_current) {
+ if (lof_store) {
record_dma_event(DMA_EVENT_LOF, REFRESH_FIRST_HPOS + 2, vpos);
}
if (lol) {
if (vpos == maxvpos_display_vsync) {
vsync_display_render();
vsync_display_rendered = false;
+ lof_display = lof_store;
reset_autoscale();
}
vsync_line = vs;
}
#endif
}
- lof_store = lof_current = 0;
+ lof_store = lof_display = 0;
lof_lace = false;
setextblank();
}
(unsigned int)diwstrt, (unsigned int)diwstop, (unsigned int)ddfstrt, (unsigned int)ddfstop);
console_out_f(_T("BPLCON 0: %04x 1: %04x 2: %04x 3: %04x 4: %04x LOF=%d/%d HDIW=%d VDIW=%d\n"),
bplcon0, bplcon1, bplcon2, bplcon3, bplcon4,
- lof_current, lof_store,
+ lof_display, lof_store,
hdiwstate == DIW_waiting_start ? 0 : 1, diwstate == DIW_waiting_start ? 0 : 1);
if (timeframes) {
console_out_f(_T("Average frame time: %.2f ms [frames: %d time: %d]\n"),
dsklen = RW; /* 024 DSKLEN */
RW; /* 026 DSKDAT */
refptr = RW; /* 028 REFPTR */
- i = RW; lof_store = lof_current = (i & 0x8000) ? 1 : 0; lol = (i & 0x0080) ? 1 : 0; /* 02A VPOSW */
+ i = RW; lof_store = lof_display = (i & 0x8000) ? 1 : 0; lol = (i & 0x0080) ? 1 : 0; /* 02A VPOSW */
RW; /* 02C VHPOSW */
COPCON(RW); /* 02E COPCON */
RW; /* 030 SERDAT* */
extern int ddffirstword_total, ddflastword_total;
extern bool vertical_changed, horizontal_changed;
extern int firstword_bplcon1;
-extern int lof_store;
+extern int lof_display;
#define MIN_DISPLAY_W 256
#define MIN_DISPLAY_H 192
if (!ecs_denise) {
vbstrt--;
}
- int vbstop = maxvpos + lof_store;
+ int vbstop = maxvpos + lof_display;
if (!ecs_denise && !ecs_agnus) {
vbstop++;
} else if (ecs_agnus && !ecs_denise) {
if (interlace_seen) {
static int interlace_count;
// interlace = only use long frames
- if (lof_store && (interlace_count & 1) == 0)
+ if (lof_display && (interlace_count & 1) == 0)
interlace_count++;
- if (!lof_store && (interlace_count & 1) != 0)
+ if (!lof_display && (interlace_count & 1) != 0)
interlace_count++;
if (interlace_count < 3)
return ret;
- if (!lof_store)
+ if (!lof_display)
return ret;
interlace_count = 0;
/* program may have set last visible line as last possible line (CD32 boot screen) */
int endpos = visible_left_border + vidinfo->drawbuffer.inwidth;
int w = endpos - lastpos;
- if (lineno < visible_top_start || lineno < vblank_top_start || lineno >= visible_bottom_stop || lineno >= vblank_bottom_stop) {
+ if (lineno < visible_top_start || lineno < vblank_top_start || lineno >= visible_bottom_stop || lineno >= vblank_bottom_stop || vb_state >= 4) {
int b = hposblank;
hposblank = 3;
fill_line2(lastpos, w);
}
// vblank + programmed vblank / hardwired vblank
- if (vb_state == 2 || vbarea) {
+ if (vb_state == 2 || vb_state >= 4 || vbarea) {
+ if (vbarea || vb_state >= 4) {
+ hposblank = 3;
+ }
if (nextpos_in_range > lastpos && lastpos < playfield_end) {
int t = nextpos_in_range <= playfield_end ? nextpos_in_range : playfield_end;
(*worker_border)(lastpos, t, 1);
if (ad->framecnt != 0)
return;
+ //write_log("%d:%d:%d ", lineno, how, lof_display);
+
state = linestate + lineno;
changed |= ad->frame_redraw_necessary != 0 || refresh_indicator_buffer != NULL ||
((lineno >= lightpen_y1[0] && lineno < lightpen_y2[0]) ||
}
break;
case nln_lower:
- if (lineno > 0 && state[-1] == LINE_UNDECIDED) {
+ if (state[-1] == LINE_UNDECIDED) {
state[-1] = LINE_DECIDED; //LINE_BLACK;
}
*state = changed ? LINE_DECIDED : LINE_DONE;
case nln_lower_black_always:
state[1] = LINE_BLACK;
*state = LINE_DECIDED;
-// if (lineno == (maxvpos + lof_store) * 2 - 1)
-// *state = LINE_BLACK;
break;
case nln_lower_black:
changed |= state[0] != LINE_DONE;
- state[1] = LINE_DONE;
*state = changed ? LINE_DECIDED : LINE_DONE;
-// if (lineno == (maxvpos + lof_store) * 2 - 1)
-// *state = LINE_BLACK;
+ state[1] = LINE_DONE;
break;
case nln_upper_black_always:
*state = LINE_DECIDED;
- if (lineno > 0) {
- state[-1] = LINE_BLACK;
- }
- if (!interlace_seen && lineno == (maxvpos + lof_store) * 2 - 2) {
- state[1] = LINE_BLACK;
- }
+ state[-1] = LINE_BLACK;
break;
case nln_upper_black:
changed |= state[0] != LINE_DONE;
*state = changed ? LINE_DECIDED : LINE_DONE;
- if (lineno > 0) {
- state[-1] = LINE_DONE;
- }
- if (!interlace_seen && lineno == (maxvpos + lof_store) * 2 - 2) {
- state[1] = LINE_DONE;
- }
+ state[-1] = LINE_DONE;
break;
}
}