mirror of
https://github.com/Zenithsiz/dcb.git
synced 2026-02-08 19:34:27 +00:00
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:
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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),
|
||||
},
|
||||
])
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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(),
|
||||
|
||||
@@ -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),
|
||||
},
|
||||
])
|
||||
}
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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))),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user