]> git.unchartedbackwaters.co.uk Git - francis/winuae.git/commitdiff
chipset updates, part 1
authorToni Wilen <twilen@winuae.net>
Sat, 16 Sep 2023 16:33:54 +0000 (19:33 +0300)
committerToni Wilen <twilen@winuae.net>
Sat, 16 Sep 2023 16:33:54 +0000 (19:33 +0300)
custom.cpp
debug.cpp
drawing.cpp
events.cpp
include/custom.h
include/debug.h
include/drawing.h
include/events.h

index bdeb807f415b09d8347a10fad9a097d8f14b85f5..787c04e500aaae9e347b62893cc39816fbef3ce0 100644 (file)
@@ -73,6 +73,7 @@
 #define DMAL_FIRST_HPOS 11
 #define SPR_FIRST_HPOS 25
 #define COPPER_CYCLE_POLARITY 0
+#define HARDWIRED_DMA_TRIGGER_HPOS 1
 
 #define REF_RAS_ADD_AGA 0x000
 #define REF_RAS_ADD_ECS 0x200
@@ -136,6 +137,7 @@ int scandoubled_line;
 static bool lof_lastline, lof_prev_lastline;
 static int lol, lol_prev;
 static int next_lineno;
+static int linear_vpos;
 static enum nln_how nextline_how;
 static int lof_changed = 0, lof_changing = 0, interlace_changed = 0;
 static int lof_changed_previous_field;
@@ -159,6 +161,7 @@ static evt_t line_start_cycles;
 static bool initial_frame;
 static evt_t custom_color_write_cycle;
 static int color_writes_num;
+static bool line_equ_freerun;
 
 #define LOF_TOGGLES_NEEDED 3
 //#define NLACE_CNT_NEEDED 50
@@ -309,6 +312,7 @@ int maxvpos = MAXVPOS_PAL;
 int maxvpos_nom = MAXVPOS_PAL; // nominal value (same as maxvpos but "faked" maxvpos in fake 60hz modes)
 int maxvpos_display = MAXVPOS_PAL; // value used for display size
 int maxhpos_display = AMIGA_WIDTH_MAX;
+int maxvsize_display = AMIGA_HEIGHT_MAX;
 int maxvpos_display_vsync; // extra lines from top visible in bottom
 static int vblank_extraline;
 static int maxhposm1;
@@ -325,6 +329,7 @@ int hsyncendpos_hw;
 int denisehtotal;
 static int maxvpos_total = 511;
 int minfirstline = VBLANK_ENDLINE_PAL;
+int minfirstline_linear = VBLANK_ENDLINE_PAL;
 static int firstblankedline;
 static int equ_vblank_endline = EQU_ENDLINE_PAL;
 static bool equ_vblank_toggle = true;
@@ -337,12 +342,13 @@ int doublescan;
 int programmedmode;
 frame_time_t syncbase;
 static int fmode_saved, fmode;
-uae_u16 beamcon0, new_beamcon0, beamcon0_previous;
+uae_u16 beamcon0, new_beamcon0;
 uae_u16 bemcon0_hsync_mask, bemcon0_vsync_mask;
 static uae_u16 beamcon0_saved;
 static uae_u16 bplcon0_saved, bplcon1_saved, bplcon2_saved;
 static uae_u16 bplcon3_saved, bplcon4_saved;
 static int varsync_changed;
+static uae_u16 vt_old, ht_old, hs_old, vs_old;
 uae_u16 vtotal, htotal;
 static int maxvpos_stored, maxhpos_stored;
 uae_u16 hsstop, hsstrt;
@@ -352,7 +358,7 @@ static uae_u16 vsstop, vsstrt;
 static uae_u16 vbstop, vbstrt;
 static uae_u16 hcenter, hcenter_v2, hcenter_v2_end, hcenter_sync_v2;
 static bool hcenter_active;
-static uae_u16 hbstop_v, hbstrt_v, hbstop_v2, hbstrt_v2, hbstop_sync_v2, hbstrt_sync_v2;
+static uae_u16 hbstop_v, hbstrt_v, hbstop_v2, hbstrt_v2, hbstop_sync_v2, hbstrt_sync_v2, hbstop_reg, hbstrt_reg;
 static uae_u16 hsstrt_v2, hsstop_v2;
 static int vsstrt_m, vsstop_m, vbstrt_m, vbstop_m;
 static bool vb_state, vb_end_line;
@@ -366,15 +372,14 @@ static int hhbpl, hhspr;
 static int ciavsyncmode;
 static int diw_hstrt, diw_hstop;
 static int hdiw_counter;
-static uae_u16 hdiw_counter_sconflict, hdiw_counter_sconflict_mask;
-static uae_u16 hdiw_counter_conflict;
 static int hstrobe_hdiw_min;
 static uae_u32 ref_ras_add;
 static uaecptr refptr, refptr_p;
 static uae_u32 refmask;
 static int refresh_handled_slot;
 static bool refptr_preupdated;
-static bool hstrobe_conflict, hstrobe_conflict2;
+static bool hstrobe_conflict;
+static bool vhposw_modified;
 static int line_disabled;
 static bool custom_disabled;
 
@@ -413,7 +418,8 @@ static uae_u8 magic_sprite_mask = 0xff;
 
 static int hardwired_vbstop;
 
-static int last_sprite_point, nr_armed;
+static int last_sprite_point, last_sprite_point_abs;
+static int nr_armed;
 static int sprite_width, sprres;
 static int sprite_sprctlmask;
 int sprite_buffer_res;
@@ -454,7 +460,7 @@ int plffirstline_total, plflastline_total;
 int vblank_firstline_hw;
 static int autoscale_bordercolors;
 static int plfstrt, plfstop;
-static int sprite_minx, sprite_maxx;
+static int sprite_minx;
 static int first_bpl_vpos;
 static int last_decide_line_hpos;
 static int last_fetch_hpos, last_decide_sprite_hpos;
@@ -462,11 +468,11 @@ static int diwfirstword, diwlastword;
 static int last_diwlastword;
 static int hb_last_diwlastword;
 static int last_hdiw;
-static diw_states vdiwstate, hdiwstate, hdiwstate_conflict;
+static diw_states vdiwstate, hdiwstate, hdiwstate_blank;
 static int bpl_hstart;
 static bool exthblank, exthblank_state, hcenterblank_state;
 static int hsyncdebug;
-static int last_diw_hpos, last_diw_hpos2;
+static int last_diw_hpos;
 static int last_recorded_diw_hpos;
 static int last_hblank_start;
 static int collision_hpos;
@@ -613,7 +619,7 @@ struct custom_store custom_storage[256];
 static int out_nbits, out_offs;
 static uae_u32 todisplay[MAX_PLANES], todisplay2[MAX_PLANES];
 static uae_u32 outword[MAX_PLANES];
-static uae_u64 outword64[MAX_PLANES];
+static uae_u64 outword64[MAX_PLANES], outword64_extra[MAX_PLANES];
 static uae_u16 fetched[MAX_PLANES];
 static uae_u16 todisplay_fetched;
 #ifdef AGA
@@ -636,7 +642,7 @@ static int toscr_delay_adjusted[2], toscr_delay_sh[2];
 static bool shdelay_disabled;
 static int delay_cycles, delay_cycles2;
 static int delay_lastcycle[2], delay_hsynccycle;
-static int vhposr_delay_offset, vhposr_sprite_offset;
+static int vhposr_delay_offset;
 static bool bplcon1_written;
 static bool bplcon0_planes_changed;
 static bool sprites_enabled_this_line;
@@ -652,7 +658,7 @@ static bool dmal_ce;
 static void update_copper(int until_hpos);
 static void decide_sprites_fetch(int endhpos);
 static void decide_line(int endhpos);
-static void decide_sprites(int hpos, bool usepointx, bool quick);
+static void decide_sprites(int hpos, bool quick, bool halfcycle);
 static void decide_sprites(int hpos);
 
 /* The number of bits left from the last fetched words.
@@ -969,10 +975,23 @@ static void remember_ctable_for_border(void)
        remember_ctable();
 }
 
-// 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_store ? 1 : 0) : 0);
+       if (new_beamcon0 & (BEAMCON0_BLANKEN | BEAMCON0_VARCSYEN)) {
+               return -1;
+       }
+       return equ_vblank_endline + (equ_vblank_toggle ? (lof_store ? 1 : 0) : 0) + (agnusa1000 ? 1 : 0);
+}
+static int get_equ_vblank_startline(void)
+{
+       if (new_beamcon0 & (BEAMCON0_BLANKEN | BEAMCON0_VARCSYEN)) {
+               return 30000;
+       }
+       if (agnusa1000) {
+               return 1;
+       } else {
+               return 0;
+       }
 }
 
 static int output_res(int res)
@@ -995,7 +1014,7 @@ static void reset_bpl_vars()
 
 STATIC_INLINE bool line_hidden(void)
 {
-       return vpos >= maxvpos_display_vsync && vpos < minfirstline - 1 && currprefs.gfx_overscanmode < OVERSCANMODE_ULTRA;
+       return linear_vpos >= maxvpos_display_vsync && linear_vpos < minfirstline - 1 && currprefs.gfx_overscanmode < OVERSCANMODE_ULTRA;
 }
 
 // hblank start = enable border (bitplane not visible until next BPL1DAT)..
@@ -1419,9 +1438,9 @@ static void sync_color_changes(int hpos)
        record_color_change2(hpos, 0xffff, 0);
 }
 
-static void insert_actborder(int diw, bool onoff)
+static void insert_actborder(int diw, bool onoff, bool blank)
 {
-       if (line_hidden() || custom_disabled) {
+       if (custom_disabled) {
                return;
        }
 
@@ -1430,7 +1449,7 @@ static void insert_actborder(int diw, bool onoff)
        for (i = last_color_change; i < next_color_change; i++) {
                struct color_change *cc = &curr_color_changes[i];
                if (cc->linepos == diw && cc->regno == 0 && (cc->value & COLOR_CHANGE_MASK) == COLOR_CHANGE_ACTBORDER) {
-                       cc->value = COLOR_CHANGE_ACTBORDER | (onoff ? 1 : 0);
+                       cc->value = COLOR_CHANGE_ACTBORDER | (onoff ? 1 : 0) | (blank ? 2 : 0);
                        return;
                }
        }
@@ -1449,19 +1468,20 @@ static void insert_actborder(int diw, bool onoff)
        struct color_change *cc = &curr_color_changes[i];
        cc->linepos = diw;
        cc->regno = 0;
-       cc->value = COLOR_CHANGE_ACTBORDER | (onoff ? 1 : 0);
+       cc->value = COLOR_CHANGE_ACTBORDER | (onoff ? 1 : 0) | (blank ? 2 : 0);
        next_color_change++;
 }
 
 // hdiw opened again in same scanline
 // erase (color0 or bblank) area between previous end and new start
-static void hdiw_restart(int diw_last, int diw_current)
+static void hdiw_restart(int diw_last, int diw_current, bool blank)
 {
        if (diw_last >= diw_current || line_hidden() || custom_disabled) {
                return;
        }
        // update state
        diw_current = adjust_hr(diw_current);
+       diw_last = adjust_hr(diw_last);
        record_color_change2(-diw_current, 0xffff, 0);
 
        // find slot to insert into
@@ -1480,90 +1500,63 @@ static void hdiw_restart(int diw_last, int diw_current)
        struct color_change *cc = &curr_color_changes[i];
        cc->linepos = diw_last;
        cc->regno = 0;
-       cc->value = COLOR_CHANGE_ACTBORDER | 1;
+       cc->value = COLOR_CHANGE_ACTBORDER | 1 | (blank ? 2 : 0);
        next_color_change++;
 
        record_color_change2(-diw_current, 0, COLOR_CHANGE_ACTBORDER | 0);
 }
 
-static void decide_hstrobe_hdiw(int hpos)
-{
-       int off = hdiw_counter_conflict;
-
-       hpos += hpos_hsync_extra;
-       if (hpos <= hstrobe_hdiw_min) {
-               return;
-       }
-
-       int max = (hpos * 2 + 1) << 2;
-       int min = (hstrobe_hdiw_min * 2 + 1) << 2;
-
-       int hdiw1 = (diw_hstrt - off) & ((512 << 2) - 1);
-       int hdiw2 = (diw_hstop - off) & ((512 << 2) - 1);
-
-       hdiw1 = adjust_hr(hdiw1);
-       hdiw2 = adjust_hr(hdiw2);
-
-       max = adjust_hr(max);
-       min = adjust_hr(min);
+/* Called to determine the state of the horizontal display window state
+* machine at the current position. It might have changed since we last
+* checked.  */
 
-       if (hdiw1 < min) {
-               hdiw1 = min;
-       }
-       if (hdiw2 < min) {
-               hdiw2 = min;
-       }
-       if (hdiw1 > max) {
-               hdiw1 = max;
-       }
-       if (hdiw2 > max) {
-               hdiw2 = max;
-       }
+static int hdiw_denisecounter, hdiw_denisecounter_abs, hdiw_denisecounter_reset;
 
