Skip to content

Commit

Permalink
spu: ignore KeyOff events fired right after KeyOn
Browse files Browse the repository at this point in the history
Fixes Dragon Ball - Final Bout: Title Screen (Track 29)
  • Loading branch information
JaCzekanski committed Feb 3, 2020
1 parent 1d0163a commit e4556d4
Show file tree
Hide file tree
Showing 5 changed files with 22 additions and 6 deletions.
1 change: 1 addition & 0 deletions src/cpu/cpu.cpp
Expand Up @@ -108,6 +108,7 @@ bool CPU::executeInstructions(int count) {

moveLoadDelaySlots();

sys->cycles++;
if (sys->state != System::State::run) return false;
}
return true;
Expand Down
15 changes: 12 additions & 3 deletions src/device/spu/voice.cpp
Expand Up @@ -90,7 +90,7 @@ void Voice::parseFlags(uint8_t flags) {
repeatAddress = currentAddress;
}

// Jump to Repeat address AFTER playing current sample
// Jump to Repeat address AFTER playing current sample
if (flags & ADPCM::Flag::LoopEnd) {
loopEnd = true;
loadRepeatAddress = true;
Expand All @@ -103,7 +103,7 @@ void Voice::parseFlags(uint8_t flags) {
}
}

void Voice::keyOn() {
void Voice::keyOn(uint64_t cycles) {
decodedSamples.clear();
counter.sample = 0;
adsrVolume._reg = 0;
Expand All @@ -124,9 +124,18 @@ void Voice::keyOn() {

prevSample[0] = prevSample[1] = 0;
prevDecodedSamples.clear();

this->cycles = cycles;
}

void Voice::keyOff() {
void Voice::keyOff(uint64_t cycles) {
// SPU seems to ignore KeyOff events that were fired close to KeyOn.
// Value of 384 cycles was picked by listening to Dragon Ball Final Bout - BGM 29
// and comparing it to recording from real HW.
// It's not verified by any tests for now
if (cycles != 0 && cycles - this->cycles < 384) {
return;
}
state = Voice::State::Release;
adsrWaitCycles = 0;
}
Expand Down
8 changes: 5 additions & 3 deletions src/device/spu/voice.h
Expand Up @@ -39,7 +39,8 @@ struct Voice {

float sample; // Used for Pitch Modulation

bool enabled; // Allows for muting individual channels
bool enabled; // Allows for muting individual channels
uint64_t cycles; // For dismissing KeyOff write right after KeyOn

// ADPCM decoding
int32_t prevSample[2];
Expand All @@ -52,8 +53,8 @@ struct Voice {
void processEnvelope();
void parseFlags(uint8_t flags);

void keyOn();
void keyOff();
void keyOn(uint64_t cycles = 0);
void keyOff(uint64_t cycles = 0);

template <class Archive>
void serialize(Archive& ar) {
Expand All @@ -72,6 +73,7 @@ struct Voice {
ar(loadRepeatAddress);
ar(flagsParsed);
ar(sample);
ar(cycles);
ar(prevSample);
ar(decodedSamples);
ar(prevDecodedSamples);
Expand Down
2 changes: 2 additions & 0 deletions src/system.cpp
Expand Up @@ -34,6 +34,8 @@ System::System() {

debugOutput = config["debug"]["log"]["system"].get<int>();
biosLog = config["debug"]["log"]["bios"];

cycles = 0;
}

// Note: stupid static_casts and asserts are only to suppress MSVC warnings
Expand Down
2 changes: 2 additions & 0 deletions src/system.h
Expand Up @@ -64,6 +64,8 @@ struct System {
bool debugOutput = true; // Print BIOS logs
bool biosLoaded = false;

uint64_t cycles;

// Devices
std::unique_ptr<mips::CPU> cpu;

Expand Down

0 comments on commit e4556d4

Please sign in to comment.