qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [PATCH 1/1] vga: honor blink attribute in text modes


From: Michael Slade
Subject: [Qemu-devel] [PATCH 1/1] vga: honor blink attribute in text modes
Date: Sun, 26 Aug 2018 18:59:56 +1000

Signed-off-by: Michael Slade <address@hidden>
---
 hw/display/vga.c     | 50 +++++++++++++++++++++++++++++++++-----------
 hw/display/vga_int.h |  2 ++
 2 files changed, 40 insertions(+), 12 deletions(-)

diff --git a/hw/display/vga.c b/hw/display/vga.c
index 72181330b8..03d9181d58 100644
--- a/hw/display/vga.c
+++ b/hw/display/vga.c
@@ -36,8 +36,10 @@
 //#define DEBUG_VGA_MEM
 //#define DEBUG_VGA_REG
 
-/* 16 state changes per vertical frame @60 Hz */
+/* state change per 16 frames @60 Hz */
 #define VGA_TEXT_CURSOR_PERIOD_MS       (1000 * 2 * 16 / 60)
+/* state change per 32 frames @60 Hz */
+#define VGA_TEXT_BLINK_PERIOD_MS        (1000 * 2 * 32 / 60)
 
 /*
  * Video Graphics Array (VGA)
@@ -1165,6 +1167,7 @@ static void vga_get_text_resolution(VGACommonState *s, 
int *pwidth, int *pheight
     *pcheight = cheight;
 }
 
+
 /*
  * Text mode update
  * Missing:
@@ -1185,6 +1188,8 @@ static void vga_draw_text(VGACommonState *s, int 
full_update)
     uint32_t *palette;
     uint32_t *ch_attr_ptr;
     int64_t now = qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL);
+    bool cursor_blink = 0;
+    bool attr_blink = 0;
 
     /* compute font data address (in plane 2) */
     v = sr(s, VGA_SEQ_CHARACTER_MAP);
@@ -1266,6 +1271,13 @@ static void vga_draw_text(VGACommonState *s, int 
full_update)
     if (now >= s->cursor_blink_time) {
         s->cursor_blink_time = now + VGA_TEXT_CURSOR_PERIOD_MS / 2;
         s->cursor_visible_phase = !s->cursor_visible_phase;
+        cursor_blink = 1;
+    }
+    bool blink_active = s->ar[VGA_ATC_MODE] & 0x08;
+    if (now >= s->attr_blink_time) {
+        s->attr_blink_time = now + VGA_TEXT_BLINK_PERIOD_MS / 2;
+        s->attr_blink_visible_phase = !s->attr_blink_visible_phase;
+        attr_blink = blink_active;
     }
 
     dest = surface_data(surface);
@@ -1283,23 +1295,36 @@ static void vga_draw_text(VGACommonState *s, int 
full_update)
                 break;
             }
             ch_attr = *(uint16_t *)src;
-            if (full_update || ch_attr != *ch_attr_ptr || src == cursor_ptr) {
+#ifdef HOST_WORDS_BIGENDIAN
+            ch = ch_attr >> 8;
+            cattr = ch_attr & 0xff;
+#else
+            ch = ch_attr & 0xff;
+            cattr = ch_attr >> 8;
+#endif
+
+            if (
+                full_update ||
+                    ch_attr != *ch_attr_ptr ||
+                    (src == cursor_ptr && cursor_blink) ||
+                    (attr_blink && (cattr & 0x80))
+                ) {
                 if (cx < cx_min)
                     cx_min = cx;
                 if (cx > cx_max)
                     cx_max = cx;
                 *ch_attr_ptr = ch_attr;
-#ifdef HOST_WORDS_BIGENDIAN
-                ch = ch_attr >> 8;
-                cattr = ch_attr & 0xff;
-#else
-                ch = ch_attr & 0xff;
-                cattr = ch_attr >> 8;
-#endif
                 font_ptr = font_base[(cattr >> 3) & 1];
                 font_ptr += 32 * 4 * ch;
-                bgcol = palette[cattr >> 4];
-                fgcol = palette[cattr & 0x0f];
+                if (blink_active) {
+                    bgcol = palette[(cattr >> 4) & 7];
+                    fgcol = (!(cattr & 0x80) || s->attr_blink_visible_phase) ?
+                        palette[cattr & 0x0f] :
+                        bgcol;
+                } else {
+                    bgcol = palette[cattr >> 4];
+                    fgcol = palette[cattr & 0x0f];
+                }
                 if (cw == 16) {
                     vga_draw_glyph16(d1, linesize,
                                      font_ptr, cheight, fgcol, bgcol);
@@ -1756,7 +1781,8 @@ static void vga_update_display(void *opaque)
         }
         if (graphic_mode != s->graphic_mode) {
             s->graphic_mode = graphic_mode;
-            s->cursor_blink_time = qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL);
+            s->cursor_blink_time = s->attr_blink_time =
+                qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL);
             full_update = 1;
         }
         switch(graphic_mode) {
diff --git a/hw/display/vga_int.h b/hw/display/vga_int.h
index fe23b81442..775b3e7aa9 100644
--- a/hw/display/vga_int.h
+++ b/hw/display/vga_int.h
@@ -157,7 +157,9 @@ typedef struct VGACommonState {
     bool force_shadow;
     uint8_t cursor_start, cursor_end;
     bool cursor_visible_phase;
+    bool attr_blink_visible_phase;
     int64_t cursor_blink_time;
+    int64_t attr_blink_time;
     uint32_t cursor_offset;
     const GraphicHwOps *hw_ops;
     bool full_update_text;
-- 
2.17.1




reply via email to

[Prev in Thread] Current Thread [Next in Thread]