diff --git a/Cargo.lock b/Cargo.lock index 8b4aeb3..e1353ab 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -331,7 +331,7 @@ dependencies = [ [[package]] name = "decomp-toolkit" -version = "0.5.1" +version = "0.5.2" dependencies = [ "anyhow", "ar", diff --git a/Cargo.toml b/Cargo.toml index 1a544f8..4870da9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,7 +3,7 @@ name = "decomp-toolkit" description = "Yet another GameCube/Wii decompilation toolkit." authors = ["Luke Street "] license = "MIT OR Apache-2.0" -version = "0.5.1" +version = "0.5.2" edition = "2021" publish = false build = "build.rs" diff --git a/src/cmd/dol.rs b/src/cmd/dol.rs index d45c987..a8ac2db 100644 --- a/src/cmd/dol.rs +++ b/src/cmd/dol.rs @@ -142,6 +142,12 @@ pub struct ConfigArgs { #[inline] fn bool_true() -> bool { true } +#[inline] +fn is_true(b: &bool) -> bool { *b } + +#[inline] +fn is_default(t: &T) -> bool { t == &T::default() } + mod path_slash_serde { use std::path::PathBuf; @@ -187,51 +193,56 @@ mod path_slash_serde_option { pub struct ProjectConfig { #[serde(flatten)] pub base: ModuleConfig, - #[serde(with = "path_slash_serde_option", default)] + #[serde(with = "path_slash_serde_option", default, skip_serializing_if = "is_default")] pub selfile: Option, + #[serde(skip_serializing_if = "is_default")] pub selfile_hash: Option, /// Version of the MW `.comment` section format. /// If not present, no `.comment` sections will be written. + #[serde(skip_serializing_if = "is_default")] pub mw_comment_version: Option, /// Disables some time-consuming analysis passes. /// Useful when the symbols file is already created. - #[serde(default)] + #[serde(default, skip_serializing_if = "is_default")] pub quick_analysis: bool, - #[serde(default)] + #[serde(default, skip_serializing_if = "is_default")] pub modules: Vec, // Analysis options - #[serde(default = "bool_true")] + #[serde(default = "bool_true", skip_serializing_if = "is_true")] pub detect_objects: bool, - #[serde(default = "bool_true")] + #[serde(default = "bool_true", skip_serializing_if = "is_true")] pub detect_strings: bool, - #[serde(default = "bool_true")] + #[serde(default = "bool_true", skip_serializing_if = "is_true")] pub write_asm: bool, /// Specifies the start of the common BSS section. + #[serde(skip_serializing_if = "is_default")] pub common_start: Option, /// Disables all analysis passes that yield new symbols, /// and instead assumes that all symbols are known. - #[serde(default)] + #[serde(default, skip_serializing_if = "is_default")] pub symbols_known: bool, /// Fills gaps between symbols with - #[serde(default = "bool_true")] + #[serde(default = "bool_true", skip_serializing_if = "is_true")] pub fill_gaps: bool, } -#[derive(Serialize, Deserialize, Debug, Clone)] +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)] pub struct ModuleConfig { /// Object name. If not specified, the file name without extension will be used. + #[serde(skip_serializing_if = "is_default")] pub name: Option, #[serde(with = "path_slash_serde")] pub object: PathBuf, + #[serde(skip_serializing_if = "is_default")] pub hash: Option, - #[serde(with = "path_slash_serde_option", default)] + #[serde(with = "path_slash_serde_option", default, skip_serializing_if = "is_default")] pub splits: Option, - #[serde(with = "path_slash_serde_option", default)] + #[serde(with = "path_slash_serde_option", default, skip_serializing_if = "is_default")] pub symbols: Option, - #[serde(with = "path_slash_serde_option", default)] + #[serde(with = "path_slash_serde_option", default, skip_serializing_if = "is_default")] pub map: Option, /// Forces the given symbols to be active in the linker script. - #[serde(default)] + #[serde(default, skip_serializing_if = "is_default")] pub force_active: Vec, } @@ -262,6 +273,8 @@ pub struct OutputUnit { pub object: PathBuf, pub name: String, pub autogenerated: bool, + pub code_size: u32, + pub data_size: u32, } #[derive(Serialize, Deserialize, Debug, Clone, Default)] @@ -797,6 +810,8 @@ fn split_write_obj( object: out_path.clone(), name: unit.name.clone(), autogenerated: unit.autogenerated, + code_size: split_obj.code_size(), + data_size: split_obj.data_size(), }); if let Some(parent) = out_path.parent() { DirBuilder::new().recursive(true).create(parent)?; diff --git a/src/obj/mod.rs b/src/obj/mod.rs index 462ecd1..fb3750d 100644 --- a/src/obj/mod.rs +++ b/src/obj/mod.rs @@ -293,4 +293,29 @@ impl ObjInfo { .filter(|(_, _, _, split)| split.unit == unit) .all(|(_, _, _, split)| split.autogenerated) } + + /// Calculate the total size of all code sections. + pub fn code_size(&self) -> u32 { + self.sections + .iter() + .filter(|(_, section)| section.kind == ObjSectionKind::Code) + .map(|(_, section)| section.size as u32) + .sum() + } + + /// Calculate the total size of all data sections, including common BSS symbols. + pub fn data_size(&self) -> u32 { + self.sections + .iter() + .filter(|(_, section)| section.kind != ObjSectionKind::Code) + .map(|(_, section)| section.size as u32) + .chain( + // Include common symbols + self.symbols + .iter() + .filter(|&symbol| symbol.flags.is_common()) + .map(|s| s.size as u32), + ) + .sum() + } }