mirror of
https://github.com/NinjaCheetah/rustii.git
synced 2026-03-03 03:15:28 -05:00
Add setting.txt gen command
This commit is contained in:
@@ -188,6 +188,9 @@ fn main() -> Result<()> {
|
||||
},
|
||||
nand::setting::Commands::Encrypt { input, output } => {
|
||||
nand::setting::encrypt_setting(input, output)?;
|
||||
},
|
||||
nand::setting::Commands::Gen { serno, region } => {
|
||||
nand::setting::generate_setting(serno, region)?;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@@ -7,7 +7,9 @@ use std::{str, fs};
|
||||
use std::path::{Path, PathBuf};
|
||||
use anyhow::{bail, Context, Result};
|
||||
use clap::Subcommand;
|
||||
use regex::RegexBuilder;
|
||||
use rustwii::nand::setting;
|
||||
use rustwii::nand::setting::SettingTxt;
|
||||
|
||||
#[derive(Subcommand)]
|
||||
#[command(arg_required_else_help = true)]
|
||||
@@ -27,6 +29,13 @@ pub enum Commands {
|
||||
/// An optional output path; defaults to setting_enc.txt
|
||||
#[arg(short, long)]
|
||||
output: Option<String>,
|
||||
},
|
||||
/// Generate a new setting.txt from the provided values
|
||||
Gen {
|
||||
/// The serial number of the console this file is for
|
||||
serno: String,
|
||||
/// Region of the console this file is for (USA, EUR, JPN, or KOR)
|
||||
region: String
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,6 +51,9 @@ pub fn decrypt_setting(input: &str, output: &Option<String>) -> Result<()> {
|
||||
};
|
||||
let setting = setting::SettingTxt::from_bytes(&fs::read(in_path)?).with_context(|| "The provided setting.txt could not be parsed, and is likely invalid.")?;
|
||||
fs::write(out_path, setting.to_string()?)?;
|
||||
|
||||
println!("Successfully decrypted setting.txt!");
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -57,5 +69,72 @@ pub fn encrypt_setting(input: &str, output: &Option<String>) -> Result<()> {
|
||||
};
|
||||
let setting = setting::SettingTxt::from_string(String::from_utf8(fs::read(in_path)?).with_context(|| "Invalid characters found in input file!")?)?;
|
||||
fs::write(out_path, setting.to_bytes()?)?;
|
||||
|
||||
println!("Successfully encrypted setting.txt!");
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn generate_setting(serno: &str, region: &str) -> Result<()> {
|
||||
// Validate the provided SN. It should be 2 or 3 letters followed by 9 numbers.
|
||||
if serno.len() != 11 && serno.len() != 12 {
|
||||
bail!("The provided Serial Number is not valid!")
|
||||
}
|
||||
|
||||
let re = RegexBuilder::new(r"[0-9]+").case_insensitive(true).build()?;
|
||||
if !re.is_match(&serno[serno.len() - 9..]) {
|
||||
bail!("The provided Serial Number is not valid!")
|
||||
}
|
||||
|
||||
let prefix = &serno[..serno.len() - 9];
|
||||
|
||||
// Detect the console revision based on the SN.
|
||||
let revision = match prefix.chars().next().unwrap() {
|
||||
'L' => "RVL-001",
|
||||
'K' => "RVL-101",
|
||||
'H' => "RVL-201",
|
||||
_ => "RVL-001"
|
||||
};
|
||||
|
||||
// Validate the region, and then validate the SN based on the region. USA has a two-letter
|
||||
// prefix for a total length of 11 characters, while other regions have a three-letter prefix
|
||||
// for a total length of 12 characters.
|
||||
let valid_regions = ["USA", "EUR", "JPN", "KOR"];
|
||||
if !valid_regions.contains(®ion) {
|
||||
bail!("The provided region \"{region}\" is not valid!")
|
||||
}
|
||||
if (prefix.len() == 2 && region != "USA") || (prefix.len() == 3 && region == "USA") {
|
||||
bail!("The provided region \"{region}\" does not match the provided Serial Number {serno}!")
|
||||
}
|
||||
|
||||
// Find the values of VIDEO and GAME.
|
||||
let (video, game) = match region {
|
||||
"USA" => ("NTSC", "US"),
|
||||
"EUR" => ("PAL", "EU"),
|
||||
"JPN" => ("NTSC", "JP"),
|
||||
"KOR" => ("NTSC", "KR"),
|
||||
_ => bail!("The provided region \"{region}\" is not valid!")
|
||||
};
|
||||
|
||||
let model = format!("{revision}({region})");
|
||||
let serial_number = &serno[serno.len() - 9..];
|
||||
|
||||
let setting_str = format!("\
|
||||
AREA={}\r\n\
|
||||
MODEL={}\r\n\
|
||||
DVD=0\r\n\
|
||||
MPCH=0x7FFE\r\n\
|
||||
CODE={}\r\n\
|
||||
SERNO={}\r\n\
|
||||
VIDEO={}\r\n\
|
||||
GAME={}\r\n", region, model, prefix, serial_number, video, game
|
||||
);
|
||||
let setting_txt = SettingTxt::from_string(setting_str)?;
|
||||
fs::write("setting.txt", setting_txt.to_bytes()?)
|
||||
.with_context(|| "Failed to write setting.txt!")?;
|
||||
|
||||
println!("Successfully created setting.txt for console with serial number {serno} and \
|
||||
region {region}!");
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user