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",
|
"log",
|
||||||
"pixels",
|
"pixels",
|
||||||
"rfd",
|
"rfd",
|
||||||
|
"ringbuf",
|
||||||
"vergen",
|
"vergen",
|
||||||
"winit",
|
"winit",
|
||||||
"winit_input_helper",
|
"winit_input_helper",
|
||||||
|
@ -1963,6 +1964,15 @@ dependencies = [
|
||||||
"windows",
|
"windows",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ringbuf"
|
||||||
|
version = "0.2.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "fd3064490f4a0c5bc127544803fbc2bb5f77ec5170f0208f2d7b605a4f396d44"
|
||||||
|
dependencies = [
|
||||||
|
"cache-padded",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustc-hash"
|
name = "rustc-hash"
|
||||||
version = "1.1.0"
|
version = "1.1.0"
|
||||||
|
|
|
@ -12,6 +12,7 @@ image = "0.24"
|
||||||
log = "0.4"
|
log = "0.4"
|
||||||
pixels = "0.9.0"
|
pixels = "0.9.0"
|
||||||
rfd = "0.7.0"
|
rfd = "0.7.0"
|
||||||
|
ringbuf = "0.2"
|
||||||
winit = "0.26"
|
winit = "0.26"
|
||||||
winit_input_helper = "0.11"
|
winit_input_helper = "0.11"
|
||||||
|
|
||||||
|
|
35
src/bus.rs
35
src/bus.rs
|
@ -1,12 +1,13 @@
|
||||||
// bus.rs
|
// bus.rs
|
||||||
|
|
||||||
use crate::{DiskController, Memory, Mouse, Overlay};
|
use crate::{DiskController, Keyboard, Memory, Mouse, Overlay};
|
||||||
|
|
||||||
use std::io::{stdout, Write};
|
use std::io::{stdout, Write};
|
||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, Mutex};
|
||||||
|
|
||||||
pub struct Bus {
|
pub struct Bus {
|
||||||
pub disk_controller: DiskController,
|
pub disk_controller: DiskController,
|
||||||
|
pub keyboard: Arc<Mutex<Keyboard>>,
|
||||||
pub memory: Memory,
|
pub memory: Memory,
|
||||||
pub mouse: Arc<Mutex<Mouse>>,
|
pub mouse: Arc<Mutex<Mouse>>,
|
||||||
pub overlays: Arc<Mutex<Vec<Overlay>>>,
|
pub overlays: Arc<Mutex<Vec<Overlay>>>,
|
||||||
|
@ -72,17 +73,21 @@ impl Bus {
|
||||||
_ => panic!("invalid mouse control port"),
|
_ => panic!("invalid mouse control port"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
0x80001000..=0x80002200 => { // disk controller port
|
0x80000500 => { // keyboard port
|
||||||
let address_or_id = (port & 0x00000FFF) as usize;
|
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;
|
let operation = (port & 0x0000F000) >> 8;
|
||||||
|
|
||||||
match operation {
|
match operation {
|
||||||
0x10 => {
|
0x10 => {
|
||||||
// we're reading the current insert state of the specified disk id
|
// we're reading the current insert state of the specified disk id
|
||||||
if address_or_id > 3 {
|
if id > 3 {
|
||||||
panic!("invalid disk ID");
|
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
|
Some(disk) => disk.size as u32, // return size if this disk is inserted
|
||||||
None => 0, // return 0 if this disk is not inserted
|
None => 0, // return 0 if this disk is not inserted
|
||||||
}
|
}
|
||||||
|
@ -154,19 +159,19 @@ impl Bus {
|
||||||
_ => panic!("invalid mouse control port"),
|
_ => panic!("invalid mouse control port"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
0x80001000..=0x80004200 => { // disk controller port
|
0x80001000..=0x80004003 => { // disk controller port
|
||||||
let address_or_id = (port & 0x00000FFF) as usize;
|
let id = port as u8;
|
||||||
let operation = (port & 0x0000F000) >> 8;
|
let operation = (port & 0x0000F000) >> 8;
|
||||||
|
|
||||||
match operation {
|
match operation {
|
||||||
0x10 => {
|
0x10 => {
|
||||||
// we're requesting a disk to be inserted to the specified disk id
|
// 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");
|
panic!("invalid disk ID");
|
||||||
}
|
}
|
||||||
let file = self.disk_controller.select_file();
|
let file = self.disk_controller.select_file();
|
||||||
match file {
|
match file {
|
||||||
Some(file) => self.disk_controller.insert(file, address_or_id as u8),
|
Some(file) => self.disk_controller.insert(file, id),
|
||||||
None => {},
|
None => {},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -176,19 +181,19 @@ impl Bus {
|
||||||
}
|
}
|
||||||
0x30 => {
|
0x30 => {
|
||||||
// we're reading the specified sector of the specified disk id into the memory sector buffer
|
// 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");
|
panic!("invalid disk ID");
|
||||||
}
|
}
|
||||||
self.disk_controller.set_current_sector(address_or_id as u8, word);
|
self.disk_controller.set_current_sector(id, word);
|
||||||
self.disk_controller.read_into_memory(address_or_id as u8, self.memory.ram());
|
self.disk_controller.read_into_memory(id, self.memory.ram());
|
||||||
}
|
}
|
||||||
0x40 => {
|
0x40 => {
|
||||||
// we're writing the specified sector to the specified disk id from the memory sector buffer
|
// 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");
|
panic!("invalid disk ID");
|
||||||
}
|
}
|
||||||
self.disk_controller.set_current_sector(address_or_id as u8, word);
|
self.disk_controller.set_current_sector(id, word);
|
||||||
self.disk_controller.write_from_memory(address_or_id as u8, self.memory.ram());
|
self.disk_controller.write_from_memory(id, self.memory.ram());
|
||||||
}
|
}
|
||||||
_ => panic!("invalid disk controller port"),
|
_ => 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 bus;
|
||||||
pub mod cpu;
|
pub mod cpu;
|
||||||
pub mod disk;
|
pub mod disk;
|
||||||
|
pub mod keyboard;
|
||||||
pub mod memory;
|
pub mod memory;
|
||||||
pub mod mouse;
|
pub mod mouse;
|
||||||
use bus::Bus;
|
use bus::Bus;
|
||||||
use cpu::{Cpu, Interrupt};
|
use cpu::{Cpu, Interrupt};
|
||||||
use disk::DiskController;
|
use disk::DiskController;
|
||||||
|
use keyboard::Keyboard;
|
||||||
use memory::{MEMORY_RAM_START, MEMORY_ROM_START, Memory, MemoryRam};
|
use memory::{MEMORY_RAM_START, MEMORY_ROM_START, Memory, MemoryRam};
|
||||||
use mouse::Mouse;
|
use mouse::Mouse;
|
||||||
|
|
||||||
|
@ -21,7 +23,7 @@ use image;
|
||||||
use log::error;
|
use log::error;
|
||||||
use pixels::{Pixels, SurfaceTexture};
|
use pixels::{Pixels, SurfaceTexture};
|
||||||
use winit::dpi::LogicalSize;
|
use winit::dpi::LogicalSize;
|
||||||
use winit::event::{Event, VirtualKeyCode};
|
use winit::event::{ElementState, Event, WindowEvent};
|
||||||
use winit::event_loop::{ControlFlow, EventLoop};
|
use winit::event_loop::{ControlFlow, EventLoop};
|
||||||
use winit::window::{WindowBuilder, Icon};
|
use winit::window::{WindowBuilder, Icon};
|
||||||
use winit_input_helper::WinitInputHelper;
|
use winit_input_helper::WinitInputHelper;
|
||||||
|
@ -73,6 +75,7 @@ fn main() {
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
let mut display = Display::new();
|
let mut display = Display::new();
|
||||||
|
let keyboard = Arc::new(Mutex::new(Keyboard::new()));
|
||||||
let mouse = Arc::new(Mutex::new(Mouse::new()));
|
let mouse = Arc::new(Mutex::new(Mouse::new()));
|
||||||
|
|
||||||
let memory = Memory::new(read_rom().as_slice());
|
let memory = Memory::new(read_rom().as_slice());
|
||||||
|
@ -90,10 +93,11 @@ fn main() {
|
||||||
let rom_top_address = rom_bottom_address + rom_size - 1;
|
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);
|
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_mouse = Arc::clone(&mouse);
|
||||||
let bus_overlays = Arc::clone(&display.overlays);
|
let bus_overlays = Arc::clone(&display.overlays);
|
||||||
let disk_controller = DiskController::new();
|
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)
|
Cpu::new(bus)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -180,9 +184,21 @@ fn main() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// handle input events
|
// 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) {
|
if input.update(&event) {
|
||||||
// close events
|
// close events
|
||||||
if input.key_pressed(VirtualKeyCode::Escape) || input.quit() {
|
if input.quit() {
|
||||||
*control_flow = ControlFlow::Exit;
|
*control_flow = ControlFlow::Exit;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user