[SeaBIOS] [PATCH] vgabios: Simplify scroll logic

Kevin O'Connor kevin at koconnor.net
Thu Jul 21 17:01:10 CEST 2016


Introduce a new function vgafb_scroll() to scroll a window on the
screen and update vgabios.c to use only that function for scrolling.
This makes the low-level vgafb_move_chars() and vgafb_clear_chars()
local to vgafb.c, and it simplifies the callers.

Signed-off-by: Kevin O'Connor <kevin at koconnor.net>
---
 vgasrc/vgabios.c | 57 ++++++++++++---------------------------------
 vgasrc/vgabios.h |  6 ++---
 vgasrc/vgafb.c   | 70 ++++++++++++++++++++++++++++++++++++++------------------
 3 files changed, 64 insertions(+), 69 deletions(-)

diff --git a/vgasrc/vgabios.c b/vgasrc/vgabios.c
index cfb6ba2..2c8cc79 100644
--- a/vgasrc/vgabios.c
+++ b/vgasrc/vgabios.c
@@ -198,15 +198,10 @@ write_teletype(struct cursorpos *pcp, struct carattr ca)
     if (pcp->y > nbrows) {
         pcp->y--;
 
-        struct cursorpos dest = {0, 0, pcp->page};
-        struct cursorpos src = {0, 1, pcp->page};
-        struct cursorpos size = {GET_BDA(video_cols), nbrows};
-        vgafb_move_chars(dest, src, size);
-
-        struct cursorpos clr = {0, nbrows, pcp->page};
+        struct cursorpos win = {0, 0, pcp->page};
+        struct cursorpos winsize = {GET_BDA(video_cols), nbrows+1};
         struct carattr attr = {' ', 0, 0};
-        struct cursorpos clrsize = {GET_BDA(video_cols), 1};
-        vgafb_clear_chars(clr, attr, clrsize);
+        vgafb_scroll(win, winsize, 1, attr);
     }
 }
 
@@ -400,6 +395,7 @@ handle_1005(struct bregs *regs)
 static void
 verify_scroll(struct bregs *regs, int dir)
 {
+    // Verify parameters
     u8 ulx = regs->cl, uly = regs->ch, lrx = regs->dl, lry = regs->dh;
     u16 nbrows = GET_BDA(video_rows) + 1;
     if (lry >= nbrows)
@@ -410,41 +406,16 @@ verify_scroll(struct bregs *regs, int dir)
     int wincols = lrx - ulx + 1, winrows = lry - uly + 1;
     if (wincols <= 0 || winrows <= 0)
         return;
-
-    u8 page = GET_BDA(video_page);
-    int clearlines = regs->al, movelines = winrows - clearlines;
-    if (!clearlines || movelines <= 0) {
-        // Clear whole area.
-        struct cursorpos clr = {ulx, uly, page};
-        struct carattr attr = {' ', regs->bh, 1};
-        struct cursorpos clrsize = {wincols, winrows};
-        vgafb_clear_chars(clr, attr, clrsize);
-        return;
-    }
-
-    if (dir > 0) {
-        // Normal scroll
-        struct cursorpos dest = {ulx, uly, page};
-        struct cursorpos src = {ulx, uly + clearlines, page};
-        struct cursorpos size = {wincols, movelines};
-        vgafb_move_chars(dest, src, size);
-
-        struct cursorpos clr = {ulx, uly + movelines, page};
-        struct carattr attr = {' ', regs->bh, 1};
-        struct cursorpos clrsize = {wincols, clearlines};
-        vgafb_clear_chars(clr, attr, clrsize);
-    } else {
-        // Scroll down
-        struct cursorpos dest = {ulx, uly + clearlines, page};
-        struct cursorpos src = {ulx, uly, page};
-        struct cursorpos size = {wincols, movelines};
-        vgafb_move_chars(dest, src, size);
-
-        struct cursorpos clr = {ulx, uly, page};
-        struct carattr attr = {' ', regs->bh, 1};
-        struct cursorpos clrsize = {wincols, clearlines};
-        vgafb_clear_chars(clr, attr, clrsize);
-    }
+    int lines = regs->al;
+    if (lines >= winrows)
+        lines = 0;
+    lines *= dir;
+
+    // Scroll (or clear) window
+    struct cursorpos win = {ulx, uly, GET_BDA(video_page)};
+    struct cursorpos winsize = {wincols, winrows};
+    struct carattr attr = {' ', regs->bh, 1};
+    vgafb_scroll(win, winsize, lines, attr);
 }
 
 static void
diff --git a/vgasrc/vgabios.h b/vgasrc/vgabios.h
index 831f694..9fbfb14 100644
--- a/vgasrc/vgabios.h
+++ b/vgasrc/vgabios.h
@@ -126,10 +126,8 @@ extern struct video_func_static static_functionality;
 void init_gfx_op(struct gfx_op *op, struct vgamode_s *vmode_g);
 void handle_gfx_op(struct gfx_op *op);
 void *text_address(struct cursorpos cp);
-void vgafb_move_chars(struct cursorpos dest
-                      , struct cursorpos src, struct cursorpos movesize);
-void vgafb_clear_chars(struct cursorpos dest
-                       , struct carattr ca, struct cursorpos movesize);
+void vgafb_scroll(struct cursorpos win, struct cursorpos winsize
+                  , int lines, struct carattr ca);
 void vgafb_write_char(struct cursorpos cp, struct carattr ca);
 struct carattr vgafb_read_char(struct cursorpos cp);
 void vgafb_write_pixel(u8 color, u16 x, u16 y);
