#[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
Struct { .. } syntax; cannot be matched against without a wildcard ..; and struct update syntax will not work.region: RegionCartridge 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: u32v3.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: HardwareOptionsv2.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: StartPointWhere playback begins.
frames: Vec<FrameInput>Per-frame controller inputs, in playback order.
rerecord_count: u32TAS 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
impl Movie
Sourcepub const fn new(
region: Region,
rom_sha256: [u8; 32],
options: HardwareOptions,
board: Option<BoardDescription>,
start: StartPoint,
frames: Vec<FrameInput>,
) -> Self
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.
Sourcepub fn serialize(&self) -> Vec<u8> ⓘ
pub fn serialize(&self) -> Vec<u8> ⓘ
Serialize the movie to its .rnm byte representation.
Deterministic: the same Movie always produces identical bytes.
Sourcepub fn deserialize(bytes: &[u8]) -> Result<Self, MovieError>
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.
Sourcepub fn seek_to_start(&self, nes: &mut Nes) -> Result<(), MovieError>
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.
Sourcepub fn verify(&self, nes: &mut Nes) -> Result<VerifyOutcome, MovieError>
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.