From bb99e4ad5335c8c0fe8588a2ca99a08a9813ef89 Mon Sep 17 00:00:00 2001 From: Toni Wilen Date: Sun, 15 Aug 2021 18:01:26 +0300 Subject: [PATCH] Custom chipset WIP updates. --- custom.cpp | 207 ++++++++++++++++++++++++++++------------------ drawing.cpp | 25 +++--- include/drawing.h | 1 - 3 files changed, 137 insertions(+), 96 deletions(-) diff --git a/custom.cpp b/custom.cpp index 730240bf..687ab0b4 100644 --- a/custom.cpp +++ b/custom.cpp @@ -428,6 +428,7 @@ static enum diw_states diwstate, hdiwstate; 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; @@ -533,7 +534,7 @@ static int ddf_stopping, ddf_enable_on; 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; @@ -968,6 +969,54 @@ static void hdiw_restart(int diw_last, int diw_current) /* 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 @@ -976,53 +1025,29 @@ static void decide_diw(int hpos) 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; @@ -1600,7 +1625,7 @@ int get_bitplane_dma_rel(int hpos, int off) 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 @@ -1688,6 +1713,7 @@ static void update_toscr_vars(void) } toscr_res_pixels = 1 << toscr_res_pixels_shift; toscr_res2p = 2 << toscr_res; + } /* fetchstart_mask can be larger than fm_maxplane if FMODE > 0. @@ -2673,6 +2699,7 @@ static void update_denise_vars(void) toscr_res = res; toscr_res_old = res; update_toscr_vars(); + compute_toscr_delay(bplcon1); compute_shifter_mask(); } @@ -2750,10 +2777,10 @@ static void hbstrt_bordercheck(int hpos) 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(); @@ -2764,7 +2791,6 @@ static void beginning_of_plane_block_early(int hpos) // 1.5 lores pixels thisline_decision.diwfirstword = coord_diw_shres_to_window_x(((left - DDF_OFFSET / 2) << CCK_SHRES_SHIFT) + 6); } - hbstrt_bordercheck(hpos); } @@ -2787,6 +2813,7 @@ static void beginning_of_plane_block(int 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; @@ -3336,7 +3363,10 @@ STATIC_INLINE void one_fetch_cycle_0(int hpos, int fm) 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; + } } } @@ -3672,6 +3702,9 @@ static bool issprbrd(int hpos, uae_u16 bplcon0, uae_u16 bplcon3) 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); } @@ -3950,7 +3983,7 @@ stays equal or increases between successive calls. 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; @@ -4117,20 +4150,18 @@ static void decide_sprites(int hpos, bool usepointx, bool quick) 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; } @@ -4160,8 +4191,7 @@ static void decide_sprites(int hpos, bool usepointx, bool quick) 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); } @@ -4186,13 +4216,14 @@ static void decide_sprites(int hpos, bool usepointx, bool quick) 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; @@ -4205,7 +4236,9 @@ static void decide_sprites(int hpos, bool usepointx, bool quick) gotdata = 1; } #endif + } + last_sprite_point = point; #if AUTOSCALE_SPRITES @@ -4338,8 +4371,8 @@ static void finish_decisions(int hpos) * 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) { @@ -4348,9 +4381,6 @@ static void finish_decisions(int hpos) 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; @@ -4422,6 +4452,8 @@ static void reset_decisions_scanline_start(void) 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; @@ -4451,15 +4483,16 @@ static void reset_decisions_hsync_start(void) 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; @@ -4503,6 +4536,10 @@ static void reset_decisions_hsync_start(void) // 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; } @@ -4524,7 +4561,9 @@ static void reset_decisions_hsync_start(void) 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; @@ -4532,10 +4571,17 @@ static void reset_decisions_hsync_start(void) 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++) { @@ -4557,13 +4603,13 @@ static void reset_decisions_hsync_start(void) // 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; @@ -4578,7 +4624,6 @@ static void reset_decisions_hsync_start(void) #endif } - plane0_prehsync = false; toscr_hend = 0; } @@ -5144,7 +5189,7 @@ static void init_hz(bool checkvposw) } } 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; @@ -5410,14 +5455,12 @@ static void calcdiw(void) 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. diff --git a/drawing.cpp b/drawing.cpp index a2444602..4abf7dba 100644 --- a/drawing.cpp +++ b/drawing.cpp @@ -542,6 +542,7 @@ static void set_blanking_limits(void) 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; @@ -1014,7 +1015,7 @@ static void set_res_shift(void) /* 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; @@ -1147,10 +1148,6 @@ static void pfield_init_linetoscr (bool border) 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); @@ -1891,7 +1888,8 @@ static void pfield_do_linetoscr(int start, int stop, int blank) 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; } @@ -1899,8 +1897,9 @@ static void pfield_do_linetoscr_spr(int start, int stop, int blank) { 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) { @@ -2495,7 +2494,7 @@ static void NOINLINE draw_sprites_normal_dp_at(struct sprite_entry *e) { draw_sp #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); } @@ -3189,8 +3188,8 @@ static void do_color_changes(line_draw_func worker_border, line_draw_func worker 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; @@ -3426,7 +3425,7 @@ static void pfield_draw_line(struct vidbuffer *vb, int lineno, int gfx_ypos, int 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); @@ -3509,7 +3508,7 @@ static void pfield_draw_line(struct vidbuffer *vb, int lineno, int gfx_ypos, int 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 diff --git a/include/drawing.h b/include/drawing.h index 10608058..cc552f02 100644 --- a/include/drawing.h +++ b/include/drawing.h @@ -296,7 +296,6 @@ struct decision { int plfleft, plfright, plflinelen; /* Display window: native coordinates, depend on lores state. */ int diwfirstword, diwlastword; - bool diwfull; int ctable; uae_u16 bplcon0, bplcon2; -- 2.47.3