Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

37 Commits
 
 
 
 
 
 
 
 

Repository files navigation

NeonRewind

NeonRewind is an unofficial, open-source project for Retro Rewind: Video Store Simulator. It currently reads data from an installed Steam copy of the game, converts the film tables into a consistent JSON catalog, and compiles normalized rental, fee, and return mechanics. The public guide, calculators, and website have not been built yet.

Data and distribution boundary

The repository contains source code, JSON Schemas, normalization logic, and instructions. Users provide their own licensed game installation and run the acquisition commands locally.

Do not commit or publish:

  • Compiled extractor binaries
  • Game binaries, package files, mappings, or saves
  • Build manifests or static censuses produced from a game installation
  • Structured values, rental evidence, Blueprint pseudocode, or Blueprint function traces
  • Compiled film catalogs, mechanic artifacts, runtime observations, validation reports, or extracted game text
  • Extracted or modified game assets

The documented output directories are ignored by Git.

What the current workflow does

The commands form one pipeline, and each command uses the file produced by the previous command.

Step Result Meaning
Build manifest build-manifest.json Identifies the exact Steam build and package hashes
Static census static-census.json Lists files, Unreal packages, and exported classes
Structured index structured-asset-index.json Locates DataTables and StringTables using a matching Unreal mapping
Structured values structured-values.json Extracts table rows and strings into deterministic JSON
Rental evidence rental-evidence.json Extracts the rental subsystem's fields, functions, explicit defaults, and default-value object references
Rental Blueprint bodies rental-blueprint-bodies.json Decompiles the rental subsystem's cooked Blueprint bytecode into reviewable pseudocode
Blueprint call sites blueprint-call-sites.movie-return.json Searches parsed Blueprint bytecode for calls to the movie-return selector
Blueprint caller bodies blueprint-caller-bodies.movie-return.json Decompiles the exact functions found by the movie-return call-site scan
Customer entry call sites blueprint-call-sites.movie-customer-entry.json Searches parsed Blueprint bytecode for calls into the discovered movie-customer function
Customer event-graph body blueprint-caller-bodies.movie-customer-entry.json Decompiles the event-graph function that invokes the movie-customer function
AI client ubergraph call sites blueprint-call-sites.ai-client-ubergraph.json Finds Blueprint wrappers that enter the AI client event graph
AI client wrapper bodies blueprint-caller-bodies.ai-client-ubergraph.json Decompiles those wrappers to recover their numeric event-graph entry points
Blueprint function trace blueprint-function-trace.movie-customer.json Converts the linked caller functions into typed Kismet nodes with branch-variable identities
Rental function trace rental-function-trace.movie-return.json Converts selected rental functions into typed Kismet nodes tied to the rental-body artifact
Console return mechanics console-return-mechanics.json Normalizes console-return eligibility and queue movement with source locators
Membership fee mechanics membership-fee-mechanics.json Normalizes membership fee storage, accumulation, and removal with source locators
Movie return mechanics movie-return-mechanics.json Normalizes movie readiness, weighted selection, and customer flow from typed traces
Movie return validation movie-return-validation.json Verifies a private runtime observation against its exact movie-return mechanics artifact
Film catalog film-catalog.json Converts the film rows into stable NeonRewind records

An artifact is a JSON file produced by one of these commands. Package files such as .pak contain the installed game's Unreal assets. An Unreal DataTable stores many records with the same fields, and a StringTable stores named text entries. A JSON Schema is a rule file used to check a JSON artifact's required fields and value types. Acquisition artifacts contain extracted game data, so the examples store them in ignored .local directories.

Before you start

You need the following items:

  • Windows and a licensed Steam installation of Retro Rewind: Video Store Simulator.
  • The .NET 10 SDK for the acquisition commands.
  • Node.js 24.19.0 and pnpm 11.x for the normalized-data compilers.
  • An internet connection for the first dependency installation unless the packages are already cached.
  • A .usmap mapping generated for the exact game executable when running the structured-index, structured-values, rental-evidence, rental-blueprint-bodies, blueprint-call-sites, blueprint-caller-bodies, blueprint-function-trace, and rental-function-trace steps.

The recommended setup uses portable tool archives extracted into ignored local directories. Follow Portable local tool setup to install nothing system-wide and change PATH only for the current shell process.

The repository does not currently generate the .usmap mapping. If you do not already have a matching mapping, you can complete the probe, build-manifest, and static-census steps, then stop. Do not reuse a mapping from a different game build.

Open PowerShell or Git Bash in the repository root and verify the installed tools.

dotnet --version
node --version
pnpm --version
dotnet --version
node --version
pnpm --version

The expected major versions are .NET 10, Node.js 24, and pnpm 11. If a command is unavailable, use the official .NET installation guide, Node.js download page, or pnpm installation guide.

Set your local paths

The following example uses Steam's default Windows location. Change only $steamRoot if your Steam library is on another drive or in another folder.