diff --git a/vgasrc/vgafb.c b/vgasrc/vgafb.c
index 58c60ad..bd1c8dd 100644
--- a/vgasrc/vgafb.c
+++ b/vgasrc/vgafb.c
@@ -346,7 +346,7 @@ handle_gfx_op(struct gfx_op *op)
 // Move characters when in graphics mode.
 static void
 gfx_move_chars(struct vgamode_s *vmode_g, struct cursorpos dest
-               , struct cursorpos src, struct cursorpos movesize)
+               , struct cursorpos movesize, int lines)
 {
     struct gfx_op op;
     init_gfx_op(&op, vmode_g);
@@ -355,23 +355,23 @@ gfx_move_chars(struct vgamode_s *vmode_g, struct cursorpos dest
     int cheight = GET_BDA(char_height);
     op.y = dest.y * cheight;
     op.ylen = movesize.y * cheight;
-    op.srcy = src.y * cheight;
+    op.srcy = op.y + lines * cheight;
     op.op = GO_MEMMOVE;
     handle_gfx_op(&op);
 }
 
 // Clear area of screen in graphics mode.
 static void
-gfx_clear_chars(struct vgamode_s *vmode_g, struct cursorpos dest
-                , struct carattr ca, struct cursorpos clearsize)
+gfx_clear_chars(struct vgamode_s *vmode_g, struct cursorpos win
+                , struct cursorpos winsize, struct carattr ca)
 {
     struct gfx_op op;
     init_gfx_op(&op, vmode_g);
-    op.x = dest.x * 8;
-    op.xlen = clearsize.x * 8;
+    op.x = win.x * 8;
+    op.xlen = winsize.x * 8;
     int cheight = GET_BDA(char_height);
-    op.y = dest.y * cheight;
-    op.ylen = clearsize.y * cheight;
+    op.y = win.y * cheight;
+    op.ylen = winsize.y * cheight;
     op.pixels[0] = ca.attr;
     if (vga_emulate_text())
         op.pixels[0] = ca.attr >> 4;
@@ -580,45 +580,71 @@ text_address(struct cursorpos cp)
 }
 
 // Move characters on screen.
-void
-vgafb_move_chars(struct cursorpos dest
-                 , struct cursorpos src, struct cursorpos movesize)
+static void
+vgafb_move_chars(struct cursorpos dest, struct cursorpos movesize, int lines)
 {
     struct vgamode_s *vmode_g = get_current_mode();
     if (!vmode_g)
         return;
-    vgafb_set_swcursor(0);
 
     if (GET_GLOBAL(vmode_g->memmodel) != MM_TEXT) {
-        gfx_move_chars(vmode_g, dest, src, movesize);
+        gfx_move_chars(vmode_g, dest, movesize, lines);
         return;
     }
 
     int stride = GET_BDA(video_cols) * 2;
-    memmove_stride(GET_GLOBAL(vmode_g->sstart)
-                   , text_address(dest), text_address(src)
+    void *dest_addr = text_address(dest), *src_addr = dest_addr + lines * stride;
+    memmove_stride(GET_GLOBAL(vmode_g->sstart), dest_addr, src_addr
                    , movesize.x * 2, stride, movesize.y);
 }
 
 // Clear area of screen.
-void
-vgafb_clear_chars(struct cursorpos dest
-                  , struct carattr ca, struct cursorpos clearsize)
+static void
+vgafb_clear_chars(struct cursorpos win, struct cursorpos winsize
+                  , struct carattr ca)
 {
     struct vgamode_s *vmode_g = get_current_mode();
     if (!vmode_g)
         return;
-    vgafb_set_swcursor(0);
 
     if (GET_GLOBAL(vmode_g->memmodel) != MM_TEXT) {
-        gfx_clear_chars(vmode_g, dest, ca, clearsize);
+        gfx_clear_chars(vmode_g, win, winsize, ca);
         return;
     }
 
     int stride = GET_BDA(video_cols) * 2;
     u16 attr = ((ca.use_attr ? ca.attr : 0x07) << 8) | ca.car;
-    memset16_stride(GET_GLOBAL(vmode_g->sstart), text_address(dest), attr
-                    , clearsize.x * 2, stride, clearsize.y);
+    memset16_stride(GET_GLOBAL(vmode_g->sstart), text_address(win), attr
+                    , winsize.x * 2, stride, winsize.y);
+}
+
+// Scroll characters within a window on the screen
+void
+vgafb_scroll(struct cursorpos win, struct cursorpos winsize
+             , int lines, struct carattr ca)
+{
+    vgafb_set_swcursor(0);
+    if (!lines) {
+        // Clear window
+        vgafb_clear_chars(win, winsize, ca);
+    } else if (lines > 0) {
+        // Scroll the window up (eg, from page down key)
+        winsize.y -= lines;
+        vgafb_move_chars(win, winsize, lines);
+
+        win.y += winsize.y;
+        winsize.y = lines;
+        vgafb_clear_chars(win, winsize, ca);
+    } else {
+        // Scroll the window down (eg, from page up key)
+        win.y -= lines;
+        winsize.y += lines;
+        vgafb_move_chars(win, winsize, lines);
+
+        win.y += lines;
+        winsize.y = -lines;
+        vgafb_clear_chars(win, winsize, ca);
+    }
 }
 
 // Write a character to the screen.
-- 
2.5.5




More information about the SeaBIOS mailing list