// 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.
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;
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;
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);
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
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;
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);
}
static void
handle_1008(struct bregs *regs)
{
- // XXX - inline
- biosfn_read_char_attr(regs->bh, ®s->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);
}
{
// 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
{
// 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));
}