diff src/console/Gb_Apu.cxx @ 316:fb513e10174e trunk

[svn] - merge libconsole-blargg into mainline libconsole: + obsoletes plugins-ugly:sapplug
author nenolod
date Thu, 30 Nov 2006 19:54:33 -0800
parents 3da1b8942b8b
children
line wrap: on
line diff
--- a/src/console/Gb_Apu.cxx	Wed Nov 29 14:42:11 2006 -0800
+++ b/src/console/Gb_Apu.cxx	Thu Nov 30 19:54:33 2006 -0800
@@ -1,5 +1,4 @@
-
-// Gb_Snd_Emu 0.1.4. http://www.slack.net/~ant/
+// Gb_Snd_Emu 0.1.5. http://www.slack.net/~ant/
 
 #include "Gb_Apu.h"
 
@@ -11,15 +10,15 @@
 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
+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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
 
-#include BLARGG_SOURCE_BEGIN
+#include "blargg_source.h"
 
-const unsigned vol_reg    = 0xFF24;
-const unsigned status_reg = 0xFF26;
+unsigned const vol_reg    = 0xFF24;
+unsigned const status_reg = 0xFF26;
 
 Gb_Apu::Gb_Apu()
 {
@@ -37,21 +36,18 @@
 	{
 		Gb_Osc& osc = *oscs [i];
 		osc.regs = &regs [i * 5];
-		osc.output = NULL;
-		osc.outputs [0] = NULL;
-		osc.outputs [1] = NULL;
-		osc.outputs [2] = NULL;
-		osc.outputs [3] = NULL;
+		osc.output = 0;
+		osc.outputs [0] = 0;
+		osc.outputs [1] = 0;
+		osc.outputs [2] = 0;
+		osc.outputs [3] = 0;
 	}
 	
+	set_tempo( 1.0 );
 	volume( 1.0 );
 	reset();
 }
 
-Gb_Apu::~Gb_Apu()
-{
-}
-
 void Gb_Apu::treble_eq( const blip_eq_t& eq )
 {
 	square_synth.treble_eq( eq );
@@ -77,14 +73,15 @@
 
 void Gb_Apu::update_volume()
 {
-	// to do: doesn't handle differing left/right global volume
+	// TODO: doesn't handle differing left/right global volume (support would
+	// require modification to all oscillator code)
 	int data = regs [vol_reg - start_addr];
 	double vol = (max( data & 7, data >> 4 & 7 ) + 1) * volume_unit;
 	square_synth.volume( vol );
 	other_synth.volume( vol );
 }
 
-static unsigned char const powerup_regs [0x30] = {
+static unsigned char const powerup_regs [0x20] = {
 	0x80,0x3F,0x00,0xFF,0xBF, // square 1
 	0xFF,0x3F,0x00,0xFF,0xBF, // square 2
 	0x7F,0xFF,0x9F,0xFF,0xBF, // wave
@@ -92,17 +89,21 @@
 	0x00, // left/right enables
 	0x77, // master volume
 	0x80, // power
-	0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
-	0x84,0x40,0x43,0xAA,0x2D,0x78,0x92,0x3C, // wave table
-	0x60,0x59,0x59,0xB0,0x34,0xB8,0x2E,0xDA
+	0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
 };
 
+void Gb_Apu::set_tempo( double t )
+{
+	frame_period = 4194304 / 256; // 256 Hz
+	if ( t != 1.0 )
+		frame_period = blip_time_t (frame_period / t);
+}
+
 void Gb_Apu::reset()
 {
 	next_frame_time = 0;
-	last_time = 0;
-	frame_count = 0;
-	stereo_found = false;
+	last_time       = 0;
+	frame_count     = 0;
 	
 	square1.reset();
 	square2.reset();
@@ -117,12 +118,15 @@
 	
 	regs [status_reg - start_addr] = 0x01; // force power
 	write_register( 0, status_reg, 0x00 );
+	
+	static unsigned char const initial_wave [] = {
+		0x84,0x40,0x43,0xAA,0x2D,0x78,0x92,0x3C, // wave table
+		0x60,0x59,0x59,0xB0,0x34,0xB8,0x2E,0xDA
+	};
+	memcpy( wave.wave, initial_wave, sizeof wave.wave );
 }
 
-// to do: remove
-static unsigned long abs_time;
-
-void Gb_Apu::run_until( gb_time_t end_time )
+void Gb_Apu::run_until( blip_time_t end_time )
 {
 	require( end_time >= last_time ); // end_time must not be before previous time
 	if ( end_time == last_time )
@@ -130,7 +134,7 @@
 	
 	while ( true )
 	{
-		gb_time_t time = next_frame_time;
+		blip_time_t time = next_frame_time;
 		if ( time > end_time )
 			time = end_time;
 		
@@ -140,12 +144,11 @@
 			Gb_Osc& osc = *oscs [i];
 			if ( osc.output )
 			{
+				osc.output->set_modified(); // TODO: misses optimization opportunities?
 				int playing = false;
 				if ( osc.enabled && osc.volume &&
 						(!(osc.regs [4] & osc.len_enabled_mask) || osc.length) )
 					playing = -1;
-				if ( osc.output != osc.outputs [3] )
-					stereo_found = true;
 				switch ( i )
 				{
 				case 0: square1.run( last_time, time, playing ); break;
@@ -160,7 +163,7 @@
 		if ( time == end_time )
 			break;
 		
-		next_frame_time += 4194304 / 256; // 256 Hz
+		next_frame_time += frame_period;
 		
 		// 256 Hz actions
 		square1.clock_length();
@@ -182,25 +185,19 @@
 	}
 }
 
-bool Gb_Apu::end_frame( gb_time_t end_time )
+void Gb_Apu::end_frame( blip_time_t end_time )
 {
 	if ( end_time > last_time )
 		run_until( end_time );
 	
-	abs_time += end_time;
-	
 	assert( next_frame_time >= end_time );
 	next_frame_time -= end_time;
 	
 	assert( last_time >= end_time );
 	last_time -= end_time;
-	
-	bool result = stereo_found;
-	stereo_found = false;
-	return result;
 }
 
-void Gb_Apu::write_register( gb_time_t time, gb_addr_t addr, int data )
+void Gb_Apu::write_register( blip_time_t time, unsigned addr, int data )
 {
 	require( (unsigned) data < 0x100 );
 	
@@ -266,7 +263,7 @@
 		{
 			if ( !(data & 0x80) )
 			{
-				for ( int i = 0; i < (int) sizeof powerup_regs; i++ )
+				for ( unsigned i = 0; i < sizeof powerup_regs; i++ )
 				{
 					if ( i != status_reg - start_addr )
 						write_register( time, i + start_addr, powerup_regs [i] );
@@ -280,14 +277,13 @@
 	}
 	else if ( addr >= 0xFF30 )
 	{
-		
 		int index = (addr & 0x0F) * 2;
 		wave.wave [index] = data >> 4;
 		wave.wave [index + 1] = data & 0x0F;
 	}
 }
 
-int Gb_Apu::read_register( gb_time_t time, gb_addr_t addr )
+int Gb_Apu::read_register( blip_time_t time, unsigned addr )
 {
 	run_until( time );
 	
@@ -308,4 +304,3 @@
 	
 	return data;
 }
-