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