]> git.unchartedbackwaters.co.uk Git - francis/winuae.git/commitdiff
Custom chipset WIP updates.
authorToni Wilen <twilen@winuae.net>
Sun, 29 Aug 2021 16:59:16 +0000 (19:59 +0300)
committerToni Wilen <twilen@winuae.net>
Sun, 29 Aug 2021 16:59:16 +0000 (19:59 +0300)
blitter.cpp
custom.cpp
debug.cpp
drawing.cpp
identify.cpp
include/custom.h
include/debug.h
include/drawing.h
include/events.h

index 3a058259f7fb7ad34d209279d8ed55c8cd7b893a..c97256318d288d6404a5e5aa3d3bed559fec24c3 100644 (file)
@@ -394,12 +394,12 @@ static void check_channel_mods(int hpos, int ch, uaecptr *pt)
        if (bltptxpos != hpos)
                return;
        if (ch == bltptxc) {
-               bltptxpos = -1;
-               *pt = bltptx;
                if (blit_warned > 0) {
                        write_log(_T("BLITTER: %08X -> %08X write to %cPT ignored! %08x\n"), bltptx, *pt, ch + 'A' - 1, m68k_getpc());
                        blit_warned--;
                }
+               bltptxpos = -1;
+               *pt = bltptx;
        }
 }
 
