Add keyboard shortcuts
This commit is contained in:
parent
dd93e414c5
commit
3137312831
16
src/audio.rs
16
src/audio.rs
@ -49,14 +49,6 @@ enum FanState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl FanState {
|
impl FanState {
|
||||||
/// Returns `true` if the fan state is [`Off`].
|
|
||||||
///
|
|
||||||
/// [`Off`]: FanState::Off
|
|
||||||
#[must_use]
|
|
||||||
fn is_off(&self) -> bool {
|
|
||||||
matches!(self, Self::Off)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns `true` if the fan state is [`Starting`].
|
/// Returns `true` if the fan state is [`Starting`].
|
||||||
///
|
///
|
||||||
/// [`Starting`]: FanState::Starting
|
/// [`Starting`]: FanState::Starting
|
||||||
@ -72,14 +64,6 @@ impl FanState {
|
|||||||
fn is_on(&self) -> bool {
|
fn is_on(&self) -> bool {
|
||||||
matches!(self, Self::On)
|
matches!(self, Self::On)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns `true` if the fan state is [`Stopping`].
|
|
||||||
///
|
|
||||||
/// [`Stopping`]: FanState::Stopping
|
|
||||||
#[must_use]
|
|
||||||
fn is_stopping(&self) -> bool {
|
|
||||||
matches!(self, Self::Stopping { .. })
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AudioThread {
|
impl AudioThread {
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
|
||||||
use eframe::{
|
use eframe::{
|
||||||
egui::{self, Sense, TextureOptions, Ui, Widget},
|
egui::{self, KeyboardShortcut, Modifiers, Sense, TextureOptions, Ui, Widget, Key},
|
||||||
epaint::{vec2, Pos2, Rect, TextureHandle},
|
epaint::{vec2, Pos2, Rect, TextureHandle},
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -26,7 +26,7 @@ pub enum ActionSwitch {
|
|||||||
|
|
||||||
#[derive(Clone, Copy, Debug)]
|
#[derive(Clone, Copy, Debug)]
|
||||||
pub enum FrontpanelInteraction {
|
pub enum FrontpanelInteraction {
|
||||||
ActionSwClicked(ActionSwitch, SwitchState),
|
ActionSwChanged(ActionSwitch, SwitchState),
|
||||||
AdChanged(u16),
|
AdChanged(u16),
|
||||||
PowerChanged(bool),
|
PowerChanged(bool),
|
||||||
}
|
}
|
||||||
@ -119,12 +119,9 @@ impl Widget for &mut Frontpanel<'_> {
|
|||||||
led::Textures::new(self.textures.led_on.clone(), self.textures.led_off.clone());
|
led::Textures::new(self.textures.led_on.clone(), self.textures.led_off.clone());
|
||||||
let resp = ui.allocate_response(
|
let resp = ui.allocate_response(
|
||||||
vec2(800.0, 333.0),
|
vec2(800.0, 333.0),
|
||||||
Sense {
|
Sense::click(),
|
||||||
click: false,
|
|
||||||
drag: false,
|
|
||||||
focusable: false,
|
|
||||||
},
|
|
||||||
);
|
);
|
||||||
|
resp.request_focus();
|
||||||
let fp_rect = resp.rect;
|
let fp_rect = resp.rect;
|
||||||
ui.allocate_ui_at_rect(fp_rect, |ui| {
|
ui.allocate_ui_at_rect(fp_rect, |ui| {
|
||||||
ui.image(&self.textures.fp);
|
ui.image(&self.textures.fp);
|
||||||
@ -152,8 +149,12 @@ impl Widget for &mut Frontpanel<'_> {
|
|||||||
ui.allocate_ui_at_rect(Rect::from_center_size(pos, vec2(11.0, 25.0)), |ui| {
|
ui.allocate_ui_at_rect(Rect::from_center_size(pos, vec2(11.0, 25.0)), |ui| {
|
||||||
let mut power_inv = !self.state.power;
|
let mut power_inv = !self.state.power;
|
||||||
if ui
|
if ui
|
||||||
.add(switch::ToggleSwitch::new(&mut power_inv, &sw_textures))
|
.add(switch::ToggleSwitch::new(
|
||||||
.drag_started()
|
&mut power_inv,
|
||||||
|
&sw_textures,
|
||||||
|
Some(KeyboardShortcut::new(Modifiers::NONE, Key::Q)),
|
||||||
|
))
|
||||||
|
.changed()
|
||||||
{
|
{
|
||||||
self.state.power = !power_inv;
|
self.state.power = !power_inv;
|
||||||
self.interaction =
|
self.interaction =
|
||||||
@ -165,9 +166,18 @@ impl Widget for &mut Frontpanel<'_> {
|
|||||||
let bit_mask = 1 << (16 - i);
|
let bit_mask = 1 << (16 - i);
|
||||||
let mut sw_state = self.state.ad_sws & bit_mask > 0;
|
let mut sw_state = self.state.ad_sws & bit_mask > 0;
|
||||||
ui.allocate_ui_at_rect(Rect::from_center_size(pos, vec2(11.0, 25.0)), |ui| {
|
ui.allocate_ui_at_rect(Rect::from_center_size(pos, vec2(11.0, 25.0)), |ui| {
|
||||||
|
let key_offset = (i - 1) % 8;
|
||||||
|
let key = (b'1' + key_offset as u8) as char;
|
||||||
|
let key = Key::from_name(&key.to_string()).unwrap();
|
||||||
|
let mods = if (i - 1) >= 8 {
|
||||||
|
Modifiers::SHIFT
|
||||||
|
} else {
|
||||||
|
Modifiers::NONE
|
||||||
|
};
|
||||||
|
let shortcut = KeyboardShortcut::new(mods, key);
|
||||||
if ui
|
if ui
|
||||||
.add(switch::ToggleSwitch::new(&mut sw_state, &sw_textures))
|
.add(switch::ToggleSwitch::new(&mut sw_state, &sw_textures, Some(shortcut)))
|
||||||
.drag_started()
|
.changed()
|
||||||
{
|
{
|
||||||
self.state.ad_sws =
|
self.state.ad_sws =
|
||||||
(self.state.ad_sws & !(bit_mask)) | ((sw_state as u16) << (16 - i));
|
(self.state.ad_sws & !(bit_mask)) | ((sw_state as u16) << (16 - i));
|
||||||
@ -189,9 +199,16 @@ impl Widget for &mut Frontpanel<'_> {
|
|||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
};
|
};
|
||||||
ui.allocate_ui_at_rect(Rect::from_center_size(pos, vec2(11.0, 25.0)), |ui| {
|
ui.allocate_ui_at_rect(Rect::from_center_size(pos, vec2(11.0, 25.0)), |ui| {
|
||||||
|
let sw_offset = i - 17;
|
||||||
|
let up_key = ["W", "E", "R", "T", "Y", "U", "I", "O"][sw_offset];
|
||||||
|
let down_key = ["S", "D", "F", "G", "H", "J", "K", "L"][sw_offset];
|
||||||
|
let up_key = Key::from_name(up_key).unwrap();
|
||||||
|
let down_key = Key::from_name(down_key).unwrap();
|
||||||
|
let up_shortcut = KeyboardShortcut::new(Modifiers::NONE, up_key);
|
||||||
|
let down_shortcut = KeyboardShortcut::new(Modifiers::NONE, down_key);
|
||||||
if ui
|
if ui
|
||||||
.add(switch::ThreePosSwitch::new(state, &sw_textures))
|
.add(switch::ThreePosSwitch::new(state, &sw_textures, Some(up_shortcut), Some(down_shortcut)))
|
||||||
.drag_started()
|
.changed()
|
||||||
{
|
{
|
||||||
let sw = match i {
|
let sw = match i {
|
||||||
17 => ActionSwitch::RunStop,
|
17 => ActionSwitch::RunStop,
|
||||||
@ -205,12 +222,15 @@ impl Widget for &mut Frontpanel<'_> {
|
|||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
};
|
};
|
||||||
self.interaction =
|
self.interaction =
|
||||||
Some(FrontpanelInteraction::ActionSwClicked(sw, *state));
|
Some(FrontpanelInteraction::ActionSwChanged(sw, *state));
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
// if ui.input_mut(|input| input.consume_shortcut(&KeyboardShortcut::new(Modifiers::NONE, Key::Q))) {
|
||||||
|
// dbg!();
|
||||||
|
// }
|
||||||
resp
|
resp
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
use eframe::{
|
use eframe::{
|
||||||
egui::{Sense, Widget},
|
egui::{KeyboardShortcut, Sense, Widget},
|
||||||
epaint::{pos2, vec2, Color32, Rect, TextureHandle, TextureId},
|
epaint::{pos2, vec2, Color32, Rect, TextureHandle, TextureId},
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -54,11 +54,13 @@ impl Default for SwitchState {
|
|||||||
pub struct ThreePosSwitch<'a> {
|
pub struct ThreePosSwitch<'a> {
|
||||||
state: &'a mut SwitchState,
|
state: &'a mut SwitchState,
|
||||||
textures: &'a Textures,
|
textures: &'a Textures,
|
||||||
|
up_shortcut: Option<KeyboardShortcut>,
|
||||||
|
down_shortcut: Option<KeyboardShortcut>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> ThreePosSwitch<'a> {
|
impl<'a> ThreePosSwitch<'a> {
|
||||||
pub fn new(state: &'a mut SwitchState, textures: &'a Textures) -> Self {
|
pub fn new(state: &'a mut SwitchState, textures: &'a Textures, up_shortcut: Option<KeyboardShortcut>, down_shortcut: Option<KeyboardShortcut>) -> Self {
|
||||||
Self { state, textures }
|
Self { state, textures, up_shortcut, down_shortcut }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -71,6 +73,18 @@ impl Widget for ThreePosSwitch<'_> {
|
|||||||
NULL_UV,
|
NULL_UV,
|
||||||
NULL_TINT,
|
NULL_TINT,
|
||||||
);
|
);
|
||||||
|
let up_shortcut_pressed = self.up_shortcut.map_or(false, |shortcut| {
|
||||||
|
ui.input_mut(|input| input.key_pressed(shortcut.logical_key) && shortcut.modifiers == input.modifiers)
|
||||||
|
});
|
||||||
|
let down_shortcut_pressed = self.down_shortcut.map_or(false, |shortcut| {
|
||||||
|
ui.input_mut(|input| input.key_pressed(shortcut.logical_key) && shortcut.modifiers == input.modifiers)
|
||||||
|
});
|
||||||
|
let up_shortcut_released = self.up_shortcut.map_or(false, |shortcut| {
|
||||||
|
ui.input_mut(|input| input.key_released(shortcut.logical_key) && shortcut.modifiers == input.modifiers)
|
||||||
|
});
|
||||||
|
let down_shortcut_released = self.down_shortcut.map_or(false, |shortcut| {
|
||||||
|
ui.input_mut(|input| input.key_released(shortcut.logical_key) && shortcut.modifiers == input.modifiers)
|
||||||
|
});
|
||||||
if resp.drag_started() {
|
if resp.drag_started() {
|
||||||
let interact_pos = resp.interact_pointer_pos().unwrap();
|
let interact_pos = resp.interact_pointer_pos().unwrap();
|
||||||
let sw_center = painter.clip_rect().left_top() + vec2(5.0, 12.0);
|
let sw_center = painter.clip_rect().left_top() + vec2(5.0, 12.0);
|
||||||
@ -80,7 +94,17 @@ impl Widget for ThreePosSwitch<'_> {
|
|||||||
*self.state = SwitchState::Up;
|
*self.state = SwitchState::Up;
|
||||||
};
|
};
|
||||||
resp.mark_changed();
|
resp.mark_changed();
|
||||||
} else if resp.drag_released() {
|
} else if up_shortcut_pressed {
|
||||||
|
*self.state = SwitchState::Up;
|
||||||
|
resp.mark_changed();
|
||||||
|
} else if down_shortcut_pressed {
|
||||||
|
*self.state = SwitchState::Down;
|
||||||
|
resp.mark_changed();
|
||||||
|
} else if resp.drag_released() || up_shortcut_released || down_shortcut_released {
|
||||||
|
*self.state = SwitchState::Neut;
|
||||||
|
resp.mark_changed();
|
||||||
|
}
|
||||||
|
if *self.state != SwitchState::Neut && !resp.dragged() && ui.input(|input| input.keys_down.is_empty()) {
|
||||||
*self.state = SwitchState::Neut;
|
*self.state = SwitchState::Neut;
|
||||||
resp.mark_changed();
|
resp.mark_changed();
|
||||||
}
|
}
|
||||||
@ -91,11 +115,20 @@ impl Widget for ThreePosSwitch<'_> {
|
|||||||
pub struct ToggleSwitch<'a> {
|
pub struct ToggleSwitch<'a> {
|
||||||
state: &'a mut bool,
|
state: &'a mut bool,
|
||||||
textures: &'a Textures,
|
textures: &'a Textures,
|
||||||
|
press_shortcut: Option<KeyboardShortcut>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> ToggleSwitch<'a> {
|
impl<'a> ToggleSwitch<'a> {
|
||||||
pub fn new(state: &'a mut bool, textures: &'a Textures) -> Self {
|
pub fn new(
|
||||||
Self { state, textures }
|
state: &'a mut bool,
|
||||||
|
textures: &'a Textures,
|
||||||
|
press_shortcut: Option<KeyboardShortcut>,
|
||||||
|
) -> Self {
|
||||||
|
Self {
|
||||||
|
state,
|
||||||
|
textures,
|
||||||
|
press_shortcut,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -108,7 +141,10 @@ impl Widget for ToggleSwitch<'_> {
|
|||||||
NULL_UV,
|
NULL_UV,
|
||||||
NULL_TINT,
|
NULL_TINT,
|
||||||
);
|
);
|
||||||
if resp.drag_started() {
|
let shortcut_pressed = self.press_shortcut.map_or(false, |press_shortcut| {
|
||||||
|
ui.input_mut(|input| input.consume_shortcut(&press_shortcut))
|
||||||
|
});
|
||||||
|
if resp.drag_started() || shortcut_pressed {
|
||||||
*self.state = !*self.state;
|
*self.state = !*self.state;
|
||||||
resp.mark_changed();
|
resp.mark_changed();
|
||||||
}
|
}
|
||||||
|
447
src/main.rs
447
src/main.rs
@ -4,16 +4,16 @@ mod cpu;
|
|||||||
mod frontpanel;
|
mod frontpanel;
|
||||||
mod ram;
|
mod ram;
|
||||||
|
|
||||||
use std::{path::Path, sync::mpsc::Sender};
|
use std::sync::mpsc::Sender;
|
||||||
|
|
||||||
use audio::{AudioMessage, AudioThread};
|
use audio::{AudioMessage, AudioThread};
|
||||||
use cpu::{MemCycle, Status, I8080};
|
use cpu::{MemCycle, Status, I8080};
|
||||||
use device_query::DeviceState;
|
|
||||||
use eframe::{
|
use eframe::{
|
||||||
egui::{self, menu, Button, Label, TextureHandle, TextureOptions},
|
egui::{self, menu, Button},
|
||||||
NativeOptions,
|
NativeOptions,
|
||||||
};
|
};
|
||||||
use egui_modal::Modal;
|
use egui_modal::Modal;
|
||||||
|
use frontpanel::Textures;
|
||||||
use rand::RngCore;
|
use rand::RngCore;
|
||||||
use rfd::FileDialog;
|
use rfd::FileDialog;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
@ -36,16 +36,13 @@ struct Options {
|
|||||||
}
|
}
|
||||||
|
|
||||||
struct AltairEmulator {
|
struct AltairEmulator {
|
||||||
textures: frontpanel::Textures,
|
textures: Textures,
|
||||||
mem: [u8; 65536],
|
mem: [u8; 65536],
|
||||||
cpu: I8080,
|
cpu: I8080,
|
||||||
running: bool,
|
running: bool,
|
||||||
audio_tx: Sender<AudioMessage>,
|
audio_tx: Sender<AudioMessage>,
|
||||||
options: Options,
|
options: Options,
|
||||||
option_window: Option<OptionWindow>,
|
option_window: Option<OptionWindow>,
|
||||||
device_state: DeviceState,
|
|
||||||
kbd_newdown: bool,
|
|
||||||
kbd_olddown: bool,
|
|
||||||
fp_state: FrontpanelState,
|
fp_state: FrontpanelState,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -88,16 +85,13 @@ impl AltairEmulator {
|
|||||||
// 20: 004
|
// 20: 004
|
||||||
// 21: 005
|
// 21: 005
|
||||||
Self {
|
Self {
|
||||||
textures: frontpanel::Textures::new(&cc.egui_ctx),
|
textures: Textures::new(&cc.egui_ctx),
|
||||||
mem,
|
mem,
|
||||||
cpu,
|
cpu,
|
||||||
running: false,
|
running: false,
|
||||||
audio_tx,
|
audio_tx,
|
||||||
options,
|
options,
|
||||||
option_window: None,
|
option_window: None,
|
||||||
device_state: DeviceState::new(),
|
|
||||||
kbd_newdown: false,
|
|
||||||
kbd_olddown: false,
|
|
||||||
fp_state: FrontpanelState::new(),
|
fp_state: FrontpanelState::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -210,18 +204,22 @@ impl eframe::App for AltairEmulator {
|
|||||||
if let Some(interaction) = interaction {
|
if let Some(interaction) = interaction {
|
||||||
self.audio_tx.send(AudioMessage::PlaySwitchClick).unwrap();
|
self.audio_tx.send(AudioMessage::PlaySwitchClick).unwrap();
|
||||||
match interaction {
|
match interaction {
|
||||||
FrontpanelInteraction::ActionSwClicked(sw, state) => {
|
FrontpanelInteraction::ActionSwChanged(sw, state) => {
|
||||||
if self.fp_state.power() {
|
if self.fp_state.power() {
|
||||||
match sw {
|
match sw {
|
||||||
frontpanel::ActionSwitch::RunStop => {
|
frontpanel::ActionSwitch::RunStop => {
|
||||||
if state == SwitchState::Up {
|
if state == SwitchState::Up {
|
||||||
|
println!("STOP RUN");
|
||||||
self.running = false;
|
self.running = false;
|
||||||
} else {
|
} else if state == SwitchState::Down {
|
||||||
|
println!("START RUN");
|
||||||
self.running = true;
|
self.running = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
frontpanel::ActionSwitch::SingleStep => {
|
frontpanel::ActionSwitch::SingleStep => {
|
||||||
self.run_cpu_cycle();
|
if state == SwitchState::Up {
|
||||||
|
self.run_cpu_cycle();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
frontpanel::ActionSwitch::Examine => {
|
frontpanel::ActionSwitch::Examine => {
|
||||||
if state == SwitchState::Up {
|
if state == SwitchState::Up {
|
||||||
@ -231,7 +229,7 @@ impl eframe::App for AltairEmulator {
|
|||||||
self.cpu
|
self.cpu
|
||||||
.finish_m_cycle((self.fp_state.ad_sws() >> 8) as u8);
|
.finish_m_cycle((self.fp_state.ad_sws() >> 8) as u8);
|
||||||
self.update_fp();
|
self.update_fp();
|
||||||
} else {
|
} else if state == SwitchState::Down {
|
||||||
// Assume M1
|
// Assume M1
|
||||||
self.cpu.finish_m_cycle(0x0); // NOP
|
self.cpu.finish_m_cycle(0x0); // NOP
|
||||||
self.update_fp();
|
self.update_fp();
|
||||||
@ -243,7 +241,7 @@ impl eframe::App for AltairEmulator {
|
|||||||
self.mem[self.cpu.get_mem_cycle().address() as usize] =
|
self.mem[self.cpu.get_mem_cycle().address() as usize] =
|
||||||
self.fp_state.ad_sws() as u8;
|
self.fp_state.ad_sws() as u8;
|
||||||
self.update_fp();
|
self.update_fp();
|
||||||
} else {
|
} else if state == SwitchState::Down {
|
||||||
// Assume M1
|
// Assume M1
|
||||||
self.cpu.finish_m_cycle(0x0); // NOP
|
self.cpu.finish_m_cycle(0x0); // NOP
|
||||||
self.mem[self.cpu.get_mem_cycle().address() as usize] =
|
self.mem[self.cpu.get_mem_cycle().address() as usize] =
|
||||||
@ -282,358 +280,6 @@ impl eframe::App for AltairEmulator {
|
|||||||
if self.running {
|
if self.running {
|
||||||
self.run_cpu_cycle();
|
self.run_cpu_cycle();
|
||||||
}
|
}
|
||||||
// dbg!(ui.input(|input| input.pointer.latest_pos()));
|
|
||||||
// dbg!(ui.input(|input| input.pointer.latest_pos()));
|
|
||||||
// let (_, fp_rect) = ui.allocate_space((800.0, 333.0).into());
|
|
||||||
// image_topleft(fp_rect.left_top(), &self.textures.fp, ui);
|
|
||||||
// for led in &LEDS {
|
|
||||||
// let led_data = match led.source {
|
|
||||||
// LedSource::Protect => 0x0,
|
|
||||||
// LedSource::Iff => 0x0,
|
|
||||||
// LedSource::Run => 0x0,
|
|
||||||
// LedSource::CpuStatus => u16::from(self.fp_status.bits()),
|
|
||||||
// LedSource::Data => u16::from(self.fp_data),
|
|
||||||
// LedSource::Address => self.fp_address,
|
|
||||||
// };
|
|
||||||
// let led_on = (led_data & led.mask) > 0;
|
|
||||||
// let texture = if led_on {
|
|
||||||
// &self.textures.led_on
|
|
||||||
// } else {
|
|
||||||
// &self.textures.led_off
|
|
||||||
// };
|
|
||||||
// image_center(led.pos + fp_rect.left_top().to_vec2(), texture, ui);
|
|
||||||
// }
|
|
||||||
// let pointer_state = ctx.input(|inp| inp.pointer.clone());
|
|
||||||
// let interact_pos = pointer_state.interact_pos();
|
|
||||||
// let mut switch_clicked = false;
|
|
||||||
// fn bool_to_texture(state: bool, textures: &Textures) -> &TextureHandle {
|
|
||||||
// if state {
|
|
||||||
// &textures.sw_up
|
|
||||||
// } else {
|
|
||||||
// &textures.sw_down
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// fn state_to_texture(state: SwitchState, textures: &Textures) -> &TextureHandle {
|
|
||||||
// match state {
|
|
||||||
// SwitchState::Up => &textures.sw_up,
|
|
||||||
// SwitchState::Neut => &textures.sw_neut,
|
|
||||||
// SwitchState::Down => &textures.sw_down,
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// for (i, switch) in SWITCHES.iter().enumerate() {
|
|
||||||
// let pos = switch.pos + fp_rect.left_top().to_vec2();
|
|
||||||
// let texture = match i {
|
|
||||||
// 0 => bool_to_texture(!self.power, &self.textures),
|
|
||||||
// (1..=16) => {
|
|
||||||
// bool_to_texture((self.ad_sws & (1 << (16 - i))) > 0, &self.textures)
|
|
||||||
// }
|
|
||||||
// 17 => state_to_texture(self.runstop, &self.textures),
|
|
||||||
// 18 => state_to_texture(self.single_step, &self.textures),
|
|
||||||
// 19 => state_to_texture(self.exam, &self.textures),
|
|
||||||
// 20 => state_to_texture(self.dep, &self.textures),
|
|
||||||
// 21 => state_to_texture(self.reset, &self.textures),
|
|
||||||
// 22 => state_to_texture(self.prot, &self.textures),
|
|
||||||
// 23 => state_to_texture(self.aux1, &self.textures),
|
|
||||||
// 24 => state_to_texture(self.aux2, &self.textures),
|
|
||||||
// _ => unreachable!(),
|
|
||||||
// };
|
|
||||||
// image_center(pos, texture, ui);
|
|
||||||
// let interacted = interact_pos.map(|interact_pos| {
|
|
||||||
// Rect::from_center_size(interact_pos, (10.0, 24.0).into()).contains(pos)
|
|
||||||
// && !disable_fp_sws
|
|
||||||
// });
|
|
||||||
// if pointer_state.primary_clicked() && interacted.unwrap() {
|
|
||||||
// match i {
|
|
||||||
// 0 => {
|
|
||||||
// switch_clicked = true;
|
|
||||||
// self.power = !self.power;
|
|
||||||
// if self.options.fan_enabled {
|
|
||||||
// self.fan_audio_tx.send(self.power).unwrap();
|
|
||||||
// }
|
|
||||||
// if self.power {
|
|
||||||
// self.cpu = I8080::new();
|
|
||||||
// self.update_fp();
|
|
||||||
// } else {
|
|
||||||
// self.running = false;
|
|
||||||
// self.fp_status = Status::empty();
|
|
||||||
// self.fp_data = 0;
|
|
||||||
// self.fp_address = 0;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// (1..=16) => {
|
|
||||||
// switch_clicked = true;
|
|
||||||
// if (self.ad_sws & (1 << (16 - i))) > 0 {
|
|
||||||
// self.ad_sws &= !(1 << (16 - i));
|
|
||||||
// } else {
|
|
||||||
// self.ad_sws |= 1 << (16 - i);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// _ => (),
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// if pointer_state.primary_down() && interacted.unwrap() {
|
|
||||||
// if (17..=24).contains(&i) && self.mouse_newdown {
|
|
||||||
// switch_clicked = true;
|
|
||||||
// }
|
|
||||||
// let newstate = if interact_pos.unwrap().y > pos.y {
|
|
||||||
// SwitchState::Down
|
|
||||||
// } else {
|
|
||||||
// SwitchState::Up
|
|
||||||
// };
|
|
||||||
// match i {
|
|
||||||
// 17 => self.runstop = newstate,
|
|
||||||
// 18 => self.single_step = newstate,
|
|
||||||
// 19 => self.exam = newstate,
|
|
||||||
// 20 => self.dep = newstate,
|
|
||||||
// 21 => self.reset = newstate,
|
|
||||||
// 22 => self.prot = newstate,
|
|
||||||
// 23 => self.aux1 = newstate,
|
|
||||||
// 24 => self.aux2 = newstate,
|
|
||||||
// _ => (),
|
|
||||||
// }
|
|
||||||
// } else {
|
|
||||||
// match i {
|
|
||||||
// 17 => self.runstop = SwitchState::Neut,
|
|
||||||
// 18 => self.single_step = SwitchState::Neut,
|
|
||||||
// 19 => self.exam = SwitchState::Neut,
|
|
||||||
// 20 => self.dep = SwitchState::Neut,
|
|
||||||
// 21 => self.reset = SwitchState::Neut,
|
|
||||||
// 22 => self.prot = SwitchState::Neut,
|
|
||||||
// 23 => self.aux1 = SwitchState::Neut,
|
|
||||||
// 24 => self.aux2 = SwitchState::Neut,
|
|
||||||
// _ => (),
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// if !disable_fp_sws {
|
|
||||||
// let mut kbd_ad = None;
|
|
||||||
// let pressed_keys = self.device_state.query_keymap();
|
|
||||||
// if pressed_keys
|
|
||||||
// .iter()
|
|
||||||
// .filter(|&&k| k != Keycode::LShift && k != Keycode::RShift)
|
|
||||||
// .count()
|
|
||||||
// != 0
|
|
||||||
// {
|
|
||||||
// if self.kbd_newdown {
|
|
||||||
// self.kbd_olddown = true;
|
|
||||||
// self.kbd_newdown = false;
|
|
||||||
// } else if !self.kbd_newdown && !self.kbd_olddown {
|
|
||||||
// self.kbd_newdown = true;
|
|
||||||
// }
|
|
||||||
// } else {
|
|
||||||
// self.kbd_newdown = false;
|
|
||||||
// self.kbd_olddown = false;
|
|
||||||
// }
|
|
||||||
// if self.kbd_newdown {
|
|
||||||
// if pressed_keys.contains(&Keycode::W)
|
|
||||||
// || pressed_keys.contains(&Keycode::E)
|
|
||||||
// || pressed_keys.contains(&Keycode::R)
|
|
||||||
// || pressed_keys.contains(&Keycode::T)
|
|
||||||
// || pressed_keys.contains(&Keycode::Y)
|
|
||||||
// || pressed_keys.contains(&Keycode::U)
|
|
||||||
// || pressed_keys.contains(&Keycode::I)
|
|
||||||
// || pressed_keys.contains(&Keycode::O)
|
|
||||||
// || pressed_keys.contains(&Keycode::S)
|
|
||||||
// || pressed_keys.contains(&Keycode::D)
|
|
||||||
// || pressed_keys.contains(&Keycode::F)
|
|
||||||
// || pressed_keys.contains(&Keycode::G)
|
|
||||||
// || pressed_keys.contains(&Keycode::H)
|
|
||||||
// || pressed_keys.contains(&Keycode::J)
|
|
||||||
// || pressed_keys.contains(&Keycode::K)
|
|
||||||
// || pressed_keys.contains(&Keycode::L)
|
|
||||||
// {
|
|
||||||
// switch_clicked = true;
|
|
||||||
// }
|
|
||||||
// if pressed_keys.contains(&Keycode::LShift)
|
|
||||||
// || pressed_keys.contains(&Keycode::RShift)
|
|
||||||
// {
|
|
||||||
// if pressed_keys.contains(&Keycode::Key1) {
|
|
||||||
// kbd_ad = Some(15);
|
|
||||||
// } else if pressed_keys.contains(&Keycode::Key2) {
|
|
||||||
// kbd_ad = Some(14);
|
|
||||||
// } else if pressed_keys.contains(&Keycode::Key3) {
|
|
||||||
// kbd_ad = Some(13);
|
|
||||||
// } else if pressed_keys.contains(&Keycode::Key4) {
|
|
||||||
// kbd_ad = Some(12);
|
|
||||||
// } else if pressed_keys.contains(&Keycode::Key5) {
|
|
||||||
// kbd_ad = Some(11);
|
|
||||||
// } else if pressed_keys.contains(&Keycode::Key6) {
|
|
||||||
// kbd_ad = Some(10);
|
|
||||||
// } else if pressed_keys.contains(&Keycode::Key7) {
|
|
||||||
// kbd_ad = Some(9);
|
|
||||||
// } else if pressed_keys.contains(&Keycode::Key8) {
|
|
||||||
// kbd_ad = Some(8);
|
|
||||||
// }
|
|
||||||
// } else {
|
|
||||||
// if pressed_keys.contains(&Keycode::Key1) {
|
|
||||||
// kbd_ad = Some(7);
|
|
||||||
// } else if pressed_keys.contains(&Keycode::Key2) {
|
|
||||||
// kbd_ad = Some(6);
|
|
||||||
// } else if pressed_keys.contains(&Keycode::Key3) {
|
|
||||||
// kbd_ad = Some(5);
|
|
||||||
// } else if pressed_keys.contains(&Keycode::Key4) {
|
|
||||||
// kbd_ad = Some(4);
|
|
||||||
// } else if pressed_keys.contains(&Keycode::Key5) {
|
|
||||||
// kbd_ad = Some(3);
|
|
||||||
// } else if pressed_keys.contains(&Keycode::Key6) {
|
|
||||||
// kbd_ad = Some(2);
|
|
||||||
// } else if pressed_keys.contains(&Keycode::Key7) {
|
|
||||||
// kbd_ad = Some(1);
|
|
||||||
// } else if pressed_keys.contains(&Keycode::Key8) {
|
|
||||||
// kbd_ad = Some(0);
|
|
||||||
// }
|
|
||||||
// if pressed_keys.contains(&Keycode::Q) {
|
|
||||||
// switch_clicked = true;
|
|
||||||
// self.power = !self.power;
|
|
||||||
// if self.options.fan_enabled {
|
|
||||||
// self.fan_audio_tx.send(self.power).unwrap();
|
|
||||||
// }
|
|
||||||
// if self.power {
|
|
||||||
// self.cpu = I8080::new();
|
|
||||||
// self.update_fp();
|
|
||||||
// } else {
|
|
||||||
// self.running = false;
|
|
||||||
// self.fp_status = Status::empty();
|
|
||||||
// self.fp_data = 0;
|
|
||||||
// self.fp_address = 0;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// if pressed_keys.contains(&Keycode::W) {
|
|
||||||
// self.runstop = SwitchState::Up;
|
|
||||||
// }
|
|
||||||
// if pressed_keys.contains(&Keycode::E) {
|
|
||||||
// self.single_step = SwitchState::Up;
|
|
||||||
// }
|
|
||||||
// if pressed_keys.contains(&Keycode::R) {
|
|
||||||
// self.exam = SwitchState::Up;
|
|
||||||
// }
|
|
||||||
// if pressed_keys.contains(&Keycode::T) {
|
|
||||||
// self.dep = SwitchState::Up;
|
|
||||||
// }
|
|
||||||
// if pressed_keys.contains(&Keycode::Y) {
|
|
||||||
// self.reset = SwitchState::Up;
|
|
||||||
// }
|
|
||||||
// if pressed_keys.contains(&Keycode::U) {
|
|
||||||
// self.prot = SwitchState::Up;
|
|
||||||
// }
|
|
||||||
// if pressed_keys.contains(&Keycode::I) {
|
|
||||||
// self.aux1 = SwitchState::Up;
|
|
||||||
// }
|
|
||||||
// if pressed_keys.contains(&Keycode::O) {
|
|
||||||
// self.aux2 = SwitchState::Up;
|
|
||||||
// }
|
|
||||||
// if pressed_keys.contains(&Keycode::S) {
|
|
||||||
// self.runstop = SwitchState::Down;
|
|
||||||
// }
|
|
||||||
// if pressed_keys.contains(&Keycode::D) {
|
|
||||||
// self.single_step = SwitchState::Down;
|
|
||||||
// }
|
|
||||||
// if pressed_keys.contains(&Keycode::F) {
|
|
||||||
// self.exam = SwitchState::Down;
|
|
||||||
// }
|
|
||||||
// if pressed_keys.contains(&Keycode::G) {
|
|
||||||
// self.dep = SwitchState::Down;
|
|
||||||
// }
|
|
||||||
// if pressed_keys.contains(&Keycode::H) {
|
|
||||||
// self.reset = SwitchState::Down;
|
|
||||||
// }
|
|
||||||
// if pressed_keys.contains(&Keycode::J) {
|
|
||||||
// self.prot = SwitchState::Down;
|
|
||||||
// }
|
|
||||||
// if pressed_keys.contains(&Keycode::K) {
|
|
||||||
// self.aux1 = SwitchState::Down;
|
|
||||||
// }
|
|
||||||
// if pressed_keys.contains(&Keycode::L) {
|
|
||||||
// self.aux2 = SwitchState::Down;
|
|
||||||
// }
|
|
||||||
// if let Some(kbd_ad) = kbd_ad {
|
|
||||||
// switch_clicked = true;
|
|
||||||
// if (self.ad_sws & (1 << kbd_ad)) > 0 {
|
|
||||||
// self.ad_sws &= !(1 << kbd_ad);
|
|
||||||
// } else {
|
|
||||||
// self.ad_sws |= 1 << kbd_ad;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// if switch_clicked {
|
|
||||||
// self.main_audio_tx
|
|
||||||
// .send(AudioMessage::PlaySwitchClick)
|
|
||||||
// .unwrap();
|
|
||||||
// }
|
|
||||||
// if pointer_state.primary_down() {
|
|
||||||
// if self.mouse_newdown {
|
|
||||||
// self.mouse_olddown = true;
|
|
||||||
// self.mouse_newdown = false;
|
|
||||||
// } else if !self.mouse_newdown && !self.mouse_olddown {
|
|
||||||
// self.mouse_newdown = true;
|
|
||||||
// }
|
|
||||||
// } else {
|
|
||||||
// self.mouse_newdown = false;
|
|
||||||
// self.mouse_olddown = false;
|
|
||||||
// }
|
|
||||||
// if switch_clicked && self.power {
|
|
||||||
// if !self.running {
|
|
||||||
// if self.exam == SwitchState::Up {
|
|
||||||
// // Assume M1
|
|
||||||
// self.cpu.finish_m_cycle(0xC3); // JMP
|
|
||||||
// self.cpu.finish_m_cycle(self.ad_sws as u8);
|
|
||||||
// self.cpu.finish_m_cycle((self.ad_sws >> 8) as u8);
|
|
||||||
// self.update_fp();
|
|
||||||
// }
|
|
||||||
// if self.exam == SwitchState::Down {
|
|
||||||
// // Assume M1
|
|
||||||
// self.cpu.finish_m_cycle(0x0); // NOP
|
|
||||||
// self.update_fp();
|
|
||||||
// }
|
|
||||||
// if self.dep == SwitchState::Up {
|
|
||||||
// // Assume M1
|
|
||||||
// self.mem[self.cpu.get_mem_cycle().address() as usize] = self.ad_sws as u8;
|
|
||||||
// self.update_fp();
|
|
||||||
// }
|
|
||||||
// if self.dep == SwitchState::Down {
|
|
||||||
// // Assume M1
|
|
||||||
// self.cpu.finish_m_cycle(0x0); // NOP
|
|
||||||
// self.mem[self.cpu.get_mem_cycle().address() as usize] = self.ad_sws as u8;
|
|
||||||
// self.update_fp();
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// if self.runstop == SwitchState::Up {
|
|
||||||
// self.running = false;
|
|
||||||
// }
|
|
||||||
// if self.runstop == SwitchState::Down {
|
|
||||||
// self.running = true;
|
|
||||||
// }
|
|
||||||
// if self.reset == SwitchState::Up {
|
|
||||||
// self.cpu.reset();
|
|
||||||
// self.update_fp();
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// if ((switch_clicked && self.single_step != SwitchState::Neut) || self.running)
|
|
||||||
// && self.power
|
|
||||||
// {
|
|
||||||
// let cycle = self.cpu.get_mem_cycle();
|
|
||||||
// let data = match cycle {
|
|
||||||
// MemCycle::Fetch(a) | MemCycle::Read(a) | MemCycle::StackRead(a) => {
|
|
||||||
// self.mem[a as usize]
|
|
||||||
// }
|
|
||||||
// MemCycle::Write(a, d) | MemCycle::StackWrite(a, d) => {
|
|
||||||
// self.mem[a as usize] = d;
|
|
||||||
// 0
|
|
||||||
// }
|
|
||||||
// MemCycle::In(_) => 0,
|
|
||||||
// MemCycle::Out(_, _) => 0,
|
|
||||||
// MemCycle::Inta(_) => todo!(),
|
|
||||||
// MemCycle::Hlta(_) => {
|
|
||||||
// self.running = false;
|
|
||||||
// 0
|
|
||||||
// }
|
|
||||||
// MemCycle::IntaHlt(_) => todo!(),
|
|
||||||
// };
|
|
||||||
// self.cpu.finish_m_cycle(data);
|
|
||||||
// self.update_fp();
|
|
||||||
// }
|
|
||||||
});
|
});
|
||||||
|
|
||||||
let old_fan_enabled = self.options.fan_enabled;
|
let old_fan_enabled = self.options.fan_enabled;
|
||||||
@ -703,68 +349,3 @@ impl OptionWindow {
|
|||||||
!modal.is_open()
|
!modal.is_open()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Textures {
|
|
||||||
fp: TextureHandle,
|
|
||||||
sw_up: TextureHandle,
|
|
||||||
sw_neut: TextureHandle,
|
|
||||||
sw_down: TextureHandle,
|
|
||||||
led_off: TextureHandle,
|
|
||||||
led_on: TextureHandle,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Textures {
|
|
||||||
fn new(ctx: &egui::Context) -> Self {
|
|
||||||
Self {
|
|
||||||
fp: Self::load_texture(
|
|
||||||
ctx,
|
|
||||||
"fp",
|
|
||||||
"/home/pjht/projects/altair_emu/resources/altair800.png",
|
|
||||||
)
|
|
||||||
.unwrap(),
|
|
||||||
sw_up: Self::load_texture(
|
|
||||||
ctx,
|
|
||||||
"sw_up",
|
|
||||||
"/home/pjht/projects/altair_emu/resources/Togup.png",
|
|
||||||
)
|
|
||||||
.unwrap(),
|
|
||||||
sw_neut: Self::load_texture(
|
|
||||||
ctx,
|
|
||||||
"sw_neut",
|
|
||||||
"/home/pjht/projects/altair_emu/resources/Togneut.png",
|
|
||||||
)
|
|
||||||
.unwrap(),
|
|
||||||
sw_down: Self::load_texture(
|
|
||||||
ctx,
|
|
||||||
"sw_down",
|
|
||||||
"/home/pjht/projects/altair_emu/resources/Togdown.png",
|
|
||||||
)
|
|
||||||
.unwrap(),
|
|
||||||
led_off: Self::load_texture(
|
|
||||||
ctx,
|
|
||||||
"led_off",
|
|
||||||
"/home/pjht/projects/altair_emu/resources/Led_off.png",
|
|
||||||
)
|
|
||||||
.unwrap(),
|
|
||||||
led_on: Self::load_texture(
|
|
||||||
ctx,
|
|
||||||
"led_on",
|
|
||||||
"/home/pjht/projects/altair_emu/resources/Led_on.png",
|
|
||||||
)
|
|
||||||
.unwrap(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn load_texture(
|
|
||||||
ctx: &egui::Context,
|
|
||||||
name: impl Into<String>,
|
|
||||||
path: impl AsRef<Path>,
|
|
||||||
) -> Result<TextureHandle, image::ImageError> {
|
|
||||||
let image = image::io::Reader::open(path.as_ref())?.decode()?;
|
|
||||||
let image = egui::ColorImage::from_rgba_unmultiplied(
|
|
||||||
[image.width() as _, image.height() as _],
|
|
||||||
image.to_rgba8().as_flat_samples().as_slice(),
|
|
||||||
);
|
|
||||||
Ok(ctx.load_texture(name, image, TextureOptions::LINEAR))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
Loading…
Reference in New Issue
Block a user