1
0

Controls and collisions

This commit is contained in:
Mark 2025-03-01 20:09:44 -08:00
parent 23bb3e1153
commit 57a634d4ee
Signed by: Mark
GPG Key ID: C6D63995FE72FD80
4 changed files with 95 additions and 6 deletions

View File

@ -1,7 +1,10 @@
- improve collisions
- controls (input)
- clear lines
- deadlocks
- deadlocks?
- fix arrow keys
- better rng
- keypress on start
- enum and consts for interrupt index
- fix asm loader
- minimal interrupts
- quick drop
- document everything

View File

@ -38,6 +38,7 @@ lazy_static! {
idt.divide_error.set_handler_fn(divide_handler);
idt.double_fault.set_handler_fn(double_fault_handler);
idt.interrupts[InterruptIndex::Timer.as_idx()].set_handler_fn(timer_handler);
idt.interrupts[InterruptIndex::Keyboard.as_idx()].set_handler_fn(keyboard_handler);
idt
};
@ -64,6 +65,85 @@ 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,
Right,
Up,
Down,
}
extern "x86-interrupt" fn keyboard_handler(stack_frame: InterruptStackFrame) {
println!("KEYBOARD {:?}", stack_frame);
let scancode = unsafe { inb(0x60) };
println!("{:x?}", scancode);
let key = match scancode {
0x11 => Some(InputKey::Up),
0x1E => Some(InputKey::Left),
0x1F => Some(InputKey::Down),
0x20 => Some(InputKey::Right),
0xE0 => {
let scancode = unsafe { inb(0x60) };
println!("e {:x?}", scancode);
None
}
_ => None,
};
if let Some(fall) = &mut *FALLING.lock() {
let board = BOARD.lock();
let mut fall_test = fall.clone();
match key {
Some(InputKey::Up) => {
fall_test.rotate_cw();
if board.tetromino_valid(&fall_test) {
fall.rotate_cw()
};
}
Some(InputKey::Down) => {
fall_test.rotate_ccw();
if board.tetromino_valid(&fall_test) {
fall.rotate_ccw()
};
}
Some(InputKey::Left) => {
fall_test.translate(-1, 0);
if board.tetromino_valid(&fall_test) {
fall.translate(-1, 0);
};
}
Some(InputKey::Right) => {
fall_test.translate(1, 0);
if board.tetromino_valid(&fall_test) {
fall.translate(1, 0);
};
}
_ => {}
}
}
PIC.lock().send_eoi(InterruptIndex::Keyboard.as_u8());
}
extern "x86-interrupt" fn timer_handler(_stack_frame: InterruptStackFrame) {
if !*RUN_TICKS.lock() {
PIC.lock().send_eoi(InterruptIndex::Timer.as_u8());
@ -86,7 +166,10 @@ extern "x86-interrupt" fn timer_handler(_stack_frame: InterruptStackFrame) {
if let Some(fall_inner) = fall.as_mut() {
if t % 6 == 0 {
if board.tetromino_free_below(fall_inner) {
let mut fall_test = fall_inner.clone();
fall_test.translate(0, 1);
if board.tetromino_valid(&fall_test) {
fall_inner.translate(0, 1);
} else {
let mut x = None;

View File

@ -72,6 +72,7 @@ impl Direction {
}
}
#[derive(Debug, Clone)]
pub struct FallingTetromino {
tetromino: Tetromino,
direction: Direction,

View File

@ -39,9 +39,11 @@ impl TetrisBoard {
}
}
pub fn tetromino_free_below(&self, tetromino: &FallingTetromino) -> bool {
/// Returns `false` if the given tetromino intersects a filled cell
/// or exits the board boundary
pub fn tetromino_valid(&self, tetromino: &FallingTetromino) -> bool {
for (x, y) in tetromino.tiles() {
let cell = self.get_cell(x, y + 1);
let cell = self.get_cell(x, y);
if cell != Some(&TetrisCell::Empty) {
return false;
}