@@ -913,6 +913,7 @@ static void blit_bltset(int con)
                blit_changed = true;
                if (blit_warned > 0) {
                        write_log(_T("BLITTER: BLTCON0 %04x -> %04x BLTCON1 %04x -> %04x PC=%08x (%d %d)\n"), bltcon0_old, bltcon0, bltcon1_old, bltcon1, M68K_GETPC, current_hpos(), vpos);
+                       blitter_dump();
                        blitshifterdebug(bltcon0_old, false);
                        blit_warned--;
                        //activate_debugger();
index 50e2244580b68b1aeff28c09a29a6d664cf4bc86..93adae57dcf3b19f2a7096ab9865cbc82b0a3225 100644 (file)
@@ -51,7 +51,6 @@
 #define CYCLE_CONFLICT_LOGGING 0
 
 #define SPEEDUP 1
-
 #define CUSTOM_DEBUG 0
 #define SPRITE_DEBUG 0
 #define SPRITE_DEBUG_MINY 0
@@ -72,7 +71,7 @@
 #define EXTRAWIDTH_BROADCAST 15
 #define EXTRAHEIGHT_BROADCAST_TOP 0
 #define EXTRAHEIGHT_BROADCAST_BOTTOM 0
-#define EXTRAWIDTH_EXTREME 31
+#define EXTRAWIDTH_EXTREME 33
 #define EXTRAHEIGHT_EXTREME 24
 
 #define LORES_TO_SHRES_SHIFT 2
@@ -326,14 +325,15 @@ static uae_u16 bplcon3_saved, bplcon4_saved;
 static int varsync_changed;
 uae_u16 vtotal, htotal;
 static int maxvpos_stored, maxhpos_stored;
-uae_u16 hsstop, hsstrt;
+uae_u16 hsstop, hsstop_detect, hsstrt;
 static uae_u16 hbstop, hbstrt;
 static uae_u16 vsstop, vsstrt;
-static uae_u16 vbstop, vbstrt;
-static uae_u16 hcenter;
+static uae_u16 vbstop, vbstopm1, vbstrt;
+static uae_u16 hcenter, hcenter_v2, hcenter_v2_end;
 static uae_u16 hbstop_v, hbstrt_v, hbstop_v2, hbstrt_v2, hbstrt_v2o, hbstop_v2o;
 static int vsstrt_m, vsstop_m, vbstrt_m, vbstop_m;
-static bool vs_state, vb_state, vb_end_line;
+static bool vb_state, vb_end_line;
+static bool vs_state, vs_state_on, vs_state_hw;
 static bool vb_end_next_line;
 static int vb_start_line;
 static bool ocs_blanked;
@@ -358,6 +358,7 @@ struct sprite {
        int dmastate;
        int dmacycle;
        int width;
+       bool ecs_denise_hires;
 
        uae_u16 ctl, pos;
 #ifdef AGA
@@ -369,7 +370,6 @@ struct sprite {
 
 static struct sprite spr[MAX_SPRITES];
 static int plfstrt_sprite;
-
 uaecptr sprite_0;
 int sprite_0_width, sprite_0_height, sprite_0_doubled;
 uae_u32 sprite_0_colors[4];
@@ -413,7 +413,7 @@ enum diw_states
 
 static int plffirstline, plflastline;
 int plffirstline_total, plflastline_total;
-int vblank_firstline_hw, vblank_lastline_hw;
+int vblank_firstline_hw;
 static int autoscale_bordercolors;
 static int plfstrt, plfstop;
 static int sprite_minx;
@@ -429,6 +429,8 @@ static int diwstate_vpos;
 static int bpl_hstart;
 static bool exthblank, exthblank_state;
 static int last_diw_hpos, last_diw_hpos2;
+static int last_recorded_diw_hpos;
+static int last_hblank_start;
 
 int first_planes_vpos, last_planes_vpos;
 static int first_bplcon0, first_bplcon0_old;
@@ -535,6 +537,7 @@ static int bprun;
 static int bprun_cycle;
 static int bprun_pipeline_flush_delay;
 static bool plane0, plane0p, plane0p_enabled, plane0p_forced, plane0_first_done;
+static int last_bpl1dat_hpos;
 static bool harddis_v, harddis_h;
 static uae_u16 dmal_alloc_mask;
 
@@ -609,6 +612,19 @@ STATIC_INLINE int nodraw(void)
        return !currprefs.cpu_memory_cycle_exact && ad->framecnt != 0;
 }
 
+STATIC_INLINE int diw_to_hpos(int diw)
+{
+       diw /= 4;
+       diw += DDF_OFFSET;
+       diw /= 2;
+       return diw;
+}
+
+STATIC_INLINE int hpos_to_diw(int pos)
+{
+       return ((pos + hpos_hsync_extra) * 2 - DDF_OFFSET) * 4;
+}
+
 static int doflickerfix(void)
 {
        return currprefs.gfx_vresolution && doublescan < 0 && vpos < MAXVPOS;
@@ -646,17 +662,26 @@ static void setclr(uae_u16 *p, uae_u16 val)
        }
 }
 
-static void adjust_hr(uae_u16 *vp)
+static int adjust_hr(int v)
 {
-       uae_u16 v = *vp;
        if (currprefs.chipset_hr) {
                v &= ~(3 >> currprefs.gfx_resolution);
        } else {
                v &= ~3;
        }
-       *vp = v;
+       return v;
+}
+static int adjust_hr2(int v)
+{
+       if (currprefs.chipset_hr) {
+               v &= ~(1 >> currprefs.gfx_resolution);
+       } else {
+               v &= ~1;
+       }
+       return v;
 }
 
+
 static void alloc_cycle(int hpos, int type)
 {
 #ifdef CPUEMU_13
@@ -837,14 +862,15 @@ static void hblank_reset(int hblankpos)
        if (thisline_decision.plfleft < 0) {
                return;
        }
-       hb_last_diwlastword = coord_diw_shres_to_window_x(hblankpos);
+       // border re-enable takes 1 lores pixel
+       hb_last_diwlastword = hblankpos + 4;
        SET_LINE_CYCLEBASED;
 }
 
 static void record_color_change2(int hpos, int regno, uae_u32 value)
 {
        color_change *cc;
-       int pos = hpos < 0 ? -hpos : ((hpos + hpos_hsync_extra) * 2 - DDF_OFFSET) * 4;
+       int pos = hpos < 0 ? -hpos : hpos_to_diw(hpos);
 
        if (scandoubled_line) {
                return;
@@ -878,13 +904,46 @@ static void record_color_change2(int hpos, int regno, uae_u32 value)
                }
        }
 
+       // HCENTER blanking
+       if (hcenter_v2 && vs_state_on && vpos < maxvpos_display_vsync && lof_current) {
+               int chpos = pos;
+               if (hcenter_v2_end == 0xffff && hcenter_v2 < chpos && hcenter_v2 >= last_recorded_diw_hpos) {
+                       cc = &curr_color_changes[next_color_change];
+                       cc->linepos = hcenter_v2;
+                       cc->regno = RECORDED_REGISTER_CHANGE_OFFSET + 0x200;
+                       cc->value = 1;
+                       next_color_change++;
+                       cc[1].regno = -1;
+                       last_recorded_diw_hpos = cc->linepos;
+                       hcenter_v2_end = hcenter_v2;
+                       hcenter_v2_end += ((beamcon0 & 0x20) ? 8 : 9) << CCK_SHRES_SHIFT;
+                       if (hcenter_v2_end >= maxhpos << CCK_SHRES_SHIFT) {
+                               hcenter_v2_end -= maxhpos << CCK_SHRES_SHIFT;
+                       }
+                       if (debug_dma) {
+                               record_dma_event(DMA_EVENT_HBS, diw_to_hpos(cc->linepos), vpos);
+                       }
+               }
+               if (!exthblank_state && hcenter_v2_end < chpos && hcenter_v2_end >= last_recorded_diw_hpos) {
+                       cc = &curr_color_changes[next_color_change];
+                       cc->linepos = hcenter_v2_end;
+                       cc->regno = RECORDED_REGISTER_CHANGE_OFFSET + 0x200;
+                       cc->value = 0;
+                       next_color_change++;
+                       cc[1].regno = -1;
+                       last_recorded_diw_hpos = cc->linepos;
+                       hcenter_v2_end = 0xffff;
+                       if (debug_dma) {
+                               record_dma_event(DMA_EVENT_HBE, diw_to_hpos(cc->linepos), vpos);
+                       }
+               }
+       }
+
        if (exthblank) {
-               cc = &curr_color_changes[next_color_change];
-               int prevpos = last_color_change == next_color_change ? 0 : cc[-1].linepos;
                int chpos = pos;
                // inject programmed hblank start and end in color changes
-               if (hbstrt_v2 <= hbstop_v2) {
-                       if (chpos >= hbstrt_v2 && prevpos < hbstrt_v2) {
+               if (hbstrt_v2 < hbstop_v2) {
+                       if (hbstrt_v2 < chpos && hbstrt_v2 >= last_recorded_diw_hpos) {
                                cc = &curr_color_changes[next_color_change];
                                cc->linepos = hbstrt_v2;
                                cc->regno = RECORDED_REGISTER_CHANGE_OFFSET + 0x200;
@@ -893,8 +952,21 @@ static void record_color_change2(int hpos, int regno, uae_u32 value)
                                cc[1].regno = -1;
                                hblank_reset(hbstrt_v2);
                                exthblank_state = true;
+                               last_recorded_diw_hpos = cc->linepos;
+                               last_hblank_start = cc->linepos;
+                               if (debug_dma) {
+                                       record_dma_event(DMA_EVENT_HBS, diw_to_hpos(cc->linepos), vpos);
+                               }
                        }
-                       if (chpos >= hbstop_v2 && prevpos < hbstop_v2) {
+                       if (hbstop_v2 < chpos && hbstop_v2 >= last_recorded_diw_hpos) {
+                               // do_color_changes() HBLANK workaround
+                               if (next_color_change == last_color_change && exthblank_state) {
+                                       cc = &curr_color_changes[next_color_change];
+                                       cc->linepos = 0;
+                                       cc->regno = RECORDED_REGISTER_CHANGE_OFFSET + 0x200;
+                                       cc->value = 1;
+                                       next_color_change++;
+                               }
                                cc = &curr_color_changes[next_color_change];
                                cc->linepos = hbstop_v2;
                                cc->regno = RECORDED_REGISTER_CHANGE_OFFSET + 0x200;
@@ -902,9 +974,20 @@ static void record_color_change2(int hpos, int regno, uae_u32 value)
                                next_color_change++;
                                cc[1].regno = -1;
                                exthblank_state = false;
+                               last_recorded_diw_hpos = cc->linepos;
+                               if (debug_dma) {
+                                       record_dma_event(DMA_EVENT_HBE, diw_to_hpos(cc->linepos), vpos);
+                               }
                        }
-               } else {
-                       if (chpos >= hbstop_v2 && prevpos < hbstop_v2) {
+               } else  if (hbstrt_v2 > hbstop_v2) {
+                       if (hbstop_v2 < chpos && hbstop_v2 >= last_recorded_diw_hpos) {
+                               if (next_color_change == last_color_change && exthblank_state) {
+                                       cc = &curr_color_changes[next_color_change];
+                                       cc->linepos = 0;
+                                       cc->regno = RECORDED_REGISTER_CHANGE_OFFSET + 0x200;
+                                       cc->value = 1;
+                                       next_color_change++;
+                               }
                                cc = &curr_color_changes[next_color_change];
                                cc->linepos = hbstop_v2;
                                cc->regno = RECORDED_REGISTER_CHANGE_OFFSET + 0x200;
@@ -912,8 +995,12 @@ static void record_color_change2(int hpos, int regno, uae_u32 value)
                                next_color_change++;
                                cc[1].regno = -1;
                                exthblank_state = false;
+                               last_recorded_diw_hpos = cc->linepos;
+                               if (debug_dma) {
+                                       record_dma_event(DMA_EVENT_HBE, diw_to_hpos(cc->linepos), vpos);
+                               }
                        }
-                       if (chpos >= hbstrt_v2 && prevpos < hbstrt_v2) {
+                       if (hbstrt_v2 < chpos && hbstrt_v2 >= last_recorded_diw_hpos) {
                                cc = &curr_color_changes[next_color_change];
                                cc->linepos = hbstrt_v2;
                                cc->regno = RECORDED_REGISTER_CHANGE_OFFSET + 0x200;
@@ -922,6 +1009,11 @@ static void record_color_change2(int hpos, int regno, uae_u32 value)
                                cc[1].regno = -1;
                                hblank_reset(hbstrt_v2);
                                exthblank_state = true;
+                               last_recorded_diw_hpos = cc->linepos;
+                               last_hblank_start = cc->linepos;
+                               if (debug_dma) {
+                                       record_dma_event(DMA_EVENT_HBS, diw_to_hpos(cc->linepos), vpos);
+                               }
                        }
                }
        }
@@ -934,20 +1026,34 @@ static void record_color_change2(int hpos, int regno, uae_u32 value)
                next_color_change++;
                cc[1].regno = -1;
        }
+
+       if (pos > last_recorded_diw_hpos) {
+               last_recorded_diw_hpos = pos;
+       }
+
+}
+
+static void sync_color_changes(int hpos)
+{
+       record_color_change2(hpos, 0xffff, 0);
 }
 
 // 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)
 {
+       if (diw_last >= diw_current) {
+               return;
+       }
        // update state
-       record_color_change2(-(diw_current - 1), 0xffff, 0);
+       diw_current = adjust_hr(diw_current);
+       record_color_change2(-diw_current, 0xffff, 0);
 
        // find slot to insert into
        int i;
        for (i = last_color_change; i < next_color_change; i++) {
                struct color_change *cc = &curr_color_changes[i];
-               if (cc->linepos >= diw_last) {
+               if (cc->linepos > diw_last) {
                        break;
                }
        }
@@ -970,50 +1076,62 @@ static void hdiw_restart(int diw_last, int diw_current)
 * machine at the current position. It might have changed since we last
 * checked.  */
 
-static void decide_diw_check_start(int start_diw_hpos, int end_diw_hpos)
+static void decide_diw_check_start(int start_diw_hpos, int end_diw_hpos, int extrahpos)
 {
        if (hdiwstate == DIW_waiting_start) {
-               if (diw_hstrt > start_diw_hpos && diw_hstrt <= end_diw_hpos) {
-                       int first = diwfirstword + coord_diw_shres_to_window_x(hpos_hsync_extra << CCK_SHRES_SHIFT);
+               if (diw_hstrt > start_diw_hpos && diw_hstrt < end_diw_hpos) {
+                       int first = diwfirstword + extrahpos;
                        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 * 2, first * 2);
+                               hdiw_restart(last_diwlastword, first2);
                                last_diwlastword = -1;
+                               if (debug_dma) {
+                                       record_dma_event(DMA_EVENT_HDIWS, diw_to_hpos(first2), vpos);
+                               }
                        }
                        if (thisline_decision.diwfirstword < 0) {
-                               thisline_decision.diwfirstword = first;
+                               thisline_decision.diwfirstword = adjust_hr2(first);
                                // opened before first BPL1DAT?
                                if (!plane0_first_done) {
                                        plane0p_enabled = ecs_denise && (bplcon0 & 1) && (bplcon3 & 0x20);
                                }
+                               if (debug_dma) {
+                                       record_dma_event(DMA_EVENT_HDIWS, diw_to_hpos(first), vpos);
+                               }
                        }
                        hdiwstate = DIW_waiting_stop;
                }
        }
 }
-static void decide_diw_check_stop(int start_diw_hpos, int end_diw_hpos)
+static void decide_diw_check_stop(int start_diw_hpos, int end_diw_hpos, int extrahpos)
 {
        if (hdiwstate == DIW_waiting_stop) {
                if (diw_hstop > start_diw_hpos && diw_hstop <= end_diw_hpos) {
-                       int last = diwlastword + coord_diw_shres_to_window_x(hpos_hsync_extra << CCK_SHRES_SHIFT);
+                       int last = diwlastword + extrahpos;
                        if (last > thisline_decision.diwlastword) {
-                               thisline_decision.diwlastword = last;
+                               thisline_decision.diwlastword = adjust_hr2(last);
                                // if HDIW opens again in same line
-                               last_diwlastword = thisline_decision.diwlastword;
+                               int v = thisline_decision.diwlastword * 2;
+                               last_diwlastword = adjust_hr(v);
+                               if (debug_dma) {
+                                       record_dma_event(DMA_EVENT_HDIWE, diw_to_hpos(last), vpos);
+                               }
                        }
                        hdiwstate = DIW_waiting_start;
                }
        }
 }
 
-static void decide_diw_check(int start_diw_hpos, int end_diw_hpos)
+static void decide_diw_check(int start_diw_hpos, int end_diw_hpos, int extrahpos)
 {
-       if (diw_hstrt <= diw_hstop) {
-               decide_diw_check_start(start_diw_hpos, end_diw_hpos);
-               decide_diw_check_stop(start_diw_hpos, end_diw_hpos);
+       if (diw_hstrt < diw_hstop) {
+               decide_diw_check_start(start_diw_hpos, end_diw_hpos, extrahpos);
+               decide_diw_check_stop(start_diw_hpos, end_diw_hpos, extrahpos);
        } else {
-               decide_diw_check_stop(start_diw_hpos, end_diw_hpos);
-               decide_diw_check_start(start_diw_hpos, end_diw_hpos);
+               decide_diw_check_stop(start_diw_hpos, end_diw_hpos, extrahpos);
+               decide_diw_check_start(start_diw_hpos, end_diw_hpos, extrahpos);
        }
 }
 
@@ -1029,22 +1147,26 @@ static void decide_diw(int hpos)
        if (hpos2 <= last_diw_hpos2) {
                return;
        }
-
-       int start_diw_hpos = last_diw_hpos * 2 + 1;
-       int end_diw_hpos = hpos * 2 + 1;
+       int start_diw_hpos = ((last_diw_hpos * 2 - DDF_OFFSET + 1) << 2) + 3;
+       int end_diw_hpos = (hpos * 2 + 1) << 2;
+       // should handle wrap around..
+       if (start_diw_hpos < ((1 << 2) + 3)) {
+               start_diw_hpos = (1 << 2) + 3;
+       }
+       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 = diw_hcounter;
-               end_diw_hpos = diw_hcounter + end_diw_hpos;
-               decide_diw_check(start_diw_hpos, end_diw_hpos);
-               if (end_diw_hpos >= maxhpos * 2 + 1) {
-                       start_diw_hpos = 1;
-                       end_diw_hpos -= maxhpos * 2 + 1;
-                       decide_diw_check(start_diw_hpos, end_diw_hpos);
+               start_diw_hpos = (diw_hcounter & 511) << 2;
+               end_diw_hpos = start_diw_hpos + end_diw_hpos;
+               decide_diw_check(start_diw_hpos, end_diw_hpos, extrahpos);
+               if (end_diw_hpos >= (512 << 2)) {
+                       start_diw_hpos = -1;
+                       end_diw_hpos -= (512 << 2);
+                       decide_diw_check(start_diw_hpos, end_diw_hpos, extrahpos);
                }
        } else {
-               decide_diw_check(start_diw_hpos, end_diw_hpos);
+               decide_diw_check(start_diw_hpos, end_diw_hpos, extrahpos);
        }
        last_diw_hpos = hpos;
        last_diw_hpos2 = hpos2;
@@ -1264,12 +1386,14 @@ static void clear_bitplane_pipeline(int type)
 #define ESTIMATED_FETCH_MODE 1
 #define OPTIMIZED_ESTIMATE 1
 
-static uae_u8 estimated_cycles_buf[256];
+static uae_u8 estimated_cycles_buf0[256];
+static uae_u8 estimated_cycles_buf1[256];
 static uae_u8 estimated_cycles_empty[256];
 static int estimate_cycles_empty_index = -1;
 static uae_u16 estimated_bplcon0, estimated_fm, estimated_plfstrt, estimated_plfstop;
 static uae_u8* estimated_cycles = estimated_cycles_empty;
 static bool estimated_empty;
+static int estimated_maxhpos[2];
 
 #if ESTIMATED_FETCH_MODE
 
@@ -1288,11 +1412,11 @@ static void end_estimate_last_fetch_cycle(int hpos)
                estimate_cycles_empty_index = hpos;
                for (int i = 0; i < RGA_PIPELINE_ADJUST; i++) {
                        int pos = (hpos + i) % maxhpos;
-                       estimated_cycles_empty[pos] = estimated_cycles_buf[pos];
+                       estimated_cycles_empty[pos] = maxhposeven ? estimated_cycles_buf1[pos] : estimated_cycles_buf0[pos];
                }
        }
 #else
-       estimated_cycles = estimated_cycles_buf;
+       estimated_cycles = estimated_cycles_buf0;
        int start_pos = (hpos + RGA_PIPELINE_ADJUST) % maxhpos;
        if (start_pos >= hpos) {
                memset(estimated_cycles + start_pos, 0, maxhpos - start_pos);
@@ -1314,8 +1438,16 @@ static void estimate_last_fetch_cycle(int hpos)
 
 #if OPTIMIZED_ESTIMATE
                if (estimated_bplcon0 == bplcon0 && plfstrt == hpos && estimated_plfstrt == plfstrt && estimated_plfstop == plfstop && estimated_fm == fetchmode) {
-                       estimated_cycles = estimated_cycles_buf;
-                       return;
+                       if (maxhpos == estimated_maxhpos[0]) {
+                               estimated_cycles = estimated_cycles_buf0;
+                               return;
+                       }
+                       if (maxhpos == estimated_maxhpos[1]) {
+                               estimated_cycles = estimated_cycles_buf1;
+                               return;
+                       }
+               } else {
+                       estimated_maxhpos[0] = estimated_maxhpos[1] = -1;
                }
 #endif
 #if 0
@@ -1375,7 +1507,11 @@ static void estimate_last_fetch_cycle(int hpos)
                        estimated_cycle_count = (starting_last_block_at - fc) + lastfetchunit;
                }
 
-               estimated_cycles = estimated_cycles_buf;
+#if OPTIMIZED_ESTIMATE
+               estimated_cycles = maxhposeven ? estimated_cycles_buf1 : estimated_cycles_buf0;
+#else
+               estimated_cycles = estimated_cycles_buf0;
+#endif
                // bitplane DMA end can wrap around, even in non-overrun cases
                int start_pos = (hpos + RGA_PIPELINE_ADJUST) % maxhpos;
                int start_pos2 = start_pos;
@@ -1425,8 +1561,11 @@ static void estimate_last_fetch_cycle(int hpos)
                        estimated_plfstrt = plfstrt;
                        estimated_plfstop = plfstop;
                        estimated_fm = fetchmode;
+                       estimated_maxhpos[maxhposeven] = maxhpos;
                } else {
                        estimated_fm = 0xffff;
+                       estimated_maxhpos[0] = -1;
+                       estimated_maxhpos[1] = -1;
                }
 #endif
        }
@@ -1551,6 +1690,7 @@ static void set_chipset_mode(void)
                spr[i].width = sprite_width;
        }
        shdelay_disabled = false;
+       exthblank_state = false;
        calcdiw();
 }
 
@@ -1791,36 +1931,24 @@ static void setup_fmodes(int hpos)
        SET_LINE_CYCLEBASED;
 }
 