-       if (hdiw1 < hdiw2) {
-               if (hdiw1 > min && hdiwstate_conflict == diw_states::DIW_waiting_start) {
-                       insert_actborder(min, true);
-                       insert_actborder(hdiw1, false);
-                       hdiwstate_conflict = diw_states::DIW_waiting_stop;
-               }
-               if (hdiw2 < max && hdiwstate_conflict == diw_states::DIW_waiting_stop) {
-                       insert_actborder(hdiw2, true);
-                       insert_actborder(max, false);
+// hblank start
+static void decide_hdiw_blank_check_start(int hpos, int start_diw_hpos, int end_diw_hpos)
+{
+       if (hdiwstate_blank == diw_states::DIW_waiting_start) {
+               if (hbstrt_reg >= start_diw_hpos && hbstrt_reg < end_diw_hpos) {
+                       int val = hdiw_denisecounter_abs + (hbstrt_reg - start_diw_hpos);
+                       insert_actborder(val, true, true);
+                       MARK_LINE_CHANGED;
+                       hdiwstate_blank = diw_states::DIW_waiting_stop;
                }
-       } else if (hdiw1 > hdiw2) {
-               insert_actborder(hdiw2, true);
-               insert_actborder(hdiw1, false);
-               hdiwstate_conflict = diw_states::DIW_waiting_stop;
        }
-
-       hstrobe_hdiw_min = hpos;
 }
-
-static void decide_conflict_hdiw(int hpos)
+// hblank end
+static void decide_hdiw_blank_check_stop(int hpos, int start_diw_hpos, int end_diw_hpos)
 {
-       if (hstrobe_conflict) {
-               decide_hstrobe_hdiw(hpos);
+       if (hdiwstate_blank == diw_states::DIW_waiting_stop) {
+               if (hbstop_reg >= start_diw_hpos && hbstop_reg < end_diw_hpos) {
+                       int val = hdiw_denisecounter_abs + (hbstop_reg - start_diw_hpos);
+                       insert_actborder(val, false, true);
+                       MARK_LINE_CHANGED;
+                       hdiwstate_blank = diw_states::DIW_waiting_start;
+               }
        }
 }
-
-/* 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_hdiw_check_start(int start_diw_hpos, int end_diw_hpos, int extrahpos)
+// hdiw open
+static void decide_hdiw_check_start(int start_diw_hpos, int end_diw_hpos)
 {
        if (hdiwstate == diw_states::DIW_waiting_start) {
-               if (diw_hstrt > start_diw_hpos && diw_hstrt < end_diw_hpos && !hstrobe_conflict) {
-                       int first = diwfirstword + extrahpos;
+               if (diw_hstrt >= start_diw_hpos && diw_hstrt < end_diw_hpos) {
+                       int val = hdiw_denisecounter_abs + (diw_hstrt - start_diw_hpos);
+                       int first = coord_diw_shres_to_window_x(val);
                        if (last_diwlastword >= 0) {
-                               int first2 = first * 2;
-                               first2 = adjust_hr(first2);
-                               // was closed previously in same line: blank closed part.
-                               hdiw_restart(last_diwlastword, first2);
+                               // was closed previously in same line: fill closed part using color0.
+                               if (denisea1000) {
+                                       last_diwlastword += 4 << shres_shift;
+                                       if (last_diwlastword < val) {
+                                               hdiw_restart(last_diwlastword, val, false);
+                                       }
+                               } else {
+                                       hdiw_restart(last_diwlastword, val, false);
+                               }
                                last_diwlastword = -1;
 #ifdef DEBUGGER
                                if (debug_dma) {
-                                       record_dma_event(DMA_EVENT_HDIWS, diw_to_hpos(first2), vpos);
+                                       record_dma_event(DMA_EVENT_HDIWS, diw_to_hpos(val), vpos);
                                }
 #endif
                        }
@@ -1583,16 +1576,17 @@ static void decide_hdiw_check_start(int start_diw_hpos, int end_diw_hpos, int ex
                }
        }
 }
-static void decide_hdiw_check_stop(int start_diw_hpos, int end_diw_hpos, int extrahpos)
+// hdiw close
+static void decide_hdiw_check_stop(int start_diw_hpos, int end_diw_hpos)
 {
        if (hdiwstate == diw_states::DIW_waiting_stop) {
-               if (diw_hstop > start_diw_hpos && diw_hstop <= end_diw_hpos && !hstrobe_conflict) {
-                       int last = diwlastword + extrahpos;
+               if (diw_hstop >= start_diw_hpos && diw_hstop < end_diw_hpos) {
+                       int val = hdiw_denisecounter_abs + (diw_hstop - start_diw_hpos);
+                       int last = coord_diw_shres_to_window_x(val);
                        if (last > thisline_decision.diwlastword) {
                                thisline_decision.diwlastword = adjust_hr2(last);
                                // if HDIW opens again in same line
-                               int v = thisline_decision.diwlastword * 2;
-                               last_diwlastword = adjust_hr(v);
+                               last_diwlastword = val;
 #ifdef DEBUGGER
                                if (debug_dma) {
                                        record_dma_event(DMA_EVENT_HDIWE, diw_to_hpos(last), vpos);
@@ -1604,52 +1598,101 @@ static void decide_hdiw_check_stop(int start_diw_hpos, int end_diw_hpos, int ext
        }
 }
 
-static void decide_hdiw_check(int start_diw_hpos, int end_diw_hpos, int extrahpos)
+static void decide_hdiw_check(int hpos, int start_diw_hpos, int end_diw_hpos)
 {
-       if (diw_hstrt < diw_hstop) {
-               decide_hdiw_check_start(start_diw_hpos, end_diw_hpos, extrahpos);
-               decide_hdiw_check_stop(start_diw_hpos, end_diw_hpos, extrahpos);
+       if ((diw_hstrt >= start_diw_hpos && diw_hstrt < end_diw_hpos) &&
+               (diw_hstop >= start_diw_hpos && diw_hstop < end_diw_hpos)) {
+               if (diw_hstrt > diw_hstop) {
+                       decide_hdiw_check_stop(start_diw_hpos, end_diw_hpos);
+                       decide_hdiw_check_start(start_diw_hpos, end_diw_hpos);
+               } else {
+                       decide_hdiw_check_start(start_diw_hpos, end_diw_hpos);
+                       decide_hdiw_check_stop(start_diw_hpos, end_diw_hpos);
+               }
        } else {
-               decide_hdiw_check_stop(start_diw_hpos, end_diw_hpos, extrahpos);
-               decide_hdiw_check_start(start_diw_hpos, end_diw_hpos, extrahpos);
+               decide_hdiw_check_start(start_diw_hpos, end_diw_hpos);
+               decide_hdiw_check_stop(start_diw_hpos, end_diw_hpos);
        }
+       // check also hblank if there is chance it has been moved to visible area
+       static bool xcv = true;
+       if (xcv && 1) {
+               if (hstrobe_conflict || vhposw_modified) {
+                       decide_hdiw_blank_check_start(hpos, start_diw_hpos, end_diw_hpos);
+               }
+               if (hdiwstate_blank == diw_states::DIW_waiting_stop) {
+                       decide_hdiw_blank_check_stop(hpos, start_diw_hpos, end_diw_hpos);
+               }
+       }
+       hdiw_denisecounter_abs += end_diw_hpos - start_diw_hpos;
 }
 
-static void decide_hdiw(int hpos)
+static void decide_hdiw2(int hpos, bool halfcycle)
 {
-       /* Last hpos = hpos + 0.5, eg. normal PAL end hpos is 227.5 * 2 = 455
-          OCS Denise: 9 bit hdiw counter does not reset during lines 0 to 9
-          (PAL) or lines 0 to 10 (NTSC). A1000 PAL: 1 to 9, NTSC: 1 to 10.
-          ECS Denise and AGA: no above "features"
-       */
-
-       int hpos2 = hpos + (hpos_hsync_extra ? 0 : hsyncstartpos_start_cycles);
-       if (hpos2 <= last_diw_hpos2) {
+       int hp = (hpos << 1) + halfcycle; // cck->lores
+       int c = (hp - last_diw_hpos) << (CCK_SHRES_SHIFT - 1); // ->shres
+       if (c <= 0) {
                return;
        }
-       int start_diw_hpos = ((last_diw_hpos * 2 - DDF_OFFSET + 1) << 2) + 3;
-       int end_diw_hpos = ((hpos * 2 + 1) << 2) + 3;
-       // should handle wrap around..
-       if (start_diw_hpos < ((1 << 2) + 3)) {
-               start_diw_hpos = (1 << 2) + 3;
+       if (last_diw_hpos < (HARDWIRED_DMA_TRIGGER_HPOS << 1) && hp >= (HARDWIRED_DMA_TRIGGER_HPOS << 1)) {
+               hdiw_denisecounter_reset = (REFRESH_FIRST_HPOS - HARDWIRED_DMA_TRIGGER_HPOS + 3) << CCK_SHRES_SHIFT;
+               //hdiw_denisecounter_reset += 1 << (CCK_SHRES_SHIFT - 1);
        }
-       int extrahpos = coord_diw_shres_to_window_x(hpos_hsync_extra << CCK_SHRES_SHIFT);
 
-       if (!ecs_denise && vpos <= get_equ_vblank_endline()) {
-               // free running horizontal counter
-               start_diw_hpos = (hdiw_counter & 511) << 2;
-               end_diw_hpos = start_diw_hpos + end_diw_hpos;
-               decide_hdiw_check(start_diw_hpos, end_diw_hpos, extrahpos);
-               if (end_diw_hpos >= (512 << 2)) {
-                       start_diw_hpos = -1;
-                       end_diw_hpos -= (512 << 2);
-                       decide_hdiw_check(start_diw_hpos, end_diw_hpos, extrahpos);
+       int start = hdiw_denisecounter;
+       int max = 512 << (CCK_SHRES_SHIFT - 1);
+
+       if (hdiw_denisecounter_reset > 0 && c >= hdiw_denisecounter_reset && !line_equ_freerun && !hstrobe_conflict) {
+               // strobe crossed?
+               hdiw_denisecounter += hdiw_denisecounter_reset;
+               decide_hdiw_check(hpos, start, hdiw_denisecounter);
+               hdiw_denisecounter = 2 << LORES_TO_SHRES_SHIFT;
+               start = hdiw_denisecounter;
+               hdiw_denisecounter += c - hdiw_denisecounter_reset;
+               decide_hdiw_check(hpos, start, hdiw_denisecounter);
+               hdiw_denisecounter_reset = -1;
+       } else {
+               hdiw_denisecounter += c;
+               // wrap around?
+               if (hdiw_denisecounter >= max) {
+                       decide_hdiw_check(hpos, start, max);
+                       hdiw_denisecounter &= max - 1;
+                       if (hdiw_denisecounter > 0) {
+                               decide_hdiw_check(hpos, 0, hdiw_denisecounter);
+                       }
+               } else {
+                       decide_hdiw_check(hpos, start, hdiw_denisecounter);
                }
+               if (hdiw_denisecounter_reset >= 0) {
+                       hdiw_denisecounter_reset -= c;
+               }
+       }
+
+       last_diw_hpos = hp;
+}
+
+static void decide_hdiw(int hpos, bool halfcycle = false)
+{
+#ifdef DEBUGGER
+       if (!debug_dma) {
+               decide_hdiw2(hpos, halfcycle);
        } else {
-               decide_hdiw_check(start_diw_hpos, end_diw_hpos, extrahpos);
+               for (int i = (last_diw_hpos >> 1); i <= hpos; i++) {
+                       decide_hdiw2(i, halfcycle);
+                       halfcycle = false;
+                       record_dma_denise(i, hdiw_denisecounter >> 2);
+               }
        }
-       last_diw_hpos = hpos;
-       last_diw_hpos2 = hpos2;
+#else
+       decide_hdiw2(hpos);
+#endif
+}
+
+static void sync_changes(int hpos)
+{
+       decide_hdiw(hpos);
+       decide_sprites(hpos);
+       record_color_change2(hpos, 0xffff, 0);
+
 }
 
 static int fetchmode, fetchmode_size, fetchmode_mask, fetchmode_bytes;
@@ -1925,7 +1968,7 @@ static void estimate_last_fetch_cycle(int hpos)
        } else {
 
 #if OPTIMIZED_ESTIMATE
-               if (estimated_bplcon0 == bplcon0 && plfstrt == hpos && estimated_plfstrt == plfstrt && estimated_plfstop == plfstop && estimated_fm == fetchmode) {
+               if (estimated_bplcon0 == bplcon0 && bpl_hstart == hpos && estimated_plfstrt == bpl_hstart && estimated_plfstop == plfstop && estimated_fm == fetchmode) {
                        if (maxhpos == estimated_maxhpos[0]) {
                                estimated_cycles = estimated_cycles_buf0;
                                return;
@@ -2035,7 +2078,7 @@ static void estimate_last_fetch_cycle(int hpos)
                        }
                }
 #if OPTIMIZED_ESTIMATE
-               if (estimated_empty && plfstrt == hpos && !ddf_stopping) {
+               if (estimated_empty && bpl_hstart == hpos && !ddf_stopping) {
                        estimated_empty = false;
                        // zero rest of buffer
                        if (end_pos != start_pos2) {
@@ -2047,7 +2090,7 @@ static void estimate_last_fetch_cycle(int hpos)
                                }
                        }
                        estimated_bplcon0 = bplcon0;
-                       estimated_plfstrt = plfstrt;
+                       estimated_plfstrt = bpl_hstart;
                        estimated_plfstop = plfstop;
                        estimated_fm = fetchmode;
                        estimated_maxhpos[maxhposeven] = maxhpos;
@@ -2190,7 +2233,6 @@ static void set_chipset_mode(void)
                        refmask >>= 1;
                }
        }
-       hdiw_counter_sconflict_mask = (512 << sprite_buffer_res) - 1;
        calcdiw();
 }
 
@@ -2200,6 +2242,10 @@ static void update_mirrors(void)
        ecs_agnus = (currprefs.chipset_mask & CSMASK_ECS_AGNUS) != 0;
        ecs_denise = (currprefs.chipset_mask & CSMASK_ECS_DENISE) != 0;
        agnusa1000 = currprefs.cs_agnusmodel == AGNUSMODEL_A1000 || currprefs.cs_agnusmodel == AGNUSMODEL_VELVET;
+       if (agnusa1000) {
+               ecs_agnus = false;
+               aga_mode = false;
+       }
        denisea1000_noehb = currprefs.cs_denisemodel == DENISEMODEL_VELVET || currprefs.cs_denisemodel == DENISEMODEL_A1000NOEHB;
        denisea1000 = currprefs.cs_denisemodel == DENISEMODEL_VELVET || currprefs.cs_denisemodel == DENISEMODEL_A1000NOEHB || currprefs.cs_denisemodel == DENISEMODEL_A1000;
        direct_rgb = aga_mode;
@@ -2458,9 +2504,9 @@ static uae_u16 get_strobe_reg(int slot)
        uae_u16 strobe = 0x1fe;
        if (slot == 0) {
                strobe = 0x3c;
-               if (vb_state && vpos < equ_vblank_endline) {
+               if (vb_start_line > 1 && vpos < get_equ_vblank_endline() && vpos >= get_equ_vblank_startline()) {
                        strobe = 0x38;
-               } else if (vb_state) {
+               } else if (vb_start_line > 1 || vb_end_line || vb_end_next_line) {
                        strobe = 0x3a;
                }
        } else if (slot == 1 && ecs_agnus && lol) {
@@ -2767,22 +2813,8 @@ static void fetch_strobe_conflict(int nr, int fm, int hpos, bool addmodulo)
        // decide sprites before sprite offset change
        decide_sprites(hpos + 1);
 
-       if (!hstrobe_conflict) {
-               hdiwstate_conflict = hdiwstate;
-       }
-
-       hdiw_counter_sconflict += (512 - ((maxhpos * 2 + 1) - 1)) << sprite_buffer_res;
-       hdiw_counter_sconflict &= hdiw_counter_sconflict_mask;
-
-       if (hstrobe_conflict) {
-               hdiw_counter_conflict += ((maxhpos * 2 + 1) - 1) << 2;
-       }
-       hdiw_counter_conflict &= (512 << 2) - 1;
-
-       hstrobe_conflict2 = true;
        hstrobe_conflict = true;
 
-
        SET_LINE_CYCLEBASED(hpos);
 }
 
@@ -3238,18 +3270,11 @@ static void pull_toscr_output_bits(int nbits, int planes, uae_u32 *ptrs)
                return;
        }
        int tbits = nbits - out_nbits;
-       uae_u64 tmask = (1 << tbits) - 1;
        uae_u64 nmask = (1 << out_nbits) - 1;
-       uae_u8 *dataptr = line_data[next_lineno] + (out_offs - 2) * 4;
        for (int i = 0; i < planes; i++) {
                ptrs[i] = 0;
-               if (out_offs >= 2) {
-                       uae_u64 *dataptr64 = (uae_u64*)dataptr;
-                       uae_u64 vv = *dataptr64;
-                       uae_u64 v = (vv >> 32) | (vv << 32);
-                       ptrs[i] = (uae_u32)((v << out_nbits) & mask);
-                       dataptr += MAX_WORDS_PER_LINE * 2;
-               }
+               uae_u64 v = outword64_extra[i];
+               ptrs[i] = (uae_u32)((v << out_nbits) & mask);
                ptrs[i] |= outword64[i] & nmask;
        }
 }
@@ -3267,21 +3292,13 @@ static void push_toscr_output_bits(int nbits, int planes, uae_u32 *ptrs)
        int tbits = nbits - out_nbits;
        uae_u64 tmask = (1 << tbits) - 1;
        uae_u64 nmask = (1 << out_nbits) - 1;
-       uae_u8 *dataptr = line_data[next_lineno] + (out_offs - 2) * 4;
        for (int i = 0; i < planes; i++) {
-               if (out_offs >= 2) {
-                       uae_u64 *dataptr64 = (uae_u64*)dataptr;
-                       uae_u64 vv = *dataptr64;
-                       uae_u64 v = (vv >> 32) | (vv << 32);
-                       v &= ~tmask;
-                       v |= (ptrs[i] >> out_nbits) & tmask;
-                       vv = (v >> 32) | (v << 32);
-                       *dataptr64 = vv;
-                       dataptr += MAX_WORDS_PER_LINE * 2;
-               }
+               uae_u64 v = outword64_extra[i];
+               v &= ~tmask;
+               v |= (ptrs[i] >> out_nbits) & tmask;
+               outword64_extra[i] = v;
                outword64[i] &= ~nmask;
                outword64[i] |= ptrs[i] & nmask;
-               thisline_changed = 1;
        }
 }
 
@@ -3291,7 +3308,10 @@ STATIC_INLINE void toscr_1_hr_nbits(void)
                uae_u8 *dataptr = line_data[next_lineno] + out_offs * 4;
                for (int i = 0; i < toscr_nr_planes2; i++) {
                        uae_u64 *dataptr64 = (uae_u64 *)dataptr;
-                       uae_u64 v = (outword64[i] >> 32) | (outword64[i] << 32);
+                       uae_u64 v = outword64[i];
+//                     uae_u64 v = outword64_extra[i];
+//                     outword64_extra[i] = outword64[i];
+                       v = (v >> 32) | (v << 32);
                        if (thisline_changed || *dataptr64 != v) {
                                thisline_changed = 1;
                                *dataptr64 = v;
@@ -4209,7 +4229,7 @@ static void hbstrt_bordercheck(int hpos, bool early)
        }
        pos -= 2; // 1 hires pixel early
        pos = adjust_hr(pos);
-       hdiw_restart(hb_last_diwlastword, pos);
+       hdiw_restart(hb_last_diwlastword, pos, false);
        hb_last_diwlastword = -1;
 }
 
@@ -4278,7 +4298,7 @@ static void beginning_of_plane_block(int hpos)
 
        // do not mistake end of bitplane as start of low value hblank programmed mode
        if (bpl_shifter <= 0 && hpos > REFRESH_FIRST_HPOS) {
-               if (ecs_denise || hpos >= OCS_DENISE_HBLANK_DISABLE_HPOS + 1 || hdiwstate == diw_states::DIW_waiting_stop) {
+               if (ecs_denise || hpos >= OCS_DENISE_HBLANK_DISABLE_HPOS || hdiwstate == diw_states::DIW_waiting_stop) {
                        start_noborder(hpos + hpos_hsync_extra);
                }
        }
@@ -5137,11 +5157,13 @@ static void record_color_change(int hpos, int regno, uae_u32 value)
 {
        if (regno < RECORDED_REGISTER_CHANGE_OFFSET && nodraw())
                return;
+
+       decide_hdiw(hpos);
+
        /* vsync period don't appear on-screen. */
        if (line_hidden())
                return;
 
-       decide_hdiw(hpos);
        decide_line(hpos);
 
        if (thisline_decision.ctable < 0) {
@@ -5690,13 +5712,9 @@ static void add_sprite(int *countp, int num, int sprxp, int posns[], int nrs[])
 static void calcsprite(void)
 {
        sprite_minx = 0;
-       sprite_maxx = -1;
        if (thisline_decision.diwfirstword >= 0) {
                sprite_minx = tospritexdiw(thisline_decision.diwfirstword);
        }
-       if (thisline_decision.diwlastword >= 0) {
-               sprite_maxx = tospritexdiw(thisline_decision.diwlastword);
-       }
        if (thisline_decision.plfleft >= 0) {
                int min = tospritexddf(thisline_decision.plfleft);
                int max = tospritexddf(thisline_decision.plfright);
@@ -5711,42 +5729,25 @@ static void calcsprite(void)
        }
 }
 
-static void decide_sprites(int hpos, bool usepointx, bool quick)
+static int last_sprite_hpos, last_sprite_hpos_reset;
+
+static void decide_sprites2(int start, int end, int *countp, int *nrs, int *posns)
 {
-       int nrs[MAX_SPRITES * 2], posns[MAX_SPRITES * 2];
-       int count;
-       int point;
+       int count = *countp;
        int sscanmask = 0x100 << sprite_buffer_res;
-       int gotdata = 0;
-       int extrahpos = hsyncstartpos_start_cycles * 2; // hpos 0 to this value is visible in right border
-
-       point = (hpos + hpos_hsync_extra) * 2 - DDF_OFFSET;
-
-       if (point <= last_sprite_point) {
-               return;
-       }
 
        if (nodraw() || nr_armed == 0) {
-               last_sprite_point = point;
                return;
        }
 
-       if (!quick) {
-               decide_hdiw(hpos);
-               decide_line(hpos);
-               calcsprite();
-       }
-
-       count = 0;
        for (int i = 0; i < MAX_SPRITES; i++) {
                struct sprite *s = &spr[i];
-               int xpos = (spr[i].xpos + hdiw_counter_sconflict + vhposr_sprite_offset) & hdiw_counter_sconflict_mask;
+               int xpos = spr[i].xpos;
                int sprxp = (fmode & 0x8000) ? (xpos & ~sscanmask) : xpos;
                int hw_xp = sprxp >> sprite_buffer_res;
-               int pointx = usepointx && (s->ctl & sprite_sprctlmask) ? 0 : 1;
 
                // Sprite does not start if X=0 but SSCAN2 sprite does. Don't do X == 0 check here.
-               if (sprxp < 0 || hw_xp > maxhpos * 2 + 1) {
+               if (sprxp < 0) {
                        continue;
                }
 
@@ -5769,42 +5770,113 @@ static void decide_sprites(int hpos, bool usepointx, bool quick)
                        hw_xp = sprxp >> sprite_buffer_res;
                }
 
-               if ((hw_xp > 0 || hdiw_counter_sconflict) && hw_xp > last_sprite_point && hw_xp <= point + pointx) {
-                       add_sprite(&count, i, sprxp, posns, nrs);
+               if (hw_xp >= start && hw_xp < end) {
+                       int xdiff = hw_xp - start;
+                       int sprxp_abs = (last_sprite_point_abs + xdiff) << sprite_buffer_res;
+                       // add hires/shres back
+                       sprxp_abs |= xpos & (3 >> (RES_MAX - sprite_buffer_res));
+                       add_sprite(&count, i, sprxp_abs, posns, nrs);
                }
 
                /* SSCAN2-bit is fun.. */
-               if ((fmode & 0x8000) && !(sprxp & sscanmask)) {
+               if (1 && (fmode & 0x8000) && !(sprxp & sscanmask)) {
                        sprxp |= sscanmask;
                        hw_xp = sprxp >> sprite_buffer_res;
-                       if (hw_xp > last_sprite_point && hw_xp <= point + pointx) {
-                               add_sprite(&count, MAX_SPRITES + i, sprxp, posns, nrs);
+                       if (hw_xp >= start && hw_xp < end) {
+                               int xdiff = hw_xp - start;
+                               int sprxp_abs = (last_sprite_point_abs + xdiff) << sprite_buffer_res;
+                               sprxp_abs |= xpos & (3 >> (RES_MAX - sprite_buffer_res));
+                               add_sprite(&count, MAX_SPRITES + i, sprxp_abs, posns, nrs);
                        }
-               } else if (xpos >= (2 << sprite_buffer_res) && xpos <= (extrahpos << sprite_buffer_res)) {
-                       // right border wrap around. SPRxCTL horizontal bits do not matter.
-                       sprxp += (maxhpos * 2) << sprite_buffer_res;
-                       hw_xp = sprxp >> sprite_buffer_res;
-                       if (hw_xp > last_sprite_point && hw_xp <= point + pointx) {
-                               add_sprite(&count, MAX_SPRITES + i, sprxp, posns, nrs);
+               }
+       }
+       *countp = count;
+
+
+}
+
+static void decide_sprites(int hpos, bool quick, bool halfcycle = false)
+{
+       int count = 0;
+       int gotdata = 0;
+       int nrs[MAX_SPRITES * 2], posns[MAX_SPRITES * 2];
+       int hp = (hpos << 1) + halfcycle;
+
+       // don't bother with sprites during vblank lines
+       if (vb_start_line > 1) {
+               last_sprite_hpos = hp;
+               return;
+       }
+
+       int c = hp - last_sprite_hpos;
+       if (c <= 0) {
+               return;
+       }
+
+       if (!quick) {
+               decide_hdiw(hpos);
+               decide_line(hpos);
+               calcsprite();
+       }
+
+       if (last_sprite_hpos < (HARDWIRED_DMA_TRIGGER_HPOS << 1) && hp >= (HARDWIRED_DMA_TRIGGER_HPOS << 1)) {
+               last_sprite_hpos_reset = (REFRESH_FIRST_HPOS - HARDWIRED_DMA_TRIGGER_HPOS + 2) << 1;
+               last_sprite_hpos_reset += 1;
+       }
+
+       int start = last_sprite_point;
+       int max = 512;
+
+       if (last_sprite_hpos_reset > 0 && c >= last_sprite_hpos_reset && !line_equ_freerun && !hstrobe_conflict) {
+               // strobe crossed?
+               last_sprite_point += last_sprite_hpos_reset + 0;
+               decide_sprites2(start, last_sprite_point, &count, nrs, posns);
+               last_sprite_point_abs += last_sprite_point - start;
+               last_sprite_point = 2;
+               start = last_sprite_point;
+               last_sprite_point += c - last_sprite_hpos_reset;
+               decide_sprites2(start, last_sprite_point, &count, nrs, posns);
+               last_sprite_point_abs += last_sprite_point - start;
+               last_sprite_hpos_reset = -1;
+       } else {
+               last_sprite_point += c;
+               // wrap around?
+               if (last_sprite_point >= max) {
+                       decide_sprites2(start, max, &count, nrs, posns);
+                       last_sprite_point_abs += max - start;
+                       last_sprite_point &= max - 1;
+                       if (last_sprite_point > 0) {
+                               decide_sprites2(0, last_sprite_point, &count, nrs, posns);
+                               last_sprite_point_abs += last_sprite_point - 0;
                        }
-                       // (not really mutually exclusive of SSCAN2-bit but not worth the trouble)
+               } else {
+                       decide_sprites2(start, last_sprite_point, &count, nrs, posns);
+                       last_sprite_point_abs += last_sprite_point - start;
+               }
+               if (last_sprite_hpos_reset >= 0) {
+                       last_sprite_hpos_reset -= c;
                }
        }
+       last_sprite_hpos = hp;
+
 
        for (int i = 0; i < count; i++) {
                int nr = nrs[i] & (MAX_SPRITES - 1);
                struct sprite *s = &spr[nr];
+
+               // ECS Denise weird behavior in shres
                if (s->ecs_denise_hires && !(bplcon0d & 0x40)) {
                        s->data[0] &= 0x7fff;
                        s->datb[0] &= 0x7fff;
                }
+
                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) {
+               if (dmaen(DMA_SPRITE) && brdspractive() && !(bplcon3 & 0x20) && nr > 0) {
                        int j, jj;
-                       for (j = 0, jj = 0; j < sprite_width; j+= 16, jj++) {
+                       for (j = 0, jj = 0; j < sprite_width; j += 16, jj++) {
                                int nx = fromspritexdiw(posns[i] + j);
                                if (s->data[jj] || s->datb[jj]) {
                                        if (diwfirstword_total > nx && nx >= (48 << currprefs.gfx_resolution)) {
@@ -5818,11 +5890,8 @@ static void decide_sprites(int hpos, bool usepointx, bool quick)
                        gotdata = 1;
                }
 #endif
-
        }
 
-       last_sprite_point = point;
-
 #if AUTOSCALE_SPRITES
        /* get upper and lower sprite position if brdsprt enabled */
        if (gotdata) {
@@ -5841,6 +5910,7 @@ static void decide_sprites(int hpos, bool usepointx, bool quick)
        }
 #endif
 }
+
 static void decide_sprites(int hpos)
 {
        decide_sprites(hpos, false, false);
@@ -5926,19 +5996,12 @@ static void hstrobe_conflict_check(uae_u32 v)
        // not conflict?
        if (!(datreg & CYCLE_PIPE_BITPLANE)) {
                hstrobe_conflict = false;
-               hdiw_counter_conflict += ((maxhpos * 2 + 1) - 1) << 2;
-               hdiw_counter_conflict &= (512 << 2) - 1;
-               decide_hstrobe_hdiw(hpos);
-               hdiwstate = hdiwstate_conflict;
-               decide_hdiw(hpos);
-               hdiw_counter_sconflict = 0;
-               hdiw_counter_conflict = 0;
-               flush_display(fetchmode);
-               delay_cycles = (2 + 2) << LORES_TO_SHRES_SHIFT;
+               int pos = hpos_to_diwx(hpos);
+               addcc(pos, 0, COLOR_CHANGE_ACTBORDER | 2);
+               MARK_LINE_CHANGED;
        }
 }
 
-
 static void finish_decisions(int hpos)
 {
        struct amigadisplay *ad = &adisplays[0];
@@ -5958,10 +6021,12 @@ static void finish_decisions(int hpos)
                thisline_decision.bplres = output_res(RES_LORES);
        }
 
+#if 0
        if (hstrobe_conflict) {
                sync_color_changes(hpos + DDF_OFFSET / 2 + 1);
                decide_hstrobe_hdiw(hpos);
        }
+#endif
 
        // Add DDF_OFFSET to detect blanking changes past hpos max
        sync_color_changes(hpos + DDF_OFFSET / 2 + 1);
@@ -5973,8 +6038,6 @@ static void finish_decisions(int hpos)
                thisline_decision.diwlastword = max_diwlastword;
        }
 
-       last_diwlastword = -1;
-
        if (thisline_decision.diwfirstword != line_decisions[next_lineno].diwfirstword) {
                MARK_LINE_CHANGED;
        }
@@ -6048,7 +6111,6 @@ static void reset_decisions_scanline_start(void)
                return;
 
        if (hstrobe_conflict) {
-               hstrobe_conflict2 = false;
                event2_newevent_xx(-1, REFRESH_FIRST_HPOS * CYCLE_UNIT, 0, hstrobe_conflict_check);
        }
 
@@ -6059,7 +6121,8 @@ static void reset_decisions_scanline_start(void)
        ddfstrt_hpos = -1;
        ddfstop_hpos = -1;
        last_diw_hpos = 0;
-       last_diw_hpos2 = 0;
+       last_sprite_hpos = 0;
+       last_sprite_hpos_reset = 0;
        blt_info.finishhpos = -1;
 
        /* Default to no bitplane DMA overriding sprite DMA */
@@ -6136,6 +6199,8 @@ static void reset_decisions_hsync_start(void)
                return;
        }
 
+       int hpos = current_hpos();
+
        thisline_decision.diwfirstword = -1;
        thisline_decision.diwlastword = -1;
        // hdiw already open?
@@ -6153,8 +6218,9 @@ static void reset_decisions_hsync_start(void)
        last_color_change = next_color_change;
        curr_drawinfo[next_lineno].first_sprite_entry = next_sprite_entry;
        next_sprite_forced = 1;
+       last_sprite_point_abs = ((1 + (hpos - REFRESH_FIRST_HPOS - 2)) << 1) + 1;
+       hdiw_denisecounter_abs = ((1 + (hpos - REFRESH_FIRST_HPOS - 2)) << CCK_SHRES_SHIFT) + 0;
 
-       last_sprite_point = 0;
        sprites_enabled_this_line = false;
        bpl1mod_hpos = -1;
        bpl2mod_hpos = -1;
@@ -6162,7 +6228,7 @@ static void reset_decisions_hsync_start(void)
        collision_hpos = 0;
 
        vhposr_delay_offset = 0;
-       vhposr_sprite_offset = 0;
+       vhposw_modified = false;
 
        compute_toscr_delay(bplcon1);
 
@@ -6220,6 +6286,7 @@ static void reset_decisions_hsync_start(void)
        } else {
                thisline_decision.vb = vb_start_line >= 2 + vblank_extraline || vb_end_next_line ? 0 : VB_NOVB;
        }
+
        // if programmed vblank
        if ((new_beamcon0 & BEAMCON0_VARVBEN) && ecs_agnus) {
                if (!thisline_decision.vb) {
@@ -6284,7 +6351,6 @@ static void reset_decisions_hsync_start(void)
        thisline_decision.max_planes = toscr_nr_planes2 > toscr_nr_planes_agnus ? toscr_nr_planes2 : toscr_nr_planes_agnus;
 
        hpos_hsync_extra = 0;
-       int hpos = current_hpos();
        bool normalstart = true;
        plane0p_enabled = ecs_denise && (bplcon0 & 1) && (bplcon3 & 0x20);
        plane0p_forced = false;
@@ -6389,6 +6455,7 @@ static void reset_decisions_hsync_start(void)
                        //memset(todisplay_aga, 0, sizeof todisplay_aga);
                        memset(todisplay2_aga, 0, sizeof todisplay2_aga);
                        memset(outword64, 0, sizeof outword64);
+                       memset(outword64_extra, 0, sizeof outword64_extra);
                }
 #endif
        }
@@ -6468,7 +6535,7 @@ void compute_vsynctime(void)
 void getsyncregisters(uae_u16 *phsstrt, uae_u16 *phsstop, uae_u16 *pvsstrt, uae_u16 *pvsstop)
 {
        *phsstrt = hsstrt;
-       *phsstop = hsstop_detect * 2;
+       *phsstop = hsstop_detect2 / 2;
        *pvsstrt = vsstrt;
        *pvsstop = vsstop;
 }
@@ -6581,11 +6648,11 @@ static void updateextblk(void)
                // hblank has 1 lores pixel offset
                hbstrt_v2 = hbstrt_v - 4;
                if (hbstrt_v >= (1 << CCK_SHRES_SHIFT) && hbstrt_v2 < (1 << CCK_SHRES_SHIFT)) {
-                       hbstrt_v2 += maxhpos << CCK_SHRES_SHIFT;
+                       hbstrt_v2 += maxhpos_short << CCK_SHRES_SHIFT;
                }
                hbstop_v2 = hbstop_v - 4;
                if (hbstop_v >= (1 << CCK_SHRES_SHIFT) && hbstop_v2 < (1 << CCK_SHRES_SHIFT)) {
-                       hbstop_v2 += maxhpos << CCK_SHRES_SHIFT;
+                       hbstop_v2 += maxhpos_short << CCK_SHRES_SHIFT;
                }
                exthblank = (bplcon0 & 1) && (bplcon3 & 1);
        } else {
@@ -6614,10 +6681,10 @@ static void updateextblk(void)
                hbstrt_v2 -= 4;
                hbstop_v2 -= 4;
                if (hbstrt_v >= (1 << CCK_SHRES_SHIFT) && hbstrt_v2 < (1 << CCK_SHRES_SHIFT)) {
-                       hbstrt_v2 += maxhpos << CCK_SHRES_SHIFT;
+                       hbstrt_v2 += maxhpos_short << CCK_SHRES_SHIFT;
                }
                if (hbstop_v >= (1 << CCK_SHRES_SHIFT) && hbstop_v2 < (1 << CCK_SHRES_SHIFT)) {
-                       hbstop_v2 += maxhpos << CCK_SHRES_SHIFT;
+                       hbstop_v2 += maxhpos_short << CCK_SHRES_SHIFT;
                }
                exthblank = (bplcon0 & 1) && (bplcon3 & 1);
        }
@@ -6629,25 +6696,29 @@ static void updateextblk(void)
                hbstop_v2 = adjust_hr(hbstop_v2);
        }
 
-       if (new_beamcon0 & bemcon0_hsync_mask) {
+       hbstrt_reg = hbstrt_v2;
+       hbstop_reg = hbstop_v2;
+
+       if ((new_beamcon0 & bemcon0_hsync_mask) && (!currprefs.monitoremu || currprefs.cs_hvcsync > 0)) {
 
                hsyncstartpos = hsstrt + 2;
-               if (hsyncstartpos >= maxhpos) {
-                       hsyncstartpos -= maxhpos;
+
+               if (hsyncstartpos >= maxhpos_short) {
+                       hsyncstartpos -= maxhpos_short;
                }
                hsyncendpos = hsstop;
 
                hsstop_detect2 = (hsstrt + 21) * 2;
-               if (hsstop_detect2 >= maxhpos * 2) {
-                       hsstop_detect2 -= maxhpos * 2;
+               if (hsstop_detect2 >= maxhpos_short * 2) {
+                       hsstop_detect2 -= maxhpos_short * 2;
                }
 
                hsyncstartpos_start = hsyncstartpos;
-               if (hsyncstartpos < maxhpos / 2) {
+               if (hsyncstartpos < maxhpos_short / 2) {
                        hsyncstartpos = maxhpos_short + hsyncstartpos_start;
                        denisehtotal = hsyncstartpos;
                } else {
-                       denisehtotal = maxhpos + hsyncstartpos;
+                       denisehtotal = maxhpos_short + hsyncstartpos;
                }
                // make sure possible BPL DMA cycles before first refresh slot are processed before hsync
                if (hsyncstartpos_start < REFRESH_FIRST_HPOS + 1) {
@@ -6661,17 +6732,19 @@ static void updateextblk(void)
 
                hsyncstartpos_start = hsyncstartpos_start_hw;
                hsyncstartpos = hsyncstartpos_hw;
-               denisehtotal = maxhpos + 7;
+               denisehtotal = maxhpos_short + 7;
                hsstop_detect2 = (35 + 9) * 2;
 
                hsstrt_v2 = 18 << CCK_SHRES_SHIFT;
                hsstop_v2 = 35 << CCK_SHRES_SHIFT;
                hsyncendpos = hsyncendpos_hw;
+
        }
 
        hsstrt_v2 = adjust_hr(hsstrt_v2);
        hsstop_v2 = adjust_hr(hsstop_v2);
 
+
        // Out of range left. Denise/Lisa hcounter starts from 2 (skips first 2 lores pixels)
        if (hbstrt_v2 < (1 << CCK_SHRES_SHIFT)) {
                hbstrt_v2 = 0xffff;
@@ -6680,22 +6753,22 @@ static void updateextblk(void)
                hbstop_v2 = 0xffff;
        }
        // Out of range right
-       if (hbstrt_v2 >= (maxhpos << CCK_SHRES_SHIFT) + (1 << CCK_SHRES_SHIFT)) {
+       if (hbstrt_v2 >= (maxhpos_short << CCK_SHRES_SHIFT) + (1 << CCK_SHRES_SHIFT)) {
                hbstrt_v2 = 0xffff;
        }
-       if (hbstop_v2 >= (maxhpos << CCK_SHRES_SHIFT) + (1 << CCK_SHRES_SHIFT)) {
+       if (hbstop_v2 >= (maxhpos_short << CCK_SHRES_SHIFT) + (1 << CCK_SHRES_SHIFT)) {
                hbstop_v2 = 0xffff;
        }
        // hsync start offset adjustment
        if (hbstrt_v2 <= (hsyncstartpos_start << CCK_SHRES_SHIFT)) {
-               hbstrt_v2 += maxhpos << CCK_SHRES_SHIFT;
-               if (hbstrt_v2 > (maxhpos + hsyncstartpos_start_cycles) << CCK_SHRES_SHIFT) {
+               hbstrt_v2 += maxhpos_short << CCK_SHRES_SHIFT;
+               if (hbstrt_v2 > (maxhpos_short + hsyncstartpos_start_cycles) << CCK_SHRES_SHIFT) {
                        hbstrt_v2 = 1 << CCK_SHRES_SHIFT;
                }
        }
        if (hbstop_v2 <= (hsyncstartpos_start << CCK_SHRES_SHIFT)) {
-               hbstop_v2 += maxhpos << CCK_SHRES_SHIFT;
-               if (hbstop_v2 > (maxhpos + hsyncstartpos_start_cycles) << CCK_SHRES_SHIFT) {
+               hbstop_v2 += maxhpos_short << CCK_SHRES_SHIFT;
+               if (hbstop_v2 > (maxhpos_short + hsyncstartpos_start_cycles) << CCK_SHRES_SHIFT) {
                        hbstop_v2 = 1 << CCK_SHRES_SHIFT;
                }
        }
@@ -6709,12 +6782,12 @@ static void updateextblk(void)
                int add = currprefs.chipset_hr ? (1 << currprefs.gfx_resolution) : 4;
                if (strt < stop) {
                        hbstop_v2 += add;
-                       if (hbstop_v2 >= (maxhpos << CCK_SHRES_SHIFT) + (1 << CCK_SHRES_SHIFT)) {
+                       if (hbstop_v2 >= (maxhpos_short << CCK_SHRES_SHIFT) + (1 << CCK_SHRES_SHIFT)) {
                                hbstop_v2 = 0;
                        }
                } else if (strt > stop) {
                        hbstrt_v2 += add;
-                       if (hbstrt_v2 >= (maxhpos << CCK_SHRES_SHIFT) + (1 << CCK_SHRES_SHIFT)) {
+                       if (hbstrt_v2 >= (maxhpos_short << CCK_SHRES_SHIFT) + (1 << CCK_SHRES_SHIFT)) {
                                hbstrt_v2 = 0;
                        }
                }
@@ -6915,7 +6988,7 @@ void compute_framesync(void)
        if (vidinfo->drawbuffer.extrawidth == -2 && ((new_beamcon0 & (BEAMCON0_VARVBEN | bemcon0_vsync_mask)) || currprefs.gfx_overscanmode >= OVERSCANMODE_EXTREME)) {
                vidinfo->drawbuffer.extrawidth = -1;
        }
-       vidinfo->drawbuffer.inheight = (maxvpos_display + maxvpos_display_vsync - minfirstline) << vres2;
+       vidinfo->drawbuffer.inheight = maxvsize_display << vres2;
        vidinfo->drawbuffer.inheight2 = vidinfo->drawbuffer.inheight;
        vidinfo->drawbuffer.inxoffset = 0;
 
@@ -6984,7 +7057,7 @@ void compute_framesync(void)
 }
 
 /* set PAL/NTSC or custom timing variables */
-static void init_beamcon0(void)
+static void init_beamcon0(bool fakehz)
 {
        int isntsc, islace;
        int hpos = current_hpos();
@@ -7223,7 +7296,7 @@ static void init_beamcon0(void)
                minfirstline_hw = 0;
        }
 
-       if (vpos_count > 0) {
+       if (fakehz && vpos_count > maxvpos_display_vsync) {
                // we come here if vpos_count != maxvpos and beamcon0 didn't change
                // (someone poked VPOSW)
                if (vpos_count < 10) {
@@ -7365,6 +7438,7 @@ static void init_beamcon0(void)
                vblank_hz = 300;
        }
        maxhpos_short = maxhpos;
+       minfirstline_linear = minfirstline;
        set_delay_lastcycle();
        updateextblk();
        maxvpos_total = ecs_agnus ? (MAXVPOS_LINES_ECS - 1) : (MAXVPOS_LINES_OCS - 1);
@@ -7372,8 +7446,8 @@ static void init_beamcon0(void)
                maxvpos_total = MAXVPOS;
        }
        set_maxhpos(maxhpos);
-       display_reset = 2;
        estimated_fm = 0xffff;
+       maxvsize_display = maxvpos_display + maxvpos_display_vsync - minfirstline;
 
        if ((currprefs.m68k_speed == 0 || copper_access) && maxhpos != oldmaxhpos) {
                if (hpos >= maxhpos) {
@@ -7423,7 +7497,7 @@ static void init_hz(bool checkvposw)
                hzc = 1;
        }
 
-       init_beamcon0();
+       init_beamcon0(checkvposw);
 
        if (doublescan != odbl || maxvpos != omaxvpos) {
                hzc = 1;
@@ -7515,11 +7589,9 @@ static void calcdiw(void)
 
        diwfirstword = coord_diw_shres_to_window_x(hstrt);
        diwlastword = coord_diw_shres_to_window_x(hstop);
-       if (diwfirstword < min_diwlastword) {
-               diwfirstword = min_diwlastword;
-       }
-       if (diwlastword < min_diwlastword) {
-               diwlastword = min_diwlastword;
+       int mindiw = min_diwlastword;
+       if (diwfirstword < mindiw) {
+               diwfirstword = mindiw;
        }
 
        int hpos = current_hpos();
@@ -7650,15 +7722,15 @@ STATIC_INLINE uae_u16 DMACONR(int hpos)
 }
 STATIC_INLINE uae_u16 INTENAR(void)
 {
-       return intena;
+       return intena & 0x7fff;
 }
 uae_u16 INTREQR(void)
 {
-       return intreq;
+       return intreq & 0x7fff;
 }
 STATIC_INLINE uae_u16 ADKCONR(void)
 {
-       return adkcon;
+       return adkcon & 0x7fff;
 }
 
 STATIC_INLINE int islightpentriggered(void)
@@ -7725,6 +7797,12 @@ static void vb_check(void)
                vb_end_line = true;
                vb_state = false;
        }
+       if (vpos == hardwired_vbstop) {
+               vb_end_line = false;
+               vb_state = false;
+               vb_start_line = 0;
+               vb_end_next_line = true;
+       }
 }
 
 static void vhpos_adj(uae_u16 *hpp, uae_u16 *vpp)
@@ -7842,10 +7920,15 @@ static void VHPOSW_delayed(uae_u32 v)
        int oldvpos = vpos;
        int newvpos = vpos;
        int hpos_org = current_hpos();
+       int hnew = hpos_org;
        bool enabled = false;
 
+       decide_vline(hpos_org);
+       decide_hdiw(hpos_org);
        decide_line(hpos_org);
        decide_fetch_safe(hpos_org);
+       decide_sprites(hpos_org);
+       flush_display(fetchmode);
 
 #if 0
        if (M68K_GETPC < 0xf00000 || 1)
@@ -7855,7 +7938,7 @@ static void VHPOSW_delayed(uae_u32 v)
        if ((currprefs.m68k_speed >= 0 && !currprefs.cachesize) || copper_access) {
                enabled = true;
                int hpos = hpos_org;
-               int hnew = (v & 0xff);
+               hnew = (v & 0xff);
                int hnew_org = hnew;
                bool newinc = false;
                if (hpos == 0 || hpos == 1) {
@@ -7877,11 +7960,9 @@ static void VHPOSW_delayed(uae_u32 v)
                }
 
                if (hdiff) {
-                       delay_cycles += ((-hdiff * 8 - 2) & 7) << LORES_TO_SHRES_SHIFT;
                        if (hdiff & 1) {
                                vhposr_delay_offset = 1;
                        }
-                       vhposr_sprite_offset += (hdiff * 4 - 2) << sprite_buffer_res;
 
                        evt_t hsync_evtime = eventtab[ev_hsync].evtime;
                        evt_t hsync_oldcycles = eventtab[ev_hsync].oldcycles;
@@ -7946,10 +8027,19 @@ static void VHPOSW_delayed(uae_u32 v)
                                                memset(blitter_pipe, 0, t * sizeof(uae_u16));
                                        }
                                }
-                               set_blitter_last(hnew + 1);
-                               last_copper_hpos = hnew + 1;
+                               int nhp = hnew + 1;
+                               set_blitter_last(nhp);
+                               last_copper_hpos = nhp;
+                               last_fetch_hpos = nhp;
+                               last_decide_line_hpos = nhp;
+                               last_decide_sprite_hpos = nhp;
                        }
                }
+
+               delay_cycles = ((hnew + 0) & 0xff) << CCK_SHRES_SHIFT;
+
+               last_diw_hpos = hnew << 1;
+               hdiw_denisecounter = ((hnew + 0) & 0xff) << CCK_SHRES_SHIFT;
        }
 
        newvpos &= 0xff00;
@@ -7970,16 +8060,32 @@ static void VHPOSW_delayed(uae_u32 v)
                        }
                }
 #endif
-               SET_LINE_CYCLEBASED(hpos_org);
        }
        vpos = newvpos;
+       record_dma_denise(hnew, hdiw_denisecounter >> 2);
        vb_check();
-       decide_vline(hpos_org);
+       decide_vline(hnew);
+       vhposw_modified = true;
+}
+
+static void VHPOSW_delayed1(uae_u32 v)
+{
+       int hpos = current_hpos();
+       decide_hdiw(hpos);
+       decide_line(hpos);
+       decide_fetch_safe(hpos);
+       decide_sprites(hpos, false, true);
+
+       int hnew = v & 0xff;
+       last_sprite_hpos = (hnew << 1) - 1;
+       last_sprite_point = (((hnew + 0) & 0xff) << 1) + 0;
+
+       event2_newevent_xx(-1, 1 * CYCLE_UNIT, v, VHPOSW_delayed);
 }
 
 static void VHPOSW(uae_u16 v)
 {
-       event2_newevent_xx(-1, 2 * CYCLE_UNIT, v, VHPOSW_delayed);
+       event2_newevent_xx(-1, 1 * CYCLE_UNIT, v, VHPOSW_delayed1);
 }
 
 static uae_u16 VHPOSR(void)
@@ -8456,16 +8562,17 @@ static void DMACON(int hpos, uae_u16 v)
        if (!oldcop && newcop) {
                bootwarpmode();
        }
-       if (oldcop != newcop && (copper_access || safecpu())) {
-               copper_dma_change_cycle = get_cycles();
-       }
        if (newcop && !oldcop) {
-               if (copper_dma_change_cycle == get_cycles()) {
+               if (copper_access || safecpu()) {
+                       copper_dma_change_cycle = get_cycles();
                        event2_newevent_xx(-1, CYCLE_UNIT, 0, compute_spcflag_copper_delayed);
                } else {
                        compute_spcflag_copper();
                }
        } else if (!newcop && oldcop) {
+               if (copper_access || safecpu()) {
+                       copper_dma_change_cycle = get_cycles();
+               }
                compute_spcflag_copper();
        }
 
@@ -8773,18 +8880,12 @@ static void check_harddis(void)
        harddis_v = ecs_agnus && ((new_beamcon0 & BEAMCON0_VARBEAMEN) || (new_beamcon0 & BEAMCON0_VARVBEN) || (new_beamcon0 & BEAMCON0_HARDDIS));
 }
 
-static bool beamcon0_changed_critical(uae_u16 beamcon0a, uae_u16 beamcon0b)
-{
-       return (beamcon0a & (BEAMCON0_VARCSYEN | BEAMCON0_PAL | BEAMCON0_VARBEAMEN | BEAMCON0_VARHSYEN | BEAMCON0_VARVSYEN | BEAMCON0_VARVBEN | BEAMCON0_HARDDIS)) !=
-               (beamcon0b & (BEAMCON0_VARCSYEN | BEAMCON0_PAL | BEAMCON0_VARBEAMEN | BEAMCON0_VARHSYEN | BEAMCON0_VARVSYEN | BEAMCON0_VARVBEN | BEAMCON0_HARDDIS));
-}
-
 static void BEAMCON0(int hpos, uae_u16 v)
 {
        if (ecs_agnus) {
                bool beamcon0_changed = false;
                if (v != new_beamcon0) {
-                       sync_color_changes(hpos);
+                       sync_changes(hpos);
                        new_beamcon0 = v;
                        write_log(_T("BEAMCON0 = %04X, PC=%08X\n"), v, M68K_GETPC);
                        // not LPENDIS, LOLDIS, PAL, BLANKEN, SYNC INVERT
@@ -8798,7 +8899,7 @@ static void BEAMCON0(int hpos, uae_u16 v)
                check_harddis();
                calcdiw();
                if (beamcon0_changed) {
-                       init_beamcon0();
+                       init_beamcon0(false);
                }
        }
 }
@@ -8839,7 +8940,7 @@ static void varsync(int reg, bool resync)
                varsync_changed = 1;
        }
        if (varsync_changed) {
-               init_beamcon0();
+               init_beamcon0(false);
        }
 }
 
@@ -9232,42 +9333,53 @@ static void BPLxDAT(int hpos, int num, uae_u16 data)
        if (!num) {
                SET_LINE_CYCLEBASED(hpos);
        }
-       event2_newevent_xx(-1, 1 * CYCLE_UNIT, vv, BPLxDAT_next);
+       event2_newevent_xx_ce(1 * CYCLE_UNIT, vv, BPLxDAT_next);
 }
 
+static void DIWSTRT_next(uae_u32 v)
+{
+       int hpos = current_hpos();
+       decide_hdiw(hpos);
+       decide_line(hpos);
+       diwhigh_written = 0;
+       diwstrt = v;
+       calcdiw();
+}
 static void DIWSTRT(int hpos, uae_u16 v)
 {
        if (diwstrt == v && !diwhigh_written) {
                return;
        }
-       // if hpos matches previous hstart: it gets ignored.
-       if ((diw_hstrt >> 2) + DDF_OFFSET >= hpos * 2 - 2 && (diw_hstrt >> 2) + DDF_OFFSET <= hpos * 2 + 2) {
-               diw_hstrt = max_diwlastword << 2;
-       }
+       event2_newevent_xx_ce(1 * CYCLE_UNIT, v, DIWSTRT_next);
+}
+
+static void DIWSTOP_next(uae_u32 v)
+{
+       int hpos = current_hpos();
        decide_hdiw(hpos);
-       decide_conflict_hdiw(hpos);
        decide_line(hpos);
        diwhigh_written = 0;
-       diwstrt = v;
+       diwstop = v;
        calcdiw();
 }
-
 static void DIWSTOP(int hpos, uae_u16 v)
 {
        if (diwstop == v && !diwhigh_written) {
                return;
        }
-       if ((diw_hstop >> 2) + DDF_OFFSET >= hpos * 2 - 2 && (diw_hstop >> 2) + DDF_OFFSET <= hpos * 2 + 2) {
-               diw_hstop = min_diwlastword << 2;
-       }
-       decide_hdiw(hpos);
-       decide_conflict_hdiw(hpos);
+       event2_newevent_xx_ce(1 * CYCLE_UNIT, v, DIWSTOP_next);
+}
+
+static void DIWHIGH_next(uae_u32 v)
+{
+       int hpos = current_hpos();
+       // DIWHIGH has 1.5CCK delay
+       decide_hdiw(hpos, true);
        decide_line(hpos);
-       diwhigh_written = 0;
-       diwstop = v;
+       diwhigh_written = 1;
+       diwhigh = v;
        calcdiw();
 }
-
 static void DIWHIGH(int hpos, uae_u16 v)
 {
        if (!ecs_agnus && !ecs_denise) {
@@ -9280,12 +9392,7 @@ static void DIWHIGH(int hpos, uae_u16 v)
        if (diwhigh_written && diwhigh == v) {
                return;
        }
-       decide_hdiw(hpos);
-       decide_conflict_hdiw(hpos);
-       decide_line(hpos);
-       diwhigh_written = 1;
-       diwhigh = v;
-       calcdiw();
+       event2_newevent_xx_ce(1 * CYCLE_UNIT, v, DIWHIGH_next);
 }
 
 static void DDFSTRT(int hpos, uae_u16 v)
@@ -9723,7 +9830,7 @@ static void sprite_get_bpl_data(int hpos, struct sprite *s, uae_u16 *dat)
 static void SPRxDATA(int hpos, uae_u16 v, int num)
 {
        struct sprite *s = &spr[num];
-       decide_sprites(hpos, true, false);
+       decide_sprites(hpos, false);
        SPRxDATA_1(v, num, hpos);
        // if 32 (16-bit double CAS only) or 64 pixel wide sprite and SPRxDATx write:
        // - first 16 pixel part: previous chipset bus data
@@ -9736,10 +9843,11 @@ static void SPRxDATA(int hpos, uae_u16 v, int num)
                }
        }
 }
+
 static void SPRxDATB(int hpos, uae_u16 v, int num)
 {
        struct sprite *s = &spr[num];
-       decide_sprites(hpos, true, false);
+       decide_sprites(hpos, false);
        SPRxDATB_1(v, num, hpos);
        // See above
        if (fmode & 8) {
@@ -9751,8 +9859,11 @@ static void SPRxDATB(int hpos, uae_u16 v, int num)
        }
 }
 
-static void SPRxCTL(int hpos, uae_u16 v, int num)
+static void SPRxCTL_2(uae_u32 vv)
 {
+       int hpos = current_hpos();
+       uae_u16 v = vv >> 16;
+       int num = vv & 7;
 #if SPRITE_DEBUG > 0
        if (vpos >= SPRITE_DEBUG_MINY && vpos <= SPRITE_DEBUG_MAXY && (SPRITE_DEBUG & (1 << num))) {
                write_log(_T("%d:%d:SPR%dCTLC %06X\n"), vpos, hpos, num, spr[num].pt);
@@ -9762,8 +9873,17 @@ static void SPRxCTL(int hpos, uae_u16 v, int num)
        decide_sprites(hpos);
        SPRxCTL_1(v, num, hpos);
 }
-static void SPRxPOS(int hpos, uae_u16 v, int num)
+static void SPRxCTL(int hpos, uae_u16 v, int num)
 {
+       uae_u32 vv = (v << 16) | num;
+       event2_newevent_xx_ce(1 * CYCLE_UNIT, vv, SPRxCTL_2);
+}
+
+static void SPRxPOS_2(uae_u32 vv)
+{
+       int hpos = current_hpos();
+       uae_u16 v = vv >> 16;
+       int num = vv & 7;
        struct sprite *s = &spr[num];
 #if SPRITE_DEBUG > 0
        if (vpos >= SPRITE_DEBUG_MINY && vpos <= SPRITE_DEBUG_MAXY && (SPRITE_DEBUG & (1 << num))) {
@@ -9773,6 +9893,11 @@ static void SPRxPOS(int hpos, uae_u16 v, int num)
        decide_sprites(hpos);
        SPRxPOS_1(v, num, hpos);
 }
+static void SPRxPOS(int hpos, uae_u16 v, int num)
+{
+       uae_u32 vv = (v << 16) | num;
+       event2_newevent_xx_ce(1 * CYCLE_UNIT, vv, SPRxPOS_2);
+}
 
 static void SPRxPTH(int hpos, uae_u16 v, int num)
 {
@@ -11098,9 +11223,9 @@ static void compute_spcflag_copper(void)
 {
        copper_enabled_thisline = 0;
        unset_special(SPCFLAG_COPPER);
-       if (!is_copper_dma(false) || cop_state.state == COP_stop || cop_state.state == COP_waitforever || cop_state.state == COP_bltwait || cop_state.state == COP_bltwait2 || custom_disabled)
+       if (!is_copper_dma(true) || cop_state.state == COP_stop || cop_state.state == COP_waitforever || cop_state.state == COP_bltwait || cop_state.state == COP_bltwait2 || custom_disabled)
                return;
-       if (cop_state.state == COP_wait1) {
+       if (cop_state.state == COP_wait1 && is_copper_dma(false)) {
                int vp = vpos & (((cop_state.ir[1] >> 8) & 0x7F) | 0x80);
                if (vp < cop_state.vcmp) {
                        return;
@@ -11305,7 +11430,7 @@ static void do_sprite_fetch(int hpos, uae_u16 dat)
        bool dmastate = (dat & 0x10) != 0;
 
        // render sprites first
-       decide_sprites(hpos, false, true);
+       decide_sprites(hpos, true);
 
        sprite_fetch_full(s, hpos, slot, dmastate, &data, &data321, &data322);
 
@@ -11580,7 +11705,8 @@ void init_hardware_for_drawing_frame(void)
        end_sprite_entry = MAX_SPRITE_ENTRIES - 2;
        spixels_max = sizeof(spixels) / sizeof(*spixels) - MAX_PIXELS_PER_LINE;
 
-       next_lineno = calculate_lineno(vpos);
+       linear_vpos = vpos;
+       next_lineno = calculate_lineno(linear_vpos);
        last_color_change = 0;
        next_color_change = 0;
        next_color_entry = 0;
@@ -12070,7 +12196,7 @@ static void vsync_check_vsyncmode(void)
 {
        if (varsync_changed == 1) {
                init_hz_normal();
-       } else if (vpos_count > 0 && abs(vpos_count - vpos_count_diff) > 1 && vposw_change < 4) {
+       } else if (vpos_count > 0 && abs(vpos_count - vpos_count_diff) > 1 && vposw_change && vposw_change < 4) {
                init_hz_vposw();
        } else if (interlace_changed || changed_chipset_refresh() || lof_changed) {
                compute_framesync();
@@ -12081,6 +12207,40 @@ static void vsync_check_vsyncmode(void)
        }
 }
 
+static void check_display_mode_change(void)
+{
+       int vt, ht, hs, vs;
+       if (new_beamcon0 & BEAMCON0_VARBEAMEN) {
+               vt = vtotal;
+               ht = htotal;
+       } else {
+               vt = maxvpos;
+               ht = maxhpos;
+       }
+       if (new_beamcon0 & (BEAMCON0_VARHSYEN | BEAMCON0_VARCSYEN)) {
+               hs = hsstrt;
+       } else {
+               hs = 18;
+       }
+       if (new_beamcon0 & (BEAMCON0_VARVSYEN | BEAMCON0_VARCSYEN)) {
+               vs = vsstrt;
+       } else {
+               vs = (new_beamcon0 & BEAMCON0_PAL) ? 2 : 3;
+       }
+
+       // recalculate display if vtotal, htotal, hsync start or vsync start changed > 1
+       if ((abs(vt - vt_old) > 1 || abs(ht - ht_old) > 1 || abs(hs - hs_old) > 1 || abs(vs - vs_old) > 1)  && vt_old && ht_old) {
+               varsync_changed = 1;
+               nosignal_trigger = true;
+               display_reset = 2;
+       }
+
+       vt_old = vt;
+       ht_old = ht;
+       vs_old = vs;
+       hs_old = hs;
+}
+
 // emulated hardware vsync
 static void vsync_handler_post(void)
 {
@@ -12247,18 +12407,7 @@ static void vsync_handler_post(void)
 
        devices_vsync_post();
 
-       if (beamcon0_changed_critical(new_beamcon0, beamcon0_previous)) {
-               varsync_changed = 1;
-               if ((beamcon0_previous ^ new_beamcon0) & BEAMCON0_PAL) {
-                       nosignal_trigger = true;
-               }
-               if ((beamcon0_previous ^ new_beamcon0) & BEAMCON0_VARBEAMEN) {
-                       if (vtotal != maxvpos || htotal != maxhpos) {
-                               nosignal_trigger = true;
-                       }
-               }
-       }
-       beamcon0_previous = new_beamcon0;
+       check_display_mode_change();
 
        vsync_check_vsyncmode();
 
@@ -12276,16 +12425,19 @@ static void vsync_handler_post(void)
                }
        }
        if (nosignal_trigger) {
+               struct amigadisplay *ad = &adisplays[0];
                nosignal_trigger = false;
-               if (currprefs.gfx_monitorblankdelay > 0) {
-                       nosignal_status = 1;
-                       nosignal_cnt = (int)(currprefs.gfx_monitorblankdelay / (1000.0f / vblank_hz));
-                       if (nosignal_cnt <= 0) {
-                               nosignal_cnt = 1;
+               if (!ad->specialmonitoron) {
+                       if (currprefs.gfx_monitorblankdelay > 0) {
+                               nosignal_status = 1;
+                               nosignal_cnt = (int)(currprefs.gfx_monitorblankdelay / (1000.0f / vblank_hz));
+                               if (nosignal_cnt <= 0) {
+                                       nosignal_cnt = 1;
+                               }
+                       } else {
+                               nosignal_status = 2;
+                               nosignal_cnt = (int)(vblank_hz / 2);
                        }
-               } else {
-                       nosignal_status = 2;
-                       nosignal_cnt = (int)(vblank_hz / 2);
                }
        }
 
@@ -12324,7 +12476,7 @@ static void reset_scandoubler_sync(int hpos)
        last_fetch_hpos = hpos;
        last_copper_hpos = hpos;
        last_diw_hpos = hpos;
-       last_diw_hpos2 = hpos;
+       last_sprite_hpos = hpos;
        sprites_enabled_this_line = false;
        plfstrt_sprite = 0x100;
        bprun = 0;
@@ -12703,8 +12855,16 @@ static void hautoscale_check(int vp)
        }
        if (diw_change == 0) {
                if (vp_start >= first_planes_vpos && vp_end <= last_planes_vpos) {
-                       int diwlastword_lores = diwlastword;
                        int diwfirstword_lores = diwfirstword;
+                       int diwlastword_lores = diwlastword;
+                       // >0x1c7? Calculate "real" right edge for scaling modes
+                       if (diwlastword_lores < min_diwlastword && diwfirstword_lores >= 2) {
+                               if (diwlastword_lores < diwfirstword_lores) {
+                                       diwlastword_lores = max_diwlastword + (diwlastword_lores - 2);
+                               } else {
+                                       diwlastword_lores = min_diwlastword;
+                               }
+                       }
                        if (diwlastword_lores > diwlastword_total) {
                                diwlastword_total = diwlastword_lores;
                                if (diwlastword_total > coord_diw_shres_to_window_x(hsyncstartpos)) {
@@ -12765,11 +12925,14 @@ static void hsync_handlerh(bool onvsync)
 
                hautoscale_check(vposh);
 
-               int lineno = calculate_lineno(vposh);
-               next_lineno = lineno;
+               next_lineno = calculate_lineno(linear_vpos);
                reset_decisions_hsync_start();
        }
 
+       linear_vpos++;
+       if (vpos >= minfirstline && minfirstline_linear == minfirstline) {
+               minfirstline_linear = linear_vpos;
+       }
        vposh++;
 
        hpos_hsync_extra = 0;
@@ -12868,6 +13031,9 @@ static void hsync_handler_pre(bool onvsync)
        if (vpos >= maxvpos_total) {
                vpos = 0;
        }
+
+       line_equ_freerun = !ecs_denise && vpos >= get_equ_vblank_startline() && vpos <= get_equ_vblank_endline();
+
        if (onvsync) {
 #ifdef DEBUGGER
                if (debug_dma) {
@@ -14083,9 +14249,7 @@ static void hsync_handler(void)
                vsync_display_rendered = false;
                lof_display = lof_store;
                hstrobe_conflict = false;
-               hstrobe_conflict2 = false;
-               hdiw_counter_conflict = 0;
-               hdiw_counter_sconflict = 0;
+               minfirstline_linear = minfirstline;
                reset_autoscale();
        }
        vsync_line = vs;
@@ -14206,6 +14370,9 @@ void custom_reset(bool hardreset, bool keyboardreset)
        blitter_dma_change_cycle = -1;
        sprite_dma_change_cycle_on = -1;
        custom_color_write_cycle = -1;
+       vt_old = 0;
+       ht_old = 0;
+       hdiwstate_blank = diw_states::DIW_waiting_start;
 
        irq_forced_delay = 0;
        irq_forced = 0;
@@ -14312,7 +14479,7 @@ void custom_reset(bool hardreset, bool keyboardreset)
                CLXCON(-1, 0);
                CLXCON2(-1, 0);
                setup_fmodes(0, bplcon0);
-               beamcon0 = new_beamcon0 = beamcon0_previous = beamcon0_saved = currprefs.ntscmode ? 0x00 : BEAMCON0_PAL;
+               beamcon0 = new_beamcon0 = beamcon0_saved = currprefs.ntscmode ? 0x00 : BEAMCON0_PAL;
                blt_info.blit_main = 0;
                blt_info.blit_finald = 0;
                blt_info.blit_pending = 0;
@@ -14995,28 +15162,28 @@ static int REGPARAM2 custom_wput_1 (int hpos, uaecptr addr, uae_u32 value, int n
        case 0x1DC: BEAMCON0(hpos, value); break;
        case 0x1C0:
                if (htotal != value) {
-                       sync_color_changes(hpos);
+                       sync_changes(hpos);
                        htotal = value & (MAXHPOS_ROWS - 1);
                        varsync(addr, 1);
                }
                break;
        case 0x1C2:
                if (hsstop != value) {
-                       sync_color_changes(hpos);
+                       sync_changes(hpos);
                        hsstop = value & (MAXHPOS_ROWS - 1);
                        varsync(addr, 1);
                }
                break;
        case 0x1C4:
                if (hbstrt != value) {
-                       sync_color_changes(hpos);
+                       sync_changes(hpos);
                        hbstrt = value & 0x7ff;
                        varsync(addr, 0);
                }
                break;
        case 0x1C6:
                if (hbstop != value) {
-                       sync_color_changes(hpos);
+                       sync_changes(hpos);
                        hbstop = value & 0x7ff;
                        varsync(addr, 0);
                }
@@ -15029,42 +15196,42 @@ static int REGPARAM2 custom_wput_1 (int hpos, uaecptr addr, uae_u32 value, int n
                break;
        case 0x1CA:
                if (vsstop != value) {
-                       sync_color_changes(hpos);
+                       sync_changes(hpos);
                        vsstop = value & (MAXVPOS_LINES_ECS - 1);
                        varsync(addr, 1);
                }
                break;
        case 0x1CC:
                if (vbstrt != value) {
-                       sync_color_changes(hpos);
+                       sync_changes(hpos);
                        vbstrt = value & (MAXVPOS_LINES_ECS - 1);
                        varsync(addr, 0);
                }
                break;
        case 0x1CE:
                if (vbstop != value) {
-                       sync_color_changes(hpos);
+                       sync_changes(hpos);
                        vbstop = value & (MAXVPOS_LINES_ECS - 1);
                        varsync(addr, 0);
                }
                break;
        case 0x1DE:
                if (hsstrt != value) {
-                       sync_color_changes(hpos);
+                       sync_changes(hpos);
                        hsstrt = value & (MAXHPOS_ROWS - 1);
                        varsync(addr, 1);
                }
                break;
        case 0x1E0:
                if (vsstrt != value) {
-                       sync_color_changes(hpos);
+                       sync_changes(hpos);
                        vsstrt = value & (MAXVPOS_LINES_ECS - 1);
                        varsync(addr, 1);
                }
                break;
        case 0x1E2:
                if (hcenter != value) {
-                       sync_color_changes(hpos);
+                       sync_changes(hpos);
                        hcenter = value & (MAXHPOS_ROWS - 1);
                        varsync(addr, 0);
                }
@@ -16040,8 +16207,6 @@ void check_prefs_changed_custom(void)
        currprefs.cs_deniserev = changed_prefs.cs_deniserev;
        currprefs.cs_mbdmac = changed_prefs.cs_mbdmac;
        currprefs.cs_df0idhw = changed_prefs.cs_df0idhw;
-       currprefs.cs_denisemodel = changed_prefs.cs_denisemodel;
-       currprefs.cs_agnusmodel = changed_prefs.cs_agnusmodel;
        currprefs.cs_agnussize = changed_prefs.cs_agnussize;
        currprefs.cs_z3autoconfig = changed_prefs.cs_z3autoconfig;
        currprefs.cs_bytecustomwritebug = changed_prefs.cs_bytecustomwritebug;
@@ -16058,6 +16223,8 @@ void check_prefs_changed_custom(void)
        if (currprefs.chipset_mask != changed_prefs.chipset_mask ||
                currprefs.picasso96_nocustom != changed_prefs.picasso96_nocustom ||
                currprefs.ntscmode != changed_prefs.ntscmode ||
+               currprefs.cs_agnusmodel != changed_prefs.cs_agnusmodel ||
+               currprefs.cs_denisemodel != changed_prefs.cs_denisemodel ||
                currprefs.cs_hvcsync != changed_prefs.cs_hvcsync
                ) {
                        currprefs.picasso96_nocustom = changed_prefs.picasso96_nocustom;
@@ -16069,7 +16236,7 @@ void check_prefs_changed_custom(void)
                                new_beamcon0 = beamcon0_saved;
                        } else if (!(changed_prefs.chipset_mask & CSMASK_ECS_AGNUS) && (currprefs.chipset_mask & CSMASK_ECS_AGNUS)) {
                                beamcon0_saved = beamcon0;
-                               beamcon0 = new_beamcon0 = beamcon0_previous = currprefs.ntscmode ? 0x00 : BEAMCON0_PAL;
+                               beamcon0 = new_beamcon0 = currprefs.ntscmode ? 0x00 : BEAMCON0_PAL;
                                diwhigh = 0;
                                diwhigh_written = 0;
                                bplcon0 &= ~(0x10 | 0x01);
@@ -16081,7 +16248,6 @@ void check_prefs_changed_custom(void)
                        }
                        currprefs.chipset_mask = changed_prefs.chipset_mask;
                        currprefs.cs_agnusmodel = changed_prefs.cs_agnusmodel;
-                       currprefs.cs_agnussize = changed_prefs.cs_agnussize;
                        currprefs.cs_denisemodel = changed_prefs.cs_denisemodel;
                        currprefs.cs_hvcsync = changed_prefs.cs_hvcsync;
                        init_custom();
index ce5c3219ea7d338c2292fa39d8b3325b5a3d621e..8681f7f4db2398405fabe0e3aa3bf12532ee84f4 100644 (file)
--- a/debug.cpp
+++ b/debug.cpp
@@ -235,7 +235,8 @@ static const TCHAR help[] = {
        _T("  dj [<level bitmask>]  Enable joystick/mouse input debugging.\n")
        _T("  smc [<0-1>]           Enable self-modifying code detector. 1 = enable break.\n")
        _T("  dm                    Dump current address space map.\n")
-       _T("  v <vpos> [<hpos>]     Show DMA data (accurate only in cycle-exact mode).\n")
+       _T("  v <vpos> [<hpos>] [<lines>]\n")
+       _T("                        Show DMA data (accurate only in cycle-exact mode).\n")
        _T("                        v [-1 to -4] = enable visual DMA debugger.\n")
        _T("  vh [<ratio> <lines>]  \"Heat map\"\n")
        _T("  I <custom event>      Send custom event string\n")
@@ -2234,6 +2235,7 @@ void record_dma_read_value(uae_u32 v)
                last_dma_rec->size = 2;
        }
 }
+
 void record_dma_read_value_wide(uae_u64 v, bool quad)
 {
        if (last_dma_rec) {
@@ -2245,6 +2247,7 @@ void record_dma_read_value_wide(uae_u64 v, bool quad)
                last_dma_rec->size = quad ? 8 : 4;
        }
 }
+
 bool record_dma_check(int hpos, int vpos)
 {
        if (!dma_record[0]) {
@@ -2257,6 +2260,20 @@ bool record_dma_check(int hpos, int vpos)
        struct dma_rec *dr = &dma_record[dma_record_toggle][vpos * NR_DMA_REC_HPOS + hpos];
        return dr->reg != 0xffff;
 }
+
+void record_dma_denise(int hpos, int dhpos)
+{
+       if (!dma_record[0]) {
+               return;
+       }
+       hpos += dma_record_hoffset;
+       if (hpos >= NR_DMA_REC_HPOS || vpos >= NR_DMA_REC_VPOS) {
+               return;
+       }
+       struct dma_rec *dr = &dma_record[dma_record_toggle][vpos * NR_DMA_REC_HPOS + hpos];
+       dr->dhpos = dhpos;
+}
+
 void record_dma_clear(int hpos, int vpos)
 {
        if (!dma_record[0]) {
@@ -2362,6 +2379,7 @@ static bool get_record_dma_info(struct dma_rec *drs, struct dma_rec *dr, TCHAR *
                l6[0] = 0;
 
        int hpos = dr->hpos;
+       int dhpos = dr->dhpos;
        if (hpos < 0) {
                struct dma_rec *dr2 = dr;
                int cnt = 0;
@@ -2466,7 +2484,7 @@ static bool get_record_dma_info(struct dma_rec *drs, struct dma_rec *dr, TCHAR *
                }
        }
        if (ipl >= 0) {
-               _stprintf(l1, _T("[%02X     %d]"), hpos, ipl);
+               _stprintf(l1, _T("[%02X %03X %d]"), hpos, dhpos, ipl);
        } else if (ipl == -2) {
                _stprintf(l1, _T("[%02X     -]"), hpos);
        } else {
@@ -2670,7 +2688,7 @@ static bool get_record_dma_info(struct dma_rec *drs, struct dma_rec *dr, TCHAR *
 
 
 
-static void decode_dma_record(int hpos, int vpos, int toggle, bool logfile)
+static void decode_dma_record(int hpos, int vpos, int count, int toggle, bool logfile)
 {
        struct dma_rec *dr, *dr_start;
        int h, i, maxh = 0;
@@ -2783,6 +2801,12 @@ static void decode_dma_record(int hpos, int vpos, int toggle, bool logfile)
                        console_out_f(_T("%s\n"), l6);
                        console_out_f(_T("\n"));
                }
+               if (count > 0) {
+                       count--;
+                       if (!count) {
+                               break;
+                       }
+               }
        }
        if (logfile)
                flush_log();
@@ -2794,7 +2818,7 @@ void log_dma_record (void)
                return;
        if (!debug_dma)
                return;
-       decode_dma_record (0, 0, 0, true);
+       decode_dma_record (0, 0, 0, 0, true);
 }
 
 static void init_record_copper(void)
@@ -6950,7 +6974,7 @@ static bool debug_line (TCHAR *input)
                case 'v':
                case 'V':
                        {
-                               int v1 = vpos, v2 = 0;
+                               int v1 = vpos, v2 = 0, v3 = 0;
                                if (*inptr == 'h') {
                                        inptr++;
                                        if (more_params(&inptr) && *inptr == '?') {
@@ -7036,19 +7060,21 @@ static bool debug_line (TCHAR *input)
                                                if (nextcmd == 'l') {
                                                        next_char(&inptr);
                                                }
-                                               if (more_params (&inptr))
-                                                       v1 = readint (&inptr, NULL);
-                                               if (more_params (&inptr))
-                                                       v2 = readint (&inptr, NULL);
+                                               if (more_params(&inptr))
+                                                       v1 = readint(&inptr, NULL);
+                                               if (more_params(&inptr))
+                                                       v2 = readint(&inptr, NULL);
+                                               if (more_params(&inptr))
+                                                       v3 = readint(&inptr, NULL);
                                                if (debug_dma && v1 >= 0 && v2 >= 0) {
-                                                       decode_dma_record (v2, v1, cmd == 'v', nextcmd == 'l');
+                                                       decode_dma_record(v2, v1, v3, cmd == 'v', nextcmd == 'l');
                                                } else {
                                                        if (debug_dma) {
                                                                record_dma_reset(0);
                                                                reset_drawing();
                                                        }
                                                        debug_dma = v1 < 0 ? -v1 : 1;
-                                                       console_out_f (_T("DMA debugger enabled, mode=%d.\n"), debug_dma);
+                                                       console_out_f(_T("DMA debugger enabled, mode=%d.\n"), debug_dma);
                                                }
                                        }
                                }
index 59cda0eee262f496563acdf94e6489862e25fd94..128a637118627ddcc0614d1d15a5410f052c52ad 100644 (file)
@@ -262,6 +262,7 @@ static int hblank_left_start, hblank_right_stop;
 static int hblank_left_start_hard, hblank_right_stop_hard;
 static bool extborder, exthblanken, exthblankon;
 static int exthblank;
+static bool exthblank_force;
 static int exthblank_set;
 static bool ehb_enable;
 static bool syncdebug;
@@ -595,7 +596,7 @@ int get_vertical_visible_height(bool useoldsize)
        int vbstrt, vbstop;
 
        if (programmedmode <= 1) {
-               h = maxvpos_display + maxvpos_display_vsync - minfirstline;
+               h = maxvsize_display;
                if (useoldsize) {
                        // 288/576 or 243/486
                        if (h == 288 || h == 243) {
@@ -1082,7 +1083,9 @@ static int sprite_playfield_start, sprite_end;
 static int may_require_hard_way;
 static int linetoscr_diw_start, linetoscr_diw_end;
 static int native_ddf_left, native_ddf_right;
+#if 0
 static int hamleftborderhidden;
+#endif
 
 static int pixels_offset;
 static int src_pixel;
@@ -1110,7 +1113,7 @@ static xcolnr getbgc(int blank)
        //return colors_for_drawing.acolors[0];
        return xcolors[0xf0f];
 #endif
-       if (exthblank > 0) {
+       if (exthblank > 0 || exthblank_force) {
                return fullblack;
        }
        bool extblken = ce_is_extblankset(colors_for_drawing.extra);
@@ -1160,7 +1163,6 @@ static void pfield_init_linetoscr (bool border)
        /* First, get data fetch start/stop in DIW coordinates.  */
        int ddf_left = dp_for_drawing->plfleft + DIW_DDF_OFFSET - DDF_OFFSET;
        int ddf_right = dp_for_drawing->plfright + DIW_DDF_OFFSET - DDF_OFFSET;
-       int leftborderhidden;
        int native_ddf_left2;
        bool expanded = false;
 
@@ -1188,10 +1190,6 @@ static void pfield_init_linetoscr (bool border)
        if (linetoscr_diw_start < 0) {
                linetoscr_diw_start = 0;
        }
-       // OCS Denise shows only background until hpos 95.
-       if (!ecs_denise && linetoscr_diw_start < shres_coord_hw_to_window_x(95 << 2)) {
-               linetoscr_diw_start = shres_coord_hw_to_window_x(95 << 2);
-       }
        /* Perverse cases happen. */
        if (linetoscr_diw_end < linetoscr_diw_start)
                linetoscr_diw_end = linetoscr_diw_start;
@@ -1364,13 +1362,15 @@ static void pfield_init_linetoscr (bool border)
        ddf_left <<= bplres;
        pixels_offset = MAX_PIXELS_PER_LINE - ddf_left;
 
-       leftborderhidden = playfield_start - native_ddf_left2;
-       hamleftborderhidden = 0;
+       int leftborderhidden = playfield_start - native_ddf_left2;
 
+#if 0
+       hamleftborderhidden = 0;
        if (hblank_left_start > playfield_start) {
                leftborderhidden += hblank_left_start - playfield_start;
                hamleftborderhidden = hblank_left_start - playfield_start;
        }
+#endif
 
        src_pixel = MAX_PIXELS_PER_LINE + res_shift_from_window(leftborderhidden);
 
@@ -1698,7 +1698,7 @@ static void fill_line2(int startpos, int len)
        }
 }
 
-static void fill_line_border(int lineno)
+static void fill_line_border(int lineno, int bordertype)
 {
        struct vidbuf_description *vidinfo = &adisplays[0].gfxvidinfo;
        int lastpos = visible_left_border;
@@ -1712,7 +1712,7 @@ static void fill_line_border(int lineno)
                int b = hposblank;
                hposblank = 3;
                fill_line2(lastpos, w);
-               if (syncdebug) {
+               if (syncdebug && bordertype >= 0) {
                        pfield_do_darken_line(lastpos, endpos, lineno);
                }
                if (need_genlock_data) {
@@ -1726,7 +1726,7 @@ static void fill_line_border(int lineno)
        if (hposblank) {
                hposblank = 3;
                fill_line2(lastpos, w);
-               if (syncdebug) {
+               if (syncdebug && bordertype >= 0) {
                        pfield_do_darken_line(lastpos, endpos, lineno);
                }
                if (need_genlock_data) {
@@ -1769,7 +1769,7 @@ static uae_u8 render_sprites(int pos, int dualpf, uae_u8 apixel, int aga)
        int *shift_lookup = dualpf ? (bpldualpfpri ? dblpf_ms2 : dblpf_ms1) : dblpf_ms;
        int maskshift, plfmask;
 
-       if (exthblank) {
+       if (exthblank || exthblank_force) {
                return 0;
        }
        if (extborder && (ce_is_borderblank(colors_for_drawing.extra) || !ce_is_bordersprite(colors_for_drawing.extra))) {
@@ -1869,7 +1869,7 @@ static uae_u8 sh_render_sprites(int pos, int dualpf, uae_u8 apixel, int aga)
        int *shift_lookup = dualpf ? (bpldualpfpri ? dblpf_ms2 : dblpf_ms1) : dblpf_ms;
        int maskshift, plfmask;
 
-       if (exthblank) {
+       if (exthblank || exthblank_force) {
                return 0;
        }
        if (extborder && ce_is_borderblank(colors_for_drawing.extra)) {
@@ -2257,7 +2257,7 @@ static call_linetoscrb pfield_do_linetoscr_spriteonly;
 static void pfield_do_linetoscr(int start, int stop, int blank)
 {
        int pixel = pfield_do_linetoscr_normal(src_pixel, start, stop);
-       if (exthblank) {
+       if (exthblank || exthblank_force) {
                pfield_do_fill_line(start, stop, 1);
        } else if (extborder) {
 #if EXTBORDER_BLANK
@@ -2279,10 +2279,10 @@ static void pfield_do_linetoscr_spr(int start, int stop, int blank)
                bool bb = ce_is_borderblank(colors_for_drawing.extra);
 #endif
                pixel = pfield_do_linetoscr_sprite(src_pixel, start, stop);
-               pfield_do_fill_line(start, stop, bb || exthblank > 0);
+               pfield_do_fill_line(start, stop, bb || exthblank > 0 || exthblank_force);
        } else {
                pixel = pfield_do_linetoscr_sprite(src_pixel, start, stop);
-               if (exthblank) {
+               if (exthblank || exthblank_force) {
                        pfield_do_fill_line(start, stop, 1);
                }
        }
@@ -2667,7 +2667,7 @@ static void pfield_set_linetoscr (void)
 // A1000 Denise right border bug: sprites have 1 extra lores pixel visible
 static void pfield_do_linetoscr_bordersprite_a1000(int start, int stop, int blank)
 {
-       if (blank || exthblank > 0 || extborder) {
+       if (blank || exthblank > 0 || exthblank_force || extborder) {
                pfield_do_fill_line(start, stop, blank);
                return;
        }
@@ -2687,7 +2687,7 @@ static void pfield_do_linetoscr_bordersprite_a1000(int start, int stop, int blan
 // left or right AGA border sprite
 static void pfield_do_linetoscr_bordersprite_aga(int start, int stop, int blank)
 {
-       if (blank || exthblank > 0 || extborder) {
+       if (blank || exthblank > 0 || exthblank_force || extborder) {
                pfield_do_fill_line(start, stop, blank);
                return;
        }
@@ -2772,7 +2772,10 @@ static void init_ham_decoding(void)
 {
        int unpainted_amiga = unpainted;
 
-       ham_decode_pixel = src_pixel - hamleftborderhidden;
+       ham_decode_pixel = src_pixel;
+#if 0
+       ham_decode_pixel = -hamleftborderhidden;
+#endif
        ham_lastcolor = color_reg_get(&colors_for_drawing, 0);
        while (unpainted_amiga-- > 0) {
                decode_ham_pixel(ham_decode_pixel++);
@@ -3146,6 +3149,7 @@ static void NOINLINE pfield_doline64_n8(uae_u64 *data, int count, uae_u8* real_b
 static void pfield_doline(int lineno)
 {
        uae_u8 *real_bplpt[8];
+       int offset = 0; // currprefs.chipset_hr ? 8 : 0;
 
 #if 0
        int wordcount = (dp_for_drawing->plflinelen + 1) / 2;
@@ -3181,7 +3185,7 @@ static void pfield_doline(int lineno)
        int wordcount = dp_for_drawing->plflinelen;
        uae_u32 *data = pixdata.apixels_l + MAX_PIXELS_PER_LINE / sizeof(uae_u32);
 
-#define DATA_POINTER(n) ((debug_bpl_mask & (1 << n)) ? (line_data[lineno] + (n) * MAX_WORDS_PER_LINE * 2) : (debug_bpl_mask_one ? all_ones : all_zeros))
+#define DATA_POINTER(n) ((debug_bpl_mask & (1 << n)) ? (line_data[lineno] + (n) * MAX_WORDS_PER_LINE * 2 + offset) : (debug_bpl_mask_one ? all_ones : all_zeros))
        real_bplpt[0] = DATA_POINTER(0);
        real_bplpt[1] = DATA_POINTER(1);
        real_bplpt[2] = DATA_POINTER(2);
@@ -3525,6 +3529,15 @@ static void pfield_expand_dp_bplconx (int regno, int v, int hp, int vp)
                        exthblank = 0;
                }
                return;
+       case 0x208: // forced hblank
+               if (v) {
+                       exthblanken = true;
+                       exthblankon = true;
+               } else {
+                       exthblanken = false;
+                       exthblank = 0;
+               }
+               return;
        case 0x202: // hsync (debug)
                hsync_debug = v;
                return;
@@ -3657,6 +3670,10 @@ static void do_color_changes(line_draw_func worker_border, line_draw_func worker
                                if (nextpos_in_range > lastpos && lastpos < hblank_left) {
                                        int t = nextpos_in_range <= hblank_left ? nextpos_in_range : hblank_left;
                                        (*worker_border)(lastpos, t, 1);
+                                       // if playfield starts before hblank end: adjust back to playfield start
+                                       if (t > playfield_start) {
+                                               t = playfield_start;
+                                       }
                                        lastpos = t;
                                }
 
@@ -3684,6 +3701,10 @@ static void do_color_changes(line_draw_func worker_border, line_draw_func worker
                                                } else {
                                                        (*worker_pfield)(lastpos, t, 0);
                                                }
+                                               // playfield started inside hblank? Overwrite it with blank.
+                                               if (playfield_start < hblank_left) {
+                                                       (*worker_border)(playfield_start, hblank_left, 1);
+                                               }
                                                lastpos = t;
                                        }
 
@@ -3756,10 +3777,18 @@ static void do_color_changes(line_draw_func worker_border, line_draw_func worker
                                colors_for_drawing.acolors[regno] = getxcolor(value);
                        } else if (regno == 0 && (value & COLOR_CHANGE_MASK)) {
                                if ((value & COLOR_CHANGE_MASK) == COLOR_CHANGE_ACTBORDER) {
-                                       if (value & 1) {
-                                               extborder = true;
+                                       if (value & 2) {
+                                               if (value & 1) {
+                                                       exthblank_force = true;
+                                               } else {
+                                                       exthblank_force = false;
+                                               }
                                        } else {
-                                               extborder = false;
+                                               if (value & 1) {
+                                                       extborder = true;
+                                               } else {
+                                                       extborder = false;
+                                               }
                                        }
                                } else if (value & COLOR_CHANGE_BLANK) {
                                        if (value & 1) {
@@ -3992,18 +4021,18 @@ static void pfield_draw_line(struct vidbuffer *vb, int lineno, int gfx_ypos, int
                                // blanked border line
                                int tmp = hposblank;
                                hposblank = 1;
-                               fill_line_border(lineno);
+                               fill_line_border(lineno, border);
                                hposblank = tmp;
                        } else {
                                // normal border line
-                               fill_line_border(lineno);
+                               fill_line_border(lineno, border);
                        }
 
                        if (do_double) {
                                if (dh == dh_buf) {
                                        xlinebuffer = row_map[follow_ypos] - linetoscr_x_adjust_pixbytes;
                                        xlinebuffer_genlock = row_map_genlock[follow_ypos] - linetoscr_x_adjust_pixels;
-                                       fill_line_border(lineno);
+                                       fill_line_border(lineno, border);
                                }
                                /* If dh == dh_line, do_flush_line will re-use the rendered line
                                * from linemem.  */
@@ -4047,7 +4076,7 @@ static void pfield_draw_line(struct vidbuffer *vb, int lineno, int gfx_ypos, int
                // top or bottom blanking region
                int tmp = hposblank;
                hposblank = 1;
-               fill_line_border(lineno);
+               fill_line_border(lineno, border);
                hposblank = tmp;
 
        }
@@ -5316,6 +5345,7 @@ void reset_drawing(void)
        max_diwstop = 0;
        vb_state = 0;
        exthblank = 0;
+       exthblank_force = false;
        exthblank_set = syncdebug ? -1 : 1;
        exthblanken = false;
        exthblankon = false;
index 6503c55c0c22fc2ce0e4a216d47a6a8e6cf94a2b..92bbc8f8d9abec1a108b7c006b77ba7f8ebc1c34 100644 (file)
@@ -360,7 +360,16 @@ void MISC_handler(void)
        recursive--;
 }
 
-void event2_newevent_xx (int no, evt_t t, uae_u32 data, evfunc2 func)
+void event2_newevent_xx_ce(evt_t t, uae_u32 data, evfunc2 func)
+{
+       if (!currprefs.cpu_memory_cycle_exact) {
+               func(data);
+               return;
+       }
+       event2_newevent_xx(-1, t, data, func);
+}
+
+void event2_newevent_xx(int no, evt_t t, uae_u32 data, evfunc2 func)
 {
        evt_t et;
        static int next = ev2_misc;
index f6a7f558ca40b06d4fc314547dc5b1ad8abef516..16dca1b02a531e03a2513bdd0a422a286dc5a5d8 100644 (file)
@@ -143,14 +143,15 @@ extern uae_u16 INTREQR(void);
 #define VSYNC_ENDLINE_PAL 5
 #define VSYNC_ENDLINE_NTSC 6
 #define EQU_ENDLINE_PAL 8
-#define EQU_ENDLINE_NTSC 10
+#define EQU_ENDLINE_NTSC 9
 
-#define OCS_DENISE_HBLANK_DISABLE_HPOS 0x2d
+#define OCS_DENISE_HBLANK_DISABLE_HPOS 0x2e
 
 extern int maxhpos, maxhposm0, maxhpos_short;
 extern int maxvpos, maxvpos_nom, maxvpos_display, maxvpos_display_vsync, maxhpos_display;
+extern int maxvsize_display;
 extern int hsyncstartpos_hw, hsyncendpos_hw;
-extern int minfirstline, vblank_endline, numscrlines;
+extern int minfirstline, minfirstline_linear, vblank_endline, numscrlines;
 extern float vblank_hz, fake_vblank_hz;
 extern float hblank_hz;
 extern int vblank_skip, doublescan;
index 9121e99f6636ed957ad1b71021705ba6622d0557..ccf355748472c4f2b93174734aa4cc1794b51189 100644 (file)
@@ -226,6 +226,7 @@ extern struct peekdma peekdma_data;
 struct dma_rec
 {
        int hpos, vpos;
+       int dhpos;
     uae_u16 reg;
     uae_u64 dat;
        uae_u16 size;
@@ -312,6 +313,7 @@ extern void record_dma_reoffset(int, int, int);
 extern void record_cia_access(int r, int mask, uae_u16 value, bool rw, int hpos, int vpos, int phase);
 extern void record_dma_ipl(int hpos, int vpos);
 extern void record_dma_ipl_sample(int hpos, int vpos);
+extern void record_dma_denise(int pos, int dhpos);
 extern void debug_mark_refreshed(uaecptr);
 extern void debug_draw(uae_u8 *buf, int bpp, int line, int width, int height, uae_u32 *xredcolors, uae_u32 *xgreencolors, uae_u32 *xbluescolors);
 
index dbdd1fcc0a18884be02716559dfba0c897a2c1a8..1b0db893c95acfbf4775a3e0b5003b4bd6e55eb2 100644 (file)
@@ -89,7 +89,7 @@ STATIC_INLINE int PIXEL_XPOS(int xx)
        return x;
 }
 
-#define min_diwlastword (0)
+#define min_diwlastword (PIXEL_XPOS(hsyncstartpos_start_cycles << CCK_SHRES_SHIFT))
 #define max_diwlastword (PIXEL_XPOS(denisehtotal))
 
 STATIC_INLINE int coord_window_to_hw_x(int x)
index de3c8a81e73e96d26b59192842a0704c1e97e60d..cc04dfb6ed708539dc3c2f7bbc818a35ed6f6921 100644 (file)
@@ -137,6 +137,7 @@ extern void event2_newevent_xx(int no, evt_t t, uae_u32 data, evfunc2 func);
 extern void event2_newevent_x_replace(evt_t t, uae_u32 data, evfunc2 func);
 extern void event2_newevent_x_replace_exists(evt_t t, uae_u32 data, evfunc2 func);
 extern void event2_newevent_x_remove(evfunc2 func);
+extern void event2_newevent_xx_ce(evt_t t, uae_u32 data, evfunc2 func);
 
 STATIC_INLINE void event2_newevent_x(int no, evt_t t, uae_u32 data, evfunc2 func)
 {