forked from AbleOS/ableos
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
This commit is contained in:
parent
ea8eca1089
commit
96c2bd5cd5
6
Cargo.lock
generated
6
Cargo.lock
generated
|
@ -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",
|
||||
]
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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(())
|
||||
}
|
||||
|
|
|
@ -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",
|
||||
]);
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
51
sysdata/libraries/render/src/image.hb
Normal file
51
sysdata/libraries/render/src/image.hb
Normal file
|
@ -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))
|
||||
}
|
|
@ -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,
|
||||
}
|
||||
sync := mode.sync
|
|
@ -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
|
||||
}
|
|
@ -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
|
||||
}
|
|
@ -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))
|
||||
}
|
31
sysdata/programs/render_example/src/examples/image.hb
Normal file
31
sysdata/programs/render_example/src/examples/image.hb
Normal file
|
@ -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
|
||||
}
|
BIN
sysdata/programs/render_example/src/examples/mini.bmp
Normal file
BIN
sysdata/programs/render_example/src/examples/mini.bmp
Normal file
Binary file not shown.
After Width: | Height: | Size: 100 KiB |
|
@ -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
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
.{example} := @use("./examples/amogus.hb")
|
||||
.{example} := @use("./examples/image.hb")
|
||||
|
||||
main := fn(): void {
|
||||
@inline(example)
|
||||
|
|
|
@ -1,11 +0,0 @@
|
|||
[package]
|
||||
name = "tetris"
|
||||
authors = ["peony"]
|
||||
|
||||
[dependants.libraries]
|
||||
|
||||
[dependants.binaries]
|
||||
hblang.version = "1.0.0"
|
||||
|
||||
[build]
|
||||
command = "hblang src/main.hb"
|
|
@ -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
|
||||
}
|
Loading…
Reference in a new issue