Signed-off-by: Kevin O'Connor kevin@koconnor.net --- Makefile | 2 +- vgasrc/swcursor.c | 65 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ vgasrc/vgabios.h | 2 ++ vgasrc/vgafb.c | 57 ------------------------------------------------ 4 files changed, 68 insertions(+), 58 deletions(-) create mode 100644 vgasrc/swcursor.c
diff --git a/Makefile b/Makefile index 4930b3a..41bfcf4 100644 --- a/Makefile +++ b/Makefile @@ -207,7 +207,7 @@ $(OUT)bios.bin.elf: $(OUT)rom.o $(OUT)bios.bin.prep
# VGA src files SRCVGA=src/output.c src/string.c src/hw/pci.c src/hw/serialio.c \ - vgasrc/vgainit.c vgasrc/vgabios.c vgasrc/vgafb.c \ + vgasrc/vgainit.c vgasrc/vgabios.c vgasrc/vgafb.c vgasrc/swcursor.c \ vgasrc/vgafonts.c vgasrc/vbe.c \ vgasrc/stdvga.c vgasrc/stdvgamodes.c vgasrc/stdvgaio.c \ vgasrc/clext.c vgasrc/bochsvga.c vgasrc/geodevga.c \ diff --git a/vgasrc/swcursor.c b/vgasrc/swcursor.c new file mode 100644 index 0000000..35f857a --- /dev/null +++ b/vgasrc/swcursor.c @@ -0,0 +1,65 @@ +// Virtual software based cursor support +// +// Copyright (C) 2014-2016 Kevin O'Connor kevin@koconnor.net +// +// This file may be distributed under the terms of the GNU LGPLv3 license. + +#include "biosvar.h" // GET_BDA +#include "vgabios.h" // handle_gfx_op + +// Draw/undraw a cursor on the framebuffer by xor'ing the cursor cell +static void +gfx_set_swcursor(struct vgamode_s *vmode_g, int enable, struct cursorpos cp) +{ + u16 cursor_type = get_cursor_shape(); + u8 start = cursor_type >> 8, end = cursor_type & 0xff; + struct gfx_op op; + init_gfx_op(&op, vmode_g); + op.x = cp.x * 8; + int cheight = GET_BDA(char_height); + op.y = cp.y * cheight + start; + + int i; + for (i = start; i < cheight && i <= end; i++, op.y++) { + op.op = GO_READ8; + handle_gfx_op(&op); + int j; + for (j = 0; j < 8; j++) + op.pixels[j] ^= 0x07; + op.op = GO_WRITE8; + handle_gfx_op(&op); + } +} + +// Draw/undraw a cursor on the screen +void +vgafb_set_swcursor(int enable) +{ + if (!vga_emulate_text()) + return; + u8 flags = GET_BDA_EXT(flags); + if (!!(flags & BF_SWCURSOR) == enable) + // Already in requested mode. + return; + struct vgamode_s *vmode_g = get_current_mode(); + if (!vmode_g) + return; + struct cursorpos cp = get_cursor_pos(GET_BDA(video_page)); + if (cp.x >= GET_BDA(video_cols) || cp.y > GET_BDA(video_rows) + || GET_BDA(cursor_type) >= 0x2000) + // Cursor not visible + return; + + SET_BDA_EXT(flags, (flags & ~BF_SWCURSOR) | (enable ? BF_SWCURSOR : 0)); + + if (GET_GLOBAL(vmode_g->memmodel) != MM_TEXT) { + gfx_set_swcursor(vmode_g, enable, cp); + return; + } + + // In text mode, swap foreground and background attributes for cursor + void *dest_far = text_address(cp) + 1; + u8 attr = GET_FARVAR(GET_GLOBAL(vmode_g->sstart), *(u8*)dest_far); + attr = (attr >> 4) | (attr << 4); + SET_FARVAR(GET_GLOBAL(vmode_g->sstart), *(u8*)dest_far, attr); +} diff --git a/vgasrc/vgabios.h b/vgasrc/vgabios.h index 9fbfb14..9764020 100644 --- a/vgasrc/vgabios.h +++ b/vgasrc/vgabios.h @@ -132,6 +132,8 @@ 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); u8 vgafb_read_pixel(u16 x, u16 y); + +// swcursor.c void vgafb_set_swcursor(int enable);
// vbe.c diff --git a/vgasrc/vgafb.c b/vgasrc/vgafb.c index bd1c8dd..46a1ab8 100644 --- a/vgasrc/vgafb.c +++ b/vgasrc/vgafb.c @@ -497,30 +497,6 @@ fail: return (struct carattr){0, 0, 0}; }
-// Draw/undraw a cursor on the framebuffer by xor'ing the cursor cell -void -gfx_set_swcursor(struct vgamode_s *vmode_g, int enable, struct cursorpos cp) -{ - u16 cursor_type = get_cursor_shape(); - u8 start = cursor_type >> 8, end = cursor_type & 0xff; - struct gfx_op op; - init_gfx_op(&op, vmode_g); - op.x = cp.x * 8; - int cheight = GET_BDA(char_height); - op.y = cp.y * cheight + start; - - int i; - for (i = start; i < cheight && i <= end; i++, op.y++) { - op.op = GO_READ8; - handle_gfx_op(&op); - int j; - for (j = 0; j < 8; j++) - op.pixels[j] ^= 0x07; - op.op = GO_WRITE8; - handle_gfx_op(&op); - } -} - // Set the pixel at the given position. void vgafb_write_pixel(u8 color, u16 x, u16 y) @@ -686,36 +662,3 @@ vgafb_read_char(struct cursorpos cp) u16 v = GET_FARVAR(GET_GLOBAL(vmode_g->sstart), *dest_far); return (struct carattr){v, v>>8, 0}; } - -// Draw/undraw a cursor on the screen -void -vgafb_set_swcursor(int enable) -{ - if (!vga_emulate_text()) - return; - u8 flags = GET_BDA_EXT(flags); - if (!!(flags & BF_SWCURSOR) == enable) - // Already in requested mode. - return; - struct vgamode_s *vmode_g = get_current_mode(); - if (!vmode_g) - return; - struct cursorpos cp = get_cursor_pos(GET_BDA(video_page)); - if (cp.x >= GET_BDA(video_cols) || cp.y > GET_BDA(video_rows) - || GET_BDA(cursor_type) >= 0x2000) - // Cursor not visible - return; - - SET_BDA_EXT(flags, (flags & ~BF_SWCURSOR) | (enable ? BF_SWCURSOR : 0)); - - if (GET_GLOBAL(vmode_g->memmodel) != MM_TEXT) { - gfx_set_swcursor(vmode_g, enable, cp); - return; - } - - // In text mode, swap foreground and background attributes for cursor - void *dest_far = text_address(cp) + 1; - u8 attr = GET_FARVAR(GET_GLOBAL(vmode_g->sstart), *(u8*)dest_far); - attr = (attr >> 4) | (attr << 4); - SET_FARVAR(GET_GLOBAL(vmode_g->sstart), *(u8*)dest_far, attr); -}