commit 57312d1113faa1e8bf6d44de454b0b5803808803
parent f7c0fc41f1f618fc3f342f67e80104010d06f557
Author: dsp56300 <dsp56300@users.noreply.github.com>
Date: Sat, 18 May 2024 12:54:40 +0200
[Osirus] [OsTIrus] [Imp] added support for .vtibackup files
Diffstat:
3 files changed, 59 insertions(+), 0 deletions(-)
diff --git a/source/virusJucePlugin/PatchManager.cpp b/source/virusJucePlugin/PatchManager.cpp
@@ -270,6 +270,9 @@ namespace genericVirusUI
if (virusLib::Device::parsePowercorePreset(_results, _data))
return true;
+ if(virusLib::Device::parseVTIBackup(_results, _data))
+ return true;
+
if(!synthLib::MidiToSysex::extractSysexFromData(_results, _data))
return false;
diff --git a/source/virusLib/device.cpp b/source/virusLib/device.cpp
@@ -342,6 +342,61 @@ namespace virusLib
return !_sysexPresets.empty();
}
+ bool Device::parseVTIBackup(std::vector<std::vector<uint8_t>>& _sysexPresets, const std::vector<uint8_t>& _data)
+ {
+ if(_data.size() < 512)
+ return false;
+
+ // first 11 bytes are the serial number. Check if they're all ASCII
+ for(size_t i=0; i<11; ++i)
+ {
+ if(_data[i] < 32 || _data[i] > 127)
+ return false;
+ }
+
+ constexpr size_t presetSize = sizeof(Microcontroller::TPreset);
+ Microcontroller::TPreset preset;
+
+ constexpr uint32_t maxPresets = (4 + 26) * 128; // 4x RAM banks, 26x ROM banks, 128 patches per bank
+
+ uint32_t presetIdx = 0;
+
+ // presets start at $20
+ // They are "raw" presets, i.e. 512 bytes or preset data each
+ // The sysex packaging is missing, i.e. the single dump header, the checksums and the sysex terminator
+ for(size_t i=0x20; i<_data.size() - presetSize; i += presetSize)
+ {
+ memcpy(preset.data(), &_data[i], presetSize);
+
+ const auto name = ROMFile::getSingleName(preset);
+
+ if(name.size() != 10)
+ break;
+
+ auto& sysex = _sysexPresets.emplace_back(std::vector<uint8_t>{
+ 0xf0, 0x00, 0x20, 0x33, 0x01, OMNI_DEVICE_ID, DUMP_SINGLE,
+ static_cast<uint8_t>((presetIdx >> 7) & 0x7f),
+ static_cast<uint8_t>(presetIdx & 0x7f)});
+
+ sysex.reserve(9 + 256 + 1 + 256 + 2); // header, 256 preset bytes, 1st checksum, 256 preset bytes, 2nd checksum, EOX
+
+ for(size_t j=0; j<256; ++j)
+ sysex.push_back(preset[j]);
+ sysex.push_back(Microcontroller::calcChecksum(sysex, 5));
+ for(size_t j=256; j<512; ++j)
+ sysex.push_back(preset[j]);
+ sysex.push_back(Microcontroller::calcChecksum(sysex, 5));
+ sysex.push_back(0xf7);
+
+ ++presetIdx;
+
+ if(presetIdx == maxPresets)
+ break;
+ }
+
+ return true;
+ }
+
uint32_t Device::getInternalLatencyMidiToOutput() const
{
// Note that this is an average value, midi latency drifts in a range of roughly +/- 61 samples
diff --git a/source/virusLib/device.h b/source/virusLib/device.h
@@ -39,6 +39,7 @@ namespace virusLib
static bool find4CC(uint32_t& _offset, const std::vector<uint8_t>& _data, const std::string_view& _4cc);
static bool parseTIcontrolPreset(std::vector<synthLib::SMidiEvent>& _events, const std::vector<uint8_t>& _state);
static bool parsePowercorePreset(std::vector<std::vector<uint8_t>>& _sysexPresets, const std::vector<uint8_t>& _data);
+ static bool parseVTIBackup(std::vector<std::vector<uint8_t>>& _sysexPresets, const std::vector<uint8_t>& _data);
uint32_t getInternalLatencyMidiToOutput() const override;
uint32_t getInternalLatencyInputToOutput() const override;