Mesen-S/Core/Msu1.cpp
2019-11-01 21:15:11 -04:00

118 lines
3.2 KiB
C++

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