editor works

This commit is contained in:
2025-06-15 21:21:02 +01:00
parent 5d1ea86cdd
commit 277f210b3e
8 changed files with 641 additions and 80 deletions
Generated
+284 -41
View File
@@ -35,7 +35,7 @@ dependencies = [
"atspi-common",
"serde",
"thiserror 1.0.69",
"zvariant",
"zvariant 4.2.0",
]
[[package]]
@@ -78,7 +78,7 @@ dependencies = [
"futures-lite",
"futures-util",
"serde",
"zbus",
"zbus 4.4.0",
]
[[package]]
@@ -212,6 +212,25 @@ dependencies = [
"libloading",
]
[[package]]
name = "ashpd"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6cbdf310d77fd3aaee6ea2093db7011dc2d35d2eb3481e5607f1f8d942ed99df"
dependencies = [
"async-fs",
"async-net",
"enumflags2",
"futures-channel",
"futures-util",
"rand 0.9.1",
"raw-window-handle",
"serde",
"serde_repr",
"url",
"zbus 5.7.1",
]
[[package]]
name = "async-broadcast"
version = "0.7.2"
@@ -291,6 +310,17 @@ dependencies = [
"pin-project-lite",
]
[[package]]
name = "async-net"
version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b948000fad4873c1c9339d60f2623323a0cfd3816e5181033c6a5cb68b2accf7"
dependencies = [
"async-io",
"blocking",
"futures-lite",
]
[[package]]
name = "async-process"
version = "2.3.1"
@@ -382,11 +412,11 @@ dependencies = [
"enumflags2",
"serde",
"static_assertions",
"zbus",
"zbus 4.4.0",
"zbus-lockstep",
"zbus-lockstep-macros",
"zbus_names",
"zvariant",
"zbus_names 3.0.0",
"zvariant 4.2.0",
]
[[package]]
@@ -398,7 +428,7 @@ dependencies = [
"atspi-common",
"atspi-proxies",
"futures-lite",
"zbus",
"zbus 4.4.0",
]
[[package]]
@@ -409,8 +439,8 @@ checksum = "a5e6c5de3e524cf967569722446bcd458d5032348554d9a17d7d72b041ab7496"
dependencies = [
"atspi-common",
"serde",
"zbus",
"zvariant",
"zbus 4.4.0",
"zvariant 4.2.0",
]
[[package]]
@@ -473,6 +503,15 @@ dependencies = [
"objc2 0.5.2",
]
[[package]]
name = "block2"
version = "0.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "340d2f0bdb2a43c1d3cd40513185b2bd7def0aa1052f956455114bc98f82dcf2"
dependencies = [
"objc2 0.6.1",
]
[[package]]
name = "blocking"
version = "1.6.1"
@@ -722,6 +761,7 @@ version = "0.1.0"
dependencies = [
"eframe",
"egui",
"rfd",
]
[[package]]
@@ -740,6 +780,18 @@ version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bd0c93bb4b0c6d9b77f4435b0ae98c24d17f1c45b2ff844c6151a07256ca923b"
[[package]]
name = "dispatch2"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1a0d569e003ff27784e0e14e4a594048698e0c0f0b66cabcb51511be55a7caa0"
dependencies = [
"bitflags 2.9.1",
"block2 0.6.1",
"libc",
"objc2 0.6.1",
]
[[package]]
name = "dispatch2"
version = "0.3.0"
@@ -1081,6 +1133,15 @@ dependencies = [
"percent-encoding",
]
[[package]]
name = "futures-channel"
version = "0.3.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10"
dependencies = [
"futures-core",
]
[[package]]
name = "futures-core"
version = "0.3.31"
@@ -1221,7 +1282,7 @@ dependencies = [
"bitflags 2.9.1",
"cfg_aliases",
"cgl",
"dispatch2",
"dispatch2 0.3.0",
"glutin_egl_sys",
"glutin_glx_sys",
"glutin_wgl_sys",
@@ -1753,6 +1814,19 @@ dependencies = [
"memoffset",
]
[[package]]
name = "nix"
version = "0.30.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "74523f3a35e05aba87a1d978330aef40f67b0304ac79c1c00b294c9830543db6"
dependencies = [
"bitflags 2.9.1",
"cfg-if",
"cfg_aliases",
"libc",
"memoffset",
]
[[package]]
name = "nohash-hasher"
version = "0.2.0"
@@ -1830,7 +1904,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e4e89ad9e3d7d297152b17d39ed92cd50ca8063a89a9fa569046d41568891eff"
dependencies = [
"bitflags 2.9.1",
"block2",
"block2 0.5.1",
"libc",
"objc2 0.5.2",
"objc2-core-data",
@@ -1846,6 +1920,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e6f29f568bec459b0ddff777cec4fe3fd8666d82d5a40ebd0ff7e66134f89bcc"
dependencies = [
"bitflags 2.9.1",
"block2 0.6.1",
"objc2 0.6.1",
"objc2-core-foundation",
"objc2-core-graphics",
@@ -1859,7 +1934,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "74dd3b56391c7a0596a295029734d3c1c5e7e510a4cb30245f8221ccea96b009"
dependencies = [
"bitflags 2.9.1",
"block2",
"block2 0.5.1",
"objc2 0.5.2",
"objc2-core-location",
"objc2-foundation 0.2.2",
@@ -1871,7 +1946,7 @@ version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a5ff520e9c33812fd374d8deecef01d4a840e7b41862d849513de77e44aa4889"
dependencies = [
"block2",
"block2 0.5.1",
"objc2 0.5.2",
"objc2-foundation 0.2.2",
]
@@ -1883,7 +1958,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "617fbf49e071c178c0b24c080767db52958f716d9eabdf0890523aeae54773ef"
dependencies = [
"bitflags 2.9.1",
"block2",
"block2 0.5.1",
"objc2 0.5.2",
"objc2-foundation 0.2.2",
]
@@ -1895,7 +1970,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1c10c2894a6fed806ade6027bcd50662746363a9589d3ec9d9bef30a4e4bc166"
dependencies = [
"bitflags 2.9.1",
"dispatch2",
"dispatch2 0.3.0",
"objc2 0.6.1",
]
@@ -1906,7 +1981,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "989c6c68c13021b5c2d6b71456ebb0f9dc78d752e86a98da7c716f4f9470f5a4"
dependencies = [
"bitflags 2.9.1",
"dispatch2",
"dispatch2 0.3.0",
"objc2 0.6.1",
"objc2-core-foundation",
"objc2-io-surface",
@@ -1918,7 +1993,7 @@ version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "55260963a527c99f1819c4f8e3b47fe04f9650694ef348ffd2227e8196d34c80"
dependencies = [
"block2",
"block2 0.5.1",
"objc2 0.5.2",
"objc2-foundation 0.2.2",
"objc2-metal",
@@ -1930,7 +2005,7 @@ version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "000cfee34e683244f284252ee206a27953279d370e309649dc3ee317b37e5781"
dependencies = [
"block2",
"block2 0.5.1",
"objc2 0.5.2",
"objc2-contacts",
"objc2-foundation 0.2.2",
@@ -1949,7 +2024,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0ee638a5da3799329310ad4cfa62fbf045d5f56e3ef5ba4149e7452dcf89d5a8"
dependencies = [
"bitflags 2.9.1",
"block2",
"block2 0.5.1",
"dispatch",
"libc",
"objc2 0.5.2",
@@ -1983,7 +2058,7 @@ version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a1a1ae721c5e35be65f01a03b6d2ac13a54cb4fa70d8a5da293d7b0020261398"
dependencies = [
"block2",
"block2 0.5.1",
"objc2 0.5.2",
"objc2-app-kit 0.2.2",
"objc2-foundation 0.2.2",
@@ -1996,7 +2071,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dd0cba1276f6023976a406a14ffa85e1fdd19df6b0f737b063b95f6c8c7aadd6"
dependencies = [
"bitflags 2.9.1",
"block2",
"block2 0.5.1",
"objc2 0.5.2",
"objc2-foundation 0.2.2",
]
@@ -2008,7 +2083,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e42bee7bff906b14b167da2bac5efe6b6a07e6f7c0a21a7308d40c960242dc7a"
dependencies = [
"bitflags 2.9.1",
"block2",
"block2 0.5.1",
"objc2 0.5.2",
"objc2-foundation 0.2.2",
"objc2-metal",
@@ -2031,7 +2106,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b8bb46798b20cd6b91cbd113524c490f1686f4c4e8f49502431415f3512e2b6f"
dependencies = [
"bitflags 2.9.1",
"block2",
"block2 0.5.1",
"objc2 0.5.2",
"objc2-cloud-kit",
"objc2-core-data",
@@ -2051,7 +2126,7 @@ version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "44fa5f9748dbfe1ca6c0b79ad20725a11eca7c2218bceb4b005cb1be26273bfe"
dependencies = [
"block2",
"block2 0.5.1",
"objc2 0.5.2",
"objc2-foundation 0.2.2",
]
@@ -2063,7 +2138,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "76cfcbf642358e8689af64cee815d139339f3ed8ad05103ed5eaf73db8d84cb3"
dependencies = [
"bitflags 2.9.1",
"block2",
"block2 0.5.1",
"objc2 0.5.2",
"objc2-core-location",
"objc2-foundation 0.2.2",
@@ -2230,6 +2305,12 @@ dependencies = [
"windows-sys 0.59.0",
]
[[package]]
name = "pollster"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2f3a9f18d041e6d0e102a0a46750538147e5e8992d3b4873aaafee2520b00ce3"
[[package]]
name = "potential_utf"
version = "0.1.2"
@@ -2313,8 +2394,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
dependencies = [
"libc",
"rand_chacha",
"rand_core",
"rand_chacha 0.3.1",
"rand_core 0.6.4",
]
[[package]]
name = "rand"
version = "0.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9fbfd9d094a40bf3ae768db9361049ace4c0e04a4fd6b359518bd7b73a73dd97"
dependencies = [
"rand_chacha 0.9.0",
"rand_core 0.9.3",
]
[[package]]
@@ -2324,7 +2415,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
dependencies = [
"ppv-lite86",
"rand_core",
"rand_core 0.6.4",
]
[[package]]
name = "rand_chacha"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb"
dependencies = [
"ppv-lite86",
"rand_core 0.9.3",
]
[[package]]
@@ -2336,6 +2437,15 @@ dependencies = [
"getrandom 0.2.16",
]
[[package]]
name = "rand_core"
version = "0.9.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38"
dependencies = [
"getrandom 0.3.3",
]
[[package]]
name = "raw-window-handle"
version = "0.6.2"
@@ -2366,6 +2476,30 @@ version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "19b30a45b0cd0bcca8037f3d0dc3421eaf95327a17cad11964fb8179b4fc4832"
[[package]]
name = "rfd"
version = "0.15.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "80c844748fdc82aae252ee4594a89b6e7ebef1063de7951545564cbc4e57075d"
dependencies = [
"ashpd",
"block2 0.6.1",
"dispatch2 0.2.0",
"js-sys",
"log",
"objc2 0.6.1",
"objc2-app-kit 0.3.1",
"objc2-core-foundation",
"objc2-foundation 0.3.1",
"pollster",
"raw-window-handle",
"urlencoding",
"wasm-bindgen",
"wasm-bindgen-futures",
"web-sys",
"windows-sys 0.59.0",
]
[[package]]
name = "rustc-hash"
version = "1.1.0"
@@ -2868,8 +3002,15 @@ dependencies = [
"form_urlencoded",
"idna",
"percent-encoding",
"serde",
]
[[package]]
name = "urlencoding"
version = "2.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "daf8dba3b7eb870caf1ddeed7bc9d2a049f3cfdfae7cb521b087cc33ae4c49da"
[[package]]
name = "utf8_iter"
version = "1.0.4"
@@ -3606,7 +3747,7 @@ dependencies = [
"android-activity",
"atomic-waker",
"bitflags 2.9.1",
"block2",
"block2 0.5.1",
"bytemuck",
"calloop",
"cfg_aliases",
@@ -3791,9 +3932,9 @@ dependencies = [
"futures-sink",
"futures-util",
"hex",
"nix",
"nix 0.29.0",
"ordered-stream",
"rand",
"rand 0.8.5",
"serde",
"serde_repr",
"sha1",
@@ -3802,9 +3943,42 @@ dependencies = [
"uds_windows",
"windows-sys 0.52.0",
"xdg-home",
"zbus_macros",
"zbus_names",
"zvariant",
"zbus_macros 4.4.0",
"zbus_names 3.0.0",
"zvariant 4.2.0",
]
[[package]]
name = "zbus"
version = "5.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d3a7c7cee313d044fca3f48fa782cb750c79e4ca76ba7bc7718cd4024cdf6f68"
dependencies = [
"async-broadcast",
"async-executor",
"async-io",
"async-lock",
"async-process",
"async-recursion",
"async-task",
"async-trait",
"blocking",
"enumflags2",
"event-listener",
"futures-core",
"futures-lite",
"hex",
"nix 0.30.1",
"ordered-stream",
"serde",
"serde_repr",
"tracing",
"uds_windows",
"windows-sys 0.59.0",
"winnow",
"zbus_macros 5.7.1",
"zbus_names 4.2.0",
"zvariant 5.5.3",
]
[[package]]
@@ -3814,7 +3988,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4ca2c5dceb099bddaade154055c926bb8ae507a18756ba1d8963fd7b51d8ed1d"
dependencies = [
"zbus_xml",
"zvariant",
"zvariant 4.2.0",
]
[[package]]
@@ -3828,7 +4002,7 @@ dependencies = [
"syn",
"zbus-lockstep",
"zbus_xml",
"zvariant",
"zvariant 4.2.0",
]
[[package]]
@@ -3841,7 +4015,22 @@ dependencies = [
"proc-macro2",
"quote",
"syn",
"zvariant_utils",
"zvariant_utils 2.1.0",
]
[[package]]
name = "zbus_macros"
version = "5.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a17e7e5eec1550f747e71a058df81a9a83813ba0f6a95f39c4e218bdc7ba366a"
dependencies = [
"proc-macro-crate",
"proc-macro2",
"quote",
"syn",
"zbus_names 4.2.0",
"zvariant 5.5.3",
"zvariant_utils 3.2.0",
]
[[package]]
@@ -3852,7 +4041,19 @@ checksum = "4b9b1fef7d021261cc16cba64c351d291b715febe0fa10dc3a443ac5a5022e6c"
dependencies = [
"serde",
"static_assertions",
"zvariant",
"zvariant 4.2.0",
]
[[package]]
name = "zbus_names"
version = "4.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7be68e64bf6ce8db94f63e72f0c7eb9a60d733f7e0499e628dfab0f84d6bcb97"
dependencies = [
"serde",
"static_assertions",
"winnow",
"zvariant 5.5.3",
]
[[package]]
@@ -3864,8 +4065,8 @@ dependencies = [
"quick-xml 0.30.0",
"serde",
"static_assertions",
"zbus_names",
"zvariant",
"zbus_names 3.0.0",
"zvariant 4.2.0",
]
[[package]]
@@ -3952,7 +4153,22 @@ dependencies = [
"enumflags2",
"serde",
"static_assertions",
"zvariant_derive",
"zvariant_derive 4.2.0",
]
[[package]]
name = "zvariant"
version = "5.5.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9d30786f75e393ee63a21de4f9074d4c038d52c5b1bb4471f955db249f9dffb1"
dependencies = [
"endi",
"enumflags2",
"serde",
"url",
"winnow",
"zvariant_derive 5.5.3",
"zvariant_utils 3.2.0",
]
[[package]]
@@ -3965,7 +4181,20 @@ dependencies = [
"proc-macro2",
"quote",
"syn",
"zvariant_utils",
"zvariant_utils 2.1.0",
]
[[package]]
name = "zvariant_derive"
version = "5.5.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "75fda702cd42d735ccd48117b1630432219c0e9616bf6cb0f8350844ee4d9580"
dependencies = [
"proc-macro-crate",
"proc-macro2",
"quote",
"syn",
"zvariant_utils 3.2.0",
]
[[package]]
@@ -3978,3 +4207,17 @@ dependencies = [
"quote",
"syn",
]
[[package]]
name = "zvariant_utils"
version = "3.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e16edfee43e5d7b553b77872d99bc36afdda75c223ca7ad5e3fbecd82ca5fc34"
dependencies = [
"proc-macro2",
"quote",
"serde",
"static_assertions",
"syn",
"winnow",
]
+1
View File
@@ -10,3 +10,4 @@ path = "src/lib.rs"
[dependencies]
eframe = "0.31.1"
egui = "0.31.1"
rfd = "0.15.3"
+17 -30
View File
@@ -15,33 +15,20 @@ use crate::{
},
};
pub fn run_emulator(cmd_rx: &Receiver<Command>, state_tx: &Sender<State>, cpu: Processor) {
pub fn run_emulator(
cmd_rx: &Receiver<Command>,
state_tx: &Sender<State>,
mut processor: Processor,
) {
println!("starting");
let mut running = Running::Paused;
let mut addr = 0u32;
let size = 256;
// Send initial state.
// let Ok(mut cpu_lock) = cpu.lock() else {
// panic!("Failed to lock CPU.")
// };
let mut cpu_lock = cpu;
cpu_lock.get_stack(32);
println!("got stack");
cpu_lock.display();
println!("got display");
let memory_view = cpu_lock.memory.read_range(addr, size);
println!("got view");
let initial_state = state(&mut cpu_lock, running, 0, memory_view);
println!("got state");
let memory_view = processor.memory.read_range(addr, size);
let initial_state = state(&mut processor, running, 0, memory_view);
let _ = state_tx.send(initial_state);
println!("sent state");
let mut instruction_count = 0;
@@ -75,7 +62,7 @@ pub fn run_emulator(cmd_rx: &Receiver<Command>, state_tx: &Sender<State>, cpu: P
}
Command::Reset => {
running = Running::Paused;
cpu_lock.reset();
processor.reset();
instruction_count = 0;
println!("Emulator rebooted");
}
@@ -83,10 +70,10 @@ pub fn run_emulator(cmd_rx: &Receiver<Command>, state_tx: &Sender<State>, cpu: P
running = Running::Paused;
// Execute one cycle.
match cpu_lock.cycle() {
match processor.cycle() {
Ok(_) => {}
Err(why) => {
let pcx = cpu_lock.get(Register::Pcx);
let pcx = processor.get(Register::Pcx);
eprintln!("Could not decode instruction at {pcx:x}. Reason: {why}");
continue;
}
@@ -100,7 +87,7 @@ pub fn run_emulator(cmd_rx: &Receiver<Command>, state_tx: &Sender<State>, cpu: P
println!("Memory view for address 0x{addr:08x}");
}
Command::Write(offset, data) => {
cpu_lock.memory.write_range(offset, data);
processor.memory.write_range(offset, data);
println!("Program loaded");
}
Command::Interrupt(_interrupt) => {
@@ -108,8 +95,8 @@ pub fn run_emulator(cmd_rx: &Receiver<Command>, state_tx: &Sender<State>, cpu: P
}
}
let memory_view = cpu_lock.memory.read_range(addr, size);
let state = state(&mut cpu_lock, running, instruction_count, memory_view);
let memory_view = processor.memory.read_range(addr, size);
let state = state(&mut processor, running, instruction_count, memory_view);
let _ = state_tx.send(state);
}
@@ -118,10 +105,10 @@ pub fn run_emulator(cmd_rx: &Receiver<Command>, state_tx: &Sender<State>, cpu: P
let mut update = false;
// Execute one cycle.
let instruction = match cpu_lock.cycle() {
let instruction = match processor.cycle() {
Ok(instruction) => instruction,
Err(why) => {
let pcx = cpu_lock.get(Register::Pcx);
let pcx = processor.get(Register::Pcx);
eprintln!("Could not decode instruction at {pcx:x}. Reason: {why}");
continue;
}
@@ -142,8 +129,8 @@ pub fn run_emulator(cmd_rx: &Receiver<Command>, state_tx: &Sender<State>, cpu: P
}
if update {
let memory_view = cpu_lock.memory.read_range(addr, size);
let state = state(&mut cpu_lock, running, instruction_count, memory_view);
let memory_view = processor.memory.read_range(addr, size);
let state = state(&mut processor, running, instruction_count, memory_view);
let _ = state_tx.send(state);
}
} else {
+6 -2
View File
@@ -104,7 +104,11 @@ impl MemoryUnit for MainStore {
block.data[(offset + 3) as usize] = value as u8;
}
fn write_range(&mut self, _addr: u32, _value: Vec<u8>) {
todo!("We might need this for DMA.");
fn write_range(&mut self, addr: u32, value: Vec<u8>) {
for byte in value {
let (block_addr, offset) = Self::segment_addr(addr);
let block = self.mut_block(block_addr);
block.data[offset as usize] = byte;
}
}
}
-1
View File
@@ -23,7 +23,6 @@ impl Processor {
#[must_use]
pub fn new(memory: Box<dyn MemoryUnit>, io_devices: Vec<Arc<dyn IODevice>>) -> Self {
Self {
// io_devices,
memory,
registers: RegFile::default(),
halted: false,
+326
View File
@@ -0,0 +1,326 @@
use std::sync::mpsc::Sender;
use egui::{Align, Context, Layout, Ui};
use rfd::FileDialog;
use crate::emulator::{
system::model::{Command, State},
ui::interface::Component,
};
pub struct Editor {
filename: String,
text: String,
output: Vec<u8>,
sender: Sender<Command>,
cursor_col: usize,
cursor_line: usize,
visible: bool,
load_offset: u32,
offset_str: String,
error: Option<String>,
}
impl Component for Editor {
fn name(&self) -> &'static str {
"Editor"
}
fn visible(&mut self) -> &mut bool {
&mut self.visible
}
fn category(&self) -> super::interface::Category {
super::interface::Category::Programming
}
fn render(&mut self, state: &mut State, ui: &mut Ui, ctx: &Context) {
ui.vertical(|ui| {
// Top bar
self.render_toolbar(state, ui, ctx);
ui.add_space(4.0); // Add some spacing instead of just a separator
ui.separator();
let remaining_height = f32::max(ui.available_height() - 100.0, 100.0);
ui.allocate_ui_with_layout(
egui::Vec2::new(ui.available_width(), remaining_height),
Layout::left_to_right(Align::Min),
|ui| {
self.render_editor(state, ui, ctx);
ui.separator();
self.render_output(state, ui, ctx);
},
);
ui.label(format!("Ln {}, Col {}", self.cursor_line, self.cursor_col));
});
}
}
impl Editor {
pub fn new(sender: Sender<Command>) -> Self {
Self {
filename: String::new(),
text: String::new(),
output: Vec::new(),
sender,
cursor_col: 1,
cursor_line: 1,
visible: false,
load_offset: 0,
offset_str: String::new(),
error: None,
}
}
fn render_output(&mut self, _state: &mut State, ui: &mut Ui, _ctx: &Context) {
// Output area with synchronized scrolling
egui::ScrollArea::vertical()
.id_salt("output_scroll")
.max_width(300.0)
.show(ui, |ui| {
if self.output.is_empty() {
ui.label(
egui::RichText::new("No output data")
.font(egui::FontId::monospace(12.0))
.color(egui::Color32::GRAY),
);
return;
}
egui::Grid::new("output_grid")
.num_columns(4)
.spacing([20.0, 2.0]) // Horizontal and vertical spacing
.striped(false)
.show(ui, |ui| {
// Process bytes in chunks of 4
for (line_num, chunk) in self.output.chunks(4).enumerate() {
let address = line_num * 4;
// Convert chunk to u32 (little-endian)
let mut bytes = [0u8; 4];
for (i, &byte) in chunk.iter().enumerate() {
if i < 4 {
bytes[i] = byte;
}
}
let value = u32::from_le_bytes(bytes);
// Address column
ui.with_layout(
egui::Layout::left_to_right(egui::Align::Center),
|ui| {
ui.set_min_width(80.0);
let style = ui.style_mut();
style.visuals.widgets.inactive.bg_fill =
egui::Color32::from_gray(30);
ui.label(
egui::RichText::new(format!("0x{:04X}", address))
.font(egui::FontId::monospace(12.0)),
);
},
);
// Individual bytes column
let byte_str = chunk
.iter()
.map(|b| format!("{:02X}", b))
.collect::<Vec<_>>()
.join(" ");
ui.label(
egui::RichText::new(format!("{:<11}", byte_str))
.font(egui::FontId::monospace(12.0))
.color(egui::Color32::from_rgb(200, 200, 255)),
);
// Hex column
ui.label(
egui::RichText::new(format!("0x{:08X}", value))
.font(egui::FontId::monospace(12.0))
.color(egui::Color32::from_rgb(255, 200, 200)),
);
// Decimal column
ui.label(
egui::RichText::new(format!("{:10}", value))
.font(egui::FontId::monospace(12.0))
.color(egui::Color32::from_rgb(200, 255, 200)),
);
ui.end_row();
}
});
});
}
fn render_editor(&mut self, _state: &mut State, ui: &mut Ui, _ctx: &Context) {
let available_width = ui.available_width();
// Main editor area with synchronized scrolling
egui::ScrollArea::vertical()
.max_width(available_width - 400.0)
.id_salt("editor_scroll")
.show(ui, |ui| {
ui.horizontal(|ui| {
// Line numbers column
let line_count = self.text.lines().count();
ui.vertical(|ui| {
ui.set_width(50.0);
ui.style_mut().visuals.widgets.inactive.bg_fill =
egui::Color32::from_gray(30);
// Calculate line height to match text editor
let line_height = ui.text_style_height(&egui::TextStyle::Monospace);
for line_num in 1..=line_count {
let line_response = ui.allocate_response(
egui::vec2(50.0, line_height),
egui::Sense::hover(),
);
ui.painter().text(
line_response.rect.left_center() + egui::vec2(5.0, 0.0),
egui::Align2::LEFT_CENTER,
format!("{:3}", line_num),
egui::FontId::monospace(12.0),
ui.style().visuals.text_color(),
);
}
});
ui.separator();
// Text editor area
ui.vertical(|ui| {
let available_size = ui.available_size();
let response = ui.add_sized(
available_size,
egui::TextEdit::multiline(&mut self.text)
.font(egui::TextStyle::Monospace)
.margin(egui::vec2(5.0, 0.0))
.code_editor(),
);
// Update cursor position when text changes
if response.changed() {
// Simple but functional cursor tracking
let lines = self.text.lines().collect::<Vec<_>>();
self.cursor_line = lines.len().max(1);
// Get the length of the last line for column position
if let Some(last_line) = lines.last() {
self.cursor_col = last_line.chars().count() + 1;
} else {
self.cursor_col = 1;
}
}
});
});
});
}
fn render_toolbar(&mut self, _state: &mut State, ui: &mut Ui, _ctx: &Context) {
ui.horizontal(|ui| {
// current filename
ui.label(format!("File: {}", self.filename));
// error display
ui.label(
egui::RichText::new(self.error.clone().unwrap_or("".to_string()))
.color(egui::Color32::RED),
);
// number of lines in the file
ui.with_layout(egui::Layout::right_to_left(egui::Align::Center), |ui| {
let line_count = self.text.lines().count();
ui.label(format!("Lines: {}", line_count));
});
});
ui.horizontal(|ui| {
ui.spacing_mut().button_padding = egui::vec2(8.0, 4.0);
ui.spacing_mut().item_spacing.x = 6.0;
// Opens a file
if ui.button("Open").clicked() {
if let Some(path) = FileDialog::new()
.add_filter("dsafiles", &["dsa", "dsb", "dsc", "dsd"])
.add_filter("all", &["*"])
.set_directory(std::env::current_dir().unwrap())
.pick_file()
{
if let Ok(content) = std::fs::read_to_string(&path) {
self.text = content;
self.filename = path.display().to_string();
}
}
self.output = Vec::new();
}
// Saves the current file
if ui.button("Save").clicked() {
if let Some(path) = FileDialog::new()
.add_filter("dsafiles", &["dsa", "dsb", "dsc", "dsd"])
.add_filter("all", &["*"])
.set_directory(std::env::current_dir().unwrap())
.save_file()
{
if let Err(e) = std::fs::write(&path, &self.text) {
self.error = Some(format!("Failed to save file: {}", e));
} else {
self.filename = path.display().to_string();
}
}
}
// builds the current file
if ui.button("Build").clicked() {
self.output = vec![0x00; 256];
}
// Loads the generated binary into the assembler at the provided offset
if ui.button("Load").clicked() {
if self.error.is_some() {
self.error = Some("Can't load program at invalid offset!".to_string());
}
self.sender
.send(Command::Write(self.load_offset, self.output.clone()))
.unwrap_or_else(|_| self.error = Some("Failed to send command".to_string()));
}
// Entry widget to enter a load offset
if ui.text_edit_singleline(&mut self.offset_str).changed() {
if let Some(offset) = parse_address(&self.offset_str) {
self.load_offset = offset;
self.error = None;
} else {
self.error = Some("Invalid offset".to_string());
}
}
// Resets the emulator and all attached devices
if ui.button("Reset Emulator").clicked() {
self.sender
.send(Command::Reset)
.unwrap_or_else(|_| self.error = Some("Failed to send command".to_string()));
}
});
}
}
fn parse_address(address: &str) -> Option<u32> {
if address.starts_with("0x") {
u32::from_str_radix(&address[2..], 16).ok()
} else if address.starts_with("0b") {
u32::from_str_radix(&address[2..], 2).ok()
} else if address.starts_with("0o") {
u32::from_str_radix(&address[2..], 8).ok()
} else {
address.parse::<u32>().ok()
}
}
+1
View File
@@ -1,4 +1,5 @@
pub mod control_unit;
pub mod editor;
pub mod interface;
pub mod memory_inspector;
pub mod menu;
+6 -6
View File
@@ -1,13 +1,10 @@
use std::{
sync::{Arc, Mutex},
thread,
};
use std::thread;
use dsa_rs::emulator::{
system::{emulator::run_emulator, memory::MainStore, processor::Processor},
ui::{
control_unit::ControlPanel, interface::EmulatorUI, memory_inspector::MemoryInspector,
stack_inspector::StackInspector,
control_unit::ControlPanel, editor::Editor, interface::EmulatorUI,
memory_inspector::MemoryInspector, stack_inspector::StackInspector,
},
};
@@ -36,6 +33,9 @@ fn main() -> Result<(), eframe::Error> {
let stack_inspector = StackInspector::new();
ui.add_component(Box::new(stack_inspector));
let editor = Editor::new(cmd_sender.clone());
ui.add_component(Box::new(editor));
// Run UI
let options = eframe::NativeOptions {
viewport: egui::ViewportBuilder::default().with_inner_size([800.0, 600.0]),