PSG (programmable sound generator) channels
Mostly the same as the Game Boy Color APU channels, though the wavetable channel works a bit differently
5mod wavetable;
Number of 1 MHz cycles for a tick rate of 512 Hz
16const FRAME_SEQUENCER_DIVIDER: u64 = (1 << 20) / 512;
18#[derive(Debug, Clone, Encode, Decode)] 19pub struct Psg { 20 odd_tick: bool, 21 pulse_1: PulseChannel, 22 pulse_2: PulseChannel, 23 wavetable: WavetableChannel, 24 noise: NoiseChannel, 25 stereo_control: StereoControl, 26 frame_sequencer_step: u8, 27 frame_sequencer_divider: u64, 28} 29 30impl Psg { 31 pub fn new() -> Self { 32 Self { 33 odd_tick: false, 34 pulse_1: PulseChannel::new(), 35 pulse_2: PulseChannel::new(), 36 wavetable: WavetableChannel::new(), 37 noise: NoiseChannel::new(), 38 stereo_control: StereoControl::zero(), 39 frame_sequencer_step: 0, 40 frame_sequencer_divider: FRAME_SEQUENCER_DIVIDER, 41 } 42 } 43 44 pub fn tick_2mhz(&mut self, apu_enabled: bool) { 45 self.odd_tick = !self.odd_tick; 46 if !self.odd_tick { 47 self.tick_frame_sequencer(apu_enabled); 48 49 self.pulse_1.tick_m_cycle(); 50 self.pulse_2.tick_m_cycle(); 51 self.noise.tick_m_cycle(); 52 } 53 54 self.wavetable.tick_2mhz(); 55 } 56 57 fn tick_frame_sequencer(&mut self, apu_enabled: bool) { 58 self.frame_sequencer_divider -= 1; 59 if self.frame_sequencer_divider != 0 { 60 return; 61 } 62 self.frame_sequencer_divider = FRAME_SEQUENCER_DIVIDER; 63 64 self.frame_sequencer_step = (self.frame_sequencer_step + 1) % 8; 65 66 if !apu_enabled { 67 return; 68 } 69 70 // Length counters clock on steps 0, 2, 4, 6 71 if !self.frame_sequencer_step.bit(0) { 72 self.pulse_1.clock_length_counter(); 73 self.pulse_2.clock_length_counter(); 74 self.wavetable.clock_length_counter(); 75 self.noise.clock_length_counter(); 76 } 77 78 // Envelopes clock on step 7 79 if self.frame_sequencer_step == 7 { 80 self.pulse_1.clock_envelope(); 81 self.pulse_2.clock_envelope(); 82 self.noise.clock_envelope(); 83 } 84 85 // Channel 1 sweep clocks on steps 2 and 6 86 if self.frame_sequencer_step == 2 || self.frame_sequencer_step == 6 { 87 self.pulse_1.clock_sweep(); 88 } 89 } 90 91 pub fn sample(&self, channels_enabled: [bool; 4]) -> (i16, i16) { 92 let channels_enabled = channels_enabled.map(i16::from); 93 94 // On GBA, DAC-disabled channels behave as if they're outputting 0 95 let raw_samples = [ 96 self.pulse_1.sample().unwrap_or(0), 97 self.pulse_2.sample().unwrap_or(0), 98 self.wavetable.sample(), 99 self.noise.sample().unwrap_or(0), 100 ] 101 .map(i16::from); 102 103 // To try and emulate the GBC's DACs, GBA biases each channel by its current volume 104 // Wavetable channel is always biased by -15 (tested on hardware) 105 let channel_bias = 106 [self.pulse_1.volume(), self.pulse_2.volume(), 15, self.noise.volume()].map(i16::from); 107 108 // Convert from unsigned 4-bit to signed 5-bit while applying bias 109 let samples: [i16; 4] = 110 array::from_fn(|i| channels_enabled[i] * (2 * raw_samples[i] - channel_bias[i])); 111 112 // Mix channels; result is signed 7-bit 113 let stereo_l = self.stereo_control.left_channels.map(i16::from); 114 let stereo_r = self.stereo_control.right_channels.map(i16::from); 115 let mut sample_l: i16 = 116 samples.into_iter().enumerate().map(|(i, sample)| stereo_l[i] * sample).sum(); 117 let mut sample_r: i16 = 118 samples.into_iter().enumerate().map(|(i, sample)| stereo_r[i] * sample).sum(); 119 120 // Apply master volume (1-8); result is signed 10-bit 121 sample_l *= i16::from(self.stereo_control.left_volume + 1); 122 sample_r *= i16::from(self.stereo_control.right_volume + 1); 123 124 debug_assert!((-0x200..0x200).contains(&sample_l)); 125 debug_assert!((-0x200..0x200).contains(&sample_r)); 126 127 (sample_l, sample_r) 128 } 129 130 pub fn disable(&mut self) { 131 *self = Self { 132 frame_sequencer_step: self.frame_sequencer_step, 133 frame_sequencer_divider: self.frame_sequencer_divider, 134 ..Self::new() 135 }; 136 } 137 138 // $4000060: SOUND1CNT_L / NR10 (Channel 1 sweep) 139 pub fn write_sound1cnt_l(&mut self, value: u8) { 140 self.pulse_1.write_register_0(value); 141 } 142 143 // $4000060: SOUND1CNT_L / NR10 (Channel 1 sweep) 144 pub fn read_sound1cnt_l(&self) -> u8 { 145 self.pulse_1.read_register_0() & 0x7F 146 } 147 148 // $4000062: SOUND1CNT_H low / NR11 (Channel 1 duty cycle and length counter) 149 pub fn write_sound1cnt_h_low(&mut self, value: u8) { 150 self.pulse_1.write_register_1(value, true); 151 } 152 153 // $4000062: SOUND1CNT_H low / NR11 (Channel 1 duty cycle and length counter) 154 pub fn read_sound1cnt_h_low(&self) -> u8 { 155 self.pulse_1.read_register_1() & 0xC0 156 } 157 158 // $4000063: SOUND1CNT_H high / NR12 (Channel 1 envelope) 159 pub fn write_sound1cnt_h_high(&mut self, value: u8) { 160 self.pulse_1.write_register_2(value); 161 } 162 163 // $4000063: SOUND1CNT_H high / NR12 (Channel 1 envelope) 164 pub fn read_sound1cnt_h_high(&self) -> u8 { 165 self.pulse_1.read_register_2() 166 } 167 168 // $4000064: SOUND1CNT_X low / NR13 (Channel 1 frequency low bits) 169 pub fn write_sound1cnt_x_low(&mut self, value: u8) { 170 self.pulse_1.write_register_3(value); 171 } 172 173 // $4000065: SOUND1CNT_X high / NR14 (Channel 1 control) 174 pub fn write_sound1cnt_x_high(&mut self, value: u8) { 175 self.pulse_1.write_register_4(value, self.frame_sequencer_step); 176 } 177 178 // $4000065: SOUND1CNT_X high / NR14 (Channel 1 control) 179 pub fn read_sound1cnt_x_high(&self) -> u8 { 180 self.pulse_1.read_register_4() & 0x40 181 } 182 183 // $4000068: SOUND2CNT_L low / NR21 (Channel 2 duty cycle and length counter) 184 pub fn write_sound2cnt_l_low(&mut self, value: u8) { 185 self.pulse_2.write_register_1(value, true); 186 } 187 188 // $4000068: SOUND2CNT_L low / NR21 (Channel 2 duty cycle and length counter) 189 pub fn read_sound2cnt_l_low(&self) -> u8 { 190 self.pulse_2.read_register_1() & 0xC0 191 } 192 193 // $4000069: SOUND2CNT_L high / NR22 (Channel 2 envelope) 194 pub fn write_sound2cnt_l_high(&mut self, value: u8) { 195 self.pulse_2.write_register_2(value); 196 } 197 198 // $4000069: SOUND2CNT_L high / NR22 (Channel 2 envelope) 199 pub fn read_sound2cnt_l_high(&self) -> u8 { 200 self.pulse_2.read_register_2() 201 } 202 203 // $400006C: SOUND2CNT_H low / NR23 (Channel 2 frequency low bits) 204 pub fn write_sound2cnt_h_low(&mut self, value: u8) { 205 self.pulse_2.write_register_3(value); 206 } 207 208 // $400006D: SOUND2CNT_H high / NR24 (Channel 2 control) 209 pub fn write_sound2cnt_h_high(&mut self, value: u8) { 210 self.pulse_2.write_register_4(value, self.frame_sequencer_step); 211 } 212 213 // $400006D: SOUND2CNT_H high / NR24 (Channel 2 control) 214 pub fn read_sound2cnt_h_high(&self) -> u8 { 215 self.pulse_2.read_register_4() & 0x40 216 } 217 218 // $4000070: SOUND3CNT_L / NR30 (Channel 3 enabled and wave RAM control) 219 pub fn write_sound3cnt_l(&mut self, value: u8) { 220 self.wavetable.write_nr30(value); 221 } 222 223 // $4000070: SOUND3CNT_L / NR30 (Channel 3 enabled and wave RAM control) 224 pub fn read_sound3cnt_l(&self) -> u8 { 225 self.wavetable.read_nr30() & 0xE0 226 } 227 228 // $4000072: SOUND3CNT_H low / NR31 (Channel 3 length counter) 229 pub fn write_sound3cnt_h_low(&mut self, value: u8) { 230 self.wavetable.write_nr31(value); 231 } 232 233 // $4000073: SOUND3CNT_H high / NR32 (Channel 3 volume) 234 pub fn write_sound3cnt_h_high(&mut self, value: u8) { 235 self.wavetable.write_nr32(value); 236 } 237 238 // $4000073: SOUND3CNT_H high / NR32 (Channel 3 volume) 239 pub fn read_sound3cnt_h_high(&self) -> u8 { 240 self.wavetable.read_nr32() & 0xE0 241 } 242 243 // $4000074: SOUND3CNT_X low / NR33 (Channel 3 frequency low bits) 244 pub fn write_sound3cnt_x_low(&mut self, value: u8) { 245 self.wavetable.write_nr33(value); 246 } 247 248 // $4000075: SOUND3CNT_X high / NR34 (Channel 3 control) 249 pub fn write_sound3cnt_x_high(&mut self, value: u8) { 250 self.wavetable.write_nr34(value, self.frame_sequencer_step); 251 } 252 253 // $4000075: SOUND3CNT_X high / NR34 (Channel 3 control) 254 pub fn read_sound3cnt_x_high(&self) -> u8 { 255 self.wavetable.read_nr34() & 0x40 256 } 257 258 // $4000078: SOUND4CNT_L low / NR41 (Channel 4 length counter) 259 pub fn write_sound4cnt_l_low(&mut self, value: u8) { 260 self.noise.write_register_1(value); 261 } 262 263 // $4000079: SOUND4CNT_L high / NR42 (Channel 4 envelope) 264 pub fn write_sound4cnt_l_high(&mut self, value: u8) { 265 self.noise.write_register_2(value); 266 } 267 268 // $4000079: SOUND4CNT_L high / NR42 (Channel 4 envelope) 269 pub fn read_sound4cnt_l_high(&self) -> u8 { 270 self.noise.read_register_2() 271 } 272 273 // $400007C: SOUND4CNT_H low / NR43 (Channel 4 frequency) 274 pub fn write_sound4cnt_h_low(&mut self, value: u8) { 275 self.noise.write_register_3(value); 276 } 277 278 // $400007C: SOUND4CNT_H low / NR43 (Channel 4 frequency) 279 pub fn read_sound4cnt_h_low(&self) -> u8 { 280 self.noise.read_register_3() 281 } 282 283 // $400007D: SOUND4CNT_H high / NR44 (Channel 4 control) 284 pub fn write_sound4cnt_h_high(&mut self, value: u8) { 285 self.noise.write_register_4(value, self.frame_sequencer_step); 286 } 287 288 // $400007D: SOUND4CNT_H high / NR44 (Channel 4 control) 289 pub fn read_sound4cnt_h_high(&self) -> u8 { 290 self.noise.read_register_4() & 0x40 291 } 292 293 // $4000080: SOUNDCNT_L low / NR50 (PSG master volume) 294 pub fn write_soundcnt_l_low(&mut self, value: u8) { 295 self.stereo_control.write_volume(value); 296 } 297 298 // $4000080: SOUNDCNT_L low / NR50 (PSG master volume) 299 pub fn read_soundcnt_l_low(&self) -> u8 { 300 self.stereo_control.read_volume() & 0x77 301 } 302 303 // $4000081: SOUNDCNT_L high / NR51 (PSG stereo control) 304 pub fn write_soundcnt_l_high(&mut self, value: u8) { 305 self.stereo_control.write_enabled(value); 306 } 307 308 // $4000081: SOUNDCNT_L high / NR51 (PSG stereo control) 309 pub fn read_soundcnt_l_high(&self) -> u8 { 310 self.stereo_control.read_enabled() 311 } 312 313 // $4000084: SOUNDCNT_X / NR52 (Channels and APU enabled) 314 pub fn read_soundcnt_x(&self, apu_enabled: bool) -> u8 { 315 (u8::from(self.pulse_1.enabled())) 316 | (u8::from(self.pulse_2.enabled()) << 1) 317 | (u8::from(self.wavetable.active()) << 2) 318 | (u8::from(self.noise.enabled()) << 3) 319 | (u8::from(apu_enabled) << 7) 320 } 321 322 // $4000090-$400009F: Wave RAM 323 pub fn read_wave_ram(&self, address: u32) -> u8 { 324 self.wavetable.read_wave_ram(address) 325 } 326 327 // $4000090-$400009F: Wave RAM 328 pub fn write_wave_ram(&mut self, address: u32, value: u8) { 329 self.wavetable.write_wave_ram(address, value); 330 } 331}