]> git.unchartedbackwaters.co.uk Git - francis/winuae.git/commitdiff
Custom emulation update WIP. Sprites.
authorToni Wilen <twilen@winuae.net>
Sat, 10 Apr 2021 14:15:51 +0000 (17:15 +0300)
committerToni Wilen <twilen@winuae.net>
Sat, 10 Apr 2021 14:15:51 +0000 (17:15 +0300)
custom.cpp

index 055f6d64c80ca6a4f82538c49f8acf2f2cf75059..526ccc402308434b18dc774db6c42bfb083ce456 100644 (file)
@@ -1,5 +1,4 @@
 /*
-/*
 * UAE - The Un*x Amiga Emulator
 *
 * Custom chip emulation
@@ -58,6 +57,8 @@
 #define AUTOSCALE_SPRITES 1
 #define ALL_SUBPIXEL 1
 
+#define RGA_COPPER_PIPELINE_DEPTH 2
+#define RGA_SPRITE_PIPELINE_DEPTH 3
 #define REFRESH_FIRST_HPOS 3
 #define DMAL_FIRST_HPOS 11
 #define SPR_FIRST_HPOS 25
@@ -133,6 +134,7 @@ static bool genlockvtoggle;
 static bool graphicsbuffer_retry;
 static int cia_hsync;
 static bool toscr_scanline_complex_bplcon1;
+static bool cant_this_last_line;
 
 #define LOF_TOGGLES_NEEDED 3
 //#define NLACE_CNT_NEEDED 50
@@ -510,8 +512,8 @@ static int bprun_pipeline_flush_delay;
 
 static uae_u16 rga_pipeline[256];
 static int rga_pipeline_bpl_read, rga_pipeline_bpl_write;
-static int rga_pipeline_copper_read;
-static int rga_pipeline_sprite_read;
+static int rga_pipeline_copper;
+static int rga_pipeline_sprite;
 #define RGA_PIPELINE_MASK 255
 
 struct custom_store custom_storage[256];
@@ -1097,6 +1099,15 @@ STATIC_INLINE int isocs7planes(void)
        return !aga_mode && bplcon0_res == 0 && bplcon0_planes == 7;
 }
 
+int get_sprite_dma_rel(int off)
+{
+       uae_u16 v = rga_pipeline[(rga_pipeline_sprite + off) & RGA_PIPELINE_MASK] & 0xff;
+       if (v >= 0x40 && v <= 0x5f) {
+               return v & 7;
+       }
+       return -1;
+}
+
 int get_bitplane_dma_rel(int off)
 {
        uae_u16 v = rga_pipeline[(rga_pipeline_bpl_read + off) & RGA_PIPELINE_MASK] & 0xff;
@@ -3016,7 +3027,7 @@ static void decide_bpl_fetch(int endhpos)
        }
 }
 
-static bool cant_this_last_line(void)
+static bool is_cant_this_last_line(void)
 {
        // Last line..
        // ..works normally if A1000 Agnus
@@ -3038,7 +3049,7 @@ static void decide_vline(int endhpos)
                }
        }
        // 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)) {
+       if (vpos == plflastline || cant_this_last_line || (vpos == 0 && currprefs.cs_dipagnus)) {
                diwstate = DIW_waiting_start;
                diwstate_vpos = vpos;
                SET_LINE_CYCLEBASED;
@@ -3564,9 +3575,10 @@ static void decide_sprites(int hpos, bool usepointx, bool quick)
        if (thisline_decision.plfleft < 0 && !brdspractive() && !quick)
                return;
 
+       point = hpos * 2 - DDF_OFFSET;
+
        // let sprite shift register empty completely
        // if sprite is at the very edge of right border
-       point = hpos * 2 - DDF_OFFSET;
        if (hpos >= maxhpos) {
                point += (extrahpos >> 2) - 2;
        }
@@ -5906,12 +5918,15 @@ 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 (vpos < sprite_vblank_endline || cant_this_last_line || s->ignoreverticaluntilnextline) {
                return;
-       if (vpos == s->vstart)
+       }
+       if (vpos == s->vstart) {
                s->dmastate = 1;
-       if (vpos == s->vstop)
+       }
+       if (vpos == s->vstop) {
                s->dmastate = 0;
+       }
 }
 
 static void SPRxCTLPOS(int num)
@@ -5981,6 +5996,7 @@ static void SPRxCTL_1(uae_u16 v, int num, int hpos)
 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);
@@ -6119,7 +6135,7 @@ static void SPRxPOS(int hpos, uae_u16 v, int num)
        // Superfrog flashing intro bees fix.
        // if SPRxPOS is written one cycle before sprite's first DMA slot and sprite's vstart matches after
        // SPRxPOS write, current line's DMA slot's stay idle. DMA decision seems to be done 4 cycles earlier.
-       if (hpos >= SPR_FIRST_HPOS + num * 4 - 4 && hpos <= SPR_FIRST_HPOS + num * 4 - 1 && oldvpos != vpos) {
+       if (hpos >= SPR_FIRST_HPOS + num * 4 - 4 && hpos <= SPR_FIRST_HPOS + num * 4 - 1 && oldvpos != vpos && (copper_access || currprefs.cpu_memory_cycle_exact)) {
                s->ptxvpos2 = vpos;
                s->ptxhpos2 = hpos + 4;
        }
@@ -6128,7 +6144,7 @@ static void SPRxPOS(int hpos, uae_u16 v, int num)
 static void SPRxPTH(int hpos, uae_u16 v, int num)
 {
        decide_sprites(hpos);
-       if (hpos - 1 != spr[num].ptxhpos) {
+       if (get_sprite_dma_rel(-2) != num || (!copper_access && !currprefs.cpu_memory_cycle_exact)) {
                spr[num].pt &= 0xffff;
                spr[num].pt |= (uae_u32)v << 16;
        }
@@ -6141,7 +6157,7 @@ static void SPRxPTH(int hpos, uae_u16 v, int num)
 static void SPRxPTL(int hpos, uae_u16 v, int num)
 {
        decide_sprites(hpos);
-       if (hpos - 1 != spr[num].ptxhpos) {
+       if (hpos != spr[num].ptxhpos || (!copper_access && !currprefs.cpu_memory_cycle_exact)) {
                spr[num].pt &= ~0xffff;
                spr[num].pt |= v & ~1;
        }
@@ -6338,7 +6354,7 @@ static int custom_wput_copper(int hpos, uaecptr pt, uaecptr addr, uae_u32 value,
        return v;
 }
 
-static void do_sprites(int endhpos);
+static void decide_sprite_fetch(int endhpos);
 
 
 static void decide_line_decision(int endhpos)
@@ -6449,7 +6465,9 @@ static void decide_line_decision(int endhpos)
                        if (!bprun && dma && diw && hwi && !hwi_old) {
                                // Bitplane sequencer activated
                                bprun = -1;
-                               plfstrt_sprite = hpos + 4;
+                               if (plfstrt_sprite > hpos) {
+                                       plfstrt_sprite = hpos;
+                               }
                        }
 
                        hwi_old = hwi;
@@ -6510,7 +6528,9 @@ static void decide_line_decision(int endhpos)
                        if (!ddf_limit && ddfstrt_match && !bprun && dma && diw) {
                                // Bitplane sequencer activated
                                bprun = -1;
-                               plfstrt_sprite = hpos + 2;
+                               if (plfstrt_sprite > hpos) {
+                                       plfstrt_sprite = hpos;
+                               }
                        }
 
                        // DMA or DIW off: clear BPRUN
@@ -6531,9 +6551,7 @@ static void decide_line_decision(int endhpos)
                        }
                }
 
-               if (hpos >= last_decide_sprite_hpos && last_decide_sprite_hpos < SPR_FIRST_HPOS + 4 * MAX_SPRITES) {
-                       do_sprites(hpos + 1);
-               }
+               decide_sprite_fetch(hpos + 1);
 
                hpos++;
        }
@@ -6566,7 +6584,7 @@ static int customdelay[]= {
        /* BPLxDAT */
        0,0,0,0,0,0,0,0, /* 8 */
        /* SPRxPTH/SPRxPTL */
