Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions crates/chippie-emulator/src/constants.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,5 @@ pub const CYCLES_PER_FRAME: usize = 5;
pub const ROM_START_ADDRESS: u16 = 0x200;
/// Amount of registers CHIP-8 has
pub const NUM_REGISTERS: u8 = 16;
/// Amount of available keys
pub const NUM_KEYS: u8 = 16;
13 changes: 6 additions & 7 deletions crates/chippie-emulator/src/cpu.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use rand::{Rng, SeedableRng};
use rand_chacha::ChaCha8Rng;

use crate::Framebuffer;
use crate::constants::{DISPLAY_HEIGHT, DISPLAY_WIDTH, RAM_SIZE, ROM_START_ADDRESS};
use crate::constants::{DISPLAY_HEIGHT, DISPLAY_WIDTH, NUM_KEYS, RAM_SIZE, ROM_START_ADDRESS};
use crate::instruction::Instruction;
use crate::ram::Ram;
use crate::registers::Registers;
Expand All @@ -30,7 +30,7 @@ pub struct Cpu {
///Program counter, used to keep track of what to fetch,decode and execute from ram, initialized at 0x200
program_counter: u16,
/// A list of "buttons", for the keyboard. set to true when pressed, false otherwise
keyboard: [bool; 16],
keyboard: [bool; NUM_KEYS as usize],
/// The memory, stores the rom data when loaded from disk
memory: Ram,
/// A random number generator. Added for testability reaons as it allows to test all random instructions with a fixed seed
Expand Down Expand Up @@ -328,11 +328,10 @@ impl Cpu {
.position(|button_pressed| *button_pressed)
}

//this should be part of an interface somehow, maybe a trait that lets external programs set the keys for the emulator
pub fn set_pressed_key(&mut self, key: usize) {
if !self.keyboard[key] {
self.keyboard[key] = true;
}
/// Set key's state
pub fn set_key_state(&mut self, key: u8, state: bool) {
assert!(key <= NUM_KEYS);
self.keyboard[key as usize] = state;
}

/// A single cpu cycle, fetches, decodes, executes opcodes and
Expand Down
2 changes: 1 addition & 1 deletion crates/chippie-emulator/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ mod rombuffer;
mod stack;

// Re-export structs and modules that migth be used by graphics libraries
pub use constants::{DISPLAY_HEIGHT, DISPLAY_WIDTH};
pub use constants::{DISPLAY_HEIGHT, DISPLAY_WIDTH, NUM_KEYS};
pub use cpu::Cpu;
pub use rombuffer::RomBuffer;

Expand Down
40 changes: 36 additions & 4 deletions crates/chippie-gui/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,23 @@
use std::cell::RefCell;
use std::rc::Rc;

use iced::keyboard;
use iced::time;
use iced::widget::column;
use iced::{Element, Fill, Subscription};

use chippie_emulator::{Cpu, DISPLAY_HEIGHT, DISPLAY_WIDTH, RomBuffer};
use chippie_emulator::{Cpu, DISPLAY_HEIGHT, DISPLAY_WIDTH, NUM_KEYS, RomBuffer};

mod constants;
mod widgets;

/// Messages that are used for communication between iced widgets.
#[derive(Debug, Clone, Copy)]
#[derive(Debug, Clone)]
pub enum Message {
/// A messages that is used as a clock source's signal
/// A message that is used as a clock source's signal
Tick,
KeyPressed(keyboard::Key),
KeyReleased(keyboard::Key),
}

/// The main application struct, which constructs GUI and reacts on messages
Expand Down Expand Up @@ -55,12 +58,41 @@ impl Application {
pub fn update(&mut self, message: Message) {
match message {
Message::Tick => self.cpu.cycle(),
Message::KeyPressed(key) => {
if let Some(index) = Application::to_index(key) {
self.cpu.set_key_state(index, true);
}
}
Message::KeyReleased(key) => {
if let Some(index) = Application::to_index(key) {
self.cpu.set_key_state(index, false);
}
}
}
}

/// Creates a specific task, that is run asynchronously by iced
pub fn subscription(&self) -> Subscription<Message> {
time::every(constants::TICK_INTERVAL).map(|_| Message::Tick)
Subscription::batch(vec![
keyboard::on_key_press(|key, _| Some(Message::KeyPressed(key))),
keyboard::on_key_release(|key, _| Some(Message::KeyReleased(key))),
time::every(constants::TICK_INTERVAL).map(|_| Message::Tick),
])
}

/// The function is used to convert iced::keyboard::Key values to key indexes, used inside the
/// emulator
fn to_index(key: keyboard::Key) -> Option<u8> {
match key {
keyboard::Key::Character(ch) => {
if let Ok(index) = u8::from_str_radix(ch.as_str(), 16) {
if index < NUM_KEYS { Some(index) } else { None }
} else {
None
}
}
_ => None,
}
}
}

Expand Down