midiFileToRomData.cpp (3844B)
1 #include "midiFileToRomData.h" 2 3 #include "dsp56kEmu/logging.h" 4 5 #include "synthLib/midiToSysex.h" 6 7 namespace virusLib 8 { 9 bool MidiFileToRomData::load(const std::string& _filename) 10 { 11 std::vector<uint8_t> sysex; 12 13 if(!synthLib::MidiToSysex::readFile(sysex, _filename.c_str())) 14 return false; 15 16 return load(sysex); 17 } 18 19 bool MidiFileToRomData::load(const std::vector<uint8_t>& _fileData, bool _isMidiFileData/* = false*/) 20 { 21 std::vector<std::vector<uint8_t>> packets; 22 23 synthLib::MidiToSysex::splitMultipleSysex(packets, _fileData, _isMidiFileData); 24 25 return add(packets); 26 } 27 28 bool MidiFileToRomData::add(const std::vector<Packet>& _packets) 29 { 30 for (const auto& packet : _packets) 31 { 32 if(!add(packet)) 33 return false; 34 if(isComplete()) 35 return true; 36 } 37 return false; 38 } 39 40 bool MidiFileToRomData::add(const Packet& _packet) 41 { 42 if(isComplete()) 43 return isValid(); 44 45 if(_packet.size() < 11) 46 return isValid(); 47 48 const auto cmd = _packet[5]; 49 50 switch (cmd) 51 { 52 case 0x50: // Virus A 53 case 0x53: // Virus B OS 54 case 0x54: // Virus Rack Classic (B) 55 case 0x55: // Virus B Demo 56 case 0x57: // Virus C 57 case 0x58: // Virus Rack XL (C) 58 case 0x59: // Virus Classic Demo 59 { 60 const auto msb = _packet[6]; // packet number MSB 61 const auto lsb = _packet[7]; // packet number LSB 62 63 uint8_t checksum = 0; 64 for(size_t i=5; i<_packet.size()-2; ++i) 65 checksum += _packet[i]; 66 checksum &= 0x7f; 67 68 if(checksum != _packet[_packet.size()-2]) 69 { 70 LOG("Packet MSB " << static_cast<int>(msb) << " LSB " << static_cast<int>(lsb) << " is invalid, wrong checksum"); 71 m_valid = false; 72 return false; 73 } 74 75 if(!processPacket(_packet, msb, lsb)) 76 { 77 m_valid = false; 78 return false; 79 } 80 return isValid(); 81 } 82 default: 83 // skip unknown packets 84 return true; 85 } 86 } 87 88 bool MidiFileToRomData::setCompleted() 89 { 90 m_complete = true; 91 if(!toBinary(m_data)) 92 m_valid = false; 93 return isComplete(); 94 } 95 96 bool MidiFileToRomData::toBinary(std::vector<uint8_t>& _binary) const 97 { 98 if(!isComplete()) 99 return false; 100 101 for (const auto& p : m_packets) 102 { 103 // midi bytes in a sysex frame can only carry 7 bit, not 8. They've chosen the easy way that costs more storage 104 // They transfer only one nibble of a ROM byte in one midi byte to ensure that the most significant nibble is 105 // always zero. By concating two nibbles together we get one ROM byte 106 for(size_t s=8; s<p.size()-2; s += 2) 107 { 108 const uint8_t a = p[s]; 109 const uint8_t b = p[s+1]; 110 if(a > 0xf || b > 0xf) 111 { 112 LOG("Invalid data, high nibble must be 0"); 113 return false; 114 } 115 _binary.push_back(static_cast<uint8_t>(b << 4) | a); 116 } 117 } 118 return true; 119 } 120 bool MidiFileToRomData::processPacket(const Packet& _packet, uint8_t msb, uint8_t lsb) 121 { 122 // LOG("Got Packet " << static_cast<int>(msb) << " " << static_cast<int>(lsb) << ", size " << _packet.size()); 123 124 auto packetInvalid = [&]() 125 { 126 LOG("Packet invalid, expected packet index " << static_cast<int>(m_expectedMSB) << " " << static_cast<int>(m_expectedLSB) << " but got " << static_cast<int>(msb) << " " << static_cast<int>(lsb)); 127 return false; 128 }; 129 130 auto matchExpected = [&]() 131 { 132 return msb == m_expectedMSB && lsb == m_expectedLSB; 133 }; 134 135 if(msb == 127 && m_expectedLSB > 3) 136 { 137 if(m_expectedSector == 0xff) 138 { 139 m_firstSector = m_expectedSector = lsb; 140 } 141 142 if(lsb != m_expectedSector) 143 { 144 if(lsb == 127 || lsb == 126) 145 return setCompleted(); 146 return packetInvalid(); 147 } 148 m_expectedLSB = m_expectedMSB = 0; 149 ++m_expectedSector; 150 // addPacket(_packet); 151 return true; 152 } 153 154 if(!matchExpected()) 155 return packetInvalid(); 156 157 addPacket(_packet); 158 ++m_expectedLSB; 159 160 if(m_expectedLSB > 3 && msb != 127) 161 { 162 m_expectedLSB = 0; 163 ++m_expectedMSB; 164 } 165 return true; 166 } 167 }