-       1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 16 */
+       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 16 */
        /* SPRxPOS/SPRxCTL/SPRxDATA/SPRxDATB */
        0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
        /* COLORxx */
@@ -6862,8 +6880,8 @@ static void copper_ff(int hpos)
 {
        int diff = hpos - last_copper_hpos;
        if (diff > 0) {
-               rga_pipeline_copper_read += diff;
-               rga_pipeline_copper_read &= RGA_PIPELINE_MASK;
+               rga_pipeline_copper += diff;
+               rga_pipeline_copper &= RGA_PIPELINE_MASK;
        }
        last_copper_hpos = hpos;
 }
@@ -6924,7 +6942,7 @@ static void update_copper(int until_hpos)
                // NOTE: can use odd cycles if DMA request was done during last cycle of line and it was even cycle (always in PAL).
                // request cycle 226 (even), request always completes in 2 cycles = cycle 1 (odd).
                // pipelined copper DMA read?
-               int rpos = (rga_pipeline_copper_read - 2) & RGA_PIPELINE_MASK;
+               int rpos = (rga_pipeline_copper - RGA_COPPER_PIPELINE_DEPTH) & RGA_PIPELINE_MASK;
                bool copper_dma = rga_pipeline[rpos] >= 0x80 && rga_pipeline[rpos] <= 0x8f;
                if (copper_dma) {
                        uae_u16 v = rga_pipeline[rpos];
@@ -6953,7 +6971,7 @@ static void update_copper(int until_hpos)
                        }
                }
 
-               cp = &rga_pipeline[(rga_pipeline_copper_read + 0) & RGA_PIPELINE_MASK];
+               cp = &rga_pipeline[(rga_pipeline_copper + 0) & RGA_PIPELINE_MASK];
 
                switch (cop_state.state)
                {
@@ -7132,8 +7150,8 @@ next:
                }
 
                hpos++;
-               rga_pipeline_copper_read++;
-               rga_pipeline_copper_read &= RGA_PIPELINE_MASK;
+               rga_pipeline_copper++;
+               rga_pipeline_copper &= RGA_PIPELINE_MASK;
                last_copper_hpos = hpos;
        }
 }
@@ -7214,7 +7232,7 @@ static void cursorsprite (void)
        }
 }
 
-static uae_u16 sprite_fetch(struct sprite *s, uaecptr pt, bool dma, int hpos, int cycle, int mode)
+static uae_u16 sprite_fetch(struct sprite *s, uaecptr pt, int hpos, int slot, int mode)
 {
        uae_u16 data = last_custom_value1;
 
@@ -7223,40 +7241,37 @@ static uae_u16 sprite_fetch(struct sprite *s, uaecptr pt, bool dma, int hpos, in
                write_log(_T("Sprite %d, hpos %d wrong cycle polarity!\n"), num, hpos);
        }
 
-       if (dma) {
-               if (cycle && currprefs.cpu_memory_cycle_exact)
-                       s->ptxhpos = hpos;
+       s->ptxhpos = hpos;
 #ifdef DEBUGGER
-               int num = s - &spr[0];
-               if (debug_dma) {
-                       record_dma_read(num * 8 + 0x140 + mode * 4 + cycle * 2, pt, hpos, vpos, DMARECORD_SPRITE, num);
-               }
-               if (memwatch_enabled) {
-                       debug_getpeekdma_chipram(pt, MW_MASK_SPR_0 << num, num * 8 + 0x140 + mode * 4 + cycle * 2, num * 4 + 0x120);
-               }
+       int num = s - &spr[0];
+       if (debug_dma) {
+               record_dma_read(num * 8 + 0x140 + mode * 4 + slot * 2, pt, hpos, vpos, DMARECORD_SPRITE, num);
+       }
+       if (memwatch_enabled) {
+               debug_getpeekdma_chipram(pt, MW_MASK_SPR_0 << num, num * 8 + 0x140 + mode * 4 + slot * 2, num * 4 + 0x120);
+       }
 #endif
-               data = last_custom_value1 = chipmem_wget_indirect(pt);
+       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);
+       if (debug_dma) {
+               record_dma_read_value(data);
+       }
+       if (memwatch_enabled) {
+               debug_getpeekdma_value(data);
        }
+#endif
+       alloc_cycle(hpos, CYCLE_SPRITE);
        return data;
 }
 
