Browse code

* Fixes for gcc and clang (while they can compile the code, the DLLs made aren't functional, but oh well).

* [2SF] Used more up-to-date asmjit, despite the ugly looking code.

Naram Qashat authored on 2014/09/17 19:51:45
Showing 1 changed files
... ...
@@ -2,6 +2,7 @@
2 2
 
3 3
 #include <algorithm>
4 4
 #include "Gb_Apu.h"
5
+#include "XSFCommon.h"
5 6
 
6 7
 /* Copyright (C) 2003-2007 Shay Green. This module is free software; you
7 8
 can redistribute it and/or modify it under the terms of the GNU Lesser
... ...
@@ -76,7 +77,7 @@ void Gb_Apu::apply_volume()
76 77
 
77 78
 void Gb_Apu::volume(double v)
78 79
 {
79
-	if (this->volume_ != v)
80
+	if (!fEqual(this->volume_, v))
80 81
 	{
81 82
 		this->volume_ = v;
82 83
 		this->apply_volume();
... ...
@@ -157,7 +158,7 @@ void Gb_Apu::reset(mode_t mode, bool agb_wave)
157 158
 void Gb_Apu::set_tempo(double t)
158 159
 {
159 160
 	this->frame_period = 4194304 / 512; // 512 Hz
160
-	if (t != 1.0)
161
+	if (!fEqual(t, 1.0))
161 162
 		this->frame_period = static_cast<blip_time_t>(this->frame_period / t);
162 163
 }
163 164
 
Browse code

[GSF] Copied a few things from kode54's viogsf.

Naram Qashat authored on 2014/09/15 14:27:18
Showing 1 changed files
... ...
@@ -24,7 +24,8 @@ static const int power_mask = 0x80;
24 24
 void Gb_Apu::treble_eq(const blip_eq_t &eq)
25 25
 {
26 26
 	this->good_synth.treble_eq(eq);
27
-	this->med_synth.treble_eq(eq);
27
+	this->med_synth[0].treble_eq(eq);
28
+	this->med_synth[1].treble_eq(eq);
28 29
 }
29 30
 
30 31
 int Gb_Apu::calc_output(int osc) const
... ...
@@ -57,7 +58,8 @@ void Gb_Apu::synth_volume(int iv)
57 58
 {
58 59
 	double v = this->volume_ * 0.60 / osc_count / 15 /*steps*/ / 8 /*master vol range*/ * iv;
59 60
 	this->good_synth.volume(v);
60
-	this->med_synth.volume(v);
61
+	this->med_synth[0].volume(v);
62
+	this->med_synth[1].volume(v * 1.4);
61 63
 }
62 64
 
63 65
 void Gb_Apu::apply_volume()
... ...
@@ -174,7 +176,7 @@ Gb_Apu::Gb_Apu()
174 176
 		o.regs = &this->regs[i * 5];
175 177
 		o.output = o.outputs[0] = o.outputs[1] = o.outputs[2] = o.outputs[3] = nullptr;
176 178
 		o.good_synth = &this->good_synth;
177
-		o.med_synth = &this->med_synth;
179
+		o.med_synth = &this->med_synth[i == 3 ? 1 : 0];
178 180
 	}
179 181
 
180 182
 	this->reduce_clicks_ = false;
... ...
@@ -255,7 +257,7 @@ void Gb_Apu::silence_osc(Gb_Osc &o)
255 257
 		if (o.output)
256 258
 		{
257 259
 			o.output->set_modified();
258
-			this->med_synth.offset(this->last_time, delta, o.output);
260
+			this->med_synth[0].offset(this->last_time, delta, o.output);
259 261
 		}
260 262
 	}
261 263
 }
Browse code

Use std::copy_n/std::fill_n instead of std::copy/std::fill where possible.

Naram Qashat authored on 2014/09/08 16:52:49
Showing 1 changed files
... ...
@@ -83,7 +83,7 @@ void Gb_Apu::volume(double v)
83 83
 
84 84
 void Gb_Apu::reset_regs()
85 85
 {
86
-	std::fill(&this->regs[0], &this->regs[0x20], 0);
86
+	std::fill_n(&this->regs[0], 0x20, 0);
87 87
 
88 88
 	this->square1.reset();
89 89
 	this->square2.reset();
Browse code

Updating the VBA-M code to revision 1231.

Naram Qashat authored on 2014/09/08 12:20:28
Showing 1 changed files
... ...
@@ -30,7 +30,7 @@ void Gb_Apu::treble_eq(const blip_eq_t &eq)
30 30
 int Gb_Apu::calc_output(int osc) const
31 31
 {
32 32
 	int bits = this->regs[stereo_reg - start_addr] >> osc;
33
-	return ((bits >> 3) & 2) | (bits & 1);
33
+	return (bits >> 3 & 2) | (bits & 1);
34 34
 }
35 35
 
36 36
 void Gb_Apu::set_output(Blip_Buffer *center, Blip_Buffer *left, Blip_Buffer *right, int osc)
... ...
@@ -65,7 +65,7 @@ void Gb_Apu::apply_volume()
65 65
 	// TODO: Doesn't handle differing left and right volumes (panning).
66 66
 	// Not worth the complexity.
67 67
 	int data = this->regs[vol_reg - start_addr];
68
-	int left = (data >> 4) & 7;
68
+	int left = data >> 4 & 7;
69 69
 	int right = data & 7;
70 70
 	//if ( data & 0x88 ) dprintf( "Vin: %02X\n", data & 0x88 );
71 71
 	//if ( left != right ) dprintf( "l: %d r: %d\n", left, right );
... ...
@@ -83,8 +83,7 @@ void Gb_Apu::volume(double v)
83 83
 
84 84
 void Gb_Apu::reset_regs()
85 85
 {
86
-	for (int i = 0; i < 0x20; ++i)
87
-		this->regs[i] = 0;
86
+	std::fill(&this->regs[0], &this->regs[0x20], 0);
88 87
 
89 88
 	this->square1.reset();
90 89
 	this->square2.reset();
... ...
@@ -173,11 +172,7 @@ Gb_Apu::Gb_Apu()
173 172
 	{
174 173
 		auto &o = *this->oscs[i];
175 174
 		o.regs = &this->regs[i * 5];
176
-		o.output = nullptr;
177
-		o.outputs[0] = nullptr;
178
-		o.outputs[1] = nullptr;
179
-		o.outputs[2] = nullptr;
180
-		o.outputs[3] = nullptr;
175
+		o.output = o.outputs[0] = o.outputs[1] = o.outputs[2] = o.outputs[3] = nullptr;
181 176
 		o.good_synth = &this->good_synth;
182 177
 		o.med_synth = &this->med_synth;
183 178
 	}
... ...
@@ -190,7 +185,7 @@ Gb_Apu::Gb_Apu()
190 185
 
191 186
 void Gb_Apu::run_until_(blip_time_t end_time)
192 187
 {
193
-	while (1)
188
+	while (true)
194 189
 	{
195 190
 		// run oscillators
196 191
 		blip_time_t time = end_time;
Browse code

[GSF] Some more code cleanup, also removed a few files that were unneeded.

Naram Qashat authored on 2013/05/16 01:25:34
Showing 1 changed files
... ...
@@ -14,8 +14,6 @@ details. You should have received a copy of the GNU Lesser General Public
14 14
 License along with this module; if not, write to the Free Software Foundation,
15 15
 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
16 16
 
17
-#include "blargg_source.h"
18
-
19 17
 static const unsigned vol_reg = 0xFF24;
20 18
 static const unsigned stereo_reg = 0xFF25;
21 19
 static const unsigned status_reg = 0xFF26;
... ...
@@ -76,7 +74,7 @@ void Gb_Apu::apply_volume()
76 74
 
77 75
 void Gb_Apu::volume(double v)
78 76
 {
79
-	if (volume_ != v)
77
+	if (this->volume_ != v)
80 78
 	{
81 79
 		this->volume_ = v;
82 80
 		this->apply_volume();
... ...
@@ -117,7 +115,7 @@ void Gb_Apu::reduce_clicks(bool reduce)
117 115
 		this->oscs[i]->dac_off_amp = dac_off_amp;
118 116
 
119 117
 	// AGB always eliminates clicks on wave channel using same method
120
-	if (wave.mode == mode_agb)
118
+	if (this->wave.mode == mode_agb)
121 119
 		this->wave.dac_off_amp = -Gb_Osc::dac_bias;
122 120
 }
123 121
 
... ...
@@ -166,10 +164,10 @@ Gb_Apu::Gb_Apu()
166 164
 {
167 165
 	this->wave.wave_ram = &this->regs[wave_ram - start_addr];
168 166
 
169
-	this->oscs [0] = &this->square1;
170
-	this->oscs [1] = &this->square2;
171
-	this->oscs [2] = &this->wave;
172
-	this->oscs [3] = &this->noise;
167
+	this->oscs[0] = &this->square1;
168
+	this->oscs[1] = &this->square2;
169
+	this->oscs[2] = &this->wave;
170
+	this->oscs[3] = &this->noise;
173 171
 
174 172
 	for (int i = osc_count; --i >= 0; )
175 173
 	{
... ...
@@ -199,10 +197,10 @@ void Gb_Apu::run_until_(blip_time_t end_time)
199 197
 		if (time > this->frame_time)
200 198
 			time = this->frame_time;
201 199
 
202
-		this->square1.run(last_time, time);
203
-		this->square2.run(last_time, time);
204
-		this->wave.run(last_time, time);
205
-		this->noise.run(last_time, time);
200
+		this->square1.run(this->last_time, time);
201
+		this->square2.run(this->last_time, time);
202
+		this->wave.run(this->last_time, time);
203
+		this->noise.run(this->last_time, time);
206 204
 		this->last_time = time;
207 205
 
208 206
 		if (time == end_time)
... ...
@@ -358,7 +356,7 @@ int Gb_Apu::read_register(blip_time_t time, unsigned addr)
358 356
 		return this->wave.read(addr);
359 357
 
360 358
 	// Value read back has some bits always set
361
-	static const uint8_t masks [] =
359
+	static const uint8_t masks[] =
362 360
 	{
363 361
 		0x80, 0x3F, 0x00, 0xFF, 0xBF,
364 362
 		0xFF, 0x3F, 0x00, 0xFF, 0xBF,
Browse code

[GSF] Massive code cleanup.

(As an aside, blargg's code style makes me go blarg myself.)

Naram Qashat authored on 2013/05/14 01:07:18
Showing 1 changed files
... ...
@@ -1,5 +1,6 @@
1 1
 // Gb_Snd_Emu 0.2.0. http://www.slack.net/~ant/
2 2
 
3
+#include <algorithm>
3 4
 #include "Gb_Apu.h"
4 5
 
5 6
 /* Copyright (C) 2003-2007 Shay Green. This module is free software; you
... ...
@@ -15,379 +16,370 @@ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
15 16
 
16 17
 #include "blargg_source.h"
17 18
 
18
-unsigned const vol_reg    = 0xFF24;
19
-unsigned const stereo_reg = 0xFF25;
20
-unsigned const status_reg = 0xFF26;
21
-unsigned const wave_ram   = 0xFF30;
19
+static const unsigned vol_reg = 0xFF24;
20
+static const unsigned stereo_reg = 0xFF25;
21
+static const unsigned status_reg = 0xFF26;
22
+static const unsigned wave_ram = 0xFF30;
22 23
 
23
-int const power_mask = 0x80;
24
+static const int power_mask = 0x80;
24 25
 
25
-void Gb_Apu::treble_eq( blip_eq_t const& eq )
26
+void Gb_Apu::treble_eq(const blip_eq_t &eq)
26 27
 {
27
-	good_synth.treble_eq( eq );
28
-	med_synth .treble_eq( eq );
28
+	this->good_synth.treble_eq(eq);
29
+	this->med_synth.treble_eq(eq);
29 30
 }
30 31
 
31
-inline int Gb_Apu::calc_output( int osc ) const
32
+int Gb_Apu::calc_output(int osc) const
32 33
 {
33
-	int bits = regs [stereo_reg - start_addr] >> osc;
34
-	return (bits >> 3 & 2) | (bits & 1);
34
+	int bits = this->regs[stereo_reg - start_addr] >> osc;
35
+	return ((bits >> 3) & 2) | (bits & 1);
35 36
 }
36 37
 
37
-void Gb_Apu::set_output( Blip_Buffer* center, Blip_Buffer* left, Blip_Buffer* right, int osc )
38
+void Gb_Apu::set_output(Blip_Buffer *center, Blip_Buffer *left, Blip_Buffer *right, int osc)
38 39
 {
39 40
 	// Must be silent (all NULL), mono (left and right NULL), or stereo (none NULL)
40
-	require( !center || (center && !left && !right) || (center && left && right) );
41
-	require( (unsigned) osc <= osc_count ); // fails if you pass invalid osc index
41
+	assert(!center || (center && !left && !right) || (center && left && right));
42
+	assert(static_cast<unsigned>(osc) <= osc_count); // fails if you pass invalid osc index
42 43
 
43
-	if ( !center || !left || !right )
44
-	{
45
-		left  = center;
46
-		right = center;
47
-	}
44
+	if (!center || !left || !right)
45
+		left = right = center;
48 46
 
49
-	int i = (unsigned) osc % osc_count;
47
+	int i = static_cast<unsigned>(osc) % osc_count;
50 48
 	do
51 49
 	{
52
-		Gb_Osc& o = *oscs [i];
53
-		o.outputs [1] = right;
54
-		o.outputs [2] = left;
55
-		o.outputs [3] = center;
56
-		o.output = o.outputs [calc_output( i )];
57
-	}
58
-	while ( ++i < osc );
50
+		auto &o = *this->oscs[i];
51
+		o.outputs[1] = right;
52
+		o.outputs[2] = left;
53
+		o.outputs[3] = center;
54
+		o.output = o.outputs[this->calc_output(i)];
55
+	} while (++i < osc);
59 56
 }
60 57
 
61
-void Gb_Apu::synth_volume( int iv )
58
+void Gb_Apu::synth_volume(int iv)
62 59
 {
63
-	double v = volume_ * 0.60 / osc_count / 15 /*steps*/ / 8 /*master vol range*/ * iv;
64
-	good_synth.volume( v );
65
-	med_synth .volume( v );
60
+	double v = this->volume_ * 0.60 / osc_count / 15 /*steps*/ / 8 /*master vol range*/ * iv;
61
+	this->good_synth.volume(v);
62
+	this->med_synth.volume(v);
66 63
 }
67 64
 
68 65
 void Gb_Apu::apply_volume()
69 66
 {
70 67
 	// TODO: Doesn't handle differing left and right volumes (panning).
71 68
 	// Not worth the complexity.
72
-	int data  = regs [vol_reg - start_addr];
73
-	int left  = data >> 4 & 7;
69
+	int data = this->regs[vol_reg - start_addr];
70
+	int left = (data >> 4) & 7;
74 71
 	int right = data & 7;
75 72
 	//if ( data & 0x88 ) dprintf( "Vin: %02X\n", data & 0x88 );
76 73
 	//if ( left != right ) dprintf( "l: %d r: %d\n", left, right );
77
-	synth_volume( max( left, right ) + 1 );
74
+	this->synth_volume(std::max(left, right) + 1);
78 75
 }
79 76
 
80
-void Gb_Apu::volume( double v )
77
+void Gb_Apu::volume(double v)
81 78
 {
82
-	if ( volume_ != v )
79
+	if (volume_ != v)
83 80
 	{
84
-		volume_ = v;
85
-		apply_volume();
81
+		this->volume_ = v;
82
+		this->apply_volume();
86 83
 	}
87 84
 }
88 85
 
89 86
 void Gb_Apu::reset_regs()
90 87
 {
91
-	for ( int i = 0; i < 0x20; i++ )
92
-		regs [i] = 0;
88
+	for (int i = 0; i < 0x20; ++i)
89
+		this->regs[i] = 0;
93 90
 
94
-	square1.reset();
95
-	square2.reset();
96
-	wave   .reset();
97
-	noise  .reset();
91
+	this->square1.reset();
92
+	this->square2.reset();
93
+	this->wave.reset();
94
+	this->noise.reset();
98 95
 
99
-	apply_volume();
96
+	this->apply_volume();
100 97
 }
101 98
 
102 99
 void Gb_Apu::reset_lengths()
103 100
 {
104
-	square1.length_ctr = 64;
105
-	square2.length_ctr = 64;
106
-	wave   .length_ctr = 256;
107
-	noise  .length_ctr = 64;
101
+	this->square1.length_ctr = 64;
102
+	this->square2.length_ctr = 64;
103
+	this->wave.length_ctr = 256;
104
+	this->noise.length_ctr = 64;
108 105
 }
109 106
 
110
-void Gb_Apu::reduce_clicks( bool reduce )
107
+void Gb_Apu::reduce_clicks(bool reduce)
111 108
 {
112
-	reduce_clicks_ = reduce;
109
+	this->reduce_clicks_ = reduce;
113 110
 
114 111
 	// Click reduction makes DAC off generate same output as volume 0
115 112
 	int dac_off_amp = 0;
116
-	if ( reduce && wave.mode != mode_agb ) // AGB already eliminates clicks
113
+	if (reduce && this->wave.mode != mode_agb) // AGB already eliminates clicks
117 114
 		dac_off_amp = -Gb_Osc::dac_bias;
118 115
 
119
-	for ( int i = 0; i < osc_count; i++ )
120
-		oscs [i]->dac_off_amp = dac_off_amp;
116
+	for (int i = 0; i < osc_count; ++i)
117
+		this->oscs[i]->dac_off_amp = dac_off_amp;
121 118
 
122 119
 	// AGB always eliminates clicks on wave channel using same method
123
-	if ( wave.mode == mode_agb )
124
-		wave.dac_off_amp = -Gb_Osc::dac_bias;
120
+	if (wave.mode == mode_agb)
121
+		this->wave.dac_off_amp = -Gb_Osc::dac_bias;
125 122
 }
126 123
 
127
-void Gb_Apu::reset( mode_t mode, bool agb_wave )
124
+void Gb_Apu::reset(mode_t mode, bool agb_wave)
128 125
 {
129 126
 	// Hardware mode
130
-	if ( agb_wave )
127
+	if (agb_wave)
131 128
 		mode = mode_agb; // using AGB wave features implies AGB hardware
132
-	wave.agb_mask = agb_wave ? 0xFF : 0;
133
-	for ( int i = 0; i < osc_count; i++ )
134
-		oscs [i]->mode = mode;
135
-	reduce_clicks( reduce_clicks_ );
129
+	this->wave.agb_mask = agb_wave ? 0xFF : 0;
130
+	for (int i = 0; i < osc_count; ++i)
131
+		this->oscs[i]->mode = mode;
132
+	this->reduce_clicks(this->reduce_clicks_);
136 133
 
137 134
 	// Reset state
138
-	frame_time  = 0;
139
-	last_time   = 0;
140
-	frame_phase = 0;
135
+	this->frame_time = 0;
136
+	this->last_time = 0;
137
+	this->frame_phase = 0;
141 138
 
142
-	reset_regs();
143
-	reset_lengths();
139
+	this->reset_regs();
140
+	this->reset_lengths();
144 141
 
145 142
 	// Load initial wave RAM
146
-	static byte const initial_wave [2] [16] = {
147
-		{0x84,0x40,0x43,0xAA,0x2D,0x78,0x92,0x3C,0x60,0x59,0x59,0xB0,0x34,0xB8,0x2E,0xDA},
148
-		{0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF},
143
+	static const uint8_t initial_wave[][16] =
144
+	{
145
+		{ 0x84, 0x40, 0x43, 0xAA, 0x2D, 0x78, 0x92, 0x3C, 0x60, 0x59, 0x59, 0xB0, 0x34, 0xB8, 0x2E, 0xDA },
146
+		{ 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF }
149 147
 	};
150
-	for ( int b = 2; --b >= 0; )
148
+	for (int b = 2; --b >= 0; )
151 149
 	{
152 150
 		// Init both banks (does nothing if not in AGB mode)
153 151
 		// TODO: verify that this works
154
-		write_register( 0, 0xFF1A, b * 0x40 );
155
-		for ( unsigned i = 0; i < sizeof initial_wave [0]; i++ )
156
-			write_register( 0, i + wave_ram, initial_wave [(mode != mode_dmg)] [i] );
152
+		this->write_register(0, 0xFF1A, b * 0x40);
153
+		for (unsigned i = 0; i < sizeof(initial_wave[0]); ++i)
154
+			this->write_register(0, i + wave_ram, initial_wave[mode != mode_dmg][i]);
157 155
 	}
158 156
 }
159 157
 
160
-void Gb_Apu::set_tempo( double t )
158
+void Gb_Apu::set_tempo(double t)
161 159
 {
162
-	frame_period = 4194304 / 512; // 512 Hz
163
-	if ( t != 1.0 )
164
-		frame_period = blip_time_t (frame_period / t);
160
+	this->frame_period = 4194304 / 512; // 512 Hz
161
+	if (t != 1.0)
162
+		this->frame_period = static_cast<blip_time_t>(this->frame_period / t);
165 163
 }
166 164
 
167 165
 Gb_Apu::Gb_Apu()
168 166
 {
169
-	wave.wave_ram = &regs [wave_ram - start_addr];
167
+	this->wave.wave_ram = &this->regs[wave_ram - start_addr];
170 168
 
171
-	oscs [0] = &square1;
172
-	oscs [1] = &square2;
173
-	oscs [2] = &wave;
174
-	oscs [3] = &noise;
169
+	this->oscs [0] = &this->square1;
170
+	this->oscs [1] = &this->square2;
171
+	this->oscs [2] = &this->wave;
172
+	this->oscs [3] = &this->noise;
175 173
 
176
-	for ( int i = osc_count; --i >= 0; )
174
+	for (int i = osc_count; --i >= 0; )
177 175
 	{
178
-		Gb_Osc& o = *oscs [i];
179
-		o.regs        = &regs [i * 5];
180
-		o.output      = 0;
181
-		o.outputs [0] = 0;
182
-		o.outputs [1] = 0;
183
-		o.outputs [2] = 0;
184
-		o.outputs [3] = 0;
185
-		o.good_synth  = &good_synth;
186
-		o.med_synth   = &med_synth;
176
+		auto &o = *this->oscs[i];
177
+		o.regs = &this->regs[i * 5];
178
+		o.output = nullptr;
179
+		o.outputs[0] = nullptr;
180
+		o.outputs[1] = nullptr;
181
+		o.outputs[2] = nullptr;
182
+		o.outputs[3] = nullptr;
183
+		o.good_synth = &this->good_synth;
184
+		o.med_synth = &this->med_synth;
187 185
 	}
188 186
 
189
-	reduce_clicks_ = false;
190
-	set_tempo( 1.0 );
191
-	volume_ = 1.0;
192
-	reset();
187
+	this->reduce_clicks_ = false;
188
+	this->set_tempo(1.0);
189
+	this->volume_ = 1.0;
190
+	this->reset();
193 191
 }
194 192
 
195
-void Gb_Apu::run_until_( blip_time_t end_time )
193
+void Gb_Apu::run_until_(blip_time_t end_time)
196 194
 {
197
-	while ( true )
195
+	while (1)
198 196
 	{
199 197
 		// run oscillators
200 198
 		blip_time_t time = end_time;
201
-		if ( time > frame_time )
202
-			time = frame_time;
199
+		if (time > this->frame_time)
200
+			time = this->frame_time;
203 201
 
204
-		square1.run( last_time, time );
205
-		square2.run( last_time, time );
206
-		wave   .run( last_time, time );
207
-		noise  .run( last_time, time );
208
-		last_time = time;
202
+		this->square1.run(last_time, time);
203
+		this->square2.run(last_time, time);
204
+		this->wave.run(last_time, time);
205
+		this->noise.run(last_time, time);
206
+		this->last_time = time;
209 207
 
210
-		if ( time == end_time )
208
+		if (time == end_time)
211 209
 			break;
212 210
 
213 211
 		// run frame sequencer
214
-		frame_time += frame_period * Gb_Osc::clk_mul;
215
-		switch ( frame_phase++ )
212
+		this->frame_time += this->frame_period * Gb_Osc::clk_mul;
213
+		switch (this->frame_phase++)
216 214
 		{
217
-		case 2:
218
-		case 6:
219
-			// 128 Hz
220
-			square1.clock_sweep();
221
-		case 0:
222
-		case 4:
223
-			// 256 Hz
224
-			square1.clock_length();
225
-			square2.clock_length();
226
-			wave   .clock_length();
227
-			noise  .clock_length();
228
-			break;
229
-
230
-		case 7:
231
-			// 64 Hz
232
-			frame_phase = 0;
233
-			square1.clock_envelope();
234
-			square2.clock_envelope();
235
-			noise  .clock_envelope();
215
+			case 2:
216
+			case 6:
217
+				// 128 Hz
218
+				this->square1.clock_sweep();
219
+			case 0:
220
+			case 4:
221
+				// 256 Hz
222
+				this->square1.clock_length();
223
+				this->square2.clock_length();
224
+				this->wave.clock_length();
225
+				this->noise.clock_length();
226
+				break;
227
+			case 7:
228
+				// 64 Hz
229
+				this->frame_phase = 0;
230
+				this->square1.clock_envelope();
231
+				this->square2.clock_envelope();
232
+				this->noise.clock_envelope();
236 233
 		}
237 234
 	}
238 235
 }
239 236
 
240
-inline void Gb_Apu::run_until( blip_time_t time )
237
+void Gb_Apu::run_until(blip_time_t time)
241 238
 {
242
-	require( time >= last_time ); // end_time must not be before previous time
243
-	if ( time > last_time )
244
-		run_until_( time );
239
+	assert(time >= this->last_time); // end_time must not be before previous time
240
+	if (time > this->last_time)
241
+		this->run_until_(time);
245 242
 }
246 243
 
247
-void Gb_Apu::end_frame( blip_time_t end_time )
244
+void Gb_Apu::end_frame(blip_time_t end_time)
248 245
 {
249
-	if ( end_time > last_time )
250
-		run_until( end_time );
246
+	if (end_time > this->last_time)
247
+		this->run_until(end_time);
251 248
 
252
-	frame_time -= end_time;
253
-	assert( frame_time >= 0 );
249
+	this->frame_time -= end_time;
250
+	assert(this->frame_time >= 0);
254 251
 
255
-	last_time -= end_time;
256
-	assert( last_time >= 0 );
252
+	this->last_time -= end_time;
253
+	assert(this->last_time >= 0);
257 254
 }
258 255
 
259
-void Gb_Apu::silence_osc( Gb_Osc& o )
256
+void Gb_Apu::silence_osc(Gb_Osc &o)
260 257
 {
261 258
 	int delta = -o.last_amp;
262
-	if ( delta )
259
+	if (delta)
263 260
 	{
264 261
 		o.last_amp = 0;
265
-		if ( o.output )
262
+		if (o.output)
266 263
 		{
267 264
 			o.output->set_modified();
268
-			med_synth.offset( last_time, delta, o.output );
265
+			this->med_synth.offset(this->last_time, delta, o.output);
269 266
 		}
270 267
 	}
271 268
 }
272 269
 
273 270
 void Gb_Apu::apply_stereo()
274 271
 {
275
-	for ( int i = osc_count; --i >= 0; )
272
+	for (int i = osc_count; --i >= 0; )
276 273
 	{
277
-		Gb_Osc& o = *oscs [i];
278
-		Blip_Buffer* out = o.outputs [calc_output( i )];
279
-		if ( o.output != out )
274
+		auto &o = *this->oscs[i];
275
+		auto out = o.outputs[this->calc_output(i)];
276
+		if (o.output != out)
280 277
 		{
281
-			silence_osc( o );
278
+			this->silence_osc(o);
282 279
 			o.output = out;
283 280
 		}
284 281
 	}
285 282
 }
286 283
 
287
-void Gb_Apu::write_register( blip_time_t time, unsigned addr, int data )
284
+void Gb_Apu::write_register(blip_time_t time, unsigned addr, int data)
288 285
 {
289
-	require( (unsigned) data < 0x100 );
286
+	assert(static_cast<unsigned>(data) < 0x100);
290 287
 
291 288
 	int reg = addr - start_addr;
292
-	if ( (unsigned) reg >= register_count )
289
+	if (static_cast<unsigned>(reg) >= register_count)
293 290
 	{
294
-		require( false );
291
+		assert(false);
295 292
 		return;
296 293
 	}
297 294
 
298
-	if ( addr < status_reg && !(regs [status_reg - start_addr] & power_mask) )
295
+	if (addr < status_reg && !(this->regs[status_reg - start_addr] & power_mask))
299 296
 	{
300 297
 		// Power is off
301 298
 
302 299
 		// length counters can only be written in DMG mode
303
-		if ( wave.mode != mode_dmg || (reg != 1 && reg != 5+1 && reg != 10+1 && reg != 15+1) )
300
+		if (this->wave.mode != mode_dmg || (reg != 1 && reg != 6 && reg != 11 && reg != 16))
304 301
 			return;
305 302
 
306
-		if ( reg < 10 )
303
+		if (reg < 10)
307 304
 			data &= 0x3F; // clear square duty
308 305
 	}
309 306
 
310
-	run_until( time );
307
+	this->run_until(time);
311 308
 
312
-	if ( addr >= wave_ram )
313
-	{
314
-		wave.write( addr, data );
315
-	}
309
+	if (addr >= wave_ram)
310
+		this->wave.write(addr, data);
316 311
 	else
317 312
 	{
318
-		int old_data = regs [reg];
319
-		regs [reg] = data;
313
+		int old_data = this->regs[reg];
314
+		this->regs[reg] = data;
320 315
 
321
-		if ( addr < vol_reg )
322
-		{
316
+		if (addr < vol_reg)
323 317
 			// Oscillator
324
-			write_osc( reg / 5, reg, old_data, data );
325
-		}
326
-		else if ( addr == vol_reg && data != old_data )
318
+			this->write_osc(reg / 5, reg, old_data, data);
319
+		else if (addr == vol_reg && data != old_data)
327 320
 		{
328 321
 			// Master volume
329
-			for ( int i = osc_count; --i >= 0; )
330
-				silence_osc( *oscs [i] );
322
+			for (int i = osc_count; --i >= 0; )
323
+				this->silence_osc(*this->oscs[i]);
331 324
 
332
-			apply_volume();
325
+			this->apply_volume();
333 326
 		}
334
-		else if ( addr == stereo_reg )
335
-		{
327
+		else if (addr == stereo_reg)
336 328
 			// Stereo panning
337
-			apply_stereo();
338
-		}
339
-		else if ( addr == status_reg && (data ^ old_data) & power_mask )
329
+			this->apply_stereo();
330
+		else if (addr == status_reg && ((data ^ old_data) & power_mask))
340 331
 		{
341 332
 			// Power control
342
-			frame_phase = 0;
343
-			for ( int i = osc_count; --i >= 0; )
344
-				silence_osc( *oscs [i] );
333
+			this->frame_phase = 0;
334
+			for (int i = osc_count; --i >= 0; )
335
+				this->silence_osc(*this->oscs[i]);
345 336
 
346
-			reset_regs();
347
-			if ( wave.mode != mode_dmg )
348
-				reset_lengths();
337
+			this->reset_regs();
338
+			if (this->wave.mode != mode_dmg)
339
+				this->reset_lengths();
349 340
 
350
-			regs [status_reg - start_addr] = data;
341
+			this->regs[status_reg - start_addr] = data;
351 342
 		}
352 343
 	}
353 344
 }
354 345
 
355
-int Gb_Apu::read_register( blip_time_t time, unsigned addr )
346
+int Gb_Apu::read_register(blip_time_t time, unsigned addr)
356 347
 {
357
-	run_until( time );
348
+	this->run_until(time);
358 349
 
359 350
 	int reg = addr - start_addr;
360
-	if ( (unsigned) reg >= register_count )
351
+	if (static_cast<unsigned>(reg) >= register_count)
361 352
 	{
362
-		require( false );
353
+		assert(false);
363 354
 		return 0;
364 355
 	}
365 356
 
366
-	if ( addr >= wave_ram )
367
-		return wave.read( addr );
357
+	if (addr >= wave_ram)
358
+		return this->wave.read(addr);
368 359
 
369 360
 	// Value read back has some bits always set
370
-	static byte const masks [] = {
371
-		0x80,0x3F,0x00,0xFF,0xBF,
372
-		0xFF,0x3F,0x00,0xFF,0xBF,
373
-		0x7F,0xFF,0x9F,0xFF,0xBF,
374
-		0xFF,0xFF,0x00,0x00,0xBF,
375
-		0x00,0x00,0x70,
376
-		0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
361
+	static const uint8_t masks [] =
362
+	{
363
+		0x80, 0x3F, 0x00, 0xFF, 0xBF,
364
+		0xFF, 0x3F, 0x00, 0xFF, 0xBF,
365
+		0x7F, 0xFF, 0x9F, 0xFF, 0xBF,
366
+		0xFF, 0xFF, 0x00, 0x00, 0xBF,
367
+		0x00, 0x00, 0x70,
368
+		0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
377 369
 	};
378
-	int mask = masks [reg];
379
-	if ( wave.agb_mask && (reg == 10 || reg == 12) )
370
+	int mask = masks[reg];
371
+	if (this->wave.agb_mask && (reg == 10 || reg == 12))
380 372
 		mask = 0x1F; // extra implemented bits in wave regs on AGB
381
-	int data = regs [reg] | mask;
373
+	int data = this->regs[reg] | mask;
382 374
 
383 375
 	// Status register
384
-	if ( addr == status_reg )
376
+	if (addr == status_reg)
385 377
 	{
386 378
 		data &= 0xF0;
387
-		data |= (int) square1.enabled << 0;
388
-		data |= (int) square2.enabled << 1;
389
-		data |= (int) wave   .enabled << 2;
390
-		data |= (int) noise  .enabled << 3;
379
+		data |= static_cast<int>(this->square1.enabled);
380
+		data |= static_cast<int>(this->square2.enabled) << 1;
381
+		data |= static_cast<int>(this->wave.enabled) << 2;
382
+		data |= static_cast<int>(this->noise.enabled) << 3;
391 383
 	}
392 384
 
393 385
 	return data;
... ...
@@ -395,10 +387,9 @@ int Gb_Apu::read_register( blip_time_t time, unsigned addr )
395 387
 
396 388
 int Gb_Apu::read_status()
397 389
 {
398
-	int data = 0;
399
-	data |= (int) square1.enabled << 0;
400
-	data |= (int) square2.enabled << 1;
401
-	data |= (int) wave   .enabled << 2;
402
-	data |= (int) noise  .enabled << 3;
390
+	int data = static_cast<int>(this->square1.enabled);
391
+	data |= static_cast<int>(this->square2.enabled) << 1;
392
+	data |= static_cast<int>(this->wave.enabled) << 2;
393
+	data |= static_cast<int>(this->noise.enabled) << 3;
403 394
 	return data;
404 395
 }
Browse code

Import actual code.

Naram Qashat authored on 2013/03/26 02:41:19
Showing 1 changed files
1 1
new file mode 100644
... ...
@@ -0,0 +1,404 @@
1
+// Gb_Snd_Emu 0.2.0. http://www.slack.net/~ant/
2
+
3
+#include "Gb_Apu.h"
4
+
5
+/* Copyright (C) 2003-2007 Shay Green. This module is free software; you
6
+can redistribute it and/or modify it under the terms of the GNU Lesser
7
+General Public License as published by the Free Software Foundation; either
8
+version 2.1 of the License, or (at your option) any later version. This
9
+module is distributed in the hope that it will be useful, but WITHOUT ANY
10
+WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11
+FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
12
+details. You should have received a copy of the GNU Lesser General Public
13
+License along with this module; if not, write to the Free Software Foundation,
14
+Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
15
+
16
+#include "blargg_source.h"
17
+
18
+unsigned const vol_reg    = 0xFF24;
19
+unsigned const stereo_reg = 0xFF25;
20
+unsigned const status_reg = 0xFF26;
21
+unsigned const wave_ram   = 0xFF30;
22
+
23
+int const power_mask = 0x80;
24
+
25
+void Gb_Apu::treble_eq( blip_eq_t const& eq )
26
+{
27
+	good_synth.treble_eq( eq );
28
+	med_synth .treble_eq( eq );
29
+}
30
+
31
+inline int Gb_Apu::calc_output( int osc ) const
32
+{
33
+	int bits = regs [stereo_reg - start_addr] >> osc;
34
+	return (bits >> 3 & 2) | (bits & 1);
35
+}
36
+
37
+void Gb_Apu::set_output( Blip_Buffer* center, Blip_Buffer* left, Blip_Buffer* right, int osc )
38
+{
39
+	// Must be silent (all NULL), mono (left and right NULL), or stereo (none NULL)
40
+	require( !center || (center && !left && !right) || (center && left && right) );
41
+	require( (unsigned) osc <= osc_count ); // fails if you pass invalid osc index
42
+
43
+	if ( !center || !left || !right )
44
+	{
45
+		left  = center;
46
+		right = center;
47
+	}
48
+
49
+	int i = (unsigned) osc % osc_count;
50
+	do
51
+	{
52
+		Gb_Osc& o = *oscs [i];
53
+		o.outputs [1] = right;
54
+		o.outputs [2] = left;
55
+		o.outputs [3] = center;
56
+		o.output = o.outputs [calc_output( i )];
57
+	}
58
+	while ( ++i < osc );
59
+}
60
+
61
+void Gb_Apu::synth_volume( int iv )
62
+{
63
+	double v = volume_ * 0.60 / osc_count / 15 /*steps*/ / 8 /*master vol range*/ * iv;
64
+	good_synth.volume( v );
65
+	med_synth .volume( v );
66
+}
67
+
68
+void Gb_Apu::apply_volume()
69
+{
70
+	// TODO: Doesn't handle differing left and right volumes (panning).
71
+	// Not worth the complexity.
72
+	int data  = regs [vol_reg - start_addr];
73
+	int left  = data >> 4 & 7;
74
+	int right = data & 7;
75
+	//if ( data & 0x88 ) dprintf( "Vin: %02X\n", data & 0x88 );
76
+	//if ( left != right ) dprintf( "l: %d r: %d\n", left, right );
77
+	synth_volume( max( left, right ) + 1 );
78
+}
79
+
80
+void Gb_Apu::volume( double v )
81
+{
82
+	if ( volume_ != v )
83
+	{
84
+		volume_ = v;
85
+		apply_volume();
86
+	}
87
+}
88
+
89
+void Gb_Apu::reset_regs()
90
+{
91
+	for ( int i = 0; i < 0x20; i++ )
92
+		regs [i] = 0;
93
+
94
+	square1.reset();
95
+	square2.reset();
96
+	wave   .reset();
97
+	noise  .reset();
98
+
99
+	apply_volume();
100
+}
101
+
102
+void Gb_Apu::reset_lengths()
103
+{
104
+	square1.length_ctr = 64;
105
+	square2.length_ctr = 64;
106
+	wave   .length_ctr = 256;
107
+	noise  .length_ctr = 64;
108
+}
109
+
110
+void Gb_Apu::reduce_clicks( bool reduce )
111
+{
112
+	reduce_clicks_ = reduce;
113
+
114
+	// Click reduction makes DAC off generate same output as volume 0
115
+	int dac_off_amp = 0;
116
+	if ( reduce && wave.mode != mode_agb ) // AGB already eliminates clicks
117
+		dac_off_amp = -Gb_Osc::dac_bias;
118
+
119
+	for ( int i = 0; i < osc_count; i++ )
120
+		oscs [i]->dac_off_amp = dac_off_amp;
121
+
122
+	// AGB always eliminates clicks on wave channel using same method
123
+	if ( wave.mode == mode_agb )
124
+		wave.dac_off_amp = -Gb_Osc::dac_bias;
125
+}
126
+
127
+void Gb_Apu::reset( mode_t mode, bool agb_wave )
128
+{
129
+	// Hardware mode
130
+	if ( agb_wave )
131
+		mode = mode_agb; // using AGB wave features implies AGB hardware
132
+	wave.agb_mask = agb_wave ? 0xFF : 0;
133
+	for ( int i = 0; i < osc_count; i++ )
134
+		oscs [i]->mode = mode;
135
+	reduce_clicks( reduce_clicks_ );
136
+
137
+	// Reset state
138
+	frame_time  = 0;
139
+	last_time   = 0;
140
+	frame_phase = 0;
141
+
142
+	reset_regs();
143
+	reset_lengths();
144
+
145
+	// Load initial wave RAM
146
+	static byte const initial_wave [2] [16] = {
147
+		{0x84,0x40,0x43,0xAA,0x2D,0x78,0x92,0x3C,0x60,0x59,0x59,0xB0,0x34,0xB8,0x2E,0xDA},
148
+		{0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF},
149
+	};
150
+	for ( int b = 2; --b >= 0; )
151
+	{
152
+		// Init both banks (does nothing if not in AGB mode)
153
+		// TODO: verify that this works
154
+		write_register( 0, 0xFF1A, b * 0x40 );
155
+		for ( unsigned i = 0; i < sizeof initial_wave [0]; i++ )
156
+			write_register( 0, i + wave_ram, initial_wave [(mode != mode_dmg)] [i] );
157
+	}
158
+}
159
+
160
+void Gb_Apu::set_tempo( double t )
161
+{
162
+	frame_period = 4194304 / 512; // 512 Hz
163
+	if ( t != 1.0 )
164
+		frame_period = blip_time_t (frame_period / t);
165
+}
166
+
167
+Gb_Apu::Gb_Apu()
168
+{
169
+	wave.wave_ram = &regs [wave_ram - start_addr];
170
+
171
+	oscs [0] = &square1;
172
+	oscs [1] = &square2;
173
+	oscs [2] = &wave;
174
+	oscs [3] = &noise;
175
+
176
+	for ( int i = osc_count; --i >= 0; )
177
+	{
178
+		Gb_Osc& o = *oscs [i];
179
+		o.regs        = &regs [i * 5];
180
+		o.output      = 0;
181
+		o.outputs [0] = 0;
182
+		o.outputs [1] = 0;
183
+		o.outputs [2] = 0;
184
+		o.outputs [3] = 0;
185
+		o.good_synth  = &good_synth;
186
+		o.med_synth   = &med_synth;
187
+	}
188
+
189
+	reduce_clicks_ = false;
190
+	set_tempo( 1.0 );
191
+	volume_ = 1.0;
192
+	reset();
193
+}
194
+
195
+void Gb_Apu::run_until_( blip_time_t end_time )
196
+{
197
+	while ( true )
198
+	{
199
+		// run oscillators
200
+		blip_time_t time = end_time;
201
+		if ( time > frame_time )
202
+			time = frame_time;
203
+
204
+		square1.run( last_time, time );
205
+		square2.run( last_time, time );
206
+		wave   .run( last_time, time );
207
+		noise  .run( last_time, time );
208
+		last_time = time;
209
+
210
+		if ( time == end_time )
211
+			break;
212
+
213
+		// run frame sequencer
214
+		frame_time += frame_period * Gb_Osc::clk_mul;
215
+		switch ( frame_phase++ )
216
+		{
217
+		case 2:
218
+		case 6:
219
+			// 128 Hz
220
+			square1.clock_sweep();
221
+		case 0:
222
+		case 4:
223
+			// 256 Hz
224
+			square1.clock_length();
225
+			square2.clock_length();
226
+			wave   .clock_length();
227
+			noise  .clock_length();
228
+			break;
229
+
230
+		case 7:
231
+			// 64 Hz
232
+			frame_phase = 0;
233
+			square1.clock_envelope();
234
+			square2.clock_envelope();
235
+			noise  .clock_envelope();
236
+		}
237
+	}
238
+}
239
+
240
+inline void Gb_Apu::run_until( blip_time_t time )
241
+{
242
+	require( time >= last_time ); // end_time must not be before previous time
243
+	if ( time > last_time )
244
+		run_until_( time );
245
+}
246
+
247
+void Gb_Apu::end_frame( blip_time_t end_time )
248
+{
249
+	if ( end_time > last_time )
250
+		run_until( end_time );
251
+
252
+	frame_time -= end_time;
253
+	assert( frame_time >= 0 );
254
+
255
+	last_time -= end_time;
256
+	assert( last_time >= 0 );
257
+}
258
+
259
+void Gb_Apu::silence_osc( Gb_Osc& o )
260
+{
261
+	int delta = -o.last_amp;
262
+	if ( delta )
263
+	{
264
+		o.last_amp = 0;
265
+		if ( o.output )
266
+		{
267
+			o.output->set_modified();
268
+			med_synth.offset( last_time, delta, o.output );
269
+		}
270
+	}
271
+}
272
+
273
+void Gb_Apu::apply_stereo()
274
+{
275
+	for ( int i = osc_count; --i >= 0; )
276
+	{
277
+		Gb_Osc& o = *oscs [i];
278
+		Blip_Buffer* out = o.outputs [calc_output( i )];
279
+		if ( o.output != out )
280
+		{
281
+			silence_osc( o );
282
+			o.output = out;
283
+		}
284
+	}
285
+}
286
+
287
+void Gb_Apu::write_register( blip_time_t time, unsigned addr, int data )
288
+{
289
+	require( (unsigned) data < 0x100 );
290
+
291
+	int reg = addr - start_addr;
292
+	if ( (unsigned) reg >= register_count )
293
+	{
294
+		require( false );
295
+		return;
296
+	}
297
+
298
+	if ( addr < status_reg && !(regs [status_reg - start_addr] & power_mask) )
299
+	{
300
+		// Power is off
301
+
302
+		// length counters can only be written in DMG mode
303
+		if ( wave.mode != mode_dmg || (reg != 1 && reg != 5+1 && reg != 10+1 && reg != 15+1) )
304
+			return;
305
+
306
+		if ( reg < 10 )
307
+			data &= 0x3F; // clear square duty
308
+	}
309
+
310
+	run_until( time );
311
+
312
+	if ( addr >= wave_ram )
313
+	{
314
+		wave.write( addr, data );
315
+	}
316
+	else
317
+	{
318
+		int old_data = regs [reg];
319
+		regs [reg] = data;
320
+
321
+		if ( addr < vol_reg )
322
+		{
323
+			// Oscillator
324
+			write_osc( reg / 5, reg, old_data, data );
325
+		}
326
+		else if ( addr == vol_reg && data != old_data )
327
+		{
328
+			// Master volume
329
+			for ( int i = osc_count; --i >= 0; )
330
+				silence_osc( *oscs [i] );
331
+
332
+			apply_volume();
333
+		}
334
+		else if ( addr == stereo_reg )
335
+		{
336
+			// Stereo panning
337
+			apply_stereo();
338
+		}
339
+		else if ( addr == status_reg && (data ^ old_data) & power_mask )
340
+		{
341
+			// Power control
342
+			frame_phase = 0;
343
+			for ( int i = osc_count; --i >= 0; )
344
+				silence_osc( *oscs [i] );
345
+
346
+			reset_regs();
347
+			if ( wave.mode != mode_dmg )
348
+				reset_lengths();
349
+
350
+			regs [status_reg - start_addr] = data;
351
+		}
352
+	}
353
+}
354
+
355
+int Gb_Apu::read_register( blip_time_t time, unsigned addr )
356
+{
357
+	run_until( time );
358
+
359
+	int reg = addr - start_addr;
360
+	if ( (unsigned) reg >= register_count )
361
+	{
362
+		require( false );
363
+		return 0;
364
+	}
365
+
366
+	if ( addr >= wave_ram )
367
+		return wave.read( addr );
368
+
369
+	// Value read back has some bits always set
370
+	static byte const masks [] = {
371
+		0x80,0x3F,0x00,0xFF,0xBF,
372
+		0xFF,0x3F,0x00,0xFF,0xBF,
373
+		0x7F,0xFF,0x9F,0xFF,0xBF,
374
+		0xFF,0xFF,0x00,0x00,0xBF,
375
+		0x00,0x00,0x70,
376
+		0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
377
+	};
378
+	int mask = masks [reg];
379
+	if ( wave.agb_mask && (reg == 10 || reg == 12) )
380
+		mask = 0x1F; // extra implemented bits in wave regs on AGB
381
+	int data = regs [reg] | mask;
382
+
383
+	// Status register
384
+	if ( addr == status_reg )
385
+	{
386
+		data &= 0xF0;
387
+		data |= (int) square1.enabled << 0;
388
+		data |= (int) square2.enabled << 1;
389
+		data |= (int) wave   .enabled << 2;
390
+		data |= (int) noise  .enabled << 3;
391
+	}
392
+
393
+	return data;
394
+}
395
+
396
+int Gb_Apu::read_status()
397
+{
398
+	int data = 0;
399
+	data |= (int) square1.enabled << 0;
400
+	data |= (int) square2.enabled << 1;
401
+	data |= (int) wave   .enabled << 2;
402
+	data |= (int) noise  .enabled << 3;
403
+	return data;
404
+}