Conversation
…into benkonz-master
| None | ||
| } | ||
| fn save(&mut self, ram: Vec<u8>) { | ||
| let save_str: String = ram.iter().map(|x| format!("{:02X}", x)).collect(); |
There was a problem hiding this comment.
I tried doing saving by mapping the ram to a string like this originally, but the problem was that it was just too slow. Some games can have up to 2MB of RAM, so mapping every single byte to a string every frame slows the game down by a lot
There was a problem hiding this comment.
How did you solve the issue?
There was a problem hiding this comment.
Heh, my solution is a little hack-y, but has worked well so far. Basically, we maintain a String that is an exact copy of whatever is in the cartridge RAM and whenever it changes, update the String in-place.
This initializes the Ram String to the RAM contents before the emulation starts
let ram_str = Rc::new(RefCell::new(
ram.iter().map(|byte| format!("{:02x}", byte)).collect(),
));
This set's up an event listener for whenever the contents of the Cartridge RAM changes
self.gameboy
.set_ram_change_callback(Box::new(move |address, value| {
if has_battery {
let byte_chars: Vec<char> = format!("{:02x}", value).chars().collect();
let (first, second) = (byte_chars[0] as u8, byte_chars[1] as u8);
// unsafe because we are updating the RAM String in-place
// but since we are updating it with valid UTF-8, the updated string will also be UTF-8
unsafe {
let mut ram_str_ref = ram_str.borrow_mut();
let bytes = ram_str_ref.as_bytes_mut();
bytes[address * 2] = first;
bytes[address * 2 + 1] = second;
}
*should_save_to_local.borrow_mut() = true;
}
}));
This takes the O(n) Vec to String mapping to a O(1) in-place update, which is a lot faster, but requires a bit more code and unsafe Rust.
I want to create a generic struct for storing the save game. I am not sure how to organize the code base so that I can have a custom storage. I am writing a web server and I want to be able to store data on the server. This code will have custom URL paths that are not relevant to the project overall and I am not sure how to organize the project so that extra code is not upstreamed