chirp-imgui: Argument parsing + colors in Settings
This commit is contained in:
parent
dcbdd1383d
commit
861020a8ab
52
src/bin/chirp-imgui/args.rs
Normal file
52
src/bin/chirp-imgui/args.rs
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
//! Parses arguments into a struct
|
||||||
|
|
||||||
|
use std::path::PathBuf;
|
||||||
|
|
||||||
|
use super::Emulator;
|
||||||
|
use chirp::Mode;
|
||||||
|
use gumdrop::*;
|
||||||
|
|
||||||
|
/// Parses a hexadecimal string into a u16
|
||||||
|
fn parse_hex(value: &str) -> std::result::Result<u16, std::num::ParseIntError> {
|
||||||
|
u16::from_str_radix(value, 16)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Options, Hash)]
|
||||||
|
pub struct Arguments {
|
||||||
|
#[options(help = "Load a ROM to run on Chirp.", required, free)]
|
||||||
|
pub file: PathBuf,
|
||||||
|
#[options(help = "Print this help message.")]
|
||||||
|
help: bool,
|
||||||
|
#[options(help = "Enable debug mode at startup.")]
|
||||||
|
pub debug: bool,
|
||||||
|
#[options(help = "Enable pause mode at startup.")]
|
||||||
|
pub pause: bool,
|
||||||
|
#[options(help = "Set the instructions-per-frame rate.")]
|
||||||
|
pub speed: Option<usize>,
|
||||||
|
// #[options(help = "Enable performance benchmarking on stderr (requires -S)")]
|
||||||
|
// pub perf: bool,
|
||||||
|
#[options(help = "Run in (Chip8, SChip, XOChip) mode.")]
|
||||||
|
pub mode: Option<Mode>,
|
||||||
|
#[options(help = "Set the target framerate.", default = "60", meta = "FR")]
|
||||||
|
pub frame_rate: u64,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Arguments {
|
||||||
|
pub fn parse() -> Arguments {
|
||||||
|
Arguments::parse_args_default_or_exit()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Arguments> for Emulator {
|
||||||
|
fn from(value: Arguments) -> Self {
|
||||||
|
let mut emu = Emulator::new(value.speed.unwrap_or(10), value.file);
|
||||||
|
if let Some(mode) = value.mode {
|
||||||
|
emu.set_quirks(mode.into());
|
||||||
|
}
|
||||||
|
if value.pause {
|
||||||
|
emu.pause()
|
||||||
|
}
|
||||||
|
emu.set_disasm(value.debug);
|
||||||
|
emu
|
||||||
|
}
|
||||||
|
}
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
use super::Drawable;
|
use super::Drawable;
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
#[derive(Clone, Debug, PartialEq, PartialOrd)]
|
||||||
pub struct Menubar {
|
pub struct Menubar {
|
||||||
pub(super) active: bool,
|
pub(super) active: bool,
|
||||||
pub file: File,
|
pub file: File,
|
||||||
@ -86,12 +86,12 @@ impl Drawable for Help {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
#[derive(Clone, Debug, Default, PartialEq, PartialOrd)]
|
||||||
pub struct Settings {
|
pub struct Settings {
|
||||||
pub(super) target_ipf: usize,
|
pub(super) target_ipf: usize,
|
||||||
pub(super) quirks: chirp::Quirks,
|
pub(super) quirks: chirp::Quirks,
|
||||||
pub(super) mode_index: usize,
|
pub(super) mode_index: usize,
|
||||||
pub(super) colors: [[u8; 4]; 2],
|
pub(super) colors: [[f32; 4]; 2],
|
||||||
pub(super) applied: bool,
|
pub(super) applied: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -100,6 +100,12 @@ impl Drawable for Settings {
|
|||||||
self.applied = false;
|
self.applied = false;
|
||||||
ui.menu("Settings", || {
|
ui.menu("Settings", || {
|
||||||
use chirp::Mode::*;
|
use chirp::Mode::*;
|
||||||
|
ui.menu("Foreground Color", || {
|
||||||
|
self.applied |= ui.color_picker4("", &mut self.colors[0])
|
||||||
|
});
|
||||||
|
ui.menu("Background Color", || {
|
||||||
|
self.applied |= ui.color_picker4("", &mut self.colors[1])
|
||||||
|
});
|
||||||
const MODES: [chirp::Mode; 3] = [Chip8, SChip, XOChip];
|
const MODES: [chirp::Mode; 3] = [Chip8, SChip, XOChip];
|
||||||
if ui.combo_simple_string("Mode", &mut self.mode_index, &MODES) {
|
if ui.combo_simple_string("Mode", &mut self.mode_index, &MODES) {
|
||||||
self.quirks = MODES[self.mode_index].into();
|
self.quirks = MODES[self.mode_index].into();
|
||||||
@ -115,7 +121,7 @@ impl Drawable for Settings {
|
|||||||
| ui.checkbox("Screen wraps at edge", &mut self.quirks.screen_wrap)
|
| ui.checkbox("Screen wraps at edge", &mut self.quirks.screen_wrap)
|
||||||
| ui.checkbox("Shift ops ignore vY", &mut self.quirks.shift)
|
| ui.checkbox("Shift ops ignore vY", &mut self.quirks.shift)
|
||||||
| ui.checkbox("Jumps behave eratically", &mut self.quirks.stupid_jumps)
|
| ui.checkbox("Jumps behave eratically", &mut self.quirks.stupid_jumps)
|
||||||
}
|
};
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -127,7 +133,32 @@ impl Settings {
|
|||||||
pub fn quirks(&mut self) -> &mut chirp::Quirks {
|
pub fn quirks(&mut self) -> &mut chirp::Quirks {
|
||||||
&mut self.quirks
|
&mut self.quirks
|
||||||
}
|
}
|
||||||
pub fn applied(&mut self) -> Option<(usize, chirp::Quirks)> {
|
pub fn set_mode(&mut self, mode: chirp::Mode) {
|
||||||
self.applied.then_some((self.target_ipf, self.quirks))
|
self.mode_index = mode as usize;
|
||||||
|
}
|
||||||
|
pub fn set_color(&mut self, fg: &[u8; 4], bg: &[u8; 4]) {
|
||||||
|
for (idx, component) in fg.iter().enumerate() {
|
||||||
|
self.colors[0][idx] = *component as f32 / 255.0;
|
||||||
|
}
|
||||||
|
for (idx, component) in bg.iter().enumerate() {
|
||||||
|
self.colors[1][idx] = *component as f32 / 255.0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn applied(&mut self) -> Option<(usize, chirp::Quirks, [u8; 4], [u8; 4])> {
|
||||||
|
let (fg, bg) = (self.colors[0], self.colors[1]);
|
||||||
|
let fg = [
|
||||||
|
(fg[0] * 255.0) as u8,
|
||||||
|
(fg[1] * 255.0) as u8,
|
||||||
|
(fg[2] * 255.0) as u8,
|
||||||
|
(fg[3] * 255.0) as u8,
|
||||||
|
];
|
||||||
|
let bg = [
|
||||||
|
(bg[0] * 255.0) as u8,
|
||||||
|
(bg[1] * 255.0) as u8,
|
||||||
|
(bg[2] * 255.0) as u8,
|
||||||
|
(bg[3] * 255.0) as u8,
|
||||||
|
];
|
||||||
|
self.applied
|
||||||
|
.then_some((self.target_ipf, self.quirks, fg, bg))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,10 +2,12 @@
|
|||||||
#![deny(clippy::all)]
|
#![deny(clippy::all)]
|
||||||
#![allow(dead_code)] // TODO: finish writing the code
|
#![allow(dead_code)] // TODO: finish writing the code
|
||||||
|
|
||||||
|
mod args;
|
||||||
mod emu;
|
mod emu;
|
||||||
mod error;
|
mod error;
|
||||||
mod gui;
|
mod gui;
|
||||||
|
|
||||||
|
use crate::args::Arguments;
|
||||||
use crate::emu::*;
|
use crate::emu::*;
|
||||||
use crate::gui::*;
|
use crate::gui::*;
|
||||||
use pixels::{Pixels, SurfaceTexture};
|
use pixels::{Pixels, SurfaceTexture};
|
||||||
@ -28,17 +30,11 @@ struct Application {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn main() -> Result<(), error::Error> {
|
fn main() -> Result<(), error::Error> {
|
||||||
let rom_path;
|
let args = Arguments::parse();
|
||||||
if let Some(path) = std::env::args().nth(1) {
|
|
||||||
rom_path = path;
|
|
||||||
} else {
|
|
||||||
panic!("Supply a rom!");
|
|
||||||
}
|
|
||||||
|
|
||||||
let event_loop = EventLoop::new();
|
let event_loop = EventLoop::new();
|
||||||
let mut input = WinitInputHelper::new();
|
let mut input = WinitInputHelper::new();
|
||||||
|
|
||||||
let size = LogicalSize::new(128 * 6, 64 * 6);
|
let size = LogicalSize::new(128 * 8, 64 * 8);
|
||||||
let window = WindowBuilder::new()
|
let window = WindowBuilder::new()
|
||||||
.with_title("Chirp")
|
.with_title("Chirp")
|
||||||
.with_inner_size(size)
|
.with_inner_size(size)
|
||||||
@ -52,13 +48,18 @@ fn main() -> Result<(), error::Error> {
|
|||||||
Pixels::new(128, 64, surface_texture)?
|
Pixels::new(128, 64, surface_texture)?
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut app = Application::new(
|
let mut gui = Gui::new(&window, &pixels);
|
||||||
Emulator::new(INIT_SPEED, rom_path),
|
|
||||||
Gui::new(&window, &pixels),
|
|
||||||
);
|
|
||||||
|
|
||||||
// set initial parameters
|
// set initial parameters
|
||||||
*app.gui.menubar.settings.target_ipf() = INIT_SPEED;
|
if let Some(mode) = args.mode {
|
||||||
|
gui.menubar.settings.set_mode(mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
gui.menubar.settings.set_color(FOREGROUND, BACKGROUND);
|
||||||
|
*gui.menubar.settings.target_ipf() = args.speed.unwrap_or(INIT_SPEED);
|
||||||
|
|
||||||
|
let mut app = Application::new(args.into(), gui);
|
||||||
|
|
||||||
|
// Copy quirks from the running Emulator, for consistency
|
||||||
*app.gui.menubar.settings.quirks() = app.emu.quirks();
|
*app.gui.menubar.settings.quirks() = app.emu.quirks();
|
||||||
|
|
||||||
// Run event loop
|
// Run event loop
|
||||||
@ -114,10 +115,10 @@ fn main() -> Result<(), error::Error> {
|
|||||||
state.emu.input(&input)?;
|
state.emu.input(&input)?;
|
||||||
|
|
||||||
// Apply settings
|
// Apply settings
|
||||||
if let Some((ipf, quirks)) = state.gui.menubar.settings.applied() {
|
if let Some((ipf, quirks, fg, bg)) = state.gui.menubar.settings.applied() {
|
||||||
state.emu.ipf = ipf;
|
state.emu.ipf = ipf;
|
||||||
state.emu.set_quirks(quirks);
|
state.emu.set_quirks(quirks);
|
||||||
println!("'A");
|
state.emu.colors = [fg, bg];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update the scale factor
|
// Update the scale factor
|
||||||
|
Loading…
Reference in New Issue
Block a user