Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Image corruption when moving window in Windows 3.11 with CL-GD5446 and SVGA driver #364

Open
Vort opened this issue Oct 19, 2024 · 0 comments

Comments

@Vort
Copy link
Contributor

Vort commented Oct 19, 2024

During window movement in Windows 3.11 with CL-GD5446 card and default SVGA driver in 800x600x8 resolution, image corruption appear sometimes.

I noticed two scenarios when it happens:

  1. Movement 1 pixel up;
  2. Movement 4 pixels right.

Problem 1 is related to mode 1 writes in SVGA mode.
Problem 2 is related to Chain-4 toggling.

Here are (hack-)fixes for them:

diff --git a/bochs/iodev/display/svga_cirrus.cc b/bochs/iodev/display/svga_cirrus.cc
index 2644abaf9..3afa386f1 100644
--- a/bochs/iodev/display/svga_cirrus.cc
+++ b/bochs/iodev/display/svga_cirrus.cc
@@ -629,6 +629,25 @@ Bit8u bx_svga_cirrus_c::mem_read(bx_phy_address addr)
         offset <<= 3;
       }
       offset &= BX_CIRRUS_THIS memsize_mask;
+
+      if (BX_CIRRUS_THIS s.sequencer.chain_four) {
+        BX_CIRRUS_THIS s.graphics_ctrl.latch[0] = *(BX_CIRRUS_THIS s.memory + offset);
+        BX_CIRRUS_THIS s.graphics_ctrl.latch[1] = *(BX_CIRRUS_THIS s.memory + offset + 1);
+        BX_CIRRUS_THIS s.graphics_ctrl.latch[2] = *(BX_CIRRUS_THIS s.memory + offset + 2);
+        BX_CIRRUS_THIS s.graphics_ctrl.latch[3] = *(BX_CIRRUS_THIS s.memory + offset + 3);
+        if (BX_CIRRUS_THIS control.reg[0x0b] & 0x08) {
+          BX_CIRRUS_THIS ext_latch[0] = *(BX_CIRRUS_THIS s.memory + offset + 4);
+          BX_CIRRUS_THIS ext_latch[1] = *(BX_CIRRUS_THIS s.memory + offset + 5);
+          BX_CIRRUS_THIS ext_latch[2] = *(BX_CIRRUS_THIS s.memory + offset + 6);
+          BX_CIRRUS_THIS ext_latch[3] = *(BX_CIRRUS_THIS s.memory + offset + 7);
+        }
+      } else {
+        BX_CIRRUS_THIS s.graphics_ctrl.latch[0] = *(BX_CIRRUS_THIS s.memory + (offset << 2));
+        BX_CIRRUS_THIS s.graphics_ctrl.latch[1] = *(BX_CIRRUS_THIS s.memory + (offset << 2) + 1);
+        BX_CIRRUS_THIS s.graphics_ctrl.latch[2] = *(BX_CIRRUS_THIS s.memory + (offset << 2) + 2);
+        BX_CIRRUS_THIS s.graphics_ctrl.latch[3] = *(BX_CIRRUS_THIS s.memory + (offset << 2) + 3);
+      }
+
       return *(BX_CIRRUS_THIS s.memory + offset);
     }
     else {
@@ -866,7 +885,34 @@ void bx_svga_cirrus_c::mem_write(bx_phy_address addr, Bit8u value)
       offset &= BX_CIRRUS_THIS memsize_mask;
       mode = BX_CIRRUS_THIS control.reg[0x05] & 0x07;
       if ((mode < 4) || (mode > 5) || ((BX_CIRRUS_THIS control.reg[0x0b] & 0x4) == 0)) {
-        *(BX_CIRRUS_THIS s.memory + offset) = value;
+        if (mode == 1) {
+          if (BX_CIRRUS_THIS s.sequencer.chain_four) {
+            unsigned i;
+            for (i = 0; i < 4; i++) {
+              *(BX_CIRRUS_THIS s.memory + offset + i) = BX_CIRRUS_THIS s.graphics_ctrl.latch[i];
+            }
+            if ((BX_CIRRUS_THIS control.reg[0x0b] & 0x0c) == 0x0c) {
+              for (i = 0; i < 4; i++) {
+                *(BX_CIRRUS_THIS s.memory + offset + i + 4) = BX_CIRRUS_THIS ext_latch[i];
+              }
+            }
+          }
+          else {
+            Bit8u sequ_map_mask = BX_CIRRUS_THIS s.sequencer.map_mask & 0x0f;
+            if (sequ_map_mask & 0x0f) {
+              if (sequ_map_mask & 0x01)
+                BX_CIRRUS_THIS s.memory[offset << 2] = BX_CIRRUS_THIS s.graphics_ctrl.latch[0];
+              if (sequ_map_mask & 0x02)
+                BX_CIRRUS_THIS s.memory[(offset << 2) + 1] = BX_CIRRUS_THIS s.graphics_ctrl.latch[1];
+              if (sequ_map_mask & 0x04)
+                BX_CIRRUS_THIS s.memory[(offset << 2) + 2] = BX_CIRRUS_THIS s.graphics_ctrl.latch[2];
+              if (sequ_map_mask & 0x08)
+                BX_CIRRUS_THIS s.memory[(offset << 2) + 3] = BX_CIRRUS_THIS s.graphics_ctrl.latch[3];
+            }
+          }
+        } else {
+          *(BX_CIRRUS_THIS s.memory + offset) = value;
+        }
       } else {
         if ((BX_CIRRUS_THIS control.reg[0x0b] & 0x14) != 0x14) {
           mem_write_mode4and5_8bpp(mode, offset, value); 

Result with these changes applied is not perfect - some movements still produce corruptions: either because my implementation have bugs, or because there are more unimplemented things left.

Screenshot for problem 1 (small window with WinMode icon was moved):
image
Screenshot for problem 2 (same window):
image

Version: 60491a6.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant