From 7008d6f38d9fcfa3fc0cd302746c26f235e47a1f Mon Sep 17 00:00:00 2001 From: gram Date: Wed, 20 May 2026 17:44:08 +0200 Subject: [PATCH 1/2] copy-paste emulator args from emulator --- Cargo.toml | 2 +- src/args.rs | 48 ++++++++++++++++++++++++++++++++++++++-- src/commands/emulator.rs | 45 ++++++++++++++++++++++++++++++++++++- 3 files changed, 91 insertions(+), 4 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 4a18c91..d2b8c5b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,7 +7,7 @@ authors = ["Firefly Zero team"] description = "CLI tool for working with Firefly Zero" homepage = "https://fireflyzero.com/" repository = "https://github.com/firefly-zero/firefly-cli" -license = "MIT" +license = "GPL-3.0" keywords = ["gamedev", "firefly-zero", "cli"] categories = [ "command-line-utilities", diff --git a/src/args.rs b/src/args.rs index f92e3be..558b9dd 100644 --- a/src/args.rs +++ b/src/args.rs @@ -216,8 +216,52 @@ pub struct EmulatorArgs { #[arg(long, default_value_t = false)] pub update: bool, - /// Arguments to pass into the emulator. - pub args: Vec, + /// The scale for the window and each pixel. + /// + /// Must be a power of 2: 1, 2, 4, 8, 16, or 32. + #[arg(long, default_value = None)] + pub scale: Option, + + /// Run the emulator in borderless mode and scale to fit the screen. + /// + /// If specified, "--scale" has no effect. + #[arg(long, default_value_t = false)] + pub fullscreen: bool, + + /// The full ID of the app to run. + /// + /// If not specified, will start launcher (if installed) or the latest installed app. + #[arg(long, default_value = None)] + pub id: Option, + + /// The TCP IP address where to listen for serial events. + #[arg(long, default_value = None)] + pub tcp_ip: Option, + + /// The UDP IP address where to listen for netplay events. + #[arg(long, default_value = None)] + pub udp_ip: Option, + + /// The UDP IP addresses where to send netplay advertisements. + #[arg(long, default_value = None)] + pub peers: Option, + + /// Path to the virtual FS to use. + /// + /// By default, the global one (~/.local/share/firefly) is used. + #[arg(long, default_value = None)] + pub vfs: Option, + + /// If provided, the path where to save the audio output (as a WAV file). + #[arg(long, default_value = None)] + pub wav: Option, + + /// Disable reading input from keyboard. + /// + /// Useful if you have troubles with keyboard (like a stuck key) + /// and just want to use gamepad as input. + #[arg(long, default_value_t = false)] + pub no_keyboard: bool, } #[derive(Debug, Parser)] diff --git a/src/commands/emulator.rs b/src/commands/emulator.rs index 9313414..844ffcb 100644 --- a/src/commands/emulator.rs +++ b/src/commands/emulator.rs @@ -20,11 +20,54 @@ pub fn cmd_emulator(vfs: &Path, args: &EmulatorArgs) -> Result<()> { download_emulator(&bin_path).context("download emulator")?; } println!("⌛ running..."); - let exit_status = Command::new(bin_path).args(&args.args).status()?; + let exit_status = Command::new(bin_path).args(format_args(args)).status()?; check_exit_status(exit_status).context("run emulator")?; Ok(()) } +fn format_args(args: &EmulatorArgs) -> Vec<&str> { + let mut res = Vec::new(); + if args.update { + res.push("--update"); + } + if args.fullscreen { + res.push("--fullscreen"); + } + if args.no_keyboard { + res.push("--no_keyboard"); + } + + if let Some(val) = &args.scale { + res.push("--scale"); + res.push(val); + } + if let Some(val) = &args.id { + res.push("--id"); + res.push(val); + } + if let Some(val) = &args.tcp_ip { + res.push("--tcp_ip"); + res.push(val); + } + if let Some(val) = &args.udp_ip { + res.push("--udp_ip"); + res.push(val); + } + if let Some(val) = &args.peers { + res.push("--peers"); + res.push(val); + } + if let Some(val) = &args.vfs { + res.push("--vfs"); + res.push(val); + } + if let Some(val) = &args.wav { + res.push("--wav"); + res.push(val); + } + res +} + fn download_emulator(bin_path: &Path) -> Result<()> { // Send HTTP request. let url = get_release_url(); From 92eebe8a6a6953dfb2535c5651c4ad4acd0049fe Mon Sep 17 00:00:00 2001 From: gram Date: Wed, 20 May 2026 18:10:24 +0200 Subject: [PATCH 2/2] add run subcommand --- src/args.rs | 9 ++++----- src/cli.rs | 1 + src/commands/mod.rs | 2 ++ src/commands/run.rs | 27 +++++++++++++++++++++++++++ 4 files changed, 34 insertions(+), 5 deletions(-) create mode 100644 src/commands/run.rs diff --git a/src/args.rs b/src/args.rs index 558b9dd..d845ab2 100644 --- a/src/args.rs +++ b/src/args.rs @@ -19,6 +19,9 @@ pub enum Commands { #[clap(hide = true)] Postinstall(PostinstallArgs), + /// Build the project, run it in emulator, and export the ROM. + Run(BuildArgs), + /// Build the project and install it locally (into VFS). Build(BuildArgs), @@ -130,10 +133,6 @@ pub struct BuildArgs { #[arg(default_value = ".")] pub root: PathBuf, - /// Path to the directory where to store roms - #[arg(short, long, default_value = None)] - pub roms: Option, - /// Path to the firefly config. #[arg(short, long, default_value = None)] pub config: Option, @@ -210,7 +209,7 @@ pub struct NewArgs { pub lang: String, } -#[derive(Debug, Parser)] +#[derive(Debug, Parser, Default)] pub struct EmulatorArgs { /// Download the latest emulator release. #[arg(long, default_value_t = false)] diff --git a/src/cli.rs b/src/cli.rs index 2195f22..7b3021d 100644 --- a/src/cli.rs +++ b/src/cli.rs @@ -17,6 +17,7 @@ pub fn run_command(vfs: PathBuf, command: &Commands) -> anyhow::Result<()> { Boards(args) => cmd_boards(&vfs, args), Inspect(args) => cmd_inspect(&vfs, args), Repl(args) => cmd_repl(&vfs, args), + Run(args) => cmd_run(&vfs, args), Shots(ShotsCommands::Download(args)) => cmd_shots_download(&vfs, args), Catalog(command) => match command { CatalogCommands::List(args) => cmd_catalog_list(args), diff --git a/src/commands/mod.rs b/src/commands/mod.rs index 2bffbfa..945e28f 100644 --- a/src/commands/mod.rs +++ b/src/commands/mod.rs @@ -12,6 +12,7 @@ mod monitor; mod new; mod postinstall; mod repl; +mod run; mod runtime; mod shots; mod test; @@ -31,6 +32,7 @@ pub use monitor::cmd_monitor; pub use new::cmd_new; pub use postinstall::cmd_postinstall; pub use repl::cmd_repl; +pub use run::cmd_run; pub use runtime::{cmd_exit, cmd_id, cmd_launch, cmd_restart, cmd_screenshot}; pub use shots::cmd_shots_download; pub use test::cmd_test; diff --git a/src/commands/run.rs b/src/commands/run.rs new file mode 100644 index 0000000..9f9b46d --- /dev/null +++ b/src/commands/run.rs @@ -0,0 +1,27 @@ +use crate::args::{BuildArgs, EmulatorArgs, ExportArgs}; +use crate::commands::{cmd_build, cmd_emulator, cmd_export}; +use crate::config::Config; +use anyhow::{Context, Result}; +use std::path::Path; + +pub fn cmd_run(vfs: &Path, build_args: &BuildArgs) -> Result<()> { + let config = + Config::load(vfs.to_path_buf(), &build_args.root).context("load project config")?; + let id = format!("{}.{}", config.author_id, config.app_id); + + cmd_build(vfs.to_path_buf(), build_args).context("build")?; + + let emulator_args = EmulatorArgs { + id: Some(id.clone()), + ..Default::default() + }; + cmd_emulator(vfs, &emulator_args).context("emulator")?; + + let export_args = ExportArgs { + root: build_args.root.clone(), + id: Some(id), + output: None, + }; + cmd_export(vfs, &export_args).context("export")?; + Ok(()) +}