qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH 0/3] vga: first round of hardware emulation fixes
@ 2015-08-08 13:11 Paolo Bonzini
  2015-08-08 13:11 ` [Qemu-devel] [PATCH 1/3] vga: mask addresses in non-VESA modes to 256k Paolo Bonzini
                   ` (2 more replies)
  0 siblings, 3 replies; 4+ messages in thread
From: Paolo Bonzini @ 2015-08-08 13:11 UTC (permalink / raw)
  To: qemu-devel

During the last Christmas holidays I spent some time fixing VGA emulation
with old games and old software in general.  In particular I fixed
Commander Keen 4, Jazz Jackrabbit and GW Basic.  I never had the time to
post the patches, however.  Here is a start, it's enough to fix GW Basic
SCREEN 2 and to make Keen 4 playable while a bit jerky.

Paolo

Paolo Bonzini (3):
  vga: mask addresses in non-VESA modes to 256k
  vga: remove unused macros
  vga: fix CGA 640x200 mode

 hw/display/vga-helpers.h | 52 ++++++++++++++++++++++++++++++------------------
 hw/display/vga.c         | 24 ++++++----------------
 2 files changed, 39 insertions(+), 37 deletions(-)

-- 
2.4.3

^ permalink raw reply	[flat|nested] 4+ messages in thread

* [Qemu-devel] [PATCH 1/3] vga: mask addresses in non-VESA modes to 256k
  2015-08-08 13:11 [Qemu-devel] [PATCH 0/3] vga: first round of hardware emulation fixes Paolo Bonzini
@ 2015-08-08 13:11 ` Paolo Bonzini
  2015-08-08 13:11 ` [Qemu-devel] [PATCH 2/3] vga: remove unused macros Paolo Bonzini
  2015-08-08 13:11 ` [Qemu-devel] [PATCH 3/3] vga: fix CGA 640x200 mode Paolo Bonzini
  2 siblings, 0 replies; 4+ messages in thread
From: Paolo Bonzini @ 2015-08-08 13:11 UTC (permalink / raw)
  To: qemu-devel

This allows setting the start address to a high value, and reading the
bottom of the screen from the beginning of VRAM.  Commander Keen 4
("Goodbye, Galaxy!") relies on this behavior.

Signed-off-by: Paolo Bonzini <bonzini@gnu.org>
---
 hw/display/vga-helpers.h | 52 ++++++++++++++++++++++++++++++------------------
 hw/display/vga.c         |  7 +++++--
 2 files changed, 38 insertions(+), 21 deletions(-)

diff --git a/hw/display/vga-helpers.h b/hw/display/vga-helpers.h
index 94f6de2..ae61890 100644
--- a/hw/display/vga-helpers.h
+++ b/hw/display/vga-helpers.h
@@ -99,7 +99,7 @@ static void vga_draw_glyph9(uint8_t *d, int linesize,
  * 4 color mode
  */
 static void vga_draw_line2(VGACommonState *s1, uint8_t *d,
-                           const uint8_t *s, int width)
+                           unsigned int addr, int width)
 {
     uint32_t plane_mask, *palette, data, v;
     int x;
@@ -108,6 +108,7 @@ static void vga_draw_line2(VGACommonState *s1, uint8_t *d,
     plane_mask = mask16[s1->ar[VGA_ATC_PLANE_ENABLE] & 0xf];
     width >>= 3;
     for(x = 0; x < width; x++) {
+        const uint8_t *s = s1->vram_ptr + (addr & (VGA_VRAM_SIZE - 1));
         data = ((uint32_t *)s)[0];
         data &= plane_mask;
         v = expand2[GET_PLANE(data, 0)];
@@ -124,7 +125,7 @@ static void vga_draw_line2(VGACommonState *s1, uint8_t *d,
         ((uint32_t *)d)[6] = palette[(v >> 4) & 0xf];
         ((uint32_t *)d)[7] = palette[(v >> 0) & 0xf];
         d += 32;
-        s += 4;
+        addr += 4;
     }
 }
 
@@ -135,7 +136,7 @@ static void vga_draw_line2(VGACommonState *s1, uint8_t *d,
  * 4 color mode, dup2 horizontal
  */
 static void vga_draw_line2d2(VGACommonState *s1, uint8_t *d,
-                             const uint8_t *s, int width)
+                             unsigned int addr, int width)
 {
     uint32_t plane_mask, *palette, data, v;
     int x;
@@ -144,6 +145,7 @@ static void vga_draw_line2d2(VGACommonState *s1, uint8_t *d,
     plane_mask = mask16[s1->ar[VGA_ATC_PLANE_ENABLE] & 0xf];
     width >>= 3;
     for(x = 0; x < width; x++) {
+        const uint8_t *s = s1->vram_ptr + (addr & (VGA_VRAM_SIZE - 1));
         data = ((uint32_t *)s)[0];
         data &= plane_mask;
         v = expand2[GET_PLANE(data, 0)];
@@ -160,7 +162,7 @@ static void vga_draw_line2d2(VGACommonState *s1, uint8_t *d,
         PUT_PIXEL2(d, 6, palette[(v >> 4) & 0xf]);
         PUT_PIXEL2(d, 7, palette[(v >> 0) & 0xf]);
         d += 64;
-        s += 4;
+        addr += 4;
     }
 }
 
@@ -168,7 +170,7 @@ static void vga_draw_line2d2(VGACommonState *s1, uint8_t *d,
  * 16 color mode
  */
 static void vga_draw_line4(VGACommonState *s1, uint8_t *d,
-                           const uint8_t *s, int width)
+                           unsigned int addr, int width)
 {
     uint32_t plane_mask, data, v, *palette;
     int x;
@@ -177,6 +179,7 @@ static void vga_draw_line4(VGACommonState *s1, uint8_t *d,
     plane_mask = mask16[s1->ar[VGA_ATC_PLANE_ENABLE] & 0xf];
     width >>= 3;
     for(x = 0; x < width; x++) {
+        const uint8_t *s = s1->vram_ptr + (addr & (VGA_VRAM_SIZE - 1));
         data = ((uint32_t *)s)[0];
         data &= plane_mask;
         v = expand4[GET_PLANE(data, 0)];
@@ -192,7 +195,7 @@ static void vga_draw_line4(VGACommonState *s1, uint8_t *d,
         ((uint32_t *)d)[6] = palette[(v >> 4) & 0xf];
         ((uint32_t *)d)[7] = palette[(v >> 0) & 0xf];
         d += 32;
-        s += 4;
+        addr += 4;
     }
 }
 
@@ -200,7 +203,7 @@ static void vga_draw_line4(VGACommonState *s1, uint8_t *d,
  * 16 color mode, dup2 horizontal
  */
 static void vga_draw_line4d2(VGACommonState *s1, uint8_t *d,
-                             const uint8_t *s, int width)
+                             unsigned int addr, int width)
 {
     uint32_t plane_mask, data, v, *palette;
     int x;
@@ -209,6 +212,7 @@ static void vga_draw_line4d2(VGACommonState *s1, uint8_t *d,
     plane_mask = mask16[s1->ar[VGA_ATC_PLANE_ENABLE] & 0xf];
     width >>= 3;
     for(x = 0; x < width; x++) {
+        const uint8_t *s = s1->vram_ptr + (addr & (VGA_VRAM_SIZE - 1));
         data = ((uint32_t *)s)[0];
         data &= plane_mask;
         v = expand4[GET_PLANE(data, 0)];
@@ -224,7 +228,7 @@ static void vga_draw_line4d2(VGACommonState *s1, uint8_t *d,
         PUT_PIXEL2(d, 6, palette[(v >> 4) & 0xf]);
         PUT_PIXEL2(d, 7, palette[(v >> 0) & 0xf]);
         d += 64;
-        s += 4;
+        addr += 4;
     }
 }
 
@@ -234,7 +238,7 @@ static void vga_draw_line4d2(VGACommonState *s1, uint8_t *d,
  * XXX: add plane_mask support (never used in standard VGA modes)
  */
 static void vga_draw_line8d2(VGACommonState *s1, uint8_t *d,
-                             const uint8_t *s, int width)
+                             unsigned int addr, int width)
 {
     uint32_t *palette;
     int x;
@@ -242,12 +246,13 @@ static void vga_draw_line8d2(VGACommonState *s1, uint8_t *d,
     palette = s1->last_palette;
     width >>= 3;
     for(x = 0; x < width; x++) {
+        const uint8_t *s = s1->vram_ptr + (addr & (VGA_VRAM_SIZE - 1));
         PUT_PIXEL2(d, 0, palette[s[0]]);
         PUT_PIXEL2(d, 1, palette[s[1]]);
         PUT_PIXEL2(d, 2, palette[s[2]]);
         PUT_PIXEL2(d, 3, palette[s[3]]);
         d += 32;
-        s += 4;
+        addr += 4;
     }
 }
 
@@ -257,8 +262,9 @@ static void vga_draw_line8d2(VGACommonState *s1, uint8_t *d,
  * XXX: add plane_mask support (never used in standard VGA modes)
  */
 static void vga_draw_line8(VGACommonState *s1, uint8_t *d,
-                           const uint8_t *s, int width)
+                           unsigned int addr, int width)
 {
+    const uint8_t *s = s1->vram_ptr + addr;
     uint32_t *palette;
     int x;
 
@@ -282,8 +288,9 @@ static void vga_draw_line8(VGACommonState *s1, uint8_t *d,
  * 15 bit color
  */
 static void vga_draw_line15_le(VGACommonState *s1, uint8_t *d,
-                               const uint8_t *s, int width)
+                               unsigned int addr, int width)
 {
+    const uint8_t *s = s1->vram_ptr + addr;
     int w;
     uint32_t v, r, g, b;
 
@@ -300,8 +307,9 @@ static void vga_draw_line15_le(VGACommonState *s1, uint8_t *d,
 }
 
 static void vga_draw_line15_be(VGACommonState *s1, uint8_t *d,
-                               const uint8_t *s, int width)
+                               unsigned int addr, int width)
 {
+    const uint8_t *s = s1->vram_ptr + addr;
     int w;
     uint32_t v, r, g, b;
 
@@ -321,8 +329,9 @@ static void vga_draw_line15_be(VGACommonState *s1, uint8_t *d,
  * 16 bit color
  */
 static void vga_draw_line16_le(VGACommonState *s1, uint8_t *d,
-                               const uint8_t *s, int width)
+                               unsigned int addr, int width)
 {
+    const uint8_t *s = s1->vram_ptr + addr;
     int w;
     uint32_t v, r, g, b;
 
@@ -339,8 +348,9 @@ static void vga_draw_line16_le(VGACommonState *s1, uint8_t *d,
 }
 
 static void vga_draw_line16_be(VGACommonState *s1, uint8_t *d,
-                               const uint8_t *s, int width)
+                               unsigned int addr, int width)
 {
+    const uint8_t *s = s1->vram_ptr + addr;
     int w;
     uint32_t v, r, g, b;
 
@@ -360,8 +370,9 @@ static void vga_draw_line16_be(VGACommonState *s1, uint8_t *d,
  * 24 bit color
  */
 static void vga_draw_line24_le(VGACommonState *s1, uint8_t *d,
-                               const uint8_t *s, int width)
+                               unsigned int addr, int width)
 {
+    const uint8_t *s = s1->vram_ptr + addr;
     int w;
     uint32_t r, g, b;
 
@@ -377,8 +388,9 @@ static void vga_draw_line24_le(VGACommonState *s1, uint8_t *d,
 }
 
 static void vga_draw_line24_be(VGACommonState *s1, uint8_t *d,
-                               const uint8_t *s, int width)
+                               unsigned int addr, int width)
 {
+    const uint8_t *s = s1->vram_ptr + addr;
     int w;
     uint32_t r, g, b;
 
@@ -397,8 +409,9 @@ static void vga_draw_line24_be(VGACommonState *s1, uint8_t *d,
  * 32 bit color
  */
 static void vga_draw_line32_le(VGACommonState *s1, uint8_t *d,
-                               const uint8_t *s, int width)
+                               unsigned int addr, int width)
 {
+    const uint8_t *s = s1->vram_ptr + addr;
 #ifndef HOST_WORDS_BIGENDIAN
     memcpy(d, s, width * 4);
 #else
@@ -418,8 +431,9 @@ static void vga_draw_line32_le(VGACommonState *s1, uint8_t *d,
 }
 
 static void vga_draw_line32_be(VGACommonState *s1, uint8_t *d,
-                               const uint8_t *s, int width)
+                               unsigned int addr, int width)
 {
+    const uint8_t *s = s1->vram_ptr + addr;
 #ifdef HOST_WORDS_BIGENDIAN
     memcpy(d, s, width * 4);
 #else
diff --git a/hw/display/vga.c b/hw/display/vga.c
index b35d523..5965ab2 100644
--- a/hw/display/vga.c
+++ b/hw/display/vga.c
@@ -41,6 +41,9 @@
 /* 16 state changes per vertical frame @60 Hz */
 #define VGA_TEXT_CURSOR_PERIOD_MS       (1000 * 2 * 16 / 60)
 
+/* Address mask for non-VESA modes.  */
+#define VGA_VRAM_SIZE                   262144
+
 /*
  * Video Graphics Array (VGA)
  *
@@ -978,7 +981,7 @@ void vga_mem_writeb(VGACommonState *s, hwaddr addr, uint32_t val)
 }
 
 typedef void vga_draw_line_func(VGACommonState *s1, uint8_t *d,
-                                const uint8_t *s, int width);
+                                unsigned int s, int width);
 
 #include "vga-helpers.h"
 
@@ -1629,7 +1632,7 @@ static void vga_draw_graphic(VGACommonState *s, int full_update)
             if (page1 > page_max)
                 page_max = page1;
             if (!(is_buffer_shared(surface))) {
-                vga_draw_line(s, d, s->vram_ptr + addr, width);
+                vga_draw_line(s, d, addr, width);
                 if (s->cursor_draw_line)
                     s->cursor_draw_line(s, d, y);
             }
-- 
2.4.3

^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [Qemu-devel] [PATCH 2/3] vga: remove unused macros
  2015-08-08 13:11 [Qemu-devel] [PATCH 0/3] vga: first round of hardware emulation fixes Paolo Bonzini
  2015-08-08 13:11 ` [Qemu-devel] [PATCH 1/3] vga: mask addresses in non-VESA modes to 256k Paolo Bonzini
