Skip to content

Commit

Permalink
Prevent NROs from the original game from being double-registered. (#543)
Browse files Browse the repository at this point in the history
* Prevent NROs from the original game from being double-registered

* remove binrw as a dependency
  • Loading branch information
itsmeft24 authored Sep 21, 2023
1 parent a2f1647 commit 39d02a2
Showing 1 changed file with 44 additions and 2 deletions.
46 changes: 44 additions & 2 deletions src/chainloader.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use std::{cmp::Ordering, fmt, io, mem::MaybeUninit, ops::Deref, path::Path};
use std::{cmp::Ordering, fmt, io::{self, Seek, Read}, mem::MaybeUninit, ops::Deref, path::Path};

use nn::ro::{self, Module, NrrHeader, RegistrationInfo};
use once_cell::sync::Lazy;
use skyline::{libc, nn};

macro_rules! align_up {
Expand Down Expand Up @@ -64,6 +65,43 @@ pub struct NrrBuilder {
hashes: Vec<Sha256Hash>,
}

static ORIGINAL_GAME_NRO_HASHES: Lazy<Vec<Sha256Hash>> = Lazy::new(|| {
let mut out = Vec::new();
let read_dir = std::fs::read_dir("rom:/.nrr/").unwrap();
for entry in read_dir {
if let Ok(dir_entry) = entry {
let path = dir_entry.path();
if path.is_file() {
let mut file = std::fs::File::open(path).unwrap();
file.seek(io::SeekFrom::Start(0x340)).unwrap();

// Manually read in the hashes_offset and num_hashes members of NRR file header.
let mut hashes_offset_bytes = [0u8; 4];
file.read_exact(&mut hashes_offset_bytes).unwrap();
let hashes_offset = u32::from_le_bytes(hashes_offset_bytes);

let mut num_hashes_bytes = [0u8; 4];
file.read_exact(&mut num_hashes_bytes).unwrap();
let num_hashes = u32::from_le_bytes(num_hashes_bytes);

// Seek to hashes_offset and read the module hashes into nrr_hashes.
file.seek(io::SeekFrom::Start(hashes_offset as u64)).unwrap();
let mut nrr_hashes = Vec::with_capacity(num_hashes as usize);
for i in 0..num_hashes {
let mut hash_bytes = [0u8; 0x20];
file.read_exact(&mut hash_bytes).unwrap();
nrr_hashes.push(Sha256Hash { hash: hash_bytes });
}

// Append the module hashes from this NRR into the global vector.
out.extend(nrr_hashes);
}
}
}
out
}
);

const NRR_SIZE: usize = std::mem::size_of::<NrrHeader>();

impl NrrBuilder {
Expand All @@ -72,7 +110,11 @@ impl NrrBuilder {
}

pub fn add_module(&mut self, data: &[u8]) {
self.hashes.push(Sha256Hash::new(data));
let hash = Sha256Hash::new(data);
let original_hashes = Lazy::force(&ORIGINAL_GAME_NRO_HASHES);
if !original_hashes.contains(&hash) {
self.hashes.push(hash);
}
}

pub fn register(self) -> Result<Option<RegistrationInfo>, NrrRegistrationFailedError> {
Expand Down

0 comments on commit 39d02a2

Please sign in to comment.