#![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(); } }