@ 2015-08-08 13:11 ` Paolo Bonzini
  2015-08-08 13:11 ` [Qemu-devel] [PATCH 3/3] vga: fix CGA 640x200 mode Paolo Bonzini
  2 siblings, 0 replies; 4+ messages in thread
From: Paolo Bonzini @ 2015-08-08 13:11 UTC (permalink / raw)
  To: qemu-devel

Signed-off-by: Paolo Bonzini <bonzini@gnu.org>
---
 hw/display/vga.c | 14 --------------
 1 file changed, 14 deletions(-)

diff --git a/hw/display/vga.c b/hw/display/vga.c
index 5965ab2..19dcb6b 100644
--- a/hw/display/vga.c
+++ b/hw/display/vga.c
@@ -101,12 +101,6 @@ const uint8_t gr_mask[16] = {
 #endif
 
 #ifdef HOST_WORDS_BIGENDIAN
-#define BIG 1
-#else
-#define BIG 0
-#endif
-
-#ifdef HOST_WORDS_BIGENDIAN
 #define GET_PLANE(data, p) (((data) >> (24 - (p) * 8)) & 0xff)
 #else
 #define GET_PLANE(data, p) (((data) >> ((p) * 8)) & 0xff)
@@ -131,14 +125,6 @@ static const uint32_t mask16[16] = {
     PAT(0xffffffff),
 };
 
-#undef PAT
-
-#ifdef HOST_WORDS_BIGENDIAN
-#define PAT(x) (x)
-#else
-#define PAT(x) cbswap_32(x)
-#endif
-
 static uint32_t expand4[256];
 static uint16_t expand2[256];
 static uint8_t expand4to8[16];
-- 
2.4.3

^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [Qemu-devel] [PATCH 3/3] vga: fix CGA 640x200 mode
  2015-08-08 13:11 [Qemu-devel] [PATCH 0/3] vga: first round of hardware emulation fixes Paolo Bonzini
  2015-08-08 13:11 ` [Qemu-devel] [PATCH 1/3] vga: mask addresses in non-VESA modes to 256k Paolo Bonzini
  2015-08-08 13:11 ` [Qemu-devel] [PATCH 2/3] vga: remove unused macros Paolo Bonzini
@ 2015-08-08 13:11 ` Paolo Bonzini
  2 siblings, 0 replies; 4+ messages in thread
From: Paolo Bonzini @ 2015-08-08 13:11 UTC (permalink / raw)
  To: qemu-devel

SeaBIOS programs the CGA 2-color 640x200 mode with 0xC1 in the maximum
scan line register.  Ordinarily, this would mean 100 vertical lines,
but the CGA modes ignore bits 4:0 (DOSBox's BIOS also uses 0xC1).
Unfortunately, the test used to catch CGA modes worked for 4-color
320x200 graphics, but not for the 2-color 640x200 mode.

Signed-off-by: Paolo Bonzini <bonzini@gnu.org>
---
 hw/display/vga.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/hw/display/vga.c b/hw/display/vga.c
index 19dcb6b..7d4e1b0 100644
--- a/hw/display/vga.c
+++ b/hw/display/vga.c
@@ -1442,12 +1442,11 @@ static void vga_draw_graphic(VGACommonState *s, int full_update)
 
     shift_control = (s->gr[VGA_GFX_MODE] >> 5) & 3;
     double_scan = (s->cr[VGA_CRTC_MAX_SCAN] >> 7);
-    if (shift_control != 1) {
+    if (s->cr[VGA_CRTC_MODE] & 1) {
         multi_scan = (((s->cr[VGA_CRTC_MAX_SCAN] & 0x1f) + 1) << double_scan)
             - 1;
     } else {
         /* in CGA modes, multi_scan is ignored */
-        /* XXX: is it correct ? */
         multi_scan = double_scan;
     }
     multi_run = multi_scan;
-- 
2.4.3

^ permalink raw reply related	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2015-08-08 13:11 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2015-08-08 13:11 [Qemu-devel] [PATCH 0/3] vga: first round of hardware emulation fixes Paolo Bonzini
2015-08-08 13:11 ` [Qemu-devel] [PATCH 1/3] vga: mask addresses in non-VESA modes to 256k Paolo Bonzini
2015-08-08 13:11 ` [Qemu-devel] [PATCH 2/3] vga: remove unused macros Paolo Bonzini
2015-08-08 13:11 ` [Qemu-devel] [PATCH 3/3] vga: fix CGA 640x200 mode Paolo Bonzini

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).