]> git.unchartedbackwaters.co.uk Git - francis/winuae.git/commitdiff
Hardware emulated RTG card horizontal panning improvements
authorToni Wilen <twilen@winuae.net>
Fri, 29 Dec 2023 15:48:14 +0000 (17:48 +0200)
committerToni Wilen <twilen@winuae.net>
Fri, 29 Dec 2023 15:48:14 +0000 (17:48 +0200)
pcem/vid_cl5429.cpp
pcem/vid_ncr.cpp
pcem/vid_svga.cpp
pcem/vid_svga.h
pcem/vid_svga_render.cpp

index acc145d594ed99f1a8c665f8eb9f42938071ffec..92ea4819e00fb95ab8b9ee01fcc766c10580e35d 100644 (file)
@@ -517,7 +517,7 @@ void gd5429_out(uint16_t addr, uint8_t val, void *p)
                 break;
                         
                 case 0x3c4:
-                svga->seqaddr = val;
+                svga->seqaddr = val & 0x1f;
                 break;
                 case 0x3c5:
                 if (svga->seqaddr > 5)
@@ -525,14 +525,12 @@ void gd5429_out(uint16_t addr, uint8_t val, void *p)
                         svga->seqregs[svga->seqaddr & 0x1f] = val;
                         switch (svga->seqaddr & 0x1f)
                         {
-                                case 0x10: case 0x30: case 0x50: case 0x70:
-                                case 0x90: case 0xb0: case 0xd0: case 0xf0:
+                                case 0x10:
                                 svga->hwcursor.x = (val << 3) | ((svga->seqaddr >> 5) & 7);
                                 gd5429->sr10_read = svga->seqaddr & 0xe0;
 //                                pclog("svga->hwcursor.x = %i\n", svga->hwcursor.x);
                                 break;
-                                case 0x11: case 0x31: case 0x51: case 0x71:
-                                case 0x91: case 0xb1: case 0xd1: case 0xf1:
+                                case 0x11:
                                 svga->hwcursor.y = (val << 3) | ((svga->seqaddr >> 5) & 7);
                                 gd5429->sr11_read = svga->seqaddr & 0xe0;
 //                                pclog("svga->hwcursor.y = %i\n", svga->hwcursor.y);
@@ -561,6 +559,7 @@ void gd5429_out(uint16_t addr, uint8_t val, void *p)
                                     }
                                     svga->packed_chain4 = svga->seqregs[7] & 1;
                                     svga_recalctimings(svga);
+                                    break;
                                 case 0x0f:
                                 case 0x17:
                                 //UAE
@@ -790,7 +789,7 @@ void gd5429_out(uint16_t addr, uint8_t val, void *p)
                         old = val;
                 }
 
-                if (old != val)
+                if (1)
                 {
                         // overlay registers
                         switch (svga->crtcreg)
@@ -879,7 +878,7 @@ void gd5429_out(uint16_t addr, uint8_t val, void *p)
                                 break;
                         }
 
