#![warn(clippy::nursery, clippy::pedantic)]
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::usage_checks::is_arm9_expanded;
pub fn determine_game_overlay(patch_path: &str) -> &'static str {
if patch_path.contains("_HG") {
GAME_DEPENDENT_OVERLAY_HG
} else if patch_path.contains("_PLAT") {
GAME_DEPENDENT_OVERLAY_PLAT
} else {
panic!("Unknown game type in patch path: {patch_path}");
}
}
pub fn find_injection_offset(data: &[u8], required_size: usize) -> Option<usize> {
let mut i = 0;
while i + required_size <= data.len() {
if i % 0x10 == 0 {
let window = &data[i..i + required_size];
if window.iter().all(|&b| b == 0) {
return Some(i);
}
}
i += 1;
}
None
}
pub fn insert_corrected_offset(asm_path: &str, new_addr: u32) -> io::Result<PathBuf> {
let input = BufReader::new(fs::File::open(asm_path)?);
let mut lines: Vec<String> = Vec::new();
for line in input.lines() {
let mut line = line?;
if line.contains("INJECT_ADDR equ") {
line = format!("INJECT_ADDR equ 0x{new_addr:08X}");
}
lines.push(line);
}
let out_path = PathBuf::from(asm_path);
fs::write(&out_path, lines.join("\n"))?;
Ok(out_path)
}
pub fn handle_synthoverlay(patch_path: &str, project_path: &str, game_version: &str, required_size: usize) -> io::Result<()> {
if is_arm9_expanded(project_path, game_version)? {
info!("arm9 is expanded, proceeding");
} else {
return Err(io::Error::other(
"arm9 is not expanded, please expand it before applying the patch.",
));
}
let synth_overlay_path = format!(
"{}\\unpacked\\synthOverlay\\{}",
project_path,
determine_game_overlay(patch_path)
);
let synth_overlay = fs::read(&synth_overlay_path)?;
info!(
"Read synthOverlay file successfully. Located at: {synth_overlay_path}"
);
info!("Searching for injection offset");
let offset =
find_injection_offset(&synth_overlay, required_size).expect("Failed to find injection offset");
info!(
"Found injection offset at {:#X} in synthOverlay {}",
offset,
determine_game_overlay(patch_path)
);
let corrected_offset = 0x23c8000 + offset as u32;
info!("Corrected offset: {corrected_offset:#X}");
insert_corrected_offset(patch_path, corrected_offset)
.expect("Failed to correct offset in asm file");
Ok(())
}