aboutsummaryrefslogtreecommitdiffstats
path: root/vgasrc
diff options
context:
space:
mode:
authorKevin O'Connor <kevin@koconnor.net>2009-05-31 21:15:33 -0400
committerKevin O'Connor <kevin@koconnor.net>2009-05-31 21:15:33 -0400
commitafb287d4b22e6a1fc3154d97bdd33ec9ceae7060 (patch)
tree58c6b1df88a22672b65c30ab9324da1e483ebdc6 /vgasrc
parent0ad77f09fa0dc35f8ad1ede6dd1acbb68455dec7 (diff)
downloadseabios-afb287d4b22e6a1fc3154d97bdd33ec9ceae7060.tar.gz
VGA: Arrange screen writing functions to minimize stack.
Pass pointer to cursor position into write_string and write_teletype. Handle flag processing of write_string in handle_1013. Implement a tail-recursive scroll_one() function.
Diffstat (limited to 'vgasrc')
-rw-r--r--vgasrc/vga.c71
1 files changed, 50 insertions, 21 deletions
diff --git a/vgasrc/vga.c b/vgasrc/vga.c
index a01b0fc3..7d40c8bd 100644
--- a/vgasrc/vga.c
+++ b/vgasrc/vga.c
@@ -175,9 +175,23 @@ biosfn_set_active_page(u8 page)
set_cursor_pos(cp);
}
-static struct cursorpos
-write_teletype(struct cursorpos cp, struct carattr ca)
+// Scroll the screen one line. This function is designed to be called
+// tail-recursive to reduce stack usage.
+static void noinline
+scroll_one(u16 nbrows, u16 nbcols, u8 page)
{
+ struct cursorpos ul = {0, 0, page};
+ struct cursorpos lr = {nbcols-1, nbrows-1, page};
+ vgafb_scroll(1, -1, ul, lr);
+}
+
+// Write a character to the screen at a given position. Implement
+// special characters and scroll the screen if necessary.
+static void
+write_teletype(struct cursorpos *pcp, struct carattr ca)
+{
+ struct cursorpos cp = *pcp;
+
// Get the dimensions
u16 nbrows = GET_BDA(video_rows) + 1;
u16 nbcols = GET_BDA(video_cols);
@@ -214,34 +228,42 @@ write_teletype(struct cursorpos cp, struct carattr ca)
cp.y++;
}
// Do we need to scroll ?
- if (cp.y == nbrows) {
- struct cursorpos ul = {0, 0, cp.page};
- struct cursorpos lr = {nbcols-1, nbrows-1, cp.page};
- vgafb_scroll(1, -1, ul, lr);
- cp.y--;
+ if (cp.y < nbrows) {
+ *pcp = cp;
+ return;
}
-
- return cp;
+ // Scroll screen
+ cp.y--;
+ *pcp = cp;
+ scroll_one(nbrows, nbcols, cp.page);
}
+// Write out a buffer of alternating characters and attributes.
static void
-write_string(struct cursorpos cp, u8 flag, u8 attr, u16 count,
- u16 seg, u8 *offset_far)
+write_attr_string(struct cursorpos *pcp, u16 count, u16 seg, u8 *offset_far)
{
while (count--) {
u8 car = GET_FARVAR(seg, *offset_far);
offset_far++;
- if (flag & 0x02) {
- attr = GET_FARVAR(seg, *offset_far);
- offset_far++;
- }
+ u8 attr = GET_FARVAR(seg, *offset_far);
+ offset_far++;
struct carattr ca = {car, attr, 1};
- cp = write_teletype(cp, ca);
+ write_teletype(pcp, ca);
}
+}
- if (flag & 0x01)
- set_cursor_pos(cp);
+// Write out a buffer of characters.
+static void
+write_string(struct cursorpos *pcp, u8 attr, u16 count, u16 seg, u8 *offset_far)
+{
+ while (count--) {
+ u8 car = GET_FARVAR(seg, *offset_far);
+ offset_far++;
+
+ struct carattr ca = {car, attr, 1};
+ write_teletype(pcp, ca);
+ }
}
static void
@@ -588,7 +610,7 @@ handle_100e(struct bregs *regs)
// We do output only on the current page !
struct carattr ca = {regs->al, regs->bl, 0};
struct cursorpos cp = get_cursor_pos(0xff);
- cp = write_teletype(cp, ca);
+ write_teletype(&cp, ca);
set_cursor_pos(cp);
}
@@ -987,6 +1009,7 @@ handle_1012(struct bregs *regs)
}
+// Write string
static void noinline
handle_1013(struct bregs *regs)
{
@@ -994,8 +1017,14 @@ handle_1013(struct bregs *regs)
// if row=0xff special case : use current cursor position
if (cp.y == 0xff)
cp = get_cursor_pos(cp.page);
- write_string(cp, regs->al, regs->bl, regs->cx
- , regs->es, (void*)(regs->bp + 0));
+ u8 flag = regs->al;
+ if (flag & 2)
+ write_attr_string(&cp, regs->cx, regs->es, (void*)(regs->bp + 0));
+ else
+ write_string(&cp, regs->bl, regs->cx, regs->es, (void*)(regs->bp + 0));
+
+ if (flag & 1)
+ set_cursor_pos(cp);
}