finished: use slices instead of fixed-size arrays

This commit is contained in:
Vivian Lim 2019-12-24 16:10:32 -08:00
parent bb558096b2
commit 6b330d64ce
3 changed files with 96 additions and 93 deletions

View File

@ -4,7 +4,7 @@ use ferretro::retro::constants::{InputIndex, JoypadButton, AnalogAxis, DeviceTyp
use ferretro::retro::wrapped_types::{ControllerDescription2, InputDescriptor2, InputDeviceId, SubsystemInfo2, Variable2};
use ferretro::retro::wrapper::LibretroWrapper;
use ferretro_synced::sync::memory_rw::MemoryRw;
use ferretro_synced::sync::memory_rw::ReadWriteMemoryMap;
use ferretro_synced::sync::pokemon_rb::SyncedPokemonRedBlue;
use std::ffi::CStr;
@ -21,7 +21,7 @@ use sdl2::keyboard::Keycode;
use sdl2::rect::Rect;
use sdl2::render::WindowCanvas;
pub struct MyEmulator<'emu> {
pub struct MyEmulator {
retro: retro::wrapper::LibretroWrapper,
core_path: PathBuf,
sys_path: Option<PathBuf>,
@ -49,14 +49,12 @@ pub struct MyEmulator<'emu> {
pressed_keys: Vec<Keycode>,
// memory
memory_map: Vec<MyMemoryMap>,
memory_map: ReadWriteMemoryMap,
synced_pokemonrb: SyncedPokemonRedBlue<'emu>,
_marker: std::marker::PhantomData<&'emu()>,
synced_pokemonrb: SyncedPokemonRedBlue,
}
impl MyEmulator<'static> {
impl MyEmulator {
pub fn new(core_path: impl AsRef<Path>, sys_path: &Option<impl AsRef<Path>>) -> Pin<Box<Self>> {
let core_path = PathBuf::from(core_path.as_ref());
let lib = libloading::Library::new(&core_path).unwrap();
@ -120,11 +118,9 @@ impl MyEmulator<'static> {
let pressed_keys = Vec::new();
let memory_map = Vec::new();
let memory_map = std::default::Default::default();
let synced_pokemonrb = std::default::Default::default();
let _marker = std::marker::PhantomData::default();
let emu = MyEmulator {
retro,
core_path,
@ -144,7 +140,6 @@ impl MyEmulator<'static> {
pressed_keys,
memory_map,
synced_pokemonrb,
_marker
};
let mut pin_emu = Box::pin(emu);
retro::wrapper::set_handler(pin_emu.as_mut());
@ -181,7 +176,7 @@ impl MyEmulator<'static> {
spf = 1.0 / 60.0;
}
self.synced_pokemonrb.update_from_emu(self);
self.synced_pokemonrb.update_from_mem(&self.memory_map);
println!("{}", self.synced_pokemonrb);
Duration::from_secs_f64(spf)
@ -278,35 +273,15 @@ impl MyEmulator<'static> {
}
fn find_bank(&self, offset: usize, length: usize, bank_switch: usize) -> Option<*const std::ffi::c_void> {
if self.memory_map.len() == 0 {
return None;
}
for item in self.memory_map.iter() {
if (item.start <= offset) && (offset < item.end) {
if offset + length > item.end {
println!("({:x}, {:x}) overruns ({:x}, {:x}) memory bank.", offset, length, item.start, item.end);
return None;
}
let bank_size = item.end - item.start;
let relative_offset = isize::try_from(offset - item.start + (bank_size * bank_switch)).unwrap();
return unsafe { Some(item.pointer.offset(relative_offset)) }
}
}
println!("({:x}, {:x}) address range not found in any memory map region.", offset, length);
None
}
}
impl Drop for MyEmulator<'_> {
impl Drop for MyEmulator {
fn drop(&mut self) {
retro::wrapper::unset_handler();
}
}
impl retro::wrapper::Handler for MyEmulator<'static> {
impl retro::wrapper::Handler for MyEmulator {
fn libretro_core(&mut self) -> &mut LibretroWrapper {
&mut self.retro
}
@ -435,48 +410,11 @@ impl retro::wrapper::Handler for MyEmulator<'static> {
}
fn set_memory_maps(&mut self, memory_map: MemoryMap) -> bool {
let mut descs: Vec<MyMemoryMap> = Vec::new();
let num_descriptors = isize::try_from(memory_map.num_descriptors).unwrap();
for i in 0..num_descriptors {
let desc = unsafe { &*memory_map.descriptors.offset(i) };
let mut length = desc.len;
if desc.select > 0 { // FIXME: hack for oversized SRAM eating addr space
length = (!desc.select + 1) & 0xffffffff;
println!("truncating memory region {:x} from size {:x} to {:x} banks of size {:x}", desc.start, desc.len, desc.len/length, length)
}
descs.push(MyMemoryMap {
start: desc.start,
end: desc.start + length,
pointer: desc.ptr,
})
}
self.memory_map = descs;
self.memory_map.libretro_set_memory_maps(memory_map);
true
}
}
impl<'emu> MemoryRw<'emu> for MyEmulator<'emu> {
fn peek_region(&self, offset: usize, length: usize, bank_switch: usize) -> Option<&[u8]> {
match self.find_bank(offset, length, bank_switch) {
Some(ptr) => Some(unsafe { std::slice::from_raw_parts::<'emu>(ptr, length) }),
None => None
}
}
fn poke_region<T>(&mut self, offset: usize, data: T, bank_switch: usize) {
}
}
struct MyMemoryMap<> {
start: usize,
end: usize,
pointer: *const std::ffi::c_void,
}
struct MySdlAudio {
audio_spec: AudioSpec,

View File

@ -1,4 +1,70 @@
pub trait MemoryRw<'emu> {
fn peek_region(&self, offset: usize, length: usize, bank_switch: usize) -> Option<&[u8]>;
fn poke_region<T>(&mut self, offset: usize, data: T, bank_switch: usize);
use std::convert::TryFrom;
use std::default::Default;
use ferretro::retro::ffi::{MemoryMap};
#[derive(Default)]
pub struct ReadWriteMemoryMap {
regions: Vec<MemoryRegion>,
}
impl ReadWriteMemoryMap {
pub fn peek_region(&self, offset: usize, length: usize, bank_switch: usize) -> Option<&'static [u8]> {
match self.find_bank(offset, length, bank_switch) {
Some(ptr) => Some(unsafe { std::slice::from_raw_parts(ptr as *const u8, length) }),
None => None
}
}
pub fn poke_region<T>(&mut self, offset: usize, data: T, bank_switch: usize) {
}
fn find_bank(&self, offset: usize, length: usize, bank_switch: usize) -> Option<*const std::ffi::c_void> {
if self.regions.len() == 0 {
return None;
}
for item in self.regions.iter() {
if (item.start <= offset) && (offset < item.end) {
if offset + length > item.end {
println!("({:x}, {:x}) overruns ({:x}, {:x}) memory bank.", offset, length, item.start, item.end);
return None;
}
let bank_size = item.end - item.start;
let relative_offset = isize::try_from(offset - item.start + (bank_size * bank_switch)).unwrap();
return unsafe { Some(item.pointer.offset(relative_offset)) }
}
}
println!("({:x}, {:x}) address range not found in any memory map region.", offset, length);
None
}
pub fn libretro_set_memory_maps(&mut self, memory_map: MemoryMap) {
let mut regions: Vec<MemoryRegion> = Vec::new();
let num_descriptors = isize::try_from(memory_map.num_descriptors).unwrap();
for i in 0..num_descriptors {
let region = unsafe { &*memory_map.descriptors.offset(i) };
let mut length = region.len;
if region.select > 0 { // FIXME: hack for oversized SRAM eating addr space
length = (!region.select + 1) & 0xffffffff;
println!("truncating memory region {:x} from size {:x} to {:x} banks of size {:x}", region.start, region.len, region.len/length, length)
}
regions.push(MemoryRegion {
start: region.start,
end: region.start + length,
pointer: region.ptr,
})
}
self.regions = regions;
}
}
struct MemoryRegion {
start: usize,
end: usize,
pointer: *const std::ffi::c_void,
}

View File

@ -1,12 +1,12 @@
use std::default::Default;
use std::fmt::Display;
use crate::sync::memory_rw::MemoryRw;
use crate::sync::memory_rw::ReadWriteMemoryMap;
use serde::{Serialize, Deserialize};
use ferretro::retro::wrapper::LibretroWrapper; // want LibretroWrapper.api : LibretroApi.get_memory()
#[derive(Default)]
pub struct SyncedPokemonRedBlue<'emu> {
raw: Raw<'emu>,
pub struct SyncedPokemonRedBlue {
raw: Raw,
battle_context: BattleContext,
}
@ -15,25 +15,25 @@ pub struct Message {
active_pkmn: Box<[u8]>
}
struct Raw<'emu> {
active_pokemon_raw: EmulatorMemory<'emu>,
player_and_party: EmulatorMemory<'emu>,
pokemon_out: EmulatorMemory<'emu>,
struct Raw {
active_pokemon_raw: EmulatorMemory,
player_and_party: EmulatorMemory,
pokemon_out: EmulatorMemory,
}
struct EmulatorMemory<'emu> {
struct EmulatorMemory {
offset: usize,
length: usize,
bank_switch: usize,
data: Option<&'emu [u8]>,
data: Option<&'static [u8]>,
}
impl<'emu> EmulatorMemory<'emu> {
pub fn get_data<T: MemoryRw<'emu>>(&mut self, emu: &'emu T) -> Option<&'emu [u8]> {
impl EmulatorMemory {
pub fn get_data(&mut self, mem: &ReadWriteMemoryMap) -> Option<&'static [u8]> {
match self.data {
Some(_) => self.data,
None => {
self.data = emu.peek_region(self.offset, self.length, self.bank_switch);
self.data = mem.peek_region(self.offset, self.length, self.bank_switch);
self.data
}
}
@ -42,14 +42,13 @@ impl<'emu> EmulatorMemory<'emu> {
struct BattleContext {
active_pokemon: Pokemon,
}
impl<'emu> SyncedPokemonRedBlue<'emu> {
pub fn update_from_emu<T: MemoryRw<'emu>>(&mut self, emu: &'emu T) {
impl SyncedPokemonRedBlue {
pub fn update_from_mem(&mut self, mem: &ReadWriteMemoryMap) {
let battle_context = BattleContext {
active_pokemon: match self.raw.active_pokemon_raw.get_data(emu) {
active_pokemon: match self.raw.active_pokemon_raw.get_data(mem) {
Some(d) => num::FromPrimitive::from_u8(d[0xB]).unwrap_or(Pokemon::Unknown),
None => Pokemon::Unknown
}
@ -67,7 +66,7 @@ impl<'emu> SyncedPokemonRedBlue<'emu> {
// }
}
impl<'emu> Default for Raw<'emu> {
impl Default for Raw {
fn default() -> Self {
Raw {
active_pokemon_raw: EmulatorMemory {
@ -100,7 +99,7 @@ impl Default for BattleContext {
}
}
impl Display for SyncedPokemonRedBlue<'_> {
impl Display for SyncedPokemonRedBlue {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "active: pk {:?}", &self.battle_context.active_pokemon)
}