JaffarPlus
High-performance best-first search optimizer for tool-assisted speedruns
Loading...
Searching...
No Matches
player.cpp File Reference

The jaffar-player (jaffar-tester) executable: loads a config and a solution sequence and plays it back through a jaffarPlus::Runner. More...

#include "emulator.hpp"
#include "game.hpp"
#include "playback.hpp"
#include "runner.hpp"
#include <argparse/argparse.hpp>
#include <chrono>
#include <emulatorList.hpp>
#include <gameList.hpp>
#include <jaffarCommon/json.hpp>
#include <jaffarCommon/logger.hpp>
#include <jaffarCommon/string.hpp>
#include <map>
#include <set>

Go to the source code of this file.

Functions

static size_t parseUInt (const std::string &value, const std::string &flag)
 Parses a non-negative integer from a CLI argument value.
 
bool mainCycle (jaffarPlus::Runner &r, const std::string &solutionFile, bool disableRender)
 Runs one full pass over a solution sequence, optionally interactive, and reports state info.
 
int main (int argc, char *argv[])
 Entry point for the jaffar-player (jaffar-tester) executable.
 

Variables

bool isUnattended
 Prevents the interactive player from stalling for a keystroke.
 
bool isExitOnEnd
 Determines that the reproduction must end on reaching the last step.
 
bool isReload
 Switch to toggle whether to reload the movie on reaching the end of the sequence.
 
bool isReproduce
 Switch to toggle whether to reproduce (auto-advance) the movie.
 
size_t frameskip
 Number of frames to skip between renderings.
 
std::string runCommand
 Command to run initially and then exit.
 
bool printFinalState
 When set, prints a stable, machine-readable summary of the final state on exit (for headless verification of a reproduction: determinism checks and golden-hash comparisons).
 
std::string dumpHashesPath
 When non-empty, writes the per-step game-state hash for every step to this file (one "step\thashHi\thashLo" line per step).
 
size_t dumpHashesLookahead = 0
 Null-input advances applied before hashing each step in the –dumpHashes pass (mirrors engine "Hash Lookahead").
 
std::string dumpRamPath
 When non-empty, writes the full low work-RAM ("LRAM") segment for every step to this file as a flat binary blob (size-of-LRAM bytes per step).
 
std::string dumpVramPath
 When non-empty, writes the full VRAM for every step to this file as a flat binary blob.
 
std::string dumpPollsPath
 When non-empty (–dumpPolls), writes the per-step joypad read count ("step\tcount" per line) for the replayed solution to this file.
 
std::string dumpRewardPath
 When non-empty (–dumpReward), writes the per-step game reward (one value per line) for the replayed solution to this file.
 
std::string dumpTracePath
 When non-empty (–dumpTrace), writes the game's per-step trace line (Game::getTraceLine, one line per step) for the replayed solution to this file.
 
std::string dumpRacerPath
 When non-empty (–dumpRacer), dumps frame,gx,gy,spd + the full 234-byte racer struct per frame.
 
std::string saveStateStepStr
 When set (–saveStateStep), the step at which to capture a full emulator savestate (paired with –saveStateFile).
 
