diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0abe66a..835781e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -2,9 +2,9 @@ name: CI "on": push: - branches: [main, master] + branches: [main] pull_request: - branches: [main, master] + branches: [main] workflow_dispatch: concurrency: @@ -42,6 +42,7 @@ jobs: - name: Setup Rust toolchain uses: dtolnay/rust-toolchain@stable with: + targets: wasm32-unknown-unknown components: rustfmt, clippy - name: Setup Rust cache @@ -53,8 +54,11 @@ jobs: - name: Run Clippy linter run: cargo clippy --workspace --all-targets --all-features -- -D warnings + - name: Run Clippy on WASM crate + run: cargo clippy -p ppf-wasm --target wasm32-unknown-unknown -- -D warnings + test: - name: Test (${{ matrix.os }}) + name: Test & Build (${{ matrix.os }}) runs-on: ${{ matrix.os }} strategy: fail-fast: false @@ -92,41 +96,5 @@ jobs: - name: Run tests run: cargo test --workspace --all-targets --all-features --verbose - build-check: - name: Build Check (${{ matrix.os }}) - runs-on: ${{ matrix.os }} - strategy: - fail-fast: false - matrix: - os: [ubuntu-latest, windows-latest, macos-latest] - steps: - - name: Checkout repository - uses: actions/checkout@v4 - - - name: Install Linux GUI & system dependencies - if: runner.os == 'Linux' - run: | - sudo apt-get update - sudo apt-get install -y --no-install-recommends \ - pkg-config \ - libgtk-3-dev \ - libxcb-render0-dev \ - libxcb-shape0-dev \ - libxcb-xfixes0-dev \ - libxkbcommon-dev \ - libxkbcommon-x11-dev \ - libgl1-mesa-dev \ - libegl1-mesa-dev \ - libwayland-dev \ - libssl-dev - - - name: Setup Rust toolchain - uses: dtolnay/rust-toolchain@stable - - - name: Setup Rust cache - uses: Swatinem/rust-cache@v2 - with: - key: ${{ matrix.os }} - - - name: Build release binaries - run: cargo build --workspace --release + - name: Build release desktop binaries + run: cargo build --release --bin ppf_cli --bin ppf_gui diff --git a/.github/workflows/deploy-pages.yml b/.github/workflows/deploy-pages.yml new file mode 100644 index 0000000..75c4221 --- /dev/null +++ b/.github/workflows/deploy-pages.yml @@ -0,0 +1,53 @@ +name: Deploy Web Patcher to GitHub Pages + +on: + push: + branches: [main] + workflow_dispatch: + +permissions: + contents: read + pages: write + id-token: write + +concurrency: + group: "pages" + cancel-in-progress: false + +jobs: + build-and-deploy: + environment: + name: github-pages + url: ${{ steps.deployment.outputs.page_url }} + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Setup Rust toolchain + uses: dtolnay/rust-toolchain@stable + with: + targets: wasm32-unknown-unknown + + - name: Setup Rust cache + uses: Swatinem/rust-cache@v2 + + - name: Install wasm-bindgen CLI + run: cargo install wasm-bindgen-cli --version 0.2.100 --locked + + - name: Build WebAssembly and Bindings + run: | + cargo build --package ppf-wasm --target wasm32-unknown-unknown --release + wasm-bindgen --target web --out-dir web/pkg --out-name ppf_wasm target/wasm32-unknown-unknown/release/ppf_wasm.wasm + + - name: Setup Pages + uses: actions/configure-pages@v5 + + - name: Upload Pages artifact + uses: actions/upload-pages-artifact@v3 + with: + path: 'web' + + - name: Deploy to GitHub Pages + id: deployment + uses: actions/deploy-pages@v4 diff --git a/Cargo.lock b/Cargo.lock index be33eee..87cb2f2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -385,6 +385,15 @@ version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0d8c1fef690941d3e7788d328517591fecc684c084084702d6ff1641e993699a" +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] + [[package]] name = "block2" version = "0.5.1" @@ -702,6 +711,15 @@ dependencies = [ "libc", ] +[[package]] +name = "cpufeatures" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" +dependencies = [ + "libc", +] + [[package]] name = "crc32fast" version = "1.5.0" @@ -736,12 +754,32 @@ version = "0.8.22" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "61803da095bee82a81bb1a452ecc25d3b2f1416d1897eb86430c6159ef717c17" +[[package]] +name = "crypto-common" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78c8292055d1c1df0cce5d180393dc8cce0abec0a7102adb6c7b1eef6016d60a" +dependencies = [ + "generic-array", + "typenum", +] + [[package]] name = "cursor-icon" version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f27ae1dd37df86211c42e150270f82743308803d90a6f6e6651cd730d5e1732f" +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer", + "crypto-common", +] + [[package]] name = "dispatch" version = "0.2.0" @@ -1163,6 +1201,16 @@ dependencies = [ "slab", ] +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", +] + [[package]] name = "gethostname" version = "1.1.0" @@ -1563,12 +1611,11 @@ dependencies = [ [[package]] name = "js-sys" -version = "0.3.104" +version = "0.3.77" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e0c1080212aad755ea003d18543e8768dd432c48819efd73a7bf1e39b7a5a3a" +checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f" dependencies = [ - "cfg-if", - "futures-util", + "once_cell", "wasm-bindgen", ] @@ -1665,6 +1712,16 @@ dependencies = [ "libc", ] +[[package]] +name = "md-5" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d89e7ee0cfbedfc4da3340218492196241d89eefb6dab27de5df917a6d2e78cf" +dependencies = [ + "cfg-if", + "digest", +] + [[package]] name = "memchr" version = "2.8.3" @@ -2288,7 +2345,7 @@ dependencies = [ [[package]] name = "ppf-cli" -version = "0.2.0" +version = "0.3.1" dependencies = [ "anyhow", "clap", @@ -2298,22 +2355,39 @@ dependencies = [ [[package]] name = "ppf-core" -version = "0.2.0" +version = "0.3.1" dependencies = [ "memmap2", "rayon", + "serde", "tempfile", "thiserror 2.0.20", ] [[package]] name = "ppf-gui" -version = "0.2.0" +version = "0.3.1" dependencies = [ + "crc32fast", "eframe", "egui", + "image", + "md-5", "ppf-core", "rfd", + "sha1", + "tempfile", +] + +[[package]] +name = "ppf-wasm" +version = "0.3.1" +dependencies = [ + "js-sys", + "ppf-core", + "serde", + "serde-wasm-bindgen", + "wasm-bindgen", ] [[package]] @@ -2593,6 +2667,17 @@ dependencies = [ "serde_derive", ] +[[package]] +name = "serde-wasm-bindgen" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8302e169f0eddcc139c70f139d19d6467353af16f9fce27e8c30158036a1e16b" +dependencies = [ + "js-sys", + "serde", + "wasm-bindgen", +] + [[package]] name = "serde_core" version = "1.0.229" @@ -2624,6 +2709,17 @@ dependencies = [ "syn 3.0.3", ] +[[package]] +name = "sha1" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a978451301f4db1d02937a4ab3ccce137717b81826e79b7d49ffe3244a13c3b8" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + [[package]] name = "shlex" version = "2.0.1" @@ -2975,6 +3071,12 @@ dependencies = [ "rustc-hash 2.1.3", ] +[[package]] +name = "typenum" +version = "1.20.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6f5e870be6c3b371b77fe0ee0bafb859fa4964b4404c27de1d380043c4dda20" + [[package]] name = "uds_windows" version = "1.2.1" @@ -3091,32 +3193,48 @@ dependencies = [ [[package]] name = "wasm-bindgen" -version = "0.2.127" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b70935747edd64d89de3efa29d73789b806c15798f8e7dca4d8ac356b50ce70" +checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5" dependencies = [ "cfg-if", "once_cell", "rustversion", "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6" +dependencies = [ + "bumpalo", + "log", + "proc-macro2", + "quote", + "syn 2.0.119", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-futures" -version = "0.4.77" +version = "0.4.50" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b7777d5cc23d0e91404e53ce2d5e8ec7acae3026b16233dba62cd3246457950" +checksum = "555d470ec0bc3bb57890405e5d4322cc9ea83cebb085523ced7be4144dac1e61" dependencies = [ + "cfg-if", "js-sys", + "once_cell", "wasm-bindgen", + "web-sys", ] [[package]] name = "wasm-bindgen-macro" -version = "0.2.127" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77775f8f3f7217702089053b94958f8f54061a3f663417df76e19cbdcca29bc1" +checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -3124,22 +3242,22 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.127" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e11d33f857dc2fb11b8bc75aee111aa9cbeb12cd9f25efd3d4c2a3dd4e235284" +checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" dependencies = [ - "bumpalo", "proc-macro2", "quote", "syn 2.0.119", + "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.127" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ef64dbcc55df09c7e5a46182d181c2cfa3e925f3da937ea764728b4bbb9dcbf" +checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d" dependencies = [ "unicode-ident", ] @@ -3281,9 +3399,9 @@ dependencies = [ [[package]] name = "web-sys" -version = "0.3.104" +version = "0.3.77" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c435338968042f4f59a557f690a253676d47ce13ceb55d70100e7facf6620a30" +checksum = "33b6dd2ef9186f1f2072e409e99cd22a975331a6b3591b12c764e0e55c60d5d2" dependencies = [ "js-sys", "wasm-bindgen", diff --git a/Cargo.toml b/Cargo.toml index f790fdf..0d88505 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,11 +3,12 @@ members = [ "crates/ppf-core", "crates/ppf-cli", "crates/ppf-gui", + "crates/ppf-wasm", ] resolver = "2" [workspace.package] -version = "0.2.0" +version = "0.3.1" edition = "2024" authors = ["Aliet Exposito"] license = "MIT" @@ -17,6 +18,10 @@ repository = "https://github.com/plinkr/ppf_rust" ppf-core = { path = "crates/ppf-core" } anyhow = "1.0.104" thiserror = "2.0.20" +serde = { version = "1.0.218", features = ["derive"] } +wasm-bindgen = "=0.2.100" +serde-wasm-bindgen = "0.6.5" +js-sys = "=0.3.77" memmap2 = "0.9.11" rayon = "1.12.0" clap = { version = "4.6.6", features = ["derive"] } @@ -25,6 +30,10 @@ eframe = { version = "0.29.1", default-features = false, features = ["default_fo egui = "0.29.1" rfd = "0.15.2" tempfile = "3.27.0" +image = { version = "0.25.10", default-features = false, features = ["png"] } +md-5 = "0.10.6" +sha1 = "0.10.6" +crc32fast = "1.4.2" [profile.release] opt-level = 3 diff --git a/README.md b/README.md index ce31d8a..e27da25 100644 --- a/README.md +++ b/README.md @@ -4,14 +4,14 @@ High-performance Rust suite for creating, applying, inspecting, and reverting patches in the **PlayStation Patch File (PPF v1.0, v2.0, and v3.0)** format. -The project is organized as a modular **Cargo Workspace** comprising a core engine library (`ppf-core`), a command-line interface tool (`ppf-cli`), and a desktop graphical user interface (`ppf-gui`) built with `egui`. +The project is organized as a modular **Cargo Workspace** comprising a core engine library (`ppf-core`), a command-line interface tool (`ppf-cli`), a desktop graphical user interface (`ppf-gui`) built with `egui`, a WebAssembly package (`ppf-wasm`), and a static web client (`web/`) in HTML5 and JavaScript. -Implements concurrency with Rayon and memory-mapped I/O (`memmap2`), delivering maximum processing throughput with strict memory safety. +For desktop tools (`ppf-cli` and `ppf-gui`), it implements concurrency with Rayon and memory-mapped I/O (`memmap2`), delivering maximum processing throughput with strict memory safety. ---
A few screenshots, click a thumbnail to open the full image.
+Screenshots (click a thumbnail to view full size):
Capturas de pantalla (haz clic en una miniatura para verla en tamaño completo):
+ +Drag & drop your target binary image here, or
+Drag & drop your .ppf patch file here, or
+Drag & drop clean original binary here, or
+Drag & drop modified binary here, or
+Drag & drop any .ppf patch file here, or
++ This tool allows you to easily apply, reverse, and create PPF (PlayStation Patch Format) patches for disc images (CD/DVD) and ROM files directly in your web browser with native WebAssembly performance. +
+ +PPF (PlayStation Patch Format) is a binary diff patching standard originally designed for PlayStation CD-ROM images and widely used for translations, game modifications, and fan patches.
+If a PPF 3.0 patch was created with Undo Data enabled, you can completely reverse the changes and restore the original binary bytes without needing a fresh game dump.
+The target binary image size does not match what the patch expects. Make sure you are using an uncompressed raw image (.bin/.iso).
+The disc image checksum did not match. You might be using a different game region (e.g. NTSC vs PAL), a bad dump, or a file that has already been patched.
+This patch is a one-way patch and did not include original restoration data.
+