diff --git a/dcb-tools/src/decompiler/main.rs b/dcb-tools/src/decompiler/main.rs index 52a8825..ac6abae 100644 --- a/dcb-tools/src/decompiler/main.rs +++ b/dcb-tools/src/decompiler/main.rs @@ -236,7 +236,7 @@ fn main() -> Result<(), anyhow::Error> { } // Comment any `dw` instructions that are function, data or string pointers - if let Instruction::Directive(Directive::Dw(target) | Directive::DwRepeated { value: target, .. }) = instruction { + if let Instruction::Directive(Directive::Dw(target)) = instruction { if let Some(func) = functions.get(Pos(*target)) { print!(" # {}", func.name); } diff --git a/dcb/src/game/exe/data.rs b/dcb/src/game/exe/data.rs index acd67f5..cd0328e 100644 --- a/dcb/src/game/exe/data.rs +++ b/dcb/src/game/exe/data.rs @@ -23,9 +23,6 @@ pub enum Data> { /// Start position start_pos: Pos, - - /// End position (non-inclusive) - end_pos: Pos, }, /// Bytes @@ -38,9 +35,6 @@ pub enum Data> { /// Start position start_pos: Pos, - - /// End position (non-inclusive) - end_pos: Pos, }, } @@ -105,25 +99,33 @@ impl> Data { Self::Bytes { start_pos, .. } => *start_pos, } } - - /// Accesses the end position of this data - pub fn end_pos(&self) -> Pos { - match self { - Self::Ascii { end_pos, .. } => *end_pos, - Self::Bytes { end_pos, .. } => *end_pos, - } - } } impl Data<&'static str> { /// Returns an iterator of all known data pub fn known() -> impl Iterator { - std::array::IntoIter::new([Self::Bytes { - name: "StackStart", - desc: "Stack position", - start_pos: Pos(0x8006dd44), - end_pos: Pos(0x8006dd48), - }]) + std::array::IntoIter::new([ + Self::Bytes { + name: "StackTop", + desc: "Stack top address", + start_pos: Pos(0x8006dd44), + }, + Self::Bytes { + name: "StackSize", + desc: "Stack size", + start_pos: Pos(0x8006dd48), + }, + Self::Bytes { + name: "ZeroStart", + desc: "Start of the zero section in `start`", + start_pos: Pos(0x80077a08), + }, + Self::Bytes { + name: "HeapStart", + desc: "start of the heap", + start_pos: Pos(0x801ddf38), + }, + ]) } } diff --git a/dcb/src/game/exe/data/all_data.rs b/dcb/src/game/exe/data/all_data.rs index 1923d35..8e2299f 100644 --- a/dcb/src/game/exe/data/all_data.rs +++ b/dcb/src/game/exe/data/all_data.rs @@ -47,27 +47,15 @@ impl + Into> AllData { self.0 .into_iter() .map(|data| match data { - Data::Ascii { - name, - desc, - start_pos, - end_pos, - } => Data::Ascii { + Data::Ascii { name, desc, start_pos } => Data::Ascii { name: name.into(), desc: desc.into(), start_pos, - end_pos, }, - Data::Bytes { - name, - desc, - start_pos, - end_pos, - } => Data::Bytes { + Data::Bytes { name, desc, start_pos } => Data::Bytes { name: name.into(), desc: desc.into(), start_pos, - end_pos, }, }) .collect(), @@ -109,7 +97,7 @@ impl AllData { PseudoInstruction::SwImm { offset, .. } | PseudoInstruction::SwrImm { offset, .. }, ) | - Instruction::Directive(Directive::Dw(offset) | Directive::DwRepeated { value: offset, .. }) => Some(Pos(*offset)), + Instruction::Directive(Directive::Dw(offset)) => Some(Pos(*offset)), _ => None, }) .collect(); @@ -126,14 +114,12 @@ impl AllData { name: format!("string_{idx}"), desc: "".to_string(), start_pos: pos, - end_pos: pos + directive.size(), }, - Directive::Dw(_) | Directive::DwRepeated { .. } => Data::Bytes { + Directive::Dw(_) => Data::Bytes { name: format!("data_{idx}"), desc: "".to_string(), start_pos: pos, - end_pos: pos + directive.size(), }, }) .collect(), diff --git a/dcb/src/game/exe/func.rs b/dcb/src/game/exe/func.rs index f923c65..72d7ce8 100644 --- a/dcb/src/game/exe/func.rs +++ b/dcb/src/game/exe/func.rs @@ -82,20 +82,20 @@ impl Func<&'static str> { signature: "void(void)", desc: "Executable start", comments: hashmap! { - Pos(0x80056280) => "Zero out 0x80077a08 .. 0x801ddf38 word by word.", + Pos(0x80056280) => "Zero out ZeroStart .. HeapStart word by word.", Pos(0x80056284) => "^", Pos(0x80056288) => "^", Pos(0x8005628c) => "^", - Pos(0x800562a8) => "Initialize stack to (*StackStart - 0x10) | 0x80000000", - Pos(0x800562f8) => "args: (0x8007f988, ???)", - Pos(0x8005630c) => "args: (0x8007f98c)", + Pos(0x800562a8) => "Initialize stack to (*StackTop - 0x10) | 0x80000000", + Pos(0x800562f8) => "args: (HeapStart, (*StackTop - 0x10) - *StackSize - (HeapStart & 0x1fff_ffff))", + Pos(0x8005630c) => "args: (HeapStart + 0x4)", Pos(0x80056324) => "args: (string_0, string_0)", }, labels: hashmap! { Pos(0x80056280) => "zero_loop", }, start_pos: Pos(0x80056270), - end_pos: Pos(0x80056388), + end_pos: Pos(0x80056330), }, ]) } diff --git a/dcb/src/game/exe/func/funcs.rs b/dcb/src/game/exe/func/funcs.rs index 609f545..eac26e1 100644 --- a/dcb/src/game/exe/func/funcs.rs +++ b/dcb/src/game/exe/func/funcs.rs @@ -128,7 +128,7 @@ impl Funcs { let function_entrances: BTreeSet = instructions .filter_map(|(_, instruction)| match instruction { Instruction::Simple(SimpleInstruction::Jal { target }) => Some(*target), - Instruction::Directive(Directive::Dw(target) | Directive::DwRepeated { value: target, .. }) => Some(Pos(*target)), + Instruction::Directive(Directive::Dw(target)) => Some(Pos(*target)), _ => None, }) .filter(|target| (Instruction::CODE_START..Instruction::CODE_END).contains(target) && offsets.contains(target)) diff --git a/dcb/src/game/exe/func/iter.rs b/dcb/src/game/exe/func/iter.rs index bd48e79..67c3641 100644 --- a/dcb/src/game/exe/func/iter.rs +++ b/dcb/src/game/exe/func/iter.rs @@ -2,10 +2,7 @@ // Imports use super::{Func, Funcs}; -use crate::game::exe::{ - instruction::{Register, SimpleInstruction}, - Instruction, Pos, -}; +use crate::game::exe::{Instruction, Pos}; /// Iterator of instructions along with the current function pub struct WithInstructionsIter<'a, S: AsRef, I: Iterator> { @@ -15,9 +12,6 @@ pub struct WithInstructionsIter<'a, S: AsRef, I: Iterator, - /// Last instruction - last_instruction: Option<&'a Instruction>, - /// Current function cur_func: Option<&'a Func>, } @@ -28,7 +22,6 @@ impl<'a, S: AsRef, I: Iterator> WithInstruct Self { instructions, funcs, - last_instruction: None, cur_func: None, } } @@ -41,19 +34,17 @@ impl<'a, S: AsRef, I: Iterator> Iterator for fn next(&mut self) -> Option { let (pos, instruction) = self.instructions.next()?; - // Update our last instruction - let last_instruction = self.last_instruction.replace(instruction); - - // Check if we had a return last instruction - if let Some(Instruction::Simple(SimpleInstruction::Jr { rs: Register::Ra })) = last_instruction { - // Set our cur function to `None` and return it - let cur_func = self.cur_func.take(); - return Some((pos, instruction, cur_func)); + // If we're past the last instruction in the current function, + // reset the instruction + if let Some(cur_func) = self.cur_func { + if cur_func.end_pos == pos { + self.cur_func = None; + } } // Else check if we have a current function match self.cur_func { - // If we go, return it + // If we do, return it Some(cur_func) => Some((pos, instruction, Some(cur_func))), // Else check if we're at the start of a new function. diff --git a/dcb/src/game/exe/instruction/directive.rs b/dcb/src/game/exe/instruction/directive.rs index cff92b5..72e1957 100644 --- a/dcb/src/game/exe/instruction/directive.rs +++ b/dcb/src/game/exe/instruction/directive.rs @@ -14,16 +14,6 @@ pub enum Directive { #[display(fmt = "dw {_0:#x}")] Dw(u32), - /// Repeated words - #[display(fmt = "dw {value:#x}, {len}")] - DwRepeated { - /// Value being repeated - value: u32, - - /// Times the value was repeated - len: u32, - }, - /// Ascii string #[display(fmt = ".ascii {_0:?}")] Ascii(AsciiString), @@ -36,43 +26,9 @@ impl Directive { #[allow(clippy::as_conversions, clippy::cast_possible_truncation)] // Our length will always fit into a `u32`. match self { Self::Dw(_) => 4, - Self::DwRepeated { len, .. } => 4 * len, Self::Ascii(ascii) => 4 * (ascii.len() as u32), } } - - /// Decodes a `dw` instruction - pub fn decode_dw(first_raw: Raw, iter: &mut (impl Iterator + Clone)) -> Self { - let mut times_repeated = 0; - - // Keep getting values until either eof or a different one - loop { - let mut cur_iter = iter.clone(); - match cur_iter.next().map(|next_raw| next_raw.repr == first_raw.repr) { - // If we got a different value, keep fetching values until they're different - Some(true) => { - *iter = cur_iter; - times_repeated += 1; - }, - - // If we didn't get it or we got a different value, exit - // Note: No need t update the iterator, as it either returned `None` or - // a different raw. - None | Some(false) => match times_repeated { - // If the value didn't repeat, use a single `dw` - 0 => break Self::Dw(first_raw.repr), - - // Else return the table - _ => { - break Self::DwRepeated { - value: first_raw.repr, - len: times_repeated + 1, - } - }, - }, - } - } - } } @@ -101,7 +57,7 @@ impl FromRawIter for Directive { // If we're past all the code, there are no more strings, // so just decode a `dw`. if raw.pos >= Instruction::CODE_END { - return Some((raw.pos, Self::decode_dw(raw, iter))); + return Some((raw.pos, Self::Dw(raw.repr))); } // Try to get an ascii string from the raw and check for nulls @@ -153,7 +109,7 @@ impl FromRawIter for Directive { // Else if it was full null, non-uniformly null or non-ascii, // try to get a dw table - _ => Some((raw.pos, Self::decode_dw(raw, iter))), + _ => Some((raw.pos, Self::Dw(raw.repr))), } } }