Skip to content

Commit

Permalink
feat: basic dip switch functionality (#409)
Browse files Browse the repository at this point in the history
* show on console
* edit in frontend
  • Loading branch information
francisdb authored Dec 16, 2024
1 parent 2716c0c commit 8e106b1
Show file tree
Hide file tree
Showing 4 changed files with 258 additions and 23 deletions.
68 changes: 68 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ vpin = { version = "0.17.0" }
rust-ini = "0.21.1"
edit = "0.1.5"
jojodiff = "0.1.2"
pinmame-nvram = "0.3.3"

[dev-dependencies]
pretty_assertions = "1.4.1"
Expand Down
163 changes: 141 additions & 22 deletions src/frontend.rs
Original file line number Diff line number Diff line change
@@ -1,28 +1,28 @@
use std::collections::HashSet;
use std::{
fs::File,
io,
io::Write,
path::{Path, PathBuf},
process::{exit, ExitStatus},
};

use colored::Colorize;
use console::Emoji;
use dialoguer::theme::ColorfulTheme;
use dialoguer::{FuzzySelect, Input, Select};
use indicatif::{ProgressBar, ProgressStyle};
use is_executable::IsExecutable;

use crate::config::ResolvedConfig;
use crate::indexer::{IndexError, IndexedTable, Progress};
use crate::patcher::LineEndingsResult::{NoChanges, Unified};
use crate::patcher::{patch_vbs_file, unify_line_endings_vbs_file};
use crate::{
indexer, info_diff, info_edit, info_gather, open_editor, run_diff, script_diff,
confirm, indexer, info_diff, info_edit, info_gather, open_editor, run_diff, script_diff,
vpx::{extractvbs, vbs_path_for, ExtractResult},
DiffColor, ProgressBarProgress,
};
use colored::Colorize;
use console::Emoji;
use dialoguer::theme::ColorfulTheme;
use dialoguer::{FuzzySelect, Input, MultiSelect, Select};
use indicatif::{ProgressBar, ProgressStyle};
use is_executable::IsExecutable;
use pinmame_nvram::dips::{get_all_dip_switches, set_dip_switches};
use std::collections::HashSet;
use std::fs::OpenOptions;
use std::{
fs::File,
io,
io::Write,
path::{Path, PathBuf},
process::{exit, ExitStatus},
};

const LAUNCH: Emoji = Emoji("🚀", "[launch]");
const CRASH: Emoji = Emoji("💥", "[crash]");
Expand All @@ -46,11 +46,12 @@ enum TableOption {
UnifyLineEndings,
ShowVBSDiff,
CreateVBSPatch,
// ClearNVRAM,
DIPSwitches,
NVRAMClear,
}

impl TableOption {
const ALL: [TableOption; 13] = [
const ALL: [TableOption; 15] = [
TableOption::Launch,
TableOption::LaunchFullscreen,
TableOption::LaunchWindowed,
Expand All @@ -64,7 +65,8 @@ impl TableOption {
TableOption::UnifyLineEndings,
TableOption::ShowVBSDiff,
TableOption::CreateVBSPatch,
// TableOption::ClearNVRAM,
TableOption::DIPSwitches,
TableOption::NVRAMClear,
];

fn from_index(index: usize) -> Option<TableOption> {
Expand All @@ -82,7 +84,8 @@ impl TableOption {
10 => Some(TableOption::UnifyLineEndings),
11 => Some(TableOption::ShowVBSDiff),
12 => Some(TableOption::CreateVBSPatch),
// 13 => Some(TableOption::ClearNVRAM),
13 => Some(TableOption::DIPSwitches),
14 => Some(TableOption::NVRAMClear),
_ => None,
}
}
Expand All @@ -102,7 +105,8 @@ impl TableOption {
TableOption::UnifyLineEndings => "VBScript > Unify line endings".to_string(),
TableOption::ShowVBSDiff => "VBScript > Diff".to_string(),
TableOption::CreateVBSPatch => "VBScript > Create patch file".to_string(),
// TableOption::ClearNVRAM => "Clear NVRAM".to_string(),
TableOption::DIPSwitches => "DIP Switches".to_string(),
TableOption::NVRAMClear => "NVRAM > Clear".to_string(),
}
}
}
Expand Down Expand Up @@ -412,10 +416,125 @@ fn table_menu(
prompt(msg.truecolor(255, 125, 0).to_string());
}
},
Some(TableOption::DIPSwitches) => {
if info.requires_pinmame {
let nvram = nvram_for_rom(info);
if let Some(nvram) = nvram {
// open file in read/write mode
match edit_dip_switches(nvram) {
Ok(_) => {
// ok
}
Err(err) => {
let msg = format!("Unable to edit DIP switches: {}", err);
prompt(msg.truecolor(255, 125, 0).to_string());
}
}
} else {
prompt(
"This table does not have an NVRAM file, try launching it once."
.to_string(),
);
}
} else {
prompt("This table is not using used PinMAME".to_string());
}
}
Some(TableOption::NVRAMClear) => {
clear_nvram(info);
}
None => (),
}
}

