pub struct Movie {
pub region: Region,
pub rom_sha256: [u8; 32],
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.
Fields§
§region: RegionCartridge region the movie was recorded under.
rom_sha256: [u8; 32]Full SHA-256 of the ROM the movie was recorded against.
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 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.
For StartPoint::PowerOn this power-cycles nes. For
StartPoint::SaveState it restores the embedded snapshot. In both
cases the ROM hash is checked against the movie’s recorded hash.
§Errors
Returns MovieError::RomMismatch if nes is running a different
ROM, or 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::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.