Skip to content

Commit

Permalink
feat: VPURemix patching (#393)
Browse files Browse the repository at this point in the history
  • Loading branch information
francisdb authored Nov 8, 2024
1 parent 2e3c93e commit b5bcead
Show file tree
Hide file tree
Showing 4 changed files with 98 additions and 21 deletions.
10 changes: 10 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ regex = { version = "1.11.1", features = [] }
vpin = { version = "0.15.6" }
rust-ini = "0.21.1"
edit = "0.1.5"
jojodiff = "0.1.2"

[dev-dependencies]
pretty_assertions = "1.4.1"
Expand Down
41 changes: 25 additions & 16 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ 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.
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
Expand All @@ -28,19 +29,24 @@ Extracts and assembles vpx files
Usage: vpxtool [COMMAND]
Commands:
info Show information about a vpx file
diff Prints out a diff between the vbs in the vpx and the sidecar vbs
frontend Acts as a frontend for launching vpx files
index Indexes a directory of vpx files
script Cat the vpx script
ls List directory contents without extracting the vpx file
extract Extracts a vpx file
extractvbs Extracts the vbs from a vpx file next to it
importvbs Imports the vbs next to it into a vpx file
verify Verify the structure of a vpx file
assemble Assembles a vpx file
new Creates a minimal empty new vpx file
help Print this message or the help of the given subcommand(s)
info Vpx table info related commands
diff Prints out a diff between the vbs in the vpx and the sidecar vbs
frontend Text based frontend for launching vpx files
simplefrontend Simple text based frontend for launching vpx files
index Indexes a directory of vpx files
script Vpx script code related commands
ls Show a vpx file content
extract Extracts a vpx file
extractvbs Extracts the vbs from a vpx file next to it
importvbs Imports the vbs next to it into a vpx file
verify Verify the structure of 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
gamedata Vpx gamedata related commands
help Print this message or the help of the given subcommand(s)
Options:
-h, --help Print help
Expand Down Expand Up @@ -75,13 +81,15 @@ launch them.
A configuration file will be written to store the Visual Pinball executable location.

To show the current config location use the following command

```
vpxtool config show
```

### 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 you can add the following line to the config file:
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 you can add the following line to the config file:

```yaml
# use Visual Studio Code as default editor
Expand Down Expand Up @@ -110,6 +118,7 @@ https://github.com/vbousquet/flexdmd/tree/master/FlexDemo

## Building

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

`cargo build --release`
67 changes: 62 additions & 5 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,11 @@ use console::Emoji;
use git_version::git_version;
use indicatif::{ProgressBar, ProgressDrawTarget, ProgressStyle};
use std::error::Error;
use std::ffi::OsStr;
use std::fmt::Display;
use std::fs::{metadata, File};
use std::io;
use std::io::{BufReader, Read, Write};
use std::io::{BufReader, BufWriter, Read, Write};
use std::path::{Path, PathBuf};
use std::process::{exit, ExitCode};
use vpin::directb2s::read;
Expand All @@ -38,6 +39,9 @@ const CMD_EXTRACT: &str = "extract";
const CMD_ASSEMBLE: &str = "assemble";
const CMD_EXTRACT_VBS: &str = "extractvbs";
const CMD_IMPORT_VBS: &str = "importvbs";
const CMD_PATCH: &str = "patch";
const CMD_VERIFY: &str = "verify";
const CMD_NEW: &str = "new";

const CMD_SIMPLE_FRONTEND: &str = "simplefrontend";

Expand Down Expand Up @@ -569,8 +573,54 @@ fn handle_command(matches: ArgMatches) -> io::Result<ExitCode> {
}
}
}
Some((CMD_PATCH, sub_matches)) => {
let vpx_path = sub_matches
.get_one::<String>("VPXPATH")
.map(|s| Path::new(OsStr::new(s)))
.expect("VPXPATH is required");
let patch_path = sub_matches
.get_one::<String>("PATCHPATH")
.map(|s| Path::new(OsStr::new(s)))
.expect("PATCHPATH is required");
let patched_vpx_path = sub_matches
.get_one::<String>("OUTVPXPATH")
.map(PathBuf::from)
.unwrap_or_else(|| vpx_path.with_extension("patched.vpx"));

if !vpx_path.exists() {
return Err(io::Error::new(
io::ErrorKind::NotFound,
format!("VPXPATH not found: {}", vpx_path.display()),
));
}
if !patch_path.exists() {
return Err(io::Error::new(
io::ErrorKind::NotFound,
format!("PATCHPATH not found: {}", patch_path.display()),
));
}
if patched_vpx_path.exists() {
return Err(io::Error::new(
io::ErrorKind::AlreadyExists,
format!("OUTVPXPATH already exists: {}", patched_vpx_path.display()),
));
}
let vpx_file = File::open(vpx_path)?;
let patch_file = File::open(patch_path)?;
let patched_vpx_file = File::create(patched_vpx_path)?;

let mut vpx_reader = BufReader::new(vpx_file);
let mut patch_reader = BufReader::new(patch_file);
let mut patched_vpx_writer = BufWriter::new(patched_vpx_file);

jojodiff::patch(&mut vpx_reader, &mut patch_reader, &mut patched_vpx_writer)?;

patched_vpx_writer.flush()?;

Some(("verify", sub_matches)) => {
Ok(ExitCode::SUCCESS)
}

Some((CMD_VERIFY, sub_matches)) => {
let paths: Vec<&str> = sub_matches
.get_many::<String>("VPXPATH")
.unwrap_or_default()
Expand All @@ -591,7 +641,7 @@ fn handle_command(matches: ArgMatches) -> io::Result<ExitCode> {
}
Ok(ExitCode::SUCCESS)
}
Some(("new", sub_matches)) => {
Some((CMD_NEW, sub_matches)) => {
let path = {
let this = sub_matches.get_one::<String>("VPXPATH").map(|v| v.as_str());
match this {
Expand Down Expand Up @@ -918,7 +968,7 @@ fn build_command() -> Command {
),
)
.subcommand(
Command::new("verify")
Command::new(CMD_VERIFY)
.about("Verify the structure of a vpx file")
.arg(
arg!(<VPXPATH> "The path(s) to the vpx file(s)")
Expand All @@ -940,7 +990,14 @@ fn build_command() -> Command {
.arg(arg!([VPXPATH] "Optional path of the VPX file to assemble to. Defaults to <DIRPATH>.vpx.")),
)
.subcommand(
Command::new("new")
Command::new(CMD_PATCH)
.about("Applies a VPURemix System patch to a table")
.arg(arg!(<VPXPATH> "The path to the vpx file").required(true))
.arg(arg!(<PATCHPATH> "The path to the dif file").required(true))
.arg(arg!(<OUTVPXPATH> "The path to the output vpx file. Defaults to <VPXPATH>.patched.vpx").required(false))
)
.subcommand(
Command::new(CMD_NEW)
.about("Creates a minimal empty new vpx file")
.arg(arg!(<VPXPATH> "The path(s) to the vpx file").required(true)),
)
Expand Down

0 comments on commit b5bcead

Please sign in to comment.