diff --git a/crates/volamos-core/src/dispatch.rs b/crates/volamos-core/src/dispatch.rs index 29cd45d..f8cf4f9 100644 --- a/crates/volamos-core/src/dispatch.rs +++ b/crates/volamos-core/src/dispatch.rs @@ -2361,6 +2361,12 @@ impl Runtime { cpu.set_data_register(DataRegister(0), line_len); cpu.set_pc(config.entry); + // pr_Arguments: the same command-line buffer A0/D0 just got, + // also reachable later via the process struct -- see + // `exectask::PR_ARGUMENTS_OFFSET`'s doc for why a real guest + // startup may read this instead of (or in addition to) A0/D0. + mem.write_u32(task + exectask::PR_ARGUMENTS_OFFSET, args_addr); + // ReadArgs's default source (rdargs == NULL): the same // command-line buffer just built above, per crate::dosargs's // module docs. Registers hold this too, but a guest program is @@ -3737,6 +3743,29 @@ mod tests { assert_eq!(bytes, b"COMMENT \"a whole sentence\" \n"); } + #[test] + fn pr_arguments_points_at_the_same_command_line_buffer_as_a0() { + // Found running the real `sidick/micropython` Amiga port: + // its own startup reads argv from `pr_Arguments` (the + // `struct Process` field), not from A0/D0 -- left at NULL, it + // always decided "no arguments" and fell back to its REPL + // even with a real script path passed on the command line. + // See `exectask::PR_ARGUMENTS_OFFSET`'s doc. + let rt = runtime_with_program_and_args(&[RTS], vec!["script.py".to_string()]); + let a0 = rt.cpu.address_register(AddressRegister(0)); + let pr_arguments = rt + .mem + .read_u32(rt.task + crate::exectask::PR_ARGUMENTS_OFFSET); + assert_eq!( + pr_arguments, a0, + "pr_Arguments should point at the same buffer A0 does" + ); + assert_eq!( + crate::guestmem::read_c_string(&rt.mem, pr_arguments), + b"script.py \n" + ); + } + #[test] fn empty_args_still_produce_a_bare_newline_command_line() { let rt = runtime_with_program_and_args(&[RTS], Vec::new()); diff --git a/crates/volamos-core/src/exectask.rs b/crates/volamos-core/src/exectask.rs index debcef7..ce37633 100644 --- a/crates/volamos-core/src/exectask.rs +++ b/crates/volamos-core/src/exectask.rs @@ -321,6 +321,23 @@ pub const PR_CLI_OFFSET: u32 = 172; /// called once from `crates/volamos/src/main.rs` after `set_vfs`). /// Found needed running the real SAS/C `sc` compiler (issue #17). pub const PR_HOMEDIR_OFFSET: u32 = 188; +/// `pr_Arguments`: `STRPTR`, offset 204 (`pr_HomeDir` 188 + 4, `pr_Flags` +/// 192, `pr_ExitCode` 196, `pr_ExitData` 200, `pr_Arguments` 204). Per +/// ``: "Arguments passed to the process at start". +/// This runtime already builds the exact same command-line buffer for +/// `A0`/`D0` at process entry (see `crate::dispatch::Runtime::new`) -- +/// `pr_Arguments` just needs to point at it too, since a real +/// AmigaOS process (via `RunCommand`/`CreateNewProc`) gets both: A0/D0 +/// are the entry-time convention a `crt0` reads once at startup, but +/// `pr_Arguments` is the same string surviving in the process struct +/// for any code to re-read later (e.g. after `A0`/`D0` have long since +/// been clobbered). Found running the real `sidick/micropython` +/// Amiga port (its own startup reads argv from `pr_Arguments`, not +/// A0/D0): left at 0/NULL, it always decided "no arguments" and fell +/// back to its REPL even when a script path was passed, regardless of +/// A0/D0 being correct -- confirmed by cross-checking against vamos, +/// which does set this field (`amitools`' `Process.init_args()`). +pub const PR_ARGUMENTS_OFFSET: u32 = 204; /// `sizeof(struct Process)` per `` -- `pr_CLI`'s own /// offset (172) plus every field after it (`pr_ReturnAddr`/ /// `pr_PktWait`/`pr_WindowPtr`/`pr_HomeDir` 4 each = 16, `pr_Flags` 4,