1010#include " SoundMixer.h"
1111#include " MemoryManager.h"
1212
13- APU* APU::Instance = nullptr ;
14- bool APU::_apuEnabled = true ;
15-
16- APU::APU (MemoryManager* memoryManager)
13+ APU::APU (shared_ptr<Console> console)
1714{
18- APU::Instance = this ;
19-
20- _memoryManager = memoryManager;
21-
2215 _nesModel = NesModel::Auto;
23-
2416 _apuEnabled = true ;
2517
26- _mixer.reset (new SoundMixer ());
18+ _console = console;
19+ _mixer = _console->GetSoundMixer ();
2720
28- _squareChannel[0 ].reset (new SquareChannel (AudioChannel::Square1, _mixer.get (), true ));
29- _squareChannel[1 ].reset (new SquareChannel (AudioChannel::Square2, _mixer.get (), false ));
30- _triangleChannel.reset (new TriangleChannel (AudioChannel::Triangle, _mixer.get ()));
31- _noiseChannel.reset (new NoiseChannel (AudioChannel::Noise, _mixer.get ()));
32- _deltaModulationChannel.reset (new DeltaModulationChannel (AudioChannel::DMC, _mixer.get (), _memoryManager ));
33- _frameCounter.reset (new ApuFrameCounter (&APU::FrameCounterTick ));
21+ _squareChannel[0 ].reset (new SquareChannel (AudioChannel::Square1, _console, _mixer.get (), true ));
22+ _squareChannel[1 ].reset (new SquareChannel (AudioChannel::Square2, _console, _mixer.get (), false ));
23+ _triangleChannel.reset (new TriangleChannel (AudioChannel::Triangle, _console, _mixer.get ()));
24+ _noiseChannel.reset (new NoiseChannel (AudioChannel::Noise, _console, _mixer.get ()));
25+ _deltaModulationChannel.reset (new DeltaModulationChannel (AudioChannel::DMC, _console, _mixer.get ()));
26+ _frameCounter.reset (new ApuFrameCounter (_console ));
3427
35- _memoryManager ->RegisterIODevice (_squareChannel[0 ].get ());
36- _memoryManager ->RegisterIODevice (_squareChannel[1 ].get ());
37- _memoryManager ->RegisterIODevice (_frameCounter.get ());
38- _memoryManager ->RegisterIODevice (_triangleChannel.get ());
39- _memoryManager ->RegisterIODevice (_noiseChannel.get ());
40- _memoryManager ->RegisterIODevice (_deltaModulationChannel.get ());
28+ _console-> GetMemoryManager () ->RegisterIODevice (_squareChannel[0 ].get ());
29+ _console-> GetMemoryManager () ->RegisterIODevice (_squareChannel[1 ].get ());
30+ _console-> GetMemoryManager () ->RegisterIODevice (_frameCounter.get ());
31+ _console-> GetMemoryManager () ->RegisterIODevice (_triangleChannel.get ());
32+ _console-> GetMemoryManager () ->RegisterIODevice (_noiseChannel.get ());
33+ _console-> GetMemoryManager () ->RegisterIODevice (_deltaModulationChannel.get ());
4134
4235 Reset (false );
4336}
@@ -67,20 +60,20 @@ void APU::SetNesModel(NesModel model, bool forceInit)
6760void APU::FrameCounterTick (FrameType type)
6861{
6962 // Quarter & half frame clock envelope & linear counter
70- Instance-> _squareChannel [0 ]->TickEnvelope ();
71- Instance-> _squareChannel [1 ]->TickEnvelope ();
72- Instance-> _triangleChannel ->TickLinearCounter ();
73- Instance-> _noiseChannel ->TickEnvelope ();
63+ _squareChannel[0 ]->TickEnvelope ();
64+ _squareChannel[1 ]->TickEnvelope ();
65+ _triangleChannel->TickLinearCounter ();
66+ _noiseChannel->TickEnvelope ();
7467
7568 if (type == FrameType::HalfFrame) {
7669 // Half frames clock length counter & sweep
77- Instance-> _squareChannel [0 ]->TickLengthCounter ();
78- Instance-> _squareChannel [1 ]->TickLengthCounter ();
79- Instance-> _triangleChannel ->TickLengthCounter ();
80- Instance-> _noiseChannel ->TickLengthCounter ();
70+ _squareChannel[0 ]->TickLengthCounter ();
71+ _squareChannel[1 ]->TickLengthCounter ();
72+ _triangleChannel->TickLengthCounter ();
73+ _noiseChannel->TickLengthCounter ();
8174
82- Instance-> _squareChannel [0 ]->TickSweep ();
83- Instance-> _squareChannel [1 ]->TickSweep ();
75+ _squareChannel[0 ]->TickSweep ();
76+ _squareChannel[1 ]->TickSweep ();
8477 }
8578}
8679
@@ -95,11 +88,11 @@ uint8_t APU::ReadRAM(uint16_t addr)
9588 status |= _triangleChannel->GetStatus () ? 0x04 : 0x00 ;
9689 status |= _noiseChannel->GetStatus () ? 0x08 : 0x00 ;
9790 status |= _deltaModulationChannel->GetStatus () ? 0x10 : 0x00 ;
98- status |= CPU::HasIRQSource (IRQSource::FrameCounter) ? 0x40 : 0x00 ;
99- status |= CPU::HasIRQSource (IRQSource::DMC) ? 0x80 : 0x00 ;
91+ status |= _console-> GetCpu ()-> HasIrqSource (IRQSource::FrameCounter) ? 0x40 : 0x00 ;
92+ status |= _console-> GetCpu ()-> HasIrqSource (IRQSource::DMC) ? 0x80 : 0x00 ;
10093
10194 // Reading $4015 clears the Frame Counter interrupt flag.
102- CPU::ClearIRQSource (IRQSource::FrameCounter);
95+ _console-> GetCpu ()-> ClearIrqSource (IRQSource::FrameCounter);
10396
10497 return status;
10598}
@@ -111,7 +104,7 @@ void APU::WriteRAM(uint16_t addr, uint8_t value)
111104
112105 // Writing to $4015 clears the DMC interrupt flag.
113106 // This needs to be done before setting the enabled flag for the DMC (because doing so can trigger an IRQ)
114- CPU::ClearIRQSource (IRQSource::DMC);
107+ _console-> GetCpu ()-> ClearIrqSource (IRQSource::DMC);
115108
116109 _squareChannel[0 ]->SetEnabled ((value & 0x01 ) == 0x01 );
117110 _squareChannel[1 ]->SetEnabled ((value & 0x02 ) == 0x02 );
@@ -153,19 +146,17 @@ void APU::Run()
153146 }
154147}
155148
156- void APU::StaticRun ()
149+ void APU::SetNeedToRun ()
157150{
158- Instance-> Run () ;
151+ _needToRun = true ;
159152}
160153
161154bool APU::NeedToRun (uint32_t currentCycle)
162155{
163- if (ApuLengthCounter::NeedToRun ()) {
164- return true ;
165- }
166-
167- if (_deltaModulationChannel->NeedToRun ()) {
156+ if (_needToRun || _deltaModulationChannel->NeedToRun ()) {
157+ // Need to run whenever we alter the length counters
168158 // Need to run every cycle when DMC is running to get accurate emulation (CPU stalling, interaction with sprite DMA, etc.)
159+ _needToRun = false ;
169160 return true ;
170161 }
171162
@@ -203,6 +194,21 @@ void APU::EndFrame()
203194 _previousCycle = 0 ;
204195}
205196
197+ void APU::ProcessCpuClock ()
198+ {
199+ if (_apuEnabled) {
200+ if (EmulationSettings::GetOverclockRate () == 100 || !EmulationSettings::GetOverclockAdjustApu ()) {
201+ Exec ();
202+ } else {
203+ _cyclesNeeded += 1.0 / ((double )EmulationSettings::GetOverclockRate () / 100.0 );
204+ while (_cyclesNeeded >= 1.0 ) {
205+ Exec ();
206+ _cyclesNeeded--;
207+ }
208+ }
209+ }
210+ }
211+
206212void APU::Reset (bool softReset)
207213{
208214 _apuEnabled = true ;
@@ -239,7 +245,7 @@ void APU::StreamState(bool saving)
239245
240246void APU::AddExpansionAudioDelta (AudioChannel channel, int16_t delta)
241247{
242- Instance-> _mixer ->AddDelta (channel, Instance-> _currentCycle , delta);
248+ _mixer->AddDelta (channel, _currentCycle, delta);
243249}
244250
245251void APU::SetApuStatus (bool enabled)
@@ -256,9 +262,9 @@ bool APU::IsApuEnabled()
256262 return _apuEnabled;
257263}
258264
259- void APU::WriteDmc4011 ( uint8_t value )
265+ void APU::FillDmcReadBuffer ( )
260266{
261- Instance-> _deltaModulationChannel ->WriteRAM ( 0x4011 , value );
267+ _deltaModulationChannel->FillReadBuffer ( );
262268}
263269
264270ApuState APU::GetState ()
@@ -271,4 +277,4 @@ ApuState APU::GetState()
271277 state.Square2 = _squareChannel[1 ]->GetState ();
272278 state.Triangle = _triangleChannel->GetState ();
273279 return state;
274- }
280+ }
0 commit comments