std::string saveStateFilePath
 When non-empty (–saveStateFile), the path to write the emulator savestate captured at –saveStateStep (e.g.
 
std::string savePokedStatePath
 When non-empty (–savePokedState), save the post-poke full-fidelity emulator state to this path and exit (pairs with –pokeRAM for cross-emulator state transplants).
 
std::string pokeNtabPath
 When non-empty (–pokeNTAB), binary file to block-copy into nametable memory post-init.
 
std::string dumpNtabPath
 When non-empty (–dumpNTAB), dump post-init nametable memory to this file and exit.
 
std::string savePokedStateStepStr
 Steps of the solution to advance after the poke before saving (–savePokedStateStep).
 
std::string screenshotDir
 Directory to write per-frame screenshots (BMP) into; empty disables screenshotting.
 
std::set< size_t > screenshotSteps
 Steps to capture as screenshots; empty captures all rendered steps when a dir is given.
 
std::vector< std::pair< uint32_t, uint8_t > > pokeRam
 Work-RAM bytes to poke into the post-initial-sequence state before replaying (for mechanic experiments, e.g.
 
std::string terrainSweepSpec
 When set (–terrainSweep "out.csv:x0,x1,y0,y1,step"), probe the terrain the game computes at a grid of player positions: reload the post-init state, poke player pos (0x80A6/0x80A8), step, read the surface byte (0xA649), attribute (0xA648) and fall state (0xA66C).
 
std::string terrainDrivePath
 When set (–terrainDrive out.csv), branch off the replayed solution every few frames and steer a REAL driving car into neighboring cells, logging the true physics effect (min speed = slowdown, fall = hole, max Z = jump) per grid cell.
 

Detailed Description

The jaffar-player (jaffar-tester) executable: loads a config and a solution sequence and plays it back through a jaffarPlus::Runner.

Supports interactive stepping/playback in a terminal, headless/unattended replay, per-frame BMP screenshot capture, single-command runs (--runCommand), and a machine-readable final-state summary (--printFinalState) used as an oracle for headless reproduction tests (determinism / golden-hash comparisons). Behavior is driven by the command-line flags parsed in main and the file-scope switches below.

Definition in file player.cpp.

Function Documentation

◆ main()

int main ( int  argc,
char *  argv[] 
)

Entry point for the jaffar-player (jaffar-tester) executable.

Parses the command-line arguments (required configFile and solutionFile, plus the --reproduce, --reload, --exitOnEnd, --unattended, --disableRender, --frameskip, --initialSequence, --runCommand, --screenshotDir, --screenshotSteps and --printFinalState flags), seeding the file-scope playback switches from them. Loads and parses the JSON config, optionally overrides the emulator's "Initial Sequence File Path", forces the runner's frameskip rate to 0, then builds and initializes a jaffarPlus::Runner. If rendering is enabled it initializes video output and rendering. Serializes the runner's initial state, then repeatedly invokes mainCycle; when a cycle requests another pass it sleeps briefly and restores the saved initial state. Finalizes video output and the terminal on exit.

Parameters
argcArgument count.
argvArgument vector.
Returns
0 on normal exit (implicit).

Definition at line 992 of file player.cpp.

◆ mainCycle()

bool mainCycle ( jaffarPlus::Runner r,
const std::string &  solutionFile,
bool  disableRender 
)

Runs one full pass over a solution sequence, optionally interactive, and reports state info.

Loads the solution sequence file, builds a jaffarPlus::Playback over the runner, and enters a loop that (unless rendering is disabled) renders the current frame, optionally saves a BMP screenshot for the current step, prints per-step information (step index, input, hashes, allowed inputs, game/emulator names, checkpoint and save-solution status, plus game-specific info), and handles navigation/playback commands. Commands move the current step (n/m +/-1, h/j +/-10, y/u +/-100, k/i +/-1000), quicksave the emulator state to "quicksave.state" (s), toggle playback (p), toggle auto-reload (r), quit (q), or are forwarded to the game's player command parser. In unattended or reproduce mode, key input is non-blocking; runCommand forces a single command then finalizes. On reaching the end it reloads, exits, or stops depending on the reload/exit-on-end flags. When printFinalState is set, prints a stable end-of-sequence summary (final step, state type, first win/fail steps, final state hash, not-allowed-input count, repeated-state count).

Parameters
rThe runner to play the solution back on.
solutionFilePath to the solution sequence file to load and reproduce.
disableRenderWhether to skip frame rendering (and screenshot capture).
Returns
false when the cycle finalized (quit requested), true to keep looping (e.g. for reload).

Definition at line 156 of file player.cpp.

◆ parseUInt()

static size_t parseUInt ( const std::string &  value,
const std::string &  flag 
)
static

Parses a non-negative integer from a CLI argument value.

Reports a clear logic error (instead of a raw std::stoul exception) when the value is malformed or contains trailing characters.

Parameters
valueThe string value to parse.
flagThe name of the CLI flag the value came from, used in the error message.
Returns
The parsed non-negative integer.

Definition at line 121 of file player.cpp.

Variable Documentation

◆ dumpHashesLookahead

size_t dumpHashesLookahead = 0

Null-input advances applied before hashing each step in the –dumpHashes pass (mirrors engine "Hash Lookahead").

Definition at line 49 of file player.cpp.

◆ dumpHashesPath

std::string dumpHashesPath

When non-empty, writes the per-step game-state hash for every step to this file (one "step\thashHi\thashLo" line per step).

Used to cross-validate two emulators replaying the same solution: diffing the two dumps pinpoints the exact first frame at which they diverge.

Definition at line 46 of file player.cpp.

◆ dumpNtabPath

std::string dumpNtabPath

When non-empty (–dumpNTAB), dump post-init nametable memory to this file and exit.

Definition at line 91 of file player.cpp.

◆ dumpPollsPath

std::string dumpPollsPath

When non-empty (–dumpPolls), writes the per-step joypad read count ("step\tcount" per line) for the replayed solution to this file.

A count of 0 marks a lag frame (input not polled); the polled frame right before a lag group is a level's true start frame. The counter is not part of the serialized state, so this pass replays the solution live instead of restoring per-step states.

Definition at line 63 of file player.cpp.

◆ dumpRacerPath

std::string dumpRacerPath

When non-empty (–dumpRacer), dumps frame,gx,gy,spd + the full 234-byte racer struct per frame.

Definition at line 73 of file player.cpp.

◆ dumpRamPath

std::string dumpRamPath

When non-empty, writes the full low work-RAM ("LRAM") segment for every step to this file as a flat binary blob (size-of-LRAM bytes per step).

Diffing two emulators' RAM dumps byte-by-byte identifies the exact RAM addresses (hence game variables) that diverge.

Definition at line 54 of file player.cpp.

◆ dumpRewardPath

std::string dumpRewardPath

When non-empty (–dumpReward), writes the per-step game reward (one value per line) for the replayed solution to this file.

Suitable as a driver "Reference Reward Floor" trace.

Definition at line 67 of file player.cpp.

◆ dumpTracePath

std::string dumpTracePath

When non-empty (–dumpTrace), writes the game's per-step trace line (Game::getTraceLine, one line per step) for the replayed solution to this file.

Suitable as a game "Trace File Path" (trace-magnet ref).

Definition at line 71 of file player.cpp.

◆ dumpVramPath

std::string dumpVramPath

When non-empty, writes the full VRAM for every step to this file as a flat binary blob.

Definition at line 56 of file player.cpp.

◆ frameskip

size_t frameskip

Number of frames to skip between renderings.

Definition at line 35 of file player.cpp.

◆ isExitOnEnd

bool isExitOnEnd

Determines that the reproduction must end on reaching the last step.

Definition at line 29 of file player.cpp.

◆ isReload

bool isReload

Switch to toggle whether to reload the movie on reaching the end of the sequence.

Definition at line 31 of file player.cpp.

◆ isReproduce

bool isReproduce

Switch to toggle whether to reproduce (auto-advance) the movie.

Definition at line 33 of file player.cpp.

◆ isUnattended

bool isUnattended

Prevents the interactive player from stalling for a keystroke.

Definition at line 27 of file player.cpp.

◆ pokeNtabPath

std::string pokeNtabPath

When non-empty (–pokeNTAB), binary file to block-copy into nametable memory post-init.

Definition at line 88 of file player.cpp.

◆ pokeRam

std::vector<std::pair<uint32_t, uint8_t> > pokeRam

Work-RAM bytes to poke into the post-initial-sequence state before replaying (for mechanic experiments, e.g.

perturbing an RNG/counter). Parsed from –pokeRAM "0xADDR=VAL,0xADDR=VAL".

Definition at line 103 of file player.cpp.

◆ printFinalState

bool printFinalState

When set, prints a stable, machine-readable summary of the final state on exit (for headless verification of a reproduction: determinism checks and golden-hash comparisons).

Definition at line 41 of file player.cpp.

◆ runCommand

std::string runCommand

Command to run initially and then exit.

Definition at line 37 of file player.cpp.

◆ savePokedStatePath

std::string savePokedStatePath

When non-empty (–savePokedState), save the post-poke full-fidelity emulator state to this path and exit (pairs with –pokeRAM for cross-emulator state transplants).

Definition at line 85 of file player.cpp.

◆ savePokedStateStepStr

std::string savePokedStateStepStr

Steps of the solution to advance after the poke before saving (–savePokedStateStep).

Definition at line 94 of file player.cpp.

◆ saveStateFilePath

std::string saveStateFilePath

When non-empty (–saveStateFile), the path to write the emulator savestate captured at –saveStateStep (e.g.

to seed another search cleanly from a chosen frame).

Definition at line 81 of file player.cpp.

◆ saveStateStepStr

std::string saveStateStepStr

When set (–saveStateStep), the step at which to capture a full emulator savestate (paired with –saveStateFile).

Parsed as an unsigned step index; empty unless saving is requested.

Definition at line 77 of file player.cpp.

◆ screenshotDir

std::string screenshotDir

Directory to write per-frame screenshots (BMP) into; empty disables screenshotting.

Definition at line 97 of file player.cpp.

◆ screenshotSteps

std::set<size_t> screenshotSteps

Steps to capture as screenshots; empty captures all rendered steps when a dir is given.

Definition at line 99 of file player.cpp.

◆ terrainDrivePath

std::string terrainDrivePath

When set (–terrainDrive out.csv), branch off the replayed solution every few frames and steer a REAL driving car into neighboring cells, logging the true physics effect (min speed = slowdown, fall = hole, max Z = jump) per grid cell.

Correct effects (consistent state) for the drivable band. Writes CSV & exits.

Definition at line 111 of file player.cpp.

◆ terrainSweepSpec

std::string terrainSweepSpec

When set (–terrainSweep "out.csv:x0,x1,y0,y1,step"), probe the terrain the game computes at a grid of player positions: reload the post-init state, poke player pos (0x80A6/0x80A8), step, read the surface byte (0xA649), attribute (0xA648) and fall state (0xA66C).

Writes CSV and exits.

Definition at line 107 of file player.cpp.