bsnes/gba/apu/apu.cpp
Tim Allen 41c478ac4a Update to v095r07 release.
byuu says:

Changelog:
- entire GBA core ported to auto function() -> return; syntax
- fixed GBA BLDY bug that was causing flickering in a few games
- replaced nall/config usage with nall/string/markup/node
  - this merges all configuration files to a unified settings.bml file
- added "Ignore Manifests" option to the advanced setting tab
  - this lets you keep a manifest.bml for an older version of higan; if
    you want to do regression testing

Be sure to remap your controller/hotkey inputs, and for SNES, choose
"Gamepad" from "Controller Port 1" in the system menu. Otherwise you
won't get any input. No need to blow away your old config files, unless
you want to.
2015-11-16 19:38:05 +11:00

99 lines
2.6 KiB
C++

#include <gba/gba.hpp>
namespace GameBoyAdvance {
#include "registers.cpp"
#include "mmio.cpp"
#include "square.cpp"
#include "square1.cpp"
#include "square2.cpp"
#include "wave.cpp"
#include "noise.cpp"
#include "sequencer.cpp"
#include "fifo.cpp"
#include "serialization.cpp"
APU apu;
auto APU::Enter() -> void {
while(true) {
if(scheduler.sync == Scheduler::SynchronizeMode::All) {
scheduler.exit(Scheduler::ExitReason::SynchronizeEvent);
}
apu.main();
}
}
auto APU::main() -> void {
for(auto n : range(64)) {
runsequencer();
}
int lsample = regs.bias.level - 0x0200;
int rsample = regs.bias.level - 0x0200;
//(4-bit x 4 -> 6-bit) + 3-bit volume = 9-bit output
if(sequencer.masterenable) {
int lsequence = 0;
if(sequencer.lenable[0]) lsequence += square1.output;
if(sequencer.lenable[1]) lsequence += square2.output;
if(sequencer.lenable[2]) lsequence += wave.output;
if(sequencer.lenable[3]) lsequence += noise.output;
int rsequence = 0;
if(sequencer.renable[0]) rsequence += square1.output;
if(sequencer.renable[1]) rsequence += square2.output;
if(sequencer.renable[2]) rsequence += wave.output;
if(sequencer.renable[3]) rsequence += noise.output;
if(sequencer.volume < 3) {
lsample += lsequence * (sequencer.lvolume + 1) >> (2 - sequencer.volume);
rsample += rsequence * (sequencer.rvolume + 1) >> (2 - sequencer.volume);
}
}
//(8-bit x 2 -> 7-bit) + 1-bit volume = 10-bit output
int fifo0 = fifo[0].output + (1 << fifo[0].volume);
int fifo1 = fifo[1].output + (1 << fifo[1].volume);
if(fifo[0].lenable) lsample += fifo0;
if(fifo[1].lenable) lsample += fifo1;
if(fifo[0].renable) rsample += fifo0;
if(fifo[1].renable) rsample += fifo1;
lsample = sclamp<10>(lsample);
rsample = sclamp<10>(rsample);
if(regs.bias.amplitude == 1) lsample &= ~3, rsample &= ~3;
if(regs.bias.amplitude == 2) lsample &= ~7, rsample &= ~7;
if(regs.bias.amplitude == 3) lsample &= ~15, rsample &= ~15;
if(cpu.regs.mode == CPU::Registers::Mode::Stop) lsample = 0, rsample = 0;
interface->audioSample(sclamp<16>(lsample << 6), sclamp<16>(rsample << 6)); //should be <<5, use <<6 for added volume
step(512);
}
auto APU::step(uint clocks) -> void {
clock += clocks;
if(clock >= 0 && scheduler.sync != Scheduler::SynchronizeMode::All) co_switch(cpu.thread);
}
auto APU::power() -> void {
create(APU::Enter, 16777216);
square1.power();
square2.power();
wave.power();
noise.power();
sequencer.power();
fifo[0].power();
fifo[1].power();
regs.bias = 0x0200;
for(uint n = 0x060; n <= 0x0a7; n++) bus.mmio[n] = this;
}
}