-static void sprite_fetch_full(struct sprite *s, int hpos, int cycle, int mode, uae_u16 *v0, uae_u32 *v1, uae_u32 *v2)
+static void sprite_fetch_full(struct sprite *s, int hpos, int slot, int mode, uae_u16 *v0, uae_u32 *v1, uae_u32 *v2)
 {
        uae_u32 data321 = 0, data322 = 0;
        uae_u16 data16;
 
        if (sprite_width == 16) {
 
-               data16 = sprite_fetch(s, s->pt, true, hpos, cycle, mode);
+               data16 = sprite_fetch(s, s->pt, hpos, slot, mode);
                s->pt += 2;
 
        } else if (sprite_width == 64) {
@@ -7270,7 +7285,7 @@ static void sprite_fetch_full(struct sprite *s, int hpos, int cycle, int mode, u
                        pm1 = pm;
                        pm2 = pm + 4;
                }
-               data321 = sprite_fetch(s, pm1, true, hpos, cycle, mode) << 16;
+               data321 = sprite_fetch(s, pm1, hpos, slot, mode) << 16;
                data321 |= chipmem_wget_indirect(pm1 + 2);
                data322 = chipmem_wget_indirect(pm2) << 16;
                data322 |= chipmem_wget_indirect(pm2 + 2);
@@ -7286,7 +7301,7 @@ static void sprite_fetch_full(struct sprite *s, int hpos, int cycle, int mode, u
        } else { // 32
 
                uaecptr pm = s->pt & ~3;
-               data321 = sprite_fetch(s, pm, true, hpos, cycle, mode) << 16;
+               data321 = sprite_fetch(s, pm, hpos, slot, mode) << 16;
                data321 |= chipmem_wget_indirect(pm + 2);
                if (s->pt & 2) {
                        data321 &= 0x0000ffff;
@@ -7305,157 +7320,26 @@ static void sprite_fetch_full(struct sprite *s, int hpos, int cycle, int mode, u
        *v2 = data322;
 }
 
-static void do_sprite_dma(uae_u16 dat, int hpos)
+static void do_sprite_fetch(int hpos, uae_u16 dat)
 {
        int num = dat & 7;
        struct sprite *s = &spr[num];
        uae_u32 data321, data322;
        uae_u16 data;
-       bool cycle = (dat & 8) != 0;
-
-       sprite_fetch_full(s, hpos, cycle, false, &data, &data321, &data322);
-       if (1) {
-               if (cycle) {
-                       SPRxDATB_1(data, num, hpos);
-               } else {
-                       SPRxDATA_1(data, num, hpos);
-               }
-#ifdef AGA
-               switch (sprite_width)
-               {
-               case 64:
-                       if (cycle == 0) {
-                               s->data[1] = data321;
-                               s->data[2] = data322 >> 16;
-                               s->data[3] = data322;
-                       } else {
-                               s->datb[1] = data321;
-                               s->datb[2] = data322 >> 16;
-                               s->datb[3] = data322;
-                       }
-                       break;
-               case 32:
-                       if (cycle == 0) {
-                               s->data[1] = data321;
-                               s->data[2] = data;
-                               s->data[3] = data321;
-                       } else {
-                               s->datb[1] = data321;
-                               s->datb[2] = data;
-                               s->datb[3] = data321;
-                       }
-                       break;
-               }
-#endif
-       } else {
-               if (cycle) {
-                       SPRxPOS_1(data, num, hpos);
-               } else {
-                       SPRxCTL_1(data, num, hpos);
-               }
-       }
-
-}
-
-static void do_sprites_1(int num, int cycle, int hpos)
-{
-       struct sprite *s = &spr[num];
-       int posctl = 0;
-       uae_u16 data;
-       // fetch both sprite pairs even if DMA was switched off between sprites
-       int isdma = dmaen(DMA_SPRITE) || ((num & 1) && spr[num & ~1].dmacycle);
-       bool unaligned = (spr[num].pt & 2) != 0;
-
-       if (cant_this_last_line())
-               return;
-
-//     see SPRxCTRL below
-//     if (isdma && vpos == sprite_vblank_endline)
-//             spr_arm(num, 0);
-
-#ifdef AGA
-       if (isdma && s->dblscan && (fmode & 0x8000) && (vpos & 1) != (s->vstart & 1) && s->dmastate) {
-               spr_arm(num, 1);
-               return;
-       }
-#endif
-#if SPRITE_DEBUG >= 3 * 256
-       if (vpos >= SPRITE_DEBUG_MINY && vpos <= SPRITE_DEBUG_MAXY && (SPRITE_DEBUG & (1 << num)))
-               write_log(_T("%d:%d:slot%d:%d\n"), vpos, hpos, num, cycle);
-#endif
-       if (vpos == s->vstart) {
-#if SPRITE_DEBUG > 0
-               if (!s->dmastate && vpos >= SPRITE_DEBUG_MINY && vpos <= SPRITE_DEBUG_MAXY && (SPRITE_DEBUG & (1 << num)))
-                       write_log(_T("%d:%d:SPR%d START\n"), vpos, hpos, num);
-#endif
-               s->dmastate = 1;
-               if (s->ptxvpos2 == vpos && hpos < s->ptxhpos2)
-                       return;
-               if (num == 0 && cycle == 0)
-                       cursorsprite();
-       }
-       if (vpos == s->vstop || vpos == sprite_vblank_endline) {
-#if SPRITE_DEBUG > 0
-               if (s->dmastate && vpos >= SPRITE_DEBUG_MINY && vpos <= SPRITE_DEBUG_MAXY && (SPRITE_DEBUG & (1 << num)))
-                       write_log(_T("%d:%d:SPR%d STOP\n"), vpos, hpos, num);
-#endif
-               s->dmastate = 0;
-       }
-
-       if (!isdma)
-               return;
+       bool slot = (dat & 8) != 0;
+       bool dmastate = (dat & 0x10) != 0;
 
-       int dma = hpos < plfstrt_sprite || diwstate != DIW_waiting_stop;
+       spr[num].ptxhpos = MAXHPOS;
+       sprite_fetch_full(s, hpos, slot, false, &data, &data321, &data322);
        int sprxp = s->xpos >> (sprite_buffer_res + 1);
        bool start_before_dma = hpos >= sprxp && sprxp >= 16;
-       if (vpos == s->vstop || vpos == sprite_vblank_endline) {
-               s->dmastate = 0;
-               posctl = 1;
-               if (dma) {
-                       uae_u32 data321, data322;
-                       sprite_fetch_full(s, hpos, cycle, false, &data, &data321, &data322);
-                       //write_log (_T("%d:%d: %04X=%04X\n"), vpos, hpos, 0x140 + cycle * 2 + num * 8, data);
-                       if (cycle == 0) {
-                               if (start_before_dma && s->armed) {
-                                       maybe_decide_sprites(num, hpos);
-                               }
-                               SPRxPOS_1(data, num, hpos);
-                               s->dmacycle = 1;
-                       } else {
-                               // This is needed to disarm previous field's sprite.
-                               // It can be seen on OCS Agnus + ECS Denise combination where
-                               // this cycle is disabled due to weird DDFTSTR=$18 copper list
-                               // which causes corrupted sprite to "wrap around" the display.
-                               SPRxCTL_1(data, num, hpos);
-                               s->dmastate = 0;
-                               sprstartstop(s);
-                       }
-               }
-               if (vpos == sprite_vblank_endline) {
-                       // s->vstart == sprite_vblank_endline won't enable the sprite.
-                       s->dmastate = 0;
-               }
-#if SPRITE_DEBUG >= 256
-               if (vpos >= SPRITE_DEBUG_MINY && vpos <= SPRITE_DEBUG_MAXY && (SPRITE_DEBUG & (1 << num))) {
-                       write_log(_T("%d:%d:dma:P=%06X "), vpos, hpos, s->pt);
-               }
-#endif
-       }
-       if (s->dmastate && !posctl && dma) {
-               uae_u32 data321, data322;
-               sprite_fetch_full(s, hpos, cycle, true, &data, &data321, &data322);
-#if SPRITE_DEBUG >= 256
-               if (vpos >= SPRITE_DEBUG_MINY && vpos <= SPRITE_DEBUG_MAXY && (SPRITE_DEBUG & (1 << num))) {
-                       write_log(_T("%d:%d:dma:P=%06X "), vpos, hpos, s->pt);
-               }
-#endif
-               if (cycle == 0) {
+       if (dmastate) {
+               if (!slot) {
                        // if xpos is earlier than this cycle, decide it first.
                        if (start_before_dma) {
                                maybe_decide_sprites(num, hpos);
                        }
                        SPRxDATA_1(data, num, hpos);
-                       s->dmacycle = 1;
                } else {
                        // This is needed if xpos is between DATA and DATB fetches
                        // Test does not need to be accurate, only purpose is to
@@ -7469,7 +7353,7 @@ static void do_sprites_1(int num, int cycle, int hpos)
                switch (sprite_width)
                {
                case 64:
-                       if (cycle == 0) {
+                       if (!slot) {
                                s->data[1] = data321;
                                s->data[2] = data322 >> 16;
                                s->data[3] = data322;
@@ -7480,7 +7364,7 @@ static void do_sprites_1(int num, int cycle, int hpos)
                        }
                        break;
                case 32:
-                       if (cycle == 0) {
+                       if (!slot) {
                                s->data[1] = data321;
                                s->data[2] = data;
                                s->data[3] = data321;
@@ -7492,57 +7376,107 @@ static void do_sprites_1(int num, int cycle, int hpos)
                        break;
                }
 #endif
+       } else {
+               if (!slot) {
+                       if (start_before_dma && s->armed) {
+                               maybe_decide_sprites(num, hpos);
+                       }
+                       SPRxPOS_1(data, num, hpos);
+               } else {
+                       SPRxCTL_1(data, num, hpos);
+                       // This is needed to disarm previous field's sprite.
+                       // It can be seen on OCS Agnus + ECS Denise combination where
+                       // this cycle is disabled due to weird DDFTSTR=$18 copper list
+                       // which causes corrupted sprite to "wrap around" the display.
+                       s->dmastate = 0;
+                       sprstartstop(s);
+               }
        }
+
 }
 
-static void do_sprites(int endhpos)
+static void decide_sprite_fetch(int endhpos)
 {
-       int maxspr, minspr;
-
-       if (vpos < sprite_vblank_endline) {
-               last_decide_sprite_hpos = maxhpos;
-               return;
-       }
-
-       if (doflickerfix() && interlace_seen && (next_lineno & 1))
-               return;
-
-       minspr = last_decide_sprite_hpos;
-       maxspr = endhpos;
-
-       if (minspr >= maxspr || last_decide_sprite_hpos == endhpos)
-               return;
-
-       if (maxspr > SPR_FIRST_HPOS + MAX_SPRITES * 4)
-               maxspr = SPR_FIRST_HPOS + MAX_SPRITES * 4;
-       if (minspr < SPR_FIRST_HPOS)
-               minspr = SPR_FIRST_HPOS;
-
-       if (minspr >= maxspr) {
+       if ((vpos < sprite_vblank_endline) || (doflickerfix() && interlace_seen && (next_lineno & 1)) || (cant_this_last_line)) {
+               int diff = endhpos - last_decide_sprite_hpos;
+               if (diff > 0) {
+                       rga_pipeline_sprite += diff;
+                       rga_pipeline_sprite &= RGA_PIPELINE_MASK;
+               }
                last_decide_sprite_hpos = endhpos;
                return;
        }
 
-       for (int hpos = minspr; hpos < maxspr; hpos++) {
-               int cycle = -1;
-               int num = (hpos - SPR_FIRST_HPOS) / 4;
-               int slot = (hpos - SPR_FIRST_HPOS) & 3;
-               switch (slot)
-               {
-               case 0:
-                       cycle = 0;
-                       spr[num].dmacycle = 0;
-                       break;
-               case 2:
-                       cycle = 1;
-                       break;
-               }
-               if (cycle >= 0) {
-                       spr[num].ptxhpos = MAXHPOS;
-                       do_sprites_1(num, cycle, hpos);
+       int hpos = last_decide_sprite_hpos;
+       while (hpos < endhpos) {
+               if (hpos >= SPR_FIRST_HPOS - RGA_SPRITE_PIPELINE_DEPTH && hpos < SPR_FIRST_HPOS + MAX_SPRITES * 4) {
+                       int rpos = (rga_pipeline_sprite - RGA_SPRITE_PIPELINE_DEPTH) & RGA_PIPELINE_MASK;
+                       bool sprite_dma = rga_pipeline[rpos] >= 0x40 && rga_pipeline[rpos] <= 0x5f;
+                       if (sprite_dma) {
+                               uae_u16 dat = rga_pipeline[rpos];
+                               do_sprite_fetch(hpos, dat);
+                               rga_pipeline[rpos] = 0;
+                       }
+                       if (hpos < SPR_FIRST_HPOS + MAX_SPRITES * 4 - RGA_SPRITE_PIPELINE_DEPTH) {
+                               int num = (hpos - (SPR_FIRST_HPOS - RGA_SPRITE_PIPELINE_DEPTH)) / 4;
+                               int slot = (hpos - (SPR_FIRST_HPOS - RGA_SPRITE_PIPELINE_DEPTH)) & 3;
+                               if (slot == 0 || slot == 2) {
+                                       struct sprite *s = &spr[num];
+                                       if (slot == 0) {
+                                               if (!s->dmacycle && s->dmastate) {
+                                                       s->dmacycle = 1;
+                                               }
+                                               if (vpos == s->vstart) {
+                                                       s->dmastate = 1;
+                                                       s->dmacycle = 1;
+                                                       if (s->ptxvpos2 == vpos && hpos < s->ptxhpos2)
+                                                               return;
+                                                       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) {
+                                                       s->dmastate = 0;
+                                                       s->dmacycle = 1;
+                                               }
+                                       }
+                                       if (dmaen(DMA_SPRITE) && hpos < plfstrt_sprite && s->dmacycle) {
+                                               bool dodma = true;
+#ifdef AGA
+                                               if (s->dblscan && (fmode & 0x8000) && (vpos & 1) != (s->vstart & 1) && s->dmastate) {
+                                                       spr_arm(num, 1);
+                                                       dodma = false;
+                                               }
+#endif
+                                               if (dodma) {
+                                                       uae_u16 *sp = &rga_pipeline[(rga_pipeline_sprite + 0) & RGA_PIPELINE_MASK];
+                                                       uae_u16 dat = 0x40 | (s->dmastate ? 0x10 : 0x00) | (s->dmacycle == 1 ? 0 : 8) | num;
+                                                       if (*sp) {
+                                                               write_log(_T("sprite cycle already allocated! %02x\n"), *sp);
+                                                       }
+                                                       *sp = dat;
+                                               }
+                                       }
+                                       if (s->dmacycle) {
+                                               s->dmacycle++;
+                                               if (s->dmacycle > 2) {
+                                                       s->dmacycle = 0;
+                                                       if (s->dmastate) {
+                                                               s->dmacycle = 1;
+                                                       }
+                                               }
+                                       }
+                               }
+                       }
                }
+               hpos++;
+               rga_pipeline_sprite++;
+               rga_pipeline_sprite &= RGA_PIPELINE_MASK;
        }
-
        last_decide_sprite_hpos = endhpos;
 }
 
@@ -7550,12 +7484,11 @@ static void init_sprites(void)
 {
        for (int i = 0; i < MAX_SPRITES; i++) {
                struct sprite *s = &spr[i];
-               s->pos = 0;
-               s->ctl = 0;
+               memset(s, 0, sizeof(struct sprite));
        }
 }
 
-static void init_hardware_frame (void)
+static void init_hardware_frame(void)
 {
        int i;
 
@@ -7595,7 +7528,7 @@ static void init_hardware_frame (void)
        ddffirstword_total = max_diwlastword;
        ddflastword_total = 0;
        plflastline_total = 0;
-       plffirstline_total = current_maxvpos ();
+       plffirstline_total = current_maxvpos();
        first_bplcon0 = 0;
        autoscale_bordercolors = 0;
 
@@ -7605,7 +7538,7 @@ static void init_hardware_frame (void)
        }
 }
 
-void init_hardware_for_drawing_frame (void)
+void init_hardware_for_drawing_frame(void)
 {
        /* Avoid this code in the first frame after a customreset.  */
        if (prev_sprite_entries) {
@@ -7642,9 +7575,9 @@ void init_hardware_for_drawing_frame (void)
        next_sprite_forced = 1;
 }
 
-static int rpt_vsync (int adjust)
+static int rpt_vsync(int adjust)
 {
-       frame_time_t curr_time = read_processor_time ();
+       frame_time_t curr_time = read_processor_time();
        int v = curr_time - vsyncwaittime + adjust;
        if (v > syncbase || v < -syncbase) {
                vsyncmintime = vsyncmaxtime = vsyncwaittime = curr_time;
@@ -9378,6 +9311,7 @@ static void hsync_handler_post (bool onvsync)
        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();
 
        if (ecs_agnus) {
                if (vpos == sprhstrt) {
@@ -9741,15 +9675,16 @@ void custom_cpuchange(void)
        intena = intena | 0x8000;
 }
 
-void custom_reset (bool hardreset, bool keyboardreset)
+void custom_reset(bool hardreset, bool keyboardreset)
 {
-       if (hardreset)
+       if (hardreset) {
                board_prefs_changed(-1, -1);
+       }
 
-       target_reset ();
+       target_reset();
        devices_reset(hardreset);
-       write_log (_T("Reset at %08X. Chipset mask = %08X\n"), M68K_GETPC, currprefs.chipset_mask);
-       memory_map_dump ();
+       write_log(_T("Reset at %08X. Chipset mask = %08X\n"), M68K_GETPC, currprefs.chipset_mask);
+       memory_map_dump();
 
        lightpen_active = 0;
        lightpen_triggered = 0;
@@ -9764,8 +9699,8 @@ void custom_reset (bool hardreset, bool keyboardreset)
        memset(rga_pipeline, 0, sizeof(rga_pipeline));
        rga_pipeline_bpl_read = 0;
        rga_pipeline_bpl_write = 3;
-       rga_pipeline_copper_read = 2;
-       rga_pipeline_sprite_read = 3;
+       rga_pipeline_copper = 2;
+       rga_pipeline_sprite = 3;
 
        if (!savestate_state) {
                cia_hsync = 0;
@@ -9847,7 +9782,7 @@ void custom_reset (bool hardreset, bool keyboardreset)
        vpos_prev = maxvpos - 1;
        vpos_count = vpos_count_diff = 0;
 
-       inputdevice_reset ();
+       inputdevice_reset();
        timehack_alive = 0;
 
        curr_sprite_entries = 0;
@@ -9856,8 +9791,8 @@ void custom_reset (bool hardreset, bool keyboardreset)
        sprite_entries[1][0].first_pixel = MAX_SPR_PIXELS;
        sprite_entries[0][1].first_pixel = 0;
        sprite_entries[1][1].first_pixel = MAX_SPR_PIXELS;
-       memset (spixels, 0, 2 * MAX_SPR_PIXELS * sizeof *spixels);
-       memset (&spixstate, 0, sizeof spixstate);
+       memset(spixels, 0, 2 * MAX_SPR_PIXELS * sizeof *spixels);
+       memset(&spixstate, 0, sizeof spixstate);
        toscr_delay_sh[0] = 0;
        toscr_delay_sh[1] = 0;
 
@@ -9876,16 +9811,16 @@ void custom_reset (bool hardreset, bool keyboardreset)
        lof_togglecnt_nlace = lof_togglecnt_lace = 0;
        //nlace_cnt = NLACE_CNT_NEEDED;
 
-       audio_reset ();
-       if (!isrestore ()) {
+       audio_reset();
+       if (!isrestore()) {
                /* must be called after audio_reset */
                adkcon = 0;
-               serial_uartbreak (0);
-               audio_update_adkmasks ();
+               serial_uartbreak(0);
+               audio_update_adkmasks();
        }
 
-       init_hardware_frame ();
-       drawing_init ();
+       init_hardware_frame();
+       drawing_init();
 
        reset_decisions_scanline_start();
        reset_decisions_hsync_start();
@@ -9899,7 +9834,7 @@ void custom_reset (bool hardreset, bool keyboardreset)
                uae_u16 v;
                uae_u32 vv;
 
-               audio_update_adkmasks ();
+               audio_update_adkmasks();
                INTENA(0);
                INTREQ(0);
                COPJMP(1, 1);
@@ -9969,8 +9904,9 @@ void custom_reset (bool hardreset, bool keyboardreset)
        enforcer_disable();
 #endif
 
-       if (hardreset)
+       if (hardreset) {
                rtc_hardreset();
+       }
 
        // must be last
 #ifdef AUTOCONFIG
@@ -10738,7 +10674,7 @@ uae_u8 *restore_custom(uae_u8 *src)
 #define SW save_u16
 #define SL save_u32
 
-uae_u8 *save_custom (int *len, uae_u8 *dstptr, int full)
+uae_u8 *save_custom(int *len, uae_u8 *dstptr, int full)
 {
        uae_u8 *dstbak, *dst;
        int i, dummy;
@@ -10746,104 +10682,104 @@ uae_u8 *save_custom (int *len, uae_u8 *dstptr, int full)
        uae_u16 dsklen, dsksync, dskbytr;
        uae_u16 v;
 
-       DISK_save_custom (&dskpt, &dsklen, &dsksync, &dskbytr);
+       DISK_save_custom(&dskpt, &dsklen, &dsksync, &dskbytr);
 
        if (dstptr)
                dstbak = dst = dstptr;
        else
                dstbak = dst = xmalloc (uae_u8, 8 + 256 * 2);
 
-       SL (currprefs.chipset_mask);
-       SW (0);                                 /* 000 BLTDDAT */
-       SW (dmacon);                    /* 002 DMACONR */
-       SW (VPOSR ());                  /* 004 VPOSR */
-       SW (VHPOSR ());                 /* 006 VHPOSR */
-       SW (0);                                 /* 008 DSKDATR */
-       SW (JOYGET (0));                /* 00A JOY0DAT */
-       SW (JOYGET (1));                /* 00C JOY1DAT */
-       SW (clxdat | 0x8000);   /* 00E CLXDAT */
-       SW (ADKCONR ());                /* 010 ADKCONR */
-       SW (POT0DAT ());                /* 012 POT0DAT */
-       SW (POT1DAT ());                /* 014 POT1DAT */
-       SW (0);                                 /* 016 POTINP * */
-       SW (0);                                 /* 018 SERDATR * */
-       SW (dskbytr);                   /* 01A DSKBYTR */
-       SW (INTENAR ());                /* 01C INTENAR */
-       SW (INTREQR ());                /* 01E INTREQR */
-       SL (dskpt);                             /* 020-023 DSKPT */
-       SW (dsklen);                    /* 024 DSKLEN */
-       SW (0);                                 /* 026 DSKDAT */
-       SW (refptr);                    /* 028 REFPTR */
-       SW ((lof_store ? 0x8001 : 0) | (lol ? 0x0080 : 0));/* 02A VPOSW */
-       SW (0);                                 /* 02C VHPOSW */
-       SW (copcon);                    /* 02E COPCON */
-       SW (serdat);                    /* 030 SERDAT * */
-       SW (serper);                    /* 032 SERPER * */
-       SW (potgo_value);               /* 034 POTGO */
-       SW (0);                                 /* 036 JOYTEST * */
-       SW (0);                                 /* 038 STREQU */
-       SW (0);                                 /* 03A STRVBL */
-       SW (0);                                 /* 03C STRHOR */
-       SW (0);                                 /* 03E STRLONG */
-       SW (bltcon0);                   /* 040 BLTCON0 */
-       SW (bltcon1);                   /* 042 BLTCON1 */
-       SW (blt_info.bltafwm);  /* 044 BLTAFWM */
-       SW (blt_info.bltalwm);  /* 046 BLTALWM */
-       SL (bltcpt);                    /* 048-04B BLTCPT */
-       SL (bltbpt);                    /* 04C-04F BLTCPT */
-       SL (bltapt);                    /* 050-053 BLTCPT */
-       SL (bltdpt);                    /* 054-057 BLTCPT */
+       SL(currprefs.chipset_mask);
+       SW(0);                                  /* 000 BLTDDAT */
+       SW(dmacon);                             /* 002 DMACONR */
+       SW(VPOSR());                    /* 004 VPOSR */
+       SW(VHPOSR());                   /* 006 VHPOSR */
+       SW(0);                                  /* 008 DSKDATR */
+       SW(JOYGET(0));                  /* 00A JOY0DAT */
+       SW(JOYGET(1));                  /* 00C JOY1DAT */
+       SW(clxdat | 0x8000);    /* 00E CLXDAT */
+       SW(ADKCONR());                  /* 010 ADKCONR */
+       SW(POT0DAT());                  /* 012 POT0DAT */
+       SW(POT1DAT());                  /* 014 POT1DAT */
+       SW(0);                                  /* 016 POTINP * */
+       SW(0);                                  /* 018 SERDATR * */
+       SW(dskbytr);                    /* 01A DSKBYTR */
+       SW(INTENAR());                  /* 01C INTENAR */
+       SW(INTREQR());                  /* 01E INTREQR */
+       SL(dskpt);                              /* 020-023 DSKPT */
+       SW(dsklen);                             /* 024 DSKLEN */
+       SW(0);                                  /* 026 DSKDAT */
+       SW(refptr);                             /* 028 REFPTR */
+       SW((lof_store ? 0x8001 : 0) | (lol ? 0x0080 : 0));/* 02A VPOSW */
+       SW(0);                                  /* 02C VHPOSW */
+       SW(copcon);                             /* 02E COPCON */
+       SW(serdat);                             /* 030 SERDAT * */
+       SW(serper);                             /* 032 SERPER * */
+       SW(potgo_value);                /* 034 POTGO */
+       SW(0);                                  /* 036 JOYTEST * */
+       SW(0);                                  /* 038 STREQU */
+       SW(0);                                  /* 03A STRVBL */
+       SW(0);                                  /* 03C STRHOR */
+       SW(0);                                  /* 03E STRLONG */
+       SW(bltcon0);                    /* 040 BLTCON0 */
+       SW(bltcon1);                    /* 042 BLTCON1 */
+       SW(blt_info.bltafwm);   /* 044 BLTAFWM */
+       SW(blt_info.bltalwm);   /* 046 BLTALWM */
+       SL(bltcpt);                             /* 048-04B BLTCPT */
+       SL(bltbpt);                             /* 04C-04F BLTCPT */
+       SL(bltapt);                             /* 050-053 BLTCPT */
+       SL(bltdpt);                             /* 054-057 BLTCPT */
        if (blt_info.vblitsize > 1024 || blt_info.hblitsize > 64) {
                v = 0;
        } else {
                v = (blt_info.vblitsize << 6) | (blt_info.hblitsize & 63);
        }
        SW (v);                                 /* 058 BLTSIZE */
-       SW (bltcon0 & 0xff);    /* 05A BLTCON0L (use BLTCON0 instead) */
-       SW (blt_info.vblitsize);/* 05C BLTSIZV */
-       SW (blt_info.hblitsize);/* 05E BLTSIZH */
-       SW (blt_info.bltcmod);  /* 060 BLTCMOD */
-       SW (blt_info.bltbmod);  /* 062 BLTBMOD */
-       SW (blt_info.bltamod);  /* 064 BLTAMOD */
-       SW (blt_info.bltdmod);  /* 066 BLTDMOD */
-       SW (0);                                 /* 068 ? */
-       SW (0);                                 /* 06A ? */
-       SW (0);                                 /* 06C ? */
-       SW (0);                                 /* 06E ? */
-       SW (blt_info.bltcdat);  /* 070 BLTCDAT */
-       SW (blt_info.bltbdat);  /* 072 BLTBDAT */
-       SW (blt_info.bltadat);  /* 074 BLTADAT */
-       SW (0);                                 /* 076 ? */
-       SW (0);                                 /* 078 ? */
-       SW (0);                                 /* 07A ? */
-       SW (DENISEID (&dummy)); /* 07C DENISEID/LISAID */
-       SW (dsksync);                   /* 07E DSKSYNC */
-       SL (cop1lc);                    /* 080-083 COP1LC */
-       SL (cop2lc);                    /* 084-087 COP2LC */
-       SW (0);                                 /* 088 ? */
-       SW (0);                                 /* 08A ? */
-       SW (0);                                 /* 08C ? */
-       SW (diwstrt);                   /* 08E DIWSTRT */
-       SW (diwstop);                   /* 090 DIWSTOP */
-       SW (ddfstrt);                   /* 092 DDFSTRT */
-       SW (ddfstop);                   /* 094 DDFSTOP */
-       SW (dmacon);                    /* 096 DMACON */
-       SW (clxcon);                    /* 098 CLXCON */
-       SW (intena);                    /* 09A INTENA */
-       SW (intreq);                    /* 09C INTREQ */
-       SW (adkcon);                    /* 09E ADKCON */
+       SW(bltcon0 & 0xff);             /* 05A BLTCON0L (use BLTCON0 instead) */
+       SW(blt_info.vblitsize); /* 05C BLTSIZV */
+       SW(blt_info.hblitsize); /* 05E BLTSIZH */
+       SW(blt_info.bltcmod);   /* 060 BLTCMOD */
+       SW(blt_info.bltbmod);   /* 062 BLTBMOD */
+       SW(blt_info.bltamod);   /* 064 BLTAMOD */
+       SW(blt_info.bltdmod);   /* 066 BLTDMOD */
+       SW(0);                                  /* 068 ? */
+       SW(0);                                  /* 06A ? */
+       SW(0);                                  /* 06C ? */
+       SW(0);                                  /* 06E ? */
+       SW(blt_info.bltcdat);   /* 070 BLTCDAT */
+       SW(blt_info.bltbdat);   /* 072 BLTBDAT */
+       SW(blt_info.bltadat);   /* 074 BLTADAT */
+       SW(0);                                  /* 076 ? */
+       SW(0);                                  /* 078 ? */
+       SW(0);                                  /* 07A ? */
+       SW(DENISEID(&dummy));   /* 07C DENISEID/LISAID */
+       SW(dsksync);                    /* 07E DSKSYNC */
+       SL(cop1lc);                             /* 080-083 COP1LC */
+       SL(cop2lc);                             /* 084-087 COP2LC */
+       SW(0);                                  /* 088 ? */
+       SW(0);                                  /* 08A ? */
+       SW(0);                                  /* 08C ? */
+       SW(diwstrt);                    /* 08E DIWSTRT */
+       SW(diwstop);                    /* 090 DIWSTOP */
+       SW(ddfstrt);                    /* 092 DDFSTRT */
+       SW(ddfstop);                    /* 094 DDFSTOP */
+       SW(dmacon);                             /* 096 DMACON */
+       SW(clxcon);                             /* 098 CLXCON */
+       SW(intena);                             /* 09A INTENA */
+       SW(intreq);                             /* 09C INTREQ */
+       SW(adkcon);                             /* 09E ADKCON */
        for (i = 0; full && i < 32; i++)
-               SW (0);
+               SW(0);
        for (i = 0; i < 8; i++)
-               SL (bplpt[i]);          /* 0E0-0FE BPLxPT */
-       SW (bplcon0);                   /* 100 BPLCON0 */
-       SW (bplcon1);                   /* 102 BPLCON1 */
-       SW (bplcon2);                   /* 104 BPLCON2 */
-       SW (bplcon3);                   /* 106 BPLCON3 */
-       SW (bpl1mod);                   /* 108 BPL1MOD */
-       SW (bpl2mod);                   /* 10A BPL2MOD */
-       SW (bplcon4);                   /* 10C BPLCON4 */
-       SW (clxcon2);                   /* 10E CLXCON2 */
+               SL(bplpt[i]);           /* 0E0-0FE BPLxPT */
+       SW(bplcon0);                    /* 100 BPLCON0 */
+       SW(bplcon1);                    /* 102 BPLCON1 */
+       SW(bplcon2);                    /* 104 BPLCON2 */
+       SW(bplcon3);                    /* 106 BPLCON3 */
+       SW(bpl1mod);                    /* 108 BPL1MOD */
+       SW(bpl2mod);                    /* 10A BPL2MOD */
+       SW(bplcon4);                    /* 10C BPLCON4 */
+       SW(clxcon2);                    /* 10E CLXCON2 */
        for (i = 0;i < 8; i++)
                SW (fetched[i]);        /* 110 BPLxDAT */
        if (full) {
@@ -10852,10 +10788,10 @@ uae_u8 *save_custom (int *len, uae_u8 *dstptr, int full)
                }
                for (i = 0; i < 8; i++) {
                        struct sprite *s = &spr[i];
-                       SW (s->pos);    /* 1x0 SPRxPOS */
-                       SW (s->ctl);    /* 1x2 SPRxPOS */
-                       SW (s->data[0]);        /* 1x4 SPRxDATA */
-                       SW (s->datb[0]);        /* 1x6 SPRxDATB */
+                       SW(s->pos);     /* 1x0 SPRxPOS */
+                       SW(s->ctl);     /* 1x2 SPRxPOS */
+                       SW(s->data[0]); /* 1x4 SPRxDATA */
+                       SW(s->datb[0]); /* 1x6 SPRxDATB */
                }
        }
        for (i = 0; i < 32; i++) {
@@ -10866,45 +10802,45 @@ uae_u8 *save_custom (int *len, uae_u8 *dstptr, int full)
                        v2 = (v >> 4) & 15;
                        v2 |= ((v >> 12) & 15) << 4;
                        v2 |= ((v >> 20) & 15) << 8;
-                       SW (v2);
+                       SW(v2);
                } else {
                        uae_u16 v = current_colors.color_regs_ecs[i];
                        if (color_regs_genlock[i])
                                v |= 0x8000;
-                       SW (v); /* 180-1BE COLORxx */
-               }
-       }
-       SW (htotal);            /* 1C0 HTOTAL */
-       SW (hsstop);            /* 1C2 HSTOP*/
-       SW (hbstrt);            /* 1C4 HBSTRT */
-       SW (hbstop);            /* 1C6 HBSTOP */
-       SW (vtotal);            /* 1C8 VTOTAL */
-       SW (vsstop);            /* 1CA VSSTOP */
-       SW (vbstrt);            /* 1CC VBSTRT */
-       SW (vbstop);            /* 1CE VBSTOP */
-       SW (sprhstrt);          /* 1D0 SPRHSTRT */
-       SW (sprhstop);          /* 1D2 SPRHSTOP */
-       SW (bplhstrt);          /* 1D4 BPLHSTRT */
-       SW (bplhstop);          /* 1D6 BPLHSTOP */
-       SW (hhpos);                     /* 1D8 HHPOSW */
-       SW (0);                         /* 1DA */
-       SW (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 (0);                         /* 1E6 */
-       SW (0);                         /* 1E8 */
-       SW (0);                         /* 1EA */
-       SW (0);                         /* 1EC */
-       SW (0);                         /* 1EE */
-       SW (0);                         /* 1F0 */
-       SW (0);                         /* 1F2 */
-       SW (0);                         /* 1F4 */
-       SW (0);                         /* 1F6 */
-       SW (0);                         /* 1F8 */
-       SW (0x8000 | (currprefs.ntscmode ? 1 : 0));                     /* 1FA (re-used for NTSC) */
-       SW (fmode);                     /* 1FC FMODE */
+                       SW(v); /* 180-1BE COLORxx */
+               }
+       }
+       SW(htotal);                     /* 1C0 HTOTAL */
+       SW(hsstop);                     /* 1C2 HSTOP*/
+       SW(hbstrt);                     /* 1C4 HBSTRT */
+       SW(hbstop);                     /* 1C6 HBSTOP */
+       SW(vtotal);                     /* 1C8 VTOTAL */
+       SW(vsstop);                     /* 1CA VSSTOP */
+       SW(vbstrt);                     /* 1CC VBSTRT */
+       SW(vbstop);                     /* 1CE VBSTOP */
+       SW(sprhstrt);           /* 1D0 SPRHSTRT */
+       SW(sprhstop);           /* 1D2 SPRHSTOP */
+       SW(bplhstrt);           /* 1D4 BPLHSTRT */
+       SW(bplhstop);           /* 1D6 BPLHSTOP */
+       SW(hhpos);                      /* 1D8 HHPOSW */
+       SW(0);                          /* 1DA */
+       SW(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(0);                          /* 1E6 */
+       SW(0);                          /* 1E8 */
+       SW(0);                          /* 1EA */
+       SW(0);                          /* 1EC */
+       SW(0);                          /* 1EE */
+       SW(0);                          /* 1F0 */
+       SW(0);                          /* 1F2 */
+       SW(0);                          /* 1F4 */
+       SW(0);                          /* 1F6 */
+       SW(0);                          /* 1F8 */
+       SW(0x8000 | (currprefs.ntscmode ? 1 : 0));                      /* 1FA (re-used for NTSC) */
+       SW(fmode);                      /* 1FC FMODE */
        SW (last_custom_value1);        /* 1FE */
 
        *len = dst - dstbak;