From ccc81273d59014444b250eaeb1bf4ee7088125a0 Mon Sep 17 00:00:00 2001 From: Rafal Mielniczuk Date: Sat, 12 Oct 2024 18:04:03 +0100 Subject: [PATCH] Add rust doom port --- .gitmodules | 4 + Cargo.lock | 52 +--- cykusz-rs/src/arch/x86_64/asm/linker.ld | 1 - cykusz-rs/src/drivers/ps2/mouse/handler.rs | 1 + disk-scripts/install_os.sh | 2 +- syscall-defs/src/events/buttons.rs | 2 + syscall-defs/src/events/keys.rs | 1 + syscall-defs/src/ioctl/fb.rs | 1 + userspace/.cargo/config.toml | 4 + userspace/Cargo.lock | 29 ++- userspace/Cargo.toml | 2 +- userspace/doom/Cargo.toml | 16 ++ userspace/doom/build.rs | 37 +++ userspace/doom/doomgeneric | 1 + userspace/doom/src/cykusz.rs | 44 ++++ userspace/doom/src/cykusz/fb.rs | 68 +++++ userspace/doom/src/cykusz/input.rs | 232 ++++++++++++++++++ userspace/doom/src/keys.rs | 66 +++++ userspace/doom/src/main.rs | 130 ++++++++++ .../sound-daemon/src/sound-daemon/bin/main.rs | 2 +- 20 files changed, 643 insertions(+), 52 deletions(-) create mode 100644 userspace/doom/Cargo.toml create mode 100644 userspace/doom/build.rs create mode 160000 userspace/doom/doomgeneric create mode 100644 userspace/doom/src/cykusz.rs create mode 100644 userspace/doom/src/cykusz/fb.rs create mode 100644 userspace/doom/src/cykusz/input.rs create mode 100644 userspace/doom/src/keys.rs create mode 100644 userspace/doom/src/main.rs diff --git a/.gitmodules b/.gitmodules index 5f7f5af2..64227c52 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,7 @@ [submodule "acpica/acpica"] path = acpica/acpica url = https://github.com/acpica/acpica +[submodule "userspace/doom/doomgeneric"] + path = userspace/doom/doomgeneric + url = https://github.com/rafalmiel/doomgeneric.git + branch = cykusz diff --git a/Cargo.lock b/Cargo.lock index 65f1975a..38f09634 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6,18 +6,6 @@ version = 3 name = "acpica" version = "0.1.0" -[[package]] -name = "ahash" -version = "0.8.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" -dependencies = [ - "cfg-if", - "once_cell", - "version_check", - "zerocopy", -] - [[package]] name = "allocator-api2" version = "0.2.18" @@ -60,12 +48,6 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" -[[package]] -name = "cfg-if" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" - [[package]] name = "chrono" version = "0.4.38" @@ -85,7 +67,7 @@ dependencies = [ "bitmaps", "chrono", "downcast-rs", - "hashbrown 0.15.0", + "hashbrown", "intrusive-collections", "lazy_static", "linked_list_allocator", @@ -118,16 +100,6 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f81ec6369c545a7d40e4589b5597581fa1c441fe1cce96dd1de43159910a36a2" -[[package]] -name = "hashbrown" -version = "0.14.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" -dependencies = [ - "ahash", - "allocator-api2", -] - [[package]] name = "hashbrown" version = "0.15.0" @@ -178,11 +150,11 @@ dependencies = [ [[package]] name = "lru" -version = "0.12.4" +version = "0.12.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37ee39891760e7d94734f6f63fedc29a2e4a152f836120753a72503f09fcf904" +checksum = "234cf4f4a04dc1f57e24b96cc0cd600cf2af460d4161ac5ecdd0af8e1f3b2a38" dependencies = [ - "hashbrown 0.14.5", + "hashbrown", ] [[package]] @@ -203,12 +175,6 @@ dependencies = [ "autocfg", ] -[[package]] -name = "once_cell" -version = "1.20.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" - [[package]] name = "paste" version = "1.0.15" @@ -226,9 +192,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.86" +version = "1.0.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" +checksum = "b3e4daa0dcf6feba26f985457cdf104d4b4256fc5a09547140f3631bb076b19a" dependencies = [ "unicode-ident", ] @@ -343,12 +309,6 @@ version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "81dfa00651efa65069b0b6b651f4aaa31ba9e3c3ce0137aaad053604ee7e0314" -[[package]] -name = "version_check" -version = "0.9.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" - [[package]] name = "vte" version = "0.13.0" diff --git a/cykusz-rs/src/arch/x86_64/asm/linker.ld b/cykusz-rs/src/arch/x86_64/asm/linker.ld index 909a70eb..42ce32d6 100644 --- a/cykusz-rs/src/arch/x86_64/asm/linker.ld +++ b/cykusz-rs/src/arch/x86_64/asm/linker.ld @@ -13,7 +13,6 @@ SECTIONS { KEEP(*(.multiboot_header)) build/arch/x86_64/asm/boot.o(.text* .rodata* .data* .bss*) build/arch/x86_64/asm/paging.o(.text* .rodata* .data* .bss*) - build/arch/x86_64/asm/sse.o(.text* .rodata* .data* .bss*) build/arch/x86_64/asm/test.o(.text* .rodata* .data* .bss*) build/arch/x86_64/asm/long_mode_init.o(.text* .rodata* .data* .bss*) } diff --git a/cykusz-rs/src/drivers/ps2/mouse/handler.rs b/cykusz-rs/src/drivers/ps2/mouse/handler.rs index b6c2f3b7..4e0c60c9 100644 --- a/cykusz-rs/src/drivers/ps2/mouse/handler.rs +++ b/cykusz-rs/src/drivers/ps2/mouse/handler.rs @@ -150,6 +150,7 @@ impl INode for MouseState { flags: OpenFlags, ) -> crate::kernel::fs::vfs::Result { if buf.len() % core::mem::size_of::() != 0 { + dbgln!(mouse, "Failed mouse read of {} bytes", buf.len()); Err(FsError::InvalidParam) } else { Ok(self.buf.read_data_flags( diff --git a/disk-scripts/install_os.sh b/disk-scripts/install_os.sh index f815c767..0a71fab6 100755 --- a/disk-scripts/install_os.sh +++ b/disk-scripts/install_os.sh @@ -32,7 +32,7 @@ fi sudo umount mnt PROGS="test testcpp hello stack nyancat ttytest fork poweroff stat fbdoom doom1.wad open_sleep" -RUST_PROGS="init shell mount umount unixsocket-server unixsocket-client forktest mprotecttest playwav playmidi threads sound-daemon" +RUST_PROGS="init shell mount umount unixsocket-server unixsocket-client forktest mprotecttest playwav playmidi threads sound-daemon doom" sudo mount /dev/loop0p2 mnt sudo chown -R $USER:$USER mnt diff --git a/syscall-defs/src/events/buttons.rs b/syscall-defs/src/events/buttons.rs index fc8bbe16..ffcf2be8 100644 --- a/syscall-defs/src/events/buttons.rs +++ b/syscall-defs/src/events/buttons.rs @@ -1,5 +1,6 @@ #[allow(non_camel_case_types, dead_code)] #[derive(Copy, Clone, Eq, PartialEq, Debug)] +#[repr(u16)] pub enum ButtonCode { BTN_MOUSE = 0x100, BTN_LEFT = 0x110, @@ -11,6 +12,7 @@ pub enum ButtonCode { #[allow(non_camel_case_types, dead_code)] #[derive(Copy, Clone, Eq, PartialEq, Debug)] +#[repr(u16)] pub enum RelCode { REL_X = 0x00, REL_Y = 0x01, diff --git a/syscall-defs/src/events/keys.rs b/syscall-defs/src/events/keys.rs index b69029cc..f0d9cac3 100644 --- a/syscall-defs/src/events/keys.rs +++ b/syscall-defs/src/events/keys.rs @@ -3,6 +3,7 @@ pub const NR_KEYS: usize = 256; #[derive(Copy, Clone, Eq, PartialEq, Debug)] #[allow(non_camel_case_types, dead_code)] +#[repr(u16)] pub enum KeyCode { KEY_RESERVED = 0, KEY_ESC = 1, diff --git a/syscall-defs/src/ioctl/fb.rs b/syscall-defs/src/ioctl/fb.rs index d0fa89e5..91a0cf96 100644 --- a/syscall-defs/src/ioctl/fb.rs +++ b/syscall-defs/src/ioctl/fb.rs @@ -1,5 +1,6 @@ pub const GFBINFO: usize = 0x3415; +#[derive(Default)] pub struct FbInfo { pub width: u64, pub height: u64, diff --git a/userspace/.cargo/config.toml b/userspace/.cargo/config.toml index dcc1bb78..13ec6590 100644 --- a/userspace/.cargo/config.toml +++ b/userspace/.cargo/config.toml @@ -3,6 +3,10 @@ rustc = "../sysroot/cross/usr/local/bin/rustc" target = "x86_64-unknown-cykusz" rustflags = ["-C", "link-args=-no-pie", "-C", "link-args=-lgcc_s", "-Z", "threads=8"] +[env] +CC = { value = "../sysroot/cross/usr/bin/x86_64-cykusz-gcc", relative = true } +AR = { value = "../sysroot/cross/usr/bin/x86_64-cykusz-ar", relative = true } + [target.x86_64-unknown-cykusz] linker = "../sysroot/cross/usr/bin/x86_64-cykusz-gcc" diff --git a/userspace/Cargo.lock b/userspace/Cargo.lock index 240b3196..00432ea0 100644 --- a/userspace/Cargo.lock +++ b/userspace/Cargo.lock @@ -20,6 +20,15 @@ version = "1.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94bbb0ad554ad961ddc5da507a12a29b14e4ae5bda06b19f575a3e6079d2e2ae" +[[package]] +name = "cc" +version = "1.1.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b16803a61b81d9eabb7eae2588776c4c1e584b738ede45fdbb4c972cec1e9945" +dependencies = [ + "shlex", +] + [[package]] name = "chrono" version = "0.4.38" @@ -29,6 +38,16 @@ dependencies = [ "num-traits", ] +[[package]] +name = "doom" +version = "0.1.0" +dependencies = [ + "cc", + "libc", + "syscall-defs", + "syscall-user", +] + [[package]] name = "init" version = "0.1.0" @@ -77,9 +96,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.86" +version = "1.0.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" +checksum = "b3e4daa0dcf6feba26f985457cdf104d4b4256fc5a09547140f3631bb076b19a" dependencies = [ "unicode-ident", ] @@ -108,6 +127,12 @@ dependencies = [ "syscall-user", ] +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + [[package]] name = "sound-daemon" version = "0.1.0" diff --git a/userspace/Cargo.toml b/userspace/Cargo.toml index 64579ce7..1674cae2 100644 --- a/userspace/Cargo.toml +++ b/userspace/Cargo.toml @@ -1,3 +1,3 @@ [workspace] resolver = "2" -members = ["init", "shell", "mount", "umount", "syscall-user", "unixsockets", "testprogs", "playaudio", "sound-daemon"] \ No newline at end of file +members = ["doom", "init", "shell", "mount", "umount", "syscall-user", "unixsockets", "testprogs", "playaudio", "sound-daemon"] \ No newline at end of file diff --git a/userspace/doom/Cargo.toml b/userspace/doom/Cargo.toml new file mode 100644 index 00000000..50e10d56 --- /dev/null +++ b/userspace/doom/Cargo.toml @@ -0,0 +1,16 @@ +[package] +name = "doom" +version = "0.1.0" +edition = "2021" + +[dependencies] +libc = "*" + +[dependencies.syscall-defs] +path = "../../syscall-defs" + +[dependencies.syscall-user] +path = "../syscall-user" + +[build-dependencies] +cc = "1.0" diff --git a/userspace/doom/build.rs b/userspace/doom/build.rs new file mode 100644 index 00000000..1696f000 --- /dev/null +++ b/userspace/doom/build.rs @@ -0,0 +1,37 @@ +fn main() -> Result<(), Box> { + 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)? { + let entry = entry?; + if let Some(filename) = entry.file_name().to_str() { + if filename.starts_with("doomgeneric_") + || filename == "i_main.c" + || filename.contains("sdl") + || filename.contains("allegro") + { + 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") // Disable warnings + .files(dg_c_paths) + .compile("doomgeneric"); + + println!("cargo:rustc-link-lib=static=doomgeneric"); + Ok(()) +} diff --git a/userspace/doom/doomgeneric b/userspace/doom/doomgeneric new file mode 160000 index 00000000..6ba55ea9 --- /dev/null +++ b/userspace/doom/doomgeneric @@ -0,0 +1 @@ +Subproject commit 6ba55ea945e57c14ed9edae7a74defda3aa70067 diff --git a/userspace/doom/src/cykusz.rs b/userspace/doom/src/cykusz.rs new file mode 100644 index 00000000..e344ccfc --- /dev/null +++ b/userspace/doom/src/cykusz.rs @@ -0,0 +1,44 @@ +mod fb; +mod input; + +use crate::DoomScreen; +use std::process::ExitCode; + +pub struct CykuszDoom { + fb: fb::Fb, + input: input::Input, +} + +impl CykuszDoom { + pub fn new(doom_screen: DoomScreen) -> Result { + Ok(CykuszDoom { + fb: fb::Fb::new(doom_screen)?, + input: input::Input::new(), + }) + } + + pub fn get_ticks_ms(&self) -> u32 { + ((unsafe { syscall_user::syscall0(syscall_defs::SYS_TICKSNS).unwrap() }) / 1_000_000) as u32 + } + + pub fn sleep_ms(&self, ms: u32) { + syscall_user::sleep(ms as usize).unwrap(); + } + + pub fn draw_frame(&mut self) { + self.input.poll(); + self.fb.flip(); + } + + pub fn get_key(&mut self) -> Option<(bool, u8)> { + self.input.get_key() + } + + pub fn get_mouse(&mut self) -> Option<((bool, bool, bool), i32, i32)> { + self.input.get_mouse() + } + + pub fn quit(&self) { + self.input.quit(); + } +} diff --git a/userspace/doom/src/cykusz/fb.rs b/userspace/doom/src/cykusz/fb.rs new file mode 100644 index 00000000..3b6a30b2 --- /dev/null +++ b/userspace/doom/src/cykusz/fb.rs @@ -0,0 +1,68 @@ +use crate::DoomScreen; +use std::fs::File; +use std::os::fd::AsRawFd; +use std::process::ExitCode; +use syscall_defs::{MMapFlags, MMapProt}; + +#[derive(Debug)] +pub struct Fb { + mem: Option<&'static mut [u32]>, + #[allow(unused)] + width: usize, + #[allow(unused)] + height: usize, + pitch: usize, + + doom_screen: DoomScreen, +} + +impl Fb { + pub fn new(doom_screen: DoomScreen) -> Result { + let fb = File::open("/dev/fb").map_err(|_| ExitCode::FAILURE)?; + + let mut fb_info = syscall_defs::ioctl::fb::FbInfo::default(); + + syscall_user::ioctl( + fb.as_raw_fd() as usize, + syscall_defs::ioctl::fb::GFBINFO, + (&raw mut fb_info) as usize, + ) + .map_err(|_| ExitCode::FAILURE)?; + + let map = syscall_user::mmap( + None, + fb_info.pitch as usize * fb_info.height as usize, + MMapProt::PROT_READ | MMapProt::PROT_WRITE, + MMapFlags::MAP_SHARED, + Some(fb.as_raw_fd() as usize), + 0, + ) + .map_err(|_| ExitCode::FAILURE)?; + + let fb = Ok(Fb { + mem: Some(unsafe { + std::slice::from_raw_parts_mut( + map as *mut u32, + fb_info.pitch as usize / 4 * fb_info.height as usize, + ) + }), + width: fb_info.width as usize, + height: fb_info.height as usize, + pitch: fb_info.pitch as usize / 4, + doom_screen, + }); + + fb + } + + pub fn flip(&mut self) { + if let Some(mem) = self.mem.as_mut() { + for i in 0..self.doom_screen.height { + mem[i * self.pitch..i * self.pitch + self.doom_screen.width].copy_from_slice( + &self.doom_screen.map[i * self.doom_screen.width + ..i * self.doom_screen.width + self.doom_screen.width], + ) + } + } + } +} diff --git a/userspace/doom/src/cykusz/input.rs b/userspace/doom/src/cykusz/input.rs new file mode 100644 index 00000000..c7fe55eb --- /dev/null +++ b/userspace/doom/src/cykusz/input.rs @@ -0,0 +1,232 @@ +use std::fs::File; +use std::mem::MaybeUninit; +use std::os::fd::AsRawFd; +use syscall_defs::events::buttons::{ButtonCode, RelCode}; +use syscall_defs::events::keys::KeyCode; +use syscall_defs::events::{Event, EventType}; +use syscall_defs::poll::{PollEventFlags, PollFd}; + +pub struct Input { + orig_termios: libc::termios, + kbd: File, + mouse: File, + + key_queue: [(bool, u8); 16], + write_pos: usize, + read_pos: usize, + + mouse_has_data: bool, + mouse_buttons: (bool, bool, bool), + mouse_relx: i32, + mouse_rely: i32, +} + +impl Input { + pub fn new() -> Input { + let mut termios = MaybeUninit::::uninit(); + + unsafe { + libc::tcgetattr(0, termios.as_mut_ptr()); + } + + let termios = unsafe { termios.assume_init() }; + + let kbd = File::open("/dev/kbd").unwrap(); + let mouse = File::open("/dev/mouse").unwrap(); + + let input = Input { + orig_termios: termios, + + kbd, + mouse, + + key_queue: [(false, 0); 16], + write_pos: 0, + read_pos: 0, + + mouse_has_data: false, + mouse_buttons: (false, false, false), + mouse_relx: 0, + mouse_rely: 0, + }; + + input.enable_raw_mode(); + + input + } + + fn read_event(file: &mut File) -> Event { + let mut event = MaybeUninit::::uninit(); + + syscall_user::read(file.as_raw_fd() as usize, unsafe { + std::mem::transmute::<&mut MaybeUninit, &mut [u8; core::mem::size_of::()]>(&mut event) + }).unwrap(); + + unsafe { event.assume_init() } + } + + pub fn poll(&mut self) { + let mut to_poll = [ + PollFd::new(self.kbd.as_raw_fd(), PollEventFlags::READ), + PollFd::new(self.mouse.as_raw_fd(), PollEventFlags::READ), + ]; + + loop { + let res = syscall_user::poll(&mut to_poll, 0).unwrap(); + + if res == 0 { + break; + } + + if to_poll[0].revents.contains(PollEventFlags::READ) { + self.handle_keyboard(); + } + + if to_poll[1].revents.contains(PollEventFlags::READ) { + self.handle_mouse(); + } + } + } + + fn handle_mouse(&mut self) { + let event = Self::read_event(&mut self.mouse); + + self.mouse_has_data = true; + + match event.typ { + EventType::Key => { + let button: ButtonCode = unsafe { std::mem::transmute(event.code) }; + match button { + ButtonCode::BTN_LEFT => { + self.mouse_buttons.0 = event.val == 1; + } + ButtonCode::BTN_RIGHT => { + self.mouse_buttons.1 = event.val == 1; + } + ButtonCode::BTN_MIDDLE => { + self.mouse_buttons.2 = event.val == 1; + } + _ => {} + } + } + EventType::Rel => { + let rel: RelCode = unsafe { std::mem::transmute(event.code) }; + + match rel { + RelCode::REL_X => { + self.mouse_relx += event.val; + } + RelCode::REL_Y => { + self.mouse_rely += event.val; + } + } + } + } + } + + fn handle_keyboard(&mut self) { + let event = Self::read_event(&mut self.kbd); + + if event.val == 2 { + // ignore repeat keys + return; + } + + self.add_to_queue(event.val == 0, unsafe { std::mem::transmute(event.code) }); + } + + fn add_to_queue(&mut self, pressed: bool, key: KeyCode) { + let key = Input::conv_to_doomkey(key); + + self.key_queue[self.write_pos] = (pressed, key); + self.write_pos = (self.write_pos + 1) % self.key_queue.len(); + } + + pub fn get_key(&mut self) -> Option<(bool, u8)> { + if self.write_pos == self.read_pos { + return None; + } + + let ret = self.key_queue[self.read_pos]; + self.read_pos = (self.read_pos + 1) % self.key_queue.len(); + + Some(ret) + } + + pub fn get_mouse(&mut self) -> Option<((bool, bool, bool), i32, i32)> { + if !self.mouse_has_data { + return None; + } + + self.mouse_has_data = false; + + let ret = Some((self.mouse_buttons, self.mouse_relx, self.mouse_rely)); + + self.mouse_relx = 0; + self.mouse_rely = 0; + + ret + } + + pub fn quit(&self) { + self.disable_raw_mode(); + } + + fn enable_raw_mode(&self) { + let mut new = self.orig_termios; + + unsafe { + libc::cfmakeraw(&raw mut new); + libc::tcsetattr(0, libc::TCSAFLUSH, &raw const new); + } + } + + fn disable_raw_mode(&self) { + unsafe { + libc::tcsetattr(0, libc::TCSAFLUSH, &raw const self.orig_termios); + } + } + + fn conv_to_doomkey(key: KeyCode) -> u8 { + match key { + KeyCode::KEY_ENTER => crate::keys::KEY_ENTER, + KeyCode::KEY_ESC => crate::keys::KEY_ESCAPE, + KeyCode::KEY_LEFT => crate::keys::KEY_LEFTARROW, + KeyCode::KEY_RIGHT => crate::keys::KEY_RIGHTARROW, + KeyCode::KEY_W => crate::keys::KEY_UPARROW, + KeyCode::KEY_S => crate::keys::KEY_DOWNARROW, + KeyCode::KEY_LEFTCTRL => crate::keys::KEY_FIRE, + KeyCode::KEY_SPACE => crate::keys::KEY_USE, + KeyCode::KEY_A => crate::keys::KEY_STRAFE_L, + KeyCode::KEY_D => crate::keys::KEY_STRAFE_R, + KeyCode::KEY_LEFTSHIFT => crate::keys::KEY_RSHIFT, + + KeyCode::KEY_Q => 'q' as u8, + KeyCode::KEY_E => 'e' as u8, + KeyCode::KEY_R => 'r' as u8, + KeyCode::KEY_T => 't' as u8, + KeyCode::KEY_Y => 'y' as u8, + KeyCode::KEY_U => 'u' as u8, + KeyCode::KEY_I => 'i' as u8, + KeyCode::KEY_O => 'o' as u8, + KeyCode::KEY_P => 'p' as u8, + + KeyCode::KEY_F => 'f' as u8, + KeyCode::KEY_G => 'g' as u8, + KeyCode::KEY_H => 'h' as u8, + KeyCode::KEY_J => 'j' as u8, + KeyCode::KEY_K => 'k' as u8, + KeyCode::KEY_L => 'l' as u8, + + KeyCode::KEY_Z => 'z' as u8, + KeyCode::KEY_X => 'x' as u8, + KeyCode::KEY_C => 'c' as u8, + KeyCode::KEY_V => 'v' as u8, + KeyCode::KEY_B => 'b' as u8, + KeyCode::KEY_N => 'n' as u8, + KeyCode::KEY_M => 'm' as u8, + + _ => 0, + } + } +} diff --git a/userspace/doom/src/keys.rs b/userspace/doom/src/keys.rs new file mode 100644 index 00000000..52b6fef6 --- /dev/null +++ b/userspace/doom/src/keys.rs @@ -0,0 +1,66 @@ +#![allow(unused)] +pub const KEY_RIGHTARROW: u8 = 0xae; +pub const KEY_LEFTARROW: u8 = 0xac; +pub const KEY_UPARROW: u8 = 0xad; +pub const KEY_DOWNARROW: u8 = 0xaf; +pub const KEY_STRAFE_L: u8 = 0xa0; +pub const KEY_STRAFE_R: u8 = 0xa1; +pub const KEY_USE: u8 = 0xa2; +pub const KEY_FIRE: u8 = 0xa3; +pub const KEY_ESCAPE: u8 = 27; +pub const KEY_ENTER: u8 = 13; +pub const KEY_TAB: u8 = 9; +pub const KEY_F1: u8 = 0x80 + 0x3b; +pub const KEY_F2: u8 = 0x80 + 0x3c; +pub const KEY_F3: u8 = 0x80 + 0x3d; +pub const KEY_F4: u8 = 0x80 + 0x3e; +pub const KEY_F5: u8 = 0x80 + 0x3f; +pub const KEY_F6: u8 = 0x80 + 0x40; +pub const KEY_F7: u8 = 0x80 + 0x41; +pub const KEY_F8: u8 = 0x80 + 0x42; +pub const KEY_F9: u8 = 0x80 + 0x43; +pub const KEY_F10: u8 = 0x80 + 0x44; +pub const KEY_F11: u8 = 0x80 + 0x57; +pub const KEY_F12: u8 = 0x80 + 0x58; + +pub const KEY_BACKSPACE: u8 = 0x7f; +pub const KEY_PAUSE: u8 = 0xff; + +pub const KEY_EQUALS: u8 = 0x3d; +pub const KEY_MINUS: u8 = 0x2d; + +pub const KEY_RSHIFT: u8 = 0x80 + 0x36; +pub const KEY_RCTRL: u8 = 0x80 + 0x1d; +pub const KEY_RALT: u8 = 0x80 + 0x38; + +pub const KEY_LALT: u8 = KEY_RALT; + +pub const KEY_CAPSLOCK: u8 = 0x80 + 0x3a; +pub const KEY_NUMLOCK: u8 = 0x80 + 0x45; +pub const KEY_SCRLCK: u8 = 0x80 + 0x46; +pub const KEY_PRTSCR: u8 = 0x80 + 0x59; +pub const KEY_HOME: u8 = 0x80 + 0x47; +pub const KEY_END: u8 = 0x80 + 0x4f; +pub const KEY_PGUP: u8 = 0x80 + 0x49; +pub const KEY_PGDN: u8 = 0x80 + 0x51; +pub const KEY_INS: u8 = 0x80 + 0x52; +pub const KEY_DEL: u8 = 0x80 + 0x53; + +pub const KEYP_0: u8 = 0; +pub const KEYP_1: u8 = KEY_END; +pub const KEYP_2: u8 = KEY_DOWNARROW; +pub const KEYP_3: u8 = KEY_PGDN; +pub const KEYP_4: u8 = KEY_LEFTARROW; +pub const KEYP_5: u8 = '5' as u8; +pub const KEYP_6: u8 = KEY_RIGHTARROW; +pub const KEYP_7: u8 = KEY_HOME; +pub const KEYP_8: u8 = KEY_UPARROW; +pub const KEYP_9: u8 = KEY_PGUP; + +pub const KEYP_DIVIDE: u8 = '/' as u8; +pub const KEYP_PLUS: u8 = '+' as u8; +pub const KEYP_MINUS: u8 = '-' as u8; +pub const KEYP_MULTIPLY: u8 = '*' as u8; +pub const KEYP_PERIOD: u8 = 0; +pub const KEYP_EQUALS: u8 = KEY_EQUALS; +pub const KEYP_ENTER: u8 = KEY_ENTER; diff --git a/userspace/doom/src/main.rs b/userspace/doom/src/main.rs new file mode 100644 index 00000000..3bc30c3f --- /dev/null +++ b/userspace/doom/src/main.rs @@ -0,0 +1,130 @@ +#![allow(non_snake_case)] +#![feature(raw_ref_op)] + +mod cykusz; +mod keys; + +use std::ffi::{c_char, c_int, c_uchar, c_uint, CString}; + +static mut DOOM: Option = None; + +#[derive(Debug)] +pub struct DoomScreen { + map: &'static [u32], + width: usize, + height: usize, +} + +fn doom<'a>() -> &'a mut cykusz::CykuszDoom { + unsafe { DOOM.as_mut().unwrap_unchecked() } +} + +extern "C" { + fn doomgeneric_Create(c: c_int, argv: *const *const c_char); + fn doomgeneric_Tick(); + + static DG_ScreenBuffer: *mut u32; +} + +fn doomgeneric_screen() -> DoomScreen { + pub const DOOMGENERIC_RESX: usize = 640; + pub const DOOMGENERIC_RESY: usize = 400; + + DoomScreen { + map: unsafe { + std::slice::from_raw_parts(DG_ScreenBuffer, DOOMGENERIC_RESX * DOOMGENERIC_RESY * 4) + }, + width: DOOMGENERIC_RESX, + height: DOOMGENERIC_RESY, + } +} + +#[no_mangle] +extern "C" fn DG_Init() { + unsafe { + (&raw mut DOOM).write(Some(cykusz::CykuszDoom::new(doomgeneric_screen()).unwrap())); + } +} + +#[no_mangle] +extern "C" fn DG_DrawFrame() { + doom().draw_frame() +} + +#[no_mangle] +extern "C" fn DG_SleepMs(ms: c_uint) { + doom().sleep_ms(ms as u32); +} + +#[no_mangle] +extern "C" fn DG_GetTicksMs() -> c_uint { + doom().get_ticks_ms() +} + +#[no_mangle] +extern "C" fn DG_GetKey(pressed: *mut c_int, doomkey: *mut c_uchar) -> c_int { + if let Some((p, key)) = doom().get_key() { + unsafe { + pressed.write(if p { 1 } else { 0 }); + doomkey.write(key); + } + + 1 + } else { + 0 + } +} + +#[no_mangle] +extern "C" fn DG_GetMouse(buttons: *mut c_int, rel_x: *mut c_int, rel_y: *mut c_int) -> c_int { + if let Some(((left, right, mid), relx, rely)) = doom().get_mouse() { + let mut btns: c_int = 0; + if left { + btns |= 1 << 0; + } + if right { + btns |= 1 << 1; + } + if mid { + btns |= 1 << 2; + } + + unsafe { + buttons.write(btns); + rel_x.write(relx); + rel_y.write(rely); + } + + 1 + } else { + 0 + } +} + +#[no_mangle] +extern "C" fn DG_SetWindowTitle(_title: *const c_char) {} + +extern "C" fn DG_Quit() { + doom().quit(); +} + +fn main() { + unsafe { + let args = std::env::args() + .map(|arg| CString::new(arg).unwrap()) + .collect::>(); + // convert the strings to raw pointers + let c_args = args + .iter() + .map(|arg| arg.as_ptr()) + .collect::>(); + + doomgeneric_Create(c_args.len() as c_int, c_args.as_ptr()); + + libc::atexit(DG_Quit); + + loop { + doomgeneric_Tick(); + } + } +} diff --git a/userspace/sound-daemon/src/sound-daemon/bin/main.rs b/userspace/sound-daemon/src/sound-daemon/bin/main.rs index 82e46935..910e1aa5 100644 --- a/userspace/sound-daemon/src/sound-daemon/bin/main.rs +++ b/userspace/sound-daemon/src/sound-daemon/bin/main.rs @@ -18,7 +18,7 @@ struct MixChunk([i32; CHUNK_SIZE / 2]); const CHUNK_COUNT: u64 = 32; const WRITE_HEADROOM: u64 = 3; -const MAX_CHUNKS_IN_BUF: usize = 16; +const MAX_CHUNKS_IN_BUF: usize = 1; #[derive(Copy, Clone, Eq, PartialEq)] enum FetchResult {