Skip to content
francisdbPublic

About

Terminal based frontend and utilities for Visual Pinball

Topics

Resources

Stars

54 stars

Watchers

2 watching

Forks

Repository files navigation

vpxtool

Cross-platform utility for the vpinball ecosystem

Join #vpxtool on "Virtual Pinball Chat" discord for support and questions.

Install

Download the latest release for your operating system at https://github.com/francisdb/vpxtool/releases, extract it and if wanted copy or symlink the binary to $HOME/bin to put in on your path

macOS

After extracting the archive you will have to remove the quarantine flag through System Settings / Privacy & Security / Allow Anyway button or on the command line as shown below.

xattr -d com.apple.quarantine vpxtool

Homebrew

@gitfool set up a homebrew tap for vpxtool, with installation instructions in its repository:

https://github.com/gitfool/homebrew-vpinball

Using cargo

If you have cargo installed you can install vpxtool with the following command:

cargo install vpxtool

Usage

Command Line Interface (CLI)

Show help

> vpxtool --help
Vpxtool v0.35.1

Terminal based frontend and utilities for Visual Pinball

Usage: vpxtool [OPTIONS] [COMMAND]

Commands:
  info         Vpx table info related commands
  table        Vpx table level commands
  diff         Prints out a diff between the vbs in the vpx and the sidecar vbs
  frontend     Text based frontend for launching vpx files
  index        Indexes a directory of vpx files
  capture      Capture a playfield screenshot using vpinball
  script       Vpx script code related commands
  ls           Show the vpx file contents
  extract      Extracts a vpx file
  extractvbs   Extracts the script from a vpx file
  importvbs    Imports the vbs next to it into a vpx file
  verify       Verify the structure of a vpx file
  audit        Reports consistency problems in a vpx file
  optimize     Shrinks and repairs a vpx file
  lock         Lock a vpx file, preventing edits in vpinball
  unlock       Unlock a vpx file
  lock-status  Show the lock state of a vpx file
  convert      Converts a vpx file to a table pack, or a table pack to a vpx file
  assemble     Assembles a vpx file
  patch        Applies a VPURemix System patch to a table
  new          Creates a minimal empty new vpx file
  config       Vpxtool related config file
  images       Vpx image related commands
  sounds       Vpx sound related commands
  collections  Vpx collection related commands
  materials    Vpx material related commands
  gameitems    Vpx gameitem (table element) related commands
  gamedata     Vpx gamedata related commands
  dipswitches  NVRAM file DIP switch related commands
  nvram        PinMAME NVRAM related commands
  scores       Table high-score related commands
  romname      Prints the PinMAME ROM name from a vpx file
  export       Export a vpx table to obj, gltf or glb, or to a vpxz mobile archive
  help         Print this message or the help of the given subcommand(s)

Options:
  -v, --verbose  Enable verbose logging
  -h, --help     Print help
  -V, --version  Print version

Show help for a specific command

> vpxtool frontend --help
Text based frontend for launching vpx files

Usage: vpxtool frontend [OPTIONS]

Options:
  -r, --recursive              Recursively index subdirectories
  -v, --verbose                Enable verbose logging
      --max-depth <MAX_DEPTH>  Maximum directory depth to scan when indexing tables
  -h, --help                   Print help

Extracting part of a table

extract writes the whole table as a directory of JSON, script, image, sound and mesh files. To get only some of them, filter on the paths that ls prints, relative to the output directory. A * does not cross a directory separator, so gameitems/*.json is the game item files and *.json the top level index files.

# only the game data
vpxtool extract --only gamedata.json table.vpx
# the script and every game item, but no meshes
vpxtool extract --only script.vbs --only 'gameitems/*.json' table.vpx
# everything except the image and sound files; their index files are still written
vpxtool extract --no-media table.vpx

Files that are filtered out are not produced at all, so extracting only the JSON of a large table takes milliseconds. A partial directory cannot be assembled back into a table.

Table packs

vpinball can also store a table as a pack: JSON documents and the assets in their own formats, as a .vpz zip archive or as a folder. convert turns a vpx file into a pack and back, the way vpinball saves them; the output is a vpx file for a .vpx name, a zip archive for a .vpz name and a folder otherwise.

vpxtool convert table.vpx              # -> table.vpz
vpxtool convert table.vpz "Table 1.5"  # -> a pack folder
vpxtool convert "Table 1.5"            # -> Table 1.5.vpx

audit and info show also take a pack, and the frontend indexes and launches packs, see below.

Verifying a table

verify checks the signature (MAC) vpinball stores in a table against its content. --json prints the stored and the computed MAC of each file, for scripting:

vpxtool verify --json table.vpx

Shrinking a table

optimize applies the lossless fixes from the vpin library and rewrites the table in one go, which also compacts the file: unused embedded fonts are dropped, and bitmap, png and tga images are re-encoded as lossless webp where that is smaller. Images the script hands to FlexDMD are left alone. Sounds with the legacy * Backglass Output * path, which vpinball 10.8.1 fails to load, get the sound name with .wav as path. It prints what changed with the bytes saved and what was left alone and why; --dry-run reports without writing.

--mono downmixes stereo playfield sounds to the mono vpinball 10.8.1 and later play them as, exactly as vpinball does it, and --flac re-encodes PCM WAV sounds as lossless FLAC. Both are opt-in: vpinball 10.8.0 plays stereo playfield sounds in stereo in its two speaker mode and does not decode FLAC.

--max-image-size scales every image with a side over that many pixels down to fit, keeping the aspect ratio, for phones and other devices with a texture size limit; without a value it takes 1536, vpinball's mobile default. vpinball does the same on load for images over its "Maximum texture dimension" video setting (1536 by default on mobile), so the table stores what such a device shows anyway, resampled once with a better filter, and no longer carries the pixels the device throws away: the file is smaller, loads faster and needs less memory. It is lossy, a jpeg is re-encoded, so keep the original for other setups. Images FlexDMD draws, color grade LUTs and images whose smaller encoding would not be smaller are left alone and reported.

vpxtool optimize table.vpx
vpxtool optimize --dry-run table.vpx
vpxtool optimize --mono --flac table.vpx
vpxtool optimize table.vpx --max-image-size
vpxtool optimize --max-image-size=768 table.vpx

audit reports the findings these fixes act on, next to everything else it checks.

Logging

To get more information about what vpxtool is doing, you can set the -v flag to increase verbosity.

vpxtool -v extract test.vpx

You can also set the log level using the RUST_LOG environment variable. For example to get debug output:

RUST_LOG=debug vpxtool extract test.vpx

High scores

Show the high-score entries stored for a table:

vpxtool scores show /path/to/table.vpx

Works with PinMAME tables (resolved through pinmame-nvram maps) as well as rom-less tables backed by VPReg.ini, GLF <cGameName>_glf.ini sidecars, or Black's-style user/*.txt EM hiscore files. Use --format tsv for scripting or --format pinemhi for a PINemHi-like layout.

Text UI Frontend

Vpxtool can act as a frontend for launching vpx files. It will index a directory of vpx files and then present a menu to launch them. Table packs, a .vpz file or a folder with a vpinball pack manifest.json, are indexed and launched too; they need a vpinball version that loads packs, and the menu only offers the actions that do not read the vpx file itself.

> vpxtool frontend

Frontend

Every launch from the frontend is appended to a play log in the platform data directory (~/.local/share/vpxtool/play_log.jsonl on Linux). The "Recently played" and "Most played" entries in the main menu are built from it; runs shorter than 30 seconds are kept in the log but do not count as a play.

Configuration

A configuration file will be written to store among others the Visual Pinball executable location. The config file is using the TOML format.

When launching the frontend for the first time, it will help you to set up the required settings.

The config file is stored in the default config location for your operating system:

  • Linux: $XDG_CONFIG_HOME/vpxtool/vpxtool.cfg or $HOME/.config/vpxtool/vpxtool.cfg
  • macOS: $HOME/Library/Application Support/vpxtool/vpxtool.cfg
  • Windows: C:\Users\<user>\AppData\Roaming\vpxtool\vpxtool.cfg

To show the current config location, use the following command:

vpxtool config path

To edit the config file using your system default editor, do the following:

vpxtool config edit

Configuring vpinball paths

vpx_executable = "/home/myuser/vpinball/VPinballX_BGFX"

# Optional settings below, only needed if the defaults don't work
tables_folder = "/home/myuser/vpinball/tables"
vpx_config = "/home/myuser/.local/share/VPinballX/10.8/VPinballX.ini"
# how deep the frontend looks for tables below the tables folder
tables_scan_max_depth = 3

Further settings will be picked up from the Visual Pinball config.

Launch templates

Sometimes you want to use a different executables, extra arguments or environment variables. This can be done by setting up launch templates. Each entry will show up on top of the frontend table menu.

To force fullscreen or windowed mode, point a template at a separate vpinball ini file (passed to vpinball as -Ini <path>) with the relevant FullScreen / PlayfieldFullScreen keys overridden. The previous -EnableTrueFullscreen / -DisableTrueFullscreen CLI flags are deprecated upstream and not present in modern (BGFX) vpinball builds.

[[launch_templates]]
name = "Launch fullscreen"
executable = "/home/myuser/vpinball/VPinballX_BGFX"
vpinball_config = "/home/myuser/.local/share/VPinballX/10.8/VPinballX.fullscreen.ini"

[[launch_templates]]
name = "Launch GL"
executable = "/home/myuser/vpinball/VPinballX_GL"
[launch_templates.env]
SDL_VIDEODRIVER = "X11"

Configuring a custom diff

When actions are invoked that run diff, the default diff configured for your system will be used. In case you want to override this with a specific diff, optionally specifying the path, you can add the following line to the config file:

# use mydiff as default diff
diff = "/path/to/mydiff"

Configuring a custom editor

When actions are invoked that open an editor, the default editor configured for your system will be used. In case you want to override this with a specific editor, optionally specifying the path, you can add the following line to the config file:

# use Visual Studio Code as default editor
editor = "code"

Excluding files from export vpxz

vpxtool export vpxz bundles the chosen vpx and its parent-folder contents into a .vpxz archive for the Visual Pinball mobile app. A few classes of files are dropped automatically:

  • other .vpx files in the tree (the mobile importer rejects archives with more than one vpx) and their stem-keyed sidecars,
  • .directb2s files whose stem doesn't match the chosen vpx,
  • previously generated .vpxz archives.

Anything else is included by default. To skip additional patterns, set vpxz_excludes in the config file. Patterns are gitignore-ish globs matched against paths relative to the vpx's parent folder; a trailing / matches the directory both at the top level and nested anywhere:

vpxz_excludes = [
    "Downloads/",          # the table author's original archive / install docs
    "downloads/",
    "cache/",              # VPX runtime cache, regenerated on the device
    "**/Thumbs.db",        # Windows folder thumbnails
    "**/.DS_Store",        # macOS folder metadata
    "**/*.bak",            # editor / VPX backups
    "**/*~",               # Emacs-style backups

    # Add your own. Examples:
    # "user/",             # also drop desktop save state (high scores, options)
    # "**/*.pov",          # camera POV files (desktop only)
    # "**/*.res",          # legacy B2S Server resolution files (desktop only)
]

The list above is the built-in default; if you don't set vpxz_excludes, that's what gets applied. Setting it replaces the default in full, so copy the entries you still want.

Projects using vpxtool

References / Research

Other related projects that read and/or assemble vpx files:

An example vpx managed in github with some imagemagick scripts to compose textures

https://github.com/vbousquet/flexdmd/tree/master/FlexDemo

Building

The project uses the default rust build tool cargo. To get going read the docs on installation and first steps at https://doc.rust-lang.org/cargo/

Some dependencies require extra dependencies. Make sure you install developer tools:

  • Fedora: sudo dnf install @development-tools
  • Ubuntu: sudo apt install build-essential

cargo build --release

About

Terminal based frontend and utilities for Visual Pinball

Topics

Resources

Stars

54 stars

Watchers

2 watching

Forks

Releases

Packages

Used by

Contributors

Languages