diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index 3ae24e0..188a40a 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -1,4 +1,4 @@
-# This file was autogenerated by dist: https://opensource.axo.dev/cargo-dist/
+# This file was autogenerated by dist: https://axodotdev.github.io/cargo-dist
#
# Copyright 2022-2024, axodotdev
# SPDX-License-Identifier: MIT or Apache-2.0
@@ -58,12 +58,13 @@ jobs:
steps:
- uses: actions/checkout@v4
with:
+ persist-credentials: false
submodules: recursive
- name: Install dist
# we specify bash to get pipefail; it guards against the `curl` command
# failing. otherwise `sh` won't catch that `curl` returned non-0
shell: bash
- run: "curl --proto '=https' --tlsv1.2 -LsSf https://github.com/axodotdev/cargo-dist/releases/download/v0.28.0/cargo-dist-installer.sh | sh"
+ run: "curl --proto '=https' --tlsv1.2 -LsSf https://github.com/axodotdev/cargo-dist/releases/download/v0.29.0/cargo-dist-installer.sh | sh"
- name: Cache dist
uses: actions/upload-artifact@v4
with:
@@ -117,6 +118,7 @@ jobs:
git config --global core.longpaths true
- uses: actions/checkout@v4
with:
+ persist-credentials: false
submodules: recursive
- name: Install Rust non-interactively if not already installed
if: ${{ matrix.container }}
@@ -175,6 +177,7 @@ jobs:
steps:
- uses: actions/checkout@v4
with:
+ persist-credentials: false
submodules: recursive
- name: Install cached dist
uses: actions/download-artifact@v4
@@ -224,6 +227,7 @@ jobs:
steps:
- uses: actions/checkout@v4
with:
+ persist-credentials: false
submodules: recursive
- name: Install cached dist
uses: actions/download-artifact@v4
@@ -288,4 +292,5 @@ jobs:
steps:
- uses: actions/checkout@v4
with:
+ persist-credentials: false
submodules: recursive
diff --git a/.gitignore b/.gitignore
index ea8c4bf..1317ea1 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1 +1,3 @@
/target
+/.idea
+*.lock
\ No newline at end of file
diff --git a/.idea/.gitignore b/.idea/.gitignore
deleted file mode 100644
index b58b603..0000000
--- a/.idea/.gitignore
+++ /dev/null
@@ -1,5 +0,0 @@
-# Default ignored files
-/shelf/
-/workspace.xml
-# Editor-based HTTP Client requests
-/httpRequests/
diff --git a/.idea/G4Patcher.iml b/.idea/G4Patcher.iml
deleted file mode 100644
index cf84ae4..0000000
--- a/.idea/G4Patcher.iml
+++ /dev/null
@@ -1,11 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
deleted file mode 100644
index 7896a57..0000000
--- a/.idea/modules.xml
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
deleted file mode 100644
index 35eb1dd..0000000
--- a/.idea/vcs.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-
-
-
-
\ No newline at end of file
diff --git a/Cargo.lock b/Cargo.lock
deleted file mode 100644
index 9e64e85..0000000
--- a/Cargo.lock
+++ /dev/null
@@ -1,1513 +0,0 @@
-# This file is automatically @generated by Cargo.
-# It is not intended for manual editing.
-version = 4
-
-[[package]]
-name = "G4Patcher"
-version = "0.12.1"
-dependencies = [
- "fs_extra",
- "log",
- "rfd",
-]
-
-[[package]]
-name = "ashpd"
-version = "0.11.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6cbdf310d77fd3aaee6ea2093db7011dc2d35d2eb3481e5607f1f8d942ed99df"
-dependencies = [
- "async-fs",
- "async-net",
- "enumflags2",
- "futures-channel",
- "futures-util",
- "rand",
- "raw-window-handle",
- "serde",
- "serde_repr",
- "url",
- "zbus",
-]
-
-[[package]]
-name = "async-broadcast"
-version = "0.7.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "435a87a52755b8f27fcf321ac4f04b2802e337c8c4872923137471ec39c37532"
-dependencies = [
- "event-listener",
- "event-listener-strategy",
- "futures-core",
- "pin-project-lite",
-]
-
-[[package]]
-name = "async-channel"
-version = "2.3.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "89b47800b0be77592da0afd425cc03468052844aff33b84e33cc696f64e77b6a"
-dependencies = [
- "concurrent-queue",
- "event-listener-strategy",
- "futures-core",
- "pin-project-lite",
-]
-
-[[package]]
-name = "async-executor"
-version = "1.13.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bb812ffb58524bdd10860d7d974e2f01cc0950c2438a74ee5ec2e2280c6c4ffa"
-dependencies = [
- "async-task",
- "concurrent-queue",
- "fastrand",
- "futures-lite",
- "pin-project-lite",
- "slab",
-]
-
-[[package]]
-name = "async-fs"
-version = "2.1.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ebcd09b382f40fcd159c2d695175b2ae620ffa5f3bd6f664131efff4e8b9e04a"
-dependencies = [
- "async-lock",
- "blocking",
- "futures-lite",
-]
-
-[[package]]
-name = "async-io"
-version = "2.4.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1237c0ae75a0f3765f58910ff9cdd0a12eeb39ab2f4c7de23262f337f0aacbb3"
-dependencies = [
- "async-lock",
- "cfg-if",
- "concurrent-queue",
- "futures-io",
- "futures-lite",
- "parking",
- "polling",
- "rustix",
- "slab",
- "tracing",
- "windows-sys",
-]
-
-[[package]]
-name = "async-lock"
-version = "3.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ff6e472cdea888a4bd64f342f09b3f50e1886d32afe8df3d663c01140b811b18"
-dependencies = [
- "event-listener",
- "event-listener-strategy",
- "pin-project-lite",
-]
-
-[[package]]
-name = "async-net"
-version = "2.0.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b948000fad4873c1c9339d60f2623323a0cfd3816e5181033c6a5cb68b2accf7"
-dependencies = [
- "async-io",
- "blocking",
- "futures-lite",
-]
-
-[[package]]
-name = "async-process"
-version = "2.3.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cde3f4e40e6021d7acffc90095cbd6dc54cb593903d1de5832f435eb274b85dc"
-dependencies = [
- "async-channel",
- "async-io",
- "async-lock",
- "async-signal",
- "async-task",
- "blocking",
- "cfg-if",
- "event-listener",
- "futures-lite",
- "rustix",
- "tracing",
-]
-
-[[package]]
-name = "async-recursion"
-version = "1.1.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3b43422f69d8ff38f95f1b2bb76517c91589a924d1559a0e935d7c8ce0274c11"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn",
-]
-
-[[package]]
-name = "async-signal"
-version = "0.2.11"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d7605a4e50d4b06df3898d5a70bf5fde51ed9059b0434b73105193bc27acce0d"
-dependencies = [
- "async-io",
- "async-lock",
- "atomic-waker",
- "cfg-if",
- "futures-core",
- "futures-io",
- "rustix",
- "signal-hook-registry",
- "slab",
- "windows-sys",
-]
-
-[[package]]
-name = "async-task"
-version = "4.7.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8b75356056920673b02621b35afd0f7dda9306d03c79a30f5c56c44cf256e3de"
-
-[[package]]
-name = "async-trait"
-version = "0.1.88"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e539d3fca749fcee5236ab05e93a52867dd549cc157c8cb7f99595f3cedffdb5"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn",
-]
-
-[[package]]
-name = "atomic-waker"
-version = "1.1.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0"
-
-[[package]]
-name = "autocfg"
-version = "1.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26"
-
-[[package]]
-name = "bitflags"
-version = "2.9.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1b8e56985ec62d17e9c1001dc89c88ecd7dc08e47eba5ec7c29c7b5eeecde967"
-
-[[package]]
-name = "block2"
-version = "0.6.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "340d2f0bdb2a43c1d3cd40513185b2bd7def0aa1052f956455114bc98f82dcf2"
-dependencies = [
- "objc2",
-]
-
-[[package]]
-name = "blocking"
-version = "1.6.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "703f41c54fc768e63e091340b424302bb1c29ef4aa0c7f10fe849dfb114d29ea"
-dependencies = [
- "async-channel",
- "async-task",
- "futures-io",
- "futures-lite",
- "piper",
-]
-
-[[package]]
-name = "bumpalo"
-version = "3.18.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "793db76d6187cd04dff33004d8e6c9cc4e05cd330500379d2394209271b4aeee"
-
-[[package]]
-name = "cfg-if"
-version = "1.0.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9555578bc9e57714c812a1f84e4fc5b4d21fcb063490c624de019f7464c91268"
-
-[[package]]
-name = "cfg_aliases"
-version = "0.2.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724"
-
-[[package]]
-name = "concurrent-queue"
-version = "2.5.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4ca0197aee26d1ae37445ee532fefce43251d24cc7c166799f4d46817f1d3973"
-dependencies = [
- "crossbeam-utils",
-]
-
-[[package]]
-name = "crossbeam-utils"
-version = "0.8.21"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28"
-
-[[package]]
-name = "dispatch2"
-version = "0.2.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1a0d569e003ff27784e0e14e4a594048698e0c0f0b66cabcb51511be55a7caa0"
-dependencies = [
- "bitflags",
- "block2",
- "libc",
- "objc2",
-]
-
-[[package]]
-name = "dispatch2"
-version = "0.3.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "89a09f22a6c6069a18470eb92d2298acf25463f14256d24778e1230d789a2aec"
-dependencies = [
- "bitflags",
- "objc2",
-]
-
-[[package]]
-name = "displaydoc"
-version = "0.2.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn",
-]
-
-[[package]]
-name = "endi"
-version = "1.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a3d8a32ae18130a3c84dd492d4215c3d913c3b07c6b63c2eb3eb7ff1101ab7bf"
-
-[[package]]
-name = "enumflags2"
-version = "0.7.12"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1027f7680c853e056ebcec683615fb6fbbc07dbaa13b4d5d9442b146ded4ecef"
-dependencies = [
- "enumflags2_derive",
- "serde",
-]
-
-[[package]]
-name = "enumflags2_derive"
-version = "0.7.12"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "67c78a4d8fdf9953a5c9d458f9efe940fd97a0cab0941c075a813ac594733827"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn",
-]
-
-[[package]]
-name = "equivalent"
-version = "1.0.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f"
-
-[[package]]
-name = "errno"
-version = "0.3.12"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cea14ef9355e3beab063703aa9dab15afd25f0667c341310c1e5274bb1d0da18"
-dependencies = [
- "libc",
- "windows-sys",
-]
-
-[[package]]
-name = "event-listener"
-version = "5.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3492acde4c3fc54c845eaab3eed8bd00c7a7d881f78bfc801e43a93dec1331ae"
-dependencies = [
- "concurrent-queue",
- "parking",
- "pin-project-lite",
-]
-
-[[package]]
-name = "event-listener-strategy"
-version = "0.5.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8be9f3dfaaffdae2972880079a491a1a8bb7cbed0b8dd7a347f668b4150a3b93"
-dependencies = [
- "event-listener",
- "pin-project-lite",
-]
-
-[[package]]
-name = "fastrand"
-version = "2.3.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be"
-
-[[package]]
-name = "form_urlencoded"
-version = "1.2.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456"
-dependencies = [
- "percent-encoding",
-]
-
-[[package]]
-name = "fs_extra"
-version = "1.3.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "42703706b716c37f96a77aea830392ad231f44c9e9a67872fa5548707e11b11c"
-
-[[package]]
-name = "futures-channel"
-version = "0.3.31"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10"
-dependencies = [
- "futures-core",
-]
-
-[[package]]
-name = "futures-core"
-version = "0.3.31"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e"
-
-[[package]]
-name = "futures-io"
-version = "0.3.31"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6"
-
-[[package]]
-name = "futures-lite"
-version = "2.6.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f5edaec856126859abb19ed65f39e90fea3a9574b9707f13539acf4abf7eb532"
-dependencies = [
- "fastrand",
- "futures-core",
- "futures-io",
- "parking",
- "pin-project-lite",
-]
-
-[[package]]
-name = "futures-macro"
-version = "0.3.31"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn",
-]
-
-[[package]]
-name = "futures-task"
-version = "0.3.31"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988"
-
-[[package]]
-name = "futures-util"
-version = "0.3.31"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81"
-dependencies = [
- "futures-core",
- "futures-io",
- "futures-macro",
- "futures-task",
- "memchr",
- "pin-project-lite",
- "pin-utils",
- "slab",
-]
-
-[[package]]
-name = "getrandom"
-version = "0.3.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "26145e563e54f2cadc477553f1ec5ee650b00862f0a58bcd12cbdc5f0ea2d2f4"
-dependencies = [
- "cfg-if",
- "libc",
- "r-efi",
- "wasi",
-]
-
-[[package]]
-name = "hashbrown"
-version = "0.15.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5971ac85611da7067dbfcabef3c70ebb5606018acd9e2a3903a0da507521e0d5"
-
-[[package]]
-name = "hermit-abi"
-version = "0.5.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c"
-
-[[package]]
-name = "hex"
-version = "0.4.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
-
-[[package]]
-name = "icu_collections"
-version = "2.0.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "200072f5d0e3614556f94a9930d5dc3e0662a652823904c3a75dc3b0af7fee47"
-dependencies = [
- "displaydoc",
- "potential_utf",
- "yoke",
- "zerofrom",
- "zerovec",
-]
-
-[[package]]
-name = "icu_locale_core"
-version = "2.0.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0cde2700ccaed3872079a65fb1a78f6c0a36c91570f28755dda67bc8f7d9f00a"
-dependencies = [
- "displaydoc",
- "litemap",
- "tinystr",
- "writeable",
- "zerovec",
-]
-
-[[package]]
-name = "icu_normalizer"
-version = "2.0.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "436880e8e18df4d7bbc06d58432329d6458cc84531f7ac5f024e93deadb37979"
-dependencies = [
- "displaydoc",
- "icu_collections",
- "icu_normalizer_data",
- "icu_properties",
- "icu_provider",
- "smallvec",
- "zerovec",
-]
-
-[[package]]
-name = "icu_normalizer_data"
-version = "2.0.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "00210d6893afc98edb752b664b8890f0ef174c8adbb8d0be9710fa66fbbf72d3"
-
-[[package]]
-name = "icu_properties"
-version = "2.0.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "016c619c1eeb94efb86809b015c58f479963de65bdb6253345c1a1276f22e32b"
-dependencies = [
- "displaydoc",
- "icu_collections",
- "icu_locale_core",
- "icu_properties_data",
- "icu_provider",
- "potential_utf",
- "zerotrie",
- "zerovec",
-]
-
-[[package]]
-name = "icu_properties_data"
-version = "2.0.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "298459143998310acd25ffe6810ed544932242d3f07083eee1084d83a71bd632"
-
-[[package]]
-name = "icu_provider"
-version = "2.0.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "03c80da27b5f4187909049ee2d72f276f0d9f99a42c306bd0131ecfe04d8e5af"
-dependencies = [
- "displaydoc",
- "icu_locale_core",
- "stable_deref_trait",
- "tinystr",
- "writeable",
- "yoke",
- "zerofrom",
- "zerotrie",
- "zerovec",
-]
-
-[[package]]
-name = "idna"
-version = "1.0.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "686f825264d630750a544639377bae737628043f20d38bbc029e8f29ea968a7e"
-dependencies = [
- "idna_adapter",
- "smallvec",
- "utf8_iter",
-]
-
-[[package]]
-name = "idna_adapter"
-version = "1.2.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3acae9609540aa318d1bc588455225fb2085b9ed0c4f6bd0d9d5bcd86f1a0344"
-dependencies = [
- "icu_normalizer",
- "icu_properties",
-]
-
-[[package]]
-name = "indexmap"
-version = "2.9.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cea70ddb795996207ad57735b50c5982d8844f38ba9ee5f1aedcfb708a2aa11e"
-dependencies = [
- "equivalent",
- "hashbrown",
-]
-
-[[package]]
-name = "js-sys"
-version = "0.3.77"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f"
-dependencies = [
- "once_cell",
- "wasm-bindgen",
-]
-
-[[package]]
-name = "libc"
-version = "0.2.173"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d8cfeafaffdbc32176b64fb251369d52ea9f0a8fbc6f8759edffef7b525d64bb"
-
-[[package]]
-name = "linux-raw-sys"
-version = "0.9.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cd945864f07fe9f5371a27ad7b52a172b4b499999f1d97574c9fa68373937e12"
-
-[[package]]
-name = "litemap"
-version = "0.8.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "241eaef5fd12c88705a01fc1066c48c4b36e0dd4377dcdc7ec3942cea7a69956"
-
-[[package]]
-name = "log"
-version = "0.4.27"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94"
-
-[[package]]
-name = "memchr"
-version = "2.7.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "32a282da65faaf38286cf3be983213fcf1d2e2a58700e808f83f4ea9a4804bc0"
-
-[[package]]
-name = "memoffset"
-version = "0.9.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "488016bfae457b036d996092f6cb448677611ce4449e970ceaf42695203f218a"
-dependencies = [
- "autocfg",
-]
-
-[[package]]
-name = "nix"
-version = "0.30.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "74523f3a35e05aba87a1d978330aef40f67b0304ac79c1c00b294c9830543db6"
-dependencies = [
- "bitflags",
- "cfg-if",
- "cfg_aliases",
- "libc",
- "memoffset",
-]
-
-[[package]]
-name = "objc2"
-version = "0.6.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "88c6597e14493ab2e44ce58f2fdecf095a51f12ca57bec060a11c57332520551"
-dependencies = [
- "objc2-encode",
-]
-
-[[package]]
-name = "objc2-app-kit"
-version = "0.3.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e6f29f568bec459b0ddff777cec4fe3fd8666d82d5a40ebd0ff7e66134f89bcc"
-dependencies = [
- "bitflags",
- "block2",
- "objc2",
- "objc2-foundation",
-]
-
-[[package]]
-name = "objc2-core-foundation"
-version = "0.3.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1c10c2894a6fed806ade6027bcd50662746363a9589d3ec9d9bef30a4e4bc166"
-dependencies = [
- "bitflags",
- "dispatch2 0.3.0",
- "objc2",
-]
-
-[[package]]
-name = "objc2-encode"
-version = "4.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ef25abbcd74fb2609453eb695bd2f860d389e457f67dc17cafc8b8cbc89d0c33"
-
-[[package]]
-name = "objc2-foundation"
-version = "0.3.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "900831247d2fe1a09a683278e5384cfb8c80c79fe6b166f9d14bfdde0ea1b03c"
-dependencies = [
- "bitflags",
- "objc2",
- "objc2-core-foundation",
-]
-
-[[package]]
-name = "once_cell"
-version = "1.21.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d"
-
-[[package]]
-name = "ordered-stream"
-version = "0.2.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9aa2b01e1d916879f73a53d01d1d6cee68adbb31d6d9177a8cfce093cced1d50"
-dependencies = [
- "futures-core",
- "pin-project-lite",
-]
-
-[[package]]
-name = "parking"
-version = "2.2.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f38d5652c16fde515bb1ecef450ab0f6a219d619a7274976324d5e377f7dceba"
-
-[[package]]
-name = "percent-encoding"
-version = "2.3.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e"
-
-[[package]]
-name = "pin-project-lite"
-version = "0.2.16"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b"
-
-[[package]]
-name = "pin-utils"
-version = "0.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
-
-[[package]]
-name = "piper"
-version = "0.2.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "96c8c490f422ef9a4efd2cb5b42b76c8613d7e7dfc1caf667b8a3350a5acc066"
-dependencies = [
- "atomic-waker",
- "fastrand",
- "futures-io",
-]
-
-[[package]]
-name = "polling"
-version = "3.8.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b53a684391ad002dd6a596ceb6c74fd004fdce75f4be2e3f615068abbea5fd50"
-dependencies = [
- "cfg-if",
- "concurrent-queue",
- "hermit-abi",
- "pin-project-lite",
- "rustix",
- "tracing",
- "windows-sys",
-]
-
-[[package]]
-name = "pollster"
-version = "0.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2f3a9f18d041e6d0e102a0a46750538147e5e8992d3b4873aaafee2520b00ce3"
-
-[[package]]
-name = "potential_utf"
-version = "0.1.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e5a7c30837279ca13e7c867e9e40053bc68740f988cb07f7ca6df43cc734b585"
-dependencies = [
- "zerovec",
-]
-
-[[package]]
-name = "ppv-lite86"
-version = "0.2.21"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9"
-dependencies = [
- "zerocopy",
-]
-
-[[package]]
-name = "proc-macro-crate"
-version = "3.3.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "edce586971a4dfaa28950c6f18ed55e0406c1ab88bbce2c6f6293a7aaba73d35"
-dependencies = [
- "toml_edit",
-]
-
-[[package]]
-name = "proc-macro2"
-version = "1.0.95"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778"
-dependencies = [
- "unicode-ident",
-]
-
-[[package]]
-name = "quote"
-version = "1.0.40"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d"
-dependencies = [
- "proc-macro2",
-]
-
-[[package]]
-name = "r-efi"
-version = "5.2.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "74765f6d916ee2faa39bc8e68e4f3ed8949b48cccdac59983d287a7cb71ce9c5"
-
-[[package]]
-name = "rand"
-version = "0.9.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9fbfd9d094a40bf3ae768db9361049ace4c0e04a4fd6b359518bd7b73a73dd97"
-dependencies = [
- "rand_chacha",
- "rand_core",
-]
-
-[[package]]
-name = "rand_chacha"
-version = "0.9.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb"
-dependencies = [
- "ppv-lite86",
- "rand_core",
-]
-
-[[package]]
-name = "rand_core"
-version = "0.9.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38"
-dependencies = [
- "getrandom",
-]
-
-[[package]]
-name = "raw-window-handle"
-version = "0.6.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "20675572f6f24e9e76ef639bc5552774ed45f1c30e2951e1e99c59888861c539"
-
-[[package]]
-name = "rfd"
-version = "0.15.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "80c844748fdc82aae252ee4594a89b6e7ebef1063de7951545564cbc4e57075d"
-dependencies = [
- "ashpd",
- "block2",
- "dispatch2 0.2.0",
- "js-sys",
- "log",
- "objc2",
- "objc2-app-kit",
- "objc2-core-foundation",
- "objc2-foundation",
- "pollster",
- "raw-window-handle",
- "urlencoding",
- "wasm-bindgen",
- "wasm-bindgen-futures",
- "web-sys",
- "windows-sys",
-]
-
-[[package]]
-name = "rustix"
-version = "1.0.7"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c71e83d6afe7ff64890ec6b71d6a69bb8a610ab78ce364b3352876bb4c801266"
-dependencies = [
- "bitflags",
- "errno",
- "libc",
- "linux-raw-sys",
- "windows-sys",
-]
-
-[[package]]
-name = "rustversion"
-version = "1.0.21"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8a0d197bd2c9dc6e53b84da9556a69ba4cdfab8619eb41a8bd1cc2027a0f6b1d"
-
-[[package]]
-name = "serde"
-version = "1.0.219"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6"
-dependencies = [
- "serde_derive",
-]
-
-[[package]]
-name = "serde_derive"
-version = "1.0.219"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn",
-]
-
-[[package]]
-name = "serde_repr"
-version = "0.1.20"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "175ee3e80ae9982737ca543e96133087cbd9a485eecc3bc4de9c1a37b47ea59c"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn",
-]
-
-[[package]]
-name = "signal-hook-registry"
-version = "1.4.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9203b8055f63a2a00e2f593bb0510367fe707d7ff1e5c872de2f537b339e5410"
-dependencies = [
- "libc",
-]
-
-[[package]]
-name = "slab"
-version = "0.4.9"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67"
-dependencies = [
- "autocfg",
-]
-
-[[package]]
-name = "smallvec"
-version = "1.15.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03"
-
-[[package]]
-name = "stable_deref_trait"
-version = "1.2.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3"
-
-[[package]]
-name = "static_assertions"
-version = "1.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
-
-[[package]]
-name = "syn"
-version = "2.0.103"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e4307e30089d6fd6aff212f2da3a1f9e32f3223b1f010fb09b7c95f90f3ca1e8"
-dependencies = [
- "proc-macro2",
- "quote",
- "unicode-ident",
-]
-
-[[package]]
-name = "synstructure"
-version = "0.13.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn",
-]
-
-[[package]]
-name = "tempfile"
-version = "3.20.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e8a64e3985349f2441a1a9ef0b853f869006c3855f2cda6862a94d26ebb9d6a1"
-dependencies = [
- "fastrand",
- "getrandom",
- "once_cell",
- "rustix",
- "windows-sys",
-]
-
-[[package]]
-name = "tinystr"
-version = "0.8.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5d4f6d1145dcb577acf783d4e601bc1d76a13337bb54e6233add580b07344c8b"
-dependencies = [
- "displaydoc",
- "zerovec",
-]
-
-[[package]]
-name = "toml_datetime"
-version = "0.6.11"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "22cddaf88f4fbc13c51aebbf5f8eceb5c7c5a9da2ac40a13519eb5b0a0e8f11c"
-
-[[package]]
-name = "toml_edit"
-version = "0.22.27"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "41fe8c660ae4257887cf66394862d21dbca4a6ddd26f04a3560410406a2f819a"
-dependencies = [
- "indexmap",
- "toml_datetime",
- "winnow",
-]
-
-[[package]]
-name = "tracing"
-version = "0.1.41"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0"
-dependencies = [
- "pin-project-lite",
- "tracing-attributes",
- "tracing-core",
-]
-
-[[package]]
-name = "tracing-attributes"
-version = "0.1.29"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1b1ffbcf9c6f6b99d386e7444eb608ba646ae452a36b39737deb9663b610f662"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn",
-]
-
-[[package]]
-name = "tracing-core"
-version = "0.1.34"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b9d12581f227e93f094d3af2ae690a574abb8a2b9b7a96e7cfe9647b2b617678"
-dependencies = [
- "once_cell",
-]
-
-[[package]]
-name = "uds_windows"
-version = "1.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "89daebc3e6fd160ac4aa9fc8b3bf71e1f74fbf92367ae71fb83a037e8bf164b9"
-dependencies = [
- "memoffset",
- "tempfile",
- "winapi",
-]
-
-[[package]]
-name = "unicode-ident"
-version = "1.0.18"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512"
-
-[[package]]
-name = "url"
-version = "2.5.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "32f8b686cadd1473f4bd0117a5d28d36b1ade384ea9b5069a1c40aefed7fda60"
-dependencies = [
- "form_urlencoded",
- "idna",
- "percent-encoding",
- "serde",
-]
-
-[[package]]
-name = "urlencoding"
-version = "2.1.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "daf8dba3b7eb870caf1ddeed7bc9d2a049f3cfdfae7cb521b087cc33ae4c49da"
-
-[[package]]
-name = "utf8_iter"
-version = "1.0.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be"
-
-[[package]]
-name = "wasi"
-version = "0.14.2+wasi-0.2.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9683f9a5a998d873c0d21fcbe3c083009670149a8fab228644b8bd36b2c48cb3"
-dependencies = [
- "wit-bindgen-rt",
-]
-
-[[package]]
-name = "wasm-bindgen"
-version = "0.2.100"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-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",
- "wasm-bindgen-shared",
-]
-
-[[package]]
-name = "wasm-bindgen-futures"
-version = "0.4.50"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "555d470ec0bc3bb57890405e5d4322cc9ea83cebb085523ced7be4144dac1e61"
-dependencies = [
- "cfg-if",
- "js-sys",
- "once_cell",
- "wasm-bindgen",
- "web-sys",
-]
-
-[[package]]
-name = "wasm-bindgen-macro"
-version = "0.2.100"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407"
-dependencies = [
- "quote",
- "wasm-bindgen-macro-support",
-]
-
-[[package]]
-name = "wasm-bindgen-macro-support"
-version = "0.2.100"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn",
- "wasm-bindgen-backend",
- "wasm-bindgen-shared",
-]
-
-[[package]]
-name = "wasm-bindgen-shared"
-version = "0.2.100"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d"
-dependencies = [
- "unicode-ident",
-]
-
-[[package]]
-name = "web-sys"
-version = "0.3.77"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "33b6dd2ef9186f1f2072e409e99cd22a975331a6b3591b12c764e0e55c60d5d2"
-dependencies = [
- "js-sys",
- "wasm-bindgen",
-]
-
-[[package]]
-name = "winapi"
-version = "0.3.9"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
-dependencies = [
- "winapi-i686-pc-windows-gnu",
- "winapi-x86_64-pc-windows-gnu",
-]
-
-[[package]]
-name = "winapi-i686-pc-windows-gnu"
-version = "0.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
-
-[[package]]
-name = "winapi-x86_64-pc-windows-gnu"
-version = "0.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
-
-[[package]]
-name = "windows-sys"
-version = "0.59.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b"
-dependencies = [
- "windows-targets",
-]
-
-[[package]]
-name = "windows-targets"
-version = "0.52.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973"
-dependencies = [
- "windows_aarch64_gnullvm",
- "windows_aarch64_msvc",
- "windows_i686_gnu",
- "windows_i686_gnullvm",
- "windows_i686_msvc",
- "windows_x86_64_gnu",
- "windows_x86_64_gnullvm",
- "windows_x86_64_msvc",
-]
-
-[[package]]
-name = "windows_aarch64_gnullvm"
-version = "0.52.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
-
-[[package]]
-name = "windows_aarch64_msvc"
-version = "0.52.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
-
-[[package]]
-name = "windows_i686_gnu"
-version = "0.52.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b"
-
-[[package]]
-name = "windows_i686_gnullvm"
-version = "0.52.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
-
-[[package]]
-name = "windows_i686_msvc"
-version = "0.52.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
-
-[[package]]
-name = "windows_x86_64_gnu"
-version = "0.52.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
-
-[[package]]
-name = "windows_x86_64_gnullvm"
-version = "0.52.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
-
-[[package]]
-name = "windows_x86_64_msvc"
-version = "0.52.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
-
-[[package]]
-name = "winnow"
-version = "0.7.11"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "74c7b26e3480b707944fc872477815d29a8e429d2f93a1ce000f5fa84a15cbcd"
-dependencies = [
- "memchr",
-]
-
-[[package]]
-name = "wit-bindgen-rt"
-version = "0.39.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1"
-dependencies = [
- "bitflags",
-]
-
-[[package]]
-name = "writeable"
-version = "0.6.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ea2f10b9bb0928dfb1b42b65e1f9e36f7f54dbdf08457afefb38afcdec4fa2bb"
-
-[[package]]
-name = "yoke"
-version = "0.8.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5f41bb01b8226ef4bfd589436a297c53d118f65921786300e427be8d487695cc"
-dependencies = [
- "serde",
- "stable_deref_trait",
- "yoke-derive",
- "zerofrom",
-]
-
-[[package]]
-name = "yoke-derive"
-version = "0.8.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "38da3c9736e16c5d3c8c597a9aaa5d1fa565d0532ae05e27c24aa62fb32c0ab6"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn",
- "synstructure",
-]
-
-[[package]]
-name = "zbus"
-version = "5.7.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d3a7c7cee313d044fca3f48fa782cb750c79e4ca76ba7bc7718cd4024cdf6f68"
-dependencies = [
- "async-broadcast",
- "async-executor",
- "async-io",
- "async-lock",
- "async-process",
- "async-recursion",
- "async-task",
- "async-trait",
- "blocking",
- "enumflags2",
- "event-listener",
- "futures-core",
- "futures-lite",
- "hex",
- "nix",
- "ordered-stream",
- "serde",
- "serde_repr",
- "tracing",
- "uds_windows",
- "windows-sys",
- "winnow",
- "zbus_macros",
- "zbus_names",
- "zvariant",
-]
-
-[[package]]
-name = "zbus_macros"
-version = "5.7.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a17e7e5eec1550f747e71a058df81a9a83813ba0f6a95f39c4e218bdc7ba366a"
-dependencies = [
- "proc-macro-crate",
- "proc-macro2",
- "quote",
- "syn",
- "zbus_names",
- "zvariant",
- "zvariant_utils",
-]
-
-[[package]]
-name = "zbus_names"
-version = "4.2.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7be68e64bf6ce8db94f63e72f0c7eb9a60d733f7e0499e628dfab0f84d6bcb97"
-dependencies = [
- "serde",
- "static_assertions",
- "winnow",
- "zvariant",
-]
-
-[[package]]
-name = "zerocopy"
-version = "0.8.25"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a1702d9583232ddb9174e01bb7c15a2ab8fb1bc6f227aa1233858c351a3ba0cb"
-dependencies = [
- "zerocopy-derive",
-]
-
-[[package]]
-name = "zerocopy-derive"
-version = "0.8.25"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "28a6e20d751156648aa063f3800b706ee209a32c0b4d9f24be3d980b01be55ef"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn",
-]
-
-[[package]]
-name = "zerofrom"
-version = "0.1.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "50cc42e0333e05660c3587f3bf9d0478688e15d870fab3346451ce7f8c9fbea5"
-dependencies = [
- "zerofrom-derive",
-]
-
-[[package]]
-name = "zerofrom-derive"
-version = "0.1.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn",
- "synstructure",
-]
-
-[[package]]
-name = "zerotrie"
-version = "0.2.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "36f0bbd478583f79edad978b407914f61b2972f5af6fa089686016be8f9af595"
-dependencies = [
- "displaydoc",
- "yoke",
- "zerofrom",
-]
-
-[[package]]
-name = "zerovec"
-version = "0.11.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4a05eb080e015ba39cc9e23bbe5e7fb04d5fb040350f99f34e338d5fdd294428"
-dependencies = [
- "yoke",
- "zerofrom",
- "zerovec-derive",
-]
-
-[[package]]
-name = "zerovec-derive"
-version = "0.11.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5b96237efa0c878c64bd89c436f661be4e46b2f3eff1ebb976f7ef2321d2f58f"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn",
-]
-
-[[package]]
-name = "zvariant"
-version = "5.5.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9d30786f75e393ee63a21de4f9074d4c038d52c5b1bb4471f955db249f9dffb1"
-dependencies = [
- "endi",
- "enumflags2",
- "serde",
- "url",
- "winnow",
- "zvariant_derive",
- "zvariant_utils",
-]
-
-[[package]]
-name = "zvariant_derive"
-version = "5.5.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "75fda702cd42d735ccd48117b1630432219c0e9616bf6cb0f8350844ee4d9580"
-dependencies = [
- "proc-macro-crate",
- "proc-macro2",
- "quote",
- "syn",
- "zvariant_utils",
-]
-
-[[package]]
-name = "zvariant_utils"
-version = "3.2.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e16edfee43e5d7b553b77872d99bc36afdda75c223ca7ad5e3fbecd82ca5fc34"
-dependencies = [
- "proc-macro2",
- "quote",
- "serde",
- "static_assertions",
- "syn",
- "winnow",
-]
diff --git a/Cargo.toml b/Cargo.toml
index a018407..4be7431 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "G4Patcher"
-version = "0.12.1"
+version = "0.14.0"
edition = "2021"
repository = "https://github.com/KalaayPT/g4patcher"
authors = ["KalaayPT "]
@@ -23,6 +23,8 @@ include = [
log = "0.4.27"
rfd = "0.15.3"
fs_extra = "1.3.0"
+eframe = "0.32.0"
+clap = "4.5.43"
[build-dependencies]
fs_extra = "1.3"
diff --git a/README.md b/README.md
index 9564a8f..1067a70 100644
--- a/README.md
+++ b/README.md
@@ -11,6 +11,8 @@ After checking these things, it adjusts the patch file with the corrected inject
An [armips](https://github.com/Kingcom/armips) binary is bundled into the release, so no need to install anything!
+Please credit me (Kalaay) and the people behind the research for the patches if you use them in your own projects. Credits for research can always be found in the patch files themselves, as well as in the [wiki](https://github.com/KalaayPT/G4Patcher/wiki)
+
## 1. Usage:
1. Download the latest [release](https://github.com/KalaayPT/g4patcher/releases)
@@ -29,7 +31,22 @@ An [armips](https://github.com/Kingcom/armips) binary is bundled into the releas
can now be found [in the wiki](https://github.com/KalaayPT/G4Patcher/wiki/Included-Patches)
-## 4. Contributing:
+## 4. Build Instructions:
+
+1. Install Rust and Cargo: Follow the instructions at https://www.rust-lang.org/tools/install
+2. Clone the repository:
+```bash
+git clone https://github.com/KalaayPT/G4Patcher.git
+cd G4Patcher
+```
+3. Build the project:
+```bash
+cargo build
+```
+4. Find the executable in target/release/g4patcher
+5. Run G4Patcher
+
+## 5. Contributing:
If you want to contribute your own patches, you can use the included ones as templates as to what yours are supposed to look like.
diff --git a/dist-workspace.toml b/dist-workspace.toml
index 66c0e26..9fc7dd3 100644
--- a/dist-workspace.toml
+++ b/dist-workspace.toml
@@ -4,13 +4,13 @@ members = ["cargo:."]
# Config for 'dist'
[dist]
# The preferred dist version to use in CI (Cargo.toml SemVer syntax)
-cargo-dist-version = "0.28.0"
+cargo-dist-version = "0.29.0"
# CI backends to support
ci = "github"
# The installers to generate for each app
installers = []
# Target platforms to build apps for (Rust target-triple syntax)
-targets = ["aarch64-apple-darwin", "x86_64-pc-windows-msvc"]
+targets = ["aarch64-apple-darwin", "x86_64-unknown-linux-gnu", "x86_64-pc-windows-msvc"]
# Path that installers should place binaries in
install-path = "CARGO_HOME"
# Whether to install an updater program
diff --git a/patches/HG_SS/Code Injection (needs arm9 expansion)/ButtonScript_HG_SS.asm b/patches/HG_SS/Code Injection (needs arm9 expansion)/ButtonScript_HG_SS.asm
index 59c9185..84e36b0 100644
--- a/patches/HG_SS/Code Injection (needs arm9 expansion)/ButtonScript_HG_SS.asm
+++ b/patches/HG_SS/Code Injection (needs arm9 expansion)/ButtonScript_HG_SS.asm
@@ -23,6 +23,8 @@ RButton equ 256
LButton equ 512
XButton equ 1024
+StartMapSceneScript equ 0x0203FE74 ; StartMapSceneScript(fieldSystem, scriptID, lastInteracted)
+
INJECT_ADDR equ 0x023C8000
; ------- Inject hook into arm9.bin -------
@@ -51,30 +53,30 @@ INJECT_ADDR equ 0x023C8000
PortaPC:
push {r3, r4, r5, r6, r7, lr}
- add r4, r1, #0 ; putting fieldSystem back into r4
+ add r4, r1, #0 ; putting fieldSystem back into r4
; these next two are both overwritten instructions that we have to copy over
- lsl r0, r0, #23
- lsr r0, r0, #31
- beq end_rel
+ lsl r0, r0, #23
+ lsr r0, r0, #31
+ beq end_rel
; Access gSystem->newKeys
- ldr r3, =0x021D110C ; r3 = gSystem
- ldr r2, [r3, #0x48] ; r2 = gSystem->newKeys
- ldr r3, =PressedButton ; Button bitmask
- tst r2, r3 ; check if pressed
- bne call_script
- pop {r3, r4, r5, r6, r7, pc}
+ ldr r3, =0x021D110C ; r3 = gSystem
+ ldr r2, [r3, #0x48] ; r2 = gSystem->newKeys
+ ldr r3, =PressedButton ; Button bitmask
+ tst r2, r3 ; check if pressed
+ bne call_script
+ pop {r3, r4, r5, r6, r7, pc}
call_script:
- add r0, r4, #0
- ldr r1, =ScriptID ; ScriptID: 2072
- mov r2, #0 ; lastInteracted = NULL
- bl 0x0203FE74 ; StartMapSceneScript(fieldSystem, 2072, NULL)
- pop {r3, r4, r5, r6, r7, pc}
+ add r0, r4, #0
+ ldr r1, =ScriptID ; ScriptID: 2072
+ mov r2, #0 ; lastInteracted = NULL
+ bl StartMapSceneScript ; StartMapSceneScript(fieldSystem, 2072, NULL)
+ pop {r3, r4, r5, r6, r7, pc}
end_rel:
- mov r0, #0
- pop {r3, r4, r5, r6, r7, pc}
+ mov r0, #0
+ pop {r3, r4, r5, r6, r7, pc}
.pool
diff --git a/patches/HG_SS/Code Injection (needs arm9 expansion)/QoLItems_HG_SS.asm b/patches/HG_SS/Code Injection (needs arm9 expansion)/QoLItems_HG_SS.asm
new file mode 100644
index 0000000..dd6e963
--- /dev/null
+++ b/patches/HG_SS/Code Injection (needs arm9 expansion)/QoLItems_HG_SS.asm
@@ -0,0 +1,384 @@
+; QoLItems_HG_SS.asm
+
+.nds
+.thumb
+
+ScriptID equ 2072 ; (Commonscript ID)
+
+NULL equ 0x00000000
+ItemFieldUseFunc_Generic equ 0x02065150+1
+ItemMenuUseFunc_HealingItem equ 0x02064B54+1
+ItemCheckUseFunc_Dummy equ 0x02064BF4+1
+ItemMenuUseFunc_Bicycle equ 0x02064BFC+1
+ItemFieldUseFunc_Bicycle equ 0x02064C30+1
+ItemCheckUseFunc_Bicycle equ 0x02064DA8+1
+ItemMenuUseFunc_TMHM equ 0x02064E18+1
+ItemMenuUseFunc_Mail equ 0x02064EB8+1
+ItemMenuUseFunc_Berry equ 0x02064F08+1
+ItemCheckUseFunc_Berry equ 0x02064F04+1
+ItemMenuUseFunc_PalPad equ 0x02064F28+1
+ItemFieldUseFunc_PalPad equ 0x02064F5C+1
+ItemMenuUseFunc_Honey equ 0x02064F7C+1
+ItemMenuUseFunc_OldRod equ 0x02064FD4+1
+ItemFieldUseFunc_OldRod equ 0x02065010+1
+ItemMenuUseFunc_GoodRod equ 0x02065030+1
+ItemFieldUseFunc_GoodRod equ 0x0206506C+1
+ItemMenuUseFunc_SuperRod equ 0x0206508C+1
+ItemFieldUseFunc_SuperRod equ 0x020650C8+1
+ItemCheckUseFunc_FishingRod equ 0x020650E8+1
+ItemMenuUseFunc_EvoStone equ 0x02065258+1
+ItemMenuUseFunc_EscapeRope equ 0x02065310+1
+ItemCheckUseFunc_EscapeRope equ 0x0206536C+1
+ItemMenuUseFunc_ApricornBox equ 0x020653D8+1
+ItemFieldUseFunc_ApricornBox equ 0x02065408+1
+ItemMenuUseFunc_BerryPots equ 0x02065428+1
+ItemFieldUseFunc_BerryPots equ 0x02065458+1
+ItemMenuUseFunc_UnownReport equ 0x02065474+1
+ItemFieldUseFunc_UnownReport equ 0x020654A4+1
+ItemMenuUseFunc_DowsingMchn equ 0x020654C0+1
+ItemFieldUseFunc_DowsingMchn equ 0x020654F4+1
+ItemMenuUseFunc_Gracidea equ 0x020655B8+1
+ItemFieldUseFunc_Gracidea equ 0x020655F0+1
+ItemMenuUseFunc_VSRecorder equ 0x02065614+1
+ItemFieldUseFunc_VSRecorder equ 0x02065648+1
+ItemFieldUseFunc_GbSounds equ 0x02065560+1
+
+SEQ_SE_DP_CARD2 equ 1535
+PlaySE equ 0x0200604C ; PlaySE(soundId)
+SaveData_Get equ 0x020272B0
+Save_VarsFlags_Get equ 0x020503D0
+Save_VarsFlags_GetVarAddr equ 0x020504A4
+RepelFlag equ 0x416F ; (Flag ID, Hexadecimal)
+Save_VarsFlags_SetFlagInArray equ 0x02050408
+Save_VarsFlags_GetFlagAddr equ 0x0205045C
+Save_VarsFlags_ClearFlagInArray equ 0x02050430
+TaskManager_GetFieldSystem equ 0x0205064C
+TaskManager_GetEnvironment equ 0x02050650
+FieldSystem_LoadFieldOverlay equ 0x020505C0
+AllocFromHeap equ 0x0201AA8C
+NewMsgDataFromNarc equ 0x0200BAF8
+NewString_ReadMsgData equ 0x0200BBA0
+DestroyMsgData equ 0x0200BB44
+FieldSystem_CreateTask equ 0x020504F0
+String_New equ 0x02026354
+TryFormatRegisteredKeyItemUseMessage equ 0x02077980
+SoundSys_GetGBSoundsState equ 0x02005C18
+SoundSys_ToggleGBSounds equ 0x02005C24
+StringExpandPlaceholders equ 0x0200CBBC
+String_Delete equ 0x02026380
+HealParty equ 0x02090C1C
+SaveArray_Party_Get equ 0x02074904
+SEQ_SE_DP_KAIFUKU equ 1516 ; pokemon healed sound effect
+StartMapSceneScript equ 0x0203FE74 ; StartMapSceneScript(fieldSystem, scriptID, lastInteracted)
+Task_MountOrDismountBicycle equ 0x02064C59
+Task_RunScripts equ 0x0203FF44
+ScriptEnvironment_New equ 0x0204001C
+SetupScriptEngine equ 0x0204005C
+Task_StartMenu_HandleReturn equ 0x0203CFC0
+
+INJECT_ADDR equ 0x023C8000
+
+; ------- Inject hook into arm9.bin -------
+.ifdef PATCH
+.open "arm9.bin", 0x02000000
+
+.org 0x020649ac
+ .word sItemFieldUseFuncs
+.org 0x020649b0
+ .word sItemFieldUseFuncs+4
+.org 0x020649b4
+ .word sItemFieldUseFuncs+8
+
+.org 0x0210051C ; overwrite narc ids table for entry 113, make infinite repel
+; this copies the max repel entry, but with a different narc id, you will have to create this narc (0514) yourself
+ .byte 0x02, 0x02, 0x6D, 0x00, 0x6F, 0x00, 0x54, 0x00
+
+;.org 0x02100524 ; overwrite narc ids table for entry 114, make infinite candy/cap candy, NOT IMPLEMENTED YET
+;; this copies the rare candy entry, but with a different narc id, you will have to create this narc (0515) yourself
+; .byte 0x03, 0x02, 0x5A, 0x00, 0x5B, 0x00, 0x44, 0x00
+
+.org 0x0210052C ; overwrite narc ids table for entry 115, make medkit
+; this copies the full restore entry, but with a different narc id, you will have to create this narc (0516) yourself
+ .byte 0x04, 0x02, 0x21, 0x00, 0x22, 0x00, 0x13, 0x00
+
+.org 0x02100534 ; overwrite narc ids table for entry 116, make pkmn box link
+; this copies the gracidea entry, but with a different narc id, you will have to create this narc (0517) yourself
+ .byte 0x05, 0x02, 0xBF, 0x02, 0xC0, 0x02, 0x00, 0x00
+
+.close
+
+.open "overlay/overlay_0015.bin", 0x021F9380
+.org 0x021FBA76
+ bl BagApp_UseItemExpansion ; overwrite the return of the BagApp_TryUseItemInPlace function
+.close
+
+.endif
+
+; ------- Write function to synthOverlay 0000 -------
+.ifdef PREASSEMBLE
+.create "temp.bin", 0x023C8000
+.elseifdef PATCH
+.open "unpacked/synthOverlay/0000", 0x023C8000
+.endif
+
+
+.org INJECT_ADDR
+.ascii "QoLItems_start"
+
+.align 4
+sItemFieldUseFuncs:
+ .word NULL, ItemFieldUseFunc_Generic, NULL
+ .word ItemMenuUseFunc_HealingItem, NULL, NULL
+ .word NULL, NULL, ItemCheckUseFunc_Dummy
+ .word NULL, NULL, ItemCheckUseFunc_Dummy
+ .word ItemMenuUseFunc_Bicycle, ItemFieldUseFunc_Bicycle, ItemCheckUseFunc_Bicycle
+ .word NULL, NULL, ItemCheckUseFunc_Dummy
+ .word ItemMenuUseFunc_TMHM, NULL, NULL
+ .word ItemMenuUseFunc_Mail, NULL, NULL
+ .word ItemMenuUseFunc_Berry, NULL, ItemCheckUseFunc_Berry
+ .word NULL, NULL, ItemCheckUseFunc_Dummy
+ .word ItemMenuUseFunc_PalPad, ItemFieldUseFunc_PalPad, NULL
+ .word NULL, NULL, ItemCheckUseFunc_Dummy
+ .word NULL, NULL, ItemCheckUseFunc_Dummy
+ .word NULL, NULL, ItemCheckUseFunc_Dummy
+ .word ItemMenuUseFunc_Honey, NULL, NULL
+ .word NULL, NULL, ItemCheckUseFunc_Dummy
+ .word ItemMenuUseFunc_OldRod, ItemFieldUseFunc_OldRod, ItemCheckUseFunc_FishingRod
+ .word ItemMenuUseFunc_GoodRod, ItemFieldUseFunc_GoodRod, ItemCheckUseFunc_FishingRod
+ .word ItemMenuUseFunc_SuperRod, ItemFieldUseFunc_SuperRod, ItemCheckUseFunc_FishingRod
+ .word NULL, ItemFieldUseFunc_Generic, NULL
+ .word ItemMenuUseFunc_EvoStone, NULL, NULL
+ .word ItemMenuUseFunc_EscapeRope, NULL, ItemCheckUseFunc_EscapeRope
+ .word NULL, NULL, ItemCheckUseFunc_Dummy
+ .word ItemMenuUseFunc_ApricornBox, ItemFieldUseFunc_ApricornBox, NULL
+ .word ItemMenuUseFunc_BerryPots, ItemFieldUseFunc_BerryPots, NULL
+ .word ItemMenuUseFunc_UnownReport, ItemFieldUseFunc_UnownReport, NULL
+ .word ItemMenuUseFunc_DowsingMchn, ItemFieldUseFunc_DowsingMchn, NULL
+ .word NULL, ItemFieldUseFunc_GbSounds, NULL
+ .word ItemMenuUseFunc_Gracidea, ItemFieldUseFunc_Gracidea, NULL
+ .word ItemMenuUseFunc_VSRecorder, ItemFieldUseFunc_VSRecorder, NULL ; normal table until here
+ .word NULL, ItemFieldUseFunc_InfiniteRepel+1,NULL ; new entry 30: infinite repel
+ .word NULL, ItemFieldUseFunc_MedKit+1, NULL ; new entry 31: medkit
+ .word ItemMenuUseFunc_PKMNBoxLink+1,ItemFieldUseFunc_PKMNBoxLink+1,NULL ; new entry 32: pkmn box link
+
+.align 4
+
+ItemFieldUseFunc_InfiniteRepel:
+ push {r4,r5,r6,lr}
+ add r6,r0,#0x0
+ mov r0,#0xb
+ mov r1,#0x18
+ bl AllocFromHeap
+ add r4,r0,#0x0
+ mov r0,#0x0
+ mov r1,#0x1b
+ mov r2,#0xa
+ mov r3,#0xb
+ strh r0,[r4,#0x16]
+ bl NewMsgDataFromNarc
+ add r5,r0,#0x0
+ bl IsRepelOn
+ cmp r0,#0x0
+ beq LAB_02065590
+ add r0,r5,#0x0
+ mov r1,#66
+ bl NewString_ReadMsgData
+ b LAB_02065598
+LAB_02065590:
+ add r0,r5,#0x0
+ mov r1,#67
+ bl NewString_ReadMsgData
+LAB_02065598:
+ str r0,[r4,#0x10]
+ add r0,r5,#0x0
+ bl DestroyMsgData
+ bl UseInfiniteRepel
+ ldr r0,[r6]
+ ldr r1,=0x0206518D
+ add r2,r4,#0x0
+ bl FieldSystem_CreateTask
+ mov r0,#0x0
+ pop {r4,r5,r6,pc}
+
+ItemMenuUseFunc_PKMNBoxLink:
+ push {r0-r7,lr}
+ add r4,r0,#0x0
+ ldr r0,[r4,#0x0 ]
+ bl TaskManager_GetFieldSystem
+ add r5,r0,#0x0
+ ldr r0,[r4,#0x0 ]
+ bl TaskManager_GetEnvironment
+ add r4,r0,#0x0
+ add r0,r5,#0x0
+ bl FieldSystem_LoadFieldOverlay ; leave the bag
+ bl ScriptEnvironment_New
+ mov r6,r0 ; r6 = ScriptEnvironment *scriptEnvironment
+ mov r0,r5 ; r0 = fieldSystem
+ mov r1,r6 ; r1 = scriptEnvironment
+ ldr r2,=ScriptID ; ScriptID: 2072
+ mov r3,#0 ; lastInteracted = NULL
+ push {r4}
+ mov r4,#0 ; NULL
+ bl SetupScriptEngine ; SetupScriptEngine(fieldSystem, scriptEnvironment, 2072, NULL, NULL)
+ pop {r4} ; r4 = env->taskManager
+ mov r0,#0xd5
+ ldr r1,=Task_RunScripts+1 ; env->exitTaskFunc
+ lsl r0,r0,#0x2
+ str r1,[r4,r0]
+ mov r1,r6 ; env->exitTaskEnvironment
+ add r0,#0x2c
+ str r1,[r4,r0]
+ mov r0,#12 ; env->state
+ strh r0,[r4,#0x26]
+ pop {r0-r7,pc}
+
+ItemFieldUseFunc_PKMNBoxLink:
+ push {r0-r7,lr}
+ ldr r0,[r0] ; r0 = fieldSystem
+ ldr r1,=ScriptID ; ScriptID: 2072
+ mov r2,#0 ; lastInteracted = NULL
+ bl StartMapSceneScript ; StartMapSceneScript(fieldSystem, ScriptID, NULL)
+ pop {r0-r7,pc}
+
+ItemFieldUseFunc_MedKit:
+ push {r4,r5,r6,lr}
+ add r6,r0,#0x0
+ mov r0,#0xb
+ mov r1,#0x18
+ bl AllocFromHeap
+ add r4,r0,#0x0
+ mov r0,#0x0
+ mov r1,#0x1b
+ mov r2,#0xa
+ mov r3,#0xb
+ strh r0,[r4,#0x16]
+ bl NewMsgDataFromNarc
+ add r5,r0,#0x0
+ add r0,r5,#0x0
+ mov r1,#68
+ bl NewString_ReadMsgData
+ str r0,[r4,#0x10]
+ add r0,r5,#0x0
+ bl DestroyMsgData
+ bl UseMedKit
+ ldr r0,[r6]
+ ldr r1,=0x0206518D
+ add r2,r4,#0x0
+ bl FieldSystem_CreateTask
+ mov r0,#0x0
+ pop {r4,r5,r6,pc}
+
+
+BagApp_UseItemExpansion:
+check_infinite_repel:
+ mov r0, #113 ; =ITEM_INFINITE_REPEL
+ cmp r5, r0
+ bne check_cap_candy
+ add r0,r4,#0x0
+ add r1,r5,#0x0
+ bl BagApp_UseInfiniteRepel
+ add r5,r0,#0x0
+ b used_item
+check_cap_candy: ; NOT IMPLEMENTED YET
+; mov r0, #114 ; =ITEM_CAP_CANDY
+; cmp r5, r0
+; bne check_medkit
+; add r0,r4,#0x0
+; add r1,r5,#0x0
+; bl BagApp_UseCapCandy
+; add r5,r0,#0x0
+; b used_item
+check_medkit:
+ mov r0, #115 ; =ITEM_MEDKIT
+ cmp r5, r0
+ bne return ; if not medkit, return
+ add r0,r4,#0x0
+ add r1,r5,#0x0
+ bl BagApp_UseMedKit
+ add r5,r0,#0x0
+ b used_item
+return:
+ mov r0, #0
+ pop {r3, r4, r5, pc} ; return false
+used_item:
+ bl 0x021fba7a ; call the original function to handle the cleanup after using an item
+
+BagApp_UseInfiniteRepel:
+ push {r3, r4, r5, pc}
+ add r4, r0, #0
+ add r5, r1, #0
+ bl IsRepelOn
+ cmp r0, #0
+ bne _021FBAC4
+ bl UseInfiniteRepel
+ mov r0, #0x2f
+ lsl r0, r0, #4
+ ldr r0, [r4, r0]
+ mov r1, #67
+ bl NewString_ReadMsgData
+ pop {r3, r4, r5, pc}
+_021FBAC4:
+ bl UseInfiniteRepel
+ mov r0, #0x2f
+ lsl r0, r0, #4
+ ldr r0, [r4, r0]
+ mov r1, #66
+ bl NewString_ReadMsgData
+ pop {r3, r4, r5, pc}
+
+UseInfiniteRepel:
+ push {r3,r4,r5,lr}
+ ldr r0, =SEQ_SE_DP_CARD2
+ bl PlaySE
+ bl IsRepelOn
+ cmp r0, #0 ; Check if the flag is set
+ bne repel_in_use
+ bl SaveData_Get
+ bl Save_VarsFlags_Get
+ ldr r1, =RepelFlag ; RepelFlag
+ bl Save_VarsFlags_SetFlagInArray
+ pop {r3,r4,r5,pc}
+repel_in_use:
+ bl SaveData_Get
+ bl Save_VarsFlags_Get
+ ldr r1, =RepelFlag ; RepelFlag
+ bl Save_VarsFlags_ClearFlagInArray
+ pop {r3,r4,r5,pc}
+
+IsRepelOn:
+ push {r3,r4,r5,lr}
+ bl SaveData_Get
+ bl Save_VarsFlags_Get
+ ldr r1, =RepelFlag ; RepelFlag
+ bl Save_VarsFlags_GetFlagAddr
+ ldr r0, [r0] ; Load the flag value
+ pop {r3,r4,r5,pc}
+
+BagApp_UseMedKit:
+ push {r3, r4, r5, pc}
+ add r4, r0, #0
+ add r5, r1, #0
+ bl UseMedKit
+ mov r0, #0x2f
+ lsl r0, r0, #4
+ ldr r0, [r4, r0]
+ mov r1, #68
+ bl NewString_ReadMsgData ; prints "Party Healed!", you need to add this string to line 68 in file 10
+ pop {r3, r4, r5, pc}
+
+UseMedKit:
+ push {r3,r4,r5,lr}
+ ldr r0, =SEQ_SE_DP_KAIFUKU ; pokemon healed sound effect
+ bl PlaySE
+ bl SaveData_Get
+ bl SaveArray_Party_Get
+ add r4,r0,#0x0
+ bl HealParty
+ pop {r3,r4,r5,pc}
+
+
+.pool
+
+.ascii "QoLItems_end"
+
+.close
\ No newline at end of file
diff --git a/patches/HG_SS/Code Injection (needs arm9 expansion)/ToggleRepel_HG_SS.asm b/patches/HG_SS/Code Injection (needs arm9 expansion)/ToggleRepel_HG_SS.asm
new file mode 100644
index 0000000..16b83c6
--- /dev/null
+++ b/patches/HG_SS/Code Injection (needs arm9 expansion)/ToggleRepel_HG_SS.asm
@@ -0,0 +1,78 @@
+; ToggleRepel_HG_SS.asm
+; toggles the repel depending on a flag
+; if toggle repel is off, preserves standard repel behavior for those hard of reading
+
+.nds
+.thumb
+
+; Settings:
+RepelFlag equ 0x416F ; (Flag ID, Hexadecimal)
+
+; ------------------------------------------------------------------------------------
+; DO NOT EDIT BELOW HERE UNLESS YOU KNOW WHAT YOURE DOING
+; ------------------------------------------------------------------------------------
+
+SaveData_Get equ 0x020272B0
+Save_VarsFlags_GetFlagAddr equ 0x0205045C
+Save_VarsFlags_Get equ 0x020503D0
+Save_VarsFlags_GetVarAddr equ 0x020504A4
+
+
+INJECT_ADDR equ 0x023C8000
+
+; ------- Inject hook into arm9.bin -------
+.ifdef PATCH
+.open "arm9.bin", 0x02000000
+
+.org 0x0202DB08 ; RoamerSave_RepelNotInUse
+ push {lr}
+ bl ToggleRepel
+ pop {pc}
+
+.close
+.endif
+
+; ------- Write function to synthOverlay 0000 -------
+.ifdef PREASSEMBLE
+.create "temp.bin", 0x023C8000
+.elseifdef PATCH
+.open "unpacked/synthOverlay/0000", 0x023C8000
+.endif
+
+
+.org INJECT_ADDR
+.ascii "ToggleRepel_start"
+.align 2
+
+ToggleRepel:
+ push {lr}
+ push {r0} ; probably not necessary but cba to confirm
+ bl SaveData_Get
+ bl Save_VarsFlags_Get
+ ldr r1, =RepelFlag
+ bl Save_VarsFlags_GetFlagAddr
+ ldr r0, [r0] ; Load the flag value
+ cmp r0, #0 ; Check if the flag is set
+ beq normal_repel
+ pop {r0} ; Restore the pointer
+ mov r0, #0 ; If set, return false: repel in use
+ pop {pc} ; Return
+
+normal_repel: ; can probably be reduced to a bl back into the function
+ pop {r0} ; Restore the pointer
+ add r0,#0x65
+ ldrb r0,[r0,#0x0 ]
+ cmp r0,#0x0
+ bne LAB_0202db14
+ mov r0,#0x1
+ pop {pc} ; Return
+LAB_0202db14:
+ mov r0,#0x0
+ pop {pc} ; Return
+
+.pool
+
+end:
+.ascii "ToggleRepel_end"
+
+.close
\ No newline at end of file
diff --git a/patches/HG_SS/Code Injection (needs arm9 expansion)/apply_status_from_ow_HG_SS.asm b/patches/HG_SS/Code Injection (needs arm9 expansion)/apply_status_from_ow_HG_SS.asm
index a837a9d..ad10332 100644
--- a/patches/HG_SS/Code Injection (needs arm9 expansion)/apply_status_from_ow_HG_SS.asm
+++ b/patches/HG_SS/Code Injection (needs arm9 expansion)/apply_status_from_ow_HG_SS.asm
@@ -12,8 +12,8 @@ Party_GetPokemonBySlotIndex equ 0x02074644 ; Party_GetMonByIndex
Pokemon_GetValue equ 0x0206E540 ; GetMonData
Pokemon_SetValue equ 0x0206EC40 ; SetMonData
-ScriptVar_8004 equ 0x8004 ; Script variable 0x8004
-ScriptVar_8005 equ 0x8005 ; Script variable 0x8005
+ScriptVar_PartySlot equ 0x8004 ; Script variable 0x8004
+ScriptVar_Condition equ 0x8005 ; Script variable 0x8005
MON_DATA_STATUS_CONDITION equ 160
@@ -64,11 +64,11 @@ apply_status_from_ow:
mov r1, 0x80
add r1, r4, r1 ; r1 = scriptContext + 128 = &fieldSystem
ldr r5,[r1] ; r5 = scriptContext->fieldSystem
- ldr r1, =ScriptVar_8004 ; read script variable 0x8004
+ ldr r1, =ScriptVar_PartySlot ; read script variable 0x8004
mov r0, r5
bl FieldSystem_TryGetVar ; FieldSystem_TryGetVar(ctx->fieldSystem, 0x8004)
mov r6, r0 ; r6 = partySlot
- ldr r1, =ScriptVar_8005 ; read script variable 0x8005
+ ldr r1, =ScriptVar_Condition ; read script variable 0x8005
mov r0, r5
bl FieldSystem_TryGetVar ; FieldSystem_TryGetVar(ctx->fieldSystem, 0x8005)
mov r4, r0 ; r4 = status parameter
diff --git a/patches/HG_SS/Code Injection (needs arm9 expansion)/levelcaps_HG_SS.asm b/patches/HG_SS/Code Injection (needs arm9 expansion)/levelcaps_HG_SS.asm
new file mode 100644
index 0000000..7ad0bf6
--- /dev/null
+++ b/patches/HG_SS/Code Injection (needs arm9 expansion)/levelcaps_HG_SS.asm
@@ -0,0 +1,132 @@
+;
+; LEVEL CAP PATCH FOR POKEMON HEARTGOLD/SOULSILVER
+; original Platinum concept by Memory5ty7
+; adapted for HGSS by Kalaay
+; Please credit if used
+;
+
+; INSTALLATION
+;
+; - Modify the VarNum variable below to match your DSPRE settings
+; - Modify the game scripts using DSPRE to set the selected variable to the level cap you want (the levelcap is 0 by default)
+;
+; - If the patch doesnt work, DM me on Discord (Kalaay) or join the Kingdom of DS hacking Discord Server (https://discord.gg/zAtqJDW2jC) for help
+;
+
+; CONFIGURATION
+
+ VarNum equ 0x4156 ; Variable used for the level cap
+
+; LIMITATIONS
+;
+; - when trying to apply a rare candy at level cap, the level doesnt increase but the candy gets used anyways. make sure to consider that.
+;
+
+; START OF CUSTOM CODE - DO NOT MODIFY UNLESS YOU KNOW WHAT YOU ARE DOING
+
+.nds
+.thumb
+
+; GetItemAttr_PreloadedItemData in HGSS
+Item_Get equ 0x02077DAC
+; GetMonData in HGSS
+Pokemon_GetValue equ 0x0206E540
+Heap_Free equ 0x0201AB0C
+; SaveData_Get in HGSS
+SaveData_Ptr equ 0x020272B0
+; Save_VarsFlags_Get in HGSS
+SaveData_GetVarsFlags equ 0x020503D0
+; Save_VarsFlags_GetVarAddr in HGSS
+VarsFlags_GetVarAddress equ 0x020504A4
+
+INJECT_ADDR equ 0x023C8E30
+
+.ifdef PATCH
+.open "arm9.bin", 0x02000000
+
+.org 0x02090438 ; Rare Candy repoint, hooks into UseItemOnPokemon
+
+ bl candycheck
+
+;.fill 34,0x0
+
+.close
+
+.open "overlay/overlay_0012.bin", 0x022378C0
+
+.org 0x2245A2C ; In-Battle EXP repoint, hooks into Task_GetExp
+
+ bl inbattlecheck
+
+.close
+.endif
+
+.ifdef PREASSEMBLE
+.create "temp.bin", 0x023C8000
+.elseifdef PATCH
+.open "unpacked/synthOverlay/0000", 0x023C8000
+.endif
+
+
+.org INJECT_ADDR
+.ascii "LevelCaps_start"
+.align 2
+
+inbattlecheck:
+ push {r0}
+ bl getlevelcap
+ mov r1, r0
+ pop {r0}
+ cmp r0, r1
+ blt end
+ bl #0x2245A30
+ blt end
+
+end:
+ bl #0x2245A32
+
+candycheck:
+ push {r0}
+ bl getlevelcap
+ mov r1, r0
+ pop {r0}
+ cmp r0, r1
+ bge end2
+
+ bl 0x0209043c
+
+end2:
+ bl 0x02090474
+
+getlevelcap:
+ push {r3-r7,lr}
+ bl getscriptvar
+
+getscriptvar:
+ bl SaveData_Ptr
+ bl SaveData_GetVarsFlags
+ ldr r1, =VarNum
+ bl VarsFlags_GetVarAddress
+ ldrh r0, [r0]
+ pop {r3-r7,pc}
+
+.pool
+.align 4
+
+;cap_set:
+; .ascii "LevelCaps_apply"
+; .byte 0x00 ; end of string
+;
+;cap_unset:
+; .ascii "LevelCaps_dontapply"
+; .byte 0x00 ; end of string
+;
+;debug:
+; .ascii "LevelCaps_debug"
+; .byte 0x00 ; end of string
+
+.ascii "LevelCaps_end"
+
+.close
+
+; END OF CUSTOM CODE
\ No newline at end of file
diff --git a/patches/HG_SS/Simple Patches/forgettable_HMs_HG_SS.asm b/patches/HG_SS/Simple Patches/forgettable_HMs_HG_SS.asm
new file mode 100644
index 0000000..b39f3ab
--- /dev/null
+++ b/patches/HG_SS/Simple Patches/forgettable_HMs_HG_SS.asm
@@ -0,0 +1,26 @@
+; forgettable_HMs_HG_SS.asm
+; forgettable HMs in overworld and in battle, research by AdAstra
+; make sure to not let players softlock themselves
+
+.nds
+.thumb
+
+.open "overlay/overlay_0008.bin", 0x0221BE20
+
+.org 0x0221C75A
+
+ .byte 0xC0, 0x46, 0x00, 0x20, 0x01, 0x28
+
+.close
+
+.open "arm9.bin", 0x02000000
+
+.org 0x020890A8
+
+ .byte 0xC0, 0x46, 0x00, 0x20, 0x01, 0x28
+
+.org 0x0208917A
+
+ .byte 0xC0, 0x46, 0x00, 0x20, 0x01, 0x28
+
+.close
\ No newline at end of file
diff --git a/patches/HG_SS/Simple Patches/infinite_TMs_HG_SS.asm b/patches/HG_SS/Simple Patches/infinite_TMs_HG_SS.asm
new file mode 100644
index 0000000..0433c99
--- /dev/null
+++ b/patches/HG_SS/Simple Patches/infinite_TMs_HG_SS.asm
@@ -0,0 +1,22 @@
+; infinite_TMs_HG_SS.asm
+; forgettable HMs in overworld and in battle, HexEdit by Drayano, research by Mikelan98, NextWorld, BagBoy
+; Mikelan98 requests that you give credit to him if you implement this in your hack.
+
+.nds
+.thumb
+
+.open "overlay/overlay_0015.bin", 0x021F9380
+
+.org 0x021FF5B9
+
+ .byte 0xE0
+
+.close
+
+.open "arm9.bin", 0x02000000
+
+.org 0x020825A7
+
+ .byte 0xE0
+
+.close
\ No newline at end of file
diff --git a/patches/HG_SS/Simple Patches/instant_party_healing_HG_SS.asm b/patches/HG_SS/Simple Patches/instant_party_healing_HG_SS.asm
new file mode 100644
index 0000000..fd8c404
--- /dev/null
+++ b/patches/HG_SS/Simple Patches/instant_party_healing_HG_SS.asm
@@ -0,0 +1,14 @@
+; instant_party_healing_HG_SS.asm
+; instant item healing in party menu, research by Fantafaust
+
+.nds
+.thumb
+
+.open "arm9.bin", 0x02000000
+
+.org 0x02081750
+
+ .byte 0x21
+ .byte 0x00
+
+.close
\ No newline at end of file
diff --git a/patches/PLAT/Code Injection (needs arm9 expansion)/apply_status_from_ow_PLAT.asm b/patches/PLAT/Code Injection (needs arm9 expansion)/apply_status_from_ow_PLAT.asm
index e79de6d..b174dba 100644
--- a/patches/PLAT/Code Injection (needs arm9 expansion)/apply_status_from_ow_PLAT.asm
+++ b/patches/PLAT/Code Injection (needs arm9 expansion)/apply_status_from_ow_PLAT.asm
@@ -11,8 +11,8 @@ Party_GetPokemonBySlotIndex equ 0x0207A0FC
Pokemon_GetValue equ 0x02074470
Pokemon_SetValue equ 0x02074B30
-ScriptVar_8004 equ 0x8004 ; Script variable 0x8004
-ScriptVar_8005 equ 0x8005 ; Script variable 0x8005
+ScriptVar_PartySlot equ 0x8004 ; Script variable 0x8004
+ScriptVar_Condition equ 0x8005 ; Script variable 0x8005
MON_DATA_STATUS_CONDITION equ 160
@@ -60,11 +60,11 @@ apply_status_from_ow:
mov r1, 0x80
add r1, r4, r1 ; r1 = scriptContext + 128 = &fieldSystem
ldr r5,[r1] ; r5 = scriptContext->fieldSystem
- ldr r1, =ScriptVar_8004 ; read script variable 0x8004
+ ldr r1, =ScriptVar_PartySlot ; read script variable 0x8004
mov r0, r5
bl FieldSystem_TryGetVar ; FieldSystem_TryGetVar(ctx->fieldSystem, 0x8004)
mov r6, r0 ; r6 = partySlot
- ldr r1, =ScriptVar_8005 ; read script variable 0x8005
+ ldr r1, =ScriptVar_Condition ; read script variable 0x8005
mov r0, r5
bl FieldSystem_TryGetVar ; FieldSystem_TryGetVar(ctx->fieldSystem, 0x8005)
mov r4, r0 ; r4 = status parameter
diff --git a/patches/PLAT/Code Injection (needs arm9 expansion)/frame_unlock_settings_PLAT.asm b/patches/PLAT/Code Injection (needs arm9 expansion)/frame_unlock_settings_PLAT.asm
new file mode 100644
index 0000000..a658b45
--- /dev/null
+++ b/patches/PLAT/Code Injection (needs arm9 expansion)/frame_unlock_settings_PLAT.asm
@@ -0,0 +1,76 @@
+; frame_unlock_settings_PLAT.asm
+;
+; replaces the "button mode" setting with a "unlock fps" setting
+; initially implemented by Mikelan98 and AdAstra in Following Platinum, reverse engineered and adapted for G4P by Kalaay
+; requires you to change the settings strings to "UNLOCK FPS", "OFF", "BATTLE" and "ALWAYS"
+
+.nds
+.thumb
+
+INJECT_ADDR equ 0x023C8000
+
+OS_WaitIrq equ 0x020C12B4
+SaveData_GetOptions equ 0x02025E44
+Options_ButtonMode equ 0x02027B30
+SaveData_Ptr equ 0x020245A4
+
+.ifdef PATCH
+
+.open "arm9.bin", 0x02000000
+.org 0x02000DCE
+ bl function
+.org 0x02017CA0 ; ApplyButtonModeToInput skip
+ b 0x02017dc4
+.close
+
+.endif
+
+.ifdef PREASSEMBLE
+.create "temp.bin", 0x023C8000
+.elseifdef PATCH
+.open "unpacked/synthOverlay/0009", 0x023C8000
+.endif
+
+.org INJECT_ADDR
+.ascii "frame_unlock_settings_start"
+.align 4
+
+function:
+ push {r4,lr}
+ mov r4,r0
+ bl SaveData_Ptr
+ bl SaveData_GetOptions
+ bl Options_ButtonMode
+ cmp r0,#0x1
+ bne LAB_023cdb9e
+ ldr r1,=0x021BF370 ; loaded overlay
+ ldr r1,[r1]
+ cmp r1,#0x10 ; 16 = battle overlay
+ bne LAB_023cdb9e
+ mov r4,#0x0
+ b LAB_023cdba4
+LAB_023cdb9e:
+ cmp r0,#0x2
+ bne LAB_023cdba4
+ mov r4,#0x0
+LAB_023cdba4:
+ mov r0,r4
+ mov r1,#0x1
+ blx OS_WaitIrq
+ pop {r4,pc}
+
+.pool
+.align 4
+
+FUN_023c9b0c:
+ ldr r0, =0x02101D2C ; currApplication
+ ldr r0,[r0,#0x0]
+ ldr r0,[r0,#0x1c]
+ bx lr
+
+.pool
+.align 4
+
+.ascii "frame_unlock_settings_end"
+
+.close
\ No newline at end of file
diff --git a/patches/PLAT/Code Injection (needs arm9 expansion)/levelcaps_PLAT.asm b/patches/PLAT/Code Injection (needs arm9 expansion)/levelcaps_PLAT.asm
index 936190b..49b98f2 100644
--- a/patches/PLAT/Code Injection (needs arm9 expansion)/levelcaps_PLAT.asm
+++ b/patches/PLAT/Code Injection (needs arm9 expansion)/levelcaps_PLAT.asm
@@ -31,6 +31,13 @@
INJECT_ADDR equ 0x023C8B20
+Item_Get equ 0x0207D014
+Pokemon_GetValue equ 0x2074470
+Heap_Free equ 0x020181c4
+SaveData_Ptr equ 0x020245a4
+SaveData_GetVarsFlags equ 0x020507E4
+VarsFlags_GetVarAddress equ 0x020508B8
+
.ifdef PATCH
.open "arm9.bin", 0x02000000
@@ -78,13 +85,13 @@ end:
candycheck:
add r0, r4, #0
mov r1, #0x19
- bl 0x207d014
+ bl Item_Get
cmp r0, #0
beq end2
add r0, r6, #0
mov r1, #0xa1
mov r2, #0
- bl 0x2074470
+ bl Pokemon_GetValue
push {r0}
bl getlevelcap
@@ -94,7 +101,7 @@ candycheck:
bhs end2
add r0, r4, #0
- bl 0x20181c4
+ bl Heap_Free
add sp, #0x18
mov r0, #1
pop {r3, r4, r5, r6, r7, pc}
@@ -102,20 +109,15 @@ candycheck:
end2:
bl 0x209657e
-end3:
- pop {r0-r2}
- bl 0x209657e
-
getlevelcap:
push {r3-r7,lr}
bl getscriptvar
- pop {r3-r7,pc}
-
+
getscriptvar:
- bl 0x020245a4
- bl 0x020507E4
+ bl SaveData_Ptr
+ bl SaveData_GetVarsFlags
ldr r1, =VarNum
- bl 0x020508B8
+ bl VarsFlags_GetVarAddress
ldrh r0, [r0]
pop {r3-r7,pc}
diff --git a/patches/PLAT/Simple Patches/dry_skin_ai_fix_PLAT.asm b/patches/PLAT/Simple Patches/dry_skin_ai_fix_PLAT.asm
new file mode 100644
index 0000000..0e95c02
--- /dev/null
+++ b/patches/PLAT/Simple Patches/dry_skin_ai_fix_PLAT.asm
@@ -0,0 +1,13 @@
+; vs_seeker_qol_PLAT.asm
+; battery 1 step recharge and 100% chance of finding trainers, research by Memory5ty7
+
+.nds
+.thumb
+
+.open "overlay/overlay_0014.bin", 0x0221FC20
+
+.org 0x022249CC
+
+ .byte 0x57
+
+.close
\ No newline at end of file
diff --git a/patches/PLAT/Simple Patches/forgettable_HMs_PLAT.asm b/patches/PLAT/Simple Patches/forgettable_HMs_PLAT.asm
new file mode 100644
index 0000000..34281c9
--- /dev/null
+++ b/patches/PLAT/Simple Patches/forgettable_HMs_PLAT.asm
@@ -0,0 +1,22 @@
+; forgettable_HMs_PLAT.asm
+; forgettable HMs in overworld and in battle, research by AdAstra
+; make sure to not let players softlock themselves
+
+.nds
+.thumb
+
+.open "overlay/overlay_0013.bin", 0x0221FC20
+
+.org 0x0222056E
+
+ .byte 0xC0, 0x46, 0x00, 0x20, 0x01, 0x28
+
+.close
+
+.open "arm9.bin", 0x02000000
+
+.org 0x0208CDD2
+
+ .byte 0xC0, 0x46, 0x00, 0x20, 0x01, 0x28
+
+.close
\ No newline at end of file
diff --git a/patches/PLAT/Simple Patches/infinite_TMs_PLAT.asm b/patches/PLAT/Simple Patches/infinite_TMs_PLAT.asm
new file mode 100644
index 0000000..a279c57
--- /dev/null
+++ b/patches/PLAT/Simple Patches/infinite_TMs_PLAT.asm
@@ -0,0 +1,22 @@
+; infinite_TMs_PLAT.asm
+; forgettable HMs in overworld and in battle, HexEdit by Drayano, research by Mikelan98, NextWorld, BagBoy
+; Mikelan98 requests that you give credit to him if you implement this in your hack.
+
+.nds
+.thumb
+
+.open "overlay/overlay_0084.bin", 0x0223B5A0
+
+.org 0x0223F912
+
+ .word 0
+
+.close
+
+.open "arm9.bin", 0x02000000
+
+.org 0x020865EB
+
+ .byte 0xE0
+
+.close
\ No newline at end of file
diff --git a/patches/PLAT/Simple Patches/instant_party_healing_PLAT.asm b/patches/PLAT/Simple Patches/instant_party_healing_PLAT.asm
new file mode 100644
index 0000000..ceb721e
--- /dev/null
+++ b/patches/PLAT/Simple Patches/instant_party_healing_PLAT.asm
@@ -0,0 +1,14 @@
+; instant_party_healing_PLAT.asm
+; instant item healing in party menu, research by Yako
+
+.nds
+.thumb
+
+.open "arm9.bin", 0x02000000
+
+.org 0x02085734
+
+ .byte 0x21
+ .byte 0x46
+
+.close
\ No newline at end of file
diff --git a/patches/PLAT/Simple Patches/instant_pokeradar_recharge_PLAT.asm b/patches/PLAT/Simple Patches/instant_pokeradar_recharge_PLAT.asm
new file mode 100644
index 0000000..ff6eb82
--- /dev/null
+++ b/patches/PLAT/Simple Patches/instant_pokeradar_recharge_PLAT.asm
@@ -0,0 +1,13 @@
+; instant_pokeradar_recharge_PLAT.asm
+; lets you use the pokeradar without having to recharge it, research by BagBoy and Mikelan98
+
+.nds
+.thumb
+
+.open "arm9.bin", 0x02000000
+
+.org 0x02069A42
+
+ .byte 0x00
+
+.close
\ No newline at end of file
diff --git a/patches/PLAT/Simple Patches/vs_seeker_qol_PLAT.asm b/patches/PLAT/Simple Patches/vs_seeker_qol_PLAT.asm
new file mode 100644
index 0000000..7c34f87
--- /dev/null
+++ b/patches/PLAT/Simple Patches/vs_seeker_qol_PLAT.asm
@@ -0,0 +1,19 @@
+; vs_seeker_qol_PLAT.asm
+; battery 1 step recharge and 100% chance of finding trainers, research by BagBoy
+
+.nds
+.thumb
+
+.open "overlay/overlay_0005.bin", 0x021D0D80
+
+.org 0x021DBBC4
+
+ .byte 0x64
+ .byte 0x26
+ .byte 0x31
+
+.org 0x021DBD28
+
+ .byte 0x64
+
+.close
\ No newline at end of file
diff --git a/patches/REMEMBER TO READ THE DOCS FOR THE PATCH YOU ARE APPLYING/REMEMBER TO READ THE DOCS FOR THE PATCH YOU ARE APPLYING b/patches/REMEMBER TO READ THE DOCS FOR THE PATCH YOU ARE APPLYING/REMEMBER TO READ THE DOCS FOR THE PATCH YOU ARE APPLYING
new file mode 100644
index 0000000..e69de29
diff --git a/src/filedialog.rs b/src/filedialog.rs
new file mode 100644
index 0000000..4fc9f14
--- /dev/null
+++ b/src/filedialog.rs
@@ -0,0 +1,44 @@
+use std::path::{Path, PathBuf};
+use log::{debug, info};
+use rfd::FileDialog;
+
+pub fn get_project_path() -> Option {
+ debug!("Opening ROM folder dialog...");
+ FileDialog::new()
+ .set_title("Select unpacked ROM folder")
+ .pick_folder()
+ .map_or_else(
+ || {
+ info!("No folder selected");
+ None
+ },
+ |selected_folder| {
+ info!("Selected folder: {}", selected_folder.display());
+ Some(selected_folder)
+ },
+ )
+}
+
+pub fn get_patch_path(exe_dir: &Path) -> Option {
+ //println!("Please select the patch file to apply");
+ debug!("Opening patch file dialog...");
+
+ let patches_dir = exe_dir.join("patches");
+
+ // Use rfd to open a file dialog and select the project path
+ FileDialog::new()
+ .add_filter("Patch files", &["asm"])
+ .set_title("Select Patch file")
+ .set_directory(patches_dir)
+ .pick_file()
+ .map_or_else(
+ || {
+ info!("No patch selected.");
+ None
+ },
+ |selected_patch| {
+ info!("Selected patch: {}", selected_patch.display());
+ Some(selected_patch)
+ },
+ )
+}
\ No newline at end of file
diff --git a/src/gui.rs b/src/gui.rs
new file mode 100644
index 0000000..714c958
--- /dev/null
+++ b/src/gui.rs
@@ -0,0 +1,183 @@
+use crate::constants::{PATCH_DIRECTIVE, PREASSEMBLE_DIRECTIVE};
+use crate::filedialog::{get_patch_path, get_project_path};
+use crate::io::Error;
+use crate::run_armips;
+use crate::synthoverlay_utils::handle_synthoverlay;
+use crate::usage_checks::{determine_game_version, is_patch_compatible, needs_synthoverlay};
+use eframe::egui;
+use eframe::egui::{Color32, RichText};
+use log::{debug, error, info, warn, Level, LevelFilter, Log, Metadata, Record};
+use std::path::{Path, PathBuf};
+use std::sync::{Mutex, OnceLock};
+use std::{fs, io};
+
+pub struct GuiLogger {
+ log_buffer: Mutex>,
+}
+#[derive(Clone)]
+pub struct LogEntry {
+ pub level: Level,
+ pub message: String,
+}
+static LOGGER: OnceLock = OnceLock::new();
+impl Log for GuiLogger {
+ fn enabled(&self, _: &Metadata) -> bool {
+ true
+ }
+ fn log(&self, record: &Record) {
+ if self.enabled(record.metadata()) {
+ let mut buffer = self.log_buffer.lock().unwrap();
+ buffer.push(LogEntry {
+ level: record.level(),
+ message: format!("{}", record.args()),
+ });
+ }
+ }
+ fn flush(&self) {}
+}
+
+impl GuiLogger {
+ pub fn get_logs() -> Vec {
+ LOGGER
+ .get()
+ .map(|l| l.log_buffer.lock().unwrap().clone())
+ .unwrap_or_default()
+ }
+ pub fn init(max_level: LevelFilter) {
+ LOGGER
+ .set(Self {
+ log_buffer: Mutex::new(Vec::new()),
+ })
+ .ok();
+ log::set_logger(LOGGER.get().unwrap()).unwrap();
+ log::set_max_level(max_level);
+ }
+}
+
+pub struct G4PatcherApp {
+ project_path: Option,
+ patch: Option,
+ game_version: Option,
+ exe_dir: PathBuf,
+}
+
+impl Default for G4PatcherApp {
+ fn default() -> Self {
+ Self {
+ project_path: None,
+ patch: None,
+ game_version: None,
+ exe_dir: std::env::current_exe()
+ .ok()
+ .and_then(|p| p.parent().map(Path::to_path_buf))
+ .unwrap_or_else(|| PathBuf::from(".")),
+ }
+ }
+}
+
+impl eframe::App for G4PatcherApp {
+ fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) {
+ egui::CentralPanel::default().show(ctx, |ui| {
+ ui.heading("Pokemon Gen 4 Code Injection Patcher");
+ ui.horizontal(|ui| {
+ if ui.button("Select ROM Folder").clicked() {
+ if let Some(path) = get_project_path() {
+ self.project_path = Some(path.display().to_string());
+ self.game_version = match determine_game_version(&path.display().to_string()) {
+ Ok(version) => {
+ info!("Game version: {version}");
+ Some(version.to_string())
+ },
+ Err(e) => {
+ error!("Error determining game version: {e}\nPlease ensure you are selecting the ROM folder, usually called 'romname_DSPRE_contents.'");
+ self.project_path = None;
+ None
+ }
+ };
+ } else {self.project_path = None;}
+ }
+ ui.with_layout(egui::Layout::left_to_right(egui::Align::TOP).with_main_wrap(true), |ui| {
+ ui.label(RichText::new(self.project_path.clone()
+ .unwrap_or_else(|| "No ROM folder selected".to_string())));
+ });
+ });
+ ui.horizontal(|ui| {
+ let selectpatch_enabled = self.project_path.is_some();
+ if ui.add_enabled(selectpatch_enabled, egui::Button::new("Select Patch")).clicked() {
+ if let Some(file) = get_patch_path(&self.exe_dir) {
+ self.patch = Some(file.display().to_string());
+ if !is_patch_compatible(&self.patch.clone().unwrap(), &self.project_path.clone().unwrap()) {
+ warn!("This patch is not compatible with this ROM, please select a compatible patch.");
+ self.patch = None;
+ }
+ } else {self.patch = None;}
+ }
+ ui.with_layout(egui::Layout::left_to_right(egui::Align::TOP).with_main_wrap(true), |ui| {
+ ui.label(RichText::new(self.patch.clone()
+ .unwrap_or_else(|| "No patch selected".to_string())));
+ });
+ });
+ ui.horizontal(|ui| {
+ let apply_enabled = self.project_path.is_some() && self.patch.is_some();
+ if ui.add_enabled(apply_enabled, egui::Button::new("Apply Patch")).clicked() {
+ if needs_synthoverlay(&self.patch.clone().unwrap()) {
+ if let Err(e) = run_armips(&self.patch.clone().unwrap(),
+ &self.project_path.clone().unwrap(),
+ &self.exe_dir,
+ PREASSEMBLE_DIRECTIVE) {
+ error!("Failed to assemble the patch: {e}");
+ }
+ let patch_size = fs::metadata(format!("{}/temp.bin", self.project_path.clone().unwrap()))
+ .map_err(|e| Error::new(io::ErrorKind::NotFound, format!("Failed to read temp.bin: {}", e))).unwrap()
+ .len() as usize;
+ info!("Patch size: {patch_size} bytes");
+ fs::remove_file(format!("{}/temp.bin", self.project_path.clone().unwrap()))
+ .map_err(|e| Error::new(io::ErrorKind::NotFound, format!("Failed to delete temp.bin: {e}"))).unwrap();
+ match handle_synthoverlay(&self.patch.clone().unwrap(), &self.project_path.clone().unwrap(), &self.game_version.clone().unwrap(), patch_size){
+ Ok(()) => debug!("SynthOverlay handled successfully."),
+ Err(e) => {
+ warn!("Failed to handle synthOverlay: {e}");
+ return
+ }
+ }
+ }
+ if matches!(run_armips(&self.patch.clone().unwrap(), &self.project_path.clone().unwrap(), &self.exe_dir, PATCH_DIRECTIVE), Ok(())) {
+ debug!("armips ran successfully.");
+ info!("\nPatch applied! You can now repack your ROM.\n");
+ } else {
+ error!("there was an error running armips, please contact the developer with the log below.");
+ }
+
+ }
+ });
+ ui.separator();
+ ui.collapsing("Limitations", |ui| {
+ ui.label("- Does not check if patch is already applied (may duplicate).");
+ ui.label("- Does not verify overlay compression (ensure hook overlay is uncompressed).");
+ });
+ ui.label("Make sure to read the documentation for the patch you are applying!");
+ ui.separator();
+ ui.with_layout(egui::Layout::top_down_justified(egui::Align::LEFT), |ui| {
+ ui.group(|ui| {
+ ui.label("Log:");
+ egui::ScrollArea::vertical()
+ .max_height(ui.available_height())
+ .stick_to_bottom(true)
+ .show(ui, |ui| {
+ for entry in GuiLogger::get_logs() {
+ let color = match entry.level {
+ Level::Error => Color32::LIGHT_RED,
+ Level::Warn => Color32::YELLOW,
+ Level::Info => Color32::WHITE,
+ Level::Debug => Color32::LIGHT_BLUE,
+ Level::Trace => Color32::GREEN,
+ };
+ ui.label(RichText::new(format!("[{}] {}", entry.level, entry.message))
+ .color(color));
+ }
+ });
+ });
+ });
+ });
+ }
+}
diff --git a/src/main.rs b/src/main.rs
index e12038b..471be60 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1,78 +1,39 @@
+#![windows_subsystem = "windows"]
#![warn(clippy::nursery, clippy::pedantic)]
mod constants;
mod synthoverlay_utils;
mod usage_checks;
+mod filedialog;
+mod gui;
use std::fs;
-use rfd::FileDialog;
use std::io::{self, Write};
use std::path::{Path, PathBuf};
use std::process::Command;
+use eframe::{egui};
use usage_checks::{determine_game_version, is_patch_compatible, needs_synthoverlay};
use synthoverlay_utils::handle_synthoverlay;
use constants::{PATCH_DIRECTIVE, PREASSEMBLE_DIRECTIVE};
-
-fn get_project_path() -> PathBuf {
- // Use rfd to open a file dialog and select the project path
- FileDialog::new()
- .set_title("Select unpacked ROM folder")
- .pick_folder()
- .map_or_else(
- || {
- println!("No folder selected, exiting.");
- std::process::exit(0);
- },
- |selected_folder| {
- println!("Selected folder: {}", selected_folder.display());
- selected_folder
- },
- )
-}
-
-fn get_patch_path(exe_dir: &Path, game_version: &str) -> PathBuf {
- println!("Please select the patch file to apply");
-
- let patches_dir = exe_dir.join("patches");
-
- // Use rfd to open a file dialog and select the project path
- FileDialog::new()
- .add_filter("Patch files", &["asm"])
- .set_title("Select Patch file")
- .set_directory(patches_dir.join(
- match game_version {
- "Platinum" => "PLAT",
- "HeartGold" | "SoulSilver" => "HG_SS",
- _ => {
- panic!("Unknown game version: {game_version}.");
- }
- }
- ))
- .pick_file()
- .map_or_else(
- || {
- println!("No patch selected, exiting.");
- std::process::exit(0);
- },
- |selected_patch| {
- println!("\nSelected patch: {}", selected_patch.display());
- selected_patch
- },
- )
-}
+use log::{error, info, warn};
+use filedialog::{get_project_path, get_patch_path};
+use crate::gui::{G4PatcherApp, GuiLogger};
fn run_armips(asm_path: &str, rom_dir: &str, exe_dir: &Path, armips_directive: &str) -> io::Result<()> {
let armips_path = exe_dir.join("assets").join("armips.exe");
- //println!("Using armips at: {}", armips_path.display());
-
+ if !armips_path.exists() {
+ error!("armips executable not found at {}", armips_path.display());
+ return Err(io::Error::new(io::ErrorKind::NotFound, "armips.exe not found"));
+ }
+
if armips_directive == PREASSEMBLE_DIRECTIVE {
- println!("Calculating patch size...");
+ info!("Calculating patch size...");
Command::new(armips_path)
.args([asm_path, "-definelabel", PREASSEMBLE_DIRECTIVE, "1"])
.current_dir(rom_dir)
.status()?;
} else {
- println!("Patching ROM with armips...");
+ info!("Patching ROM with armips...");
Command::new(armips_path)
.args([asm_path, "-definelabel", PATCH_DIRECTIVE, "1"])
.current_dir(rom_dir)
@@ -88,11 +49,18 @@ fn enter_to_exit() -> Result<(), io::Error> {
Ok(())
}
-fn main() -> io::Result<()> {
+fn run_cli() -> io::Result<()> {
println!("Welcome to the Platinum/HGSS code injection patcher!\n\nMake sure to read the documentation for the patch you are trying to apply!\n\nPlease select your unpacked ROM folder");
// Get the project path from the user
- let project_path = get_project_path().display().to_string();
+ let project_path = match get_project_path() {
+ Some(path) => path.display().to_string(),
+ None => {
+ println!("No project path selected, exiting.");
+ return enter_to_exit();
+ }
+ };
+
let game_version = match determine_game_version(&project_path) {
Ok(version) => version,
Err(e) => {
@@ -110,14 +78,16 @@ fn main() -> io::Result<()> {
.unwrap_or_else(|| PathBuf::from("."));
// Get the selected patch file from the user
- let patch_path = get_patch_path(&exe_dir, game_version).display().to_string();
+ let patch_path = get_patch_path(&exe_dir)
+ .ok_or_else(|| io::Error::new(io::ErrorKind::NotFound, "No patch file selected"))?
+ .display().to_string();
// Check if the patch is compatible with the selected ROM
if !is_patch_compatible(&patch_path, &project_path) {
println!("This patch is not compatible with this ROM, please select a compatible patch.");
return enter_to_exit();
}
-
+
if needs_synthoverlay(&patch_path) {
// preassemble the patch to calculate the size from the created temp.bin
if !matches!(run_armips(&patch_path, &project_path, &exe_dir, PREASSEMBLE_DIRECTIVE), Ok(())) {
@@ -134,7 +104,30 @@ fn main() -> io::Result<()> {
if matches!(run_armips(&patch_path, &project_path, &exe_dir, PATCH_DIRECTIVE), Ok(())) {
println!("\narmips ran successfully, patch applied! You can now repack your ROM.\n");
- }
+ }
enter_to_exit()
}
+
+fn main() -> eframe::Result {
+ GuiLogger::init(log::LevelFilter::Info);
+
+ let options = eframe::NativeOptions {
+ viewport: egui::ViewportBuilder::default()
+ .with_inner_size([640.0, 400.0])
+ .with_drag_and_drop(true),
+ ..Default::default()
+ };
+ eframe::run_native(
+ "G4Patcher",
+ options,
+ Box::new(|_cc| Ok(Box::::default())),
+ )
+
+ //if let Err(e) = run_cli() {
+ // error!("An error occurred: {e}");
+ // return Err(e);
+ //}
+ //Ok(())
+}
+
diff --git a/src/synthoverlay_utils.rs b/src/synthoverlay_utils.rs
index dda4762..4602310 100644
--- a/src/synthoverlay_utils.rs
+++ b/src/synthoverlay_utils.rs
@@ -3,8 +3,8 @@
use std::{fs, io};
use std::io::{BufRead, BufReader};
use std::path::PathBuf;
+use log::info;
use crate::constants::{GAME_DEPENDENT_OVERLAY_HG, GAME_DEPENDENT_OVERLAY_PLAT};
-use crate::enter_to_exit;
use crate::usage_checks::is_arm9_expanded;
/// Determine the game overlay based on the patch name.
@@ -135,10 +135,11 @@ pub fn handle_synthoverlay(patch_path: &str, project_path: &str, game_version: &
// Check if the arm9 is expanded, if not, prompt the user to expand it
if is_arm9_expanded(project_path, game_version)? {
- println!("arm9 is expanded, proceeding");
+ info!("arm9 is expanded, proceeding");
} else {
- println!("arm9 is not expanded, please expand it before running this tool.");
- return enter_to_exit();
+ return Err(io::Error::other(
+ "arm9 is not expanded, please expand it before applying the patch.",
+ ));
}
// Read and process the synthOverlay file
let synth_overlay_path = format!(
@@ -147,20 +148,20 @@ pub fn handle_synthoverlay(patch_path: &str, project_path: &str, game_version: &
determine_game_overlay(patch_path)
);
let synth_overlay = fs::read(&synth_overlay_path)?;
- println!(
+ info!(
"Read synthOverlay file successfully. Located at: {synth_overlay_path}"
);
- println!("Searching for injection offset");
+ info!("Searching for injection offset");
let offset =
find_injection_offset(&synth_overlay, required_size).expect("Failed to find injection offset");
- println!(
+ info!(
"Found injection offset at {:#X} in synthOverlay {}",
offset,
determine_game_overlay(patch_path)
);
let corrected_offset = 0x23c8000 + offset as u32;
- println!("Corrected offset: {corrected_offset:#X}");
+ info!("Corrected offset: {corrected_offset:#X}");
insert_corrected_offset(patch_path, corrected_offset)
.expect("Failed to correct offset in asm file");
Ok(())
diff --git a/src/usage_checks.rs b/src/usage_checks.rs
index 0a057a8..dd88da9 100644
--- a/src/usage_checks.rs
+++ b/src/usage_checks.rs
@@ -6,6 +6,7 @@ use crate::constants::{
use std::io::{BufRead, BufReader, Read, Seek, SeekFrom};
use std::path::PathBuf;
use std::{fs, io};
+use log::error;
/// Determine the game version based on the header.bin file in the project path.
///
@@ -29,20 +30,17 @@ pub fn determine_game_version(project_path: &str) -> io::Result<&str> {
let header_path = PathBuf::from(project_path).join("header.bin");
fs::File::open(&header_path).map_or_else(|_| {
- eprintln!("header.bin not found at path: {}", header_path.display());
Err(io::Error::new(io::ErrorKind::NotFound, "header.bin not found"))
}, |mut file| {
let mut buf = [0u8; 4];
- file.seek(SeekFrom::Start(0xC))
- .expect("Failed to seek in header.bin");
- file.read_exact(&mut buf)
- .expect("Failed to read from header.bin");
+ file.seek(SeekFrom::Start(0xC))?;
+ file.read_exact(&mut buf)?;
match buf {
PLATINUM_BYTES => Ok(PLATINUM),
HEARTGOLD_BYTES => Ok(HEARTGOLD),
SOULSILVER_BYTES => Ok(SOULSILVER),
_ => {
- eprintln!("Unknown game version in header.bin at path: {}\nBytes found:{:02X} {:02X} {:02X} {:02X}",
+ error!("Unknown game version in header.bin at path: {}\nBytes found:{:02X} {:02X} {:02X} {:02X}",
header_path.display(), buf[0], buf[1], buf[2], buf[3]);
Err(io::Error::new(io::ErrorKind::InvalidData, "Unknown game version in header.bin"))
}