MSU1 support
This commit is contained in:
parent
305ec6e446
commit
6b85b6a579
15 changed files with 427 additions and 16 deletions
|
@ -33,6 +33,7 @@
|
|||
#include "MovieManager.h"
|
||||
#include "SystemActionManager.h"
|
||||
#include "SpcHud.h"
|
||||
#include "Msu1.h"
|
||||
#include "../Utilities/Serializer.h"
|
||||
#include "../Utilities/Timer.h"
|
||||
#include "../Utilities/VirtualFile.h"
|
||||
|
@ -241,6 +242,7 @@ void Console::Stop(bool sendNotification)
|
|||
_controlManager.reset();
|
||||
_memoryManager.reset();
|
||||
_dmaController.reset();
|
||||
_msu1.reset();
|
||||
|
||||
_soundMixer->StopAudio(true);
|
||||
|
||||
|
@ -331,6 +333,8 @@ bool Console::LoadRom(VirtualFile romFile, VirtualFile patchFile, bool stopRom)
|
|||
_dmaController.reset(new DmaController(_memoryManager.get()));
|
||||
_spc.reset(new Spc(this));
|
||||
|
||||
_msu1.reset(Msu1::Init(romFile, _spc.get()));
|
||||
|
||||
if(_cart->GetSpcData()) {
|
||||
_spc->LoadSpcFile(_cart->GetSpcData());
|
||||
_spcHud.reset(new SpcHud(this, _cart->GetSpcData()));
|
||||
|
@ -553,6 +557,9 @@ void Console::Serialize(ostream &out)
|
|||
serializer.Stream(_cart.get());
|
||||
serializer.Stream(_controlManager.get());
|
||||
serializer.Stream(_spc.get());
|
||||
if(_msu1) {
|
||||
serializer.Stream(_msu1.get());
|
||||
}
|
||||
serializer.Save(out);
|
||||
}
|
||||
|
||||
|
@ -567,7 +574,9 @@ void Console::Deserialize(istream &in, uint32_t fileFormatVersion)
|
|||
serializer.Stream(_cart.get());
|
||||
serializer.Stream(_controlManager.get());
|
||||
serializer.Stream(_spc.get());
|
||||
|
||||
if(_msu1) {
|
||||
serializer.Stream(_msu1.get());
|
||||
}
|
||||
_notificationManager->SendNotification(ConsoleNotificationType::StateLoaded);
|
||||
}
|
||||
|
||||
|
@ -666,6 +675,11 @@ shared_ptr<DmaController> Console::GetDmaController()
|
|||
return _dmaController;
|
||||
}
|
||||
|
||||
shared_ptr<Msu1> Console::GetMsu1()
|
||||
{
|
||||
return _msu1;
|
||||
}
|
||||
|
||||
shared_ptr<Debugger> Console::GetDebugger(bool autoStart)
|
||||
{
|
||||
shared_ptr<Debugger> debugger = _debugger;
|
||||
|
|
|
@ -30,6 +30,7 @@ class MovieManager;
|
|||
class SpcHud;
|
||||
class FrameLimiter;
|
||||
class DebugStats;
|
||||
class Msu1;
|
||||
|
||||
enum class MemoryOperationType;
|
||||
enum class SnesMemoryType;
|
||||
|
@ -49,6 +50,8 @@ private:
|
|||
shared_ptr<InternalRegisters> _internalRegisters;
|
||||
shared_ptr<ControlManager> _controlManager;
|
||||
shared_ptr<DmaController> _dmaController;
|
||||
|
||||
shared_ptr<Msu1> _msu1;
|
||||
|
||||
shared_ptr<Debugger> _debugger;
|
||||
|
||||
|
@ -143,6 +146,7 @@ public:
|
|||
shared_ptr<InternalRegisters> GetInternalRegisters();
|
||||
shared_ptr<ControlManager> GetControlManager();
|
||||
shared_ptr<DmaController> GetDmaController();
|
||||
shared_ptr<Msu1> GetMsu1();
|
||||
|
||||
shared_ptr<Debugger> GetDebugger(bool autoStart = true);
|
||||
void StopDebugger();
|
||||
|
|
|
@ -114,6 +114,7 @@
|
|||
<ClInclude Include="MessageType.h" />
|
||||
<ClInclude Include="MovieDataMessage.h" />
|
||||
<ClInclude Include="MovieTypes.h" />
|
||||
<ClInclude Include="Msu1.h" />
|
||||
<ClInclude Include="Multitap.h" />
|
||||
<ClInclude Include="MesenMovie.h" />
|
||||
<ClInclude Include="MovieManager.h" />
|
||||
|
@ -124,6 +125,7 @@
|
|||
<ClInclude Include="NetMessage.h" />
|
||||
<ClInclude Include="NtscFilter.h" />
|
||||
<ClInclude Include="Obc1.h" />
|
||||
<ClInclude Include="PcmReader.h" />
|
||||
<ClInclude Include="PlayerListMessage.h" />
|
||||
<ClInclude Include="PpuTools.h" />
|
||||
<ClInclude Include="RecordedRomTest.h" />
|
||||
|
@ -261,12 +263,14 @@
|
|||
<ClCompile Include="MessageManager.cpp" />
|
||||
<ClCompile Include="MovieManager.cpp" />
|
||||
<ClCompile Include="MovieRecorder.cpp" />
|
||||
<ClCompile Include="Msu1.cpp" />
|
||||
<ClCompile Include="Multitap.cpp" />
|
||||
<ClCompile Include="NecDsp.cpp" />
|
||||
<ClCompile Include="NecDspDisUtils.cpp" />
|
||||
<ClCompile Include="NotificationManager.cpp" />
|
||||
<ClCompile Include="NtscFilter.cpp" />
|
||||
<ClCompile Include="Obc1.cpp" />
|
||||
<ClCompile Include="PcmReader.cpp" />
|
||||
<ClCompile Include="Ppu.cpp" />
|
||||
<ClCompile Include="PpuTools.cpp" />
|
||||
<ClCompile Include="RecordedRomTest.cpp" />
|
||||
|
|
|
@ -479,6 +479,12 @@
|
|||
<ClInclude Include="IDebugger.h">
|
||||
<Filter>Debugger\Debuggers</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Msu1.h">
|
||||
<Filter>SNES\Coprocessors\MSU1</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="PcmReader.h">
|
||||
<Filter>SNES\Coprocessors\MSU1</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="stdafx.cpp" />
|
||||
|
@ -761,6 +767,12 @@
|
|||
<ClCompile Include="GameServer.cpp">
|
||||
<Filter>Netplay</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="PcmReader.cpp">
|
||||
<Filter>SNES\Coprocessors\MSU1</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Msu1.cpp">
|
||||
<Filter>SNES\Coprocessors\MSU1</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Filter Include="SNES">
|
||||
|
@ -829,5 +841,8 @@
|
|||
<Filter Include="Netplay\Messages">
|
||||
<UniqueIdentifier>{c58f689e-a6af-4b9c-bb77-0be9d2b1142c}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="SNES\Coprocessors\MSU1">
|
||||
<UniqueIdentifier>{9fb8db1f-a7b5-4570-99ca-bbc15d262632}</UniqueIdentifier>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
</Project>
|
|
@ -272,7 +272,7 @@ uint8_t MemoryManager::ReadDma(uint32_t addr, bool forBusA)
|
|||
uint8_t value;
|
||||
IMemoryHandler* handler = _mappings.GetHandler(addr);
|
||||
if(handler) {
|
||||
if(forBusA && handler == _registerHandlerB.get()) {
|
||||
if(forBusA && addr >= 0x2100 && addr <= 0x21FF && handler == _registerHandlerB.get()) {
|
||||
//Trying to read from bus B using bus A returns open bus
|
||||
value = _openBus;
|
||||
} else if(handler == _registerHandlerA.get()) {
|
||||
|
|
117
Core/Msu1.cpp
Normal file
117
Core/Msu1.cpp
Normal file
|
@ -0,0 +1,117 @@
|
|||
#include "stdafx.h"
|
||||
#include "Msu1.h"
|
||||
#include "Spc.h"
|
||||
#include "../Utilities/Serializer.h"
|
||||
#include "../Utilities/FolderUtilities.h"
|
||||
|
||||
Msu1* Msu1::Init(VirtualFile romFile, Spc* spc)
|
||||
{
|
||||
string romFolder = romFile.GetFolderPath();
|
||||
string romName = FolderUtilities::GetFilename(romFile.GetFileName(), false);
|
||||
if(ifstream(FolderUtilities::CombinePath(romFolder, romName + ".msu"))) {
|
||||
return new Msu1(romFile, spc);
|
||||
} else if(ifstream(FolderUtilities::CombinePath(romFolder, "msu1.rom"))) {
|
||||
return new Msu1(romFile, spc);
|
||||
} else {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
Msu1::Msu1(VirtualFile romFile, Spc* spc)
|
||||
{
|
||||
_spc = spc;
|
||||
_romFolder = romFile.GetFolderPath();
|
||||
_romName = FolderUtilities::GetFilename(romFile.GetFileName(), false);
|
||||
_dataFile.open(FolderUtilities::CombinePath(_romFolder, _romName) + ".msu", ios::binary);
|
||||
if(_dataFile) {
|
||||
_trackPath = FolderUtilities::CombinePath(_romFolder, _romName);
|
||||
} else {
|
||||
_dataFile.open(FolderUtilities::CombinePath(_romFolder, "msu1.rom"), ios::binary);
|
||||
_trackPath = FolderUtilities::CombinePath(_romFolder, "track");
|
||||
}
|
||||
|
||||
if(_dataFile) {
|
||||
_dataFile.seekg(0, ios::end);
|
||||
_dataSize = (uint32_t)_dataFile.tellg();
|
||||
} else {
|
||||
_dataSize = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void Msu1::Write(uint16_t addr, uint8_t value)
|
||||
{
|
||||
switch(addr) {
|
||||
case 0x2000: _tmpDataPointer = (_tmpDataPointer & 0xFFFFFF00) | value; break;
|
||||
case 0x2001: _tmpDataPointer = (_tmpDataPointer & 0xFFFF00FF) | (value << 8); break;
|
||||
case 0x2002: _tmpDataPointer = (_tmpDataPointer & 0xFF00FFFF) | (value << 16); break;
|
||||
case 0x2003:
|
||||
_tmpDataPointer = (_tmpDataPointer & 0x00FFFFFF) | (value << 24);
|
||||
_dataPointer = _tmpDataPointer;
|
||||
_dataFile.seekg(_dataPointer, ios::beg);
|
||||
break;
|
||||
|
||||
case 0x2004: _trackSelect = (_trackSelect & 0xFF00) | value; break;
|
||||
case 0x2005:
|
||||
_trackSelect = (_trackSelect & 0xFF) | (value << 8);
|
||||
LoadTrack();
|
||||
break;
|
||||
|
||||
case 0x2006: _volume = value; break;
|
||||
case 0x2007:
|
||||
if(!_audioBusy) {
|
||||
_repeat = (value & 0x02) != 0;
|
||||
_paused = (value & 0x01) == 0;
|
||||
_pcmReader.SetLoopFlag(_repeat);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t Msu1::Read(uint16_t addr)
|
||||
{
|
||||
switch(addr) {
|
||||
case 0x2000:
|
||||
//status
|
||||
return (_dataBusy << 7) | (_audioBusy << 6) | (_repeat << 5) | ((!_paused) << 4) | (_trackMissing << 3) | 0x01;
|
||||
|
||||
case 0x2001:
|
||||
//data
|
||||
if(!_dataBusy && _dataPointer < _dataSize) {
|
||||
_dataPointer++;
|
||||
return (uint8_t)_dataFile.get();
|
||||
}
|
||||
return 0;
|
||||
|
||||
case 0x2002: return 'S';
|
||||
case 0x2003: return '-';
|
||||
case 0x2004: return 'M';
|
||||
case 0x2005: return 'S';
|
||||
case 0x2006: return 'U';
|
||||
case 0x2007: return '1';
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Msu1::MixAudio(int16_t* buffer, size_t sampleCount, uint32_t sampleRate)
|
||||
{
|
||||
if(!_paused) {
|
||||
_pcmReader.SetSampleRate(sampleRate);
|
||||
_pcmReader.ApplySamples(buffer, sampleCount, _spc->IsMuted() ? 0 : _volume);
|
||||
}
|
||||
}
|
||||
|
||||
void Msu1::LoadTrack(uint32_t startOffset)
|
||||
{
|
||||
_trackMissing = !_pcmReader.Init(_trackPath + "-" + std::to_string(_trackSelect) + ".pcm", _repeat, startOffset);
|
||||
}
|
||||
|
||||
void Msu1::Serialize(Serializer &s)
|
||||
{
|
||||
uint32_t offset = _pcmReader.GetOffset();
|
||||
s.Stream(_trackSelect, _tmpDataPointer, _dataPointer, _repeat, _paused, _volume, _trackMissing, _audioBusy, _dataBusy, offset);
|
||||
if(!s.IsSaving()) {
|
||||
_dataFile.seekg(_dataPointer, ios::beg);
|
||||
LoadTrack(offset);
|
||||
}
|
||||
}
|
44
Core/Msu1.h
Normal file
44
Core/Msu1.h
Normal file
|
@ -0,0 +1,44 @@
|
|||
#pragma once
|
||||
#include "stdafx.h"
|
||||
#include "PcmReader.h"
|
||||
#include "../Utilities/ISerializable.h"
|
||||
#include "../Utilities/VirtualFile.h"
|
||||
|
||||
class Spc;
|
||||
|
||||
class Msu1 : public ISerializable
|
||||
{
|
||||
private:
|
||||
Spc * _spc;
|
||||
PcmReader _pcmReader;
|
||||
uint8_t _volume = 100;
|
||||
uint16_t _trackSelect = 0;
|
||||
uint32_t _tmpDataPointer = 0;
|
||||
uint32_t _dataPointer = 0;
|
||||
string _romName;
|
||||
string _romFolder;
|
||||
string _trackPath;
|
||||
|
||||
bool _repeat = false;
|
||||
bool _paused = false;
|
||||
bool _audioBusy = false; //Always false
|
||||
bool _dataBusy = false; //Always false
|
||||
bool _trackMissing = false;
|
||||
|
||||
ifstream _dataFile;
|
||||
uint32_t _dataSize;
|
||||
|
||||
void LoadTrack(uint32_t startOffset = 8);
|
||||
|
||||
public:
|
||||
Msu1(VirtualFile romFile, Spc* spc);
|
||||
|
||||
static Msu1* Init(VirtualFile romFile, Spc* spc);
|
||||
|
||||
void Write(uint16_t addr, uint8_t value);
|
||||
uint8_t Read(uint16_t addr);
|
||||
|
||||
void MixAudio(int16_t *buffer, size_t sampleCount, uint32_t sampleRate);
|
||||
|
||||
void Serialize(Serializer &s);
|
||||
};
|
150
Core/PcmReader.cpp
Normal file
150
Core/PcmReader.cpp
Normal file
|
@ -0,0 +1,150 @@
|
|||
#include "stdafx.h"
|
||||
#include "PcmReader.h"
|
||||
#include "../Utilities/VirtualFile.h"
|
||||
|
||||
PcmReader::PcmReader()
|
||||
{
|
||||
_done = true;
|
||||
_loop = false;
|
||||
_prevLeft = 0;
|
||||
_prevRight = 0;
|
||||
_loopOffset = 8;
|
||||
_sampleRate = 48000;
|
||||
_blipLeft = blip_new(10000);
|
||||
_blipRight = blip_new(10000);
|
||||
_outputBuffer = new int16_t[20000];
|
||||
}
|
||||
|
||||
PcmReader::~PcmReader()
|
||||
{
|
||||
blip_delete(_blipLeft);
|
||||
blip_delete(_blipRight);
|
||||
delete[] _outputBuffer;
|
||||
}
|
||||
|
||||
bool PcmReader::Init(string filename, bool loop, uint32_t startOffset)
|
||||
{
|
||||
if(_file) {
|
||||
_file.close();
|
||||
}
|
||||
|
||||
_file.open(filename, ios::binary);
|
||||
if(_file) {
|
||||
_file.seekg(0, ios::end);
|
||||
_fileSize = (uint32_t)_file.tellg();
|
||||
if(_fileSize < 12) {
|
||||
return false;
|
||||
}
|
||||
|
||||
_file.seekg(4, ios::beg);
|
||||
uint32_t loopOffset = (uint8_t)_file.get();
|
||||
loopOffset |= ((uint8_t)_file.get()) << 8;
|
||||
loopOffset |= ((uint8_t)_file.get()) << 16;
|
||||
loopOffset |= ((uint8_t)_file.get()) << 24;
|
||||
|
||||
_loopOffset = (uint32_t)loopOffset;
|
||||
|
||||
_prevLeft = 0;
|
||||
_prevRight = 0;
|
||||
_done = false;
|
||||
_loop = loop;
|
||||
_fileOffset = startOffset;
|
||||
_file.seekg(_fileOffset, ios::beg);
|
||||
|
||||
blip_clear(_blipLeft);
|
||||
blip_clear(_blipRight);
|
||||
|
||||
return true;
|
||||
} else {
|
||||
_done = true;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool PcmReader::IsPlaybackOver()
|
||||
{
|
||||
return _done;
|
||||
}
|
||||
|
||||
void PcmReader::SetSampleRate(uint32_t sampleRate)
|
||||
{
|
||||
if(sampleRate != _sampleRate) {
|
||||
_sampleRate = sampleRate;
|
||||
|
||||
blip_clear(_blipLeft);
|
||||
blip_clear(_blipRight);
|
||||
blip_set_rates(_blipLeft, PcmReader::PcmSampleRate, _sampleRate);
|
||||
blip_set_rates(_blipRight, PcmReader::PcmSampleRate, _sampleRate);
|
||||
}
|
||||
}
|
||||
|
||||
void PcmReader::SetLoopFlag(bool loop)
|
||||
{
|
||||
_loop = loop;
|
||||
}
|
||||
|
||||
void PcmReader::ReadSample(int16_t &left, int16_t &right)
|
||||
{
|
||||
uint8_t val[4];
|
||||
_file.get(((char*)val)[0]);
|
||||
_file.get(((char*)val)[1]);
|
||||
_file.get(((char*)val)[2]);
|
||||
_file.get(((char*)val)[3]);
|
||||
|
||||
left = val[0] | (val[1] << 8);
|
||||
right = val[2] | (val[3] << 8);
|
||||
}
|
||||
|
||||
void PcmReader::LoadSamples(uint32_t samplesToLoad)
|
||||
{
|
||||
uint32_t samplesRead = 0;
|
||||
|
||||
int16_t left = 0;
|
||||
int16_t right = 0;
|
||||
for(uint32_t i = _fileOffset; i < _fileSize && samplesRead < samplesToLoad; i+=4) {
|
||||
ReadSample(left, right);
|
||||
|
||||
blip_add_delta(_blipLeft, samplesRead, left - _prevLeft);
|
||||
blip_add_delta(_blipRight, samplesRead, right - _prevRight);
|
||||
|
||||
_prevLeft = left;
|
||||
_prevRight = right;
|
||||
|
||||
_fileOffset += 4;
|
||||
samplesRead++;
|
||||
|
||||
if(samplesRead < samplesToLoad && i + 4 >= _fileSize) {
|
||||
if(_loop) {
|
||||
i = _loopOffset * 4 + 8;
|
||||
_fileOffset = i;
|
||||
_file.seekg(_fileOffset, ios::beg);
|
||||
} else {
|
||||
_done = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
blip_end_frame(_blipLeft, samplesRead);
|
||||
blip_end_frame(_blipRight, samplesRead);
|
||||
}
|
||||
|
||||
void PcmReader::ApplySamples(int16_t *buffer, size_t sampleCount, uint8_t volume)
|
||||
{
|
||||
if(_done) {
|
||||
return;
|
||||
}
|
||||
|
||||
LoadSamples((uint32_t)sampleCount * PcmReader::PcmSampleRate / _sampleRate + 1 - blip_samples_avail(_blipLeft));
|
||||
|
||||
int samplesRead = blip_read_samples(_blipLeft, _outputBuffer, (int)sampleCount, 1);
|
||||
blip_read_samples(_blipRight, _outputBuffer + 1, (int)sampleCount, 1);
|
||||
|
||||
for(size_t i = 0, len = samplesRead * 2; i < len; i++) {
|
||||
buffer[i] += (int16_t)((int32_t)_outputBuffer[i] * volume / 255);
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t PcmReader::GetOffset()
|
||||
{
|
||||
return _fileOffset;
|
||||
}
|
43
Core/PcmReader.h
Normal file
43
Core/PcmReader.h
Normal file
|
@ -0,0 +1,43 @@
|
|||
#pragma once
|
||||
#include "stdafx.h"
|
||||
#include "../Utilities/stb_vorbis.h"
|
||||
#include "../Utilities/blip_buf.h"
|
||||
|
||||
class PcmReader
|
||||
{
|
||||
private:
|
||||
static constexpr int PcmSampleRate = 44100;
|
||||
static constexpr int SamplesToRead = 100;
|
||||
|
||||
int16_t* _outputBuffer;
|
||||
|
||||
ifstream _file;
|
||||
uint32_t _fileOffset;
|
||||
uint32_t _fileSize;
|
||||
uint32_t _loopOffset;
|
||||
|
||||
int16_t _prevLeft;
|
||||
int16_t _prevRight;
|
||||
|
||||
bool _loop;
|
||||
bool _done;
|
||||
|
||||
blip_t* _blipLeft;
|
||||
blip_t* _blipRight;
|
||||
|
||||
uint32_t _sampleRate = 0;
|
||||
|
||||
void LoadSamples(uint32_t samplesToLoad);
|
||||
void ReadSample(int16_t &left, int16_t &right);
|
||||
|
||||
public:
|
||||
PcmReader();
|
||||
~PcmReader();
|
||||
|
||||
bool Init(string filename, bool loop, uint32_t startOffset = 0);
|
||||
bool IsPlaybackOver();
|
||||
void SetSampleRate(uint32_t sampleRate);
|
||||
void SetLoopFlag(bool loop);
|
||||
void ApplySamples(int16_t* buffer, size_t sampleCount, uint8_t volume);
|
||||
uint32_t GetOffset();
|
||||
};
|
|
@ -5,6 +5,7 @@
|
|||
#include "Spc.h"
|
||||
#include "BaseCartridge.h"
|
||||
#include "Sa1.h"
|
||||
#include "Msu1.h"
|
||||
#include "CheatManager.h"
|
||||
#include "../Utilities/Serializer.h"
|
||||
|
||||
|
@ -15,6 +16,7 @@ RegisterHandlerB::RegisterHandlerB(Console *console, Ppu * ppu, Spc * spc, uint8
|
|||
_sa1 = console->GetCartridge()->GetSa1();
|
||||
_ppu = ppu;
|
||||
_spc = spc;
|
||||
_msu1 = console->GetMsu1().get();
|
||||
_workRam = workRam;
|
||||
_wramPosition = 0;
|
||||
_memoryType = SnesMemoryType::Register;
|
||||
|
@ -33,6 +35,8 @@ uint8_t RegisterHandlerB::Read(uint32_t addr)
|
|||
return value;
|
||||
} else if(addr >= 0x2300 && addr <= 0x23FF && _console->GetCartridge()->GetSa1()) {
|
||||
return _console->GetCartridge()->GetSa1()->CpuRegisterRead(addr);
|
||||
} else if(_msu1 && addr <= 0x2007) {
|
||||
return _msu1->Read(addr);
|
||||
} else {
|
||||
return _ppu->Read(addr);
|
||||
}
|
||||
|
@ -69,6 +73,8 @@ void RegisterHandlerB::Write(uint32_t addr, uint8_t value)
|
|||
}
|
||||
} else if(addr >= 0x2200 && addr <= 0x22FF && _console->GetCartridge()->GetSa1()) {
|
||||
_console->GetCartridge()->GetSa1()->CpuRegisterWrite(addr, value);
|
||||
} else if(_msu1 && addr <= 0x2007) {
|
||||
return _msu1->Write(addr, value);
|
||||
} else {
|
||||
_ppu->Write(addr, value);
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@ class Console;
|
|||
class Ppu;
|
||||
class Spc;
|
||||
class Sa1;
|
||||
class Msu1;
|
||||
class CheatManager;
|
||||
|
||||
class RegisterHandlerB : public IMemoryHandler, public ISerializable
|
||||
|
@ -17,6 +18,7 @@ private:
|
|||
Ppu *_ppu;
|
||||
Spc *_spc;
|
||||
Sa1 *_sa1;
|
||||
Msu1 *_msu1;
|
||||
|
||||
uint8_t *_workRam;
|
||||
uint32_t _wramPosition;
|
||||
|
|
|
@ -44,7 +44,7 @@ public:
|
|||
// a pair of samples is be generated.
|
||||
void run();
|
||||
|
||||
void setEchoWriteEnabled(bool enabled);
|
||||
bool isMuted() { return (m.regs[r_flg] & 0x40) != 0; }
|
||||
|
||||
// Sound control
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
#include "RewindManager.h"
|
||||
#include "VideoRenderer.h"
|
||||
#include "WaveRecorder.h"
|
||||
#include "Msu1.h"
|
||||
#include "../Utilities/Equalizer.h"
|
||||
#include "../Utilities/blip_buf.h"
|
||||
|
||||
|
@ -69,25 +70,30 @@ void SoundMixer::PlayAudioBuffer(int16_t* samples, uint32_t sampleCount)
|
|||
_leftSample = samples[0];
|
||||
_rightSample = samples[1];
|
||||
|
||||
int16_t *out = nullptr;
|
||||
uint32_t count = 0;
|
||||
if(cfg.SampleRate == SoundResampler::SpcSampleRate && cfg.DisableDynamicSampleRate) {
|
||||
out = samples;
|
||||
count = sampleCount;
|
||||
} else {
|
||||
count = _resampler->Resample(samples, sampleCount, cfg.SampleRate, _sampleBuffer);
|
||||
out = _sampleBuffer;
|
||||
}
|
||||
|
||||
shared_ptr<Msu1> msu1 = _console->GetMsu1();
|
||||
if(msu1) {
|
||||
msu1->MixAudio(out, count, cfg.SampleRate);
|
||||
}
|
||||
|
||||
if(masterVolume < 100) {
|
||||
//Apply volume if not using the default value
|
||||
for(uint32_t i = 0; i < sampleCount * 2; i++) {
|
||||
samples[i] = (int32_t)samples[i] * (int32_t)masterVolume / 100;
|
||||
for(uint32_t i = 0; i < count * 2; i++) {
|
||||
out[i] = (int32_t)out[i] * (int32_t)masterVolume / 100;
|
||||
}
|
||||
}
|
||||
|
||||
shared_ptr<RewindManager> rewindManager = _console->GetRewindManager();
|
||||
if(rewindManager && rewindManager->SendAudio(samples, (uint32_t)sampleCount)) {
|
||||
int16_t *out = nullptr;
|
||||
uint32_t count = 0;
|
||||
if(cfg.SampleRate == SoundResampler::SpcSampleRate && cfg.DisableDynamicSampleRate) {
|
||||
out = samples;
|
||||
count = sampleCount;
|
||||
} else {
|
||||
count = _resampler->Resample(samples, sampleCount, cfg.SampleRate, _sampleBuffer);
|
||||
out = _sampleBuffer;
|
||||
}
|
||||
|
||||
if(rewindManager && rewindManager->SendAudio(out, count)) {
|
||||
bool isRecording = _waveRecorder || _console->GetVideoRenderer()->IsRecording();
|
||||
if(isRecording) {
|
||||
if(_waveRecorder) {
|
||||
|
|
|
@ -342,6 +342,11 @@ SpcState Spc::GetState()
|
|||
return _state;
|
||||
}
|
||||
|
||||
bool Spc::IsMuted()
|
||||
{
|
||||
return _dsp->isMuted();
|
||||
}
|
||||
|
||||
AddressInfo Spc::GetAbsoluteAddress(uint16_t addr)
|
||||
{
|
||||
if(addr < 0xFFC0 || !_state.RomEnabled) {
|
||||
|
|
|
@ -298,6 +298,7 @@ public:
|
|||
void ProcessEndFrame();
|
||||
|
||||
SpcState GetState();
|
||||
bool IsMuted();
|
||||
AddressInfo GetAbsoluteAddress(uint16_t addr);
|
||||
int GetRelativeAddress(AddressInfo & absAddress);
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue