Remember whether game is muted
This commit is contained in:
parent
8dd64598ed
commit
e1d08672fb
|
|
@ -61,12 +61,12 @@ impl Application {
|
|||
pub fn new(
|
||||
client: EmulatorClient,
|
||||
proxy: EventLoopProxy<UserEvent>,
|
||||
persistence: Persistence,
|
||||
debug_port: Option<u16>,
|
||||
profiling: bool,
|
||||
) -> Self {
|
||||
let wgpu = WgpuState::new();
|
||||
let icon = load_icon().ok().map(Arc::new);
|
||||
let persistence = Persistence::new();
|
||||
let mappings = MappingProvider::new(persistence.clone());
|
||||
let shortcuts = ShortcutProvider::new(persistence.clone());
|
||||
let controllers = ControllerManager::new(client.clone(), &mappings);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,58 @@
|
|||
use anyhow::Result;
|
||||
use egui::{Color32, Vec2};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::{emulator::SimId, persistence::Persistence, window::DisplayMode};
|
||||
|
||||
pub const COLOR_PRESETS: [[Color32; 2]; 3] = [
|
||||
[
|
||||
Color32::from_rgb(0xff, 0x00, 0x00),
|
||||
Color32::from_rgb(0x00, 0xc6, 0xf0),
|
||||
],
|
||||
[
|
||||
Color32::from_rgb(0x00, 0xb4, 0x00),
|
||||
Color32::from_rgb(0xc8, 0x00, 0xff),
|
||||
],
|
||||
[
|
||||
Color32::from_rgb(0xb4, 0x9b, 0x00),
|
||||
Color32::from_rgb(0x00, 0x00, 0xff),
|
||||
],
|
||||
];
|
||||
|
||||
const fn default_audio_enabled() -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, PartialEq, Eq)]
|
||||
pub struct SimConfig {
|
||||
pub display_mode: DisplayMode,
|
||||
pub colors: [Color32; 2],
|
||||
pub dimensions: Vec2,
|
||||
#[serde(default = "default_audio_enabled")]
|
||||
pub audio_enabled: bool,
|
||||
}
|
||||
|
||||
impl SimConfig {
|
||||
pub fn load(persistence: &Persistence, sim_id: SimId) -> Self {
|
||||
if let Ok(config) = persistence.load_config(config_filename(sim_id)) {
|
||||
return config;
|
||||
}
|
||||
Self {
|
||||
display_mode: DisplayMode::Anaglyph,
|
||||
colors: COLOR_PRESETS[0],
|
||||
dimensions: DisplayMode::Anaglyph.proportions() + Vec2::new(0.0, 22.0),
|
||||
audio_enabled: true,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn save(&self, persistence: &Persistence, sim_id: SimId) -> Result<()> {
|
||||
persistence.save_config(config_filename(sim_id), self)
|
||||
}
|
||||
}
|
||||
|
||||
fn config_filename(sim_id: SimId) -> &'static str {
|
||||
match sim_id {
|
||||
SimId::Player1 => "config_p1",
|
||||
SimId::Player2 => "config_p2",
|
||||
}
|
||||
}
|
||||
|
|
@ -96,7 +96,6 @@ impl EmulatorBuilder {
|
|||
queue,
|
||||
sim_state: builder.sim_state.clone(),
|
||||
state: builder.state.clone(),
|
||||
audio_on: builder.audio_on.clone(),
|
||||
linked: builder.linked.clone(),
|
||||
};
|
||||
(builder, client)
|
||||
|
|
@ -116,6 +115,12 @@ impl EmulatorBuilder {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn with_audio_on(self, p1: bool, p2: bool) -> Self {
|
||||
self.audio_on[0].store(p1, Ordering::Relaxed);
|
||||
self.audio_on[1].store(p2, Ordering::Relaxed);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn build(self) -> Result<Emulator> {
|
||||
let mut emulator = Emulator::new(
|
||||
self.commands,
|
||||
|
|
@ -715,9 +720,8 @@ impl Emulator {
|
|||
};
|
||||
sim.watch_stdout(true);
|
||||
}
|
||||
EmulatorCommand::SetAudioEnabled(p1, p2) => {
|
||||
self.audio_on[SimId::Player1.to_index()].store(p1, Ordering::Release);
|
||||
self.audio_on[SimId::Player2.to_index()].store(p2, Ordering::Release);
|
||||
EmulatorCommand::SetAudioEnabled(sim_id, enabled) => {
|
||||
self.audio_on[sim_id.to_index()].store(enabled, Ordering::Release);
|
||||
}
|
||||
EmulatorCommand::Link => {
|
||||
self.link_sims();
|
||||
|
|
@ -792,7 +796,7 @@ pub enum EmulatorCommand {
|
|||
AddWatchpoint(SimId, u32, usize, VBWatchpointType),
|
||||
RemoveWatchpoint(SimId, u32, usize, VBWatchpointType),
|
||||
WatchStdout(SimId, mpsc::Sender<String>),
|
||||
SetAudioEnabled(bool, bool),
|
||||
SetAudioEnabled(SimId, bool),
|
||||
Link,
|
||||
Unlink,
|
||||
Reset(SimId),
|
||||
|
|
@ -858,7 +862,6 @@ pub struct EmulatorClient {
|
|||
queue: mpsc::Sender<EmulatorCommand>,
|
||||
sim_state: Arc<[Atomic<SimState>; 2]>,
|
||||
state: Arc<Atomic<EmulatorState>>,
|
||||
audio_on: Arc<[AtomicBool; 2]>,
|
||||
linked: Arc<AtomicBool>,
|
||||
}
|
||||
|
||||
|
|
@ -869,9 +872,6 @@ impl EmulatorClient {
|
|||
pub fn emulator_state(&self) -> EmulatorState {
|
||||
self.state.load(Ordering::Acquire)
|
||||
}
|
||||
pub fn is_audio_enabled(&self, sim_id: SimId) -> bool {
|
||||
self.audio_on[sim_id.to_index()].load(Ordering::Acquire)
|
||||
}
|
||||
pub fn are_sims_linked(&self) -> bool {
|
||||
self.linked.load(Ordering::Acquire)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,8 +12,11 @@ use tracing::error;
|
|||
use tracing_subscriber::{EnvFilter, Layer, layer::SubscriberExt, util::SubscriberInitExt};
|
||||
use winit::event_loop::{ControlFlow, EventLoop};
|
||||
|
||||
use crate::{config::SimConfig, emulator::SimId, persistence::Persistence};
|
||||
|
||||
mod app;
|
||||
mod audio;
|
||||
mod config;
|
||||
mod controller;
|
||||
mod emulator;
|
||||
mod gdbserver;
|
||||
|
|
@ -100,6 +103,8 @@ fn main() -> Result<()> {
|
|||
|
||||
let args = Args::parse();
|
||||
|
||||
let persistence = Persistence::new();
|
||||
|
||||
let (mut builder, client) = EmulatorBuilder::new();
|
||||
if let Some(path) = &args.rom {
|
||||
builder = builder.with_rom(path);
|
||||
|
|
@ -113,6 +118,9 @@ fn main() -> Result<()> {
|
|||
if args.profile {
|
||||
builder = builder.start_paused(true)
|
||||
}
|
||||
let p1_audio_on = SimConfig::load(&persistence, SimId::Player1).audio_enabled;
|
||||
let p2_audio_on = SimConfig::load(&persistence, SimId::Player2).audio_enabled;
|
||||
builder = builder.with_audio_on(p1_audio_on, p2_audio_on);
|
||||
|
||||
ThreadBuilder::default()
|
||||
.name("Emulator".to_owned())
|
||||
|
|
@ -134,6 +142,7 @@ fn main() -> Result<()> {
|
|||
event_loop.run_app(&mut Application::new(
|
||||
client,
|
||||
proxy,
|
||||
persistence,
|
||||
args.debug_port,
|
||||
args.profile,
|
||||
))?;
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ use std::sync::Arc;
|
|||
pub use about::AboutWindow;
|
||||
use egui::{Context, ViewportBuilder, ViewportId};
|
||||
pub use game::GameWindow;
|
||||
pub use game_screen::DisplayMode;
|
||||
pub use gdb::GdbServerWindow;
|
||||
pub use hotkeys::HotkeysWindow;
|
||||
pub use input::InputWindow;
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ use std::{
|
|||
|
||||
use crate::{
|
||||
app::UserEvent,
|
||||
config::{COLOR_PRESETS, SimConfig},
|
||||
emulator::{EmulatorClient, EmulatorCommand, EmulatorState, SimId, SimState},
|
||||
input::{Command, ShortcutProvider},
|
||||
persistence::Persistence,
|
||||
|
|
@ -16,7 +17,6 @@ use egui::{
|
|||
ViewportBuilder, ViewportCommand, ViewportId, Window,
|
||||
};
|
||||
use egui_notify::{Anchor, Toast, Toasts};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use winit::event_loop::EventLoopProxy;
|
||||
|
||||
use super::{
|
||||
|
|
@ -25,28 +25,13 @@ use super::{
|
|||
utils::UiExt as _,
|
||||
};
|
||||
|
||||
const COLOR_PRESETS: [[Color32; 2]; 3] = [
|
||||
[
|
||||
Color32::from_rgb(0xff, 0x00, 0x00),
|
||||
Color32::from_rgb(0x00, 0xc6, 0xf0),
|
||||
],
|
||||
[
|
||||
Color32::from_rgb(0x00, 0xb4, 0x00),
|
||||
Color32::from_rgb(0xc8, 0x00, 0xff),
|
||||
],
|
||||
[
|
||||
Color32::from_rgb(0xb4, 0x9b, 0x00),
|
||||
Color32::from_rgb(0x00, 0x00, 0xff),
|
||||
],
|
||||
];
|
||||
|
||||
pub struct GameWindow {
|
||||
client: EmulatorClient,
|
||||
proxy: EventLoopProxy<UserEvent>,
|
||||
persistence: Persistence,
|
||||
shortcuts: ShortcutProvider,
|
||||
sim_id: SimId,
|
||||
config: GameConfig,
|
||||
config: SimConfig,
|
||||
toasts: Toasts,
|
||||
screen: Option<GameScreen>,
|
||||
messages: Option<mpsc::Receiver<Toast>>,
|
||||
|
|
@ -62,7 +47,7 @@ impl GameWindow {
|
|||
shortcuts: ShortcutProvider,
|
||||
sim_id: SimId,
|
||||
) -> Self {
|
||||
let config = load_config(&persistence, sim_id);
|
||||
let config = SimConfig::load(&persistence, sim_id);
|
||||
let toasts = Toasts::new()
|
||||
.with_anchor(Anchor::BottomLeft)
|
||||
.with_margin((10.0, 10.0).into())
|
||||
|
|
@ -410,15 +395,15 @@ impl GameWindow {
|
|||
});
|
||||
});
|
||||
ui.menu_button("Audio", |ui| {
|
||||
let p1_enabled = self.client.is_audio_enabled(SimId::Player1);
|
||||
let p2_enabled = self.client.is_audio_enabled(SimId::Player2);
|
||||
if ui.selectable_button(p1_enabled, "Player 1").clicked() {
|
||||
self.client
|
||||
.send_command(EmulatorCommand::SetAudioEnabled(!p1_enabled, p2_enabled));
|
||||
}
|
||||
if ui.selectable_button(p2_enabled, "Player 2").clicked() {
|
||||
self.client
|
||||
.send_command(EmulatorCommand::SetAudioEnabled(p1_enabled, !p2_enabled));
|
||||
if ui
|
||||
.selectable_button(self.config.audio_enabled, "Enabled")
|
||||
.clicked()
|
||||
{
|
||||
self.update_config(|c| c.audio_enabled = !c.audio_enabled);
|
||||
self.client.send_command(EmulatorCommand::SetAudioEnabled(
|
||||
self.sim_id,
|
||||
self.config.audio_enabled,
|
||||
));
|
||||
}
|
||||
});
|
||||
ui.menu_button("Input", |ui| {
|
||||
|
|
@ -460,13 +445,11 @@ impl GameWindow {
|
|||
}
|
||||
}
|
||||
|
||||
fn update_config(&mut self, update: impl FnOnce(&mut GameConfig)) {
|
||||
fn update_config(&mut self, update: impl FnOnce(&mut SimConfig)) {
|
||||
let mut new_config = self.config.clone();
|
||||
update(&mut new_config);
|
||||
if self.config != new_config {
|
||||
let _ = self
|
||||
.persistence
|
||||
.save_config(config_filename(self.sim_id), &new_config);
|
||||
let _ = new_config.save(&self.persistence, self.sim_id);
|
||||
}
|
||||
self.config = new_config;
|
||||
}
|
||||
|
|
@ -480,24 +463,6 @@ impl GameWindow {
|
|||
}
|
||||
}
|
||||
|
||||
fn config_filename(sim_id: SimId) -> &'static str {
|
||||
match sim_id {
|
||||
SimId::Player1 => "config_p1",
|
||||
SimId::Player2 => "config_p2",
|
||||
}
|
||||
}
|
||||
|
||||
fn load_config(persistence: &Persistence, sim_id: SimId) -> GameConfig {
|
||||
if let Ok(config) = persistence.load_config(config_filename(sim_id)) {
|
||||
return config;
|
||||
}
|
||||
GameConfig {
|
||||
display_mode: DisplayMode::Anaglyph,
|
||||
colors: COLOR_PRESETS[0],
|
||||
dimensions: DisplayMode::Anaglyph.proportions() + Vec2::new(0.0, 22.0),
|
||||
}
|
||||
}
|
||||
|
||||
impl AppWindow for GameWindow {
|
||||
fn viewport_id(&self) -> ViewportId {
|
||||
match self.sim_id {
|
||||
|
|
@ -580,10 +545,3 @@ struct ColorPickerState {
|
|||
just_opened: bool,
|
||||
unpause_on_close: bool,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, PartialEq, Eq)]
|
||||
struct GameConfig {
|
||||
display_mode: DisplayMode,
|
||||
colors: [Color32; 2],
|
||||
dimensions: Vec2,
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue