fox32: Start implementing keyboard input support
This commit is contained in:
parent
22c7b26317
commit
1f89b59f83
10
Cargo.lock
generated
10
Cargo.lock
generated
|
@ -739,6 +739,7 @@ dependencies = [
|
|||
"log",
|
||||
"pixels",
|
||||
"rfd",
|
||||
"ringbuf",
|
||||
"vergen",
|
||||
"winit",
|
||||
"winit_input_helper",
|
||||
|
@ -1963,6 +1964,15 @@ dependencies = [
|
|||
"windows",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ringbuf"
|
||||
version = "0.2.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fd3064490f4a0c5bc127544803fbc2bb5f77ec5170f0208f2d7b605a4f396d44"
|
||||
dependencies = [
|
||||
"cache-padded",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustc-hash"
|
||||
version = "1.1.0"
|
||||
|
|
|
@ -12,6 +12,7 @@ image = "0.24"
|
|||
log = "0.4"
|
||||
pixels = "0.9.0"
|
||||
rfd = "0.7.0"
|
||||
ringbuf = "0.2"
|
||||
winit = "0.26"
|
||||
winit_input_helper = "0.11"
|
||||
|
||||
|
|
35
src/bus.rs
35
src/bus.rs
|
@ -1,12 +1,13 @@
|
|||
// bus.rs
|
||||
|
||||
use crate::{DiskController, Memory, Mouse, Overlay};
|
||||
use crate::{DiskController, Keyboard, Memory, Mouse, Overlay};
|
||||
|
||||
use std::io::{stdout, Write};
|
||||
use std::sync::{Arc, Mutex};
|
||||
|
||||
pub struct Bus {
|
||||
pub disk_controller: DiskController,
|
||||
pub keyboard: Arc<Mutex<Keyboard>>,
|
||||
pub memory: Memory,
|
||||
pub mouse: Arc<Mutex<Mouse>>,
|
||||
pub overlays: Arc<Mutex<Vec<Overlay>>>,
|
||||
|
@ -72,17 +73,21 @@ impl Bus {
|
|||
_ => panic!("invalid mouse control port"),
|
||||
}
|
||||
}
|
||||
0x80001000..=0x80002200 => { // disk controller port
|
||||
let address_or_id = (port & 0x00000FFF) as usize;
|
||||
0x80000500 => { // keyboard port
|
||||
let mut keyboard_lock = self.keyboard.lock().expect("failed to lock the keyboard mutex");
|
||||
keyboard_lock.pop() as u32
|
||||
}
|
||||
0x80001000..=0x80002003 => { // disk controller port
|
||||
let id = port as u8;
|
||||
let operation = (port & 0x0000F000) >> 8;
|
||||
|
||||
match operation {
|
||||
0x10 => {
|
||||
// we're reading the current insert state of the specified disk id
|
||||
if address_or_id > 3 {
|
||||
if id > 3 {
|
||||
panic!("invalid disk ID");
|
||||
}
|
||||
match &self.disk_controller.disk[address_or_id] {
|
||||
match &self.disk_controller.disk[id as usize] {
|
||||
Some(disk) => disk.size as u32, // return size if this disk is inserted
|
||||
None => 0, // return 0 if this disk is not inserted
|
||||
}
|
||||
|
@ -154,19 +159,19 @@ impl Bus {
|
|||
_ => panic!("invalid mouse control port"),
|
||||
}
|
||||
}
|
||||
0x80001000..=0x80004200 => { // disk controller port
|
||||
let address_or_id = (port & 0x00000FFF) as usize;
|
||||
0x80001000..=0x80004003 => { // disk controller port
|
||||
let id = port as u8;
|
||||
let operation = (port & 0x0000F000) >> 8;
|
||||
|
||||
match operation {
|
||||
0x10 => {
|
||||
// we're requesting a disk to be inserted to the specified disk id
|
||||
if address_or_id > 3 {
|
||||
if id > 3 {
|
||||
panic!("invalid disk ID");
|
||||
}
|
||||
let file = self.disk_controller.select_file();
|
||||
match file {
|
||||
Some(file) => self.disk_controller.insert(file, address_or_id as u8),
|
||||
Some(file) => self.disk_controller.insert(file, id),
|
||||
None => {},
|
||||
};
|
||||
}
|
||||
|
@ -176,19 +181,19 @@ impl Bus {
|
|||
}
|
||||
0x30 => {
|
||||
// we're reading the specified sector of the specified disk id into the memory sector buffer
|
||||
if address_or_id > 3 {
|
||||
if id > 3 {
|
||||
panic!("invalid disk ID");
|
||||
}
|
||||
self.disk_controller.set_current_sector(address_or_id as u8, word);
|
||||
self.disk_controller.read_into_memory(address_or_id as u8, self.memory.ram());
|
||||
self.disk_controller.set_current_sector(id, word);
|
||||
self.disk_controller.read_into_memory(id, self.memory.ram());
|
||||
}
|
||||
0x40 => {
|
||||
// we're writing the specified sector to the specified disk id from the memory sector buffer
|
||||
if address_or_id > 3 {
|
||||
if id > 3 {
|
||||
panic!("invalid disk ID");
|
||||
}
|
||||
self.disk_controller.set_current_sector(address_or_id as u8, word);
|
||||
self.disk_controller.write_from_memory(address_or_id as u8, self.memory.ram());
|
||||
self.disk_controller.set_current_sector(id, word);
|
||||
self.disk_controller.write_from_memory(id, self.memory.ram());
|
||||
}
|
||||
_ => panic!("invalid disk controller port"),
|
||||
}
|
||||
|
|
28
src/keyboard.rs
Normal file
28
src/keyboard.rs
Normal file
|
@ -0,0 +1,28 @@
|
|||
// keyboard.rs
|
||||
|
||||
use crate::warn;
|
||||
|
||||
use ringbuf::{Consumer, Producer, RingBuffer};
|
||||
|
||||
pub struct Keyboard {
|
||||
consumer: Consumer<u32>,
|
||||
producer: Producer<u32>,
|
||||
}
|
||||
|
||||
impl Keyboard {
|
||||
pub fn new() -> Self {
|
||||
let buffer = RingBuffer::<u32>::new(32);
|
||||
let (producer, consumer) = buffer.split();
|
||||
Keyboard { consumer, producer }
|
||||
}
|
||||
|
||||
pub fn push(&mut self, scancode: u32) {
|
||||
self.producer.push(scancode).unwrap_or_else(|_| {
|
||||
warn("keyboard buffer full!");
|
||||
});
|
||||
}
|
||||
|
||||
pub fn pop(&mut self) -> u32 {
|
||||
self.consumer.pop().unwrap_or_else(|| 0)
|
||||
}
|
||||
}
|
22
src/main.rs
22
src/main.rs
|
@ -3,11 +3,13 @@
|
|||
pub mod bus;
|
||||
pub mod cpu;
|
||||
pub mod disk;
|
||||
pub mod keyboard;
|
||||
pub mod memory;
|
||||
pub mod mouse;
|
||||
use bus::Bus;
|
||||
use cpu::{Cpu, Interrupt};
|
||||
use disk::DiskController;
|
||||
use keyboard::Keyboard;
|
||||
use memory::{MEMORY_RAM_START, MEMORY_ROM_START, Memory, MemoryRam};
|
||||
use mouse::Mouse;
|
||||
|
||||
|
@ -21,7 +23,7 @@ use image;
|
|||
use log::error;
|
||||
use pixels::{Pixels, SurfaceTexture};
|
||||
use winit::dpi::LogicalSize;
|
||||
use winit::event::{Event, VirtualKeyCode};
|
||||
use winit::event::{ElementState, Event, WindowEvent};
|
||||
use winit::event_loop::{ControlFlow, EventLoop};
|
||||
use winit::window::{WindowBuilder, Icon};
|
||||
use winit_input_helper::WinitInputHelper;
|
||||
|
@ -73,6 +75,7 @@ fn main() {
|
|||
}*/
|
||||
|
||||
let mut display = Display::new();
|
||||
let keyboard = Arc::new(Mutex::new(Keyboard::new()));
|
||||
let mouse = Arc::new(Mutex::new(Mouse::new()));
|
||||
|
||||
let memory = Memory::new(read_rom().as_slice());
|
||||
|
@ -90,10 +93,11 @@ fn main() {
|
|||
let rom_top_address = rom_bottom_address + rom_size - 1;
|
||||
println!("ROM: {:.2} KiB mapped at {:#010X}-{:#010X}", rom_size / 1024, rom_bottom_address, rom_top_address);
|
||||
|
||||
let bus_keyboard = Arc::clone(&keyboard);
|
||||
let bus_mouse = Arc::clone(&mouse);
|
||||
let bus_overlays = Arc::clone(&display.overlays);
|
||||
let disk_controller = DiskController::new();
|
||||
let bus = Bus { disk_controller, memory: memory_cpu, mouse: bus_mouse, overlays: bus_overlays };
|
||||
let bus = Bus { disk_controller, keyboard: bus_keyboard, memory: memory_cpu, mouse: bus_mouse, overlays: bus_overlays };
|
||||
Cpu::new(bus)
|
||||
};
|
||||
|
||||
|
@ -180,9 +184,21 @@ fn main() {
|
|||
}
|
||||
|
||||
// handle input events
|
||||
if let Event::WindowEvent { ref event, .. } = event {
|
||||
if let WindowEvent::KeyboardInput { input, .. } = event {
|
||||
let mut keyboard_lock = keyboard.lock().unwrap();
|
||||
let mut scancode = input.scancode;
|
||||
if input.state == ElementState::Released {
|
||||
scancode |= 0x80; // "break" scancode
|
||||
}
|
||||
println!("scancode: {:x}", scancode);
|
||||
keyboard_lock.push(scancode);
|
||||
}
|
||||
}
|
||||
|
||||
if input.update(&event) {
|
||||
// close events
|
||||
if input.key_pressed(VirtualKeyCode::Escape) || input.quit() {
|
||||
if input.quit() {
|
||||
*control_flow = ControlFlow::Exit;
|
||||
return;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user