]> git.unchartedbackwaters.co.uk Git - francis/winuae.git/commitdiff
PCem RTG updates and fixes.
authorToni Wilen <twilen@winuae.net>
Sat, 10 Oct 2020 14:15:35 +0000 (17:15 +0300)
committerToni Wilen <twilen@winuae.net>
Sat, 10 Oct 2020 14:15:35 +0000 (17:15 +0300)
pcem/vid_cl5429.cpp
pcem/vid_s3.cpp
pcem/vid_s3_virge.cpp
pcem/vid_svga.cpp
pcem/vid_svga.h
pcem/vid_svga_render.cpp

index 849ed71ea3b049f0f29522c0b423d204759a70d6..7ad082dc219e9a52005b9421593a67f6b68fb66d 100644 (file)
@@ -767,10 +767,12 @@ void gd5429_out(uint16_t addr, uint8_t val, void *p)
                 svga->crtc[svga->crtcreg] = val;
 
                 if (svga->crtcreg == 0x11) {
-                    if (!(val & 0x10))
-                        gd5429->vblank_irq = -1;
-                    else if (gd5429->vblank_irq < 0)
+                    if (!(val & 0x10)) {
+                        if (gd5429->vblank_irq > 0)
+                            gd5429->vblank_irq = -1;
+                    } else if (gd5429->vblank_irq < 0) {
                         gd5429->vblank_irq = 0;
+                    }
                     gd5429_update_irqs(gd5429);
                 }
 
@@ -1153,8 +1155,14 @@ void gd5429_recalctimings(svga_t *svga)
         
         svga->interlace = svga->crtc[0x1a] & 1;
         
-        if (svga->seqregs[7] & 0x01)
+        svga->horizontal_linedbl = svga->dispend * 9 / 10 >= svga->hdisp;
+
+        if (svga->seqregs[7] & 0x01) {
+            if (svga->horizontal_linedbl)
+                svga->render = svga_render_8bpp_lowres;
+            else
                 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) {
@@ -1170,23 +1178,35 @@ void gd5429_recalctimings(svga_t *svga)
                         switch (gd5429->hidden_dac_reg & 0xf)
                         {
                                 case 0x0:
-                                svga->render = svga_render_15bpp_highres;
+                                if (svga->horizontal_linedbl)
+                                    svga->render = svga_render_15bpp_lowres;
+                                else
+                                    svga->render = svga_render_15bpp_highres;
                                 svga->bpp = 15;
                                 break;
                                 case 0x1:
-                                svga->render = svga_render_16bpp_highres;
+                                if (svga->horizontal_linedbl)
+                                    svga->render = svga_render_16bpp_lowres;
+                                else
+                                    svga->render = svga_render_16bpp_highres;
                                 svga->bpp = 16;
                                 break;
                                 case 0x5:
                                 if (gd5429->type >= CL_TYPE_GD5434 && (svga->seqregs[7] & 8))
                                 {
-                                        svga->render = svga_render_32bpp_highres;
+                                        if (svga->horizontal_linedbl)
+                                            svga->render = svga_render_32bpp_lowres;
+                                        else
+                                            svga->render = svga_render_32bpp_highres;
                                         svga->bpp = 32;
                                         svga->rowoffset *= 2;
                                 }
                                 else
                                 {
-                                        svga->render = svga_render_24bpp_highres;
+                                        if (svga->horizontal_linedbl)
+                                            svga->render = svga_render_24bpp_lowres;
+                                        else
+                                            svga->render = svga_render_24bpp_highres;
                                         svga->bpp = 24;
                                 }
                                 break;
@@ -1194,7 +1214,10 @@ void gd5429_recalctimings(svga_t *svga)
                 }
                 else
                 {
-                        svga->render = svga_render_15bpp_highres; 
+                        if (svga->horizontal_linedbl)
+                            svga->render = svga_render_15bpp_lowres;
+                        else
+                            svga->render = svga_render_15bpp_highres;
                         svga->bpp = 15;
                 }
         }
@@ -1231,6 +1254,8 @@ void gd5429_hwcursor_draw(svga_t *svga, int displine)
         int offset = svga->hwcursor_latch.x - svga->hwcursor_latch.xoff;
         int line_offset = (svga->seqregs[0x12] & 0x04) ? 16 : 4;
 
+        offset <<= svga->horizontal_linedbl;
+
         if (svga->interlace && svga->hwcursor_oddeven)
                 svga->hwcursor_latch.addr += line_offset;
 
@@ -1886,23 +1911,31 @@ void gd5429_start_blit(uint32_t cpu_dat, int count, void *p)
         int fg_col = gd5429->blt.fg_col;
         int bg_col = gd5429->blt.bg_col;
         int x_max = 0;
+        int bplcnt = 0;
+        int bpp;
+        uint8_t dststore[4];
+        int maskstore = 0;
 
         switch (gd5429->blt.depth)
         {
                 case BLIT_DEPTH_8:
                 x_max = 8;
+                bpp = 1;
                 break;
                 case BLIT_DEPTH_16:
                 x_max = 16;
                 blt_mask *= 2;
+                bpp = 2;
                 break;
                 case BLIT_DEPTH_24:
                 x_max = 24;
                 blt_mask *= 3;
+                bpp = 3;
                 break;
                 case BLIT_DEPTH_32:
                 x_max = 32;
                 blt_mask *= 4;
+                bpp = 4;
                 break;
         }
                 
@@ -1924,8 +1957,8 @@ void gd5429_start_blit(uint32_t cpu_dat, int count, void *p)
                         gd5429->blt.y_count = gd5429->blt.src_addr & 7;
                 else
                         gd5429->blt.y_count = 0;
-//                pclog("gd5429_start_blit : size %i, %i %i %02x %02x %02x %02x\n",
-//                    gd5429->blt.width, gd5429->blt.height, gd5429->blt.x_count, gd5429->blt.rop, gd5429->blt.mode, gd5429->blt.extensions, gd5429->blt.mask);
+//                pclog("gd5429_start_blit : size %i, %i %i %02x %02x %02x %02x %d\n",
+//                    gd5429->blt.width, gd5429->blt.height, gd5429->blt.x_count, gd5429->blt.rop, gd5429->blt.mode, gd5429->blt.extensions, gd5429->blt.mask, gd5429->blt.depth);
 
                 if (gd5429->blt.mode & 0x04)
                 {
@@ -2135,6 +2168,40 @@ void gd5429_start_blit(uint32_t cpu_dat, int count, void *p)
                         case 0xda: dst = ~(src &  dst); break;
                 }
 
