Skip to content

Commit

Permalink
NRO Hook Plugin Initial Commit
Browse files Browse the repository at this point in the history
  • Loading branch information
jam1garner committed May 1, 2020
1 parent 87a09eb commit fa182df
Show file tree
Hide file tree
Showing 3 changed files with 46 additions and 154 deletions.
6 changes: 4 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[package]
name = "skyline_rs_template"
name = "nro_hook"
version = "0.1.0"
authors = ["jam1garner <[email protected]>"]
edition = "2018"
Expand All @@ -11,8 +11,10 @@ titleid = "01006A800016E000"
crate-type = ["cdylib"]

[dependencies]
skyline = { git = "https://github.com/ultimate-research/skyline-rs.git" }
#skyline = { git = "https://github.com/ultimate-research/skyline-rs.git" }
skyline = { path = "../../skyline-rs", features = ["nro_internal"] }
skyline_smash = { git = "https://github.com/ultimate-research/skyline-smash.git" }
parking_lot = { version = "0.10", features = ["nightly"] }

[profile.dev]
panic = "abort"
Expand Down
109 changes: 9 additions & 100 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,110 +1,19 @@
# skyline-rs-template
# NRO hook plugin

A template for writing skyline plugins for modding switch games using Rust and skyline-rs.
A plugin allowing for centralized hooking of NROs, allowing multiple plugins to all hook NRO load.

[Documentation for skyline-rs](https://ultimate-research.github.io/skyline-rs-template/doc/skyline/index.html)
## Install

## Prerequisites
**Note:** Requires [cargo-skyline](https://github.com/jam1garner/cargo-skyline) to be installed

* [Rust](https://www.rust-lang.org/install.html) - make sure rustup, cargo, and rustc (preferrably nightly) are installed.
* [git](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git)
To install, simply run:

## Setup

NOTE: for easier/newer setup, use [cargo skyline](https://github.com/jam1garner/cargo-skyline)

1. Install linkle and my fork of Xargo:
```sh
# Install linkle
cargo install --features=binaries --git https://github.com/MegatonHammer/linkle

# Install Xargo
cargo install --force --git https://github.com/jam1garner/xargo.git
```
2. Make a folder for you to store all of your plugins
```
mkdir plugins
cd plugins
```
3. Within your plugins folder, clone [rust-std-skyline-squashed](https://github.com/jam1garner/rust-std-skyline-squashed)
```sh
# Make sure you are inside of your plugins folder
git clone https://github.com/jam1garner/rust-std-skyline-squashed
```
Note: you only have to clone the `std` once to be shared between every plugin in the folder.

## Creating and building a plugin

1. From within the same folder as where you cloned `rust-std-skyline-squashed` clone this repo and rename it to match the
name of your plugin. To clone and rename all at once, use:
```
git clone https://github.com/jam1garner/skyline-rs-template [name of plugin]
```
2. Make sure you're inside the folder for your plugin:
```sh
cd [name of plugin]
cargo skyline install
```
3. There's a few places you'll need to rename your plugin. First in `Cargo.toml` near the top, change
```
name = "skyline-rs-template"
```
To a name suitable for your plugin. Next, go into `src/lib.rs` and edit the following line:
```rust
#[skyline::main(name = "module_name_test")]
```
to reflect what you want your module to be named on your console.

4. Lastly, to compile your plugin use the following command in the root of the project (beside the `Cargo.toml` file):
```sh
cargo nro
```
Your resulting plugin will be the `.nro` found in the folder
```
[plugin name]/target/aarch64-skyline-switch
Or, if your IP isn't configured yet, use
```
To install (you must already have skyline installed on your switch), put the plugin on your SD at:
```
sd:/atmosphere/contents/[title id]/romfs/skyline/plugins
```
So, for example, smash plugins go in the following folder:
```
sd:/atmosphere/contents/01006A800016E000/romfs/skyline/plugins
```

## Troubleshooting

**"Cannot be used on stable"**

First, make sure you have a nightly installed:
```
rustup install nightly
```
Second, make sure it is your default channel:
```
rustup default nightly
```
---
```
thread 'main' panicked at 'called `Option::unwrap()` on a `None` value', src/bin/cargo-nro.rs:280:13
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
```

Make sure you are *inside* the root of the plugin you created before running `cargo nro`

Have a problem/solution that is missing here? Create an issue or a PR!

## Updating

For updating your dependencies such as skyline-rs:

```
cargo update
```

For updating your version of `rust-std-skyline-squashed`:

```
# From inside your plugins folder
rm -rf && git clone https://github.com/jam1garner/rust-std-skyline-squashed
cargo skyline install --ip X.X.X.X
```
Where `X.X.X.X` is your switch's IP address
85 changes: 33 additions & 52 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,67 +1,48 @@
#![feature(proc_macro_hygiene)]

use skyline::{hook, install_hook};
use std::thread;
use std::time::Duration;
use skyline::nn::ro;
use skyline::libc::{c_void, c_int, size_t};
use skyline::from_c_str;

extern "C" fn test() -> u32 {
2
}

//#[hook(offset = 0x12345)]
#[hook(replace = test)]
fn test_replacement() -> u32 {

let original_test = original!();

let val = original_test();

println!("[override] original value: {}", val); // 2

val + 1
}
use parking_lot::Mutex;

#[skyline::main(name = "skyline_rs_template")]
pub fn main() {
println!("Hello from Skyline Rust Plugin!");

install_hook!(test_replacement);
use skyline::nro::NroInfo;

let x = test();
type Callback = fn(&NroInfo);

// Make a vector to hold the children which are spawned.
let mut children = vec![];
static HOOKS: Mutex<Vec<Callback>> = Mutex::new(Vec::new());

let sleep_times = [0, 100, 500, 200, 5000, 100, 150, 0, 0, 300];
#[hook(replace = ro::LoadModule)]
pub fn handle_load_module(
out_module: *mut ro::Module,
image: *const c_void,
buffer: *mut c_void,
buffer_size: size_t,
flag: c_int
) -> c_int {
let ret = original!()(out_module, image, buffer, buffer_size, flag);

for i in 0..10 {
let sleep_time = sleep_times[i];
// Spin up another thread
children.push(thread::spawn(move || {
thread::sleep(Duration::from_millis(sleep_time));
println!("this is thread number {}", i);
}));
let name = unsafe { from_c_str(&(*out_module).Name as *const u8) };
println!("Test test test {}", name);
let nro_info = NroInfo::new(&name, unsafe { &mut *out_module });
for hook in HOOKS.lock().iter() {
hook(&nro_info)
}

for child in children {
// Wait for the thread to finish. Returns a result.
let _ = child.join();
}
ret
}

println!("[main] test returned: {}", x); // 3
#[skyline::main(name = "nro_hook")]
pub fn main() {
println!("[NRO hook] Installing NRO hook...");
install_hook!(handle_load_module);
println!("[NRO hook] NRO hook installed.");
}

println!("{}", std::fs::read_to_string("sd:/test.txt").unwrap());
for x in std::fs::read_dir("sd:/atmosphere").unwrap() {
println!("{:?}", x.unwrap());
}
#[no_mangle]
pub extern "Rust" fn add_nro_load_hook(callback: Callback) {
let mut hooks = HOOKS.lock();

// keep-alive thread
thread::spawn(||{
loop {
println!("Still alive?");
thread::sleep(Duration::from_secs(3));
println!("Still alive!");
thread::sleep(Duration::from_secs(1));
}
});
hooks.push(callback);
}

0 comments on commit fa182df

Please sign in to comment.