Some simplification

This commit is contained in:
Sergio Martin 2024-01-14 17:05:10 +01:00
parent 361b42be9c
commit d8b904f53f
14 changed files with 366 additions and 473 deletions

View File

@ -5,17 +5,95 @@
// Nes_Snd_Emu 0.1.7
#include <cstdint>
#include "blargg_source.h"
#include "blargg_endian.h"
typedef long nes_time_t; // CPU clock cycle count
typedef unsigned nes_addr_t; // 16-bit memory address
#include "Nes_Oscs.h"
struct apu_state_t;
class Nes_Buffer;
class Nes_Apu {
public:
typedef uint8_t env_t [3];
/*struct env_t {
uint8_t delay;
uint8_t env;
uint8_t written;
};*/
struct apu_t {
uint8_t w40xx [0x14]; // $4000-$4013
uint8_t w4015; // enables
uint8_t w4017; // mode
uint16_t frame_delay;
uint8_t frame_step;
uint8_t irq_flag;
};
struct square_t {
uint16_t delay;
env_t env;
uint8_t length_counter;
uint8_t phase;
uint8_t swp_delay;
uint8_t swp_reset;
uint8_t unused2 [1];
};
struct triangle_t {
uint16_t delay;
uint8_t length_counter;
uint8_t phase;
uint8_t linear_counter;
uint8_t linear_mode;
};
struct noise_t {
uint16_t delay;
env_t env;
uint8_t length_counter;
uint16_t shift_reg;
};
struct dmc_t {
uint16_t delay;
uint16_t remain;
uint16_t addr;
uint8_t buf;
uint8_t bits_remain;
uint8_t bits;
uint8_t buf_full;
uint8_t silence;
uint8_t irq_flag;
};
struct apu_state_t
{
apu_t apu;
square_t square1;
square_t square2;
triangle_t triangle;
noise_t noise;
dmc_t dmc;
enum { tag = 0x41505552 }; // 'APUR'
void swap()
{
SWAP_LE( apu.frame_delay );
SWAP_LE( square1.delay );
SWAP_LE( square2.delay );
SWAP_LE( triangle.delay );
SWAP_LE( noise.delay );
SWAP_LE( noise.shift_reg );
SWAP_LE( dmc.delay );
SWAP_LE( dmc.remain );
SWAP_LE( dmc.addr );
}
};
BOOST_STATIC_ASSERT( sizeof (apu_state_t) == 72 );
Nes_Apu();
~Nes_Apu();
@ -172,3 +250,125 @@ inline nes_time_t Nes_Dmc::next_read_time() const
inline nes_time_t Nes_Apu::next_dmc_read_time() const { return dmc.next_read_time(); }
template<int mode>
struct apu_reflection
{
#define REFLECT( apu, state ) (mode ? void (apu = state) : void (state = apu))
static void reflect_env( Nes_Apu::env_t* state, Nes_Envelope& osc )
{
REFLECT( (*state) [0], osc.env_delay );
REFLECT( (*state) [1], osc.envelope );
REFLECT( (*state) [2], osc.reg_written [3] );
}
static void reflect_square( Nes_Apu::square_t& state, Nes_Square& osc )
{
reflect_env( &state.env, osc );
REFLECT( state.delay, osc.delay );
REFLECT( state.length_counter, osc.length_counter );
REFLECT( state.phase, osc.phase );
REFLECT( state.swp_delay, osc.sweep_delay );
REFLECT( state.swp_reset, osc.reg_written [1] );
}
static void reflect_triangle( Nes_Apu::triangle_t& state, Nes_Triangle& osc )
{
REFLECT( state.delay, osc.delay );
REFLECT( state.length_counter, osc.length_counter );
REFLECT( state.linear_counter, osc.linear_counter );
REFLECT( state.phase, osc.phase );
REFLECT( state.linear_mode, osc.reg_written [3] );
}
static void reflect_noise( Nes_Apu::noise_t& state, Nes_Noise& osc )
{
reflect_env( &state.env, osc );
REFLECT( state.delay, osc.delay );
REFLECT( state.length_counter, osc.length_counter );
REFLECT( state.shift_reg, osc.noise );
}
static void reflect_dmc( Nes_Apu::dmc_t& state, Nes_Dmc& osc )
{
REFLECT( state.delay, osc.delay );
REFLECT( state.remain, osc.length_counter );
REFLECT( state.buf, osc.buf );
REFLECT( state.bits_remain, osc.bits_remain );
REFLECT( state.bits, osc.bits );
REFLECT( state.buf_full, osc.buf_full );
REFLECT( state.silence, osc.silence );
REFLECT( state.irq_flag, osc.irq_flag );
if ( mode )
state.addr = osc.address | 0x8000;
else
osc.address = state.addr & 0x7fff;
}
};
inline void Nes_Apu::save_state( apu_state_t* state ) const
{
for ( int i = 0; i < osc_count * 4; i++ )
{
int index = i >> 2;
state->apu.w40xx [i] = oscs [index]->regs [i & 3];
//if ( index < 4 )
// state->length_counters [index] = oscs [index]->length_counter;
}
state->apu.w40xx [0x11] = dmc.dac;
state->apu.w4015 = osc_enables;
state->apu.w4017 = frame_mode;
state->apu.frame_delay = frame_delay;
state->apu.frame_step = frame;
state->apu.irq_flag = irq_flag;
typedef apu_reflection<1> refl;
Nes_Apu& apu = *(Nes_Apu*) this; // const_cast
refl::reflect_square ( state->square1, apu.square1 );
refl::reflect_square ( state->square2, apu.square2 );
refl::reflect_triangle( state->triangle, apu.triangle );
refl::reflect_noise ( state->noise, apu.noise );
refl::reflect_dmc ( state->dmc, apu.dmc );
}
inline void Nes_Apu::load_state( apu_state_t const& state )
{
reset();
write_register( 0, 0x4017, state.apu.w4017 );
write_register( 0, 0x4015, state.apu.w4015 );
osc_enables = state.apu.w4015; // DMC clears bit 4
for ( int i = 0; i < osc_count * 4; i++ )
{
int n = state.apu.w40xx [i];
int index = i >> 2;
oscs [index]->regs [i & 3] = n;
write_register( 0, 0x4000 + i, n );
//if ( index < 4 )
// oscs [index]->length_counter = state.length_counters [index];
}
frame_delay = state.apu.frame_delay;
frame = state.apu.frame_step;
irq_flag = state.apu.irq_flag;
typedef apu_reflection<0> refl;
apu_state_t& st = (apu_state_t&) state; // const_cast
refl::reflect_square ( st.square1, square1 );
refl::reflect_square ( st.square2, square2 );
refl::reflect_triangle( st.triangle, triangle );
refl::reflect_noise ( st.noise, noise );
refl::reflect_dmc ( st.dmc, dmc );
dmc.recalc_irq();
//force channels to have correct last_amp levels after load state
square1.run(last_time, last_time);
square2.run(last_time, last_time);
triangle.run(last_time, last_time);
noise.run(last_time, last_time);
dmc.run(last_time, last_time);
}

View File

@ -2,8 +2,8 @@
// Nes_Emu 0.7.0. http://www.slack.net/~ant/
#include "Nes_File.h"
#include "blargg_endian.h"
#include "blargg_source.h"
/* Copyright (C) 2004-2006 Shay Green. This module is free software; you
can redistribute it and/or modify it under the terms of the GNU Lesser
@ -16,7 +16,6 @@ more details. You should have received a copy of the GNU Lesser General
Public License along with this module; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#include "blargg_source.h"
// Nes_File_Writer

View File

@ -7,6 +7,7 @@
#include <string.h>
#include "blargg_endian.h"
#include "Nes_Apu.h"
#include "Nes_Emu.h"
#include "Nes_Mapper.h"
@ -121,7 +122,7 @@ const char * Nes_State_::write_blocks( Nes_File_Writer& out ) const
if ( apu_valid )
{
apu_state_t s = *apu;
Nes_Apu::apu_state_t s = *apu;
RETURN_ERR( write_nes_state( out, s ) );
}
@ -232,7 +233,7 @@ const char * Nes_State_::read_blocks( Nes_File_Reader& in )
ppu_valid = true;
break;
case apu_state_t::tag:
case FOUR_CHAR('APUR'):
memset( apu, 0, sizeof *apu );
RETURN_ERR( read_nes_state( in, apu ) );
apu_valid = true;

View File

@ -8,6 +8,7 @@
#include "Nes_File.h"
#include "Nes_Cpu.h"
#include "Nes_Apu.h"
class Nes_Emu;
class Nes_State;
@ -63,7 +64,7 @@ public:
nes_state_t nes;
Nes_Cpu::registers_t* cpu;
joypad_state_t* joypad;
apu_state_t* apu;
Nes_Apu::apu_state_t* apu;
ppu_state_t* ppu;
mapper_state_t* mapper;
@ -96,7 +97,7 @@ public:
private:
Nes_Cpu::registers_t cpu;
joypad_state_t joypad;
apu_state_t apu;
Nes_Apu::apu_state_t apu;
ppu_state_t ppu;
mapper_state_t mapper;
uint8_t ram [ram_size];

View File

@ -1,124 +0,0 @@
#include "abstract_file.h"
#include "blargg_config.h"
#include <string.h>
#include <stdlib.h>
/* Copyright (C) 2005-2006 Shay Green. Permission is hereby granted, free of
charge, to any person obtaining a copy of this software module and associated
documentation files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use, copy, modify,
merge, publish, distribute, sublicense, and/or sell copies of the Software, and
to permit persons to whom the Software is furnished to do so, subject to the
following conditions: The above copyright notice and this permission notice
shall be included in all copies or substantial portions of the Software. THE
SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
const char *Data_Writer::write( const void*, long ) { return 0; }
// Mem_Writer
Mem_Writer::Mem_Writer( void* p, long s, int b )
{
data_ = (char*) p;
size_ = 0;
allocated = s;
mode = b ? ignore_excess : fixed;
}
Mem_Writer::Mem_Writer()
{
data_ = 0;
size_ = 0;
allocated = 0;
mode = expanding;
}
Mem_Writer::~Mem_Writer()
{
if ( ( mode == expanding ) && data_ )
free( data_ );
}
const char *Mem_Writer::write( const void* p, long s )
{
long remain = allocated - size_;
if ( s > remain )
{
if ( mode == fixed )
return "Tried to write more data than expected";
if ( mode == ignore_excess )
{
s = remain;
}
else // expanding
{
long new_allocated = size_ + s;
new_allocated += (new_allocated >> 1) + 2048;
void* p = realloc( data_, new_allocated );
if ( !p )
return "Out of memory";
data_ = (char*) p;
allocated = new_allocated;
}
}
memcpy( data_ + size_, p, s );
size_ += s;
return 0;
}
// Dry_Writer for determining size
Dry_Writer::Dry_Writer()
{
size_ = 0;
}
Dry_Writer::~Dry_Writer()
{
}
const char *Dry_Writer::write( const void* p, long s )
{
size_ += s;
return 0;
}
// Auto_File_Reader
const char* Auto_File_Reader::open()
{
return 0;
}
Auto_File_Reader::~Auto_File_Reader()
{
if ( path )
delete data;
}
// Auto_File_Writer
const char* Auto_File_Writer::open()
{
return 0;
}
const char* Auto_File_Writer::open_comp( int level )
{
return 0;
}
Auto_File_Writer::~Auto_File_Writer()
{
}

View File

@ -1,12 +1,24 @@
#pragma once
/* Copyright (C) 2005-2006 Shay Green. Permission is hereby granted, free of
charge, to any person obtaining a copy of this software module and associated
documentation files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use, copy, modify,
merge, publish, distribute, sublicense, and/or sell copies of the Software, and
to permit persons to whom the Software is furnished to do so, subject to the
following conditions: The above copyright notice and this permission notice
shall be included in all copies or substantial portions of the Software. THE
SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
// Abstract file access interfaces
#ifndef ABSTRACT_FILE_H
#define ABSTRACT_FILE_H
#undef BLARGG_CONFIG_H
#include "Data_Reader.h"
#include <cstring>
// Supports writing
class Data_Writer {
@ -15,8 +27,8 @@ public:
virtual ~Data_Writer() { }
// Write 'n' bytes. NULL on success, otherwise error string.
virtual const char *write( const void*, long n ) = 0;
virtual const char *write( const void*, long ) { return 0; }
private:
// noncopyable
Data_Writer( const Data_Writer& );
@ -31,39 +43,93 @@ class Mem_Writer : public Data_Writer {
enum { expanding, fixed, ignore_excess } mode;
public:
// Keep all written data in expanding block of memory
Mem_Writer();
Mem_Writer()
{
data_ = 0;
size_ = 0;
allocated = 0;
mode = expanding;
}
// Write to fixed-size block of memory. If ignore_excess is false, returns
// error if more than 'size' data is written, otherwise ignores any excess.
Mem_Writer( void*, long size, int ignore_excess = 0 );
const char *write( const void*, long );
Mem_Writer( void* p, long s, int b )
{
data_ = (char*) p;
size_ = 0;
allocated = s;
mode = b ? ignore_excess : fixed;
}
const char * write( const void* p, long s )
{
long remain = allocated - size_;
if ( s > remain )
{
if ( mode == fixed )
return "Tried to write more data than expected";
if ( mode == ignore_excess )
{
s = remain;
}
else // expanding
{
long new_allocated = size_ + s;
new_allocated += (new_allocated >> 1) + 2048;
void* p = realloc( data_, new_allocated );
if ( !p )
return "Out of memory";
data_ = (char*) p;
allocated = new_allocated;
}
}
memcpy( data_ + size_, p, s );
size_ += s;
return 0;
}
// Pointer to beginning of written data
char* data() { return data_; }
// Number of bytes written
size_t size() const { return size_; }
~Mem_Writer();
~Mem_Writer()
{
if ( ( mode == expanding ) && data_ ) free( data_ );
}
};
// Dry writer to get the state size
class Dry_Writer : public Data_Writer {
long size_;
public:
// Keep all written data in expanding block of memory
Dry_Writer();
const char *write( const void*, long );
Dry_Writer()
{
size_ = 0;
}
~Dry_Writer()
{
}
const char *write( const void* p, long s )
{
size_ += s;
return 0;
}
// Pointer to beginning of written data
char* data() { return NULL; }
// Number of bytes written
long size() const { return size_; }
~Dry_Writer();
};
@ -76,9 +142,18 @@ public:
Auto_File_Reader( Data_Reader& r ) : data( &r ), path( 0 ) { }
Auto_File_Reader( Auto_File_Reader const& );
Auto_File_Reader& operator = ( Auto_File_Reader const& );
~Auto_File_Reader();
const char* open();
const char* open()
{
return 0;
}
~Auto_File_Reader()
{
if ( path )
delete data;
}
int operator ! () const { return !data; }
Data_Reader* operator -> () const { return data; }
Data_Reader& operator * () const { return *data; }
@ -93,9 +168,20 @@ public:
Auto_File_Writer( Data_Writer& r ) : data( &r ), path( 0 ) { }
Auto_File_Writer( Auto_File_Writer const& );
Auto_File_Writer& operator = ( Auto_File_Writer const& );
~Auto_File_Writer();
const char* open();
const char* open_comp( int level = -1 ); // compress output if possible
~Auto_File_Writer()
{
}
const char* open()
{
return 0;
}
const char* open_comp( int level = -1 )
{
return 0;
}
int operator ! () const { return !data; }
Data_Writer* operator -> () const { return data; }
@ -122,5 +208,3 @@ inline Auto_File_Writer& Auto_File_Writer::operator = ( Auto_File_Writer const&
return *this;
}
inline Auto_File_Writer::Auto_File_Writer( Auto_File_Writer const& r ) { *this = r; }
#endif

View File

@ -1,139 +0,0 @@
// Nes_Snd_Emu 0.1.7. http://www.slack.net/~ant/libs/
#include "apu_state.h"
#include "Nes_Apu.h"
/* Copyright (C) 2003-2006 Shay Green. This module is free software; you
can redistribute it and/or modify it under the terms of the GNU Lesser
General Public License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version. This
module is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
more details. You should have received a copy of the GNU Lesser General
Public License along with this module; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#include "blargg_source.h"
template<int mode>
struct apu_reflection
{
#define REFLECT( apu, state ) (mode ? void (apu = state) : void (state = apu))
static void reflect_env( apu_state_t::env_t* state, Nes_Envelope& osc )
{
REFLECT( (*state) [0], osc.env_delay );
REFLECT( (*state) [1], osc.envelope );
REFLECT( (*state) [2], osc.reg_written [3] );
}
static void reflect_square( apu_state_t::square_t& state, Nes_Square& osc )
{
reflect_env( &state.env, osc );
REFLECT( state.delay, osc.delay );
REFLECT( state.length_counter, osc.length_counter );
REFLECT( state.phase, osc.phase );
REFLECT( state.swp_delay, osc.sweep_delay );
REFLECT( state.swp_reset, osc.reg_written [1] );
}
static void reflect_triangle( apu_state_t::triangle_t& state, Nes_Triangle& osc )
{
REFLECT( state.delay, osc.delay );
REFLECT( state.length_counter, osc.length_counter );
REFLECT( state.linear_counter, osc.linear_counter );
REFLECT( state.phase, osc.phase );
REFLECT( state.linear_mode, osc.reg_written [3] );
}
static void reflect_noise( apu_state_t::noise_t& state, Nes_Noise& osc )
{
reflect_env( &state.env, osc );
REFLECT( state.delay, osc.delay );
REFLECT( state.length_counter, osc.length_counter );
REFLECT( state.shift_reg, osc.noise );
}
static void reflect_dmc( apu_state_t::dmc_t& state, Nes_Dmc& osc )
{
REFLECT( state.delay, osc.delay );
REFLECT( state.remain, osc.length_counter );
REFLECT( state.buf, osc.buf );
REFLECT( state.bits_remain, osc.bits_remain );
REFLECT( state.bits, osc.bits );
REFLECT( state.buf_full, osc.buf_full );
REFLECT( state.silence, osc.silence );
REFLECT( state.irq_flag, osc.irq_flag );
if ( mode )
state.addr = osc.address | 0x8000;
else
osc.address = state.addr & 0x7fff;
}
};
void Nes_Apu::save_state( apu_state_t* state ) const
{
for ( int i = 0; i < osc_count * 4; i++ )
{
int index = i >> 2;
state->apu.w40xx [i] = oscs [index]->regs [i & 3];
//if ( index < 4 )
// state->length_counters [index] = oscs [index]->length_counter;
}
state->apu.w40xx [0x11] = dmc.dac;
state->apu.w4015 = osc_enables;
state->apu.w4017 = frame_mode;
state->apu.frame_delay = frame_delay;
state->apu.frame_step = frame;
state->apu.irq_flag = irq_flag;
typedef apu_reflection<1> refl;
Nes_Apu& apu = *(Nes_Apu*) this; // const_cast
refl::reflect_square ( state->square1, apu.square1 );
refl::reflect_square ( state->square2, apu.square2 );
refl::reflect_triangle( state->triangle, apu.triangle );
refl::reflect_noise ( state->noise, apu.noise );
refl::reflect_dmc ( state->dmc, apu.dmc );
}
void Nes_Apu::load_state( apu_state_t const& state )
{
reset();
write_register( 0, 0x4017, state.apu.w4017 );
write_register( 0, 0x4015, state.apu.w4015 );
osc_enables = state.apu.w4015; // DMC clears bit 4
for ( int i = 0; i < osc_count * 4; i++ )
{
int n = state.apu.w40xx [i];
int index = i >> 2;
oscs [index]->regs [i & 3] = n;
write_register( 0, 0x4000 + i, n );
//if ( index < 4 )
// oscs [index]->length_counter = state.length_counters [index];
}
frame_delay = state.apu.frame_delay;
frame = state.apu.frame_step;
irq_flag = state.apu.irq_flag;
typedef apu_reflection<0> refl;
apu_state_t& st = (apu_state_t&) state; // const_cast
refl::reflect_square ( st.square1, square1 );
refl::reflect_square ( st.square2, square2 );
refl::reflect_triangle( st.triangle, triangle );
refl::reflect_noise ( st.noise, noise );
refl::reflect_dmc ( st.dmc, dmc );
dmc.recalc_irq();
//force channels to have correct last_amp levels after load state
square1.run(last_time, last_time);
square2.run(last_time, last_time);
triangle.run(last_time, last_time);
noise.run(last_time, last_time);
dmc.run(last_time, last_time);
}

View File

@ -1,77 +0,0 @@
// NES APU state snapshot support
// Nes_Snd_Emu 0.1.7
#ifndef APU_STATE_H
#define APU_STATE_H
#include <stdint.h>
#include "blargg_common.h"
struct apu_state_t
{
typedef uint8_t env_t [3];
/*struct env_t {
uint8_t delay;
uint8_t env;
uint8_t written;
};*/
struct apu_t {
uint8_t w40xx [0x14]; // $4000-$4013
uint8_t w4015; // enables
uint8_t w4017; // mode
uint16_t frame_delay;
uint8_t frame_step;
uint8_t irq_flag;
} apu;
struct square_t {
uint16_t delay;
env_t env;
uint8_t length_counter;
uint8_t phase;
uint8_t swp_delay;
uint8_t swp_reset;
uint8_t unused2 [1];
};
square_t square1;
square_t square2;
struct triangle_t {
uint16_t delay;
uint8_t length_counter;
uint8_t phase;
uint8_t linear_counter;
uint8_t linear_mode;
} triangle;
struct noise_t {
uint16_t delay;
env_t env;
uint8_t length_counter;
uint16_t shift_reg;
} noise;
struct dmc_t {
uint16_t delay;
uint16_t remain;
uint16_t addr;
uint8_t buf;
uint8_t bits_remain;
uint8_t bits;
uint8_t buf_full;
uint8_t silence;
uint8_t irq_flag;
} dmc;
//uint8_t length_counters [4];
enum { tag = 0x41505552 }; // 'APUR'
void swap();
};
BOOST_STATIC_ASSERT( sizeof (apu_state_t) == 72 );
#endif

