mirror of
https://github.com/SourMesen/Mesen2.git
synced 2024-06-02 19:38:34 -04:00
Compare commits
4 commits
99e326e204
...
5e757ca20c
Author | SHA1 | Date | |
---|---|---|---|
5e757ca20c | |||
78130ed3bb | |||
2fddc85527 | |||
72f5445aba |
|
@ -799,7 +799,6 @@
|
|||
<ClCompile Include="NES\HdPacks\HdPackLoader.cpp" />
|
||||
<ClCompile Include="NES\HdPacks\HdVideoFilter.cpp" />
|
||||
<ClCompile Include="NES\HdPacks\OggMixer.cpp" />
|
||||
<ClCompile Include="NES\HdPacks\OggReader.cpp" />
|
||||
<ClCompile Include="NES\Loaders\FdsLoader.cpp" />
|
||||
<ClCompile Include="NES\Loaders\iNesLoader.cpp" />
|
||||
<ClCompile Include="NES\Loaders\NsfLoader.cpp" />
|
||||
|
@ -979,6 +978,7 @@
|
|||
<ClCompile Include="SNES\SnesNtscFilter.cpp" />
|
||||
<ClCompile Include="SNES\Coprocessors\OBC1\Obc1.cpp" />
|
||||
<ClCompile Include="Shared\Audio\PcmReader.cpp" />
|
||||
<ClCompile Include="Shared\Audio\OggReader.cpp" />
|
||||
<ClCompile Include="SNES\SnesPpu.cpp" />
|
||||
<ClCompile Include="Debugger\PpuTools.cpp" />
|
||||
<ClCompile Include="Debugger\Profiler.cpp" />
|
||||
|
@ -1240,4 +1240,4 @@
|
|||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
||||
</Project>
|
||||
|
|
|
@ -844,12 +844,6 @@
|
|||
<ClInclude Include="NES\HdPacks\OggMixer.h">
|
||||
<Filter>NES\HdPacks</Filter>
|
||||
</ClInclude>
|
||||
<ClCompile Include="NES\HdPacks\OggReader.cpp">
|
||||
<Filter>NES\HdPacks</Filter>
|
||||
</ClCompile>
|
||||
<ClInclude Include="NES\HdPacks\OggReader.h">
|
||||
<Filter>NES\HdPacks</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="NES\Input\ArkanoidController.h">
|
||||
<Filter>NES\Input</Filter>
|
||||
</ClInclude>
|
||||
|
@ -979,6 +973,12 @@
|
|||
<ClInclude Include="Shared\Audio\PcmReader.h">
|
||||
<Filter>Shared\Audio</Filter>
|
||||
</ClInclude>
|
||||
<ClCompile Include="Shared\Audio\OggReader.cpp">
|
||||
<Filter>Shared\Audio</Filter>
|
||||
</ClCompile>
|
||||
<ClInclude Include="Shared\Audio\OggReader.h">
|
||||
<Filter>Shared\Audio</Filter>
|
||||
</ClInclude>
|
||||
<ClCompile Include="Shared\Audio\SoundMixer.cpp">
|
||||
<Filter>Shared\Audio</Filter>
|
||||
</ClCompile>
|
||||
|
@ -3185,4 +3185,4 @@
|
|||
<UniqueIdentifier>{4cc96bee-c354-4a9b-9947-85959ccc072f}</UniqueIdentifier>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
</Project>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#include "pch.h"
|
||||
#include <algorithm>
|
||||
#include "NES/HdPacks/OggReader.h"
|
||||
#include "Shared/Audio/OggReader.h"
|
||||
#include "NES/HdPacks/OggMixer.h"
|
||||
|
||||
enum class OggPlaybackOptions
|
||||
|
|
|
@ -913,13 +913,18 @@ template<class T> void NesPpu<T>::ProcessScanlineImpl()
|
|||
//copy vertical scrolling value from t
|
||||
_videoRamAddr = (_videoRamAddr & ~0x7BE0) | (_tmpVideoRamAddr & 0x7BE0);
|
||||
}
|
||||
// Load the extra sprites before tile loading starts (which matters for MMC5)
|
||||
// The CHR banks are switched back to the bg tileset in LoadTileInfo on cycle 321
|
||||
// and the extra sprites will potentially read from the wrong banks
|
||||
if(_cycle == 320) {
|
||||
LoadExtraSprites();
|
||||
}
|
||||
}
|
||||
} else if(_cycle >= 321 && _cycle <= 336) {
|
||||
LoadTileInfo();
|
||||
|
||||
if(_cycle == 321) {
|
||||
if(IsRenderingEnabled()) {
|
||||
LoadExtraSprites();
|
||||
_oamCopybuffer = _secondarySpriteRam[0];
|
||||
}
|
||||
} else if(_prevRenderingEnabled && (_cycle == 328 || _cycle == 336)) {
|
||||
|
|
|
@ -5,14 +5,80 @@
|
|||
#include "Shared/Audio/SoundMixer.h"
|
||||
#include "Utilities/Serializer.h"
|
||||
#include "Utilities/FolderUtilities.h"
|
||||
#include "Utilities/StringUtilities.h"
|
||||
|
||||
bool ends_with(std::string const & value, std::string const & ending)
|
||||
{
|
||||
if (ending.size() > value.size()) return false;
|
||||
return std::equal(ending.rbegin(), ending.rend(), value.rbegin());
|
||||
}
|
||||
|
||||
std::optional<std::string> GetFileForExt(std::string& base, std::string ext) {
|
||||
if (base.back() == '\x1') {
|
||||
auto withoutEnd = base;
|
||||
withoutEnd.pop_back();
|
||||
auto reader = ArchiveReader::GetReader(withoutEnd);
|
||||
for (const auto& f : reader->GetFileList()) {
|
||||
if (ends_with(StringUtilities::ToLower(f), ext)) {
|
||||
return base + f;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
auto ret = base + ext;
|
||||
if (VirtualFile(ret).IsValid()) {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
void PcmOrOggReader::SetLoopFlag(bool loop) {
|
||||
if (_usingOgg) { _oggReader.SetLoopFlag(loop); }
|
||||
else { _pcmReader.SetLoopFlag(loop); }
|
||||
}
|
||||
void PcmOrOggReader::SetSampleRate(uint32_t sampleRate) {
|
||||
if (_usingOgg) { _oggReader.SetSampleRate(sampleRate); }
|
||||
else { _pcmReader.SetSampleRate(sampleRate); }
|
||||
}
|
||||
void PcmOrOggReader::ApplySamples(int16_t* buffer, size_t sampleCount, uint8_t volume) {
|
||||
if (_usingOgg) { _oggReader.ApplySamples(buffer, sampleCount, volume); }
|
||||
else { _pcmReader.ApplySamples(buffer, sampleCount, volume); }
|
||||
}
|
||||
bool PcmOrOggReader::IsPlaybackOver() {
|
||||
return _usingOgg ? _oggReader.IsPlaybackOver() : _pcmReader.IsPlaybackOver();
|
||||
}
|
||||
uint32_t PcmOrOggReader::GetOffset() {
|
||||
return _usingOgg ? _oggReader.GetOffset() * 4 : _pcmReader.GetOffset();
|
||||
}
|
||||
bool PcmOrOggReader::Init(string base, size_t track, bool loop, uint32_t startOffset) {
|
||||
_usingOgg = false;
|
||||
auto pcm = GetFileForExt(base, "-" + std::to_string(track) + ".pcm");
|
||||
if (pcm.has_value()) {
|
||||
if (_pcmReader.Init(*pcm, loop, startOffset)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
auto ogg = GetFileForExt(base, "-" + std::to_string(track) + ".ogg");
|
||||
if (ogg.has_value()) {
|
||||
if (_oggReader.Init(*ogg, loop, 44100, startOffset / 4)) {
|
||||
_usingOgg = true;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
Msu1* Msu1::Init(Emulator* emu, VirtualFile& romFile, Spc* spc)
|
||||
{
|
||||
string romFolder = romFile.GetFolderPath();
|
||||
string romName = FolderUtilities::GetFilename(romFile.GetFileName(), false);
|
||||
if(ifstream(FolderUtilities::CombinePath(romFolder, romName + ".msu"))) {
|
||||
if(romFile.IsArchive()) {
|
||||
return new Msu1(emu, romFile, spc);
|
||||
} else if(ifstream(FolderUtilities::CombinePath(romFolder, "msu1.rom"))) {
|
||||
} else if(VirtualFile(FolderUtilities::CombinePath(romFolder, romName + ".msu")).IsValid()) {
|
||||
return new Msu1(emu, romFile, spc);
|
||||
} else if(VirtualFile(FolderUtilities::CombinePath(romFolder, "msu1.rom")).IsValid()) {
|
||||
return new Msu1(emu, romFile, spc);
|
||||
} else {
|
||||
return nullptr;
|
||||
|
@ -25,17 +91,28 @@ Msu1::Msu1(Emulator* emu, 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) {
|
||||
if (romFile.IsArchive()) {
|
||||
_trackPath = romFile.GetFilePath() + "\x1";
|
||||
auto path = GetFileForExt(_trackPath, ".msu");
|
||||
if (path.has_value()) {
|
||||
auto dataVirtualFileArchive = VirtualFile(*path);
|
||||
_dataFile = dataVirtualFileArchive.Stream();
|
||||
}
|
||||
} else if(
|
||||
auto dataVirtualFile = VirtualFile(FolderUtilities::CombinePath(_romFolder, _romName) + ".msu");
|
||||
dataVirtualFile.IsValid()
|
||||
) {
|
||||
_dataFile = dataVirtualFile.Stream();
|
||||
_trackPath = FolderUtilities::CombinePath(_romFolder, _romName);
|
||||
} else {
|
||||
_dataFile.open(FolderUtilities::CombinePath(_romFolder, "msu1.rom"), ios::binary);
|
||||
auto dataVirtualFileRom = VirtualFile(FolderUtilities::CombinePath(_romFolder, "msu1.rom"));
|
||||
_dataFile = dataVirtualFileRom.Stream();
|
||||
_trackPath = FolderUtilities::CombinePath(_romFolder, "track");
|
||||
}
|
||||
|
||||
if(_dataFile) {
|
||||
_dataFile.seekg(0, ios::end);
|
||||
_dataSize = (uint32_t)_dataFile.tellg();
|
||||
_dataFile->seekg(0, ios::end);
|
||||
_dataSize = (uint32_t)_dataFile->tellg();
|
||||
} else {
|
||||
_dataSize = 0;
|
||||
}
|
||||
|
@ -57,7 +134,7 @@ void Msu1::Write(uint16_t addr, uint8_t value)
|
|||
case 0x2003:
|
||||
_tmpDataPointer = (_tmpDataPointer & 0x00FFFFFF) | (value << 24);
|
||||
_dataPointer = _tmpDataPointer;
|
||||
_dataFile.seekg(_dataPointer, ios::beg);
|
||||
_dataFile->seekg(_dataPointer, ios::beg);
|
||||
break;
|
||||
|
||||
case 0x2004: _trackSelect = (_trackSelect & 0xFF00) | value; break;
|
||||
|
@ -71,7 +148,7 @@ void Msu1::Write(uint16_t addr, uint8_t value)
|
|||
if(!_audioBusy) {
|
||||
_repeat = (value & 0x02) != 0;
|
||||
_paused = (value & 0x01) == 0;
|
||||
_pcmReader.SetLoopFlag(_repeat);
|
||||
_soundReader.SetLoopFlag(_repeat);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -88,7 +165,7 @@ uint8_t Msu1::Read(uint16_t addr)
|
|||
//data
|
||||
if(!_dataBusy && _dataPointer < _dataSize) {
|
||||
_dataPointer++;
|
||||
return (uint8_t)_dataFile.get();
|
||||
return (uint8_t)_dataFile->get();
|
||||
}
|
||||
return 0;
|
||||
|
||||
|
@ -106,24 +183,26 @@ uint8_t Msu1::Read(uint16_t addr)
|
|||
void Msu1::MixAudio(int16_t* buffer, uint32_t sampleCount, uint32_t sampleRate)
|
||||
{
|
||||
if(!_paused) {
|
||||
_pcmReader.SetSampleRate(sampleRate);
|
||||
_pcmReader.ApplySamples(buffer, (size_t)sampleCount, _spc->IsMuted() ? 0 : _volume);
|
||||
_soundReader.SetSampleRate(sampleRate);
|
||||
_soundReader.ApplySamples(buffer, (size_t)sampleCount, _spc->IsMuted() ? 0 : _volume);
|
||||
|
||||
_paused |= _pcmReader.IsPlaybackOver();
|
||||
_paused |= _soundReader.IsPlaybackOver();
|
||||
}
|
||||
}
|
||||
|
||||
void Msu1::LoadTrack(uint32_t startOffset)
|
||||
{
|
||||
_trackMissing = !_pcmReader.Init(_trackPath + "-" + std::to_string(_trackSelect) + ".pcm", _repeat, startOffset);
|
||||
_trackMissing = !_soundReader.Init(_trackPath, _trackSelect, _repeat, startOffset);
|
||||
}
|
||||
|
||||
void Msu1::Serialize(Serializer &s)
|
||||
{
|
||||
uint32_t offset = _pcmReader.GetOffset();
|
||||
uint32_t offset = _soundReader.GetOffset();
|
||||
SV(_trackSelect); SV(_tmpDataPointer); SV(_dataPointer); SV(_repeat); SV(_paused); SV(_volume); SV(_trackMissing); SV(_audioBusy); SV(_dataBusy); SV(offset);
|
||||
if(!s.IsSaving()) {
|
||||
_dataFile.seekg(_dataPointer, ios::beg);
|
||||
if (_dataFile) {
|
||||
_dataFile->seekg(_dataPointer, ios::beg);
|
||||
}
|
||||
LoadTrack(offset);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,19 +1,38 @@
|
|||
#pragma once
|
||||
#include "pch.h"
|
||||
#include "Shared/Interfaces/IAudioProvider.h"
|
||||
|
||||
#include "Shared/Audio/PcmReader.h"
|
||||
#include "Shared/Audio/OggReader.h"
|
||||
#include "Utilities/ISerializable.h"
|
||||
#include "Utilities/VirtualFile.h"
|
||||
#include "Utilities/StringUtilities.h"
|
||||
#include "Utilities/ArchiveReader.h"
|
||||
|
||||
class Spc;
|
||||
class Emulator;
|
||||
|
||||
class PcmOrOggReader final {
|
||||
private:
|
||||
PcmReader _pcmReader;
|
||||
OggReader _oggReader;
|
||||
bool _usingOgg = false;
|
||||
|
||||
public:
|
||||
void SetLoopFlag(bool loop);
|
||||
void SetSampleRate(uint32_t sampleRate);
|
||||
void ApplySamples(int16_t* buffer, size_t sampleCount, uint8_t volume);
|
||||
bool IsPlaybackOver();
|
||||
uint32_t GetOffset();
|
||||
bool Init(string base, size_t track, bool loop, uint32_t startOffset);
|
||||
};
|
||||
|
||||
class Msu1 final : public ISerializable, public IAudioProvider
|
||||
{
|
||||
private:
|
||||
Spc* _spc = nullptr;
|
||||
Emulator* _emu = nullptr;
|
||||
PcmReader _pcmReader;
|
||||
PcmOrOggReader _soundReader;
|
||||
uint8_t _volume = 100;
|
||||
uint16_t _trackSelect = 0;
|
||||
uint32_t _tmpDataPointer = 0;
|
||||
|
@ -28,7 +47,7 @@ private:
|
|||
bool _dataBusy = false; //Always false
|
||||
bool _trackMissing = false;
|
||||
|
||||
ifstream _dataFile;
|
||||
unique_ptr<istream> _dataFile;
|
||||
uint32_t _dataSize;
|
||||
|
||||
void LoadTrack(uint32_t startOffset = 8);
|
||||
|
@ -45,4 +64,4 @@ public:
|
|||
void MixAudio(int16_t* buffer, uint32_t sampleCount, uint32_t sampleRate) override;
|
||||
|
||||
void Serialize(Serializer &s) override;
|
||||
};
|
||||
};
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
#include "Utilities/VirtualFile.h"
|
||||
#include "Utilities/PlatformUtilities.h"
|
||||
#include "Utilities/FolderUtilities.h"
|
||||
#include "Utilities/StringUtilities.h"
|
||||
#include "Shared/EventType.h"
|
||||
#include "SNES/RegisterHandlerA.h"
|
||||
#include "SNES/RegisterHandlerB.h"
|
||||
|
@ -100,7 +101,7 @@ void SnesConsole::Reset()
|
|||
_memoryManager->IncMasterClockStartup();
|
||||
}
|
||||
|
||||
LoadRomResult SnesConsole::LoadRom(VirtualFile& romFile)
|
||||
LoadRomResult SnesConsole::InnerLoadRom(VirtualFile& romFile)
|
||||
{
|
||||
SnesConfig config = _settings->GetSnesConfig();
|
||||
LoadRomResult loadResult = LoadRomResult::UnknownType;
|
||||
|
@ -144,6 +145,16 @@ LoadRomResult SnesConsole::LoadRom(VirtualFile& romFile)
|
|||
return loadResult;
|
||||
}
|
||||
|
||||
LoadRomResult SnesConsole::LoadRom(VirtualFile& romFile)
|
||||
{
|
||||
if (StringUtilities::ToLower(romFile.GetFileExtension()) == ".msu1") {
|
||||
auto r = VirtualFile(romFile.GetFilePath(), "program.rom");
|
||||
return this->InnerLoadRom(r);
|
||||
} else {
|
||||
return this->InnerLoadRom(romFile);
|
||||
}
|
||||
}
|
||||
|
||||
bool SnesConsole::LoadSpcFile(VirtualFile& romFile)
|
||||
{
|
||||
_spc->LoadSpcFile(_cart->GetSpcData());
|
||||
|
@ -549,4 +560,4 @@ void SnesConsole::InitializeRam(void* data, uint32_t length)
|
|||
state = settings->GetSnesConfig().RamPowerOnState;
|
||||
}
|
||||
settings->InitializeRam(state, data, length);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -66,13 +66,14 @@ private:
|
|||
bool _frameRunning = false;
|
||||
|
||||
void UpdateRegion();
|
||||
LoadRomResult InnerLoadRom(VirtualFile& romFile);
|
||||
bool LoadSpcFile(VirtualFile& romFile);
|
||||
|
||||
public:
|
||||
SnesConsole(Emulator* emu);
|
||||
~SnesConsole();
|
||||
|
||||
static vector<string> GetSupportedExtensions() { return { ".sfc", ".swc", ".fig", ".smc", ".bs", ".gb", ".gbc", ".spc" }; }
|
||||
static vector<string> GetSupportedExtensions() { return { ".sfc", ".swc", ".fig", ".smc", ".bs", ".gb", ".gbc", ".spc", ".msu1" }; }
|
||||
static vector<string> GetSupportedSignatures() { return { "SNES-SPC700 Sound File Data" }; }
|
||||
|
||||
void Initialize();
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#include "pch.h"
|
||||
#include "NES/HdPacks/OggReader.h"
|
||||
#include "Shared/Audio/OggReader.h"
|
||||
#include "Utilities/Audio/stb_vorbis.h"
|
||||
#include "Utilities/StringUtilities.h"
|
||||
|
||||
OggReader::OggReader()
|
||||
{
|
||||
|
@ -21,12 +22,29 @@ OggReader::~OggReader()
|
|||
|
||||
bool OggReader::Init(string filename, bool loop, uint32_t sampleRate, uint32_t startOffset, uint32_t loopPosition)
|
||||
{
|
||||
_loaded = false;
|
||||
int error;
|
||||
VirtualFile file = filename;
|
||||
_fileData = vector<uint8_t>(100000);
|
||||
if(file.ReadFile(_fileData)) {
|
||||
_vorbis = stb_vorbis_open_memory(_fileData.data(), (int)_fileData.size(), &error, nullptr);
|
||||
if(_vorbis) {
|
||||
auto comments = stb_vorbis_get_comment(_vorbis);
|
||||
for (int i = 0; i < comments.comment_list_length; i++) {
|
||||
auto comment = comments.comment_list[i];
|
||||
vector<string> commentParts = StringUtilities::Split(comment, '=');
|
||||
if (commentParts.size() != 2) { continue; }
|
||||
if (commentParts[0] != "LOOPSTART") { continue; }
|
||||
uint32_t loopPositionFromFile;
|
||||
try {
|
||||
loopPositionFromFile = std::stoi(commentParts[1]);
|
||||
} catch (std::invalid_argument const& _e) {
|
||||
throw std::runtime_error("Mis-formatted loop start in .ogg");
|
||||
} catch (std::out_of_range const& _e) {
|
||||
throw std::runtime_error("Out-of-range integer loop start in .ogg");
|
||||
}
|
||||
loopPosition = loopPositionFromFile;
|
||||
}
|
||||
_loop = loop;
|
||||
if(loopPosition > 0) {
|
||||
unsigned int sampleCount = stb_vorbis_stream_length_in_samples(_vorbis);
|
||||
|
@ -38,6 +56,7 @@ bool OggReader::Init(string filename, bool loop, uint32_t sampleRate, uint32_t s
|
|||
if(startOffset > 0) {
|
||||
stb_vorbis_seek(_vorbis, startOffset);
|
||||
}
|
||||
_loaded = true;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -63,6 +82,9 @@ void OggReader::SetLoopFlag(bool loop)
|
|||
|
||||
void OggReader::ApplySamples(int16_t* buffer, size_t sampleCount, uint8_t volume)
|
||||
{
|
||||
if (!_loaded) {
|
||||
return;
|
||||
}
|
||||
int32_t samplesNeeded = (int32_t)sampleCount - _resampler.GetPendingCount();
|
||||
uint32_t samplesRead = 0;
|
||||
if(samplesNeeded > 0) {
|
||||
|
@ -88,5 +110,8 @@ void OggReader::ApplySamples(int16_t* buffer, size_t sampleCount, uint8_t volume
|
|||
|
||||
uint32_t OggReader::GetOffset()
|
||||
{
|
||||
return stb_vorbis_get_file_offset(_vorbis);
|
||||
}
|
||||
if (!_loaded) {
|
||||
return 0;
|
||||
}
|
||||
return stb_vorbis_get_sample_offset(_vorbis);
|
||||
}
|
|
@ -14,6 +14,7 @@ private:
|
|||
|
||||
HermiteResampler _resampler;
|
||||
|
||||
bool _loaded = false;
|
||||
bool _loop = false;
|
||||
bool _done = false;
|
||||
|
|
@ -17,23 +17,21 @@ PcmReader::~PcmReader()
|
|||
|
||||
bool PcmReader::Init(string filename, bool loop, uint32_t startOffset)
|
||||
{
|
||||
if(_file) {
|
||||
_file.close();
|
||||
}
|
||||
auto v = VirtualFile(filename);
|
||||
_file = v.Stream();
|
||||
|
||||
_file.open(filename, ios::binary);
|
||||
if(_file) {
|
||||
_file.seekg(0, ios::end);
|
||||
_fileSize = (uint32_t)_file.tellg();
|
||||
_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;
|
||||
_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;
|
||||
|
||||
|
@ -42,7 +40,7 @@ bool PcmReader::Init(string filename, bool loop, uint32_t startOffset)
|
|||
_done = false;
|
||||
_loop = loop;
|
||||
_fileOffset = startOffset;
|
||||
_file.seekg(_fileOffset, ios::beg);
|
||||
_file->seekg(_fileOffset, ios::beg);
|
||||
|
||||
_leftoverSampleCount = 0;
|
||||
_pcmBuffer.clear();
|
||||
|
@ -77,10 +75,10 @@ void PcmReader::SetLoopFlag(bool 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]);
|
||||
_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);
|
||||
|
@ -108,7 +106,7 @@ void PcmReader::LoadSamples(uint32_t samplesToLoad)
|
|||
if(_loop) {
|
||||
i = _loopOffset * 4 + 8;
|
||||
_fileOffset = i;
|
||||
_file.seekg(_fileOffset, ios::beg);
|
||||
_file->seekg(_fileOffset, ios::beg);
|
||||
} else {
|
||||
_done = true;
|
||||
}
|
||||
|
@ -140,4 +138,4 @@ void PcmReader::ApplySamples(int16_t *buffer, size_t sampleCount, uint8_t volume
|
|||
uint32_t PcmReader::GetOffset()
|
||||
{
|
||||
return _fileOffset;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,7 +11,7 @@ private:
|
|||
|
||||
int16_t* _outputBuffer = nullptr;
|
||||
|
||||
ifstream _file;
|
||||
unique_ptr<istream> _file;
|
||||
uint32_t _fileOffset = 0;
|
||||
uint32_t _fileSize = 0;
|
||||
uint32_t _loopOffset = 0;
|
||||
|
|
|
@ -582,7 +582,7 @@
|
|||
|
||||
<Control ID="tpgFiles">Folders/Files</Control>
|
||||
<Control ID="grpFileAssociations">File Associations</Control>
|
||||
<Control ID="chkSnesRomFiles">SNES roms: .sfc, .smc, .swc, .fig, .bs</Control>
|
||||
<Control ID="chkSnesRomFiles">SNES roms: .sfc, .smc, .swc, .fig, .bs, .msu1</Control>
|
||||
<Control ID="chkSnesMusicFiles">SNES music: .spc</Control>
|
||||
<Control ID="chkNesRomFiles">NES roms: .nes, .unif, .fds, .studybox</Control>
|
||||
<Control ID="chkNesMusicFiles">NES music: .nsf, .nsfe</Control>
|
||||
|
|
|
@ -49,8 +49,8 @@ namespace Mesen.Utilities
|
|||
List<FilePickerFileType> filter = new List<FilePickerFileType>();
|
||||
foreach(string ext in extensions) {
|
||||
if(ext == FileDialogHelper.RomExt) {
|
||||
filter.Add(new FilePickerFileType("All ROM files") { Patterns = new List<string>() { "*.sfc", "*.fig", "*.smc", "*.bs", "*.spc", "*.nes", "*.fds", "*.unif", "*.unf", "*.studybox", "*.nsf", "*.nsfe", "*.gb", "*.gbc", "*.gbs", "*.pce", "*.sgx", "*.cue", "*.hes", "*.sms", "*.gg", "*.sg", "*.gba", "*.zip", "*.7z" } });
|
||||
filter.Add(new FilePickerFileType("SNES ROM files") { Patterns = new List<string>() { "*.sfc", "*.fig", "*.smc", "*.bs", "*.spc" } });
|
||||
filter.Add(new FilePickerFileType("All ROM files") { Patterns = new List<string>() { "*.sfc", "*.fig", "*.smc", "*.bs", "*.spc", "*.nes", "*.fds", "*.unif", "*.unf", "*.studybox", "*.nsf", "*.nsfe", "*.gb", "*.gbc", "*.gbs", "*.pce", "*.sgx", "*.cue", "*.hes", "*.sms", "*.gg", "*.sg", "*.gba", "*.zip", "*.7z", "*.msu1" } });
|
||||
filter.Add(new FilePickerFileType("SNES ROM files") { Patterns = new List<string>() { "*.sfc", "*.fig", "*.smc", "*.bs", "*.spc", "*.msu1" } });
|
||||
filter.Add(new FilePickerFileType("NES ROM files") { Patterns = new List<string>() { "*.nes", "*.fds", "*.unif", "*.unf", "*.studybox", "*.nsf", "*.nsfe" } });
|
||||
filter.Add(new FilePickerFileType("GB ROM files") { Patterns = new List<string>() { "*.gb", "*.gbc", "*.gbs" } });
|
||||
filter.Add(new FilePickerFileType("GBA ROM files") { Patterns = new List<string>() { "*.gba" } });
|
||||
|
@ -138,4 +138,4 @@ namespace Mesen.Utilities
|
|||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -11,7 +11,7 @@ namespace Mesen.Utilities
|
|||
public static class FolderHelper
|
||||
{
|
||||
private static HashSet<string> _romExtensions = new HashSet<string>() {
|
||||
".sfc", ".smc", ".fig", ".swc", ".bs",
|
||||
".sfc", ".smc", ".fig", ".swc", ".bs", ".msu1",
|
||||
".gb", ".gbc",
|
||||
".nes", ".unif", ".unf", ".fds", ".studybox",
|
||||
".pce", ".sgx", ".cue",
|
||||
|
@ -55,4 +55,4 @@ namespace Mesen.Utilities
|
|||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -13,7 +13,7 @@
|
|||
|
||||
const std::initializer_list<string> VirtualFile::RomExtensions = {
|
||||
".nes", ".fds", ".unif", ".unf", ".nsf", ".nsfe", ".studybox",
|
||||
".sfc", ".swc", ".fig", ".smc", ".bs", ".spc",
|
||||
".sfc", ".swc", ".fig", ".smc", ".bs", ".spc", ".msu1",
|
||||
".gb", ".gbc", ".gbs",
|
||||
".pce", ".sgx", ".cue", ".hes",
|
||||
".sms", ".gg", ".sg",
|
||||
|
@ -265,6 +265,21 @@ bool VirtualFile::ReadFile(uint8_t* out, uint32_t expectedSize)
|
|||
return false;
|
||||
}
|
||||
|
||||
std::unique_ptr<std::istream> VirtualFile::Stream()
|
||||
{
|
||||
if(!_innerFile.empty()) {
|
||||
auto out = std::make_unique<std::stringstream>();
|
||||
ReadFile(*out);
|
||||
return out;
|
||||
} else {
|
||||
auto ret = std::make_unique<std::ifstream>(_path, std::ios::in | std::ios::binary);
|
||||
if(ret) {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
return std::make_unique<std::istream>(nullptr);
|
||||
}
|
||||
|
||||
uint8_t VirtualFile::ReadByte(uint32_t offset)
|
||||
{
|
||||
InitChunks();
|
||||
|
@ -310,4 +325,4 @@ bool VirtualFile::ApplyPatch(VirtualFile& patch)
|
|||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -48,6 +48,8 @@ public:
|
|||
bool ReadFile(std::stringstream &out);
|
||||
bool ReadFile(uint8_t* out, uint32_t expectedSize);
|
||||
|
||||
std::unique_ptr<std::istream> Stream();
|
||||
|
||||
uint8_t ReadByte(uint32_t offset);
|
||||
|
||||
bool ApplyPatch(VirtualFile &patch);
|
||||
|
@ -67,4 +69,4 @@ public:
|
|||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue