Files
damn_simple_architecture/emulator/src/lib.rs
T

133 lines
3.5 KiB
Rust

#![deny(
clippy::unwrap_used,
clippy::nursery,
clippy::perf,
clippy::pedantic,
clippy::complexity
)]
#![allow(
clippy::cast_possible_truncation,
clippy::missing_panics_doc,
clippy::missing_errors_doc,
clippy::match_wildcard_for_single_variants
)]
pub mod emulator;
use std::{
sync::{
Arc,
mpsc::{Receiver, Sender},
},
thread,
};
#[cfg(target_os = "android")]
use winit::platform::android::{EventLoopBuilderExtAndroid, activity::AndroidApp};
use crate::emulator::{
misc::rpc::RpcClient,
system::{
emulator::run_emulator,
memory::MainStore,
model::{Command, StateUpdate},
processor::Processor,
},
ui::{
control_unit::ControlPanel, display::Display, editor::Editor,
interface::EmulatorUI, memory_inspector::MemoryInspector,
stack_inspector::StackInspector,
},
};
#[cfg(target_os = "android")]
#[unsafe(no_mangle)]
pub fn android_main(app: AndroidApp) -> Result<(), Box<dyn std::error::Error>> {
use crate::emulator::{config::Config, misc::rpc::get_rpc_client_or_none};
use std::path::Path;
// Initialize channels and read in configuration.
let (cmd_sender, cmd_receiver) = std::sync::mpsc::channel();
let (state_sender, state_reciever) = std::sync::mpsc::channel();
let config = Config::load(Path::new(".dsa.emulator.toml"))?;
// Setup RPC if enabled.
let (rpc_sender, rpc_reciever) = std::sync::mpsc::channel();
let rpc_client =
get_rpc_client_or_none(&config, rpc_sender, rpc_reciever)?.map(Arc::new);
setup_emulator(cmd_receiver, state_sender, rpc_client);
let ui = setup_ui(cmd_sender, state_reciever);
// Run UI.
#[allow(unused_variables)]
let options = eframe::NativeOptions {
viewport: egui::ViewportBuilder::default().with_inner_size([800.0, 600.0]),
event_loop_builder: Some(Box::new(move |builder| {
#[cfg(target_os = "android")]
builder.with_android_app(app);
})),
..Default::default()
};
eframe::run_native(
"DSA Simulator (Damn Simple Architecture 🔥)",
options,
Box::new(move |cc| {
cc.egui_ctx.set_visuals(egui::Visuals::default());
Ok(Box::new(ui))
}),
)?;
Ok(())
}
pub fn setup_emulator(
cmd_receiver: Receiver<Command>,
state_sender: Sender<StateUpdate>,
rpc_client: Option<Arc<RpcClient>>,
) {
let main_store = MainStore::new();
let processor = Processor::new(Box::new(main_store), vec![]);
thread::spawn(move || {
run_emulator(&cmd_receiver, &state_sender, processor, rpc_client.as_ref());
});
}
/// Creates the [`EmulatorUI`].
#[must_use]
pub fn setup_ui(
cmd_sender: Sender<Command>,
state_reciever: Receiver<StateUpdate>,
) -> EmulatorUI {
let mut ui = EmulatorUI::new(cmd_sender, state_reciever);
// Create UI modules.
let control_unit = ControlPanel::new();
ui.add_component(Box::new(control_unit));
let mem_inspector = MemoryInspector::new();
ui.add_component(Box::new(mem_inspector));
let stack_inspector = StackInspector::new();
ui.add_component(Box::new(stack_inspector));
let editor = Editor::new();
ui.add_component(Box::new(editor));
let display = Display::new();
ui.add_component(Box::new(display));
let history = emulator::ui::history::History::new();
ui.add_component(Box::new(history));
let loader = emulator::ui::loader::Loader::new();
ui.add_component(Box::new(loader));
ui
}