diff --git a/src/engine/fileOpsIns.cpp b/src/engine/fileOpsIns.cpp index 6a163d7c..4fe9be3c 100644 --- a/src/engine/fileOpsIns.cpp +++ b/src/engine/fileOpsIns.cpp @@ -1081,8 +1081,10 @@ void DivEngine::loadGYB(SafeReader& reader, std::vector& ret, St ins->fm.alg = tmp & 0x3; ins->fm.fb = ((tmp>>3) & 0x3); - if (!readRegB4) { // PAN - reader.readC(); // skip as not kept in Furnace instrument + if (!readRegB4) { // PAN / PMS / AMS + tmp = reader.readC(); + ins->fm.fms = tmp & 0x7; + ins->fm.ams = ((tmp>>4) & 0x3); } return ins; }; @@ -1098,6 +1100,10 @@ void DivEngine::loadGYB(SafeReader& reader, std::vector& ret, St insMelodyCount = reader.readC(); insDrumCount = reader.readC(); + if (insMelodyCount > 128 || insDrumCount > 128) { + throw std::invalid_argument(fmt::sprintf("GYBv1/2 patch count is out of bounds.")); + } + if (!reader.seek(0x100, SEEK_CUR)) { // skip MIDI instrument mapping throw EndOfFileException(&reader, reader.tell() + 0x100); } @@ -1108,27 +1114,24 @@ void DivEngine::loadGYB(SafeReader& reader, std::vector& ret, St // Instrument data for (int i = 0; i < (insMelodyCount+insDrumCount); ++i) { - // Note: melody and drum patches are interleaved... + // TODO determine if a patch is 'empty' -> ignore and move on + bool isDrum = (i >= insMelodyCount); DivInstrument* newIns = readInstrument(reader, (version==2)); reader.readC(); // skip transpose if (version == 2) { reader.readC(); // skip padding } + + uint8_t nameLen = reader.readC(); + String insName = (nameLen > 0) ? reader.readString(nameLen) : fmt::sprintf("%s [%d]", stripPath, readCount); + + newIns->name = insName; insList.push_back(newIns); ++readCount; } - // Instrument name - for (int i = 0; i < (insMelodyCount+insDrumCount); ++i) { - uint8_t nameLen = reader.readC(); - String insName = (nameLen > 0) ? reader.readString(nameLen) : fmt::sprintf("%s [%d]", stripPath, readCount); + // Map to note assignment currently not supported. - // TODO determine if a patch is 'empty' -> ignore and move on - if (insList[i] == NULL) { - continue; - } - insList[i]->name = insName; - } } else { // GYBv3+ reader.readC(); // skip LFO speed (chip-global) uint32_t fileSize = reader.readI(); @@ -1175,6 +1178,12 @@ void DivEngine::loadGYB(SafeReader& reader, std::vector& ret, St delete insList[i]; } is_failed = true; + + } catch (std::invalid_argument& e) { + lastError = fmt::sprintf("Invalid value found in patch file. %s", e.what()); + logE("Invalid value found in patch file."); + logE(e.what()); + is_failed = true; } if (!is_failed) {