semi-working snake game
This commit is contained in:
84
Cargo.lock
generated
84
Cargo.lock
generated
@@ -18,6 +18,7 @@ version = "0.1.0"
|
||||
dependencies = [
|
||||
"abi_sys",
|
||||
"embedded-graphics",
|
||||
"rand_core 0.9.3",
|
||||
"shared",
|
||||
"spin",
|
||||
"talc",
|
||||
@@ -956,6 +957,14 @@ dependencies = [
|
||||
"heapless",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "embedded-snake"
|
||||
version = "0.0.3"
|
||||
dependencies = [
|
||||
"embedded-graphics",
|
||||
"rand_core 0.9.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "embedded-storage"
|
||||
version = "0.3.1"
|
||||
@@ -1198,9 +1207,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "hashbrown"
|
||||
version = "0.15.5"
|
||||
version = "0.16.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1"
|
||||
checksum = "5419bdc4f6a9207fbeba6d11b604d481addf78ecd10c11ad51e76c2f6482748d"
|
||||
|
||||
[[package]]
|
||||
name = "heapless"
|
||||
@@ -1227,12 +1236,12 @@ checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"
|
||||
|
||||
[[package]]
|
||||
name = "indexmap"
|
||||
version = "2.11.1"
|
||||
version = "2.11.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "206a8042aec68fa4a62e8d3f7aa4ceb508177d9324faf261e1959e495b7a1921"
|
||||
checksum = "4b0f83760fb341a774ed326568e19f5a863af4a952def8c39f9ab92fd95b88e5"
|
||||
dependencies = [
|
||||
"equivalent",
|
||||
"hashbrown 0.15.5",
|
||||
"hashbrown 0.16.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1266,9 +1275,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "js-sys"
|
||||
version = "0.3.78"
|
||||
version = "0.3.80"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0c0b063578492ceec17683ef2f8c5e89121fbd0b172cbc280635ab7567db2738"
|
||||
checksum = "852f13bec5eba4ba9afbeb93fd7c13fe56147f055939ae21c43a29a0ecb2702e"
|
||||
dependencies = [
|
||||
"once_cell",
|
||||
"wasm-bindgen",
|
||||
@@ -1319,6 +1328,7 @@ dependencies = [
|
||||
"once_cell",
|
||||
"panic-probe",
|
||||
"portable-atomic",
|
||||
"rand",
|
||||
"shared",
|
||||
"spin",
|
||||
"st7365p-lcd",
|
||||
@@ -1416,9 +1426,9 @@ checksum = "6a82ae493e598baaea5209805c49bbf2ea7de956d50d7da0da1164f9c6d28543"
|
||||
|
||||
[[package]]
|
||||
name = "libredox"
|
||||
version = "0.1.9"
|
||||
version = "0.1.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "391290121bad3d37fbddad76d8f5d1c1c314cfc646d143d7e07a3086ddff0ce3"
|
||||
checksum = "416f7e718bdb06000964960ffa43b4335ad4012ae8b99060261aa4a8088d5ccb"
|
||||
dependencies = [
|
||||
"bitflags 2.9.4",
|
||||
"libc",
|
||||
@@ -1806,6 +1816,15 @@ version = "0.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09"
|
||||
|
||||
[[package]]
|
||||
name = "rand"
|
||||
version = "0.9.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6db2770f06117d490610c7488547d543617b21bfa07796d7a12f6f1bd53850d1"
|
||||
dependencies = [
|
||||
"rand_core 0.9.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_core"
|
||||
version = "0.6.4"
|
||||
@@ -1954,18 +1973,27 @@ checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.219"
|
||||
version = "1.0.225"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6"
|
||||
checksum = "fd6c24dee235d0da097043389623fb913daddf92c76e9f5a1db88607a0bcbd1d"
|
||||
dependencies = [
|
||||
"serde_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_core"
|
||||
version = "1.0.225"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "659356f9a0cb1e529b24c01e43ad2bdf520ec4ceaf83047b83ddcc2251f96383"
|
||||
dependencies = [
|
||||
"serde_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.219"
|
||||
version = "1.0.225"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00"
|
||||
checksum = "0ea936adf78b1f766949a4977b91d2f5595825bd6ec079aa9543ad2685fc4516"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@@ -2026,6 +2054,16 @@ dependencies = [
|
||||
"rgb",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "snake"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"abi",
|
||||
"embedded-graphics",
|
||||
"embedded-snake",
|
||||
"rand",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "spin"
|
||||
version = "0.10.0"
|
||||
@@ -2371,9 +2409,9 @@ checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b"
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen"
|
||||
version = "0.2.101"
|
||||
version = "0.2.103"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7e14915cadd45b529bb8d1f343c4ed0ac1de926144b746e2710f9cd05df6603b"
|
||||
checksum = "ab10a69fbd0a177f5f649ad4d8d3305499c42bab9aef2f7ff592d0ec8f833819"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"once_cell",
|
||||
@@ -2384,9 +2422,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-backend"
|
||||
version = "0.2.101"
|
||||
version = "0.2.103"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e28d1ba982ca7923fd01448d5c30c6864d0a14109560296a162f80f305fb93bb"
|
||||
checksum = "0bb702423545a6007bbc368fde243ba47ca275e549c8a28617f56f6ba53b1d1c"
|
||||
dependencies = [
|
||||
"bumpalo",
|
||||
"log",
|
||||
@@ -2398,9 +2436,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-macro"
|
||||
version = "0.2.101"
|
||||
version = "0.2.103"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7c3d463ae3eff775b0c45df9da45d68837702ac35af998361e2c84e7c5ec1b0d"
|
||||
checksum = "fc65f4f411d91494355917b605e1480033152658d71f722a90647f56a70c88a0"
|
||||
dependencies = [
|
||||
"quote",
|
||||
"wasm-bindgen-macro-support",
|
||||
@@ -2408,9 +2446,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-macro-support"
|
||||
version = "0.2.101"
|
||||
version = "0.2.103"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7bb4ce89b08211f923caf51d527662b75bdc9c9c7aab40f86dcb9fb85ac552aa"
|
||||
checksum = "ffc003a991398a8ee604a401e194b6b3a39677b3173d6e74495eb51b82e99a32"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@@ -2421,9 +2459,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-shared"
|
||||
version = "0.2.101"
|
||||
version = "0.2.103"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f143854a3b13752c6950862c906306adb27c7e839f7414cec8fea35beab624c1"
|
||||
checksum = "293c37f4efa430ca14db3721dfbe48d8c33308096bd44d80ebaa775ab71ba1cf"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[workspace]
|
||||
resolver = "3"
|
||||
members = ["kernel", "abi", "shared", "user-apps/calculator"]
|
||||
members = ["kernel", "abi", "shared", "user-apps/calculator", "user-apps/snake"]
|
||||
|
||||
[profile.release]
|
||||
debug = true
|
||||
|
||||
@@ -9,3 +9,4 @@ shared = { path = "../shared" }
|
||||
abi_sys = { path = "../abi_sys" }
|
||||
talc = "4.4.3"
|
||||
spin = "0.10.0"
|
||||
rand_core = "0.9.3"
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
#![no_std]
|
||||
|
||||
use abi_sys::draw_iter;
|
||||
use abi_sys::{RngRequest, draw_iter, gen_rand};
|
||||
pub use abi_sys::{get_key, lock_display, print, sleep};
|
||||
use rand_core::RngCore;
|
||||
pub use shared::keyboard::{KeyCode, KeyEvent, KeyState, Modifiers};
|
||||
use talc::*;
|
||||
|
||||
@@ -71,3 +72,32 @@ pub mod display {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Rng;
|
||||
|
||||
impl RngCore for Rng {
|
||||
fn next_u32(&mut self) -> u32 {
|
||||
let mut req = RngRequest::U32(0);
|
||||
gen_rand(&mut req);
|
||||
if let RngRequest::U32(i) = req {
|
||||
return i;
|
||||
};
|
||||
0
|
||||
}
|
||||
|
||||
fn next_u64(&mut self) -> u64 {
|
||||
let mut req = RngRequest::U64(0);
|
||||
gen_rand(&mut req);
|
||||
if let RngRequest::U64(i) = req {
|
||||
return i;
|
||||
};
|
||||
0
|
||||
}
|
||||
fn fill_bytes(&mut self, dst: &mut [u8]) {
|
||||
let mut req = RngRequest::Bytes {
|
||||
ptr: dst.as_mut_ptr(),
|
||||
len: dst.len(),
|
||||
};
|
||||
gen_rand(&mut req);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,10 +24,11 @@ pub enum CallAbiTable {
|
||||
LockDisplay = 2,
|
||||
DrawIter = 3,
|
||||
GetKey = 4,
|
||||
GenRand = 5,
|
||||
}
|
||||
|
||||
impl CallAbiTable {
|
||||
pub const COUNT: usize = 5;
|
||||
pub const COUNT: usize = 6;
|
||||
}
|
||||
|
||||
pub type PrintAbi = extern "Rust" fn(msg: &str);
|
||||
@@ -84,3 +85,21 @@ pub fn get_key() -> Option<KeyEvent> {
|
||||
f()
|
||||
}
|
||||
}
|
||||
|
||||
pub type GenRand = extern "Rust" fn(req: &mut RngRequest);
|
||||
|
||||
#[repr(C)]
|
||||
pub enum RngRequest {
|
||||
U32(u32),
|
||||
U64(u64),
|
||||
Bytes { ptr: *mut u8, len: usize },
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
pub fn gen_rand(req: &mut RngRequest) {
|
||||
unsafe {
|
||||
let ptr = CALL_ABI_TABLE[CallAbiTable::GenRand as usize];
|
||||
let f: GenRand = core::mem::transmute(ptr);
|
||||
f(req)
|
||||
}
|
||||
}
|
||||
|
||||
4
justfile
4
justfile
@@ -1,4 +1,6 @@
|
||||
kernel: calculator
|
||||
kernel:
|
||||
cargo run --bin kernel
|
||||
calculator:
|
||||
RUSTFLAGS="-C link-arg=--noinhibit-exec" cargo build --bin calculator --profile release-binary
|
||||
snake:
|
||||
RUSTFLAGS="-C link-arg=--noinhibit-exec" cargo build --bin snake --profile release-binary
|
||||
|
||||
@@ -79,6 +79,7 @@ embedded-text = "0.7.2"
|
||||
embedded-layout = "0.4.2"
|
||||
kolibri-embedded-gui = "0.1.0"
|
||||
|
||||
rand = { version = "0.9.0", default-features = false }
|
||||
once_cell = { version = "1.21.3", default-features = false }
|
||||
static_cell = "2.1.1"
|
||||
bitflags = "2.9.4"
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
use core::sync::atomic::Ordering;
|
||||
|
||||
use abi_sys::{DrawIterAbi, GetKeyAbi, LockDisplay, PrintAbi, SleepAbi};
|
||||
use embassy_rp::clocks::clk_sys_freq;
|
||||
use abi_sys::{DrawIterAbi, GetKeyAbi, LockDisplay, PrintAbi, RngRequest, SleepAbi};
|
||||
use core::{ptr::slice_from_raw_parts, sync::atomic::Ordering};
|
||||
use embassy_rp::clocks::{RoscRng, clk_sys_freq};
|
||||
use embedded_graphics::{Pixel, draw_target::DrawTarget, pixelcolor::Rgb565};
|
||||
use rand::Rng;
|
||||
use shared::keyboard::KeyEvent;
|
||||
|
||||
use crate::{
|
||||
@@ -23,10 +23,10 @@ pub extern "Rust" fn print(msg: &str) {
|
||||
|
||||
pub extern "Rust" fn sleep(ms: u64) {
|
||||
let cycles_per_ms = clk_sys_freq() / 1000;
|
||||
for _ in 0..ms {
|
||||
for _ in 0..cycles_per_ms {
|
||||
cortex_m::asm::nop();
|
||||
}
|
||||
let total_cycles = ms * cycles_per_ms as u64;
|
||||
|
||||
for _ in 0..total_cycles {
|
||||
cortex_m::asm::nop();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,3 +42,16 @@ pub extern "Rust" fn draw_iter(pixels: &[Pixel<Rgb565>]) {
|
||||
pub extern "Rust" fn get_key() -> Option<KeyEvent> {
|
||||
unsafe { KEY_CACHE.dequeue() }
|
||||
}
|
||||
|
||||
pub extern "Rust" fn gen_rand(req: &mut RngRequest) {
|
||||
let mut rng = RoscRng;
|
||||
|
||||
match req {
|
||||
RngRequest::U32(i) => *i = rng.next_u32(),
|
||||
RngRequest::U64(i) => *i = rng.next_u64(),
|
||||
RngRequest::Bytes { ptr, len } => {
|
||||
let slice: &mut [u8] = unsafe { core::slice::from_raw_parts_mut(*ptr, *len) };
|
||||
rng.fill_bytes(slice);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -59,6 +59,6 @@ pub async fn display_handler(mut display: DISPLAY) {
|
||||
}
|
||||
}
|
||||
|
||||
Timer::after_millis(32).await; // 30 fps
|
||||
Timer::after_millis(10).await;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -57,6 +57,7 @@ pub async unsafe fn load_binary(name: &ShortFileName) -> Result<EntryFn, &str> {
|
||||
(CallAbiTable::LockDisplay, abi::lock_display as usize),
|
||||
(CallAbiTable::DrawIter, abi::draw_iter as usize),
|
||||
(CallAbiTable::GetKey, abi::get_key as usize),
|
||||
(CallAbiTable::GenRand, abi::gen_rand as usize),
|
||||
];
|
||||
assert!(entries.len() == CallAbiTable::COUNT);
|
||||
|
||||
|
||||
@@ -15,10 +15,10 @@ use embedded_graphics::{
|
||||
text::Text,
|
||||
};
|
||||
use embedded_layout::{
|
||||
align::{horizontal, vertical},
|
||||
View,
|
||||
align::{Align, horizontal, vertical},
|
||||
layout::linear::LinearLayout,
|
||||
object_chain::Chain,
|
||||
prelude::*,
|
||||
prelude::Chain,
|
||||
};
|
||||
|
||||
#[panic_handler]
|
||||
@@ -37,7 +37,7 @@ pub extern "Rust" fn _start() {
|
||||
}
|
||||
|
||||
pub fn main() {
|
||||
print("Starting Async Calculator app");
|
||||
print("Starting Calculator app");
|
||||
let mut display = Display;
|
||||
|
||||
let mut input = vec!['e', 'x', 'p', 'r', ':', ' '];
|
||||
|
||||
10
user-apps/snake/Cargo.toml
Normal file
10
user-apps/snake/Cargo.toml
Normal file
@@ -0,0 +1,10 @@
|
||||
[package]
|
||||
name = "snake"
|
||||
version = "0.1.0"
|
||||
edition = "2024"
|
||||
|
||||
[dependencies]
|
||||
abi = { path = "../../abi" }
|
||||
embedded-graphics = "0.8.1"
|
||||
embedded-snake = { path = "../../../embedded-snake-rs" }
|
||||
rand = { version = "0.9.0", default-features = false }
|
||||
28
user-apps/snake/build.rs
Normal file
28
user-apps/snake/build.rs
Normal file
@@ -0,0 +1,28 @@
|
||||
//! This build script copies the `memory.x` file from the crate root into
|
||||
//! a directory where the linker can always find it at build time.
|
||||
//! For many projects this is optional, as the linker always searches the
|
||||
//! project root directory -- wherever `Cargo.toml` is. However, if you
|
||||
//! are using a workspace or have a more complicated build setup, this
|
||||
//! build script becomes required. Additionally, by requesting that
|
||||
//! Cargo re-run the build script whenever `memory.x` is changed,
|
||||
//! updating `memory.x` ensures a rebuild of the application with the
|
||||
//! new memory settings.
|
||||
|
||||
use std::env;
|
||||
use std::fs::File;
|
||||
use std::io::Write;
|
||||
use std::path::PathBuf;
|
||||
|
||||
fn main() {
|
||||
// Put `memory.x` in our output directory and ensure it's
|
||||
// on the linker search path.
|
||||
let out = &PathBuf::from(env::var_os("OUT_DIR").unwrap());
|
||||
File::create(out.join("memory.x"))
|
||||
.unwrap()
|
||||
.write_all(include_bytes!("../memory.x"))
|
||||
.unwrap();
|
||||
println!("cargo:rustc-link-search={}", out.display());
|
||||
|
||||
println!("cargo:rerun-if-changed=memory.x");
|
||||
println!("cargo:rustc-link-arg-bins=-Tmemory.x");
|
||||
}
|
||||
69
user-apps/snake/src/main.rs
Normal file
69
user-apps/snake/src/main.rs
Normal file
@@ -0,0 +1,69 @@
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
extern crate alloc;
|
||||
use abi::{
|
||||
KeyCode, Rng,
|
||||
display::{Display, SCREEN_HEIGHT, SCREEN_WIDTH},
|
||||
get_key, lock_display, print, sleep,
|
||||
};
|
||||
use alloc::format;
|
||||
use core::panic::PanicInfo;
|
||||
use embedded_graphics::{pixelcolor::Rgb565, prelude::RgbColor};
|
||||
use embedded_snake::{Direction, SnakeGame};
|
||||
|
||||
#[panic_handler]
|
||||
fn panic(info: &PanicInfo) -> ! {
|
||||
print(&format!(
|
||||
"user panic: {} @ {:?}",
|
||||
info.message(),
|
||||
info.location(),
|
||||
));
|
||||
loop {}
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
pub extern "Rust" fn _start() {
|
||||
main()
|
||||
}
|
||||
|
||||
const CELL_SIZE: usize = 8;
|
||||
|
||||
pub fn main() {
|
||||
print("Starting Snake app");
|
||||
let mut display = Display;
|
||||
|
||||
let mut game = SnakeGame::<100, Rgb565, Rng>::new(
|
||||
SCREEN_WIDTH as u16,
|
||||
SCREEN_HEIGHT as u16,
|
||||
CELL_SIZE as u16,
|
||||
CELL_SIZE as u16,
|
||||
Rng,
|
||||
Rgb565::BLACK,
|
||||
Rgb565::GREEN,
|
||||
Rgb565::RED,
|
||||
50,
|
||||
);
|
||||
|
||||
loop {
|
||||
if let Some(event) = get_key() {
|
||||
let direction = match event.key {
|
||||
KeyCode::Up => Direction::Up,
|
||||
KeyCode::Down => Direction::Down,
|
||||
KeyCode::Right => Direction::Right,
|
||||
KeyCode::Left => Direction::Left,
|
||||
KeyCode::Esc => return,
|
||||
_ => Direction::None,
|
||||
};
|
||||
game.set_direction(direction);
|
||||
}
|
||||
|
||||
// ensure all draws show up at once
|
||||
lock_display(true);
|
||||
game.pre_draw(&mut display);
|
||||
game.draw(&mut display);
|
||||
lock_display(false);
|
||||
|
||||
sleep(15);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user