1 // AY-3-8910 sound chip emulator
2 
3 // $package
4 #ifndef AY_APU_H
5 #define AY_APU_H
6 
7 #include "blargg_common.h"
8 #include "Blip_Buffer.h"
9 
10 class Ay_Apu {
11 public:
12 // Basics
13 	enum Ay_Apu_Type
14 	{
15 		Ay8910 = 0,
16 		Ay8912,
17 		Ay8913,
18 		Ay8914,
19 		Ym2149 = 0x10,
20 		Ym3439,
21 		Ymz284,
22 		Ymz294,
23 		Ym2203 = 0x20,
24 		Ym2608,
25 		Ym2610,
26 		Ym2610b
27 	};
28 
set_type(Ay_Apu_Type type)29 	void set_type( Ay_Apu_Type type ) { type_ = type; }
30 
31 	// Sets buffer to generate sound into, or 0 to mute.
32 	void set_output( Blip_Buffer* );
33 
34 	// Writes to address register
write_addr(int data)35 	void write_addr( int data )                 { addr_ = data & 0x0F; }
36 
37 	// Emulates to time t, then writes to current data register
write_data(blip_time_t t,int data)38 	void write_data( blip_time_t t, int data )  { run_until( t ); write_data_( addr_, data ); }
39 
40 	// Emulates to time t, then subtracts t from the current time.
41 	// OK if previous write call had time slightly after t.
42 	void end_frame( blip_time_t t );
43 
44 // More features
45 
46 	// Reads from current data register
47 	int read();
48 
49 	// Resets sound chip
50 	void reset();
51 
52 	// Number of registers
53 	enum { reg_count = 16 };
54 
55 	// Same as set_output(), but for a particular channel
56 	enum { osc_count = 3 };
57 	void set_output( int chan, Blip_Buffer* );
58 
59 	// Sets overall volume, where 1.0 is normal
volume(double v)60 	void volume( double v )                     { synth_.volume( 0.7/osc_count/amp_range * v ); }
61 
62 	// Sets treble equalization
treble_eq(blip_eq_t const & eq)63 	void treble_eq( blip_eq_t const& eq )       { synth_.treble_eq( eq ); }
64 
65 private:
66 	// noncopyable
67 	Ay_Apu( const Ay_Apu& );
68 	Ay_Apu& operator = ( const Ay_Apu& );
69 
70 // Implementation
71 public:
72 	Ay_Apu();
73 	BLARGG_DISABLE_NOTHROW
74 	typedef BOOST::uint8_t byte;
75 
76 private:
77 	struct osc_t
78 	{
79 		blip_time_t  period;
80 		blip_time_t  delay;
81 		short        last_amp;
82 		short        phase;
83 		Blip_Buffer* output;
84 	} oscs [osc_count];
85 
86 	Ay_Apu_Type type_;
87 
88 	blip_time_t last_time;
89 	byte        addr_;
90 	byte        regs [reg_count];
91 
92 	blip_time_t noise_delay;
93 	unsigned    noise_lfsr;
94 
95 	blip_time_t env_delay;
96 	byte const* env_wave;
97 	int         env_pos;
98 	byte        env_modes [8] [48]; // values already passed through volume table
99 
100 	void write_data_( int addr, int data );
101 	void run_until( blip_time_t );
102 
103 public:
104 	enum { amp_range = 255 };
105 	Blip_Synth_Norm synth_; // used by Ay_Core for beeper sound
106 };
107 
set_output(int i,Blip_Buffer * out)108 inline void Ay_Apu::set_output( int i, Blip_Buffer* out )
109 {
110 	assert( (unsigned) i < osc_count );
111 	oscs [i].output = out;
112 }
113 
end_frame(blip_time_t time)114 inline void Ay_Apu::end_frame( blip_time_t time )
115 {
116 	if ( time > last_time )
117 		run_until( time );
118 
119 	last_time -= time;
120 	assert( last_time >= 0 );
121 }
122 
123 #endif
124