1
0
Fork 0
mirror of https://github.com/jugeeya/UltimateTrainingModpack.git synced 2024-11-28 04:44:06 +00:00

Move files to sd:/ultimate/TrainingModpack (#480)

* Initial

* Move filepaths

* Small fix

* Notification on save state save
This commit is contained in:
jugeeya 2023-02-13 19:58:22 -08:00 committed by GitHub
parent 8ac2a3e8b1
commit e981a0bfd0
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 1272 additions and 1220 deletions

View file

@ -357,7 +357,7 @@ To install a beta version of the modpack, follow the same procedure using the [l
`SD:/atmosphere/contents/01006A800016E000/romfs/skyline/plugins/libnro_hook.nro` `SD:/atmosphere/contents/01006A800016E000/romfs/skyline/plugins/libnro_hook.nro`
`SD:/atmosphere/contents/01006A800016E000/romfs/skyline/plugins/libparam_hook.nro` `SD:/atmosphere/contents/01006A800016E000/romfs/skyline/plugins/libparam_hook.nro`
`SD:/atmosphere/contents/01006A800016E000/romfs/skyline/plugins/libtraining_modpack.nro` `SD:/atmosphere/contents/01006A800016E000/romfs/skyline/plugins/libtraining_modpack.nro`
`SD:/TrainingModpack/` `SD:/ultimate/TrainingModpack/`
17. **Can I donate to the Training Modpack?** 17. **Can I donate to the Training Modpack?**
You can find the donation link in the [#faq](https://discord.com/channels/407970595418931200/714960353058095216) Discord channel. We use the money to commission video edits for releases, so thank you if you do end up donating! You can find the donation link in the [#faq](https://discord.com/channels/407970595418931200/714960353058095216) Discord channel. We use the money to commission video edits for releases, so thank you if you do end up donating!
@ -386,7 +386,7 @@ To install a beta version of the modpack, follow the same procedure using the [l
25. **How do I reset my Training Modpack settings?** 25. **How do I reset my Training Modpack settings?**
If you want to completely reset your menu selections back to the factory default, all you have to do is delete this file: If you want to completely reset your menu selections back to the factory default, all you have to do is delete this file:
`SD:/TrainingModpack/training_modpack_menu.conf` `SD:/ultimate/TrainingModpack/training_modpack_menu.conf`
26. **What input delay should I pick for practicing online?** 26. **What input delay should I pick for practicing online?**
Good LAN connections can be simulated with an input delay of 3-5 frames. Poorer Wifi connections can be up to 6-8 frames. Good LAN connections can be simulated with an input delay of 3-5 frames. Poorer Wifi connections can be up to 6-8 frames.

View file

@ -1,6 +1,8 @@
use std::collections::HashMap; use std::collections::HashMap;
use std::fs; use std::fs;
use crate::consts::TRAINING_MODPACK_TOML_PATH;
use lazy_static::lazy_static; use lazy_static::lazy_static;
use log::info; use log::info;
use serde::Deserialize; use serde::Deserialize;
@ -78,13 +80,13 @@ pub struct TopLevelBtnComboConfig {
} }
pub fn load_from_file() { pub fn load_from_file() {
let combo_path = "sd:/TrainingModpack/training_modpack.toml"; let combo_path = TRAINING_MODPACK_TOML_PATH;
info!("Checking for previous button combo settings in training_modpack.toml..."); info!("Checking for previous button combo settings in {TRAINING_MODPACK_TOML_PATH}...");
let mut valid_button_config = false; let mut valid_button_config = false;
if fs::metadata(combo_path).is_ok() { if fs::metadata(combo_path).is_ok() {
info!("Previous button combo settings found. Loading..."); info!("Previous button combo settings found. Loading...");
let combo_conf = let combo_conf = fs::read_to_string(combo_path)
fs::read_to_string(combo_path).unwrap_or_else(|_| panic!("Could not read {}", combo_path)); .unwrap_or_else(|_| panic!("Could not read {}", combo_path));
let conf: Result<TopLevelBtnComboConfig, toml::de::Error> = toml::from_str(&combo_conf); let conf: Result<TopLevelBtnComboConfig, toml::de::Error> = toml::from_str(&combo_conf);
if let Ok(conf) = conf { if let Ok(conf) = conf {
if validate_config(conf) { if validate_config(conf) {
@ -96,13 +98,11 @@ pub fn load_from_file() {
if !valid_button_config { if !valid_button_config {
info!("No previous button combo file found. Creating..."); info!("No previous button combo file found. Creating...");
fs::write(combo_path, DEFAULT_BTN_CONFIG) fs::write(combo_path, DEFAULT_BTN_CONFIG).expect("Failed to write button config conf file");
.expect("Failed to write button config conf file");
save_all_btn_config_from_defaults(); save_all_btn_config_from_defaults();
} }
} }
fn save_all_btn_config_from_defaults() { fn save_all_btn_config_from_defaults() {
let conf = TopLevelBtnComboConfig { let conf = TopLevelBtnComboConfig {
button_config: BtnComboConfig { button_config: BtnComboConfig {
@ -146,8 +146,13 @@ fn save_all_btn_config_from_toml(data: &str) {
fn validate_config(conf: TopLevelBtnComboConfig) -> bool { fn validate_config(conf: TopLevelBtnComboConfig) -> bool {
let conf = conf.button_config; let conf = conf.button_config;
let configs = [conf.open_menu, conf.save_state, conf.load_state, let configs = [
conf.previous_save_state_slot, conf.next_save_state_slot]; conf.open_menu,
conf.save_state,
conf.load_state,
conf.previous_save_state_slot,
conf.next_save_state_slot,
];
let bad_keys = configs let bad_keys = configs
.iter() .iter()
.flat_map(|btn_list| { .flat_map(|btn_list| {
@ -164,8 +169,9 @@ fn validate_config(conf: TopLevelBtnComboConfig) -> bool {
0x71, 0x71,
"Training Modpack custom button\nconfiguration is invalid!\0", "Training Modpack custom button\nconfiguration is invalid!\0",
&format!( &format!(
"The following keys are invalid in\nsd:/TrainingModpack/training_modpack.toml:\n\ "The following keys are invalid in\n{}:\n\
{:?}\n\nPossible Keys: {:#?}\0", {:?}\n\nPossible Keys: {:#?}\0",
TRAINING_MODPACK_TOML_PATH,
&bad_keys, &bad_keys,
BUTTON_MAPPING.keys() BUTTON_MAPPING.keys()
), ),
@ -207,13 +213,14 @@ fn combo_passes(
) -> bool { ) -> bool {
unsafe { unsafe {
let (hold, press) = get_combo_keys(combo); let (hold, press) = get_combo_keys(combo);
let this_combo_passes = hold.iter() let this_combo_passes = hold
.iter()
.map(|hold| *BUTTON_MAPPING.get(&*hold.to_uppercase()).unwrap()) .map(|hold| *BUTTON_MAPPING.get(&*hold.to_uppercase()).unwrap())
.all(|hold| ControlModule::check_button_on(module_accessor, hold)) .all(|hold| ControlModule::check_button_on(module_accessor, hold))
&& press && press
.iter() .iter()
.map(|press| *BUTTON_MAPPING.get(&*press.to_uppercase()).unwrap()) .map(|press| *BUTTON_MAPPING.get(&*press.to_uppercase()).unwrap())
.all(|press| ControlModule::check_button_trigger(module_accessor, press)); .all(|press| ControlModule::check_button_trigger(module_accessor, press));
this_combo_passes this_combo_passes
} }

View file

@ -6,12 +6,13 @@ use serde::Deserialize;
use skyline::nn::hid::NpadGcState; use skyline::nn::hid::NpadGcState;
use toml; use toml;
use crate::consts::DEV_TOML_PATH;
use crate::logging::info; use crate::logging::info;
/// Hot-reloadable configs for quicker development /// Hot-reloadable configs for quicker development
/// ///
/// In game, press L+R+A at any point to reread these configs from /// In game, press L+R+A at any point to reread these configs from
/// the file in sd:/TrainingModpack/dev.toml /// the file in DEV_TOML_PATH on the SD card
/// ///
/// Example usage: /// Example usage:
/// ///
@ -42,7 +43,7 @@ lazy_static! {
impl DevConfig { impl DevConfig {
fn load_from_toml() -> DevConfig { fn load_from_toml() -> DevConfig {
let dev_path = "sd:/TrainingModpack/dev.toml"; let dev_path = DEV_TOML_PATH;
if fs::metadata(dev_path).is_ok() { if fs::metadata(dev_path).is_ok() {
info!("Loading dev.toml configs..."); info!("Loading dev.toml configs...");
let dev_config_str = fs::read_to_string(dev_path).unwrap_or_else(|_| panic!("Could not read {}", dev_path)); let dev_config_str = fs::read_to_string(dev_path).unwrap_or_else(|_| panic!("Could not read {}", dev_path));

View file

@ -8,6 +8,7 @@ use training_mod_consts::MenuJsonStruct;
use training_mod_tui::AppPage; use training_mod_tui::AppPage;
use crate::common::*; use crate::common::*;
use crate::consts::MENU_OPTIONS_PATH;
use crate::events::{Event, EVENT_QUEUE}; use crate::events::{Event, EVENT_QUEUE};
use crate::logging::*; use crate::logging::*;
@ -22,14 +23,11 @@ pub unsafe fn menu_condition(module_accessor: &mut app::BattleObjectModuleAccess
button_config::combo_passes_exclusive(module_accessor, button_config::ButtonCombo::OpenMenu) button_config::combo_passes_exclusive(module_accessor, button_config::ButtonCombo::OpenMenu)
} }
const MENU_CONF_PATH: &str = "sd:/TrainingModpack/training_modpack_menu.json";
pub fn load_from_file() { pub fn load_from_file() {
let menu_conf_path = "sd:/TrainingModpack/training_modpack_menu.json"; info!("Checking for previous menu in {MENU_OPTIONS_PATH}...");
info!("Checking for previous menu in training_modpack_menu.json..."); if fs::metadata(MENU_OPTIONS_PATH).is_ok() {
if fs::metadata(menu_conf_path).is_ok() { let menu_conf = fs::read_to_string(MENU_OPTIONS_PATH)
let menu_conf = fs::read_to_string(menu_conf_path) .unwrap_or_else(|_| panic!("Could not remove {}", MENU_OPTIONS_PATH));
.unwrap_or_else(|_| panic!("Could not remove {}", menu_conf_path));
if let Ok(menu_conf_json) = serde_json::from_str::<MenuJsonStruct>(&menu_conf) { if let Ok(menu_conf_json) = serde_json::from_str::<MenuJsonStruct>(&menu_conf) {
unsafe { unsafe {
MENU = menu_conf_json.menu; MENU = menu_conf_json.menu;
@ -38,10 +36,10 @@ pub fn load_from_file() {
} }
} else { } else {
warn!("Previous menu found but is invalid. Deleting..."); warn!("Previous menu found but is invalid. Deleting...");
fs::remove_file(menu_conf_path).unwrap_or_else(|_| { fs::remove_file(MENU_OPTIONS_PATH).unwrap_or_else(|_| {
panic!( panic!(
"{} has invalid schema but could not be deleted!", "{} has invalid schema but could not be deleted!",
menu_conf_path MENU_OPTIONS_PATH
) )
}); });
} }
@ -58,7 +56,7 @@ pub unsafe fn set_menu_from_json(message: &str) {
MENU = message_json.menu; MENU = message_json.menu;
DEFAULTS_MENU = message_json.defaults_menu; DEFAULTS_MENU = message_json.defaults_menu;
fs::write( fs::write(
MENU_CONF_PATH, MENU_OPTIONS_PATH,
serde_json::to_string_pretty(&message_json).unwrap(), serde_json::to_string_pretty(&message_json).unwrap(),
) )
.expect("Failed to write menu settings file"); .expect("Failed to write menu settings file");
@ -208,7 +206,7 @@ pub fn handle_get_npad_state(state: *mut NpadGcState, _controller_id: *const u32
BUTTON_PRESSES.r.is_pressed = true; BUTTON_PRESSES.r.is_pressed = true;
} }
// Special case for frame-by-frame // Special case for frame-by-frame
if FRAME_COUNTER < MENU_INPUT_WAIT_FRAMES && (*state).Buttons & (1 << 8) > 0 { if FRAME_COUNTER > MENU_INPUT_WAIT_FRAMES && (*state).Buttons & (1 << 8) > 0 {
BUTTON_PRESSES.zl.is_pressed = true; BUTTON_PRESSES.zl.is_pressed = true;
} }
if (*state).Buttons & (1 << 9) > 0 { if (*state).Buttons & (1 << 9) > 0 {
@ -223,7 +221,10 @@ pub fn handle_get_npad_state(state: *mut NpadGcState, _controller_id: *const u32
if (*state).Buttons & ((1 << 15) | (1 << 19)) > 0 { if (*state).Buttons & ((1 << 15) | (1 << 19)) > 0 {
BUTTON_PRESSES.down.is_pressed = true; BUTTON_PRESSES.down.is_pressed = true;
} }
if (*state).Buttons & ((1 << 13) | (1 << 17)) > 0 { // Special case for "UP" in menu open button combo
if FRAME_COUNTER > MENU_INPUT_WAIT_FRAMES
&& (*state).Buttons & ((1 << 13) | (1 << 17)) > 0
{
BUTTON_PRESSES.up.is_pressed = true; BUTTON_PRESSES.up.is_pressed = true;
} }

View file

@ -2,10 +2,12 @@ use std::fs;
use skyline_web::DialogOk; use skyline_web::DialogOk;
use crate::consts::{
LEGACY_MENU_OPTIONS_PATH, MENU_DEFAULT_OPTIONS_PATH, MENU_OPTIONS_PATH, VERSION_TXT_PATH,
};
use crate::logging::*; use crate::logging::*;
pub const CURRENT_VERSION: &str = env!("CARGO_PKG_VERSION"); pub const CURRENT_VERSION: &str = env!("CARGO_PKG_VERSION");
const VERSION_FILE_PATH: &str = "sd:/TrainingModpack/version.txt";
enum VersionCheck { enum VersionCheck {
Current, Current,
@ -33,7 +35,7 @@ fn record_current_version(fpath: &str) {
} }
pub fn version_check() { pub fn version_check() {
match is_current_version(VERSION_FILE_PATH) { match is_current_version(VERSION_TXT_PATH) {
VersionCheck::Current => { VersionCheck::Current => {
// Version is current, no need to take any action // Version is current, no need to take any action
} }
@ -47,13 +49,16 @@ pub fn version_check() {
) )
); );
// Remove old menu selections, silently ignoring errors (i.e. if the file doesn't exist) // Remove old menu selections, silently ignoring errors (i.e. if the file doesn't exist)
fs::remove_file("sd:/TrainingModpack/training_modpack_menu.conf") [
.unwrap_or_else(|_| error!("Couldn't remove training_modpack_menu.conf")); MENU_OPTIONS_PATH,
fs::remove_file("sd:/TrainingModpack/training_modpack_menu.json") MENU_DEFAULT_OPTIONS_PATH,
.unwrap_or_else(|_| error!("Couldn't remove training_modpack_menu.json")); LEGACY_MENU_OPTIONS_PATH,
fs::remove_file("sd:/TrainingModpack/training_modpack_menu_defaults.conf") ]
.unwrap_or_else(|_| error!("Couldn't remove training_modpack_menu_defaults.conf")); .iter()
record_current_version(VERSION_FILE_PATH); .for_each(|path| {
fs::remove_file(path).unwrap_or_else(|_| error!("Couldn't remove {path}"))
});
record_current_version(VERSION_TXT_PATH);
} }
VersionCheck::NoFile => { VersionCheck::NoFile => {
// Display dialog box on fresh installation // Display dialog box on fresh installation
@ -63,7 +68,7 @@ pub fn version_check() {
Please refer to the Github page and the Discord server for a full list of features and instructions on how to utilize the improved Training Mode." Please refer to the Github page and the Discord server for a full list of features and instructions on how to utilize the improved Training Mode."
) )
); );
record_current_version(VERSION_FILE_PATH); record_current_version(VERSION_TXT_PATH);
} }
} }
} }

View file

@ -4,23 +4,25 @@
#![feature(once_cell)] #![feature(once_cell)]
#![feature(c_variadic)] #![feature(c_variadic)]
#![allow( #![allow(
clippy::borrow_interior_mutable_const, clippy::borrow_interior_mutable_const,
clippy::declare_interior_mutable_const, clippy::declare_interior_mutable_const,
clippy::not_unsafe_ptr_arg_deref, clippy::not_unsafe_ptr_arg_deref,
clippy::missing_safety_doc, clippy::missing_safety_doc,
clippy::wrong_self_convention, clippy::wrong_self_convention,
clippy::option_map_unit_fn, clippy::option_map_unit_fn,
clippy::fn_null_check, clippy::fn_null_check,
clippy::transmute_num_to_bytes clippy::transmute_num_to_bytes
)] )]
use std::fs; use std::fs;
use std::path::PathBuf;
use skyline::libc::mkdir;
use skyline::nro::{self, NroInfo}; use skyline::nro::{self, NroInfo};
use training_mod_consts::LEGACY_TRAINING_MODPACK_ROOT;
use crate::common::*;
use crate::common::events::events_loop; use crate::common::events::events_loop;
use crate::common::*;
use crate::consts::TRAINING_MODPACK_ROOT;
use crate::events::{Event, EVENT_QUEUE}; use crate::events::{Event, EVENT_QUEUE};
use crate::logging::*; use crate::logging::*;
use crate::menu::quick_menu_loop; use crate::menu::quick_menu_loop;
@ -47,12 +49,6 @@ fn nro_main(nro: &NroInfo<'_>) {
} }
} }
macro_rules! c_str {
($l:tt) => {
[$l.as_bytes(), "\u{0}".as_bytes()].concat().as_ptr()
};
}
#[skyline::main(name = "training_modpack")] #[skyline::main(name = "training_modpack")]
pub fn main() { pub fn main() {
std::panic::set_hook(Box::new(|info| { std::panic::set_hook(Box::new(|info| {
@ -79,8 +75,16 @@ pub fn main() {
unsafe { unsafe {
EVENT_QUEUE.push(Event::smash_open()); EVENT_QUEUE.push(Event::smash_open());
notification("Training Modpack".to_string(), "Welcome!".to_string(), 60); notification("Training Modpack".to_string(), "Welcome!".to_string(), 60);
notification("Open Menu".to_string(), "Special + Uptaunt".to_string(), 120); notification(
notification("Save State".to_string(), "Grab + Downtaunt".to_string(), 120); "Open Menu".to_string(),
"Special + Uptaunt".to_string(),
120,
);
notification(
"Save State".to_string(),
"Grab + Downtaunt".to_string(),
120,
);
notification("Load State".to_string(), "Grab + Uptaunt".to_string(), 120); notification("Load State".to_string(), "Grab + Uptaunt".to_string(), 120);
} }
@ -89,14 +93,21 @@ pub fn main() {
training::training_mods(); training::training_mods();
nro::add_hook(nro_main).unwrap(); nro::add_hook(nro_main).unwrap();
unsafe { fs::create_dir_all(TRAINING_MODPACK_ROOT)
mkdir(c_str!("sd:/TrainingModpack/"), 777); .expect("Could not create Training Modpack root folder!");
}
let ovl_path = "sd:/switch/.overlays/ovlTrainingModpack.ovl"; // Migrate legacy if exists
if fs::metadata(ovl_path).is_ok() { if fs::metadata(LEGACY_TRAINING_MODPACK_ROOT).is_ok() {
warn!("Removing ovlTrainingModpack.ovl..."); for entry in fs::read_dir(LEGACY_TRAINING_MODPACK_ROOT).unwrap() {
fs::remove_file(ovl_path).unwrap_or_else(|_| panic!("Could not remove {}", ovl_path)) let entry = entry.unwrap();
let src_path = &entry.path();
let dest_path = &PathBuf::from(TRAINING_MODPACK_ROOT).join(entry.file_name());
fs::rename(src_path, dest_path).unwrap_or_else(|e| {
error!("Could not move file from {src_path:#?} to {dest_path:#?} with error {e}")
});
}
fs::remove_dir_all(LEGACY_TRAINING_MODPACK_ROOT)
.expect("Could not delete legacy Training Modpack folder!");
} }
info!("Performing version check..."); info!("Performing version check...");

View file

@ -17,6 +17,7 @@ use crate::common::consts::get_random_int;
use crate::common::consts::FighterId; use crate::common::consts::FighterId;
use crate::common::consts::OnOff; use crate::common::consts::OnOff;
use crate::common::consts::SaveStateMirroring; use crate::common::consts::SaveStateMirroring;
use crate::common::consts::SAVE_STATES_TOML_PATH;
use crate::common::is_dead; use crate::common::is_dead;
use crate::common::MENU; use crate::common::MENU;
use crate::is_operation_cpu; use crate::is_operation_cpu;
@ -114,14 +115,13 @@ pub fn load_from_file() -> SaveStateSlots {
cpu: [default_save_state!(); NUM_SAVE_STATE_SLOTS], cpu: [default_save_state!(); NUM_SAVE_STATE_SLOTS],
}; };
let save_states_path = "sd:/TrainingModpack/save_states.toml"; info!("Checking for previous save state settings in {SAVE_STATES_TOML_PATH}...");
info!("Checking for previous save state settings in save_states.toml..."); if std::fs::metadata(SAVE_STATES_TOML_PATH).is_err() {
if std::fs::metadata(save_states_path).is_err() {
return defaults; return defaults;
} }
info!("Previous save state settings found. Loading..."); info!("Previous save state settings found. Loading...");
if let Ok(data) = std::fs::read_to_string(save_states_path) { if let Ok(data) = std::fs::read_to_string(SAVE_STATES_TOML_PATH) {
let input_slots = toml::from_str::<SaveStateSlots>(&data); let input_slots = toml::from_str::<SaveStateSlots>(&data);
if let Ok(input_slots) = input_slots { if let Ok(input_slots) = input_slots {
return input_slots; return input_slots;
@ -134,7 +134,7 @@ pub fn load_from_file() -> SaveStateSlots {
pub unsafe fn save_to_file() { pub unsafe fn save_to_file() {
let save_states_str = toml::to_string_pretty(&*SAVE_STATE_SLOTS.data_ptr()) let save_states_str = toml::to_string_pretty(&*SAVE_STATE_SLOTS.data_ptr())
.expect("Error serializing save state information"); .expect("Error serializing save state information");
std::fs::write("sd:/TrainingModpack/save_states.toml", save_states_str) std::fs::write(SAVE_STATES_TOML_PATH, save_states_str)
.expect("Could not write save state information to file"); .expect("Could not write save state information to file");
} }
@ -596,6 +596,12 @@ pub unsafe fn save_states(module_accessor: &mut app::BattleObjectModuleAccessor)
MIRROR_STATE = 1.0; MIRROR_STATE = 1.0;
save_state_player().state = Save; save_state_player().state = Save;
save_state_cpu().state = Save; save_state_cpu().state = Save;
notifications::clear_notifications("Save State");
notifications::notification(
"Save State".to_string(),
format!("Saved Slot {SAVE_STATE_SLOT}"),
120,
);
} }
if save_state.state == Save && !fighter_is_nana { if save_state.state == Save && !fighter_is_nana {

View file

@ -1,8 +1,10 @@
use sarc::SarcFile; use sarc::SarcFile;
use skyline::nn::ui2d::*; use skyline::nn::ui2d::*;
use training_mod_consts::{MENU, OnOff}; use training_mod_consts::{OnOff, MENU};
use crate::common::{is_ready_go, is_training_mode}; use crate::common::{is_ready_go, is_training_mode};
#[cfg(feature = "layout_arc_from_file")]
use crate::consts::LAYOUT_ARC_PATH;
mod damage; mod damage;
mod display; mod display;
@ -37,8 +39,7 @@ pub unsafe fn handle_draw(layout: *mut Layout, draw_info: u64, cmd_buffer: u64)
static mut LAYOUT_ARC: &mut [u8; 600000] = &mut [0u8; 600000]; static mut LAYOUT_ARC: &mut [u8; 600000] = &mut [0u8; 600000];
/// We are editing the info_training/layout.arc and replacing the original file with our /// We are editing the info_training/layout.arc and replacing the original file with our
/// modified version from `sd://TrainingModpack/layout.arc` or, in the case of Ryujinx for the cool /// modified version from `LAYOUT_ARC_PATH`
/// kids `${RYUJINX_DIR}/sdcard/TrainingModpack/layout.arc`
/// ///
/// When we edit the layout we are doing two things. /// When we edit the layout we are doing two things.
/// ///
@ -72,9 +73,7 @@ static mut LAYOUT_ARC: &mut [u8; 600000] = &mut [0u8; 600000];
/// label_material.set_black_res_color(LABEL_BLACK_SELECTED_COLOR); /// label_material.set_black_res_color(LABEL_BLACK_SELECTED_COLOR);
/// ``` /// ```
#[skyline::hook(offset = 0x37730d4, inline)] #[skyline::hook(offset = 0x37730d4, inline)]
unsafe fn handle_layout_arc_malloc( unsafe fn handle_layout_arc_malloc(ctx: &mut skyline::hooks::InlineCtx) {
ctx: &mut skyline::hooks::InlineCtx
) {
if !is_training_mode() { if !is_training_mode() {
return; return;
} }
@ -82,9 +81,11 @@ unsafe fn handle_layout_arc_malloc(
let decompressed_file = *ctx.registers[21].x.as_ref() as *const u8; let decompressed_file = *ctx.registers[21].x.as_ref() as *const u8;
let decompressed_size = *ctx.registers[1].x.as_ref() as usize; let decompressed_size = *ctx.registers[1].x.as_ref() as usize;
let layout_arc = SarcFile::read( let layout_arc = SarcFile::read(std::slice::from_raw_parts(
std::slice::from_raw_parts(decompressed_file, decompressed_size) decompressed_file,
).unwrap(); decompressed_size,
))
.unwrap();
let training_layout = layout_arc.files.iter().find(|f| { let training_layout = layout_arc.files.iter().find(|f| {
f.name.is_some() && f.name.as_ref().unwrap() == &String::from("blyt/info_training.bflyt") f.name.is_some() && f.name.as_ref().unwrap() == &String::from("blyt/info_training.bflyt")
}); });
@ -95,8 +96,9 @@ unsafe fn handle_layout_arc_malloc(
let inject_arc; let inject_arc;
let inject_arc_size: u64; let inject_arc_size: u64;
#[cfg(feature = "layout_arc_from_file")] { #[cfg(feature = "layout_arc_from_file")]
let inject_arc_from_file = std::fs::read("sd:/TrainingModpack/layout.arc").unwrap(); {
let inject_arc_from_file = std::fs::read(LAYOUT_ARC_PATH).unwrap();
inject_arc_size = inject_arc_from_file.len() as u64; inject_arc_size = inject_arc_from_file.len() as u64;
// Copy read file to global // Copy read file to global
@ -107,7 +109,8 @@ unsafe fn handle_layout_arc_malloc(
inject_arc = LAYOUT_ARC.as_ptr(); inject_arc = LAYOUT_ARC.as_ptr();
} }
#[cfg(not(feature = "layout_arc_from_file"))] { #[cfg(not(feature = "layout_arc_from_file"))]
{
include_flate::flate!(static INJECT_ARC_FROM_FILE: [u8] from "src/static/layout.arc"); include_flate::flate!(static INJECT_ARC_FROM_FILE: [u8] from "src/static/layout.arc");
inject_arc = INJECT_ARC_FROM_FILE.as_ptr(); inject_arc = INJECT_ARC_FROM_FILE.as_ptr();
@ -125,8 +128,5 @@ unsafe fn handle_layout_arc_malloc(
} }
pub fn init() { pub fn init() {
skyline::install_hooks!( skyline::install_hooks!(handle_draw, handle_layout_arc_malloc);
handle_draw,
handle_layout_arc_malloc
);
} }

View file

@ -0,0 +1,14 @@
pub const ULTIMATE_ROOT: &str = "sd:/ultimate/";
pub const LEGACY_TRAINING_MODPACK_ROOT: &str = "sd:/TrainingModpack";
pub const TRAINING_MODPACK_ROOT: &str = "sd:/ultimate/TrainingModpack";
pub const TRAINING_MODPACK_TOML_PATH: &str = "sd:/ultimate/TrainingModpack/training_modpack.toml";
pub const SAVE_STATES_TOML_PATH: &str = "sd:/ultimate/TrainingModpack/save_states.toml";
pub const DEV_TOML_PATH: &str = "sd:/ultimate/TrainingModpack/dev.toml";
pub const VERSION_TXT_PATH: &str = "sd:/ultimate/TrainingModpack/version.txt";
pub const LAYOUT_ARC_PATH: &str = "sd:/ultimate/TrainingModpack/layout.arc";
pub const MENU_OPTIONS_PATH: &str = "sd:/ultimate/TrainingModpack/training_modpack_menu.conf";
pub const LEGACY_MENU_OPTIONS_PATH: &str =
"sd:/ultimate/TrainingModpack/training_modpack_menu.json";
pub const MENU_DEFAULT_OPTIONS_PATH: &str =
"sd:/ultimate/TrainingModpack/training_modpack_menu_defaults.conf";

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff