mirror of
https://github.com/koute/pinky.git
synced 2024-05-16 19:20:43 -04:00
Add workspace and #[no_std]
support
This commit is contained in:
parent
17c51a1e96
commit
59c2a652db
18
.gitignore
vendored
18
.gitignore
vendored
|
@ -1,16 +1,2 @@
|
|||
pinky-devui/target
|
||||
pinky-devui/Cargo.lock
|
||||
pinky-libretro/target
|
||||
pinky-libretro/Cargo.lock
|
||||
pinky-web/target
|
||||
pinky-web/Cargo.lock
|
||||
nes-testsuite/target
|
||||
nes-testsuite/Cargo.lock
|
||||
mos6502/target
|
||||
mos6502/Cargo.lock
|
||||
nes/target
|
||||
nes/Cargo.lock
|
||||
emumisc/target
|
||||
emumisc/Cargo.lock
|
||||
rp2c02-testsuite/target
|
||||
rp2c02-testsuite/Cargo.lock
|
||||
Cargo.toml
|
||||
Cargo.lock
|
||||
|
|
14
Cargo.toml
Normal file
14
Cargo.toml
Normal file
|
@ -0,0 +1,14 @@
|
|||
[workspace]
|
||||
members = [
|
||||
"emumisc",
|
||||
"mos6502",
|
||||
"nes",
|
||||
"nes-testsuite",
|
||||
"pinky-devui",
|
||||
"pinky-libretro",
|
||||
"pinky-web",
|
||||
"rp2c02-testsuite"
|
||||
]
|
||||
|
||||
[profile.test]
|
||||
opt-level = 2
|
|
@ -1,4 +1,4 @@
|
|||
use std::mem;
|
||||
use core::mem;
|
||||
|
||||
#[inline(always)] pub fn is_b0_set( value: u8 ) -> bool { (value & (1 << 0)) != 0 }
|
||||
#[inline(always)] pub fn is_b1_set( value: u8 ) -> bool { (value & (1 << 1)) != 0 }
|
||||
|
@ -11,8 +11,6 @@ use std::mem;
|
|||
|
||||
#[inline(always)]
|
||||
pub fn to_bit( bit: u8, value: bool ) -> u8 {
|
||||
use std::mem;
|
||||
|
||||
debug_assert!( bit < 8 );
|
||||
let converted: u8 = unsafe { mem::transmute( value ) };
|
||||
debug_assert!( converted == 0 || converted == 1 );
|
||||
|
@ -37,7 +35,7 @@ macro_rules! impl_bit_extra {
|
|||
impl BitExtra for $typ {
|
||||
#[inline(always)]
|
||||
fn mask_to_shift( mask: Self ) -> u8 {
|
||||
use std::mem::size_of;
|
||||
use core::mem::size_of;
|
||||
debug_assert!( mask != 0 );
|
||||
|
||||
for n_bit in 0..(size_of::< Self >() * 8) as u8 {
|
||||
|
|
|
@ -1,4 +1,7 @@
|
|||
#![no_std]
|
||||
|
||||
extern crate unreachable;
|
||||
extern crate alloc;
|
||||
|
||||
#[macro_use]
|
||||
mod misc;
|
||||
|
@ -31,7 +34,7 @@ pub use memory::{as_bytes, allocate_slice, copy_memory};
|
|||
#[macro_export]
|
||||
macro_rules! impl_deref {
|
||||
($container: ty, $field_type: ty, $field: ident) => (
|
||||
impl ::std::ops::Deref for $container {
|
||||
impl ::core::ops::Deref for $container {
|
||||
type Target = $field_type;
|
||||
|
||||
#[inline(always)]
|
||||
|
@ -40,7 +43,7 @@ macro_rules! impl_deref {
|
|||
}
|
||||
}
|
||||
|
||||
impl ::std::ops::DerefMut for $container {
|
||||
impl ::core::ops::DerefMut for $container {
|
||||
#[inline(always)]
|
||||
fn deref_mut( &mut self ) -> &mut Self::Target {
|
||||
&mut self.$field
|
||||
|
@ -52,14 +55,14 @@ macro_rules! impl_deref {
|
|||
#[macro_export]
|
||||
macro_rules! impl_as_ref {
|
||||
($container: ty, $field_type: ty, $field: ident) => (
|
||||
impl ::std::convert::AsRef< $field_type > for $container {
|
||||
impl ::core::convert::AsRef< $field_type > for $container {
|
||||
#[inline(always)]
|
||||
fn as_ref( &self ) -> &$field_type {
|
||||
&self.$field
|
||||
}
|
||||
}
|
||||
|
||||
impl ::std::convert::AsMut< $field_type > for $container {
|
||||
impl ::core::convert::AsMut< $field_type > for $container {
|
||||
#[inline(always)]
|
||||
fn as_mut( &mut self ) -> &mut $field_type {
|
||||
&mut self.$field
|
||||
|
@ -74,7 +77,7 @@ macro_rules! newtype {
|
|||
$(#[$attr])*
|
||||
pub struct $new( pub $old );
|
||||
|
||||
impl ::std::ops::Deref for $new {
|
||||
impl ::core::ops::Deref for $new {
|
||||
type Target = $old;
|
||||
|
||||
#[inline(always)]
|
||||
|
@ -83,21 +86,21 @@ macro_rules! newtype {
|
|||
}
|
||||
}
|
||||
|
||||
impl ::std::ops::DerefMut for $new {
|
||||
impl ::core::ops::DerefMut for $new {
|
||||
#[inline(always)]
|
||||
fn deref_mut( &mut self ) -> &mut Self::Target {
|
||||
&mut self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl ::std::convert::AsRef< $old > for $new {
|
||||
impl ::core::convert::AsRef< $old > for $new {
|
||||
#[inline(always)]
|
||||
fn as_ref( &self ) -> &$old {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl ::std::convert::AsMut< $old > for $new {
|
||||
impl ::core::convert::AsMut< $old > for $new {
|
||||
#[inline(always)]
|
||||
fn as_mut( &mut self ) -> &mut $old {
|
||||
&mut self.0
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
use std::ptr;
|
||||
use std::slice;
|
||||
use std::mem;
|
||||
use core::ptr;
|
||||
use core::slice;
|
||||
use core::mem;
|
||||
use alloc::boxed::Box;
|
||||
use alloc::vec::Vec;
|
||||
|
||||
#[inline]
|
||||
pub fn as_bytes< T: Copy >( array: &[T] ) -> &[u8] {
|
||||
|
|
|
@ -9,3 +9,6 @@ bitflags = "0.7"
|
|||
[dependencies.emumisc]
|
||||
path = "../emumisc"
|
||||
|
||||
[features]
|
||||
default = ["std"]
|
||||
std = []
|
||||
|
|
|
@ -345,9 +345,8 @@ def generate_opcode_attributes
|
|||
|
||||
#[inline(always)]
|
||||
fn get_register( &self ) -> Register8 {
|
||||
use std::mem;
|
||||
unsafe {
|
||||
mem::transmute( (self.attr & 0b00011000) >> 3 )
|
||||
core::mem::transmute( (self.attr & 0b00011000) >> 3 )
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,12 @@
|
|||
#![cfg_attr(not(feature = "std"), no_std)]
|
||||
#![cfg_attr(not(feature = "std"), feature(error_in_core))]
|
||||
|
||||
#![allow(non_snake_case)]
|
||||
#![allow(non_upper_case_globals)]
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
extern crate std as core;
|
||||
|
||||
#[macro_use]
|
||||
extern crate emumisc;
|
||||
|
||||
|
|
|
@ -1,10 +1,9 @@
|
|||
use self::Register8::*;
|
||||
use self::Direction::*;
|
||||
|
||||
use std::mem::transmute;
|
||||
use std::fmt;
|
||||
use std::ops::Deref;
|
||||
use std::error;
|
||||
use core::mem::transmute;
|
||||
use core::fmt;
|
||||
use core::ops::Deref;
|
||||
|
||||
use emumisc::WrappingExtra;
|
||||
|
||||
|
@ -227,7 +226,7 @@ impl fmt::Display for EmulationError {
|
|||
}
|
||||
}
|
||||
|
||||
impl error::Error for EmulationError {
|
||||
impl core::error::Error for EmulationError {
|
||||
fn description( &self ) -> &str {
|
||||
use self::EmulationError::*;
|
||||
match *self {
|
||||
|
@ -1018,6 +1017,7 @@ trait Private: Sized + Context {
|
|||
result
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
fn print_registers( &self ) {
|
||||
println!( " NV-BDIZC A X Y PC" );
|
||||
println!( " {:08b} {:02X} {:02X} {:02X} {:04X}", self.state().status, self.state().a, self.state().x, self.state().y, self.state().pc );
|
||||
|
|
|
@ -761,9 +761,8 @@ macro_rules! decoding_logic {
|
|||
|
||||
#[inline(always)]
|
||||
fn get_register( &self ) -> Register8 {
|
||||
use std::mem;
|
||||
unsafe {
|
||||
mem::transmute( (self.attr & 0b00011000) >> 3 )
|
||||
core::mem::transmute( (self.attr & 0b00011000) >> 3 )
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -4,8 +4,7 @@ version = "0.1.0"
|
|||
authors = ["Jan Bujak <j@exia.io>"]
|
||||
|
||||
[dependencies]
|
||||
byteorder = "0.5"
|
||||
log = "0.3"
|
||||
log = { version = "0.4", default-features = false, optional = true }
|
||||
bitflags = "0.7"
|
||||
|
||||
[dependencies.emumisc]
|
||||
|
@ -13,6 +12,7 @@ path = "../emumisc"
|
|||
|
||||
[dependencies.mos6502]
|
||||
path = "../mos6502"
|
||||
default-features = false
|
||||
|
||||
[dev-dependencies.nes-testsuite]
|
||||
path = "../nes-testsuite"
|
||||
|
@ -20,10 +20,6 @@ path = "../nes-testsuite"
|
|||
[dev-dependencies.rp2c02-testsuite]
|
||||
path = "../rp2c02-testsuite"
|
||||
|
||||
[profile.test]
|
||||
opt-level = 2
|
||||
debug = true
|
||||
rpath = false
|
||||
lto = false
|
||||
debug-assertions = true
|
||||
codegen-units = 4
|
||||
[features]
|
||||
default = ["std"]
|
||||
std = ["mos6502/std", "log", "log/std"]
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
use std::fmt;
|
||||
use core::fmt;
|
||||
use alloc::vec::Vec;
|
||||
|
||||
use emumisc::{PeekPoke, At};
|
||||
use rom::Mirroring;
|
||||
use mappers::Mapper;
|
||||
|
@ -464,6 +466,7 @@ impl GenericMapper {
|
|||
#[inline]
|
||||
pub fn poke_cpu_memory_space( &mut self, address: u16, value: u8 ) {
|
||||
if self.is_cpu_address_writable( address ) == false {
|
||||
#[cfg(feature = "log")]
|
||||
warn!( "Unhandled write to 0x{:04X} (value=0x{:02X})", address, value );
|
||||
return;
|
||||
}
|
||||
|
@ -523,7 +526,7 @@ impl Mapper for GenericMapper {
|
|||
}
|
||||
}
|
||||
|
||||
use std::ops::Sub;
|
||||
use core::ops::Sub;
|
||||
use rom::{NesRom, LoadError};
|
||||
#[inline]
|
||||
fn wraparound< T: Sub< Output = T > + PartialOrd + Copy >( limit: T, mut value: T ) -> T {
|
||||
|
|
|
@ -1,11 +1,22 @@
|
|||
#![cfg_attr(not(feature = "std"), no_std)]
|
||||
#![cfg_attr(not(feature = "std"), feature(error_in_core))]
|
||||
|
||||
#![allow(dead_code)]
|
||||
#![allow(non_camel_case_types)]
|
||||
#![allow(non_upper_case_globals)]
|
||||
#![allow(non_snake_case)]
|
||||
#![allow(missing_copy_implementations)]
|
||||
|
||||
extern crate byteorder;
|
||||
#[cfg(feature = "std")]
|
||||
extern crate std as core;
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
extern crate std as alloc;
|
||||
|
||||
#[cfg(not(feature = "std"))]
|
||||
extern crate alloc;
|
||||
|
||||
#[cfg(feature = "log")]
|
||||
#[macro_use]
|
||||
extern crate log;
|
||||
|
||||
|
|
|
@ -152,6 +152,7 @@ impl Mapper for MapperMMC1 {
|
|||
_ => unsafe { fast_unreachable!() }
|
||||
};
|
||||
|
||||
#[cfg(feature = "log")]
|
||||
debug!( "ROM switching mode = {:?}, VROM switching mode = {:?}",
|
||||
self.rom_switching_mode,
|
||||
self.vrom_switching_mode
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
use alloc::boxed::Box;
|
||||
use alloc::format;
|
||||
|
||||
use rom::{NesRom, LoadError};
|
||||
use generic_mapper::GenericMapper;
|
||||
use mapper_mmc1::MapperMMC1;
|
||||
|
@ -10,20 +13,24 @@ pub trait Mapper {
|
|||
fn poke_rom( &mut self, address: u16, value: u8 );
|
||||
|
||||
fn peek_sram( &self, address: u16 ) -> u8 {
|
||||
#[cfg(feature = "log")]
|
||||
warn!( "Unhandled read from the save RAM at 0x{:04X}", address );
|
||||
0
|
||||
}
|
||||
|
||||
fn poke_sram( &mut self, address: u16, value: u8 ) {
|
||||
#[cfg(feature = "log")]
|
||||
warn!( "Unhandled write to the save RAM at 0x{:04X} (value=0x{:02X})", address, value );
|
||||
}
|
||||
|
||||
fn peek_expansion_rom( &self, address: u16 ) -> u8 {
|
||||
#[cfg(feature = "log")]
|
||||
warn!( "Unhandled read from the expansion ROM at 0x{:04X}", address );
|
||||
0
|
||||
}
|
||||
|
||||
fn poke_expansion_rom( &self, address: u16, value: u8 ) {
|
||||
#[cfg(feature = "log")]
|
||||
warn!( "Unhandled write to the expansion ROM at 0x{:04X} (value=0x{:02X})", address, value );
|
||||
}
|
||||
|
||||
|
@ -35,20 +42,24 @@ pub struct MapperNull;
|
|||
|
||||
impl Mapper for MapperNull {
|
||||
fn peek_rom( &self, address: u16 ) -> u8 {
|
||||
#[cfg(feature = "log")]
|
||||
warn!( "Unhandled read from the ROM at 0x{:04X}", address );
|
||||
0
|
||||
}
|
||||
|
||||
fn poke_rom( &mut self, address: u16, value: u8 ) {
|
||||
#[cfg(feature = "log")]
|
||||
warn!( "Unhandled write to the ROM at 0x{:04X} (value=0x{:02X})", address, value );
|
||||
}
|
||||
|
||||
fn peek_video_memory( &self, address: u16 ) -> u8 {
|
||||
#[cfg(feature = "log")]
|
||||
warn!( "Unhandled read from the VROM at 0x{:04X}", address );
|
||||
0
|
||||
}
|
||||
|
||||
fn poke_video_memory( &mut self, address: u16, value: u8 ) {
|
||||
#[cfg(feature = "log")]
|
||||
warn!( "Unhandled write to the VROM at 0x{:04X} (value=0x{:02X})", address, value );
|
||||
}
|
||||
}
|
||||
|
@ -65,6 +76,7 @@ pub fn create_mapper( rom: NesRom ) -> Result< Box< Mapper >, LoadError > {
|
|||
mapper.initialize_video_rom( &rom.video_rom[..] );
|
||||
mapper.initialize_background_tilemaps( rom.mirroring );
|
||||
|
||||
#[cfg(feature = "log")]
|
||||
debug!( "Initialized mapper: {:?}", mapper );
|
||||
Ok( Box::new( mapper ) )
|
||||
},
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use std::mem;
|
||||
use std::ops::{Deref, DerefMut};
|
||||
use core::mem;
|
||||
use core::ops::{Deref, DerefMut};
|
||||
|
||||
// A shim like this is necessary to implement an orphaned instance in Rust.
|
||||
// It's very important to keep the structure opaque to keep it safe to use.
|
||||
|
|
|
@ -1,23 +1,9 @@
|
|||
use std::io;
|
||||
use std::io::{Read, Error, ErrorKind, Seek, SeekFrom};
|
||||
use std::cmp::max;
|
||||
use std::fmt;
|
||||
use std::error;
|
||||
|
||||
use byteorder::{ReadBytesExt, LittleEndian};
|
||||
|
||||
fn fill_array< T: Read >( fp: &mut T, out: &mut [u8] ) -> io::Result<()> {
|
||||
match fp.read( out ) {
|
||||
Ok( size ) => {
|
||||
if size == out.len() {
|
||||
Ok(())
|
||||
} else {
|
||||
Err( Error::new( ErrorKind::Other, "Unexpected end of file found" ) )
|
||||
}
|
||||
},
|
||||
Err( error ) => Err( error )
|
||||
}
|
||||
}
|
||||
use core::cmp::max;
|
||||
use core::fmt;
|
||||
use core::error;
|
||||
use alloc::string::String;
|
||||
use alloc::vec::Vec;
|
||||
use alloc::format;
|
||||
|
||||
fn decapitalize< M: fmt::Display >( msg: M ) -> String {
|
||||
let message = format!( "{}", msg );
|
||||
|
@ -32,7 +18,6 @@ fn decapitalize< M: fmt::Display >( msg: M ) -> String {
|
|||
#[derive(Debug)]
|
||||
pub enum LoadError {
|
||||
Custom( String ),
|
||||
IO( io::Error )
|
||||
}
|
||||
|
||||
impl LoadError {
|
||||
|
@ -45,7 +30,6 @@ impl fmt::Display for LoadError {
|
|||
fn fmt( &self, fmt: &mut fmt::Formatter ) -> fmt::Result {
|
||||
match *self {
|
||||
LoadError::Custom( ref message ) => try!( write!( fmt, "Unable to load ROM - {}", decapitalize( message ))),
|
||||
LoadError::IO( ref error ) => try!( write!( fmt, "Unable to load ROM - {}", decapitalize( error ))),
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
@ -56,17 +40,10 @@ impl error::Error for LoadError {
|
|||
fn description( &self ) -> &str {
|
||||
match *self {
|
||||
LoadError::Custom( ref message ) => &message[..],
|
||||
LoadError::IO( ref error ) => error.description()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From< io::Error > for LoadError {
|
||||
fn from( error: io::Error ) -> LoadError {
|
||||
LoadError::IO( error )
|
||||
}
|
||||
}
|
||||
|
||||
pub const ROM_BANK_SIZE: usize = 16 * 1024;
|
||||
pub const VROM_BANK_SIZE: usize = 8 * 1024;
|
||||
|
||||
|
@ -100,23 +77,23 @@ pub enum Mirroring {
|
|||
}
|
||||
|
||||
impl NesRom {
|
||||
pub fn load< T: Read + Seek >( fp: &mut T ) -> Result< Self, LoadError > {
|
||||
let magic = try!( fp.read_u32::< LittleEndian >() );
|
||||
pub fn load( mut data: &[u8] ) -> Result< Self, LoadError > {
|
||||
if data.len() < 16 {
|
||||
return Err( LoadError::new( "unexpected end of file" ) );
|
||||
}
|
||||
|
||||
let magic = u32::from_le_bytes( [data[0], data[1], data[2], data[3]] );
|
||||
if magic != 0x1a53454e {
|
||||
return Err( LoadError::new( format!( "Not an INES ROM file: magic number mismatch (got: 0x{:08X})", magic ) ) );
|
||||
}
|
||||
|
||||
let rom_bank_count = try!( fp.read_u8() ) as usize;
|
||||
let video_rom_bank_count = try!( fp.read_u8() ) as usize;
|
||||
let flags_1 = try!( fp.read_u8() );
|
||||
let flags_2 = try!( fp.read_u8() );
|
||||
let rom_bank_count = data[ 4 ] as usize;
|
||||
let video_rom_bank_count = data[ 5 ] as usize;
|
||||
let flags_1 = data[ 6 ];
|
||||
let flags_2 = data[ 7 ];
|
||||
|
||||
// For compatibility with older INES files we assume there must be always one RAM bank.
|
||||
let save_ram_length = max( 1, try!( fp.read_u8() ) as u32 ) * 8 * 1024;
|
||||
|
||||
// Skip padding.
|
||||
try!( fp.seek( SeekFrom::Current(7) ) );
|
||||
let save_ram_length = max( 1, data[ 8 ] as u32 ) * 8 * 1024;
|
||||
|
||||
let mirroring = {
|
||||
if flags_1 & 0b1000 != 0 {
|
||||
|
@ -131,20 +108,23 @@ impl NesRom {
|
|||
let has_trainer = flags_1 & 0b100 != 0;
|
||||
let mapper = (flags_2 & 0xF0) | ((flags_1 & 0xF0) >> 4);
|
||||
|
||||
let mut rom = Vec::< u8 >::with_capacity( rom_bank_count * ROM_BANK_SIZE );
|
||||
let mut video_rom = Vec::< u8 >::with_capacity( video_rom_bank_count * VROM_BANK_SIZE );
|
||||
|
||||
unsafe {
|
||||
rom.set_len( rom_bank_count * ROM_BANK_SIZE );
|
||||
video_rom.set_len( video_rom_bank_count * VROM_BANK_SIZE );
|
||||
}
|
||||
let rom_size = rom_bank_count * ROM_BANK_SIZE;
|
||||
let video_rom_size = video_rom_bank_count * VROM_BANK_SIZE;
|
||||
|
||||
data = &data[ 16.. ];
|
||||
if has_trainer {
|
||||
try!( fp.seek( SeekFrom::Current( 512 ) ) ); // Skip trainer.
|
||||
if data.len() < 512 {
|
||||
return Err( LoadError::new( "unexpected end of file" ) );
|
||||
}
|
||||
data = &data[ 512.. ]; // Skip trainer.
|
||||
}
|
||||
|
||||
try!( fp.read_exact( &mut rom[..] ) );
|
||||
try!( fp.read_exact( &mut video_rom[..] ) );
|
||||
if data.len() < rom_size + video_rom_size {
|
||||
return Err( LoadError::new( "unexpected end of file" ) );
|
||||
}
|
||||
|
||||
let rom = data[ ..rom_size ].to_vec();
|
||||
let video_rom = data[ rom_size..rom_size + video_rom_size ].to_vec();
|
||||
|
||||
Ok( NesRom {
|
||||
mapper: mapper,
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
use std::mem;
|
||||
use std::default::Default;
|
||||
use std::slice;
|
||||
use core::mem;
|
||||
use core::default::Default;
|
||||
use core::slice;
|
||||
use alloc::vec::Vec;
|
||||
|
||||
use emumisc::{WrappingExtra, BitExtra, HiLoAccess, PeekPoke, At, is_b5_set, is_b6_set, is_b7_set, reverse_bits};
|
||||
|
||||
|
|
|
@ -39,7 +39,7 @@ impl nes_testsuite::EmulatorInterface for Instance {
|
|||
testcase_state: testcase_state
|
||||
};
|
||||
|
||||
try!( nes::Interface::load_rom_from_memory( &mut instance, rom_data ) );
|
||||
try!( nes::Interface::load_rom( &mut instance, rom_data ) );
|
||||
Ok( instance )
|
||||
}
|
||||
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
use std::path::Path;
|
||||
use std::error::Error;
|
||||
use std::fs::File;
|
||||
use std::io::{Read, Seek};
|
||||
use std::mem;
|
||||
use core::error::Error;
|
||||
use core::mem;
|
||||
use alloc::boxed::Box;
|
||||
|
||||
use mos6502;
|
||||
use rp2c02;
|
||||
|
@ -24,16 +22,8 @@ pub trait Context: Sized {
|
|||
}
|
||||
|
||||
pub trait Interface: Sized + Context {
|
||||
fn load_rom< T: Read + Seek >( &mut self, stream: &mut T ) -> Result< (), LoadError > {
|
||||
Private::load_rom( self, stream )
|
||||
}
|
||||
|
||||
fn load_rom_from_memory( &mut self, buffer: &[u8] ) -> Result< (), LoadError > {
|
||||
Private::load_rom_from_memory( self, buffer )
|
||||
}
|
||||
|
||||
fn load_rom_from_file< P: AsRef< Path >>( &mut self, path: P ) -> Result< (), LoadError > {
|
||||
Private::load_rom_from_file( self, path )
|
||||
fn load_rom( &mut self, buffer: &[u8] ) -> Result< (), LoadError > {
|
||||
Private::load_rom( self, buffer )
|
||||
}
|
||||
|
||||
fn hard_reset( &mut self ) {
|
||||
|
@ -319,8 +309,10 @@ trait Private: Sized + Context {
|
|||
Orphan::< Self >::cast_mut( self )
|
||||
}
|
||||
|
||||
fn load_rom< T: Read + Seek >( &mut self, stream: &mut T ) -> Result< (), LoadError > {
|
||||
let rom = try!( NesRom::load( stream ) );
|
||||
fn load_rom( &mut self, buffer: &[u8] ) -> Result< (), LoadError > {
|
||||
let rom = try!( NesRom::load( buffer ) );
|
||||
|
||||
#[cfg(feature = "log")]
|
||||
info!( "Loaded ROM: {:?}", rom );
|
||||
|
||||
let mapper = try!( create_mapper( rom ) );
|
||||
|
@ -332,17 +324,6 @@ trait Private: Sized + Context {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn load_rom_from_memory( &mut self, buffer: &[u8] ) -> Result< (), LoadError > {
|
||||
use std::io::Cursor;
|
||||
let mut cursor = Cursor::new( buffer );
|
||||
self.load_rom( &mut cursor )
|
||||
}
|
||||
|
||||
fn load_rom_from_file< P: AsRef< Path >>( &mut self, path: P ) -> Result< (), LoadError > {
|
||||
let mut fp = try!( File::open( path ) );
|
||||
self.load_rom( &mut fp )
|
||||
}
|
||||
|
||||
fn hard_reset( &mut self ) {
|
||||
let mut mapper: Box< Mapper + 'static > = Box::new( MapperNull );
|
||||
mem::swap( &mut mapper, &mut self.state_mut().mapper );
|
||||
|
@ -456,6 +437,7 @@ trait Private: Sized + Context {
|
|||
4 => rp2c02::Interface::peek_oamdata( self.newtype_mut() ),
|
||||
7 => rp2c02::Interface::peek_ppudata( self.newtype_mut() ),
|
||||
_ => {
|
||||
#[cfg(feature = "log")]
|
||||
warn!( "Unhandled read from PPU register 0x{:04X}", address );
|
||||
0
|
||||
}
|
||||
|
@ -495,7 +477,10 @@ trait Private: Sized + Context {
|
|||
5 => rp2c02::Interface::poke_ppuscroll( self.newtype_mut(), value ),
|
||||
6 => rp2c02::Interface::poke_ppuaddr( self.newtype_mut(), value ),
|
||||
7 => rp2c02::Interface::poke_ppudata( self.newtype_mut(), value ),
|
||||
_ => warn!( "Unhandled write to PPU register 0x{:04X} (value=0x{:02X})", address, value )
|
||||
_ => {
|
||||
#[cfg(feature = "log")]
|
||||
warn!( "Unhandled write to PPU register 0x{:04X} (value=0x{:02X})", address, value )
|
||||
}
|
||||
}
|
||||
}, {
|
||||
match translate_address_ioreg_other( address ) {
|
||||
|
@ -535,7 +520,10 @@ trait Private: Sized + Context {
|
|||
let is_on_odd_cycle = self.is_on_odd_cycle();
|
||||
virtual_apu::Interface::poke_frame_sequencer_ctrl( self.newtype_mut(), value, is_on_odd_cycle )
|
||||
},
|
||||
_ => warn!( "Unhandled write to IO register 0x{:04X} (value=0x{:02X})", address, value )
|
||||
_ => {
|
||||
#[cfg(feature = "log")]
|
||||
warn!( "Unhandled write to IO register 0x{:04X} (value=0x{:02X})", address, value )
|
||||
}
|
||||
}
|
||||
}, {
|
||||
self.state().mapper.poke_expansion_rom( address, value );
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
extern crate std as core;
|
||||
|
||||
extern crate sdl2;
|
||||
extern crate clock_ticks;
|
||||
extern crate serde_json;
|
||||
|
|
|
@ -170,7 +170,7 @@ impl UserInterface {
|
|||
state: nes::State::new(),
|
||||
audio_buffer: Vec::new()
|
||||
};
|
||||
self.nes.load_rom_from_file( &self.rom_filename ).unwrap();
|
||||
self.nes.load_rom( &std::fs::read( &self.rom_filename ).unwrap() ).unwrap();
|
||||
|
||||
let frame;
|
||||
loop {
|
||||
|
@ -269,7 +269,8 @@ impl UserInterface {
|
|||
if let Some( filename ) = env::args().skip(1).next() {
|
||||
println!( "Loading '{}'...", filename );
|
||||
self.rom_filename = PathBuf::from( &filename );
|
||||
self.nes.load_rom_from_file( filename ).unwrap();
|
||||
let data = std::fs::read( filename ).unwrap();
|
||||
self.nes.load_rom( &data ).unwrap();
|
||||
|
||||
self.is_emulating = true;
|
||||
self.image_buffer.clear();
|
||||
|
|
|
@ -83,9 +83,15 @@ impl libretro_backend::Core for PinkyCore {
|
|||
}
|
||||
|
||||
let result = if let Some( data ) = game_data.data() {
|
||||
nes::Interface::load_rom_from_memory( self, data )
|
||||
nes::Interface::load_rom( self, data )
|
||||
} else if let Some( path ) = game_data.path() {
|
||||
nes::Interface::load_rom_from_file( self, path )
|
||||
let data = match std::fs::read( path ) {
|
||||
Ok( data ) => data,
|
||||
Err( _ ) => {
|
||||
return LoadGameResult::Failed( game_data );
|
||||
}
|
||||
};
|
||||
nes::Interface::load_rom( self, &data )
|
||||
} else {
|
||||
unreachable!();
|
||||
};
|
||||
|
|
|
@ -613,7 +613,7 @@ fn load_rom( pinky: &Rc< RefCell< PinkyWeb > >, rom_data: &[u8] ) {
|
|||
|
||||
let mut pinky = pinky.borrow_mut();
|
||||
let pinky = pinky.deref_mut();
|
||||
if let Err( err ) = nes::Interface::load_rom_from_memory( pinky, rom_data ) {
|
||||
if let Err( err ) = nes::Interface::load_rom( pinky, rom_data ) {
|
||||
handle_error( err );
|
||||
return;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue