#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); } }