static int diwstate_vpos;
static int bpl_hstart;
static bool exthblank, exthblank_state;
+static int last_diw_hpos, last_diw_hpos2;
int first_planes_vpos, last_planes_vpos;
static int first_bplcon0, first_bplcon0_old;
static int bprun;
static int bprun_cycle;
static int bprun_pipeline_flush_delay;
-static bool plane0, plane0p, plane0p_enabled, plane0_prehsync;
+static bool plane0, plane0p, plane0p_enabled, plane0p_forced, plane0_first_done;
static bool harddis_v, harddis_h;
static uae_u16 dmal_alloc_mask;
/* Called to determine the state of the horizontal display window state
* machine at the current position. It might have changed since we last
* checked. */
+
+static void decide_diw_check_start(int start_diw_hpos, int end_diw_hpos)
+{
+ if (hdiwstate == DIW_waiting_start) {
+ if (diw_hstrt > start_diw_hpos && diw_hstrt <= end_diw_hpos) {
+ int first = diwfirstword + coord_diw_shres_to_window_x(hpos_hsync_extra << CCK_SHRES_SHIFT);
+ if (last_diwlastword >= 0) {
+ // was closed previously in same line: blank closed part.
+ hdiw_restart(last_diwlastword * 2, first * 2);
+ last_diwlastword = -1;
+ }
+ if (thisline_decision.diwfirstword < 0) {
+ thisline_decision.diwfirstword = first;
+ // opened before first BPL1DAT?
+ if (!plane0_first_done) {
+ plane0p_enabled = ecs_denise && (bplcon0 & 1) && (bplcon3 & 0x20);
+ }
+ }
+ hdiwstate = DIW_waiting_stop;
+ }
+ }
+}
+static void decide_diw_check_stop(int start_diw_hpos, int end_diw_hpos)
+{
+ if (hdiwstate == DIW_waiting_stop) {
+ if (diw_hstop > start_diw_hpos && diw_hstop <= end_diw_hpos) {
+ int last = diwlastword + coord_diw_shres_to_window_x(hpos_hsync_extra << CCK_SHRES_SHIFT);
+ if (last > thisline_decision.diwlastword) {
+ thisline_decision.diwlastword = last;
+ // if HDIW opens again in same line
+ last_diwlastword = thisline_decision.diwlastword;
+ }
+ hdiwstate = DIW_waiting_start;
+ }
+ }
+}
+
+static void decide_diw_check(int start_diw_hpos, int end_diw_hpos)
+{
+ if (diw_hstrt <= diw_hstop) {
+ decide_diw_check_start(start_diw_hpos, end_diw_hpos);
+ decide_diw_check_stop(start_diw_hpos, end_diw_hpos);
+ } else {
+ decide_diw_check_stop(start_diw_hpos, end_diw_hpos);
+ decide_diw_check_start(start_diw_hpos, end_diw_hpos);
+ }
+}
+
static void decide_diw(int hpos)
{
/* Last hpos = hpos + 0.5, eg. normal PAL end hpos is 227.5 * 2 = 455
ECS Denise and AGA: no above "features"
*/
- int hdiw = hpos >= maxhpos ? maxhpos * 2 + 1 : hpos * 2 + 2;
+ int hpos2 = hpos + (hpos_hsync_extra ? 0 : hsyncstartpos_start_cycles);
+ if (hpos2 <= last_diw_hpos2) {
+ return;
+ }
+
+ int start_diw_hpos = last_diw_hpos * 2 + 1;
+ int end_diw_hpos = hpos * 2 + 1;
+
if (!ecs_denise && vpos <= get_equ_vblank_endline()) {
- hdiw = diw_hcounter;
- }
- /* always mask, bad programs may have set maxhpos = 256 */
- hdiw &= 511;
- for (;;) {
- int lhdiw = hdiw;
- if (last_hdiw > lhdiw) {
- lhdiw = 512;
- }
-
- if (hdiwstate == DIW_waiting_start) {
- if (lhdiw >= diw_hstrt && last_hdiw < diw_hstrt) {
- if (last_diwlastword >= 0) {
- uae_u16 pos = (((hpos_hsync_extra) * 2 - DDF_OFFSET) * 4);
- hdiw_restart(last_diwlastword * 2, diwfirstword * 2 + coord_diw_shres_to_window_x(pos * 2));
- last_diwlastword = -1;
- }
- if (thisline_decision.diwfirstword < 0) {
- thisline_decision.diwfirstword = diwfirstword < 0 ? min_diwlastword : diwfirstword;
- } else if (thisline_decision.diwlastword >= 0 && diwfirstword > thisline_decision.diwfirstword) {
- last_diwlastword = thisline_decision.diwlastword;
- }
- hdiwstate = DIW_waiting_stop;
- }
+ // free running horizontal counter
+ start_diw_hpos = diw_hcounter;
+ end_diw_hpos = diw_hcounter + end_diw_hpos;
+ decide_diw_check(start_diw_hpos, end_diw_hpos);
+ if (end_diw_hpos >= maxhpos * 2 + 1) {
+ start_diw_hpos = 1;
+ end_diw_hpos -= maxhpos * 2 + 1;
+ decide_diw_check(start_diw_hpos, end_diw_hpos);
}
- if (hdiwstate == DIW_waiting_stop) {
- if (lhdiw >= diw_hstop && last_hdiw < diw_hstop) {
- int last = diwlastword < 0 ? 0 : diwlastword;
- if (last > thisline_decision.diwlastword) {
- thisline_decision.diwlastword = last;
- if (last_diwlastword >= 0) {
- hdiw_restart(last_diwlastword * 2, diwfirstword * 2);
- } else {
- last_diwlastword = thisline_decision.diwlastword;
- }
- }
- hdiwstate = DIW_waiting_start;
- }
- }
- if (lhdiw != 512) {
- break;
- }
- last_hdiw = 0 - 1;
+ } else {
+ decide_diw_check(start_diw_hpos, end_diw_hpos);
}
- last_hdiw = hdiw;
+ last_diw_hpos = hpos;
+ last_diw_hpos2 = hpos2;
}
static int fetchmode, fetchmode_size, fetchmode_mask, fetchmode_bytes;
static int islinetoggle(void)
{
int linetoggle = 0;
- if (!(beamcon0 & 0x0800) && !(beamcon0 & 0x0020) && ecs_agnus) {
+ if (!(new_beamcon0 & 0x0800) && !(new_beamcon0 & 0x0020) && ecs_agnus) {
linetoggle = 1; // NTSC and !LOLDIS -> LOL toggles every line
} else if (!ecs_agnus && currprefs.ntscmode) {
linetoggle = 1; // hardwired NTSC Agnus
}
toscr_res_pixels = 1 << toscr_res_pixels_shift;
toscr_res2p = 2 << toscr_res;
+
}
/* fetchstart_mask can be larger than fm_maxplane if FMODE > 0.
toscr_res = res;
toscr_res_old = res;
update_toscr_vars();
+ compute_toscr_delay(bplcon1);
compute_shifter_mask();
}
static void beginning_of_plane_block_early(int hpos)
{
plane0p = false;
- if (thisline_decision.plfleft >= 0 || plane0_prehsync) {
+ plane0p_enabled = false;
+ if (thisline_decision.plfleft >= 0) {
return;
}
- plane0_prehsync = true;
bprun_pipeline_flush_delay = maxhpos;
flush_display(fetchmode);
reset_bpl_vars();
// 1.5 lores pixels
thisline_decision.diwfirstword = coord_diw_shres_to_window_x(((left - DDF_OFFSET / 2) << CCK_SHRES_SHIFT) + 6);
}
-
hbstrt_bordercheck(hpos);
}
#endif
todisplay_fetched = 3;
sprites_enabled_this_line = true;
+ plane0_first_done = true;
if (thisline_decision.plfleft < 0) {
int left = hpos + hpos_hsync_extra;
int offset = get_rga_pipeline(hpos, 1);
uae_u16 d = cycle_line_pipe[offset];
if ((d & CYCLE_PIPE_BITPLANE) && (d & 7) == 1) {
- plane0p = true;
+ decide_diw(hpos);
+ if (hdiwstate == DIW_waiting_stop || plane0p_forced) {
+ plane0p = true;
+ }
}
}
thisline_decision.bordersprite_seen = true;
}
}
+ if (!plane0_first_done) {
+ plane0p_enabled = ecs_denise && (bplcon0 & 1) && (bplcon3 & 0x20);
+ }
return brdsprt && !ce_is_borderblank(current_colors.extra);
}
The data is recorded either in lores pixels (if OCS/ECS), or in hires or
superhires pixels (if AGA). */
-static void record_sprite(int line, int num, int sprxp, uae_u16 *data, uae_u16 *datb, unsigned int ctl)
+static void record_sprite(int num, int sprxp, uae_u16 *data, uae_u16 *datb, unsigned int ctl)
{
struct sprite_entry *e = curr_sprite_entries + next_sprite_entry;
int word_offs;
int point;
int sscanmask = 0x100 << sprite_buffer_res;
int gotdata = 0;
- int extrahpos = hsyncstartpos; // hpos 0 to this value is visible in right border
+ int extrahpos = hsyncstartpos_start_cycles * 2; // hpos 0 to this value is visible in right border
if (!sprites_enabled_this_line && !brdspractive() && !quick)
return;
- point = hpos * 2 - DDF_OFFSET;
-
- // let sprite shift register empty completely
- // if sprite is at the very edge of right border
- if (hpos >= maxhpos) {
- point += (extrahpos >> 2) - 2;
+ point = (hpos + hpos_hsync_extra) * 2 - DDF_OFFSET;
+ if (point == last_sprite_point) {
+ return;
}
- if (nodraw() || hpos < 0x14 || nr_armed == 0 || point == last_sprite_point) {
+ if (nodraw() || nr_armed == 0) {
+ last_sprite_point = point;
return;
}
continue;
}
- int end = 0x1d4;
- if (hw_xp > last_sprite_point && hw_xp <= point + pointx && hw_xp <= maxhpos * 2 + 1) {
+ if (hw_xp > last_sprite_point && hw_xp <= point + pointx) {
add_sprite(&count, i, sprxp, posns, nrs);
}
for (int i = 0; i < count; i++) {
int nr = nrs[i] & (MAX_SPRITES - 1);
struct sprite *s = &spr[nr];
- record_sprite(next_lineno, nr, posns[i], s->data, s->datb, s->ctl);
+ record_sprite(nr, posns[i], s->data, s->datb, s->ctl);
+
/* get left and right sprite edge if brdsprt enabled */
#if AUTOSCALE_SPRITES
if (dmaen (DMA_SPRITE) && brdspractive() && !(bplcon3 & 0x20) && nr > 0) {
int j, jj;
for (j = 0, jj = 0; j < sprite_width; j+= 16, jj++) {
- int nx = fromspritexdiw (posns[i] + j);
+ int nx = fromspritexdiw(posns[i] + j);
if (s->data[jj] || s->datb[jj]) {
if (diwfirstword_total > nx && nx >= (48 << currprefs.gfx_resolution)) {
diwfirstword_total = nx;
gotdata = 1;
}
#endif
+
}
+
last_sprite_point = point;
#if AUTOSCALE_SPRITES
* there's a more-or-less full-screen DIW. */
if (hdiwstate == DIW_waiting_stop && thisline_decision.diwfirstword >= 0) {
thisline_decision.diwlastword = max_diwlastword;
- thisline_decision.diwfull = true;
}
+
last_diwlastword = -1;
if (thisline_decision.diwfirstword != line_decisions[next_lineno].diwfirstword) {
if (thisline_decision.diwlastword != line_decisions[next_lineno].diwlastword) {
MARK_LINE_CHANGED;
}
- if (thisline_decision.diwfull != line_decisions[next_lineno].diwfull) {
- MARK_LINE_CHANGED;
- }
dip = curr_drawinfo + next_lineno;
dip_old = prev_drawinfo + next_lineno;
ddfstrt_hpos = -1;
ddfstop_hpos = -1;
sprites_enabled_this_line = false;
+ last_diw_hpos = 0;
+ last_diw_hpos2 = 0;
/* Default to no bitplane DMA overriding sprite DMA */
plfstrt_sprite = 0x100;
return;
}
- thisline_decision.diwfirstword = -2;
- thisline_decision.diwlastword = -2;
- thisline_decision.diwfull = false;
+ thisline_decision.diwfirstword = -1;
+ thisline_decision.diwlastword = -1;
+ // hdiw already open?
if (hdiwstate == DIW_waiting_stop) {
- thisline_decision.diwfirstword = -1;
+ thisline_decision.diwfirstword = min_diwlastword;
if (thisline_decision.diwfirstword != line_decisions[next_lineno].diwfirstword) {
MARK_LINE_CHANGED;
}
}
+
thisline_decision.ctable = -1;
thisline_changed = 0;
// 0 = vb, 1 = vb off, 3 = vb off, previous line was bitplane + vb on
//bool t = thisline_decision.plfleft >= 0 && (thisline_decision.vb & 1) == 0 && !vb_state && !vb_end_line;
thisline_decision.vb = vb_start_line > 1 + vblank_extraline ? 0 : 1;
+ // if programmed vblank
+ if (!thisline_decision.vb && (beamcon0 & 0x1000) && aga_mode) {
+ thisline_decision.vb |= 2;
+ }
if (!ecs_denise && vb_end_line && currprefs.cs_ocshblankbug) {
thisline_decision.vb = 1;
}
hpos_hsync_extra = 0;
int hpos = current_hpos();
bool normalstart = true;
- plane0p_enabled = false;
+ plane0p_enabled = ecs_denise && (bplcon0 & 1) && (bplcon3 & 0x20);
+ plane0p_forced = false;
+ plane0_first_done = false;
speedup_first = true;
delay_cycles = ((hpos) * 2 - DDF_OFFSET + 0) << LORES_TO_SHRES_SHIFT;
delay_cycles2 = delay_cycles;
if (1 && fetchmode >= 2 && !doflickerfix()) {
// handle bitplane data wrap around
- if (bprun != 0 || todisplay_fetched || plane0 || plane0p || plane0_prehsync) {
+ bool toshift = false;
+ if ((exthblank || (beamcon0 & 0x0110)) && thisline_decision.bplres == 0) {
+ for (int i = 0; i < thisline_decision.nr_planes; i++) {
+ if (todisplay2_aga_saved[i]) {
+ toshift = true;
+ }
+ }
+ }
+ if (bprun != 0 || todisplay_fetched || plane0 || plane0p || toshift) {
normalstart = false;
SET_LINE_CYCLEBASED;
- //thisline_decision.plfleft = hpos;
bpl_shifter = true;
if (toscr_hend == 2) {
for (int i = 0; i < MAX_PLANES; i++) {
// make sure bprun stays enabled until next line
bprun_pipeline_flush_delay = maxhpos;
plane0p_enabled = true;
+ plane0p_forced = true;
}
}
if (normalstart) {
plane0 = false;
plane0p = false;
- plane0p_enabled = false;
memset(outword, 0, sizeof outword);
// fetched[] must not be cleared (Sony VX-90 / Royal Amiga Force)
todisplay_fetched = 0;
#endif
}
- plane0_prehsync = false;
toscr_hend = 0;
}
}
} else if (currprefs.gfx_overscanmode == OVERSCANMODE_EXTREME) {
maxhpos_display += EXTRAWIDTH_EXTREME;
- maxvpos_display_vsync++;
+ maxvpos_display_vsync += 2;
minfirstline--;
} else if (currprefs.gfx_overscanmode == OVERSCANMODE_BROADCAST) {
maxhpos_display += EXTRAWIDTH_BROADCAST;
diwfirstword = coord_diw_shres_to_window_x(hstrt);
diwlastword = coord_diw_shres_to_window_x(hstop);
-
- if (diwfirstword >= diwlastword) {
- diwfirstword = min_diwlastword;
- diwlastword = max_diwlastword;
- }
if (diwfirstword < min_diwlastword) {
diwfirstword = min_diwlastword;
}
+ if (diwlastword < min_diwlastword) {
+ diwlastword = min_diwlastword;
+ }
if (vstrt == vpos && vstop != vpos && diwstate == DIW_waiting_start) {
// This may start BPL DMA immediately.
if (aga_mode) {
hardwired = (new_beamcon0 & 0x1000) == 0;
}
+ // vb_state handles programmed vblank
if (hardwired) {
int vbstrt = vblank_firstline_hw;
int vbstop = vblank_lastline_hw;
/* Initialize the variables necessary for drawing a line.
* This involves setting up start/stop positions and display window
* borders. */
-static void pfield_init_linetoscr (bool border)
+static void pfield_init_linetoscr (int lineno, bool border)
{
/* First, get data fetch start/stop in DIW coordinates. */
int ddf_left = dp_for_drawing->plfleft + DIW_DDF_OFFSET - DDF_OFFSET;
playfield_start_pre -= bplres;
playfield_end_pre -= bplres;
}
- // if DIW was not closed horizontally, borderblank leaves color0 stripe before bitplanes
- if (ce_is_borderblank(colors_for_drawing.extra) && dp_for_drawing->diwfull) {
- playfield_start_pre = playfield_start - 2 * 4;
- }
unpainted = visible_left_border < playfield_start ? 0 : visible_left_border - playfield_start;
unpainted = res_shift_from_window (unpainted);
if (exthblank) {
pfield_do_fill_line(start, stop, 1);
} else if (extborder) {
- pfield_do_fill_line(start, stop, ce_is_borderblank(colors_for_drawing.extra) ? 1 : 0);
+ bool bb = ce_is_borderblank(colors_for_drawing.extra);
+ pfield_do_fill_line(start, stop, bb ? 1 : 0);
}
src_pixel = pixel;
}
{
int pixel;
if (extborder) {
- pfield_do_fill_line(start, stop, ce_is_borderblank(colors_for_drawing.extra) || exthblank ? 1 : 0);
- pixel = pfield_do_linetoscr_spriteonly(src_pixel, start, stop, ce_is_borderblank(colors_for_drawing.extra) || exthblank);
+ bool bb = ce_is_borderblank(colors_for_drawing.extra);
+ pfield_do_fill_line(start, stop, bb || exthblank ? 1 : 0);
+ pixel = pfield_do_linetoscr_spriteonly(src_pixel, start, stop, bb || exthblank);
} else {
pixel = pfield_do_linetoscr_sprite(src_pixel, start, stop);
if (exthblank) {
#ifdef AGA
/* not very optimized */
-STATIC_INLINE void draw_sprites_aga (struct sprite_entry *e)
+STATIC_INLINE void draw_sprites_aga(struct sprite_entry *e)
{
draw_sprites_1(e, bpldualpf, e->has_attached);
}
lastpos = t;
}
- // vblank + extblanken: blanked
- if ((!(vb_state & 1) && ce_is_extblankset(colors_for_drawing.extra) && aga_mode) || vp < vblank_top_start || vp >= vblank_bottom_stop) {
+ // vblank + programmed vblank: blanked (hardwired is handled separately)
+ if (vb_state == 2 || vp < vblank_top_start || vp >= vblank_bottom_stop) {
if (nextpos_in_range > lastpos && lastpos < playfield_end) {
int t = nextpos_in_range <= playfield_end ? nextpos_in_range : playfield_end;
pfield_expand_dp_bplcon();
set_blanking_limits();
- pfield_init_linetoscr(false);
+ pfield_init_linetoscr(lineno, false);
pfield_doline(lineno);
adjust_drawing_colors(dp_for_drawing->ctable, dp_for_drawing->ham_seen || bplehb || ecsshres);
if (dp_for_drawing->bordersprite_seen && !ce_is_borderblank(colors_for_drawing.extra) && dip_for_drawing->nr_sprites) {
dosprites = true;
pfield_expand_dp_bplcon();
- pfield_init_linetoscr(true);
+ pfield_init_linetoscr(lineno, true);
pfield_erase_vborder_sprites();
}
#endif