Controls and collisions
This commit is contained in:
parent
23bb3e1153
commit
57a634d4ee
@ -1,7 +1,10 @@
|
|||||||
- improve collisions
|
|
||||||
- controls (input)
|
|
||||||
- clear lines
|
- clear lines
|
||||||
- deadlocks
|
- deadlocks?
|
||||||
|
- fix arrow keys
|
||||||
|
- better rng
|
||||||
|
- keypress on start
|
||||||
- enum and consts for interrupt index
|
- enum and consts for interrupt index
|
||||||
- fix asm loader
|
- fix asm loader
|
||||||
|
- minimal interrupts
|
||||||
|
- quick drop
|
||||||
- document everything
|
- document everything
|
||||||
|
@ -38,6 +38,7 @@ lazy_static! {
|
|||||||
idt.divide_error.set_handler_fn(divide_handler);
|
idt.divide_error.set_handler_fn(divide_handler);
|
||||||
idt.double_fault.set_handler_fn(double_fault_handler);
|
idt.double_fault.set_handler_fn(double_fault_handler);
|
||||||
idt.interrupts[InterruptIndex::Timer.as_idx()].set_handler_fn(timer_handler);
|
idt.interrupts[InterruptIndex::Timer.as_idx()].set_handler_fn(timer_handler);
|
||||||
|
idt.interrupts[InterruptIndex::Keyboard.as_idx()].set_handler_fn(keyboard_handler);
|
||||||
|
|
||||||
idt
|
idt
|
||||||
};
|
};
|
||||||
@ -64,6 +65,85 @@ extern "x86-interrupt" fn divide_handler(stack_frame: InterruptStackFrame) {
|
|||||||
println!("DIVIDE ERROR {:?}", stack_frame);
|
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) {
|
extern "x86-interrupt" fn timer_handler(_stack_frame: InterruptStackFrame) {
|
||||||
if !*RUN_TICKS.lock() {
|
if !*RUN_TICKS.lock() {
|
||||||
PIC.lock().send_eoi(InterruptIndex::Timer.as_u8());
|
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 let Some(fall_inner) = fall.as_mut() {
|
||||||
if t % 6 == 0 {
|
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);
|
fall_inner.translate(0, 1);
|
||||||
} else {
|
} else {
|
||||||
let mut x = None;
|
let mut x = None;
|
||||||
|
@ -72,6 +72,7 @@ impl Direction {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
pub struct FallingTetromino {
|
pub struct FallingTetromino {
|
||||||
tetromino: Tetromino,
|
tetromino: Tetromino,
|
||||||
direction: Direction,
|
direction: Direction,
|
||||||
|
@ -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() {
|
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) {
|
if cell != Some(&TetrisCell::Empty) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user