#![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> { 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, state_sender: Sender, rpc_client: Option>, ) { 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, state_reciever: Receiver, ) -> 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 }