hachem.wtf
aboutsummaryrefslogtreecommitdiff
path: root/kernel
diff options
context:
space:
mode:
authorhachem <im@hachem.wtf>2026-10-09 11:08:09 +0200
committerhachem <im@hachem.wtf>2026-10-09 11:08:09 +0200
commite0572c37d970d601c17085bdb082cc6ef4356891 (patch)
treef0b4d71c92978e74d127d7090d3e11380378a8b3 /kernel
parent8cb66100fe802c38d180ea29a11a902decf0fd8b (diff)
chore: fmt some revo code based on lung's example
Diffstat (limited to 'kernel')
-rw-r--r--kernel/console.rv176
-rw-r--r--kernel/fs.rv4
-rw-r--r--kernel/input.rv86
-rw-r--r--kernel/io.rv27
-rw-r--r--kernel/main.rv2
-rw-r--r--kernel/proc.rv55
-rw-r--r--kernel/shell.rv6
-rw-r--r--kernel/ttf.rv459
-rw-r--r--kernel/tty.rv167
-rw-r--r--kernel/vfs.rv35
-rw-r--r--kernel/vmm.rv14
11 files changed, 687 insertions, 344 deletions
diff --git a/kernel/console.rv b/kernel/console.rv
index 9447860..ba322f9 100644
--- a/kernel/console.rv
+++ b/kernel/console.rv
@@ -20,41 +20,50 @@ const CURSOR_COLOR = BASE0B
global wd = { path = "/" }
global shell_status = { code = 0 }
-global prompt = fn() do
- let mid = ""
- unless (shell_status.code == 0) do mid = "\x1b[31m#{shell_status.code} " end
- return "\x1b[33m#{wd.path} #{mid}\x1b[97m$\x1b[0m "
+global prompt = fn() -> string do
+ let middle = ""
+ unless (shell_status.code == 0) do
+ middle = "\x1b[31m#{shell_status.code} "
+ end
+ return "\x1b[33m#{wd.path} #{middle}\x1b[97m$\x1b[0m "
end
-fn parse_int(text) do
+fn parse_int(text) -> num do
let value = 0
for index in 0..text:len() do
const digit = text[index]:ascii()
- if (digit >= 48 and digit <= 57) do value = value * 10 + (digit - 48) end
+ if (digit >= 48 and digit <= 57)
+ value = value * 10 + (digit - 48)
end
return value
end
-fn sgr_color(code, current) do
- if (code == 0 or code == 39) return BASE05
- if code == 30 return BASE00
- if code == 90 return BASE03
- if (code == 31 or code == 91) return BASE08
- if (code == 32 or code == 92) return BASE0B
- if (code == 33 or code == 93) return BASE0A
- if (code == 34 or code == 94) return BASE0D
- if (code == 35 or code == 95) return BASE0E
- if (code == 36 or code == 96) return BASE0C
- if code == 37 return BASE05
- if code == 97 return BASE07
- return current
+fn sgr_color(code, current) -> num do
+ return match code
+ | 0, 39 => BASE05
+ | 30 => BASE00
+ | 90 => BASE03
+ | 31, 91 => BASE08
+ | 32, 92 => BASE0B
+ | 33, 93 => BASE0A
+ | 34, 94 => BASE0D
+ | 35, 95 => BASE0E
+ | 36, 96 => BASE0C
+ | 37 => BASE05
+ | 97 => BASE07
+ | _ => current
end
# runtime font bs
-fn embolden(byte, row) do return (byte bor (byte shl 1)) band 0xFF end
-fn slant(byte, row) do return (byte shl ((FONT_HEIGHT - 1 - row) shr 2)) band 0xFF end
+fn embolden(byte, row) -> num do
+ return (byte bor (byte shl 1)) band 0xFF
+end
-fn remap_glyphs(transform) do
+fn slant(byte, row) -> num do
+ return (byte shl ((FONT_HEIGHT - 1 - row) shr 2)) band 0xFF
+end
+
+fn remap_glyphs(transform) -> table do
let out = {}
for glyph_index in 0..FONT:len() do
const glyph = FONT[glyph_index]
@@ -65,15 +74,18 @@ fn remap_glyphs(transform) do
return out
end
-global reverse8 = fn(byte) do
+global reverse8 = fn(byte) -> num do
let out = 0
for bit in 0..8 do
- if (byte shr bit) band 1 == 1 do out = out bor (1 shl (7 - bit)) end
+ if (byte shr bit) band 1 == 1 do
+ out = out bor (1 shl (7 - bit))
+ end
end
return out
end
global fonts = {}
+
global add_font = fn(name, glyphs, width, height, kind, path, size) do
for index in 0..fonts:len() do
if fonts[index].name == name do
@@ -86,11 +98,14 @@ global add_font = fn(name, glyphs, width, height, kind, path, size) do
return :nil
end
end
+
fonts:push({ name = name, glyphs = glyphs, width = width, height = height, kind = kind, path = path, size = size })
end
-global find_font = fn(name) do
+
+global find_font = fn(name) -> table | :nil do
for index in 0..fonts:len() do
- if fonts[index].name == name return fonts[index]
+ if (fonts[index].name == name)
+ return fonts[index]
end
return :nil
end
@@ -120,40 +135,49 @@ global console = {
ansi_param = "",
# this is now font dependent
- cell_width = fn(self) self.font_width * self.scale,
- cell_height = fn(self) self.font_height * self.scale,
- columns = fn(self) fb_width() / self:cell_width(),
- rows = fn(self) fb_height() / self:cell_height(),
+ fn cell_width(self) self.font_width * self.scale,
+ fn cell_height(self) self.font_height * self.scale,
+ fn columns(self) fb_width() / self:cell_width(),
+ fn rows(self) fb_height() / self:cell_height(),
- set_font = fn(self, entry) do
+ fn set_font(self, entry) do
self.font = entry.glyphs
self.font_width = entry.width
self.font_height = entry.height
self.font_entry = entry
+
# a ttf renders at its true pixel size so we js bitmap zoom scale
- if entry.kind == :ttf do self.scale = 1 end
+ if (entry.kind == :ttf)
+ self.scale = 1
self:clear()
end,
- draw_glyph = fn(self, column, row, character) do
+ fn draw_glyph(self, column, row, character) do
const origin_x = column * self:cell_width()
const origin_y = row * self:cell_height()
fill_rect(origin_x, origin_y, self:cell_width(), self:cell_height(), BG_COLOR) # clear the cell
+
const code = character:ascii()
- if code < 32 return :nil
- if code > 127 return :nil
+ if (code < 32)
+ return :nil
+ if (code > 127)
+ return :nil
+
const glyph = self.font[code - 32]
for glyph_row in 0..self.font_height do
const bits = glyph[glyph_row]
for glyph_col in 0..self.font_width do
- if (bits shr glyph_col) band 1 == 1 fill_rect(origin_x + glyph_col * self.scale, origin_y + glyph_row * self.scale, self.scale, self.scale, self.fg)
+ if (bits shr glyph_col) band 1 == 1 do
+ fill_rect(origin_x + glyph_col * self.scale, origin_y + glyph_row * self.scale, self.scale, self.scale, self.fg)
+ end
end
end
end,
- newline = fn(self) do
+ fn newline(self) do
self.column = 0
self.row += 1
+
if self.row >= self:rows() do
fb_scroll(self:cell_height(), BG_COLOR)
self.row = self:rows() - 1
@@ -162,52 +186,84 @@ global console = {
# we dont do shift/cntrl, thats a job for future me lmao
# NOTE: future me kinda delt with it, i was mad drunk
- apply_sgr = fn(self, param) do
- if param:len() == 0 do self.fg = BASE05 return :nil end
+ fn apply_sgr(self, param) do
+ if param:len() == 0 do
+ self.fg = BASE05
+ return :nil
+ end
+
const parts = param:split(";")
for index in 0..parts:len() do self.fg = sgr_color(parse_int(parts[index]), self.fg) end
end,
- putc = fn(self, character) do
+ fn putc(self, character) do
const code = character:ascii()
if self.ansi == 1 do
- if code == 91 do self.ansi = 2 self.ansi_param = "" end
- else do self.ansi = 0 end
+ if code == 91 do
+ self.ansi = 2
+ self.ansi_param = ""
+ end else do
+ self.ansi = 0
+ end
+
return :nil
end
+
if self.ansi == 2 do
- if (code >= 48 and code <= 57) or code == 59 do self.ansi_param = self.ansi_param ~ character return :nil end
- if code == 109 do self:apply_sgr(self.ansi_param) end
+ if (code >= 48 and code <= 57) or code == 59 do
+ self.ansi_param = self.ansi_param ~ character
+ return :nil
+ end
+
+ if (code == 109)
+ self:apply_sgr(self.ansi_param)
self.ansi = 0
+
+ return :nil
+ end
+
+ if code == 27 do # ESC
+ self.ansi = 1
+ return :nil
+ end
+ # \n
+ if code == 10 do # \n
+ self:newline()
return :nil
end
- if code == 27 do self.ansi = 1 return :nil end # ESC, start a sequence
- if code == 10 do self:newline() return :nil end # \n
- if code == 13 do self.column = 0 return :nil end # \r
- if code == 8 do # backspace: move left
- if self.column > 0 self.column -= 1
+ if code == 13 do # \r
+ self.column = 0
return :nil
end
- if code < 32 return :nil
+ if code == 8 do # backspace
+ if (self.column > 0)
+ self.column -= 1
+ return :nil
+ end
+ if (code < 32)
+ return :nil
+
self:draw_glyph(self.column, self.row, character)
self.column += 1
- if self.column >= self:columns() self:newline()
+
+ if (self.column >= self:columns())
+ self:newline()
end,
- clear = fn(self) do
+ fn clear(self) do
fill_rect(0, 0, fb_width(), fb_height(), BG_COLOR)
self.column = 0
self.row = 0
end,
- cursor_clear = fn(self) do
+ fn cursor_clear(self) do
if self.shown do
fill_rect(self.cursor_x * self:cell_width(), self.cursor_y * self:cell_height(), self:cell_width(), self:cell_height(), BG_COLOR)
self.shown = :false
end
end,
- cursor_show = fn(self) do
+ fn cursor_show(self) do
self.cursor_x = self.column
self.cursor_y = self.row
fill_rect(self.cursor_x * self:cell_width(), self.cursor_y * self:cell_height(), self:cell_width(), self:cell_height(), CURSOR_COLOR)
@@ -215,9 +271,12 @@ global console = {
end,
# render every byte the serial mirror has buffered
- drain = fn(self) do
+ fn drain(self) do
let byte = serial_next()
- while byte >= 0 do self:putc(string.of_ascii(byte)) byte = serial_next() end
+ while (byte >= 0) do
+ self:putc(string.of_ascii(byte))
+ byte = serial_next()
+ end
end,
}
@@ -237,6 +296,7 @@ end
global on_tick = fn(ticks) do
let byte = serial_next()
+
if byte >= 0 do
console:cursor_clear()
console:putc(string.of_ascii(byte))
@@ -245,6 +305,7 @@ global on_tick = fn(ticks) do
console:cursor_show()
return :nil
end
+
if proc_exited() do
console:cursor_clear()
puts(prompt())
@@ -253,9 +314,10 @@ global on_tick = fn(ticks) do
console:cursor_show()
return :nil
end
+
console.blink += 1
if console.blink >= 50 do
console.blink = 0
- if console.shown console:cursor_clear() else console:cursor_show()
+ if (console.shown) console:cursor_clear() else console:cursor_show()
end
end
diff --git a/kernel/fs.rv b/kernel/fs.rv
index f732573..63442cd 100644
--- a/kernel/fs.rv
+++ b/kernel/fs.rv
@@ -511,7 +511,7 @@ global fs = {
return result
end,
- fn read_into(self, path, dest) -> num do
+ fn read_into(self, path, destination) -> num do
const entry = self:resolve(path)
if entry == :nil or entry.type == T_DIR do
@@ -525,7 +525,7 @@ global fs = {
while (block != 0 and block != END and remaining > 0) do
const next_block = self:fat_get(block)
- disk_read(block, dest + offset)
+ disk_read(block, destination + offset)
offset += BLOCK
remaining -= BLOCK
block = next_block
diff --git a/kernel/input.rv b/kernel/input.rv
index 139edf0..68313b7 100644
--- a/kernel/input.rv
+++ b/kernel/input.rv
@@ -12,7 +12,9 @@ fn pic_remap() do
outb(0x21, 0x01) outb(0xa1, 0x01)
outb(0x21, 0xff) outb(0xa1, 0xff)
end
-fn pic_unmask(line) outb(0x21, inb(0x21) band (255 bxor (1 shl line)))
+
+fn pic_unmask(line)
+ outb(0x21, inb(0x21) band (255 bxor (1 shl line)))
# 8253/8254 pit channel 0, mode 3 (square wave)
# divisor 11931 -> ~100 hz (1193182 / 11931)
@@ -27,46 +29,82 @@ end
# no fr this is just a key stroke handler
global shell = { shift = :false, extended = :false, ctrl = :false }
-fn decode_key(code) do
- if code == 0x2a or code == 0x36 do shell.shift = :true return :nil end # shift down
- if code == 0xaa or code == 0xb6 do shell.shift = :false return :nil end # shift up
- if code == 0x1d do shell.ctrl = :true return :nil end # ctrl down
- if code == 0x9d do shell.ctrl = :false return :nil end # ctrl up
- if code >= 128 return :nil # other releases
- if code == 28 return "\n" # enter
+fn decode_key(code) -> string | :nil do
+ # shift down
+ if code == 0x2a or code == 0x36 do
+ shell.shift = :true
+ return :nil
+ end
+ # shift up
+ if code == 0xaa or code == 0xb6 do
+ shell.shift = :false
+ return :nil
+ end
+ # ctrl down
+ if code == 0x1d do
+ shell.ctrl = :true
+ return :nil
+ end
+ # ctrl up
+ if code == 0x9d do
+ shell.ctrl = :false
+ return :nil
+ end
+ # other releases
+ if (code >= 128)
+ return :nil
+ # enter
+ if (code == 28)
+ return "\n"
+ # backspace
if code == 14 do
if shell.ctrl do
return "\x7f"
end
-
return "\x08"
- end # backspace (ctrl: word erase)
- if code < 2 return :nil
- if code >= KEYMAP:len() return :nil
- const character = if shell.shift KEYMAP_SHIFT[code] else KEYMAP[code]
- if character == " " and code != 0x39 return :nil # blank cells = modifiers/unmapped
- if shell.ctrl return string.of_ascii(character:ascii() band 0x1f)
+ end
+ if (code < 2)
+ return :nil
+ if (code >= KEYMAP:len())
+ return :nil
+
+ const character = if (shell.shift) KEYMAP_SHIFT[code] else KEYMAP[code]
+ # blank cells = modifiers/unmapped
+ if (character == " " and code != 0x39)
+ return :nil
+ if (shell.ctrl)
+ return string.of_ascii(character:ascii() band 0x1f)
return character
end
global on_key = fn(code) do
- if code == 0xe0 do shell.extended = :true return :nil end
+ if code == 0xe0 do
+ shell.extended = :true
+ return :nil
+ end
+
if shell.extended do
shell.extended = :false
let final = 0
- if code == 0x48 do final = 65 end # up
- else if code == 0x50 do final = 66 end # down
- else if code == 0x4d do final = 67 end # right
- else if code == 0x4b do final = 68 end # left
- else if code == 0x47 do final = 72 end # home
- else if code == 0x4f do final = 70 end # end
+
+ match code
+ | 0x48 => final = 65 # up
+ | 0x50 => final = 66 # down
+ | 0x4d => final = 67 # right
+ | 0x4b => final = 68 # left
+ | 0x47 => final = 72 # home
+ | 0x4f => final = 70 # end
+ | _ => :nil
+
if final != 0 do
tty:feed(27) tty:feed(91) tty:feed(final)
end
return :nil
end
+
const character = decode_key(code)
- if character == :nil return :nil
+
+ if (character == :nil)
+ return :nil
tty:feed(character:ascii())
end
-
diff --git a/kernel/io.rv b/kernel/io.rv
index 68b7039..af28403 100644
--- a/kernel/io.rv
+++ b/kernel/io.rv
@@ -1,37 +1,44 @@
# stdio stuff
global io = {
- open = fn(self, path, mode) do
- if mode == "w" do fs:store(path, "") end
+ fn open(self, path, mode) -> { path: string, offset: num } do
+ if mode == "w" do
+ fs:store(path, "")
+ end
+
let offset = 0
if mode == "a" do
const size = fs:size(path)
- if size > 0 do offset = size end
+ if (size > 0)
+ offset = size
end
+
return { path = path, offset = offset }
end,
- read = fn(self, handle, count) do
+ fn read(self, handle, count) -> string do
const data = fs:read_bytes(handle.path, handle.offset, count)
handle.offset += data:len()
return data
end,
- read_all = fn(self, handle) do
+ fn read_all(self, handle) -> string do
const size = fs:size(handle.path)
- if size <= handle.offset return ""
+ if (size <= handle.offset)
+ return ""
+
const data = fs:read_bytes(handle.path, handle.offset, size - handle.offset)
handle.offset += data:len()
return data
end,
- write = fn(self, handle, data) do
+ fn write(self, handle, data) -> num do
fs:write_at(handle.path, handle.offset, data)
handle.offset += data:len()
return data:len()
end,
- seek = fn(self, handle, offset) do handle.offset = offset end,
- tell = fn(self, handle) handle.offset,
- close = fn(self, handle) :nil,
+ fn seek(self, handle, offset) do handle.offset = offset end,
+ fn tell(self, handle) -> num do return handle.offset end,
+ fn close(self, handle) :nil,
}
diff --git a/kernel/main.rv b/kernel/main.rv
index 3547665..64af212 100644
--- a/kernel/main.rv
+++ b/kernel/main.rv
@@ -9,7 +9,7 @@ wipe()
dump_memmap()
fs:mount()
-if (disk_sectors() != 0 and fs.ready == :false) do
+if disk_sectors() != 0 and fs.ready == :false do
puts("blank disk, formatting + seeding default files\n")
fs:format()
seed_fs()
diff --git a/kernel/proc.rv b/kernel/proc.rv
index 92d48f1..8d7827a 100644
--- a/kernel/proc.rv
+++ b/kernel/proc.rv
@@ -9,35 +9,45 @@ fn load_elf(base, arg) do
puts("not an ELF\n")
return :nil
end
+
const entry = mem_read(base + 24, 8)
const program_header_offset = mem_read(base + 32, 8)
const program_header_count = mem_read(base + 56, 2)
const program_header_size = mem_read(base + 54, 2)
const space = as_create()
+
for index in 0..program_header_count do
const header = base + program_header_offset + index * program_header_size
+
if mem_read(header, 4) == PT_LOAD do
const file_offset = mem_read(header + 8, 8)
const virtual_address = mem_read(header + 16, 8)
const file_size = mem_read(header + 32, 8)
const memory_size = mem_read(header + 40, 8)
let segment_offset = 0
- while segment_offset < memory_size do
+
+ while (segment_offset < memory_size) do
const frame = frame_alloc()
mem_zero(frame, 4096)
+
if segment_offset < file_size do
const remaining = file_size - segment_offset
- mem_copy(frame, base + file_offset + segment_offset, if remaining > 4096 4096 else remaining)
+ mem_copy(frame, base + file_offset + segment_offset, if (remaining > 4096) 4096 else remaining)
end
+
as_map(space, virtual_address + segment_offset, frame, PAGE_FLAGS)
segment_offset = segment_offset + 4096
end
end
end
+
const stack_top = 0x7fff0000
+
for page in 0..4 do as_map(space, stack_top - (page + 1) * 4096, frame_alloc(), PAGE_FLAGS) end
+
let arg_ptr = 0
const arg_len = arg:len()
+
if arg_len > 0 do
const arg_frame = frame_alloc()
mem_zero(arg_frame, 4096)
@@ -45,31 +55,50 @@ fn load_elf(base, arg) do
as_map(space, ARG_VADDR, arg_frame, PAGE_FLAGS)
arg_ptr = ARG_VADDR
end
+
proc_run(space, entry, stack_top, arg_ptr, arg_len)
end
-# one reused contiguous buffer to stage an elf image read off the disk, since
-# load_elf wants a flat base to mem_read from and a file lands in scattered frames
-# its a weird arch but wtv
+#* one reused contiguous buffer to stage an elf image read off the disk, since
+ load_elf wants a flat base to mem_read from and a file lands in scattered frames
+ its a weird arch but wtv *#
global loader = { scratch = 0 }
const SCRATCH_PAGES = 64
-fn load_file_elf(path, arg) do
+fn load_file_elf(path, arg) -> bool do
const size = fs:size(path)
- if size < 0 do puts("#{path}: not found\n") return :false end
- if size > SCRATCH_PAGES * 4096 do puts("#{path}: too big to load\n") return :false end
- if loader.scratch == 0 do loader.scratch = alloc_contig(SCRATCH_PAGES) end
- if loader.scratch == 0 do puts("no memory for elf load\n") return :false end
+ if size < 0 do
+ puts("#{path}: not found\n")
+ return :false
+ end
+ if size > SCRATCH_PAGES * 4096 do
+ puts("#{path}: too big to load\n")
+ return :false
+ end
+
+ if loader.scratch == 0 do
+ loader.scratch = alloc_contig(SCRATCH_PAGES)
+ end
+ if loader.scratch == 0 do
+ puts("no memory for elf load\n")
+ return :false
+ end
+
blit_str(loader.scratch, fs:read_bytes(path, 0, size))
load_elf(loader.scratch, arg)
+
return :true
end
-fn run_prog(name, arg) do
+fn run_prog(name, arg) -> bool do
let bare_name = name
- if bare_name:starts_with?("/usr/bin/") bare_name = bare_name[9..]
+ if (bare_name:starts_with?("/usr/bin/"))
+ bare_name = bare_name[9..]
+
const path = "/usr/bin/#{bare_name}"
- if fs:size(path) < 0 return :false
+ if (fs:size(path) < 0)
+ return :false
+
return load_file_elf(path, arg)
end
diff --git a/kernel/shell.rv b/kernel/shell.rv
index 99ead73..e016d18 100644
--- a/kernel/shell.rv
+++ b/kernel/shell.rv
@@ -10,13 +10,13 @@ fn pad(text, width) -> string do
end
fn help_row(label, description) do
- let col = pad(label, 22)
+ let column = pad(label, 22)
if label:len() >= 22 do
- col = label ~ " "
+ column = label ~ " "
end
- puts(" #{col}#{description}\n")
+ puts(" #{column}#{description}\n")
end
fn help_group(title, group_name) do
diff --git a/kernel/ttf.rv b/kernel/ttf.rv
index 17d1a19..fb1bab7 100644
--- a/kernel/ttf.rv
+++ b/kernel/ttf.rv
@@ -6,84 +6,120 @@
# fuck lung
# fuck me
# im like 90% confident this works, but im like 10% confident its fucked
-fn ttf_mod(a, b) a - math.floor(a / b) * b
+fn ttf_mod(value, modulus) -> num do
+ return value - math.floor(value / modulus) * modulus
+end
+
+fn ttf_u8(data, offset) -> num do
+ return mem_read(data + offset, 1)
+end
-fn ttf_u8(d, o) mem_read(d + o, 1)
-fn ttf_u16(d, o) mem_read(d + o, 1) * 256 + mem_read(d + o + 1, 1)
-fn ttf_i16(d, o) do
- const v = ttf_u16(d, o)
- if v >= 32768 return v - 65536
- return v
+fn ttf_u16(data, offset) -> num do
+ return mem_read(data + offset, 1) * 256 + mem_read(data + offset + 1, 1)
end
-fn ttf_u32(d, o) ((mem_read(d + o, 1) * 256 + mem_read(d + o + 1, 1)) * 256 + mem_read(d + o + 2, 1)) * 256 + mem_read(d + o + 3, 1)
-fn ttf_tag_eq(d, o, tag) do
- for i in 0..4 do if mem_read(d + o + i, 1) != tag[i]:ascii() return :false end
+fn ttf_i16(data, offset) -> num do
+ const value = ttf_u16(data, offset)
+ if (value >= 32768)
+ return value - 65536
+ return value
+end
+
+fn ttf_u32(data, offset) -> num do
+ return ((mem_read(data + offset, 1) * 256 + mem_read(data + offset + 1, 1)) * 256 + mem_read(data + offset + 2, 1)) * 256 + mem_read(data + offset + 3, 1)
+end
+
+fn ttf_tag_eq(data, offset, tag) -> bool do
+ for i in 0..4 do
+ if (mem_read(data + offset + i, 1) != tag[i]:ascii())
+ return :false
+ end
+
return :true
end
-fn ttf_table(d, tag) do
- const n = ttf_u16(d, 4)
- for i in 0..n do
- const rec = 12 + i * 16
- if ttf_tag_eq(d, rec, tag) return ttf_u32(d, rec + 8)
+fn ttf_table(data, tag) -> num do
+ const count = ttf_u16(data, 4)
+ for i in 0..count do
+ const record = 12 + i * 16
+ if (ttf_tag_eq(data, record, tag))
+ return ttf_u32(data, record + 8)
end
return -1
end
-fn ttf_cmap_sub(d, cmap_off) do
- const n = ttf_u16(d, cmap_off + 2)
+fn ttf_cmap_sub(data, cmap_off) -> num do
+ const count = ttf_u16(data, cmap_off + 2)
let best = -1
- for i in 0..n do
- const rec = cmap_off + 4 + i * 8
- const plat = ttf_u16(d, rec)
- const enc = ttf_u16(d, rec + 2)
- if (plat == 3 and (enc == 1 or enc == 0)) or plat == 0 do best = cmap_off + ttf_u32(d, rec + 4) end
+
+ for i in 0..count do
+ const record = cmap_off + 4 + i * 8
+ const platform = ttf_u16(data, record)
+ const encoding = ttf_u16(data, record + 2)
+ if (platform == 3 and (encoding == 1 or encoding == 0)) or platform == 0 do
+ best = cmap_off + ttf_u32(data, record + 4)
+ end
end
+
return best
end
-fn ttf_glyph_of(d, sub, c) do
- if ttf_u16(d, sub) != 4 return 0
- const segCount = ttf_u16(d, sub + 6) / 2
- const endBase = sub + 14
- const startBase = endBase + segCount * 2 + 2
- const deltaBase = startBase + segCount * 2
- const rangeBase = deltaBase + segCount * 2
- for i in 0..segCount do
- if c <= ttf_u16(d, endBase + i * 2) do
- const startC = ttf_u16(d, startBase + i * 2)
- if c < startC return 0
- const idro = ttf_u16(d, rangeBase + i * 2)
- if idro == 0 return (c + ttf_i16(d, deltaBase + i * 2)) band 0xFFFF
- const g = ttf_u16(d, rangeBase + i * 2 + idro + (c - startC) * 2)
- if g == 0 return 0
- return (g + ttf_i16(d, deltaBase + i * 2)) band 0xFFFF
+fn ttf_glyph_of(data, subtable, code) -> num do
+ if (ttf_u16(data, subtable) != 4)
+ return 0
+
+ const segment_count = ttf_u16(data, subtable + 6) / 2
+ const end_base = subtable + 14
+ const start_base = end_base + segment_count * 2 + 2
+ const delta_base = start_base + segment_count * 2
+ const range_base = delta_base + segment_count * 2
+
+ for i in 0..segment_count do
+ if code <= ttf_u16(data, end_base + i * 2) do
+ const start_code = ttf_u16(data, start_base + i * 2)
+ if (code < start_code)
+ return 0
+
+ const idro = ttf_u16(data, range_base + i * 2)
+ if (idro == 0)
+ return (code + ttf_i16(data, delta_base + i * 2)) band 0xFFFF
+
+ const glyph_id = ttf_u16(data, range_base + i * 2 + idro + (code - start_code) * 2)
+ if (glyph_id == 0)
+ return 0
+
+ return (glyph_id + ttf_i16(data, delta_base + i * 2)) band 0xFFFF
end
end
+
return 0
end
-fn ttf_glyph_offset(d, loca, long, g) do
- if long return ttf_u32(d, loca + g * 4)
- return ttf_u16(d, loca + g * 2) * 2
+fn ttf_glyph_offset(data, loca, long, glyph_id) -> num do
+ if (long)
+ return ttf_u32(data, loca + glyph_id * 4)
+ return ttf_u16(data, loca + glyph_id * 2) * 2
end
-fn ttf_advance(d, hmtx, numH, g) do
- if g < numH return ttf_u16(d, hmtx + g * 4)
- return ttf_u16(d, hmtx + (numH - 1) * 4)
+fn ttf_advance(data, hmtx, num_hmetrics, glyph_id) -> num do
+ if (glyph_id < num_hmetrics)
+ return ttf_u16(data, hmtx + glyph_id * 4)
+ return ttf_u16(data, hmtx + (num_hmetrics - 1) * 4)
end
-fn ttf_add_line(edges, x0, y0, x1, y1) edges:push({ ax = x0, ay = y0, bx = x1, by = y1 })
+fn ttf_add_line(edges, x0, y0, x1, y1)
+ edges:push({ ax = x0, ay = y0, bx = x1, by = y1 })
-fn ttf_add_quad(edges, x0, y0, cx, cy, x1, y1, n) do
+fn ttf_add_quad(edges, x0, y0, cx, cy, x1, y1, steps) do
let px = x0
let py = y0
- for i in 1..(n + 1) do
- const t = i / n
+
+ for i in 1..(steps + 1) do
+ const t = i / steps
const mt = 1 - t
const qx = mt * mt * x0 + 2 * mt * t * cx + t * t * x1
const qy = mt * mt * y0 + 2 * mt * t * cy + t * t * y1
+
ttf_add_line(edges, px, py, qx, qy)
px = qx
py = qy
@@ -91,196 +127,289 @@ fn ttf_add_quad(edges, x0, y0, cx, cy, x1, y1, n) do
end
fn ttf_contour(pts, edges, nsub) do
- const m = pts:len()
- if m < 2 return :nil
- let exp = {}
- for i in 0..m do
- exp:push(pts[i])
- const j = ttf_mod(i + 1, m)
- if (pts[i].on == :false and pts[j].on == :false) do
- exp:push({ x = (pts[i].x + pts[j].x) / 2, y = (pts[i].y + pts[j].y) / 2, on = :true })
+ const point_count = pts:len()
+ if (point_count < 2)
+ return :nil
+
+ let expanded = {}
+ for i in 0..point_count do
+ expanded:push(pts[i])
+ const j = ttf_mod(i + 1, point_count)
+
+ if pts[i].on == :false and pts[j].on == :false do
+ expanded:push({ x = (pts[i].x + pts[j].x) / 2, y = (pts[i].y + pts[j].y) / 2, on = :true })
end
end
- const n = exp:len()
- let s = -1
- for i in 0..n do if (s < 0 and exp[i].on) do s = i end end
- if s < 0 return :nil
- let cx = exp[s].x
- let cy = exp[s].y
+
+ const expanded_count = expanded:len()
+ let start = -1
+ for i in 0..expanded_count do
+ if (start < 0 and expanded[i].on)
+ start = i
+ end
+
+ if (start < 0)
+ return :nil
+
+ let cx = expanded[start].x
+ let cy = expanded[start].y
let k = 1
- while k <= n do
- const a = exp[ttf_mod(s + k, n)]
- if a.on do
- ttf_add_line(edges, cx, cy, a.x, a.y)
- cx = a.x
- cy = a.y
+
+ while (k <= expanded_count) do
+ const point = expanded[ttf_mod(start + k, expanded_count)]
+
+ if point.on do
+ ttf_add_line(edges, cx, cy, point.x, point.y)
+ cx = point.x
+ cy = point.y
k += 1
- end
- else do
- const b = exp[ttf_mod(s + k + 1, n)]
- ttf_add_quad(edges, cx, cy, a.x, a.y, b.x, b.y, nsub)
- cx = b.x
- cy = b.y
+ end else do
+ const endpoint = expanded[ttf_mod(start + k + 1, expanded_count)]
+ ttf_add_quad(edges, cx, cy, point.x, point.y, endpoint.x, endpoint.y, nsub)
+ cx = endpoint.x
+ cy = endpoint.y
k += 2
end
end
end
# how about you contour my fucking asshole
-fn ttf_glyph_edges(d, glyf, loca, long, g, scale, ox, baseline, edges, nsub) do
- const off = ttf_glyph_offset(d, loca, long, g)
- const next = ttf_glyph_offset(d, loca, long, g + 1)
- if next <= off return :nil # empty glyph
- const base = glyf + off
- const nc = ttf_i16(d, base)
- if nc < 0 return :nil # skip
+fn ttf_glyph_edges(data, glyf, loca, long, glyph_id, scale, ox, baseline, edges, nsub) do
+ const offset = ttf_glyph_offset(data, loca, long, glyph_id)
+ const next = ttf_glyph_offset(data, loca, long, glyph_id + 1)
+
+ # empty glyph
+ if (next <= offset)
+ return :nil
+ const base = glyf + offset
+ const contour_count = ttf_i16(data, base)
+
+ # skip
+ if (contour_count < 0)
+ return :nil
+
let ends = {}
- for i in 0..nc do ends:push(ttf_u16(d, base + 10 + i * 2)) end
- const npts = ends[nc - 1] + 1
- let p = base + 10 + nc * 2
- p += 2 + ttf_u16(d, p) # skip instructions
+ for i in 0..contour_count do ends:push(ttf_u16(data, base + 10 + i * 2)) end
+
+ const point_count = ends[contour_count - 1] + 1
+ let pos = base + 10 + contour_count * 2
+
+ pos += 2 + ttf_u16(data, pos) # skip instructions
let flags = {}
- while flags:len() < npts do
- const f = ttf_u8(d, p)
- p += 1
- flags:push(f)
- if (f band 0x08) != 0 do
- let rep = ttf_u8(d, p)
- p += 1
- while rep > 0 do flags:push(f) rep -= 1 end
+ while (flags:len() < point_count) do
+ const flag = ttf_u8(data, pos)
+
+ pos += 1
+ flags:push(flag)
+
+ if (flag band 0x08) != 0 do
+ let repeat = ttf_u8(data, pos)
+ pos += 1
+
+ while (repeat > 0) do
+ flags:push(flag)
+ repeat -= 1
+ end
end
end
+
let xs = {}
let x = 0
- for i in 0..npts do
- const f = flags[i]
- if (f band 0x02) != 0 do
- const dx = ttf_u8(d, p)
- p += 1
- if (f band 0x10) != 0 do x += dx end else do x -= dx end
- end
- else do
- if (f band 0x10) == 0 do x += ttf_i16(d, p) p += 2 end
+
+ for i in 0..point_count do
+ const flag = flags[i]
+
+ if (flag band 0x02) != 0 do
+ const dx = ttf_u8(data, pos)
+ pos += 1
+
+ if (flag band 0x10) != 0 do
+ x += dx
+ end else do
+ x -= dx
+ end
+ end else do
+ if (flag band 0x10) == 0 do
+ x += ttf_i16(data, pos)
+ pos += 2
+ end
end
+
xs:push(x)
end
+
let ys = {}
let y = 0
- for i in 0..npts do
- const f = flags[i]
- if (f band 0x04) != 0 do
- const dy = ttf_u8(d, p)
- p += 1
- if (f band 0x20) != 0 do y += dy end else do y -= dy end
- end
- else do
- if (f band 0x20) == 0 do y += ttf_i16(d, p) p += 2 end
+
+ for i in 0..point_count do
+ const flag = flags[i]
+
+ if (flag band 0x04) != 0 do
+ const dy = ttf_u8(data, pos)
+ pos += 1
+
+ if (flag band 0x20) != 0 do
+ y += dy
+ end else do
+ y -= dy
+ end
+ end else do
+ if (flag band 0x20) == 0 do
+ y += ttf_i16(data, pos)
+ pos += 2
+ end
end
+
ys:push(y)
end
+
# split into contours
let start = 0
- for ci in 0..nc do
+
+ for ci in 0..contour_count do
const stop = ends[ci]
let pts = {}
+
for i in start..(stop + 1) do
pts:push({ x = xs[i] * scale + ox, y = baseline - ys[i] * scale, on = (flags[i] band 0x01) != 0 })
end
+
ttf_contour(pts, edges, nsub)
start = stop + 1
end
end
-fn ttf_fill(edges, w, h) do
+fn ttf_fill(edges, width, height) -> table do
let rows = {}
- for py in 0..h do
+
+ for py in 0..height do
const yc = py + 0.5
let cross = {}
- for e in 0..edges:len() do
- const ed = edges[e]
- const y0 = ed.ay
- const y1 = ed.by
- if ((y0 <= yc and yc < y1) or (y1 <= yc and yc < y0)) do
+
+ for i in 0..edges:len() do
+ const edge = edges[i]
+ const y0 = edge.ay
+ const y1 = edge.by
+
+ if (y0 <= yc and yc < y1) or (y1 <= yc and yc < y0) do
const t = (yc - y0) / (y1 - y0)
- let dir = 1
- if y1 < y0 do dir = -1 end
- cross:push({ x = ed.ax + t * (ed.bx - ed.ax), dir = dir })
+ let direction = 1
+
+ if y1 < y0 do
+ direction = -1
+ end
+
+ cross:push({ x = edge.ax + t * (edge.bx - edge.ax), dir = direction })
end
end
+
# sort crossings left to right
# insertion sort
- for a in 1..cross:len() do
- const key = cross[a]
- let b = a - 1
- while (b >= 0 and cross[b].x > key.x) do
- cross[b + 1] = cross[b]
- b -= 1
+ for i in 1..cross:len() do
+ const key = cross[i]
+ let j = i - 1
+ while (j >= 0 and cross[j].x > key.x) do
+ cross[j + 1] = cross[j]
+ j -= 1
end
- cross[b + 1] = key
+
+ cross[j + 1] = key
end
+
let bits = 0
- let wind = 0
+ let winding = 0
+
for k in 0..cross:len() do
- wind += cross[k].dir
- if (wind != 0 and k + 1 < cross:len()) do
+ winding += cross[k].dir
+
+ if (winding != 0 and k + 1 < cross:len()) do
const xa = cross[k].x
const xb = cross[k + 1].x
+
if xb > xa do
let any = :false
- for px in 0..w do
- if (px + 0.5 >= xa and px + 0.5 < xb) do bits = bits bor (1 shl px) any = :true end
+ for px in 0..width do
+ if (px + 0.5 >= xa and px + 0.5 < xb) do
+ bits = bits bor (1 shl px)
+ any = :true
+ end
end
+
if any == :false do
- const mid = math.floor((xa + xb) / 2)
- if (mid >= 0 and mid < w) do bits = bits bor (1 shl mid) end
+ const midpoint = math.floor((xa + xb) / 2)
+ if (midpoint >= 0 and midpoint < width)
+ bits = bits bor (1 shl midpoint)
end
end
end
end
+
rows:push(bits)
end
+
return rows
end
-global ttf_io = { buf = 0, pages = 512 }
+global ttf_io = { buffer = 0, pages = 512 }
-global load_ttf = fn(path, size) do
+global load_ttf = fn(path, size) -> { glyphs: table, width: num, height: num } | :nil do
const total = fs:size(path)
- if total < 12 return :nil
- if ttf_io.buf == 0 do ttf_io.buf = alloc_contig(ttf_io.pages) end
- if ttf_io.buf == 0 return :nil
- if total > ttf_io.pages * 4096 return :nil
- fs:read_into(path, ttf_io.buf)
- const d = ttf_io.buf
- const head = ttf_table(d, "head")
- const maxp = ttf_table(d, "maxp")
- const cmap = ttf_table(d, "cmap")
- const loca = ttf_table(d, "loca")
- const glyf = ttf_table(d, "glyf")
- const hhea = ttf_table(d, "hhea")
- const hmtx = ttf_table(d, "hmtx")
- if (head < 0 or cmap < 0 or loca < 0 or glyf < 0 or hhea < 0) return :nil
- const upm = ttf_u16(d, head + 18)
- if upm == 0 return :nil
- const long = ttf_i16(d, head + 50) == 1
- const ascent = ttf_i16(d, hhea + 4)
- const descent = ttf_i16(d, hhea + 6)
- const numH = ttf_u16(d, hhea + 34)
+ if (total < 12)
+ return :nil
+
+ if ttf_io.buffer == 0 do
+ ttf_io.buffer = alloc_contig(ttf_io.pages)
+ end
+ if (ttf_io.buffer == 0)
+ return :nil
+ if (total > ttf_io.pages * 4096)
+ return :nil
+
+ fs:read_into(path, ttf_io.buffer)
+
+ const data = ttf_io.buffer
+ const head = ttf_table(data, "head")
+ const maxp = ttf_table(data, "maxp")
+ const cmap = ttf_table(data, "cmap")
+ const loca = ttf_table(data, "loca")
+ const glyf = ttf_table(data, "glyf")
+ const hhea = ttf_table(data, "hhea")
+ const hmtx = ttf_table(data, "hmtx")
+
+ if (head < 0 or cmap < 0 or loca < 0 or glyf < 0 or hhea < 0)
+ return :nil
+
+ const upm = ttf_u16(data, head + 18)
+ if (upm == 0)
+ return :nil
+
+ const long = ttf_i16(data, head + 50) == 1
+ const ascent = ttf_i16(data, hhea + 4)
+ const descent = ttf_i16(data, hhea + 6)
+ const num_hmetrics = ttf_u16(data, hhea + 34)
const scale = size / upm
const baseline = math.floor(ascent * scale)
let height = math.floor((ascent - descent) * scale) + 1
- const sub = ttf_cmap_sub(d, cmap)
- if sub < 0 return :nil
- const mgate = ttf_glyph_of(d, sub, 77) # 'M'
- let width = math.floor(ttf_advance(d, hmtx, numH, mgate) * scale) + 1
- if width < 2 do width = math.floor(size * 0.6) + 1 end
+
+ const subtable = ttf_cmap_sub(data, cmap)
+ if (subtable < 0)
+ return :nil
+
+ const mgate = ttf_glyph_of(data, subtable, 77) # 'M'
+ let width = math.floor(ttf_advance(data, hmtx, num_hmetrics, mgate) * scale) + 1
+ if (width < 2)
+ width = math.floor(size * 0.6) + 1
+
const nsub = 5
let glyphs = {}
+
for code in 32..128 do
- const g = ttf_glyph_of(d, sub, code)
+ const glyph_id = ttf_glyph_of(data, subtable, code)
let edges = {}
- ttf_glyph_edges(d, glyf, loca, long, g, scale, 1, baseline, edges, nsub)
+
+ ttf_glyph_edges(data, glyf, loca, long, glyph_id, scale, 1, baseline, edges, nsub)
glyphs:push(ttf_fill(edges, width, height))
end
+
return { glyphs = glyphs, width = width, height = height }
end
diff --git a/kernel/tty.rv b/kernel/tty.rv
index 680289f..7ea2492 100644
--- a/kernel/tty.rv
+++ b/kernel/tty.rv
@@ -6,51 +6,70 @@ global tty = {
line = "", cursor = 0, esc = 0,
history = {}, hist_index = 0,
- back = fn(self, n) do
+ fn back(self, n) do
let i = 0
- while i < n do puts("\x08") i += 1 end
+ while (i < n) do
+ puts("\x08")
+ i += 1
+ end
end,
- blanks = fn(self, n) do
+
+ fn blanks(self, n) do
let i = 0
- while i < n do puts(" ") i += 1 end
+ while (i < n) do
+ puts(" ")
+ i += 1
+ end
end,
- insert = fn(self, ch) do
+ fn insert(self, character) do
const pre = self.line[0..self.cursor]
const post = self.line[self.cursor..]
- self.line = pre ~ ch ~ post
- puts(ch ~ post)
+ self.line = pre ~ character ~ post
+ puts(character ~ post)
self:back(post:len())
self.cursor += 1
end,
- backspace = fn(self) do
- if self.cursor == 0 return :nil
+ fn backspace(self) do
+ if (self.cursor == 0)
+ return :nil
+
const pre = self.line[0..(self.cursor - 1)]
const post = self.line[self.cursor..]
self.line = pre ~ post
self.cursor -= 1
+
puts("\x08")
puts(post ~ " ")
self:back(post:len() + 1)
end,
- move_left = fn(self) do
- if self.cursor > 0 do puts("\x08") self.cursor -= 1 end
+ fn move_left(self) do
+ if self.cursor > 0 do
+ puts("\x08")
+ self.cursor -= 1
+ end
end,
- move_right = fn(self) do
- if self.cursor < self.line:len() do puts(self.line[self.cursor]) self.cursor += 1 end
+
+ fn move_right(self) do
+ if self.cursor < self.line:len() do
+ puts(self.line[self.cursor])
+ self.cursor += 1
+ end
end,
- home = fn(self) do
+
+ fn home(self) do
self:back(self.cursor)
self.cursor = 0
end,
- to_end = fn(self) do
+
+ fn to_end(self) do
puts(self.line[self.cursor..])
self.cursor = self.line:len()
end,
- kill = fn(self) do
+ fn kill(self) do
self:back(self.cursor)
self:blanks(self.line:len())
self:back(self.line:len())
@@ -58,50 +77,65 @@ global tty = {
self.cursor = 0
end,
- erase_word = fn(self) do
- if self.cursor == 0 return :nil
+ fn erase_word(self) do
+ if (self.cursor == 0)
+ return :nil
+
let at = self.cursor
- while (at > 0 and self.line[at - 1] == " ") do at -= 1 end
- while (at > 0 and self.line[at - 1] != " ") do at -= 1 end
+ while (at > 0 and self.line[at - 1] == " ")
+ at -= 1
+ while (at > 0 and self.line[at - 1] != " ")
+ at -= 1
+
let count = self.cursor - at
- while count > 0 do self:backspace() count -= 1 end
+ while (count > 0) do
+ self:backspace()
+ count -= 1
+ end
end,
- replace_line = fn(self, text) do
+ fn replace_line(self, text) do
self:kill()
self.line = text
puts(text)
self.cursor = text:len()
end,
- history_prev = fn(self) do
- if self.history:len() == 0 return :nil
- if self.hist_index > 0 do self.hist_index -= 1 end
+ fn history_prev(self) do
+ if (self.history:len() == 0)
+ return :nil
+ if (self.hist_index > 0)
+ self.hist_index -= 1
+
self:replace_line(self.history[self.hist_index])
end,
- history_next = fn(self) do
- if self.history:len() == 0 return :nil
+
+ fn history_next(self) do
+ if (self.history:len() == 0)
+ return :nil
+
if self.hist_index < self.history:len() - 1 do
self.hist_index += 1
self:replace_line(self.history[self.hist_index])
- end
- else do
+ end else do
self.hist_index = self.history:len()
self:replace_line("")
end
end,
- submit = fn(self) do
+ fn submit(self) do
puts("\n")
const entered = self.line
- if entered:len() > 0 do self.history:push(entered) end
+ if (entered:len() > 0)
+ self.history:push(entered)
+
self.hist_index = self.history:len()
self.line = ""
self.cursor = 0
run(entered)
end,
- cancel = fn(self) do
+ fn cancel(self) do
puts("^C\n")
self.line = ""
self.cursor = 0
@@ -109,44 +143,65 @@ global tty = {
puts(prompt())
end,
- clear_screen = fn(self) do
+ fn clear_screen(self) do
console:clear()
puts(prompt())
puts(self.line)
self:back(self.line:len() - self.cursor)
end,
- feed = fn(self, byte) do
- if stdin_deliver(byte) return :nil
+ fn feed(self, byte) do
+ if (stdin_deliver(byte))
+ return :nil
if self.esc == 1 do
- if byte == 91 do self.esc = 2 end
- else do self.esc = 0 end
+ if byte == 91 do
+ self.esc = 2
+ end else do
+ self.esc = 0
+ end
+
return :nil
end
+
if self.esc == 2 do
self.esc = 0
- if byte == 65 do self:history_prev() end # up
- else if byte == 66 do self:history_next() end # down
- else if byte == 67 do self:move_right() end # right
- else if byte == 68 do self:move_left() end # left
- else if byte == 72 do self:home() end # home
- else if byte == 70 do self:to_end() end # end
+
+ match byte
+ | 65 => self:history_prev() # up
+ | 66 => self:history_next() # down
+ | 67 => self:move_right() # right
+ | 68 => self:move_left() # left
+ | 72 => self:home() # home
+ | 70 => self:to_end() # end
+ | _ => :nil
+
+ return :nil
+ end
+
+ # ESC, start a sequence
+ if byte == 27 do
+ self.esc = 1
return :nil
end
- if byte == 27 do self.esc = 1 return :nil end # ESC, start a sequence
- if byte == 10 do self:submit() return :nil end # enter
- if byte == 8 do self:backspace() return :nil end # bs
- if byte == 127 do self:erase_word() return :nil end # del (ctrl-bs): erase word
- if byte == 1 do self:home() return :nil end # ctrl-a
- if byte == 5 do self:to_end() return :nil end # ctrl-e
- if byte == 3 do self:cancel() return :nil end # ctrl-c
- if byte == 12 do self:clear_screen() return :nil end # ctrl-l
- if byte == 21 do self:kill() return :nil end # ctrl-u
- if byte == 23 do self:erase_word() return :nil end # ctrl-w
- if byte < 32 return :nil # ctrl-d and other ctrls: ignore
- if byte > 126 return :nil
- self:insert(string.of_ascii(byte))
+ match byte
+ | 10 => self:submit() # enter
+ | 8 => self:backspace() # bs
+ | 127 => self:erase_word() # del (ctrl-bs)
+ | 1 => self:home() # ctrl-a
+ | 5 => self:to_end() # ctrl-e
+ | 3 => self:cancel() # ctrl-c
+ | 12 => self:clear_screen() # ctrl-l
+ | 21 => self:kill() # ctrl-u
+ | 23 => self:erase_word() # ctrl-w
+ | _ => do
+ # ctrl-d and other shits
+ if (byte < 32)
+ return :nil
+ if (byte > 126)
+ return :nil
+ self:insert(string.of_ascii(byte))
+ end
end,
}
diff --git a/kernel/vfs.rv b/kernel/vfs.rv
index 22c399e..6df71cc 100644
--- a/kernel/vfs.rv
+++ b/kernel/vfs.rv
@@ -3,35 +3,51 @@
const TASK_STATES = { "free", "ready", "dead", "blocked" }
-global vfs_owns = fn(path) do
- if path == "/proc" or path:starts_with?("/proc/") return :true
+global vfs_owns = fn(path) -> bool do
+ if (path == "/proc" or path:starts_with?("/proc/"))
+ return :true
return :false
end
-global parse_pid = fn(text) do
- if text:len() == 0 return -1
+global parse_pid = fn(text) -> num do
+ if (text:len() == 0)
+ return -1
+
let number = 0
for index in 0..text:len() do
const code = text[index]:ascii()
- if code < 48 or code > 57 return -1
+ if (code < 48 or code > 57)
+ return -1
number = number * 10 + (code - 48)
end
+
return number
end
global vfs_ls = fn(path) do
if path == "/proc" do
puts(" uptime\n meminfo\n")
+
for pid in 0..task_max() do
- if task_state(pid) != 0 puts(" #{pid}\n")
+ if (task_state(pid) != 0)
+ puts(" #{pid}\n")
end
+ end else do
+ puts("ls: #{path}: no such directory\n")
end
- else do puts("ls: #{path}: no such directory\n") end
end
global vfs_cat = fn(path) do
- if path == "/proc/uptime" do puts("#{math.floor(uptime() / 100)}s\n") return :nil end
- if path == "/proc/meminfo" do puts("#{(mem_free() shr 20)} MiB free / #{(mem_total() shr 20)} MiB total\n") return :nil end
+ if path == "/proc/uptime" do
+ puts("#{math.floor(uptime() / 100)}s\n")
+ return :nil
+ end
+
+ if path == "/proc/meminfo" do
+ puts("#{(mem_free() shr 20)} MiB free / #{(mem_total() shr 20)} MiB total\n")
+ return :nil
+ end
+
if path:starts_with?("/proc/") do
const pid = parse_pid(path[6..])
if pid >= 0 and pid < task_max() and task_state(pid) != 0 do
@@ -41,5 +57,6 @@ global vfs_cat = fn(path) do
puts("cat: #{path}: no such file\n")
return :nil
end
+
puts("cat: #{path}: no such file\n")
end
diff --git a/kernel/vmm.rv b/kernel/vmm.rv
index 0de5f33..54d1695 100644
--- a/kernel/vmm.rv
+++ b/kernel/vmm.rv
@@ -2,22 +2,28 @@
# everything here only writes small entries we construct, so its f64 safe
const PTE_ADDR = 0x000FFFFFFFFFF000
-fn pte_index(virtual_address, level) (virtual_address shr (12 + 9 * level)) band 0x1ff
+fn pte_index(virtual_address, level) -> num do
+ return (virtual_address shr (12 + 9 * level)) band 0x1ff
+end
-fn next_table(table, index) do
+fn next_table(table, index) -> num do
const slot = table + index * 8
const entry = mem_read(slot, 8)
- if (entry band 1) != 0 return entry band PTE_ADDR
+ if (entry band 1) != 0 do
+ return entry band PTE_ADDR
+ end
+
const frame = frame_alloc()
mem_zero(frame, 4096)
mem_write(slot, frame bor 7, 8) # present | write | user
- frame
+ return frame
end
fn as_map(pml4, virtual_address, physical_address, flags) do
const pdpt = next_table(pml4, pte_index(virtual_address, 3))
const pd = next_table(pdpt, pte_index(virtual_address, 2))
const pt = next_table(pd, pte_index(virtual_address, 1))
+
mem_write(pt + pte_index(virtual_address, 0) * 8, (physical_address band PTE_ADDR) bor flags bor 1, 8)
invlpg(virtual_address)
end