lib KernelShim
fun hide_cursor()
fun show_cursor()
fun set_cursor_pos(
row : UInt32,
col : UInt32
)
end
module VGA
VGA_ADDRESS = 0xB8000_u64
VGA_BUFFER = Pointer(UInt8).new(VGA_ADDRESS)
VGA_WIDTH = 80
VGA_HEIGHT = 25
VGA_SIZE = VGA_WIDTH * VGA_HEIGHT
TAB_SIZE = 2
DEFAULT_COLOR = 0x07_u8
def self.color_code(
fg : VGA::Color,
bg : VGA::Color,
) : UInt16
(bg.value << 4) | fg.value
end
enum Color : UInt16
Black = 0
Blue = 1
Green = 2
Cyan = 3
Red = 4
Magenta = 5
Brown = 6
LightGray = 7
DarkGray = 8
LightBlue = 9
LightGreen = 10
LightCyan = 11
LightRed = 12
Pink = 13
Yellow = 14
White = 15
end
module Colors
DEFAULT = 0x07_u8
BLACK_ON_CYAN = 0xB0_u8
BLACK_ON_LIME = 0xA0_u8
RED_ON_BLACK = 0x04_u8
GREEN_ON_BLACK = 0x02_u8
CYAN_ON_BLACK = 0x03_u8
GREEN_ON_WHITE = 0xF2_u8
end
def self.init : Nil
clear
end
def self.clear : Nil
i = 0
while i < VGA_SIZE
(VGA_BUFFER + (i * 2)).value = " ".to_unsafe.value
(VGA_BUFFER + (i * 2) + 1).value = Colors::DEFAULT
i += 1
end
col = 0
row = 0
end
def self.hide_cursor
KernelShim.hide_cursor
end
def self.show_cursor
KernelShim.show_cursor
end
def self.set_cursor(
next_col : Int32,
next_row : Int32
) : Nil
KernelShim
.set_cursor_pos(next_row.to_u32, col.to_u32)
@@row = next_row
@@col = next_col
end
@@puts_count = 0
property puts_count
@@col = 0
class_property col
@@row = 0
class_property row
def self.putchar(
ch : UInt8,
i : Int32? = 0,
line : Int32? = 0,
color : UInt8? = Colors::DEFAULT
) : Nil
@@col ||= i || 0
@@row ||= line || 0
offset = (@@row * VGA_WIDTH + @@col) * 2
(VGA_BUFFER + offset).value = ch
(VGA_BUFFER + offset + 1).value = color
@@col += 1
if @@col >= VGA_WIDTH
@@col = 0
@@row += 1
if @@row >= VGA_HEIGHT
@@row = VGA_HEIGHT - 1
end
end
end
def self.puts(
str : String,
color : UInt8? = Colors::DEFAULT,
line : Int32? = nil,
) : Nil
@@col ||= 0
@@row ||= (line || 0)
i = 0
while i < str.size
ch = (str.to_unsafe + i).value
if ch == 0x0A_u8
@@row += 1
@@col = 0
i += 1
next
elsif ch == 0x09_u8
@@col += TAB_SIZE
i += 1
next
elsif ch == 0x1B_u8
j = 0
is_reset = false
while ((str.to_unsafe + i + j).value) != 0x6D_u8
if str[i+j+1] == '[' && str[i+j+2] == '0' && str[i+j+3] == 'm'
is_reset = true
else
is_reset = false
end
j += 1
end
i += j
puts "[" if is_reset == false
puts "]" if is_reset
i += 1
next
end
putchar(ch, @@col, @@row, color)
i += 1
end
VGA.set_cursor(@@col, @@row)
end
end