$steamRoot = "C:\Program Files (x86)\Steam"
$gameRoot = Join-Path $steamRoot "steamapps\common\RetroRewind"
$steamManifest = Join-Path $steamRoot "steamapps\appmanifest_3552140.acf"
$packageDirectory = Join-Path $gameRoot "RetroRewind\Content\Paks"
$packageFile = Join-Path $packageDirectory "RetroRewind-Windows.pak"
$executable = Join-Path $gameRoot "RetroRewind\Binaries\Win64\RetroRewind-Win64-Shipping.exe"
$extractor = "projects/game-data-exporter/static-extractor/NeonRewind.StaticExtractor.csproj"
$generationId = (Get-Date).ToUniversalTime().ToString("yyyyMMddTHHmmssZ")
$buildDirectory = Join-Path (Get-Location) "projects/game-data-exporter/.local/acquisition/runs/$generationId"
$domainDirectory = Join-Path (Get-Location) "projects/typescript/.local/domain/runs/$generationId"

New-Item -ItemType Directory -Force -Path $buildDirectory, $domainDirectory | Out-Null
steamRoot="C:\Program Files (x86)\Steam"
gameRoot="$steamRoot/steamapps\common\RetroRewind"
steamManifest="$steamRoot/steamapps\appmanifest_3552140.acf"
packageDirectory="$gameRoot/RetroRewind\Content\Paks"
packageFile="$packageDirectory/RetroRewind-Windows.pak"
executable="$gameRoot/RetroRewind\Binaries\Win64\RetroRewind-Win64-Shipping.exe"
extractor="projects/game-data-exporter/static-extractor/NeonRewind.StaticExtractor.csproj"
generationId="$(date -u +%Y%m%dT%H%M%SZ)"
buildDirectory="$PWD/projects/game-data-exporter/.local/acquisition/runs/$generationId"
domainDirectory="$PWD/projects/typescript/.local/domain/runs/$generationId"

mkdir -p "$buildDirectory" "$domainDirectory"

Each run uses a new generation directory so immutable artifacts can keep stable, unversioned filenames.

Close the game before reading its package files. The game does not need to be running for any command in this README.

Restore the locked .NET dependencies once.

dotnet restore $extractor --locked-mode
dotnet restore "$extractor" --locked-mode

1. Check that the package can be read

The probe opens the package directory and reports how many containers, files, and Unreal packages it can see. It does not extract game values or create an output file.

dotnet run --project $extractor -- $packageDirectory
dotnet run --project "$extractor" -- "$packageDirectory"

Continue when the command reports at least one mounted container and a nonzero file and package count.

2. Create the build manifest

The build manifest records the Steam application, build number, executable hash, package hash, engine profile, and extractor version. Later steps use these hashes to make sure their inputs still belong to the same build.

dotnet run --project $extractor -- manifest `
  --steam-manifest $steamManifest `
  --executable $executable `
  --package $packageFile `
  --output (Join-Path $buildDirectory "build-manifest.json")
dotnet run --project "$extractor" -- manifest \
  --steam-manifest "$steamManifest" \
  --executable "$executable" \
  --package "$packageFile" \
  --output "$buildDirectory/build-manifest.json"

Repeat --package <path> if a future build uses more than one package-container file. The command accepts an identical existing output and refuses to overwrite different content.

3. Create the static census

The census inventories the package without needing an Unreal mapping. It records files, package headers, imports, exports, exported classes, and parse failures.

dotnet run --project $extractor -- census `
  --build-manifest (Join-Path $buildDirectory "build-manifest.json") `
  --package-directory $packageDirectory `
  --output (Join-Path $buildDirectory "static-census.json")
dotnet run --project "$extractor" -- census \
  --build-manifest "$buildDirectory/build-manifest.json" \
  --package-directory "$packageDirectory" \
  --output "$buildDirectory/static-census.json"

The command verifies the package hashes before and after scanning.

4. Supply the matching Unreal mapping

A .usmap file describes the Unreal properties needed to read DataTable rows and similar structured assets. Set $mappings to a mapping produced for the same executable recorded in the build manifest.

$mappings = "C:\path\to\the\matching-build.usmap"
mappings="C:\path\to\the\matching-build.usmap"

The mapped acquisition commands cannot run reliably without this file.

5. Create the structured index

The structured index fully reads candidate DataTables, StringTables, and direct data assets without copying their row values. It records the table locations, structures, row counts, property counts, and failures.

dotnet run --project $extractor -- structured-index `
  --build-manifest (Join-Path $buildDirectory "build-manifest.json") `
  --static-census (Join-Path $buildDirectory "static-census.json") `
  --mappings $mappings `
  --package-directory $packageDirectory `
  --output (Join-Path $buildDirectory "structured-asset-index.json")
dotnet run --project "$extractor" -- structured-index \
  --build-manifest "$buildDirectory/build-manifest.json" \
  --static-census "$buildDirectory/static-census.json" \
  --mappings "$mappings" \
  --package-directory "$packageDirectory" \
  --output "$buildDirectory/structured-asset-index.json"

The command validates the manifest, census, mapping, and package identities before and after parsing.

6. Extract the structured values

This step copies the indexed DataTable rows and StringTable entries into deterministic JSON. The output contains game text and must remain in the ignored local acquisition directory.

dotnet run --project $extractor -- structured-values `
  --build-manifest (Join-Path $buildDirectory "build-manifest.json") `
  --structured-index (Join-Path $buildDirectory "structured-asset-index.json") `
  --mappings $mappings `
  --package-directory $packageDirectory `
  --output (Join-Path $buildDirectory "structured-values.json")
dotnet run --project "$extractor" -- structured-values \
  --build-manifest "$buildDirectory/build-manifest.json" \
  --structured-index "$buildDirectory/structured-asset-index.json" \
  --mappings "$mappings" \
  --package-directory "$packageDirectory" \
  --output "$buildDirectory/structured-values.json"

The command verifies every input again after extraction and refuses to overwrite different output.

7. Extract the rental-system evidence

This step reads six packages that define the rental manager, its two structs, and three related AI tasks. It records generated-class fields, function names, class-default values, struct defaults, and object references contained in those mapped defaults. The command stops if the exact package cluster is absent from the census.

dotnet run --project $extractor -- rental-evidence `
  --build-manifest (Join-Path $buildDirectory "build-manifest.json") `
  --static-census (Join-Path $buildDirectory "static-census.json") `
  --mappings $mappings `
  --package-directory $packageDirectory `
  --output (Join-Path $buildDirectory "rental-evidence.json")
dotnet run --project "$extractor" -- rental-evidence \
  --build-manifest "$buildDirectory/build-manifest.json" \
  --static-census "$buildDirectory/static-census.json" \
  --mappings "$mappings" \
  --package-directory "$packageDirectory" \
  --output "$buildDirectory/rental-evidence.json"

The output contains extracted game values and must remain in the ignored local acquisition directory.

8. Extract readable rental Blueprint bodies

This step loads the cooked script bytecode for the four generated classes recorded in the rental-evidence artifact. It records each function's flags and bytecode-expression count, then uses CUE4Parse to produce deterministic pseudocode for review. The pseudocode is a decompiler interpretation and must be checked against the underlying function metadata before it becomes a mechanic fact.

dotnet run --project $extractor -- rental-blueprint-bodies `
  --build-manifest (Join-Path $buildDirectory "build-manifest.json") `
  --rental-evidence (Join-Path $buildDirectory "rental-evidence.json") `
  --mappings $mappings `
  --package-directory $packageDirectory `
  --output (Join-Path $buildDirectory "rental-blueprint-bodies.json")
dotnet run --project "$extractor" -- rental-blueprint-bodies \
  --build-manifest "$buildDirectory/build-manifest.json" \
  --rental-evidence "$buildDirectory/rental-evidence.json" \
  --mappings "$mappings" \
  --package-directory "$packageDirectory" \
  --output "$buildDirectory/rental-blueprint-bodies.json"

The output contains extracted game logic and must remain in the ignored local acquisition directory.

9. Find calls to the movie-return selector

This step uses the static census to select parsed packages that export Blueprint functions. It reads their Kismet expressions and records calls to one exact function name without copying the surrounding Blueprint bodies. The artifact reports complete or partial coverage, scan totals, call-site metadata, and package failure types.

dotnet run --project $extractor -- blueprint-call-sites `
  --build-manifest (Join-Path $buildDirectory "build-manifest.json") `
  --static-census (Join-Path $buildDirectory "static-census.json") `
  --mappings $mappings `
  --package-directory $packageDirectory `
  --target-function "Get Random List Of Cartridges From Rent List" `
  --output (Join-Path $buildDirectory "blueprint-call-sites.movie-return.json")
dotnet run --project "$extractor" -- blueprint-call-sites \
  --build-manifest "$buildDirectory/build-manifest.json" \
  --static-census "$buildDirectory/static-census.json" \
  --mappings "$mappings" \
  --package-directory "$packageDirectory" \
  --target-function "Get Random List Of Cartridges From Rent List" \
  --output "$buildDirectory/blueprint-call-sites.movie-return.json"

The output contains game-specific caller locations and must remain in the ignored local acquisition directory.

10. Extract the movie-return caller bodies

This step accepts only a complete call-site artifact for the same build and mappings. It rechecks every recorded call and decompiles only the functions that contain them.

dotnet run --project $extractor -- blueprint-caller-bodies `
  --build-manifest (Join-Path $buildDirectory "build-manifest.json") `
  --call-sites (Join-Path $buildDirectory "blueprint-call-sites.movie-return.json") `
  --mappings $mappings `
  --package-directory $packageDirectory `
  --output (Join-Path $buildDirectory "blueprint-caller-bodies.movie-return.json")
dotnet run --project "$extractor" -- blueprint-caller-bodies \
  --build-manifest "$buildDirectory/build-manifest.json" \
  --call-sites "$buildDirectory/blueprint-call-sites.movie-return.json" \
  --mappings "$mappings" \
  --package-directory "$packageDirectory" \
  --output "$buildDirectory/blueprint-caller-bodies.movie-return.json"

The output contains game-specific function bodies and must remain in the ignored local acquisition directory.

11. Trace the movie-customer function entry

This step searches the same complete Blueprint package set for calls to the customer function discovered by the movie-return scan. It determines whether another Blueprint function invokes that customer function before any broader event or native-boundary investigation.

dotnet run --project $extractor -- blueprint-call-sites `
  --build-manifest (Join-Path $buildDirectory "build-manifest.json") `
  --static-census (Join-Path $buildDirectory "static-census.json") `
  --mappings $mappings `
  --package-directory $packageDirectory `
  --target-function "Initial creation - Get if I have Product to return" `
  --output (Join-Path $buildDirectory "blueprint-call-sites.movie-customer-entry.json")
dotnet run --project "$extractor" -- blueprint-call-sites \
  --build-manifest "$buildDirectory/build-manifest.json" \
  --static-census "$buildDirectory/static-census.json" \
  --mappings "$mappings" \
  --package-directory "$packageDirectory" \
  --target-function "Initial creation - Get if I have Product to return" \
  --output "$buildDirectory/blueprint-call-sites.movie-customer-entry.json"

The output contains game-specific caller locations and must remain in the ignored local acquisition directory.

12. Extract the movie-customer event graph

This step verifies the complete customer-entry call-site artifact and decompiles only the event-graph function that contains its call. The result exposes the entry label and control flow immediately surrounding the movie-customer function.

dotnet run --project $extractor -- blueprint-caller-bodies `
  --build-manifest (Join-Path $buildDirectory "build-manifest.json") `
  --call-sites (Join-Path $buildDirectory "blueprint-call-sites.movie-customer-entry.json") `
  --mappings $mappings `
  --package-directory $packageDirectory `
  --output (Join-Path $buildDirectory "blueprint-caller-bodies.movie-customer-entry.json")
dotnet run --project "$extractor" -- blueprint-caller-bodies \
  --build-manifest "$buildDirectory/build-manifest.json" \
  --call-sites "$buildDirectory/blueprint-call-sites.movie-customer-entry.json" \
  --mappings "$mappings" \
  --package-directory "$packageDirectory" \
  --output "$buildDirectory/blueprint-caller-bodies.movie-customer-entry.json"

The output contains game-specific event-graph pseudocode and must remain in the ignored local acquisition directory.

13. Trace the AI client event-graph wrappers

This step searches the complete Blueprint package set for wrapper functions that call the AI client ubergraph. The resulting wrapper list can then be decompiled to identify which numeric entry point each wrapper supplies.

dotnet run --project $extractor -- blueprint-call-sites `
  --build-manifest (Join-Path $buildDirectory "build-manifest.json") `
  --static-census (Join-Path $buildDirectory "static-census.json") `
  --mappings $mappings `
  --package-directory $packageDirectory `
  --target-function "ExecuteUbergraph_AI_Client_Character" `
  --output (Join-Path $buildDirectory "blueprint-call-sites.ai-client-ubergraph.json")
dotnet run --project "$extractor" -- blueprint-call-sites \
  --build-manifest "$buildDirectory/build-manifest.json" \
  --static-census "$buildDirectory/static-census.json" \
  --mappings "$mappings" \
  --package-directory "$packageDirectory" \
  --target-function "ExecuteUbergraph_AI_Client_Character" \
  --output "$buildDirectory/blueprint-call-sites.ai-client-ubergraph.json"

The output contains game-specific wrapper locations and must remain in the ignored local acquisition directory.

14. Extract the AI client event-graph wrappers

This step verifies the preceding call-site artifact and decompiles the exact wrapper functions it found. The result maps each wrapper to the numeric entry point it passes into the AI client event graph.

dotnet run --project $extractor -- blueprint-caller-bodies `
  --build-manifest (Join-Path $buildDirectory "build-manifest.json") `
  --call-sites (Join-Path $buildDirectory "blueprint-call-sites.ai-client-ubergraph.json") `
  --mappings $mappings `
  --package-directory $packageDirectory `
  --output (Join-Path $buildDirectory "blueprint-caller-bodies.ai-client-ubergraph.json")
dotnet run --project "$extractor" -- blueprint-caller-bodies \
  --build-manifest "$buildDirectory/build-manifest.json" \
  --call-sites "$buildDirectory/blueprint-call-sites.ai-client-ubergraph.json" \
  --mappings "$mappings" \
  --package-directory "$packageDirectory" \
  --output "$buildDirectory/blueprint-caller-bodies.ai-client-ubergraph.json"

The output contains game-specific wrapper pseudocode and must remain in the ignored local acquisition directory.

15. Create the typed Blueprint function trace

This step rereads the exact functions in the three caller-body artifacts from cooked Kismet bytecode. It writes typed nodes for calls, call arguments, branches, jumps, assignments, variables, symbols, literals, contexts, and returns. Each input file is recorded by hash, and the command confirms that its functions and target calls still match the game package.

dotnet run --project $extractor -- blueprint-function-trace `
  --build-manifest (Join-Path $buildDirectory "build-manifest.json") `
  --caller-bodies (Join-Path $buildDirectory "blueprint-caller-bodies.ai-client-ubergraph.json") `
  --caller-bodies (Join-Path $buildDirectory "blueprint-caller-bodies.movie-customer-entry.json") `
  --caller-bodies (Join-Path $buildDirectory "blueprint-caller-bodies.movie-return.json") `
  --mappings $mappings `
  --package-directory $packageDirectory `
  --output (Join-Path $buildDirectory "blueprint-function-trace.movie-customer.json")
dotnet run --project "$extractor" -- blueprint-function-trace \
  --build-manifest "$buildDirectory/build-manifest.json" \
  --caller-bodies "$buildDirectory/blueprint-caller-bodies.ai-client-ubergraph.json" \
  --caller-bodies "$buildDirectory/blueprint-caller-bodies.movie-customer-entry.json" \
  --caller-bodies "$buildDirectory/blueprint-caller-bodies.movie-return.json" \
  --mappings "$mappings" \
  --package-directory "$packageDirectory" \
  --output "$buildDirectory/blueprint-function-trace.movie-customer.json"

The output contains game-specific bytecode structure and must remain in the ignored local acquisition directory.

16. Create the typed rental function trace

This step rereads four exact RentSystem functions from cooked Kismet bytecode. The rental Blueprint-body artifact supplies the expected package, class, function paths, flags, and bytecode-expression counts. The command verifies that source artifact, the build, the mappings, and the game packages before and after extraction.

$rentSystemClass = "RetroRewind/Content/VideoStore/core/blueprint/RentSystem/RentSystem.RentSystem_C:"

dotnet run --project $extractor -- rental-function-trace `
  --build-manifest (Join-Path $buildDirectory "build-manifest.json") `
  --rental-blueprint-bodies (Join-Path $buildDirectory "rental-blueprint-bodies.json") `
  --function-path ($rentSystemClass + "Weather - New Day Event") `
  --function-path ($rentSystemClass + "Get Movie ready for return") `
  --function-path ($rentSystemClass + "ExecuteUbergraph_RentSystem") `
  --function-path ($rentSystemClass + "Get Random List Of Cartridges From Rent List") `
  --mappings $mappings `
  --package-directory $packageDirectory `
  --output (Join-Path $buildDirectory "rental-function-trace.movie-return.json")
rentSystemClass="RetroRewind/Content/VideoStore/core/blueprint/RentSystem/RentSystem.RentSystem_C:"

dotnet run --project "$extractor" -- rental-function-trace \
  --build-manifest "$buildDirectory/build-manifest.json" \
  --rental-blueprint-bodies "$buildDirectory/rental-blueprint-bodies.json" \
  --function-path "${rentSystemClass}Weather - New Day Event" \
  --function-path "${rentSystemClass}Get Movie ready for return" \
  --function-path "${rentSystemClass}ExecuteUbergraph_RentSystem" \
  --function-path "${rentSystemClass}Get Random List Of Cartridges From Rent List" \
  --mappings "$mappings" \
  --package-directory "$packageDirectory" \
  --output "$buildDirectory/rental-function-trace.movie-return.json"

The output contains game-specific bytecode structure and must remain in the ignored local acquisition directory.

17. Compile the console-return mechanics

This step validates both rental artifacts and confirms the expected class, fields, defaults, functions, and decompiled expressions before writing normalized facts. The artifact records the configured rental duration, the eligibility comparison, the missing-weather result, and movement from the rented queue to the ready-to-return queue. Each fact points back to its source class, property, or function. The evidence level remains decompiled-blueprint, and runtime validation remains not-run.

Move into the TypeScript workspace if you are not already there.

Push-Location projects/typescript
pnpm install --frozen-lockfile
pushd projects/typescript >/dev/null
pnpm install --frozen-lockfile

Compile the private mechanic artifact.

pnpm console-return-mechanics `
  --rental-evidence (Join-Path $buildDirectory "rental-evidence.json") `
  --rental-evidence-schema "../game-data-exporter/schemas/acquisition/rental-evidence.schema.json" `
  --blueprint-bodies (Join-Path $buildDirectory "rental-blueprint-bodies.json") `
  --blueprint-bodies-schema "../game-data-exporter/schemas/acquisition/rental-blueprint-bodies.schema.json" `
  --output (Join-Path $domainDirectory "console-return-mechanics.json")
pnpm console-return-mechanics \
  --rental-evidence "$buildDirectory/rental-evidence.json" \
  --rental-evidence-schema "../game-data-exporter/schemas/acquisition/rental-evidence.schema.json" \
  --blueprint-bodies "$buildDirectory/rental-blueprint-bodies.json" \
  --blueprint-bodies-schema "../game-data-exporter/schemas/acquisition/rental-blueprint-bodies.schema.json" \
  --output "$domainDirectory/console-return-mechanics.json"

Return to the repository root when the command finishes.

Pop-Location
popd >/dev/null

The output contains normalized game rules and remains private and uncommitted.

18. Compile the membership-fee mechanics

This step uses the same two private rental artifacts as the console-return compiler. It confirms the membership fee map, the five-field fee record, both mutation functions, and their decompiled expressions. The result records how membership ID zero is handled, which fee counters accumulate, which counters are cleared, and how a fee record is removed. Each fact points back to its source class field, struct field, or function. The evidence level remains decompiled-blueprint, and runtime validation remains not-run.

Move into the TypeScript workspace if you are not already there.

Push-Location projects/typescript
pnpm install --frozen-lockfile
pushd projects/typescript >/dev/null
pnpm install --frozen-lockfile

Compile the private mechanic artifact.

pnpm membership-fee-mechanics `
  --rental-evidence (Join-Path $buildDirectory "rental-evidence.json") `
  --rental-evidence-schema "../game-data-exporter/schemas/acquisition/rental-evidence.schema.json" `
  --blueprint-bodies (Join-Path $buildDirectory "rental-blueprint-bodies.json") `
  --blueprint-bodies-schema "../game-data-exporter/schemas/acquisition/rental-blueprint-bodies.schema.json" `
  --output (Join-Path $domainDirectory "membership-fee-mechanics.json")
pnpm membership-fee-mechanics \
  --rental-evidence "$buildDirectory/rental-evidence.json" \
  --rental-evidence-schema "../game-data-exporter/schemas/acquisition/rental-evidence.schema.json" \
  --blueprint-bodies "$buildDirectory/rental-blueprint-bodies.json" \
  --blueprint-bodies-schema "../game-data-exporter/schemas/acquisition/rental-blueprint-bodies.schema.json" \
  --output "$domainDirectory/membership-fee-mechanics.json"

Return to the repository root when the command finishes.

Pop-Location
popd >/dev/null

The output contains normalized game rules and remains private and uncommitted.

19. Compile the movie-return mechanics

This step uses the two private rental artifacts, the complete movie-selector call-site artifact, the extracted caller-body artifact, and both typed function traces. It traces the new-day event through its Blueprint dispatcher and confirms that all rented movies move into the ready-to-return queue before the rented queue is cleared. It separately records the weighted selector's configured probabilities, override condition, four-item limit, candidate queue, and result behavior. It records complete caller-search coverage, the BeginPlay entry path, the console-first customer branch, both selector calls, and movement of selected cartridges from the ready queue into customer inventory. The compiler validates calls, arguments, branch targets, branch symbols, queue operations, selection outcomes, loop structure, and input hashes from the typed traces. It does not parse rental or customer-flow pseudocode. The evidence level remains decompiled-blueprint, and runtime validation remains not-run.

Move into the TypeScript workspace if you are not already there.

Push-Location projects/typescript
pnpm install --frozen-lockfile
pushd projects/typescript >/dev/null
pnpm install --frozen-lockfile

Compile the private mechanic artifact.

pnpm movie-return-mechanics `
  --rental-evidence (Join-Path $buildDirectory "rental-evidence.json") `
  --rental-evidence-schema "../game-data-exporter/schemas/acquisition/rental-evidence.schema.json" `
  --blueprint-bodies (Join-Path $buildDirectory "rental-blueprint-bodies.json") `
  --blueprint-bodies-schema "../game-data-exporter/schemas/acquisition/rental-blueprint-bodies.schema.json" `
  --call-sites (Join-Path $buildDirectory "blueprint-call-sites.movie-return.json") `
  --call-sites-schema "../game-data-exporter/schemas/acquisition/blueprint-call-sites.schema.json" `
  --caller-bodies (Join-Path $buildDirectory "blueprint-caller-bodies.movie-return.json") `
  --caller-bodies-schema "../game-data-exporter/schemas/acquisition/blueprint-caller-bodies.schema.json" `
  --function-trace (Join-Path $buildDirectory "blueprint-function-trace.movie-customer.json") `
  --function-trace-schema "../game-data-exporter/schemas/acquisition/blueprint-function-trace.schema.json" `
  --rental-function-trace (Join-Path $buildDirectory "rental-function-trace.movie-return.json") `
  --rental-function-trace-schema "../game-data-exporter/schemas/acquisition/rental-function-trace.schema.json" `
  --output (Join-Path $domainDirectory "movie-return-mechanics.json")
pnpm movie-return-mechanics \
  --rental-evidence "$buildDirectory/rental-evidence.json" \
  --rental-evidence-schema "../game-data-exporter/schemas/acquisition/rental-evidence.schema.json" \
  --blueprint-bodies "$buildDirectory/rental-blueprint-bodies.json" \
  --blueprint-bodies-schema "../game-data-exporter/schemas/acquisition/rental-blueprint-bodies.schema.json" \
  --call-sites "$buildDirectory/blueprint-call-sites.movie-return.json" \
  --call-sites-schema "../game-data-exporter/schemas/acquisition/blueprint-call-sites.schema.json" \
  --caller-bodies "$buildDirectory/blueprint-caller-bodies.movie-return.json" \
  --caller-bodies-schema "../game-data-exporter/schemas/acquisition/blueprint-caller-bodies.schema.json" \
  --function-trace "$buildDirectory/blueprint-function-trace.movie-customer.json" \
  --function-trace-schema "../game-data-exporter/schemas/acquisition/blueprint-function-trace.schema.json" \
  --rental-function-trace "$buildDirectory/rental-function-trace.movie-return.json" \
  --rental-function-trace-schema "../game-data-exporter/schemas/acquisition/rental-function-trace.schema.json" \
  --output "$domainDirectory/movie-return-mechanics.json"

Return to the repository root when the command finishes.

Pop-Location
popd >/dev/null

The output contains normalized game rules and remains private and uncommitted.

20. Compile the normalized film catalog

The TypeScript compiler validates the structured-values artifact against its JSON Schema. It maps the 13 catalog DataTables into film records and retains the source table path and row key for each record. The game's numeric SKU is the unique film key, and records are written in ascending SKU order. Two auxiliary tables reuse the same Unreal row structure and are explicitly excluded from the film catalog.

Move into the TypeScript workspace and install its locked dependencies.

Push-Location projects/typescript
pnpm install --frozen-lockfile
pushd projects/typescript >/dev/null
pnpm install --frozen-lockfile

Compile the catalog into the ignored local domain directory.

pnpm film-catalog `
  --input (Join-Path $buildDirectory "structured-values.json") `
  --input-schema "../game-data-exporter/schemas/acquisition/structured-values.schema.json" `
  --output (Join-Path $domainDirectory "film-catalog.json")
pnpm film-catalog \
  --input "$buildDirectory/structured-values.json" \
  --input-schema "../game-data-exporter/schemas/acquisition/structured-values.schema.json" \
  --output "$domainDirectory/film-catalog.json"

Return to the repository root when the command finishes.

Pop-Location
popd >/dev/null

The compiler creates missing output directories, accepts identical existing output, and refuses to overwrite different content. The film catalog still contains extracted game text and remains private and uncommitted.

Prepare the runtime compatibility probe

This command verifies the game executable against the supplied private build manifest and checks the exact UE4SS archive before creating an ignored local staging directory. It checks that the game is closed and that neither proposed game-directory file already exists. It does not copy anything into the game directory.

Set the paths to the private inputs and choose a new staging directory.

$runtimeExporter = "projects/game-data-exporter/runtime-exporter/NeonRewind.RuntimeExporter.csproj"
$ue4ssArchive = "C:\path\to\zDEV-UE4SS_v3.0.1-1018-g662df915.zip"
$probeScript = "projects/game-data-exporter/runtime-exporter/Probe/NeonRewindMovieReturnProbe/Scripts/main.lua"
$runtimeStageId = (Get-Date).ToUniversalTime().ToString("yyyyMMddTHHmmssZ")
$runtimeStage = "projects/game-data-exporter/.local/runtime-host/runs/$runtimeStageId/probe"

New-Item -ItemType Directory -Force -Path (Split-Path $runtimeStage) | Out-Null
runtimeExporter="projects/game-data-exporter/runtime-exporter/NeonRewind.RuntimeExporter.csproj"
ue4ssArchive="C:\path\to\zDEV-UE4SS_v3.0.1-1018-g662df915.zip"
probeScript="projects/game-data-exporter/runtime-exporter/Probe/NeonRewindMovieReturnProbe/Scripts/main.lua"
runtimeStageId="$(date -u +%Y%m%dT%H%M%SZ)"
runtimeStage="projects/game-data-exporter/.local/runtime-host/runs/$runtimeStageId/probe"

mkdir -p "$(dirname "$runtimeStage")"

Run the staging command while the game is closed.

dotnet run --project $runtimeExporter -- stage-probe `
  --ue4ss-archive $ue4ssArchive `
  --build-manifest (Join-Path $buildDirectory "build-manifest.json") `
  --game-executable $executable `
  --probe-script $probeScript `
  --output $runtimeStage
dotnet run --project "$runtimeExporter" -- stage-probe \
  --ue4ss-archive "$ue4ssArchive" \
  --build-manifest "$buildDirectory/build-manifest.json" \
  --game-executable "$executable" \
  --probe-script "$probeScript" \
  --output "$runtimeStage"

Review runtime-host-staging.json in the new staging directory. It identifies the private inputs and lists the exact size and SHA-256 hash of the proposed dwmapi.dll and override.txt files.

Preview installation while the game is closed.

$stagingManifest = Join-Path $runtimeStage "runtime-host-staging.json"

dotnet run --project $runtimeExporter -- install-probe `
  --staging-manifest $stagingManifest
