Start reafctoring fp code
This commit is contained in:
parent
448850bce1
commit
8221544efb
18
src/cpu.rs
18
src/cpu.rs
@ -427,7 +427,7 @@ impl I8080 {
|
||||
self.update_arith_flags(ac, cy, res);
|
||||
self.regs.a = res;
|
||||
}
|
||||
},
|
||||
}
|
||||
Opcode::AnaM => (),
|
||||
Opcode::Ana(src) => {
|
||||
self.regs.a &= self.regs[src];
|
||||
@ -455,32 +455,32 @@ impl I8080 {
|
||||
Opcode::Rlc => {
|
||||
self.regs.a = self.regs.a.rotate_left(1);
|
||||
self.carry = (self.regs.a & 0x1) > 0;
|
||||
},
|
||||
}
|
||||
Opcode::Rrc => {
|
||||
self.regs.a = self.regs.a.rotate_right(1);
|
||||
self.carry = (self.regs.a & 0x80) > 0;
|
||||
},
|
||||
}
|
||||
Opcode::Ral => {
|
||||
let high_bit = (self.regs.a & 0x80) > 0;
|
||||
self.regs.a <<= 1;
|
||||
self.regs.a |= u8::from(self.carry);
|
||||
self.carry = high_bit;
|
||||
},
|
||||
}
|
||||
Opcode::Rar => {
|
||||
let low_bit = (self.regs.a & 0x1) > 0;
|
||||
self.regs.a >>= 1;
|
||||
self.regs.a |= u8::from(self.carry) << 7;
|
||||
self.carry = low_bit;
|
||||
},
|
||||
}
|
||||
Opcode::Cma => {
|
||||
self.regs.a = !self.regs.a;
|
||||
},
|
||||
}
|
||||
Opcode::Cmc => {
|
||||
self.carry = !self.carry;
|
||||
},
|
||||
}
|
||||
Opcode::Stc => {
|
||||
self.carry = true;
|
||||
},
|
||||
}
|
||||
Opcode::Jmp => (),
|
||||
Opcode::Jcc(cc) => {
|
||||
cond_failed = !self.check_cond(cc);
|
||||
@ -532,7 +532,7 @@ impl I8080 {
|
||||
}
|
||||
Opcode::Hlt => {
|
||||
self.halted = true;
|
||||
},
|
||||
}
|
||||
Opcode::Nop => (),
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,12 @@
|
||||
use super::opcode::{
|
||||
Condition,
|
||||
Opcode::{self, Aci, Adc, AdcM, Add, AddM, Adi, Ana, AnaM, Ani, Call, Ccc, Cma, Cmc, Cmp, CmpM, Cpi, Daa, Dad, Dcr, DcrM, Dcx, Di, Ei, Hlt, In, Inr, InrM, Inx, Jcc, Jmp, Lda, Ldax, Lhld, Lxi, Mov, MovMR, MovRM, Mvi, MviM, Nop, Ora, OraM, Ori, Out, Pchl, Pop, PopPsw, Push, PushPsw, Ral, Rar, Rcc, Ret, Rlc, Rrc, Rst, Sbb, SbbM, Sbi, Shld, Sphl, Sta, Stax, Stc, Sub, SubM, Sui, Xchg, Xra, XraM, Xri, Xthl},
|
||||
Opcode::{
|
||||
self, Aci, Adc, AdcM, Add, AddM, Adi, Ana, AnaM, Ani, Call, Ccc, Cma, Cmc, Cmp, CmpM, Cpi,
|
||||
Daa, Dad, Dcr, DcrM, Dcx, Di, Ei, Hlt, In, Inr, InrM, Inx, Jcc, Jmp, Lda, Ldax, Lhld, Lxi,
|
||||
Mov, MovMR, MovRM, Mvi, MviM, Nop, Ora, OraM, Ori, Out, Pchl, Pop, PopPsw, Push, PushPsw,
|
||||
Ral, Rar, Rcc, Ret, Rlc, Rrc, Rst, Sbb, SbbM, Sbi, Shld, Sphl, Sta, Stax, Stc, Sub, SubM,
|
||||
Sui, Xchg, Xra, XraM, Xri, Xthl,
|
||||
},
|
||||
Register, RegisterPair,
|
||||
};
|
||||
pub(super) static OPCODE_TABLE: [Opcode; 256] = [
|
||||
|
1
src/frontpanel.rs
Normal file
1
src/frontpanel.rs
Normal file
@ -0,0 +1 @@
|
||||
pub mod switch;
|
79
src/frontpanel/switch.rs
Normal file
79
src/frontpanel/switch.rs
Normal file
@ -0,0 +1,79 @@
|
||||
use eframe::{
|
||||
egui::{Id, Sense, Widget},
|
||||
epaint::{pos2, vec2, Color32, Rect, TextureHandle},
|
||||
};
|
||||
|
||||
const NULL_UV: Rect = Rect::from_min_max(pos2(0.0, 0.0), pos2(1.0, 1.0));
|
||||
const NULL_TINT: Color32 = Color32::WHITE;
|
||||
|
||||
pub struct Textures {
|
||||
sw_up: TextureHandle,
|
||||
sw_neut: TextureHandle,
|
||||
sw_down: TextureHandle,
|
||||
}
|
||||
|
||||
impl Textures {
|
||||
pub fn new(sw_up: TextureHandle, sw_neut: TextureHandle, sw_down: TextureHandle) -> Self {
|
||||
Self {
|
||||
sw_up,
|
||||
sw_neut,
|
||||
sw_down,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||
pub enum SwitchState {
|
||||
Up,
|
||||
Neut,
|
||||
Down,
|
||||
}
|
||||
|
||||
pub struct Switch<'a> {
|
||||
state: &'a mut SwitchState,
|
||||
textures: &'a Textures,
|
||||
}
|
||||
|
||||
impl<'a> Switch<'a> {
|
||||
pub fn new(state: &'a mut SwitchState, textures: &'a Textures) -> Self {
|
||||
Self { state, textures }
|
||||
}
|
||||
}
|
||||
|
||||
impl Widget for Switch<'_> {
|
||||
fn ui(self, ui: &mut eframe::egui::Ui) -> eframe::egui::Response {
|
||||
let (resp, painter) = ui.allocate_painter((32.0, 32.0).into(), Sense::click());
|
||||
let id = Id::new((
|
||||
painter.clip_rect().left_top().x as u32,
|
||||
painter.clip_rect().left_top().y as u32,
|
||||
));
|
||||
let texture = match self.state {
|
||||
SwitchState::Up => self.textures.sw_up.id(),
|
||||
SwitchState::Neut => self.textures.sw_neut.id(),
|
||||
SwitchState::Down => self.textures.sw_down.id(),
|
||||
};
|
||||
painter.image(
|
||||
texture,
|
||||
Rect::from_min_size(painter.clip_rect().left_top(), vec2(32.0, 32.0)),
|
||||
NULL_UV,
|
||||
NULL_TINT,
|
||||
);
|
||||
let pointer_state = ui.ctx().input(|inp| inp.pointer.clone());
|
||||
let interact_pos = pointer_state.interact_pos();
|
||||
dbg!(interact_pos);
|
||||
let interacted = interact_pos.map(|interact_pos| {
|
||||
Rect::from_center_size(interact_pos, (10.0, 24.0).into()).contains(painter.clip_rect().left_top())
|
||||
}).unwrap_or(false);
|
||||
let newstate = if interacted {
|
||||
if interact_pos.unwrap().y > painter.clip_rect().left_top().y {
|
||||
SwitchState::Down
|
||||
} else {
|
||||
SwitchState::Up
|
||||
}
|
||||
} else {
|
||||
SwitchState::Neut
|
||||
};
|
||||
*self.state = newstate;
|
||||
resp
|
||||
}
|
||||
}
|
732
src/main.rs
732
src/main.rs
@ -1,5 +1,6 @@
|
||||
mod card;
|
||||
mod cpu;
|
||||
mod frontpanel;
|
||||
mod ram;
|
||||
|
||||
use std::{
|
||||
@ -11,7 +12,10 @@ use std::{
|
||||
|
||||
use cpu::{MemCycle, Status, I8080};
|
||||
use device_query::{DeviceState, Keycode};
|
||||
use eframe::{egui::{self, menu, Button, Pos2, Rect, TextureHandle, TextureOptions, Ui}, NativeOptions};
|
||||
use eframe::{
|
||||
egui::{self, menu, Button, Pos2, Rect, TextureHandle, TextureOptions, Ui},
|
||||
NativeOptions,
|
||||
};
|
||||
use egui_modal::Modal;
|
||||
use log::{debug, trace, warn};
|
||||
use parking_lot::Mutex;
|
||||
@ -20,6 +24,8 @@ use rfd::FileDialog;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use soloud::{audio, AudioExt, LoadExt, Soloud};
|
||||
|
||||
use crate::frontpanel::switch;
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
enum AudioMessage {
|
||||
PlaySwitchClick,
|
||||
@ -182,7 +188,7 @@ struct AltairEmulator {
|
||||
runstop: SwitchState,
|
||||
single_step: SwitchState,
|
||||
exam: SwitchState,
|
||||
dep: SwitchState,
|
||||
dep: switch::SwitchState,
|
||||
reset: SwitchState,
|
||||
prot: SwitchState,
|
||||
aux1: SwitchState,
|
||||
@ -253,7 +259,7 @@ impl AltairEmulator {
|
||||
runstop: SwitchState::Neut,
|
||||
single_step: SwitchState::Neut,
|
||||
exam: SwitchState::Neut,
|
||||
dep: SwitchState::Neut,
|
||||
dep: switch::SwitchState::Neut,
|
||||
reset: SwitchState::Neut,
|
||||
prot: SwitchState::Neut,
|
||||
aux1: SwitchState::Neut,
|
||||
@ -291,7 +297,7 @@ impl AltairEmulator {
|
||||
MemCycle::In(a) => {
|
||||
self.fp_address = a;
|
||||
self.fp_data = 0;
|
||||
},
|
||||
}
|
||||
MemCycle::Inta(_) => todo!(),
|
||||
MemCycle::Hlta(_) => {
|
||||
self.fp_data = 0xff;
|
||||
@ -339,11 +345,16 @@ impl eframe::App for AltairEmulator {
|
||||
if ui.button("Load binary file").clicked() {
|
||||
let ihex_exts = ["hex", "mcs", "int", "ihex", "ihe", "ihx"];
|
||||
let file = FileDialog::new()
|
||||
.add_filter("Binary files", &["bin", "img", "hex", "mcs", "int", "ihex", "ihe", "ihx"])
|
||||
.add_filter(
|
||||
"Binary files",
|
||||
&["bin", "img", "hex", "mcs", "int", "ihex", "ihe", "ihx"],
|
||||
)
|
||||
.add_filter("All files", &["*"])
|
||||
.pick_file();
|
||||
if let Some(file) = file {
|
||||
if file.extension().map_or(false, |ext| ihex_exts.contains(&ext.to_str().unwrap_or(""))) {
|
||||
if file.extension().map_or(false, |ext| {
|
||||
ihex_exts.contains(&ext.to_str().unwrap_or(""))
|
||||
}) {
|
||||
let data = std::fs::read_to_string(file).unwrap();
|
||||
for record in ihex::Reader::new(&data) {
|
||||
let record = record.unwrap();
|
||||
@ -352,7 +363,7 @@ impl eframe::App for AltairEmulator {
|
||||
for (i, &byte) in value.iter().enumerate() {
|
||||
self.mem[offset as usize + i] = byte;
|
||||
}
|
||||
},
|
||||
}
|
||||
ihex::Record::StartLinearAddress(_) => todo!(),
|
||||
_ => unimplemented!(),
|
||||
};
|
||||
@ -367,357 +378,364 @@ impl eframe::App for AltairEmulator {
|
||||
});
|
||||
});
|
||||
egui::CentralPanel::default().show(ctx, |ui| {
|
||||
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;
|
||||
for (i, switch) in SWITCHES.iter().enumerate() {
|
||||
let pos = switch.pos + fp_rect.left_top().to_vec2();
|
||||
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,
|
||||
}
|
||||
}
|
||||
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 (_, 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 sw_texts = switch::Textures::new(
|
||||
self.textures.sw_up.clone(),
|
||||
self.textures.sw_neut.clone(),
|
||||
self.textures.sw_down.clone(),
|
||||
);
|
||||
ui.add(switch::Switch::new(&mut self.dep, &sw_texts));
|
||||
});
|
||||
|
||||
let old_fan_enabled = self.options.fan_enabled;
|
||||
if let Some(option_window) = self.option_window.as_mut() {
|
||||
if option_window.draw(ctx, &mut self.options) {
|
||||
|
Loading…
Reference in New Issue
Block a user