mirror of https://github.com/bsnes-emu/bsnes.git
143 lines
3.6 KiB
C++
143 lines
3.6 KiB
C++
auto APU::Sequencer::run() -> void {
|
|
if(enable == false) {
|
|
center = 0;
|
|
left = 0;
|
|
right = 0;
|
|
return;
|
|
}
|
|
|
|
int sample = 0;
|
|
sample += apu.square1.output;
|
|
sample += apu.square2.output;
|
|
sample += apu.wave.output;
|
|
sample += apu.noise.output;
|
|
center = (sample * 512) - 16384;
|
|
|
|
sample = 0;
|
|
if(square1.leftEnable) sample += apu.square1.output;
|
|
if(square2.leftEnable) sample += apu.square2.output;
|
|
if( wave.leftEnable) sample += apu.wave.output;
|
|
if( noise.leftEnable) sample += apu.noise.output;
|
|
sample = (sample * 512) - 16384;
|
|
sample = (sample * (leftVolume + 1)) / 8;
|
|
left = sample;
|
|
|
|
sample = 0;
|
|
if(square1.rightEnable) sample += apu.square1.output;
|
|
if(square2.rightEnable) sample += apu.square2.output;
|
|
if( wave.rightEnable) sample += apu.wave.output;
|
|
if( noise.rightEnable) sample += apu.noise.output;
|
|
sample = (sample * 512) - 16384;
|
|
sample = (sample * (rightVolume + 1)) / 8;
|
|
right = sample;
|
|
|
|
//reduce audio volume
|
|
center >>= 1;
|
|
left >>= 1;
|
|
right >>= 1;
|
|
}
|
|
|
|
auto APU::Sequencer::read(uint16 addr) -> uint8 {
|
|
if(addr == 0xff24) { //NR50
|
|
return leftEnable << 7 | leftVolume << 4 | rightEnable << 3 | rightVolume;
|
|
}
|
|
|
|
if(addr == 0xff25) { //NR51
|
|
return noise.leftEnable << 7
|
|
| wave.leftEnable << 6
|
|
| square2.leftEnable << 5
|
|
| square1.leftEnable << 4
|
|
| noise.rightEnable << 3
|
|
| wave.rightEnable << 2
|
|
| square2.rightEnable << 1
|
|
| square1.rightEnable << 0;
|
|
}
|
|
|
|
if(addr == 0xff26) { //NR52
|
|
return enable << 7 | 0x70
|
|
| apu.noise.enable << 3
|
|
| apu.wave.enable << 2
|
|
| apu.square2.enable << 1
|
|
| apu.square1.enable << 0;
|
|
}
|
|
|
|
return 0xff;
|
|
}
|
|
|
|
auto APU::Sequencer::write(uint16 addr, uint8 data) -> void {
|
|
if(addr == 0xff24) { //NR50
|
|
leftEnable = data.bit (7);
|
|
leftVolume = data.bits(6,4);
|
|
rightEnable = data.bit (3);
|
|
rightVolume = data.bits(2,0);
|
|
}
|
|
|
|
if(addr == 0xff25) { //NR51
|
|
noise.leftEnable = data.bit(7);
|
|
wave.leftEnable = data.bit(6);
|
|
square2.leftEnable = data.bit(5);
|
|
square1.leftEnable = data.bit(4);
|
|
noise.rightEnable = data.bit(3);
|
|
wave.rightEnable = data.bit(2);
|
|
square2.rightEnable = data.bit(1);
|
|
square1.rightEnable = data.bit(0);
|
|
}
|
|
|
|
if(addr == 0xff26) { //NR52
|
|
if(enable != data.bit(7)) {
|
|
enable = data.bit(7);
|
|
|
|
if(!enable) {
|
|
//power(bool) resets length counters when true (eg for CGB only)
|
|
apu.square1.power(Model::GameBoyColor());
|
|
apu.square2.power(Model::GameBoyColor());
|
|
apu.wave.power(Model::GameBoyColor());
|
|
apu.noise.power(Model::GameBoyColor());
|
|
power();
|
|
} else {
|
|
apu.phase = 0;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
auto APU::Sequencer::power() -> void {
|
|
leftEnable = 0;
|
|
leftVolume = 0;
|
|
rightEnable = 0;
|
|
rightVolume = 0;
|
|
noise.leftEnable = 0;
|
|
wave.leftEnable = 0;
|
|
square2.leftEnable = 0;
|
|
square1.leftEnable = 0;
|
|
noise.rightEnable = 0;
|
|
wave.rightEnable = 0;
|
|
square2.rightEnable = 0;
|
|
square1.rightEnable = 0;
|
|
enable = 0;
|
|
|
|
center = 0;
|
|
left = 0;
|
|
right = 0;
|
|
}
|
|
|
|
auto APU::Sequencer::serialize(serializer& s) -> void {
|
|
s.integer(leftEnable);
|
|
s.integer(leftVolume);
|
|
s.integer(rightEnable);
|
|
s.integer(rightVolume);
|
|
s.integer(noise.leftEnable);
|
|
s.integer(wave.leftEnable);
|
|
s.integer(square2.leftEnable);
|
|
s.integer(square1.leftEnable);
|
|
s.integer(noise.rightEnable);
|
|
s.integer(wave.rightEnable);
|
|
s.integer(square2.rightEnable);
|
|
s.integer(square1.rightEnable);
|
|
s.integer(enable);
|
|
|
|
s.integer(center);
|
|
s.integer(left);
|
|
s.integer(right);
|
|
}
|