+                dststore[bplcnt++] = dst;
+                maskstore |= mask;
+                if (bplcnt >= bpp) {
+                    if (bpp == 1) {
+                        if ((gd5429->blt.width_backup - gd5429->blt.width) >= blt_mask &&
+                            !((gd5429->blt.mode & 0x08) && !mask))
+                            svga->vram[gd5429->blt.dst_addr & svga->vram_mask] = dst;
+                    } else if (bpp == 2) {
+                        if ((gd5429->blt.width_backup - gd5429->blt.width) >= blt_mask &&
+                            !((gd5429->blt.mode & 0x08) && !maskstore)) {
+                            svga->vram[(gd5429->blt.dst_addr + 0) & svga->vram_mask] = dststore[0];
+                            svga->vram[(gd5429->blt.dst_addr + 1) & svga->vram_mask] = dststore[1];
+                        }
+                    } else if (bpp == 3) {
+                        if ((gd5429->blt.width_backup - gd5429->blt.width) >= blt_mask &&
+                            !((gd5429->blt.mode & 0x08) && !maskstore)) {
+                            svga->vram[(gd5429->blt.dst_addr + 0) & svga->vram_mask] = dststore[0];
+                            svga->vram[(gd5429->blt.dst_addr + 1) & svga->vram_mask] = dststore[1];
+                            svga->vram[(gd5429->blt.dst_addr + 2) & svga->vram_mask] = dststore[2];
+                        }
+                    } else if (bpp == 3) {
+                        if ((gd5429->blt.width_backup - gd5429->blt.width) >= blt_mask &&
+                            !((gd5429->blt.mode & 0x08) && !maskstore)) {
+                            svga->vram[(gd5429->blt.dst_addr + 0) & svga->vram_mask] = dststore[0];
+                            svga->vram[(gd5429->blt.dst_addr + 1) & svga->vram_mask] = dststore[1];
+                            svga->vram[(gd5429->blt.dst_addr + 2) & svga->vram_mask] = dststore[2];
+                            svga->vram[(gd5429->blt.dst_addr + 3) & svga->vram_mask] = dststore[3];
+                        }
+                    }
+                    gd5429->blt.dst_addr += ((gd5429->blt.mode & 0x01) ? -bpp : bpp);
+                    bplcnt = 0;
+                    maskstore = 0;
+                }
+#if 0
                 if (0 && gd5429->type <= CL_TYPE_GD5428)
                 {
                         if ((gd5429->blt.width_backup - gd5429->blt.width) >= blt_mask &&
@@ -2147,8 +2214,8 @@ void gd5429_start_blit(uint32_t cpu_dat, int count, void *p)
                             !((gd5429->blt.mode & 0x08) && !mask))
                                 svga->vram[gd5429->blt.dst_addr & svga->vram_mask] = dst;
                 }
-                
                 gd5429->blt.dst_addr += ((gd5429->blt.mode & 0x01) ? -1 : 1);
+#endif           
 
                 gd5429->blt.x_count++;
                 if (gd5429->blt.x_count == x_max)
index 490a73b75098c0981ff51762f0842e84966be235..030dc59a7371cd1ab781e977bfc25b51a447057f 100644 (file)
@@ -134,6 +134,7 @@ typedef struct s3_t
         fifo_entry_t fifo[FIFO_SIZE];
         volatile int fifo_read_idx, fifo_write_idx;
 
+        volatile int fifo_thread_state;
         thread_t *fifo_thread;
         event_t *wake_fifo_thread;
         event_t *fifo_not_full_event;
@@ -882,7 +883,8 @@ static void fifo_thread(void *param)
 {
         s3_t *s3 = (s3_t *)param;
         
-        while (1)
+        s3->fifo_thread_state = 1;
+        while (s3->fifo_thread_state > 0)
         {
                 thread_set_event(s3->fifo_not_full_event);
                 thread_wait_event(s3->wake_fifo_thread, -1);
@@ -929,6 +931,7 @@ static void fifo_thread(void *param)
                 s3->subsys_stat |= INT_FIFO_EMP;
                 s3_update_irqs(s3);
         }
+        s3->fifo_thread_state = 0;
 }
 
 static void s3_vblank_start(svga_t *svga)
@@ -1241,6 +1244,8 @@ void s3_recalctimings(svga_t *svga)
         svga->interlace = svga->crtc[0x42] & 0x20;
         //svga->clock = (cpuclock * (float)(1ull << 32)) / s3->getclock(clk_sel, s3->getclock_p);
 
