Some simplification
This commit is contained in:
parent
361b42be9c
commit
d8b904f53f
|
@ -5,17 +5,95 @@
|
||||||
// Nes_Snd_Emu 0.1.7
|
// Nes_Snd_Emu 0.1.7
|
||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
#include "blargg_source.h"
|
||||||
|
#include "blargg_endian.h"
|
||||||
|
|
||||||
typedef long nes_time_t; // CPU clock cycle count
|
typedef long nes_time_t; // CPU clock cycle count
|
||||||
typedef unsigned nes_addr_t; // 16-bit memory address
|
typedef unsigned nes_addr_t; // 16-bit memory address
|
||||||
|
|
||||||
#include "Nes_Oscs.h"
|
#include "Nes_Oscs.h"
|
||||||
|
|
||||||
struct apu_state_t;
|
|
||||||
class Nes_Buffer;
|
|
||||||
|
|
||||||
class Nes_Apu {
|
class Nes_Apu {
|
||||||
public:
|
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();
|
||||||
~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(); }
|
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);
|
||||||
|
}
|
|
@ -2,8 +2,8 @@
|
||||||
// Nes_Emu 0.7.0. http://www.slack.net/~ant/
|
// Nes_Emu 0.7.0. http://www.slack.net/~ant/
|
||||||
|
|
||||||
#include "Nes_File.h"
|
#include "Nes_File.h"
|
||||||
|
|
||||||
#include "blargg_endian.h"
|
#include "blargg_endian.h"
|
||||||
|
#include "blargg_source.h"
|
||||||
|
|
||||||
/* Copyright (C) 2004-2006 Shay Green. This module is free software; you
|
/* 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
|
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
|
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 */
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
||||||
|
|
||||||
#include "blargg_source.h"
|
|
||||||
|
|
||||||
// Nes_File_Writer
|
// Nes_File_Writer
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include "blargg_endian.h"
|
#include "blargg_endian.h"
|
||||||
|
#include "Nes_Apu.h"
|
||||||
#include "Nes_Emu.h"
|
#include "Nes_Emu.h"
|
||||||
#include "Nes_Mapper.h"
|
#include "Nes_Mapper.h"
|
||||||
|
|
||||||
|
@ -121,7 +122,7 @@ const char * Nes_State_::write_blocks( Nes_File_Writer& out ) const
|
||||||
|
|
||||||
if ( apu_valid )
|
if ( apu_valid )
|
||||||
{
|
{
|
||||||
apu_state_t s = *apu;
|
Nes_Apu::apu_state_t s = *apu;
|
||||||
RETURN_ERR( write_nes_state( out, s ) );
|
RETURN_ERR( write_nes_state( out, s ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -232,7 +233,7 @@ const char * Nes_State_::read_blocks( Nes_File_Reader& in )
|
||||||
ppu_valid = true;
|
ppu_valid = true;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case apu_state_t::tag:
|
case FOUR_CHAR('APUR'):
|
||||||
memset( apu, 0, sizeof *apu );
|
memset( apu, 0, sizeof *apu );
|
||||||
RETURN_ERR( read_nes_state( in, apu ) );
|
RETURN_ERR( read_nes_state( in, apu ) );
|
||||||
apu_valid = true;
|
apu_valid = true;
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
|
|
||||||
#include "Nes_File.h"
|
#include "Nes_File.h"
|
||||||
#include "Nes_Cpu.h"
|
#include "Nes_Cpu.h"
|
||||||
|
#include "Nes_Apu.h"
|
||||||
class Nes_Emu;
|
class Nes_Emu;
|
||||||
class Nes_State;
|
class Nes_State;
|
||||||
|
|
||||||
|
@ -63,7 +64,7 @@ public:
|
||||||
nes_state_t nes;
|
nes_state_t nes;
|
||||||
Nes_Cpu::registers_t* cpu;
|
Nes_Cpu::registers_t* cpu;
|
||||||
joypad_state_t* joypad;
|
joypad_state_t* joypad;
|
||||||
apu_state_t* apu;
|
Nes_Apu::apu_state_t* apu;
|
||||||
ppu_state_t* ppu;
|
ppu_state_t* ppu;
|
||||||
mapper_state_t* mapper;
|
mapper_state_t* mapper;
|
||||||
|
|
||||||
|
@ -96,7 +97,7 @@ public:
|
||||||
private:
|
private:
|
||||||
Nes_Cpu::registers_t cpu;
|
Nes_Cpu::registers_t cpu;
|
||||||
joypad_state_t joypad;
|
joypad_state_t joypad;
|
||||||
apu_state_t apu;
|
Nes_Apu::apu_state_t apu;
|
||||||
ppu_state_t ppu;
|
ppu_state_t ppu;
|
||||||
mapper_state_t mapper;
|
mapper_state_t mapper;
|
||||||
uint8_t ram [ram_size];
|
uint8_t ram [ram_size];
|
||||||
|
|
|
@ -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()
|
|
||||||
{
|
|
||||||
}
|
|
|
@ -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
|
// Abstract file access interfaces
|
||||||
|
|
||||||
#ifndef ABSTRACT_FILE_H
|
|
||||||
#define ABSTRACT_FILE_H
|
|
||||||
|
|
||||||
#undef BLARGG_CONFIG_H
|
|
||||||
|
|
||||||
#include "Data_Reader.h"
|
#include "Data_Reader.h"
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
// Supports writing
|
// Supports writing
|
||||||
class Data_Writer {
|
class Data_Writer {
|
||||||
|
@ -15,8 +27,8 @@ public:
|
||||||
virtual ~Data_Writer() { }
|
virtual ~Data_Writer() { }
|
||||||
|
|
||||||
// Write 'n' bytes. NULL on success, otherwise error string.
|
// 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:
|
private:
|
||||||
// noncopyable
|
// noncopyable
|
||||||
Data_Writer( const Data_Writer& );
|
Data_Writer( const Data_Writer& );
|
||||||
|
@ -31,39 +43,93 @@ class Mem_Writer : public Data_Writer {
|
||||||
enum { expanding, fixed, ignore_excess } mode;
|
enum { expanding, fixed, ignore_excess } mode;
|
||||||
public:
|
public:
|
||||||
// Keep all written data in expanding block of memory
|
// 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
|
// 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.
|
// error if more than 'size' data is written, otherwise ignores any excess.
|
||||||
Mem_Writer( void*, long size, int ignore_excess = 0 );
|
Mem_Writer( void* p, long s, int b )
|
||||||
|
{
|
||||||
const char *write( const void*, long );
|
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
|
// Pointer to beginning of written data
|
||||||
char* data() { return data_; }
|
char* data() { return data_; }
|
||||||
|
|
||||||
// Number of bytes written
|
// Number of bytes written
|
||||||
size_t size() const { return size_; }
|
size_t size() const { return size_; }
|
||||||
|
|
||||||
~Mem_Writer();
|
~Mem_Writer()
|
||||||
|
{
|
||||||
|
if ( ( mode == expanding ) && data_ ) free( data_ );
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Dry writer to get the state size
|
// Dry writer to get the state size
|
||||||
class Dry_Writer : public Data_Writer {
|
class Dry_Writer : public Data_Writer {
|
||||||
long size_;
|
long size_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// Keep all written data in expanding block of memory
|
|
||||||
Dry_Writer();
|
Dry_Writer()
|
||||||
|
{
|
||||||
const char *write( const void*, long );
|
size_ = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
~Dry_Writer()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *write( const void* p, long s )
|
||||||
|
{
|
||||||
|
size_ += s;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Pointer to beginning of written data
|
// Pointer to beginning of written data
|
||||||
char* data() { return NULL; }
|
char* data() { return NULL; }
|
||||||
|
|
||||||
// Number of bytes written
|
// Number of bytes written
|
||||||
long size() const { return size_; }
|
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( Data_Reader& r ) : data( &r ), path( 0 ) { }
|
||||||
Auto_File_Reader( Auto_File_Reader const& );
|
Auto_File_Reader( Auto_File_Reader const& );
|
||||||
Auto_File_Reader& operator = ( 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; }
|
int operator ! () const { return !data; }
|
||||||
Data_Reader* operator -> () const { return data; }
|
Data_Reader* 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( Data_Writer& r ) : data( &r ), path( 0 ) { }
|
||||||
Auto_File_Writer( Auto_File_Writer const& );
|
Auto_File_Writer( Auto_File_Writer const& );
|
||||||
Auto_File_Writer& operator = ( Auto_File_Writer const& );
|
Auto_File_Writer& operator = ( Auto_File_Writer const& );
|
||||||
~Auto_File_Writer();
|
|
||||||
const char* open();
|
~Auto_File_Writer()
|
||||||
const char* open_comp( int level = -1 ); // compress output if possible
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* open()
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* open_comp( int level = -1 )
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int operator ! () const { return !data; }
|
int operator ! () const { return !data; }
|
||||||
Data_Writer* 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;
|
return *this;
|
||||||
}
|
}
|
||||||
inline Auto_File_Writer::Auto_File_Writer( Auto_File_Writer const& r ) { *this = r; }
|
inline Auto_File_Writer::Auto_File_Writer( Auto_File_Writer const& r ) { *this = r; }
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
|
@ -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);
|
|
||||||
}
|
|
|
@ -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
|
|
|
@ -34,9 +34,6 @@ arithmetic on smaller types. */
|
||||||
// In case compiler doesn't support these properly. Used rarely.
|
// In case compiler doesn't support these properly. Used rarely.
|
||||||
#define STATIC_CAST(T,expr) static_cast<T> (expr)
|
#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.
|
// BOOST_STATIC_ASSERT( expr ): Generates compile error if expr is 0.
|
||||||
#ifndef BOOST_STATIC_ASSERT
|
#ifndef BOOST_STATIC_ASSERT
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
|
|
|
@ -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
|
|
|
@ -1,11 +1,9 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
// CPU Byte Order Utilities
|
// CPU Byte Order Utilities
|
||||||
|
|
||||||
// Nes_Emu 0.7.0
|
// Nes_Emu 0.7.0
|
||||||
|
|
||||||
#ifndef BLARGG_ENDIAN
|
|
||||||
#define BLARGG_ENDIAN
|
|
||||||
|
|
||||||
#include "blargg_common.h"
|
#include "blargg_common.h"
|
||||||
|
|
||||||
// BLARGG_CPU_CISC: Defined if CPU has very few general-purpose registers (< 16)
|
// 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 get_be( uint16_t* p ) { return GET_BE16( p ); }
|
||||||
inline unsigned long get_be( uint32_t* p ) { return GET_BE32( 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) ))
|
|
@ -1,23 +1,18 @@
|
||||||
# quickerNES Core sources
|
# quickerNES Core sources
|
||||||
|
|
||||||
quickerNESCoreSrc = [
|
quickerNESCoreSrc = [
|
||||||
'abstract_file.cpp',
|
|
||||||
'Nes_Apu.cpp',
|
'Nes_Apu.cpp',
|
||||||
'Nes_File.cpp',
|
'Nes_File.cpp',
|
||||||
'Nes_Oscs.cpp',
|
'Nes_Oscs.cpp',
|
||||||
'apu_state.cpp',
|
|
||||||
'Nes_Buffer.cpp',
|
'Nes_Buffer.cpp',
|
||||||
'Nes_Fme7_Apu.cpp',
|
'Nes_Fme7_Apu.cpp',
|
||||||
'Nes_Ppu.cpp',
|
'Nes_Ppu.cpp',
|
||||||
'Blip_Buffer.cpp',
|
'Blip_Buffer.cpp',
|
||||||
'Nes_Cart.cpp',
|
'Nes_Cart.cpp',
|
||||||
'Nes_Mapper.cpp',
|
|
||||||
'Nes_Ppu_Impl.cpp',
|
'Nes_Ppu_Impl.cpp',
|
||||||
'Data_Reader.cpp',
|
'Data_Reader.cpp',
|
||||||
'Nes_Core.cpp',
|
|
||||||
'Nes_Ppu_Rendering.cpp',
|
'Nes_Ppu_Rendering.cpp',
|
||||||
'Effects_Buffer.cpp',
|
'Effects_Buffer.cpp',
|
||||||
'Nes_Cpu.cpp',
|
|
||||||
'Nes_State.cpp',
|
'Nes_State.cpp',
|
||||||
'emu2413.cpp',
|
'emu2413.cpp',
|
||||||
'nes_data.cpp',
|
'nes_data.cpp',
|
||||||
|
@ -30,6 +25,9 @@ quickerNESCoreSrc = [
|
||||||
'Nes_Emu.cpp',
|
'Nes_Emu.cpp',
|
||||||
'nes_ntsc.cpp',
|
'nes_ntsc.cpp',
|
||||||
'Nes_Vrc7.cpp',
|
'Nes_Vrc7.cpp',
|
||||||
|
'Nes_Mapper.cpp',
|
||||||
|
'Nes_Core.cpp',
|
||||||
|
'Nes_Cpu.cpp',
|
||||||
]
|
]
|
||||||
|
|
||||||
# quickerNES Core Configuration
|
# quickerNES Core Configuration
|
||||||
|
|
|
@ -3,64 +3,8 @@
|
||||||
|
|
||||||
#include "nes_data.h"
|
#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"
|
#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] );
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,13 +1,21 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
// NES data file block formats
|
// 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
|
// Nes_Emu 0.7.0
|
||||||
|
|
||||||
#ifndef NES_DATA_H
|
|
||||||
#define NES_DATA_H
|
|
||||||
|
|
||||||
#include "blargg_common.h"
|
#include "blargg_common.h"
|
||||||
#include "apu_state.h"
|
#include "blargg_endian.h"
|
||||||
|
|
||||||
typedef long nes_tag_t;
|
typedef long nes_tag_t;
|
||||||
|
|
||||||
|
@ -48,7 +56,11 @@ struct nes_block_t
|
||||||
uint32_t tag; // ** stored in big-endian
|
uint32_t tag; // ** stored in big-endian
|
||||||
uint32_t size;
|
uint32_t size;
|
||||||
|
|
||||||
void swap();
|
void swap()
|
||||||
|
{
|
||||||
|
SWAP_BE( tag );
|
||||||
|
SWAP_LE( size );
|
||||||
|
}
|
||||||
};
|
};
|
||||||
BOOST_STATIC_ASSERT( sizeof (nes_block_t) == 8 );
|
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
|
uint32_t frame_count; // number of frames emulated since power-up
|
||||||
|
|
||||||
enum { tag = FOUR_CHAR('TIME') };
|
enum { tag = FOUR_CHAR('TIME') };
|
||||||
void swap();
|
void swap()
|
||||||
|
{
|
||||||
|
SWAP_LE( timestamp );
|
||||||
|
SWAP_LE( frame_count );
|
||||||
|
}
|
||||||
};
|
};
|
||||||
BOOST_STATIC_ASSERT( sizeof (nes_state_t) == 8 );
|
BOOST_STATIC_ASSERT( sizeof (nes_state_t) == 8 );
|
||||||
|
|
||||||
|
@ -74,7 +90,11 @@ struct joypad_state_t
|
||||||
uint8_t unused [3];
|
uint8_t unused [3];
|
||||||
|
|
||||||
enum { tag = FOUR_CHAR('CTRL') };
|
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 );
|
BOOST_STATIC_ASSERT( sizeof (joypad_state_t) == 12 );
|
||||||
|
|
||||||
|
@ -104,7 +124,10 @@ struct cpu_state_t
|
||||||
uint8_t unused [1];
|
uint8_t unused [1];
|
||||||
|
|
||||||
enum { tag = FOUR_CHAR('CPUR') };
|
enum { tag = FOUR_CHAR('CPUR') };
|
||||||
void swap();
|
void swap()
|
||||||
|
{
|
||||||
|
SWAP_LE( pc );
|
||||||
|
}
|
||||||
};
|
};
|
||||||
BOOST_STATIC_ASSERT( sizeof (cpu_state_t) == 8 );
|
BOOST_STATIC_ASSERT( sizeof (cpu_state_t) == 8 );
|
||||||
|
|
||||||
|
@ -127,7 +150,13 @@ struct ppu_state_t
|
||||||
uint8_t unused2[3];
|
uint8_t unused2[3];
|
||||||
|
|
||||||
enum { tag = FOUR_CHAR('PPUR') };
|
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 );
|
BOOST_STATIC_ASSERT( sizeof (ppu_state_t) == 20 + 0x20 );
|
||||||
|
|
||||||
|
@ -151,5 +180,3 @@ struct mmc3_state_t
|
||||||
uint8_t irq_flag;
|
uint8_t irq_flag;
|
||||||
};
|
};
|
||||||
BOOST_STATIC_ASSERT( sizeof (mmc3_state_t) == 15 );
|
BOOST_STATIC_ASSERT( sizeof (mmc3_state_t) == 15 );
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
Loading…
Reference in New Issue