mirror of
https://github.com/koute/pinky.git
synced 2024-06-01 02:48:08 -04:00
Allow for the state to be const initialized
This commit is contained in:
parent
af8ce41088
commit
8ebc612a53
|
@ -303,7 +303,7 @@ def generate_opcode_attributes
|
|||
}
|
||||
|
||||
impl OpcodeAttributes {
|
||||
fn empty() -> OpcodeAttributes {
|
||||
const fn empty() -> OpcodeAttributes {
|
||||
OpcodeAttributes {
|
||||
attr: 0
|
||||
}
|
||||
|
|
|
@ -115,14 +115,14 @@ pub struct State {
|
|||
}
|
||||
|
||||
impl State {
|
||||
pub fn new() -> State {
|
||||
pub const fn new() -> State {
|
||||
State {
|
||||
pc: 0,
|
||||
a: 0,
|
||||
x: 0,
|
||||
y: 0,
|
||||
sp: 0xFD,
|
||||
status: (StatusFlag::Unused | StatusFlag::IRQDisable).bits(),
|
||||
status: StatusFlag::Unused.bits() | StatusFlag::IRQDisable.bits(),
|
||||
irq_line_state: false,
|
||||
nmi_latch_state: false,
|
||||
nmi_pending: false,
|
||||
|
|
|
@ -716,7 +716,7 @@ macro_rules! decoding_logic {
|
|||
}
|
||||
|
||||
impl OpcodeAttributes {
|
||||
fn empty() -> OpcodeAttributes {
|
||||
const fn empty() -> OpcodeAttributes {
|
||||
OpcodeAttributes {
|
||||
attr: 0
|
||||
}
|
||||
|
|
|
@ -41,7 +41,7 @@ pub struct State {
|
|||
}
|
||||
|
||||
impl State {
|
||||
pub fn new() -> State {
|
||||
pub const fn new() -> State {
|
||||
State {
|
||||
dmc_dma_requested: false,
|
||||
dmc_dma_source_address: 0,
|
||||
|
|
|
@ -14,7 +14,7 @@ pub struct Filter {
|
|||
}
|
||||
|
||||
impl Filter {
|
||||
pub fn new() -> Filter {
|
||||
pub const fn new() -> Filter {
|
||||
Filter {
|
||||
delay_00: 0.0,
|
||||
delay_01: 0.0,
|
||||
|
|
|
@ -255,7 +255,8 @@ end
|
|||
|
||||
def generate_scanlines( constant_name, chunks_per_scanline )
|
||||
|
||||
output "static #{constant_name}: &'static [Scanline] = &["
|
||||
output "static #{constant_name}: &'static [Scanline] = #{constant_name}_CONST;"
|
||||
output "const #{constant_name}_CONST: &'static [Scanline] = &["
|
||||
|
||||
index = 0
|
||||
chunks_per_scanline.each do |scanline|
|
||||
|
@ -278,7 +279,8 @@ end
|
|||
|
||||
def generate_chunks( constant_name, chunks_per_scanline )
|
||||
|
||||
output "static #{constant_name}: &'static [Chunk] = &["
|
||||
output "static #{constant_name}: &'static [Chunk] = #{constant_name}_CONST;"
|
||||
output "const #{constant_name}_CONST: &'static [Chunk] = &["
|
||||
|
||||
index = 0
|
||||
chunks_per_scanline.flat_map { |scanline| scanline[:chunks] }.each do |chunk|
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
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};
|
||||
|
||||
|
@ -18,7 +17,7 @@ pub trait Context: Sized {
|
|||
|
||||
pub trait Interface: Sized + Context {
|
||||
#[inline]
|
||||
fn framebuffer( &self ) -> &Framebuffer {
|
||||
fn framebuffer( &mut self ) -> &Framebuffer {
|
||||
Private::framebuffer( self )
|
||||
}
|
||||
|
||||
|
@ -95,7 +94,7 @@ pub struct State {
|
|||
palette_ram: [u8; 32],
|
||||
sprite_list_ram: [u8; 256],
|
||||
secondary_sprite_list_ram: [u8; 32],
|
||||
framebuffer: Framebuffer,
|
||||
framebuffer: Option< Framebuffer >,
|
||||
odd_frame_flag: bool,
|
||||
vblank_flag_was_cleared: bool,
|
||||
|
||||
|
@ -151,12 +150,17 @@ pub struct State {
|
|||
}
|
||||
|
||||
impl State {
|
||||
pub fn new() -> State {
|
||||
pub const fn new() -> State {
|
||||
let last_scanline = match SCANLINES_CONST.last() {
|
||||
Some(value) => value,
|
||||
None => unreachable!()
|
||||
};
|
||||
|
||||
State {
|
||||
palette_ram: [0; 32],
|
||||
sprite_list_ram: [0; 64 * 4],
|
||||
secondary_sprite_list_ram: [0; 8 * 4],
|
||||
framebuffer: Framebuffer::new(),
|
||||
framebuffer: None,
|
||||
odd_frame_flag: false,
|
||||
vblank_flag_was_cleared: false,
|
||||
|
||||
|
@ -173,7 +177,7 @@ impl State {
|
|||
bg_palette_index_lo_shift_register: 0,
|
||||
bg_palette_index_hi_shift_register: 0,
|
||||
|
||||
sprites: [Sprite::default(); 8],
|
||||
sprites: [Sprite::new(); 8],
|
||||
|
||||
sprite_list_address: 0,
|
||||
ppudata_read_buffer: 0,
|
||||
|
@ -192,11 +196,11 @@ impl State {
|
|||
background_palette_index_latch: 0,
|
||||
tile_lo_latch: 0,
|
||||
tile_hi_latch: 0,
|
||||
scanline_index: SCANLINES.len() as u8 - 1, // Point at the prerender scanline.
|
||||
scanline_index: SCANLINES_CONST.len() as u8 - 1, // Point at the prerender scanline.
|
||||
scanline_counter: 0,
|
||||
chunk_index: SCANLINES.last().unwrap().first_chunk_index,
|
||||
chunk_index: last_scanline.first_chunk_index,
|
||||
chunk_counter: 0,
|
||||
action_index: CHUNKS[ SCANLINES.last().unwrap().first_chunk_index as usize ].first_action_index,
|
||||
action_index: CHUNKS_CONST[ last_scanline.first_chunk_index as usize ].first_action_index,
|
||||
auxiliary_sprite_list_address: 0,
|
||||
secondary_sprite_list_address: 0,
|
||||
sprite_list_data_latch: 0,
|
||||
|
@ -210,9 +214,12 @@ impl State {
|
|||
}
|
||||
}
|
||||
|
||||
fn initialize_framebuffer_if_needed( &mut self ) {
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn framebuffer( &self ) -> &Framebuffer {
|
||||
&self.framebuffer
|
||||
pub fn framebuffer( &mut self ) -> &mut Framebuffer {
|
||||
self.framebuffer.get_or_insert_with( Framebuffer::default )
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -220,7 +227,7 @@ impl State {
|
|||
struct PpuCtrl(u8);
|
||||
|
||||
impl PpuCtrl {
|
||||
fn new() -> PpuCtrl {
|
||||
const fn new() -> PpuCtrl {
|
||||
PpuCtrl(0)
|
||||
}
|
||||
|
||||
|
@ -273,7 +280,7 @@ impl PpuCtrl {
|
|||
struct PpuMask(u8);
|
||||
|
||||
impl PpuMask {
|
||||
fn new() -> PpuMask {
|
||||
const fn new() -> PpuMask {
|
||||
PpuMask(0)
|
||||
}
|
||||
|
||||
|
@ -296,7 +303,7 @@ impl PpuMask {
|
|||
struct PpuStatus(u8);
|
||||
|
||||
impl PpuStatus {
|
||||
fn new() -> PpuStatus {
|
||||
const fn new() -> PpuStatus {
|
||||
PpuStatus(0)
|
||||
}
|
||||
|
||||
|
@ -455,18 +462,11 @@ impl PpuStatus {
|
|||
Each scanline takes 341 PPU cycles, with each cycle producing one pixel.
|
||||
*/
|
||||
|
||||
#[derive(PartialEq, Eq)]
|
||||
pub struct Framebuffer {
|
||||
buffer: Vec< u16 >
|
||||
buffer: alloc::boxed::Box<[u16; 256 * 240]>
|
||||
}
|
||||
|
||||
impl PartialEq for Framebuffer {
|
||||
fn eq( &self, other: &Framebuffer ) -> bool {
|
||||
&self.buffer[..] == &other.buffer[..]
|
||||
}
|
||||
}
|
||||
|
||||
impl Eq for Framebuffer {}
|
||||
|
||||
impl Framebuffer {
|
||||
fn new() -> Framebuffer {
|
||||
Framebuffer::default()
|
||||
|
@ -534,11 +534,8 @@ impl< 'a > Iterator for FramebufferIterator< 'a > {
|
|||
|
||||
impl Default for Framebuffer {
|
||||
fn default() -> Self {
|
||||
let mut buffer = Vec::new();
|
||||
buffer.resize( 256 * 240, 0 );
|
||||
|
||||
Framebuffer {
|
||||
buffer
|
||||
buffer: alloc::boxed::Box::new([0; 256 * 240])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -649,6 +646,16 @@ struct Sprite {
|
|||
}
|
||||
|
||||
impl Sprite {
|
||||
#[inline]
|
||||
const fn new() -> Self {
|
||||
Sprite {
|
||||
pattern_lo_shift_register: 0,
|
||||
pattern_hi_shift_register: 0,
|
||||
attributes_latch: 0,
|
||||
dots_until_is_displayed: 0
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn display_sprite_behind_background( &self ) -> bool {
|
||||
is_b5_set( self.attributes_latch )
|
||||
|
@ -662,12 +669,7 @@ impl Sprite {
|
|||
|
||||
impl Default for Sprite {
|
||||
fn default() -> Self {
|
||||
Sprite {
|
||||
pattern_lo_shift_register: 0,
|
||||
pattern_hi_shift_register: 0,
|
||||
attributes_latch: 0,
|
||||
dots_until_is_displayed: 0
|
||||
}
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -883,12 +885,12 @@ trait Private: Sized + Context {
|
|||
(self.sprite_tile_hi_address() >> 8) as u8
|
||||
}
|
||||
|
||||
fn framebuffer( &self ) -> &Framebuffer {
|
||||
&self.state().framebuffer
|
||||
fn framebuffer( &mut self ) -> &Framebuffer {
|
||||
self.state_mut().framebuffer()
|
||||
}
|
||||
|
||||
fn swap_framebuffer( &mut self, mut other: Framebuffer ) -> Framebuffer {
|
||||
mem::swap( &mut self.state_mut().framebuffer, &mut other );
|
||||
mem::swap( self.state_mut().framebuffer(), &mut other );
|
||||
other
|
||||
}
|
||||
|
||||
|
@ -1077,7 +1079,13 @@ trait Private: Sized + Context {
|
|||
// let color_in_system_palette_index = self.state_mut().palette_ram.peek( (palette_index as usize * 4) + color_in_palette_index as usize );
|
||||
let nth = self.state().n_pixel;
|
||||
let pixel = ((self.state().ppumask.color_emphasize_bits() as u16) << 6) | (color_in_system_palette_index as u16);
|
||||
self.state_mut().framebuffer.buffer.poke( nth, pixel );
|
||||
{
|
||||
let framebuffer = match self.state_mut().framebuffer {
|
||||
Some( ref mut framebuffer ) => framebuffer,
|
||||
None => unsafe { core::hint::unreachable_unchecked() }
|
||||
};
|
||||
framebuffer.buffer.poke( nth, pixel );
|
||||
}
|
||||
self.state_mut().n_pixel += 1;
|
||||
}
|
||||
|
||||
|
@ -1093,6 +1101,8 @@ trait Private: Sized + Context {
|
|||
}
|
||||
|
||||
fn execute( &mut self ) {
|
||||
self.state_mut().framebuffer(); // Make sure the framebuffer is initialized.
|
||||
|
||||
self.execute_next_action();
|
||||
self.on_cycle();
|
||||
|
||||
|
|
|
@ -16,7 +16,8 @@ macro_rules! ppu_scheduling_logic {
|
|||
last_action_index: u16
|
||||
}
|
||||
|
||||
static SCANLINES: &'static [Scanline] = &[
|
||||
static SCANLINES: &'static [Scanline] = SCANLINES_CONST;
|
||||
const SCANLINES_CONST: &'static [Scanline] = &[
|
||||
Scanline {
|
||||
times: 1,
|
||||
first_chunk_index: 0,
|
||||
|
@ -59,7 +60,8 @@ macro_rules! ppu_scheduling_logic {
|
|||
},
|
||||
];
|
||||
|
||||
static CHUNKS: &'static [Chunk] = &[
|
||||
static CHUNKS: &'static [Chunk] = CHUNKS_CONST;
|
||||
const CHUNKS_CONST: &'static [Chunk] = &[
|
||||
Chunk {
|
||||
times: 1,
|
||||
first_action_index: 0,
|
||||
|
|
|
@ -160,11 +160,11 @@ pub struct State {
|
|||
}
|
||||
|
||||
impl State {
|
||||
pub fn new() -> State {
|
||||
pub const fn new() -> State {
|
||||
State {
|
||||
cycles_to_next_step: SEQUENCER_STEPS_MODE_0[ 2 ].0,
|
||||
cycles_to_next_step: SEQUENCER_STEPS_MODE_0_CONST[ 2 ].0,
|
||||
sequencer_reconfigured: None,
|
||||
sequencer_table: SEQUENCER_STEPS_MODE_0,
|
||||
sequencer_table: SEQUENCER_STEPS_MODE_0_CONST,
|
||||
sequencer_current_step: 2,
|
||||
sequencer_mode: SequencerMode::Mode0,
|
||||
inhibit_interrupts: false,
|
||||
|
@ -250,7 +250,7 @@ impl Sequence {
|
|||
fn clk_volume_generator( &self ) -> bool { self.6 }
|
||||
}
|
||||
|
||||
static SEQUENCER_STEPS_MODE_0: &'static [Sequence] = &[
|
||||
const SEQUENCER_STEPS_MODE_0_CONST: &'static [Sequence] = &[
|
||||
Sequence( 1, 1, false, false, false, false, false ),
|
||||
Sequence( 1, 2, false, false, false, false, false ),
|
||||
Sequence( 1, 3, false, false, false, false, false ),
|
||||
|
@ -262,6 +262,8 @@ static SEQUENCER_STEPS_MODE_0: &'static [Sequence] = &[
|
|||
Sequence( 1, 3, true, false, false, false, false )
|
||||
];
|
||||
|
||||
static SEQUENCER_STEPS_MODE_0: &'static [Sequence] = SEQUENCER_STEPS_MODE_0_CONST;
|
||||
|
||||
static SEQUENCER_STEPS_MODE_1: &'static [Sequence] = &[
|
||||
Sequence( 1, 1, false, false, false, false, false ),
|
||||
Sequence( 3, 2, false, true, true, true, true ),
|
||||
|
@ -313,7 +315,7 @@ struct Channel {
|
|||
}
|
||||
|
||||
impl Channel {
|
||||
fn new() -> Channel {
|
||||
const fn new() -> Channel {
|
||||
Channel {
|
||||
length_counter: 0,
|
||||
length_counter_disabled: false,
|
||||
|
@ -365,7 +367,7 @@ struct VolumeGenerator {
|
|||
}
|
||||
|
||||
impl VolumeGenerator {
|
||||
fn new() -> VolumeGenerator {
|
||||
const fn new() -> VolumeGenerator {
|
||||
VolumeGenerator {
|
||||
is_manually_controlled: false,
|
||||
should_loop: false,
|
||||
|
@ -445,7 +447,7 @@ struct ChannelSquare {
|
|||
}
|
||||
|
||||
impl ChannelSquare {
|
||||
fn new( is_second_channel: bool ) -> ChannelSquare {
|
||||
const fn new( is_second_channel: bool ) -> ChannelSquare {
|
||||
ChannelSquare {
|
||||
base: Channel::new(),
|
||||
duty: SquareChannelDuty::Duty125,
|
||||
|
@ -592,7 +594,7 @@ struct ChannelTriangle {
|
|||
}
|
||||
|
||||
impl ChannelTriangle {
|
||||
fn new() -> ChannelTriangle {
|
||||
const fn new() -> ChannelTriangle {
|
||||
ChannelTriangle {
|
||||
base: Channel::new(),
|
||||
period: 0,
|
||||
|
@ -699,7 +701,7 @@ struct ChannelNoise {
|
|||
}
|
||||
|
||||
impl ChannelNoise {
|
||||
fn new() -> ChannelNoise {
|
||||
const fn new() -> ChannelNoise {
|
||||
ChannelNoise {
|
||||
base: Channel::new(),
|
||||
volume_generator: VolumeGenerator::new(),
|
||||
|
@ -786,7 +788,7 @@ struct ChannelDeltaModulation {
|
|||
// The DMC channel plays back DPCM samples stored in memory as 1-bit deltas.
|
||||
// A bit of 1 will increment the output; a bit of 0 will decrement the output.
|
||||
impl ChannelDeltaModulation {
|
||||
fn new() -> ChannelDeltaModulation {
|
||||
const fn new() -> ChannelDeltaModulation {
|
||||
ChannelDeltaModulation {
|
||||
enabled: false,
|
||||
|
||||
|
|
|
@ -50,7 +50,7 @@ pub trait Interface: Sized + Context {
|
|||
Private::execute_cycle( self )
|
||||
}
|
||||
|
||||
fn framebuffer( &self ) -> &rp2c02::Framebuffer {
|
||||
fn framebuffer( &mut self ) -> &rp2c02::Framebuffer {
|
||||
Private::framebuffer( self )
|
||||
}
|
||||
|
||||
|
@ -87,12 +87,13 @@ impl< T: Context > Interface for T {}
|
|||
impl< T: Context > Private for T {}
|
||||
|
||||
pub struct State {
|
||||
mapper_null: MapperNull,
|
||||
ram: [u8; 2048],
|
||||
cpu_state: mos6502::State,
|
||||
ppu_state: rp2c02::State,
|
||||
apu_state: virtual_apu::State,
|
||||
dma_state: dma::State,
|
||||
mapper: Box< dyn Mapper >,
|
||||
mapper: Option< Box< dyn Mapper > >,
|
||||
error: Option< Box< dyn Error > >,
|
||||
ready: bool,
|
||||
cpu_cycle: u32,
|
||||
|
@ -107,14 +108,15 @@ pub struct State {
|
|||
}
|
||||
|
||||
impl State {
|
||||
pub fn new() -> State {
|
||||
pub const fn new() -> State {
|
||||
State {
|
||||
mapper_null: MapperNull,
|
||||
ram: [0; 2048],
|
||||
cpu_state: mos6502::State::new(),
|
||||
ppu_state: rp2c02::State::new(),
|
||||
apu_state: virtual_apu::State::new(),
|
||||
dma_state: dma::State::new(),
|
||||
mapper: Box::new( MapperNull ),
|
||||
mapper: None,
|
||||
error: None,
|
||||
ready: false,
|
||||
cpu_cycle: 0,
|
||||
|
@ -130,9 +132,19 @@ impl State {
|
|||
}
|
||||
|
||||
#[inline]
|
||||
pub fn framebuffer( &self ) -> &rp2c02::Framebuffer {
|
||||
pub fn framebuffer( &mut self ) -> &rp2c02::Framebuffer {
|
||||
self.ppu_state.framebuffer()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn mapper( &self ) -> &dyn Mapper {
|
||||
self.mapper.as_ref().map( |mapper| &**mapper ).unwrap_or( &self.mapper_null )
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn mapper_mut( &mut self ) -> &mut dyn Mapper {
|
||||
self.mapper.as_mut().map( |mapper| &mut **mapper ).unwrap_or( &mut self.mapper_null )
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Eq, PartialEq, Copy, Clone)]
|
||||
|
@ -221,12 +233,12 @@ impl< C: Context > rp2c02::Context for Orphan< C > {
|
|||
|
||||
#[inline]
|
||||
fn peek_video_memory( &self, address: u16 ) -> u8 {
|
||||
self.as_ref().state().mapper.peek_video_memory( address )
|
||||
self.as_ref().state().mapper().peek_video_memory( address )
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn poke_video_memory( &mut self, address: u16, value: u8 ) {
|
||||
self.as_mut().state_mut().mapper.poke_video_memory( address, value );
|
||||
self.as_mut().state_mut().mapper_mut().poke_video_memory( address, value );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -320,7 +332,7 @@ trait Private: Sized + Context {
|
|||
|
||||
let mapper = create_mapper( rom )?;
|
||||
|
||||
self.state_mut().mapper = mapper;
|
||||
self.state_mut().mapper = Some( mapper );
|
||||
self.state_mut().ready = true;
|
||||
self.hard_reset();
|
||||
|
||||
|
@ -328,7 +340,7 @@ trait Private: Sized + Context {
|
|||
}
|
||||
|
||||
fn hard_reset( &mut self ) {
|
||||
let mut mapper: Box< dyn Mapper + 'static > = Box::new( MapperNull );
|
||||
let mut mapper: Option< Box< dyn Mapper + 'static > > = None;
|
||||
mem::swap( &mut mapper, &mut self.state_mut().mapper );
|
||||
let ready = self.state().ready;
|
||||
|
||||
|
@ -405,8 +417,8 @@ trait Private: Sized + Context {
|
|||
Ok( self.state().full_frame_counter != last_counter_value )
|
||||
}
|
||||
|
||||
fn framebuffer( &self ) -> &rp2c02::Framebuffer {
|
||||
rp2c02::Interface::framebuffer( self.newtype() )
|
||||
fn framebuffer( &mut self ) -> &rp2c02::Framebuffer {
|
||||
rp2c02::Interface::framebuffer( self.newtype_mut() )
|
||||
}
|
||||
|
||||
fn swap_framebuffer( &mut self, other: rp2c02::Framebuffer ) -> rp2c02::Framebuffer {
|
||||
|
@ -461,11 +473,11 @@ trait Private: Sized + Context {
|
|||
_ => unsafe { fast_unreachable!() }
|
||||
}
|
||||
}, {
|
||||
self.state().mapper.peek_expansion_rom( address )
|
||||
self.state().mapper().peek_expansion_rom( address )
|
||||
}, {
|
||||
self.state().mapper.peek_sram( address )
|
||||
self.state().mapper().peek_sram( address )
|
||||
}, {
|
||||
self.state().mapper.peek_rom( address )
|
||||
self.state().mapper().peek_rom( address )
|
||||
}
|
||||
)
|
||||
}
|
||||
|
@ -533,11 +545,11 @@ trait Private: Sized + Context {
|
|||
}
|
||||
}
|
||||
}, {
|
||||
self.state().mapper.poke_expansion_rom( address, value );
|
||||
self.state().mapper().poke_expansion_rom( address, value );
|
||||
}, {
|
||||
self.state_mut().mapper.poke_sram( address, value );
|
||||
self.state_mut().mapper_mut().poke_sram( address, value );
|
||||
}, {
|
||||
self.state_mut().mapper.poke_rom( address, value );
|
||||
self.state_mut().mapper_mut().poke_rom( address, value );
|
||||
}
|
||||
)
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue