gearmulator

Emulation of classic VA synths of the late 90s/2000s that are based on Motorola 56300 family DSPs
Log | Files | Refs | Submodules | README | LICENSE

commit 899cc9836ac454e7409f06dcccb8d4afad3a8441
parent 985e8061d7fd80fb547d95e9d73bfcf7ecba1685
Author: dsp56300 <dsp56300@users.noreply.github.com>
Date:   Tue, 23 Apr 2024 19:39:14 +0200

add model detection, also fixes VB OS 5.4 no longer working

Diffstat:
Msource/virusLib/romfile.cpp | 13+++++--------
Msource/virusLib/romfile.h | 2+-
Msource/virusLib/romloader.cpp | 59++++++++++++++++++++++++++++++++++++++++++++++++++++++++---
Msource/virusLib/romloader.h | 2++
4 files changed, 64 insertions(+), 12 deletions(-)

diff --git a/source/virusLib/romfile.cpp b/source/virusLib/romfile.cpp @@ -53,7 +53,7 @@ bool ROMFile::initialize() dsp.reset(new imemstream(fw.DSP)); } #endif - const auto chunks = readChunks(*dsp, m_model); + const auto chunks = readChunks(*dsp); if (chunks.empty()) return false; @@ -185,7 +185,7 @@ uint32_t ROMFile::getRomBankCount(const DeviceModel _model) } } -std::vector<ROMFile::Chunk> ROMFile::readChunks(std::istream& _file, const DeviceModel _wantedTIModel) +std::vector<ROMFile::Chunk> ROMFile::readChunks(std::istream& _file) const { _file.seekg(0, std::ios_base::end); const auto fileSize = _file.tellg(); @@ -195,14 +195,14 @@ std::vector<ROMFile::Chunk> ROMFile::readChunks(std::istream& _file, const Devic if(fileSize == getRomSizeModelD()) { - m_model = _wantedTIModel; + assert(isTIFamily()); offset = 0x70000; lastChunkId = 14; } else if (fileSize == getRomSizeModelABC() || fileSize == getRomSizeModelABC()/2) // the latter is a ROM without presets { // ABC - m_model = DeviceModel::C; + assert(isABCFamily(m_model)); offset = 0x18000; lastChunkId = 4; } @@ -227,11 +227,8 @@ std::vector<ROMFile::Chunk> ROMFile::readChunks(std::istream& _file, const Devic _file.read(reinterpret_cast<char*>(&chunk.size1), 1); _file.read(reinterpret_cast<char*>(&chunk.size2), 1); - if(i == 0 && chunk.chunk_id == 3 && lastChunkId == 4) // Virus A has one chunk less - { - m_model = DeviceModel::A; + if(i == 0 && chunk.chunk_id == 3 && lastChunkId == 4) // Virus A and old Virus B OSs have one chunk less lastChunkId = 3; - } if(chunk.chunk_id != lastChunkId - i) return {}; diff --git a/source/virusLib/romfile.h b/source/virusLib/romfile.h @@ -118,7 +118,7 @@ public: const auto& getHash() const { return m_romDataHash; } private: - std::vector<Chunk> readChunks(std::istream& _file, DeviceModel _wantedTIModel); + std::vector<Chunk> readChunks(std::istream& _file) const; bool loadPresetFiles(); bool loadPresetFile(std::istream& _file, DeviceModel _model); diff --git a/source/virusLib/romloader.cpp b/source/virusLib/romloader.cpp @@ -1,5 +1,7 @@ #include "romloader.h" +#include <algorithm> + #include "midiFileToRomData.h" #include "../synthLib/os.h" @@ -144,6 +146,48 @@ namespace virusLib return data; } + DeviceModel ROMLoader::detectModel(const std::vector<uint8_t>& _data) + { + // examples + // A: (C)ACCESS [08-20-2001-16:58:54][v280g] + // B: (C)ACCESS [12-23-2003-14:43:27][VB_490T] + // C: (C)ACCESS [11-10-2003-12:15:42][vc_650b] + + const std::string key = "(C)ACCESS ["; + const auto result = std::search(_data.begin(), _data.end(), std::begin(key), std::end(key)); + if(result == _data.end()) + return DeviceModel::Invalid; + + const auto bracketOpen = std::find(result+static_cast<int32_t>(key.size())+1, _data.end(), '['); + if(bracketOpen == _data.end()) + return DeviceModel::Invalid; + + const auto bracketClose = std::find(bracketOpen+1, _data.end(), ']'); + if(bracketClose == _data.end()) + return DeviceModel::Invalid; + + const auto versionString = synthLib::lowercase(std::string(bracketOpen+1, bracketClose-1)); + + const auto test = [&versionString](const char* _key) + { + return versionString.find(_key) == 0; + }; + + if(test("vb") || test("vcl") || test("vrt")) + return DeviceModel::B; + + if(test("vc") || test("vr_6")) + return DeviceModel::C; + + if(test("vr")) + return DeviceModel::B; + + if(test("v2")) + return DeviceModel::A; + + return DeviceModel::Invalid; + } + std::vector<ROMFile> ROMLoader::initializeRoms(const std::vector<std::string>& _files, const DeviceModel _model) { if(_files.empty()) @@ -180,10 +224,19 @@ namespace virusLib if(fd.type == MidiPresets) continue; + auto model = detectModel(fd.data); + + if(model == DeviceModel::Invalid) + { + assert(false && "retry model detection for debugging purposes below"); + detectModel(fd.data); + model = _model; // Must be based on DSP 56362 or hell breaks loose + } + if(fd.type == BinaryRom) { // load as-is - auto& rom = roms.emplace_back(fd.data, fd.filename, _model); + auto& rom = roms.emplace_back(fd.data, fd.filename, model); if(!rom.isValid()) roms.pop_back(); } @@ -193,7 +246,7 @@ namespace virusLib if(presets.empty()) { // none available, use without presets - auto& rom = roms.emplace_back(fd.data, fd.filename, _model); + auto& rom = roms.emplace_back(fd.data, fd.filename, model); if(!rom.isValid()) roms.pop_back(); } @@ -204,7 +257,7 @@ namespace virusLib auto data = fd.data; data.insert(data.end(), p.data.begin(), p.data.end()); - auto& rom = roms.emplace_back(data, fd.filename, _model); + auto& rom = roms.emplace_back(data, fd.filename, model); if(!rom.isValid()) roms.pop_back(); else if(presets.size() > 1) diff --git a/source/virusLib/romloader.h b/source/virusLib/romloader.h @@ -36,6 +36,8 @@ namespace virusLib static FileData loadFile(const std::string& _name); + static DeviceModel detectModel(const std::vector<uint8_t>& _data); + static std::vector<ROMFile> initializeRoms(const std::vector<std::string>& _files, DeviceModel _model); }; }