From 96c2bd5cd550fb224bd9c1f6bbd3aee90f17775f Mon Sep 17 00:00:00 2001 From: koniifer <aurlex1@gmail.com> Date: Sun, 13 Oct 2024 23:38:43 +0100 Subject: [PATCH] bitmap image support & better mem opts restructure render lib add peony's render api additions and example add image example fix some dubious bugs i had made in unused code in mem_serve.rs remove tetris stub (now in peony's fork) update hblang --- Cargo.lock | 6 +- kernel/src/holeybytes/ecah.rs | 8 +- .../holeybytes/kernel_services/mem_serve.rs | 65 ++++-- kernel/src/holeybytes/mem.rs | 1 - repbuild/src/main.rs | 7 +- sysdata/libraries/dt_api/src/lib.hb | 2 +- sysdata/libraries/render/src/image.hb | 51 +++++ sysdata/libraries/render/src/lib.hb | 50 ++--- sysdata/libraries/render/src/software.hb | 185 ++++++++---------- sysdata/libraries/render/src/svga.hb | 36 ++-- sysdata/libraries/stn/src/memory.hb | 31 +++ .../render_example/src/examples/image.hb | 31 +++ .../render_example/src/examples/mini.bmp | Bin 0 -> 102454 bytes .../src/examples/tactical_screen.hb | 83 ++++++++ sysdata/programs/render_example/src/main.hb | 2 +- sysdata/programs/tetris/meta.toml | 11 -- sysdata/programs/tetris/src/main.hb | 15 -- 17 files changed, 373 insertions(+), 211 deletions(-) create mode 100644 sysdata/libraries/render/src/image.hb create mode 100644 sysdata/programs/render_example/src/examples/image.hb create mode 100644 sysdata/programs/render_example/src/examples/mini.bmp create mode 100644 sysdata/programs/render_example/src/examples/tactical_screen.hb delete mode 100644 sysdata/programs/tetris/meta.toml delete mode 100644 sysdata/programs/tetris/src/main.hb diff --git a/Cargo.lock b/Cargo.lock index bfd0b3e..25cd7bf 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -350,12 +350,12 @@ checksum = "1e087f84d4f86bf4b218b927129862374b72199ae7d8657835f1e89000eea4fb" [[package]] name = "hbbytecode" version = "0.1.0" -source = "git+https://git.ablecorp.us/AbleOS/holey-bytes.git#6d7e726066109e8b08f049bbc4684bba2a2eb88a" +source = "git+https://git.ablecorp.us/AbleOS/holey-bytes.git#c9b85f9004b7a5d4a4cad68bdf4eb2c1e75d811e" [[package]] name = "hblang" version = "0.1.0" -source = "git+https://git.ablecorp.us/AbleOS/holey-bytes.git#6d7e726066109e8b08f049bbc4684bba2a2eb88a" +source = "git+https://git.ablecorp.us/AbleOS/holey-bytes.git#c9b85f9004b7a5d4a4cad68bdf4eb2c1e75d811e" dependencies = [ "hashbrown 0.15.0", "hbbytecode", @@ -367,7 +367,7 @@ dependencies = [ [[package]] name = "hbvm" version = "0.1.0" -source = "git+https://git.ablecorp.us/AbleOS/holey-bytes.git#6d7e726066109e8b08f049bbc4684bba2a2eb88a" +source = "git+https://git.ablecorp.us/AbleOS/holey-bytes.git#c9b85f9004b7a5d4a4cad68bdf4eb2c1e75d811e" dependencies = [ "hbbytecode", ] diff --git a/kernel/src/holeybytes/ecah.rs b/kernel/src/holeybytes/ecah.rs index 8d67692..0d077d3 100644 --- a/kernel/src/holeybytes/ecah.rs +++ b/kernel/src/holeybytes/ecah.rs @@ -97,7 +97,8 @@ pub fn handler(vm: &mut Vm) { match msg_type { 0 => unsafe { let size = msg_vec[1]; - let addr = u16::from_le_bytes(msg_vec[2..4].try_into().unwrap()); + let addr = + u16::from_le_bytes(msg_vec[2..4].try_into().unwrap_unchecked()); let value = match size { 0 => x86_in::<u8>(addr) as u64, 1 => x86_in::<u16>(addr) as u64, @@ -109,7 +110,8 @@ pub fn handler(vm: &mut Vm) { }, 1 => unsafe { let size = msg_vec[1]; - let addr = u16::from_le_bytes(msg_vec[2..4].try_into().unwrap()); + let addr = + u16::from_le_bytes(msg_vec[2..4].try_into().unwrap_unchecked()); // info!("Setting address {}", addr); match size { @@ -173,7 +175,7 @@ pub fn handler(vm: &mut Vm) { Ok(msg) => msg, Err(_) => return, }; - if msg.len() > max_length.try_into().unwrap() { + if msg.len() > unsafe { max_length.try_into().unwrap_unchecked() } { info!("{}", max_length); error!("Message is too long to map in."); } else { diff --git a/kernel/src/holeybytes/kernel_services/mem_serve.rs b/kernel/src/holeybytes/kernel_services/mem_serve.rs index 935ca9b..e99a1aa 100644 --- a/kernel/src/holeybytes/kernel_services/mem_serve.rs +++ b/kernel/src/holeybytes/kernel_services/mem_serve.rs @@ -32,40 +32,37 @@ pub fn memory_msg_handler( let msg_vec = block_read(mem_addr, length); let msg_type = msg_vec[0]; match msg_type { - 0 => { + 0 => unsafe { let page_count = msg_vec[1]; let mptr_raw: [u8; 8] = msg_vec[2..10].try_into().unwrap(); let mptr: u64 = u64::from_le_bytes(mptr_raw); log::debug!("Allocating {} pages @ {:x}", page_count, mptr); - let ptr = unsafe { - alloc(Layout::from_size_align_unchecked( - page_count as usize * 4096, - 4096, - )) - }; + let ptr = alloc(Layout::from_size_align_unchecked( + page_count as usize * 4096, + 4096, + )); vm.registers[1] = hbvm::value::Value(ptr as u64); log::debug!("Kernel ptr: {:x}", ptr as u64); - } + }, - 1 => { + 1 => unsafe { let page_count = msg_vec[1]; let mptr_raw: [u8; 8] = msg_vec[2..10].try_into().unwrap(); let mptr: u64 = u64::from_le_bytes(mptr_raw); log::debug!("Deallocating {} pages @ {:x}", page_count, mptr); - unsafe { - dealloc( - mptr as *mut u8, - Layout::from_size_align_unchecked(page_count as usize * 4096, 4096), - ) - } - } + + dealloc( + mptr as *mut u8, + Layout::from_size_align_unchecked(page_count as usize * 4096, 4096), + ) + }, 2 => { use MemoryQuotaType::*; - let quota_type = match msg_vec[0] { + let quota_type = match msg_vec[1] { 0 => NoQuota, 1 => SoftQuota, 2 => HardQuota, @@ -82,10 +79,42 @@ pub fn memory_msg_handler( ) } 3 => { - let page_count = msg_vec[0]; + let page_count = msg_vec[1]; log::debug!(" {} pages", page_count); } + // memcpy + 4 => unsafe { + let count = u64::from_le_bytes(msg_vec[1..9].try_into().unwrap_unchecked()) as usize; + let src = u64::from_le_bytes(msg_vec[9..17].try_into().unwrap_unchecked()) as *const u8; + let dest = u64::from_le_bytes(msg_vec[17..25].try_into().unwrap_unchecked()) as *mut u8; + src.copy_to(dest, count); + }, + // memset + 5 => unsafe { + let count = u64::from_le_bytes(msg_vec[1..9].try_into().unwrap_unchecked()) as usize; + let size = u64::from_le_bytes(msg_vec[9..17].try_into().unwrap_unchecked()) as usize; + let dest = u64::from_le_bytes(msg_vec[17..25].try_into().unwrap_unchecked()) as *mut u8; + let src = u64::from_le_bytes(msg_vec[25..33].try_into().unwrap_unchecked()) as *mut u8; + let total_size = count * size; + + if total_size > 32 { + core::ptr::copy(src, dest, size); + let pattern = core::slice::from_raw_parts(dest, size); + let mut offset = size; + + while offset < total_size { + let remaining = total_size - offset; + let copy_size = remaining.min(offset); + core::ptr::copy_nonoverlapping(pattern.as_ptr(), dest.add(offset), copy_size); + offset += copy_size; + } + } else { + for i in 0..total_size { + *dest.add(i) = *src.add(i % size); + } + } + }, _ => { log::debug!("Unknown memory service message type: {}", msg_type); } diff --git a/kernel/src/holeybytes/mem.rs b/kernel/src/holeybytes/mem.rs index 79a3614..94d6583 100644 --- a/kernel/src/holeybytes/mem.rs +++ b/kernel/src/holeybytes/mem.rs @@ -37,7 +37,6 @@ impl hbvm::mem::Memory for Memory { target: *mut u8, count: usize, ) -> Result<(), hbvm::mem::LoadError> { - // if addr.get() % 4096 == 0 {} core::ptr::copy_nonoverlapping(addr.get() as *const u8, target, count); Ok(()) } diff --git a/repbuild/src/main.rs b/repbuild/src/main.rs index 4420c29..9963774 100644 --- a/repbuild/src/main.rs +++ b/repbuild/src/main.rs @@ -395,12 +395,7 @@ fn run(release: bool, target: Target, do_accel: bool) -> Result<(), Error> { "-parallel", "none", "-monitor", "none", "-machine", accel, - "-cpu", - if accel != "accel=tcg" { - "host" - } else { - "Broadwell-v4" - }, + "-cpu", "max", "-device", "isa-debug-exit,iobase=0xf4,iosize=0x04", ]); } diff --git a/sysdata/libraries/dt_api/src/lib.hb b/sysdata/libraries/dt_api/src/lib.hb index 8f2dffe..9159c83 100644 --- a/sysdata/libraries/dt_api/src/lib.hb +++ b/sysdata/libraries/dt_api/src/lib.hb @@ -1,6 +1,6 @@ .{string} := @use("../../stn/src/lib.hb") -dt_get := fn(query: ^u8): int { +dt_get := fn($Expr: type, query: ^u8): Expr { length := string.length(query) return @eca(3, 5, query, length) } \ No newline at end of file diff --git a/sysdata/libraries/render/src/image.hb b/sysdata/libraries/render/src/image.hb new file mode 100644 index 0000000..ee43be2 --- /dev/null +++ b/sysdata/libraries/render/src/image.hb @@ -0,0 +1,51 @@ +.{Color} := @use("./lib.hb"); +.{memory, log} := @use("../../stn/src/lib.hb") + +Image := struct { + buf: ^Color, + width: i32, + height: i32, +} + +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, +} + +from_bmp := fn(bmp: ^u8): Image { + 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 @as(Image, idk) + } + info_header := @as(^BitmapInfoHeader, @bitcast(bmp + @sizeof(BitmapFileHeader))) + bmp += file_header.offset + + return .(@bitcast(bmp), @bitcast(info_header.width), @bitcast(info_header.height)) +} \ No newline at end of file diff --git a/sysdata/libraries/render/src/lib.hb b/sysdata/libraries/render/src/lib.hb index 5c0baed..556387c 100644 --- a/sysdata/libraries/render/src/lib.hb +++ b/sysdata/libraries/render/src/lib.hb @@ -1,5 +1,6 @@ svga := @use("svga.hb") software := @use("software.hb") +image := @use("image.hb") // default mode mode := software @@ -8,23 +9,24 @@ init := mode.init doublebuffer := mode.doublebuffer // Colours -Color := mode.Color -white := mode.white -black := mode.black -gray := mode.gray -red := mode.red -green := mode.green -yellow := mode.yellow -blue := mode.blue -magenta := mode.magenta -cyan := mode.cyan -light_gray := mode.light_gray -light_red := mode.light_red -light_green := mode.light_green -light_yellow := mode.light_yellow -light_blue := mode.light_blue -light_magenta := mode.light_magenta -light_cyan := mode.light_cyan +Color := packed struct {b: u8, g: u8, r: u8, a: u8} +Image := image.Image +white := Color.(255, 255, 255, 255) +black := Color.(0, 0, 0, 255) +gray := Color.(127, 127, 127, 255) +red := Color.(0, 0, 205, 255) +green := Color.(0, 205, 0, 255) +yellow := Color.(0, 205, 205, 255) +blue := Color.(205, 0, 0, 255) +magenta := Color.(205, 0, 205, 255) +cyan := Color.(205, 205, 0, 255) +light_gray := Color.(229, 229, 229, 255) +light_red := Color.(0, 0, 255, 255) +light_green := Color.(0, 255, 0, 255) +light_yellow := Color.(0, 255, 255, 255) +light_blue := Color.(255, 0, 0, 255) +light_magenta := Color.(255, 0, 255, 255) +light_cyan := Color.(255, 255, 0, 255) // Drawing put_pixel := mode.put_pixel @@ -32,7 +34,11 @@ put_rect := mode.put_rect put_filled_rect := mode.put_filled_rect put_line := mode.put_line clear := mode.clear -put_img := mode.put_img +put_image := mode.put_image +// thanks peony for these three! +put_trirect := mode.put_trirect +put_vline := mode.put_vline +put_hline := mode.put_hline // Display width := mode.width @@ -41,10 +47,4 @@ dimensions := mode.dimensions set_height := mode.set_height set_width := mode.set_width set_dimensions := mode.set_dimensions -sync := mode.sync - -// Trash Image -Image := struct { - start: ^Color, - end: ^Color, -} \ No newline at end of file +sync := mode.sync \ No newline at end of file diff --git a/sysdata/libraries/render/src/software.hb b/sysdata/libraries/render/src/software.hb index a89057b..01107df 100644 --- a/sysdata/libraries/render/src/software.hb +++ b/sysdata/libraries/render/src/software.hb @@ -1,62 +1,32 @@ .{math, memory} := @use("../../stn/src/lib.hb"); .{dt_get} := @use("../../dt_api/src/lib.hb"); -.{Image} := @use("lib.hb"); +.{Color, Image} := @use("lib.hb"); .{Vec2} := math -Color := struct {b: u8, g: u8, r: u8, a: u8} -white := Color.(255, 255, 255, 255) -black := Color.(0, 0, 0, 255) -gray := Color.(127, 127, 127, 255) -red := Color.(0, 0, 205, 255) -green := Color.(0, 205, 0, 255) -yellow := Color.(0, 205, 205, 255) -blue := Color.(205, 0, 0, 255) -magenta := Color.(205, 0, 205, 255) -cyan := Color.(205, 205, 0, 255) -light_gray := Color.(229, 229, 229, 255) -light_red := Color.(0, 0, 255, 255) -light_green := Color.(0, 255, 0, 255) -light_yellow := Color.(0, 255, 255, 255) -light_blue := Color.(255, 0, 0, 255) -light_magenta := Color.(255, 0, 255, 255) -light_cyan := Color.(255, 255, 0, 255) - -// might not work for some resolutions, but needs to be comptime because... -copy_pixels := 0xC000 >> 2 - ctx := @as(Context, idk) -// some of these are redudant holdovers from fb_driver -// will keep them for future work if necessary Context := struct { fb: ^Color, bb: ^Color, buf: ^Color, width: int, height: int, - partitions: int, pixels: int, - bb_pages: int, double_buffer: bool, } init := fn(): void { - width := dt_get("framebuffer/fb0/width\0") - height := dt_get("framebuffer/fb0/height\0") + width := dt_get(int, "framebuffer/fb0/width\0") + height := dt_get(int, "framebuffer/fb0/height\0") pixels := width * height - bytes := pixels << 2 - partitions := pixels / copy_pixels - pages := 1 + bytes >> 12 - back_buffer := create_back_buffer(pages) + back_buffer := memory.alloc(Color, pixels * @bitcast(@sizeof(Color))) ctx = Context.{ - fb: dt_get("framebuffer/fb0/ptr\0"), + fb: dt_get(^Color, "framebuffer/fb0/ptr\0"), bb: back_buffer, buf: back_buffer, width, height, - partitions, pixels, - bb_pages: pages, double_buffer: true, } return @@ -72,60 +42,12 @@ doublebuffer := fn(enable: bool): void { return } -create_back_buffer := fn(pages: int): ^Color { - if pages <= 0xFF { - return @bitcast(@inline(memory.request_page, pages)) - } - ptr := @inline(memory.request_page, 255) - remaining := pages - 0xFF - loop if remaining <= 0 break else { - if remaining < 0xFF { - memory.request_page(remaining) - } else { - memory.request_page(0xFF) - } - remaining -= 0xFF - } - return @bitcast(ptr) -} - clear := fn(color: Color): void { - cursor := ctx.buf - boundary := cursor + 512 - loop if cursor == boundary break else { - *cursor = color - cursor += 1 - } - boundary += 512 * 7 - loop if cursor == boundary break else { - *@as(^[Color; 512], @bitcast(cursor)) = *@as(^[Color; 512], @bitcast(ctx.buf)) - cursor += 512 - } - boundary += copy_pixels - 4096 - loop if cursor == boundary break else { - *@as(^[Color; 4096], @bitcast(cursor)) = *@as(^[Color; 4096], @bitcast(ctx.buf)) - cursor += 4096 - } - boundary += (ctx.partitions - 1) * copy_pixels - loop if cursor == boundary break else { - *@as(^[Color; copy_pixels], @bitcast(cursor)) = *@as(^[Color; copy_pixels], @bitcast(ctx.buf)) - cursor += @sizeof([u8; copy_pixels]) - } - return + return @inline(memory.set, Color, &color, ctx.buf, @bitcast(ctx.pixels)) } sync := fn(): void { - if ctx.double_buffer { - bb := ctx.buf - fb := ctx.fb - boundary := bb + ctx.pixels - loop if bb == boundary break else { - *@as(^[Color; copy_pixels], @bitcast(fb)) = *@as(^[Color; copy_pixels], @bitcast(bb)) - bb += copy_pixels - fb += copy_pixels - } - } - return + return @inline(memory.copy, Color, ctx.buf, ctx.fb, @bitcast(ctx.pixels)) } width := fn(): int { @@ -146,35 +68,25 @@ put_pixel := fn(pos: Vec2(int), color: Color): void { } put_filled_rect := fn(pos: Vec2(int), tr: Vec2(int), color: Color): void { - x := pos.x y := pos.y - end := pos + tr - loop if x == end.x break else { - loop if y == end.y break else { - *(ctx.buf + @inline(screenidx, x, y)) = color - y += 1 - } - x += 1 - y = pos.y + end_y := y + tr.y + loop if y == end_y break else { + @inline(memory.set, Color, &color, ctx.buf + @inline(screenidx, pos.x, y), @bitcast(tr.x)) + y += 1 } return } put_rect := fn(pos: Vec2(int), tr: Vec2(int), color: Color): void { - x := pos.x y := pos.y - end := pos + tr - loop if y == end.y break else { - *(ctx.buf + @inline(screenidx, x, y)) = color; - *(ctx.buf + @inline(screenidx, x + tr.x, y)) = color + end_y := y + tr.y + loop if y == end_y break else { + *(ctx.buf + @inline(screenidx, pos.x, y)) = color; + *(ctx.buf + @inline(screenidx, pos.x + tr.x, y)) = color y += 1 } - y = pos.y - loop if x == end.x break else { - *(ctx.buf + @inline(screenidx, x, y)) = color; - *(ctx.buf + @inline(screenidx, x, y + tr.y)) = color - x += 1 - } + @inline(memory.set, Color, &color, ctx.buf + @inline(screenidx, pos.x, y), @bitcast(tr.x)) + @inline(memory.set, Color, &color, ctx.buf + @inline(screenidx, pos.x, y - tr.y), @bitcast(tr.x)) return } @@ -259,6 +171,67 @@ set_dimensions := fn(new: Vec2(int)): void { return } -put_img := fn(img: Image, pos: Vec2(int)): void { +put_image := fn(image: Image, pos: Vec2(int)): void { + y := 0 + loop if y == image.height break else { + @inline(memory.copy, Color, image.buf + y * image.width, ctx.buf + @inline(screenidx, pos.x, pos.y + image.height - y), @intcast(image.width)) + y += 1 + } + return +} + +// peony-made +put_trirect := fn(pos: Vec2(int), size: Vec2(int), color0: Color, color1: Color): void { + step := Vec2(int).(1, 1) + if size.x < 0 { + step.x = -1 + } + if size.y < 0 { + step.y = size.y / size.x + } + + start_y := pos.y + target := pos + size + + loop if pos.x == target.x break else { + put_vline(pos.x, pos.y, target.y, color0) + @inline(put_vline, pos.x, pos.y, start_y, color1) + pos += step + } + + return +} + +// peony-made +put_vline := fn(x: int, y0: int, y1: int, color: Color): void { + if y1 < y0 { + tmp := y0 + y0 = y1 + y1 = tmp + } + y := y0 + + loop if y == y1 break else { + *(ctx.buf + @inline(screenidx, x, y)) = color + y += 1 + } + + return +} + +// peony-made +put_hline := fn(y: int, x0: int, x1: int, color: Color): void { + if x1 < x0 { + tmp := x0 + x0 = x1 + x1 = tmp + } + x := x0 + + loop if x == x1 break else { + *(ctx.buf + @inline(screenidx, x, y)) = color + x += 1 + } + return } \ No newline at end of file diff --git a/sysdata/libraries/render/src/svga.hb b/sysdata/libraries/render/src/svga.hb index 0790198..033d762 100644 --- a/sysdata/libraries/render/src/svga.hb +++ b/sysdata/libraries/render/src/svga.hb @@ -1,23 +1,5 @@ -.{Vec2, Image} := @use("lib.hb") -// .{pci, memory, string, log} := @use("../../stn/src/lib.hb"); - -Color := struct {b: u8, g: u8, r: u8, a: u8} -white := Color.(255, 255, 255, 255) -black := Color.(0, 0, 0, 255) -gray := Color.(127, 127, 127, 255) -red := Color.(0, 0, 205, 255) -green := Color.(0, 205, 0, 255) -yellow := Color.(0, 205, 205, 255) -blue := Color.(205, 0, 0, 255) -magenta := Color.(205, 0, 205, 255) -cyan := Color.(205, 205, 0, 255) -light_gray := Color.(229, 229, 229, 255) -light_red := Color.(0, 0, 255, 255) -light_green := Color.(0, 255, 0, 255) -light_yellow := Color.(0, 255, 255, 255) -light_blue := Color.(255, 0, 0, 255) -light_magenta := Color.(255, 0, 255, 255) -light_cyan := Color.(255, 255, 0, 255) +.{Vec2} := @use("../../stn/src/lib.hb").math; +.{Image, Color} := @use("lib.hb") clear := fn(color: Color): void { return @@ -79,6 +61,18 @@ init := fn(): void { return } -put_img := fn(img: Image, pos: Vec2(int)): void { +put_image := fn(img: Image, pos: Vec2(int)): void { + return +} + +put_trirect := fn(pos: Vec2(int), size: Vec2(int), color0: Color, color1: Color): void { + return +} + +put_vline := fn(x: int, y0: int, y1: int, color: Color): void { + return +} + +put_hline := fn(y: int, x0: int, x1: int, color: Color): void { return } \ No newline at end of file diff --git a/sysdata/libraries/stn/src/memory.hb b/sysdata/libraries/stn/src/memory.hb index 4cbdd6d..21a0387 100644 --- a/sysdata/libraries/stn/src/memory.hb +++ b/sysdata/libraries/stn/src/memory.hb @@ -1,3 +1,24 @@ +PAGE_SIZE := 4096 +MAX_ALLOC := 0xFF + +alloc := fn($Expr: type, bytes: int): ^Expr { + pages := (1 + bytes) / PAGE_SIZE + if pages <= MAX_ALLOC { + return @bitcast(@inline(request_page, pages)) + } + ptr := @inline(request_page, 0xFF) + remaining := pages - MAX_ALLOC + loop if remaining <= 0 break else { + if remaining < MAX_ALLOC { + request_page(remaining) + } else { + request_page(MAX_ALLOC) + } + remaining -= MAX_ALLOC + } + return @bitcast(ptr) +} + request_page := fn(page_count: u8): ^u8 { msg := "\{00}\{01}xxxxxxxx\0" msg_page_count := msg + 1; @@ -36,4 +57,14 @@ outl := fn(addr: u16, value: u32): void { inl := fn(addr: u16): u32 { return @eca(3, 3, &InlMsg.(0, 2, addr), @sizeof(InlMsg)) +} + +CopyMsg := packed struct {a: u8, count: uint, src: uint, dest: ^u8} +copy := fn($Expr: type, src: ^Expr, dest: ^Expr, count: uint): void { + return @eca(3, 2, &CopyMsg.(4, count * @sizeof(Expr), @bitcast(src), @bitcast(dest)), @sizeof(CopyMsg)) +} + +SetMsg := packed struct {a: u8, count: uint, size: uint, dest: ^u8, src: ^u8} +set := fn($Expr: type, src: ^Expr, dest: ^Expr, count: uint): void { + return @eca(3, 2, &SetMsg.(5, count, @sizeof(Expr), @bitcast(dest), @bitcast(src)), @sizeof(SetMsg)) } \ No newline at end of file diff --git a/sysdata/programs/render_example/src/examples/image.hb b/sysdata/programs/render_example/src/examples/image.hb new file mode 100644 index 0000000..6546d74 --- /dev/null +++ b/sysdata/programs/render_example/src/examples/image.hb @@ -0,0 +1,31 @@ +.{Vec2} := @use("../../../../libraries/stn/src/lib.hb").math; +render := @use("../../../../libraries/render/src/lib.hb") + +/* expected result: + a cute image bounces around the screen */ + +mini_bmp := @embed("./mini.bmp") + +example := fn(): void { + render.init() + mini := render.image.from_bmp(@bitcast(&mini_bmp)) + vel := Vec2(int).(1, 1) + pos := Vec2(int).(100, 100) + width := render.width() + height := render.height() + loop { + render.put_image(mini, pos) + render.sync() + render.clear(render.black) + + if pos.x == 0 | pos.x == width - mini.width { + vel.x = -vel.x + } + if pos.y == 0 | pos.y == height - mini.height { + vel.y = -vel.y + } + + pos += vel + } + return +} \ No newline at end of file diff --git a/sysdata/programs/render_example/src/examples/mini.bmp b/sysdata/programs/render_example/src/examples/mini.bmp new file mode 100644 index 0000000000000000000000000000000000000000..7e0b4ceec3f9c4bdab3a64aa01c75826149183ac GIT binary patch literal 102454 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 X^XDOEuT^AZWLDtJYJIDO@b~`!1F?>E literal 0 HcmV?d00001 diff --git a/sysdata/programs/render_example/src/examples/tactical_screen.hb b/sysdata/programs/render_example/src/examples/tactical_screen.hb new file mode 100644 index 0000000..4f227de --- /dev/null +++ b/sysdata/programs/render_example/src/examples/tactical_screen.hb @@ -0,0 +1,83 @@ +render := @use("../../../../libraries/render/src/lib.hb"); +.{math, random} := @use("../../../../libraries/stn/src/lib.hb") +Vec2 := math.Vec2 + +/* expected result: + a grid of green lines scrolling from the left top corner to the right bottom one + with a "target" randomly apperaing in one of them and a "seeker" "catching" it*/ + +example := fn(): void { + render.init() + + width := render.width() + height := render.height() + cell_size := 0 + range := Vec2(int).(0, 0) + if width > height { + cell_size = width / 40 + range = .(39, height / cell_size - 1) + } else { + cell_size = height / 40 + range = .(width / cell_size - 1, 39) + } + width -= 1 + height -= 1 + + scroll := 0 + target := Vec2(int).(random.range(int, 0, range.x), random.range(int, 0, range.y)) + + halfcell := cell_size / 2 + octcell := cell_size / 8 + sevenoctcell := cell_size - octcell + + seeker := Vec2(int).(random.range(int, 0, range.x), random.range(int, 0, range.y)) + + loop { + render.clear(render.black) + + target_pixel_coord := target * .(cell_size, cell_size) + .(scroll, scroll) + render.put_trirect(target_pixel_coord, .(cell_size, cell_size), render.red, render.light_red) + + render.put_hline(target_pixel_coord.y + halfcell, target_pixel_coord.x - octcell, target_pixel_coord.x - sevenoctcell, render.light_red) + render.put_hline(target_pixel_coord.y + halfcell, target_pixel_coord.x + cell_size + octcell, target_pixel_coord.x + cell_size + sevenoctcell, render.light_red) + render.put_vline(target_pixel_coord.x + halfcell, target_pixel_coord.y - octcell, target_pixel_coord.y - sevenoctcell, render.light_red) + render.put_vline(target_pixel_coord.x + halfcell, target_pixel_coord.y + cell_size + octcell, target_pixel_coord.y + cell_size + sevenoctcell, render.light_red) + + x := scroll + loop if x > width break else { + render.put_vline(x, 0, height, .(0, 127, 0, 127)) + x += cell_size + } + + y := scroll + loop if y > height break else { + render.put_hline(y, 0, width, .(0, 127, 0, 127)) + y += cell_size + } + + render.put_hline(seeker.y * cell_size + halfcell + scroll, 0, width, render.light_green) + render.put_vline(seeker.x * cell_size + halfcell + scroll, 0, height, render.light_green) + + render.sync() + + if seeker.x < target.x { + seeker.x += 1 + } else if seeker.x > target.x { + seeker.x -= 1 + } else if seeker.y < target.y { + seeker.y += 1 + } else if seeker.y > target.y { + seeker.y -= 1 + } else { + target = .(random.range(int, 0, range.x), random.range(int, 0, range.y)) + } + + scroll += 1 + if scroll > cell_size { + scroll = 0 + target += .(1, 1) + seeker += .(1, 1) + } + } + return +} \ No newline at end of file diff --git a/sysdata/programs/render_example/src/main.hb b/sysdata/programs/render_example/src/main.hb index 35b2706..1ce2d4e 100644 --- a/sysdata/programs/render_example/src/main.hb +++ b/sysdata/programs/render_example/src/main.hb @@ -1,4 +1,4 @@ -.{example} := @use("./examples/amogus.hb") +.{example} := @use("./examples/image.hb") main := fn(): void { @inline(example) diff --git a/sysdata/programs/tetris/meta.toml b/sysdata/programs/tetris/meta.toml deleted file mode 100644 index d2a5f97..0000000 --- a/sysdata/programs/tetris/meta.toml +++ /dev/null @@ -1,11 +0,0 @@ -[package] -name = "tetris" -authors = ["peony"] - -[dependants.libraries] - -[dependants.binaries] -hblang.version = "1.0.0" - -[build] -command = "hblang src/main.hb" diff --git a/sysdata/programs/tetris/src/main.hb b/sysdata/programs/tetris/src/main.hb deleted file mode 100644 index e61324b..0000000 --- a/sysdata/programs/tetris/src/main.hb +++ /dev/null @@ -1,15 +0,0 @@ -.{memory, log, string, buffer} := @use("../../../libraries/stn/src/lib.hb") - -main := fn(): void { - storage := @as(u8, 0) - output_buffer := memory.request_page(1) - input_buffer := buffer.search("XKeyboard\0") - loop { - buffer.recv(input_buffer, &storage, 1) - if storage != 0 { - log.info(string.display_int(storage, output_buffer)) - storage = 0 - } - } - return -} \ No newline at end of file