Skip to content

Commit

Permalink
GB: APU - Improved square 1 sweep behavior
Browse files Browse the repository at this point in the history
Passes channel_1_sweep test
  • Loading branch information
SourMesen committed Jan 31, 2024
1 parent 25142a9 commit 7a83827
Show file tree
Hide file tree
Showing 3 changed files with 31 additions and 12 deletions.
41 changes: 29 additions & 12 deletions Core/Gameboy/APU/GbSquareChannel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,18 +52,16 @@ void GbSquareChannel::ClockSweepUnit()
if(newFreq >= 2048) {
_state.Enabled = false;
_state.SweepEnabled = false;
UpdateOutput();
} else {
//"If the new frequency is 2047 or less and the sweep shift is not zero, this new frequency is written back to the shadow frequency and square 1's frequency in NR13 and NR14,"
if(_state.SweepShift) {
_state.Frequency = newFreq;
_state.SweepFreq = newFreq;

newFreq = GetSweepTargetFrequency();
if(newFreq >= 2048) {
//"then frequency calculation and overflow check are run AGAIN immediately using this new value, but this second new frequency is not written back."
_state.Enabled = false;
_state.SweepEnabled = false;
}
//8 cpu cycles later, the next frequency is checked
//This is checked by SameSuite's channel_1_sweep test
_state.SweepUpdateDelay = 8 * 4;
}
}
}
Expand Down Expand Up @@ -144,6 +142,26 @@ void GbSquareChannel::Exec(uint32_t clocksToRun)
return;
}

if(_state.SweepUpdateDelay) {
if(_state.SweepUpdateDelay > clocksToRun) {
_state.SweepUpdateDelay -= clocksToRun;
} else {
_state.SweepUpdateDelay = 0;

//"If the new frequency is 2047 or less and the sweep shift is not zero, this new frequency is written back to the shadow frequency and square 1's frequency in NR13 and NR14,"
if(_state.SweepShift) {
uint16_t newFreq = GetSweepTargetFrequency();
if(newFreq >= 2048) {
//"then frequency calculation and overflow check are run AGAIN immediately using this new value, but this second new frequency is not written back."
_state.Enabled = false;
_state.SweepEnabled = false;
UpdateOutput();
return;
}
}
}
}

_state.Timer -= clocksToRun;

if(_state.Timer == 0) {
Expand Down Expand Up @@ -196,6 +214,7 @@ void GbSquareChannel::Write(uint16_t addr, uint8_t value)
//while negate mode was enabled will disable the channel
//Required for sweep-details tests 4, 5 and 6
_state.Enabled = false;
UpdateOutput();
}
break;

Expand Down Expand Up @@ -229,6 +248,7 @@ void GbSquareChannel::Write(uint16_t addr, uint8_t value)

if(!(value & 0xF8)) {
_state.Enabled = false;
UpdateOutput();
}
break;
}
Expand Down Expand Up @@ -283,12 +303,8 @@ void GbSquareChannel::Write(uint16_t addr, uint8_t value)

//"If the sweep shift is non-zero, frequency calculation and the overflow check are performed immediately."
if(_state.SweepShift > 0) {
//Calculate new frequency and disable channel as needed (but don't save it in SweepFreq - otherwise sweep-details #2 fails)
if(GetSweepTargetFrequency() > 2047) {
_state.Enabled = false;
_state.SweepEnabled = false;
}

//After ~8 cpu cycles, the next frequency is checked (which can disable the channel)
_state.SweepUpdateDelay = 8 * 4 + 2;
if(_state.SweepNegate) {
_state.SweepNegateCalcDone = true;
}
Expand All @@ -307,5 +323,6 @@ void GbSquareChannel::Serialize(Serializer& s)
SV(_state.Volume); SV(_state.EnvVolume); SV(_state.EnvRaiseVolume); SV(_state.EnvPeriod); SV(_state.EnvTimer); SV(_state.Duty); SV(_state.Frequency);
SV(_state.Length); SV(_state.LengthEnabled); SV(_state.Enabled); SV(_state.Timer); SV(_state.DutyPos); SV(_state.Output);
SV(_state.SweepNegateCalcDone); SV(_state.EnvStopped);
SV(_state.SweepUpdateDelay);
SV(_dac);
}
1 change: 1 addition & 0 deletions Core/Gameboy/GbTypes.h
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,7 @@ struct GbSquareState
uint16_t SweepTimer;
uint16_t SweepFreq;
uint16_t SweepPeriod;
uint8_t SweepUpdateDelay;
bool SweepNegate;
uint8_t SweepShift;

Expand Down
1 change: 1 addition & 0 deletions UI/Interop/DebugState.cs
Original file line number Diff line number Diff line change
Expand Up @@ -875,6 +875,7 @@ public struct GbSquareState
public UInt16 SweepTimer;
public UInt16 SweepFreq;
public UInt16 SweepPeriod;
public byte SweepUpdateDelay;
[MarshalAs(UnmanagedType.I1)] public bool SweepNegate;
public byte SweepShift;

Expand Down

0 comments on commit 7a83827

Please sign in to comment.