From 622f6d17917dfb0ed31af91661b6bfcabe5756ac Mon Sep 17 00:00:00 2001 From: Mark Date: Mon, 17 Feb 2025 21:33:40 -0800 Subject: [PATCH] Basic tetris board --- bootloader/bootloader/src/os/bios/mod.rs | 3 + bootloader/bootloader/src/os/bios/tetris.rs | 116 ++++++++++++++++++++ 2 files changed, 119 insertions(+) create mode 100644 bootloader/bootloader/src/os/bios/tetris.rs diff --git a/bootloader/bootloader/src/os/bios/mod.rs b/bootloader/bootloader/src/os/bios/mod.rs index b626167..8bde669 100644 --- a/bootloader/bootloader/src/os/bios/mod.rs +++ b/bootloader/bootloader/src/os/bios/mod.rs @@ -64,6 +64,9 @@ pub unsafe extern "C" fn start( } */ + let t = TetrisBoard::new(); + t.draw(&mut v); + let (heap_start, heap_size) = memory_map(thunk15).expect("No memory for heap"); ALLOCATOR.lock().init(heap_start as *mut u8, heap_size); diff --git a/bootloader/bootloader/src/os/bios/tetris.rs b/bootloader/bootloader/src/os/bios/tetris.rs new file mode 100644 index 0000000..763b47f --- /dev/null +++ b/bootloader/bootloader/src/os/bios/tetris.rs @@ -0,0 +1,116 @@ +use super::vga::Vga13h; + +#[repr(u8)] +#[derive(Debug, Clone, Copy)] +pub enum TetrisCell { + Empty, + Blue, + Cyan, + Orange, + Red, + Green, + Purple, + Yellow, +} + +impl TetrisCell { + pub fn to_vga_color(&self) -> u8 { + match self { + Self::Empty => 0b000_00000, + Self::Blue => 0b000_00001, + Self::Cyan => 0b000_00011, + Self::Orange => 0b000_00110, + Self::Red => 0b000_00100, + Self::Green => 0b000_00010, + Self::Purple => 0b000_00101, + Self::Yellow => 0b110_000_00, + } + } + + pub fn is_empty(&self) -> bool { + matches!(self, Self::Empty) + } +} + +pub struct TetrisBoard { + board: [TetrisCell; TetrisBoard::BOARD_WIDTH * TetrisBoard::BOARD_HEIGHT], +} + +impl TetrisBoard { + const BOARD_WIDTH: usize = 10; + const BOARD_HEIGHT: usize = 20; + + const CELL_SIZE: usize = 9; + + pub fn new() -> Self { + let mut x = Self { + board: [TetrisCell::Empty; TetrisBoard::BOARD_WIDTH * TetrisBoard::BOARD_HEIGHT], + }; + + x.board[0] = TetrisCell::Blue; + x.board[1] = TetrisCell::Cyan; + x.board[2] = TetrisCell::Orange; + x.board[3] = TetrisCell::Red; + x.board[4] = TetrisCell::Green; + x.board[5] = TetrisCell::Purple; + x.board[6] = TetrisCell::Yellow; + + x.board[9] = TetrisCell::Blue; + x.board[8] = TetrisCell::Blue; + x.board[10] = TetrisCell::Blue; + x.board[12] = TetrisCell::Blue; + + x + } + + fn draw_cell(&self, fb: &mut [u8], state: TetrisCell, x: usize, y: usize) { + let color = state.to_vga_color(); + 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 = 0b111_000_00; + 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) { + 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; + + self.draw_cell(fb, cell, 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, + ); + } + } +}