View File

@ -34,9 +34,6 @@ arithmetic on smaller types. */
// In case compiler doesn't support these properly. Used rarely.
#define STATIC_CAST(T,expr) static_cast<T> (expr)
// User configuration can override the above macros if necessary
#include "blargg_config.h"
// BOOST_STATIC_ASSERT( expr ): Generates compile error if expr is 0.
#ifndef BOOST_STATIC_ASSERT
#ifdef _MSC_VER

View File

@ -1,17 +0,0 @@
// Library configuration. Modify this file as necessary.
// File_Extractor 1.0.0
#ifndef BLARGG_CONFIG_H
#define BLARGG_CONFIG_H
#ifndef HAVE_STDINT_H
#define HAVE_STDINT_H
#endif
// Use standard config.h if present
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#endif

View File

@ -1,11 +1,9 @@
#pragma once
// CPU Byte Order Utilities
// Nes_Emu 0.7.0
#ifndef BLARGG_ENDIAN
#define BLARGG_ENDIAN
#include "blargg_common.h"
// BLARGG_CPU_CISC: Defined if CPU has very few general-purpose registers (< 16)
@ -105,4 +103,5 @@ inline void set_be( uint32_t* p, unsigned long n ) { SET_BE32( p, n ); }
inline unsigned get_be( uint16_t* p ) { return GET_BE16( p ); }
inline unsigned long get_be( uint32_t* p ) { return GET_BE32( p ); }
#endif
#define SWAP_BE( n ) (void) (set_be( &(n), (n) ))
#define SWAP_LE( n ) (void) (set_le( &(n), (n) ))