-                        if (svga->crtcreg < 0xe || svga->crtcreg > 0x10)
+                        if ((svga->crtcreg < 0xe || svga->crtcreg > 0x10) && old != val)
                         {
                                 svga->fullchange = changeframecount;
                                 svga_recalctimings(svga);
@@ -1174,7 +1173,8 @@ void gd5429_recalctimings(svga_t *svga)
         if (svga->seqregs[7] & 0x01) {
             svga->render = svga_render_8bpp_highres;
         }
-        
+
+
         svga->ma_latch |= ((svga->crtc[0x1b] & 0x01) << 16) | (((svga->crtc[0x1b] >> 2) & 3) << 17);
         if (gd5429->type >= CL_TYPE_GD5436) {
             svga->ma_latch |= (((svga->crtc[0x1d] >> 7) & 1) << 19);
@@ -1249,6 +1249,44 @@ void gd5429_recalctimings(svga_t *svga)
         svga->vram_display_mask = (svga->crtc[0x1b] & 2) ? gd5429->vram_mask : 0x3ffff;
 }
 
+static void gd5429_adjust_panning(svga_t *svga)
+{
+    gd5429_t *gd5429 = (gd5429_t *)svga->p;
+    int ar11 = svga->attrregs[0x13] & 7;
+    int src = 0, dst = 8;
+    switch (svga->bpp)
+    {
+        case 8:
+            if (svga->horizontal_linedbl) {
+                dst = 8 - ((ar11 & 3) << 1);
+            } else {
+                dst = 8 - ar11;
+            }
+            break;
+        case 15:
+        case 16:
+            dst = 8 - ((ar11 & 2) >> 1);
+            break;
+        case 24:
+            if (gd5429->type >= CL_TYPE_GD5446) {
+                dst = 8 - ((ar11 & 3) << 1);
+                if (ar11 >= 4) {
+                    src += 3;
+                }
+            } else {
+                src = ar11;
+            }
+            break;
+        case 32:
+            dst = 8 - (ar11 & 1);
+            break;
+    }
+
+    dst += 24;
+    svga->scrollcache_dst = dst;
+    svga->scrollcache_src = src;
+}
+
 void gd5429_hwcursor_draw(svga_t *svga, int displine)
 {
         gd5429_t *gd5429 = (gd5429_t *)svga->p;
@@ -2735,6 +2773,7 @@ static void *cl_init(int type, char *fn, int pci_card, uint32_t force_vram_size)
                    gd5429_overlay_draw);
 
         gd5429->svga.vblank_start = gd5429_vblank_start;
+        gd5429->svga.adjust_panning = gd5429_adjust_panning;
 
         mem_mapping_set_handlerx(&gd5429->svga.mapping, gd5429_read, gd5429_readw, gd5429_readl, gd5429_write, gd5429_writew, gd5429_writel);
         mem_mapping_set_px(&gd5429->svga.mapping, gd5429);
index 5fcf8d053b73b31c08448ce484dc6ef84c702872..77cd00e92bd3e48b03e8fdfc0d37571eed2c1068 100644 (file)
@@ -1050,6 +1050,29 @@ void ncr_updatemapping(ncr_t *ncr)
         }
 }
 
+static void ncr_adjust_panning(svga_t *svga)
+{
+    int ar11 = svga->attrregs[0x13] & 7;
+    int src = 0, dst = 8;
+
+    switch (svga->bpp)
+    {
+        case 16:
+            dst = (ar11 & 4) ? 7 : 8;
+            break;
+        case 24:
+            src = ar11 >> 1;
+            break;
+        default:
+            return;
+    }
+
+    dst += 24;
+    svga->scrollcache_dst = dst;
+    svga->scrollcache_src = src;
+
+}
+
 static inline uint32_t dword_remap(uint32_t in_addr)
 {
     return in_addr;
@@ -1119,6 +1142,7 @@ static void *ncr_init(char *bios_fn, int chip)
         }
                 
         svga->vblank_start = ncr_vblank_start;
+        svga->adjust_panning = ncr_adjust_panning;
 
         ncr_io_set(ncr);
 
index 00da7515b9149e8825a599164c39521a628521e5..7580986dd48f1d130a7a8c4d6d5ffa86af65cc3c 100644 (file)
@@ -694,8 +694,10 @@ int svga_poll(void *p)
 //                               pclog("VC split\n");
                                 svga->ma = svga->maback = 0;
                                 svga->sc = 0;
-                                if (svga->attrregs[0x10] & 0x20)
-                                        svga->scrollcache = 0;
+                                if (svga->attrregs[0x10] & 0x20) {
+                                        svga->scrollcache_dst = 0;
+                                        svga->scrollcache_src = 0;
+                                }
                         }
                 }
                 if (svga->vc == svga->dispend)
@@ -812,7 +814,7 @@ int svga_poll(void *p)
                         svga->sc = svga->crtc[8] & 0x1f;
                         svga->dispon = 1;
                         svga->displine = (svga->interlace && svga->oddeven) ? 1 : 0;
-                        svga->scrollcache = svga->attrregs[0x13] & 7;
+                        int scrollcache = svga->attrregs[0x13] & 7;
                         svga->linecountff = 0;
                         
                         svga->hwcursor_on = 0;
@@ -820,9 +822,35 @@ int svga_poll(void *p)
 
                         svga->overlay_on = 0;
                         svga->overlay_latch = svga->overlay;
+
+                        if (svga->render == svga_render_4bpp_highres ||
+                            svga->render == svga_render_2bpp_highres) {
+                            svga->scrollcache_dst = (8 - scrollcache) + 24;
+                        } else if (svga->render == svga_render_4bpp_lowres ||
+                            svga->render == svga_render_2bpp_lowres) {
+                            svga->scrollcache_dst = ((8 - scrollcache) << 1) + 16;
+                        } else if (svga->render == svga_render_16bpp_highres ||
+                            svga->render == svga_render_15bpp_highres ||
+                            svga->render == svga_render_8bpp_highres ||
+                            svga->render == svga_render_32bpp_highres ||
+                            svga->render == svga_render_32bpp_highres_swaprb ||
+                            svga->render == svga_render_ABGR8888_highres ||
+                            svga->render == svga_render_RGBA8888_highres) {
+                            svga->scrollcache_dst = (8 - ((scrollcache & 6) >> 1)) + 24;
+                        } else {
+                            svga->scrollcache_dst = (8 - (scrollcache & 6)) + 24;
+                        }
+                        svga->scrollcache_src = 0;
+
+                        if (svga->adjust_panning) {
+                            svga->adjust_panning(svga);
+                        }
+
 //                        pclog("Latch HWcursor addr %08X\n", svga_hwcursor_latch.addr);
                         
 //                        pclog("ADDR %08X\n",hwcursor_addr);
+
+                          //pclog("%08x %d %d %d\n", svga->ma_latch, svga->attrregs[0x13] & 7, svga->scrollcache_src, svga->scrollcache_dst);
                 }
                 if (svga->sc == (svga->crtc[10] & 31)) 
                         svga->con = 1;
index df5c0f88c52b41acdd5ce6f12a409d512322a13e..0bcd429a103ac45151b7cd0d36c3e140b1776541 100644 (file)
@@ -76,7 +76,7 @@ typedef struct svga_t
         int sc;
         int linepos, vslines, linecountff, oddeven;
         int con, cursoron, blink;
-        int scrollcache;
+        int scrollcache_src, scrollcache_dst;
         int char_width;
         
         int firstline, lastline;
@@ -126,6 +126,8 @@ typedef struct svga_t
         
         void (*vblank_start)(struct svga_t *svga);
         
+        void (*adjust_panning)(struct svga_t *svga);
+
         /*Called when VC=R18 and friends. If this returns zero then MA resetting
           is skipped. Matrox Mystique in Power mode reuses this counter for
           vertical line interrupt*/
