1 // Private oscillators used by Gb_Apu
2
3 // Gb_Snd_Emu $vers
4 #ifndef GB_OSCS_H
5 #define GB_OSCS_H
6
7 #include "blargg_common.h"
8 #include "Blip_Buffer.h"
9
10 #ifndef GB_APU_OVERCLOCK
11 #define GB_APU_OVERCLOCK 1
12 #endif
13
14 #if GB_APU_OVERCLOCK & (GB_APU_OVERCLOCK - 1)
15 #error "GB_APU_OVERCLOCK must be a power of 2"
16 #endif
17
18 class Gb_Osc {
19 protected:
20
21 // 11-bit frequency in NRx3 and NRx4
frequency()22 int frequency() const { return (regs [4] & 7) * 0x100 + regs [3]; }
23
24 void update_amp( blip_time_t, int new_amp );
25 int write_trig( int frame_phase, int max_len, int old_data );
26 public:
27
28 enum { clk_mul = GB_APU_OVERCLOCK };
29 enum { dac_bias = 7 };
30
31 Blip_Buffer* outputs [4];// NULL, right, left, center
32 Blip_Buffer* output; // where to output sound
33 BOOST::uint8_t* regs; // osc's 5 registers
34 int mode; // mode_dmg, mode_cgb, mode_agb
35 int dac_off_amp;// amplitude when DAC is off
36 int last_amp; // current amplitude in Blip_Buffer
37 Blip_Synth_Norm const* norm_synth;
38 Blip_Synth_Fast const* fast_synth;
39
40 int delay; // clocks until frequency timer expires
41 int length_ctr; // length counter
42 unsigned phase; // waveform phase (or equivalent)
43 bool enabled; // internal enabled flag
44
45 void clock_length();
46 void reset();
47 };
48
49 class Gb_Env : public Gb_Osc {
50 public:
51 int env_delay;
52 int volume;
53 bool env_enabled;
54
55 void clock_envelope();
56 bool write_register( int frame_phase, int reg, int old_data, int data );
57
reset()58 void reset()
59 {
60 env_delay = 0;
61 volume = 0;
62 Gb_Osc::reset();
63 }
64 protected:
65 // Non-zero if DAC is enabled
dac_enabled()66 int dac_enabled() const { return regs [2] & 0xF8; }
67 private:
68 void zombie_volume( int old, int data );
69 int reload_env_timer();
70 };
71
72 class Gb_Square : public Gb_Env {
73 public:
74 bool write_register( int frame_phase, int reg, int old_data, int data );
75 void run( blip_time_t, blip_time_t );
76
reset()77 void reset()
78 {
79 Gb_Env::reset();
80 delay = 0x40000000; // TODO: something less hacky (never clocked until first trigger)
81 }
82 private:
83 // Frequency timer period
period()84 int period() const { return (2048 - frequency()) * (4 * clk_mul); }
85 };
86
87 class Gb_Sweep_Square : public Gb_Square {
88 public:
89 int sweep_freq;
90 int sweep_delay;
91 bool sweep_enabled;
92 bool sweep_neg;
93
94 void clock_sweep();
95 void write_register( int frame_phase, int reg, int old_data, int data );
96
reset()97 void reset()
98 {
99 sweep_freq = 0;
100 sweep_delay = 0;
101 sweep_enabled = false;
102 sweep_neg = false;
103 Gb_Square::reset();
104 }
105 private:
106 enum { period_mask = 0x70 };
107 enum { shift_mask = 0x07 };
108
109 void calc_sweep( bool update );
110 void reload_sweep_timer();
111 };
112
113 class Gb_Noise : public Gb_Env {
114 public:
115 int divider; // noise has more complex frequency divider setup
116
117 void run( blip_time_t, blip_time_t );
118 void write_register( int frame_phase, int reg, int old_data, int data );
119
reset()120 void reset()
121 {
122 divider = 0;
123 Gb_Env::reset();
124 delay = 4 * clk_mul; // TODO: remove?
125 }
126
127 private:
128 enum { period2_mask = 0x1FFFF };
129
period2_index()130 int period2_index() const { return regs [3] >> 4; }
131 int period2( int base = 8 ) const { return base << period2_index(); }
lfsr_mask()132 unsigned lfsr_mask() const { return (regs [3] & 0x08) ? ~0x4040 : ~0x4000; }
133 };
134
135 class Gb_Wave : public Gb_Osc {
136 public:
137 int sample_buf; // last wave RAM byte read (hardware has this as well)
138
139 void write_register( int frame_phase, int reg, int old_data, int data );
140 void run( blip_time_t, blip_time_t );
141
142 // Reads/writes wave RAM
143 int read( int addr ) const;
144 void write( int addr, int data );
145
reset()146 void reset()
147 {
148 sample_buf = 0;
149 Gb_Osc::reset();
150 }
151
152 private:
153 enum { bank40_mask = 0x40 };
154 enum { bank_size = 32 };
155
156 int agb_mask; // 0xFF if AGB features enabled, 0 otherwise
157 BOOST::uint8_t* wave_ram; // 32 bytes (64 nybbles), stored in APU
158
159 friend class Gb_Apu;
160
161 // Frequency timer period
period()162 int period() const { return (2048 - frequency()) * (2 * clk_mul); }
163
164 // Non-zero if DAC is enabled
dac_enabled()165 int dac_enabled() const { return regs [0] & 0x80; }
166
167 void corrupt_wave();
168
wave_bank()169 BOOST::uint8_t* wave_bank() const { return &wave_ram [(~regs [0] & bank40_mask) >> 2 & agb_mask]; }
170
171 // Wave index that would be accessed, or -1 if no access would occur
172 int access( int addr ) const;
173 };
174
read(int addr)175 inline int Gb_Wave::read( int addr ) const
176 {
177 int index = access( addr );
178 return (index < 0 ? 0xFF : wave_bank() [index]);
179 }
180
write(int addr,int data)181 inline void Gb_Wave::write( int addr, int data )
182 {
183 int index = access( addr );
184 if ( index >= 0 )
185 wave_bank() [index] = data;;
186 }
187
188 #endif
189