diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..124759c --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "user-apps/doom/doomgeneric"] + path = user-apps/doom/doomgeneric + url = https://github.com/ozkl/doomgeneric diff --git a/Cargo.lock b/Cargo.lock index 88f54ea..7059bd5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -133,6 +133,26 @@ version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" +[[package]] +name = "bindgen" +version = "0.71.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f58bf3d7db68cfbac37cfc485a8d711e87e064c3d0fe0435b92f7a407f9d6b3" +dependencies = [ + "bitflags 2.9.4", + "cexpr", + "clang-sys", + "itertools 0.10.5", + "log", + "prettyplease", + "proc-macro2", + "quote", + "regex", + "rustc-hash", + "shlex", + "syn 2.0.104", +] + [[package]] name = "bit-set" version = "0.5.3" @@ -275,12 +295,42 @@ dependencies = [ "toml", ] +[[package]] +name = "cc" +version = "1.2.43" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "739eb0f94557554b3ca9a86d2d37bebd49c5e6d0c1d2bda35ba5bdac830befc2" +dependencies = [ + "find-msvc-tools", + "shlex", +] + +[[package]] +name = "cexpr" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766" +dependencies = [ + "nom", +] + [[package]] name = "cfg-if" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9555578bc9e57714c812a1f84e4fc5b4d21fcb063490c624de019f7464c91268" +[[package]] +name = "clang-sys" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b023947811758c97c59bf9d1c188fd619ad4718dcaa767947df1cadb14f39f4" +dependencies = [ + "glob", + "libc", + "libloading", +] + [[package]] name = "clap" version = "3.2.25" @@ -564,6 +614,16 @@ dependencies = [ "litrs", ] +[[package]] +name = "doom" +version = "0.1.0" +dependencies = [ + "abi", + "bindgen", + "cc", + "embedded-graphics", +] + [[package]] name = "either" version = "1.15.0" @@ -1107,6 +1167,12 @@ version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" +[[package]] +name = "find-msvc-tools" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52051878f80a721bb68ebfbc930e07b65ba72f2da88968ea5c06fd6ca3d3a127" + [[package]] name = "fixed" version = "1.29.0" @@ -1292,6 +1358,12 @@ dependencies = [ "tinygif", ] +[[package]] +name = "glob" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0cc23270f6e1808e30a928bdc84dea0b9b4136a8bc82338574f23baf47bbd280" + [[package]] name = "goblin" version = "0.10.2" @@ -1604,6 +1676,16 @@ version = "0.2.174" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1171693293099992e19cddea4e8b849964e9846f4acee11b3948bcc337be8776" +[[package]] +name = "libloading" +version = "0.8.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7c4b02199fee7c5d21a5ae7d8cfa79a6ef5bb2fc834d6e9058e89c825efdc55" +dependencies = [ + "cfg-if", + "windows-link", +] + [[package]] name = "libredox" version = "0.1.4" @@ -1660,6 +1742,12 @@ version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c3c8dda44ff03a2f238717214da50f65d5a53b45cd213a7370424ffdb6fae815" +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + [[package]] name = "nb" version = "0.1.3" @@ -1681,6 +1769,16 @@ version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "650eef8c711430f1a879fdd01d4745a7deea475becfb90269c06775983bbf086" +[[package]] +name = "nom" +version = "7.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" +dependencies = [ + "memchr", + "minimal-lexical", +] + [[package]] name = "num-traits" version = "0.2.19" @@ -1944,6 +2042,16 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c" +[[package]] +name = "prettyplease" +version = "0.2.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff24dfcda44452b9816fff4cd4227e1bb73ff5a2f1bc1105aa92fb8565ce44d2" +dependencies = [ + "proc-macro2", + "syn 2.0.104", +] + [[package]] name = "proc-macro-error" version = "1.0.4" @@ -2136,6 +2244,12 @@ dependencies = [ "crc-any", ] +[[package]] +name = "rustc-hash" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d" + [[package]] name = "rustc_version" version = "0.2.3" @@ -2265,6 +2379,12 @@ dependencies = [ "keccak", ] +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + [[package]] name = "siphasher" version = "1.0.1" @@ -2833,6 +2953,12 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +[[package]] +name = "windows-link" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" + [[package]] name = "windows-sys" version = "0.59.0" diff --git a/Cargo.toml b/Cargo.toml index 9e88380..768b290 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,6 +8,7 @@ members = [ "user-apps/snake", "user-apps/gallery", "user-apps/gif", + "user-apps/doom", ] [profile.release] diff --git a/user-apps/doom/Cargo.toml b/user-apps/doom/Cargo.toml new file mode 100644 index 0000000..4e57be3 --- /dev/null +++ b/user-apps/doom/Cargo.toml @@ -0,0 +1,12 @@ +[package] +name = "doom" +version = "0.1.0" +edition = "2024" + +[dependencies] +abi = { path = "../../abi" } +embedded-graphics = "0.8.1" + +[build-dependencies] +bindgen = "0.71.0" +cc = "1.0" diff --git a/user-apps/doom/build.rs b/user-apps/doom/build.rs new file mode 100644 index 0000000..6342e96 --- /dev/null +++ b/user-apps/doom/build.rs @@ -0,0 +1,70 @@ +//! 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"); + + let ref dg_src_dir = std::path::PathBuf::from("doomgeneric/doomgeneric"); + let mut dg_c_paths = vec![]; + let mut dg_h_paths = vec![]; + + // Find most c and h files + for entry in std::fs::read_dir(dg_src_dir).unwrap() { + let entry = entry.unwrap(); + if let Some(filename) = entry.file_name().to_str() { + if filename.starts_with("doomgeneric") + || filename.contains("_allegro") + || filename.contains("_sdl") + || filename == "i_main.c" + { + continue; + } + + if filename.ends_with(".h") { + dg_h_paths.push(dg_src_dir.join(filename)); + } else if filename.ends_with(".c") { + dg_c_paths.push(dg_src_dir.join(filename)); + } + } + } + dg_c_paths + .iter() + .chain(dg_h_paths.iter()) + .for_each(|path| println!("cargo:rerun-if-changed={}", path.to_str().unwrap())); + + cc::Build::new() + .flag("-w") // silence warnings + .flag("-Os") // optimize for size + .define("CMAP256", None) + .define("DOOMGENERIC_RESX", Some("320")) + .define("DOOMGENERIC_RESY", Some("200")) + .define("MAXPLAYERS", Some("1")) + .flag_if_supported("-std=gnu89") // old-style C, allows implicit int + .flag("-Wno-implicit-function-declaration") // ignore missing prototypes + .define("_POSIX_C_SOURCE", Some("200809L")) + .files(dg_c_paths) + .include(".") + .compile("doomgeneric"); +} diff --git a/user-apps/doom/doomgeneric b/user-apps/doom/doomgeneric new file mode 160000 index 0000000..fc60163 --- /dev/null +++ b/user-apps/doom/doomgeneric @@ -0,0 +1 @@ +Subproject commit fc601639494e089702a1ada082eb51aaafc03722 diff --git a/user-apps/doom/inttypes.h b/user-apps/doom/inttypes.h new file mode 100644 index 0000000..d2edacc --- /dev/null +++ b/user-apps/doom/inttypes.h @@ -0,0 +1,4 @@ +#ifndef INTTYPES_H +#define INTTYPES_H + +#endif diff --git a/user-apps/doom/limits.h b/user-apps/doom/limits.h new file mode 100644 index 0000000..9ef223e --- /dev/null +++ b/user-apps/doom/limits.h @@ -0,0 +1,4 @@ +#ifndef STRINGS_H +#define STRINGS_H + +#endif diff --git a/user-apps/doom/src/doom.rs b/user-apps/doom/src/doom.rs new file mode 100644 index 0000000..13cc7f6 --- /dev/null +++ b/user-apps/doom/src/doom.rs @@ -0,0 +1,55 @@ +const X: usize = 320; +const Y: usize = 200; +const SIZE: usize = X * Y; + +pub static mut DISPLAY: Option> = None; +pub static mut SCREEN_BUFFER: ScreenBuffer = ScreenBuffer::new(); +pub static mut START: Option = None; + +#[unsafe(no_mangle)] +extern "C" fn DG_DrawFrame() { + let palette565: [Rgb565; 256] = unsafe { + colors.map(|c| { + Rgb565::new( + ((c.r as u16 * 31) / 255) as u8, // red 5 bits + ((c.g as u16 * 63) / 255) as u8, // green 6 bits + ((c.b as u16 * 31) / 255) as u8, // blue 5 bits + ) + }) + }; + let buf = unsafe { &SCREEN_BUFFER.0 }; + + let display = unsafe { DISPLAY.as_mut().unwrap() }; + display.clear(Rgb565::BLACK).unwrap(); + + for y in 0..Y { + for x in 0..X { + let idx = y * X + x; + let color = palette565[buf[idx] as usize]; + + Pixel(Point::new(x as i32, y as i32), color) + .draw(display) + .unwrap(); + } + } +} + +#[unsafe(no_mangle)] +extern "C" fn DG_GetTicksMs() -> u32 { + let start = unsafe { START.unwrap() }; + Instant::now() + .duration_since(start) + .as_millis() + .try_into() + .expect("Cannot Fit Start time into u32") +} + +#[unsafe(no_mangle)] +extern "C" fn DG_GetKey(pressed: *mut raw::c_int, key: *mut raw::c_uchar) -> raw::c_int { + 0 +} + +#[unsafe(no_mangle)] +extern "C" fn DG_SleepMs(ms: u32) { + sleep(Duration::from_millis(ms as u64)); +} diff --git a/user-apps/doom/src/main.rs b/user-apps/doom/src/main.rs new file mode 100644 index 0000000..613849c --- /dev/null +++ b/user-apps/doom/src/main.rs @@ -0,0 +1,30 @@ +#![no_std] +#![no_main] + +extern crate alloc; +use abi::{ + display::Display, + fs::{file_len, read_file}, + get_key, get_ms, + keyboard::{KeyCode, KeyState}, + print, sleep, +}; +use alloc::vec; +use core::panic::PanicInfo; +use embedded_graphics::{pixelcolor::Rgb565, prelude::Point}; + +#[panic_handler] +fn panic(info: &PanicInfo) -> ! { + print!("user panic: {} @ {:?}", info.message(), info.location(),); + loop {} +} + +#[unsafe(no_mangle)] +pub extern "Rust" fn _start() { + main() +} + +pub fn main() { + print!("Starting Doom app"); + let mut display = Display; +} diff --git a/user-apps/doom/stdio.h b/user-apps/doom/stdio.h new file mode 100644 index 0000000..b86ad68 --- /dev/null +++ b/user-apps/doom/stdio.h @@ -0,0 +1,4 @@ +#ifndef STDIO_H +#define STDIO_H + +#endif diff --git a/user-apps/doom/string.h b/user-apps/doom/string.h new file mode 100644 index 0000000..e8f8650 --- /dev/null +++ b/user-apps/doom/string.h @@ -0,0 +1,4 @@ +#ifndef STRING_H +#define STRING_H + +#endif diff --git a/user-apps/doom/strings.h b/user-apps/doom/strings.h new file mode 100644 index 0000000..9ef223e --- /dev/null +++ b/user-apps/doom/strings.h @@ -0,0 +1,4 @@ +#ifndef STRINGS_H +#define STRINGS_H + +#endif