-static int fetch_warn(int nr, int hpos)
+static int fetch_warn(int nr, int hpos, bool *addmodulop)
 {
        static int warned1 = 30, warned2 = 30;
        int add = fetchmode_bytes;
-       if (cycle_line_slot[hpos] == CYCLE_REFRESH) {
+       if (cycle_line_slot[hpos] == CYCLE_STROBE) {
                if (warned1 >= 0) {
-                       write_log(_T("WARNING: BPL fetch conflictconflicts with strobe refresh slot, hpos %02X!\n"), hpos);
+                       write_log(_T("WARNING: BPL strobe refresh conflict, hpos %02X!\n"), hpos);
                        warned1--;
                }
+               *addmodulop = false;
                add = refptr_val;
        } else {
                if (warned2 >= 0) {
                        warned2--;
-                       write_log(_T("WARNING: BPL fetch at hpos %02X!\n"), hpos);
+                       write_log(_T("WARNING: BPL refresh conflict, hpos %02X!\n"), hpos);
                }
                add = refptr_val;
-       }
-       if (beamcon0 & 0x80) {
-               add = fetchmode_bytes;
-       } else {
-#if 0
-               line_cyclebased = vpos;
-               corrupt_offset = (vpos ^ (timeframes << 12)) & 0xff00;
-               for (int i = 0; i < bplcon0_planes_limit; i++) {
-                       uae_u16 v;
-                       v = bplpt[i] & 0xffff;
-                       v += corrupt_offset;
-                       bplpt[i] = (bplpt[i] & 0xffff0000) | v;
-               }
-#endif
+               *addmodulop = false;
        }
        return add;
 }
@@ -1829,11 +1957,17 @@ static bool fetch(int nr, int fm, int hpos, bool addmodulo)
 {
        int add = fetchmode_bytes;
 
-       if (cycle_line_slot[hpos] == CYCLE_REFRESH || cycle_line_slot[hpos] == CYCLE_STROBE) {
+       if (cycle_line_slot[hpos] == CYCLE_STROBE) {
+               // strobe refresh conflict
+               add = fetch_warn(nr, hpos, &addmodulo);
+       } else if (cycle_line_slot[hpos] == CYCLE_REFRESH) {
                // refresh conflict
-               add = fetch_warn(nr, hpos);
+               add = fetch_warn(nr, hpos, &addmodulo);
        } else if (cycle_line_slot[hpos] == CYCLE_MISC) {
                // DMAL conflict
+               // AUDxDAT AND BPLxDAT = read-only register
+               // DSKDATR AND BLPxDAT = read-only register
+               // DSKDAT AND BPLxDAT = read-only register
                return false;
        } else {
                cycle_line_slot[hpos] = CYCLE_BITPLANE;
@@ -2760,17 +2894,22 @@ static void update_toscr_planes(int fm)
        thisline_decision.nr_planes = toscr_nr_planes_agnus;
 }
 
-static void hbstrt_bordercheck(int hpos)
+static void hbstrt_bordercheck(int hpos, bool early)
 {
+       if (exthblank) {
+               sync_color_changes(hpos);
+       }
        if (hb_last_diwlastword < 0) {
                return;
        }
        // if HBSTRT re-enabled border (and HDIW was already open), BPL1DAT access will disable border again.
-       record_color_change2(hpos - 1, 0xffff, 0);
-       uae_u16 pos = (((hpos + hpos_hsync_extra) * 2 - DDF_OFFSET) * 4);
+       uae_u16 pos = hpos_to_diw(hpos);
+       if (early) {
+               pos -= 2;
+       }
        pos -= 2; // 1 hires pixel early
-       adjust_hr(&pos);
-       hdiw_restart(hb_last_diwlastword * 2, coord_diw_shres_to_window_x(pos * 2));
+       pos = adjust_hr(pos);
+       hdiw_restart(hb_last_diwlastword, pos);
        hb_last_diwlastword = -1;
 }
 
@@ -2789,9 +2928,13 @@ static void beginning_of_plane_block_early(int hpos)
        thisline_decision.plfleft = left * 2;
        if (hdiwstate == DIW_waiting_stop && thisline_decision.diwfirstword < 0) {
                // 1.5 lores pixels
-               thisline_decision.diwfirstword = coord_diw_shres_to_window_x(((left - DDF_OFFSET / 2) << CCK_SHRES_SHIFT) + 6);
+               int v = hpos_to_diw(hpos);
+               v += 6;
+               v = adjust_hr(v);
+               thisline_decision.diwfirstword = coord_diw_shres_to_window_x(v);
+
        }
-       hbstrt_bordercheck(hpos);
+       hbstrt_bordercheck(hpos, false);
 }
 
 /* Called when all planes have been fetched, i.e. when a new block
@@ -2814,6 +2957,7 @@ static void beginning_of_plane_block(int hpos)
        todisplay_fetched = 3;
        sprites_enabled_this_line = true;
        plane0_first_done = true;
+       last_bpl1dat_hpos = hpos;
 
        if (thisline_decision.plfleft < 0) {
                int left = hpos + hpos_hsync_extra;
@@ -2828,7 +2972,7 @@ static void beginning_of_plane_block(int hpos)
                }
        }
 
-       hbstrt_bordercheck(hpos);
+       hbstrt_bordercheck(hpos, true);
 
        update_denise(hpos);
        if (toscr_nr_planes_agnus > thisline_decision.nr_planes) {
@@ -3521,6 +3665,9 @@ static void update_fetch(int until, int fm)
                                        bprun_pipeline_flush_delay = 0;
                                }
                        }
+                       if (plane0) {
+                               last_bpl1dat_hpos = hpos;
+                       }
                }
        }
 #endif
@@ -3597,13 +3744,13 @@ static void decide_vline(void)
 }
 
 static void update_copper(int until_hpos);
-static void decide_sprite_fetch(int endhpos);
+static void decide_sprites_fetch(int endhpos);
 static void decide_line(int endhpos);
 
 static void decide_line_decision_fetches(int endhpos)
 {
        decide_bpl_fetch(endhpos);
-       decide_sprite_fetch(endhpos);
+       decide_sprites_fetch(endhpos);
 }
 
 static void decide_fetch_safe(int endhpos)
@@ -3760,7 +3907,7 @@ static void do_playfield_collisions(void)
        if (maxpos > hw_diwlast) {
                maxpos = hw_diwlast;
        }
-       for (i = minpos; i < maxpos && !collided; i+= 32) {
+       for (i = minpos; i < maxpos && !collided; i += 32) {
                int offs = ((i << bplres) - ddf_left) >> 3;
                int j;
                uae_u32 total = 0xffffffff;
@@ -4156,7 +4303,7 @@ static void decide_sprites(int hpos, bool usepointx, bool quick)
                return;
 
        point = (hpos + hpos_hsync_extra) * 2 - DDF_OFFSET;
-       if (point == last_sprite_point) {
+       if (point <= last_sprite_point) {
                return;
        }
 
@@ -4179,7 +4326,7 @@ static void decide_sprites(int hpos, bool usepointx, bool quick)
                int hw_xp = sprxp >> sprite_buffer_res;
                int pointx = usepointx && (s->ctl & sprite_sprctlmask) ? 0 : 1;
 
-               if (xpos < 0) {
+               if (hw_xp <= 0 || hw_xp > maxhpos * 2 + 1) {
                        continue;
                }
 
@@ -4191,6 +4338,12 @@ static void decide_sprites(int hpos, bool usepointx, bool quick)
                        continue;
                }
 
+               if (s->ecs_denise_hires && (bplcon0d & 0x0040)) {
+                       xpos |= 2 >> (RES_MAX - sprite_buffer_res);
+                       sprxp = xpos;
+                       hw_xp = sprxp >> sprite_buffer_res;
+               }
+
                if (hw_xp > last_sprite_point && hw_xp <= point + pointx) {
                        add_sprite(&count, i, sprxp, posns, nrs);
                }
@@ -4202,7 +4355,7 @@ static void decide_sprites(int hpos, bool usepointx, bool quick)
                        if (hw_xp > last_sprite_point && hw_xp <= point + pointx) {
                                add_sprite(&count, MAX_SPRITES + i, sprxp, posns, nrs);
                        }
-               } else if (!(fmode & 0x80) && xpos >= (2 << sprite_buffer_res) && xpos <= (extrahpos << sprite_buffer_res)) {
+               } 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;
@@ -4216,6 +4369,10 @@ static void decide_sprites(int hpos, bool usepointx, bool quick)
        for (int i = 0; i < count; i++) {
                int nr = nrs[i] & (MAX_SPRITES - 1);
                struct sprite *s = &spr[nr];
+               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 */
@@ -4263,17 +4420,6 @@ static void decide_sprites(int hpos)
 {
        decide_sprites(hpos, false, false);
 }
-static void maybe_decide_sprites(int spnr, int hpos)
-{
-       struct sprite *s = &spr[spnr];
-       if (!s->armed) {
-               return;
-       }
-       if (!s->data && !s->datb) {
-               return;
-       }
-       decide_sprites(hpos, true, true);
-}
 
 static int sprites_differ(struct draw_info *dip, struct draw_info *dip_old)
 {
@@ -4364,7 +4510,7 @@ static void finish_decisions(int hpos)
                thisline_decision.bplres = output_res(RES_LORES);
        }
 
-       record_color_change2(hpos + 1, 0xffff, 0);
+       sync_color_changes(hpos + 1);
 
        /* Large DIWSTOP values can cause the stop position never to be
        * reached, so the state machine always stays in the same state and
@@ -4451,7 +4597,6 @@ static void reset_decisions_scanline_start(void)
        last_copper_hpos = 0;
        ddfstrt_hpos = -1;
        ddfstop_hpos = -1;
-       sprites_enabled_this_line = false;
        last_diw_hpos = 0;
        last_diw_hpos2 = 0;
 
@@ -4502,8 +4647,10 @@ static void reset_decisions_hsync_start(void)
        next_sprite_forced = 1;
 
        last_sprite_point = 0;
+       sprites_enabled_this_line = false;
        bpl1mod_hpos = -1;
        bpl2mod_hpos = -1;
+       last_recorded_diw_hpos = 0;
 
        compute_toscr_delay(bplcon1);
 
@@ -4537,7 +4684,7 @@ static void reset_decisions_hsync_start(void)
        //bool t = thisline_decision.plfleft >= 0 && (thisline_decision.vb & 1) == 0 && !vb_state && !vb_end_line;
        thisline_decision.vb = vb_start_line > 1 + vblank_extraline ? 0 : 1;
        // if programmed vblank
-       if (!thisline_decision.vb && (beamcon0 & 0x1000) && aga_mode) {
+       if (!thisline_decision.vb && (beamcon0 & 0x1000) && ecs_agnus) {
                thisline_decision.vb |= 2;
        }
        if (!ecs_denise && vb_end_line && currprefs.cs_ocshblankbug) {
@@ -4572,7 +4719,7 @@ static void reset_decisions_hsync_start(void)
        if (1 && fetchmode >= 2 && !doflickerfix()) {
                // handle bitplane data wrap around
                bool toshift = false;
-               if ((exthblank || (beamcon0 & 0x0110)) && thisline_decision.bplres == 0) {
+               if ((exthblank || (beamcon0 & 0x0110)) && (thisline_decision.bplres == 0 || currprefs.chipset_hr)) {
                        for (int i = 0; i < thisline_decision.nr_planes; i++) {
                                if (todisplay2_aga_saved[i]) {
                                        toshift = true;
@@ -4604,6 +4751,30 @@ static void reset_decisions_hsync_start(void)
                        bprun_pipeline_flush_delay = maxhpos;
                        plane0p_enabled = true;
                        plane0p_forced = true;
+
+                       // HBLANK start before HSYNC (or HBLANK never triggered) and BPL1DAT between HBLANK and HSYNC?
+                       if (exthblank) {
+                               int hblankstart = 0;
+                               if (last_hblank_start >= 0) {
+                                       hblankstart = diw_to_hpos(last_hblank_start + 4);
+                               }
+                               else {
+                                       hblankstart = last_bpl1dat_hpos - 1;
+                               }
+                               int bpl1 = last_bpl1dat_hpos;
+                               if (bpl1 < hblankstart) {
+                                       bpl1 += maxhpos;
+                               }
+                               int hp = hpos;
+                               if (hp < hblankstart || hp < bpl1) {
+                                       hp += maxhpos;
+                               }
+                               int comp = maxhpos / 2 - 1;
+                               if (bpl1 > hblankstart && bpl1 < hp && (bpl1 - hblankstart) < comp && (bpl1 - hp) < comp) {
+                                       // Close border. (HBLANK start opens border, BPL1DAT closes it)
+                                       thisline_decision.plfleft = hpos * 2;
+                               }
+                       }
                }
        }
 
@@ -4624,7 +4795,14 @@ static void reset_decisions_hsync_start(void)
 #endif
        }
 
+       if (debug_dma && (new_beamcon0 & (0x000 | 0x0010))) {
+               record_dma_event(DMA_EVENT_HSS, hpos, vpos);
+               record_dma_event(DMA_EVENT_HSE, hsstop, vpos);
+       }
+
        toscr_hend = 0;
+       last_bpl1dat_hpos = -1;
+       last_hblank_start = -1;
 }
 
 int vsynctimebase_orig;
@@ -4690,7 +4868,7 @@ devices_update_sync(svpos, syncadjust);
 void getsyncregisters(uae_u16 *phsstrt, uae_u16 *phsstop, uae_u16 *pvsstrt, uae_u16 *pvsstop)
 {
        *phsstrt = hsstrt;
-       *phsstop = hsstop;
+       *phsstop = hsstop_detect;
        *pvsstrt = vsstrt;
        *pvsstop = vsstop;
 }
@@ -4702,16 +4880,14 @@ static void dumpsync(void)
                return;
        }
        cnt--;
-       write_log(_T("BEAMCON0=%04X VTOTAL=%04X  HTOTAL=%04X\n"), new_beamcon0, vtotal, htotal);
+       write_log(_T("BEAMCON0=%04X VTOTAL=%03d HTOTAL=%03d (%03X)\n"), new_beamcon0, vtotal, htotal, htotal);
        write_log(_T(" HS=%04X-%04X HB=%04X-%04X HC=%04X\n"), hsstrt, hsstop, hbstrt, hbstop, hcenter);
-       write_log(_T(" VS=%04X-%04X VB=%04X-%04X\n"), vsstrt, vsstop, vbstrt, vbstop);
+       write_log(_T(" VS=%04d-%04d VB=%04d-%04d\n"), vsstrt, vsstop, vbstrt, vbstop);
        write_log(_T(" HSYNCSTART=%04X.%d HSYNCEND=%04X.%d\n"),
                hsyncstartpos >> CCK_SHRES_SHIFT, hsyncstartpos & ((1 << CCK_SHRES_SHIFT) - 1),
                hsyncendpos >> CCK_SHRES_SHIFT, hsyncendpos & ((1 << CCK_SHRES_SHIFT) - 1));
-       write_log(_T(" LINES=%d-%d VB=%d-%d\n"),
-               minfirstline, maxvpos_display + maxvpos_display_vsync,
-               vblank_firstline_hw, vblank_lastline_hw);
-
+       write_log(_T(" Lines=%d-%d\n"),
+               minfirstline, maxvpos_display + maxvpos_display_vsync);
 }
 
 int current_maxvpos(void)
@@ -4751,6 +4927,28 @@ static void checklacecount(bool lace)
 }
 #endif
 
+static void set_hcenter(void)
+{
+       if (!aga_mode && ecs_denise && (bplcon0 & 1)) {
+               if (beamcon0 & 0x0210) {
+                       hcenter_v2 = (hcenter & 0xff) << CCK_SHRES_SHIFT;
+               } else {
+                       hcenter_v2 = 132 << CCK_SHRES_SHIFT;
+               }
+       } else {
+               hcenter_v2 = 0;
+       }
+       uae_u16 hc = hcenter_v2;
+       hcenter_v2 -= 3;
+       if (hc >= (1 << CCK_SHRES_SHIFT) && hcenter_v2 < (1 << CCK_SHRES_SHIFT)) {
+               hcenter_v2 += maxhpos << CCK_SHRES_SHIFT;
+       }
+       hcenter_v2 = adjust_hr(hcenter_v2);
+       if (hcenter_v2 < (1 << CCK_SHRES_SHIFT)) {
+               hcenter_v2 = 0;
+       }
+}
+
 static void updateextblk(void)
 {
        hsyncstartpos_start_hw = 13;
@@ -4766,12 +4964,12 @@ static void updateextblk(void)
                hbstop_v |= (hbstop >> 8) & 7;
        }
        if (aga_mode) {
-               // 1.5 hires pixel offset
-               hbstrt_v2 = hbstrt_v - 3;
+               // 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;
                }
-               hbstop_v2 = hbstop_v - 3;
+               hbstop_v2 = hbstop_v - 4;
                if (hbstop_v >= (1 << CCK_SHRES_SHIFT) && hbstop_v2 < (1 << CCK_SHRES_SHIFT)) {
                        hbstop_v2 += maxhpos << CCK_SHRES_SHIFT;
                }
@@ -4790,9 +4988,13 @@ static void updateextblk(void)
        if (new_beamcon0 & 0x0110) { // VARHSYEN | VARCSYEN
 
                hsyncstartpos = hsstrt;
-               hsyncendpos = hsstop;
+               hsstop_detect = hsstrt + 17;
+               if (hsstop_detect >= maxhpos) {
+                       hsstop_detect -= maxhpos;
+               }
+               hsyncendpos = hsstop_detect;
 
-               hsync_end_left_border = hsstop + 1;
+               hsync_end_left_border = hsstop_detect;
 
                hsyncstartpos_start = hsyncstartpos;
                if (hsyncstartpos < hsyncendpos) {
@@ -4851,8 +5053,25 @@ static void updateextblk(void)
                hbstop_v2 += maxhpos << CCK_SHRES_SHIFT;
        }
 
-       adjust_hr(&hbstrt_v2);
-       adjust_hr(&hbstop_v2);
+       int strt = hbstrt_v2;
+       int stop = hbstop_v2;
+       hbstrt_v2 = adjust_hr(hbstrt_v2);
+       hbstop_v2 = adjust_hr(hbstop_v2);
+       // if same after rounding: increase start/stop by minimum unit
+       if (hbstrt_v2 == hbstop_v2) {
+               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)) {
+                               hbstop_v2 = 0;
+                       }
+               } else if (strt > stop) {
+                       hbstrt_v2 += add;
+                       if (hbstrt_v2 >= (maxhpos << CCK_SHRES_SHIFT) + (1 << CCK_SHRES_SHIFT)) {
+                               hbstrt_v2 = 0;
+                       }
+               }
+       }
 
        hsyncstartpos_start_hw <<= CCK_SHRES_SHIFT;
        hsyncstartpos_hw <<= CCK_SHRES_SHIFT;
@@ -4870,6 +5089,8 @@ static void updateextblk(void)
                hsynctotal += 1 << (CCK_SHRES_SHIFT - 1);
        }
 
+       set_hcenter();
+
        calcdiw();
 }
 
@@ -5018,10 +5239,10 @@ void compute_framesync(void)
                        vres2 = VRES_QUAD;
 
                int start = hsyncstartpos >> CCK_SHRES_SHIFT;
-               int stop = hsyncendpos >> CCK_SHRES_SHIFT;
+               int stop = hsyncstartpos_start_cycles;
 
                vidinfo->drawbuffer.inwidth = ((maxhpos - (maxhpos - start + DISPLAY_LEFT_SHIFT / 2) + 1) * 2) << res2;
-               vidinfo->drawbuffer.inxoffset = hsstop * 2;
+               vidinfo->drawbuffer.inxoffset = stop * 2;
                
                vidinfo->drawbuffer.extrawidth = 0;
                vidinfo->drawbuffer.inwidth2 = vidinfo->drawbuffer.inwidth;
@@ -5166,6 +5387,18 @@ static void init_hz(bool checkvposw)
                vblank_hz_lace = clk / ((maxvpos + 0.5) * (maxhpos + 0.5));
        }
 
+       if (beamcon0 & 0x80) {
+               // programmable scanrates (ECS Agnus)
+               if (vtotal >= MAXVPOS) {
+                       vtotal = MAXVPOS - 1;
+               }
+               maxvpos = vtotal + 1;
+               if (htotal >= MAXHPOS) {
+                       htotal = MAXHPOS - 1;
+               }
+               maxhpos = htotal + 1;
+       }
+
        maxhpos_display = AMIGA_WIDTH_MAX;
        maxvpos_nom = maxvpos;
        maxvpos_display = maxvpos;
@@ -5199,8 +5432,6 @@ static void init_hz(bool checkvposw)
 
        vblank_extraline = !currprefs.cs_dipagnus && !ecs_denise ? 1 : 0;
 
-       vblank_lastline_hw = maxvpos + maxvpos_display_vsync + vblank_extraline;
-
        int minfirstline_hw = minfirstline;
        if (currprefs.gfx_overscanmode == OVERSCANMODE_EXTREME) {
                minfirstline_hw -= EXTRAHEIGHT_EXTREME / 2;
@@ -5308,16 +5539,12 @@ static void init_hz(bool checkvposw)
                }
        }
 
+       vbstopm1 = vbstop - 1;
+       if (vbstopm1 < 0) {
+               vbstopm1 += maxvpos;
+       }
+
        if (beamcon0 & 0x80) {
-               // programmable scanrates (ECS Agnus)
-               if (vtotal >= MAXVPOS) {
-                       vtotal = MAXVPOS - 1;
-               }
-               maxvpos = vtotal + 1;
-               if (htotal >= MAXHPOS) {
-                       htotal = MAXHPOS - 1;
-               }
-               maxhpos = htotal + 1;
                vblank_hz_nom = vblank_hz = clk / (maxvpos * maxhpos);
                vblank_hz_shf = vblank_hz;
                vblank_hz_lof = clk / ((maxvpos + 1) * maxhpos);
@@ -5450,8 +5677,8 @@ static void calcdiw(void)
                hstop |= (diwhigh >> 11) & 3;
        }
 
-       diw_hstrt = hstrt >> 2;
-       diw_hstop = hstop >> 2;
+       diw_hstrt = hstrt;
+       diw_hstop = hstop;
 
        diwfirstword = coord_diw_shres_to_window_x(hstrt);
        diwlastword = coord_diw_shres_to_window_x(hstop);
@@ -6480,6 +6707,10 @@ static void BPLCON0(int hpos, uae_u16 v)
        decide_line(hpos);
        decide_fetch_safe(hpos);
 
+       if ((v & 1) != (bplcon0 & 1)) {
+               sync_color_changes(hpos);
+       }
+
        if (!issyncstopped()) {
                vpos_previous = vpos;
                hpos_previous = hpos;
@@ -6560,7 +6791,7 @@ static void BPLCON3(int hpos, uae_u16 v)
                return;
        }
        if (!aga_mode) {
-               v &= 0x003f;
+               v &= (0x0020 | 0x0010 | 0x004 | 0x001);
                v |= 0x0c00;
        }
 #if SPRBORDER
@@ -6571,6 +6802,9 @@ static void BPLCON3(int hpos, uae_u16 v)
        }
        decide_line(hpos);
        decide_sprites(hpos);
+       if ((bplcon3 & 1) != (v & 1)) {
+               sync_color_changes(hpos);
+       }
        bplcon3 = v;
        if ((bplcon3 & 1) != (old & 1)) {
                updateextblk();
@@ -6670,8 +6904,8 @@ static void DIWSTRT(int hpos, uae_u16 v)
                return;
        }
        // if hpos matches previous hstart: it gets ignored.
-       if (diw_hstrt + DDF_OFFSET >= hpos * 2 - 2 && diw_hstrt + DDF_OFFSET <= hpos * 2 + 2) {
-               diw_hstrt = max_diwlastword;
+       if ((diw_hstrt >> 2) + DDF_OFFSET >= hpos * 2 - 2 && (diw_hstrt >> 2) + DDF_OFFSET <= hpos * 2 + 2) {
+               diw_hstrt = max_diwlastword << 2;
        }
        decide_diw(hpos);
        decide_line(hpos);
@@ -6685,8 +6919,8 @@ static void DIWSTOP(int hpos, uae_u16 v)
        if (diwstop == v && !diwhigh_written) {
                return;
        }
-       if (diw_hstop + DDF_OFFSET >= hpos * 2 - 2 && diw_hstop + DDF_OFFSET <= hpos * 2 + 2) {
-               diw_hstop = min_diwlastword;
+       if ((diw_hstop >> 2) + DDF_OFFSET >= hpos * 2 - 2 && (diw_hstop >> 2) + DDF_OFFSET <= hpos * 2 + 2) {
+               diw_hstop = min_diwlastword << 2;
        }
        decide_diw(hpos);
        decide_line(hpos);
@@ -6981,6 +7215,7 @@ static void SPRxCTLPOS(int num)
        sprxp = (s->pos & 0xFF) * 2 + (s->ctl & 1);
        sprxp <<= sprite_buffer_res;
        s->dblscan = 0;
+       s->ecs_denise_hires = 0;
        /* Quite a bit salad in this register... */
        if (0) {
        }
@@ -6991,8 +7226,11 @@ static void SPRxCTLPOS(int num)
        }
 #endif
 #ifdef ECS_DENISE
-       else if (ecs_denise) {
-               sprxp |= ((s->ctl >> 3) & 2) >> (RES_MAX - sprite_buffer_res);
+       else if (ecs_denise && (s->ctl & 0x10)) {
+               // This bit only works as documented if superhires bitplane resolution.
+               // If bitplane resolution is lores or hires: sprite's first pixel row
+               // becomes transparent.
+               s->ecs_denise_hires = 1;
        }
 #endif
        s->xpos = sprxp;
@@ -7544,7 +7782,7 @@ static void decide_line(int endhpos)
                        // ECS/AGA
 
                        // BPRUN latched: on
-                       if (bprun < 0) {
+                       if (bprun < 0 && (hpos & 1)) {
                                decide_line_decision_fetches(hpos);
                                bprun = 1;
                                bprun_pipeline_flush_delay = maxhpos;
@@ -7671,7 +7909,7 @@ static void decide_line(int endhpos)
                        // OCS
 
                        // BPRUN latched: On
-                       if (bprun < 0) {
+                       if (bprun < 0 && (hpos & 1)) {
                                decide_line_decision_fetches(hpos);
                                bprun = 1;
                                bprun_pipeline_flush_delay = maxhpos;
@@ -7767,7 +8005,7 @@ static void decide_line(int endhpos)
                hpos++;
        }
 
-       decide_sprite_fetch(endhpos);
+       decide_sprites_fetch(endhpos);
 
        last_decide_line_hpos = endhpos;
 }
@@ -8562,23 +8800,15 @@ static void do_sprite_fetch(int hpos, uae_u8 dat)
        bool slot = (dat & 8) != 0;
        bool dmastate = (dat & 0x10) != 0;
 
+       // render sprites first
+       decide_sprites(hpos, false, true);
+
        sprite_fetch_full(s, hpos, slot, false, &data, &data321, &data322);
        int sprxp = s->xpos >> (sprite_buffer_res + 1);
-       bool start_before_dma = hpos >= sprxp && sprxp >= 16;
        if (dmastate) {
                if (!slot) {
-                       // if xpos is earlier than this cycle, decide it first.
-                       if (start_before_dma) {
-                               maybe_decide_sprites(num, hpos);
-                       }
                        SPRxDATA_1(data, num, hpos);
                } else {
-                       // This is needed if xpos is between DATA and DATB fetches
-                       // Test does not need to be accurate, only purpose is to
-                       // not lose performance when sprites have "normal" positioning.
-                       if (start_before_dma) {
-                               maybe_decide_sprites(num, hpos);
-                       }
                        SPRxDATB_1(data, num, hpos);
                }
 #ifdef AGA
@@ -8610,9 +8840,6 @@ static void do_sprite_fetch(int hpos, uae_u8 dat)
 #endif
        } else {
                if (!slot) {
-                       if (start_before_dma && s->armed) {
-                               maybe_decide_sprites(num, hpos);
-                       }
                        SPRxPOS_1(data, num, hpos);
                } else {
                        SPRxCTL_1(data, num, hpos);
@@ -8632,7 +8859,7 @@ static void do_sprite_fetch(int hpos, uae_u8 dat)
 
 }
 
-static void decide_sprite_fetch(int endhpos)
+static void decide_sprites_fetch(int endhpos)
 {
        int hpos = last_decide_sprite_hpos;
        if (hpos >= endhpos) {
@@ -8731,10 +8958,12 @@ void init_hardware_for_drawing_frame(void)
        if (prev_sprite_entries) {
                int first_pixel = prev_sprite_entries[0].first_pixel;
                int npixels = prev_sprite_entries[prev_next_sprite_entry].first_pixel - first_pixel;
-               memset(spixels + first_pixel, 0, npixels * sizeof *spixels);
-               memset(spixstate.stb + first_pixel, 0, npixels * sizeof *spixstate.stb);
-               if (aga_mode) {
-                       memset(spixstate.stbfm + first_pixel, 0, npixels * sizeof *spixstate.stbfm);
+               if (npixels > 0) {
+                       memset(spixels + first_pixel, 0, npixels * sizeof * spixels);
+                       memset(spixstate.stb + first_pixel, 0, npixels * sizeof * spixstate.stb);
+                       if (aga_mode) {
+                               memset(spixstate.stbfm + first_pixel, 0, npixels * sizeof * spixstate.stbfm);
+                       }
                }
        }
        prev_next_sprite_entry = next_sprite_entry;
@@ -9833,6 +10062,7 @@ static void hsync_handlerh(bool onvsync)
        }
 
        eventtab[ev_hsynch].evtime = get_cycles() + HSYNCTIME;
+       eventtab[ev_hsynch].active = 1;
        eventtab[ev_hsynch].oldcycles = get_cycles();
        events_schedule();
 }
@@ -9886,7 +10116,6 @@ static void hsync_handler_pre(bool onvsync)
                }
                if (ecs_denise || vpos > get_equ_vblank_endline() || (currprefs.cs_dipagnus && vpos == 0)) {
                        diw_hcounter = maxhpos * 2;
-                       last_hdiw = 2 - 1;
                }
        }
 
@@ -9923,6 +10152,8 @@ static void hsync_handler_pre(bool onvsync)
                eventtab[ev_hsynch].active = 1;
                events_schedule();
        }
+
+       debug_hsync();
 }
 
 STATIC_INLINE bool is_last_line(void)
@@ -10753,7 +10984,7 @@ static void hsync_handler_post (bool onvsync)
                                vb_start_line = 1;
                                vb_state = true;
                        }
-                       if (vbstop == vpos) {
+                       if (vbstopm1 == vpos) {
                                vbstop_m = vpos;
                                vb_end_line = true;
                                vb_state = false;
@@ -10788,6 +11019,31 @@ static void hsync_handler_post (bool onvsync)
                }
                hhpos &= 0xff;
        }
+
+       if (beamcon0 & 0x20) {
+               if (vpos == 2 && !lof_current) {
+                       vs_state_hw = true;
+               }
+               if (vpos == 3 && lof_current) {
+                       vs_state_hw = true;
+               }
+               if (vpos == 5) {
+                       vs_state_hw = false;
+               }
+       } else {
+               if (vpos == 3) {
+                       vs_state_hw = true;
+               }
+               if (vpos == 6) {
+                       vs_state_hw = false;
+               }
+       }
+       if (new_beamcon0 & (0x0200 | 0x0010)) {
+               vs_state_on = vs_state;
+       } else {
+               vs_state_on = vs_state_hw;
+       }
+
        if (!(new_beamcon0 & 0x1000)) {
                vb_check();
        }
@@ -10796,18 +11052,22 @@ static void hsync_handler_post (bool onvsync)
 
        int hp = REFRESH_FIRST_HPOS;
        for (int i = 0; i < 4; i++) {
-               alloc_cycle(hp, i == 0 ? CYCLE_STROBE : CYCLE_REFRESH); /* strobe */
+               bool type = i == 0 || (i == 1 && ecs_agnus && lol);
+               alloc_cycle(hp, type ? CYCLE_STROBE : CYCLE_REFRESH);
 #ifdef DEBUGGER
                if (debug_dma) {
-                       uae_u16 strobe = 0x3c;
-                       if (vb_state && vpos < equ_vblank_endline) {
-                               strobe = 0x38;
-                       } else if (vb_state) {
-                               strobe = 0x3a;
-                       } else if (ecs_agnus && lol) {
+                       uae_u16 strobe = 0x1fe;
+                       if (i == 0) {
+                               strobe = 0x3c;
+                               if (vb_state && vpos < equ_vblank_endline) {
+                                       strobe = 0x38;
+                               } else if (vb_state) {
+                                       strobe = 0x3a;
+                               }
+                       } else if (i == 1 && ecs_agnus && lol) {
                                strobe = 0x3e;
                        }
-                       record_dma_read(i == 0 ? strobe : 0x1fe, 0xffffffff, hp, vpos, DMARECORD_REFRESH, i);
+                       record_dma_read(strobe, 0xffffffff, hp, vpos, DMARECORD_REFRESH, i);
                        record_dma_read_value(0xffff);
                }
 #endif
@@ -10817,6 +11077,25 @@ static void hsync_handler_post (bool onvsync)
                }
        }
 
+       if (debug_dma) {
+               if (vs_state_on) {
+                       record_dma_event(DMA_EVENT_VS, REFRESH_FIRST_HPOS, vpos);
+               }
+               if (vb_start_line) {
+                       record_dma_event(DMA_EVENT_VB, REFRESH_FIRST_HPOS, vpos);
+               }
+               if (diwstate == DIW_waiting_stop) {
+                       record_dma_event(DMA_EVENT_VDIW, REFRESH_FIRST_HPOS, vpos);
+               }
+               if (lof_current) {
+                       record_dma_event(DMA_EVENT_LOF, REFRESH_FIRST_HPOS + 2, vpos);
+               }
+               if (lol) {
+                       record_dma_event(DMA_EVENT_LOL, REFRESH_FIRST_HPOS + 2, vpos);
+               }
+       }
+
+
        events_dmal_hsync ();
 #if 0
        // AF testing stuff
@@ -11106,6 +11385,9 @@ void custom_reset(bool hardreset, bool keyboardreset)
        nr_armed = 0;
        next_lineno = 0;
        vb_start_line = 0;
+       vs_state = false;
+       vs_state_hw = false;
+       vs_state_on = false;
        memset(custom_storage, 0, sizeof(custom_storage));
        if (!currprefs.cs_dipagnus) {
                vb_start_line = 1;
@@ -11116,6 +11398,10 @@ void custom_reset(bool hardreset, bool keyboardreset)
        estimated_fm = 0xffff;
        exthblank = false;
        exthblank_state = false;
+       hbstrt_v2 = 0;
+       hbstop_v2 = 0;
+       hcenter_v2 = 0;
+       set_hcenter();
 
        if (!savestate_state) {
                cia_hsync = 0;
@@ -11841,18 +12127,14 @@ static int REGPARAM2 custom_wput_1 (int hpos, uaecptr addr, uae_u32 value, int n
                break;
        case 0x1C4:
                if (hbstrt != value) {
-                       if (exthblank) {
-                               record_color_change2(hpos, 0xffff, 0);
-                       }
+                       sync_color_changes(hpos);
                        hbstrt = value & 0x7ff;
                        varsync(addr, 0);
                }
                break;
        case 0x1C6:
                if (hbstop != value) {
-                       if (exthblank) {
-                               record_color_change2(hpos, 0xffff, 0);
-                       }
+                       sync_color_changes(hpos);
                        hbstop = value & 0x7ff;
                        varsync(addr, 0);
                }
@@ -12118,8 +12400,8 @@ uae_u8 *restore_custom(uae_u8 *src)
        SPRHSTOP(-1, RW);               /* 1D2 SPRHSTOP */
        BPLHSTRT(-1, RW);               /* 1D4 BPLHSTRT */
        BPLHSTOP(-1, RW);               /* 1D6 BPLHSTOP */
-       hhpos = RW;                             /* 1D8 HHPOS */
-       RW;                                             /* 1DA ? */
+       hhpos = RW;                             /* 1D8 HHPOSW */
+       RW;                                             /* 1DA HHPOSR */
        new_beamcon0 = RW;              /* 1DC BEAMCON0 */
        hsstrt = RW;                    /* 1DE HSSTRT */
        vsstrt = RW;                    /* 1E0 VSSTT  */
@@ -12127,8 +12409,8 @@ uae_u8 *restore_custom(uae_u8 *src)
        diwhigh = RW;                   /* 1E4 DIWHIGH */
        diwhigh_written = (diwhigh & 0x8000) ? 1 : 0;
        hdiwstate = (diwhigh & 0x4000) ? DIW_waiting_stop : DIW_waiting_start;
-       diwstate = (diwhigh & 0x2000) ? DIW_waiting_start : DIW_waiting_stop;
-       diwhigh &= 0x1fff;
+       diwstate = (diwhigh & 0x0080) ? DIW_waiting_start : DIW_waiting_stop;
+       diwhigh &= 0x3f3f;
        RW;                                             /* 1E6 ? */
        RW;                                             /* 1E8 ? */
        RW;                                             /* 1EA ? */
@@ -12332,12 +12614,12 @@ uae_u8 *save_custom(int *len, uae_u8 *dstptr, int full)
        SW(bplhstrt);           /* 1D4 BPLHSTRT */
        SW(bplhstop);           /* 1D6 BPLHSTOP */
        SW(hhpos);                      /* 1D8 HHPOSW */
-       SW(0);                          /* 1DA */
+       SW(HHPOSR());           /* 1DA HHPOSR */
        SW(new_beamcon0);       /* 1DC BEAMCON0 */
        SW(hsstrt);                     /* 1DE HSSTRT */
        SW(vsstrt);                     /* 1E0 VSSTRT */
        SW(hcenter);            /* 1E2 HCENTER */
-       SW(diwhigh | (diwhigh_written ? 0x8000 : 0) | (hdiwstate == DIW_waiting_stop ? 0x4000 : 0) | (diwstate == DIW_waiting_start ? 0x2000 : 0)); /* 1E4 DIWHIGH */
+       SW(diwhigh | (diwhigh_written ? 0x8000 : 0) | (hdiwstate == DIW_waiting_stop ? 0x4000 : 0) | (diwstate == DIW_waiting_start ? 0x0080 : 0)); /* 1E4 DIWHIGH */
        SW(0);                          /* 1E6 */
        SW(0);                          /* 1E8 */
        SW(0);                          /* 1EA */
index 2f6135bb0bd6e8d1eeeb8f263a44865c8b77b48f..f0ed240ea433815ad12e43d396dd8431cda6b0a1 100644 (file)
--- a/debug.cpp
+++ b/debug.cpp
@@ -1796,7 +1796,7 @@ static void memwatch_heatmap (uaecptr addr, int rwi, int size, uae_u32 accessmas
        hm->mask |= accessmask;
 }
 
-void record_dma_event (int evt, int hpos, int vpos)
+void record_dma_event (uae_u32 evt, int hpos, int vpos)
 {
        struct dma_rec *dr;
 
@@ -1935,6 +1935,7 @@ static bool get_record_dma_info(struct dma_rec *dr, int hpos, int vpos, uae_u32
        TCHAR srtext[10];
        bool extra64 = false;
        uae_u32 extraval;
+       bool noval = false;
 
        if (l1)
                l1[0] = 0;
@@ -1989,6 +1990,7 @@ static bool get_record_dma_info(struct dma_rec *dr, int hpos, int vpos, uae_u32
        } else if (dr->type == DMARECORD_REFRESH) {
                sr = _T("RFS");
                chcnt = br;
+               noval = true;
        } else if (dr->type == DMARECORD_AUDIO) {
                sr = _T("AUD");
                chcnt = br;
@@ -2039,7 +2041,7 @@ static bool get_record_dma_info(struct dma_rec *dr, int hpos, int vpos, uae_u32
                                        _stprintf(l2, _T("%5s %02X"), srtext, r);
                        }
                }
-               if (l3) {
+               if (l3 && !noval) {
                        uae_u64 v = dr->dat;
                        if (longsize == 4) {
                                _stprintf(l3, _T("%08X"), (uae_u32)v);
@@ -2094,6 +2096,48 @@ static bool get_record_dma_info(struct dma_rec *dr, int hpos, int vpos, uae_u32
                        l3[cl2++] = '1';
                if (dr->evt & DMA_EVENT_DDFSTOP2)
                        l3[cl2++] = '2';
+
+               if (dr->evt & DMA_EVENT_HDIWS) {
+                       l3[cl2++] = '(';
+               }
+               if (dr->evt & DMA_EVENT_HDIWE) {
+                       l3[cl2++] = ')';
+               }
+
+               if (dr->evt & DMA_EVENT_HBS) {
+                       l3[cl2++] = '[';
+               }
+               if (dr->evt & DMA_EVENT_HBE) {
+                       l3[cl2++] = ']';
+               }
+               if (dr->evt & DMA_EVENT_HSS) {
+                       l3[cl2++] = '{';
+               }
+               if (dr->evt & DMA_EVENT_HSE) {
+                       l3[cl2++] = '}';
+               }
+
+               if (dr->evt & (DMA_EVENT_VB | DMA_EVENT_VS | DMA_EVENT_LOL | DMA_EVENT_LOF | DMA_EVENT_VDIW)) {
+                       l3[cl2++] = '*';
+               }
+               if (dr->evt & DMA_EVENT_VS) {
+                       l3[cl2++] = 'S';
+               }
+               if (dr->evt & DMA_EVENT_VB) {
+                       l3[cl2++] = 'B';
+               }
+               if (dr->evt & DMA_EVENT_LOL) {
+                       l3[cl2++] = 'L';
+               }
+               if (dr->evt & DMA_EVENT_LOF) {
+                       l3[cl2++] = 'F';
+               }
+               if (dr->evt & DMA_EVENT_VDIW) {
+                       l3[cl2++] = '=';
+               }
+               if (dr->evt & (DMA_EVENT_VB | DMA_EVENT_VS | DMA_EVENT_LOL | DMA_EVENT_LOF | DMA_EVENT_VDIW)) {
+                       l3[cl2++] = 0;
+               }
        }
        if (l5) {
                _stprintf (l5, _T("%08X"), cycles + (vpos * maxhpos + hpos) * CYCLE_UNIT);
@@ -2109,25 +2153,25 @@ static bool get_record_dma_info(struct dma_rec *dr, int hpos, int vpos, uae_u32
 
 static void decode_dma_record (int hpos, int vpos, int toggle, bool logfile)
 {
-       struct dma_rec *dr;
+       struct dma_rec *dr, *dr_start;
        int h, i, maxh;
        uae_u32 cycles;
 
        if (!dma_record[0] || hpos < 0 || vpos < 0)
                return;
-       dr = &dma_record[dma_record_toggle ^ toggle][vpos * NR_DMA_REC_HPOS];
+       dr_start = dr = &dma_record[dma_record_toggle ^ toggle][vpos * NR_DMA_REC_HPOS];
        if (logfile)
                write_dlog (_T("Line: %02X %3d HPOS %02X %3d:\n"), vpos, vpos, hpos, hpos);
        else
                console_out_f (_T("Line: %02X %3d HPOS %02X %3d:\n"), vpos, vpos, hpos, hpos);
        h = hpos;
        dr += hpos;
-       maxh = hpos + (logfile ? maxhpos : 80);
-       if (maxh > maxhpos)
-               maxh = maxhpos;
+       maxh = hpos + (logfile ? maxhpos_short : 80);
+       if (maxh > maxhpos_short)
+               maxh = maxhpos_short;
        cycles = vsync_cycles;
        if (toggle)
-               cycles -= maxvpos * maxhpos * CYCLE_UNIT;
+               cycles -= maxvpos * maxhpos_short * CYCLE_UNIT;
        while (h < maxh) {
                int cols = (logfile ? 16 : 8);
                TCHAR l1[200];
@@ -2144,6 +2188,11 @@ static void decode_dma_record (int hpos, int vpos, int toggle, bool logfile)
                        TCHAR l1l[16], l2l[16], l3l[16], l4l[16], l5l[16];
 
                        get_record_dma_info(dr, h, vpos, cycles, l1l, l2l, l3l, l4l, l5l);
+                       if (dr_start[3 + 2].evt & DMA_EVENT_LOL) {
+                               if (maxh == maxhpos_short) {
+                                       maxh++;
+                               }
+                       }
 
                        TCHAR *p = l1 + _tcslen(l1);
                        _stprintf(p, _T("%9s "), l1l);
@@ -4807,11 +4856,33 @@ static void show_exec_lists (TCHAR *t)
        }
 }
 
+static int debug_vpos = -1;
+static int debug_hpos = -1;
+
 static void breakfunc(uae_u32 v)
 {
        write_log(_T("Cycle breakpoint hit\n"));
        debugging = 1;
-       set_special (SPCFLAG_BRK);
+       set_special(SPCFLAG_BRK);
+}
+
+void debug_hsync(void)
+{
+       if (debug_vpos < 0) {
+               return;
+       }
+       if (debug_vpos != vpos) {
+               return;
+       }
+       if (debug_hpos <= 0) {
+               breakfunc(0);
+       } else {
+               if (current_hpos() < debug_hpos) {
+                       event2_newevent_x(-1, debug_hpos - current_hpos(), 0, breakfunc);
+               } else {
+                       breakfunc(0);
+               }
+       }
 }
 
 static int cycle_breakpoint(TCHAR **c)
@@ -4822,27 +4893,22 @@ static int cycle_breakpoint(TCHAR **c)
                int count = readint(c);
                if (nc == 's') {
                        if (more_params(c)) {
-                               int mvp = maxvpos + lof_store;
-                               int hp = readint(c);
-                               int chp = current_hpos();
-                               if (count == vpos && chp < hp) {
-                                       count += mvp - vpos;
-                               } else if (count >= vpos) {
-                                       count = count - vpos;
+                               debug_vpos = count;
+                               debug_hpos = readint(c);
+                               if (debug_vpos == vpos && debug_hpos > current_hpos()) {
+                                       debug_vpos = -1;
+                                       count = debug_hpos - current_hpos();
+                                       debug_hpos = -1;
                                } else {
-                                       count += mvp - vpos;
-                               }
-                               count *= maxhpos;
-                               if (hp >= chp) {
-                                       count += hp - chp;
-                               } else {
-                                       count += maxhpos - chp;
+                                       return 1;
                                }
                        } else {
                                count *= maxhpos;
                        }
                }
-               event2_newevent_x(-1, count, 0, breakfunc);
+               if (count > 0) {
+                       event2_newevent_x(-1, count, 0, breakfunc);
+               }
                return 1;
        }
        return 0;
index 4abf7dba3fb15276cd7e9ad973ff2816eb02898f..d79129d5cc12fe1933b826abed8a7e8b7fe7e8f0 100644 (file)
@@ -252,8 +252,7 @@ static int visible_top_start, visible_bottom_stop;
 /* same for blank */
 static int vblank_top_start, vblank_bottom_stop;
 static int hblank_left_start, hblank_right_stop;
-static bool exthblank;
-static bool extborder;
+static bool exthblank, extborder, exthblanken;
 
 static int linetoscr_x_adjust_pixbytes, linetoscr_x_adjust_pixels;
 static int thisframe_y_adjust;
@@ -471,12 +470,10 @@ static void reset_custom_limits(void)
        center_reset = true;
 }
 
-static void set_blanking_limits(void)
+static void reset_hblanking_limits(void)
 {
        hblank_left_start = visible_left_start;
        hblank_right_stop = visible_right_stop;
-       vblank_top_start = visible_top_start;
-       vblank_bottom_stop = visible_bottom_stop;
 
        if (hblank_left_start < visible_left_border) {
                hblank_left_start = visible_left_border;
@@ -484,6 +481,15 @@ static void set_blanking_limits(void)
        if (hblank_right_stop > visible_right_border) {
                hblank_right_stop = visible_right_border;
        }
+}
+
+// this handles hardwired vblank
+// vb_state in do_color_changes() handles programmed vblank
+static void set_vblanking_limits(void)
+{
+       vblank_top_start = visible_top_start;
+       vblank_bottom_stop = visible_bottom_stop;
+
        if (vblank_top_start < visible_top_start) {
                vblank_top_start = visible_top_start;
        }
@@ -491,6 +497,34 @@ static void set_blanking_limits(void)
                vblank_bottom_stop = visible_bottom_stop;
        }
 
+       bool hardwired = false;
+       if (ecs_agnus) {
+               hardwired = (new_beamcon0 & 0x1000) == 0;
+       }
+       if (hardwired) {
+               int vbstrt = vblank_firstline_hw;
+               int vbstop = maxvpos + lof_store;
+               if (currprefs.cs_dipagnus) {
+                       vbstop++;
+               }
+               if (currprefs.gfx_overscanmode < OVERSCANMODE_OVERSCAN) {
+                       int mult = (OVERSCANMODE_OVERSCAN - currprefs.gfx_overscanmode) * 5;
+                       vbstrt += mult;
+                       vbstop -= mult;
+               }
+               vbstrt <<= currprefs.gfx_vresolution;
+               vbstop <<= currprefs.gfx_vresolution;
+               if (vblank_top_start < vbstrt) {
+                       vblank_top_start = vbstrt;
+               }
+               if (vblank_bottom_stop > vbstop) {
+                       vblank_bottom_stop = vbstop;
+               }
+       }
+}
+
+static void set_hblanking_limits(void)
+{
        // horizontal blanking
        bool hardwired = !dp_for_drawing || !ce_is_extblankset(colors_for_drawing.extra);
        bool doblank = false;
@@ -507,7 +541,6 @@ static void set_blanking_limits(void)
                }
        }
        if (hardwired) {
-               exthblank = false;
                doblank = true;
        } else if (currprefs.gfx_overscanmode <= OVERSCANMODE_OVERSCAN) {
                doblank = true;
@@ -538,31 +571,6 @@ static void set_blanking_limits(void)
                        hblank_right_stop = coord_hw_to_window_x_shres(hbstrt);
                }
        }
-
-       if (aga_mode) {
-               hardwired = (new_beamcon0 & 0x1000) == 0;
-       }
-       // vb_state handles programmed vblank
-       if (hardwired) {
-               int vbstrt = vblank_firstline_hw;
-               int vbstop = vblank_lastline_hw;
-
-               if (currprefs.gfx_overscanmode < OVERSCANMODE_OVERSCAN) {
-                       int mult = (OVERSCANMODE_OVERSCAN - currprefs.gfx_overscanmode) * 5;
-                       vbstrt += mult;
-                       vbstop -= mult;
-               }
-
-               vbstrt <<= currprefs.gfx_vresolution;
-               vbstop <<= currprefs.gfx_vresolution;
-               if (vblank_top_start < vbstrt) {
-                       vblank_top_start = vbstrt;
-               }
-               if (vblank_bottom_stop > vbstop) {
-                       vblank_bottom_stop = vbstop;
-               }
-       }
-
 }
 
 void get_custom_raw_limits(int *pw, int *ph, int *pdx, int *pdy)
@@ -1141,12 +1149,17 @@ static void pfield_init_linetoscr (int lineno, bool border)
        }
 #endif
 
-       // AGA borderblank starts horizontally 1 hires pixel before bitplanes start, leaving 1 hires pixel background color gap
+       // AGA borderblank starts horizontally 1 shres pixel before bitplanes start
        playfield_start_pre = playfield_start;
        playfield_end_pre = playfield_end;
        if (currprefs.chipset_hr && aga_mode && bplres > 0) {
-               playfield_start_pre -= bplres;
-               playfield_end_pre -= bplres;
+               if (currprefs.gfx_resolution == RES_SUPERHIRES) {
+                       playfield_start_pre -= 1;
+                       playfield_end_pre -= 1;
+               } else {
+                       playfield_start_pre &= ~1;
+                       playfield_end_pre &= ~1;
+               }
        }
 
        unpainted = visible_left_border < playfield_start ? 0 : visible_left_border - playfield_start;
@@ -1375,7 +1388,7 @@ static void fill_line_border(int lineno)
 {
        struct vidbuf_description *vidinfo = &adisplays[0].gfxvidinfo;
        int lastpos = visible_left_border;
-       int endpos = visible_right_border;
+       int endpos = visible_left_border + vidinfo->drawbuffer.inwidth;
        int w = endpos - lastpos;
 
        if (lineno < visible_top_start || lineno < vblank_top_start || lineno >= visible_bottom_stop || lineno >= vblank_bottom_stop) {
@@ -1432,6 +1445,13 @@ 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) {
+               return 0;
+       }
+       if (extborder && (ce_is_borderblank(colors_for_drawing.extra) || !ce_is_bordersprite(colors_for_drawing.extra))) {
+               return 0;
+       }
+
        // If 64 pixel wide sprite and FMODE gets lowered when sprite's
        // first 32 pixels are being drawn: matching pixel(s) in second
        // 32 pixel part gets blanked.
@@ -3054,6 +3074,16 @@ static bool isham(uae_u16 bplcon0)
        return 0;
 }
 
+static void extblankcheck(void)
+{
+       if (exthblanken && ((dp_for_drawing->bplcon3 & 1) && (dp_for_drawing->bplcon0 & 1))) {
+               exthblank = true;
+       }
+       if (exthblanken && (!(dp_for_drawing->bplcon3 & 1) || !(dp_for_drawing->bplcon0 & 1))) {
+               exthblank = false;
+       }
+}
+
 static void pfield_expand_dp_bplconx (int regno, int v, int hp, int vp)
 {
        regno -= RECORDED_REGISTER_CHANGE_OFFSET;
@@ -3068,6 +3098,7 @@ static void pfield_expand_dp_bplconx (int regno, int v, int hp, int vp)
                dp_for_drawing->ham_seen = isham(v);
                if (currprefs.chipset_hr && dp_for_drawing->bplres < currprefs.gfx_resolution)
                        dp_for_drawing->bplres = currprefs.gfx_resolution;
+               extblankcheck();
                break;
        case 0x104: // BPLCON2
                dp_for_drawing->bplcon2 = v;
@@ -3075,6 +3106,7 @@ static void pfield_expand_dp_bplconx (int regno, int v, int hp, int vp)
 #ifdef ECS_DENISE
        case 0x106: // BPLCON3
                dp_for_drawing->bplcon3 = v;
+               extblankcheck();
                break;
 #endif
 #ifdef AGA
@@ -3089,7 +3121,17 @@ static void pfield_expand_dp_bplconx (int regno, int v, int hp, int vp)
                dp_for_drawing->fmode = v;
                break;
        case 0x200: // hblank
-               exthblank = v != 0;
+               if (v) {
+                       exthblanken = true;
+                       if (vp >= 0) {
+                               extblankcheck();
+                       } else {
+                               exthblank = true;
+                       }
+               } else {
+                       exthblanken = false;
+                       exthblank = false;
+               }
                return;
 #endif
        }
@@ -3102,15 +3144,15 @@ static enum { color_match_acolors, color_match_full } color_match_type;
 
 /* Set up colors_for_drawing to the state at the beginning of the currently drawn
 line.  Try to avoid copying color tables around whenever possible.  */
-static void adjust_drawing_colors (int ctable, int need_full)
+static void adjust_drawing_colors (int ctable, int need_full, bool blankcheck)
 {
+       uae_u16 oe = colors_for_drawing.extra;
        if (drawing_color_matches != ctable || need_full < 0) {
                if (need_full) {
                        color_reg_cpy (&colors_for_drawing, curr_color_tables + ctable);
                        color_match_type = color_match_full;
                } else {
-                       memcpy (colors_for_drawing.acolors, curr_color_tables[ctable].acolors,
-                               sizeof colors_for_drawing.acolors);
+                       memcpy (colors_for_drawing.acolors, curr_color_tables[ctable].acolors, sizeof colors_for_drawing.acolors);
                        colors_for_drawing.extra = curr_color_tables[ctable].extra;
                        color_match_type = color_match_acolors;
                }
@@ -3119,6 +3161,10 @@ static void adjust_drawing_colors (int ctable, int need_full)
                color_reg_cpy (&colors_for_drawing, &curr_color_tables[ctable]);
                color_match_type = color_match_full;
        }
+       if (colors_for_drawing.extra != oe) {
+               reset_hblanking_limits();
+               set_hblanking_limits();
+       }
 }
 
 static void playfield_hard_way(line_draw_func worker_pfield, int first, int last)
@@ -3222,7 +3268,7 @@ static void do_color_changes(line_draw_func worker_border, line_draw_func worker
                                }
 
                        } else {
-                               // special AGA borderblank 1 hires pixel delay
+                               // special AGA borderblank 1 shres pixel delay
 
                                // borderblank left border (hblank end to playfield_start_pre)
                                if (nextpos_in_range > lastpos && lastpos < playfield_start_pre) {
@@ -3230,14 +3276,14 @@ static void do_color_changes(line_draw_func worker_border, line_draw_func worker
                                        (*worker_border)(lastpos, t, 0);
                                        lastpos = t;
                                }
-                               // AGA "buggy" borderblank, real background color visible, single hires pixel wide.
+                               // AGA "buggy" borderblank, real background color visible, single shres pixel wide.
                                if (nextpos_in_range > lastpos && lastpos < playfield_start) {
                                        int t = nextpos_in_range <= playfield_start ? nextpos_in_range : playfield_start;
                                        (*worker_border)(lastpos, t, -1);
                                        lastpos = t;
                                }
 
-                               // playfield with last hires pixel not drawn.
+                               // playfield with last shres pixel not drawn.
                                if (nextpos_in_range > lastpos && lastpos >= playfield_start && lastpos < playfield_end_pre) {
                                        int t = nextpos_in_range <= playfield_end_pre ? nextpos_in_range : playfield_end_pre;
                                        if (may_require_hard_way && (may_require_hard_way < 0 || (bplxor && may_require_hard_way && worker_pfield != pfield_do_linetoscr_bordersprite_aga))) {
@@ -3248,7 +3294,7 @@ static void do_color_changes(line_draw_func worker_border, line_draw_func worker
                                        lastpos = t;
                                }
 
-                               // last 1 hires pixel of playfield blanked
+                               // last shres pixel of playfield blanked
                                if (nextpos_in_range > lastpos && lastpos >= playfield_end_pre && lastpos < playfield_end) {
                                        int t = nextpos_in_range <= playfield_end ? nextpos_in_range : playfield_end;
                                        (*worker_border)(lastpos, t, 0);
@@ -3424,12 +3470,11 @@ static void pfield_draw_line(struct vidbuffer *vb, int lineno, int gfx_ypos, int
        if (border == 0) {
 
                pfield_expand_dp_bplcon();
-               set_blanking_limits();
+               // must be after pfield_expand_dp_bplcon
+               adjust_drawing_colors(dp_for_drawing->ctable, dp_for_drawing->ham_seen || bplehb || ecsshres, true);
                pfield_init_linetoscr(lineno, false);
                pfield_doline(lineno);
 
-               adjust_drawing_colors(dp_for_drawing->ctable, dp_for_drawing->ham_seen || bplehb || ecsshres);
-
                /* The problem is that we must call decode_ham() BEFORE we do the sprites. */
                if (dp_for_drawing->ham_seen) {
                        int ohposblank = hposblank;
@@ -3443,7 +3488,7 @@ static void pfield_draw_line(struct vidbuffer *vb, int lineno, int gfx_ypos, int
                        do_color_changes(dummy_worker, decode_ham, lineno);
                        if (have_color_changes) {
                                // do_color_changes() did color changes and register changes, restore them.
-                               adjust_drawing_colors(dp_for_drawing->ctable, -1);
+                               adjust_drawing_colors(dp_for_drawing->ctable, -1, false);
                                dp_for_drawing->bplcon0 = b0;
                                dp_for_drawing->bplcon2 = b2;
                                dp_for_drawing->bplcon3 = b3;
@@ -3502,7 +3547,7 @@ static void pfield_draw_line(struct vidbuffer *vb, int lineno, int gfx_ypos, int
 
                bool dosprites = false;
 
-               adjust_drawing_colors(dp_for_drawing->ctable, 0);
+               adjust_drawing_colors(dp_for_drawing->ctable, 0, true);
 
 #ifdef AGA /* this makes things complex.. */
                if (dp_for_drawing->bordersprite_seen && !ce_is_borderblank(colors_for_drawing.extra) && dip_for_drawing->nr_sprites) {
@@ -3578,8 +3623,6 @@ static void pfield_draw_line(struct vidbuffer *vb, int lineno, int gfx_ypos, int
        }
 }
 
-extern int hsync_end_left_border;
-
 static void center_image (void)
 {
        struct amigadisplay *ad = &adisplays[0];
@@ -3608,7 +3651,7 @@ static void center_image (void)
 #endif
        } else if (vidinfo->drawbuffer.extrawidth > 0 || currprefs.gfx_overscanmode == OVERSCANMODE_EXTREME) {
                // extreme wide mode
-               visible_left_border = (hsync_end_left_border * 2) << currprefs.gfx_resolution;
+               visible_left_border = (hsync_end_left_border * 2 + 1) << currprefs.gfx_resolution;
        } else if (ew == -1) {
                // wide mode
                visible_left_border = (hsync_end_left_border * 2) << currprefs.gfx_resolution;
@@ -4132,7 +4175,9 @@ static void draw_frame2(struct vidbuffer *vbin, struct vidbuffer *vbout)
        int largest = 0;
 #endif
 
-       set_blanking_limits();
+       set_vblanking_limits();
+       reset_hblanking_limits();
+       set_hblanking_limits();
 
        bool firstline = true;
        int lastline = thisframe_y_adjust_real - (1 << linedbl);
@@ -4166,6 +4211,9 @@ static void draw_frame2(struct vidbuffer *vbin, struct vidbuffer *vbout)
                        largest = whereline;
 #endif
 
+               reset_hblanking_limits();
+               set_hblanking_limits();
+
                hposblank = 0;
                pfield_draw_line(vbout, line, whereline, wherenext);
        }
@@ -4243,7 +4291,9 @@ void draw_lines(int end, int section)
        if (!lockscr(vb, false, vb->last_drawn_line ? false : true))
                return;
 
-       set_blanking_limits();
+       set_vblanking_limits();
+       reset_hblanking_limits();
+       set_hblanking_limits();
 
        bool firstline = true;
        int lastline = thisframe_y_adjust_real - (1 << linedbl);
@@ -4828,6 +4878,9 @@ void reset_drawing(void)
 
        max_diwstop = 0;
        vb_state = 0;
+       exthblank = false;
+       exthblanken = false;
+       extborder = false;
 
        lores_reset ();
 
index 67d8d97c74b8851059cdecd9ea8526191f1d44a7..f0038910fbc49e6ee607943aadf8d21b5b5ec6f7 100644 (file)
@@ -366,12 +366,12 @@ const struct customData custd[] =
        { _T("VSSTOP"),   0xdff1CA, CD_WO | CD_ECS_AGNUS }, /* Vert line for VBLANK start */
        { _T("VBSTRT"),   0xdff1CC, CD_WO | CD_ECS_AGNUS }, /* Vert line for VBLANK start */
        { _T("VBSTOP"),   0xdff1CE, CD_WO | CD_ECS_AGNUS }, /* Vert line for VBLANK stop */
-       { _T("-"), 0xdff1D0, CD_NONE }, /* UHRES sprite vertical start */
-       { _T("-"), 0xdff1D2, CD_NONE }, /* UHRES sprite vertical stop */
-       { _T("-"), 0xdff1D4, CD_NONE }, /* UHRES bit plane vertical stop */
-       { _T("-"), 0xdff1D6, CD_NONE }, /* UHRES bit plane vertical stop */
-       { _T("-"), 0xdff1D8, CD_NONE }, /* DUAL mode hires H beam counter write */
-       { _T("-"), 0xdff1DA, CD_NONE }, /* DUAL mode hires H beam counter read */
+       { _T("SPRHSTRT"), 0xdff1D0, CD_WO | CD_ECS_AGNUS }, /* UHRES sprite vertical start */
+       { _T("SPRHSTOP"), 0xdff1D2, CD_WO | CD_ECS_AGNUS }, /* UHRES sprite vertical stop */
+       { _T("BPLHSTRT"), 0xdff1D4, CD_WO | CD_ECS_AGNUS }, /* UHRES bit plane vertical stop */
+       { _T("BPLHSTOP"), 0xdff1D6, CD_WO | CD_ECS_AGNUS }, /* UHRES bit plane vertical stop */
+       { _T("HHPOSW"),   0xdff1D8, CD_WO | CD_ECS_AGNUS }, /* DUAL mode hires H beam counter write */
+       { _T("HHPOSR"),   0xdff1DA,     0 | CD_ECS_AGNUS }, /* DUAL mode hires H beam counter read */
        { _T("BEAMCON0"), 0xdff1DC, CD_WO | CD_ECS_AGNUS }, /* Beam counter control register (SHRES,UHRES,PAL) */
        { _T("HSSTRT"),   0xdff1DE, CD_WO | CD_ECS_DENISE }, /* Horizontal sync start (VARHSY) */
        { _T("VSSTRT"),   0xdff1E0, CD_WO | CD_ECS_DENISE }, /* Vertical sync start (VARVSY) */
index d510aae935eaff8c69e36da97ca595c24f9921f4..15dbd3718a4fc7f3242ddf33920ef7fa405b6474 100644 (file)
@@ -135,7 +135,7 @@ extern float vblank_hz, fake_vblank_hz;
 extern float hblank_hz;
 extern int vblank_skip, doublescan;
 extern int programmedmode;
-extern int vblank_firstline_hw, vblank_lastline_hw;
+extern int vblank_firstline_hw;
 
 #define DMA_AUD0      0x0001
 #define DMA_AUD1      0x0002
@@ -165,11 +165,12 @@ extern unsigned long frametime, timeframes;
 extern uae_u16 htotal, vtotal, beamcon0, new_beamcon0;
 
 // 100 words give you 1600 horizontal pixels. Should be more than enough for superhires. 
+// Extreme overscan superhires needs more.
 // must be divisible by 8
 #ifdef CUSTOM_SIMPLE
 #define MAX_WORDS_PER_LINE 56
 #else
-#define MAX_WORDS_PER_LINE 104
+#define MAX_WORDS_PER_LINE 112
 #endif
 
 extern uae_u32 hirestab_h[256][2];
index d00a4e9de3b79454c0f135e4e25adb0a3ed2e69c..8541332202e5e30825027cc652c78844c6a72bb7 100644 (file)
@@ -71,6 +71,7 @@ extern int memwatch_access_validator;
 #define DEBUG_SPRINTF_ADDRESS 0xbfff00
 extern bool debug_sprintf(uaecptr, uae_u32, int);
 extern bool debug_get_prefetch(int idx, uae_u16 *opword);
+extern void debug_hsync(void);
 
 extern void debug_init_trainer(const TCHAR*);
 extern void debug_trainer_match(void);
@@ -218,7 +219,7 @@ struct dma_rec
     uae_u64 dat;
        uae_u16 size;
     uae_u32 addr;
-    uae_u16 evt;
+    uae_u32 evt;
     uae_s16 type;
        uae_u16 extra;
        uae_s8 intlev;
@@ -243,6 +244,18 @@ extern struct dma_rec *last_dma_rec;
 #define DMA_EVENT_DDFSTOP 8192
 #define DMA_EVENT_DDFSTOP2 16384
 #define DMA_EVENT_SPECIAL 32768
+#define DMA_EVENT_VB 0x10000
+#define DMA_EVENT_VS 0x20000
+#define DMA_EVENT_LOF 0x40000
+#define DMA_EVENT_LOL 0x80000
+#define DMA_EVENT_HBS 0x100000
+#define DMA_EVENT_HBE 0x200000
+#define DMA_EVENT_HDIWS 0x400000
+#define DMA_EVENT_HDIWE 0x800000
+#define DMA_EVENT_VDIW 0x1000000
+#define DMA_EVENT_HSS 0x2000000
+#define DMA_EVENT_HSE 0x4000000
+
 
 #define DMARECORD_REFRESH 1
 #define DMARECORD_CPU 2
@@ -260,7 +273,7 @@ extern void record_dma_read_value(uae_u32 v);
 extern void record_dma_read_value_wide(uae_u64 v, bool quad);
 extern void record_dma_replace(int hpos, int vpos, int type, int extra);
 extern void record_dma_reset(void);
-extern void record_dma_event(int evt, int hpos, int vpos);
+extern void record_dma_event(uae_u32 evt, int hpos, int vpos);
 extern void debug_draw(uae_u8 *buf, int bpp, int line, int width, int height, uae_u32 *xredcolors, uae_u32 *xgreencolors, uae_u32 *xbluescolors);
 
 #define TRACE_SKIP_INS 1
index cc552f02fd58cb56717eee558d0ddfdfa151b08b..34713abc330510d5048277513bf2fbbf8c533691 100644 (file)
@@ -248,7 +248,7 @@ struct color_change {
 #ifdef UAE_MINI
 #define MAX_PIXELS_PER_LINE 880
 #else
-#define MAX_PIXELS_PER_LINE 2048
+#define MAX_PIXELS_PER_LINE 2304
 #endif
 
 #define MAXVPOS_WRAPLINES 10
index ec9ec74ad8e63e4c609bb7d156d2c64372bf7738..715757811b5a96be3829c5d0b04859966b19ac78 100644 (file)
@@ -107,6 +107,7 @@ STATIC_INLINE void set_cycles (unsigned long int x)
 {
        currcycle = x;
        eventtab[ev_hsync].oldcycles = x;
+       eventtab[ev_hsynch].active = 0;
 #ifdef EVT_DEBUG
        if (currcycle & (CYCLE_UNIT - 1))
                write_log (_T("%x\n"), currcycle);