finished: use slices instead of fixed-size arrays
This commit is contained in:
parent
bb558096b2
commit
6b330d64ce
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
}
|
|
@ -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)
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue