mirror of https://github.com/encounter/objdiff.git
Rework function diff view (fixes #12)
This commit is contained in:
parent
1e44f73b2f
commit
3224be21db
|
@ -1181,6 +1181,12 @@ dependencies = [
|
||||||
"web-sys",
|
"web-sys",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "itoa"
|
||||||
|
version = "1.0.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6c8af84674fe1f223a982c933a0ee1086ac4d4052aa0fb8060c12c6ad838e754"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "jni"
|
name = "jni"
|
||||||
version = "0.19.0"
|
version = "0.19.0"
|
||||||
|
@ -1533,6 +1539,15 @@ dependencies = [
|
||||||
"syn",
|
"syn",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "num_threads"
|
||||||
|
version = "0.1.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2819ce041d2ee131036f4fc9d6ae7ae125a3a40e97ba64d04fe799ad9dabbb44"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "objc"
|
name = "objc"
|
||||||
version = "0.2.7"
|
version = "0.2.7"
|
||||||
|
@ -1582,6 +1597,7 @@ dependencies = [
|
||||||
"rfd",
|
"rfd",
|
||||||
"serde",
|
"serde",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
|
"time",
|
||||||
"tracing-subscriber",
|
"tracing-subscriber",
|
||||||
"tracing-wasm",
|
"tracing-wasm",
|
||||||
"winapi",
|
"winapi",
|
||||||
|
@ -2081,6 +2097,17 @@ dependencies = [
|
||||||
"once_cell",
|
"once_cell",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "time"
|
||||||
|
version = "0.3.14"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3c3f9a28b618c3a6b9251b6908e9c99e04b9e5c02e6581ccbb67d59c34ef7f9b"
|
||||||
|
dependencies = [
|
||||||
|
"itoa",
|
||||||
|
"libc",
|
||||||
|
"num_threads",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tiny-skia"
|
name = "tiny-skia"
|
||||||
version = "0.7.0"
|
version = "0.7.0"
|
||||||
|
|
|
@ -26,6 +26,7 @@ rfd = { version = "0.10.0" } # , default-features = false, features = ['xdg-port
|
||||||
egui_extras = "0.19.0"
|
egui_extras = "0.19.0"
|
||||||
ppc750cl = { git = "https://github.com/terorie/ppc750cl" }
|
ppc750cl = { git = "https://github.com/terorie/ppc750cl" }
|
||||||
rabbitizer = { git = "https://github.com/encounter/rabbitizer-rs", rev = "10c279b2ef251c62885b1dcdcfe740b0db8e9956" }
|
rabbitizer = { git = "https://github.com/encounter/rabbitizer-rs", rev = "10c279b2ef251c62885b1dcdcfe740b0db8e9956" }
|
||||||
|
time = { version = "0.3.14", features = ["formatting", "local-offset"] }
|
||||||
|
|
||||||
[target.'cfg(windows)'.dependencies]
|
[target.'cfg(windows)'.dependencies]
|
||||||
path-slash = "0.2.0"
|
path-slash = "0.2.0"
|
||||||
|
|
|
@ -7,6 +7,7 @@ A tool for decompilation projects.
|
||||||
|
|
||||||
Currently supports:
|
Currently supports:
|
||||||
- PowerPC 750CL (GameCube & Wii)
|
- PowerPC 750CL (GameCube & Wii)
|
||||||
|
- MIPS (Nintendo 64)
|
||||||
|
|
||||||
**WARNING:** Very early & unstable.
|
**WARNING:** Very early & unstable.
|
||||||
|
|
||||||
|
|
88
src/app.rs
88
src/app.rs
|
@ -12,6 +12,7 @@ use std::{
|
||||||
use eframe::Frame;
|
use eframe::Frame;
|
||||||
use egui::Widget;
|
use egui::Widget;
|
||||||
use notify::{RecursiveMode, Watcher};
|
use notify::{RecursiveMode, Watcher};
|
||||||
|
use time::{OffsetDateTime, UtcOffset};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
jobs::{
|
jobs::{
|
||||||
|
@ -38,7 +39,14 @@ pub enum DiffKind {
|
||||||
WholeBinary,
|
WholeBinary,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default, serde::Deserialize, serde::Serialize)]
|
#[derive(Default, Clone)]
|
||||||
|
pub struct DiffConfig {
|
||||||
|
// TODO
|
||||||
|
// pub stripped_symbols: Vec<String>,
|
||||||
|
// pub mapped_symbols: HashMap<String, String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(serde::Deserialize, serde::Serialize)]
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub struct ViewState {
|
pub struct ViewState {
|
||||||
#[serde(skip)]
|
#[serde(skip)]
|
||||||
|
@ -53,11 +61,35 @@ pub struct ViewState {
|
||||||
pub current_view: View,
|
pub current_view: View,
|
||||||
#[serde(skip)]
|
#[serde(skip)]
|
||||||
pub show_config: bool,
|
pub show_config: bool,
|
||||||
|
#[serde(skip)]
|
||||||
|
pub diff_config: DiffConfig,
|
||||||
|
#[serde(skip)]
|
||||||
|
pub search: String,
|
||||||
|
#[serde(skip)]
|
||||||
|
pub utc_offset: UtcOffset,
|
||||||
// Config
|
// Config
|
||||||
pub diff_kind: DiffKind,
|
pub diff_kind: DiffKind,
|
||||||
pub reverse_fn_order: bool,
|
pub reverse_fn_order: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Default for ViewState {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
jobs: vec![],
|
||||||
|
build: None,
|
||||||
|
highlighted_symbol: None,
|
||||||
|
selected_symbol: None,
|
||||||
|
current_view: Default::default(),
|
||||||
|
show_config: false,
|
||||||
|
diff_config: Default::default(),
|
||||||
|
search: Default::default(),
|
||||||
|
utc_offset: UtcOffset::UTC,
|
||||||
|
diff_kind: Default::default(),
|
||||||
|
reverse_fn_order: false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Default, Clone, serde::Deserialize, serde::Serialize)]
|
#[derive(Default, Clone, serde::Deserialize, serde::Serialize)]
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub struct AppConfig {
|
pub struct AppConfig {
|
||||||
|
@ -107,7 +139,7 @@ const CONFIG_KEY: &str = "app_config";
|
||||||
|
|
||||||
impl App {
|
impl App {
|
||||||
/// Called once before the first frame.
|
/// Called once before the first frame.
|
||||||
pub fn new(cc: &eframe::CreationContext<'_>) -> Self {
|
pub fn new(cc: &eframe::CreationContext<'_>, utc_offset: UtcOffset) -> Self {
|
||||||
// This is also where you can customized the look at feel of egui using
|
// This is also where you can customized the look at feel of egui using
|
||||||
// `cc.egui_ctx.set_visuals` and `cc.egui_ctx.set_fonts`.
|
// `cc.egui_ctx.set_visuals` and `cc.egui_ctx.set_fonts`.
|
||||||
|
|
||||||
|
@ -120,6 +152,7 @@ impl App {
|
||||||
config.project_dir_change = true;
|
config.project_dir_change = true;
|
||||||
}
|
}
|
||||||
app.config = Arc::new(RwLock::new(config));
|
app.config = Arc::new(RwLock::new(config));
|
||||||
|
app.view_state.utc_offset = utc_offset;
|
||||||
app
|
app
|
||||||
} else {
|
} else {
|
||||||
Self::default()
|
Self::default()
|
||||||
|
@ -149,16 +182,20 @@ impl eframe::App for App {
|
||||||
if view_state.current_view == View::FunctionDiff
|
if view_state.current_view == View::FunctionDiff
|
||||||
&& matches!(&view_state.build, Some(b) if b.first_status.success && b.second_status.success)
|
&& matches!(&view_state.build, Some(b) if b.first_status.success && b.second_status.success)
|
||||||
{
|
{
|
||||||
egui::SidePanel::left("side_panel").show(ctx, |ui| {
|
// egui::SidePanel::left("side_panel").show(ctx, |ui| {
|
||||||
if ui.button("Back").clicked() {
|
// if ui.button("Back").clicked() {
|
||||||
view_state.current_view = View::SymbolDiff;
|
// view_state.current_view = View::SymbolDiff;
|
||||||
}
|
// }
|
||||||
ui.separator();
|
// ui.separator();
|
||||||
jobs_ui(ui, view_state);
|
// jobs_ui(ui, view_state);
|
||||||
});
|
// });
|
||||||
|
|
||||||
egui::CentralPanel::default().show(ctx, |ui| {
|
egui::CentralPanel::default().show(ctx, |ui| {
|
||||||
function_diff_ui(ui, view_state);
|
if function_diff_ui(ui, view_state) {
|
||||||
|
view_state
|
||||||
|
.jobs
|
||||||
|
.push(queue_build(config.clone(), view_state.diff_config.clone()));
|
||||||
|
}
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
egui::SidePanel::left("side_panel").show(ctx, |ui| {
|
egui::SidePanel::left("side_panel").show(ctx, |ui| {
|
||||||
|
@ -253,6 +290,7 @@ impl eframe::App for App {
|
||||||
},
|
},
|
||||||
first_obj: Some(state.first_obj),
|
first_obj: Some(state.first_obj),
|
||||||
second_obj: Some(state.second_obj),
|
second_obj: Some(state.second_obj),
|
||||||
|
time: OffsetDateTime::now_utc(),
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -267,7 +305,10 @@ impl eframe::App for App {
|
||||||
let mut i = 0;
|
let mut i = 0;
|
||||||
while i < self.view_state.jobs.len() {
|
while i < self.view_state.jobs.len() {
|
||||||
let job = &self.view_state.jobs[i];
|
let job = &self.view_state.jobs[i];
|
||||||
if job.should_remove && job.handle.is_none() {
|
if job.should_remove
|
||||||
|
&& job.handle.is_none()
|
||||||
|
&& job.status.read().unwrap().error.is_none()
|
||||||
|
{
|
||||||
self.view_state.jobs.remove(i);
|
self.view_state.jobs.remove(i);
|
||||||
} else {
|
} else {
|
||||||
i += 1;
|
i += 1;
|
||||||
|
@ -288,20 +329,19 @@ impl eframe::App for App {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(build_obj) = &config.obj_path {
|
if config.obj_path.is_some() && self.modified.load(Ordering::Relaxed) {
|
||||||
if self.modified.load(Ordering::Relaxed) {
|
if !self
|
||||||
if !self
|
.view_state
|
||||||
.view_state
|
.jobs
|
||||||
.jobs
|
.iter()
|
||||||
.iter()
|
.any(|j| j.job_type == Job::ObjDiff && j.handle.is_some())
|
||||||
.any(|j| j.job_type == Job::ObjDiff && j.handle.is_some())
|
{
|
||||||
{
|
self.view_state.jobs.push(queue_build(
|
||||||
self.view_state
|
self.config.clone(),
|
||||||
.jobs
|
self.view_state.diff_config.clone(),
|
||||||
.push(queue_build(build_obj.clone(), self.config.clone()));
|
));
|
||||||
}
|
|
||||||
self.modified.store(false, Ordering::Relaxed);
|
|
||||||
}
|
}
|
||||||
|
self.modified.store(false, Ordering::Relaxed);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@ use std::collections::BTreeMap;
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
app::DiffConfig,
|
||||||
editops::{editops_find, LevEditType},
|
editops::{editops_find, LevEditType},
|
||||||
obj::{
|
obj::{
|
||||||
mips, ppc, ObjArchitecture, ObjInfo, ObjInsArg, ObjInsArgDiff, ObjInsBranchFrom,
|
mips, ppc, ObjArchitecture, ObjInfo, ObjInsArg, ObjInsArgDiff, ObjInsBranchFrom,
|
||||||
|
@ -336,7 +337,7 @@ fn find_symbol<'a>(symbols: &'a mut [ObjSymbol], name: &str) -> Option<&'a mut O
|
||||||
symbols.iter_mut().find(|s| s.name == name)
|
symbols.iter_mut().find(|s| s.name == name)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn diff_objs(left: &mut ObjInfo, right: &mut ObjInfo) -> Result<()> {
|
pub fn diff_objs(left: &mut ObjInfo, right: &mut ObjInfo, _diff_config: &DiffConfig) -> Result<()> {
|
||||||
for left_section in &mut left.sections {
|
for left_section in &mut left.sections {
|
||||||
if let Some(right_section) = find_section(right, &left_section.name) {
|
if let Some(right_section) = find_section(right, &left_section.name) {
|
||||||
for left_symbol in &mut left_section.symbols {
|
for left_symbol in &mut left_section.symbols {
|
||||||
|
|
|
@ -3,7 +3,7 @@ use std::sync::{mpsc::Receiver, Arc, RwLock};
|
||||||
use anyhow::{Error, Result};
|
use anyhow::{Error, Result};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
app::AppConfig,
|
app::{AppConfig, DiffConfig},
|
||||||
diff::diff_objs,
|
diff::diff_objs,
|
||||||
jobs::{queue_job, update_status, Job, JobResult, JobState, Status},
|
jobs::{queue_job, update_status, Job, JobResult, JobState, Status},
|
||||||
obj::{elf, ObjInfo},
|
obj::{elf, ObjInfo},
|
||||||
|
@ -31,7 +31,7 @@ fn run_build(
|
||||||
let mut right_obj = elf::read(base_path)?;
|
let mut right_obj = elf::read(base_path)?;
|
||||||
|
|
||||||
update_status(status, "Performing diff".to_string(), 2, 3, &cancel)?;
|
update_status(status, "Performing diff".to_string(), 2, 3, &cancel)?;
|
||||||
diff_objs(&mut left_obj, &mut right_obj)?;
|
diff_objs(&mut left_obj, &mut right_obj, &DiffConfig::default() /* TODO */)?;
|
||||||
|
|
||||||
update_status(status, "Complete".to_string(), 3, 3, &cancel)?;
|
update_status(status, "Complete".to_string(), 3, 3, &cancel)?;
|
||||||
Ok(Box::new(BinDiffResult { first_obj: left_obj, second_obj: right_obj }))
|
Ok(Box::new(BinDiffResult { first_obj: left_obj, second_obj: right_obj }))
|
||||||
|
|
|
@ -6,9 +6,10 @@ use std::{
|
||||||
};
|
};
|
||||||
|
|
||||||
use anyhow::{Context, Error, Result};
|
use anyhow::{Context, Error, Result};
|
||||||
|
use time::OffsetDateTime;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
app::AppConfig,
|
app::{AppConfig, DiffConfig},
|
||||||
diff::diff_objs,
|
diff::diff_objs,
|
||||||
jobs::{queue_job, update_status, Job, JobResult, JobState, Status},
|
jobs::{queue_job, update_status, Job, JobResult, JobState, Status},
|
||||||
obj::{elf, ObjInfo},
|
obj::{elf, ObjInfo},
|
||||||
|
@ -23,6 +24,7 @@ pub struct ObjDiffResult {
|
||||||
pub second_status: BuildStatus,
|
pub second_status: BuildStatus,
|
||||||
pub first_obj: Option<ObjInfo>,
|
pub first_obj: Option<ObjInfo>,
|
||||||
pub second_obj: Option<ObjInfo>,
|
pub second_obj: Option<ObjInfo>,
|
||||||
|
pub time: OffsetDateTime,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run_make(cwd: &Path, arg: &Path, config: &AppConfig) -> BuildStatus {
|
fn run_make(cwd: &Path, arg: &Path, config: &AppConfig) -> BuildStatus {
|
||||||
|
@ -75,10 +77,11 @@ fn run_make(cwd: &Path, arg: &Path, config: &AppConfig) -> BuildStatus {
|
||||||
fn run_build(
|
fn run_build(
|
||||||
status: &Status,
|
status: &Status,
|
||||||
cancel: Receiver<()>,
|
cancel: Receiver<()>,
|
||||||
obj_path: String,
|
|
||||||
config: Arc<RwLock<AppConfig>>,
|
config: Arc<RwLock<AppConfig>>,
|
||||||
|
diff_config: DiffConfig,
|
||||||
) -> Result<Box<ObjDiffResult>> {
|
) -> Result<Box<ObjDiffResult>> {
|
||||||
let config = config.read().map_err(|_| Error::msg("Failed to lock app config"))?.clone();
|
let config = config.read().map_err(|_| Error::msg("Failed to lock app config"))?.clone();
|
||||||
|
let obj_path = config.obj_path.as_ref().ok_or_else(|| Error::msg("Missing obj path"))?;
|
||||||
let project_dir =
|
let project_dir =
|
||||||
config.project_dir.as_ref().ok_or_else(|| Error::msg("Missing project dir"))?;
|
config.project_dir.as_ref().ok_or_else(|| Error::msg("Missing project dir"))?;
|
||||||
let mut target_path = config
|
let mut target_path = config
|
||||||
|
@ -86,10 +89,10 @@ fn run_build(
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.ok_or_else(|| Error::msg("Missing target obj dir"))?
|
.ok_or_else(|| Error::msg("Missing target obj dir"))?
|
||||||
.to_owned();
|
.to_owned();
|
||||||
target_path.push(&obj_path);
|
target_path.push(obj_path);
|
||||||
let mut base_path =
|
let mut base_path =
|
||||||
config.base_obj_dir.as_ref().ok_or_else(|| Error::msg("Missing base obj dir"))?.to_owned();
|
config.base_obj_dir.as_ref().ok_or_else(|| Error::msg("Missing base obj dir"))?.to_owned();
|
||||||
base_path.push(&obj_path);
|
base_path.push(obj_path);
|
||||||
let target_path_rel = target_path
|
let target_path_rel = target_path
|
||||||
.strip_prefix(project_dir)
|
.strip_prefix(project_dir)
|
||||||
.context("Failed to create relative target obj path")?;
|
.context("Failed to create relative target obj path")?;
|
||||||
|
@ -107,6 +110,8 @@ fn run_build(
|
||||||
update_status(status, format!("Building base {}", obj_path), 1, total, &cancel)?;
|
update_status(status, format!("Building base {}", obj_path), 1, total, &cancel)?;
|
||||||
let second_status = run_make(project_dir, base_path_rel, &config);
|
let second_status = run_make(project_dir, base_path_rel, &config);
|
||||||
|
|
||||||
|
let time = OffsetDateTime::now_utc();
|
||||||
|
|
||||||
let mut first_obj = if first_status.success {
|
let mut first_obj = if first_status.success {
|
||||||
update_status(status, format!("Loading target {}", obj_path), 2, total, &cancel)?;
|
update_status(status, format!("Loading target {}", obj_path), 2, total, &cancel)?;
|
||||||
Some(elf::read(&target_path)?)
|
Some(elf::read(&target_path)?)
|
||||||
|
@ -123,15 +128,15 @@ fn run_build(
|
||||||
|
|
||||||
if let (Some(first_obj), Some(second_obj)) = (&mut first_obj, &mut second_obj) {
|
if let (Some(first_obj), Some(second_obj)) = (&mut first_obj, &mut second_obj) {
|
||||||
update_status(status, "Performing diff".to_string(), 4, total, &cancel)?;
|
update_status(status, "Performing diff".to_string(), 4, total, &cancel)?;
|
||||||
diff_objs(first_obj, second_obj)?;
|
diff_objs(first_obj, second_obj, &diff_config)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
update_status(status, "Complete".to_string(), total, total, &cancel)?;
|
update_status(status, "Complete".to_string(), total, total, &cancel)?;
|
||||||
Ok(Box::new(ObjDiffResult { first_status, second_status, first_obj, second_obj }))
|
Ok(Box::new(ObjDiffResult { first_status, second_status, first_obj, second_obj, time }))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn queue_build(obj_path: String, config: Arc<RwLock<AppConfig>>) -> JobState {
|
pub fn queue_build(config: Arc<RwLock<AppConfig>>, diff_config: DiffConfig) -> JobState {
|
||||||
queue_job(Job::ObjDiff, move |status, cancel| {
|
queue_job(Job::ObjDiff, move |status, cancel| {
|
||||||
run_build(status, cancel, obj_path, config).map(JobResult::ObjDiff)
|
run_build(status, cancel, config, diff_config).map(JobResult::ObjDiff)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
13
src/main.rs
13
src/main.rs
|
@ -1,15 +1,26 @@
|
||||||
#![warn(clippy::all, rust_2018_idioms)]
|
#![warn(clippy::all, rust_2018_idioms)]
|
||||||
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")] // hide console window on Windows in release
|
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")] // hide console window on Windows in release
|
||||||
|
|
||||||
|
use time::UtcOffset;
|
||||||
|
|
||||||
// When compiling natively:
|
// When compiling natively:
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
fn main() {
|
fn main() {
|
||||||
// Log to stdout (if you run with `RUST_LOG=debug`).
|
// Log to stdout (if you run with `RUST_LOG=debug`).
|
||||||
tracing_subscriber::fmt::init();
|
tracing_subscriber::fmt::init();
|
||||||
|
|
||||||
|
// Because localtime_r is unsound in multithreaded apps,
|
||||||
|
// we must call this before initializing eframe.
|
||||||
|
// https://github.com/time-rs/time/issues/293
|
||||||
|
let utc_offset = UtcOffset::current_local_offset().unwrap();
|
||||||
|
|
||||||
let native_options = eframe::NativeOptions::default();
|
let native_options = eframe::NativeOptions::default();
|
||||||
// native_options.renderer = eframe::Renderer::Wgpu;
|
// native_options.renderer = eframe::Renderer::Wgpu;
|
||||||
eframe::run_native("objdiff", native_options, Box::new(|cc| Box::new(objdiff::App::new(cc))));
|
eframe::run_native(
|
||||||
|
"objdiff",
|
||||||
|
native_options,
|
||||||
|
Box::new(move |cc| Box::new(objdiff::App::new(cc, utc_offset))),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// when compiling to web using trunk.
|
// when compiling to web using trunk.
|
||||||
|
|
|
@ -149,15 +149,19 @@ pub fn config_ui(ui: &mut egui::Ui, config: &Arc<RwLock<AppConfig>>, view_state:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if let Some(new_build_obj) = new_build_obj {
|
if let Some(new_build_obj) = new_build_obj {
|
||||||
*obj_path = Some(new_build_obj.clone());
|
*obj_path = Some(new_build_obj);
|
||||||
view_state.jobs.push(queue_build(new_build_obj, config.clone()));
|
view_state
|
||||||
|
.jobs
|
||||||
|
.push(queue_build(config.clone(), view_state.diff_config.clone()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if let Some(obj) = obj_path {
|
if let Some(obj) = obj_path {
|
||||||
ui.label(&*obj);
|
ui.label(&*obj);
|
||||||
if ui.button("Build").clicked() {
|
if ui.button("Build").clicked() {
|
||||||
view_state.jobs.push(queue_build(obj.clone(), config.clone()));
|
view_state
|
||||||
|
.jobs
|
||||||
|
.push(queue_build(config.clone(), view_state.diff_config.clone()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,9 +4,11 @@ use cwdemangle::demangle;
|
||||||
use egui::{text::LayoutJob, Color32, Label, Sense};
|
use egui::{text::LayoutJob, Color32, Label, Sense};
|
||||||
use egui_extras::{Size, StripBuilder, TableBuilder};
|
use egui_extras::{Size, StripBuilder, TableBuilder};
|
||||||
use ppc750cl::Argument;
|
use ppc750cl::Argument;
|
||||||
|
use time::format_description;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
app::ViewState,
|
app::{View, ViewState},
|
||||||
|
jobs::Job,
|
||||||
obj::{
|
obj::{
|
||||||
ObjInfo, ObjIns, ObjInsArg, ObjInsArgDiff, ObjInsDiff, ObjInsDiffKind, ObjReloc,
|
ObjInfo, ObjIns, ObjInsArg, ObjInsArgDiff, ObjInsDiff, ObjInsDiffKind, ObjReloc,
|
||||||
ObjRelocKind, ObjSymbol,
|
ObjRelocKind, ObjSymbol,
|
||||||
|
@ -305,11 +307,57 @@ fn asm_table_ui(
|
||||||
Some(())
|
Some(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn function_diff_ui(ui: &mut egui::Ui, view_state: &mut ViewState) {
|
pub fn function_diff_ui(ui: &mut egui::Ui, view_state: &mut ViewState) -> bool {
|
||||||
|
let mut rebuild = false;
|
||||||
if let (Some(result), Some(selected_symbol)) = (&view_state.build, &view_state.selected_symbol)
|
if let (Some(result), Some(selected_symbol)) = (&view_state.build, &view_state.selected_symbol)
|
||||||
{
|
{
|
||||||
StripBuilder::new(ui).size(Size::exact(40.0)).size(Size::remainder()).vertical(
|
StripBuilder::new(ui)
|
||||||
|mut strip| {
|
.size(Size::exact(20.0))
|
||||||
|
.size(Size::exact(40.0))
|
||||||
|
.size(Size::remainder())
|
||||||
|
.vertical(|mut strip| {
|
||||||
|
strip.strip(|builder| {
|
||||||
|
builder.sizes(Size::remainder(), 2).horizontal(|mut strip| {
|
||||||
|
strip.cell(|ui| {
|
||||||
|
ui.horizontal(|ui| {
|
||||||
|
if ui.button("Back").clicked() {
|
||||||
|
view_state.current_view = View::SymbolDiff;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
strip.cell(|ui| {
|
||||||
|
ui.horizontal(|ui| {
|
||||||
|
if ui.button("Build").clicked() {
|
||||||
|
rebuild = true;
|
||||||
|
}
|
||||||
|
ui.scope(|ui| {
|
||||||
|
ui.style_mut().override_text_style =
|
||||||
|
Some(egui::TextStyle::Monospace);
|
||||||
|
ui.style_mut().wrap = Some(false);
|
||||||
|
if view_state
|
||||||
|
.jobs
|
||||||
|
.iter()
|
||||||
|
.any(|job| job.job_type == Job::ObjDiff)
|
||||||
|
{
|
||||||
|
ui.label("Building...");
|
||||||
|
} else {
|
||||||
|
ui.label("Last built:");
|
||||||
|
let format =
|
||||||
|
format_description::parse("[hour]:[minute]:[second]")
|
||||||
|
.unwrap();
|
||||||
|
ui.label(
|
||||||
|
result
|
||||||
|
.time
|
||||||
|
.to_offset(view_state.utc_offset)
|
||||||
|
.format(&format)
|
||||||
|
.unwrap(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
strip.strip(|builder| {
|
strip.strip(|builder| {
|
||||||
builder.sizes(Size::remainder(), 2).horizontal(|mut strip| {
|
builder.sizes(Size::remainder(), 2).horizontal(|mut strip| {
|
||||||
let demangled = demangle(selected_symbol);
|
let demangled = demangle(selected_symbol);
|
||||||
|
@ -359,7 +407,7 @@ pub fn function_diff_ui(ui: &mut egui::Ui, view_state: &mut ViewState) {
|
||||||
asm_table_ui(table, left_obj, right_obj, selected_symbol);
|
asm_table_ui(table, left_obj, right_obj, selected_symbol);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
},
|
});
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
rebuild
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue