feat: implement cartridge saving
Implemented for MBC1, MBC2, MBC3 and MBC5
This commit is contained in:
parent
e1fe00ab64
commit
ce121864d2
|
@ -592,6 +592,27 @@ dependencies = [
|
||||||
"syn",
|
"syn",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "directories-next"
|
||||||
|
version = "2.0.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "339ee130d97a610ea5a5872d2bbb130fdf68884ff09d3028b81bec8a1ac23bbc"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if 1.0.0",
|
||||||
|
"dirs-sys-next",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "dirs-sys-next"
|
||||||
|
version = "0.1.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
"redox_users",
|
||||||
|
"winapi",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "discard"
|
name = "discard"
|
||||||
version = "1.0.4"
|
version = "1.0.4"
|
||||||
|
@ -671,6 +692,7 @@ dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"bitfield",
|
"bitfield",
|
||||||
"clap",
|
"clap",
|
||||||
|
"directories-next",
|
||||||
"gilrs",
|
"gilrs",
|
||||||
"pixels",
|
"pixels",
|
||||||
"rodio",
|
"rodio",
|
||||||
|
@ -679,6 +701,17 @@ dependencies = [
|
||||||
"winit_input_helper",
|
"winit_input_helper",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "getrandom"
|
||||||
|
version = "0.2.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7fcd999463524c52659517fe2cea98493cfe485d10565e7b0fb07dbba7ad2753"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if 1.0.0",
|
||||||
|
"libc",
|
||||||
|
"wasi",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "gilrs"
|
name = "gilrs"
|
||||||
version = "0.8.1"
|
version = "0.8.1"
|
||||||
|
@ -1493,6 +1526,16 @@ dependencies = [
|
||||||
"bitflags",
|
"bitflags",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "redox_users"
|
||||||
|
version = "0.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "528532f3d801c87aec9def2add9ca802fe569e44a544afe633765267840abe64"
|
||||||
|
dependencies = [
|
||||||
|
"getrandom",
|
||||||
|
"redox_syscall",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "regex"
|
name = "regex"
|
||||||
version = "1.5.4"
|
version = "1.5.4"
|
||||||
|
@ -1916,6 +1959,12 @@ dependencies = [
|
||||||
"winapi-util",
|
"winapi-util",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wasi"
|
||||||
|
version = "0.10.2+wasi-snapshot-preview1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasm-bindgen"
|
name = "wasm-bindgen"
|
||||||
version = "0.2.77"
|
version = "0.2.77"
|
||||||
|
|
|
@ -17,6 +17,7 @@ winit = "^0.25"
|
||||||
winit_input_helper = "^0.10"
|
winit_input_helper = "^0.10"
|
||||||
rodio = "^0.14"
|
rodio = "^0.14"
|
||||||
rtrb = "^0.1.4"
|
rtrb = "^0.1.4"
|
||||||
|
directories-next = "2.0.0"
|
||||||
|
|
||||||
[profile.release]
|
[profile.release]
|
||||||
debug = true
|
debug = true
|
||||||
|
|
10
src/bus.rs
10
src/bus.rs
|
@ -90,6 +90,16 @@ impl Bus {
|
||||||
pub(crate) fn joyp_mut(&mut self) -> &mut Joypad {
|
pub(crate) fn joyp_mut(&mut self) -> &mut Joypad {
|
||||||
&mut self.joypad
|
&mut self.joypad
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub(crate) fn cart(&self) -> Option<&Cartridge> {
|
||||||
|
self.cart.as_ref()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub(crate) fn cart_mut(&mut self) -> Option<&mut Cartridge> {
|
||||||
|
self.cart.as_mut()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Bus {
|
impl Bus {
|
||||||
|
|
153
src/cartridge.rs
153
src/cartridge.rs
|
@ -24,6 +24,14 @@ impl Cartridge {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn ext_ram(&self) -> Option<&[u8]> {
|
||||||
|
self.mbc.ext_ram()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn write_ext_ram(&mut self, memory: Vec<u8>) {
|
||||||
|
self.mbc.write_ext_ram(memory)
|
||||||
|
}
|
||||||
|
|
||||||
fn detect_mbc(memory: &[u8]) -> Box<dyn MBCIo> {
|
fn detect_mbc(memory: &[u8]) -> Box<dyn MBCIo> {
|
||||||
let ram_size = Self::detect_ram_info(memory);
|
let ram_size = Self::detect_ram_info(memory);
|
||||||
let rom_size = Self::detect_rom_info(memory);
|
let rom_size = Self::detect_rom_info(memory);
|
||||||
|
@ -38,13 +46,13 @@ impl Cartridge {
|
||||||
match mbc_kind {
|
match mbc_kind {
|
||||||
MBCKind::None => Box::new(NoMBC),
|
MBCKind::None => Box::new(NoMBC),
|
||||||
MBCKind::MBC1 => Box::new(MBC1::new(ram_size, rom_size)),
|
MBCKind::MBC1 => Box::new(MBC1::new(ram_size, rom_size)),
|
||||||
MBCKind::MBC1WithBattery => Box::new(MBC1::new(ram_size, rom_size)), // TODO: Implement Saving
|
MBCKind::MBC1WithBattery => Box::new(MBC1::with_battery(ram_size, rom_size)), // TODO: Implement Saving
|
||||||
MBCKind::MBC2 => Box::new(MBC2::new(rom_cap)),
|
MBCKind::MBC2 => Box::new(MBC2::new(rom_cap)),
|
||||||
MBCKind::MBC2WithBattery => Box::new(MBC2::new(rom_cap)), // TODO: Implement Saving
|
MBCKind::MBC2WithBattery => Box::new(MBC2::with_battery(rom_cap)), // TODO: Implement Saving
|
||||||
MBCKind::MBC3 => Box::new(MBC3::new(ram_cap)),
|
MBCKind::MBC3 => Box::new(MBC3::new(ram_cap)),
|
||||||
MBCKind::MBC3WithBattery => Box::new(MBC3::new(ram_cap)), // TODO: Implement Saving
|
MBCKind::MBC3WithBattery => Box::new(MBC3::with_battery(ram_cap)), // TODO: Implement Saving
|
||||||
MBCKind::MBC5 => Box::new(MBC5::new(ram_cap, rom_cap)),
|
MBCKind::MBC5 => Box::new(MBC5::new(ram_cap, rom_cap)),
|
||||||
MBCKind::MBC5WithBattery => Box::new(MBC5::new(ram_cap, rom_cap)), // TDO: Implement Saving
|
MBCKind::MBC5WithBattery => Box::new(MBC5::with_battery(ram_cap, rom_cap)), // TDO: Implement Saving
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -117,6 +125,8 @@ struct MBC1 {
|
||||||
memory: Vec<u8>,
|
memory: Vec<u8>,
|
||||||
rom_size: RomSize,
|
rom_size: RomSize,
|
||||||
mem_enabled: bool,
|
mem_enabled: bool,
|
||||||
|
|
||||||
|
has_battery: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MBC1 {
|
impl MBC1 {
|
||||||
|
@ -129,6 +139,20 @@ impl MBC1 {
|
||||||
ram_bank: Default::default(),
|
ram_bank: Default::default(),
|
||||||
mode: Default::default(),
|
mode: Default::default(),
|
||||||
mem_enabled: Default::default(),
|
mem_enabled: Default::default(),
|
||||||
|
has_battery: Default::default(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn with_battery(ram_size: RamSize, rom_size: RomSize) -> Self {
|
||||||
|
Self {
|
||||||
|
rom_bank: 0x01,
|
||||||
|
memory: vec![0; ram_size.capacity() as usize],
|
||||||
|
ram_size,
|
||||||
|
rom_size,
|
||||||
|
ram_bank: Default::default(),
|
||||||
|
mode: Default::default(),
|
||||||
|
mem_enabled: Default::default(),
|
||||||
|
has_battery: true,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -197,6 +221,21 @@ impl MBC1 {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Savable for MBC1 {
|
||||||
|
fn ext_ram(&self) -> Option<&[u8]> {
|
||||||
|
match self.has_battery {
|
||||||
|
true => Some(&self.memory),
|
||||||
|
false => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write_ext_ram(&mut self, memory: Vec<u8>) {
|
||||||
|
if self.has_battery {
|
||||||
|
self.memory.copy_from_slice(&memory);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl MBCIo for MBC1 {
|
impl MBCIo for MBC1 {
|
||||||
fn handle_read(&self, addr: u16) -> MBCResult {
|
fn handle_read(&self, addr: u16) -> MBCResult {
|
||||||
use MBCResult::*;
|
use MBCResult::*;
|
||||||
|
@ -256,6 +295,8 @@ struct MBC3 {
|
||||||
|
|
||||||
// RTC Data Latch Previous Write
|
// RTC Data Latch Previous Write
|
||||||
prev_latch_write: Option<u8>,
|
prev_latch_write: Option<u8>,
|
||||||
|
|
||||||
|
has_battery: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MBC3 {
|
impl MBC3 {
|
||||||
|
@ -267,6 +308,34 @@ impl MBC3 {
|
||||||
devs_enabled: Default::default(),
|
devs_enabled: Default::default(),
|
||||||
mapped: Default::default(),
|
mapped: Default::default(),
|
||||||
prev_latch_write: Default::default(),
|
prev_latch_write: Default::default(),
|
||||||
|
has_battery: Default::default(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn with_battery(ram_cap: usize) -> Self {
|
||||||
|
Self {
|
||||||
|
memory: vec![0; ram_cap],
|
||||||
|
rom_bank: Default::default(),
|
||||||
|
ram_bank: Default::default(),
|
||||||
|
devs_enabled: Default::default(),
|
||||||
|
mapped: Default::default(),
|
||||||
|
prev_latch_write: Default::default(),
|
||||||
|
has_battery: true,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Savable for MBC3 {
|
||||||
|
fn ext_ram(&self) -> Option<&[u8]> {
|
||||||
|
match self.has_battery {
|
||||||
|
true => Some(&self.memory),
|
||||||
|
false => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write_ext_ram(&mut self, memory: Vec<u8>) {
|
||||||
|
if self.has_battery {
|
||||||
|
self.memory.copy_from_slice(&memory);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -342,9 +411,10 @@ struct MBC5 {
|
||||||
ram_bank: u8,
|
ram_bank: u8,
|
||||||
|
|
||||||
rom_cap: usize,
|
rom_cap: usize,
|
||||||
|
|
||||||
memory: Vec<u8>,
|
memory: Vec<u8>,
|
||||||
mem_enabled: bool,
|
mem_enabled: bool,
|
||||||
|
|
||||||
|
has_battery: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MBC5 {
|
impl MBC5 {
|
||||||
|
@ -355,6 +425,18 @@ impl MBC5 {
|
||||||
rom_cap,
|
rom_cap,
|
||||||
ram_bank: Default::default(),
|
ram_bank: Default::default(),
|
||||||
mem_enabled: Default::default(),
|
mem_enabled: Default::default(),
|
||||||
|
has_battery: Default::default(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn with_battery(ram_cap: usize, rom_cap: usize) -> Self {
|
||||||
|
Self {
|
||||||
|
rom_bank: 0x01,
|
||||||
|
memory: vec![0; ram_cap],
|
||||||
|
rom_cap,
|
||||||
|
ram_bank: Default::default(),
|
||||||
|
mem_enabled: Default::default(),
|
||||||
|
has_battery: true,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -363,6 +445,21 @@ impl MBC5 {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Savable for MBC5 {
|
||||||
|
fn ext_ram(&self) -> Option<&[u8]> {
|
||||||
|
match self.has_battery {
|
||||||
|
true => Some(&self.memory),
|
||||||
|
false => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write_ext_ram(&mut self, memory: Vec<u8>) {
|
||||||
|
if self.has_battery {
|
||||||
|
self.memory.copy_from_slice(&memory);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl MBCIo for MBC5 {
|
impl MBCIo for MBC5 {
|
||||||
fn handle_read(&self, addr: u16) -> MBCResult {
|
fn handle_read(&self, addr: u16) -> MBCResult {
|
||||||
use MBCResult::*;
|
use MBCResult::*;
|
||||||
|
@ -401,6 +498,7 @@ struct MBC2 {
|
||||||
mem_enabled: bool,
|
mem_enabled: bool,
|
||||||
|
|
||||||
rom_cap: usize,
|
rom_cap: usize,
|
||||||
|
has_battery: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MBC2 {
|
impl MBC2 {
|
||||||
|
@ -410,8 +508,19 @@ impl MBC2 {
|
||||||
Self {
|
Self {
|
||||||
rom_bank: 0x01,
|
rom_bank: 0x01,
|
||||||
memory: Box::new([0; Self::RAM_SIZE]),
|
memory: Box::new([0; Self::RAM_SIZE]),
|
||||||
mem_enabled: Default::default(),
|
|
||||||
rom_cap,
|
rom_cap,
|
||||||
|
mem_enabled: Default::default(),
|
||||||
|
has_battery: Default::default(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn with_battery(rom_cap: usize) -> Self {
|
||||||
|
Self {
|
||||||
|
rom_bank: 0x01,
|
||||||
|
memory: Box::new([0; Self::RAM_SIZE]),
|
||||||
|
rom_cap,
|
||||||
|
mem_enabled: Default::default(),
|
||||||
|
has_battery: true,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -420,6 +529,21 @@ impl MBC2 {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Savable for MBC2 {
|
||||||
|
fn ext_ram(&self) -> Option<&[u8]> {
|
||||||
|
match self.has_battery {
|
||||||
|
true => Some(self.memory.as_ref()),
|
||||||
|
false => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write_ext_ram(&mut self, memory: Vec<u8>) {
|
||||||
|
if self.has_battery {
|
||||||
|
self.memory.copy_from_slice(&memory);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl MBCIo for MBC2 {
|
impl MBCIo for MBC2 {
|
||||||
fn handle_read(&self, addr: u16) -> MBCResult {
|
fn handle_read(&self, addr: u16) -> MBCResult {
|
||||||
use MBCResult::*;
|
use MBCResult::*;
|
||||||
|
@ -457,6 +581,16 @@ impl MBCIo for MBC2 {
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
struct NoMBC;
|
struct NoMBC;
|
||||||
|
|
||||||
|
impl Savable for NoMBC {
|
||||||
|
fn ext_ram(&self) -> Option<&[u8]> {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write_ext_ram(&mut self, _memory: Vec<u8>) {
|
||||||
|
// Nothing Happens Here
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl MBCIo for NoMBC {
|
impl MBCIo for NoMBC {
|
||||||
fn handle_read(&self, addr: u16) -> MBCResult {
|
fn handle_read(&self, addr: u16) -> MBCResult {
|
||||||
MBCResult::Address(addr as usize)
|
MBCResult::Address(addr as usize)
|
||||||
|
@ -467,7 +601,7 @@ impl MBCIo for NoMBC {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
trait MBCIo {
|
trait MBCIo: Savable {
|
||||||
fn handle_read(&self, addr: u16) -> MBCResult;
|
fn handle_read(&self, addr: u16) -> MBCResult;
|
||||||
fn handle_write(&mut self, addr: u16, byte: u8);
|
fn handle_write(&mut self, addr: u16, byte: u8);
|
||||||
}
|
}
|
||||||
|
@ -607,3 +741,8 @@ impl Default for Box<dyn MBCIo> {
|
||||||
Box::new(NoMBC)
|
Box::new(NoMBC)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
trait Savable {
|
||||||
|
fn ext_ram(&self) -> Option<&[u8]>;
|
||||||
|
fn write_ext_ram(&mut self, memory: Vec<u8>);
|
||||||
|
}
|
||||||
|
|
51
src/emu.rs
51
src/emu.rs
|
@ -2,7 +2,11 @@ use crate::apu::gen::SampleProducer;
|
||||||
use crate::cpu::Cpu;
|
use crate::cpu::Cpu;
|
||||||
use crate::joypad::{self, Joypad};
|
use crate::joypad::{self, Joypad};
|
||||||
use crate::{Cycle, GB_HEIGHT, GB_WIDTH};
|
use crate::{Cycle, GB_HEIGHT, GB_WIDTH};
|
||||||
|
use clap::crate_name;
|
||||||
use gilrs::Gilrs;
|
use gilrs::Gilrs;
|
||||||
|
use std::fs::File;
|
||||||
|
use std::io::{Read, Write};
|
||||||
|
use std::path::PathBuf;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
use winit_input_helper::WinitInputHelper;
|
use winit_input_helper::WinitInputHelper;
|
||||||
|
|
||||||
|
@ -50,7 +54,7 @@ impl Emulator {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn load_cart(&mut self, rom: Vec<u8>) {
|
fn load_cart(&mut self, rom: Vec<u8>) {
|
||||||
self.cpu.bus_mut().load_cart(rom)
|
self.cpu.bus_mut().load_cart(rom);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -65,6 +69,51 @@ impl Emulator {
|
||||||
pub fn title(&self) -> &str {
|
pub fn title(&self) -> &str {
|
||||||
self.cpu.bus().cart_title().unwrap_or(DEFAULT_TITLE)
|
self.cpu.bus().cart_title().unwrap_or(DEFAULT_TITLE)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn try_write_sav(&self) -> std::io::Result<()> {
|
||||||
|
if let Some(ext_ram) = self.cpu.bus().cart().map(|c| c.ext_ram()).flatten() {
|
||||||
|
if let Some(title) = self.cpu.bus().cart_title() {
|
||||||
|
let mut save_path = Self::data_path().unwrap_or_else(|| PathBuf::from("."));
|
||||||
|
save_path.push(title);
|
||||||
|
save_path.set_extension("sav");
|
||||||
|
|
||||||
|
let mut file = File::create(save_path)?;
|
||||||
|
file.write_all(ext_ram)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn try_load_sav(&mut self) -> std::io::Result<()> {
|
||||||
|
if let Some(cart) = self.cpu.bus_mut().cart_mut() {
|
||||||
|
if let Some(title) = cart.title() {
|
||||||
|
let mut save_path = Self::data_path().unwrap_or_else(|| PathBuf::from("."));
|
||||||
|
save_path.push(title);
|
||||||
|
save_path.set_extension("sav");
|
||||||
|
|
||||||
|
if let Ok(mut file) = File::open(save_path) {
|
||||||
|
let mut memory = Vec::new();
|
||||||
|
file.read_to_end(&mut memory)?;
|
||||||
|
|
||||||
|
cart.write_ext_ram(memory);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn data_path() -> Option<PathBuf> {
|
||||||
|
match directories_next::ProjectDirs::from("dev", "musuka", crate_name!()) {
|
||||||
|
Some(dirs) => {
|
||||||
|
let data_local = dirs.data_local_dir();
|
||||||
|
std::fs::create_dir_all(data_local).ok()?;
|
||||||
|
Some(data_local.to_path_buf())
|
||||||
|
}
|
||||||
|
None => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub mod build {
|
pub mod build {
|
||||||
|
|
|
@ -49,6 +49,9 @@ fn main() -> Result<()> {
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut emu = emu_build.finish();
|
let mut emu = emu_build.finish();
|
||||||
|
|
||||||
|
// Load Save file if it exists
|
||||||
|
emu.try_load_sav().expect("Load save if exists");
|
||||||
let rom_title = emu.title();
|
let rom_title = emu.title();
|
||||||
|
|
||||||
let mut gamepad = Gilrs::new().expect("Initialize Controller Support");
|
let mut gamepad = Gilrs::new().expect("Initialize Controller Support");
|
||||||
|
@ -96,6 +99,8 @@ fn main() -> Result<()> {
|
||||||
.map_err(|e| anyhow!("pixels.render() failed: {}", e))
|
.map_err(|e| anyhow!("pixels.render() failed: {}", e))
|
||||||
.is_err()
|
.is_err()
|
||||||
{
|
{
|
||||||
|
emu.try_write_sav().expect("Write game save if need be");
|
||||||
|
|
||||||
*control_flow = ControlFlow::Exit;
|
*control_flow = ControlFlow::Exit;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -103,6 +108,8 @@ fn main() -> Result<()> {
|
||||||
|
|
||||||
if input.update(&event) {
|
if input.update(&event) {
|
||||||
if input.key_pressed(VirtualKeyCode::Escape) || input.quit() {
|
if input.key_pressed(VirtualKeyCode::Escape) || input.quit() {
|
||||||
|
emu.try_write_sav().expect("Write game save if need be");
|
||||||
|
|
||||||
*control_flow = ControlFlow::Exit;
|
*control_flow = ControlFlow::Exit;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue