From 8f2edd69f792b09debc3d46435b0234975221ae5 Mon Sep 17 00:00:00 2001 From: Mark Date: Sun, 2 Mar 2025 10:44:55 -0800 Subject: [PATCH] Reorganize --- README.md | 1 + tetros/src/drivers/pic.rs | 10 +-- .../src/{tetrisboard/mod.rs => game/board.rs} | 74 +++++++++++++++++-- tetros/src/{tetrisboard => game}/falling.rs | 0 tetros/src/game/mod.rs | 5 ++ tetros/src/idt/entry.rs | 4 +- tetros/src/idt/mod.rs | 2 - tetros/src/idt/util.rs | 10 --- tetros/src/lib.rs | 43 ++++++----- tetros/src/os/mod.rs | 3 +- tetros/src/os/panic.rs | 2 - tetros/src/os/util.rs | 29 ++++++++ tetros/src/tetrisboard/draw.rs | 70 ------------------ 13 files changed, 130 insertions(+), 123 deletions(-) rename tetros/src/{tetrisboard/mod.rs => game/board.rs} (53%) rename tetros/src/{tetrisboard => game}/falling.rs (100%) create mode 100644 tetros/src/game/mod.rs delete mode 100644 tetros/src/idt/util.rs delete mode 100644 tetros/src/tetrisboard/draw.rs diff --git a/README.md b/README.md index 4df526e..c4d2316 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,5 @@ - quick drop +- faster timer - fix asm loader - document everything - prettier pictures \ No newline at end of file diff --git a/tetros/src/drivers/pic.rs b/tetros/src/drivers/pic.rs index 84c0aa2..afd74ac 100644 --- a/tetros/src/drivers/pic.rs +++ b/tetros/src/drivers/pic.rs @@ -1,4 +1,4 @@ -use core::arch::asm; +use crate::os::util::outb; /// IO base address for master PIC const PIC_A: u32 = 0x20; @@ -13,14 +13,6 @@ const PIC_B_DATA: u32 = PIC_B + 1; /// PIC `EOI` command const CMD_EOI: u8 = 0x20; -unsafe fn outb(port: u32, value: u8) { - asm!( - "out dx, al", - in("dx") port, - in("al") value, - ); -} - /// A driver for the PIC /// /// Reference: diff --git a/tetros/src/tetrisboard/mod.rs b/tetros/src/game/board.rs similarity index 53% rename from tetros/src/tetrisboard/mod.rs rename to tetros/src/game/board.rs index 7a9ae0d..885a138 100644 --- a/tetros/src/tetrisboard/mod.rs +++ b/tetros/src/game/board.rs @@ -1,9 +1,6 @@ -mod draw; -mod falling; +use crate::drivers::vga::{Vga13h, VgaColor}; -pub use falling::FallingTetromino; - -use crate::drivers::vga::VgaColor; +use super::FallingTetromino; #[repr(u8)] #[derive(Debug, Clone, Copy, PartialEq, Eq)] @@ -109,3 +106,70 @@ impl TetrisBoard { return Some(&mut self.board[y * TetrisBoard::BOARD_WIDTH + x]); } } + +impl TetrisBoard { + fn draw_cell(&self, fb: &mut [u8], color: VgaColor, x: usize, y: usize) { + let color = color.as_u8(); + for yo in 0..TetrisBoard::CELL_SIZE { + let left = Vga13h::pix_idx(x, y + yo); + let right = Vga13h::pix_idx(x + TetrisBoard::CELL_SIZE, y + yo); + fb[left..right].copy_from_slice(&[color; TetrisBoard::CELL_SIZE]); + } + } + + fn draw_frame(&self, fb: &mut [u8], x: usize, y: usize) { + let color = VgaColor::Gray.as_u8(); + for yo in 0..TetrisBoard::CELL_SIZE { + let left = Vga13h::pix_idx(x, y + yo); + let right = Vga13h::pix_idx(x + TetrisBoard::CELL_SIZE, y + yo); + fb[left..right].copy_from_slice(&[color; TetrisBoard::CELL_SIZE]); + } + } + + pub fn draw(&self, vga: &mut Vga13h, falling: Option<&FallingTetromino>) { + let fb = vga.get_fb(); + + // Draw cells + for bx in 0..TetrisBoard::BOARD_WIDTH { + for by in 0..TetrisBoard::BOARD_HEIGHT { + let cell = self.board[by * TetrisBoard::BOARD_WIDTH + bx]; + let dx = (bx + 1) * TetrisBoard::CELL_SIZE; + let dy = (by + 1) * TetrisBoard::CELL_SIZE; + + if let TetrisCell::Filled { color } = cell { + self.draw_cell(fb, color, dx, dy); + } else { + self.draw_cell(fb, VgaColor::Black, dx, dy); + } + } + } + + // Draw falling tetromino + if let Some(falling) = falling { + for (x, y) in falling.tiles() { + let dx = (x + 1) * TetrisBoard::CELL_SIZE; + let dy = (y + 1) * TetrisBoard::CELL_SIZE; + + self.draw_cell(fb, falling.color, dx, dy); + } + } + + // Draw frame + for bx in 0..TetrisBoard::BOARD_WIDTH + 2 { + self.draw_frame(fb, bx * TetrisBoard::CELL_SIZE, 0); + self.draw_frame( + fb, + bx * TetrisBoard::CELL_SIZE, + (TetrisBoard::BOARD_HEIGHT + 1) * TetrisBoard::CELL_SIZE, + ); + } + for by in 0..TetrisBoard::BOARD_HEIGHT + 2 { + self.draw_frame(fb, 0, by * 9); + self.draw_frame( + fb, + (TetrisBoard::BOARD_WIDTH + 1) * TetrisBoard::CELL_SIZE, + by * TetrisBoard::CELL_SIZE, + ); + } + } +} diff --git a/tetros/src/tetrisboard/falling.rs b/tetros/src/game/falling.rs similarity index 100% rename from tetros/src/tetrisboard/falling.rs rename to tetros/src/game/falling.rs diff --git a/tetros/src/game/mod.rs b/tetros/src/game/mod.rs new file mode 100644 index 0000000..e92dd16 --- /dev/null +++ b/tetros/src/game/mod.rs @@ -0,0 +1,5 @@ +mod board; +pub use board::*; + +mod falling; +pub use falling::*; diff --git a/tetros/src/idt/entry.rs b/tetros/src/idt/entry.rs index 9b3ff91..3063079 100644 --- a/tetros/src/idt/entry.rs +++ b/tetros/src/idt/entry.rs @@ -3,6 +3,8 @@ use core::{ marker::PhantomData, }; +use crate::os::util::get_cs; + use super::{HandlerFuncType, VirtAddr}; /// An Interrupt Descriptor Table entry. @@ -97,7 +99,7 @@ impl Entry { self.options = 0b1000_1110; // Present 32-bit interrupt gate // SAFETY: The current CS is a valid, long-mode code segment. - self.segment = super::util::get_cs(); + self.segment = get_cs(); } /// True if the "present" bit is set, false otherwise. diff --git a/tetros/src/idt/mod.rs b/tetros/src/idt/mod.rs index 809be38..64e681d 100644 --- a/tetros/src/idt/mod.rs +++ b/tetros/src/idt/mod.rs @@ -18,5 +18,3 @@ pub use handler::*; mod stackframe; pub use stackframe::*; - -mod util; diff --git a/tetros/src/idt/util.rs b/tetros/src/idt/util.rs deleted file mode 100644 index 13f5a94..0000000 --- a/tetros/src/idt/util.rs +++ /dev/null @@ -1,10 +0,0 @@ -use core::arch::asm; - -/// Get the current value of the CS register -pub(super) fn get_cs() -> u16 { - let segment: u16; - unsafe { - asm!("mov {0:x}, cs", out(reg) segment, options(nomem, nostack, preserves_flags)); - } - segment -} diff --git a/tetros/src/lib.rs b/tetros/src/lib.rs index 7eb0c7d..816e26a 100644 --- a/tetros/src/lib.rs +++ b/tetros/src/lib.rs @@ -4,34 +4,37 @@ #![feature(abi_x86_interrupt)] #![allow(internal_features)] -use core::arch::asm; use lazy_static::lazy_static; use rand::{rngs::SmallRng, Rng, SeedableRng}; use spin::Mutex; use drivers::{pic::PICDriver, vga::Vga13h}; +use game::{FallingTetromino, TetrisBoard}; use idt::{InterruptDescriptorTable, InterruptStackFrame}; use os::{ - util::{sti, without_interrupts}, + util::{inb, sti, without_interrupts}, ThunkData, }; -use tetrisboard::{FallingTetromino, TetrisBoard}; +mod game; mod idt; mod os; -mod tetrisboard; #[macro_use] mod drivers; const PIC_OFFSET: u8 = 32; -pub(crate) static VGA: Mutex = Mutex::new(unsafe { Vga13h::new() }); -pub(crate) static PIC: Mutex = Mutex::new(PICDriver::new(PIC_OFFSET, PIC_OFFSET + 8)); -pub(crate) static TICK_COUNTER: Mutex = Mutex::new(0); -pub(crate) static BOARD: Mutex = Mutex::new(TetrisBoard::new()); -pub(crate) static FALLING: Mutex> = Mutex::new(None); -pub(crate) static LAST_INPUT: Mutex> = Mutex::new(None); +// +// MARK: globals +// + +static VGA: Mutex = Mutex::new(unsafe { Vga13h::new() }); +static PIC: Mutex = Mutex::new(PICDriver::new(PIC_OFFSET, PIC_OFFSET + 8)); +static TICK_COUNTER: Mutex = Mutex::new(0); +static BOARD: Mutex = Mutex::new(TetrisBoard::new()); +static FALLING: Mutex> = Mutex::new(None); +static LAST_INPUT: Mutex> = Mutex::new(None); lazy_static! { static ref RNG: Mutex = Mutex::new(SmallRng::seed_from_u64(1337)); @@ -47,6 +50,10 @@ lazy_static! { }; } +// +// MARK: interrupts +// + #[derive(Debug, Clone, Copy)] #[repr(u8)] pub enum InterruptIndex { @@ -68,18 +75,6 @@ extern "x86-interrupt" fn divide_handler(stack_frame: InterruptStackFrame) { println!("DIVIDE ERROR {:?}", stack_frame); } -unsafe fn inb(port: u32) -> u8 { - let mut out; - - asm!( - "in al, dx", - out("al") out, - in("dx") port, - ); - - return out; -} - #[derive(Debug, Clone, Copy, PartialEq, Eq)] enum InputKey { Left, @@ -146,6 +141,10 @@ extern "x86-interrupt" fn double_fault_handler( panic!("DOUBLE FAULT (err = 0x{error_code:x}\n{:#?}", stack_frame); } +// +// MARK: main +// + #[no_mangle] pub unsafe extern "C" fn start(thunk10: extern "C" fn()) -> ! { println!("Entered Rust, serial ready."); diff --git a/tetros/src/os/mod.rs b/tetros/src/os/mod.rs index d738fd5..21a05fc 100644 --- a/tetros/src/os/mod.rs +++ b/tetros/src/os/mod.rs @@ -4,8 +4,7 @@ pub use thunk::*; mod eflags; pub use eflags::*; -pub mod util; - #[macro_use] pub mod panic; +pub mod util; diff --git a/tetros/src/os/panic.rs b/tetros/src/os/panic.rs index f9de158..1a0a2de 100644 --- a/tetros/src/os/panic.rs +++ b/tetros/src/os/panic.rs @@ -9,7 +9,6 @@ use crate::println; #[no_mangle] pub extern "C" fn rust_eh_personality() {} -/// Required to handle panics #[panic_handler] #[no_mangle] pub fn rust_begin_unwind(info: &PanicInfo<'_>) -> ! { @@ -22,7 +21,6 @@ pub fn rust_begin_unwind(info: &PanicInfo<'_>) -> ! { } #[no_mangle] -/// Required to handle panics pub extern "C" fn _Unwind_Resume() -> ! { loop { unsafe { diff --git a/tetros/src/os/util.rs b/tetros/src/os/util.rs index bf4f004..31a4cff 100644 --- a/tetros/src/os/util.rs +++ b/tetros/src/os/util.rs @@ -45,3 +45,32 @@ where ret } + +pub unsafe fn inb(port: u32) -> u8 { + let mut out; + + asm!( + "in al, dx", + out("al") out, + in("dx") port, + ); + + return out; +} + +pub unsafe fn outb(port: u32, value: u8) { + asm!( + "out dx, al", + in("dx") port, + in("al") value, + ); +} + +/// Get the current value of the CS register +pub fn get_cs() -> u16 { + let segment: u16; + unsafe { + asm!("mov {0:x}, cs", out(reg) segment, options(nomem, nostack, preserves_flags)); + } + segment +} diff --git a/tetros/src/tetrisboard/draw.rs b/tetros/src/tetrisboard/draw.rs deleted file mode 100644 index 8de472d..0000000 --- a/tetros/src/tetrisboard/draw.rs +++ /dev/null @@ -1,70 +0,0 @@ -use crate::drivers::vga::{Vga13h, VgaColor}; - -use super::{falling::FallingTetromino, TetrisBoard, TetrisCell}; - -impl TetrisBoard { - fn draw_cell(&self, fb: &mut [u8], color: VgaColor, x: usize, y: usize) { - let color = color.as_u8(); - for yo in 0..TetrisBoard::CELL_SIZE { - let left = Vga13h::pix_idx(x, y + yo); - let right = Vga13h::pix_idx(x + TetrisBoard::CELL_SIZE, y + yo); - fb[left..right].copy_from_slice(&[color; TetrisBoard::CELL_SIZE]); - } - } - - fn draw_frame(&self, fb: &mut [u8], x: usize, y: usize) { - let color = VgaColor::Gray.as_u8(); - for yo in 0..TetrisBoard::CELL_SIZE { - let left = Vga13h::pix_idx(x, y + yo); - let right = Vga13h::pix_idx(x + TetrisBoard::CELL_SIZE, y + yo); - fb[left..right].copy_from_slice(&[color; TetrisBoard::CELL_SIZE]); - } - } - - pub fn draw(&self, vga: &mut Vga13h, falling: Option<&FallingTetromino>) { - let fb = vga.get_fb(); - - // Draw cells - for bx in 0..TetrisBoard::BOARD_WIDTH { - for by in 0..TetrisBoard::BOARD_HEIGHT { - let cell = self.board[by * TetrisBoard::BOARD_WIDTH + bx]; - let dx = (bx + 1) * TetrisBoard::CELL_SIZE; - let dy = (by + 1) * TetrisBoard::CELL_SIZE; - - if let TetrisCell::Filled { color } = cell { - self.draw_cell(fb, color, dx, dy); - } else { - self.draw_cell(fb, VgaColor::Black, dx, dy); - } - } - } - - // Draw falling tetromino - if let Some(falling) = falling { - for (x, y) in falling.tiles() { - let dx = (x + 1) * TetrisBoard::CELL_SIZE; - let dy = (y + 1) * TetrisBoard::CELL_SIZE; - - self.draw_cell(fb, falling.color, dx, dy); - } - } - - // Draw frame - for bx in 0..TetrisBoard::BOARD_WIDTH + 2 { - self.draw_frame(fb, bx * TetrisBoard::CELL_SIZE, 0); - self.draw_frame( - fb, - bx * TetrisBoard::CELL_SIZE, - (TetrisBoard::BOARD_HEIGHT + 1) * TetrisBoard::CELL_SIZE, - ); - } - for by in 0..TetrisBoard::BOARD_HEIGHT + 2 { - self.draw_frame(fb, 0, by * 9); - self.draw_frame( - fb, - (TetrisBoard::BOARD_WIDTH + 1) * TetrisBoard::CELL_SIZE, - by * TetrisBoard::CELL_SIZE, - ); - } - } -}