From 6f3df74e79b7d4838ced1248a654e7e11def9b4e Mon Sep 17 00:00:00 2001 From: bQUARKz Date: Mon, 15 Jun 2026 05:48:24 +0100 Subject: [PATCH] implements PLN-0101 --- .../src/services/vm_runtime/dispatch.rs | 14 --- .../src/services/vm_runtime/tests.rs | 99 +++++++++++++++++++ 2 files changed, 99 insertions(+), 14 deletions(-) diff --git a/crates/console/prometeu-system/src/services/vm_runtime/dispatch.rs b/crates/console/prometeu-system/src/services/vm_runtime/dispatch.rs index 723ad03c..1425f4fd 100644 --- a/crates/console/prometeu-system/src/services/vm_runtime/dispatch.rs +++ b/crates/console/prometeu-system/src/services/vm_runtime/dispatch.rs @@ -187,7 +187,6 @@ impl NativeInterface for VmRuntimeHost<'_> { Syscall::GfxClear => { let color = self.get_color(expect_int(args, 0)?)?; self.gfx2d_commands.push(Gfx2dCommand::Clear { color }); - hw.gfx_mut().clear(color); Ok(()) } Syscall::GfxUiClear => { @@ -199,7 +198,6 @@ impl NativeInterface for VmRuntimeHost<'_> { } let color = self.get_color(expect_int(args, 0)?)?; self.gfxui_commands.push(GfxUiCommand::Clear { color }); - hw.gfx_mut().clear(color); Ok(()) } Syscall::GfxFillRect => { @@ -210,7 +208,6 @@ impl NativeInterface for VmRuntimeHost<'_> { let color = self.get_color(expect_int(args, 4)?)?; self.gfx2d_commands .push(Gfx2dCommand::FillRect { rect: Rect { x, y, w, h }, color }); - hw.gfx_mut().fill_rect(x, y, w, h, color); Ok(()) } Syscall::GfxUiFillRect => { @@ -227,7 +224,6 @@ impl NativeInterface for VmRuntimeHost<'_> { let color = self.get_color(expect_int(args, 4)?)?; self.gfxui_commands .push(GfxUiCommand::FillRect { rect: Rect { x, y, w, h }, color }); - hw.gfx_mut().fill_rect(x, y, w, h, color); Ok(()) } Syscall::GfxDrawLine => { @@ -243,7 +239,6 @@ impl NativeInterface for VmRuntimeHost<'_> { y1: y2, color, }); - hw.gfx_mut().draw_line(x1, y1, x2, y2, color); Ok(()) } Syscall::GfxUiDrawLine => { @@ -265,7 +260,6 @@ impl NativeInterface for VmRuntimeHost<'_> { y1: y2, color, }); - hw.gfx_mut().draw_line(x1, y1, x2, y2, color); Ok(()) } Syscall::GfxDrawCircle => { @@ -274,7 +268,6 @@ impl NativeInterface for VmRuntimeHost<'_> { let r = expect_int(args, 2)? as i32; let color = self.get_color(expect_int(args, 3)?)?; self.gfx2d_commands.push(Gfx2dCommand::DrawCircle { x, y, radius: r, color }); - hw.gfx_mut().draw_circle(x, y, r, color); Ok(()) } Syscall::GfxUiDrawCircle => { @@ -289,7 +282,6 @@ impl NativeInterface for VmRuntimeHost<'_> { let r = expect_int(args, 2)? as i32; let color = self.get_color(expect_int(args, 3)?)?; self.gfxui_commands.push(GfxUiCommand::DrawCircle { x, y, radius: r, color }); - hw.gfx_mut().draw_circle(x, y, r, color); Ok(()) } Syscall::GfxDrawDisc => { @@ -305,7 +297,6 @@ impl NativeInterface for VmRuntimeHost<'_> { border_color, fill_color, }); - hw.gfx_mut().draw_disc(x, y, r, border_color, fill_color); Ok(()) } Syscall::GfxUiDrawDisc => { @@ -327,7 +318,6 @@ impl NativeInterface for VmRuntimeHost<'_> { border_color, fill_color, }); - hw.gfx_mut().draw_disc(x, y, r, border_color, fill_color); Ok(()) } Syscall::GfxDrawSquare => { @@ -342,7 +332,6 @@ impl NativeInterface for VmRuntimeHost<'_> { border_color, fill_color, }); - hw.gfx_mut().draw_square(x, y, w, h, border_color, fill_color); Ok(()) } Syscall::GfxUiDrawSquare => { @@ -363,7 +352,6 @@ impl NativeInterface for VmRuntimeHost<'_> { border_color, fill_color, }); - hw.gfx_mut().draw_square(x, y, w, h, border_color, fill_color); Ok(()) } Syscall::GfxDrawText => { @@ -372,7 +360,6 @@ impl NativeInterface for VmRuntimeHost<'_> { let msg = expect_string(args, 2, "message")?; let color = self.get_color(expect_int(args, 3)?)?; self.gfx2d_commands.push(Gfx2dCommand::DrawText { x, y, text: msg.clone(), color }); - hw.gfx_mut().draw_text(x, y, &msg, color); Ok(()) } Syscall::GfxUiDrawText => { @@ -387,7 +374,6 @@ impl NativeInterface for VmRuntimeHost<'_> { let msg = expect_string(args, 2, "message")?; let color = self.get_color(expect_int(args, 3)?)?; self.gfxui_commands.push(GfxUiCommand::DrawText { x, y, text: msg.clone(), color }); - hw.gfx_mut().draw_text(x, y, &msg, color); Ok(()) } Syscall::ComposerBindScene => { diff --git a/crates/console/prometeu-system/src/services/vm_runtime/tests.rs b/crates/console/prometeu-system/src/services/vm_runtime/tests.rs index 49c75e91..4fa6e7b7 100644 --- a/crates/console/prometeu-system/src/services/vm_runtime/tests.rs +++ b/crates/console/prometeu-system/src/services/vm_runtime/tests.rs @@ -488,6 +488,105 @@ fn tick_shell_profile_closes_gfxui_commands_into_shell_packet() { assert_eq!(runtime.frame_scheduler.active_game_frame_id(), None); } +#[test] +fn tick_gfx2d_clear_buffers_without_immediate_pixel_mutation_before_frame_close() { + let mut runtime = VirtualMachineRuntime::new(None); + let mut log_service = LogService::new(4096); + let mut fs = VirtualFS::new(); + let mut fs_state = FsState::Unmounted; + let mut memcard = MemcardService::new(); + let mut open_files: HashMap = HashMap::new(); + let mut next_handle = 1; + let mut vm = VirtualMachine::default(); + let mut hardware = Hardware::new(); + let signals = InputSignals::default(); + let code = assemble("PUSH_I32 287454020\nHOSTCALL 0\nJMP 0").expect("assemble"); + let program = serialized_single_function_module( + code, + vec![SyscallDecl { + module: "gfx2d".into(), + name: "clear".into(), + version: 1, + arg_slots: 1, + ret_slots: 0, + }], + ); + let cartridge = cartridge_with_program(program, caps::GFX); + + runtime.initialize_vm(&mut log_service, &mut vm, &cartridge).expect("runtime must initialize"); + let report = runtime.tick( + &mut log_service, + &mut fs, + &mut fs_state, + &mut memcard, + &mut open_files, + &mut next_handle, + &mut vm, + &signals, + &mut hardware, + ); + + assert!(report.is_none()); + assert!(runtime.render_manager.latest_complete_submission().is_none()); + assert!(matches!( + runtime.gfx2d_commands.first(), + Some(prometeu_hal::Gfx2dCommand::Clear { color }) + if *color == Color::from_raw(0x11223344) + )); + assert_ne!(hardware.gfx.front_buffer()[0], Color::from_raw(0x11223344).raw()); +} + +#[test] +fn tick_gfx2d_draw_text_buffers_without_immediate_pixel_mutation_before_frame_close() { + let mut runtime = VirtualMachineRuntime::new(None); + let mut log_service = LogService::new(4096); + let mut fs = VirtualFS::new(); + let mut fs_state = FsState::Unmounted; + let mut memcard = MemcardService::new(); + let mut open_files: HashMap = HashMap::new(); + let mut next_handle = 1; + let mut vm = VirtualMachine::default(); + let mut hardware = Hardware::new(); + let signals = InputSignals::default(); + let code = + assemble("PUSH_I32 0\nPUSH_I32 0\nPUSH_CONST 0\nPUSH_I32 287454020\nHOSTCALL 0\nJMP 0") + .expect("assemble"); + let program = serialized_single_function_module_with_consts( + code, + vec![ConstantPoolEntry::String("I".into())], + vec![SyscallDecl { + module: "gfx2d".into(), + name: "draw_text".into(), + version: 1, + arg_slots: 4, + ret_slots: 0, + }], + ); + let cartridge = cartridge_with_program(program, caps::GFX); + + runtime.initialize_vm(&mut log_service, &mut vm, &cartridge).expect("runtime must initialize"); + let report = runtime.tick( + &mut log_service, + &mut fs, + &mut fs_state, + &mut memcard, + &mut open_files, + &mut next_handle, + &mut vm, + &signals, + &mut hardware, + ); + + assert!(report.is_none()); + assert!(runtime.render_manager.latest_complete_submission().is_none()); + assert!(matches!( + runtime.gfx2d_commands.first(), + Some(prometeu_hal::Gfx2dCommand::DrawText { x: 0, y: 0, text, color }) + if text == "I" && *color == Color::from_raw(0x11223344) + )); + assert_ne!(hardware.gfx.front_buffer()[0], Color::from_raw(0x11223344).raw()); +} + #[test] fn tick_system_profile_rejects_bank_game_surface() { let mut runtime = VirtualMachineRuntime::new(None);