Data no longer stores it's end position.

Removed `Directive::DwRepeat`.
Fixed `WithInstructionsIter` stoping on `jr $ra` instead of at the end of the function.
This commit is contained in:
2020-10-29 00:38:31 +00:00
parent 15bee575f8
commit 00a85397a7
7 changed files with 43 additions and 108 deletions

View File

@@ -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);
}

View File

@@ -23,9 +23,6 @@ pub enum Data<S: AsRef<str>> {
/// Start position
start_pos: Pos,
/// End position (non-inclusive)
end_pos: Pos,
},
/// Bytes
@@ -38,9 +35,6 @@ pub enum Data<S: AsRef<str>> {
/// Start position
start_pos: Pos,
/// End position (non-inclusive)
end_pos: Pos,
},
}
@@ -105,25 +99,33 @@ impl<S: AsRef<str>> Data<S> {
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<Item = Self> {
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),
},
])
}
}

View File

@@ -47,27 +47,15 @@ impl<S: AsRef<str> + Into<String>> AllData<S> {
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<String> {
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<String> {
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(),

View File

@@ -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),
},
])
}

View File

@@ -128,7 +128,7 @@ impl Funcs<String> {
let function_entrances: BTreeSet<Pos> = 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))

View File

@@ -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<str>, I: Iterator<Item = (Pos, &'a Instruction)>> {
@@ -15,9 +12,6 @@ pub struct WithInstructionsIter<'a, S: AsRef<str>, I: Iterator<Item = (Pos, &'a
/// All functions
funcs: &'a Funcs<S>,
/// Last instruction
last_instruction: Option<&'a Instruction>,
/// Current function
cur_func: Option<&'a Func<S>>,
}
@@ -28,7 +22,6 @@ impl<'a, S: AsRef<str>, I: Iterator<Item = (Pos, &'a Instruction)>> WithInstruct
Self {
instructions,
funcs,
last_instruction: None,
cur_func: None,
}
}
@@ -41,19 +34,17 @@ impl<'a, S: AsRef<str>, I: Iterator<Item = (Pos, &'a Instruction)>> Iterator for
fn next(&mut self) -> Option<Self::Item> {
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.

View File

@@ -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<Item = Raw> + 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))),
}
}
}