+        svga->horizontal_linedbl = svga->dispend * 9 / 10 >= svga->hdisp;
+
         switch (svga->crtc[0x67] >> 4)
         {
                 case 3: case 5: case 7:
@@ -1254,22 +1259,37 @@ void s3_recalctimings(svga_t *svga)
                 switch (svga->bpp)
                 {
                         case 8: 
-                        svga->render = svga_render_8bpp_highres; 
+                        if (svga->horizontal_linedbl)
+                            svga->render = svga_render_8bpp_lowres;
+                        else
+                            svga->render = svga_render_8bpp_highres;
                         break;
                         case 15: 
-                        svga->render = svga_render_15bpp_highres; 
+                        if (svga->horizontal_linedbl)
+                            svga->render = svga_render_15bpp_lowres;
+                        else
+                            svga->render = svga_render_15bpp_highres;
                         svga->hdisp /= 2;
                         break;
                         case 16: 
-                        svga->render = svga_render_16bpp_highres; 
+                        if (svga->horizontal_linedbl)
+                            svga->render = svga_render_16bpp_lowres;
+                        else
+                            svga->render = svga_render_16bpp_highres;
                         svga->hdisp /= 2;
                         break;
                         case 24: 
-                        svga->render = svga_render_24bpp_highres; 
+                        if (svga->horizontal_linedbl)
+                            svga->render = svga_render_24bpp_lowres;
+                        else
+                            svga->render = svga_render_24bpp_highres;
                         svga->hdisp /= 3;
                         break;
                         case 32:
-                        svga->render = svga_render_32bpp_highres; 
+                        if (svga->horizontal_linedbl)
+                            svga->render = svga_render_32bpp_lowres;
+                        else
+                            svga->render = svga_render_32bpp_highres;
                         if (s3->chip != S3_TRIO32 && s3->chip != S3_TRIO64)
                                 svga->hdisp /= 4;
                         break;
@@ -1755,10 +1775,30 @@ void s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat
         int compare_mode = (s3->accel.multifunc[0xe] >> 7) & 3;
         uint32_t rd_mask = s3->accel.rd_mask;
         int cmd = s3->accel.cmd >> 13;
+        uint32_t srcbase, dstbase;
         
         if ((s3->chip == S3_TRIO64) && (s3->accel.cmd & (1 << 11)))
                 cmd |= 8;
 
+        // SRC-BASE/DST-BASE
+        if ((s3->accel.multifunc[13] >> 4) & 7) {
+            srcbase = 0x100000 * ((s3->accel.multifunc[13] >> 4) & 3);
+        } else {
+            srcbase = 0x100000 * ((s3->accel.multifunc[14] >> 2) & 3);
+        }
+        if ((s3->accel.multifunc[13] >> 0) & 7) {
+            dstbase = 0x100000 * ((s3->accel.multifunc[13] >> 0) & 3);
+        } else {
+            dstbase = 0x100000 * ((s3->accel.multifunc[14] >> 0) & 3);
+        }
+        if (s3->bpp == 1) {
+            srcbase >>= 1;
+            dstbase >>= 1;
+        } else if (s3->bpp == 3) {
+            srcbase >>= 2;
+            dstbase >>= 2;
+        }
+
         // Amiga CGX4 driver sets all clipping values to FFF.
         if (clip_t == 0xfff)
             clip_t = 0;
@@ -1766,9 +1806,9 @@ void s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat
             clip_l = 0;
 
         s3->force_busy = 1;
-//return;
-//        if (!cpu_input) pclog("Start S3 command %i  %i, %i  %i, %i (clip %i, %i to %i, %i  %i)\n", s3->accel.cmd >> 13, s3->accel.cur_x, s3->accel.cur_y, s3->accel.maj_axis_pcnt & 0xfff, s3->accel.multifunc[0]  & 0xfff, clip_l, clip_t, clip_r, clip_b, s3->accel.multifunc[0xe] & 0x20);
-//        else            pclog("      S3 command %i, %i, %08x %08x\n", s3->accel.cmd >> 13, count, mix_dat, cpu_dat);
+        //return;
+        //if (!cpu_input) pclog("Start S3 command %i  %i, %i  %i, %i (clip %i, %i to %i, %i  %i)\n", s3->accel.cmd >> 13, s3->accel.cur_x, s3->accel.cur_y, s3->accel.maj_axis_pcnt & 0xfff, s3->accel.multifunc[0]  & 0xfff, clip_l, clip_t, clip_r, clip_b, s3->accel.multifunc[0xe] & 0x20);
+        //else            pclog("      S3 command %i, %i, %08x %08x\n", s3->accel.cmd >> 13, count, mix_dat, cpu_dat);
 
         if (!cpu_input) s3->accel.dat_count = 0;
         if (cpu_input && (s3->accel.multifunc[0xa] & 0xc0) != 0x80)
@@ -1827,8 +1867,8 @@ void s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat
                 {
                         while (count-- && s3->accel.sy >= 0)
                         {
-                                if (s3->accel.cx >= clip_l && s3->accel.cx <= clip_r &&
-                                    s3->accel.cy >= clip_t && s3->accel.cy <= clip_b)
+                                if ((s3->accel.cx & 0xfff) >= clip_l && (s3->accel.cx & 0xfff) <= clip_r &&
+                                    (s3->accel.cy & 0xfff) >= clip_t && (s3->accel.cy & 0xfff) <= clip_b)
                                 {
                                         switch ((mix_dat & mix_mask) ? frgd_mix : bkgd_mix)
                                         {
@@ -1877,8 +1917,8 @@ void s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat
                 {
                         while (count-- && s3->accel.sy >= 0)
                         {
-                                if (s3->accel.cx >= clip_l && s3->accel.cx <= clip_r &&
-                                    s3->accel.cy >= clip_t && s3->accel.cy <= clip_b)
+                                if ((s3->accel.cx & 0xfff) >= clip_l && (s3->accel.cx & 0xfff) <= clip_r &&
+                                    (s3->accel.cy & 0xfff) >= clip_t && (s3->accel.cy & 0xfff) <= clip_b)
                                 {
                                         switch ((mix_dat & mix_mask) ? frgd_mix : bkgd_mix)
                                         {
@@ -1962,7 +2002,7 @@ void s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat
                         s3->accel.cy   = s3->accel.cur_y;
                         if (s3->accel.cur_y & 0x1000) s3->accel.cy |= ~0xfff;
                         
-                        s3->accel.dest = s3->accel.cy * s3->width;
+                        s3->accel.dest = dstbase + s3->accel.cy * s3->width;
 
 //                        pclog("Dest %08X  (%i, %i) %04X %04X\n", s3->accel.dest, s3->accel.cx, s3->accel.cy, s3->accel.cur_x, s3->accel.cur_x & 0x1000);
                 }
@@ -1975,8 +2015,8 @@ void s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat
                 
                 while (count-- && s3->accel.sy >= 0)
                 {
-                        if (s3->accel.cx >= clip_l && s3->accel.cx <= clip_r &&
-                            s3->accel.cy >= clip_t && s3->accel.cy <= clip_b)
+                        if ((s3->accel.cx & 0xfff) >= clip_l && (s3->accel.cx & 0xfff) <= clip_r &&
+                            (s3->accel.cy & 0xfff) >= clip_t && (s3->accel.cy & 0xfff) <= clip_b)
                         {
                                 switch ((mix_dat & mix_mask) ? frgd_mix : bkgd_mix)
                                 {
@@ -2022,7 +2062,7 @@ void s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat
                                 if (s3->accel.cmd & 0x80) s3->accel.cy++;
                                 else                     s3->accel.cy--;
                                 
-                                s3->accel.dest = s3->accel.cy * s3->width;
+                                s3->accel.dest = dstbase + s3->accel.cy * s3->width;
                                 s3->accel.sy--;
 
                                 if (cpu_input/* && (s3->accel.multifunc[0xa] & 0xc0) == 0x80*/) return;
@@ -2052,8 +2092,8 @@ void s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat
                         s3->accel.cy   = s3->accel.cur_y & 0xfff;
                         if (s3->accel.cur_y & 0x1000) s3->accel.cy |= ~0xfff;
 
-                        s3->accel.src  = s3->accel.cy * s3->width;
-                        s3->accel.dest = s3->accel.dy * s3->width;
+                        s3->accel.src  = srcbase + s3->accel.cy * s3->width;
+                        s3->accel.dest = dstbase + s3->accel.dy * s3->width;
                         
 //                        pclog("Source %08X Dest %08X  (%i, %i) - (%i, %i)\n", s3->accel.src, s3->accel.dest, s3->accel.cx, s3->accel.cy, s3->accel.dx, s3->accel.dy);
                 }
@@ -2072,8 +2112,8 @@ void s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat
                 {
                         while (1)
                         {
-                                if (s3->accel.dx >= clip_l && s3->accel.dx <= clip_r &&
-                                    s3->accel.dy >= clip_t && s3->accel.dy <= clip_b)
+                                if ((s3->accel.dx & 0xfff) >= clip_l && (s3->accel.dx & 0xfff) <= clip_r &&
+                                    (s3->accel.dy & 0xfff) >= clip_t && (s3->accel.dy & 0xfff) <= clip_b)
                                 {
                                         READ_SRC(s3->accel.src + s3->accel.cx, src_dat);
                                         READ_DST(s3->accel.dest + s3->accel.dx, dest_dat);  
@@ -2095,8 +2135,8 @@ void s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat
                                         s3->accel.cy++;
                                         s3->accel.dy++;
         
-                                        s3->accel.src  = s3->accel.cy * s3->width;
-                                        s3->accel.dest = s3->accel.dy * s3->width;
+                                        s3->accel.src  = srcbase + s3->accel.cy * s3->width;
+                                        s3->accel.dest = dstbase + s3->accel.dy * s3->width;
         
                                         s3->accel.sy--;
         
@@ -2109,8 +2149,8 @@ void s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat
                 {                     
                         while (count-- && s3->accel.sy >= 0)
                         {
-                                if (s3->accel.dx >= clip_l && s3->accel.dx <= clip_r &&
-                                    s3->accel.dy >= clip_t && s3->accel.dy <= clip_b)
+                                if ((s3->accel.dx & 0xfff) >= clip_l && (s3->accel.dx & 0xfff) <= clip_r &&
+                                    (s3->accel.dy & 0xfff) >= clip_t && (s3->accel.dy & 0xfff) <= clip_b)
                                 {
                                         if (vram_mask)
                                         {
@@ -2183,8 +2223,8 @@ void s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat
                                                 s3->accel.dy--;
                                         }
 
-                                        s3->accel.src  = s3->accel.cy * s3->width;
-                                        s3->accel.dest = s3->accel.dy * s3->width;
+                                        s3->accel.src  = srcbase + s3->accel.cy * s3->width;
+                                        s3->accel.dest = dstbase + s3->accel.dy * s3->width;
 
                                         s3->accel.sy--;
 
@@ -2217,12 +2257,12 @@ void s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat
 //                        s3->accel.cy = (s3->accel.cy & ~7) | (s3->accel.dy & 7);
 
                         s3->accel.pattern  = (s3->accel.cy * s3->width) + s3->accel.cx;
-                        s3->accel.dest     = s3->accel.dy * s3->width;
+                        s3->accel.dest     = dstbase + s3->accel.dy * s3->width;
                         
                         s3->accel.cx = s3->accel.dx & 7;
                         s3->accel.cy = s3->accel.dy & 7;
                         
-                        s3->accel.src  = s3->accel.pattern + (s3->accel.cy * s3->width);
+                        s3->accel.src  = srcbase + s3->accel.pattern + (s3->accel.cy * s3->width);
 
 //                        pclog("Source %08X Dest %08X  (%i, %i) - (%i, %i)\n", s3->accel.src, s3->accel.dest, s3->accel.cx, s3->accel.cy, s3->accel.dx, s3->accel.dy);
 //                        dumpregs();
@@ -2237,8 +2277,8 @@ void s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat
 
                 while (count-- && s3->accel.sy >= 0)
                 {
-                        if (s3->accel.dx >= clip_l && s3->accel.dx <= clip_r &&
-                            s3->accel.dy >= clip_t && s3->accel.dy <= clip_b)
+                        if ((s3->accel.dx & 0xfff) >= clip_l && (s3->accel.dx & 0xfff) <= clip_r &&
+                            (s3->accel.dy & 0xfff) >= clip_t && (s3->accel.dy & 0xfff) <= clip_b)
                         {
                                 if (vram_mask)
                                 {
@@ -2310,8 +2350,8 @@ void s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat
                                         s3->accel.dy--;
                                 }
 
-                                s3->accel.src  = s3->accel.pattern + (s3->accel.cy * s3->width);
-                                s3->accel.dest = s3->accel.dy * s3->width;
+                                s3->accel.src  = srcbase + s3->accel.pattern + (s3->accel.cy * s3->width);
+                                s3->accel.dest = dstbase + s3->accel.dy * s3->width;
 
                                 s3->accel.sy--;
 
@@ -2344,12 +2384,12 @@ void s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat
                                 int y = s3->accel.poly_cy;
                                 int x_count = ABS((s3->accel.poly_cx2 >> 20) - s3->accel.poly_x) + 1;
 
-                                s3->accel.dest = y * s3->width;
+                                s3->accel.dest = dstbase + y * s3->width;
                                 
                                 while (x_count-- && count--)
                                 {
-                                        if (s3->accel.poly_x >= clip_l && s3->accel.poly_x <= clip_r &&
-                                            s3->accel.poly_cy >= clip_t && s3->accel.poly_cy <= clip_b)
+                                        if ((s3->accel.poly_x & 0xfff) >= clip_l && (s3->accel.poly_x & 0xfff) <= clip_r &&
+                                            (s3->accel.poly_cy & 0xfff) >= clip_t && (s3->accel.poly_cy & 0xfff) <= clip_b)
                                         {
                                                 switch (frgd_mix)
                                                 {
@@ -2419,15 +2459,15 @@ void s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat
                                 int y = s3->accel.poly_cy;
                                 int x_count = ABS((s3->accel.poly_cx2 >> 20) - s3->accel.poly_x) + 1;
 
-                                s3->accel.src  = s3->accel.pattern + ((y & 7) * s3->width);
-                                s3->accel.dest = y * s3->width;
+                                s3->accel.src  = srcbase + s3->accel.pattern + ((y & 7) * s3->width);
+                                s3->accel.dest = dstbase + y * s3->width;
                                 
                                 while (x_count-- && count--)
                                 {
                                         int pat_x = s3->accel.poly_x & 7;
                                         
-                                        if (s3->accel.poly_x >= clip_l && s3->accel.poly_x <= clip_r &&
-                                            s3->accel.poly_cy >= clip_t && s3->accel.poly_cy <= clip_b)
+                                        if ((s3->accel.poly_x & 0xfff) >= clip_l && (s3->accel.poly_x & 0xfff) <= clip_r &&
+                                            (s3->accel.poly_cy & 0xfff) >= clip_t && (s3->accel.poly_cy & 0xfff) <= clip_b)
                                         {
                                                 if (vram_mask)
                                                 {
@@ -2493,7 +2533,9 @@ void s3_hwcursor_draw(svga_t *svga, int displine)
         int xx;
         int offset = svga->hwcursor_latch.x - svga->hwcursor_latch.xoff;
         uint32_t fg = 0, bg = 0;
-                
+
+        offset <<= svga->horizontal_linedbl;
+
         switch (svga->bpp)
         {               
                 case 15:
@@ -2907,7 +2949,14 @@ void s3_close(void *p)
 
         svga_close(&s3->svga);
         
-        thread_kill(s3->fifo_thread);
+        if (s3->fifo_thread_state) {
+            s3->fifo_thread_state = -1;
+            wake_fifo_thread(s3);
+            while (s3->fifo_thread_state == -1) {
+                thread_sleep(1);
+            }
+            thread_kill(s3->fifo_thread);
+        }
         thread_destroy_event(s3->wake_fifo_thread);
         thread_destroy_event(s3->fifo_not_full_event);
 
index b1cb60aaf9f5299c40add5e7c345fe707c875e5f..f7031c5914943eae5966dd3a3be92be98084719c 100644 (file)
@@ -136,6 +136,7 @@ typedef struct virge_t
         int pixel_count, tri_count;
         
         thread_t *render_thread;
+        volatile int render_thread_state;
         event_t *wake_render_thread;
         event_t *wake_main_thread;
         event_t *not_full_event;
@@ -229,12 +230,14 @@ typedef struct virge_t
         volatile int fifo_read_idx, fifo_write_idx;
 
         thread_t *fifo_thread;
+        volatile int fifo_thread_state;
         event_t *wake_fifo_thread;
         event_t *fifo_not_full_event;
         
         int virge_busy;
         
         uint8_t subsys_stat, subsys_cntl;
+        int vblank_irq;
 } virge_t;
 
 static inline void wake_fifo_thread(virge_t *virge)
@@ -306,9 +309,16 @@ enum
 #define INT_3DF_EMP  (1 << 6)
 #define INT_MASK 0xff
 
+static int vsync_enabled(virge_t *virge)
+{
+    if ((virge->svga.crtc[0x32] & 0x10) && ((!(virge->svga.crtc[0x11] & 0x20) && virge->vblank_irq > 0) || (virge->subsys_stat & virge->subsys_cntl & INT_MASK)))
+        return 1;
+    return 0;
+}
+
 static void s3_virge_update_irqs(virge_t *virge)
 {
-        if ((virge->svga.crtc[0x32] & 0x10) && (virge->subsys_stat & virge->subsys_cntl & INT_MASK))
+        if (vsync_enabled(virge))
                 pci_set_irq(virge->card, PCI_INTA);
         else
                 pci_clear_irq(virge->card, PCI_INTA);
@@ -363,6 +373,15 @@ static void s3_virge_out(uint16_t addr, uint8_t val, void *p)
                 svga->crtc[svga->crtcreg] = val;
                 switch (svga->crtcreg)
                 {
+                        case 0x11:
+                        if (!(val & 0x10)) {
+                            if (virge->vblank_irq > 0)
+                                virge->vblank_irq = -1;
+                        } else if (virge->vblank_irq < 0) {
+                            virge->vblank_irq = 0;
+                        }
+                        s3_virge_update_irqs(virge);
+                        break;
                         case 0x31:
                         virge->ma_ext = (virge->ma_ext & 0x1c) | ((val & 0x30) >> 4);
                         break;
@@ -493,6 +512,7 @@ static uint8_t s3_virge_in(uint16_t addr, void *p)
                 case 0x3c2:
                     ret = svga_in(addr, svga);
                     ret |= (virge->subsys_stat & INT_VSY) ? 0x80 : 0x00;
+                    ret |= virge->vblank_irq > 0 ? 0x80 : 0x00;
                 break;
                 //case 0x3C6: case 0x3C7: case 0x3C8: case 0x3C9:
 //                pclog("Read RAMDAC %04X  %04X:%04X\n", addr, CS, pc);
@@ -572,6 +592,7 @@ static void s3_virge_recalctimings(svga_t *svga)
             }
         }
 
+        svga->horizontal_linedbl = svga->dispend * 9 / 10 >= svga->hdisp;
 
         if ((svga->crtc[0x67] & 0xc) != 0xc) /*VGA mode*/
         {
@@ -586,19 +607,34 @@ static void s3_virge_recalctimings(svga_t *svga)
                         switch (svga->bpp)
                         {
                                 case 8: 
-                                svga->render = svga_render_8bpp_highres; 
+                                if (svga->horizontal_linedbl)
+                                    svga->render = svga_render_8bpp_lowres;
+                                else
+                                    svga->render = svga_render_8bpp_highres;
                                 break;
                                 case 15: 
-                                svga->render = svga_render_15bpp_highres; 
+                                if (svga->horizontal_linedbl)
+                                    svga->render = svga_render_15bpp_lowres;
+                                else
+                                    svga->render = svga_render_15bpp_highres;
                                 break;
                                 case 16: 
-                                svga->render = svga_render_16bpp_highres; 
+                                if (svga->horizontal_linedbl)
+                                    svga->render = svga_render_16bpp_lowres;
+                                else
+                                    svga->render = svga_render_16bpp_highres;
                                 break;
-                                case 24: 
-                                svga->render = svga_render_24bpp_highres; 
+                                case 24:
+                                if (svga->horizontal_linedbl)
+                                    svga->render = svga_render_24bpp_lowres;
+                                else
+                                    svga->render = svga_render_24bpp_highres;
                                 break;
                                 case 32: 
-                                svga->render = svga_render_32bpp_highres; 
+                                if (svga->horizontal_linedbl)
+                                    svga->render = svga_render_32bpp_lowres;
+                                else
+                                    svga->render = svga_render_32bpp_highres;
                                 break;
                         }
                 }
@@ -772,6 +808,9 @@ static void s3_virge_vblank_start(svga_t *svga)
 {
         virge_t *virge = (virge_t *)svga->p;
 
+        if (virge->vblank_irq >= 0) {
+            virge->vblank_irq = 1;
+        }
         virge->subsys_stat |= INT_VSY;
         s3_virge_update_irqs(virge);
 }
@@ -987,7 +1026,8 @@ static void fifo_thread(void *param)
 {
         virge_t *virge = (virge_t *)param;
         
-        while (1)
+        virge->fifo_thread_state = 1;
+        while (virge->fifo_thread_state > 0)
         {
                 thread_set_event(virge->fifo_not_full_event);
                 thread_wait_event(virge->wake_fifo_thread, -1);
@@ -1333,6 +1373,7 @@ static void fifo_thread(void *param)
                 virge->subsys_stat |= INT_FIFO_EMP | INT_3DF_EMP;
                 s3_virge_update_irqs(virge);
         }
+        virge->fifo_thread_state = 0;
 }
 
 static void s3_virge_queue(virge_t *virge, uint32_t addr, uint32_t val, uint32_t type)
@@ -3368,7 +3409,8 @@ static void render_thread(void *param)
 {
         virge_t *virge = (virge_t *)param;
         
-        while (1)
+        virge->render_thread_state = 1;
+        while (virge->render_thread_state > 0)
         {
                 thread_wait_event(virge->wake_render_thread, -1);
                 thread_reset_event(virge->wake_render_thread);
@@ -3385,6 +3427,7 @@ static void render_thread(void *param)
                 virge->subsys_stat |= INT_S3D_DONE;
                 s3_virge_update_irqs(virge);
         }
+        virge->render_thread_state = 0;
 }
 
 static void queue_triangle(virge_t *virge)
@@ -3412,6 +3455,8 @@ static void s3_virge_hwcursor_draw(svga_t *svga, int displine)
         int offset = svga->hwcursor_latch.x - svga->hwcursor_latch.xoff;
         uint32_t fg, bg;
         
+        offset <<= svga->horizontal_linedbl;
+
 //        pclog("HWcursor %i %i  %08x %08x\n", svga->hwcursor_latch.x, svga->hwcursor_latch.y, virge->hwcursor_col[0],virge->hwcursor_col[1]);
         switch (svga->bpp)
         {               
@@ -4057,12 +4102,26 @@ static void s3_virge_close(void *p)
 #endif
 #endif
 
-        thread_kill(virge->render_thread);
+        if (virge->render_thread_state) {
+            virge->render_thread_state = -1;
+            thread_set_event(virge->wake_render_thread);
+            while (virge->render_thread_state == -1) {
+                thread_sleep(1);
+            }
+            thread_kill(virge->render_thread);
+        }
         thread_destroy_event(virge->not_full_event);
         thread_destroy_event(virge->wake_main_thread);
         thread_destroy_event(virge->wake_render_thread);
         
-        thread_kill(virge->fifo_thread);
+        if (virge->fifo_thread_state) {
+            virge->fifo_thread_state = -1;
+            thread_set_event(virge->wake_fifo_thread);
+            while (virge->fifo_thread_state == -1) {
+                thread_sleep(1);
+            }
+            thread_kill(virge->fifo_thread);
+        }
         thread_destroy_event(virge->wake_fifo_thread);
         thread_destroy_event(virge->fifo_not_full_event);
 
index 8cef1b55a507b48f4a232bb92e670a62e9925853..5de0adc3aac1deb5431b403a03b8608702b8f1ba 100644 (file)
@@ -23,7 +23,10 @@ static svga_t *svga_pri;
 
 int svga_get_vtotal(void)
 {
-    return svga_pri->vtotal;
+    int v = svga_pri->vtotal;
+    if (svga_pri->crtc[0x17] & 4)
+        v *= 2;
+    return v;
 }
 
 void *svga_get_object(void)
@@ -316,24 +319,34 @@ void svga_recalctimings(svga_t *svga)
         svga->split = svga->crtc[0x18];
         svga->vblankstart = svga->crtc[0x15];
 
-        if (svga->crtc[7] & 1)  svga->vtotal |= 0x100;
-        if (svga->crtc[7] & 32) svga->vtotal |= 0x200;
+        if (svga->crtc[7] & 1)
+            svga->vtotal |= 0x100;
+        if (svga->crtc[7] & 0x20)
+            svga->vtotal |= 0x200;
         svga->vtotal += 2;
 
-        if (svga->crtc[7] & 2)  svga->dispend |= 0x100;
-        if (svga->crtc[7] & 64) svga->dispend |= 0x200;
+        if (svga->crtc[7] & 2)
+            svga->dispend |= 0x100;
+        if (svga->crtc[7] & 0x40)
+            svga->dispend |= 0x200;
         svga->dispend++;
 
-        if (svga->crtc[7] & 4)   svga->vsyncstart |= 0x100;
-        if (svga->crtc[7] & 128) svga->vsyncstart |= 0x200;
+        if (svga->crtc[7] & 4)
+            svga->vsyncstart |= 0x100;
+        if (svga->crtc[7] & 0x80)
+            svga->vsyncstart |= 0x200;
         svga->vsyncstart++;
 
-        if (svga->crtc[7] & 0x10) svga->split|=0x100;
-        if (svga->crtc[9] & 0x40) svga->split|=0x200;
+        if (svga->crtc[7] & 0x10)
+            svga->split|=0x100;
+        if (svga->crtc[9] & 0x40)
+            svga->split|=0x200;
         svga->split++;
         
-        if (svga->crtc[7] & 0x08) svga->vblankstart |= 0x100;
-        if (svga->crtc[9] & 0x20) svga->vblankstart |= 0x200;
+        if (svga->crtc[7] & 0x08)
+            svga->vblankstart |= 0x100;
+        if (svga->crtc[9] & 0x20)
+            svga->vblankstart |= 0x200;
         svga->vblankstart++;
         
         svga->hdisp = svga->crtc[1];
@@ -347,6 +360,8 @@ void svga_recalctimings(svga_t *svga)
         svga->clock = (svga->vidclock) ? VGACONST2 : VGACONST1;
         
         svga->lowres = svga->attrregs[0x10] & 0x40;
+
+        svga->horizontal_linedbl = 0;
         
         svga->interlace = 0;
         
@@ -354,6 +369,7 @@ void svga_recalctimings(svga_t *svga)
 
         svga->hdisp_time = svga->hdisp;
         svga->render = svga_render_blank;
+
         if (!(svga->gdcreg[6] & 1) && !(svga->attrregs[0x10] & 1)) /*Text mode*/
         {
             if (svga->seqregs[1] & 8) /*40 column*/
@@ -600,7 +616,7 @@ int svga_poll(void *p)
                 svga->hsync_divisor = !svga->hsync_divisor;
                 
                 if (svga->hsync_divisor && (svga->crtc[0x17] & 4))
-                        return 1;
+                        return eod;
 
                 svga->vc++;
                 svga->vc &= 2047;
@@ -702,8 +718,12 @@ int svga_poll(void *p)
                                     svga->render == svga_render_15bpp_lowres ||
                                     svga->render == svga_render_16bpp_lowres ||
                                     svga->render == svga_render_24bpp_lowres ||
-                                    svga->render == svga_render_32bpp_lowres)
+                                    svga->render == svga_render_32bpp_lowres) {
+                                    if (svga->horizontal_linedbl)
+                                        svga->video_res_x *= 2;
+                                    else
                                         svga->video_res_x /= 2;
+                                }
 
                                 switch (svga->gdcreg[5] & 0x60)
                                 {
@@ -1359,20 +1379,17 @@ void svga_doblit(int y1, int y2, int wx, int wy, svga_t *svga)
         {
                 xsize=wx;
                 ysize=wy+1;
-                if (xsize<64) xsize=0;
+                if (xsize<128) xsize=0;
                 if (ysize<32) ysize=0;
 
-                if (svga->vertical_linedbl)
-                        updatewindowsize(xsize,ysize*2);
-                else
-                        updatewindowsize(xsize,ysize);
+                updatewindowsize(xsize * (svga->horizontal_linedbl ? 2 : 1), ysize * (svga->vertical_linedbl ? 2 : 1));
         }
         if (vid_resize)
         {
                 xsize = wx;
                 ysize = wy + 1;
         }
-        video_blit_memtoscreen(32, 0, y1, y2, xsize, ysize);
+        video_blit_memtoscreen(32, 0, y1, y2, xsize << svga->horizontal_linedbl, ysize);
 //        pclog("svga_doblit end\n");
 }
 
index e67ab42d21cefcab6a4d14f11fda1e7f39b114b4..a4bbd73c89c8dabca1472c663a0c46d9c830a0f3 100644 (file)
@@ -140,6 +140,7 @@ typedef struct svga_t
         uint8_t ksc5601_sbyte_mask;
         
         int vertical_linedbl;
+        int horizontal_linedbl;
         
         /*Used to implement CRTC[0x17] bit 2 hsync divisor*/
         int hsync_divisor;
index 6320542ef628e7a0fb44ff726a44383f6898e708..a50abb9a3f1eea7cee3a0ddc30cebcb4cbe6d2c7 100644 (file)
@@ -375,7 +375,7 @@ void svga_render_4bpp_lowres(svga_t *svga)
                         svga->firstline_draw = svga->displine;
                 svga->lastline_draw = svga->displine;
 
-                for (x = 0; x <= svga->hdisp; x += 16)
+                for (x = 0; x <= svga->hdisp << svga->horizontal_linedbl; x += 16)
                 {
                         uint8_t edat[4];
                         uint8_t dat;
@@ -457,7 +457,7 @@ void svga_render_8bpp_lowres(svga_t *svga)
                         svga->firstline_draw = svga->displine;
                 svga->lastline_draw = svga->displine;
                                                                 
-                for (x = 0; x <= svga->hdisp; x += 8)
+                for (x = 0; x <= svga->hdisp << svga->horizontal_linedbl; x += 8)
                 {
                         uint32_t dat = *(uint32_t *)(&svga->vram[svga->ma & svga->vram_display_mask]);
                         
@@ -519,17 +519,12 @@ void svga_render_15bpp_lowres(svga_t *svga)
                         svga->firstline_draw = svga->displine;
                 svga->lastline_draw = svga->displine;
                
-                for (x = 0; x <= svga->hdisp; x += 4)
+                for (x = 0; x <= svga->hdisp << svga->horizontal_linedbl; x += 4)
                 {
-                        uint32_t dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 1)) & svga->vram_display_mask]);
+                        uint32_t dat = *(uint32_t *)(&svga->vram[(svga->ma + x) & svga->vram_display_mask]);
 
-                        p[x]     = video_15to32[dat & 0xffff];
-                        p[x + 1] = video_15to32[dat >> 16];
-
-                        dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 1) + 4) & svga->vram_display_mask]);
-
-                        p[x]     = video_15to32[dat & 0xffff];
-                        p[x + 1] = video_15to32[dat >> 16];
+                        p[x]     = p[x + 1] = video_15to32[dat & 0xffff];
+                        p[x + 2] = p[x + 3] = video_15to32[dat >> 16];
                 }
                 svga->ma += x << 1; 
                 svga->ma &= svga->vram_display_mask;
@@ -583,17 +578,12 @@ void svga_render_16bpp_lowres(svga_t *svga)
                         svga->firstline_draw = svga->displine;
                 svga->lastline_draw = svga->displine;
                
-                for (x = 0; x <= svga->hdisp; x += 4)
+                for (x = 0; x <= svga->hdisp << svga->horizontal_linedbl; x += 4)
                 {
-                        uint32_t dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 1)) & svga->vram_display_mask]);
-
-                        p[x]     = video_16to32[dat & 0xffff];
-                        p[x + 1] = video_16to32[dat >> 16];
-
-                        dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 1) + 4) & svga->vram_display_mask]);
+                        uint32_t dat = *(uint32_t *)(&svga->vram[(svga->ma + x) & svga->vram_display_mask]);
 
-                        p[x]     = video_16to32[dat & 0xffff];
-                        p[x + 1] = video_16to32[dat >> 16];
+                        p[x]     = p[x + 1] = video_16to32[dat & 0xffff];
+                        p[x + 2] = p[x + 3] = video_16to32[dat >> 16];
                 }
                 svga->ma += x << 1; 
                 svga->ma &= svga->vram_display_mask;
@@ -649,16 +639,16 @@ void svga_render_24bpp_lowres(svga_t *svga)
                 offset = (8 - (svga->scrollcache & 6)) + 24;
 
                 if (svga->swaprb) {
-                    for (x = 0; x <= svga->hdisp; x++) {
+                    for (x = 0; x <= svga->hdisp << svga->horizontal_linedbl; x++) {
                         fg = svga->vram[svga->ma + 2] | (svga->vram[svga->ma + 1] << 8) | (svga->vram[svga->ma + 0] << 16);
                         svga->ma += 3;
                         svga->ma &= svga->vram_display_mask;
                         ((uint32_t *)buffer32->line[svga->displine])[(x << 1) + offset] = ((uint32_t *)buffer32->line[svga->displine])[(x << 1) + 1 + offset] = fg;
                     }
                 } else {
-                    for (x = 0; x <= svga->hdisp; x++)
+                    for (x = 0; x <= svga->hdisp << svga->horizontal_linedbl; x++)
                     {
-                        fg = svga->vram[svga->ma] | (svga->vram[svga->ma + 1] << 8) | (svga->vram[svga->ma + 2] << 16);
+                        fg = svga->vram[svga->ma] | (svga->vram[(svga->ma + 1) & svga->vram_display_mask] << 8) | (svga->vram[(svga->ma + 2) & svga->vram_display_mask] << 16);
                         svga->ma += 3;
                         svga->ma &= svga->vram_display_mask;
                         ((uint32_t *)buffer32->line[svga->displine])[(x << 1) + offset] = ((uint32_t *)buffer32->line[svga->displine])[(x << 1) + 1 + offset] = fg;
@@ -683,27 +673,36 @@ void svga_render_24bpp_highres(svga_t *svga)
                     uint32_t dat;
                     for (x = 0; x <= svga->hdisp; x++)
                     {
-                        dat = svga->vram[svga->ma + 2] | (svga->vram[svga->ma + 1] << 8) | (svga->vram[svga->ma + 0] << 16);
+                        dat = svga->vram[(svga->ma + 2) &svga->vram_display_mask] | (svga->vram[(svga->ma + 1) & svga->vram_display_mask] << 8) | (svga->vram[svga->ma + 0] << 16);
                         p[x] = dat;
                         svga->ma += 3;
                         svga->ma &= svga->vram_display_mask;
                     }
                 } else {
-                    for (x = 0; x <= svga->hdisp; x += 4)
-                    {
-                        uint32_t dat = *(uint32_t *)(&svga->vram[svga->ma & svga->vram_display_mask]);
-                        p[x] = dat & 0xffffff;
+                    if ((svga->ma & svga->vram_display_mask) + svga->hdisp * 3 + 3 > svga->vram_display_mask) {
+                        for (x = 0; x <= svga->hdisp; x++) {
+                            uint32_t dat = (svga->vram[(svga->ma + 0) & svga->vram_display_mask] << 0) |
+                                (svga->vram[(svga->ma + 1) & svga->vram_display_mask] << 8) |
+                                (svga->vram[(svga->ma + 2) & svga->vram_display_mask] << 16);
+                            p[x] = dat;
+                            svga->ma += 3;
+                        }
+                    } else {
+                        for (x = 0; x <= svga->hdisp; x += 4) {
+                            uint32_t dat = *(uint32_t *)(&svga->vram[svga->ma & svga->vram_display_mask]);
+                            p[x] = dat & 0xffffff;
 
-                        dat = *(uint32_t *)(&svga->vram[(svga->ma + 3) & svga->vram_display_mask]);
-                        p[x + 1] = dat & 0xffffff;
+                            dat = *(uint32_t *)(&svga->vram[(svga->ma + 3) & svga->vram_display_mask]);
+                            p[x + 1] = dat & 0xffffff;
 
-                        dat = *(uint32_t *)(&svga->vram[(svga->ma + 6) & svga->vram_display_mask]);
-                        p[x + 2] = dat & 0xffffff;
+                            dat = *(uint32_t *)(&svga->vram[(svga->ma + 6) & svga->vram_display_mask]);
+                            p[x + 2] = dat & 0xffffff;
 
-                        dat = *(uint32_t *)(&svga->vram[(svga->ma + 9) & svga->vram_display_mask]);
-                        p[x + 3] = dat & 0xffffff;
+                            dat = *(uint32_t *)(&svga->vram[(svga->ma + 9) & svga->vram_display_mask]);
+                            p[x + 3] = dat & 0xffffff;
 
-                        svga->ma += 12;
+                            svga->ma += 12;
+                        }
                     }
                 }
                 svga->ma &= svga->vram_display_mask;
@@ -723,7 +722,7 @@ void svga_render_32bpp_lowres(svga_t *svga)
 
                 offset = (8 - (svga->scrollcache & 6)) + 24;
 
-                for (x = 0; x <= svga->hdisp; x++)
+                for (x = 0; x <= svga->hdisp << svga->horizontal_linedbl; x++)
                 {
                         fg = svga->vram[svga->ma] | (svga->vram[svga->ma + 1] << 8) | (svga->vram[svga->ma + 2] << 16);
                         svga->ma += 4;