Func now stores the argument overrides.

This commit is contained in:
Filipe Rodrigues 2021-08-16 14:28:12 +01:00
parent 44a252e0af
commit 57ef5b3127
6 changed files with 83 additions and 103 deletions

View File

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

View File

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

View File

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

View File

@ -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> {

View File

@ -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

View File

@ -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"