bsnes/higan/sfc/dsp/dsp.cpp

302 lines
5.2 KiB
C++
Raw Normal View History

#include <sfc/sfc.hpp>
namespace SuperFamicom {
DSP dsp;
#include "audio.cpp"
#define REG(n) state.regs[n]
#define VREG(n) state.regs[v.vidx + n]
#include "gaussian.cpp"
#include "counter.cpp"
#include "envelope.cpp"
#include "brr.cpp"
#include "misc.cpp"
#include "voice.cpp"
#include "echo.cpp"
#include "serialization.cpp"
DSP::DSP() {
static_assert(sizeof(int) >= 32 / 8, "int >= 32-bits");
static_assert((int8_t)0x80 == -0x80, "8-bit sign extension");
static_assert((int16_t)0x8000 == -0x8000, "16-bit sign extension");
static_assert((uint16_t)0xffff0000 == 0, "16-bit unsigned clip");
static_assert((-1 >> 1) == -1, "arithmetic shift right");
//-0x8000 <= n <= +0x7fff
assert(sclamp<16>(+0x8000) == +0x7fff);
assert(sclamp<16>(-0x8001) == -0x8000);
}
/* timing */
auto DSP::step(uint clocks) -> void {
clock += clocks;
}
auto DSP::synchronizeSMP() -> void {
if(SMP::Threaded) {
if(clock >= 0 && !scheduler.synchronizing()) co_switch(smp.thread);
Updated to v067r21 release. byuu says: This moves toward a profile-selection mode. Right now, it is incomplete. There are three binaries, one for each profile. The GUI selection doesn't actually do anything yet. There will be a launcher in a future release that loads each profile's respective binary. I reverted away from blargg's SMP library for the time being, in favor of my own. This will fix most of the csnes/bsnes-performance bugs. This causes a 10% speed hit on 64-bit platforms, and a 15% speed hit on 32-bit platforms. I hope to be able to regain that speed in the future, I may also experiment with creating my own fast-SMP core which drops bus hold delays and TEST register support (never used by anything, ever.) Save states now work in all three cores, but they are not cross-compatible. The profile name is stored in the description field of the save states, and it won't load a state if the profile name doesn't match. The debugger only works on the research target for now. Give it time and it will return for the other targets. Other than that, let's please resume testing on all three once again. See how far we get this time :) I can confirm the following games have issues on the performance profile: - Armored Police Metal Jacket (minor logo flickering, not a big deal) - Chou Aniki (won't start, so obviously unplayable) - Robocop vs The Terminator (major in-game flickering, unplayable) Anyone still have that gigantic bsnes thread archive from the ZSNES forum? Maybe I posted about how to fix those two broken games in there, heh. I really want to release this as v1.0, but my better judgment says we need to give it another week. Damn.
2010-10-20 11:22:44 +00:00
} else {
while(clock >= 0) smp.main();
Updated to v067r21 release. byuu says: This moves toward a profile-selection mode. Right now, it is incomplete. There are three binaries, one for each profile. The GUI selection doesn't actually do anything yet. There will be a launcher in a future release that loads each profile's respective binary. I reverted away from blargg's SMP library for the time being, in favor of my own. This will fix most of the csnes/bsnes-performance bugs. This causes a 10% speed hit on 64-bit platforms, and a 15% speed hit on 32-bit platforms. I hope to be able to regain that speed in the future, I may also experiment with creating my own fast-SMP core which drops bus hold delays and TEST register support (never used by anything, ever.) Save states now work in all three cores, but they are not cross-compatible. The profile name is stored in the description field of the save states, and it won't load a state if the profile name doesn't match. The debugger only works on the research target for now. Give it time and it will return for the other targets. Other than that, let's please resume testing on all three once again. See how far we get this time :) I can confirm the following games have issues on the performance profile: - Armored Police Metal Jacket (minor logo flickering, not a big deal) - Chou Aniki (won't start, so obviously unplayable) - Robocop vs The Terminator (major in-game flickering, unplayable) Anyone still have that gigantic bsnes thread archive from the ZSNES forum? Maybe I posted about how to fix those two broken games in there, heh. I really want to release this as v1.0, but my better judgment says we need to give it another week. Damn.
2010-10-20 11:22:44 +00:00
}
}
auto DSP::Enter() -> void {
while(true) scheduler.synchronize(), dsp.main();
}
auto DSP::main() -> void {
voice5(voice[0]);
voice2(voice[1]);
tick();
voice6(voice[0]);
voice3(voice[1]);
tick();
voice7(voice[0]);
voice4(voice[1]);
voice1(voice[3]);
tick();
voice8(voice[0]);
voice5(voice[1]);
voice2(voice[2]);
tick();
voice9(voice[0]);
voice6(voice[1]);
voice3(voice[2]);
tick();
voice7(voice[1]);
voice4(voice[2]);
voice1(voice[4]);
tick();
voice8(voice[1]);
voice5(voice[2]);
voice2(voice[3]);
tick();
voice9(voice[1]);
voice6(voice[2]);
voice3(voice[3]);
tick();
voice7(voice[2]);
voice4(voice[3]);
voice1(voice[5]);
tick();
voice8(voice[2]);
voice5(voice[3]);
voice2(voice[4]);
tick();
voice9(voice[2]);
voice6(voice[3]);
voice3(voice[4]);
tick();
voice7(voice[3]);
voice4(voice[4]);
voice1(voice[6]);
tick();
voice8(voice[3]);
voice5(voice[4]);
voice2(voice[5]);
tick();
voice9(voice[3]);
voice6(voice[4]);
voice3(voice[5]);
tick();
voice7(voice[4]);
voice4(voice[5]);
voice1(voice[7]);
tick();
voice8(voice[4]);
voice5(voice[5]);
voice2(voice[6]);
tick();
voice9(voice[4]);
voice6(voice[5]);
voice3(voice[6]);
tick();
voice1(voice[0]);
voice7(voice[5]);
voice4(voice[6]);
tick();
voice8(voice[5]);
voice5(voice[6]);
voice2(voice[7]);
tick();
voice9(voice[5]);
voice6(voice[6]);
voice3(voice[7]);
tick();
voice1(voice[1]);
voice7(voice[6]);
voice4(voice[7]);
tick();
voice8(voice[6]);
voice5(voice[7]);
voice2(voice[0]);
tick();
voice3a(voice[0]);
voice9(voice[6]);
voice6(voice[7]);
echo22();
tick();
voice7(voice[7]);
echo23();
tick();
voice8(voice[7]);
echo24();
tick();
voice3b(voice[0]);
voice9(voice[7]);
echo25();
tick();
echo26();
tick();
misc27();
echo27();
tick();
misc28();
echo28();
tick();
misc29();
echo29();
tick();
misc30();
voice3c(voice[0]);
echo30();
tick();
voice4(voice[0]);
voice1(voice[2]);
tick();
}
auto DSP::tick() -> void {
step(3 * 8);
synchronizeSMP();
}
/* register interface for S-SMP $00f2,$00f3 */
auto DSP::mute() const -> bool {
return REG(FLG) & 0x40;
}
auto DSP::read(uint8 addr) -> uint8 {
return REG(addr);
}
auto DSP::write(uint8 addr, uint8 data) -> void {
REG(addr) = data;
if((addr & 0x0f) == ENVX) {
state.envxBuffer = data;
} else if((addr & 0x0f) == OUTX) {
state.outxBuffer = data;
} else if(addr == KON) {
state.konBuffer = data;
} else if(addr == ENDX) {
//always cleared, regardless of data written
state.endxBuffer = 0;
REG(ENDX) = 0;
}
}
/* initialization */
auto DSP::power() -> void {
for(auto& r : state.regs) r = 0;
state.echoHistoryOffset = 0;
state.everyOtherSample = false;
state.kon = 0;
state.noise = 0;
state.counter = 0;
state.echoOffset = 0;
state.echoLength = 0;
state.konBuffer = 0;
state.endxBuffer = 0;
state.envxBuffer = 0;
state.outxBuffer = 0;
state._pmon = 0;
state._non = 0;
state._eon = 0;
state._dir = 0;
state._koff = 0;
state._brrNextAddress = 0;
state._adsr0 = 0;
state._brrHeader = 0;
state._brrByte = 0;
state._srcn = 0;
state._esa = 0;
state._echoDisabled = 0;
state._dirAddress = 0;
state._pitch = 0;
state._output = 0;
state._looped = 0;
state._echoPointer = 0;
state._mainOut[0] = state._mainOut[1] = 0;
state._echoOut[0] = state._echoOut[1] = 0;
state._echoIn[0] = state._echoIn[1] = 0;
for(auto n : range(8)) {
voice[n].bufferOffset = 0;
voice[n].gaussianOffset = 0;
voice[n].brrAddress = 0;
voice[n].brrOffset = 1;
voice[n].vbit = 1 << n;
voice[n].vidx = n * 0x10;
voice[n].konDelay = 0;
voice[n].envelopeMode = EnvelopeRelease;
voice[n].envelope = 0;
voice[n].hiddenEnvelope = 0;
voice[n]._envxOut = 0;
}
audio.coprocessorEnable(false);
}
auto DSP::reset() -> void {
create(Enter, system.apuFrequency());
REG(FLG) = 0xe0;
state.noise = 0x4000;
state.echoHistoryOffset = 0;
state.everyOtherSample = 1;
state.echoOffset = 0;
state.counter = 0;
}
#undef REG
#undef VREG
}