fn edit_dip_switches(nvram: PathBuf) -> io::Result<()> {
let mut nvram_file = OpenOptions::new().read(true).write(true).open(nvram)?;
let mut switches = get_all_dip_switches(&mut nvram_file)?;

let items = switches
.iter()
.map(|s| format!("DIP #{}", s.nr))
.collect::<Vec<String>>();

let defaults = switches.iter().map(|s| s.on).collect::<Vec<bool>>();

let help = "(<␣> selects, <⏎> saves, <esc/q> exits)"
.dimmed()
.to_string();
let prompt_string = format!("Toggle switches {}", help);
let selection = MultiSelect::with_theme(&ColorfulTheme::default())
.with_prompt(prompt_string)
.items(&items)
.defaults(&defaults)
.interact_opt()
.unwrap();

if let Some(selection) = selection {
// update the switches
switches.iter_mut().enumerate().for_each(|(i, s)| {
s.on = selection.contains(&i);
});

set_dip_switches(&mut nvram_file, &switches)?;
prompt("DIP switches updated".to_string());
}
Ok(())
}

fn clear_nvram(info: &IndexedTable) {
if info.requires_pinmame {
let nvram_file = nvram_for_rom(info);
if let Some(nvram_file) = nvram_file {
if nvram_file.exists() {
match confirm(
"This will remove the table NVRAM file and you will lose all settings / high scores!".to_string(),
"Are you sure?".to_string(),
) {
Ok(true) => {
match std::fs::remove_file(&nvram_file) {
Ok(_) => {
prompt(format!("NVRAM file {} removed", nvram_file.display()));
}
Err(err) => {
let msg = format!("Unable to remove NVRAM file: {}", err);
prompt(msg.truecolor(255, 125, 0).to_string());
}
}
}
Ok(false) => {
prompt("NVRAM file removal canceled.".to_string());
}
Err(err) => {
let msg = format!("Error during confirmation: {}", err);
prompt(msg.truecolor(255, 125, 0).to_string());
}
}
} else {
prompt(format!(
"NVRAM file {} does not exist",
nvram_file.display()
));
}
} else {
prompt("This table does not have an NVRAM file".to_string());
}
} else {
prompt("This table is not using used PinMAME".to_string());
}
}

/// Find the NVRAM file for a ROM, not checking if it exists
fn nvram_for_rom(info: &IndexedTable) -> Option<PathBuf> {
info.local_rom_path.as_ref().and_then(|rom_path| {
// ../nvram/[romname].nv
rom_path.parent().and_then(|p| p.parent()).and_then(|p| {
rom_path
.file_name()
.map(|file_name| p.join("nvram").join(file_name).with_extension("nv"))
})
})
}

fn prompt<S: Into<String>>(msg: S) {
Input::<String>::new()
.with_prompt(format!("{} - Press enter to continue.", msg.into()))
Expand Down
Loading

0 comments on commit 8e106b1

Please sign in to comment.