summaryrefslogtreecommitdiff
path: root/src/kernel/vga.c
blob: 6ae15882c1a1773d96ff42b12ca37ecd06b099e1 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
#include <stdbool.h>
#include <stdint.h>

#define VGA_COLUMNS 80
#define VGA_ROWS 25
#define VGA_START (uint16_t *)0x000b8000
#define VGA_END (VGA_START + VGA_COLUMNS * VGA_ROWS)
static uint16_t *cursor = VGA_START;
static uint16_t mask;

void vga_set_color(uint8_t new_color) {
  mask = new_color << 8;
}

void vga_swap_color(uint16_t pos) {
  uint8_t *color_byte = (uint8_t *)(VGA_START + (pos >> 8) * VGA_COLUMNS + (pos & 0xff)) + 1;
  *color_byte = (*color_byte << 4) + (*color_byte >> 4);
}

static void vga_scroll() {
  for (uint32_t *i = (uint32_t *)VGA_START; i < (uint32_t *)(VGA_END - VGA_COLUMNS); ++i)
    *i = *(i + VGA_COLUMNS / 2);
  uint32_t f = (mask | (uint8_t)' ') * 0x00010001;
  for (uint32_t *i = (uint32_t *)(VGA_END - VGA_COLUMNS); i < (uint32_t *)VGA_END; ++i)
    *i = f;
  cursor -= VGA_COLUMNS;
}

void vga_blank() {
  uint32_t f = (mask | (uint8_t)' ') * 0x00010001;
  uint32_t *p = (uint32_t *)VGA_START;
  while (p < (uint32_t *)VGA_END)
    *p++ = f;
  cursor = VGA_END - VGA_COLUMNS;
}

void vga_printch(char ch) {
  if (ch == '\n')
    cursor = ((cursor - VGA_START) / VGA_COLUMNS + 1) * VGA_COLUMNS + VGA_START;
  else if (ch == '\b')
    *--cursor = mask | ' ';
  else
    *cursor++ = mask | (uint8_t)ch;
  if (cursor == VGA_END)
    vga_scroll();
}

void vga_print_at(uint16_t pos, const char *sz) {
  cursor = VGA_START + (pos >> 8) * VGA_COLUMNS + (pos & 0xff);
  while (*sz)
    vga_printch(*sz++);
}