diff options
| author | Miquel Sabaté Solà <mssola@mssola.com> | 2026-09-07 16:38:16 +0200 |
|---|---|---|
| committer | Miquel Sabaté Solà <mssola@mssola.com> | 2026-09-07 16:38:16 +0200 |
| commit | 44f98890a6d91cd9f0b64dec743a22a6e0013590 (patch) | |
| tree | c8c7605b3115f1b7da5007bdffc031b637421a7c | |
| parent | 292f6ba2ed1d0b828ad84d4d4475f8523eef00a0 (diff) | |
| download | tools.nes-44f98890a6d91cd9f0b64dec743a22a6e0013590.tar.gz tools.nes-44f98890a6d91cd9f0b64dec743a22a6e0013590.zip | |
vnf: improve documentation
Provide documentation for the library, and improve the documentation for
some of the structs and interfaces.
Signed-off-by: Miquel Sabaté Solà <mssola@mssola.com>
| -rw-r--r-- | README.md | 12 | ||||
| -rw-r--r-- | lib/vnf/README.md | 4 | ||||
| -rw-r--r-- | lib/vnf/src/lib.rs | 58 |
3 files changed, 65 insertions, 9 deletions
@@ -30,10 +30,14 @@ information about it. Read more about it in `runrom` is an NES/Famicom emulator that doesn't attempt to run a ROM graphically. Instead, it just runs code and exposes the data on memory, -registers, etc. for a given run. Thus, `runrom` is a tool to run an NES/Famicom -programatically, so developers can use it to test their ROM files under certain -conditions. Read more about it in -[./crates/runrom/README.md](./crates/runrom/README.md). +registers, etc. for a given run. This is all done via the [vnf](./lib/vnf) +library, which allows a developer to programatically run a ROM file from a given +address, poke memory addresses, submit joypad inputs, etc. For some uses, +running `runrom` will be fine to get a glimpse of the execution of a piece of +code, but in some other cases (e.g. unit tests for a specific function on your +NES game), using `vnf` will be a better fit. In any case, you can read more +about all of this on [runrom's documentation](./crates/runrom/README.md), and on +[vnf's documentation](./lib/vnf/README.md). ## License diff --git a/lib/vnf/README.md b/lib/vnf/README.md new file mode 100644 index 0000000..8e51163 --- /dev/null +++ b/lib/vnf/README.md @@ -0,0 +1,4 @@ +The `vnf` library allows you to programmatically run NES/Famicom ROM files under +certain conditions. You can look for examples on the +[../../tests/vnf-tests](../../tests/vnf-tests) binary crate, or check the +documentation via the usual `cargo doc` commands. diff --git a/lib/vnf/src/lib.rs b/lib/vnf/src/lib.rs index 852b6df..dfa2f7f 100644 --- a/lib/vnf/src/lib.rs +++ b/lib/vnf/src/lib.rs @@ -1,3 +1,26 @@ +//! # Virtual NES/Famicom +//! +//! This library provides all the needed interfaces in order to run an +//! NES/Famicom ROM programmatically. It allows any developer to pick up a ROM +//! file, start execution from a given address and stop it at any point. Along +//! the way, developers can poke for memory accesses, joypad inputs, etc.; and +//! they can check all the state of the instantiated Virtual Machine to validate +//! that the code runs as expected. The state also considers chips like the PPU +//! and the APU, but it does not produce graphics nor sound. This is done in +//! purpose, as this is all meant to be headless, so it can be run in CI/CD +//! environments without the hassle of coming up with solutions for +//! graphics/sound support. +//! +//! All in all, the goal of this library is twofold: +//! +//! 1. Support [`runrom`](../runrom/index.html) in any way so all the desired +//! features can be implemented. +//! 2. Provide a sane API with regards to running and inspecting an +//! NES/Famicom emulator. +//! +//! This way, NES/Famicom developers can write tests for their NES/Famicom +//! games, checking on specific hot spots for how registers and the memory are +//! modified. use header::Header; use std::assert_matches; use std::collections::HashMap; @@ -8,7 +31,9 @@ use std::path::Path; use xixanta::opcodes::AddressingMode; use xixanta::opcodes::{Instruction, InstructionIdentifier, OPCODES}; -/// Values on the 'status' register converted to bools for easier use. +/// The 'status' register from the CPU. All flags are set as booleans for easier +/// use, and the 'break_mark' byte contains the break mark from the last 'brk' +/// instruction. #[derive(Debug)] pub struct StatusRegister { pub negative: bool, @@ -116,7 +141,7 @@ pub struct PPU { pub oam_dma: u8, } -/// A byte from the memory, which other than the actual value, also contains +/// A byte from memory, which other than the actual value, also contains /// different stats for it. #[derive(Clone, Copy, Debug, Default)] pub struct MemoryCell { @@ -144,7 +169,10 @@ pub enum MemoryInitialValue { } /// Allows users to define a policy for how the memory should be initialized for -/// the given Machine. +/// the given Machine. This is one of the parameters to be passed on the +/// initialization of [`Machine`]. This policy will tell the machine how memory +/// should be initialized, which sectors are allowed to be read/written, and +/// what's the lowest point that the stack pointer can reach. #[derive(Debug)] pub struct MemoryPolicy { /// The initial value to be given for each cell. @@ -462,7 +490,27 @@ impl Machine { }) } - /// Push the given 'inputs' to the controller identified by 'id'. + /// Push the given 'inputs' to the controller identified by 'id'. In order + /// to set the 'inputs' parameter, refer to the constants from + /// [`Joypad`]. This way, after initializing a [`Machine`] object, one could + /// set the inputs to be considered like so: + /// + /// ``` + /// machine.push_inputs_to( + /// 0, + /// &[ + /// (Joypad::BUTTON_DOWN | Joypad::BUTTON_B), + /// (Joypad::BUTTON_UP | Joypad::BUTTON_A), + /// Joypad::BUTTON_A, + /// ], + /// ); + /// ``` + /// + /// Then, these values will be the ones being passed whenever the joypad 0 + /// is read. + /// + /// Be mindful on the amount of inputs being read by the code, as they will + /// be consumed upon use. /// /// NOTE: for now only standard controllers 0 and 1 are supported. pub fn push_inputs_to(&mut self, id: usize, inputs: &[u8]) { @@ -836,7 +884,7 @@ impl Machine { } /// Execute the current instruction. - pub fn execute(&mut self) -> Result<(), String> { + fn execute(&mut self) -> Result<(), String> { self.status_register.overflow = false; match self.current_instruction.identifier { |
