Compare commits
7
Commits
8f9922473e
..
v0.8.2
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
db482b5c21 | ||
|
|
3e90d7df6d | ||
|
|
1cab6524a4 | ||
|
|
cd8ebab4bf | ||
|
|
4f681d883e | ||
|
|
a00d89bc36 | ||
|
|
6e89a0c988 |
Generated
+1
-1
@@ -2165,7 +2165,7 @@ checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "lemur"
|
name = "lemur"
|
||||||
version = "0.7.3"
|
version = "0.8.2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"atoi",
|
"atoi",
|
||||||
|
|||||||
+1
-1
@@ -4,7 +4,7 @@ description = "An emulator for the Virtual Boy."
|
|||||||
repository = "https://git.virtual-boy.com/PVB/lemur"
|
repository = "https://git.virtual-boy.com/PVB/lemur"
|
||||||
publish = false
|
publish = false
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
version = "0.7.3"
|
version = "0.8.2"
|
||||||
edition = "2024"
|
edition = "2024"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
|||||||
@@ -41,6 +41,7 @@ ENV PATH="/osxcross/bin:$PATH" \
|
|||||||
SHROOMS_CFLAGS_x86_64-unknown-linux-gnu="-flto" \
|
SHROOMS_CFLAGS_x86_64-unknown-linux-gnu="-flto" \
|
||||||
CARGO_TARGET_X86_64_UNKNOWN_LINUX_GNU_RUSTFLAGS="-Clinker-plugin-lto -Clinker=clang -Clink-arg=-fuse-ld=lld" \
|
CARGO_TARGET_X86_64_UNKNOWN_LINUX_GNU_RUSTFLAGS="-Clinker-plugin-lto -Clinker=clang -Clink-arg=-fuse-ld=lld" \
|
||||||
SHROOMS_CFLAGS_x86_64-pc-windows-msvc="-flto" \
|
SHROOMS_CFLAGS_x86_64-pc-windows-msvc="-flto" \
|
||||||
|
CFLAGS_x86_64-pc-windows-msvc="-I/xwin/crt/include -I/xwin/sdk/include/ucrt -I/xwin/sdk/include/um -I/xwin/sdk/include/shared" \
|
||||||
CARGO_TARGET_X86_64_PC_WINDOWS_MSVC_RUSTFLAGS="-Lnative=/xwin/crt/lib/x86_64 -Lnative=/xwin/sdk/lib/um/x86_64 -Lnative=/xwin/sdk/lib/ucrt/x86_64 -Clinker-plugin-lto -Clink-arg=-fuse-ld=lld" \
|
CARGO_TARGET_X86_64_PC_WINDOWS_MSVC_RUSTFLAGS="-Lnative=/xwin/crt/lib/x86_64 -Lnative=/xwin/sdk/lib/um/x86_64 -Lnative=/xwin/sdk/lib/ucrt/x86_64 -Clinker-plugin-lto -Clink-arg=-fuse-ld=lld" \
|
||||||
CARGO_TARGET_X86_64_PC_WINDOWS_MSVC_LINKER="lld-link-20" \
|
CARGO_TARGET_X86_64_PC_WINDOWS_MSVC_LINKER="lld-link-20" \
|
||||||
CARGO_TARGET_X86_64_APPLE_DARWIN_LINKER="o64-clang" \
|
CARGO_TARGET_X86_64_APPLE_DARWIN_LINKER="o64-clang" \
|
||||||
|
|||||||
@@ -86,12 +86,13 @@ fn parse_elf_program<Elf: object::read::elf::FileHeader<Endian = object::Endiann
|
|||||||
let mut bytes = vec![];
|
let mut bytes = vec![];
|
||||||
let mut pstart = None;
|
let mut pstart = None;
|
||||||
for phdr in header.program_headers(endian, data).ok()? {
|
for phdr in header.program_headers(endian, data).ok()? {
|
||||||
if phdr.p_filesz(endian).into() == 0 {
|
let pma = phdr.p_paddr(endian).into();
|
||||||
|
if pma < 0x07000000 || phdr.p_filesz(endian).into() == 0 {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
let start = pstart.unwrap_or(phdr.p_paddr(endian).into());
|
let start = pstart.unwrap_or(pma);
|
||||||
pstart = Some(start);
|
pstart = Some(start);
|
||||||
bytes.resize((phdr.p_paddr(endian).into() - start) as usize, 0);
|
bytes.resize((pma - start) as usize, 0);
|
||||||
let data = phdr.data(endian, data).ok()?;
|
let data = phdr.data(endian, data).ok()?;
|
||||||
bytes.extend_from_slice(data);
|
bytes.extend_from_slice(data);
|
||||||
}
|
}
|
||||||
|
|||||||
+55
-19
@@ -1,17 +1,18 @@
|
|||||||
use std::{fs, time::Duration};
|
use std::{fs, time::Duration};
|
||||||
|
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use egui::{Button, CentralPanel, Checkbox, ViewportBuilder, ViewportId};
|
use egui::{Button, CentralPanel, Checkbox, Label, ViewportBuilder, ViewportId};
|
||||||
use egui_notify::{Anchor, Toast, Toasts};
|
use egui_notify::{Anchor, Toast, Toasts};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
emulator::{EmulatorClient, SimId},
|
emulator::{EmulatorClient, EmulatorCommand, EmulatorState, SimId},
|
||||||
profiler::{Profiler, ProfilerStatus},
|
profiler::{Profiler, ProfilerStatus},
|
||||||
window::AppWindow,
|
window::AppWindow,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub struct ProfileWindow {
|
pub struct ProfileWindow {
|
||||||
sim_id: SimId,
|
sim_id: SimId,
|
||||||
|
client: EmulatorClient,
|
||||||
profiler: Profiler,
|
profiler: Profiler,
|
||||||
toasts: Toasts,
|
toasts: Toasts,
|
||||||
}
|
}
|
||||||
@@ -20,6 +21,7 @@ impl ProfileWindow {
|
|||||||
pub fn new(sim_id: SimId, client: EmulatorClient) -> Self {
|
pub fn new(sim_id: SimId, client: EmulatorClient) -> Self {
|
||||||
Self {
|
Self {
|
||||||
sim_id,
|
sim_id,
|
||||||
|
client: client.clone(),
|
||||||
profiler: Profiler::new(sim_id, client),
|
profiler: Profiler::new(sim_id, client),
|
||||||
toasts: Toasts::new()
|
toasts: Toasts::new()
|
||||||
.with_anchor(Anchor::BottomLeft)
|
.with_anchor(Anchor::BottomLeft)
|
||||||
@@ -33,6 +35,10 @@ impl ProfileWindow {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn finish_recording(&mut self) {
|
fn finish_recording(&mut self) {
|
||||||
|
let pause = matches!(self.client.emulator_state(), EmulatorState::Running);
|
||||||
|
if pause {
|
||||||
|
self.client.send_command(EmulatorCommand::Pause);
|
||||||
|
}
|
||||||
match self.try_finish_recording() {
|
match self.try_finish_recording() {
|
||||||
Ok(Some(path)) => {
|
Ok(Some(path)) => {
|
||||||
let mut toast = Toast::info(format!("Saved to {path}"));
|
let mut toast = Toast::info(format!("Saved to {path}"));
|
||||||
@@ -46,6 +52,9 @@ impl ProfileWindow {
|
|||||||
self.toasts.add(toast);
|
self.toasts.add(toast);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if pause {
|
||||||
|
self.client.send_command(EmulatorCommand::Resume);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn try_finish_recording(&mut self) -> Result<Option<String>> {
|
fn try_finish_recording(&mut self) -> Result<Option<String>> {
|
||||||
@@ -84,8 +93,32 @@ impl AppWindow for ProfileWindow {
|
|||||||
let status = self.profiler.status();
|
let status = self.profiler.status();
|
||||||
let recording = matches!(status, ProfilerStatus::Recording);
|
let recording = matches!(status, ProfilerStatus::Recording);
|
||||||
CentralPanel::default().show(ctx, |ui| {
|
CentralPanel::default().show(ctx, |ui| {
|
||||||
|
ui.horizontal_wrapped(|ui| {
|
||||||
|
ui.spacing_mut().item_spacing.x = 0.0;
|
||||||
|
ui.add(
|
||||||
|
Label::new(
|
||||||
|
"Use this tool to record performance profiles of your game, for use in ",
|
||||||
|
)
|
||||||
|
.wrap_mode(egui::TextWrapMode::Wrap),
|
||||||
|
);
|
||||||
|
ui.hyperlink("https://profiler.firefox.com");
|
||||||
|
ui.label(".");
|
||||||
|
});
|
||||||
|
ui.horizontal_wrapped(|ui| {
|
||||||
|
ui.spacing_mut().item_spacing.x = 0.0;
|
||||||
|
ui.add(
|
||||||
|
Label::new("For more instructions, see ").wrap_mode(egui::TextWrapMode::Wrap),
|
||||||
|
);
|
||||||
|
ui.hyperlink_to(
|
||||||
|
"the Lemur wiki",
|
||||||
|
"https://git.virtual-boy.com/PVB/lemur/wiki/Profiling-with-Lemur",
|
||||||
|
);
|
||||||
|
ui.label(".");
|
||||||
|
});
|
||||||
|
ui.separator();
|
||||||
|
|
||||||
let mut enabled = status.enabled();
|
let mut enabled = status.enabled();
|
||||||
let enabled_checkbox = Checkbox::new(&mut enabled, "Profiling enabled?");
|
let enabled_checkbox = Checkbox::new(&mut enabled, "Enable profiling");
|
||||||
if ui.add_enabled(!recording, enabled_checkbox).changed() {
|
if ui.add_enabled(!recording, enabled_checkbox).changed() {
|
||||||
if enabled {
|
if enabled {
|
||||||
self.profiler.enable();
|
self.profiler.enable();
|
||||||
@@ -93,23 +126,26 @@ impl AppWindow for ProfileWindow {
|
|||||||
self.profiler.disable();
|
self.profiler.disable();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if !enabled {
|
||||||
ui.horizontal(|ui| {
|
ui.label("Enabling profiling will restart your current game.");
|
||||||
if !recording {
|
} else {
|
||||||
let record_button = Button::new("Record");
|
ui.horizontal(|ui| {
|
||||||
let can_record = matches!(status, ProfilerStatus::Enabled);
|
if !recording {
|
||||||
if ui.add_enabled(can_record, record_button).clicked() {
|
let record_button = Button::new("Record");
|
||||||
self.profiler.start_recording();
|
let can_record = matches!(status, ProfilerStatus::Enabled);
|
||||||
|
if ui.add_enabled(can_record, record_button).clicked() {
|
||||||
|
self.profiler.start_recording();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if ui.button("Finish recording").clicked() {
|
||||||
|
self.finish_recording();
|
||||||
|
}
|
||||||
|
if ui.button("Cancel recording").clicked() {
|
||||||
|
self.profiler.cancel_recording();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
});
|
||||||
if ui.button("Finish recording").clicked() {
|
}
|
||||||
self.finish_recording();
|
|
||||||
}
|
|
||||||
if ui.button("Cancel recording").clicked() {
|
|
||||||
self.profiler.cancel_recording();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
match &status {
|
match &status {
|
||||||
ProfilerStatus::Recording => {
|
ProfilerStatus::Recording => {
|
||||||
|
|||||||
Reference in New Issue
Block a user