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