]> git.unchartedbackwaters.co.uk Git - francis/winuae.git/commitdiff
Custom emulation update WIP.
authorToni Wilen <twilen@winuae.net>
Sat, 12 Jun 2021 17:19:56 +0000 (20:19 +0300)
committerToni Wilen <twilen@winuae.net>
Sat, 12 Jun 2021 17:19:56 +0000 (20:19 +0300)
14 files changed:
blitter.cpp
cfgfile.cpp
custom.cpp
debug.cpp
drawing.cpp
include/custom.h
include/debug.h
include/drawing.h
include/options.h
include/xwin.h
inputdevice.cpp
od-win32/resources/resource.h
od-win32/resources/winuae.rc
od-win32/win32gui.cpp

index 7159882b919a6ba43643d9944c0e14befc83191e..777c358902d441bf803c3f79c7bb40e6f2c6920f 100644 (file)
@@ -385,15 +385,23 @@ static void reset_channel_mods (void)
        }
 }
 
-static void check_channel_mods (int hpos, int ch)
+static void check_channel_mods(int hpos, int ch, uaecptr *pt)
 {
        static int blit_warned = 100;
+
+       if (bltptxpos < 0)
+               return;
+       hpos--;
+       if (hpos < 0) {
+               hpos += maxhpos;
+       }
        if (bltptxpos != hpos)
                return;
        if (ch == bltptxc) {
                bltptxpos = -1;
+               *pt = bltptx;
                if (blit_warned > 0) {
-                       write_log(_T("BLITTER: %08X write to %cPT ignored! %08x\n"), bltptx, ch + 'A' - 1, m68k_getpc());
+                       write_log(_T("BLITTER: %08X -> %08X write to %cPT ignored! %08x\n"), bltptx, *pt, ch + 'A' - 1, m68k_getpc());
                        blit_warned--;
                }
        }
@@ -956,7 +964,7 @@ static void blit_bltset(int con)
 
        blit_cyclecount = 4 - (shifter_skip_b + shifter_skip_y);
        blit_dmacount = ((bltcon0 & 0x800) ? 1 : 0) + ((bltcon0 & 0x400) ? 1 : 0) +
-               ((bltcon0 & 0x200) ? 1 : 0) + ((bltcon0 & 0x100) ? 1 : 0);
+               ((bltcon0 & 0x200) ? 1 : 0) + (((bltcon0 & 0x100) && !blitline) ? 1 : 0);
 
        if (blt_info.blit_main || blt_info.blit_pending) {
                blitfill_c = blitfill;
@@ -1195,6 +1203,8 @@ static int blitter_next_cycle(void)
 
 static void blitter_doddma_new(int hpos, bool addmod)
 {
+       check_channel_mods(hpos, 4, &bltdpt);
+
        record_dma_blit(0x00, ddat1, bltdpt, hpos);
        chipmem_agnus_wput2(bltdpt, ddat1);
        alloc_cycle_blitter(hpos, &bltdpt, 4);
@@ -1216,6 +1226,7 @@ static void blitter_dodma_new(int ch, int hpos, bool addmod)
        switch (ch)
        {
        case 1: // A
+               check_channel_mods(hpos, 1, &bltapt);
                reg = 0x74;
                record_dma_blit(reg, 0, bltapt, hpos);
                blt_info.bltadat = dat = chipmem_wget_indirect(bltapt);
@@ -1226,6 +1237,7 @@ static void blitter_dodma_new(int ch, int hpos, bool addmod)
                alloc_cycle_blitter(hpos, &bltapt, 1);
                break;
        case 2: // B
+               check_channel_mods(hpos, 2, &bltbpt);
                reg = 0x72;
                record_dma_blit(reg, 0, bltbpt, hpos);
                blt_info.bltbdat = dat = chipmem_wget_indirect(bltbpt);
@@ -1243,6 +1255,7 @@ static void blitter_dodma_new(int ch, int hpos, bool addmod)
                break;
        case 3: // C
                reg = 0x70;
+               check_channel_mods(hpos, 3, &bltcpt);
                record_dma_blit(reg, 0, bltcpt, hpos);
                blt_info.bltcdat = dat = chipmem_wget_indirect(bltcpt);
                record_dma_blit_val(dat);
@@ -1462,9 +1475,6 @@ static bool decide_blitter_maybe_write2(int until_hpos, uaecptr addr, uae_u32 va
                        if (dat & BLITTER_PIPELINE_PROCESS) {
                                blitfc = !!(bltcon1 & 0x4);
                        }
-
-                       // check this after end check because last D write won't cause any problems.
-                       check_channel_mods(hpos, c);
                        break;
                }
 
@@ -1593,10 +1603,10 @@ static bool decide_blitter_maybe_write2(int until_hpos, uaecptr addr, uae_u32 va
                }
 
                hpos++;
+               bltptxpos = -1;
        }
 
        last_blitter_hpos = until_hpos;
-       reset_channel_mods();
        if (hsync) {
                last_blitter_hpos = 0;
        }
@@ -1875,8 +1885,6 @@ void maybe_blit (int hpos, int hack)
 {
        static int warned = 10;
 
-       reset_channel_mods();
-
        if (!blt_info.blit_main) {
                decide_blitter(hpos);
                return;
index b9b9fcc5ab28af88980e86481a9218422a79f203..115ce0e352f81319bd324b22809bcb18418fb11a 100644 (file)
@@ -2266,7 +2266,8 @@ void cfgfile_save_options (struct zfile *f, struct uae_prefs *p, int type)
        cfgfile_write_str(f, _T("gfx_api"), filterapi[p->gfx_api]);
        cfgfile_write_str(f, _T("gfx_api_options"), filterapiopts[p->gfx_api_options]);
        cfgfile_dwrite_bool(f, _T("gfx_hdr"), p->gfx_hdr);
-       cfgfile_dwrite(f, _T("gfx_horizontal_tweak"), _T("%d"), p->gfx_extrawidth);
+       cfgfile_dwrite(f, _T("gfx_horizontal_extra"), _T("%d"), p->gfx_extrawidth);
+       cfgfile_dwrite(f, _T("gfx_vertical_extra"), _T("%d"), p->gfx_extraheight);
        cfgfile_dwrite(f, _T("gfx_frame_slices"), _T("%d"), p->gfx_display_sections);
        cfgfile_dwrite_bool(f, _T("gfx_vrr_monitor"), p->gfx_variable_sync != 0);
 
@@ -2525,7 +2526,7 @@ void cfgfile_save_options (struct zfile *f, struct uae_prefs *p, int type)
        cfgfile_dwrite_bool(f, _T("z3_autoconfig"), p->cs_z3autoconfig);
        cfgfile_dwrite_bool(f, _T("1mchipjumper"), p->cs_1mchipjumper);
        cfgfile_dwrite_bool(f, _T("color_burst"), p->cs_color_burst);
-       cfgfile_dwrite_bool(f, _T("hsync_glitch"), p->cs_ocshsyncbug);
+       cfgfile_dwrite_bool(f, _T("hblank_glitch"), p->cs_ocshblankbug);
        cfgfile_dwrite_bool(f, _T("toshiba_gary"), p->cs_toshibagary);
        cfgfile_dwrite_bool(f, _T("rom_is_slow"), p->cs_romisslow);
        cfgfile_dwrite_str(f, _T("ciaa_type"), ciatype[p->cs_ciatype[0]]);
@@ -3410,15 +3411,16 @@ static int cfgfile_parse_host (struct uae_prefs *p, TCHAR *option, TCHAR *value)
                || cfgfile_string (option, value, _T("filesys_inject_icons_project"), p->filesys_inject_icons_project, sizeof p->filesys_inject_icons_project / sizeof (TCHAR))
                || cfgfile_string (option, value, _T("filesys_inject_icons_tool"), p->filesys_inject_icons_tool, sizeof p->filesys_inject_icons_tool / sizeof (TCHAR))
 
-               || cfgfile_intval (option, value, _T("gfx_luminance"), &p->gfx_luminance, 1)
-               || cfgfile_intval (option, value, _T("gfx_contrast"), &p->gfx_contrast, 1)
-               || cfgfile_intval (option, value, _T("gfx_gamma"), &p->gfx_gamma, 1)
-               || cfgfile_intval (option, value, _T("gfx_gamma_r"), &p->gfx_gamma_ch[0], 1)
-               || cfgfile_intval (option, value, _T("gfx_gamma_g"), &p->gfx_gamma_ch[1], 1)
-               || cfgfile_intval (option, value, _T("gfx_gamma_b"), &p->gfx_gamma_ch[2], 1)
-               || cfgfile_floatval (option, value, _T("rtg_vert_zoom_multf"), &p->rtg_vert_zoom_mult)
-               || cfgfile_floatval (option, value, _T("rtg_horiz_zoom_multf"), &p->rtg_horiz_zoom_mult)
-               || cfgfile_intval (option, value, _T("gfx_horizontal_tweak"), &p->gfx_extrawidth, 1)
+               || cfgfile_intval(option, value, _T("gfx_luminance"), &p->gfx_luminance, 1)
+               || cfgfile_intval(option, value, _T("gfx_contrast"), &p->gfx_contrast, 1)
+               || cfgfile_intval(option, value, _T("gfx_gamma"), &p->gfx_gamma, 1)
+               || cfgfile_intval(option, value, _T("gfx_gamma_r"), &p->gfx_gamma_ch[0], 1)
+               || cfgfile_intval(option, value, _T("gfx_gamma_g"), &p->gfx_gamma_ch[1], 1)
+               || cfgfile_intval(option, value, _T("gfx_gamma_b"), &p->gfx_gamma_ch[2], 1)
+               || cfgfile_floatval(option, value, _T("rtg_vert_zoom_multf"), &p->rtg_vert_zoom_mult)
+               || cfgfile_floatval(option, value, _T("rtg_horiz_zoom_multf"), &p->rtg_horiz_zoom_mult)
+               || cfgfile_intval(option, value, _T("gfx_horizontal_extra"), &p->gfx_extrawidth, 1)
+               || cfgfile_intval(option, value, _T("gfx_vertical_extra"), &p->gfx_extraheight, 1)
 
                || cfgfile_intval (option, value, _T("floppy0sound"), &p->floppyslots[0].dfxclick, 1)
                || cfgfile_intval (option, value, _T("floppy1sound"), &p->floppyslots[1].dfxclick, 1)
@@ -5540,7 +5542,7 @@ static int cfgfile_parse_hardware (struct uae_prefs *p, const TCHAR *option, TCH
                || cfgfile_yesno(option, value, _T("ics_agnus"), &p->cs_dipagnus)
                || cfgfile_yesno(option, value, _T("z3_autoconfig"), &p->cs_z3autoconfig)
                || cfgfile_yesno(option, value, _T("color_burst"), &p->cs_color_burst)
-               || cfgfile_yesno(option, value, _T("hsync_glitch"), &p->cs_ocshsyncbug)
+               || cfgfile_yesno(option, value, _T("hblank_glitch"), &p->cs_ocshblankbug)
                || cfgfile_yesno(option, value, _T("toshiba_gary"), &p->cs_toshibagary)
                || cfgfile_yesno(option, value, _T("rom_is_slow"), &p->cs_romisslow)
                || cfgfile_yesno(option, value, _T("1mchipjumper"), &p->cs_1mchipjumper)
@@ -8006,7 +8008,7 @@ void default_prefs (struct uae_prefs *p, bool reset, int type)
        p->cs_ciatodbug = false;
        p->cs_unmapped_space = 0;
        p->cs_color_burst = false;
-       p->cs_ocshsyncbug = false;
+       p->cs_ocshblankbug = false;
        p->cs_ciatype[0] = 0;
        p->cs_ciatype[1] = 0;
 
@@ -9024,7 +9026,7 @@ int built_in_chipset_prefs (struct uae_prefs *p)
        p->cs_1mchipjumper = false;
        p->cs_unmapped_space = 0;
        p->cs_color_burst = false;
-       p->cs_ocshsyncbug = false;
+       p->cs_ocshblankbug = false;
        p->cs_romisslow = false;
        p->cs_toshibagary = false;
        p->cs_ciatype[0] = p->cs_ciatype[1] = 0;
index 2c97c6369229c66b419efef885aac1478cffbf6e..23d25dbab709db9a7725602fa6fbcaae25ff2558 100644 (file)
@@ -120,7 +120,7 @@ int lof_store; // real bit in custom registers
 static int lof_current; // what display device thinks
 static bool lof_lastline, lof_prev_lastline;
 static int lol;
-static int next_lineno, prev_lineno;
+static int next_lineno;
 static enum nln_how nextline_how;
 static int lof_changed = 0, lof_changing = 0, interlace_changed = 0;
 static int lof_changed_previous_field;
@@ -136,7 +136,6 @@ static bool genlockvtoggle;
 static bool graphicsbuffer_retry;
 static int cia_hsync;
 static bool toscr_scanline_complex_bplcon1, toscr_scanline_complex_bplcon1_off;
-static bool cant_this_last_line;
 
 #define LOF_TOGGLES_NEEDED 3
 //#define NLACE_CNT_NEEDED 50
@@ -283,10 +282,19 @@ int maxhpos_short = MAXHPOS_PAL;
 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
+static int maxhpos_display = AMIGA_WIDTH_MAX;
+int maxvpos_display_vsync; // extra lines from top visible in bottom
+static int vblank_extraline;
 static int maxhposm1;
 static bool maxhposeven;
 int hsyncendpos, hsyncstartpos;
+int hsync_end_left_border;
 static int hsyncstartpos_start;
+
+static int hsyncstartpos_start_hw;
+int hsyncstartpos_hw;
+int hsyncendpos_hw;
+
 int hsynctotal;
 static int maxvpos_total = 511;
 int minfirstline = VBLANK_ENDLINE_PAL;
@@ -306,10 +314,20 @@ uae_u16 beamcon0, new_beamcon0;
 static uae_u16 beamcon0_saved;
 static uae_u16 bplcon0_saved, bplcon1_saved, bplcon2_saved;
 static uae_u16 bplcon3_saved, bplcon4_saved;
-static bool varsync_changed;
-uae_u16 vtotal = MAXVPOS_PAL, htotal = MAXHPOS_PAL;
+static int varsync_changed;
+uae_u16 vtotal, htotal;
 static int maxvpos_stored, maxhpos_stored;
-static uae_u16 hsstop, hbstrt, hbstop, vsstop, vbstrt, vbstop, hsstrt, vsstrt, hcenter;
+uae_u16 hsstop, hsstrt;
+static uae_u16 hbstop, hbstrt;
+static uae_u16 vsstop, vsstrt;
+static uae_u16 vbstop, vbstrt;
+static uae_u16 hcenter;
+static uae_u16 hbstop_v, hbstrt_v, hbstop_v2, hbstrt_v2;
+static int vsstrt_m, vsstop_m, vbstrt_m, vbstop_m;
+static bool vs_state, vb_state, vb_end_line;
+static bool vb_end_next_line;
+static int vb_start_line;
+static bool ocs_blanked;
 static uae_u16 sprhstrt, sprhstop, bplhstrt, bplhstop, hhpos, hhpos_hpos;
 static uae_u16 sprhstrt_v, sprhstop_v, bplhstrt_v, bplhstop_v;
 static int hhbpl, hhspr;
@@ -330,7 +348,6 @@ struct sprite {
        int armed;
        int dmastate;
        int dmacycle;
-       bool ignoreverticaluntilnextline;
        int width;
 
        uae_u16 ctl, pos;
@@ -343,14 +360,13 @@ struct sprite {
 
 static struct sprite spr[MAX_SPRITES];
 static int plfstrt_sprite;
-static bool sprite_ignoreverticaluntilnextline;
 
 uaecptr sprite_0;
 int sprite_0_width, sprite_0_height, sprite_0_doubled;
 uae_u32 sprite_0_colors[4];
 static uae_u8 magic_sprite_mask = 0xff;
 
-static int sprite_vblank_endline = VBLANK_SPRITE_PAL;
+static int hardwired_vbstop;
 
 static int last_sprite_point, nr_armed;
 static int sprite_width, sprres;
@@ -404,6 +420,8 @@ static int last_hdiw;
 static enum diw_states diwstate, hdiwstate;
 static int diwstate_vpos;
 static int bpl_hstart;
+static bool hblankstate;
+static bool exthblank;
 
 int first_planes_vpos, last_planes_vpos;
 static int first_bplcon0, first_bplcon0_old;
@@ -438,8 +456,7 @@ enum copper_states {
        COP_strobe_delay1x,
        COP_strobe_delay2x,
        COP_strobe_extra, // just to skip current cycle when CPU wrote to COPJMP
-       COP_start_delay,
-       COP_start_delay2
+       COP_start_delay
 };
 
 struct copper {
@@ -490,7 +507,7 @@ struct color_change *curr_color_changes, *prev_color_changes;
 struct draw_info *curr_drawinfo, *prev_drawinfo;
 struct color_entry *curr_color_tables, *prev_color_tables;
 
-static int next_color_change;
+static int next_color_change, last_color_change;
 static int next_color_entry, remembered_color_entry;
 static int color_src_match, color_dest_match, color_compare_result;
 
@@ -730,6 +747,96 @@ STATIC_INLINE int get_equ_vblank_endline(void)
        return equ_vblank_endline + (equ_vblank_toggle ? (lof_current ? 1 : 0) : 0);
 }
 
+static void record_color_change2(int hpos, int regno, uae_u32 value)
+{
+       color_change *cc;
+       int pos = ((hpos + hpos_hsync_extra) * 2 - DDF_OFFSET) * 4;
+
+       // AGA has extra hires pixel delay in color changes
+       if ((regno < RECORDED_REGISTER_CHANGE_OFFSET || regno == RECORDED_REGISTER_CHANGE_OFFSET + 0x10c) && aga_mode) {
+               if (currprefs.chipset_hr) {
+                       pos += 2;
+               }
+               if (regno == RECORDED_REGISTER_CHANGE_OFFSET + 0x10c) {
+                       // BPLCON4:
+                       // Bitplane XOR change: 2 hires pixel delay
+                       // Sprite bank change: 1 hires pixel delay
+                       if (!currprefs.chipset_hr) {
+                               pos += 2;
+                       }
+                       if (value & 0xff00) {
+                               thisline_decision.xor_seen = true;
+                       }
+                       pos += 2;
+                       if ((value & 0x00ff) != (bplcon4 & 0x00ff)) {
+                               // Sprite bank delay
+                               cc = &curr_color_changes[next_color_change];
+                               cc->linepos = pos;
+                               cc->regno = regno | 1;
+                               cc->value = value;
+                               next_color_change++;
+                       }
+                       pos += 2;
+               }
+       }
+
+       if (exthblank) {
+               cc = &curr_color_changes[next_color_change];
+               int prevpos = last_color_change == next_color_change ? 0 : cc[-1].linepos;
+               int chpos = pos;
+               if (regno == 0xffff) {
+                       chpos = 0x7fff;
+               }
+               // inject programmed hblank start and end in color changes
+               if (hbstrt_v2 <= hbstop_v2) {
+                       if (chpos >= hbstrt_v2 && prevpos < hbstrt_v2) {
+                               cc = &curr_color_changes[next_color_change];
+                               cc->linepos = hbstrt_v2;
+                               cc->regno = RECORDED_REGISTER_CHANGE_OFFSET + 0x200;
+                               cc->value = 1;
+                               next_color_change++;
+                               cc[1].regno = -1;
+                       }
+                       if (chpos >= hbstop_v2 && prevpos < hbstop_v2) {
+                               cc = &curr_color_changes[next_color_change];
+                               cc->linepos = hbstop_v2;
+                               cc->regno = RECORDED_REGISTER_CHANGE_OFFSET + 0x200;
+                               cc->value = 0;
+                               next_color_change++;
+                               cc[1].regno = -1;
+                       }
+               } else {
+                       if (chpos >= hbstop_v2 && prevpos < hbstop_v2) {
+                               cc = &curr_color_changes[next_color_change];
+                               cc->linepos = hbstop_v2;
+                               cc->regno = RECORDED_REGISTER_CHANGE_OFFSET + 0x200;
+                               cc->value = 0;
+                               next_color_change++;
+                               cc[1].regno = -1;
+                       }
+                       if (chpos >= hbstrt_v2 && prevpos < hbstrt_v2) {
+                               cc = &curr_color_changes[next_color_change];
+                               cc->linepos = hbstrt_v2;
+                               cc->regno = RECORDED_REGISTER_CHANGE_OFFSET + 0x200;
+                               cc->value = 1;
+                               next_color_change++;
+                               cc[1].regno = -1;
+                       }
+               }
+       }
+
+       if (regno == 0xffff) {
+               return;
+       }
+
+       cc = &curr_color_changes[next_color_change];
+       cc->linepos = pos;
+       cc->regno = regno;
+       cc->value = value;
+       next_color_change++;
+       cc[1].regno = -1;
+}
+
 /* Called to determine the state of the horizontal display window state
 * machine at the current position. It might have changed since we last
 * checked.  */
@@ -765,6 +872,7 @@ static void decide_diw(int hpos)
                        }
                        hdiwstate = DIW_waiting_start;
                }
+
                if (lhdiw != 512) {
                        break;
                }
@@ -1034,6 +1142,9 @@ static void estimate_last_fetch_cycle(int hpos)
                        int starting_last_block_at = (fc + fetchunit - 1) & ~(fetchunit - 1);
                        if (ddf_stopping == 2) {
                                starting_last_block_at -= fetchunit;
+                               if (starting_last_block_at < 0) {
+                                       starting_last_block_at += maxhpos;
+                               }
                        }
                        estimated_cycle_count = (starting_last_block_at - fc) + lastfetchunit;
                }
@@ -1175,10 +1286,12 @@ static int toscr_nr_planes_shifter, toscr_nr_planes_shifter_new;
 static int fetchwidth;
 static int toscr_delay[2], toscr_delay_adjusted[2], toscr_delay_sh[2];
 static bool shdelay_disabled;
-static int delay_cycles, delay_lastcycle[2], delay_cycles_right_offset, toscr_right_edge_offset;
+static int delay_cycles, delay_lastcycle[2], delay_hsynccycle;
+static int delay_cycles_right_offset, toscr_right_edge_offset;
 static int hack_delay_shift;
 static bool bplcon1_written;
 static bool bplcon0_planes_changed;
+static int last_bpl1dat;
 
 /* The number of bits left from the last fetched words.
 This is an optimization - conceptually, we have to make sure the result is
@@ -1253,45 +1366,6 @@ void notice_new_xcolors(void)
        }
 }
 
-static void record_color_change2(int hpos, int regno, uae_u32 value)
-{
-       int pos = ((hpos + hpos_hsync_extra) * 2 - DDF_OFFSET) * 4;
-
-       // AGA has extra hires pixel delay in color changes
-       if ((regno < 0x1000 || regno == 0x1000 + 0x10c) && aga_mode) {
-               if (currprefs.chipset_hr) {
-                       pos += 2;
-               }
-               if (regno == 0x1000 + 0x10c) {
-                       // BPLCON4:
-                       // Bitplane XOR change: 2 hires pixel delay
-                       // Sprite bank change: 1 hires pixel delay
-                       if (!currprefs.chipset_hr) {
-                               pos += 2;
-                       }
-                       if (value & 0xff00) {
-                               thisline_decision.xor_seen = true;
-                       }
-                       pos += 2;
-                       if ((value & 0x00ff) != (bplcon4 & 0x00ff)) {
-                               // Sprite bank delay
-                               color_change *ccs = &curr_color_changes[next_color_change];
-                               ccs->linepos = pos;
-                               ccs->regno = regno | 1;
-                               ccs->value = value;
-                               next_color_change++;
-                       }
-                       pos += 2;
-               }
-       }
-       color_change *cc = &curr_color_changes[next_color_change];
-       cc->linepos = pos;
-       cc->regno = regno;
-       cc->value = value;
-       next_color_change++;
-       cc[1].regno = -1;
-}
-
 static bool isehb(uae_u16 bplcon0, uae_u16 bplcon2)
 {
        bool bplehb;
@@ -1394,6 +1468,7 @@ static void set_delay_lastcycle(void)
        if (islinetoggle()) {
                delay_lastcycle[1]++;
        }
+       delay_hsynccycle = (((maxhpos + (hsyncstartpos_start >> CCK_SHRES_SHIFT)) * 2) + 2) << (toscr_res + toscr_res_mult);
 }
 
 static int output_res(int res)
@@ -1564,12 +1639,6 @@ static bool fetch(int nr, int fm, int hpos, bool addmodulo)
                debug_getpeekdma_chipram(p, MW_MASK_BPL_0 << nr, 0x110 + nr * 2, 0xe0 + nr * 4);
        }
        uae_u32 v = aga_mode ? chipmem_lget_indirect(p & ~3) : chipmem_wget_indirect(p);
-       if (debug_dma) {
-               record_dma_read_value(v);
-       }
-       if (memwatch_enabled) {
-               debug_getpeekdma_value(v);
-       }
 #endif
        switch (fm)
        {
@@ -1590,6 +1659,14 @@ static bool fetch(int nr, int fm, int hpos, bool addmodulo)
                } else {
                        v = chipmem_wget_indirect(p);
                }
+#ifdef DEBUGGER
+               if (memwatch_enabled) {
+                       debug_getpeekdma_value(v);
+               }
+               if (debug_dma) {
+                       record_dma_read_value(v);
+               }
+#endif
                fetched_aga[nr] = fetched[nr] = v;
                last_custom_value1 = v;
                last_custom_value2 = (uae_u16)last_custom_value1;
@@ -1608,6 +1685,14 @@ static bool fetch(int nr, int fm, int hpos, bool addmodulo)
                } else {
                        fetched_aga[nr] = chipmem_lget_indirect(pm);
                }
+#ifdef DEBUGGER
+               if (memwatch_enabled) {
+                       debug_getpeekdma_value_long(fetched_aga[nr], p - pm);
+               }
+               if (debug_dma) {
+                       record_dma_read_value_wide(fetched_aga[nr], false);
+               }
+#endif
                last_custom_value1 = (uae_u32)fetched_aga[nr];
                last_custom_value2 = (uae_u16)last_custom_value1;
                fetched[nr] = (uae_u16)fetched_aga[nr];
@@ -1634,6 +1719,15 @@ static bool fetch(int nr, int fm, int hpos, bool addmodulo)
                        fetched_aga[nr] = ((uae_u64)chipmem_lget_indirect(pm1)) << 32;
                        fetched_aga[nr] |= chipmem_lget_indirect(pm2);
                }
+#ifdef DEBUGGER
+               if (memwatch_enabled) {
+                       debug_getpeekdma_value_long((uae_u32)(fetched_aga[nr] >> 32), p - pm1);
+                       debug_getpeekdma_value_long((uae_u32)(fetched_aga[nr] >> 0), p - pm2);
+               }
+               if (debug_dma) {
+                       record_dma_read_value_wide(fetched_aga[nr], true);
+               }
+#endif
                last_custom_value1 = (uae_u32)fetched_aga[nr];
                last_custom_value2 = (uae_u16)last_custom_value1;
                fetched[nr] = (uae_u16)fetched_aga[nr];
@@ -1641,6 +1735,11 @@ static bool fetch(int nr, int fm, int hpos, bool addmodulo)
        }
 #endif
        }
+
+       if (nr == 0) {
+               last_bpl1dat = hpos;
+       }
+
        return nr == 0;
 }
 
@@ -2074,6 +2173,44 @@ static void do_delays_fast_hr(int nbits, int fm)
 #endif
 
 
+static void do_delays_null(int nbits)
+{
+       for (int i = 0; i < MAX_PLANES; i++) {
+               outword[i] <<= nbits;
+       }
+}
+
+static void do_delays_null_hr(int nbits)
+{
+       for (int i = 0; i < MAX_PLANES; i++) {
+               outword64[i] <<= nbits;
+       }
+}
+
+static void toscr_hsync(int nbits, int fm)
+{
+       int diff = delay_hsynccycle - (delay_cycles_right_offset + delay_cycles);
+       if (diff > 0) {
+               do_delays(diff, fm);
+               nbits -= diff;
+       }
+       do_delays_null(nbits);
+       delay_cycles = delay_hsynccycle;
+       delay_cycles_right_offset = 0;
+}
+
+static void toscr_hsync_hr(int nbits, int fm)
+{
+       int diff = delay_hsynccycle - (delay_cycles_right_offset + delay_cycles);
+       if (diff > 0) {
+               do_delays_hr(diff, fm);
+               nbits -= diff;
+       }
+       do_delays_null_hr(nbits);
+       delay_cycles = delay_hsynccycle;
+       delay_cycles_right_offset = 0;
+}
+
 static void toscr_right_edge(int nbits, int fm)
 {
        // Emulate hpos counter (delay_cycles) reseting when Denise/Lisa gets STRHOR strobe.
@@ -2122,7 +2259,9 @@ static void toscr_right_edge_hr(int nbits, int fm)
 
 static void toscr_1(int nbits, int fm)
 {
-       if (delay_cycles + nbits >= delay_lastcycle[lol]) {
+       if (delay_cycles_right_offset + delay_cycles + nbits >= delay_hsynccycle) {
+               toscr_hsync(nbits, fm);
+       } else if (delay_cycles + nbits >= delay_lastcycle[lol]) {
                toscr_right_edge(nbits, fm);
        } else if (!toscr_scanline_complex_bplcon1) {
                // Most common case.
@@ -2157,7 +2296,9 @@ static void toscr_1(int nbits, int fm)
 
 static void toscr_1_hr(int nbits, int fm)
 {
-       if (delay_cycles + nbits >= delay_lastcycle[lol]) {
+       if (delay_cycles_right_offset + delay_cycles + nbits >= delay_hsynccycle) {
+               toscr_hsync_hr(nbits, fm);
+       } else if (delay_cycles + nbits >= delay_lastcycle[lol]) {
                toscr_right_edge_hr(nbits, fm);
        } else if (!toscr_scanline_complex_bplcon1) {
                do_delays_fast_hr(nbits, fm);
@@ -2262,7 +2403,7 @@ static void toscr_hr_fm0(int nbits) { toscr_0_hr(nbits, 0); }
 static void toscr_hr_fm1(int nbits) { toscr_0_hr(nbits, 1); }
 static void toscr_hr_fm2(int nbits) { toscr_0_hr(nbits, 2); }
 
-static int flush_plane_data_n(int fm)
+static int flush_plane_data_n(int fm, int hpos)
 {
        int i = 0;
 
@@ -2284,7 +2425,7 @@ static int flush_plane_data_n(int fm)
        return i >> (1 + toscr_res);
 }
 
-static int flush_plane_data_hr(int fm)
+static int flush_plane_data_hr(int fm, int hpos)
 {
        int i = 0;
 
@@ -2316,12 +2457,13 @@ static int flush_plane_data_hr(int fm)
        return i >> (1 + toscr_res_hr);
 }
 
-static int flush_plane_data(int fm)
+// flush remaining data but leave data after hsync
+static int flush_plane_data(int fm, int hpos)
 {
        if (currprefs.chipset_hr) {
-               return flush_plane_data_hr(fm);
+               return flush_plane_data_hr(fm, hpos);
        } else {
-               return flush_plane_data_n(fm);
+               return flush_plane_data_n(fm, hpos);
        }
 }
 
@@ -2361,11 +2503,11 @@ static void hack_shres_delay(int hpos)
        }
        if (hpos >= 0 && (toscr_delay_sh[0] != o0 || toscr_delay_sh[1] != o1)) {
                record_color_change(hpos, 0, COLOR_CHANGE_SHRES_DELAY | toscr_delay_sh[0]);
-               current_colors.extra &= ~(1 << CE_SHRES_DELAY);
-               current_colors.extra &= ~(1 << (CE_SHRES_DELAY + 1));
-               current_colors.extra |= toscr_delay_sh[0] << CE_SHRES_DELAY;
+               current_colors.extra &= ~(1 << CE_SHRES_DELAY_SHIFT);
+               current_colors.extra &= ~(1 << (CE_SHRES_DELAY_SHIFT + 1));
+               current_colors.extra |= toscr_delay_sh[0] << CE_SHRES_DELAY_SHIFT;
                remembered_color_entry = -1;
-               thisline_changed = true;
+               thisline_changed = 1;
        }
 }
 
@@ -2406,7 +2548,7 @@ static void update_denise(int hpos)
        }
        if (bplcon0d_old != bplcon0d) {
                bplcon0d_old = bplcon0d;
-               record_color_change2(hpos, 0x100 + 0x1000, bplcon0d);
+               record_color_change2(hpos, 0x100 + RECORDED_REGISTER_CHANGE_OFFSET, bplcon0d);
                toscr_nr_planes = GET_PLANES(bplcon0d);
                if (isocs7planes()) {
                        if (toscr_nr_planes2 < 6) {
@@ -2875,7 +3017,7 @@ static void finish_final_fetch(int hpos)
        flush_display(fetchmode);
 
        // This is really the end of scanline, we can finally flush all remaining data.
-       thisline_decision.plfright += flush_plane_data(fetchmode);
+       thisline_decision.plfright += flush_plane_data(fetchmode, hpos);
 
        // This can overflow if display setup is really bad.
        if (out_offs > MAX_PIXELS_PER_LINE / 32) {
@@ -2900,6 +3042,7 @@ static void finish_final_fetch(int hpos)
 #ifdef AGA
                || line_decisions[next_lineno].bplcon4bm != thisline_decision.bplcon4bm
                || line_decisions[next_lineno].fmode != thisline_decision.fmode
+               || line_decisions[next_lineno].vb != thisline_decision.vb
 #endif
                )
 #endif /* SMART_UPDATE */
@@ -3175,34 +3318,19 @@ static void decide_bpl_fetch(int endhpos)
        }
 }
 
-static bool is_cant_this_last_line(void)
-{
-       // Last line..
-       // ..works normally if A1000 Agnus
-       if (currprefs.cs_dipagnus) {
-               return false;
-       }
-       // ..or if ECS and BEAMCON0 HARDDIS set
-       if (harddis) {
-               return false;
-       }
-       // ..inhibits bitplane and sprite DMA if later Agnus revision.
-       return vpos + 1 >= maxvpos + lof_store;
-}
-
 static void decide_vline(void)
 {
        /* Take care of the vertical DIW.  */
        if (vpos == plffirstline) {
-               // A1000 Agnus won't start bitplane DMA if vertical diw is zero.
-               if (vpos > 0 || (vpos == 0 && !currprefs.cs_dipagnus)) {
+               // Following line after VB start has bitplane DMA start inhibited (if HARDDIS=0)
+               if (vb_start_line != 2 || harddis) {
                        diwstate = DIW_waiting_stop;
                        diwstate_vpos = vpos;
                        SET_LINE_CYCLEBASED;
                }
        }
-       // last line of field can never have bitplane dma active if not A1000 Agnus.
-       if (vpos == plflastline || cant_this_last_line || (vpos == 0 && currprefs.cs_dipagnus)) {
+       // VB start line forces vertical display window off (if HARDDIS=0)
+       if (vpos == plflastline || (vb_start_line == 1 && !harddis)) {
                diwstate = DIW_waiting_start;
                diwstate_vpos = vpos;
                SET_LINE_CYCLEBASED;
@@ -3238,10 +3366,10 @@ static void decide_fetch_safe(int endhpos)
 * but the new color has not been entered into the table yet. */
 static void record_color_change(int hpos, int regno, uae_u32 value)
 {
-       if (regno < 0x1000 && nodraw())
+       if (regno < RECORDED_REGISTER_CHANGE_OFFSET && nodraw())
                return;
-       /* Early positions don't appear on-screen. */
-       if (vpos < minfirstline)
+       /* vsync period don't appear on-screen. */
+       if (vpos >= maxvpos_display_vsync && vpos < minfirstline)
                return;
 
        decide_diw(hpos);
@@ -3254,22 +3382,61 @@ static void record_color_change(int hpos, int regno, uae_u32 value)
        record_color_change2(hpos, regno, value);
 }
 
+static void setextblank(void)
+{
+       bool extblank, extblankmode;
+       if (aga_mode) {
+               extblank = true;
+               extblankmode = (bplcon0 & 1) && (bplcon3 & 0x01);
+       } else {
+               extblank = !ecs_denise || !(bplcon0 & 1) || ((bplcon0 & 1) && (bplcon3 & 0x01));
+               extblankmode = false;
+       }
+       current_colors.extra &= ~(1 << CE_EXTBLANKSET);
+       current_colors.extra &= ~(1 << CE_EXTBLANKMODE);
+       if (extblank) {
+               current_colors.extra |= 1 << CE_EXTBLANKSET;
+       }
+       if (extblankmode) {
+               current_colors.extra |= 1 << CE_EXTBLANKMODE;
+       }
+}
+
 static bool isbrdblank(int hpos, uae_u16 bplcon0, uae_u16 bplcon3)
 {
-       bool brdblank, brdntrans;
+       bool brdblank, brdntrans, extblank, extblankmode;
 #ifdef ECS_DENISE
        brdblank = ecs_denise && (bplcon0 & 1) && (bplcon3 & 0x20);
        brdntrans = ecs_denise && (bplcon0 & 1) && (bplcon3 & 0x10);
+       // ECSENA=0: hardwired horizontal, strobe vertical
+       // ECSENA=1: EXTBLKEN=0: ECS Denise: no blanking AGA: hardwired blanking, strobe vertical
+       // ECSENA=1: EXTBLKEN=1: ECS Denise: hardwired horizontal, strobe vertical AGA: programmed horizontal, strobe vertical
+       // extblank = blanking enabled
+       // extblankmode = use hardwired or programmed blanking
+       if (aga_mode) {
+               extblank = true;
+               extblankmode = (bplcon0 & 1) && (bplcon3 & 0x01);
+       } else {
+               extblank = !ecs_denise || !(bplcon0 & 1) || ((bplcon0 & 1) && (bplcon3 & 0x01));
+               extblankmode = false;
+       }
 #else
        brdblank = false;
        brdntrans = false;
+       extblank = true;
+       extblankmode = true;
 #endif
-       if (hpos >= 0 && (ce_is_borderblank(current_colors.extra) != brdblank || ce_is_borderntrans(current_colors.extra) != brdntrans)) {
-               record_color_change(hpos, 0, COLOR_CHANGE_BRDBLANK | (brdblank ? 1 : 0) | (ce_is_bordersprite(current_colors.extra) ? 2 : 0) | (brdntrans ? 4 : 0));
+       if (hpos >= 0 && (ce_is_borderblank(current_colors.extra) != brdblank || ce_is_borderntrans(current_colors.extra) != brdntrans
+               || ce_is_extblankset(current_colors.extra) != extblank || ce_is_extblankmode(current_colors.extra) != extblankmode)) {
+               record_color_change(hpos, 0, COLOR_CHANGE_BRDBLANK | (brdblank ? 1 : 0) | (ce_is_bordersprite(current_colors.extra) ? 2 : 0) | (brdntrans ? 4 : 0) | (extblank ? 8 : 0));
                current_colors.extra &= ~(1 << CE_BORDERBLANK);
                current_colors.extra &= ~(1 << CE_BORDERNTRANS);
+               current_colors.extra &= ~(1 << CE_EXTBLANKSET);
+               current_colors.extra &= ~(1 << CE_EXTBLANKMODE);
                current_colors.extra |= brdblank ? (1 << CE_BORDERBLANK) : 0;
                current_colors.extra |= brdntrans ? (1 << CE_BORDERNTRANS) : 0;
+               current_colors.extra |= extblank ? (1 << CE_EXTBLANKSET) : 0;
+               current_colors.extra |= extblankmode ? (1 << CE_EXTBLANKMODE) : 0;
                remembered_color_entry = -1;
        }
        return brdblank;
@@ -3314,7 +3481,7 @@ static void record_register_change(int hpos, int regno, uae_u16 value)
                isbrdblank(hpos, bplcon0, value);
                issprbrd(hpos, bplcon0, value);
        }
-       record_color_change(hpos, regno + 0x1000, value);
+       record_color_change(hpos, regno + RECORDED_REGISTER_CHANGE_OFFSET, value);
 }
 
 typedef int sprbuf_res_t, cclockres_t, hwres_t,        bplres_t;
@@ -3946,29 +4113,21 @@ static void finish_decisions(int hpos)
 
        finish_final_fetch(hpos);
 
-#if 0
-       if (currprefs.cs_ocshsyncbug && !(currprefs.chipset_mask & CSMASK_ECS_DENISE)) {
-               if (vpos == minfirstline) {
-                       record_color_change2(hpos - 1, 0, COLOR_CHANGE_BLANK);
-               } else if (vpos == current_maxvpos() - 1) {
-                       record_color_change2(hpos - 1, 0, COLOR_CHANGE_BLANK | 1);
-               }
-       }
-#endif
-       record_color_change2(hsyncstartpos >> CCK_SHRES_SHIFT, 0xffff, 0);
        if (thisline_decision.plfleft >= 0 && thisline_decision.plflinelen < 0) {
                thisline_decision.plfright = thisline_decision.plfleft;
                thisline_decision.plflinelen = 0;
                thisline_decision.bplres = output_res(RES_LORES);
        }
 
+       record_color_change2(hpos + 1, 0xffff, 0);
+
        /* Large DIWSTOP values can cause the stop position never to be
        * reached, so the state machine always stays in the same state and
        * there's a more-or-less full-screen DIW. */
        if (hdiwstate == DIW_waiting_stop) {
                thisline_decision.diwlastword = max_diwlastword;
-               if (thisline_decision.diwfirstword < 0) {
-                       thisline_decision.diwfirstword = min_diwlastword;
+               if (thisline_decision.diwfirstword <= 0) {
+                       thisline_decision.diwfirstword = -1;
                }
        }
 
@@ -3999,6 +4158,10 @@ static void finish_decisions(int hpos)
        }
 
        dip->nr_color_changes = next_color_change - dip->first_color_change;
+       if (dip->nr_color_changes < 0) {
+               write_log("negative nr_color_changes: %d. FIXME!\n", dip->nr_color_changes);
+               dip->nr_color_changes = 0;
+       }
        dip->nr_sprites = next_sprite_entry - dip->first_sprite_entry;
 
        if (thisline_decision.plfleft != line_decisions[next_lineno].plfleft) {
@@ -4025,6 +4188,7 @@ static void finish_decisions(int hpos)
        if (next_color_change >= MAX_REG_CHANGE - 30) {
                write_log(_T("color_change buffer overflow!\n"));
                next_color_change = 0;
+               last_color_change = 0;
                dip->nr_color_changes = 0;
                dip->first_color_change = 0;
                dip->last_color_change = 0;
@@ -4054,6 +4218,16 @@ static void reset_decisions_scanline_start(void)
                        cycle_line_pipe[i] = 0;
                }
        }
+
+       if (!ecs_denise && currprefs.cs_ocshblankbug) {
+               if (vb_start_line == 2 + vblank_extraline) {
+                       record_color_change2(0, 0, COLOR_CHANGE_BLANK | 1);
+               }
+               if (vb_end_next_line) {
+                       record_color_change2(0, 0, COLOR_CHANGE_BLANK | 0);
+               }
+       }
+
 }
 
 static void reset_decisions_hsync_start(void)
@@ -4063,31 +4237,23 @@ static void reset_decisions_hsync_start(void)
        }
 
        toscr_nr_planes = toscr_nr_planes2 = 0;
-       thisline_decision.bplres = output_res(bplcon0_res);
-       thisline_decision.nr_planes = 0;
-
-       thisline_decision.plfleft = -1;
-       thisline_decision.plflinelen = -1;
-       thisline_decision.plfright = -1;
-       thisline_decision.ham_seen = !! (bplcon0 & 0x800);
-       thisline_decision.ehb_seen = !! isehb(bplcon0, bplcon2);
-       thisline_decision.ham_at_start = !! (bplcon0 & 0x800);
-       thisline_decision.bordersprite_seen = issprbrd(-1, bplcon0, bplcon3);
-       thisline_decision.xor_seen = (bplcon4 & 0xff00) != 0;
 
        /* decided_res shouldn't be touched before it's initialized by decide_line(). */
-       thisline_decision.diwfirstword = -1;
-       thisline_decision.diwlastword = -1;
+       thisline_decision.diwfirstword = -2;
+       thisline_decision.diwlastword = -2;
        if (hdiwstate == DIW_waiting_stop) {
-               thisline_decision.diwfirstword = min_diwlastword;
+               thisline_decision.diwfirstword = -1;
                if (thisline_decision.diwfirstword != line_decisions[next_lineno].diwfirstword) {
                        MARK_LINE_CHANGED;
                }
        }
        thisline_decision.ctable = -1;
 
-       thisline_changed = 0;
+       if (thisline_changed > 0) {
+               thisline_changed = 0;
+       }
        curr_drawinfo[next_lineno].first_color_change = next_color_change;
+       last_color_change = next_color_change;
        curr_drawinfo[next_lineno].first_sprite_entry = next_sprite_entry;
        next_sprite_forced = 1;
 
@@ -4095,7 +4261,7 @@ static void reset_decisions_hsync_start(void)
        bpldmawasactive = false;
        bpl1mod_hpos = -1;
        bpl2mod_hpos = -1;
-       plane0 = false;
+       //plane0 = false;
 
        delay_cycles_right_offset = 0;
        toscr_right_edge_offset = 0;
@@ -4112,6 +4278,7 @@ static void reset_decisions_hsync_start(void)
                toscr_scanline_complex_bplcon1 = false;
        }
 
+#if 0
        memset(outword, 0, sizeof outword);
        // fetched[] must not be cleared (Sony VX-90 / Royal Amiga Force)
        todisplay_fetched[0] = todisplay_fetched[1] = false;
@@ -4125,15 +4292,9 @@ static void reset_decisions_hsync_start(void)
        }
 #endif
 
+#endif
        reset_bpl_vars();
 
-       if (sprite_ignoreverticaluntilnextline) {
-               sprite_ignoreverticaluntilnextline = false;
-               for (int i = 0; i < MAX_SPRITES; i++) {
-                       spr[i].ignoreverticaluntilnextline = false;
-               }
-       }
-
        /* These are for comparison. */
        thisline_decision.bplcon0 = bplcon0;
        thisline_decision.bplcon2 = bplcon2;
@@ -4144,22 +4305,58 @@ static void reset_decisions_hsync_start(void)
        thisline_decision.bplcon4bm = bplcon4;
        thisline_decision.bplcon4sp = bplcon4;
        thisline_decision.fmode = fmode;
+       // 0 = vb, 1 = vb off, 3 = vb off, previous line was bitplane + vb on
+       //bool t = thisline_decision.plfleft >= 0 && (thisline_decision.vb & 1) == 0 && !vb_state && !vb_end_line;
+       thisline_decision.vb = vb_start_line > 1 + vblank_extraline ? 0 : 1;
+       if (!ecs_denise && vb_end_line && currprefs.cs_ocshblankbug) {
+               thisline_decision.vb = 1;
+       }
 #endif
        bplcon0d_old = -1;
        toscr_res_old = -1;
 
-#if 0
-       if (!(currprefs.chipset_mask & CSMASK_ECS_DENISE)) {
-               if (vpos == minfirstline) {
-                       record_color_change2(0, 0, COLOR_CHANGE_BLANK | 1);
-               }
-               if (!currprefs.cs_ocshsyncbug) {
-                       if (vpos == minfirstline + 1) {
-                               record_color_change2(0, 0, COLOR_CHANGE_BLANK | 0);
-                       }
+       int left = thisline_decision.plfleft;
+
+       thisline_decision.plfleft = -1;
+       thisline_decision.plflinelen = -1;
+       thisline_decision.plfright = -1;
+       thisline_decision.ham_seen = !!(bplcon0 & 0x800);
+       thisline_decision.ehb_seen = !!isehb(bplcon0, bplcon2);
+       thisline_decision.ham_at_start = !!(bplcon0 & 0x800);
+       thisline_decision.bordersprite_seen = issprbrd(-1, bplcon0, bplcon3);
+       thisline_decision.xor_seen = (bplcon4 & 0xff00) != 0;
+
+       bool toshift = false;
+       for (int i = 0; i < thisline_decision.nr_planes; i++) {
+               if (todisplay2_aga[i] || todisplay2[i]) {
+                       toshift = true;
                }
        }
+       if (bprun > 0 || todisplay_fetched[0] || toshift) {
+               int hpos = current_hpos();
+               thisline_decision.plfleft = hpos;       
+               if (hpos_hsync_extra) {
+                       //delay_cycles -= ((hpos_hsync_extra) * 2 - DDF_OFFSET) << (toscr_res + toscr_res_mult);
+                       delay_cycles = ((hpos) * 2 - DDF_OFFSET) << (toscr_res + toscr_res_mult);
+                       hpos_hsync_extra = 0;
+               }
+               toscr_nr_planes2 = toscr_nr_planes = thisline_decision.nr_planes;
+       } else {
+               thisline_decision.bplres = output_res(bplcon0_res);
+               thisline_decision.nr_planes = 0;
+               memset(outword, 0, sizeof outword);
+               // fetched[] must not be cleared (Sony VX-90 / Royal Amiga Force)
+               todisplay_fetched[0] = todisplay_fetched[1] = false;
+               memset(todisplay, 0, sizeof todisplay);
+               memset(todisplay2, 0, sizeof todisplay2);
+#ifdef AGA
+               if (aga_mode || ALL_SUBPIXEL) {
+                       memset(todisplay_aga, 0, sizeof todisplay_aga);
+                       memset(todisplay2_aga, 0, sizeof todisplay2_aga);
+                       memset(outword64, 0, sizeof outword64);
+               }
 #endif
+       }
 }
 
 int vsynctimebase_orig;
@@ -4285,64 +4482,106 @@ static void checklacecount (bool lace)
 
 static void updateextblk(void)
 {
-       if (beamcon0 & 0x0110) { // VARHSYEN | VARCSYEN
+       hsyncstartpos_start_hw = 13;
+       hsyncstartpos_hw = maxhpos_short + hsyncstartpos_start_hw;
+       hsyncendpos_hw = 24;
 
-               uae_u16 hbstrt_v = (hbstrt & 0xff) << 3;
-               if (aga_mode) {
-                       hbstrt_v |= (hbstrt >> 8) & 7;
-               }
-               uae_u16 hbstop_v = (hbstop & 0xff) << 3;
-               if (aga_mode) {
-                       hbstop_v |= (hbstop >> 8) & 7;
-               }
+       hbstrt_v = (hbstrt & 0xff) << CCK_SHRES_SHIFT;
+       if (aga_mode) {
+               hbstrt_v |= (hbstrt >> 8) & 7;
+       }
+       hbstop_v = (hbstop & 0xff) << CCK_SHRES_SHIFT;
+       if (aga_mode) {
+               hbstop_v |= (hbstop >> 8) & 7;
+       }
 
-               hsyncstartpos = hsstrt << CCK_SHRES_SHIFT;
-               hsyncendpos = hsstop << CCK_SHRES_SHIFT;
+       hbstrt_v2 = hbstrt_v;
+       hbstop_v2 = hbstop_v;
 
-               if ((bplcon0 & 1) && (bplcon3 & 1)) {
+       exthblank = (bplcon0 & 1) && (bplcon3 & 1);
 
-                       if (hbstrt_v > (maxhpos << CCK_SHRES_SHIFT) / 2) {
-                               if (hsyncstartpos < hbstrt_v)
-                                       hsyncstartpos = hbstrt_v;
-                       } else {
-                               if (hsyncstartpos > hbstrt_v)
-                                       hsyncstartpos = hbstrt_v;
-                       }
+       if (new_beamcon0 & 0x0110) { // VARHSYEN | VARCSYEN
 
-                       if (hbstop_v > (maxhpos << CCK_SHRES_SHIFT) / 2) {
-                               if (hsyncendpos > hbstop_v)
-                                       hsyncendpos = hbstop_v;
-                       } else {
-                               if (hsyncendpos < hbstop_v)
-                                       hsyncendpos = hbstop_v;
-                       }
-               }
+               hsyncstartpos = hsstrt;
+               hsyncendpos = hsstop;
 
-               hsyncstartpos_start = hsyncstartpos + (1 << CCK_SHRES_SHIFT);
+               hsync_end_left_border = hsstop;
+
+               hsyncstartpos_start = hsyncstartpos + 1;
                if (hsyncstartpos < hsyncendpos) {
-                       hsyncstartpos = (maxhpos << CCK_SHRES_SHIFT) + hsyncstartpos;
+                       hsyncstartpos = maxhpos_short + hsyncstartpos_start;
                        hsynctotal = hsyncstartpos;
                } else {
-                       hsynctotal = (maxhpos << CCK_SHRES_SHIFT) + hsyncstartpos;
+                       hsynctotal = maxhpos + hsyncstartpos;
+               }
+               // make sure possible BPL DMA cycles before first refresh slot are processed before hsync
+               if (hsyncstartpos_start < REFRESH_FIRST_HPOS + 1) {
+                       hsyncstartpos_start = REFRESH_FIRST_HPOS + 1;
                }
 
-               hsyncendpos--;
+               hsyncendpos -= 1;
 
-               if (hsyncendpos < (2 << CCK_SHRES_SHIFT)) {
-                       hsyncendpos = 2 << CCK_SHRES_SHIFT;
+               if (hsyncendpos < 2) {
+                       hsyncendpos = 2;
                }
 
-               if (hsyncstartpos - hsyncendpos < (maxhpos << CCK_SHRES_SHIFT) / 2) {
-                       hsyncstartpos = maxhpos << CCK_SHRES_SHIFT;
+               if (hsyncstartpos - hsyncendpos < maxhpos) {
+                       hsyncstartpos = maxhpos;
                }
 
        } else {
 
-               hsyncstartpos_start = 13 << CCK_SHRES_SHIFT;
-               hsyncstartpos = (maxhpos_short << CCK_SHRES_SHIFT) + hsyncstartpos_start;
-               hsyncendpos = 24 << CCK_SHRES_SHIFT;
-               hsynctotal = 234 << CCK_SHRES_SHIFT;
+               hsyncstartpos_start = hsyncstartpos_start_hw;
+               hsyncstartpos = hsyncstartpos_hw;
+               hsyncendpos = hsyncendpos_hw;
+               hsynctotal = 234;
+
+               hsync_end_left_border = 35 + 9;
+
+       }
+
+       // 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;
+       }
+       if (hbstop_v2 < (1 << CCK_SHRES_SHIFT)) {
+               hbstop_v2 = 0xffff;
+       }
+       // Out of range right
+       if (hbstrt_v2 >= (maxhpos << CCK_SHRES_SHIFT) + (1 << CCK_SHRES_SHIFT)) {
+               hbstrt_v2 = 0xffff;
+       }
+       if (hbstop_v2 >= (maxhpos << 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 (hbstop_v2 <= (hsyncstartpos_start << CCK_SHRES_SHIFT)) {
+               hbstop_v2 += maxhpos << CCK_SHRES_SHIFT;
+       }
 
+       if (currprefs.chipset_hr) {
+               hbstrt_v2 &= ~(3 >> currprefs.gfx_resolution);
+               hbstop_v2 &= ~(3 >> currprefs.gfx_resolution);
+       } else {
+               hbstrt_v2 &= ~3;
+               hbstop_v2 &= ~3;
+       }
+
+       hsyncstartpos_start_hw <<= CCK_SHRES_SHIFT;
+       hsyncstartpos_hw <<= CCK_SHRES_SHIFT;
+       hsyncendpos_hw <<= CCK_SHRES_SHIFT;
+
+       hsyncstartpos_start <<= CCK_SHRES_SHIFT;
+       hsyncstartpos <<= CCK_SHRES_SHIFT;
+       hsyncendpos <<= CCK_SHRES_SHIFT;
+       hsynctotal <<= CCK_SHRES_SHIFT;
+
+       // ECS Denise has 1 extra lores pixel in right border
+       if (ecs_denise) {
+               hsynctotal += 1 << (CCK_SHRES_SHIFT - 1);
        }
 
        calcdiw();
@@ -4496,7 +4735,7 @@ void compute_framesync(void)
                int stop = hsyncendpos >> CCK_SHRES_SHIFT;
 
                vidinfo->drawbuffer.inwidth = ((maxhpos - (maxhpos - start + DISPLAY_LEFT_SHIFT / 2) + 1) * 2) << res2;
-               vidinfo->drawbuffer.inxoffset = stop * 2;
+               vidinfo->drawbuffer.inxoffset = hsstop * 2;
                
                vidinfo->drawbuffer.extrawidth = 0;
                vidinfo->drawbuffer.inwidth2 = vidinfo->drawbuffer.inwidth;
@@ -4506,12 +4745,13 @@ void compute_framesync(void)
 
        } else {
 
-               vidinfo->drawbuffer.inwidth = AMIGA_WIDTH_MAX << currprefs.gfx_resolution;
+               vidinfo->drawbuffer.inwidth = maxhpos_display << currprefs.gfx_resolution;
                vidinfo->drawbuffer.extrawidth = currprefs.gfx_extrawidth ? currprefs.gfx_extrawidth : -1;
+               vidinfo->drawbuffer.extraheight = currprefs.gfx_extraheight ? currprefs.gfx_extraheight : -1;
                vidinfo->drawbuffer.inwidth2 = vidinfo->drawbuffer.inwidth;
-               vidinfo->drawbuffer.inheight = (maxvpos_display - minfirstline + 1) << currprefs.gfx_vresolution;
+               vidinfo->drawbuffer.inheight = (maxvpos_display - minfirstline + maxvpos_display_vsync) << currprefs.gfx_vresolution;
                vidinfo->drawbuffer.inheight2 = vidinfo->drawbuffer.inheight;
-
+               vidinfo->drawbuffer.inxoffset = 0;
        }
 
        if (vidinfo->drawbuffer.inwidth < 16)
@@ -4590,7 +4830,7 @@ static void init_hz(bool checkvposw)
 
        doublescan = 0;
        programmedmode = false;
-       if ((beamcon0 & 0xA0) != (new_beamcon0 & 0xA0)) {
+       if ((beamcon0 & (0x80 | 0x20)) != (new_beamcon0 & (0x80 | 0x20))) {
                hzc = 1;
        }
        if (beamcon0 != new_beamcon0) {
@@ -4608,7 +4848,7 @@ static void init_hz(bool checkvposw)
                maxhpos = MAXHPOS_PAL;
                minfirstline = VBLANK_ENDLINE_PAL;
                vblank_hz_nom = vblank_hz = VBLANK_HZ_PAL;
-               sprite_vblank_endline = VBLANK_SPRITE_PAL;
+               hardwired_vbstop = VBLANK_STOP_PAL;
                equ_vblank_endline = EQU_ENDLINE_PAL;
                equ_vblank_toggle = true;
                vblank_hz_shf = clk / ((maxvpos + 0) * maxhpos);
@@ -4619,7 +4859,7 @@ static void init_hz(bool checkvposw)
                maxhpos = MAXHPOS_NTSC;
                minfirstline = VBLANK_ENDLINE_NTSC;
                vblank_hz_nom = vblank_hz = VBLANK_HZ_NTSC;
-               sprite_vblank_endline = VBLANK_SPRITE_NTSC;
+               hardwired_vbstop = VBLANK_STOP_NTSC;
                equ_vblank_endline = EQU_ENDLINE_NTSC;
                equ_vblank_toggle = false;
                vblank_hz_shf = clk / ((maxvpos + 0) * (maxhpos + 0.5));
@@ -4627,8 +4867,26 @@ static void init_hz(bool checkvposw)
                vblank_hz_lace = clk / ((maxvpos + 0.5) * (maxhpos + 0.5));
        }
 
+       maxhpos_display = AMIGA_WIDTH_MAX;
        maxvpos_nom = maxvpos;
        maxvpos_display = maxvpos;
+       maxvpos_display_vsync = 2;
+       // A1000 Agnus VBSTRT=first line, OCS and later: VBSTRT=last line
+       if (currprefs.cs_dipagnus) {
+               maxvpos_display_vsync++;
+       }
+       // one pixel row missing from right border if OCS
+       if (!ecs_denise) {
+               maxhpos_display--;
+       }
+       if (currprefs.gfx_extrawidth > 0) {
+               maxhpos_display += currprefs.gfx_extrawidth;
+       }
+       // A1000/OCS Denise has topmost line "almost" blanked
+       if (!ecs_denise) {
+               minfirstline--;
+       }
+       vblank_extraline = !currprefs.cs_dipagnus && !ecs_denise ? 1 : 0;
        if (vpos_count > 0) {
                // we come here if vpos_count != maxvpos and beamcon0 didn't change
                // (someone poked VPOSW)
@@ -4653,32 +4911,47 @@ static void init_hz(bool checkvposw)
        }
 
        if ((beamcon0 & 0x1000) && (beamcon0 & (0x0200 | 0x0010))) { // VARVBEN + VARVSYEN|VARCSYEN
-               minfirstline = vsstop > vbstop ? vsstop : vbstop;
+               minfirstline = vsstop > vbstop && abs(vsstop - vbstop) < maxvpos / 2 ? vsstop : vbstop;
                if (minfirstline > maxvpos / 2)
                        minfirstline = vsstop > vbstop ? vbstop : vsstop;
-               firstblankedline = vbstrt;
                minfirstline++;
+               firstblankedline = vbstrt;
        } else if (beamcon0 & (0x0200 | 0x0010)) { // VARVSYEN | VARCSYEN
                firstblankedline = maxvpos + 1;
        } else if (beamcon0 & 0x1000) { // VARVBEN
-               minfirstline = vbstop;
-               if (minfirstline > maxvpos / 2)
-                       minfirstline = 0;
                firstblankedline = vbstrt;
-               minfirstline++;
        } else {
                firstblankedline = maxvpos + 1;
        }
 
+       if (beamcon0 & (0x1000 | 0x0200 | 0x0010)) {
+               minfirstline -= 2;
+               maxvpos_display_vsync = 4;
+       }
+
+       if (currprefs.gfx_extraheight > 0) {
+               int mfl = minfirstline;
+               maxvpos_display_vsync += currprefs.gfx_extraheight / 2;
+               minfirstline -= currprefs.gfx_extraheight / 2;
+               if (minfirstline < maxvpos_display_vsync + 1) {
+                       minfirstline = maxvpos_display_vsync + 1;
+               }
+               if (firstblankedline <= mfl && firstblankedline >= minfirstline) {
+                       firstblankedline -= currprefs.gfx_extraheight / 2;
+               }
+       }
+
        if (minfirstline < 2) {
                minfirstline = 2;
        }
+       if (!(beamcon0 & 0x80) && minfirstline < 10) {
+               minfirstline = 10;
+       }
+
        if (minfirstline >= maxvpos) {
                minfirstline = maxvpos - 1;
        }
 
-       sprite_vblank_endline = minfirstline - 1;
-
        if (firstblankedline < minfirstline) {
                firstblankedline = maxvpos + 1;
        }
@@ -4698,6 +4971,17 @@ static void init_hz(bool checkvposw)
                vblank_hz_lof = clk / ((maxvpos + 1) * maxhpos);
                vblank_hz_lace = clk / ((maxvpos + 0.5) * maxhpos);
 
+               if (beamcon0 & (0x0200 | 0x0010)) {
+                       minfirstline = vsstop;
+                       if (minfirstline > vtotal / 2) {
+                               minfirstline = 1;
+                       }
+                       firstblankedline = vsstrt;
+                       if (firstblankedline < vtotal / 2) {
+                               firstblankedline = maxvpos + 1;
+                       }
+               }
+
                maxvpos_nom = maxvpos;
                maxvpos_display = maxvpos;
                equ_vblank_endline = -1;
@@ -4706,7 +4990,7 @@ static void init_hz(bool checkvposw)
                if (doublescan && htotal >= 140 && (bplcon0 & 0x0040))
                        doublescan = 0;
                programmedmode = true;
-               varsync_changed = true;
+               varsync_changed = 1;
                vpos_count = maxvpos_nom;
                vpos_count_diff = maxvpos_nom;
                hzc = 1;
@@ -4765,8 +5049,8 @@ static void init_hz(bool checkvposw)
        }
        inputdevice_tablet_strobe();
 
-       if (varsync_changed) {
-               varsync_changed = false;
+       if (varsync_changed > 0) {
+               varsync_changed = 0;
                dumpsync();
        }
 }
@@ -5618,7 +5902,7 @@ static void check_harddis(void)
        harddis = ecs_agnus && ((new_beamcon0 & 0x80) || (new_beamcon0 & 0x4000) || (bplcon0 & 0x40) || (bplcon0 & 0x80));
 }
 
-static void BEAMCON0(uae_u16 v)
+static void BEAMCON0(int hpos, uae_u16 v)
 {
        if (ecs_agnus) {
                if (v != new_beamcon0) {
@@ -5629,7 +5913,11 @@ static void BEAMCON0(uae_u16 v)
                                dumpsync();
                        }
                }
+               if ((beamcon0 & (0x10 | 0x20 | 0x80 | 0x100 | 0x200 | 0x1000 | 0x4000)) != (new_beamcon0 & (0x10 | 0x20 | 0x80 | 0x100 | 0x200 | 0x1000 | 0x4000))) {
+                       varsync_changed = 2;
+               }
                beamcon0_saved = v;
+               record_register_change(hpos, 0x1dc, new_beamcon0);
                check_harddis();
                calcdiw();
        }
@@ -5648,9 +5936,9 @@ static void varsync(void)
        }
 #endif
        updateextblk();
-       if (!(beamcon0 & 0x80))
+       if (!(beamcon0 & (0x80 | 0x1000 | 0x0200 | 0x0100 | 0x4000)))
                return;
-       varsync_changed = true;
+       varsync_changed = 2;
 }
 
 #ifdef PICASSO96
@@ -5666,7 +5954,7 @@ void set_picasso_hack_rate(int hz)
        if (p96refresh_active > 0) {
                new_beamcon0 |= 0x80;
        }
-       varsync_changed = true;
+       varsync_changed = 1;
 }
 #endif
 
@@ -5730,7 +6018,7 @@ static void BPLCON0_Denise(int hpos, uae_u16 v)
                v |= 0x80;
        }
 
-       record_register_change(hpos, 0x100, (bplcon0d & ~(0x800 | 0x400 | 0x80)) | (v & (0x0800 | 0x400 | 0x80 | 0x01)));
+       record_register_change(hpos, 0x100, (bplcon0d & ~(0x800 | 0x400 | 0x80 | 0x01)) | (v & (0x0800 | 0x400 | 0x80 | 0x01)));
 
        bplcon0d = v & ~0x80;
 
@@ -5808,7 +6096,7 @@ static void BPLCON0(int hpos, uae_u16 v)
                bplcon0_interlace_seen = true;
        }
 
-       if ((v & 8) && !lightpen_triggered && vpos < sprite_vblank_endline) {
+       if ((v & 8) && !lightpen_triggered && vb_state) {
                // setting lightpen bit immediately freezes VPOSR if inside vblank and not already frozen
                hhpos_lpen = HHPOSR();
                lightpen_triggered = 1;
@@ -6022,7 +6310,7 @@ static void DIWHIGH(int hpos, uae_u16 v)
        if (!aga_mode) {
                v &= ~(0x0008 | 0x0010 | 0x1000 | 0x0800);
        }
-       v &= ~(0x8000 | 0x4000 | 0x0080 | 0x0040);
+       v &= ~(0x08000 | 0x4000 | 0x0080 | 0x0040);
        if (diwhigh_written && diwhigh == v) {
                return;
        }
@@ -6153,90 +6441,66 @@ static void BLTALWM(int hpos, uae_u16 v) {
 static void BLTAPTH(int hpos, uae_u16 v)
 {
        maybe_blit(hpos, 0);
-       if (blt_info.blit_main && currprefs.blitter_cycle_exact && currprefs.cpu_memory_cycle_exact) {
-               bltptx = (bltapt & 0xffff) | ((uae_u32)v << 16);
-               bltptxpos = hpos;
-               bltptxc = 1;
-       } else {
-               bltapt = (bltapt & 0xffff) | ((uae_u32)v << 16);
-       }
+       bltptx = bltapt;
+       bltptxpos = hpos;
+       bltptxc = 1;
+       bltapt = (bltapt & 0xffff) | ((uae_u32)v << 16);
 }
 static void BLTAPTL(int hpos, uae_u16 v)
 {
        maybe_blit(hpos, 0);
-       if (blt_info.blit_main && currprefs.blitter_cycle_exact && currprefs.cpu_memory_cycle_exact) {
-               bltptx = (bltapt & ~0xffff) | (v & 0xFFFE);
-               bltptxpos = hpos;
-               bltptxc = 1;
-       } else {
-               bltapt = (bltapt & ~0xffff) | (v & 0xFFFE);
-       }
+       bltptx = bltapt;
+       bltptxpos = hpos;
+       bltptxc = 1;
+       bltapt = (bltapt & ~0xffff) | (v & 0xFFFE);
 }
 static void BLTBPTH(int hpos, uae_u16 v)
 {
        maybe_blit(hpos, 0);
-       if (blt_info.blit_main && currprefs.blitter_cycle_exact && currprefs.cpu_memory_cycle_exact) {
-               bltptx = (bltbpt & 0xffff) | ((uae_u32)v << 16);
-               bltptxpos = hpos;
-               bltptxc = 2;
-       } else {
-               bltbpt = (bltbpt & 0xffff) | ((uae_u32)v << 16);
-       }
+       bltptx = bltbpt;
+       bltptxpos = hpos;
+       bltptxc = 2;
+       bltbpt = (bltbpt & 0xffff) | ((uae_u32)v << 16);
 }
 static void BLTBPTL(int hpos, uae_u16 v)
 {
        maybe_blit(hpos, 0);
-       if (blt_info.blit_main && currprefs.blitter_cycle_exact && currprefs.cpu_memory_cycle_exact) {
-               bltptx = (bltbpt & ~0xffff) | (v & 0xFFFE);
-               bltptxpos = hpos;
-               bltptxc = 2;
-       } else {
-               bltbpt = (bltbpt & ~0xffff) | (v & 0xFFFE);
-       }
+       bltptx = bltbpt;
+       bltptxpos = hpos;
+       bltptxc = 2;
+       bltbpt = (bltbpt & ~0xffff) | (v & 0xFFFE);
 }
 static void BLTCPTH(int hpos, uae_u16 v)
 {
        maybe_blit(hpos, 0);
-       if (blt_info.blit_main && currprefs.blitter_cycle_exact && currprefs.cpu_memory_cycle_exact) {
-               bltptx = (bltcpt & 0xffff) | ((uae_u32)v << 16);
-               bltptxpos = hpos;
-               bltptxc = 3;
-       } else {
-               bltcpt = (bltcpt & 0xffff) | ((uae_u32)v << 16);
-       }
+       bltptx = bltcpt;
+       bltptxpos = hpos;
+       bltptxc = 3;
+       bltcpt = (bltcpt & 0xffff) | ((uae_u32)v << 16);
 }
 static void BLTCPTL(int hpos, uae_u16 v)
 {
        maybe_blit(hpos, 0);
-       if (blt_info.blit_main && currprefs.blitter_cycle_exact && currprefs.cpu_memory_cycle_exact) {
-               bltptx = (bltcpt & ~0xffff) | (v & 0xFFFE);
-               bltptxpos = hpos;
-               bltptxc = 3;
-       } else {
-               bltcpt = (bltcpt & ~0xffff) | (v & 0xFFFE);
-       }
+       bltptx = bltcpt;
+       bltptxpos = hpos;
+       bltptxc = 3;
+       bltcpt = (bltcpt & ~0xffff) | (v & 0xFFFE);
 }
 static void BLTDPTH (int hpos, uae_u16 v)
 {
        maybe_blit(hpos, 0);
-       if ((blt_info.blit_main || blt_info.blit_finald) && currprefs.blitter_cycle_exact && currprefs.cpu_memory_cycle_exact) {
-               bltptx = (bltdpt & 0xffff) | ((uae_u32)v << 16);
-               bltptxpos = hpos;
-               bltptxc = 4;
-       } else {
-               bltdpt = (bltdpt & 0xffff) | ((uae_u32)v << 16);
-       }
+       bltptx = bltdpt;
+       bltptxpos = hpos;
+       bltptxc = 4;
+       bltdpt = (bltdpt & 0xffff) | ((uae_u32)v << 16);
 }
 static void BLTDPTL(int hpos, uae_u16 v)
 {
        maybe_blit(hpos, 0);
-       if ((blt_info.blit_main || blt_info.blit_finald) && currprefs.blitter_cycle_exact && currprefs.cpu_memory_cycle_exact) {
-               bltptx = (bltdpt & ~0xffff) | (v & 0xFFFE);
-               bltptxpos = hpos;
-               bltptxc = 4;
-       } else {
-               bltdpt = (bltdpt & ~0xffff) | (v & 0xFFFE);
-       }
+       bltptx = bltdpt;
+       bltptxpos = hpos;
+       bltptxc = 4;
+       bltdpt = (bltdpt & ~0xffff) | (v & 0xFFFE);
 }
 
 static void BLTSIZE(int hpos, uae_u16 v)
@@ -6303,7 +6567,7 @@ static void spr_arm(int num, int state)
 
 static void sprstartstop(struct sprite *s)
 {
-       if (vpos < sprite_vblank_endline || cant_this_last_line || s->ignoreverticaluntilnextline) {
+       if (vb_state || vb_end_line) {
                return;
        }
        if (vpos == s->vstart) {
@@ -6352,13 +6616,6 @@ static void SPRxCTLPOS(int num)
 static void SPRxCTL_1(uae_u16 v, int num, int hpos)
 {
        struct sprite *s = &spr[num];
-       if (0 && hpos >= maxhpos - 2 && s->ctl != v && vpos < maxvpos - 1) {
-               vpos++;
-               sprstartstop(s);
-               vpos--;
-               s->ignoreverticaluntilnextline = true;
-               sprite_ignoreverticaluntilnextline = true;
-       }
        s->ctl = v;
        spr_arm(num, 0);
        SPRxCTLPOS(num);
@@ -6382,13 +6639,6 @@ static void SPRxPOS_1(uae_u16 v, int num, int hpos)
 {
        struct sprite *s = &spr[num];
 
-       if (0 && hpos >= maxhpos - 2 && s->pos != v && vpos < maxvpos - 1) {
-               vpos++;
-               sprstartstop(s);
-               vpos--;
-               s->ignoreverticaluntilnextline = true;
-               sprite_ignoreverticaluntilnextline = true;
-       }
        s->pos = v;
        SPRxCTLPOS(num);
 #if SPRITE_DEBUG > 0
@@ -7226,7 +7476,7 @@ static void do_copper_fetch(int hpos, uae_u8 id)
                alloc_cycle(hpos, CYCLE_COPPER);
                cycle_line_slot[hpos] |= CYCLE_COPPER_SPECIAL;
                break;
-       case COP_start_delay2:
+       case COP_start_delay:
                cop_state.state = COP_read1;
 #ifdef DEBUGGER
                if (debug_dma) {
@@ -7395,9 +7645,6 @@ static void do_copper_fetch(int hpos, uae_u8 id)
 #endif
                alloc_cycle(hpos, CYCLE_COPPER);
                break;
-       case COP_start_delay:
-               // do nothing, this happens if copper requested new word while vblank restarted copper.
-               break;
        default:
                write_log(_T("copper_fetch invalid state %d! %02x\n"), cop_state.state, id);
                break;
@@ -7477,7 +7724,7 @@ static void update_copper(int until_hpos)
 
                // 226 -> 0 (even to even cycle transition) skip.
                // Copper clock signal is low bit of hpos counter.
-               if (hpos == 0 && maxhposeven == COPPER_CYCLE_POLARITY) {
+               if (hpos == 0 && maxhposeven == COPPER_CYCLE_POLARITY && cop_state.state != COP_start_delay) {
                        goto next;
                }
 
@@ -7537,11 +7784,6 @@ static void update_copper(int until_hpos)
                break;
 
                case COP_start_delay:
-                       // cycle after vblank strobe fetches word from old pointer first
-                       cop_state.state = COP_start_delay2;
-                       break;
-
-               case COP_start_delay2:
                        // cycle after vblank strobe fetches word from old pointer first
                        copper_cant_read(hpos, 0x81);
                        break;
@@ -7777,14 +8019,6 @@ static uae_u16 sprite_fetch(struct sprite *s, uaecptr pt, int hpos, int slot, in
        }
 #endif
        data = last_custom_value1 = chipmem_wget_indirect(pt);
-#ifdef DEBUGGER
-       if (debug_dma) {
-               record_dma_read_value(data);
-       }
-       if (memwatch_enabled) {
-               debug_getpeekdma_value(data);
-       }
-#endif
        alloc_cycle(hpos, CYCLE_SPRITE);
        return data;
 }
@@ -7797,6 +8031,16 @@ static void sprite_fetch_full(struct sprite *s, int hpos, int slot, int mode, ua
        if (sprite_width == 16) {
 
                data16 = sprite_fetch(s, s->pt, hpos, slot, mode);
+
+#ifdef DEBUGGER
+               if (memwatch_enabled) {
+                       debug_getpeekdma_value(data16);
+               }
+               if (debug_dma) {
+                       record_dma_read_value(data16);
+               }
+#endif
+
                s->pt += 2;
 
        } else if (sprite_width == 64) {
@@ -7821,6 +8065,17 @@ static void sprite_fetch_full(struct sprite *s, int hpos, int slot, int mode, ua
                        data322 |= data322 << 16;
                }
                data16 = data321 >> 16;
+
+#ifdef DEBUGGER
+               if (memwatch_enabled) {
+                       debug_getpeekdma_value_long(data321, pm1 - s->pt);
+                       debug_getpeekdma_value_long(data322, pm2 - s->pt);
+               }
+               if (debug_dma) {
+                       record_dma_read_value_wide((((uae_u64)data321) << 32) | data322, true);
+               }
+#endif
+
                s->pt += 8;
 
        } else { // 32
@@ -7836,8 +8091,17 @@ static void sprite_fetch_full(struct sprite *s, int hpos, int slot, int mode, ua
                        data321 |= data321 >> 16;
                }
                data16 = data321 >> 16;
-               s->pt += 4;
 
+#ifdef DEBUGGER
+               if (memwatch_enabled) {
+                       debug_getpeekdma_value_long(data321, pm - s->pt);
+               }
+               if (debug_dma) {
+                       record_dma_read_value_wide(data321, true);
+               }
+#endif
+
+               s->pt += 4;
        }
 
        *v0 = data16;
@@ -7921,7 +8185,7 @@ static void do_sprite_fetch(int hpos, uae_u8 dat)
 
 static void decide_sprite_fetch(int endhpos)
 {
-       if ((vpos < sprite_vblank_endline) || (doflickerfix() && interlace_seen && (next_lineno & 1)) || (cant_this_last_line)) {
+       if (vb_state || (doflickerfix() && interlace_seen && (next_lineno & 1))) {
                last_decide_sprite_hpos = endhpos;
                return;
        }
@@ -7942,21 +8206,21 @@ static void decide_sprite_fetch(int endhpos)
                                if (slot == 0 || slot == 2) {
                                        struct sprite *s = &spr[num];
                                        if (slot == 0) {
+                                               if (vb_end_line) {
+                                                       s->dmastate = 0;
+                                                       s->dmacycle = 0;
+                                               }
                                                if (!s->dmacycle && s->dmastate) {
                                                        s->dmacycle = 1;
                                                }
-                                               if (vpos == s->vstart) {
+                                               if (vpos == s->vstart && !vb_end_line) {
                                                        s->dmastate = 1;
                                                        s->dmacycle = 1;
                                                        if (num == 0 && slot == 0) {
                                                                cursorsprite();
                                                        }
                                                }
-                                               if (vpos <= sprite_vblank_endline) {
-                                                       s->dmacycle = 0;
-                                                       s->dmastate = 0;
-                                               }
-                                               if (vpos == s->vstop || vpos == sprite_vblank_endline) {
+                                               if (vpos == s->vstop || vb_end_line) {
                                                        s->dmastate = 0;
                                                        s->dmacycle = 1;
                                                }
@@ -8008,10 +8272,9 @@ static void init_sprites(void)
 static void init_hardware_frame(void)
 {
        first_bpl_vpos = -1;
-       next_lineno = 0;
-       prev_lineno = -1;
-       nextline_how = nln_normal;
-       diwstate = DIW_waiting_start;
+       if (!harddis) {
+               diwstate = DIW_waiting_start;
+       }
 
        if (first_bplcon0 != first_bplcon0_old) {
                vertical_changed = horizontal_changed = true;
@@ -8062,6 +8325,8 @@ void init_hardware_for_drawing_frame(void)
        }
        prev_next_sprite_entry = next_sprite_entry;
 
+       next_lineno = 0;
+       last_color_change = 0;
        next_color_change = 0;
        next_sprite_entry = 0;
        next_color_entry = 0;
@@ -8408,7 +8673,8 @@ static void fpscounter(bool frameok)
 }
 
 // vsync functions that are not hardware timing related
-static void vsync_handler_pre(void)
+// called when display is blanked, not necessarily last line but line 0 or later.
+static void vsync_handler_render(void)
 {
        struct amigadisplay *ad = &adisplays[0];
 
@@ -8482,9 +8748,6 @@ static void vsync_handler_pre(void)
                }
        }
 
-       // GUI check here, must be after frame rendering
-       devices_vsync_pre();
-
        fpscounter(frameok);
 
        bool waspaused = false;
@@ -8521,10 +8784,44 @@ static void vsync_handler_pre(void)
                vblank_hz_state = 1;
        }
 
+       nextline_how = nln_normal;
+
        vsync_handle_check();
        //checklacecount (bplcon0_interlace_seen || lof_lace);
 }
 
+static bool vsync_display_rendered;
+
+static void vsync_display_render(void)
+{
+       if (!vsync_display_rendered) {
+               vsyncmintimepre = read_processor_time();
+               vsync_handler_render();
+               vsync_display_rendered = true;
+       }
+}
+
+static void vsync_check_vsyncmode(void)
+{
+       if (varsync_changed == 1) {
+               // render screen (minus extra lines) because mode is going to change and we don't want black screen flash
+               vsync_display_render();
+               init_hz_normal();
+       } else if (vpos_count > 0 && abs(vpos_count - vpos_count_diff) > 1 && vposw_change < 4) {
+               vsync_display_render();
+               init_hz_vposw();
+       } else if (interlace_changed || changed_chipset_refresh() || lof_changed) {
+               vsync_display_render();
+               compute_framesync();
+       }
+       if (varsync_changed > 0) {
+               varsync_changed--;
+       }
+       if (thisline_changed < 0) {
+               thisline_changed++;
+       }
+}
+
 // emulated hardware vsync
 static void vsync_handler_post(void)
 {
@@ -8627,13 +8924,7 @@ static void vsync_handler_post(void)
 
        devices_vsync_post();
 
-       if (varsync_changed || (beamcon0 & (0x10 | 0x20 | 0x80 | 0x100 | 0x200 | 0x1000)) != (new_beamcon0 & (0x10 | 0x20 | 0x80 | 0x100 | 0x200 | 0x1000))) {
-               init_hz_normal();
-       } else if (vpos_count > 0 && abs (vpos_count - vpos_count_diff) > 1 && vposw_change < 4) {
-               init_hz_vposw();
-       } else if (interlace_changed || changed_chipset_refresh() || lof_changed) {
-               compute_framesync();
-       }
+       vsync_check_vsyncmode();
 
        lof_changed = 0;
        vposw_change = 0;
@@ -8992,7 +9283,6 @@ static void hsync_handlerh(bool onvsync)
                                nextline_how = currprefs.gfx_vresolution > VRES_NONDOUBLE && currprefs.gfx_pscanlines == 1 ? nln_nblack : nln_doubled;
                        }
                }
-               prev_lineno = next_lineno;
                next_lineno = lineno;
                reset_decisions_hsync_start();
        }
@@ -9001,6 +9291,10 @@ static void hsync_handlerh(bool onvsync)
        hpos_hsync_extra = 0;
        estimate_last_fetch_cycle(hpos);
 
+       if (vb_end_line && !ecs_denise && currprefs.cs_ocshblankbug) {
+               record_color_change2(hpos, 0, COLOR_CHANGE_BLANK | 1);
+       }
+
        eventtab[ev_hsynch].evtime = get_cycles() + HSYNCTIME;
        eventtab[ev_hsynch].oldcycles = get_cycles();
        events_schedule();
@@ -9026,12 +9320,12 @@ static void hsync_handler_pre(bool onvsync)
                check_sprite_collisions();
 
                /* reset light pen latch */
-               if (vpos == sprite_vblank_endline) {
+               if (vb_end_line) {
                        lightpen_triggered = 0;
                        sprite_0 = 0;
                }
 
-               if (!lightpen_triggered && vpos >= sprite_vblank_endline && (bplcon0 & 8)) {
+               if (!lightpen_triggered && !vb_state && (bplcon0 & 8)) {
                        // lightpen always triggers at the beginning of the last line
                        if (vpos + 1 == maxvpos + lof_store) {
                                vpos_lpen = vpos;
@@ -9844,9 +10138,10 @@ static void hsync_handler_post (bool onvsync)
 #endif
        } else if (currprefs.cs_ciaatod == 0 && ciavsyncs) {
                // CIA-A TOD counter increases when vsync pulse ends
-               if (beamcon0 & (0x80 | 0x200)) {
-                       if (vpos == vsstop && vsstrt <= maxvpos)
+               if (beamcon0 & 0x200) {
+                       if (vpos == vsstop && vs_state == true) {
                                CIAA_tod_inc(lof_store ? hsstop : hsstop + hcenter);
+                       }
                } else {
                        if (vpos == (currprefs.ntscmode ? VSYNC_ENDLINE_NTSC : VSYNC_ENDLINE_PAL)) {
                                CIAA_tod_inc(lof_store ? 132 : 18);
@@ -9868,22 +10163,63 @@ static void hsync_handler_post (bool onvsync)
                vsync_handler_post();
                vpos_count = 0;
        }
-       // A1000 DIP Agnus (8361): vblank interrupt is triggered on line 1!
-       if (currprefs.cs_dipagnus) {
-               if (vpos == 1)
-                       send_interrupt(5, 1 * CYCLE_UNIT);
-       } else {
-               if (vpos == 0)
-                       send_interrupt(5, 1 * CYCLE_UNIT);
+       // vblank interrupt = next line after VBSTRT
+       if (vb_start_line == 1) {
+               send_interrupt(5, 1 * CYCLE_UNIT);
        }
        // lastline - 1?
        if (vpos + 1 == maxvpos + lof_store || vpos + 1 == maxvpos + lof_store + 1) {
                lof_lastline = lof_store != 0;
        }
-       cant_this_last_line = is_cant_this_last_line();
+
        decide_vline();
 
+       vb_end_next_line = false;
+       if (vb_start_line) {
+               vb_start_line++;
+       }
+       if (vb_end_line) {
+               vb_start_line = 0;
+               vb_end_line = false;
+               vb_end_next_line = true;
+       }
        if (ecs_agnus) {
+               if (vsstrt_m == vpos) {
+                       vsstrt_m = -1;
+               }
+               if (vsstop_m == vpos) {
+                       vsstop_m = -1;
+               }
+
+               if (vbstrt_m == vpos) {
+                       vbstrt_m = -1;
+               }
+               if (vbstop_m == vpos) {
+                       vbstop_m = -1;
+               }
+
+               if (vsstrt == vpos) {
+                       vsstrt_m = vpos;
+                       vs_state = true;
+               }
+               if (vsstop == vpos) {
+                       vsstop_m = vpos;
+                       vs_state = false;
+               }
+
+               if (new_beamcon0 & 0x1000) {
+                       if (vbstrt == vpos) {
+                               vbstrt_m = vpos;
+                               vb_start_line = 1;
+                               vb_state = true;
+                       }
+                       if (vbstop == vpos) {
+                               vbstop_m = vpos;
+                               vb_end_line = true;
+                               vb_state = false;
+                       }
+               }
+
                if (vpos == sprhstrt_v) {
                        hhspr = 1;
                }
@@ -9912,6 +10248,24 @@ static void hsync_handler_post (bool onvsync)
                }
                hhpos &= 0xff;
        }
+       if (!(new_beamcon0 & 0x1000)) {
+               // A1000 Agnus VBSTRT=first line, OCS and later: VBSTRT=last line
+               if (currprefs.cs_dipagnus) {
+                       if (vpos == 0) {
+                               vb_start_line = 1;
+                               vb_state = true;
+                       }
+               } else {
+                       if (vpos == maxvpos + lof_store - 1) {
+                               vb_start_line = 1;
+                               vb_state = true;
+                       }
+               }
+               if (vpos == hardwired_vbstop) {
+                       vb_end_line = true;
+                       vb_state = false;
+               }
+       }
 
        int hp = REFRESH_FIRST_HPOS;
        for (int i = 0; i < 4; i++) {
@@ -10090,10 +10444,12 @@ static void hsync_handler_post (bool onvsync)
 
        // border detection/autoscale
        if (GET_PLANES (bplcon0) > 0 && dmaen(DMA_BITPLANE)) {
-               if (first_bplcon0 == 0)
+               if (first_bplcon0 == 0) {
                        first_bplcon0 = bplcon0;
-               if (vpos > last_planes_vpos)
+               }
+               if (vpos > last_planes_vpos) {
                        last_planes_vpos = vpos;
+               }
                if (vpos >= minfirstline && first_planes_vpos == 0) {
                        first_planes_vpos = vpos > minfirstline ? vpos - 1 : vpos;
                } else if (vpos >= current_maxvpos() - 1) {
@@ -10106,32 +10462,38 @@ static void hsync_handler_post (bool onvsync)
                        int diwfirstword_lores = diwfirstword;
                        if (diwlastword_lores > diwlastword_total) {
                                diwlastword_total = diwlastword_lores;
-                               if (diwlastword_total > coord_diw_shres_to_window_x(hsyncstartpos))
+                               if (diwlastword_total > coord_diw_shres_to_window_x(hsyncstartpos)) {
                                        diwlastword_total = coord_diw_shres_to_window_x(hsyncstartpos);
+                               }
                        }
                        if (diwfirstword_lores < diwfirstword_total) {
                                diwfirstword_total = diwfirstword_lores;
-                               if (diwfirstword_total < coord_diw_shres_to_window_x(hsyncendpos))
+                               if (diwfirstword_total < coord_diw_shres_to_window_x(hsyncendpos)) {
                                        diwfirstword_total = coord_diw_shres_to_window_x(hsyncendpos);
+                               }
                                firstword_bplcon1 = bplcon1;
                        }
                }
                if (diwstate == DIW_waiting_stop) {
                        int f = 8 << fetchmode;
-                       if (plfstrt + f < ddffirstword_total + f)
+                       if (plfstrt + f < ddffirstword_total + f) {
                                ddffirstword_total = plfstrt + f;
-                       if (plfstop + 2 * f > ddflastword_total + 2 * f)
+                       }
+                       if (plfstop + 2 * f > ddflastword_total + 2 * f) {
                                ddflastword_total = plfstop + 2 * f;
+                       }
                }
                if ((plffirstline < plffirstline_total || (plffirstline_total == minfirstline && vpos > minfirstline)) && plffirstline < maxvpos / 2) {
                        firstword_bplcon1 = bplcon1;
-                       if (plffirstline < minfirstline)
+                       if (plffirstline < minfirstline) {
                                plffirstline_total = minfirstline;
-                       else
+                       } else {
                                plffirstline_total = plffirstline;
+                       }
                }
-               if (plflastline > plflastline_total && plflastline > plffirstline_total && plflastline > maxvpos / 2)
+               if (plflastline > plflastline_total && plflastline > plffirstline_total && plflastline > maxvpos / 2) {
                        plflastline_total = plflastline;
+               }
        }
        if (diw_change > 0) {
                diw_change--;
@@ -10175,8 +10537,7 @@ static void hsync_handler(void)
        bool vs = is_custom_vsync();
        hsync_handler_pre(vs);
        if (vs) {
-               vsyncmintimepre = read_processor_time();
-               vsync_handler_pre();
+               devices_vsync_pre();
                if (savestate_check()) {
                        uae_reset(0, 0);
                        return;
@@ -10186,6 +10547,10 @@ static void hsync_handler(void)
                events_schedule();
 
        }
+       if (vpos == maxvpos_display_vsync) {
+               vsync_display_render();
+               vsync_display_rendered = false;
+       }
        vsync_line = vs;
        hsync_handler_post(vs);
 }
@@ -10197,7 +10562,9 @@ static void hsync_handlerh(void)
                eventtab[ev_hsynch].evtime = get_cycles() + HSYNCTIME;
                eventtab[ev_hsynch].active = 1;
                events_schedule();
-               vposh = 0;
+       }
+       if (vpos == maxvpos_display_vsync) {
+               vposh = maxvpos_display_vsync;
        }
        hsync_handlerh(vsync_line);
 }
@@ -10245,6 +10612,7 @@ void custom_cpuchange(void)
        intena = intena | 0x8000;
 }
 
+
 void custom_reset(bool hardreset, bool keyboardreset)
 {
        if (hardreset) {
@@ -10265,7 +10633,12 @@ void custom_reset(bool hardreset, bool keyboardreset)
        lightpen_x[1] = -1;
        lightpen_y[1] = -1;
        nr_armed = 0;
+       next_lineno = 0;
+       vb_start_line = 0;
        memset(custom_storage, 0, sizeof(custom_storage));
+       if (!currprefs.cs_dipagnus) {
+               vb_start_line = 1;
+       }
 
        if (!savestate_state) {
                cia_hsync = 0;
@@ -10277,6 +10650,17 @@ void custom_reset(bool hardreset, bool keyboardreset)
                blitter_reset();
 
                if (hardreset) {
+                       vtotal = MAXVPOS_LINES_ECS - 1;
+                       htotal = MAXHPOS_ROWS - 1;
+                       hbstrt = htotal;
+                       hbstop = htotal;
+                       hsstrt = htotal;
+                       hsstop = htotal;
+                       vbstrt = vtotal;
+                       vbstop = vtotal;
+                       vsstrt = vtotal;
+                       vsstop = vtotal;
+                       hcenter = htotal;
                        if (!aga_mode) {
                                uae_u16 c = ((ecs_denise && !aga_mode) || currprefs.cs_denisenoehb) ? 0xfff : 0x000;
                                for (int i = 0; i < 32; i++) {
@@ -10294,6 +10678,7 @@ void custom_reset(bool hardreset, bool keyboardreset)
                        }
                        lof_store = lof_current = 0;
                        lof_lace = false;
+                       setextblank();
                }
 
                clxdat = 0;
@@ -10963,18 +11348,78 @@ static int REGPARAM2 custom_wput_1 (int hpos, uaecptr addr, uae_u32 value, int n
        case 0x10C: BPLCON4(hpos, value); break;
 #endif
 
-       case 0x1DC: BEAMCON0(value); break;
-       case 0x1C0: if (htotal != value) { htotal = value & (MAXHPOS_ROWS - 1); varsync(); } break;
-       case 0x1C2: if (hsstop != value) { hsstop = value & (MAXHPOS_ROWS - 1); varsync(); } break;
-       case 0x1C4: if (hbstrt != value) { hbstrt = value & 0x7ff; varsync(); } break;
-       case 0x1C6:     if (hbstop != value) { hbstop = value & 0x7ff; varsync();} break;
-       case 0x1C8: if (vtotal != value) { vtotal = value & (MAXVPOS_LINES_ECS - 1); varsync(); } break;
-       case 0x1CA: if (vsstop != value) { vsstop = value & (MAXVPOS_LINES_ECS - 1); varsync(); } break;
-       case 0x1CC: if (vbstrt < value || vbstrt > (value & (MAXVPOS_LINES_ECS - 1)) + 1) { vbstrt = value & (MAXVPOS_LINES_ECS - 1); varsync(); } break;
-       case 0x1CE: if (vbstop < value || vbstop > (value & (MAXVPOS_LINES_ECS - 1)) + 1) { vbstop = value & (MAXVPOS_LINES_ECS - 1); varsync(); } break;
-       case 0x1DE: if (hsstrt != value) { hsstrt = value & (MAXHPOS_ROWS - 1); varsync(); } break;
-       case 0x1E0: if (vsstrt != value) { vsstrt = value & (MAXVPOS_LINES_ECS - 1); varsync(); } break;
-       case 0x1E2: if (hcenter != value) { hcenter = value & (MAXHPOS_ROWS - 1); varsync(); } break;
+       case 0x1DC: BEAMCON0(hpos, value); break;
+       case 0x1C0:
+               if (htotal != value) {
+                       htotal = value & (MAXHPOS_ROWS - 1);
+                       varsync();
+               }
+               break;
+       case 0x1C2:
+               if (hsstop != value) {
+                       hsstop = value & (MAXHPOS_ROWS - 1);
+                       //record_register_change(hpos, 0x1c2, hsstop);
+                       varsync();
+               }
+               break;
+       case 0x1C4:
+               if (hbstrt != value) {
+                       hbstrt = value & 0x7ff;
+                       varsync();
+                       updateextblk();
+                       //record_register_change(hpos, 0x1c4, hbstrt);
+               }
+               break;
+       case 0x1C6:
+               if (hbstop != value) {
+                       hbstop = value & 0x7ff;
+                       varsync();
+                       updateextblk();
+                       //record_register_change(hpos, 0x1c6, hbstop);
+               }
+               break;
+       case 0x1C8:
+               if (vtotal != value) {
+                       vtotal = value & (MAXVPOS_LINES_ECS - 1);
+                       varsync();
+               }
+               break;
+       case 0x1CA:
+               if (vsstop != value) {
+                       vsstop = value & (MAXVPOS_LINES_ECS - 1);
+                       varsync();
+               }
+               break;
+       case 0x1CC:
+               if (vbstrt != value) {
+                       vbstrt = value & (MAXVPOS_LINES_ECS - 1);
+                       varsync();
+               }
+               break;
+       case 0x1CE:
+               if (vbstop != value) {
+                       vbstop = value & (MAXVPOS_LINES_ECS - 1);
+                       varsync();
+               }
+               break;
+       case 0x1DE:
+               if (hsstrt != value) {
+                       hsstrt = value & (MAXHPOS_ROWS - 1);
+                       //record_register_change(hpos, 0x1de, hsstrt);
+                       varsync();
+               }
+               break;
+       case 0x1E0:
+               if (vsstrt != value) {
+                       vsstrt = value & (MAXVPOS_LINES_ECS - 1);
+                       varsync();
+               }
+               break;
+       case 0x1E2:
+               if (hcenter != value) {
+                       hcenter = value & (MAXHPOS_ROWS - 1); varsync();
+               }
+               break;
 
        case 0x1D0: SPRHSTRT(hpos, value); break;
        case 0x1D2: SPRHSTOP(hpos, value); break;
@@ -11203,7 +11648,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;
-       diwhigh &= 0x3fff;
+       diwstate = (diwhigh & 0x2000) ? DIW_waiting_start : DIW_waiting_stop;
+       diwhigh &= 0x1fff;
        RW;                                             /* 1E6 ? */
        RW;                                             /* 1E8 ? */
        RW;                                             /* 1EA ? */
@@ -11242,6 +11688,7 @@ uae_u8 *restore_custom(uae_u8 *src)
        if (ecs_denise && (bplcon0 & 1) && (bplcon3 & 0x10)) {
                current_colors.extra |= 1 << CE_BORDERNTRANS;
        }
+       setextblank();
 
        DISK_restore_custom(dskpt, dsklen, dskbytr);
 
@@ -11407,11 +11854,11 @@ uae_u8 *save_custom(int *len, uae_u8 *dstptr, int full)
        SW(bplhstop);           /* 1D6 BPLHSTOP */
        SW(hhpos);                      /* 1D8 HHPOSW */
        SW(0);                          /* 1DA */
-       SW(beamcon0);           /* 1DC BEAMCON0 */
+       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)); /* 1E4 DIWHIGH */
+       SW(diwhigh | (diwhigh_written ? 0x8000 : 0) | (hdiwstate == DIW_waiting_stop ? 0x4000 : 0) | (diwstate == DIW_waiting_start ? 0x2000 : 0)); /* 1E4 DIWHIGH */
        SW(0);                          /* 1E6 */
        SW(0);                          /* 1E8 */
        SW(0);                          /* 1EA */
@@ -11770,12 +12217,11 @@ void check_prefs_changed_custom (void)
        currprefs.cs_mbdmac = changed_prefs.cs_mbdmac;
        currprefs.cs_df0idhw = changed_prefs.cs_df0idhw;
        currprefs.cs_slowmemisfast = changed_prefs.cs_slowmemisfast;
-       currprefs.cs_dipagnus = changed_prefs.cs_dipagnus;
        currprefs.cs_denisenoehb = changed_prefs.cs_denisenoehb;
        currprefs.cs_z3autoconfig = changed_prefs.cs_z3autoconfig;
        currprefs.cs_bytecustomwritebug = changed_prefs.cs_bytecustomwritebug;
        currprefs.cs_color_burst = changed_prefs.cs_color_burst;
-       currprefs.cs_ocshsyncbug = changed_prefs.cs_ocshsyncbug;
+       currprefs.cs_ocshblankbug = changed_prefs.cs_ocshblankbug;
        currprefs.cs_romisslow = changed_prefs.cs_romisslow;
        currprefs.cs_toshibagary = changed_prefs.cs_toshibagary;
        currprefs.cs_unmapped_space = changed_prefs.cs_unmapped_space;
@@ -11783,6 +12229,7 @@ void check_prefs_changed_custom (void)
        currprefs.cs_ciatype[1] = changed_prefs.cs_ciatype[1];
 
        if (currprefs.chipset_mask != changed_prefs.chipset_mask ||
+               currprefs.cs_dipagnus != changed_prefs.cs_dipagnus ||
                currprefs.picasso96_nocustom != changed_prefs.picasso96_nocustom ||
                currprefs.ntscmode != changed_prefs.ntscmode) {
                        currprefs.picasso96_nocustom = changed_prefs.picasso96_nocustom;
@@ -11800,6 +12247,7 @@ void check_prefs_changed_custom (void)
                                bplcon0 &= ~(0x10 | 0x01);
                        }
                        currprefs.chipset_mask = changed_prefs.chipset_mask;
+                       currprefs.cs_dipagnus = changed_prefs.cs_dipagnus;
                        init_custom();
        }
 
@@ -11985,8 +12433,6 @@ uae_u32 wait_cpu_cycle_read_ce020(uaecptr addr, int mode)
        peekdma_data.mask = 0;
 #endif
 
-       x_do_cycles_pre(CYCLE_UNIT);
-
        switch (mode) {
                case -1:
                v = get_long(addr);
@@ -12010,7 +12456,10 @@ uae_u32 wait_cpu_cycle_read_ce020(uaecptr addr, int mode)
                record_dma_read_value(v);
        }
 #endif
-       
+
+       x_do_cycles_pre(CYCLE_UNIT);
+
+
        regs.chipset_latch_rw = regs.chipset_latch_read = v;
        SETIFCHIP;
                
index 3b4e3164b306ee89cb94d0f71919ead8815b08c4..d3da983d99de0914e6717c6c6c0a35b3753fa339 100644 (file)
--- a/debug.cpp
+++ b/debug.cpp
@@ -1863,6 +1863,7 @@ void record_dma_write(uae_u16 reg, uae_u32 dat, uae_u32 addr, int hpos, int vpos
        dr->type = type;
        dr->extra = extra;
        dr->intlev = regs.intmask;
+       dr->size = 2;
        last_dma_rec = dr;
 }
 struct dma_rec *last_dma_rec;
@@ -1874,6 +1875,18 @@ void record_dma_read_value(uae_u32 v)
                } else {
                        last_dma_rec->dat = v;
                }
+               last_dma_rec->size = 2;
+       }
+}
+void record_dma_read_value_wide(uae_u64 v, bool quad)
+{
+       if (last_dma_rec) {
+               if (last_dma_rec->cf_reg != 0xffff) {
+                       last_dma_rec->cf_dat = v;
+               } else {
+                       last_dma_rec->dat = v;
+               }
+               last_dma_rec->size = quad ? 8 : 4;
        }
 }
 void record_dma_read(uae_u16 reg, uae_u32 addr, int hpos, int vpos, int type, int extra)
@@ -1912,7 +1925,7 @@ void record_dma_read(uae_u16 reg, uae_u32 addr, int hpos, int vpos, int type, in
 
 static bool get_record_dma_info(struct dma_rec *dr, int hpos, int vpos, uae_u32 cycles, TCHAR *l1, TCHAR *l2, TCHAR *l3, TCHAR *l4, TCHAR *l5)
 {
-       bool longsize = false;
+       int longsize = dr->size;
        bool got = false;
        int r = dr->reg;
        int regsize = 3;
@@ -1920,6 +1933,8 @@ static bool get_record_dma_info(struct dma_rec *dr, int hpos, int vpos, uae_u32
        int br = dr->extra & 7;
        int chcnt = -1;
        TCHAR srtext[10];
+       bool extra64 = false;
+       uae_u32 extraval;
 
        if (l1)
                l1[0] = 0;
@@ -1993,7 +2008,6 @@ static bool get_record_dma_info(struct dma_rec *dr, int hpos, int vpos, uae_u32
        } else {
                _tcscpy(srtext, sr);
        }
-
        _stprintf (l1, _T("[%02X %3d]"), hpos, hpos);
        if (l4) {
                _tcscpy (l4, _T("        "));
@@ -2006,7 +2020,7 @@ static bool get_record_dma_info(struct dma_rec *dr, int hpos, int vpos, uae_u32
                                _tcscpy (l2, _T("CPU-W "));
                        if ((r & 0xff) == 4) {
                                l2[5] = 'L';
-                               longsize = true;
+                               longsize = 4;
                        }
                        if ((r & 0xff) == 2)
                                l2[5] = 'W';
@@ -2026,10 +2040,16 @@ static bool get_record_dma_info(struct dma_rec *dr, int hpos, int vpos, uae_u32
                        }
                }
                if (l3) {
-                       uae_u32 v = dr->dat;
-                       if (!longsize)
-                               v &= 0xffff;
-                       _stprintf (l3, longsize ? _T("%08X") : _T("    %04X"), v);
+                       uae_u64 v = dr->dat;
+                       if (longsize == 4) {
+                               _stprintf(l3, _T("%08X"), (uae_u32)v);
+                       } else if (longsize == 8) {
+                               _stprintf(l3, _T("%08X"), (uae_u32)(v >> 32));
+                               extra64 = true;
+                               extraval = (uae_u32)v;
+                       } else {
+                               _stprintf(l3, _T("    %04X"), (uae_u32)(v & 0xffff));
+                       }
                }
                if (l4 && dr->addr != 0xffffffff)
                        _stprintf (l4, _T("%08X"), dr->addr & 0x00ffffff);
@@ -2072,6 +2092,10 @@ static bool get_record_dma_info(struct dma_rec *dr, int hpos, int vpos, uae_u32
        if (l5) {
                _stprintf (l5, _T("%08X"), cycles + (vpos * maxhpos + hpos) * CYCLE_UNIT);
        }
+       if (extra64) {
+               _tcscpy(l5, l4);
+               _stprintf(l4, _T("%08X"), extraval);
+       }
        return got;
 }
 
@@ -3400,19 +3424,38 @@ static void peekdma_save(int type, uaecptr addr, uae_u32 mask, int reg, int ptrr
        peekdma_data.ptrreg = ptrreg;
 }
 
-uae_u32 debug_getpeekdma_value(uae_u32 v)
+void debug_getpeekdma_value(uae_u32 v)
 {
        uae_u32 vv = v;
-       if (!memwatch_enabled)
-               return v;
+       if (!memwatch_enabled) {
+               return;
+       }
        is_valid_dma(peekdma_data.reg, peekdma_data.ptrreg, peekdma_data.addr);
-       if (debug_mem_banks[peekdma_data.addr >> 16] == NULL)
-               return v;
-       if (!currprefs.z3chipmem.size)
+       if (debug_mem_banks[peekdma_data.addr >> 16] == NULL) {
+               return;
+       }
+       if (!currprefs.z3chipmem.size) {
                peekdma_data.addr &= chipmem_bank.mask;
+       }
        memwatch_func(peekdma_data.addr, 1, 2, &vv, peekdma_data.mask, peekdma_data.reg);
-       return vv;
 }
+void debug_getpeekdma_value_long(uae_u32 v, int offset)
+{
+       uae_u32 vv = v;
+       uae_u32 mask = 0xffffffff;
+       if (!memwatch_enabled) {
+               return;
+       }
+       is_valid_dma(peekdma_data.reg, peekdma_data.ptrreg, peekdma_data.addr + offset);
+       if (debug_mem_banks[(peekdma_data.addr + offset) >> 16] == NULL) {
+               return;
+       }
+       if (!currprefs.z3chipmem.size) {
+               mask = chipmem_bank.mask;
+       }
+       memwatch_func((peekdma_data.addr + offset) & mask, 1, 4, &vv, peekdma_data.mask, peekdma_data.reg);
+}
+
 
 uae_u32 debug_putpeekdma_chipset(uaecptr addr, uae_u32 v, uae_u32 mask, int reg)
 {
@@ -3860,6 +3903,7 @@ static void memwatch (TCHAR **c)
        mwn->modval_written = 0;
        mwn->mustchange = 0;
        mwn->bus_error = 0;
+       mwn->reportonly = false;
        ignore_ws (c);
        if (more_params (c)) {
                mwn->size = readhex (c);
@@ -7094,6 +7138,7 @@ static void debug_trainer_enable(struct trainerpatch *tp, bool enable)
                                mwn->val_enabled = 0;
                                mwn->val_mask = 0xffffffff;
                                mwn->val = 0;
+                               mwn->reportonly = false;
                                if (tp->patchtype == TRAINER_SET) {
                                        mwn->val_enabled = 1;
                                        mwn->val = tp->setvalue;
index 91d921aeaba3fe630246c764532680bcae6c9818..05c9fc6ec89678bd9acdc5b760fd746a4f061698 100644 (file)
@@ -28,6 +28,7 @@ To prevent extremely bad things (think pixels cut in half by window borders) fro
 happening, all ports should restrict window widths to be multiples of 16 pixels.  */
 
 #define SPRITE_DEBUG_HIDE 0
+#define BG_COLOR_DEBUG 0
 
 #include "sysconfig.h"
 #include "sysdeps.h"
@@ -55,7 +56,6 @@ happening, all ports should restrict window widths to be multiples of 16 pixels.
 #include "devices.h"
 #include "gfxboard.h"
 
-#define BG_COLOR_DEBUG 0
 //#define XLINECHECK
 
 struct amigadisplay adisplays[MAX_AMIGADISPLAYS];
@@ -77,6 +77,9 @@ static void pfield_set_linetoscr(void);
 
 int debug_bpl_mask = 0xff, debug_bpl_mask_one;
 
+static struct decision *dp_for_drawing;
+static struct draw_info *dip_for_drawing;
+
 static void lores_set(int lores)
 {
        int old = lores_shift;
@@ -249,10 +252,12 @@ static int visible_left_start, visible_right_stop;
 static int visible_top_start, visible_bottom_stop;
 /* same for hblank */
 static int hblank_left_start, hblank_right_stop;
+static bool exthblank;
 
 static int linetoscr_x_adjust_pixbytes, linetoscr_x_adjust_pixels;
 static int thisframe_y_adjust;
-static int thisframe_y_adjust_real, max_ypos_thisframe, min_ypos_for_screen;
+static int thisframe_y_adjust_real, min_ypos_for_screen;
+static int max_ypos_thisframe1;
 int thisframe_first_drawn_line, thisframe_last_drawn_line;
 
 /* A frame counter that forces a redraw after at least one skipped frame in
@@ -470,15 +475,31 @@ static void set_blanking_limits(void)
 {
        hblank_left_start = visible_left_start;
        hblank_right_stop = visible_right_stop;
+       if (hblank_left_start < visible_left_border) {
+               hblank_left_start = visible_left_border;
+       }
+       if (hblank_right_stop > visible_right_border) {
+               hblank_right_stop = visible_right_border;
+       }
 
-       if (beamcon0 & 0x0110) {
+       int hbstrt = 0;
+       int hbstop = 0;
+       int offset = -1;
+
+       if (!dp_for_drawing || !ce_is_extblankset(colors_for_drawing.extra) || !ce_is_extblankmode(colors_for_drawing.extra)) {
+               // hardwired blanking
                // has 1.5 hires pixel offset
-               int offset = 3;
-               if (hblank_left_start < coord_hw_to_window_x_shres(hsyncendpos - offset)) {
-                       hblank_left_start = coord_hw_to_window_x_shres(hsyncendpos - offset);
+               offset = 3;
+               hbstrt = hsyncstartpos_hw;
+               hbstop = hsyncendpos_hw;
+               exthblank = false;
+       }
+       if (offset >= 0) {
+               if (hblank_left_start < coord_hw_to_window_x_shres(hbstop - offset)) {
+                       hblank_left_start = coord_hw_to_window_x_shres(hbstop - offset);
                }
-               if (hblank_right_stop > coord_hw_to_window_x_shres(hsyncstartpos - offset)) {
-                       hblank_right_stop = coord_hw_to_window_x_shres(hsyncstartpos - offset);
+               if (hblank_right_stop > coord_hw_to_window_x_shres(hbstrt - offset)) {
+                       hblank_right_stop = coord_hw_to_window_x_shres(hbstrt - offset);
                }
        }
 }
@@ -503,7 +524,7 @@ void get_custom_raw_limits(int *pw, int *ph, int *pdx, int *pdy)
                if (y < visible_top_start)
                        y = visible_top_start;
                *pdy = y;
-               int y2 = max_ypos_thisframe;
+               int y2 = max_ypos_thisframe1;
                if (y2 > visible_bottom_stop)
                        y2 = visible_bottom_stop;
                *ph = y2 - y;
@@ -532,9 +553,7 @@ void check_custom_limits(void)
                visible_top_start = top;
        if (bottom > top && bottom < visible_bottom_stop)
                visible_bottom_stop = bottom;
-       
-       set_blanking_limits ();
-}
+       }
 
 void set_custom_limits (int w, int h, int dx, int dy)
 {
@@ -827,9 +846,6 @@ void get_custom_mouse_limits (int *pw, int *ph, int *pdx, int *pdy, int dbl)
        *pdx = dx; *pdy = dy;
 }
 
-static struct decision *dp_for_drawing;
-static struct draw_info *dip_for_drawing;
-
 /* Record DIW of the current line for use by centering code.  */
 void record_diw_line (int plfstrt, int first, int last)
 {
@@ -872,16 +888,19 @@ static int may_require_hard_way;
 static int linetoscr_diw_start, linetoscr_diw_end;
 static int native_ddf_left, native_ddf_right;
 static int hamleftborderhidden;
+static uae_u8 vb_state;
 
 static int pixels_offset;
 static int src_pixel;
 /* How many pixels in window coordinates which are to the left of the left border.  */
 static int unpainted;
 
-STATIC_INLINE xcolnr getbgc (int blank)
+STATIC_INLINE xcolnr getbgc(int blank)
 {
 #if BG_COLOR_DEBUG
-       if (blank > 0)
+       if (exthblank)
+               return xcolors[0x888];
+       else if (blank > 0)
                return xcolors[0x088];
        else if (blank < 0)
                return xcolors[0x0f8];
@@ -896,7 +915,29 @@ STATIC_INLINE xcolnr getbgc (int blank)
        //return colors_for_drawing.acolors[0];
        return xcolors[0xf0f];
 #endif
-       return (blank >= 0 && (blank > 0 || hposblank || ce_is_borderblank(colors_for_drawing.extra))) ? 0 : colors_for_drawing.acolors[0];
+       if (exthblank) {
+               return 0;
+       }
+       bool extblken = ce_is_extblankset(colors_for_drawing.extra);
+       // extblken=1: hblank and vblank = black
+       if (!(vb_state & 1) && extblken) {
+               return 0;
+       }
+       bool brdblank = ce_is_borderblank(colors_for_drawing.extra);
+#if 0
+       // if this line next line after VB end and bitplane DMA was active in previous (hidden) line: borderblank is ignored.
+       if (vb_state == 3) {
+               brdblank = false;
+       }
+#endif
+       // borderblank = black (overrides extblken)
+       if (brdblank) {
+               return 0;
+       }
+       if (hposblank || blank) {
+               return 0;
+       }
+       return colors_for_drawing.acolors[0];
 }
 
 
@@ -920,6 +961,7 @@ static void pfield_init_linetoscr (bool border)
        int leftborderhidden;
        int native_ddf_left2;
        bool expanded = false;
+       bool fulldiw = false;
 
        hsync_shift_hack = 0;
        
@@ -942,6 +984,12 @@ static void pfield_init_linetoscr (bool border)
 
        linetoscr_diw_start = dp_for_drawing->diwfirstword;
        linetoscr_diw_end = dp_for_drawing->diwlastword;
+       if (linetoscr_diw_start < 0) {
+               if (linetoscr_diw_start == -1) {
+                       fulldiw = true;
+               }
+               linetoscr_diw_start = 0;
+       }
 
        /* Perverse cases happen. */
        if (linetoscr_diw_end < linetoscr_diw_start)
@@ -971,6 +1019,8 @@ static void pfield_init_linetoscr (bool border)
        real_playfield_end = playfield_end;
        sprite_end = linetoscr_diw_end;
 
+       set_blanking_limits();
+
        // Sprite hpos don't include DIW_DDF_OFFSET and can appear 1 lores pixel
        // before first bitplane pixel appears.
        // This means "bordersprite" condition is possible under OCS/ECS too. Argh!
@@ -1042,6 +1092,10 @@ static void pfield_init_linetoscr (bool border)
                playfield_start_pre -= bplres;
                playfield_end_pre -= bplres;
        }
+       // if DIW was not closed horizontally, borderblank leaves color0 stripe before bitplanes
+       if (ce_is_borderblank(colors_for_drawing.extra) && fulldiw) {
+               playfield_start_pre = playfield_start - 2 * 4;
+       }
 
        unpainted = visible_left_border < playfield_start ? 0 : visible_left_border - playfield_start;
        unpainted = res_shift_from_window (unpainted);
@@ -1789,11 +1843,19 @@ static call_linetoscr pfield_do_linetoscr_spriteonly;
 
 static void pfield_do_linetoscr(int start, int stop, int blank)
 {
-       src_pixel = pfield_do_linetoscr_normal(src_pixel, start, stop);
+       int pixel = pfield_do_linetoscr_normal(src_pixel, start, stop);
+       if (exthblank) {
+               pfield_do_fill_line(start, stop, 1);
+       }
+       src_pixel = pixel;
 }
 static void pfield_do_linetoscr_spr(int start, int stop, int blank)
 {
-       src_pixel = pfield_do_linetoscr_sprite(src_pixel, start, stop);
+       int pixel = pfield_do_linetoscr_sprite(src_pixel, start, stop);
+       if (exthblank) {
+               pfield_do_fill_line(start, stop, 1);
+       }
+       src_pixel = pixel;
 }
 static int pfield_do_nothing(int a, int b, int c)
 {
@@ -2783,7 +2845,6 @@ static void init_aspect_maps(void)
        visible_right_stop = MAX_STOP;
        visible_top_start = 0;
        visible_bottom_stop = MAX_STOP;
-       set_blanking_limits();
 
        h = vidinfo->drawbuffer.height_allocated;
        if (h == 0)
@@ -2891,7 +2952,7 @@ static void pfield_expand_dp_bplcon(void)
        sbasecol[0] = ((dp_for_drawing->bplcon4sp >> 4) & 15) << 4;
        sbasecol[1] = ((dp_for_drawing->bplcon4sp >> 0) & 15) << 4;
        bplxor = dp_for_drawing->bplcon4bm >> 8;
-       int sh = (colors_for_drawing.extra >> CE_SHRES_DELAY) & 3;
+       int sh = (colors_for_drawing.extra >> CE_SHRES_DELAY_SHIFT) & 3;
        if (sh != bpldelay_sh) {
                bpldelay_sh = sh;
                pfield_mode_changed = true;
@@ -2911,6 +2972,7 @@ static void pfield_expand_dp_bplcon(void)
                        ecs_genlock_features_colorkey = true;
                }
        }
+
        if (pfield_mode_changed)
                pfield_set_linetoscr();
        
@@ -2936,15 +2998,13 @@ static bool isham(uae_u16 bplcon0)
        return 0;
 }
 
-static void pfield_expand_dp_bplconx (int regno, int v)
+static void pfield_expand_dp_bplconx (int regno, int v, int vp, int hp)
 {
-       if (regno == 0xffff) {
-               hposblank = 1;
-               return;
-       }
-       regno -= 0x1000;
+       regno -= RECORDED_REGISTER_CHANGE_OFFSET;
        switch (regno)
        {
+       case 0xffff - RECORDED_REGISTER_CHANGE_OFFSET:
+               return;
        case 0x100: // BPLCON0
                dp_for_drawing->bplcon0 = v;
                dp_for_drawing->bplres = GET_RES_DENISE(v);
@@ -2972,6 +3032,10 @@ static void pfield_expand_dp_bplconx (int regno, int v)
        case 0x1fc: // FMODE
                dp_for_drawing->fmode = v;
                break;
+       case 0x200: // hblank
+               exthblank = v != 0;
+               //write_log("%d,%d=%d ", hp, vp, v);
+               return;
 #endif
        }
        pfield_expand_dp_bplcon();
@@ -3068,8 +3132,17 @@ static void do_color_changes(line_draw_func worker_border, line_draw_func worker
                        lastpos = t;
                }
 
+               // vblank + extblanken: blanked
+               if (!(vb_state & 1) && ce_is_extblankset(colors_for_drawing.extra)) {
+
+                       if (nextpos_in_range > lastpos && lastpos < playfield_end) {
+                               int t = nextpos_in_range <= playfield_end ? nextpos_in_range : playfield_end;
+                               (*worker_border)(lastpos, t, 1);
+                               lastpos = t;
+                       }
+
                // normal
-               if (playfield_start_pre >= playfield_start || !ce_is_borderblank(colors_for_drawing.extra)) {
+               } else if (playfield_start_pre >= playfield_start || !ce_is_borderblank(colors_for_drawing.extra)) {
 
                        // normal left border (hblank end to playfield start)
                        if (nextpos_in_range > lastpos && lastpos < playfield_start) {
@@ -3141,38 +3214,40 @@ static void do_color_changes(line_draw_func worker_border, line_draw_func worker
                        lastpos = nextpos_in_range;
                }
 
-               if (regno >= 0x1000) {
-                       pfield_expand_dp_bplconx(regno, value);
-               } else if (regno >= 0 && !(value & COLOR_CHANGE_MASK)) {
-                       color_reg_set(&colors_for_drawing, regno, value);
-                       colors_for_drawing.acolors[regno] = getxcolor(value);
-               } else if (regno == 0 && (value & COLOR_CHANGE_MASK)) {
-                       if (value & COLOR_CHANGE_BLANK) {
-                               if (value & 1) {
-                                       colors_for_drawing.extra |= (1 << CE_BORDERBLANK);
-                                       pfield_do_linetoscr_normal = pfield_do_linetoscr_blank;
-                               } else {
+               if (i < dip_for_drawing->last_color_change) {
+                       if (regno >= RECORDED_REGISTER_CHANGE_OFFSET) {
+                               pfield_expand_dp_bplconx(regno, value, nextpos, vp);
+                       } else if (regno >= 0 && !(value & COLOR_CHANGE_MASK)) {
+                               color_reg_set(&colors_for_drawing, regno, value);
+                               colors_for_drawing.acolors[regno] = getxcolor(value);
+                       } else if (regno == 0 && (value & COLOR_CHANGE_MASK)) {
+                               if (value & COLOR_CHANGE_BLANK) {
+                                       if (value & 1) {
+                                               hposblank = 1;
+                                       } else {
+                                               hposblank = 0;
+                                       }
+                               } else if (value & COLOR_CHANGE_BRDBLANK) {
                                        colors_for_drawing.extra &= ~(1 << CE_BORDERBLANK);
-                                       pfield_do_linetoscr_normal = pfield_do_linetoscr_normal2;
+                                       colors_for_drawing.extra &= ~(1 << CE_BORDERNTRANS);
+                                       colors_for_drawing.extra &= ~(1 << CE_BORDERSPRITE);
+                                       colors_for_drawing.extra &= ~(1 << CE_EXTBLANKSET);
+                                       colors_for_drawing.extra &= ~(1 << CE_EXTBLANKMODE);
+                                       colors_for_drawing.extra |= (value & 1) != 0 ? (1 << CE_BORDERBLANK) : 0;
+                                       colors_for_drawing.extra |= (value & 3) == 2 ? (1 << CE_BORDERSPRITE) : 0;
+                                       colors_for_drawing.extra |= (value & 5) == 4 ? (1 << CE_BORDERNTRANS) : 0;
+                                       colors_for_drawing.extra |= (value & 8) == 8 ? (1 << CE_EXTBLANKSET) : 0;
+                                       colors_for_drawing.extra |= (value & 16) == 16 ? (1 << CE_EXTBLANKMODE) : 0;
+                               } else if (value & COLOR_CHANGE_SHRES_DELAY) {
+                                       colors_for_drawing.extra &= ~(1 << CE_SHRES_DELAY_SHIFT);
+                                       colors_for_drawing.extra &= ~(1 << (CE_SHRES_DELAY_SHIFT + 1));
+                                       colors_for_drawing.extra |= (value & 3) << CE_SHRES_DELAY_SHIFT;
+                                       pfield_expand_dp_bplcon();
+                               } else if (value & COLOR_CHANGE_HSYNC_HACK) {
+                                       hsync_shift_hack = (uae_s8)value;
                                }
-                       } if (value & COLOR_CHANGE_BRDBLANK) {
-                               colors_for_drawing.extra &= ~(1 << CE_BORDERBLANK);
-                               colors_for_drawing.extra &= ~(1 << CE_BORDERNTRANS);
-                               colors_for_drawing.extra &= ~(1 << CE_BORDERSPRITE);
-                               colors_for_drawing.extra |= (value & 1) != 0 ? (1 << CE_BORDERBLANK) : 0;
-                               colors_for_drawing.extra |= (value & 3) == 2 ? (1 << CE_BORDERSPRITE) : 0;
-                               colors_for_drawing.extra |= (value & 5) == 4 ? (1 << CE_BORDERNTRANS) : 0;
-                       } else if (value & COLOR_CHANGE_SHRES_DELAY) {
-                               colors_for_drawing.extra &= ~(1 << CE_SHRES_DELAY);
-                               colors_for_drawing.extra &= ~(1 << (CE_SHRES_DELAY + 1));
-                               colors_for_drawing.extra |= (value & 3) << CE_SHRES_DELAY;
-                               pfield_expand_dp_bplcon();
-                       } else if (value & COLOR_CHANGE_HSYNC_HACK) {
-                               hsync_shift_hack = (uae_s8)value;
                        }
                }
-               if (lastpos >= endpos)
-                       break;
        }
 #if 1
        if (vp < visible_top_start || vp >= visible_bottom_stop) {
@@ -3269,6 +3344,7 @@ static void pfield_draw_line(struct vidbuffer *vb, int lineno, int gfx_ypos, int
        }
 
        have_color_changes = is_color_changes(dip_for_drawing);
+       vb_state = dp_for_drawing->vb;
        sprite_smaller_than_64_inuse = false;
 
        dh = dh_line;
@@ -3440,6 +3516,8 @@ 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];
@@ -3448,6 +3526,7 @@ static void center_image (void)
        int prev_y_adjust = thisframe_y_adjust;
 
        int w = vidinfo->drawbuffer.inwidth;
+       int ew = vidinfo->drawbuffer.extrawidth;
        if (currprefs.gfx_xcenter && !currprefs.gf[0].gfx_filter_autoscale && max_diwstop > 0) {
 
                if (max_diwstop - min_diwstart < w && currprefs.gfx_xcenter == 2)
@@ -3466,14 +3545,21 @@ static void center_image (void)
                }
 #endif
        } else if (vidinfo->drawbuffer.extrawidth) {
-               visible_left_border = max_diwlastword - w;
-               if (vidinfo->drawbuffer.extrawidth > 0)
-                       visible_left_border += vidinfo->drawbuffer.extrawidth << currprefs.gfx_resolution;
+               visible_left_border = (hsync_end_left_border * 2) << currprefs.gfx_resolution;
+               if (visible_left_border + w < max_diwlastword) {
+                       visible_left_border += (max_diwlastword - (visible_left_border + w)) / 2;
+               }
+               if (ew > 0) {
+                       visible_left_border -= (ew / 2) << currprefs.gfx_resolution;
+               }
+               if (visible_left_border < ((hsync_end_left_border * 2) << currprefs.gfx_resolution)) {
+                       visible_left_border = (hsync_end_left_border * 2) << currprefs.gfx_resolution;
+               }
        } else {
                if (vidinfo->drawbuffer.inxoffset < 0) {
                        visible_left_border = 0;
                } else {
-                       visible_left_border = vidinfo->drawbuffer.inxoffset - DISPLAY_LEFT_SHIFT;
+                       visible_left_border = (vidinfo->drawbuffer.inxoffset - DISPLAY_LEFT_SHIFT) << currprefs.gfx_resolution;
                }
        }
 
@@ -3488,9 +3574,9 @@ static void center_image (void)
        linetoscr_x_adjust_pixels = visible_left_border;
        linetoscr_x_adjust_pixbytes = linetoscr_x_adjust_pixels * vidinfo->drawbuffer.pixbytes;
 
-       visible_right_border = visible_left_border + w;
-       if (visible_right_border > max_diwlastword)
-               visible_right_border = max_diwlastword;
+       visible_right_border = visible_left_border + w + ((ew > 0 ? ew : 0) << currprefs.gfx_resolution);
+       if (visible_right_border > max_diwlastword + ((ew > 0 ? ew : 0) << currprefs.gfx_resolution))
+               visible_right_border = max_diwlastword + ((ew > 0 ? ew : 0) << currprefs.gfx_resolution);
 
        int max_drawn_amiga_line_tmp = max_drawn_amiga_line;
        if (max_drawn_amiga_line_tmp > vidinfo->drawbuffer.inheight)
@@ -3522,7 +3608,7 @@ static void center_image (void)
                thisframe_y_adjust = 0;
 
        thisframe_y_adjust_real = thisframe_y_adjust << linedbl;
-       max_ypos_thisframe = (maxvpos_display - minfirstline + 1) << linedbl;
+       max_ypos_thisframe1 = (maxvpos_display - minfirstline + maxvpos_display_vsync) << linedbl;
 
        if (prev_x_adjust != visible_left_border || prev_y_adjust != thisframe_y_adjust) {
                int redraw = interlace_seen > 0 && linedbl ? 2 : 1;
@@ -3872,8 +3958,8 @@ static void lightpen_update(struct vidbuffer *vb, int lpnum)
                lightpen_y[lpnum] = LIGHTPEN_HEIGHT + 1;
        if (lightpen_y[lpnum] >= vidinfo->drawbuffer.inheight - LIGHTPEN_HEIGHT - 1)
                lightpen_y[lpnum] = vidinfo->drawbuffer.inheight - LIGHTPEN_HEIGHT - 2;
-       if (lightpen_y[lpnum] >= max_ypos_thisframe - LIGHTPEN_HEIGHT - 1)
-               lightpen_y[lpnum] = max_ypos_thisframe - LIGHTPEN_HEIGHT - 2;
+       if (lightpen_y[lpnum] >= max_ypos_thisframe1 - LIGHTPEN_HEIGHT - 1)
+               lightpen_y[lpnum] = max_ypos_thisframe1 - LIGHTPEN_HEIGHT - 2;
 
        int cx = (((lightpen_x[lpnum] + visible_left_border) >> lores_shift) >> 1) + DISPLAY_LEFT_SHIFT - DIW_DDF_OFFSET - 2;
 
@@ -3896,7 +3982,7 @@ static void lightpen_update(struct vidbuffer *vb, int lpnum)
        if (currprefs.lightpen_crosshair && lightpen_active) {
                for (int i = 0; i < LIGHTPEN_HEIGHT; i++) {
                        int line = lightpen_y[lpnum] + i - LIGHTPEN_HEIGHT / 2;
-                       if (line >= 0 && line < max_ypos_thisframe) {
+                       if (line >= 0 && line < max_ypos_thisframe1) {
                                if (lightpen_active & (1 << lpnum)) {
                                        draw_lightpen_cursor(vb->monitor_id, lightpen_x[lpnum], i, line, cx > 0, lpnum);
                                }
@@ -3934,7 +4020,7 @@ static const int refresh_indicator_colors[] = { 0x777, 0x0f0, 0x00f, 0xff0, 0xf0
 static void refresh_indicator_update(struct vidbuffer *vb)
 {
        struct vidbuf_description *vidinfo = &adisplays[vb->monitor_id].gfxvidinfo;
-       for (int i = 0; i < max_ypos_thisframe; i++) {
+       for (int i = 0; i < max_ypos_thisframe1; i++) {
                int i1 = i + min_ypos_for_screen;
                int line = i + thisframe_y_adjust_real;
                int whereline = amiga2aspect_line_map[i1];
@@ -3977,7 +4063,8 @@ static void draw_frame2(struct vidbuffer *vbin, struct vidbuffer *vbout)
        int largest = 0;
 #endif
 
-       for (int i = 0; i < max_ypos_thisframe; i++) {
+       set_blanking_limits();
+       for (int i = 0; i < max_ypos_thisframe1; i++) {
                int i1 = i + min_ypos_for_screen;
                int line = i + thisframe_y_adjust_real;
                int whereline = amiga2aspect_line_map[i1];
@@ -3988,6 +4075,8 @@ static void draw_frame2(struct vidbuffer *vbin, struct vidbuffer *vbout)
                if (whereline < 0)
                        continue;
 
+
+
 #if LARGEST_LINE_DEBUG
                if (largest < whereline)
                        largest = whereline;
@@ -4452,7 +4541,7 @@ void vsync_handle_redraw(int long_field, int lof_changed, uae_u16 bplcon0p, uae_
        gui_flicker_led (-1, 0, 0);
 }
 
-void hsync_record_line_state(int lineno, enum nln_how how, int changed)
+void hsync_record_line_state (int lineno, enum nln_how how, int changed)
 {
        struct amigadisplay *ad = &adisplays[0];
        uae_u8 *state;
@@ -4629,6 +4718,7 @@ void reset_drawing(void)
        struct vidbuf_description *vidinfo = &ad->gfxvidinfo;
 
        max_diwstop = 0;
+       vb_state = 0;
 
        lores_reset ();
 
@@ -4701,7 +4791,7 @@ void drawing_init (void)
        ad->inhibit_frame = 0;
 
        gfxbuffer_reset(0);
-       reset_drawing ();
+       reset_drawing();
 }
 
 int isvsync_chipset(void)
index ced0c4bd6a17c7a4bad6d010802ca29aba738b4e..374c2fefadb322d695030c2a49733de92c39ad6d 100644 (file)
@@ -115,8 +115,8 @@ extern uae_u16 INTREQR(void);
 #define VBLANK_ENDLINE_PAL 26
 #define VBLANK_ENDLINE_NTSC 21
 // line when sprite DMA fetches first control words
-#define VBLANK_SPRITE_PAL 25
-#define VBLANK_SPRITE_NTSC 20
+#define VBLANK_STOP_PAL 25
+#define VBLANK_STOP_NTSC 20
 #define VBLANK_HZ_PAL 50
 #define VBLANK_HZ_NTSC 60
 #define VSYNC_ENDLINE_PAL 5
@@ -125,8 +125,9 @@ extern uae_u16 INTREQR(void);
 #define EQU_ENDLINE_NTSC 10
 
 extern int maxhpos, maxhpos_short;
-extern int maxvpos, maxvpos_nom, maxvpos_display;
+extern int maxvpos, maxvpos_nom, maxvpos_display, maxvpos_display_vsync;
 extern int hsyncstartpos, hsyncendpos;
+extern int hsyncstartpos_hw, hsyncendpos_hw;
 extern int minfirstline, vblank_endline, numscrlines;
 extern float vblank_hz, fake_vblank_hz;
 extern float hblank_hz;
index b661a7b98287786f4288fedf7adb65d92b8022a4..5a764499ba44345fa72d69dfb0a479e55d6052c0 100644 (file)
@@ -175,7 +175,8 @@ extern struct memwatch_node mwnodes[MEMWATCH_TOTAL];
 extern void memwatch_dump2 (TCHAR *buf, int bufsize, int num);
 
 void debug_getpeekdma_chipram(uaecptr addr, uae_u32 mask, int reg, int ptrreg);
-uae_u32 debug_getpeekdma_value(uae_u32 v);
+void debug_getpeekdma_value(uae_u32);
+void debug_getpeekdma_value_long(uae_u32, int);
 uae_u32 debug_putpeekdma_chipram(uaecptr addr, uae_u32 v, uae_u32 mask, int reg, int ptrreg);
 uae_u32 debug_putpeekdma_chipset(uaecptr addr, uae_u32 v, uae_u32 mask, int reg);
 void debug_lgetpeek(uaecptr addr, uae_u32 v);
@@ -214,7 +215,8 @@ extern struct peekdma peekdma_data;
 struct dma_rec
 {
     uae_u16 reg;
-    uae_u32 dat;
+    uae_u64 dat;
+       uae_u16 size;
     uae_u32 addr;
     uae_u16 evt;
     uae_s16 type;
@@ -252,6 +254,7 @@ extern struct dma_rec *last_dma_rec;
 extern void record_dma_read(uae_u16 reg, uae_u32 addr, int hpos, int vpos, int type, int extra);
 extern void record_dma_write(uae_u16 reg, uae_u32 v, uae_u32 addr, int hpos, int vpos, int type, int extra);
 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);
index 0f02c2b8e6bc80e9edf5c8b8b9890e90a6b5a243..09f4d9e51d99f538a4be904065675a8f9d865fa8 100644 (file)
 #define MAX_PLANES 6
 #endif
 
-#define AMIGA_WIDTH_MAX (752 / 2)
+extern int lores_shift, shres_shift, interlace_seen;
+extern bool aga_mode, ecs_agnus, ecs_denise, direct_rgb;
+extern int visible_left_border, visible_right_border;
+extern int detected_screen_resolution;
+extern int hsync_end_left_border, hsynctotal;
+
+#define AMIGA_WIDTH_MAX (754 / 2)
 #define AMIGA_HEIGHT_MAX (576 / 2)
 
 // Cycles * 2 from start of scanline to first refresh slot (hsync strobe slot)
 #define DDF_OFFSET (2 * 4)
 
+#define RECORDED_REGISTER_CHANGE_OFFSET 0x1000
+
 /* According to the HRM, pixel data spends a couple of cycles somewhere in the chips
 before it appears on-screen. (TW: display emulation now does this automatically)  */
 #define DIW_DDF_OFFSET 1
 #define DIW_DDF_OFFSET_SHRES (DIW_DDF_OFFSET << 2)
 /* We ignore that many lores pixels at the start of the display. These are
 * invisible anyway due to hardware DDF limits. */
-#define DISPLAY_LEFT_SHIFT 0x3c
+#define DISPLAY_LEFT_SHIFT 0
 #define DISPLAY_LEFT_SHIFT_SHRES (DISPLAY_LEFT_SHIFT << 2)
 
 #define CCK_SHRES_SHIFT 3
 
-extern int lores_shift, shres_shift, interlace_seen;
-extern bool aga_mode, ecs_agnus, ecs_denise, direct_rgb;
-extern int visible_left_border, visible_right_border;
-extern int detected_screen_resolution;
-extern int hsynctotal;
-
 STATIC_INLINE int shres_coord_hw_to_window_x(int x)
 {
        x -= DISPLAY_LEFT_SHIFT_SHRES;
@@ -121,12 +123,22 @@ STATIC_INLINE int coord_window_to_diw_x(int x)
 #define CE_BORDERBLANK 0
 #define CE_BORDERNTRANS 1
 #define CE_BORDERSPRITE 2
-#define CE_SHRES_DELAY 4
+#define CE_EXTBLANKSET 3
+#define CE_EXTBLANKMODE 4
+#define CE_SHRES_DELAY_SHIFT 8
 
 STATIC_INLINE bool ce_is_borderblank(uae_u8 data)
 {
        return (data & (1 << CE_BORDERBLANK)) != 0;
 }
+STATIC_INLINE bool ce_is_extblankset(uae_u8 data)
+{
+       return (data & (1 << CE_EXTBLANKSET)) != 0;
+}
+STATIC_INLINE bool ce_is_extblankmode(uae_u8 data)
+{
+       return (data & (1 << CE_EXTBLANKMODE)) != 0;
+}
 STATIC_INLINE bool ce_is_bordersprite(uae_u8 data)
 {
        return (data & (1 << CE_BORDERSPRITE)) != 0;
@@ -144,7 +156,7 @@ struct color_entry {
        xcolnr acolors[256];
        uae_u32 color_regs_aga[256];
 #endif
-       uae_u8 extra;
+       uae_u16 extra;
 };
 
 #ifdef AGA
@@ -302,6 +314,7 @@ struct decision {
 #ifdef AGA
        bool bordersprite_seen;
        bool xor_seen;
+       uae_u8 vb;
 #endif
 };
 
index b381a6750e1882a2f4279e5565c0b15c2da8aa5c..33f09021aa265dcddecff74e0e66416a7fbae3ca 100644 (file)
@@ -564,6 +564,7 @@ struct uae_prefs {
        int gfx_api_options;
        int color_mode;
        int gfx_extrawidth;
+       int gfx_extraheight;
        bool lightboost_strobo;
        int lightboost_strobo_ratio;
        bool gfx_grayscale;
@@ -684,7 +685,7 @@ struct uae_prefs {
        int cs_hacks;
        int cs_ciatype[2];
        int cs_kbhandshake;
-       bool cs_ocshsyncbug;
+       bool cs_ocshblankbug;
 
        struct boardromconfig expansionboard[MAX_EXPANSION_BOARDS];
 
index 8a28107ae909ba0a28f019f0a241c5b600f16d4c..2e993f37b3418d6a6899b5f3dec0dfff61d74ae6 100644 (file)
@@ -126,12 +126,12 @@ struct vidbuffer
        /* tempbuffer in use */
        bool tempbufferinuse;
        /* extra width, chipset hpos extra in right border */
-       int extrawidth;
+       int extrawidth, extraheight;
 
        int xoffset; /* superhires pixels from left edge */
        int yoffset; /* lines from top edge */
 
-       int inxoffset; /* positive if sync positioning */
+       int inxoffset; /* sync positioning */
        int inyoffset;
 
        int monitor_id;
index e98998d5608d84ecd16cbc572eac1333b97eb34c..dc06fc08114e5102757bc8f9d248e8af18a9bb83 100644 (file)
@@ -4211,9 +4211,10 @@ static bool inputdevice_handle_inputcode2(int monid, int code, int state, const
                }
        }
 
+#if 0
        if (vpos != 0)
-               write_log (_T("inputcode=%d but vpos = %d"), code, vpos);
-
+               write_log (_T("inputcode=%d but vpos = %d\n"), code, vpos);
+#endif
        if (onoffstate == SET_ONOFF_ON_VALUE)
                newstate = 1;
        else if (onoffstate == SET_ONOFF_OFF_VALUE)
index 76cf5318e41758443b17ba145a8dd89c9959350c..1f48eda36356e5ed74585ee46f6cb035ebe15def 100644 (file)
 #define IDC_DBG_MEM                     1756
 #define IDC_CS_COMPOSITECOLOR           1756
 #define IDC_DBG_DASM                    1757
-#define IDC_CS_OCSHSYNCBUG              1757
+#define IDC_CS_OCSHBLANKBUG             1757
 #define IDC_DBG_MEMDOWNFAST             1758
 #define IDC_CS_TOSHIBAGARY              1758
 #define IDC_DBG_MEMTOPC                 1759
index 53a68747958ab2d5f8ea970ce8d876039ffaa940..9d1ce25ac988dc472f61d061a978262cd1fbb86a 100644 (file)
@@ -849,7 +849,7 @@ BEGIN
     CONTROL         "KS ROM has Chip RAM speed",IDC_CS_ROMISSLOW,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,127,197,125,12
     CONTROL         "CIA 391078-01 [] CIA revision that can't read IO pin status in output mode",IDC_CS_CIA,
                     "Button",BS_AUTOCHECKBOX | WS_TABSTOP,264,197,125,12
-    CONTROL         "OCS H-Sync glitch",IDC_CS_OCSHSYNCBUG,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,263,184,125,12
+    CONTROL         "OCS H-Blank glitch",IDC_CS_OCSHBLANKBUG,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,264,184,125,12
 END
 
 IDD_AVIOUTPUT DIALOGEX 0, 0, 396, 316
index ae6f3d25ba0c4f66d3a80cb494373fe84e31f15d..29877df1e9063a9e8acf582d37918447c3b7a829 100644 (file)
@@ -9012,7 +9012,7 @@ static void values_to_chipsetdlg2 (HWND hDlg)
        CheckDlgButton(hDlg, IDC_CS_1MCHIPJUMPER, workprefs.cs_1mchipjumper || workprefs.chipmem.size >= 0x100000);
        CheckDlgButton(hDlg, IDC_CS_BYTECUSTOMWRITEBUG, workprefs.cs_bytecustomwritebug);
        CheckDlgButton(hDlg, IDC_CS_COMPOSITECOLOR, workprefs.cs_color_burst);
-       CheckDlgButton(hDlg, IDC_CS_OCSHSYNCBUG, workprefs.cs_ocshsyncbug);
+       CheckDlgButton(hDlg, IDC_CS_OCSHBLANKBUG, workprefs.cs_ocshblankbug);
        CheckDlgButton(hDlg, IDC_CS_TOSHIBAGARY, workprefs.cs_toshibagary);
        CheckDlgButton(hDlg, IDC_CS_ROMISSLOW, workprefs.cs_romisslow);
        CheckDlgButton(hDlg, IDC_CS_CIA, workprefs.cs_ciatype[0]);
@@ -9105,7 +9105,7 @@ static void values_from_chipsetdlg2 (HWND hDlg, UINT msg, WPARAM wParam, LPARAM
        workprefs.cs_1mchipjumper = ischecked(hDlg, IDC_CS_1MCHIPJUMPER);
        workprefs.cs_bytecustomwritebug = ischecked(hDlg, IDC_CS_BYTECUSTOMWRITEBUG);
        workprefs.cs_color_burst = ischecked(hDlg, IDC_CS_COMPOSITECOLOR);
-       workprefs.cs_ocshsyncbug = ischecked(hDlg, IDC_CS_OCSHSYNCBUG);
+       workprefs.cs_ocshblankbug = ischecked(hDlg, IDC_CS_OCSHBLANKBUG);
        workprefs.cs_toshibagary = ischecked(hDlg, IDC_CS_TOSHIBAGARY);
        workprefs.cs_romisslow = ischecked(hDlg, IDC_CS_ROMISSLOW);
        workprefs.cs_ciatype[0] = workprefs.cs_ciatype[1] = ischecked(hDlg, IDC_CS_CIA);
@@ -9196,7 +9196,7 @@ static void enable_for_chipsetdlg2 (HWND hDlg)
        ew(hDlg, IDC_CS_1MCHIPJUMPER, e && workprefs.chipmem.size < 0x100000);
        ew(hDlg, IDC_CS_BYTECUSTOMWRITEBUG, e);
        ew(hDlg, IDC_CS_COMPOSITECOLOR, e);
-       ew(hDlg, IDC_CS_OCSHSYNCBUG, e);
+       ew(hDlg, IDC_CS_OCSHBLANKBUG, e);
        ew(hDlg, IDC_CS_TOSHIBAGARY, e);
        ew(hDlg, IDC_CS_ROMISSLOW, e);
        ew(hDlg, IDC_CS_UNMAPPED, e);