doom compiles but is BIG

This commit is contained in:
2025-10-31 13:39:16 -06:00
parent 970d021a9a
commit 46bfa89e18
11 changed files with 261 additions and 38 deletions

View File

@@ -46,7 +46,6 @@ pub fn get_key() -> KeyEvent {
pub mod display { pub mod display {
use abi_sys::CPixel; use abi_sys::CPixel;
use alloc::{vec, vec::Vec};
use embedded_graphics::{ use embedded_graphics::{
Pixel, Pixel,
geometry::{Dimensions, Point}, geometry::{Dimensions, Point},
@@ -54,7 +53,6 @@ pub mod display {
prelude::{DrawTarget, Size}, prelude::{DrawTarget, Size},
primitives::Rectangle, primitives::Rectangle,
}; };
use once_cell::unsync::Lazy;
pub const SCREEN_WIDTH: usize = 320; pub const SCREEN_WIDTH: usize = 320;
pub const SCREEN_HEIGHT: usize = 320; pub const SCREEN_HEIGHT: usize = 320;

View File

@@ -17,3 +17,4 @@ userapps: cbindgen
just userapp snake just userapp snake
just userapp gallery just userapp gallery
just userapp gif just userapp gif
just userapp doom

View File

@@ -11,9 +11,13 @@
use std::env; use std::env;
use std::fs::File; use std::fs::File;
use std::io::Write; use std::io::Write;
use std::path::PathBuf; use std::path::{Path, PathBuf};
use std::process::Command;
fn main() { fn main() {
build_newlib();
build_doom();
// Put `memory.x` in our output directory and ensure it's // Put `memory.x` in our output directory and ensure it's
// on the linker search path. // on the linker search path.
let out = &PathBuf::from(env::var_os("OUT_DIR").unwrap()); let out = &PathBuf::from(env::var_os("OUT_DIR").unwrap());
@@ -25,7 +29,58 @@ fn main() {
println!("cargo:rerun-if-changed=memory.x"); println!("cargo:rerun-if-changed=memory.x");
println!("cargo:rustc-link-arg-bins=-Tmemory.x"); println!("cargo:rustc-link-arg-bins=-Tmemory.x");
}
// TODO: use target to change newlib build - only workds for rp2350 right now
fn build_newlib() {
let out_dir = std::env::var("OUT_DIR").unwrap();
let picolibc_dir = format!("{}/picolibc", out_dir);
if !Path::new(&picolibc_dir).exists() {
let status = Command::new("git")
.args(&[
"clone",
"https://github.com/picolibc/picolibc",
&picolibc_dir,
])
.status()
.expect("Failed to clone picolibc");
assert!(status.success());
}
let build_dir = format!("{}/build", picolibc_dir);
std::fs::create_dir_all(&build_dir).unwrap();
let status = Command::new(&format!("{picolibc_dir}/scripts/do-configure"))
.current_dir(&build_dir)
.args(&[
"thumbv8m_main_fp-none-eabi",
"--buildtype=minsize",
"-Dtests=true",
"-Dtinystdio=false",
"-Dsingle-thread=true",
"-Db_pie=true",
"-Ddefault_library=static",
"-Dtinystdio=false",
"-Dmultilib=false",
".",
])
.status()
.expect("Failed to run Meson configure");
assert!(status.success());
let status = Command::new("ninja")
.current_dir(&build_dir)
.status()
.expect("Failed to run Ninja build");
assert!(status.success());
println!("cargo:rustc-link-search={}/newlib", build_dir);
println!("cargo:rustc-link-lib=c");
println!("cargo:rustc-link-lib=m");
}
fn build_doom() {
let ref dg_src_dir = std::path::PathBuf::from("doomgeneric/doomgeneric"); let ref dg_src_dir = std::path::PathBuf::from("doomgeneric/doomgeneric");
let mut dg_c_paths = vec![]; let mut dg_c_paths = vec![];
let mut dg_h_paths = vec![]; let mut dg_h_paths = vec![];
@@ -37,6 +92,7 @@ fn main() {
if filename.starts_with("doomgeneric") if filename.starts_with("doomgeneric")
|| filename.contains("_allegro") || filename.contains("_allegro")
|| filename.contains("_sdl") || filename.contains("_sdl")
|| filename.contains("net_")
|| filename == "i_main.c" || filename == "i_main.c"
{ {
continue; continue;
@@ -55,16 +111,16 @@ fn main() {
.for_each(|path| println!("cargo:rerun-if-changed={}", path.to_str().unwrap())); .for_each(|path| println!("cargo:rerun-if-changed={}", path.to_str().unwrap()));
cc::Build::new() cc::Build::new()
.compiler("arm-none-eabi-gcc")
.flag("-w") // silence warnings .flag("-w") // silence warnings
.flag("-Os") // optimize for size .flag("-Os") // optimize for size
.flag("-ffunction-sections")
.flag("-fdata-sections")
.define("CMAP256", None) .define("CMAP256", None)
.define("DOOMGENERIC_RESX", Some("320")) .define("DOOMGENERIC_RESX", Some("320"))
.define("DOOMGENERIC_RESY", Some("200")) .define("DOOMGENERIC_RESY", Some("200"))
.define("MAXPLAYERS", Some("1")) .flag_if_supported("-std=gnu99")
.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")) .define("_POSIX_C_SOURCE", Some("200809L"))
.files(dg_c_paths) .files(dg_c_paths)
.include(".")
.compile("doomgeneric"); .compile("doomgeneric");
} }

View File

@@ -1,4 +0,0 @@
#ifndef INTTYPES_H
#define INTTYPES_H
#endif

View File

@@ -1,4 +0,0 @@
#ifndef STRINGS_H
#define STRINGS_H
#endif

View File

@@ -1,10 +1,72 @@
use abi::{
abi_sys::{get_ms, sleep},
display::Display,
};
use core::ffi::{c_int, c_uchar};
use embedded_graphics::{
Drawable, Pixel,
draw_target::DrawTarget,
pixelcolor::Rgb565,
prelude::{Point, RgbColor},
};
#[unsafe(no_mangle)]
#[allow(non_snake_case)]
static mut DG_ScreenBuffer: *const u8 = core::ptr::null();
#[repr(C)]
#[derive(Clone, Copy, Debug)]
pub struct RGBA {
pub b: u8,
pub g: u8,
pub r: u8,
pub a: u8,
}
unsafe extern "C" {
fn D_DoomMain();
fn doomgeneric_Tick();
fn M_FindResponseFile();
pub static colors: [RGBA; 256];
}
pub fn tick() {
unsafe { doomgeneric_Tick() };
}
pub struct ScreenBuffer<const RESX: usize, const RESY: usize, const SIZE: usize>(pub [u8; SIZE]);
impl<const RESX: usize, const RESY: usize, const SIZE: usize> ScreenBuffer<RESX, RESY, SIZE> {
#[allow(dead_code)]
const NA: () = assert!(SIZE == RESX * RESY);
pub const fn new() -> Self {
Self([0_u8; SIZE])
}
}
#[unsafe(no_mangle)]
extern "C" fn DG_SetWindowTitle() {}
pub fn create<const RESX: usize, const RESY: usize, const SIZE: usize>(
screenbuffer: &ScreenBuffer<RESX, RESY, SIZE>,
) {
unsafe {
M_FindResponseFile();
DG_ScreenBuffer = screenbuffer.0.as_ptr();
D_DoomMain();
}
}
const X: usize = 320; const X: usize = 320;
const Y: usize = 200; const Y: usize = 200;
const SIZE: usize = X * Y; const SIZE: usize = X * Y;
pub static mut DISPLAY: Option<SimulatorDisplay<Rgb565>> = None; pub static mut DISPLAY: Option<Display> = None;
pub static mut SCREEN_BUFFER: ScreenBuffer<X, Y, SIZE> = ScreenBuffer::new(); pub static mut SCREEN_BUFFER: ScreenBuffer<X, Y, SIZE> = ScreenBuffer::new();
pub static mut START: Option<Instant> = None;
#[unsafe(no_mangle)] #[unsafe(no_mangle)]
extern "C" fn DG_DrawFrame() { extern "C" fn DG_DrawFrame() {
@@ -36,20 +98,15 @@ extern "C" fn DG_DrawFrame() {
#[unsafe(no_mangle)] #[unsafe(no_mangle)]
extern "C" fn DG_GetTicksMs() -> u32 { extern "C" fn DG_GetTicksMs() -> u32 {
let start = unsafe { START.unwrap() }; get_ms() as u32
Instant::now()
.duration_since(start)
.as_millis()
.try_into()
.expect("Cannot Fit Start time into u32")
} }
#[unsafe(no_mangle)] #[unsafe(no_mangle)]
extern "C" fn DG_GetKey(pressed: *mut raw::c_int, key: *mut raw::c_uchar) -> raw::c_int { extern "C" fn DG_GetKey(pressed: *mut c_int, key: *mut c_uchar) -> c_int {
0 0
} }
#[unsafe(no_mangle)] #[unsafe(no_mangle)]
extern "C" fn DG_SleepMs(ms: u32) { extern "C" fn DG_SleepMs(ms: u32) {
sleep(Duration::from_millis(ms as u64)); sleep(ms.into());
} }

118
user-apps/doom/src/libc.rs Normal file
View File

@@ -0,0 +1,118 @@
use core::ffi::{c_char, c_int, c_uchar, c_void};
use core::ptr;
#[unsafe(no_mangle)]
pub static _ctype_: [c_uchar; 256] = [0u8; 256];
#[repr(C)]
pub struct Reent {
pub errno: c_int,
_reserved: [u8; 32],
}
#[unsafe(no_mangle)]
pub static mut _reent_data: Reent = Reent {
errno: 0,
_reserved: [0; 32],
};
#[unsafe(no_mangle)]
pub static mut _impure_ptr: *mut Reent = unsafe { &mut _reent_data as *mut Reent };
#[unsafe(no_mangle)]
pub extern "C" fn __errno() -> *mut c_int {
unsafe { &mut (*_impure_ptr).errno as *mut c_int }
}
#[unsafe(no_mangle)]
pub extern "C" fn exit(_status: i32) -> ! {
loop {}
}
#[unsafe(no_mangle)]
pub extern "C" fn close(_file: i32) -> i32 {
-1
}
#[repr(C)]
pub struct Stat {
st_mode: u32,
}
#[unsafe(no_mangle)]
pub extern "C" fn fstat(_file: i32, st: *mut Stat) -> i32 {
unsafe {
if !st.is_null() {
(*st).st_mode = 0x2000; // S_IFCHR
}
}
0
}
#[unsafe(no_mangle)]
pub extern "C" fn isatty(_file: i32) -> i32 {
1
}
#[unsafe(no_mangle)]
pub extern "C" fn lseek(_file: i32, _ptr: i32, _dir: i32) -> i32 {
0
}
#[unsafe(no_mangle)]
pub extern "C" fn lseek64(_fd: c_int, _offset: i64, _whence: c_int) -> i64 {
0
}
#[unsafe(no_mangle)]
pub extern "C" fn open(_name: *const u8, _flags: i32, _mode: i32) -> i32 {
-1
}
#[unsafe(no_mangle)]
pub extern "C" fn read(_file: i32, _ptr: *mut u8, len: usize) -> i32 {
len as i32
}
#[unsafe(no_mangle)]
pub extern "C" fn write(_file: i32, _ptr: *const u8, len: usize) -> i32 {
len as i32
}
#[unsafe(no_mangle)]
pub extern "C" fn rename(_old: *const c_char, _new: *const c_char) -> c_int {
-1
}
#[unsafe(no_mangle)]
pub extern "C" fn kill(_pid: i32, _sig: i32) -> i32 {
-1
}
#[unsafe(no_mangle)]
pub extern "C" fn getpid() -> i32 {
1
}
#[unsafe(no_mangle)]
pub extern "C" fn link(_old: *const u8, _new: *const u8) -> i32 {
-1
}
#[unsafe(no_mangle)]
pub extern "C" fn unlink(_name: *const u8) -> i32 {
-1
}
#[unsafe(no_mangle)]
pub extern "C" fn mkdir(_path: *const u8, _mode: u32) -> i32 {
0
}
#[unsafe(no_mangle)]
pub extern "C" fn sbrk(incr: isize) -> *mut c_void {
core::ptr::null_mut()
}
#[unsafe(no_mangle)]
pub extern "C" fn fini() {}

View File

@@ -1,5 +1,7 @@
#![no_std] #![no_std]
#![no_main] #![no_main]
#![allow(static_mut_refs)]
#![feature(c_variadic)]
extern crate alloc; extern crate alloc;
use abi::{ use abi::{
@@ -13,6 +15,10 @@ use alloc::vec;
use core::panic::PanicInfo; use core::panic::PanicInfo;
use embedded_graphics::{pixelcolor::Rgb565, prelude::Point}; use embedded_graphics::{pixelcolor::Rgb565, prelude::Point};
mod doom;
use crate::doom::{DISPLAY, SCREEN_BUFFER, create, tick};
mod libc;
#[panic_handler] #[panic_handler]
fn panic(info: &PanicInfo) -> ! { fn panic(info: &PanicInfo) -> ! {
print!("user panic: {} @ {:?}", info.message(), info.location(),); print!("user panic: {} @ {:?}", info.message(), info.location(),);
@@ -26,5 +32,12 @@ pub extern "Rust" fn _start() {
pub fn main() { pub fn main() {
print!("Starting Doom app"); print!("Starting Doom app");
let mut display = Display; let display = Display;
unsafe { DISPLAY = Some(display) };
unsafe { create(&SCREEN_BUFFER) };
loop {
tick();
}
} }

View File

@@ -1,4 +0,0 @@
#ifndef STDIO_H
#define STDIO_H
#endif

View File

@@ -1,4 +0,0 @@
#ifndef STRING_H
#define STRING_H
#endif

View File

@@ -1,4 +0,0 @@
#ifndef STRINGS_H
#define STRINGS_H
#endif