VGA: Move cursor setting out of biosfn_write_teletype.
[seabios.git] / vgasrc / vga.c
index 74c5680e1791e990f1be216d49a21e50d416db85..06b3993dbfbc4d5158b1c701d4b17f0f1bd5f0c0 100644 (file)
@@ -7,7 +7,6 @@
 
 
 // TODO:
-//  * remove recursion from biosfn_write_teletype()
 //  * review correctness of converted asm by comparing with RBIL
 //  * refactor redundant code into sub-functions
 //  * See if there is a method to the in/out stuff that can be encapsulated.
@@ -149,7 +148,7 @@ biosfn_set_active_page(u8 page)
     struct cursorpos cp = get_cursor_pos(page);
 
     u16 address;
-    if (GET_GLOBAL(vmode_g->class) == TEXT) {
+    if (GET_GLOBAL(vmode_g->memmodel) & TEXT) {
         // Get the dimensions
         u16 nbcols = GET_BDA(video_cols);
         u16 nbrows = GET_BDA(video_rows) + 1;
@@ -176,22 +175,41 @@ biosfn_set_active_page(u8 page)
     set_cursor_pos(cp);
 }
 
-static void
-biosfn_write_teletype(u8 car, u8 page, u8 attr, u8 flag)
-{                               // flag = WITH_ATTR / NO_ATTR
-    // Get the mode
-    struct vgamode_s *vmode_g = find_vga_entry(GET_BDA(video_mode));
-    if (!vmode_g)
-        return;
-
-    // Get the cursor pos for the page
-    struct cursorpos cp = get_cursor_pos(page);
-
+static struct cursorpos
+check_scroll(struct cursorpos cp)
+{
     // Get the dimensions
     u16 nbrows = GET_BDA(video_rows) + 1;
     u16 nbcols = GET_BDA(video_cols);
 
-    switch (car) {
+    // Do we need to wrap ?
+    if (cp.x == nbcols) {
+        cp.x = 0;
+        cp.y++;
+    }
+    // Do we need to scroll ?
+    if (cp.y == nbrows) {
+        // Get the mode
+        struct vgamode_s *vmode_g = find_vga_entry(GET_BDA(video_mode));
+        if (!vmode_g)
+            return cp;
+
+        if (GET_GLOBAL(vmode_g->memmodel) & TEXT)
+            biosfn_scroll(0x01, 0x07, 0, 0, nbrows - 1, nbcols - 1, cp.page,
+                          SCROLL_UP);
+        else
+            biosfn_scroll(0x01, 0x00, 0, 0, nbrows - 1, nbcols - 1, cp.page,
+                          SCROLL_UP);
+        cp.y--;
+    }
+
+    return cp;
+}
+
+static struct cursorpos
+write_teletype(struct cursorpos cp, struct carattr ca)
+{
+    switch (ca.car) {
     case 7:
         //FIXME should beep
         break;
@@ -211,50 +229,28 @@ biosfn_write_teletype(u8 car, u8 page, u8 attr, u8 flag)
 
     case '\t':
         do {
-            biosfn_write_teletype(' ', page, attr, flag);
-            cp = get_cursor_pos(page);
-        } while (cp.x % 8 == 0);
+            struct carattr dummyca = {' ', ca.attr, ca.use_attr};
+            vgafb_write_char(cp, dummyca);
+            cp.x++;
+            cp = check_scroll(cp);
+        } while (cp.x % 8);
         break;
 
     default:
-        if (flag == WITH_ATTR)
-            biosfn_write_char_attr(car, cp.page, attr, 1);
-        else
-            biosfn_write_char_only(car, cp.page, attr, 1);
+        vgafb_write_char(cp, ca);
         cp.x++;
     }
 
-    // Do we need to wrap ?
-    if (cp.x == nbcols) {
-        cp.x = 0;
-        cp.y++;
-    }
-    // Do we need to scroll ?
-    if (cp.y == nbrows) {
-        if (GET_GLOBAL(vmode_g->class) == TEXT)
-            biosfn_scroll(0x01, 0x07, 0, 0, nbrows - 1, nbcols - 1, page,
-                          SCROLL_UP);
-        else
-            biosfn_scroll(0x01, 0x00, 0, 0, nbrows - 1, nbcols - 1, page,
-                          SCROLL_UP);
-        cp.y--;
-    }
-    // Set the cursor for the page
-    set_cursor_pos(cp);
+    return check_scroll(cp);
 }
 
 static void
-biosfn_write_string(struct cursorpos cp, u8 flag, u8 attr, u16 count,
-                    u16 seg, u8 *offset_far)
+write_string(struct cursorpos cp, u8 flag, u8 attr, u16 count,
+             u16 seg, u8 *offset_far)
 {
-    // Read curs info for the page
-    struct cursorpos oldcp = get_cursor_pos(cp.page);
-
     // if row=0xff special case : use current cursor position
     if (cp.y == 0xff)
-        cp = oldcp;
-
-    set_cursor_pos(cp);
+        cp = get_cursor_pos(cp.page);
 
     while (count-- != 0) {
         u8 car = GET_FARVAR(seg, *offset_far);
@@ -264,12 +260,12 @@ biosfn_write_string(struct cursorpos cp, u8 flag, u8 attr, u16 count,
             offset_far++;
         }
 
-        biosfn_write_teletype(car, cp.page, attr, WITH_ATTR);
+        struct carattr ca = {car, attr, 1};
+        cp = write_teletype(cp, ca);
     }
 
-    // Set back curs pos
-    if ((flag & 0x01) == 0)
-        set_cursor_pos(oldcp);
+    if (flag & 0x01)
+        set_cursor_pos(cp);
 }
 
 static void
@@ -428,7 +424,7 @@ handle_1000(struct bregs *regs)
     SET_BDA(video_pal, 0x00); // Unavailable on vanilla vga, but...
 
     // Set cursor shape
-    if (GET_GLOBAL(vmode_g->class) == TEXT)
+    if (GET_GLOBAL(vmode_g->memmodel) & TEXT)
         biosfn_set_cursor_shape(0x06, 0x07);
     // Set cursor pos for page 0..7
     int i;
@@ -441,7 +437,7 @@ handle_1000(struct bregs *regs)
     biosfn_set_active_page(0x00);
 
     // Write the fonts in memory
-    if (GET_GLOBAL(vmode_g->class) == TEXT) {
+    if (GET_GLOBAL(vmode_g->memmodel) & TEXT) {
         call16_vgaint(0x1104, 0);
         call16_vgaint(0x1103, 0);
     }
@@ -514,22 +510,33 @@ handle_1007(struct bregs *regs)
 static void
 handle_1008(struct bregs *regs)
 {
-    // XXX - inline
-    biosfn_read_char_attr(regs->bh, &regs->ax);
+    struct carattr ca = vgafb_read_char(get_cursor_pos(regs->bh));
+    regs->al = ca.car;
+    regs->ah = ca.attr;
+}
+
+static void
+write_chars(u8 page, struct carattr ca, u16 count)
+{
+    struct cursorpos cp = get_cursor_pos(page);
+    while (count--) {
+        vgafb_write_char(cp, ca);
+        cp.x++;
+    }
 }
 
 static void
 handle_1009(struct bregs *regs)
 {
-    // XXX - inline
-    biosfn_write_char_attr(regs->al, regs->bh, regs->bl, regs->cx);
+    struct carattr ca = {regs->al, regs->bl, 1};
+    write_chars(regs->bh, ca, regs->cx);
 }
 
 static void
 handle_100a(struct bregs *regs)
 {
-    // XXX - inline
-    biosfn_write_char_only(regs->al, regs->bh, regs->bl, regs->cx);
+    struct carattr ca = {regs->al, regs->bl, 0};
+    write_chars(regs->bh, ca, regs->cx);
 }
 
 
@@ -581,7 +588,10 @@ handle_100e(struct bregs *regs)
 {
     // Ralf Brown Interrupt list is WRONG on bh(page)
     // We do output only on the current page !
-    biosfn_write_teletype(regs->al, 0xff, regs->bl, NO_ATTR);
+    struct carattr ca = {regs->al, regs->bl, 0};
+    struct cursorpos cp = get_cursor_pos(0xff);
+    cp = write_teletype(cp, ca);
+    set_cursor_pos(cp);
 }
 
 static void
@@ -984,8 +994,8 @@ handle_1013(struct bregs *regs)
 {
     // XXX - inline
     struct cursorpos cp = {regs->dl, regs->dh, regs->bh};
-    biosfn_write_string(cp, regs->al, regs->bl, regs->cx
-                        , regs->es, (void*)(regs->bp + 0));
+    write_string(cp, regs->al, regs->bl, regs->cx
+                 , regs->es, (void*)(regs->bp + 0));
 }