mirror of
https://github.com/Zenithsiz/dcb.git
synced 2026-02-08 02:44:20 +00:00
Exe can now be sliced by a position range.
This commit is contained in:
parent
d9bc90882b
commit
5390df6d72
@ -25,6 +25,7 @@ use dcb_io::GameFile;
|
||||
use std::{
|
||||
convert::TryFrom,
|
||||
io::{Read, Seek, Write},
|
||||
ops::{self, Range},
|
||||
};
|
||||
|
||||
/// The game executable
|
||||
@ -33,7 +34,7 @@ pub struct Exe {
|
||||
/// The executable header
|
||||
header: Header,
|
||||
|
||||
/// All bytes within the executable
|
||||
/// All instruction bytes within the executable.
|
||||
bytes: Box<[u8]>,
|
||||
|
||||
/// The data table.
|
||||
@ -73,6 +74,14 @@ impl Exe {
|
||||
&self.func_table
|
||||
}
|
||||
|
||||
/// Returns this executable's instruction range
|
||||
#[must_use]
|
||||
pub fn inst_range(&self) -> Range<Pos> {
|
||||
let start = self.header.start_pos;
|
||||
let end = self.header.start_pos + self.header.size;
|
||||
start..end
|
||||
}
|
||||
|
||||
/// Creates an iterator over this executable
|
||||
#[must_use]
|
||||
pub const fn iter(&self) -> iter::Iter {
|
||||
@ -123,3 +132,14 @@ impl Exe {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl ops::Index<Range<Pos>> for Exe {
|
||||
type Output = [u8];
|
||||
|
||||
fn index(&self, index: Range<Pos>) -> &Self::Output {
|
||||
let start = index.start.offset_from(self.header.start_pos);
|
||||
let end = index.end.offset_from(self.header.start_pos);
|
||||
|
||||
&self.bytes[start..end]
|
||||
}
|
||||
}
|
||||
|
||||
@ -58,7 +58,7 @@ impl<'a> Iterator for Iter<'a> {
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
// If we're at the end, return `None`
|
||||
let cur_pos = self.cur_pos;
|
||||
if cur_pos >= self.exe.header.start_pos + self.exe.header.size {
|
||||
if cur_pos >= self.exe.inst_range().end {
|
||||
return None;
|
||||
}
|
||||
|
||||
@ -76,10 +76,7 @@ impl<'a> Iterator for Iter<'a> {
|
||||
|
||||
return Some(ExeItem::Data {
|
||||
data,
|
||||
insts: ParseIter::new(
|
||||
&self.exe.bytes[cur_pos.as_mem_idx(self.exe.header.start_pos)..end_pos.as_mem_idx(self.exe.header.start_pos)],
|
||||
cur_pos,
|
||||
),
|
||||
insts: ParseIter::new(&self.exe[cur_pos..end_pos], cur_pos),
|
||||
});
|
||||
}
|
||||
|
||||
@ -88,16 +85,13 @@ impl<'a> Iterator for Iter<'a> {
|
||||
self.cur_pos = func.end_pos;
|
||||
return Some(ExeItem::Func {
|
||||
func,
|
||||
insts: ParseIter::new(
|
||||
&self.exe.bytes[cur_pos.as_mem_idx(self.exe.header.start_pos)..func.end_pos.as_mem_idx(self.exe.header.start_pos)],
|
||||
cur_pos,
|
||||
),
|
||||
insts: ParseIter::new(&self.exe[cur_pos..func.end_pos], cur_pos),
|
||||
});
|
||||
}
|
||||
|
||||
// Else return an iterator until the next data / function, or until end, if none or past the end.
|
||||
let next_data = self.exe.data_table.range(cur_pos..).next();
|
||||
let next_func = self.exe.func_table.range(cur_pos..).next();
|
||||
let next_data = self.exe.data_table().range(cur_pos..).next();
|
||||
let next_func = self.exe.func_table().range(cur_pos..).next();
|
||||
|
||||
let end_pos = match (next_data, next_func) {
|
||||
(Some(next_data), Some(next_func)) => match next_data.pos < next_func.start_pos {
|
||||
@ -106,19 +100,16 @@ impl<'a> Iterator for Iter<'a> {
|
||||
},
|
||||
(Some(next_data), None) => next_data.pos,
|
||||
(None, Some(next_func)) => next_func.start_pos,
|
||||
(None, None) => self.exe.header.start_pos + self.exe.header.size,
|
||||
(None, None) => self.exe.inst_range().end,
|
||||
};
|
||||
|
||||
// Make sure to limit the end position
|
||||
let end_pos = end_pos.min(self.exe.header.start_pos + self.exe.header.size);
|
||||
let end_pos = end_pos.min(self.exe.inst_range().end);
|
||||
self.cur_pos = end_pos;
|
||||
|
||||
|
||||
Some(ExeItem::Unknown {
|
||||
insts: ParseIter::new(
|
||||
&self.exe.bytes[cur_pos.as_mem_idx(self.exe.header.start_pos)..end_pos.as_mem_idx(self.exe.header.start_pos)],
|
||||
cur_pos,
|
||||
),
|
||||
insts: ParseIter::new(&self.exe[cur_pos..end_pos], cur_pos),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@ -13,10 +13,10 @@ use std::{convert::TryFrom, fmt, ops};
|
||||
pub struct Pos(pub u32);
|
||||
|
||||
impl Pos {
|
||||
/// Returns the memory position of this position
|
||||
/// Calculated the offset between two positions
|
||||
#[must_use]
|
||||
pub fn as_mem_idx(self, start_pos: Self) -> usize {
|
||||
usize::try_from(self - start_pos).expect("Failed to compute index")
|
||||
pub fn offset_from(self, start_pos: Self) -> usize {
|
||||
usize::try_from(self - start_pos).expect("Negative offset")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user