From 8d7de5baff9a0b53858236557d16229e40bbbddb Mon Sep 17 00:00:00 2001 From: gram Date: Sun, 25 Jan 2026 18:47:07 +0100 Subject: [PATCH 1/6] draft fast sub-region drawing --- src/image.rs | 52 +++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 39 insertions(+), 13 deletions(-) diff --git a/src/image.rs b/src/image.rs index de551f2..9bdcf02 100644 --- a/src/image.rs +++ b/src/image.rs @@ -27,13 +27,8 @@ impl ParsedImage<'_> { self.draw_bpp(image_raw, point, frame) } 4 => { - if self.sub.is_none() { - frame.dirty = true; - self.draw_4bpp_fast(point, frame); - return; - } - let image_raw = ImageRawLE::::new(self.bytes, self.width); - self.draw_bpp(image_raw, point, frame) + frame.dirty = true; + self.draw_4bpp_fast(point, frame); } _ => {} }; @@ -73,7 +68,40 @@ impl ParsedImage<'_> { let mut p = point; let mut image = self.bytes; - // Cut the top out-of-bounds part of the image. + // Variables for cutting the left and right sides of the image. + let mut skip: usize = 0; + let mut left_x = point.x; + let mut right_x = left_x + self.width as i32; + + if let Some(sub) = self.sub { + // Cut image lines above sub-region. + { + let skip_px = sub.top_left.y * self.width as i32; + let start_i = skip_px as usize / PPB; + let Some(sub_image) = image.get(start_i..) else { + return; + }; + image = sub_image; + } + + // Cut image lines below sub-region. + { + let height = sub.size.height as i32; + let skip_px = height * self.width as i32; + let end_i = skip_px as usize / PPB; + let Some(sub_image) = image.get(..end_i) else { + return; + }; + image = sub_image; + } + + // Cut image on the left and right from the sub-region. + image = &image[sub.top_left.x as usize / PPB..]; + skip = (self.width - sub.size.width) as usize / PPB; + right_x = left_x + sub.size.width as i32; + } + + // Cut image lines above the screen. if p.y < 0 { let start_i = (-p.y * self.width as i32) as usize / PPB; let Some(sub_image) = image.get(start_i..) else { @@ -83,7 +111,7 @@ impl ParsedImage<'_> { p.y = 0; } - // Cut the bottom out-of-bounds part of the image. + // Cut image lines below the screen. let height = (image.len() * PPB) as i32 / self.width as i32; let bottom_y = p.y + height; if bottom_y > HEIGHT as i32 { @@ -95,16 +123,14 @@ impl ParsedImage<'_> { image = sub_image; } - let mut skip: usize = 0; // Skip the right out-of-bounds part of the image. - let mut right_x = point.x + self.width as i32; if right_x > WIDTH as i32 { let skip_px = (right_x - WIDTH as i32) as usize; - skip = skip_px / PPB; + skip += skip_px / PPB; right_x = WIDTH as i32 + (skip_px % PPB) as i32; } + // Skip the left out-of-bounds part of the image. - let mut left_x = point.x; if left_x < 0 { let skip_px = -left_x as usize; skip += skip_px / PPB; From 167c11e0eaa6a5f541c79a60f3fdaca8f1555282 Mon Sep 17 00:00:00 2001 From: gram Date: Mon, 26 Jan 2026 12:00:57 +0100 Subject: [PATCH 2/6] almost fix odd ox sub-image --- src/image.rs | 42 +++++++++++++++++++++++++++++------------- 1 file changed, 29 insertions(+), 13 deletions(-) diff --git a/src/image.rs b/src/image.rs index 9bdcf02..119f2b0 100644 --- a/src/image.rs +++ b/src/image.rs @@ -69,7 +69,7 @@ impl ParsedImage<'_> { let mut image = self.bytes; // Variables for cutting the left and right sides of the image. - let mut skip: usize = 0; + let mut skip_px: u32 = 0; let mut left_x = point.x; let mut right_x = left_x + self.width as i32; @@ -97,8 +97,10 @@ impl ParsedImage<'_> { // Cut image on the left and right from the sub-region. image = &image[sub.top_left.x as usize / PPB..]; - skip = (self.width - sub.size.width) as usize / PPB; - right_x = left_x + sub.size.width as i32; + // left_x = 2 * (sub.top_left.x % PPB as i32); + let sub_width = u32::min(sub.size.width, self.width); + skip_px = self.width - sub_width; + right_x = left_x + sub_width as i32; } // Cut image lines above the screen. @@ -125,30 +127,43 @@ impl ParsedImage<'_> { // Skip the right out-of-bounds part of the image. if right_x > WIDTH as i32 { - let skip_px = (right_x - WIDTH as i32) as usize; - skip += skip_px / PPB; - right_x = WIDTH as i32 + (skip_px % PPB) as i32; + let skip_diff = right_x as u32 - WIDTH as u32; + skip_px += skip_diff; + right_x = WIDTH as i32 + (skip_diff % PPB as u32) as i32; } // Skip the left out-of-bounds part of the image. if left_x < 0 { - let skip_px = -left_x as usize; - skip += skip_px / PPB; - left_x = -((skip_px % PPB) as i32); + let skip_diff = -left_x as u32; + skip_px += skip_diff; + left_x = -((skip_diff % PPB as u32) as i32); } + let skip_px = skip_px as usize; + let skip_extra = skip_px % PPB; + let skip = skip_px / PPB; + left_x -= skip_extra as i32; + p.x = left_x; + let mut i = 0; + let mut pending_skips = skip_extra; while i < image.len() { let byte = image[i]; - let c1 = usize::from((byte >> 4) & 0x0F); - if let Some(c1) = swaps[c1] { - frame.set_pixel(p, c1); - }; + + if pending_skips != 0 { + pending_skips -= 1; + } else { + let c1 = usize::from((byte >> 4) & 0x0F); + if let Some(c1) = swaps[c1] { + frame.set_pixel(p, c1); + }; + } p.x += 1; if p.x >= right_x { p.x = left_x; p.y += 1; i += skip; + pending_skips = skip_extra; } let c2 = usize::from(byte & 0x0F); @@ -160,6 +175,7 @@ impl ParsedImage<'_> { p.x = left_x; p.y += 1; i += skip; + pending_skips = skip_extra; } i += 1; } From b0f0678f6e3b4998a4be59947a1f875c60f8e011 Mon Sep 17 00:00:00 2001 From: gram Date: Mon, 26 Jan 2026 13:28:55 +0100 Subject: [PATCH 3/6] more graphics tests --- src/host/graphics_test.rs | 121 ++++++++++++++++++++++++++++++++++++++ src/image.rs | 16 +++-- 2 files changed, 132 insertions(+), 5 deletions(-) diff --git a/src/host/graphics_test.rs b/src/host/graphics_test.rs index 6b2258a..43f7a0e 100644 --- a/src/host/graphics_test.rs +++ b/src/host/graphics_test.rs @@ -17,6 +17,29 @@ const G: i32 = 2; const R: i32 = 3; const B: i32 = 4; +/// A 4x4 16 BPP image with all 16 colors. +static IMG16: &[u8] = &[ + // header + 0x21, // magic number (marker that signals that this is an image) + 0x04, // bits per pixel (BPP, either 0x01, 0x02, or 0x04) + 0x04, // ┬ image width, 16 bit little-endian + 0x00, // ┘ + 0xff, // transparency color + 0x01, // ┬ 8 bytes color palette (16 colors) + 0x23, // ┤ + 0x45, // ┤ + 0x67, // ┤ + 0x89, // ┤ + 0xAB, // ┤ + 0xCD, // ┤ + 0xEF, // ┘ + // pixels + 0x01, 0x23, // row 1 + 0x45, 0x67, // row 2 + 0x89, 0xAB, // row 3 + 0xCD, 0xEF, // row 4 +]; + #[test] fn test_clear_screen() { let mut store = make_store(); @@ -245,6 +268,104 @@ fn test_draw_circle() { ); } +/// Draw circle paritally out-of-bounds on the left. +#[test] +fn test_draw_circle_part_oob_left() { + let mut store = make_store(); + let func = wasmi::Func::wrap(&mut store, draw_circle); + + // ensure that the frame buffer is empty + let state = store.data(); + for byte in &*state.frame.data { + assert_eq!(byte, &0b_0000_0000); + } + + let inputs = wrap_input(&[-2, 2, 4, G, R, 1]); + func.call(&mut store, &inputs, &mut []).unwrap(); + + let state = store.data_mut(); + check_display( + &mut state.frame, + &[ + "WWWWW", // y=0 + "WWWWW", // y=1 + "RWWWW", // y=2 + "GRWWW", // y=3 + "GRWWW", // y=4 + "RWWWW", // y=5 + "WWWWW", // y=6 + ], + ); +} + +/// Draw circle paritally out-of-bounds on the left. +#[test] +fn test_draw_circle_part_oob_top() { + let mut store = make_store(); + let func = wasmi::Func::wrap(&mut store, draw_circle); + + // ensure that the frame buffer is empty + let state = store.data(); + for byte in &*state.frame.data { + assert_eq!(byte, &0b_0000_0000); + } + + let inputs = wrap_input(&[1, -1, 4, G, R, 1]); + func.call(&mut store, &inputs, &mut []).unwrap(); + + let state = store.data_mut(); + check_display( + &mut state.frame, + &[ + "WRGGRW", // y=0 + "WRGGRW", // y=1 + "WWRRWW", // y=2 + "WWWWWW", // y=3 + "WWWWWW", // y=4 + "WWWWWW", // y=5 + "WWWWWW", // y=6 + ], + ); +} + +/// Draw circle paritally out-of-bounds on the left. +#[test] +fn test_draw_image() { + let mut store = make_store(); + let func = wasmi::Func::wrap(&mut store, draw_image); + + // ensure that the frame buffer is empty + let state = store.data(); + for byte in &*state.frame.data { + assert_eq!(byte, &0b_0000_0000); + } + + let mem_type = wasmi::MemoryType::new(1, Some(1)); + let memory = wasmi::Memory::new(&mut store, mem_type).unwrap(); + let state = store.data_mut(); + state.memory = Some(memory); + + let data = memory.data_mut(&mut store); + data[5..5 + IMG16.len()].copy_from_slice(IMG16); + + let inputs = wrap_input(&[5, IMG16.len() as _, 1, 2]); + func.call(&mut store, &inputs, &mut []).unwrap(); + + let state = store.data_mut(); + check_display( + &mut state.frame, + &[ + "WWWWWW", // y=0 + "WWWWWW", // y=1 + "WWGRBW", // y=2 + "WKKKKW", // y=3 + "WKKKKW", // y=4 + "WKKKKW", // y=5 + "WWWWWW", // y=6 + ], + ); +} + fn wrap_input(a: &[i32]) -> Vec { let mut res = Vec::new(); for el in a { diff --git a/src/image.rs b/src/image.rs index 119f2b0..b01b213 100644 --- a/src/image.rs +++ b/src/image.rs @@ -72,6 +72,7 @@ impl ParsedImage<'_> { let mut skip_px: u32 = 0; let mut left_x = point.x; let mut right_x = left_x + self.width as i32; + let mut pending_skips = 0; if let Some(sub) = self.sub { // Cut image lines above sub-region. @@ -97,6 +98,7 @@ impl ParsedImage<'_> { // Cut image on the left and right from the sub-region. image = &image[sub.top_left.x as usize / PPB..]; + // pending_skips = (sub.top_left.x as usize % PPB) * 10; // left_x = 2 * (sub.top_left.x % PPB as i32); let sub_width = u32::min(sub.size.width, self.width); skip_px = self.width - sub_width; @@ -146,7 +148,6 @@ impl ParsedImage<'_> { p.x = left_x; let mut i = 0; - let mut pending_skips = skip_extra; while i < image.len() { let byte = image[i]; @@ -164,12 +165,17 @@ impl ParsedImage<'_> { p.y += 1; i += skip; pending_skips = skip_extra; + continue; } - let c2 = usize::from(byte & 0x0F); - if let Some(c2) = swaps[c2] { - frame.set_pixel(p, c2); - }; + if pending_skips != 0 { + pending_skips -= 1; + } else { + let c2 = usize::from(byte & 0x0F); + if let Some(c2) = swaps[c2] { + frame.set_pixel(p, c2); + }; + } p.x += 1; if p.x >= right_x { p.x = left_x; From 2774d1da4f34e2e9af1ca6864c8bf17a5bd862bf Mon Sep 17 00:00:00 2001 From: gram Date: Mon, 26 Jan 2026 13:30:56 +0100 Subject: [PATCH 4/6] simplify --- src/host/graphics_test.rs | 77 +++++---------------------------------- 1 file changed, 10 insertions(+), 67 deletions(-) diff --git a/src/host/graphics_test.rs b/src/host/graphics_test.rs index 43f7a0e..1b5b207 100644 --- a/src/host/graphics_test.rs +++ b/src/host/graphics_test.rs @@ -45,12 +45,6 @@ fn test_clear_screen() { let mut store = make_store(); let func = wasmi::Func::wrap(&mut store, clear_screen); - // ensure that the frame buffer is empty - let state = store.data(); - for byte in &*state.frame.data { - assert_eq!(byte, &0b_0000_0000); - } - let inputs = wrap_input(&[2]); let mut outputs = Vec::new(); func.call(&mut store, &inputs, &mut outputs).unwrap(); @@ -68,12 +62,6 @@ fn test_draw_line() { let mut store = make_store(); let func = wasmi::Func::wrap(&mut store, draw_line); - // ensure that the frame buffer is empty - let state = store.data(); - for byte in &*state.frame.data { - assert_eq!(byte, &0b_0000_0000); - } - let inputs = wrap_input(&[2, 1, 4, 3, R, 1]); func.call(&mut store, &inputs, &mut []).unwrap(); @@ -99,12 +87,6 @@ fn test_draw_line_out_of_bounds() { let mut store = make_store(); let func = wasmi::Func::wrap(&mut store, draw_line); - // ensure that the frame buffer is empty - let state = store.data(); - for byte in &*state.frame.data { - assert_eq!(byte, &0b_0000_0000); - } - let inputs = wrap_input(&[-1, -2, 4, 3, G, 1]); func.call(&mut store, &inputs, &mut []).unwrap(); @@ -128,12 +110,6 @@ fn test_draw_rect_filled() { let mut store = make_store(); let func = wasmi::Func::wrap(&mut store, draw_rect); - // ensure that the frame buffer is empty - let state = store.data(); - for byte in &*state.frame.data { - assert_eq!(byte, &0b_0000_0000); - } - let inputs = wrap_input(&[1, 2, 4, 3, G, B, 1]); func.call(&mut store, &inputs, &mut []).unwrap(); @@ -157,12 +133,6 @@ fn test_draw_rect_solid_w4() { let mut store = make_store(); let func = wasmi::Func::wrap(&mut store, draw_rect); - // ensure that the frame buffer is empty - let state = store.data(); - for byte in &*state.frame.data { - assert_eq!(byte, &0b_0000_0000); - } - let inputs = wrap_input(&[1, 2, 4, 3, G, N, 1]); func.call(&mut store, &inputs, &mut []).unwrap(); @@ -186,12 +156,6 @@ fn test_draw_rect_solid_w5() { let mut store = make_store(); let func = wasmi::Func::wrap(&mut store, draw_rect); - // ensure that the frame buffer is empty - let state = store.data(); - for byte in &*state.frame.data { - assert_eq!(byte, &0b_0000_0000); - } - let inputs = wrap_input(&[1, 2, 5, 3, G, N, 1]); func.call(&mut store, &inputs, &mut []).unwrap(); @@ -215,12 +179,6 @@ fn test_draw_rounded_rect() { let mut store = make_store(); let func = wasmi::Func::wrap(&mut store, draw_rounded_rect); - // ensure that the frame buffer is empty - let state = store.data(); - for byte in &*state.frame.data { - assert_eq!(byte, &0b_0000_0000); - } - let inputs = wrap_input(&[1, 2, 4, 4, 2, 2, G, B, 1]); func.call(&mut store, &inputs, &mut []).unwrap(); @@ -244,12 +202,6 @@ fn test_draw_circle() { let mut store = make_store(); let func = wasmi::Func::wrap(&mut store, draw_circle); - // ensure that the frame buffer is empty - let state = store.data(); - for byte in &*state.frame.data { - assert_eq!(byte, &0b_0000_0000); - } - let inputs = wrap_input(&[1, 2, 4, G, R, 1]); func.call(&mut store, &inputs, &mut []).unwrap(); @@ -274,12 +226,6 @@ fn test_draw_circle_part_oob_left() { let mut store = make_store(); let func = wasmi::Func::wrap(&mut store, draw_circle); - // ensure that the frame buffer is empty - let state = store.data(); - for byte in &*state.frame.data { - assert_eq!(byte, &0b_0000_0000); - } - let inputs = wrap_input(&[-2, 2, 4, G, R, 1]); func.call(&mut store, &inputs, &mut []).unwrap(); @@ -304,12 +250,6 @@ fn test_draw_circle_part_oob_top() { let mut store = make_store(); let func = wasmi::Func::wrap(&mut store, draw_circle); - // ensure that the frame buffer is empty - let state = store.data(); - for byte in &*state.frame.data { - assert_eq!(byte, &0b_0000_0000); - } - let inputs = wrap_input(&[1, -1, 4, G, R, 1]); func.call(&mut store, &inputs, &mut []).unwrap(); @@ -334,12 +274,6 @@ fn test_draw_image() { let mut store = make_store(); let func = wasmi::Func::wrap(&mut store, draw_image); - // ensure that the frame buffer is empty - let state = store.data(); - for byte in &*state.frame.data { - assert_eq!(byte, &0b_0000_0000); - } - let mem_type = wasmi::MemoryType::new(1, Some(1)); let memory = wasmi::Memory::new(&mut store, mem_type).unwrap(); let state = store.data_mut(); @@ -416,9 +350,18 @@ fn make_store<'a>() -> wasmi::Store>> { let rom_dir = device.open_dir(&["sys"]).ok().unwrap(); let id = FullID::from_str("test-author", "test-app").unwrap(); let state = State::new(id, device, rom_dir, NetHandler::None, false); - wasmi::Store::new(&engine, state) + let store = wasmi::Store::new(&engine, state); + assert_fb_empty(&store); + store } +/// Ensure that the frame buffer is empty. +fn assert_fb_empty(store: &wasmi::Store>>) { + let state = store.data(); + for byte in &*state.frame.data { + assert_eq!(byte, &0b_0000_0000); + } +} fn get_vfs() -> PathBuf { let root = std::env::temp_dir(); _ = std::fs::create_dir(root.join("sys")); From 9a328c8adf2d2465813e67bb6117c71cb980f3da Mon Sep 17 00:00:00 2001 From: gram Date: Mon, 26 Jan 2026 14:04:07 +0100 Subject: [PATCH 5/6] test draw_image --- src/host/graphics_test.rs | 102 +++++++++++++++++++++++++++----------- src/image.rs | 4 +- 2 files changed, 76 insertions(+), 30 deletions(-) diff --git a/src/host/graphics_test.rs b/src/host/graphics_test.rs index 1b5b207..ec8bc83 100644 --- a/src/host/graphics_test.rs +++ b/src/host/graphics_test.rs @@ -7,6 +7,7 @@ use embedded_graphics::draw_target::DrawTargetExt; use embedded_graphics::geometry::{Point, Size}; use embedded_graphics::mock_display::MockDisplay; use embedded_graphics::pixelcolor::Rgb888; +use embedded_graphics::prelude::RgbColor; use embedded_graphics::primitives::Rectangle; use firefly_hal::{Device, DeviceConfig, DeviceImpl}; use std::path::PathBuf; @@ -268,23 +269,13 @@ fn test_draw_circle_part_oob_top() { ); } -/// Draw circle paritally out-of-bounds on the left. #[test] fn test_draw_image() { let mut store = make_store(); let func = wasmi::Func::wrap(&mut store, draw_image); - - let mem_type = wasmi::MemoryType::new(1, Some(1)); - let memory = wasmi::Memory::new(&mut store, mem_type).unwrap(); - let state = store.data_mut(); - state.memory = Some(memory); - - let data = memory.data_mut(&mut store); - data[5..5 + IMG16.len()].copy_from_slice(IMG16); - + write_mem(&mut store, 5, IMG16); let inputs = wrap_input(&[5, IMG16.len() as _, 1, 2]); func.call(&mut store, &inputs, &mut []).unwrap(); - let state = store.data_mut(); check_display( &mut state.frame, @@ -292,7 +283,7 @@ fn test_draw_image() { "WWWWWW", // y=0 "WWWWWW", // y=1 "WWGRBW", // y=2 - "WKKKKW", // y=3 + "WYMCKW", // y=3 "WKKKKW", // y=4 "WKKKKW", // y=5 "WWWWWW", // y=6 @@ -300,6 +291,61 @@ fn test_draw_image() { ); } +#[test] +fn test_draw_image_oob_left() { + let mut store = make_store(); + let func = wasmi::Func::wrap(&mut store, draw_image); + write_mem(&mut store, 5, IMG16); + let inputs = wrap_input(&[5, IMG16.len() as _, -2, 2]); + func.call(&mut store, &inputs, &mut []).unwrap(); + let state = store.data_mut(); + check_display( + &mut state.frame, + &[ + "WWWWWW", // y=0 + "WWWWWW", // y=1 + "RBWWWW", // y=2 + "CKWWWW", // y=3 + "KKWWWW", // y=4 + "KKWWWW", // y=5 + "WWWWWW", // y=6 + ], + ); +} + +#[test] +fn test_draw_image_oob_top() { + let mut store = make_store(); + let func = wasmi::Func::wrap(&mut store, draw_image); + write_mem(&mut store, 5, IMG16); + let inputs = wrap_input(&[5, IMG16.len() as _, 1, -1]); + func.call(&mut store, &inputs, &mut []).unwrap(); + let state = store.data_mut(); + check_display( + &mut state.frame, + &[ + "WYMCKW", // y=0 + "WKKKKW", // y=1 + "WKKKKW", // y=2 + "WWWWWW", // y=3 + "WWWWWW", // y=4 + "WWWWWW", // y=5 + "WWWWWW", // y=6 + ], + ); +} + +/// Place the given buffer into the linear wasm app memory. +fn write_mem(store: &mut wasmi::Store>>, addr: usize, buf: &[u8]) { + let mem_type = wasmi::MemoryType::new(1, Some(1)); + let memory = wasmi::Memory::new(&mut *store, mem_type).unwrap(); + let state = store.data_mut(); + state.memory = Some(memory); + + let data = memory.data_mut(store); + data[addr..addr + buf.len()].copy_from_slice(buf); +} + fn wrap_input(a: &[i32]) -> Vec { let mut res = Vec::new(); for el in a { @@ -315,25 +361,25 @@ fn check_display(frame: &mut FrameBuffer, pattern: &[&str]) { let mut sub_display = display.clipped(&area); frame.palette = [ // 0-4 - Rgb16::from_rgb(255, 255, 255), - Rgb16::from_rgb(0, 255, 0), - Rgb16::from_rgb(255, 0, 0), - Rgb16::from_rgb(0, 0, 255), + Rgb16::WHITE, + Rgb16::GREEN, + Rgb16::RED, + Rgb16::BLUE, // 4-8 - Rgb16::from_rgb(0, 0, 0), - Rgb16::from_rgb(0, 0, 0), - Rgb16::from_rgb(0, 0, 0), - Rgb16::from_rgb(0, 0, 0), + Rgb16::YELLOW, + Rgb16::MAGENTA, + Rgb16::CYAN, + Rgb16::BLACK, // 8-12 - Rgb16::from_rgb(0, 0, 0), - Rgb16::from_rgb(0, 0, 0), - Rgb16::from_rgb(0, 0, 0), - Rgb16::from_rgb(0, 0, 0), + Rgb16::BLACK, + Rgb16::BLACK, + Rgb16::BLACK, + Rgb16::BLACK, // 12-16 - Rgb16::from_rgb(0, 0, 0), - Rgb16::from_rgb(0, 0, 0), - Rgb16::from_rgb(0, 0, 0), - Rgb16::from_rgb(0, 0, 0), + Rgb16::BLACK, + Rgb16::BLACK, + Rgb16::BLACK, + Rgb16::BLACK, ]; frame.draw(&mut sub_display).unwrap(); display.assert_pattern(pattern); diff --git a/src/image.rs b/src/image.rs index b01b213..9dbf439 100644 --- a/src/image.rs +++ b/src/image.rs @@ -144,8 +144,8 @@ impl ParsedImage<'_> { let skip_px = skip_px as usize; let skip_extra = skip_px % PPB; let skip = skip_px / PPB; - left_x -= skip_extra as i32; - p.x = left_x; + // left_x -= skip_extra as i32; + // p.x = left_x; let mut i = 0; while i < image.len() { From 84ea27361a03de45561f1b61d3679c5adee760a7 Mon Sep 17 00:00:00 2001 From: gram Date: Tue, 27 Jan 2026 08:42:17 +0100 Subject: [PATCH 6/6] more tests --- src/host/graphics_test.rs | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/src/host/graphics_test.rs b/src/host/graphics_test.rs index ec8bc83..a632aa9 100644 --- a/src/host/graphics_test.rs +++ b/src/host/graphics_test.rs @@ -292,7 +292,29 @@ fn test_draw_image() { } #[test] -fn test_draw_image_oob_left() { +fn test_draw_image_oob_left1() { + let mut store = make_store(); + let func = wasmi::Func::wrap(&mut store, draw_image); + write_mem(&mut store, 5, IMG16); + let inputs = wrap_input(&[5, IMG16.len() as _, -1, 2]); + func.call(&mut store, &inputs, &mut []).unwrap(); + let state = store.data_mut(); + check_display( + &mut state.frame, + &[ + "WWWWWW", // y=0 + "WWWWWW", // y=1 + "GRBWWW", // y=2 + "MCKWWW", // y=3 + "KKKWWW", // y=4 + "KKKWWW", // y=5 + "WWWWWW", // y=6 + ], + ); +} + +#[test] +fn test_draw_image_oob_left2() { let mut store = make_store(); let func = wasmi::Func::wrap(&mut store, draw_image); write_mem(&mut store, 5, IMG16);