index 19578df01e7b291827083bc04e9a97a8850c1298..cbf1eb94d08a64fda85e5748ed734612ed68df37 100644 (file)
@@ -48,7 +48,7 @@ void svga_render_text_40(svga_t *svga)
         
         if (svga->fullchange)
         {
-                int offset = ((8 - svga->scrollcache) << 1) + 16;
+                int offset = svga->scrollcache_dst;
                 uint32_t *p = &((uint32_t *)buffer32->line[svga->displine])[offset];
                 int x, xx;
                 int drawcursor;
@@ -115,7 +115,7 @@ void svga_render_text_80(svga_t *svga)
         
         if (svga->fullchange)
         {
-                int offset = (8 - svga->scrollcache) + 24;
+                int offset = svga->scrollcache_dst;
                 uint32_t *p = &((uint32_t *)buffer32->line[svga->displine])[offset];
                 int x, xx;
                 int drawcursor;
@@ -182,7 +182,7 @@ void svga_render_text_80_ksc5601(svga_t *svga)
         
         if (svga->fullchange)
         {
-                int offset = (8 - svga->scrollcache) + 24;
+                int offset = svga->scrollcache_dst;
                 uint32_t *p = &((uint32_t *)buffer32->line[svga->displine])[offset];
                 int x, xx;
                 int drawcursor;
@@ -318,7 +318,7 @@ void svga_render_2bpp_lowres(svga_t *svga)
         if (svga->changedvram[changed_addr >> 12] || svga->changedvram[(changed_addr >> 12) + 1] || svga->fullchange)
         {
                 int x;
-                int offset = ((8 - svga->scrollcache) << 1) + 16;
+                int offset = svga->scrollcache_dst;
                 uint32_t *p = &((uint32_t *)buffer32->line[svga->displine])[offset];
                 
                 if (svga->firstline_draw == 4000) 
@@ -356,7 +356,7 @@ void svga_render_2bpp_highres(svga_t *svga)
         if (svga->changedvram[changed_addr >> 12] || svga->changedvram[(changed_addr >> 12) + 1] || svga->fullchange)
         {
                 int x;
-                int offset = (8 - svga->scrollcache) + 24;
+                int offset = svga->scrollcache_dst;
                 uint32_t *p = &((uint32_t *)buffer32->line[svga->displine])[offset];
                 
                 if (svga->firstline_draw == 4000) 
@@ -392,7 +392,7 @@ void svga_render_4bpp_lowres(svga_t *svga)
         if (svga->changedvram[changed_addr >> 12] || svga->changedvram[(changed_addr >> 12) + 1] || svga->fullchange)
         {
                 int x;
-                int offset = ((8 - svga->scrollcache) << 1) + 16;
+                int offset = svga->scrollcache_dst;
                 uint32_t *p = &((uint32_t *)buffer32->line[svga->displine])[offset];
                 
                 if (svga->firstline_draw == 4000) 
@@ -434,7 +434,7 @@ void svga_render_4bpp_highres(svga_t *svga)
         if (svga->changedvram[changed_addr >> 12] || svga->changedvram[(changed_addr >> 12) + 1] || svga->fullchange)
         {
                 int x;
-                int offset = (8 - svga->scrollcache) + 24;
+                int offset = svga->scrollcache_dst;
                 uint32_t *p = &((uint32_t *)buffer32->line[svga->displine])[offset];
         
                 if (svga->firstline_draw == 4000) 
@@ -474,7 +474,7 @@ void svga_render_8bpp_lowres(svga_t *svga)
         if (svga->changedvram[changed_addr >> 12] || svga->changedvram[(changed_addr >> 12) + 1] || svga->fullchange)
         {
                 int x;
-                int offset = (8 - (svga->scrollcache & 6)) + 24;
+                int offset = svga->scrollcache_dst;
                 uint32_t *p = &((uint32_t *)buffer32->line[svga->displine])[offset];
                 
                 if (svga->firstline_draw == 4000) 
@@ -523,7 +523,7 @@ void svga_render_8bpp_highres(svga_t *svga)
         if (svga->changedvram[changed_addr >> 12] || svga->changedvram[(changed_addr >> 12) + 1] || svga->fullchange)
         {
                 int x;
-                int offset = (8 - ((svga->scrollcache & 6) >> 1)) + 24;
+                int offset = svga->scrollcache_dst;
                 uint32_t *p = &((uint32_t *)buffer32->line[svga->displine])[offset];
 
                 if (svga->firstline_draw == 4000)
@@ -576,7 +576,7 @@ void svga_render_15bpp_lowres(svga_t *svga)
         if (svga->changedvram[changed_addr >> 12] || svga->changedvram[(changed_addr >> 12) + 1] || svga->fullchange)
         {
                 int x;
-                int offset = (8 - (svga->scrollcache & 6)) + 24;
+                int offset = svga->scrollcache_dst;
                 uint32_t *p = &((uint32_t *)buffer32->line[svga->displine])[offset];
                 
                 if (svga->firstline_draw == 4000) 
@@ -623,7 +623,7 @@ void svga_render_15bpp_highres(svga_t *svga)
         if (svga->changedvram[changed_addr >> 12] || svga->changedvram[(changed_addr >> 12) + 1] || svga->fullchange)
         {
                 int x;
-                int offset = (8 - ((svga->scrollcache & 6) >> 1)) + 24;
+                int offset = svga->scrollcache_dst;
                 uint32_t *p = &((uint32_t *)buffer32->line[svga->displine])[offset];
 
                 if (svga->firstline_draw == 4000) 
@@ -677,7 +677,7 @@ void svga_render_16bpp_lowres(svga_t *svga)
         if (svga->changedvram[changed_addr >> 12] || svga->changedvram[(changed_addr >> 12) + 1] || svga->fullchange)
         {
                 int x;
-                int offset = (8 - (svga->scrollcache & 6)) + 24;
+                int offset = svga->scrollcache_dst;
                 uint32_t *p = &((uint32_t *)buffer32->line[svga->displine])[offset];
                 
                 if (svga->firstline_draw == 4000) 
@@ -724,7 +724,7 @@ void svga_render_16bpp_highres(svga_t *svga)
         if (svga->changedvram[changed_addr >> 12] || svga->changedvram[(changed_addr >> 12) + 1] || svga->fullchange)
         {
                 int x;
-                int offset = (8 - ((svga->scrollcache & 6) >> 1)) + 24;
+                int offset = svga->scrollcache_dst;
                 uint32_t *p = &((uint32_t *)buffer32->line[svga->displine])[offset];
 
                 if (svga->firstline_draw == 4000) 
@@ -778,7 +778,8 @@ void svga_render_24bpp_lowres(svga_t *svga)
         if (svga->changedvram[changed_addr >> 12] || svga->changedvram[(changed_addr >> 12) + 1] || svga->fullchange)
         {
                 int x;
-                int offset = (8 - (svga->scrollcache & 6)) + 24;
+                int offset = svga->scrollcache_dst;
+                int shift = svga->scrollcache_src;
                 uint32_t *p = &((uint32_t *)buffer32->line[svga->displine])[offset];
 
                 if (svga->firstline_draw == 4000) 
@@ -791,7 +792,7 @@ void svga_render_24bpp_lowres(svga_t *svga)
                         
                             for (x = 0; x <= svga->hdisp << svga->horizontal_linedbl; x++)
                             {
-                                uint32_t fg = svga->vram[svga->ma + 2] | (svga->vram[svga->ma + 1] << 8) | (svga->vram[svga->ma + 0] << 16);
+                                uint32_t fg = svga->vram[svga->ma + shift + 2] | (svga->vram[svga->ma + shift + 1] << 8) | (svga->vram[svga->ma + shift + 0] << 16);
                                 svga->ma += 3;
                                 svga->ma &= svga->vram_display_mask;
                                 p[0] = p[1] = fg;
@@ -804,9 +805,9 @@ void svga_render_24bpp_lowres(svga_t *svga)
                         
                             for (x = 0; x <= svga->hdisp << svga->horizontal_linedbl; x++)
                             {
-                                    uint32_t dat0 = *(uint32_t *)(&svga->vram[svga->ma & svga->vram_display_mask]);
-                                    uint32_t dat1 = *(uint32_t *)(&svga->vram[(svga->ma + 4) & svga->vram_display_mask]);
-                                    uint32_t dat2 = *(uint32_t *)(&svga->vram[(svga->ma + 8) & svga->vram_display_mask]);
+                                    uint32_t dat0 = *(uint32_t *)(&svga->vram[(svga->ma + shift) & svga->vram_display_mask]);
+                                    uint32_t dat1 = *(uint32_t *)(&svga->vram[(svga->ma + shift + 4) & svga->vram_display_mask]);
+                                    uint32_t dat2 = *(uint32_t *)(&svga->vram[(svga->ma + shift + 8) & svga->vram_display_mask]);
 
                                     p[0] = p[1] = dat0 & 0xffffff;
                                     p[2] = p[3] = (dat0 >> 24) | ((dat1 & 0xffff) << 8);
@@ -826,11 +827,11 @@ void svga_render_24bpp_lowres(svga_t *svga)
                                 uint32_t addr;
 
                                 addr = svga->remap_func(svga, svga->ma);
-                                dat0 = *(uint32_t *)(&svga->vram[addr & svga->vram_display_mask]);
+                                dat0 = *(uint32_t *)(&svga->vram[(addr + shift) & svga->vram_display_mask]);
                                 addr = svga->remap_func(svga, svga->ma + 4);
-                                dat1 = *(uint32_t *)(&svga->vram[addr & svga->vram_display_mask]);
+                                dat1 = *(uint32_t *)(&svga->vram[(addr + shift) & svga->vram_display_mask]);
                                 addr = svga->remap_func(svga, svga->ma + 8);
-                                dat2 = *(uint32_t *)(&svga->vram[addr & svga->vram_display_mask]);
+                                dat2 = *(uint32_t *)(&svga->vram[(addr + shift) & svga->vram_display_mask]);
 
                                 p[0] = p[1] = dat0 & 0xffffff;
                                 p[2] = p[3] = (dat0 >> 24) | ((dat1 & 0xffff) << 8);
@@ -851,7 +852,8 @@ void svga_render_24bpp_lowres_swaprb(svga_t *svga)
         if (svga->changedvram[changed_addr >> 12] || svga->changedvram[(changed_addr >> 12) + 1] || svga->fullchange)
         {
                 int x;
-                int offset = (8 - (svga->scrollcache & 6)) + 24;
+                int offset = svga->scrollcache_dst;
+                int shift = svga->scrollcache_src;
                 uint32_t *p = &((uint32_t *)buffer32->line[svga->displine])[offset];
 
                 if (svga->firstline_draw == 4000) 
@@ -862,7 +864,7 @@ void svga_render_24bpp_lowres_swaprb(svga_t *svga)
                 {
                             for (x = 0; x <= svga->hdisp << svga->horizontal_linedbl; x++)
                             {
-                                uint32_t fg = svga->vram[svga->ma + 2] | (svga->vram[svga->ma + 1] << 8) | (svga->vram[svga->ma + 0] << 16);
+                                uint32_t fg = svga->vram[svga->ma + shift + 2] | (svga->vram[svga->ma + shift + 1] << 8) | (svga->vram[svga->ma + shift + 0] << 16);
                                 svga->ma += 3;
                                 svga->ma &= svga->vram_display_mask;
                                 p[0] = p[1] = fg;
@@ -876,7 +878,7 @@ void svga_render_24bpp_lowres_swaprb(svga_t *svga)
                                 uint32_t addr;
 
                                 addr = svga->remap_func(svga, svga->ma);
-                                uint32_t fg = svga->vram[addr + 2] | (svga->vram[addr + 1] << 8) | (svga->vram[addr + 0] << 16);
+                                uint32_t fg = svga->vram[addr + shift + 2] | (svga->vram[addr + shift + 1] << 8) | (svga->vram[addr + shift + 0] << 16);
                                 svga->ma += 3;
                                 svga->ma &= svga->vram_display_mask;
                                 p[0] = p[1] = fg;
@@ -894,7 +896,8 @@ void svga_render_24bpp_highres(svga_t *svga)
         if (svga->changedvram[changed_addr >> 12] || svga->changedvram[(changed_addr >> 12) + 1] || svga->fullchange)
         {
                 int x;
-                int offset = (8 - ((svga->scrollcache & 6) >> 1)) + 24;
+                int offset = svga->scrollcache_dst;
+                int shift = svga->scrollcache_src;
                 uint32_t *p = &((uint32_t *)buffer32->line[svga->displine])[offset];
                 
                 if (svga->firstline_draw == 4000) 
@@ -905,9 +908,9 @@ void svga_render_24bpp_highres(svga_t *svga)
                 {
                         for (x = 0; x <= svga->hdisp; x += 4)
                         {
-                                uint32_t dat0 = *(uint32_t *)(&svga->vram[svga->ma & svga->vram_display_mask]);
-                                uint32_t dat1 = *(uint32_t *)(&svga->vram[(svga->ma + 4) & svga->vram_display_mask]);
-                                uint32_t dat2 = *(uint32_t *)(&svga->vram[(svga->ma + 8) & svga->vram_display_mask]);
+                                uint32_t dat0 = *(uint32_t *)(&svga->vram[(svga->ma + shift) & svga->vram_display_mask]);
+                                uint32_t dat1 = *(uint32_t *)(&svga->vram[(svga->ma + shift + 4) & svga->vram_display_mask]);
+                                uint32_t dat2 = *(uint32_t *)(&svga->vram[(svga->ma + shift + 8) & svga->vram_display_mask]);
 
                                 *p++ = dat0 & 0xffffff;
                                 *p++ = (dat0 >> 24) | ((dat1 & 0xffff) << 8);
@@ -925,11 +928,11 @@ void svga_render_24bpp_highres(svga_t *svga)
                                 uint32_t addr;
 
                                 addr = svga->remap_func(svga, svga->ma);
-                                dat0 = *(uint32_t *)(&svga->vram[addr & svga->vram_display_mask]);
+                                dat0 = *(uint32_t *)(&svga->vram[(addr + shift) & svga->vram_display_mask]);
                                 addr = svga->remap_func(svga, svga->ma + 4);
-                                dat1 = *(uint32_t *)(&svga->vram[addr & svga->vram_display_mask]);
+                                dat1 = *(uint32_t *)(&svga->vram[(addr + shift) & svga->vram_display_mask]);
                                 addr = svga->remap_func(svga, svga->ma + 8);
-                                dat2 = *(uint32_t *)(&svga->vram[addr & svga->vram_display_mask]);
+                                dat2 = *(uint32_t *)(&svga->vram[(addr + shift) & svga->vram_display_mask]);
 
                                 *p++ = dat0 & 0xffffff;
                                 *p++ = (dat0 >> 24) | ((dat1 & 0xffff) << 8);
@@ -950,7 +953,8 @@ void svga_render_24bpp_highres_swaprb(svga_t *svga)
         if (svga->changedvram[changed_addr >> 12] || svga->changedvram[(changed_addr >> 12) + 1] || svga->fullchange)
         {
                 int x;
-                int offset = (8 - ((svga->scrollcache & 6) >> 1)) + 24;
+                int offset = svga->scrollcache_dst;
+                int shift = svga->scrollcache_src;
                 uint32_t *p = &((uint32_t*)buffer32->line[svga->displine])[offset];
                 
                 if (svga->firstline_draw == 4000) 
@@ -961,7 +965,7 @@ void svga_render_24bpp_highres_swaprb(svga_t *svga)
                 {
                         for (x = 0; x <= svga->hdisp; x++)
                         {
-                                uint32_t fg = svga->vram[svga->ma + 2] | (svga->vram[svga->ma + 1] << 8) | (svga->vram[svga->ma + 0] << 16);
+                                uint32_t fg = svga->vram[svga->ma + shift + 2] | (svga->vram[svga->ma + shift + 1] << 8) | (svga->vram[svga->ma + shift + 0] << 16);
                                 svga->ma += 3;
                                 svga->ma &= svga->vram_display_mask;
                                 *p++ = fg;
@@ -972,7 +976,7 @@ void svga_render_24bpp_highres_swaprb(svga_t *svga)
                         for (x = 0; x <= svga->hdisp; x += 4)
                         {
                                 uint32_t addr = svga->remap_func(svga, svga->ma);
-                                uint32_t fg = svga->vram[addr + 2] | (svga->vram[addr + 1] << 8) | (svga->vram[addr + 0] << 16);
+                                uint32_t fg = svga->vram[addr + shift + 2] | (svga->vram[addr + shift + 1] << 8) | (svga->vram[addr + shift + 0] << 16);
                                 svga->ma += 3;
                                 svga->ma &= svga->vram_display_mask;
                                 *p++ = fg;
@@ -989,7 +993,7 @@ void svga_render_32bpp_lowres(svga_t *svga)
         if (svga->changedvram[changed_addr >> 12] || svga->changedvram[(changed_addr >> 12) + 1] || svga->fullchange)
         {
                 int x;
-                int offset = (8 - (svga->scrollcache & 6)) + 24;
+                int offset = svga->scrollcache_dst;
                 uint32_t *p = &((uint32_t *)buffer32->line[svga->displine])[offset];
 
                 if (svga->firstline_draw == 4000) 
@@ -1028,7 +1032,7 @@ void svga_render_32bpp_lowres_swaprb(svga_t *svga)
         if (svga->changedvram[changed_addr >> 12] || svga->changedvram[(changed_addr >> 12) + 1] || svga->fullchange)
         {
                 int x;
-                int offset = (8 - (svga->scrollcache & 6)) + 24;
+                int offset = svga->scrollcache_dst;
                 uint32_t *p = &((uint32_t *)buffer32->line[svga->displine])[offset];
 
                 if (svga->firstline_draw == 4000) 
@@ -1070,7 +1074,7 @@ void svga_render_32bpp_highres(svga_t *svga)
         if (svga->changedvram[changed_addr >> 12] || svga->changedvram[(changed_addr >> 12) + 1] || svga->fullchange)
         {
                 int x;
-                int offset = (8 - ((svga->scrollcache & 6) >> 1)) + 24;
+                int offset = svga->scrollcache_dst;
                 uint32_t *p = &((uint32_t *)buffer32->line[svga->displine])[offset];
                 
                 if (svga->firstline_draw == 4000) 
@@ -1108,7 +1112,7 @@ void svga_render_32bpp_highres_swaprb(svga_t *svga)
         if (svga->changedvram[changed_addr >> 12] || svga->changedvram[(changed_addr >> 12) + 1] || svga->fullchange)
         {
                 int x;
-                int offset = (8 - ((svga->scrollcache & 6) >> 1)) + 24;
+                int offset = svga->scrollcache_dst;
                 uint32_t *p = &((uint32_t *)buffer32->line[svga->displine])[offset];
                 
                 if (svga->firstline_draw == 4000) 
@@ -1149,7 +1153,7 @@ void svga_render_ABGR8888_highres(svga_t *svga)
         if (svga->changedvram[changed_addr >> 12] || svga->changedvram[(changed_addr >> 12) + 1] || svga->fullchange)
         {
                 int x;
-                int offset = (8 - ((svga->scrollcache & 6) >> 1)) + 24;
+                int offset = svga->scrollcache_dst;
                 uint32_t *p = &((uint32_t *)buffer32->line[svga->displine])[offset];
 
                 if (svga->firstline_draw == 4000)
@@ -1187,7 +1191,7 @@ void svga_render_RGBA8888_highres(svga_t *svga)
         if (svga->changedvram[changed_addr >> 12] || svga->changedvram[(changed_addr >> 12) + 1] || svga->fullchange)
         {
                 int x;
-                int offset = (8 - ((svga->scrollcache & 6) >> 1)) + 24;
+                int offset = svga->scrollcache_dst;
                 uint32_t *p = &((uint32_t *)buffer32->line[svga->displine])[offset];
 
                 if (svga->firstline_draw == 4000)