vbagx/source/vba/apu/Gb_Apu.h

183 lines
6.0 KiB
C++

// Nintendo Game Boy sound hardware emulator with save state support
// Gb_Snd_Emu 0.2.0
#ifndef GB_APU_H
#define GB_APU_H
#include "Gb_Oscs.h"
struct gb_apu_state_t;
class Gb_Apu {
public:
// Basics
// Clock rate that sound hardware runs at.
enum { clock_rate = 4194304 * GB_APU_OVERCLOCK };
// Sets buffer(s) to generate sound into. If left and right are NULL, output is mono.
// If all are NULL, no output is generated but other emulation still runs.
// If chan is specified, only that channel's output is changed, otherwise all are.
enum { osc_count = 4 }; // 0: Square 1, 1: Square 2, 2: Wave, 3: Noise
void set_output( Blip_Buffer* center, Blip_Buffer* left = NULL, Blip_Buffer* right = NULL,
int chan = osc_count );
// Resets hardware to initial power on state BEFORE boot ROM runs. Mode selects
// sound hardware. Additional AGB wave features are enabled separately.
enum mode_t {
mode_dmg, // Game Boy monochrome
mode_cgb, // Game Boy Color
mode_agb // Game Boy Advance
};
void reset( mode_t mode = mode_cgb, bool agb_wave = false );
// Reads and writes must be within the start_addr to end_addr range, inclusive.
// Addresses outside this range are not mapped to the sound hardware.
enum { start_addr = 0xFF10 };
enum { end_addr = 0xFF3F };
enum { register_count = end_addr - start_addr + 1 };
// Times are specified as the number of clocks since the beginning of the
// current time frame.
// Emulates CPU write of data to addr at specified time.
void write_register( blip_time_t time, unsigned addr, int data );
// Emulates CPU read from addr at specified time.
int read_register( blip_time_t time, unsigned addr );
// Emulates sound hardware up to specified time, ends current time frame, then
// starts a new frame at time 0.
void end_frame( blip_time_t frame_length );
// Sound adjustments
// Sets overall volume, where 1.0 is normal.
void volume( double );
// If true, reduces clicking by disabling DAC biasing. Note that this reduces
// emulation accuracy, since the clicks are authentic.
void reduce_clicks( bool reduce = true );
// Sets treble equalization.
void treble_eq( blip_eq_t const& );
// Treble and bass values for various hardware.
enum {
speaker_treble = -47, // speaker on system
speaker_bass = 2000,
dmg_treble = 0, // headphones on each system
dmg_bass = 30,
cgb_treble = 0,
cgb_bass = 300, // CGB has much less bass
agb_treble = 0,
agb_bass = 30
};
// Sets frame sequencer rate, where 1.0 is normal. Meant for adjusting the
// tempo in a game music player.
void set_tempo( double );
// Save states
// Saves full emulation state to state_out. Data format is portable and
// includes some extra space to avoid expansion in case more state needs
// to be stored in the future.
void save_state( gb_apu_state_t* state_out );
// Loads state. You should call reset() BEFORE this.
blargg_err_t load_state( gb_apu_state_t const& in );
public:
Gb_Apu();
// Use set_output() in place of these
BLARGG_DEPRECATED void output ( Blip_Buffer* c ) { set_output( c, c, c ); }
BLARGG_DEPRECATED void output ( Blip_Buffer* c, Blip_Buffer* l, Blip_Buffer* r ) { set_output( c, l, r ); }
BLARGG_DEPRECATED void osc_output( int i, Blip_Buffer* c ) { set_output( c, c, c, i ); }
BLARGG_DEPRECATED void osc_output( int i, Blip_Buffer* c, Blip_Buffer* l, Blip_Buffer* r ) { set_output( c, l, r, i ); }
private:
// noncopyable
Gb_Apu( const Gb_Apu& );
Gb_Apu& operator = ( const Gb_Apu& );
Gb_Osc* oscs [osc_count];
blip_time_t last_time; // time sound emulator has been run to
blip_time_t frame_period; // clocks between each frame sequencer step
double volume_;
bool reduce_clicks_;
Gb_Sweep_Square square1;
Gb_Square square2;
Gb_Wave wave;
Gb_Noise noise;
blip_time_t frame_time; // time of next frame sequencer action
int frame_phase; // phase of next frame sequencer step
enum { regs_size = register_count + 0x10 };
BOOST::uint8_t regs [regs_size];// last values written to registers
// large objects after everything else
Gb_Osc::Good_Synth good_synth;
Gb_Osc::Med_Synth med_synth;
void reset_lengths();
void reset_regs();
int calc_output( int osc ) const;
void apply_stereo();
void apply_volume();
void synth_volume( int );
void run_until_( blip_time_t );
void run_until( blip_time_t );
void silence_osc( Gb_Osc& );
void write_osc( int index, int reg, int old_data, int data );
const char* save_load( gb_apu_state_t*, bool save );
void save_load2( gb_apu_state_t*, bool save );
friend class Gb_Apu_Tester;
};
// Format of save state. Should be stable across versions of the library,
// with earlier versions properly opening later save states. Includes some
// room for expansion so the state size shouldn't increase.
struct gb_apu_state_t
{
#if GB_APU_CUSTOM_STATE
// Values stored as plain int so your code can read/write them easily.
// Structure can NOT be written to disk, since format is not portable.
typedef int val_t;
#else
// Values written in portable little-endian format, allowing structure
// to be written directly to disk.
typedef unsigned char val_t [4];
#endif
enum { format0 = 0x50414247 };
val_t format; // format of all following data
val_t version; // later versions just add fields to end
unsigned char regs [0x40];
val_t frame_time;
val_t frame_phase;
val_t sweep_freq;
val_t sweep_delay;
val_t sweep_enabled;
val_t sweep_neg;
val_t noise_divider;
val_t wave_buf;
val_t delay [4];
val_t length_ctr [4];
val_t phase [4];
val_t enabled [4];
val_t env_delay [3];
val_t env_volume [3];
val_t env_enabled [3];
val_t unused [13]; // for future expansion
};
#endif