1
0
Fork 0
forked from AbleOS/ableos

PS/2 work

This commit is contained in:
peony 2024-11-10 10:59:01 +01:00
commit 52b6272439
40 changed files with 938 additions and 480 deletions

151
Cargo.lock generated
View file

@ -17,21 +17,6 @@ version = "0.2.18"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f" checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f"
[[package]]
name = "android-tzdata"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0"
[[package]]
name = "android_system_properties"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311"
dependencies = [
"libc",
]
[[package]] [[package]]
name = "anyhow" name = "anyhow"
version = "1.0.93" version = "1.0.93"
@ -97,9 +82,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
[[package]] [[package]]
name = "cc" name = "cc"
version = "1.1.36" version = "1.1.37"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baee610e9452a8f6f0a1b6194ec09ff9e2d85dea54432acdae41aa0761c95d70" checksum = "40545c26d092346d8a8dab71ee48e7685a7a9cba76e634790c215b41a4a7b4cf"
dependencies = [ dependencies = [
"shlex", "shlex",
] ]
@ -110,26 +95,6 @@ version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "chrono"
version = "0.4.38"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401"
dependencies = [
"android-tzdata",
"iana-time-zone",
"js-sys",
"num-traits",
"wasm-bindgen",
"windows-targets",
]
[[package]]
name = "core-foundation-sys"
version = "0.8.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b"
[[package]] [[package]]
name = "crossbeam-queue" name = "crossbeam-queue"
version = "0.3.11" version = "0.3.11"
@ -208,7 +173,6 @@ checksum = "05669f8e7e2d7badc545c513710f0eba09c2fbef683eb859fd79c46c355048e0"
dependencies = [ dependencies = [
"bitflags 1.3.2", "bitflags 1.3.2",
"byteorder", "byteorder",
"chrono",
"log", "log",
] ]
@ -264,12 +228,12 @@ dependencies = [
[[package]] [[package]]
name = "hbbytecode" name = "hbbytecode"
version = "0.1.0" version = "0.1.0"
source = "git+https://git.ablecorp.us/AbleOS/holey-bytes.git#0374848b283f29547625c76e7629d5d61bac3109" source = "git+https://git.ablecorp.us/AbleOS/holey-bytes.git#a299bad75b068f565e6e10b6c3501a9422e283c4"
[[package]] [[package]]
name = "hblang" name = "hblang"
version = "0.1.0" version = "0.1.0"
source = "git+https://git.ablecorp.us/AbleOS/holey-bytes.git#0374848b283f29547625c76e7629d5d61bac3109" source = "git+https://git.ablecorp.us/AbleOS/holey-bytes.git#a299bad75b068f565e6e10b6c3501a9422e283c4"
dependencies = [ dependencies = [
"hashbrown 0.15.1", "hashbrown 0.15.1",
"hbbytecode", "hbbytecode",
@ -281,34 +245,11 @@ dependencies = [
[[package]] [[package]]
name = "hbvm" name = "hbvm"
version = "0.1.0" version = "0.1.0"
source = "git+https://git.ablecorp.us/AbleOS/holey-bytes.git#0374848b283f29547625c76e7629d5d61bac3109" source = "git+https://git.ablecorp.us/AbleOS/holey-bytes.git#a299bad75b068f565e6e10b6c3501a9422e283c4"
dependencies = [ dependencies = [
"hbbytecode", "hbbytecode",
] ]
[[package]]
name = "iana-time-zone"
version = "0.1.61"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "235e081f3925a06703c2d0117ea8b91f042756fd6e7a6e5d901e8ca1a996b220"
dependencies = [
"android_system_properties",
"core-foundation-sys",
"iana-time-zone-haiku",
"js-sys",
"wasm-bindgen",
"windows-core",
]
[[package]]
name = "iana-time-zone-haiku"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f"
dependencies = [
"cc",
]
[[package]] [[package]]
name = "icu_collections" name = "icu_collections"
version = "1.5.0" version = "1.5.0"
@ -458,15 +399,6 @@ dependencies = [
"hashbrown 0.15.1", "hashbrown 0.15.1",
] ]
[[package]]
name = "js-sys"
version = "0.3.72"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6a88f1bda2bd75b0452a14784937d796722fdebfe50df998aeb3f0b7603019a9"
dependencies = [
"wasm-bindgen",
]
[[package]] [[package]]
name = "kernel" name = "kernel"
version = "0.2.0" version = "0.2.0"
@ -567,15 +499,6 @@ version = "2.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
[[package]]
name = "num-traits"
version = "0.2.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841"
dependencies = [
"autocfg",
]
[[package]] [[package]]
name = "once_cell" name = "once_cell"
version = "1.20.2" version = "1.20.2"
@ -986,61 +909,6 @@ version = "0.11.0+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
[[package]]
name = "wasm-bindgen"
version = "0.2.95"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "128d1e363af62632b8eb57219c8fd7877144af57558fb2ef0368d0087bddeb2e"
dependencies = [
"cfg-if",
"once_cell",
"wasm-bindgen-macro",
]
[[package]]
name = "wasm-bindgen-backend"
version = "0.2.95"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cb6dd4d3ca0ddffd1dd1c9c04f94b868c37ff5fac97c30b97cff2d74fce3a358"
dependencies = [
"bumpalo",
"log",
"once_cell",
"proc-macro2",
"quote",
"syn",
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-macro"
version = "0.2.95"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e79384be7f8f5a9dd5d7167216f022090cf1f9ec128e6e6a482a2cb5c5422c56"
dependencies = [
"quote",
"wasm-bindgen-macro-support",
]
[[package]]
name = "wasm-bindgen-macro-support"
version = "0.2.95"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "26c6ab57572f7a24a4985830b120de1594465e5d500f24afe89e16b4e833ef68"
dependencies = [
"proc-macro2",
"quote",
"syn",
"wasm-bindgen-backend",
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-shared"
version = "0.2.95"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "65fc09f10666a9f147042251e0dda9c18f166ff7de300607007e96bdebc1068d"
[[package]] [[package]]
name = "webpki-roots" name = "webpki-roots"
version = "0.26.6" version = "0.26.6"
@ -1050,15 +918,6 @@ dependencies = [
"rustls-pki-types", "rustls-pki-types",
] ]
[[package]]
name = "windows-core"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9"
dependencies = [
"windows-targets",
]
[[package]] [[package]]
name = "windows-sys" name = "windows-sys"
version = "0.52.0" version = "0.52.0"

View file

@ -24,10 +24,6 @@ version = "0.3"
default-features = false default-features = false
features = ["alloc", "nightly"] features = ["alloc", "nightly"]
# [dependencies.clparse]
# git = "https://git.ablecorp.us/ableos/ableos_userland"
# default-features = false
[dependencies.derive_more] [dependencies.derive_more]
version = "1" version = "1"
default-features = false default-features = false

View file

@ -36,13 +36,26 @@ impl log::Log for Logger {
Level::Debug => "25", Level::Debug => "25",
Level::Trace => "103", Level::Trace => "103",
}; };
let module = record.module_path().unwrap_or_default(); let module = record
let line = record.line().unwrap_or_default(); .module_path()
crate::arch::log(format_args!( .unwrap_or_default()
"\x1b[38;5;{lvl_color}m{lvl}\x1b[0m [{module}:{line}]: {}\r\n", .rsplit_once(':')
record.args(), .unwrap_or_default()
)) .1;
.expect("write to serial console"); if module == "" {
crate::arch::log(format_args!(
"\x1b[38;5;{lvl_color}m{lvl}\x1b[0m: {}\r\n",
record.args(),
))
.expect("write to serial console");
} else {
let line = record.line().unwrap_or_default();
crate::arch::log(format_args!(
"\x1b[38;5;{lvl_color}m{lvl}\x1b[0m [{module}:{line}]: {}\r\n",
record.args(),
))
.expect("write to serial console");
}
} }
fn flush(&self) {} fn flush(&self) {}

View file

@ -6,29 +6,15 @@ edition = "2021"
[dependencies] [dependencies]
str-reader = "0.1" str-reader = "0.1"
derive_more = { version = "1", default-features = false, features = [ derive_more = { version = "1", default-features = false, features = [
"add",
"add_assign",
"constructor",
"display", "display",
"from",
"into",
"mul",
"mul_assign",
"not",
"sum",
] } ] }
error-stack = "0.5" error-stack = "0.5"
fatfs = "0.3" fatfs = { version = "0.3", default-features = false, features = [
toml = "0.8"
hblang = { git = "https://git.ablecorp.us/AbleOS/holey-bytes.git", features = [
"std", "std",
# "opts", "alloc",
], default-features = false } ] }
toml = "0.8"
hblang.git = "https://git.ablecorp.us/AbleOS/holey-bytes.git"
log = "0.4" log = "0.4"
raw-cpuid = "11" raw-cpuid = "11"
ureq = { version = "2", default-features = false, features = ["tls"] } ureq = { version = "2", default-features = false, features = ["tls"] }
# [dependencies.reqwest]
# version = "0.12"
# default-features = false
# features = ["rustls-tls", "blocking"]

View file

@ -62,31 +62,20 @@ impl Package {
build_cmd, build_cmd,
} }
} }
pub fn build(&self) -> std::io::Result<()> { pub fn build(&self, out: &mut Vec<u8>) -> std::io::Result<()> {
if self.binaries.contains(&"hblang".to_string()) { if self.binaries.contains(&"hblang".to_string()) {
let file = self.build_cmd.split_ascii_whitespace().last().unwrap(); let file = self.build_cmd.split_ascii_whitespace().last().unwrap();
let path = format!("sysdata/programs/{}/{}", self.name, file); let path = format!("sysdata/programs/{}/{}", self.name, file);
let mut bytes = Vec::new();
// compile here // compile here
hblang::run_compiler( hblang::run_compiler(
&path, &path,
Options { Options {
fmt: true, fmt: true,
// optimize: true,
..Default::default() ..Default::default()
}, },
&mut bytes, out,
)?;
hblang::run_compiler(
&path,
Options {
// optimize: true,
..Default::default()
},
&mut bytes,
)?; )?;
match std::fs::create_dir("target/programs") { match std::fs::create_dir("target/programs") {
@ -94,18 +83,27 @@ impl Package {
Err(e) if e.kind() == std::io::ErrorKind::AlreadyExists => (), Err(e) if e.kind() == std::io::ErrorKind::AlreadyExists => (),
Err(e) => panic!("{}", e), Err(e) => panic!("{}", e),
} }
std::fs::write(format!("target/programs/{}.hbf", self.name), &bytes).unwrap();
bytes.clear(); hblang::run_compiler(
&path,
Options {
..Default::default()
},
out,
)?;
std::fs::write(format!("target/programs/{}.hbf", self.name), &out)?;
out.clear();
hblang::run_compiler( hblang::run_compiler(
&path, &path,
Options { Options {
dump_asm: true, dump_asm: true,
// optimize: true,
..Default::default() ..Default::default()
}, },
&mut bytes, out,
)?; )?;
std::fs::write(format!("target/programs/{}.hba", self.name), &bytes).unwrap(); std::fs::write(format!("target/programs/{}.hba", self.name), &out)?;
out.clear();
} }
Ok(()) Ok(())
} }

View file

@ -1,6 +1,7 @@
mod dev; mod dev;
use { use {
core::fmt::Write as _,
derive_more::Display, derive_more::Display,
dev::Package, dev::Package,
error_stack::{bail, report, Context, Report, Result, ResultExt}, error_stack::{bail, report, Context, Report, Result, ResultExt},
@ -204,6 +205,9 @@ TERM_BACKDROP={}
let modules = value.get_mut("modules").unwrap().as_table_mut().unwrap(); let modules = value.get_mut("modules").unwrap().as_table_mut().unwrap();
// let mut real_modules = modules.clone(); // let mut real_modules = modules.clone();
let mut errors = String::new();
let mut out = Vec::new();
modules modules
.into_iter() .into_iter()
.map(|(_, value)| -> Result<(), io::Error> { .map(|(_, value)| -> Result<(), io::Error> {
@ -218,11 +222,26 @@ TERM_BACKDROP={}
let p = Package::load_from_file( let p = Package::load_from_file(
format!("sysdata/programs/{}/meta.toml", path).to_owned(), format!("sysdata/programs/{}/meta.toml", path).to_owned(),
); );
p.build()?; match p.build(&mut out) {
Ok(()) => {}
Err(_) => {
writeln!(errors, "========= while compiling {} =========", path)
.unwrap();
errors.push_str(core::str::from_utf8(&out).expect("no"));
out.clear();
}
}
} }
Ok(()) Ok(())
}) })
.for_each(drop); .for_each(drop);
if !errors.is_empty() {
let _ = writeln!(errors, "!!! STOPPING DUE TO PREVIOUS ERRORS !!!");
std::eprint!("{errors}");
continue;
}
modules.into_iter().for_each(|(_key, value)| { modules.into_iter().for_each(|(_key, value)| {
if value.is_table() { if value.is_table() {
let path = value.get("path").expect("You must have `path` as a value"); let path = value.get("path").expect("You must have `path` as a value");

View file

@ -0,0 +1,4 @@
(horizontal
spacing : 10
(label "hi")
(label "goodbye"))

View file

@ -0,0 +1 @@
(label "hello")

View file

@ -0,0 +1,3 @@
(vertical
(label "hello")
(label "hello" color:red))

View file

@ -5,7 +5,8 @@ render := @use("../../../libraries/render/src/lib.hb")
input := @use("../../intouch/src/lib.hb") input := @use("../../intouch/src/lib.hb")
widgets := @use("widgets.hb") widgets := @use("widgets/widgets.hb")
ui := @use("ui.hb")
WindowID := struct { WindowID := struct {
host_id: int, host_id: int,

View file

@ -0,0 +1,47 @@
stn := @use("../../../libraries/stn/src/lib.hb");
.{string, log} := stn;
.{Vec2} := stn.math
render := @use("../../../libraries/render/src/lib.hb");
.{Surface} := render;
.{Font} := render.text
UI := struct {raw: ^u8, raw_length: uint, is_dirty: bool, surface: Surface, // Each child has their WidgetType as their first byte
// children: ^^u8,
}
render_ui := fn(surface: Surface, ui: UI): void {
if ui.is_dirty {
render.clear(ui.surface, render.black)
ui.is_dirty = false
}
pos := Vec2(uint).(0, 0)
render.put_surface(surface, ui.surface, pos, false)
}
sexpr_parser := fn(sexpr: ^u8): UI {
cursor := sexpr
paren_balance := 0
loop {
if *cursor == 0 {
if paren_balance != 0 {
log.error("Unbalanced Parens\0")
}
break
} else if *cursor == 40 {
log.info("Open paren\0")
paren_balance += 1
} else if *cursor == 41 {
log.info("Closed paren\0")
paren_balance -= 1
}
cursor += 1
}
length := string.length(sexpr)
ui_surface := render.new_surface(100, 100)
return UI.(sexpr, length, true, ui_surface)
}

View file

@ -1,20 +0,0 @@
// Widget types
// End types
LayoutChildHorizontalFirst := 0
LayoutChildVerticalFirst := 1
Size := struct {
min_width: int,
max_width: int,
min_height: int,
max_height: int,
}
Widget := struct {
size: Size,
clickable: bool,
layout: u8,
a: bool,
}

View file

@ -0,0 +1,5 @@
Image := struct {
magic: uint,
is_dirty: bool,
surface: Surface,
}

View file

@ -0,0 +1,38 @@
stn := @use("../../../../libraries/stn/src/lib.hb");
.{string, log} := stn;
.{Vec2} := stn.math
render := @use("../../../../libraries/render/src/lib.hb");
.{Surface} := render;
.{Font} := render.text
Label := struct {
magic: uint,
is_dirty: bool,
surface: Surface,
text: ^u8,
text_length: uint,
}
set_label_text := fn(label: Label, text: ^u8): void {
text_length := string.length(text)
label.is_dirty = true
label.text = text
label.text_length = text_length
}
render_label_to_surface := fn(surface: Surface, label: Label, font: Font, pos: Vec2(uint)): void {
if label.is_dirty {
render.clear(label.surface, render.black)
render.put_text(label.surface, font, .(0, 0), render.white, label.text)
}
render.put_surface(surface, label.surface, pos, false)
}
new_label := fn(text: ^u8): Label {
text_surface := render.new_surface(1000, 20)
text_length := string.length(text)
label := Label.(3, true, text_surface, text, text_length)
return label
}

View file

@ -0,0 +1,7 @@
NoWidget := 0
VerticalWidgetType := 1
HorizontalWidgetType := 2
LabelWidgetType := 3
ImageWidgetType := 4

View file

@ -0,0 +1,36 @@
// Widget types
// End types
stn := @use("../../../../libraries/stn/src/lib.hb");
.{string, log} := stn;
.{Vec2} := stn.math
render := @use("../../../../libraries/render/src/lib.hb");
.{Surface} := render;
.{Font} := render.text
widget_types := @use("widget_types.hb")
label := @use("label.hb")
image := @use("image.hb")
Size := struct {
min_width: int,
max_width: int,
min_height: int,
max_height: int,
}
Vertical := packed struct {
magic: uint,
// array of children, idk
// use a vec or linked list or whatever
children: ^^u8,
}
Horizontal := packed struct {
magic: uint,
// array of children, idk
// use a vec or linked list or whatever
children: ^^u8,
}

View file

@ -1,15 +1,39 @@
stn := @use("../../stn/src/lib.hb"); stn := @use("../../stn/src/lib.hb");
.{log, buffer} := stn .{log, buffer, memory} := stn
keycodes := @use("keycodes.hb")
events := @use("events.hb"); events := @use("events.hb");
.{KeyEvent, MouseEvent} := events .{KeyEvent, MouseEvent} := events
recieve_key_event := fn(): ?KeyEvent { recieve_key_event := fn(): ?KeyEvent {
buf := buffer.search("PS/2 Keyboard\0") mem_page := memory.request_page(1)
buf_id := buffer.search("PS/2 Keyboard\0")
// Read out of the keyboard buffer here // Read out of the keyboard buffer here
buffer.recv(KeyEvent, buf_id, mem_page)
key_event := KeyEvent.(0, 0, 2)
// return key_event
return null return null
} }
recieve_mouse_event := fn(): ?MouseEvent { recieve_mouse_event := fn(): ?MouseEvent {
return null mem_page := memory.request_page(1)
buf_id := buffer.search("PS/2 Mouse\0")
// Read out of the Mouse buffer here
buffer.recv(MouseEvent, buf_id, mem_page)
if *mem_page != 0 {
log.info("Mouse events\0")
dx := *mem_page
dy := *mem_page + 1
mevent := MouseEvent.(dx, dy, 0, 0, 0)
return mevent
}
// log.error("No mouse events\0")
return MouseEvent.(0, 0, 0, 0, 0)
} }

View file

@ -1,102 +0,0 @@
.{Color, Surface, new_surface} := @use("./lib.hb");
.{log, memory} := @use("../../stn/src/lib.hb")
BitmapFileHeader := packed struct {
img_type: u16,
size: u32,
reserved_1: u16,
reserved_2: u16,
offset: u32,
}
BitmapInfoHeader := packed struct {
size: u32,
width: i32,
height: i32,
planes: u16,
bits: u16,
compression: u32,
image_size: u32,
x_resolution: i32,
y_resolution: i32,
n_colours: u32,
important_colours: u32,
}
BitmapColorHeader := packed struct {
red_mask: u32,
green_mask: u32,
blue_mask: u32,
alpha_mask: u32,
color_space_type: u32,
unused: u32,
}
surface_from_bmp := fn(bmp: ^u8): ?Surface {
file_header := @as(^BitmapFileHeader, @bitcast(bmp))
if file_header.img_type != 0x4D42 {
log.error("failed to load bmp image: not a bmp image, idiot\0")
return null
}
info_header := @as(^BitmapInfoHeader, @bitcast(bmp + @sizeof(BitmapFileHeader)))
bmp += file_header.offset
px := info_header.width * info_header.height
ptr := @as(^Color, @bitcast(bmp))
tmp := @as(Color, idk)
row := @as(i32, 0)
loop if row == info_header.height / 2 break else {
col := @as(i32, 0)
loop if col == info_header.width break else {
top_index := row * info_header.width + col
bottom_index := (info_header.height - 1 - row) * info_header.width + col
tmp = *(ptr + top_index);
*(ptr + top_index) = *(ptr + bottom_index);
*(ptr + bottom_index) = tmp
col += 1
}
row += 1
}
return .(@bitcast(bmp), info_header.width, info_header.height)
}
new_surface_from_bmp := fn(bmp: ^u8): ?Surface {
file_header := @as(^BitmapFileHeader, @bitcast(bmp))
if file_header.img_type != 0x4D42 {
log.error("failed to load bmp image: not a bmp image, idiot\0")
return null
}
info_header := @as(^BitmapInfoHeader, @bitcast(bmp + @sizeof(BitmapFileHeader)))
bmp += file_header.offset
width := @as(uint, @intcast(info_header.width))
height := @as(uint, @intcast(info_header.height))
surface := new_surface(width, height)
top_start_idx := surface.buf
bottom_start_idx := surface.buf + width * (height - 1)
rows_to_copy := height
top_cursor := @as(^Color, @bitcast(bmp))
bottom_cursor := top_cursor + width * (height - 1)
loop if rows_to_copy <= 1 break else {
@inline(memory.copy, Color, top_cursor, bottom_start_idx, @bitcast(width))
@inline(memory.copy, Color, bottom_cursor, top_start_idx, @bitcast(width))
top_start_idx += surface.width
bottom_start_idx -= surface.width
top_cursor += width
bottom_cursor -= width
rows_to_copy -= 2
}
if rows_to_copy == 1 {
@inline(memory.copy, Color, top_cursor, top_start_idx, @bitcast(width))
}
return surface
}

View file

@ -0,0 +1,52 @@
.{Color, Surface, new_surface, put_surface} := @use("../lib.hb");
.{log, memory} := @use("../../../stn/src/lib.hb")
BitmapFileHeader := packed struct {
magic: u16,
size: u32,
reserved_1: u16,
reserved_2: u16,
offset: u32,
}
BitmapInfoHeader := packed struct {
size: u32,
width: i32,
height: i32,
planes: u16,
bits: u16,
compression: u32,
image_size: u32,
x_resolution: i32,
y_resolution: i32,
n_colours: u32,
important_colours: u32,
}
BitmapColorHeader := packed struct {
red_mask: u32,
green_mask: u32,
blue_mask: u32,
alpha_mask: u32,
color_space_type: u32,
unused: u32,
}
from := fn(bmp: ^u8): ?Surface {
file_header := @as(^BitmapFileHeader, @bitcast(bmp))
info_header := @as(^BitmapInfoHeader, @bitcast(bmp + @sizeof(BitmapFileHeader)))
bmp += file_header.offset
if file_header.magic != 0x4D42 | info_header.width == 0 | info_header.height == 0 {
log.error("Invalid BMP image.\0")
return null
}
width := @as(uint, info_header.width)
height := @as(uint, info_header.height)
lhs := Surface.(@bitcast(bmp), width, height)
rhs := new_surface(width, height)
put_surface(rhs, lhs, .(0, 0), true)
return rhs
}

View file

@ -0,0 +1,34 @@
.{log} := @use("../../../stn/src/lib.hb");
.{Surface} := @use("../lib.hb")
bmp := @use("bmp.hb")
qoi := @use("qoi.hb")
BMP := 0x4D42
QOI := 0x66696F71
// stand-in for null until bugfix
DOES_NOT_EXIST := 1 << 32
get_format := fn(file: ^u8): uint {
if *@as(^u16, @bitcast(file)) == BMP {
return BMP
} else if *@as(^u32, @bitcast(file)) == QOI {
return QOI
} else {
return DOES_NOT_EXIST
}
}
from := fn(file: ^u8): ?Surface {
format := get_format(file)
if format == DOES_NOT_EXIST {
log.error("Could not detect image format.\0")
return null
} else if format == BMP {
return bmp.from(file)
} else if format == QOI {
return qoi.from(file)
}
return null
}

View file

@ -0,0 +1,101 @@
.{Color, Surface, new_surface} := @use("../lib.hb");
.{log, memory} := @use("../../../stn/src/lib.hb")
/* source:
https://github.com/phoboslab/qoi/blob/master/qoi.h */
QOI_SRGB := 0
QOI_LINEAR := 1
QOI_OP_INDEX := 0x0
QOI_OP_DIFF := 0x40
QOI_OP_LUMA := 0x80
QOI_OP_RUN := 0xC0
QOI_OP_RGB := 0xFE
QOI_OP_RGBA := 0xFF
QOI_MASK_2 := 0xC0
QOI_COLOR_HASH := fn(c: Color): u8 {
return (c.r * 3 + c.g * 5 + c.b * 7 + c.a * 11) % 64
}
QOI_MAGIC := 0x716F6966
QOI_PIXELS_MAX := 400000000
QuiteOkayHeader := packed struct {
magic: u32,
width: u32,
height: u32,
channels: u8,
colorspace: u8,
}
be_to_le := fn(big: u32): u32 {
return (big & 0xFF000000) >> 24 | (big & 0xFF0000) >> 8 | (big & 0xFF00) << 8 | (big & 0xFF) << 24
}
from := fn(qoi: ^u8): ?Surface {
header := @as(^QuiteOkayHeader, @bitcast(qoi))
qoi += @sizeof(QuiteOkayHeader)
width := be_to_le(header.width)
height := be_to_le(header.height)
if be_to_le(header.magic) != QOI_MAGIC | width == 0 | height == 0 | header.channels < 3 | header.channels > 4 {
log.error("Invalid QOI image.\0")
return null
}
surface := new_surface(width, height)
index := @as([Color; 64], idk)
run := 0
px := Color.(0, 0, 0, 255)
px_pos := 0
total_pixels := width * height
loop if px_pos >= total_pixels break else {
if run > 0 {
run -= 1
} else {
b1 := *qoi
qoi += 1
if b1 == QOI_OP_RGB {
px.r = *qoi
px.g = *(qoi + 1)
px.b = *(qoi + 2)
qoi += 3
} else if b1 == QOI_OP_RGBA {
px.r = *qoi
px.g = *(qoi + 1)
px.b = *(qoi + 2)
px.a = *(qoi + 3)
qoi += 4
} else if (b1 & QOI_MASK_2) == QOI_OP_INDEX {
px = index[b1 & 0x3F]
} else if (b1 & QOI_MASK_2) == QOI_OP_DIFF {
px.r = px.r + (b1 >> 4 & 0x3) - 2 & 0xFF
px.g = px.g + (b1 >> 2 & 0x3) - 2 & 0xFF
px.b = px.b + (b1 & 0x3) - 2 & 0xFF
} else if (b1 & QOI_MASK_2) == QOI_OP_LUMA {
b2 := *qoi
vg := (b1 & 0x3F) - 32
px.r = px.r + vg - 8 + (b2 >> 4 & 0xF) & 0xFF
px.g = px.g + vg & 0xFF
px.b = px.b + vg - 8 + (b2 & 0xF) & 0xFF
qoi += 1
} else if (b1 & QOI_MASK_2) == QOI_OP_RUN {
run = b1 & 0x3F
}
index[@inline(QOI_COLOR_HASH, px)] = px
};
*(surface.buf + px_pos) = px
px_pos += 1
}
return surface
}

View file

@ -1,5 +1,5 @@
software := @use("software.hb") software := @use("software.hb")
image := @use("image.hb") image := @use("image/lib.hb")
text := @use("text.hb") text := @use("text.hb")
// default mode // default mode

View file

@ -1,10 +1,10 @@
.{math, memory, dt, log} := @use("../../stn/src/lib.hb"); .{math, memory, dt, log} := @use("../../stn/src/lib.hb");
.{Color, text} := @use("lib.hb"); .{Color, text} := @use("lib.hb");
.{get_glyph, Font} := text; .{get_glyph, get_glyph_unicode, Font, UNC_TABLE_SIZE} := text;
.{Vec2} := math .{Vec2} := math
// safety: don't use before init() or you will get a memory access violation // safety: don't use before init() or you will get a memory access violation
framebuffer := memory.dangling(^Color) framebuffer := memory.dangling(Color)
Surface := struct { Surface := struct {
buf: ^Color, buf: ^Color,
@ -442,29 +442,90 @@ put_text := fn(surface: Surface, font: Font, pos: Vec2(uint), color: Color, str:
current_char := str current_char := str
loop if *current_char == 0 break else { loop if *current_char == 0 break else {
if *current_char == 10 { glyph_data := memory.dangling(u8)
cursor.x = pos.x
cursor.y += font.height + font.line_gap if font.unicode != null {
code_point := @as(uint, 0)
first_byte := *current_char
num_bytes := 1
if (first_byte & 0x80) == 0 {
code_point = first_byte
} else if (first_byte & 0xE0) == 0xC0 {
num_bytes = 2
code_point = first_byte & 0x1F
} else if (first_byte & 0xF0) == 0xE0 {
num_bytes = 3
code_point = first_byte & 0xF
} else if (first_byte & 0xF8) == 0xF0 {
// handle later
current_char += 1
continue
} else {
current_char += 1
continue
}
valid_sequence := true
i := 1
loop if i >= num_bytes break else {
current_char += 1
// have to check twice due to odd compiler bug...?
if *current_char == 0 | (*current_char & 0xC0) != 0x80 {
valid_sequence = false
}
if valid_sequence == false {
break
}
code_point = code_point << 6 | *current_char & 0x3F
i += 1
}
if valid_sequence == false {
current_char += 1
continue
}
current_char += 1
if code_point == 10 {
cursor.x = pos.x
cursor.y += font.height + font.line_gap
continue
}
if code_point < UNC_TABLE_SIZE {
glyph_index := *(font.unicode + code_point)
if glyph_index == 0xFFFF {
continue
}
glyph_data = font.data + glyph_index * font.bytes_per_glyph
} else {
continue
}
} else {
if *current_char > font.num_glyphs {
continue
}
glyph_data = @inline(get_glyph, font, *current_char)
if *current_char == 10 {
cursor.x = pos.x
cursor.y += font.height + font.line_gap
current_char += 1
continue
}
current_char += 1 current_char += 1
continue
} }
glyph_data := @inline(get_glyph, font, @intcast(*current_char)) if cursor.y + font.height > surface.height break
// ! cool null check don't disable :dead:
// !! i disabled the cool null check because compiler
// if glyph_data == null {
// current_char += 1
// continue
// }
if cursor.x % surface.width + font.width >= surface.width { if cursor.x % surface.width + font.width >= surface.width {
cursor.x = pos.x cursor.x = pos.x
cursor.y += font.height + font.line_gap cursor.y += font.height + font.line_gap
} }
if cursor.y + font.height > surface.height break
dest := @inline(indexptr, surface, cursor.x, cursor.y) dest := @inline(indexptr, surface, cursor.x, cursor.y)
src := glyph_data
rows_remaining := font.height rows_remaining := font.height
loop if rows_remaining == 0 break else { loop if rows_remaining == 0 break else {
@ -479,7 +540,7 @@ put_text := fn(surface: Surface, font: Font, pos: Vec2(uint), color: Color, str:
} }
pixel_dest += 1 pixel_dest += 1
mask >>= 1 mask >>= 1
if mask == 0 { if mask == 0 & bits_remaining > 0 {
glyph_data += 1 glyph_data += 1
byte = *glyph_data byte = *glyph_data
mask = 0x80 mask = 0x80
@ -487,13 +548,14 @@ put_text := fn(surface: Surface, font: Font, pos: Vec2(uint), color: Color, str:
bits_remaining -= 1 bits_remaining -= 1
} }
glyph_data += 1 if mask != 0x80 {
glyph_data += 1
}
dest += surface.width dest += surface.width
rows_remaining -= 1 rows_remaining -= 1
} }
cursor.x += font.width + font.char_gap cursor.x += font.width + font.char_gap
current_char += 1
} }
return return

View file

@ -1,4 +1,4 @@
.{log} := @use("../../stn/src/lib.hb") .{log, memory} := @use("../../stn/src/lib.hb")
PSF1Header := packed struct { PSF1Header := packed struct {
magic: u16, magic: u16,
@ -23,9 +23,9 @@ Font := struct {
height: uint, height: uint,
num_glyphs: uint, num_glyphs: uint,
bytes_per_glyph: uint, bytes_per_glyph: uint,
has_unicode_table: bool,
line_gap: uint, line_gap: uint,
char_gap: uint, char_gap: uint,
unicode: ?^u16,
} }
font_from_psf1 := fn(psf: ^u8): ?Font { font_from_psf1 := fn(psf: ^u8): ?Font {
@ -43,13 +43,13 @@ font_from_psf1 := fn(psf: ^u8): ?Font {
header.character_size, header.character_size,
256, 256,
header.character_size, header.character_size,
false,
0, 0,
0, 0,
null,
) )
} }
font_from_psf2 := fn(psf: ^u8): ?Font { font_from_psf2 := fn(psf: ^u8, unicode: bool): ?Font {
header := @as(^PSF2Header, @bitcast(psf)) header := @as(^PSF2Header, @bitcast(psf))
if header.magic != 0x864AB572 { if header.magic != 0x864AB572 {
log.error("failed to load psf font: not a psf2 font, idiot\0") log.error("failed to load psf font: not a psf2 font, idiot\0")
@ -58,18 +58,105 @@ font_from_psf2 := fn(psf: ^u8): ?Font {
psf += header.header_size psf += header.header_size
return .( font := Font.(
psf, psf,
header.width, header.width,
header.height, header.height,
header.num_glyph, header.num_glyph,
header.bytes_per_glyph, header.bytes_per_glyph,
(header.flags & 1) != 0,
0, 0,
0, 0,
null,
) )
if (header.flags & 1) != 0 & unicode {
init_unicode(&font)
}
return font
} }
get_glyph := fn(font: Font, index: uint): ^u8 { get_glyph := fn(font: Font, index: u8): ^u8 {
return font.data + index * font.bytes_per_glyph return font.data + @as(uint, index) * font.bytes_per_glyph
}
UNC_TABLE_SIZE := 1 << 16
init_unicode := fn(font: ^Font): void {
font.unicode = memory.alloc(u16, UNC_TABLE_SIZE)
@inline(memory.set, u16, &0xFFFF, font.unicode, UNC_TABLE_SIZE)
table := font.data + font.num_glyphs * font.bytes_per_glyph
curr_glyph := @as(u16, 0)
loop if curr_glyph >= font.num_glyphs break else {
loop {
byte := *table
table += 1
if byte == 0xFF break
if byte == 0xFE {
continue
}
unicode := @as(uint, 0)
bytes_to_read := @as(uint, 1)
if (byte & 0x80) == 0 {
unicode = byte
} else if (byte & 0xE0) == 0xC0 {
unicode = byte & 0x1F
bytes_to_read = 2
} else if (byte & 0xF0) == 0xE0 {
unicode = byte & 0xF
bytes_to_read = 3
} else if (byte & 0xF8) == 0xF0 {
unicode = byte & 0x7
bytes_to_read = 4
} else {
continue
}
valid := true
loop if bytes_to_read <= 1 break else {
next_byte := *table
if (next_byte & 0xC0) != 0x80 {
valid = false
}
if valid == false {
break
}
unicode = unicode << 6 | next_byte & 0x3F
table += 1
bytes_to_read -= 1
}
if valid == false continue
if bytes_to_read == 4 {
if unicode < 0x10000 | unicode > 0x10FFFF continue
if unicode <= 0xFFFF {
if unicode < UNC_TABLE_SIZE {
*(@unwrap(font.unicode) + unicode) = curr_glyph
}
} else {
unicode -= 0x10000
high_surrogate := 0xD800 | unicode >> 10 & 0x3FF
low_surrogate := 0xDC00 | unicode & 0x3FF
if high_surrogate < UNC_TABLE_SIZE {
*(@unwrap(font.unicode) + high_surrogate) = curr_glyph
}
if low_surrogate < UNC_TABLE_SIZE {
*(@unwrap(font.unicode) + low_surrogate) = curr_glyph
}
}
} else {
if unicode < UNC_TABLE_SIZE {
*(@unwrap(font.unicode) + unicode) = curr_glyph
}
}
}
curr_glyph += 1
}
} }

View file

@ -1,6 +1,6 @@
string := @use("string.hb") string := @use("string.hb")
recv := fn($Expr: type, buffer_id: int, memory_map_location: ^u8): ?^Expr { recv := fn($Expr: type, buffer_id: int, memory_map_location: ^u8): void {
return @eca(4, buffer_id, memory_map_location, @sizeof(Expr)) return @eca(4, buffer_id, memory_map_location, @sizeof(Expr))
} }

File diff suppressed because one or more lines are too long

View file

@ -2,8 +2,8 @@ PAGE_SIZE := 4096
MAX_ALLOC := 0xFF MAX_ALLOC := 0xFF
MAX_FREE := 0xFF MAX_FREE := 0xFF
dangling := fn($Expr: type): Expr { dangling := fn($Expr: type): ^Expr {
return @bitcast(@sizeof(Expr)) return @bitcast(@alignof(Expr))
} }
calc_pages := fn($Expr: type, num: uint): uint { calc_pages := fn($Expr: type, num: uint): uint {

View file

@ -1,4 +1,3 @@
length := fn(ptr: ^u8): uint { length := fn(ptr: ^u8): uint {
len := 0 len := 0
loop if *(ptr + len) == 0 return len else len += 1 loop if *(ptr + len) == 0 return len else len += 1
@ -69,3 +68,54 @@ reverse := fn(s: ^u8): void {
} }
return return
} }
equals := fn(lhs: ^u8, rhs: ^u8): bool {
if lhs == rhs {
return true
}
i := 0
loop if *(lhs + i) != *(rhs + i) {
return false
} else if *lhs == 0 {
return true
} else {
i += 1
}
}
contains := fn(haystack: ^u8, needle: ^u8): bool {
haystack_len := @inline(length, haystack)
needle_len := @inline(length, needle)
if needle_len == 0 {
return true
}
if haystack_len < needle_len {
return false
}
max_start := haystack_len - needle_len
pos := 0
loop if pos > max_start break else {
is_match := true
offset := 0
loop if offset >= needle_len break else {
if *(haystack + pos + offset) != *(needle + offset) {
is_match = false
}
if is_match == false {
break
}
offset += 1
}
if is_match {
return true
}
pos += 1
}
return false
}

View file

@ -2,9 +2,14 @@ stn := @use("../../../libraries/stn/src/lib.hb");
.{string, memory, buffer, random, log} := stn; .{string, memory, buffer, random, log} := stn;
.{Vec2} := stn.math .{Vec2} := stn.math
horizon_api := @use("../../../libraries/horizon_api/src/lib.hb") horizon_api := @use("../../../libraries/horizon_api/src/lib.hb");
.{new_label, render_label_to_surface, set_label_text} := horizon_api.widgets.label;
.{sexpr_parser, render_ui} := horizon_api.ui
render := @use("../../../libraries/render/src/lib.hb");
.{Surface} := render;
.{Font} := render.text
render := @use("../../../libraries/render/src/lib.hb")
intouch := @use("../../../libraries/intouch/src/lib.hb") intouch := @use("../../../libraries/intouch/src/lib.hb")
Window := struct { Window := struct {
@ -28,20 +33,26 @@ main := fn(): int {
window := render.new_surface(screen.width / 3, screen.height / 3) window := render.new_surface(screen.width / 3, screen.height / 3)
x := 0
mem_buf := memory.request_page(1) mem_buf := memory.request_page(1)
color := random.any(render.Color) color := random.any(render.Color)
side := window.width / 8 side := window.width / 8
vel_inner := Vec2(int).(1, 1)
pos_inner := Vec2(uint).((window.width - side) / 2, (window.height - side) / 2)
str := "Window Title Bar\0"
// really we should null check but it is a bit broked // really we should null check but it is a bit broked
font := @unwrap(render.text.font_from_psf2(@bitcast(&psf))) font := @unwrap(render.text.font_from_psf2(@bitcast(&psf), false))
mouse_x := 0 mouse_x := 0
mouse_y := 0 mouse_y := 0
text_label := new_label("Hi\0")
// widgets := "()\0"
// ui := sexpr_parser(widgets)
mouse_event := intouch.recieve_mouse_event()
if mouse_event == null {
log.warn("null\0")
} else {
log.warn("not null\0")
}
loop { loop {
// Clear the screen // Clear the screen
@ -58,52 +69,44 @@ main := fn(): int {
// } // }
} }
// get input events from drivers via intouch
// key_event := intouch.recieve_key_event();
// log.info("before mouse event check\0");
{ {
// get input events from drivers via intouch // Note: MLokis, this inline halts the compiler forever
key_event := intouch.recieve_key_event() // mouse_event := @inline(intouch.recieve_mouse_event)
// Note: MLokis, this function returns null unless the mouse is moving
mouse_event := intouch.recieve_mouse_event() mouse_event := intouch.recieve_mouse_event()
//
if mouse_event != null {
log.warn("Mouse event recieved\0")
mouse_x += mouse_event.x_change
mouse_y += mouse_event.y_change
set_label_text(text_label, "Mouse Moved\0")
}
// render mouse // render mouse
render.put_rect(screen, .(mouse_x, mouse_y), .(20, 20), render.white) render.put_rect(screen, .(mouse_x, mouse_y), .(20, 20), render.white)
// Send events to focused window // Send events to focused window
} }
if pos_inner.x == 0 | pos_inner.x == window.width - side {
vel_inner.x = -vel_inner.x
color = random.any(render.Color)
}
if pos_inner.y == 20 | pos_inner.y == window.height - side {
vel_inner.y = -vel_inner.y
color = random.any(render.Color)
}
// TODO: Get windows out of a collection and iter through // TODO: Get windows out of a collection and iter through
window_count := 0
render.put_rect(screen, .(0, 0), .(screen.width - 1, screen.height - 1), render.white) render.put_rect(screen, .(0, 0), .(screen.width - 1, screen.height - 1), render.white)
// loop { {
// render.clear(window, render.black) // Scroll bar :ThumbsUp:
render.put_rect(screen, .(100, 100), .(100, 10), render.white)
render.put_filled_rect(screen, .(110, 100), .(20, 10), render.white)
// // Draw the decorators render.put_rect(screen, .(90, 110), .(10, 100), render.white)
// { render.put_filled_rect(screen, .(90, 120), .(10, 20), render.white)
// render.put_rect(window, .(0, 0), .(window.width - 1, window.height - 1), render.white) }
// render.put_rect(window, .(0, 0), .(window.width - 1, 20), render.white)
// render.put_text(window, font, .(window.width / 2, 1), render.white, str)
// }
// render.put_filled_rect(window, pos_inner, .(side, side), color)
// // Apply the image to the screen
// pos := Vec2(uint).(x, 100)
// render.put_surface(screen, window, pos, false)
// if window_count >= 1 {
// x = 0
// break
// }
// window_count += 1
// x += screen.width / 2
// }
pos_inner += @bitcast(vel_inner)
{
pos := Vec2(uint).(1, screen.height - 21)
render_label_to_surface(screen, text_label, font, pos)
}
// Sync the screen // Sync the screen
render.sync(screen) render.sync(screen)
} }

View file

@ -1,6 +1,9 @@
.{memory, buffer, log, string, math} := @use("../../../libraries/stn/src/lib.hb") .{memory, buffer, log, string, math} := @use("../../../libraries/stn/src/lib.hb")
Vec2 := math.Vec2 Vec2 := math.Vec2
intouch := @use("../../../libraries/intouch/src/lib.hb");
.{MouseEvent} := intouch.events
i9 := packed struct {sign: bool, value: u8} i9 := packed struct {sign: bool, value: u8}
Button := struct {id: u8} Button := struct {id: u8}
LeftButton := Button.(1) LeftButton := Button.(1)
@ -10,13 +13,13 @@ Button4 := Button.(8)
Button5 := Button.(16) Button5 := Button.(16)
mouse_moved := fn(delta: Vec2(i9)): void { mouse_moved := fn(delta: Vec2(i9)): void {
log.info("Mouse movement.\0") // log.info("Mouse movement.\0")
} }
button_event := fn(button: Button, pressed: bool): void { button_event := fn(button: Button, pressed: bool): void {
if pressed { if pressed {
log.info("Mouse-button pressed.\0") // log.info("Mouse-button pressed.\0")
} else { } else {
log.info("Mouse-button released.\0") // log.info("Mouse-button released.\0")
} }
} }
@ -91,10 +94,9 @@ set_up_mouse := fn(): void {
button_states := @as(u8, 0) button_states := @as(u8, 0)
main := fn(): int { main := fn(): int {
mouse_buffer := buffer.create("PS/2 Mouse\0")
format_page := memory.alloc(u8, 1024) format_page := memory.alloc(u8, 1024)
mouse_buffer := buffer.create("Mouse\0")
send_byte(0x64, 0xA8) send_byte(0x64, 0xA8)
log.info("Aux mouse device enabled.\0") log.info("Aux mouse device enabled.\0")
@ -130,7 +132,7 @@ main := fn(): int {
button_states ^= changes button_states ^= changes
log.info(string.display_int(status, format_page, 10)) // log.info(string.display_int(status, format_page, 10))
dx := i9.(false, 0) dx := i9.(false, 0)
dy := i9.(false, 0) dy := i9.(false, 0)
@ -142,7 +144,12 @@ main := fn(): int {
dy.sign = (status & 0x20) == 0 dy.sign = (status & 0x20) == 0
if dy.value != 0 & dx.value != 0 { if dy.value != 0 & dx.value != 0 {
mouse_moved(.(dx, dy)) y_change := dy.value
x_change := dx.value
event := MouseEvent.(x_change, y_change, 0, 0, 0)
buffer.write(MouseEvent, &event, mouse_buffer)
// mouse_moved(.(dx, dy))
} }
} }

Binary file not shown.

Before

Width:  |  Height:  |  Size: 100 KiB

After

Width:  |  Height:  |  Size: 100 KiB

View file

@ -1,38 +1,29 @@
.{Vec2} := @use("../../../../libraries/stn/src/lib.hb").math .{log} := @use("../../../../libraries/stn/src/lib.hb")
render := @use("../../../../libraries/render/src/lib.hb") render := @use("../../../../libraries/render/src/lib.hb")
/* expected result: /* expected result:
a cute image bounces around the screen */ a cute qoi image and a cute bmp image */
bmp_1 := @embed("./assets/able.bmp") qoi := @embed("./assets/mini.qoi")
bmp_2 := @embed("./assets/mini.bmp") bmp := @embed("./assets/mini.bmp")
example := fn(): void { example := fn(): void {
// strictly we should be null checking here but i am lazy
images := [render.Surface].(
@unwrap(render.image.surface_from_bmp(@bitcast(&bmp_1))),
@unwrap(render.image.surface_from_bmp(@bitcast(&bmp_2))),
)
screen := render.init(true) screen := render.init(true)
vel := Vec2(int).(1, 1) image_qoi := render.image.from(@bitcast(&qoi))
pos := Vec2(uint).(100, 100) image_bmp := render.image.from(@bitcast(&bmp))
n := 0
loop {
image := images[n]
render.put_surface(screen, image, pos, false)
render.sync(screen)
render.clear(screen, render.black)
if pos.x == 0 | pos.x == screen.width - image.width { if image_qoi == null {
vel.x = -vel.x log.error("failed to load qoi image for whatever reason\0")
n = 1 - n return
}
if pos.y == 0 | pos.y == screen.height - image.height {
vel.y = -vel.y
n = 1 - n
}
pos += @bitcast(vel)
} }
if image_bmp == null {
log.error("failed to load bmp image for whatever reason\0")
return
}
render.clear(screen, render.black)
render.put_surface(screen, image_bmp, .((screen.width - image_bmp.width * 3) / 2, (screen.height - image_bmp.height) / 2), false)
render.put_surface(screen, image_qoi, .((screen.width + image_qoi.width) / 2, (screen.height - image_qoi.height) / 2), false)
render.sync(screen)
return return
} }

View file

@ -1,37 +1,151 @@
.{memory, log, string} := @use("../../../../libraries/stn/src/lib.hb")
render := @use("../../../../libraries/render/src/lib.hb") render := @use("../../../../libraries/render/src/lib.hb")
/* expected result: /* expected result: almost-not-trash notepad app
extended unicode test */ very jank
-----------------
features:
- basic keys
- holding support with DAS
- visible cursor
- shift key support
*/
psf := @embed("../../../../consolefonts/tamsyn/10x20r.psf") psf := @embed("../../../../consolefonts/tamsyn/10x20r.psf")
is_shift_pressed := false
is_ctrl_pressed := false
$initial_delay := 50
$repeat_delay := 7
example := fn(): void { example := fn(): void {
screen := render.init(false) screen := render.init(true)
font := render.text.font_from_psf2(@bitcast(&psf)) window := render.new_surface(480, 340)
font := render.text.font_from_psf2(@bitcast(&psf), false)
str := "Extended unicode test: if font == null {
return
}
ABCDEFGHIJKLMNOPQRSTUVWXYZ msg := "sticky note:\n\0"
abcdefghijklmnopqrstuvwxyz msg_len := string.length(msg)
0123456789
!\"#$%&'()*+,-./:;<=>?@[]^_`{|}~ buf := memory.alloc(u8, 4096)
ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝÞß
àáâãäåæçèéêëìíîïðñòóôõöøùúûüýþÿ bottom := buf + msg_len
ĀāĂ㥹ĆćĈĉĊċČčĎďĐđĒēĔĕĖėĘęĚěĜĝĞğ
ĠġĢģĤĥĦħĨĩĪīĬĭĮįİıIJijĴĵĶķĸĹĺĻļĽľĿ @inline(memory.copy, u8, msg, buf, msg_len)
„‟†‡•‣․‥…‧ cursor := buf + msg_len;
₠₡₢₣₤₥₦₧₨₩₪₫€₭₮₯₰₱₲₳₴₵₶₷₸₹₺₻₼₽₾₿
∀∁∂∃∄∅∆∇∈∉∊∋∌∍∎∏∐∑−∓∔∕∖∗∘∙√∛∜∝∞∟ *cursor = 95
─│┌┐└┘├┤┬┴┼╋╭╮╯╰╱╲╳╴╵╶╷╸╹╺╻╼╽╾╿ draw_window(window, font, buf)
▀▁▂▃▄▅▆▇█▉▊▋▌▍▎▏▐░▒▓▔▕▖▗▘▙▚▛▜▝▞▟ draw_screen(screen, window);
■□▢▣▤▥▦▧▨▩▪▫▬▭▮▯▰▱▲△▴▵▶▷▸▹►▻▼▽▾▿◀◁◂◃◄◅◆◇◈◉◊○ *cursor = 32
←↑→↓↔↕↖↗↘↙↚↛↜↝↞↟↠↡↢↣↤↥↦↧↨↩↪↫↬↭↮↯↰↱↲↳↴↵↶↷↸↹↺↻
 、。〃〄々〆〇〈〉《》「」『』【】〒〓〔〕〖〗〘〙〚〛〜〝〞〟 memory.outb(96, 238)
✀✁✂✃✄✅✆✇✈✉✊✋✌✍✎✏✐✑✒✓✔✕✖✗✘✙✚✛✜✝✞✟ memory.outb(96, 238)
✠✡✢✣✤✥✦✧✨✩✪✫✬✭✮✯✰✱✲✳✴✵✶✷✸✹✺✻✼✽✾✿\0" memory.outb(96, 244)
prev_input := @as(u8, 0xFF)
current_key := @as(u8, 0)
holding_timer := 0
loop {
input := memory.inb(96)
if input != prev_input {
if (input & 0x80) != 0 {
if (input & 0x7F) == current_key {
current_key = 0
holding_timer = 0
} else if input == 0xAA | input == 0xB6 {
is_shift_pressed = false
} else if input == 0x9D {
is_ctrl_pressed = false
}
} else {
if input == 0x2A | input == 0x36 {
is_shift_pressed = true
} else if input == 0x1D {
is_ctrl_pressed = true
} else {
current_key = input
holding_timer = 1
cursor = handle_char(map_keys(current_key), cursor, bottom)
}
}
prev_input = input
}
if current_key != 0 & holding_timer > 0 {
holding_timer += 1
if holding_timer >= initial_delay {
cursor = handle_char(map_keys(current_key), cursor, bottom)
holding_timer = initial_delay - repeat_delay
}
};
*cursor = 95
draw_window(window, font, buf)
draw_screen(screen, window);
*cursor = 32
if holding_timer > 0 & current_key != 0 {
if (memory.inb(96) & 0x80) != 0 {
current_key = 0
holding_timer = 0
}
}
}
render.clear(screen, render.black)
render.put_text(screen, @unwrap(font), .(0, 0), render.white, str)
render.sync(screen)
return return
} }
handle_char := fn(char: u8, cursor: ^u8, bottom: ^u8): ^u8 {
if char == 0 {
return cursor
}
if is_ctrl_pressed & char == 48 {
cursor = bottom
} else if char != 0x8 {
*cursor = char
return cursor + 1
} else if char == 0xA {
*cursor = 32
cursor += 1;
*cursor = 92
return cursor + 1
} else if cursor > bottom {
cursor -= 1;
*cursor = 32
return cursor
}
return cursor
}
map_keys := fn(scancode: u8): u8 {
if is_shift_pressed {
return ps2_table[scancode + 0x40]
}
return ps2_table[scancode]
}
ps2_table := [u8].(0x0, 0x1B, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x2D, 0x3D, 0x8, 0x9, 0x71, 0x77, 0x65, 0x72, 0x74, 0x79, 0x75, 0x69, 0x6F, 0x70, 0x5B, 0x5D, 0xA, 0x0, 0x61, 0x73, 0x64, 0x66, 0x67, 0x68, 0x6A, 0x6B, 0x6C, 0x3B, 0x27, 0x60, 0x0, 0x5C, 0x7A, 0x78, 0x63, 0x76, 0x62, 0x6E, 0x6D, 0x2C, 0x2E, 0x2F, 0x0, 0x2A, 0x0, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1B, 0x21, 0x40, 0x23, 0x24, 0x25, 0x5E, 0x26, 0x2A, 0x28, 0x29, 0x5F, 0x2B, 0x8, 0x9, 0x51, 0x57, 0x45, 0x52, 0x54, 0x59, 0x55, 0x49, 0x4F, 0x50, 0x7B, 0x7D, 0xA, 0x0, 0x41, 0x53, 0x44, 0x46, 0x47, 0x48, 0x4A, 0x4B, 0x4C, 0x3A, 0x22, 0x7E, 0x0, 0x7C, 0x5A, 0x58, 0x43, 0x56, 0x42, 0x4E, 0x4D, 0x3C, 0x3E, 0x3F, 0x0, 0x0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
$padding := 7
draw_window := fn(window: render.Surface, font: render.text.Font, buf: ^u8): void {
render.clear(window, render.light_yellow)
line := font.height + font.line_gap + padding - 1
render.put_rect(window, .(0, 0), .(window.width - 1, window.height - 1), render.black)
loop if line >= window.height break else {
render.put_hline(window, line, padding, window.width - padding, render.yellow)
line += font.height + font.line_gap
}
render.put_text(window, font, .(padding, padding), render.black, buf)
}
draw_screen := fn(screen: render.Surface, window: render.Surface): void {
render.clear(screen, render.light_blue)
render.put_surface(screen, window, .(100, 100), false)
render.sync(screen)
}

View file

@ -0,0 +1 @@
# test_abc

View file

@ -0,0 +1,11 @@
[package]
name = "test_abc"
authors = [""]
[dependants.libraries]
[dependants.binaries]
hblang.version = "1.0.0"
[build]
command = "hblang src/main.hb"

View file

@ -0,0 +1,19 @@
stn := @use("../../../libraries/stn/src/lib.hb");
.{log} := stn
Structure := struct {}
returner_fn := fn(): ?Structure {
structure := Structure.()
return structure
}
main := fn(): int {
ret := returner_fn()
if ret != null {
log.info("not null\0")
return 1
}
return 0
}

View file

@ -50,8 +50,8 @@ path = "boot:///horizon.hbf"
# [boot.limine.ableos.modules.svga_driver] # [boot.limine.ableos.modules.svga_driver]
# path = "boot:///svga_driver.hbf" # path = "boot:///svga_driver.hbf"
[boot.limine.ableos.modules.ps2_keyboard_driver] # [boot.limine.ableos.modules.ps2_keyboard_driver]
path = "boot:///ps2_keyboard_driver.hbf" # path = "boot:///ps2_keyboard_driver.hbf"
# [boot.limine.ableos.modules.filesystem_fat32] # [boot.limine.ableos.modules.filesystem_fat32]
# path = "boot:///filesystem_fat32.hbf" # path = "boot:///filesystem_fat32.hbf"
@ -59,5 +59,11 @@ path = "boot:///ps2_keyboard_driver.hbf"
# [boot.limine.ableos.modules.pumpkin_print] # [boot.limine.ableos.modules.pumpkin_print]
# path = "boot:///pumpkin_print.hbf" # path = "boot:///pumpkin_print.hbf"
# [boot.limine.ableos.modules.mouse_test] [boot.limine.ableos.modules.ps2_mouse_driver]
# path = "boot:///mouse_test.hbf" path = "boot:///ps2_mouse_driver.hbf"
# [boot.limine.ableos.modules.app_bar]
# path = "boot:///app_bar.hbf"
# [boot.limine.ableos.modules.test_abc]
# path = "boot:///test_abc.hbf"