PORTCLUB
Port nativo

V2000 (OpenV2K)

Port nativo de V2000 (OpenV2K) para PC.

V2000 (OpenV2K)

Port nativo basado en su ficha de origen.

README del repositorio

OpenV2K

OpenV2K is an open-source Rust reimplementation of V2000 (Frontier Developments, 1998), rebuilt from reverse engineering of the original executable, its data formats, and observed retail runtime behavior.

Unofficial fan project. OpenV2K is not affiliated with, endorsed by, or connected to Frontier Developments. "V2000" and related names belong to their respective owners. You need an original copy of V2000 to play. This repository and its releases contain no original game data, executables, videos, or music. The game loads those from your own installation, and the launcher verifies them against known retail checksums.

Status

The whole campaign plays, from Level 1 to the Queen and the closing scene. That includes the retail frontend (intro, menu ring, New Game / Load / settings, the attract demo), native save loading, campaign checkpoints and the cheats. Every map-placed actor in the 36 campaign worlds runs its recovered retail behavior. Pieces that are not proven yet stop with a logged message instead of guessing; the largest are the Possession Ray's takeover and its MindBall. Network play, retail's deathmatch for up to eight players, runs between port machines over the port's own transport; its held parts are in docs/re/MULTIPLAYER.md. docs/re/PORT_FIDELITY_GAPS.md and WATER_WORLD_TODO.md track known gaps.

RE coverage

Of the 1,761 game functions in retail V2000.EXE the port covers (642 omitted), 1,761 (100.0%) are referenced by the port's code and 1,761 (100.0%) by its code or RE notes. How this is measured.

Map of the retail functions by RE note and state

Playing

Each release has Windows and Linux (x86-64) builds.

Windows

  1. Download and extract the windows-x64 zip.
  2. Run OpenV2K.exe. If its folder doesn't already contain V2000 data, the pre-game launcher can do one of two things. It can place the executable into an existing V2000 installation, or it can install the data and music from your BIN/CUE or ISO disc image.
  3. Press Play.

Releases are unsigned, so Windows SmartScreen may warn on first launch.

Linux

Run ./openv2k for the launcher: choose an existing V2000 installation with Change..., or Install from disc image..., then press Play. Options offers the same rows as on Windows. The command line works without it:

tar -xzf OpenV2K-*-linux-x64.tar.gz && cd OpenV2K-*-linux-x64
./openv2k                                      # the launcher
./openv2k --data-dir /path/to/V2000            # play an existing installation directly
./openv2k install --image V2000.bin --destination ~/V2000   # or install from disc

SDL2 is built into the binary. Windows is the primary platform; Linux builds are newer and less tested.

Controllers

Plug in a game controller at any time; the game follows the one used last. The launcher's Options choose its layout:

  • Remastered (the default): a modern layout, menus included, with the right stick moving the camera.
  • Console original: the PlayStation release's bindings on every screen.
  • PC original: as on the 1998 PC release, a pad only flies the craft.

Without the launcher, pass --controller-layout pc-original, console-original or remastered, or set controller_layout in port-config.json beside the game data. Steam Input presents a Steam Deck's controls as a standard pad. The layouts are in CONTROLS.md.

Fixes for the original's bugs

The game runs the original's own code paths, including its frame rate cap of 125 fps. Where the original breaks on a fast PC, the port adds a fix, on by default. The launcher's Options show each fix, and turning it off restores the original behavior:

  • The C and D beam commands work at high frame rates: on a fast PC the original ignores C (collect) and D (drop). Pass --beam-commands false for one run, or set fixes.beam_commands in port-config.json.

Reverse-engineering notes

docs/re/ holds the reverse-engineering writeups behind the port: file formats, the render pipeline, actor runtimes, game mechanics, saves, and more. Start with FORMAT_DOCUMENTATION.md, GAME_MECHANICS.md and RENDER_PIPELINE.md. The notes cite retail functions and addresses. Some mention private analysis material, such as decompiler output and time-travel debugging traces, that is not published here.

V2000 is the direct predecessor of Frontier's Infestation (2000), ported by the sibling project OpenInfestation. The build paths left in Infestation's executable name its source tree V3000, and it runs on a C++ port of V2000's engine, with V2000's software rasterizer, data formats and much of its platform code carried over. INFESTATION_CROSS_REFERENCE.md gives the proof and maps the shared parts.

Building

Requirements: Rust (stable-x86_64-pc-windows-gnu), MinGW-w64 GCC and CMake on PATH. Run everything from the repository root.

cargo build --release --workspace
cargo check --workspace --all-targets
cargo test --workspace
cargo test -p v2k-game --test menu_pools

The game binary is target/release/v2k-game.exe. Release builds rename it to OpenV2K.exe.

On x86_64-pc-windows-gnu, the repository Cargo configuration selects a GCC linker launcher. The launcher uses the active Rust toolchain's bundled LLD. The Windows game bundles a static SDL build, so the launcher can start with only its executable. Standalone visual tools still use the host SDL2 development libraries. Older GNU ld rejects rustc's .drectve -exclude-symbols records, and cargo clean cannot repair that mismatch.

With the current MinGW GCC/LLD combination, keep checkout and build-output paths free of spaces. LLD errors such as could not open followed by fragments of a spaced path mean the response-file quoting is incompatible. If you override Cargo's output location, set CARGO_TARGET_DIR to a directory without spaces.

The test profile keeps line tables for file/line backtraces but omits full type/local debug data. Without that, the game unit harness exceeds Windows PE's 4 GiB image limit.

Tests and retail data

Building and running the synthetic tests needs no game files. To enable the retail-data regression tests, copy your installation into retail/. It needs at least PRELOAD.DAT and the complete Overlay/ directory with all 212 OVLs. Git ignores everything there except its setup note. To use an installation that lives elsewhere, set an override:

$env:V2K_RETAIL_DIR = 'C:\Games\V2000'
cargo test --workspace

Absolute overrides work anywhere. Relative overrides resolve from the repository root. If the configured installation is missing, empty, or contains only its setup note, Cargo reports the retail tests as ignored with a missing-retail explanation, and the synthetic tests still run. Once any payload is present, an incomplete or corrupt installation fails the relevant tests. Load and parse failures never become skips. Cargo rechecks the directory and environment on later builds, so adding or removing the installation doesn't need cargo clean. Optional demo comparisons use demo/ or V2K_DEMO_DIR and have their own ignore reason.

After cloning, enable the repository hooks once:

git config core.hooksPath .githooks

The pre-commit hook runs scripts/progress.ps1, which regenerates the reverse-engineering progress numbers and the map in docs/progress/treemap.svg, and adds them to the commit. scripts/check.ps1 fails if they are stale.

Retail tests use #[v2k_test_support::retail_test] and v2k_test_support::retail_dir(). Keep ordinary #[test] for synthetic coverage. scripts/check.ps1 runs rustfmt, the optional-corpus policy self-test (scripts/test-retail-policy.ps1) and the workspace tests. Add -RequireRetailData for a run that must exercise the retail corpus.

Running and inspecting

For desktop play, place v2k-game.exe beside PRELOAD.DAT and Overlay/, or use the launcher's setup flow. Setup tools are tucked inside Options once that installation is valid. Saves are written directly beside the executable. For direct development runs from the repository root, use --no-launcher --data-dir retail.

cargo run --release                         # launcher; setup if executable folder lacks data
cargo run --release -- --skip-intro          # launcher; skip intro after installation
cargo run --release -- --no-launcher --data-dir retail --skip-intro # menu directly
cargo run --release -- --data-dir retail --level 13 # direct first-world diagnostic entry
cargo run --release -- --renderer opengl
cargo run --release -- verify retail
cargo run --release -- init retail --level 13 --variant 1
cargo run --release -- ovl retail/Overlay/1X14XX.OVL

The Windows binaries, pre-game launcher and SDL windows use the authored OpenV2K V-only glow icon, rendered from the same authored artwork as the animated launcher header. The ICO supplies 16–256-pixel images; SDL uses a matching transparent PNG.

Display offers In a Window, Full Screen (a real mode change, undone on exit or alt-tab) and Borderless (the desktop, without a mode change). Resolution offers the original 640x480, 800x600 and 1024x768 plus every mode the display reports, in physical pixels; in Borderless it is the desktop's size and can't be changed. Each size draws with the largest original layout inside it, while Image scaling controls presentation. OpenGL renders at the full output resolution; the software renderer draws the layout's frame before enlarging it to the output (colour depth and resolution). High Native gameplay preserves the original HUD sizing through 1024x768, then gradually reaches the 800x600 HUD proportion (1.8x at 1080p, 3.6x at 4K). The weapon/cargo group and radar follow the screen's bottom corners; the challenge timer follows the top left. The full-screen map fits separately. High Native menu/story text, sprite art, panels, clips and prop projection grow together within the selected complete canvas. Its scale is bounded by the canvas fit: up to 1.8x at 1080p and 3.6x at 4K, or 1.40625x/2.8125x for the 1024x768 layout. In-game messages use actual viewport percentage anchors and the HUD scale, with bounded wrapping and clipping; Overlay51 prompts retain their backdrop's canvas mapping. Footer logos and copyright grow independently at the actual bottom edges (1.8x/3.6x). All Native growth uses the effective short axis, preserving original matching presets; Low and 4:3/Stretched keep their existing behavior. This is a port-owned readability extension beyond the original modes, not retail visual acceptance. Two renderers are available: OpenGL (the default, chosen by Automatic) and Software, a port of retail's 16-bit software raster (SOFTWARE_RASTER.md) that draws videos, menus with their 3-D scene, 2-D overlays, and gameplay and cinematic frames with ground, water, models, edges, billboards and particles through the retail producers. Choose Software in the launcher's Options, in the game's Display menu (Rendering, which switches at once, as in the original) or with --renderer software. Automatic falls back to Software when OpenGL cannot start. Software always draws the authored frame (320×240 to 1024×768); with Native scaling it is shown at 4:3.

For the original look, choose the Software renderer: it draws the authored 640×480, 800×600 or 1024×768 frame that fits the configured Resolution (Low detail keeps 320×240) in RGB565 through the retail raster. Changing the renderer or scaling redraws the paused game immediately, with its current HUD and shield frame preserved. High layout tiers also update live when Resolution changes; changing art detail requires a restart. OpenGL's RGBA8 composition remains a documented approximation.

cargo run --release opens the Windows launcher. Play starts the frontend; --skip-intro opens the menu after Play, and --no-launcher bypasses the launcher after file validation. --level N bypasses the launcher, AVI and menu and loads that overlay immediately (debug). New Game loads the first playable world: global overlay 13 (campaign slot 1). That is Level 1.

--level is a global overlay ID, not a 1-based mission index. Ordinary direct entry constructs the persistent type-46 hovercraft before the authored actors:

You wantUse
Intro then menuomit --level
Menu only--skip-intro
First world / Level 1 immediately--level 13
A later campaign world immediately--level 14 … --level 48
Intro2 (cinematic) immediately--level 50 (development entry; not a playable craft world)

--level 20 enters a later campaign world. Direct campaign launches choose the first incoming authored route's player pose in source/record order; actual warps and saved games preserve their own arrival. The six arena overlays have no incoming routes and retain the retail controller default pose. This direct entry policy is for development; it does not unlock unsupported actor behavior.

init reports session/resource coverage. ovl prints the decoded summary for one overlay.

Retail settings use a port-owned Windows registry namespace, with a portable <data-dir>/settings.json fallback. Modern display options live separately in <data-dir>/port-config.json; older config.json preferences are imported without modifying that file. The original retail settings key is read-only. See save and settings persistence for precedence. For matched VTOL comparisons, confirm the same Sensitivity and Self Righting values in both runs.

Native retail saves

The frontend discovers native Slot00 through Slot13 files directly in the selected data directory and in its parent directory. Retail's registry-selected Save Path is a final, read-only import source. The fifteenth menu row is the original informational Used for game settings entry and cannot be overwritten. Native slots are CRC validated with retail's redundant-copy fallback. Their saved logical campaign slot is converted to the global gameplay OVL with retail's exact +12 rule; for example, native Cistern logical 18 loads global level 30, not Amazon 18. Logical 37/38 map to cinematic Intro1/Intro2 (global 49/50), so save loading accepts only interactive logical worlds 1..36 (global 13..48).

Native slots restore the player pose, controller state, weapon inventory, cargo, and campaign progress through their recovered runtime owners, while retaining the original 0x248 bytes. Unsupported inputs still fail explicitly; the current scope and remaining boundaries are documented in save restoration.

Current portable JSON saves are also compatibility previews. New writes round-trip player position, velocity, heading, body pitch/roll, and health; craft mode, fuel, damage buffer, inventory, cargo, capabilities, and campaign state are not yet persisted. Legacy level-only JSON imported from data-root/saves is non-loadable and cannot shadow a valid same-numbered legacy native slot; when no native fallback exists it is shown as unsupported. Missing and corrupt Load rows remain selectable but only dispatch error feedback: missing rows stay on the list, while corrupt, unsupported, and tail-invalid rows show the decoded Access Failed screen. Back returns through the ordinary menu fly. Probe-valid occupied Save rows use the decoded Overwrite game? Yes/No screen. Campaign saving writes a native checkpoint as SlotNN directly beside the running v2k-game executable. This writable location is independent of the game-data root, working directory, and retail Save Path. Native or JSON slots beside the executable take precedence; a corrupt or unsupported file there cannot fall through to an older import. Older data-root/saves checkpoints/JSON and native slots in the data root, its parent, or retail Save Path remain read-only load fallbacks. Loading never migrates files. Explicit saving creates or replaces the row beside the executable and retires only its same-directory JSON shadow; imported originals remain unchanged. Saving reports Game Saved or Access Failed before returning to the pause root. Portable JSON remains a compatibility API, separate from campaign saving, and writes slot_N.json beside the executable too. Retail's menu probe reads only header and state records, but the port requires a recoverable tail record too. A tail-invalid row keeps its normal probe label but cannot dispatch gameplay.

The asset workbench can audit every present native slot without launching the game:

cargo run --release -p v2k-viewer -- retail/Slot00 --mode saves

Asset Workbench

cargo run --release -p v2k-viewer -- --data-dir retail
cargo run --release -p v2k-viewer -- --data-dir retail --mode models --model player4
cargo run --release -p v2k-viewer -- --data-dir retail retail/Overlay/1X13XX.OVL --mode terrain

Run it without an OVL to browse the game's global asset ids. Models isolates the selected Section-8 root at recursion depth zero; Assemblies renders that same selected root with its linked child hierarchy. Entity Types browses the cumulative Section-12 type table and shows all four authored alternative model slots, but renders only the selected slot as one linked hierarchy. It is not a runtime-entity inspector: Section-13 per-spawn overrides, live parent/child state, and behavior-driven slot changes remain separate future work. All three 3D tabs use the same resource cache, material resolver, billboards, linked-slot materialization, and OpenGL submission path as gameplay. The map tab is explicitly a raw Section-10 diagnostic, not a reconstruction of the retail world render. Passing an OVL places it at the top of the workbench cache and selects its first global-id sprite or map; known system/resource OVLs also select their first canonical model. Because the browser keeps mutually exclusive biome packs resident together, each model preview explicitly uses its owning pack's palette when that pack has one. Shared models use the initial world's palette (or the first-world pack by default), while the runtime's normal active-level palette policy remains unchanged.

The toolbar exposes Models/Assemblies/Entity Types/Sprites/Maps, Previous/Next, the current catalog position, Find, Textures, Shadows, the selected entity-type model slot, Reset Position, and the current map layer. Reset Position is enabled only after panning a 3D preview.

  • F1 through F5 select Models, Assemblies, Entity Types, Sprites, and Maps; Tab cycles them. Left/Right browse and repeat while held; Page Up/Page Down and Space remain single-step navigation. Models and Assemblies share the selected root; the other tabs remember their own positions.
  • Click the MODEL/ASSEMBLY/TYPE/SPRITE/MAP current/total field or press G, type a one-based catalog position, and press Enter to jump directly to it. Backspace edits the number and Escape cancels without moving.
  • / or Ctrl+F edits the search. Model searches accept a global id or partial name; entity-type searches accept a type id or any of its four model names; sprite searches accept a global id; map searches accept an index or partial OVL filename. Enter finds the next match.
  • V or ] selects the next authored model slot on Entity Types; [ selects the previous slot. Alternative slots are never composed together.
  • T and H toggle model textures and shadow geometry. L cycles height, false-color terrain type, and raw height/attribute/type map channels.
  • W/A/S/D or right-button drag orbit models; +/- or the mouse wheel zooms. Middle-button drag pans in screen space; Reset Position recentres that pan without changing orbit or zoom. Selecting another 3D item or entity slot also fits and recentres it. Home returns to the first asset; Q or Esc quits.

Use ASSET_EXTRACTION.md for reproducible bulk PNG, OBJ, and WAV export rather than treating viewer screenshots as extracted data.

Crate Structure

CratePurpose
v2k-coreError types (V2kError, Result)
v2k-formatsOVL parser, section decoders (sprites, palettes, strings, preload)
v2k-extractCanonical bulk sprite/model/Section-11 exporter
v2k-gameFrontend, opening cinematic, gameplay state, entities, and controls
v2k-renderSDL/OpenGL render backends and world/model drawing
v2k-viewerRuntime-backed asset workbench and command-line exporters
v2k-inspectRead-only, fingerprinted runtime probes for the original retail executable

Original-game runtime capture

cargo build --release -p v2k-inspect
.\target\release\v2k-original-inspect.exe entities

The repeatable menu, level-load, hover-physics and audio capture scenarios are part of the private analysis tooling and are not published here.

Live diagnostics

On Windows, the game's text console starts hidden when the executable owns its console (for example, when opened from Explorer). Press the backquote/tilde key (~) in any game state to show or hide it. The hidden console retains startup output and subsequent messages. A terminal shared with a launcher such as PowerShell or Cargo is left visible at startup; redirected output still works. F11 now toggles the gameplay free-fly camera.

Press F12 in any game state to show or hide the separate reverse-engineering diagnostics window. It reports frame timing, level parameters, craft position and raw 8.8 coordinates, terrain address/type, terrain/sea/wave heights, velocity and attitude, fuel, camera state, and entity counts. Input focused on that window is isolated from gameplay; closing it only hides the panel.

For a frame-by-frame VTOL comparison, pass --vtol-trace <path.jsonl>. The optional stream records only live VTOL player callbacks and does not alter the simulation. It retains physical key states, configured Sensitivity/Self Righting, pre/post-control angle words, the five ride-surface probes, lift before and after height attenuation, velocity after the specialized force, gravity, drag, solid contact, and water-response stages, plus any bare-terrain contact normal, penetration, collision impact/damage, and post-contact hull state. For example:

cargo run --release -- --no-launcher --data-dir retail --skip-intro --vtol-trace .tmp/port-vtol-up-space.jsonl

This writes into the repository's ignored .tmp/ directory. The stage split makes a mismatch attributable without inferring intermediate force values from the final rendered pose.

Verification harness

The FGDK harness is an agent skill shared by OpenV2K and OpenInfestation. It runs either port headless and repeatable, reproduces a player's bug report, sweeps every world for regressions and, with REA, compares the port against your own copy of the retail executable.

License

OpenV2K's source code, documentation and authored artwork (including the OpenV2K launcher header and icon) are licensed under either of

at your option. Unless you explicitly state otherwise, any contribution you intentionally submit for inclusion in this work, as defined in the Apache-2.0 license, is dual licensed as above, without any additional terms or conditions.

This license does not cover V2000 itself. The original game's data, executable, audio and video remain the property of their respective owners and are not distributed with this project.

Comentarios (0)

Inicia sesión para dejar un comentario.

Sé el primero en comentar sobre este juego.