| ... | ... |
@@ -1,8 +1,7 @@ |
| 1 | 1 |
// Nintendo Game Boy sound hardware emulator with save state support |
| 2 | 2 |
|
| 3 | 3 |
// Gb_Snd_Emu 0.2.0 |
| 4 |
-#ifndef GB_APU_H |
|
| 5 |
-#define GB_APU_H |
|
| 4 |
+#pragma once |
|
| 6 | 5 |
|
| 7 | 6 |
#include "Gb_Oscs.h" |
| 8 | 7 |
|
| ... | ... |
@@ -64,7 +63,7 @@ public: |
| 64 | 63 |
// Treble and bass values for various hardware. |
| 65 | 64 |
enum |
| 66 | 65 |
{
|
| 67 |
- speaker_treble = -47, // speaker on system |
|
| 66 |
+ speaker_treble = -47, // speaker on system |
|
| 68 | 67 |
speaker_bass = 2000, |
| 69 | 68 |
dmg_treble = 0, // headphones on each system |
| 70 | 69 |
dmg_bass = 30, |
| ... | ... |
@@ -114,10 +113,7 @@ private: |
| 114 | 113 |
void run_until(blip_time_t); |
| 115 | 114 |
void silence_osc(Gb_Osc &); |
| 116 | 115 |
void write_osc(int index, int reg, int old_data, int data); |
| 117 |
- friend class Gb_Apu_Tester; |
|
| 118 | 116 |
|
| 119 | 117 |
public: |
| 120 | 118 |
int read_status(); |
| 121 | 119 |
}; |
| 122 |
- |
|
| 123 |
-#endif |
(As an aside, blargg's code style makes me go blarg myself.)
| ... | ... |
@@ -6,11 +6,10 @@ |
| 6 | 6 |
|
| 7 | 7 |
#include "Gb_Oscs.h" |
| 8 | 8 |
|
| 9 |
-struct gb_apu_state_t; |
|
| 10 |
- |
|
| 11 |
-class Gb_Apu {
|
|
| 9 |
+class Gb_Apu |
|
| 10 |
+{
|
|
| 12 | 11 |
public: |
| 13 |
-// Basics |
|
| 12 |
+ // Basics |
|
| 14 | 13 |
|
| 15 | 14 |
// Clock rate that sound hardware runs at. |
| 16 | 15 |
enum { clock_rate = 4194304 * GB_APU_OVERCLOCK };
|
| ... | ... |
@@ -19,155 +18,106 @@ public: |
| 19 | 18 |
// If all are NULL, no output is generated but other emulation still runs. |
| 20 | 19 |
// If chan is specified, only that channel's output is changed, otherwise all are. |
| 21 | 20 |
enum { osc_count = 4 }; // 0: Square 1, 1: Square 2, 2: Wave, 3: Noise
|
| 22 |
- void set_output( Blip_Buffer* center, Blip_Buffer* left = NULL, Blip_Buffer* right = NULL, |
|
| 23 |
- int chan = osc_count ); |
|
| 21 |
+ void set_output(Blip_Buffer *center, Blip_Buffer *left = nullptr, Blip_Buffer *right = nullptr, int chan = osc_count); |
|
| 24 | 22 |
|
| 25 | 23 |
// Resets hardware to initial power on state BEFORE boot ROM runs. Mode selects |
| 26 | 24 |
// sound hardware. Additional AGB wave features are enabled separately. |
| 27 |
- enum mode_t {
|
|
| 28 |
- mode_dmg, // Game Boy monochrome |
|
| 29 |
- mode_cgb, // Game Boy Color |
|
| 30 |
- mode_agb // Game Boy Advance |
|
| 25 |
+ enum mode_t |
|
| 26 |
+ {
|
|
| 27 |
+ mode_dmg, // Game Boy monochrome |
|
| 28 |
+ mode_cgb, // Game Boy Color |
|
| 29 |
+ mode_agb // Game Boy Advance |
|
| 31 | 30 |
}; |
| 32 |
- void reset( mode_t mode = mode_cgb, bool agb_wave = false ); |
|
| 31 |
+ void reset(mode_t mode = mode_cgb, bool agb_wave = false); |
|
| 33 | 32 |
|
| 34 | 33 |
// Reads and writes must be within the start_addr to end_addr range, inclusive. |
| 35 | 34 |
// Addresses outside this range are not mapped to the sound hardware. |
| 36 | 35 |
enum { start_addr = 0xFF10 };
|
| 37 |
- enum { end_addr = 0xFF3F };
|
|
| 36 |
+ enum { end_addr = 0xFF3F };
|
|
| 38 | 37 |
enum { register_count = end_addr - start_addr + 1 };
|
| 39 | 38 |
|
| 40 | 39 |
// Times are specified as the number of clocks since the beginning of the |
| 41 | 40 |
// current time frame. |
| 42 | 41 |
|
| 43 | 42 |
// Emulates CPU write of data to addr at specified time. |
| 44 |
- void write_register( blip_time_t time, unsigned addr, int data ); |
|
| 43 |
+ void write_register(blip_time_t time, unsigned addr, int data); |
|
| 45 | 44 |
|
| 46 | 45 |
// Emulates CPU read from addr at specified time. |
| 47 |
- int read_register( blip_time_t time, unsigned addr ); |
|
| 46 |
+ int read_register(blip_time_t time, unsigned addr); |
|
| 48 | 47 |
|
| 49 | 48 |
// Emulates sound hardware up to specified time, ends current time frame, then |
| 50 | 49 |
// starts a new frame at time 0. |
| 51 |
- void end_frame( blip_time_t frame_length ); |
|
| 50 |
+ void end_frame(blip_time_t frame_length); |
|
| 52 | 51 |
|
| 53 |
-// Sound adjustments |
|
| 52 |
+ // Sound adjustments |
|
| 54 | 53 |
|
| 55 | 54 |
// Sets overall volume, where 1.0 is normal. |
| 56 |
- void volume( double ); |
|
| 55 |
+ void volume(double); |
|
| 57 | 56 |
|
| 58 | 57 |
// If true, reduces clicking by disabling DAC biasing. Note that this reduces |
| 59 | 58 |
// emulation accuracy, since the clicks are authentic. |
| 60 |
- void reduce_clicks( bool reduce = true ); |
|
| 59 |
+ void reduce_clicks(bool reduce = true); |
|
| 61 | 60 |
|
| 62 | 61 |
// Sets treble equalization. |
| 63 |
- void treble_eq( blip_eq_t const& ); |
|
| 62 |
+ void treble_eq(const blip_eq_t &); |
|
| 64 | 63 |
|
| 65 | 64 |
// Treble and bass values for various hardware. |
| 66 |
- enum {
|
|
| 65 |
+ enum |
|
| 66 |
+ {
|
|
| 67 | 67 |
speaker_treble = -47, // speaker on system |
| 68 |
- speaker_bass = 2000, |
|
| 69 |
- dmg_treble = 0, // headphones on each system |
|
| 70 |
- dmg_bass = 30, |
|
| 71 |
- cgb_treble = 0, |
|
| 72 |
- cgb_bass = 300, // CGB has much less bass |
|
| 73 |
- agb_treble = 0, |
|
| 74 |
- agb_bass = 30 |
|
| 68 |
+ speaker_bass = 2000, |
|
| 69 |
+ dmg_treble = 0, // headphones on each system |
|
| 70 |
+ dmg_bass = 30, |
|
| 71 |
+ cgb_treble = 0, |
|
| 72 |
+ cgb_bass = 300, // CGB has much less bass |
|
| 73 |
+ agb_treble = 0, |
|
| 74 |
+ agb_bass = 30 |
|
| 75 | 75 |
}; |
| 76 | 76 |
|
| 77 | 77 |
// Sets frame sequencer rate, where 1.0 is normal. Meant for adjusting the |
| 78 | 78 |
// tempo in a game music player. |
| 79 |
- void set_tempo( double ); |
|
| 79 |
+ void set_tempo(double); |
|
| 80 | 80 |
|
| 81 |
-public: |
|
| 82 | 81 |
Gb_Apu(); |
| 83 | 82 |
|
| 84 |
- // Use set_output() in place of these |
|
| 85 |
- BLARGG_DEPRECATED void output ( Blip_Buffer* c ) { set_output( c, c, c ); }
|
|
| 86 |
- BLARGG_DEPRECATED void output ( Blip_Buffer* c, Blip_Buffer* l, Blip_Buffer* r ) { set_output( c, l, r ); }
|
|
| 87 |
- BLARGG_DEPRECATED void osc_output( int i, Blip_Buffer* c ) { set_output( c, c, c, i ); }
|
|
| 88 |
- BLARGG_DEPRECATED void osc_output( int i, Blip_Buffer* c, Blip_Buffer* l, Blip_Buffer* r ) { set_output( c, l, r, i ); }
|
|
| 89 |
- |
|
| 90 | 83 |
private: |
| 91 | 84 |
// noncopyable |
| 92 |
- Gb_Apu( const Gb_Apu& ); |
|
| 93 |
- Gb_Apu& operator = ( const Gb_Apu& ); |
|
| 85 |
+ Gb_Apu(const Gb_Apu &); |
|
| 86 |
+ Gb_Apu &operator=(const Gb_Apu &); |
|
| 94 | 87 |
|
| 95 |
- Gb_Osc* oscs [osc_count]; |
|
| 96 |
- blip_time_t last_time; // time sound emulator has been run to |
|
| 97 |
- blip_time_t frame_period; // clocks between each frame sequencer step |
|
| 98 |
- double volume_; |
|
| 99 |
- bool reduce_clicks_; |
|
| 88 |
+ Gb_Osc *oscs[osc_count]; |
|
| 89 |
+ blip_time_t last_time; // time sound emulator has been run to |
|
| 90 |
+ blip_time_t frame_period; // clocks between each frame sequencer step |
|
| 91 |
+ double volume_; |
|
| 92 |
+ bool reduce_clicks_; |
|
| 100 | 93 |
|
| 101 | 94 |
Gb_Sweep_Square square1; |
| 102 |
- Gb_Square square2; |
|
| 103 |
- Gb_Wave wave; |
|
| 104 |
- Gb_Noise noise; |
|
| 105 |
- blip_time_t frame_time; // time of next frame sequencer action |
|
| 106 |
- int frame_phase; // phase of next frame sequencer step |
|
| 95 |
+ Gb_Square square2; |
|
| 96 |
+ Gb_Wave wave; |
|
| 97 |
+ Gb_Noise noise; |
|
| 98 |
+ blip_time_t frame_time; // time of next frame sequencer action |
|
| 99 |
+ int frame_phase; // phase of next frame sequencer step |
|
| 107 | 100 |
enum { regs_size = register_count + 0x10 };
|
| 108 |
- BOOST::uint8_t regs [regs_size];// last values written to registers |
|
| 101 |
+ uint8_t regs[regs_size];// last values written to registers |
|
| 109 | 102 |
|
| 110 | 103 |
// large objects after everything else |
| 111 |
- Gb_Osc::Good_Synth good_synth; |
|
| 112 |
- Gb_Osc::Med_Synth med_synth; |
|
| 104 |
+ Gb_Osc::Good_Synth good_synth; |
|
| 105 |
+ Gb_Osc::Med_Synth med_synth; |
|
| 113 | 106 |
|
| 114 | 107 |
void reset_lengths(); |
| 115 | 108 |
void reset_regs(); |
| 116 |
- int calc_output( int osc ) const; |
|
| 109 |
+ int calc_output(int osc) const; |
|
| 117 | 110 |
void apply_stereo(); |
| 118 | 111 |
void apply_volume(); |
| 119 |
- void synth_volume( int ); |
|
| 120 |
- void run_until_( blip_time_t ); |
|
| 121 |
- void run_until( blip_time_t ); |
|
| 122 |
- void silence_osc( Gb_Osc& ); |
|
| 123 |
- void write_osc( int index, int reg, int old_data, int data ); |
|
| 112 |
+ void synth_volume(int); |
|
| 113 |
+ void run_until_(blip_time_t); |
|
| 114 |
+ void run_until(blip_time_t); |
|
| 115 |
+ void silence_osc(Gb_Osc &); |
|
| 116 |
+ void write_osc(int index, int reg, int old_data, int data); |
|
| 124 | 117 |
friend class Gb_Apu_Tester; |
| 125 | 118 |
|
| 126 | 119 |
public: |
| 127 | 120 |
int read_status(); |
| 128 | 121 |
}; |
| 129 | 122 |
|
| 130 |
-// Format of save state. Should be stable across versions of the library, |
|
| 131 |
-// with earlier versions properly opening later save states. Includes some |
|
| 132 |
-// room for expansion so the state size shouldn't increase. |
|
| 133 |
-struct gb_apu_state_t |
|
| 134 |
-{
|
|
| 135 |
-#if GB_APU_CUSTOM_STATE |
|
| 136 |
- // Values stored as plain int so your code can read/write them easily. |
|
| 137 |
- // Structure can NOT be written to disk, since format is not portable. |
|
| 138 |
- typedef int val_t; |
|
| 139 |
-#else |
|
| 140 |
- // Values written in portable little-endian format, allowing structure |
|
| 141 |
- // to be written directly to disk. |
|
| 142 |
- typedef unsigned char val_t [4]; |
|
| 143 |
-#endif |
|
| 144 |
- |
|
| 145 |
- enum { format0 = 0x50414247 };
|
|
| 146 |
- |
|
| 147 |
- val_t format; // format of all following data |
|
| 148 |
- val_t version; // later versions just add fields to end |
|
| 149 |
- |
|
| 150 |
- unsigned char regs [0x40]; |
|
| 151 |
- val_t frame_time; |
|
| 152 |
- val_t frame_phase; |
|
| 153 |
- |
|
| 154 |
- val_t sweep_freq; |
|
| 155 |
- val_t sweep_delay; |
|
| 156 |
- val_t sweep_enabled; |
|
| 157 |
- val_t sweep_neg; |
|
| 158 |
- val_t noise_divider; |
|
| 159 |
- val_t wave_buf; |
|
| 160 |
- |
|
| 161 |
- val_t delay [4]; |
|
| 162 |
- val_t length_ctr [4]; |
|
| 163 |
- val_t phase [4]; |
|
| 164 |
- val_t enabled [4]; |
|
| 165 |
- |
|
| 166 |
- val_t env_delay [3]; |
|
| 167 |
- val_t env_volume [3]; |
|
| 168 |
- val_t env_enabled [3]; |
|
| 169 |
- |
|
| 170 |
- val_t unused [13]; // for future expansion |
|
| 171 |
-}; |
|
| 172 |
- |
|
| 173 | 123 |
#endif |
| ... | ... |
@@ -78,16 +78,6 @@ public: |
| 78 | 78 |
// tempo in a game music player. |
| 79 | 79 |
void set_tempo( double ); |
| 80 | 80 |
|
| 81 |
-// Save states |
|
| 82 |
- |
|
| 83 |
- // Saves full emulation state to state_out. Data format is portable and |
|
| 84 |
- // includes some extra space to avoid expansion in case more state needs |
|
| 85 |
- // to be stored in the future. |
|
| 86 |
- void save_state( gb_apu_state_t* state_out ); |
|
| 87 |
- |
|
| 88 |
- // Loads state. You should call reset() BEFORE this. |
|
| 89 |
- blargg_err_t load_state( gb_apu_state_t const& in ); |
|
| 90 |
- |
|
| 91 | 81 |
public: |
| 92 | 82 |
Gb_Apu(); |
| 93 | 83 |
|
| ... | ... |
@@ -131,8 +121,6 @@ private: |
| 131 | 121 |
void run_until( blip_time_t ); |
| 132 | 122 |
void silence_osc( Gb_Osc& ); |
| 133 | 123 |
void write_osc( int index, int reg, int old_data, int data ); |
| 134 |
- const char* save_load( gb_apu_state_t*, bool save ); |
|
| 135 |
- void save_load2( gb_apu_state_t*, bool save ); |
|
| 136 | 124 |
friend class Gb_Apu_Tester; |
| 137 | 125 |
|
| 138 | 126 |
public: |
| 1 | 1 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,185 @@ |
| 1 |
+// Nintendo Game Boy sound hardware emulator with save state support |
|
| 2 |
+ |
|
| 3 |
+// Gb_Snd_Emu 0.2.0 |
|
| 4 |
+#ifndef GB_APU_H |
|
| 5 |
+#define GB_APU_H |
|
| 6 |
+ |
|
| 7 |
+#include "Gb_Oscs.h" |
|
| 8 |
+ |
|
| 9 |
+struct gb_apu_state_t; |
|
| 10 |
+ |
|
| 11 |
+class Gb_Apu {
|
|
| 12 |
+public: |
|
| 13 |
+// Basics |
|
| 14 |
+ |
|
| 15 |
+ // Clock rate that sound hardware runs at. |
|
| 16 |
+ enum { clock_rate = 4194304 * GB_APU_OVERCLOCK };
|
|
| 17 |
+ |
|
| 18 |
+ // Sets buffer(s) to generate sound into. If left and right are NULL, output is mono. |
|
| 19 |
+ // If all are NULL, no output is generated but other emulation still runs. |
|
| 20 |
+ // If chan is specified, only that channel's output is changed, otherwise all are. |
|
| 21 |
+ enum { osc_count = 4 }; // 0: Square 1, 1: Square 2, 2: Wave, 3: Noise
|
|
| 22 |
+ void set_output( Blip_Buffer* center, Blip_Buffer* left = NULL, Blip_Buffer* right = NULL, |
|
| 23 |
+ int chan = osc_count ); |
|
| 24 |
+ |
|
| 25 |
+ // Resets hardware to initial power on state BEFORE boot ROM runs. Mode selects |
|
| 26 |
+ // sound hardware. Additional AGB wave features are enabled separately. |
|
| 27 |
+ enum mode_t {
|
|
| 28 |
+ mode_dmg, // Game Boy monochrome |
|
| 29 |
+ mode_cgb, // Game Boy Color |
|
| 30 |
+ mode_agb // Game Boy Advance |
|
| 31 |
+ }; |
|
| 32 |
+ void reset( mode_t mode = mode_cgb, bool agb_wave = false ); |
|
| 33 |
+ |
|
| 34 |
+ // Reads and writes must be within the start_addr to end_addr range, inclusive. |
|
| 35 |
+ // Addresses outside this range are not mapped to the sound hardware. |
|
| 36 |
+ enum { start_addr = 0xFF10 };
|
|
| 37 |
+ enum { end_addr = 0xFF3F };
|
|
| 38 |
+ enum { register_count = end_addr - start_addr + 1 };
|
|
| 39 |
+ |
|
| 40 |
+ // Times are specified as the number of clocks since the beginning of the |
|
| 41 |
+ // current time frame. |
|
| 42 |
+ |
|
| 43 |
+ // Emulates CPU write of data to addr at specified time. |
|
| 44 |
+ void write_register( blip_time_t time, unsigned addr, int data ); |
|
| 45 |
+ |
|
| 46 |
+ // Emulates CPU read from addr at specified time. |
|
| 47 |
+ int read_register( blip_time_t time, unsigned addr ); |
|
| 48 |
+ |
|
| 49 |
+ // Emulates sound hardware up to specified time, ends current time frame, then |
|
| 50 |
+ // starts a new frame at time 0. |
|
| 51 |
+ void end_frame( blip_time_t frame_length ); |
|
| 52 |
+ |
|
| 53 |
+// Sound adjustments |
|
| 54 |
+ |
|
| 55 |
+ // Sets overall volume, where 1.0 is normal. |
|
| 56 |
+ void volume( double ); |
|
| 57 |
+ |
|
| 58 |
+ // If true, reduces clicking by disabling DAC biasing. Note that this reduces |
|
| 59 |
+ // emulation accuracy, since the clicks are authentic. |
|
| 60 |
+ void reduce_clicks( bool reduce = true ); |
|
| 61 |
+ |
|
| 62 |
+ // Sets treble equalization. |
|
| 63 |
+ void treble_eq( blip_eq_t const& ); |
|
| 64 |
+ |
|
| 65 |
+ // Treble and bass values for various hardware. |
|
| 66 |
+ enum {
|
|
| 67 |
+ speaker_treble = -47, // speaker on system |
|
| 68 |
+ speaker_bass = 2000, |
|
| 69 |
+ dmg_treble = 0, // headphones on each system |
|
| 70 |
+ dmg_bass = 30, |
|
| 71 |
+ cgb_treble = 0, |
|
| 72 |
+ cgb_bass = 300, // CGB has much less bass |
|
| 73 |
+ agb_treble = 0, |
|
| 74 |
+ agb_bass = 30 |
|
| 75 |
+ }; |
|
| 76 |
+ |
|
| 77 |
+ // Sets frame sequencer rate, where 1.0 is normal. Meant for adjusting the |
|
| 78 |
+ // tempo in a game music player. |
|
| 79 |
+ void set_tempo( double ); |
|
| 80 |
+ |
|
| 81 |
+// Save states |
|
| 82 |
+ |
|
| 83 |
+ // Saves full emulation state to state_out. Data format is portable and |
|
| 84 |
+ // includes some extra space to avoid expansion in case more state needs |
|
| 85 |
+ // to be stored in the future. |
|
| 86 |
+ void save_state( gb_apu_state_t* state_out ); |
|
| 87 |
+ |
|
| 88 |
+ // Loads state. You should call reset() BEFORE this. |
|
| 89 |
+ blargg_err_t load_state( gb_apu_state_t const& in ); |
|
| 90 |
+ |
|
| 91 |
+public: |
|
| 92 |
+ Gb_Apu(); |
|
| 93 |
+ |
|
| 94 |
+ // Use set_output() in place of these |
|
| 95 |
+ BLARGG_DEPRECATED void output ( Blip_Buffer* c ) { set_output( c, c, c ); }
|
|
| 96 |
+ BLARGG_DEPRECATED void output ( Blip_Buffer* c, Blip_Buffer* l, Blip_Buffer* r ) { set_output( c, l, r ); }
|
|
| 97 |
+ BLARGG_DEPRECATED void osc_output( int i, Blip_Buffer* c ) { set_output( c, c, c, i ); }
|
|
| 98 |
+ BLARGG_DEPRECATED void osc_output( int i, Blip_Buffer* c, Blip_Buffer* l, Blip_Buffer* r ) { set_output( c, l, r, i ); }
|
|
| 99 |
+ |
|
| 100 |
+private: |
|
| 101 |
+ // noncopyable |
|
| 102 |
+ Gb_Apu( const Gb_Apu& ); |
|
| 103 |
+ Gb_Apu& operator = ( const Gb_Apu& ); |
|
| 104 |
+ |
|
| 105 |
+ Gb_Osc* oscs [osc_count]; |
|
| 106 |
+ blip_time_t last_time; // time sound emulator has been run to |
|
| 107 |
+ blip_time_t frame_period; // clocks between each frame sequencer step |
|
| 108 |
+ double volume_; |
|
| 109 |
+ bool reduce_clicks_; |
|
| 110 |
+ |
|
| 111 |
+ Gb_Sweep_Square square1; |
|
| 112 |
+ Gb_Square square2; |
|
| 113 |
+ Gb_Wave wave; |
|
| 114 |
+ Gb_Noise noise; |
|
| 115 |
+ blip_time_t frame_time; // time of next frame sequencer action |
|
| 116 |
+ int frame_phase; // phase of next frame sequencer step |
|
| 117 |
+ enum { regs_size = register_count + 0x10 };
|
|
| 118 |
+ BOOST::uint8_t regs [regs_size];// last values written to registers |
|
| 119 |
+ |
|
| 120 |
+ // large objects after everything else |
|
| 121 |
+ Gb_Osc::Good_Synth good_synth; |
|
| 122 |
+ Gb_Osc::Med_Synth med_synth; |
|
| 123 |
+ |
|
| 124 |
+ void reset_lengths(); |
|
| 125 |
+ void reset_regs(); |
|
| 126 |
+ int calc_output( int osc ) const; |
|
| 127 |
+ void apply_stereo(); |
|
| 128 |
+ void apply_volume(); |
|
| 129 |
+ void synth_volume( int ); |
|
| 130 |
+ void run_until_( blip_time_t ); |
|
| 131 |
+ void run_until( blip_time_t ); |
|
| 132 |
+ void silence_osc( Gb_Osc& ); |
|
| 133 |
+ void write_osc( int index, int reg, int old_data, int data ); |
|
| 134 |
+ const char* save_load( gb_apu_state_t*, bool save ); |
|
| 135 |
+ void save_load2( gb_apu_state_t*, bool save ); |
|
| 136 |
+ friend class Gb_Apu_Tester; |
|
| 137 |
+ |
|
| 138 |
+public: |
|
| 139 |
+ int read_status(); |
|
| 140 |
+}; |
|
| 141 |
+ |
|
| 142 |
+// Format of save state. Should be stable across versions of the library, |
|
| 143 |
+// with earlier versions properly opening later save states. Includes some |
|
| 144 |
+// room for expansion so the state size shouldn't increase. |
|
| 145 |
+struct gb_apu_state_t |
|
| 146 |
+{
|
|
| 147 |
+#if GB_APU_CUSTOM_STATE |
|
| 148 |
+ // Values stored as plain int so your code can read/write them easily. |
|
| 149 |
+ // Structure can NOT be written to disk, since format is not portable. |
|
| 150 |
+ typedef int val_t; |
|
| 151 |
+#else |
|
| 152 |
+ // Values written in portable little-endian format, allowing structure |
|
| 153 |
+ // to be written directly to disk. |
|
| 154 |
+ typedef unsigned char val_t [4]; |
|
| 155 |
+#endif |
|
| 156 |
+ |
|
| 157 |
+ enum { format0 = 0x50414247 };
|
|
| 158 |
+ |
|
| 159 |
+ val_t format; // format of all following data |
|
| 160 |
+ val_t version; // later versions just add fields to end |
|
| 161 |
+ |
|
| 162 |
+ unsigned char regs [0x40]; |
|
| 163 |
+ val_t frame_time; |
|
| 164 |
+ val_t frame_phase; |
|
| 165 |
+ |
|
| 166 |
+ val_t sweep_freq; |
|
| 167 |
+ val_t sweep_delay; |
|
| 168 |
+ val_t sweep_enabled; |
|
| 169 |
+ val_t sweep_neg; |
|
| 170 |
+ val_t noise_divider; |
|
| 171 |
+ val_t wave_buf; |
|
| 172 |
+ |
|
| 173 |
+ val_t delay [4]; |
|
| 174 |
+ val_t length_ctr [4]; |
|
| 175 |
+ val_t phase [4]; |
|
| 176 |
+ val_t enabled [4]; |
|
| 177 |
+ |
|
| 178 |
+ val_t env_delay [3]; |
|
| 179 |
+ val_t env_volume [3]; |
|
| 180 |
+ val_t env_enabled [3]; |
|
| 181 |
+ |
|
| 182 |
+ val_t unused [13]; // for future expansion |
|
| 183 |
+}; |
|
| 184 |
+ |
|
| 185 |
+#endif |