From ba8f39f28304fb92ce81908117d97139b0814b74 Mon Sep 17 00:00:00 2001 From: Logan McNaughton <848146+loganmc10@users.noreply.github.com> Date: Wed, 22 Jan 2025 11:10:54 +0100 Subject: [PATCH] Netplay sync save files (#168) --- src/device.rs | 4 +- src/device/cart.rs | 2 +- src/device/controller/mempak.rs | 2 +- src/device/sram.rs | 4 +- src/netplay.rs | 31 ++++++++++-- src/ui/storage.rs | 90 +++++++++++++++++++++++++++------ 6 files changed, 107 insertions(+), 26 deletions(-) diff --git a/src/device.rs b/src/device.rs index a89afbf..345994f 100644 --- a/src/device.rs +++ b/src/device.rs @@ -74,13 +74,13 @@ pub fn run_game( cpu::init(device); ui::storage::init(&mut device.ui, data_dir); - ui::storage::load_saves(&mut device.ui); + ui::storage::load_saves(&mut device.ui, &mut device.netplay); cart_rom::load_rom_save(device); cpu::run(device); ui::video::close(); - ui::storage::write_saves(&device.ui); + ui::storage::write_saves(&device.ui, &device.netplay); } fn swap_rom(contents: Vec) -> Vec { diff --git a/src/device/cart.rs b/src/device/cart.rs index 41f986c..e59bc44 100644 --- a/src/device/cart.rs +++ b/src/device/cart.rs @@ -16,7 +16,7 @@ const JDT_AF_RTC: u16 = 0x1000; /* RTC */ const JDT_EEPROM_4K: u16 = 0x8000; /* 4k EEPROM */ const JDT_EEPROM_16K: u16 = 0xc000; /* 16k EEPROM */ const EEPROM_BLOCK_SIZE: usize = 8; -const EEPROM_MAX_SIZE: usize = 0x800; +pub const EEPROM_MAX_SIZE: usize = 0x800; pub struct AfRtc { pub control: u16, diff --git a/src/device/controller/mempak.rs b/src/device/controller/mempak.rs index 48dc9be..0361678 100644 --- a/src/device/controller/mempak.rs +++ b/src/device/controller/mempak.rs @@ -1,6 +1,6 @@ use crate::device; -const MEMPAK_SIZE: usize = 0x8000; +pub const MEMPAK_SIZE: usize = 0x8000; const MPK_PAGE_SIZE: usize = 256; fn format_mempak(device: &mut device::Device) { diff --git a/src/device/sram.rs b/src/device/sram.rs index 9ece908..e54589a 100644 --- a/src/device/sram.rs +++ b/src/device/sram.rs @@ -2,8 +2,8 @@ use crate::device; use crate::ui; const SRAM_MASK: usize = 0xFFFF; -const SRAM_SIZE: usize = 0x8000; -const FLASHRAM_SIZE: usize = 0x20000; +pub const SRAM_SIZE: usize = 0x8000; +pub const FLASHRAM_SIZE: usize = 0x20000; pub const FLASHRAM_TYPE_ID: u32 = 0x11118001; pub const MX29L1100_ID: u32 = 0x00c2001e; const MX29L0000_ID: u32 = 0x00c20000; diff --git a/src/netplay.rs b/src/netplay.rs index 10ab273..2255e9c 100644 --- a/src/netplay.rs +++ b/src/netplay.rs @@ -9,8 +9,8 @@ use std::io::{Read, Write}; //const UDP_SYNC_DATA: u8 = 4; //TCP packet formats -//const TCP_SEND_SAVE: u8 = 1; -//const TCP_RECEIVE_SAVE: u8 = 2; +const TCP_SEND_SAVE: u8 = 1; +const TCP_RECEIVE_SAVE: u8 = 2; //const TCP_SEND_SETTINGS: u8 = 3; //const TCP_RECEIVE_SETTINGS: u8 = 4; const TCP_REGISTER_PLAYER: u8 = 5; @@ -19,8 +19,31 @@ const TCP_DISCONNECT_NOTICE: u8 = 7; pub struct Netplay { // udp_socket: std::net::UdpSocket, - tcp_stream: std::net::TcpStream, - player_number: u8, + pub tcp_stream: std::net::TcpStream, + pub player_number: u8, +} + +pub fn send_save(netplay: &mut Netplay, save_type: &str, save_data: &[u8], size: usize) { + let mut request: Vec = [TCP_SEND_SAVE].to_vec(); + request.extend_from_slice(save_type.as_bytes()); + request.push(0); // null terminate string + request.extend_from_slice(&(size as u32).to_be_bytes()); + + let mut send_data = save_data.to_owned(); + send_data.resize(size, 0); // pad with zeros if needed + request.extend(send_data); + netplay.tcp_stream.write_all(&request).unwrap(); +} + +pub fn receive_save(netplay: &mut Netplay, save_type: &str, save_data: &mut Vec, size: usize) { + let mut request: Vec = [TCP_RECEIVE_SAVE].to_vec(); + request.extend_from_slice(save_type.as_bytes()); + request.push(0); // null terminate string + netplay.tcp_stream.write_all(&request).unwrap(); + + let mut response: Vec = vec![0; size]; + netplay.tcp_stream.read_exact(&mut response).unwrap(); + *save_data = response; } pub fn init( diff --git a/src/ui/storage.rs b/src/ui/storage.rs index afcb7a7..36244a1 100644 --- a/src/ui/storage.rs +++ b/src/ui/storage.rs @@ -1,3 +1,5 @@ +use crate::device; +use crate::netplay; use crate::ui; #[derive(PartialEq)] @@ -118,7 +120,7 @@ pub fn init(ui: &mut ui::Ui, data_dir: std::path::PathBuf) { .push(ui.game_id.to_owned() + "-" + &ui.game_hash + ".romsave"); } -pub fn load_saves(ui: &mut ui::Ui) { +pub fn load_saves(ui: &mut ui::Ui, netplay: &mut Option) { let eep = std::fs::read(&mut ui.paths.eep_file_path); if eep.is_ok() { ui.saves.eeprom.0 = eep.unwrap(); @@ -139,6 +141,60 @@ pub fn load_saves(ui: &mut ui::Ui) { if romsave.is_ok() { ui.saves.romsave.0 = serde_json::from_slice(romsave.unwrap().as_ref()).unwrap(); } + if netplay.is_some() { + if netplay.as_ref().unwrap().player_number == 0 { + netplay::send_save( + netplay.as_mut().unwrap(), + "eep", + &ui.saves.eeprom.0, + device::cart::EEPROM_MAX_SIZE, + ); + netplay::send_save( + netplay.as_mut().unwrap(), + "sra", + &ui.saves.sram.0, + device::sram::SRAM_SIZE, + ); + netplay::send_save( + netplay.as_mut().unwrap(), + "fla", + &ui.saves.flash.0, + device::sram::FLASHRAM_SIZE, + ); + netplay::send_save( + netplay.as_mut().unwrap(), + "mpk", + &ui.saves.mempak.0, + device::controller::mempak::MEMPAK_SIZE * 4, + ); + } else { + netplay::receive_save( + netplay.as_mut().unwrap(), + "eep", + &mut ui.saves.eeprom.0, + device::cart::EEPROM_MAX_SIZE, + ); + netplay::receive_save( + netplay.as_mut().unwrap(), + "sra", + &mut ui.saves.sram.0, + device::sram::SRAM_SIZE, + ); + netplay::receive_save( + netplay.as_mut().unwrap(), + "fla", + &mut ui.saves.flash.0, + device::sram::FLASHRAM_SIZE, + ); + netplay::receive_save( + netplay.as_mut().unwrap(), + "mpk", + &mut ui.saves.mempak.0, + device::controller::mempak::MEMPAK_SIZE * 4, + ); + } + ui.saves.romsave.0 = Default::default(); // can't do romsaves with the current netplay implementation + } } fn write_rom_save(ui: &ui::Ui) { @@ -146,21 +202,23 @@ fn write_rom_save(ui: &ui::Ui) { serde_json::to_writer(f, &ui.saves.romsave.0).unwrap(); } -pub fn write_saves(ui: &ui::Ui) { - if ui.saves.eeprom.1 { - write_save(ui, SaveTypes::Eeprom16k) - } - if ui.saves.sram.1 { - write_save(ui, SaveTypes::Sram) - } - if ui.saves.flash.1 { - write_save(ui, SaveTypes::Flash) - } - if ui.saves.mempak.1 { - write_save(ui, SaveTypes::Mempak) - } - if ui.saves.romsave.1 { - write_save(ui, SaveTypes::Romsave) +pub fn write_saves(ui: &ui::Ui, netplay: &Option) { + if netplay.is_none() || netplay.as_ref().unwrap().player_number == 0 { + if ui.saves.eeprom.1 { + write_save(ui, SaveTypes::Eeprom16k) + } + if ui.saves.sram.1 { + write_save(ui, SaveTypes::Sram) + } + if ui.saves.flash.1 { + write_save(ui, SaveTypes::Flash) + } + if ui.saves.mempak.1 { + write_save(ui, SaveTypes::Mempak) + } + if ui.saves.romsave.1 && netplay.is_none() { + write_save(ui, SaveTypes::Romsave) + } } }