Compare commits

..
13 Commits
8 changed files with 66 additions and 16 deletions
Generated
+1 -1
View File
@@ -1807,7 +1807,7 @@ checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
[[package]]
name = "lemur"
version = "0.3.2"
version = "0.4.3"
dependencies = [
"anyhow",
"atoi",
+1 -1
View File
@@ -4,7 +4,7 @@ description = "An emulator for the Virtual Boy."
repository = "https://git.virtual-boy.com/PVB/lemur"
publish = false
license = "MIT"
version = "0.3.2"
version = "0.4.3"
edition = "2021"
[dependencies]
+31 -1
View File
@@ -291,6 +291,26 @@ impl Emulator {
);
}
fn frame_advance(&mut self) {
if self
.state
.compare_exchange(
EmulatorState::Paused,
EmulatorState::Stepping,
Ordering::AcqRel,
Ordering::Acquire,
)
.is_err_and(|s| s == EmulatorState::Running)
{
let _ = self.state.compare_exchange(
EmulatorState::Running,
EmulatorState::Stepping,
Ordering::AcqRel,
Ordering::Relaxed,
);
}
}
fn save_sram(&mut self, sim_id: SimId) -> Result<()> {
let sim = self.sims.get_mut(sim_id.to_index());
let cart = self.carts[sim_id.to_index()].as_mut();
@@ -366,6 +386,7 @@ impl Emulator {
debugger.stop_reason = None;
true
}
fn debug_step(&mut self, sim_id: SimId) {
if self.debug_continue(sim_id) {
let Some(sim) = self.sims.get_mut(sim_id.to_index()) else {
@@ -428,7 +449,7 @@ impl Emulator {
// Don't emulate if the state is "paused", or if any sim is paused in the debugger
let running = match state {
EmulatorState::Paused => false,
EmulatorState::Running => true,
EmulatorState::Running | EmulatorState::Stepping => true,
EmulatorState::Debugging => self.debuggers.values().all(|d| d.stop_reason.is_none()),
};
let p1_running = running && p1_state == SimState::Ready;
@@ -442,6 +463,10 @@ impl Emulator {
self.sims[SimId::Player2.to_index()].emulate();
}
if state == EmulatorState::Stepping {
self.state.store(EmulatorState::Paused, Ordering::Release);
}
// Debug state
if state == EmulatorState::Debugging {
for sim_id in SimId::values() {
@@ -539,6 +564,9 @@ impl Emulator {
EmulatorCommand::Resume => {
self.resume_sims();
}
EmulatorCommand::FrameAdvance => {
self.frame_advance();
}
EmulatorCommand::StartDebugging(sim_id, debugger) => {
self.start_debugging(sim_id, debugger);
}
@@ -665,6 +693,7 @@ pub enum EmulatorCommand {
StopSecondSim,
Pause,
Resume,
FrameAdvance,
StartDebugging(SimId, DebugSender),
StopDebugging(SimId),
DebugInterrupt(SimId),
@@ -700,6 +729,7 @@ pub enum SimState {
pub enum EmulatorState {
Paused,
Running,
Stepping,
Debugging,
}
+9
View File
@@ -86,6 +86,7 @@ impl GameWindow {
let is_ready = self.client.sim_state(self.sim_id) == SimState::Ready;
let can_pause = is_ready && state == EmulatorState::Running;
let can_resume = is_ready && state == EmulatorState::Paused;
let can_frame_advance = is_ready && state != EmulatorState::Debugging;
if state == EmulatorState::Running {
if ui.add_enabled(can_pause, Button::new("Pause")).clicked() {
self.client.send_command(EmulatorCommand::Pause);
@@ -100,6 +101,14 @@ impl GameWindow {
.send_command(EmulatorCommand::Reset(self.sim_id));
ui.close_menu();
}
ui.separator();
if ui
.add_enabled(can_frame_advance, Button::new("Frame Advance"))
.clicked()
{
self.client.send_command(EmulatorCommand::FrameAdvance);
ui.close_menu();
}
});
ui.menu_button("Options", |ui| self.show_options_menu(ctx, ui));
ui.menu_button("Multiplayer", |ui| {
+2 -2
View File
@@ -215,8 +215,8 @@ impl ImageRenderer<1> for FrameBufferRenderer {
fn render(&mut self, params: &Self::Params, images: &mut [ImageBuffer; 1]) {
let image = &mut images[0];
let left_buffer = self.buffers[params.index * 2].borrow();
let right_buffer = self.buffers[params.index * 2 + 1].borrow();
let left_buffer = self.buffers[params.index].borrow();
let right_buffer = self.buffers[2 + params.index].borrow();
let colors = if params.generic_palette {
[
+4 -4
View File
@@ -3,12 +3,12 @@ use egui::{Color32, Image, ImageSource, Response, Sense, TextureOptions, Ui, Wid
pub const GENERIC_PALETTE: [u8; 4] = [0, 32, 64, 128];
pub fn shade(brt: u8, color: Color32) -> Color32 {
let corrected = if brt & 0x80 != 0 {
255
let corrected = if brt > 132 {
255.0
} else {
(brt << 1) | (brt >> 6)
(brt as f32 * 255.0 / 133.0).round()
};
color.gamma_multiply(corrected as f32 / 255.0)
color.gamma_multiply(corrected / 255.0)
}
pub fn generic_palette(color: Color32) -> [Color32; 4] {
+17 -6
View File
@@ -643,6 +643,15 @@ impl WorldRenderer {
shades.map(|s| shade(s, params.right_color)),
]
};
let palettes = {
let palettes = self.palettes.borrow().read::<[u8; 8]>(0);
[
utils::parse_palette(palettes[0]),
utils::parse_palette(palettes[2]),
utils::parse_palette(palettes[4]),
utils::parse_palette(palettes[6]),
]
};
let chardata = self.chardata.borrow();
let bgmaps = self.bgmaps.borrow();
@@ -667,7 +676,8 @@ impl WorldRenderer {
let row = (sy & 0x7) as usize;
let col = (sx & 0x7) as usize;
let pixel = utils::read_char_pixel(char, cell.hflip, cell.vflip, row, col);
image.add((dx as usize, dy as usize), colors[0][pixel as usize]);
let shade = palettes[cell.palette_index][pixel as usize];
image.add((dx as usize, dy as usize), colors[0][shade as usize]);
}
let dx = x + world.dst_x + world.dst_parallax;
@@ -680,7 +690,8 @@ impl WorldRenderer {
let row = (sy & 0x7) as usize;
let col = (sx & 0x7) as usize;
let pixel = utils::read_char_pixel(char, cell.hflip, cell.vflip, row, col);
image.add((dx as usize, dy as usize), colors[1][pixel as usize]);
let shade = palettes[cell.palette_index][pixel as usize];
image.add((dx as usize, dy as usize), colors[1][shade as usize]);
}
}
}
@@ -976,8 +987,8 @@ impl<'a> SourceCoordCalculator<'a> {
(sx, sy)
}
SourceParam::Affine(affine) => {
let sx = affine_coord(affine.src_x, x, affine.dx, affine.src_parallax.min(0).abs());
let sy = affine_coord(affine.src_y, x, affine.dy, affine.src_parallax.min(0).abs());
let sx = affine_coord(affine.src_x, x, affine.dx, affine.src_parallax.min(0));
let sy = affine_coord(affine.src_y, x, affine.dy, affine.src_parallax.min(0));
(sx, sy)
}
}
@@ -997,8 +1008,8 @@ impl<'a> SourceCoordCalculator<'a> {
(sx, sy)
}
SourceParam::Affine(affine) => {
let sx = affine_coord(affine.src_x, x, affine.dx, -affine.src_parallax.max(0));
let sy = affine_coord(affine.src_y, x, affine.dy, -affine.src_parallax.max(0));
let sx = affine_coord(affine.src_x, x, affine.dx, affine.src_parallax.max(0));
let sy = affine_coord(affine.src_y, x, affine.dy, affine.src_parallax.max(0));
(sx, sy)
}
}