#include "vgatxt.h"
#include <core/sys.h>
#include <mem/mem.h>
static uint16_t *video_memory = (uint16_t*)((size_t)K_HIGHHALF_ADDR + 0xB8000);
#define VIDMEM_SIZE (80 * 25 * 2)
vgatxt *text_display;
vgatxt::vgatxt(node *parent) : display(parent) {
dev_type = DT_VGATXT;
}
int vgatxt::text_w() {
return 80;
}
int vgatxt::text_h() {
return 25;
}
void vgatxt::text_setcsr(int l, int c, bool visible) {
uint16_t cursor_location = l * 80 + c;
if (!visible) cursor_location = 10000;
outb(0x3D4, 14); //Sending high cursor byte
outb(0x3D5, cursor_location >> 8);
outb(0x3D4, 15); //Sending high cursor byte
outb(0x3D5, cursor_location);
}
void vgatxt::text_put(int l, int c, int ch, uint8_t fgcolor, uint8_t bgcolor) {
if (ch >= 0x80) ch = '?';
video_memory[l * 80 + c] = (char)ch | ((bgcolor << 4 | fgcolor) << 8);
}
void vgatxt::text_scroll(int n, uint8_t fgcolor, uint8_t bgcolor) {
//TODO: optimize
if (n > 0) {
for (int i = 0; i < n; i++) {
uint16_t blank = (((bgcolor << 4) | fgcolor) << 8) | 0x20;
int j;
for (j = 0; j < 80*24; j++) {
video_memory[j] = video_memory[j+80];
}
for (j = 80*24; j < 80*25; j++) {
video_memory[j] = blank;
}
}
} else if (n < 0) {
// TODO
}
}
// Operations as a FS node
size_t vgatxt::get_size() { // size as a node of the filesystem
return (text_w() << 16) + text_h();
}
int vgatxt::read(size_t offset, size_t len, char *buffer) {
if (offset > VIDMEM_SIZE) return 0;
if (offset + len > VIDMEM_SIZE) len = VIDMEM_SIZE - offset;
char *vm = (char*)video_memory;
memcpy(buffer, vm + offset, len);
return len;
}
int vgatxt::write(size_t offset, size_t len, char *buffer) {
if (offset > VIDMEM_SIZE) return 0;
if (offset + len > VIDMEM_SIZE) len = VIDMEM_SIZE - offset;
char *vm = (char*)video_memory;
memcpy(vm + offset, buffer, len);
return len;
}
int vgatxt::dev_control(char *data) {
uint16_t *d = (uint16_t*)data;
text_setcsr(d[0], d[1], d[2] != 0);
return 0;
}