drag and drop working for save states
This commit is contained in:
parent
7f5a71cf07
commit
c7b331cec1
|
@ -23,7 +23,7 @@ ___________________
|
|||
-------------------
|
||||
Save state: F5
|
||||
Load state: F9
|
||||
(Only one save state at a time supported currently: saving a second time overwrites the first.)
|
||||
(Saving state a second time overwrites the first unless you copy/rename the `.dat` file. You can drag and drop any `.dat` file onto the window to load it.)
|
||||
```
|
||||
The code aims to follow the explanations from the [NES dev wiki](https://wiki.nesdev.com/w/index.php/NES_reference_guide) where possible, especially in the PPU, and the comments quote from it often. Thanks to everyone who contributes to that wiki/forum, and to Michael Fogleman's [NES](https://github.com/fogleman/nes) and Scott Ferguson's [Fergulator](https://github.com/scottferg/Fergulator) for getting me unstuck at several points.
|
||||
|
||||
|
@ -47,9 +47,9 @@ The code aims to follow the explanations from the [NES dev wiki](https://wiki.ne
|
|||
|
||||
- DMC audio channel, high- and low-pass filters
|
||||
|
||||
- Better GUI and distributable solution
|
||||
- Better GUI
|
||||
|
||||
- Save states
|
||||
- Better save state handling
|
||||
|
||||
- Player 2 controller?
|
||||
|
||||
|
|
|
@ -2,8 +2,7 @@ pub type ApuData = super::Apu;
|
|||
|
||||
impl super::Apu{
|
||||
pub fn save_state(&self) -> ApuData {
|
||||
let x: ApuData = self.clone();
|
||||
x
|
||||
self.clone()
|
||||
}
|
||||
|
||||
pub fn load_state(&mut self, data: ApuData) {
|
||||
|
|
15
src/main.rs
15
src/main.rs
|
@ -13,13 +13,14 @@ use apu::Apu;
|
|||
use cartridge::get_mapper;
|
||||
use input::poll_buttons;
|
||||
use screen::{init_window, draw_pixel, draw_to_window};
|
||||
use state::{save_state, load_state};
|
||||
use state::{save_state, load_state, change_file_extension};
|
||||
|
||||
use std::sync::{Arc, Mutex};
|
||||
use std::time::{Instant, Duration};
|
||||
use sdl2::keyboard::Keycode;
|
||||
use sdl2::event::Event;
|
||||
use sdl2::pixels::PixelFormatEnum;
|
||||
use std::path::Path;
|
||||
|
||||
// use cpuprofiler::PROFILER;
|
||||
|
||||
|
@ -96,12 +97,20 @@ fn main() -> Result<(), String> {
|
|||
Event::Quit {..} | Event::KeyDown { keycode: Some(Keycode::Escape), .. }
|
||||
=> break 'running,
|
||||
Event::KeyDown{ keycode: Some(Keycode::F5), .. } => {
|
||||
let res: Result<(), String> = save_state(&cpu, &filename)
|
||||
let dat_filename = state::change_file_extension(&filename, "dat").unwrap();
|
||||
let res: Result<(), String> = save_state(&cpu, dat_filename)
|
||||
.or_else(|e| {println!("{}", e); Ok(())});
|
||||
res.unwrap();
|
||||
},
|
||||
Event::KeyDown{ keycode: Some(Keycode::F9), .. } => {
|
||||
let res: Result<(), String> = load_state(&mut cpu, &filename)
|
||||
let dat_filename = state::change_file_extension(&filename, "dat").unwrap();
|
||||
let res: Result<(), String> = load_state(&mut cpu, dat_filename)
|
||||
.or_else(|e| {println!("{}", e); Ok(())});
|
||||
res.unwrap();
|
||||
},
|
||||
Event::DropFile{ timestamp: _t, window_id: _w, filename: f } => {
|
||||
let p = Path::new(&f).to_path_buf();
|
||||
let res: Result<(), String> = load_state(&mut cpu, p)
|
||||
.or_else(|e| {println!("{}", e); Ok(())});
|
||||
res.unwrap();
|
||||
},
|
||||
|
|
36
src/state.rs
36
src/state.rs
|
@ -4,7 +4,7 @@ use super::apu;
|
|||
|
||||
use std::fs::File;
|
||||
use std::io::{Read, Write};
|
||||
use std::path::Path;
|
||||
use std::path::{Path, PathBuf};
|
||||
use serde::{Serialize, Deserialize};
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
|
@ -14,7 +14,7 @@ struct SaveState {
|
|||
apu: apu::serialize::ApuData,
|
||||
}
|
||||
|
||||
pub fn save_state(cpu: &cpu::Cpu, filename: &str) -> Result<(), String> {
|
||||
pub fn save_state(cpu: &cpu::Cpu, save_file: PathBuf) -> Result<(), String> {
|
||||
let data = SaveState{
|
||||
cpu: cpu.save_state(),
|
||||
ppu: cpu.ppu.save_state(),
|
||||
|
@ -22,16 +22,6 @@ pub fn save_state(cpu: &cpu::Cpu, filename: &str) -> Result<(), String> {
|
|||
};
|
||||
let serialized = serde_json::to_string(&data)
|
||||
.map_err(|e| e.to_string())?;
|
||||
let path = match Path::new(&filename).parent() {
|
||||
Some(p) => p,
|
||||
None => return Err("couldn't convert filename to path".to_string()),
|
||||
};
|
||||
let stem = match Path::new(&filename).file_stem() {
|
||||
Some(s) => s,
|
||||
None => return Err("couldn't get file stem".to_string()),
|
||||
};
|
||||
let mut save_file = path.join(stem);
|
||||
save_file.set_extension("dat");
|
||||
println!("state saved to file: {:?}", save_file);
|
||||
let mut f = File::create(&save_file)
|
||||
.expect("could not create output file for save state");
|
||||
|
@ -39,19 +29,7 @@ pub fn save_state(cpu: &cpu::Cpu, filename: &str) -> Result<(), String> {
|
|||
.map_err(|_| "couldn't write serialized data to file".to_string())
|
||||
}
|
||||
|
||||
pub fn load_state(cpu: &mut cpu::Cpu, filename: &str) -> Result<(), String> {
|
||||
// load file, deserialize to cpudata, set cpu fields to data fields
|
||||
let path = match Path::new(&filename).parent() {
|
||||
Some(p) => p,
|
||||
None => return Err("couldn't convert filename to path".to_string()),
|
||||
};
|
||||
let stem = match Path::new(&filename).file_stem() {
|
||||
Some(s) => s,
|
||||
None => return Err("couldn't get file stem".to_string()),
|
||||
};
|
||||
let mut save_file = path.join(stem);
|
||||
save_file.set_extension("dat");
|
||||
|
||||
pub fn load_state(cpu: &mut cpu::Cpu, save_file: PathBuf) -> Result<(), String> {
|
||||
if Path::new(&save_file).exists() {
|
||||
let mut f = File::open(save_file.clone())
|
||||
.map_err(|e| e.to_string())?;
|
||||
|
@ -71,3 +49,11 @@ pub fn load_state(cpu: &mut cpu::Cpu, filename: &str) -> Result<(), String> {
|
|||
Err(format!("no save state file at {:?}", save_file))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn change_file_extension(filename: &str, extension: &str) -> Option<PathBuf> {
|
||||
let path = Path::new(filename).parent()?;
|
||||
let stem = Path::new(&filename).file_stem()?;
|
||||
let mut save_file = path.join(stem);
|
||||
save_file.set_extension(extension);
|
||||
Some(save_file)
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue