Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 29 additions & 0 deletions crates/volamos-core/src/dispatch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2361,6 +2361,12 @@ impl<C: Cpu + 'static> Runtime<C> {
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
Expand Down Expand Up @@ -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());
Expand Down
17 changes: 17 additions & 0 deletions crates/volamos-core/src/exectask.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
/// `<dos/dosextens.h>`: "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 `<dos/dosextens.h>` -- `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,
Expand Down
Loading