stagingManifest="$runtimeStage/runtime-host-staging.json"

dotnet run --project "$runtimeExporter" -- install-probe \
  --staging-manifest "$stagingManifest"

The preview prints both source and destination paths, byte lengths, file hashes, and the staging-manifest hash. It exits with code 5 because approval was not supplied, and it does not copy either file.

Review the output, copy the displayed staging-manifest hash into $approvedStagingSha256, and rerun only when you approve that exact list.

$approvedStagingSha256 = "paste-the-reviewed-staging-manifest-sha256"

dotnet run --project $runtimeExporter -- install-probe `
  --staging-manifest $stagingManifest `
  --approve-staging-sha256 $approvedStagingSha256
approvedStagingSha256="paste-the-reviewed-staging-manifest-sha256"

dotnet run --project "$runtimeExporter" -- install-probe \
  --staging-manifest "$stagingManifest" \
  --approve-staging-sha256 "$approvedStagingSha256"

The approved command creates runtime-host-installation.json in the staging directory before copying the two files. It refuses existing targets unless it is resuming the same manifest after an interrupted installation. The tooling does not launch the game or Steam.

After using the probe, close the game before previewing cleanup.

$installationManifest = Join-Path $runtimeStage "runtime-host-installation.json"

dotnet run --project $runtimeExporter -- cleanup-probe `
  --installation-manifest $installationManifest
installationManifest="$runtimeStage/runtime-host-installation.json"

dotnet run --project "$runtimeExporter" -- cleanup-probe \
  --installation-manifest "$installationManifest"

The cleanup preview recalculates both installed file hashes and exits with code 5 without removing anything. Review the exact removal list, copy the displayed installation-manifest hash into $approvedInstallationSha256, and rerun only when you approve that exact list.

$approvedInstallationSha256 = "paste-the-reviewed-installation-manifest-sha256"

dotnet run --project $runtimeExporter -- cleanup-probe `
  --installation-manifest $installationManifest `
  --approve-installation-sha256 $approvedInstallationSha256
approvedInstallationSha256="paste-the-reviewed-installation-manifest-sha256"

dotnet run --project "$runtimeExporter" -- cleanup-probe \
  --installation-manifest "$installationManifest" \
  --approve-installation-sha256 "$approvedInstallationSha256"

Cleanup removes dwmapi.dll first and then removes override.txt. It stops before removal if the game is running, either file is missing, or either path or hash differs from the installation manifest. The ignored installation manifest remains as the local record of the approved copy.

Common problems

A command says that a file does not exist

Check $steamRoot, then run the path setup block again. Paths containing spaces are safe when passed through the variables shown above.

The output conflicts with an existing file

The artifact commands never replace different existing content. Use a new build directory for a different game build or choose a new output filename.

The structured index rejects the mapping

Confirm that the .usmap file came from the same game executable as the build manifest. The repository cannot repair or convert a mapping from another build.

pnpm is not recognized

Install pnpm 11.x, open a new PowerShell or Git Bash window, and run pnpm --version again.

Repository layout

  • projects/game-data-exporter/static-extractor contains the .NET 10 acquisition commands.
  • projects/game-data-exporter/schemas/acquisition contains the acquisition JSON Schemas.
  • projects/game-data-exporter/schemas/runtime contains the runtime observation JSON Schemas.
  • projects/game-data-exporter/schemas/validation contains the validation-report JSON Schemas.
  • projects/game-data-exporter/runtime-exporter contains the offline runtime-host staging command and Lua compatibility probe source.
  • projects/game-data-exporter/runtime-collector contains the load-only UE4SS C++ collector and its local Windows build entry points.
  • Movie-return runtime observation defines the first runtime test and the limits on its future collector.
  • projects/typescript/packages/core owns the normalized domain types and schemas.
  • projects/typescript/packages/data-compiler validates acquisition data and compiles private domain artifacts.
  • projects/typescript/packages/validator checks ordered runtime observations against deterministic mechanic relationships.

License

Original NeonRewind source code is licensed under the Apache License 2.0. NeonRewind is provided as is, without warranty of any kind, to the extent permitted by applicable law. The licence contains the complete warranty disclaimer and limitation of liability.

Disclaimer

NeonRewind is an unofficial fan project and is not affiliated with or endorsed by the developers or publishers of Retro Rewind: Video Store Simulator. The game and its related names and assets belong to their respective owners.

About

(W.I.P) S simple static Retro: Rewind guide based on the game's data

Resources

Stars

0 stars

Watchers

0 watching

Forks

Contributors

Languages