-
Notifications
You must be signed in to change notification settings - Fork 131
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
75 changed files
with
8,426 additions
and
6 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,106 @@ | ||
#include "pch.h" | ||
#include "NES/NesConsole.h" | ||
#include "Shared/Emulator.h" | ||
#include "NES/INesMemoryHandler.h" | ||
#include "NES/Epsm.h" | ||
#include "Utilities/Serializer.h" | ||
|
||
Epsm::Epsm(Emulator* emu, NesConsole* console, vector<uint8_t>& adpcmRom) : _opn(console, adpcmRom) | ||
{ | ||
_console = console; | ||
_emu = emu; | ||
_masterClockRate = _console->GetMasterClockRate(); | ||
_emu->GetSoundMixer()->RegisterAudioProvider(this); | ||
} | ||
|
||
Epsm::~Epsm() | ||
{ | ||
_emu->GetSoundMixer()->UnregisterAudioProvider(this); | ||
} | ||
|
||
void Epsm::Write(uint8_t value) | ||
{ | ||
//4016 writes | ||
bool isHigh = (value & 0x02); | ||
bool wasHigh = (_prevValue & 0x02); | ||
|
||
if(isHigh && !wasHigh) { | ||
//rising edge | ||
_data = (value & 0xF0) | (_data & 0x0F); | ||
_addr = ((value & 0x04) >> 1) | ((value & 0x08) >> 3); | ||
} else if(!isHigh && wasHigh) { | ||
//falling edge | ||
_data = (_data & 0xF0) | ((value & 0xF0) >> 4); | ||
_opn.Write(_addr, _data); | ||
} | ||
|
||
_prevValue = value; | ||
} | ||
|
||
void Epsm::WriteRam(uint16_t addr, uint8_t value) | ||
{ | ||
//401C-401F writes | ||
_opn.Write(addr, value); | ||
} | ||
|
||
void Epsm::OnRegionChanged() | ||
{ | ||
uint64_t masterClockRate = _console->GetMasterClockRate(); | ||
if(_masterClockRate != masterClockRate) { | ||
//Reset alignment between cpu & epsm clocks if the region changes (e.g pal to ntsc, etc.) | ||
_masterClockRate = masterClockRate; | ||
_clockCounter = GetTargetClock(); | ||
} | ||
} | ||
|
||
uint64_t Epsm::GetTargetClock() | ||
{ | ||
uint64_t masterClock = _console->GetMasterClock(); | ||
double clockRatio = (double)OpnInterface::ClockRate / _masterClockRate; | ||
return masterClock * clockRatio; | ||
} | ||
|
||
void Epsm::Exec() | ||
{ | ||
constexpr int clocksPerSample = 16; | ||
|
||
uint64_t targetClock = GetTargetClock(); | ||
|
||
while(_clockCounter < targetClock) { | ||
_clockCounter++; | ||
_opn.Exec(); | ||
|
||
if((_clockCounter & (clocksPerSample - 1)) == 0) { | ||
_opn.GenerateSamples(_samples); | ||
} | ||
} | ||
} | ||
|
||
void Epsm::MixAudio(int16_t* out, uint32_t sampleCount, uint32_t sampleRate) | ||
{ | ||
_resampler.SetVolume(_console->GetNesConfig().EpsmVolume / 100.0); | ||
_resampler.SetSampleRates(_opn.GetSampleRate(), sampleRate); | ||
_resampler.Resample<true>(_samples.data(), (uint32_t)_samples.size() / 2, out, sampleCount, true); | ||
_samples.clear(); | ||
} | ||
|
||
void Epsm::GetMemoryRanges(MemoryRanges& ranges) | ||
{ | ||
ranges.AddHandler(MemoryOperation::Write, 0x401C, 0x401F); | ||
} | ||
|
||
uint8_t Epsm::ReadRam(uint16_t addr) | ||
{ | ||
return 0; | ||
} | ||
|
||
void Epsm::Serialize(Serializer& s) | ||
{ | ||
SV(_clockCounter); | ||
SV(_prevValue); | ||
SV(_addr); | ||
SV(_data); | ||
SV(_masterClockRate); | ||
|
||
SV(_opn); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
#pragma once | ||
#include "NES/OpnInterface.h" | ||
#include "Shared/Audio/SoundMixer.h" | ||
#include "Shared/Interfaces/IAudioProvider.h" | ||
#include "Utilities/Audio/HermiteResampler.h" | ||
#include "Utilities/ISerializable.h" | ||
|
||
class Emulator; | ||
class NesConsole; | ||
|
||
class Epsm : public IAudioProvider, public INesMemoryHandler, public ISerializable | ||
{ | ||
private: | ||
Emulator* _emu = nullptr; | ||
NesConsole* _console = nullptr; | ||
|
||
OpnInterface _opn; | ||
|
||
vector<int16_t> _samples; | ||
HermiteResampler _resampler; | ||
|
||
uint64_t _masterClockRate = 0; | ||
uint64_t _clockCounter = 0; | ||
uint8_t _prevValue = 0; | ||
uint8_t _data = 0; | ||
uint8_t _addr = 0; | ||
|
||
uint64_t GetTargetClock(); | ||
|
||
public: | ||
Epsm(Emulator* emu, NesConsole* console, vector<uint8_t>& adpcmRom); | ||
~Epsm(); | ||
|
||
void Write(uint8_t value); | ||
void WriteRam(uint16_t addr, uint8_t value) override; | ||
void Exec(); | ||
|
||
void OnRegionChanged(); | ||
|
||
void MixAudio(int16_t* out, uint32_t sampleCount, uint32_t sampleRate) override; | ||
|
||
void GetMemoryRanges(MemoryRanges& ranges) override; | ||
uint8_t ReadRam(uint16_t addr) override; | ||
|
||
void Serialize(Serializer& s) override; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.