Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
95 commits
Select commit Hold shift + click to select a range
4454d89
Update packages
Fernthedev Nov 11, 2024
19925a8
Generate types for Unity 2022, parameters are broken
Fernthedev Nov 11, 2024
07ca277
Make ParameterInfo wrap Il2CppType
Fernthedev Nov 11, 2024
5ddc8e8
Update detour to retour fork
Fernthedev Nov 11, 2024
168aafc
Rename Unity 2022, 2021, 2019 to ilc2pp_v31, 29, 24 respectively
Fernthedev Nov 11, 2024
30fe3cd
Bring back types 2018
Fernthedev Nov 11, 2024
8e3761b
Fmt and clippy
Fernthedev Nov 11, 2024
83b2e14
Add feature
Fernthedev Nov 26, 2024
078c209
Fix version check
Fernthedev Dec 2, 2024
d99d802
Add Void type
Fernthedev Dec 2, 2024
63b28ff
Add types for cordl
Fernthedev Dec 3, 2024
e571825
Generics information
Fernthedev Dec 3, 2024
fad1763
Add ByRef/ByRefMut
Fernthedev Dec 4, 2024
0513125
static il2cpp exception lifetime
Fernthedev Dec 6, 2024
09f2ee6
Add ObjectType trait
Fernthedev Dec 7, 2024
92a6d16
Value type extension helper
Fernthedev Dec 7, 2024
ee46f01
Move value box
Fernthedev Dec 7, 2024
1917569
Implement type for pointer variants
Fernthedev Dec 7, 2024
361d9cd
Implement traits for pointer types
Fernthedev Dec 7, 2024
e6e3588
Add static lifetime
Fernthedev Dec 7, 2024
7e2afd6
ObjectType implementation for pointer type
Fernthedev Dec 7, 2024
2773c1f
Remove conflicting trait impl
Fernthedev Dec 7, 2024
a3ea98a
add type impl for char
Fernthedev Dec 8, 2024
f4cec34
ByRef ignorance
Fernthedev Dec 8, 2024
d7620c5
Increase maximum parameter count
Fernthedev Dec 8, 2024
6750adc
Add Gc/GcType for reference types
Fernthedev Dec 9, 2024
12acbce
Manually implement traits
Fernthedev Dec 9, 2024
da58e65
More GC type shenanigans
Fernthedev Dec 9, 2024
d62dd8c
aDD bounds
Fernthedev Dec 9, 2024
9faeae1
Fix Held type
Fernthedev Dec 9, 2024
95aa66c
Fix generic bounds check for Gc<T>
Fernthedev Dec 9, 2024
e1705dc
Fix generic bounds check in `caller`
Fernthedev Dec 9, 2024
6b96da1
Implement debug for `Gc`
Fernthedev Dec 9, 2024
f72a2d1
Use GC for return types
Fernthedev Dec 10, 2024
798d0b0
Fix type bindings for different platforms
Fernthedev Dec 10, 2024
d257fcc
Add types for GC callee
Fernthedev Dec 10, 2024
d059d1e
Fix GcType argument bound check
Fernthedev Dec 10, 2024
401319b
Add `convert` and documentation
Fernthedev Dec 10, 2024
7569a71
Change `convert` to `cast` and add `downcast`
Fernthedev Dec 10, 2024
7ef98df
Add debug logging information for method lookup
Fernthedev Dec 15, 2024
3decad7
Add const T* for Gc<T>
Fernthedev Jan 2, 2025
62b6103
Add Gc specialization for ObjectType
Fernthedev Jan 5, 2025
42b037c
Add ValueTypePadding type
Fernthedev Jan 5, 2025
1acb1ce
Add traits to `ValueTypePadding`
Fernthedev Jan 5, 2025
17552b1
Update beatsaber-hook
Fernthedev Jan 5, 2025
b0470ef
Change Held for Gc<T>
Fernthedev Jan 5, 2025
f07aa16
Add Send + Sync to Gc<T>
Fernthedev Jan 6, 2025
1092d6d
Refactor error handling for Send/Sync support
Fernthedev Jan 8, 2025
f0e91f7
Implement error for Gc<Exception>
Fernthedev Jan 8, 2025
d98f1d7
Debug log
Fernthedev Jan 13, 2025
5b43181
Pretty print
Fernthedev Jan 13, 2025
b64b203
Debug print lines
Fernthedev Jan 13, 2025
a20a10a
More debug logs
Fernthedev Jan 13, 2025
8d3d014
Improve bindgen
Fernthedev Jan 13, 2025
70804ea
Better intellisense
Fernthedev Jan 13, 2025
202623a
More logging
Fernthedev Jan 13, 2025
d7b20b0
More logging
Fernthedev Jan 13, 2025
25a4bdd
More logs
Fernthedev Jan 13, 2025
9c1b5d1
Fix logging to safely retrieve method parameter types
Fernthedev Jan 13, 2025
7397a98
Log parameter count
Fernthedev Jan 13, 2025
2757b3c
Even more logging
Fernthedev Jan 13, 2025
9d920ea
Log class not found
Fernthedev Jan 13, 2025
85a47e9
Fix typo
Fernthedev Jan 13, 2025
19c792b
Add ByRef wrapper type for representing ref types
Fernthedev Jan 13, 2025
89fbc12
Finish ByRef<T>
Fernthedev Jan 14, 2025
008101e
Fix feature lock
Fernthedev Jan 14, 2025
a2f699d
ByRef is not a ThisArgument
Fernthedev Jan 14, 2025
8abbbb4
Add Returned and ThisArgument
Fernthedev Jan 14, 2025
b8d35ec
Add Type traits to ByRef for callee
Fernthedev Jan 14, 2025
cd491af
Log method name
Fernthedev Jan 14, 2025
0b6fec3
More log information
Fernthedev Jan 14, 2025
0832652
Update retour
Fernthedev Aug 31, 2025
6f16ded
Add flamingo hooks
Fernthedev Jan 13, 2026
55a2b46
feat: Enable bindgen feature and improve build process
Fernthedev Jan 13, 2026
5299945
Make Gc<T> C API friendly
Fernthedev Jan 13, 2026
770c044
chore: Fixes and format
Fernthedev Jan 13, 2026
c5f8ac4
Fix build
Fernthedev Jan 13, 2026
c50f672
Fix bindgen
Fernthedev Jan 13, 2026
883ec39
Log
Fernthedev Jan 14, 2026
35eac47
Fix working directory and restore
Fernthedev Jan 14, 2026
6dd2683
Add quest_build_helper crate with build and linker utilities
Fernthedev Jan 14, 2026
7660448
Enhance documentation for QuestCpp trait methods with argument details
Fernthedev Jan 15, 2026
704fdec
Fix target os detection
Fernthedev Jan 15, 2026
0b4f03f
Make ByRef copyable
Fernthedev Jan 15, 2026
42fb4b3
Make inline_hook and flamingo optional dependencies
Fernthedev Jan 15, 2026
d4b29dc
Fix inline_hook and flamingo feature dependencies in Cargo.toml
Fernthedev Jan 15, 2026
26ef055
Implement value boxing/unboxing
Fernthedev Jan 15, 2026
0d1de3b
Use dlsym functions for value box/unbox
Fernthedev Jan 15, 2026
3e22724
Use &Path
Fernthedev Jan 15, 2026
4dec19e
Copy to out
Fernthedev Jan 15, 2026
58e3f50
Implement Type, Argument, Parameter, Returned, and Return traits for …
Fernthedev Jan 17, 2026
ca0c8d5
Fix CI
Fernthedev Jan 17, 2026
e3605d1
Fix matrix
Fernthedev Jan 17, 2026
b944950
Make libil2cpp load dynamically on Windows and Mac
Fernthedev Jan 17, 2026
1118b28
Fix DLL name
Fernthedev Jan 18, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/docs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,15 @@ jobs:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v4
- uses: actions-rs/toolchain@v1
with:
toolchain: nightly
profile: minimal
override: true
components: rust-docs

- uses: actions/cache@v2
- uses: actions/cache@v4
with:
path: |
~/.cargo/
Expand Down
12 changes: 6 additions & 6 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,19 +7,19 @@ jobs:
runs-on: ${{ matrix.os }}
strategy:
matrix:
unity: [unity2019, unity2018]
unity: [il2cpp_v31, il2cpp_v29, il2cpp_v24, unity2018]
os: [windows-latest, ubuntu-latest]

steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v4
- uses: actions-rs/toolchain@v1
with:
toolchain: nightly
profile: minimal
override: true
components: clippy, rustfmt

- uses: actions/cache@v2
- uses: actions/cache@v4
with:
path: |
~/.cargo/
Expand Down Expand Up @@ -60,7 +60,7 @@ jobs:
ndk-target: armeabi-v7a

steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v4
with:
submodules: true
- uses: actions-rs/toolchain@v1
Expand All @@ -73,9 +73,9 @@ jobs:
- uses: nttld/setup-ndk@v1
id: setup-ndk
with:
ndk-version: r22
ndk-version: r29

- uses: actions/cache@v2
- uses: actions/cache@v4
with:
path: |
~/.cargo/
Expand Down
2 changes: 1 addition & 1 deletion .gitmodules
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
[submodule "inline_hook/beatsaber-hook"]
path = inline_hook/beatsaber-hook
url = https://github.com/sc2ad/beatsaber-hook
url = https://github.com/QuestPackageManager/beatsaber-hook.git
7 changes: 5 additions & 2 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
{
"rust-analyzer.cargo.features": [
"unity2019",
"serde"
"il2cpp_v31",
"serde",
"util",
"cache",
"trace"
],
"rust-analyzer.imports.granularity.group": "module"
}
20 changes: 13 additions & 7 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[workspace]
members = ["proc_macros", "inline_hook", "libil2cpp"]
members = ["proc_macros", "inline_hook", "libil2cpp", "flamingo", "quest_build_helper"]

[package]
name = "quest_hook"
Expand All @@ -14,16 +14,17 @@ edition = "2021"

[dependencies]
quest_hook_proc_macros = { path = "./proc_macros" }
inline_hook = { path = "./inline_hook" }
inline_hook = { path = "./inline_hook", optional = true}
flamingo = { path = "./flamingo", optional = true}
libil2cpp = { path = "./libil2cpp", default-features = false }
cfg-if = "1"
tracing = { version = "0.1", features = [
"std",
], default-features = false, optional = true }
tracing-subscriber = { version = "0.3", default-features = false, optional = true }
tracing-error = { version = "0.1", default-features = false, optional = true }
paranoid-android = { version = "0.1.2", optional = true }
thiserror = "1"
tracing-error = { version = "0.2", default-features = false, optional = true }
paranoid-android = { version = "0.2", optional = true }
thiserror = "2"

[target.'cfg(not(target_os = "android"))'.dependencies]
tracing-subscriber = { version = "0.3", features = [
Expand All @@ -33,13 +34,18 @@ tracing-subscriber = { version = "0.3", features = [
], default-features = false, optional = true }

[features]
default = ["util", "cache"]
unity2019 = ["libil2cpp/unity2019"]
default = ["util", "cache", "il2cpp_v31", "bindgen", "inline_hook"]
il2cpp_v31 = ["libil2cpp/il2cpp_v31"]
il2cpp_v29 = ["libil2cpp/il2cpp_v29"]
il2cpp_v24 = ["libil2cpp/il2cpp_v24"]
unity2018 = ["libil2cpp/unity2018"]
util = ["tracing", "tracing-error", "tracing-subscriber", "paranoid-android"]
cache = ["libil2cpp/cache"]
serde = ["libil2cpp/serde"]
trace = ["libil2cpp/trace"]
bindgen = ["libil2cpp/bindgen"]
inline_hook = ["dep:inline_hook"]
flamingo = ["dep:flamingo"]

[[example]]
name = "hello_world"
Expand Down
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# quest_hook
# `quest_hook`

A library for writing (mostly) memory safe mods for Unity il2cpp games

Expand All @@ -15,8 +15,8 @@ Despite its name and initial target and scope, this library supports modding mos

### Targets

- Android ARMv8
- Android ARMv7
- Android `ARMv8`
- Android `ARMv7`
- Windows x64
- Windows x86
- Linux x64
Expand Down Expand Up @@ -90,7 +90,7 @@ This library is mainly developed using Visual Studio Code with [rust-analyzer](h

## License

quest_hook is licensed under the [MIT License](./LICENSE).
`quest_hook` is licensed under the [MIT License](./LICENSE).

## Credits

Expand Down
2 changes: 0 additions & 2 deletions examples/custom_type.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
#![feature(generic_associated_types, once_cell)]

use libil2cpp::{Il2CppArray, Type};
use quest_hook::hook;
use quest_hook::libil2cpp::{unsafe_impl_reference_type, unsafe_impl_value_type, Il2CppObject};
Expand Down
1 change: 1 addition & 0 deletions flamingo/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
extern/
14 changes: 14 additions & 0 deletions flamingo/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
[package]
name = "flamingo"
version = "0.1.0"
edition = "2024"

[dependencies]
cfg-if = "1"

[target.'cfg(not(target_os = "android"))'.dependencies]
retour = "0.4.0-alpha.3"

[build-dependencies]
cc = "1"
bindgen = "0.72"
51 changes: 51 additions & 0 deletions flamingo/build.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
use std::{env, path::PathBuf};

fn main() {
let workspace = env::var("CARGO_MANIFEST_DIR").unwrap();

// Tell cargo to look for shared libraries in the specified directory
println!("cargo:rustc-link-search={workspace}/extern/libs");

// Tell cargo to tell rustc to link the system bzip2
// shared library.
println!("cargo:rustc-link-lib=flamingo");

println!("cargo:rerun-if-changed=wrapper.h");
println!("cargo:rerun-if-changed=extern/includes");

// run qpm restore to ensure flamingo is available
use std::process::Command;
Command::new("qpm")
.args(["restore"])
.status()
.expect("Failed to run qpm restore");

// The bindgen::Builder is the main entry point
// to bindgen, and lets you build up options for
// the resulting bindings.
let bindings = bindgen::Builder::default()
// The input header we would like to generate
// bindings for.
.header("wrapper.h")
.clang_arg("-I./extern/includes")
// Tell cargo to invalidate the built crate whenever any of the
// included header files changed.
.parse_callbacks(Box::new(bindgen::CargoCallbacks::new()))
// Finish the builder and generate the bindings.
.generate()
// Unwrap the Result and panic on failure.
.expect("Unable to generate bindings");

// Write the bindings to the $OUT_DIR/bindings.rs file.
let out_path = PathBuf::from(env::var("OUT_DIR").unwrap());
bindings
.write_to_file(out_path.join("bindings.rs"))
.expect("Couldn't write bindings!");

// let target = std::env::var("TARGET").unwrap();
// if target == "aarch64-linux-android" {
// cc::Build::new()
// .file("beatsaber-hook/shared/inline-hook/And64InlineHook.cpp")
// .compile("inline_hook");
// }
}
28 changes: 28 additions & 0 deletions flamingo/qpm.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
{
"$schema": "https://raw.githubusercontent.com/QuestPackageManager/QPM.Package/refs/heads/main/qpm.schema.json",
"version": "0.4.0",
"sharedDir": "shared",
"dependenciesDir": "extern",
"info": {
"name": "flamingo-rs",
"id": "flamingo-rs",
"version": "0.1.0",
"url": null,
"additionalData": {
"cmake": false
}
},
"workspace": {
"scripts": {},
"qmodIncludeDirs": [],
"qmodIncludeFiles": [],
"qmodOutput": null
},
"dependencies": [
{
"id": "flamingo",
"versionRange": "^1.2.0",
"additionalData": {}
}
]
}
42 changes: 42 additions & 0 deletions flamingo/qpm.shared.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
{
"$schema": "https://raw.githubusercontent.com/QuestPackageManager/QPM.Package/refs/heads/main/qpm.shared.schema.json",
"config": {
"version": "0.4.0",
"sharedDir": "shared",
"dependenciesDir": "extern",
"info": {
"name": "flamingo-rs",
"id": "flamingo-rs",
"version": "0.1.0",
"url": null,
"additionalData": {
"cmake": false
}
},
"workspace": {
"scripts": {},
"qmodIncludeDirs": [],
"qmodIncludeFiles": [],
"qmodOutput": null
},
"dependencies": [
{
"id": "flamingo",
"versionRange": "^1.2.0",
"additionalData": {}
}
]
},
"restoredDependencies": [
{
"dependency": {
"id": "flamingo",
"versionRange": "=1.2.0",
"additionalData": {
"overrideSoName": "libflamingo.so"
}
},
"version": "1.2.0"
}
]
}
57 changes: 57 additions & 0 deletions flamingo/src/aarch64_linux_android.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
use std::ffi::{CString, c_void};
use std::ptr::null_mut;
use std::sync::atomic::{AtomicPtr, Ordering};

use crate::flamingo_c_api::{self, flamingo_make_name};

/// A function hook specific to `ARMv8` Android
#[derive(Debug)]
pub struct Hook {
original: AtomicPtr<c_void>,
}

impl Hook {
/// Creates a new, unitialized hook
pub const fn new() -> Self {
Self {
original: AtomicPtr::new(null_mut()),
}
}

/// Installes the hook by redirecting `target` to `hook`, returning true on
/// success
///
/// # Safety
/// `target` and `hook` must have the same signature and calling convention
pub unsafe fn install(&self, target: *const (), hook: *const ()) -> bool {
let mut original: *mut c_void = null_mut();

let name_metadata =
unsafe { flamingo_make_name(CString::new("unknown").unwrap().as_ptr()) };

unsafe {
flamingo_c_api::flamingo_install_hook_no_name(
hook as *mut c_void,
target as *mut u32,
&mut original,
)
};

self.original.store(original, Ordering::SeqCst);
true
}

/// Whether the hook is installed
pub fn is_installed(&self) -> bool {
!self.original.load(Ordering::SeqCst).is_null()
}

/// Returns the address of a trampoline function to the original target, if
/// installed
pub fn original(&self) -> Option<*const ()> {
match self.original.load(Ordering::SeqCst) {
null if null.is_null() => None,
original => Some(original as *const ()),
}
}
}
Loading