View File

@ -1,23 +1,18 @@
# quickerNES Core sources
quickerNESCoreSrc = [
'abstract_file.cpp',
'Nes_Apu.cpp',
'Nes_File.cpp',
'Nes_Oscs.cpp',
'apu_state.cpp',
'Nes_Buffer.cpp',
'Nes_Fme7_Apu.cpp',
'Nes_Ppu.cpp',
'Blip_Buffer.cpp',
'Nes_Cart.cpp',
'Nes_Mapper.cpp',
'Nes_Ppu_Impl.cpp',
'Data_Reader.cpp',
'Nes_Core.cpp',
'Nes_Ppu_Rendering.cpp',
'Effects_Buffer.cpp',
'Nes_Cpu.cpp',
'Nes_State.cpp',
'emu2413.cpp',
'nes_data.cpp',
@ -30,6 +25,9 @@ quickerNESCoreSrc = [
'Nes_Emu.cpp',
'nes_ntsc.cpp',
'Nes_Vrc7.cpp',
'Nes_Mapper.cpp',
'Nes_Core.cpp',
'Nes_Cpu.cpp',
]
# quickerNES Core Configuration

View File

@ -3,64 +3,8 @@
#include "nes_data.h"
#include "blargg_endian.h"
/* Copyright (C) 2004-2006 Shay Green. This module is free software; you
can redistribute it and/or modify it under the terms of the GNU Lesser
General Public License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version. This
module is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
more details. You should have received a copy of the GNU Lesser General
Public License along with this module; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#include "blargg_source.h"
#define SWAP_BE( n ) (void) (set_be( &(n), (n) ))
#define SWAP_LE( n ) (void) (set_le( &(n), (n) ))
void nes_block_t::swap()
{
SWAP_BE( tag );
SWAP_LE( size );
}
void nes_state_t::swap()
{
SWAP_LE( timestamp );
SWAP_LE( frame_count );
}
void cpu_state_t::swap()
{
SWAP_LE( pc );
}
void ppu_state_t::swap()
{
SWAP_LE( vram_addr );
SWAP_LE( vram_temp );
SWAP_LE( decay_low );
SWAP_LE( decay_high );
}
void apu_state_t::swap()
{
SWAP_LE( apu.frame_delay );
SWAP_LE( square1.delay );
SWAP_LE( square2.delay );
SWAP_LE( triangle.delay );
SWAP_LE( noise.delay );
SWAP_LE( noise.shift_reg );
SWAP_LE( dmc.delay );
SWAP_LE( dmc.remain );
SWAP_LE( dmc.addr );
}
void joypad_state_t::swap()
{
SWAP_LE( joypad_latches [0] );
SWAP_LE( joypad_latches [1] );
}

View File

@ -1,13 +1,21 @@
#pragma once
// NES data file block formats
/* Copyright (C) 2004-2006 Shay Green. This module is free software; you
can redistribute it and/or modify it under the terms of the GNU Lesser
General Public License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version. This
module is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
more details. You should have received a copy of the GNU Lesser General
Public License along with this module; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
// Nes_Emu 0.7.0
#ifndef NES_DATA_H
#define NES_DATA_H
#include "blargg_common.h"
#include "apu_state.h"
#include "blargg_endian.h"
typedef long nes_tag_t;
@ -48,7 +56,11 @@ struct nes_block_t
uint32_t tag; // ** stored in big-endian
uint32_t size;
void swap();
void swap()
{
SWAP_BE( tag );
SWAP_LE( size );
}
};
BOOST_STATIC_ASSERT( sizeof (nes_block_t) == 8 );
@ -63,7 +75,11 @@ struct nes_state_t
uint32_t frame_count; // number of frames emulated since power-up
enum { tag = FOUR_CHAR('TIME') };
void swap();
void swap()
{
SWAP_LE( timestamp );
SWAP_LE( frame_count );
}
};
BOOST_STATIC_ASSERT( sizeof (nes_state_t) == 8 );
@ -74,7 +90,11 @@ struct joypad_state_t
uint8_t unused [3];
enum { tag = FOUR_CHAR('CTRL') };
void swap();
void swap()
{
SWAP_LE( joypad_latches [0] );
SWAP_LE( joypad_latches [1] );
}
};
BOOST_STATIC_ASSERT( sizeof (joypad_state_t) == 12 );
@ -104,7 +124,10 @@ struct cpu_state_t
uint8_t unused [1];
enum { tag = FOUR_CHAR('CPUR') };
void swap();
void swap()
{
SWAP_LE( pc );
}
};
BOOST_STATIC_ASSERT( sizeof (cpu_state_t) == 8 );
@ -127,7 +150,13 @@ struct ppu_state_t
uint8_t unused2[3];
enum { tag = FOUR_CHAR('PPUR') };
void swap();
void swap()
{
SWAP_LE( vram_addr );
SWAP_LE( vram_temp );
SWAP_LE( decay_low );
SWAP_LE( decay_high );
}
};
BOOST_STATIC_ASSERT( sizeof (ppu_state_t) == 20 + 0x20 );
@ -151,5 +180,3 @@ struct mmc3_state_t
uint8_t irq_flag;
};
BOOST_STATIC_ASSERT( sizeof (mmc3_state_t) == 15 );
#endif