Files
k-os/crates/apps/snake/src/main.rs
Gabriel Kaszewski f5ac7189a9 fix: VirtIO GPU driver and snake rendering through display server
- Fix swapped command IDs: attach_backing was 0x0104 (FLUSH),
  resource_flush was 0x0106 (ATTACH_BACKING). Now correct.
- Increase process stack from 4 pages (16 KB) to 16 pages (64 KB)
  to prevent stack overflow in display process.
- Restructure display-qemu to avoid MockFramebuffer's 32 KB array
  inflating the VirtIO path's stack frame.
- Wire snake app to render through display server via IPC instead
  of UART escape codes. Uses existing renderer.rs pixel renderer.
- Init now delegates display endpoint to snake process.
2026-10-19 00:01:29 +02:00

92 lines
2.5 KiB
Rust

#![no_std]
#![no_main]
extern crate userspace_rt;
use snake::game::{Direction, GameState, Snake};
use snake::renderer::{self, RenderCommand};
use types::bounded::CapSlot;
use types::display::{Color, Dimension, ScreenCoord};
use types::time::Ticks;
use userspace_rt::syscall;
use server_framework::Encode;
use display_server::protocol::DisplayRequest;
const INPUT_EP: CapSlot = CapSlot::const_new(0);
const DISPLAY_EP: CapSlot = CapSlot::const_new(1);
const TICK_DELAY: u64 = 2_000_000;
const MAX_RENDER_CMDS: usize = 140;
fn display_send(req: &DisplayRequest) {
let words = req.encode();
syscall::send(DISPLAY_EP, words[0], words[1], words[2], words[3]);
syscall::receive(DISPLAY_EP);
}
fn draw_rect(x: u16, y: u16, w: u16, h: u16, color: u32) {
display_send(&DisplayRequest::DrawRect {
x: ScreenCoord::new(x),
y: ScreenCoord::new(y),
w: Dimension::new(w),
h: Dimension::new(h),
color: Color::from_raw(color),
});
}
fn flush() {
display_send(&DisplayRequest::Flush);
}
#[unsafe(no_mangle)]
extern "C" fn main() {
let mut snake = Snake::new();
let mut commands = [RenderCommand { x: 0, y: 0, w: 0, h: 0, color: 0 }; MAX_RENDER_CMDS];
loop {
let count = renderer::render(&snake, &mut commands);
for i in 0..count {
let cmd = &commands[i];
draw_rect(cmd.x, cmd.y, cmd.w, cmd.h, cmd.color);
}
flush();
wait_tick();
handle_input(&mut snake);
snake.tick();
if snake.state() == GameState::GameOver {
let gw = renderer::grid_pixel_width();
let gh = renderer::grid_pixel_height();
draw_rect(gw / 2 - 60, gh / 2 - 12, 120, 24, 0xFF800000);
flush();
let end = Ticks::from_raw(syscall::get_time().raw() + 50_000_000);
while syscall::get_time().raw() < end.raw() { syscall::yield_now(); }
return;
}
}
}
fn handle_input(snake: &mut Snake) {
let _ = syscall::send(INPUT_EP, 0, 0, 0, 0);
let (tag, kind, _, _) = syscall::receive(INPUT_EP);
if tag == 1 {
match kind {
0 => snake.set_direction(Direction::Up),
1 => snake.set_direction(Direction::Down),
2 => snake.set_direction(Direction::Left),
3 => snake.set_direction(Direction::Right),
_ => {}
}
}
}
fn wait_tick() {
let start = syscall::get_time();
let deadline = Ticks::from_raw(start.raw() + TICK_DELAY);
while syscall::get_time().raw() < deadline.raw() {
syscall::yield_now();
}
}