mirror of
https://github.com/Zenithsiz/dcb.git
synced 2026-02-03 08:12:26 +00:00
Func now stores the argument overrides.
This commit is contained in:
parent
44a252e0af
commit
57ef5b3127
@ -53,6 +53,10 @@ pub struct Func {
|
||||
#[serde(default)]
|
||||
pub labels: BTreeMap<Pos, String>,
|
||||
|
||||
/// Instruction argument overrides
|
||||
#[serde(default)]
|
||||
pub inst_arg_overrides: BTreeMap<ArgPos, String>,
|
||||
|
||||
/// Start position
|
||||
pub start_pos: Pos,
|
||||
|
||||
@ -234,6 +238,7 @@ impl Func {
|
||||
inline_comments: BTreeMap::new(),
|
||||
block_comments: BTreeMap::new(),
|
||||
labels,
|
||||
inst_arg_overrides: BTreeMap::new(),
|
||||
start_pos: func_pos,
|
||||
end_pos,
|
||||
kind: FuncKind::Heuristics,
|
||||
@ -276,3 +281,16 @@ impl Ord for Func {
|
||||
self.start_pos.cmp(&other.start_pos)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// Instruction argument position
|
||||
// TODO: Better serde serialization / deserialize from a single string
|
||||
#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Debug)]
|
||||
#[derive(serde::Serialize, serde::Deserialize)]
|
||||
pub struct ArgPos {
|
||||
/// Position
|
||||
pub pos: Pos,
|
||||
|
||||
/// Argument index
|
||||
pub arg: usize,
|
||||
}
|
||||
|
||||
@ -27,9 +27,6 @@ pub struct CliData {
|
||||
|
||||
/// Known functions path
|
||||
pub known_funcs_path: PathBuf,
|
||||
|
||||
/// Instruction overrides path
|
||||
pub inst_arg_overrides_path: PathBuf,
|
||||
}
|
||||
|
||||
impl CliData {
|
||||
@ -44,7 +41,6 @@ impl CliData {
|
||||
const KNOWN_DATA_PATH_STR: &str = "known-data-path";
|
||||
const FOREIGN_DATA_PATH_STR: &str = "foreign-data-path";
|
||||
const KNOWN_FUNCS_PATH_STR: &str = "known-funcs-path";
|
||||
const INST_ARG_OVERRIDES_PATH_STR: &str = "inst-arg-overrides-path";
|
||||
|
||||
// Get all matches from cli
|
||||
let matches = ClapApp::new("Dcb disassembler")
|
||||
@ -96,12 +92,6 @@ impl CliData {
|
||||
.help("Sets the path of the known funcs")
|
||||
.takes_value(true),
|
||||
)
|
||||
.arg(
|
||||
ClapArg::with_name(INST_ARG_OVERRIDES_PATH_STR)
|
||||
.long(INST_ARG_OVERRIDES_PATH_STR)
|
||||
.help("Sets the path of the function arguments overrides")
|
||||
.takes_value(true),
|
||||
)
|
||||
.get_matches();
|
||||
|
||||
// Get the input filename
|
||||
@ -130,9 +120,6 @@ impl CliData {
|
||||
let known_funcs_path = matches
|
||||
.value_of(KNOWN_FUNCS_PATH_STR)
|
||||
.unwrap_or(default_paths::KNOWN_FUNCS);
|
||||
let inst_arg_overrides_path = matches
|
||||
.value_of(INST_ARG_OVERRIDES_PATH_STR)
|
||||
.unwrap_or(default_paths::INST_ARG_OVERRIDES);
|
||||
|
||||
// Return the cli data
|
||||
Self {
|
||||
@ -144,7 +131,6 @@ impl CliData {
|
||||
known_data_path: PathBuf::from(known_data_path),
|
||||
foreign_data_path: PathBuf::from(foreign_data_path),
|
||||
known_funcs_path: PathBuf::from(known_funcs_path),
|
||||
inst_arg_overrides_path: PathBuf::from(inst_arg_overrides_path),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -160,7 +146,4 @@ mod default_paths {
|
||||
|
||||
/// Known functions path
|
||||
pub const KNOWN_FUNCS: &str = "resources/asm/game_funcs.yaml";
|
||||
|
||||
/// Instruction overrides path
|
||||
pub const INST_ARG_OVERRIDES: &str = "resources/asm/inst_args_override.yaml";
|
||||
}
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
// Imports
|
||||
use crate::cli::CliData;
|
||||
use dcb_exe::{data::DataKind, Data, DataTable, DataType, FuncTable, Pos};
|
||||
use std::{collections::BTreeMap, str::FromStr};
|
||||
use std::str::FromStr;
|
||||
|
||||
/// External resources
|
||||
pub struct ExternalResources {
|
||||
@ -12,9 +12,6 @@ pub struct ExternalResources {
|
||||
|
||||
/// Function table
|
||||
pub func_table: FuncTable,
|
||||
|
||||
/// Overrides
|
||||
pub inst_arg_overrides: BTreeMap<ArgPos, String>,
|
||||
}
|
||||
|
||||
impl ExternalResources {
|
||||
@ -23,7 +20,6 @@ impl ExternalResources {
|
||||
let known_data_path = &cli.known_data_path;
|
||||
let foreign_data_path = &cli.foreign_data_path;
|
||||
let known_funcs_path = &cli.known_funcs_path;
|
||||
let inst_arg_overrides_path = &cli.inst_arg_overrides_path;
|
||||
|
||||
// Read all data
|
||||
let known_data: Vec<SerializedData> = zutil::parse_from_file(&known_data_path, serde_yaml::from_reader)
|
||||
@ -55,30 +51,11 @@ impl ExternalResources {
|
||||
.map_err(zutil::fmt_err_wrapper_owned)
|
||||
.map_err(|err| log::warn!("Unable to load functions from {known_funcs_path:?}: {err}"))
|
||||
.unwrap_or_default();
|
||||
let inst_arg_overrides = zutil::parse_from_file(&inst_arg_overrides_path, serde_yaml::from_reader)
|
||||
.map_err(zutil::fmt_err_wrapper_owned)
|
||||
.map_err(|err| log::warn!("Unable to load instruction overrides from {inst_arg_overrides_path:?}: {err}"))
|
||||
.unwrap_or_default();
|
||||
|
||||
Self {
|
||||
data_table,
|
||||
func_table,
|
||||
inst_arg_overrides,
|
||||
}
|
||||
Self { data_table, func_table }
|
||||
}
|
||||
}
|
||||
|
||||
/// Argument position
|
||||
#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Debug)]
|
||||
#[derive(serde::Serialize, serde::Deserialize)]
|
||||
pub struct ArgPos {
|
||||
/// Position
|
||||
pub pos: Pos,
|
||||
|
||||
/// Argument
|
||||
pub arg: usize,
|
||||
}
|
||||
|
||||
/// Serialized game / foreign data
|
||||
#[derive(Clone, Debug)]
|
||||
#[derive(serde::Deserialize)]
|
||||
|
||||
@ -10,11 +10,12 @@ mod external;
|
||||
// Exports
|
||||
use cli::CliData;
|
||||
use display_ctx::DisplayCtx;
|
||||
use external::{ArgPos, ExternalResources};
|
||||
use external::ExternalResources;
|
||||
|
||||
// Imports
|
||||
use anyhow::Context;
|
||||
use dcb_exe::{
|
||||
func::ArgPos,
|
||||
inst::{parse::LineArgExpr, Inst, InstDisplay, InstFmtArg, ParseCtx},
|
||||
reader::{iter::ExeItem, DeserializeOpts},
|
||||
ExeReader, Func, Pos,
|
||||
@ -35,11 +36,7 @@ fn main() -> Result<(), anyhow::Error> {
|
||||
let cli = CliData::new();
|
||||
|
||||
// Load all external resources
|
||||
let ExternalResources {
|
||||
data_table,
|
||||
func_table,
|
||||
mut inst_arg_overrides,
|
||||
} = ExternalResources::load(&cli);
|
||||
let ExternalResources { data_table, func_table } = ExternalResources::load(&cli);
|
||||
|
||||
// Open the input file
|
||||
let input_file_path = &cli.input_path;
|
||||
@ -70,6 +67,9 @@ fn main() -> Result<(), anyhow::Error> {
|
||||
// Current function instructions
|
||||
let mut cur_func_insts = BTreeMap::new();
|
||||
|
||||
// Current function instruction argument overrides
|
||||
let mut cur_func_inst_arg_overrides = BTreeMap::new();
|
||||
|
||||
for item in exe.iter() {
|
||||
match item {
|
||||
// For each function or header, print a header and all it's instructions
|
||||
@ -81,6 +81,9 @@ fn main() -> Result<(), anyhow::Error> {
|
||||
cur_func_insts.clear();
|
||||
cur_func_insts.extend(insts);
|
||||
|
||||
// Get the argument overrides
|
||||
cur_func_inst_arg_overrides.clone_from(&func.inst_arg_overrides);
|
||||
|
||||
println!("\n##########");
|
||||
println!("{}:", func.name);
|
||||
if !func.signature.is_empty() {
|
||||
@ -91,6 +94,7 @@ fn main() -> Result<(), anyhow::Error> {
|
||||
}
|
||||
|
||||
let insts = &cur_func_insts;
|
||||
let inst_arg_overrides = &mut cur_func_inst_arg_overrides;
|
||||
for (pos, inst) in insts {
|
||||
// If there's a block comment, print it
|
||||
if let Some(comment) = func.block_comments.get(pos) {
|
||||
@ -126,7 +130,8 @@ fn main() -> Result<(), anyhow::Error> {
|
||||
// Then build the instruction
|
||||
let inst = &insts.get(&pos)?;
|
||||
let inst = inst_display_cache.entry(pos).or_insert_with(|| {
|
||||
self::inst_display(inst, &exe, Some(func), &mut inst_arg_overrides, pos).to_string()
|
||||
self::inst_display(inst, &exe, Some(func), Some(inst_arg_overrides), pos)
|
||||
.to_string()
|
||||
});
|
||||
let inst_len = inst.len();
|
||||
|
||||
@ -156,7 +161,7 @@ fn main() -> Result<(), anyhow::Error> {
|
||||
Some(inst) => print!("{inst}"),
|
||||
None => print!(
|
||||
"{}",
|
||||
self::inst_display(inst, &exe, Some(func), &mut inst_arg_overrides, *pos)
|
||||
self::inst_display(inst, &exe, Some(func), Some(inst_arg_overrides), *pos)
|
||||
),
|
||||
}
|
||||
|
||||
@ -189,6 +194,12 @@ fn main() -> Result<(), anyhow::Error> {
|
||||
println!();
|
||||
}
|
||||
println!("##########\n");
|
||||
|
||||
// If there are any leftover overrides, warn
|
||||
inst_arg_overrides.drain_filter(|pos, s| {
|
||||
log::warn!("Ignoring override at {}/{}: {}", pos.pos, pos.arg, s.escape_debug());
|
||||
true
|
||||
});
|
||||
},
|
||||
|
||||
ExeItem::Data { data, insts } => {
|
||||
@ -204,10 +215,7 @@ fn main() -> Result<(), anyhow::Error> {
|
||||
}
|
||||
|
||||
// Write the instruction
|
||||
print!(
|
||||
"\t{}",
|
||||
self::inst_display(&inst, &exe, None, &mut inst_arg_overrides, pos)
|
||||
);
|
||||
print!("\t{}", self::inst_display(&inst, &exe, None, None, pos));
|
||||
|
||||
println!();
|
||||
}
|
||||
@ -229,10 +237,7 @@ fn main() -> Result<(), anyhow::Error> {
|
||||
}
|
||||
|
||||
// Write the instruction
|
||||
print!(
|
||||
"{}",
|
||||
self::inst_display(&inst, &exe, None, &mut inst_arg_overrides, pos)
|
||||
);
|
||||
print!("{}", self::inst_display(&inst, &exe, None, None, pos));
|
||||
|
||||
println!();
|
||||
|
||||
@ -242,19 +247,14 @@ fn main() -> Result<(), anyhow::Error> {
|
||||
}
|
||||
}
|
||||
|
||||
// If there are any leftover overrides, warn
|
||||
for (pos, _) in inst_arg_overrides {
|
||||
log::warn!("Ignoring override at {}/{}", pos.pos, pos.arg);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Returns a display-able for an instruction inside a possible function
|
||||
#[must_use]
|
||||
pub fn inst_display<'a>(
|
||||
inst: &'a Inst, exe: &'a ExeReader, func: Option<&'a Func>, inst_arg_overrides: &'a mut BTreeMap<ArgPos, String>,
|
||||
pos: Pos,
|
||||
inst: &'a Inst, exe: &'a ExeReader, func: Option<&'a Func>,
|
||||
mut inst_arg_overrides: Option<&'a mut BTreeMap<ArgPos, String>>, pos: Pos,
|
||||
) -> impl fmt::Display + 'a {
|
||||
// Overload the target of as many as possible using `inst_target`.
|
||||
zutil::DisplayWrapper::new(move |f| {
|
||||
@ -273,7 +273,10 @@ pub fn inst_display<'a>(
|
||||
let arg = arg.into_inner();
|
||||
|
||||
// If we have an override for this argument, use it
|
||||
match inst_arg_overrides.remove(&ArgPos { pos, arg: idx }) {
|
||||
match inst_arg_overrides
|
||||
.as_mut()
|
||||
.and_then(|arg_overrides| arg_overrides.remove(&ArgPos { pos, arg: idx }))
|
||||
{
|
||||
Some(value) => {
|
||||
// Validator
|
||||
let validate = || -> Result<(), anyhow::Error> {
|
||||
|
||||
@ -1148,6 +1148,34 @@
|
||||
0x80069b60: "flush_buffer_if_large"
|
||||
0x80069b90: "write_char"
|
||||
0x80069bb0: "exit"
|
||||
arg_overrides:
|
||||
? pos: 0x80069ad8
|
||||
arg: 1
|
||||
: "b'\\t'"
|
||||
? pos: 0x80069ae4
|
||||
arg: 1
|
||||
: "b'\\n'"
|
||||
? pos: 0x80069af4
|
||||
arg: 1
|
||||
: "b'\\r'"
|
||||
? pos: 0x80069af8
|
||||
arg: 1
|
||||
: "File1.BufferCurTabAlign@addr_hi"
|
||||
? pos: 0x80069b00
|
||||
arg: 1
|
||||
: "File1.BufferCurTabAlign@addr_lo"
|
||||
? pos: 0x80069b2c
|
||||
arg: 1
|
||||
: "File1.AllowedTable@addr_hi"
|
||||
? pos: 0x80069b34
|
||||
arg: 1
|
||||
: "File1.AllowedTable@addr_lo"
|
||||
? pos: 0x80069b9c
|
||||
arg: 1
|
||||
: "File1.Buffer@addr_hi"
|
||||
? pos: 0x80069ba4
|
||||
arg: 1
|
||||
: "File1.Buffer@addr_lo"
|
||||
start_pos: 0x80069ac4
|
||||
end_pos: 0x80069bc0
|
||||
kind: Known
|
||||
@ -1173,6 +1201,14 @@
|
||||
0x8006a634: "add_char"
|
||||
0x8006a63c: "loop"
|
||||
0x8006a650: "flush_file"
|
||||
arg_overrides:
|
||||
? pos: 0x8006a628
|
||||
arg: 1
|
||||
: "File1.NullStr@addr_hi"
|
||||
? pos: 0x8006a630
|
||||
arg: 1
|
||||
: "File1.NullStr@addr_lo"
|
||||
|
||||
start_pos: 0x8006a614
|
||||
end_pos: 0x8006a668
|
||||
kind: Known
|
||||
|
||||
@ -755,40 +755,3 @@
|
||||
? pos: 0x80015a40
|
||||
arg: 2
|
||||
: "unknown21@addr_lo"
|
||||
|
||||
# File1.WriteChar
|
||||
? pos: 0x80069ad8
|
||||
arg: 1
|
||||
: "b'\\t'"
|
||||
? pos: 0x80069ae4
|
||||
arg: 1
|
||||
: "b'\\n'"
|
||||
? pos: 0x80069af4
|
||||
arg: 1
|
||||
: "b'\\r'"
|
||||
? pos: 0x80069af8
|
||||
arg: 1
|
||||
: "File1.BufferCurTabAlign@addr_hi"
|
||||
? pos: 0x80069b00
|
||||
arg: 1
|
||||
: "File1.BufferCurTabAlign@addr_lo"
|
||||
? pos: 0x80069b2c
|
||||
arg: 1
|
||||
: "File1.AllowedTable@addr_hi"
|
||||
? pos: 0x80069b34
|
||||
arg: 1
|
||||
: "File1.AllowedTable@addr_lo"
|
||||
? pos: 0x80069b9c
|
||||
arg: 1
|
||||
: "File1.Buffer@addr_hi"
|
||||
? pos: 0x80069ba4
|
||||
arg: 1
|
||||
: "File1.Buffer@addr_lo"
|
||||
|
||||
# File1.WriteStr
|
||||
? pos: 0x8006a628
|
||||
arg: 1
|
||||
: "File1.NullStr@addr_hi"
|
||||
? pos: 0x8006a630
|
||||
arg: 1
|
||||
: "File1.NullStr@addr_lo"
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user