Skip to main content

Movie

Struct Movie 

Source
#[non_exhaustive]
pub struct Movie { pub region: Region, pub rom_sha256: [u8; 32], pub epoch: u32, pub options: HardwareOptions, pub board: Option<BoardDescription>, pub start: StartPoint, pub frames: Vec<FrameInput>, pub rerecord_count: u32, pub attestation: Option<Attestation>, }
Expand description

A complete TAS movie: a versioned header, a start point, and the per-frame input stream.

#[non_exhaustive] since v3.0.0 (T-API-EXTENSIBLE): build one with Movie::new (or a MovieRecorder / an importer), then set the public fields that differ from its defaults. A later field is then not a break.

Fields (Non-exhaustive)§

This struct is marked as non-exhaustive
Non-exhaustive structs could have additional fields added in future. Therefore, non-exhaustive structs cannot be constructed in external crates using the traditional Struct { .. } syntax; cannot be matched against without a wildcard ..; and struct update syntax will not work.
§region: Region

Cartridge region the movie was recorded under. Checked, not applied: Movie::seek_to_start refuses a machine of another region.

§rom_sha256: [u8; 32]

Nes::rom_sha256 of the ROM the movie was recorded against.

§epoch: u32

v3.0.0 (ADR 0045) — the EMULATION_EPOCH the movie was recorded under. Movie::new and every recorder and importer stamp the current one; Movie::deserialize refuses another.

§options: HardwareOptions

v2.9.8 — every emulation-affecting host option the movie was recorded with. Movie::seek_to_start applies them before frame 0, so the replay does not depend on the player’s settings. A foreign import records HardwareOptions::default, the stock NES.

§board: Option<BoardDescription>

v2.9.8 — the cartridge board the recording machine was built from. None for a foreign import (its format records no header), in which case only the ROM identity and the region are checked.

§start: StartPoint

Where playback begins.

§frames: Vec<FrameInput>

Per-frame controller inputs, in playback order.

§rerecord_count: u32

TAS re-record count — how many times the author re-recorded a frame (the TAS piano-roll editor’s edit tally; 0 for a straight linear recording). Round-trips through .rnm (appended after the input stream, so older readers ignore it) and the .fm2 / .bk2 rerecordCount header.

§attestation: Option<Attestation>

Optional replay attestation (v2.3.2 “Lucid”): a rolling hash of the run’s video output plus periodic checkpoints, letting a third party replay the movie and prove it reproduces the recorded run.

None for every movie recorded without one, which is most of them. Appended after Self::rerecord_count behind ATTESTATION_MAGIC, so an older reader stops at the re-record count and never sees it — the same additive-tail trick that field itself used, and the reason no container version bump was needed.

Implementations§

Source§

impl Movie

Source

pub const fn new( region: Region, rom_sha256: [u8; 32], options: HardwareOptions, board: Option<BoardDescription>, start: StartPoint, frames: Vec<FrameInput>, ) -> Self

v3.0.0 — a movie at the current EMULATION_EPOCH with no re-records and no attestation. Set Self::rerecord_count or Self::attestation afterwards when they apply; the struct is #[non_exhaustive], so this is how code outside rustynes-core builds one.

Source

pub const fn len(&self) -> usize

Number of input frames in the movie.

Source

pub const fn is_empty(&self) -> bool

true if the movie has no input frames.

Source

pub fn serialize(&self) -> Vec<u8> ⓘ

Serialize the movie to its .rnm byte representation.

Deterministic: the same Movie always produces identical bytes.

Source

pub fn deserialize(bytes: &[u8]) -> Result<Self, MovieError>

Parse a .rnm movie from its byte representation.

§Errors

Returns MovieError for a bad magic, an unsupported container version, an unknown region byte, a frame width this build can’t parse, or a truncated body. Never panics on malformed input.

Source

pub fn seek_to_start(&self, nes: &mut Nes) -> Result<(), MovieError>

Rewind a running emulator to this movie’s start point, ready to replay from frame 0.

Checks first, then changes the machine: the ROM identity, the region and (for a recorded movie) the BoardDescription must match, or the call fails with nes untouched. Then it applies the movie’s HardwareOptions – v2.9.8: the recorded console model, die revisions, power-on fills, overclock, Four Score, Vs. settings, mirroring override and Game Genie codes replace the player’s – and moves to the start point: for StartPoint::PowerOn a power cycle with cleared cartridge RAM (power_on_for_movie), for StartPoint::SaveState the embedded snapshot.

A start refused after the checks – an old or malformed start state, an undecodable code – also leaves nes as it was: the call takes a rollback point first and restores it on any error.

After a successful start the player’s options are not restored here; a host that wants them back captures them first (HardwareOptions::capture) and calls HardwareOptions::restore_after_playback when playback ends.

§Errors

MovieError::EpochMismatch for a movie recorded under another emulation epoch (ADR 0045); MovieError::RomMismatch, MovieError::RegionMismatch or MovieError::BoardMismatch for a different machine; MovieError::OptionNotApplicable for a Game Genie code that does not decode; MovieError::BadSaveState if the embedded snapshot is malformed.

Source

pub fn verify(&self, nes: &mut Nes) -> Result<VerifyOutcome, MovieError>

v2.3.2 “Lucid” — replay this movie and check it reproduces its attestation.

Seeks nes to the movie’s start point, replays the whole input stream, and compares the resulting rolling hash (and every checkpoint along the way) against what the movie recorded. Anyone with the ROM and the .rnm can run it and get the same answer, so an accidental divergence — a different build, a nondeterminism bug, a corrupted file — or a casual edit to the input stream, the start point, or the claimed hash shows up as a VerifyOutcome::Mismatch.

Reproducibility, not provenance. The digest is a 64-bit FNV-1a variant: tamper-evident, not forgery-resistant. A Match means “these inputs, applied to this ROM, on a verifier configured like the recorder, produce this video”. It does not establish who produced the movie, and a motivated forger can edit the movie and recompute the digest.

Consumes real emulation time — it runs every frame of the movie.

§Errors

MovieError::EpochMismatch for a movie from another emulation epoch (checked first, attested or not), MovieError::RomMismatch if nes is running a different ROM, or MovieError::BadSaveState if an embedded start point is malformed. A movie with no attestation is not an error; it returns VerifyOutcome::NotAttested, because “this movie makes no claim” and “this movie makes a false claim” are different answers.

Trait Implementations§

Source§

impl Clone for Movie

Source§

fn clone(&self) -> Movie

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for Movie

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Eq for Movie

Source§

impl PartialEq for Movie

Source§

fn eq(&self, other: &Movie) -> bool

Equality operator ==. Read more
1.0.0 (const: unstable) · Source§

fn ne(&self, other: &Rhs) -> bool

Inequality operator !=. Read more
Source§

impl StructuralPartialEq for Movie

Auto Trait Implementations§

§

impl Freeze for Movie

§

impl RefUnwindSafe for Movie

§

impl Send for Movie

§

impl Sync for Movie

§

impl Unpin for Movie

§

impl UnsafeUnpin for Movie

§

impl UnwindSafe for Movie

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.