From 50ebac34fec99c853b2f010bfd100c11b5e0a603 Mon Sep 17 00:00:00 2001 From: Miquel Sabaté Solà Date: Thu, 27 Aug 2026 07:12:42 +0200 Subject: vnf: add support for all stack instructions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This also includes brk and rti, for which we are also storing and exporting the break mark, just in case it can be useful to library users in case they want to add error codes in break marks. This commit also includes a fix for accounting the Z and N flags on transfer instructions, which couldn't easily be split into a separate commit, but it's a fairly simple change. Signed-off-by: Miquel Sabaté Solà --- tests/vnf-tests/Cargo.toml | 10 ++++ tests/vnf-tests/src/main.rs | 108 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 118 insertions(+) create mode 100644 tests/vnf-tests/Cargo.toml create mode 100644 tests/vnf-tests/src/main.rs (limited to 'tests/vnf-tests') diff --git a/tests/vnf-tests/Cargo.toml b/tests/vnf-tests/Cargo.toml new file mode 100644 index 0000000..8ad6b70 --- /dev/null +++ b/tests/vnf-tests/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "vnf-tests" +version = "0.1.0" +edition = "2024" +license.workspace = true +authors.workspace = true + +[dependencies] +vnf.workspace = true +xixanta.workspace = true diff --git a/tests/vnf-tests/src/main.rs b/tests/vnf-tests/src/main.rs new file mode 100644 index 0000000..6c62dbd --- /dev/null +++ b/tests/vnf-tests/src/main.rs @@ -0,0 +1,108 @@ +use std::path::PathBuf; + +use vnf::{Machine, MemoryPolicy}; +use xixanta::opcodes::InstructionIdentifier; + +#[derive(Default)] +struct Args { + file: String, +} + +fn print_help() { + println!("End-to-end tests for the vnf library\n"); + println!("usage: vnf-tests [OPTIONS] \n"); + println!("Options:"); + println!(" -h, --help\t\t\tPrint this message and quit."); + std::process::exit(0); +} + +// Print the given `message` and exit(1). +fn die(message: String) -> ! { + eprintln!("error: {message}"); + std::process::exit(1); +} + +fn parse_arguments() -> Args { + let mut args = std::env::args(); + let mut res = Args::default(); + + // Skip command name. + args.next(); + + for arg in args { + match arg.as_str() { + "-h" | "--help" => print_help(), + _ => { + if arg.starts_with('-') { + die(format!("don't know how to handle the '{arg}' flag")); + } + if !res.file.is_empty() { + die("cannot have multiple paths".to_string()); + } + res.file = arg; + } + } + } + + if res.file.is_empty() { + die("you have to provide a path to the tests/ directory".to_string()); + } + + res +} + +fn run_break_mark_test(path: &String) -> Result<(), String> { + let rom = PathBuf::from(path).join("out/stack.nes"); + let roms: String = rom.to_string_lossy().into_owned().to_string(); + + let mut machine = Machine::from(&roms, 0x8000, MemoryPolicy::default())?; + + // Get out of + let _ = machine.next_iteration(); + + // Assert that we are at the expected location. + assert!(matches!( + machine.current_instruction.identifier, + InstructionIdentifier::Brk + )); + + // Before vs after running 'brk'. + assert_eq!(machine.status_register.break_mark, 0); + assert!(!machine.status_register.brk); + let _ = machine.next_iteration(); + assert_eq!(machine.status_register.break_mark, 0x42); + assert!(machine.status_register.brk); + + // Skip instructions we don't care about here. + for _ in 0..11 { + let _ = machine.next_iteration(); + } + + // Before running 'plp', everything is still as expected. + assert!(matches!( + machine.current_instruction.identifier, + InstructionIdentifier::Plp + )); + assert_eq!(machine.status_register.break_mark, 0x42); + assert!(machine.status_register.brk); + + // After running 'plp'. + let _ = machine.next_iteration(); + assert_eq!(machine.status_register.break_mark, 0x00); + assert!(!machine.status_register.brk); + + Ok(()) +} + +fn main() { + let args = parse_arguments(); + let file = PathBuf::from(args.file.clone()); + + if !file.is_dir() { + die("you have to provide a path to the tests/ directory".to_string()); + } + + if let Err(e) = run_break_mark_test(&args.file) { + die(e) + } +} -- cgit v1.2.3