diff options
-rw-r--r-- | utils/gen_adldata/file_formats/load_wopl.h | 11 | ||||
-rw-r--r-- | utils/gen_adldata/gen_adldata.cc | 6 | ||||
-rw-r--r-- | utils/gen_adldata/progs_cache.cpp | 173 | ||||
-rw-r--r-- | utils/gen_adldata/progs_cache.h | 121 |
4 files changed, 289 insertions, 22 deletions
diff --git a/utils/gen_adldata/file_formats/load_wopl.h b/utils/gen_adldata/file_formats/load_wopl.h index cd8765e..cef475f 100644 --- a/utils/gen_adldata/file_formats/load_wopl.h +++ b/utils/gen_adldata/file_formats/load_wopl.h @@ -18,7 +18,7 @@ enum class WOPL_Flags WOPL_RhythmModeMask = 0x38, }; -static bool LoadWopl(const char *fn, unsigned bank, const char *prefix) +static bool LoadWopl(BanksDump &db, const char *fn, unsigned bank, const char *prefix) { FILE *fp = std::fopen(fn, "rb"); if(!fp) @@ -27,6 +27,7 @@ static bool LoadWopl(const char *fn, unsigned bank, const char *prefix) std::fflush(stderr); return false; } + std::fseek(fp, 0, SEEK_END); std::vector<unsigned char> data(size_t(std::ftell(fp))); std::rewind(fp); @@ -63,6 +64,8 @@ static bool LoadWopl(const char *fn, unsigned bank, const char *prefix) setup.volumeModel = (int)data[0x12]; setup.scaleModulators = false; + size_t bankDb = (unsigned)db.initBank(bank, static_cast<uint_fast16_t>((static_cast<unsigned>(data[0x11]) << 8) | static_cast<unsigned>(data[0x12]))); + // Validate file format by size calculation if(version == 1) { @@ -98,12 +101,14 @@ static bool LoadWopl(const char *fn, unsigned bank, const char *prefix) percussion_offset = melodic_offset + (insSize * 128 * mbanks_count); - uint32_t root_offsets[2] = {melodic_offset, percussion_offset}; + //uint32_t root_sizes[2] = {mbanks_count, pbanks_count}; + uint32_t root_sizes[2] = {1, 1}; + uint32_t root_offsets[2] = {melodic_offset, percussion_offset}; for(size_t bset = 0; bset < 2; bset++) { bool is_percussion = (bset == 1); - for(uint32_t bankno = 0; bankno < 1; bankno++) // only first melodic bank (Until multi-banks support will be implemented) + for(uint32_t bankno = 0; bankno < root_sizes[bset]; bankno++) // only first melodic bank (Until multi-banks support will be implemented) { uint32_t bank_offset = root_offsets[bset] + (bankno * insSize * 128); diff --git a/utils/gen_adldata/gen_adldata.cc b/utils/gen_adldata/gen_adldata.cc index 7cb4528..1896c43 100644 --- a/utils/gen_adldata/gen_adldata.cc +++ b/utils/gen_adldata/gen_adldata.cc @@ -46,6 +46,8 @@ int main(int argc, char**argv) return 1; } + BanksDump db; + std::fprintf(outFile, "\ #include \"adldata.hh\"\n\ \n\ @@ -130,7 +132,7 @@ int main(int argc, char**argv) else if(format == "WOPL") { - if(!LoadWopl(filepath.c_str(), bank, prefix.c_str())) + if(!LoadWopl(db, filepath.c_str(), bank, prefix.c_str())) { std::fprintf(stderr, "Failed to load bank %u, file %s!\n", bank, filepath.c_str()); return 1; @@ -565,6 +567,8 @@ int main(int argc, char**argv) std::fclose(outFile); + db.exportBanks(std::string(outFile_s) + "x"); + std::printf("Generation of ADLMIDI data has been completed!\n"); std::fflush(stdout); } diff --git a/utils/gen_adldata/progs_cache.cpp b/utils/gen_adldata/progs_cache.cpp index 10124a8..df78026 100644 --- a/utils/gen_adldata/progs_cache.cpp +++ b/utils/gen_adldata/progs_cache.cpp @@ -1,4 +1,5 @@ #include "progs_cache.h" +#include <cstdio> InstrumentDataTab insdatatab; @@ -121,3 +122,175 @@ insdata MakeNoSoundIns() return { {0x00, 0x10, 0x07, 0x07, 0xF7, 0xF7, 0x00, 0x00, 0xFF, 0xFF, 0x00}, 0, false}; } + +size_t BanksDump::initBank(size_t bankId, uint_fast16_t bankSetup) +{ +#if 0 + assert(bankId <= banks.size()); + if(bankId >= banks.size()) + banks.emplace_back(); + BankEntry &b = banks[bankId]; +#else + banks.emplace_back(); + BankEntry &b = banks.back(); +#endif + b.bankId = bankId; + b.bankSetup = bankSetup; + return b.bankId; +} + +void BanksDump::addMidiBank(size_t bankId, bool percussion, BanksDump::MidiBank b) +{ + assert(bankId < banks.size()); + BankEntry &be = banks[bankId]; + + auto it = std::find(midiBanks.begin(), midiBanks.end(), b); + if(it == midiBanks.end()) + { + b.midiBankId = midiBanks.size(); + midiBanks.push_back(b); + } + else + { + b.midiBankId = it->midiBankId; + } + + if(percussion) + be.percussion.push_back(b.midiBankId); + else + be.melodic.push_back(b.midiBankId); +} + +void BanksDump::addInstrument(BanksDump::MidiBank &bank, size_t patchId, BanksDump::InstrumentEntry e, BanksDump::Operator *ops) +{ + assert(patchId < 128); + size_t opsCount = ((e.instFlags & InstrumentEntry::WOPL_Ins_4op) != 0 || + (e.instFlags & InstrumentEntry::WOPL_Ins_Pseudo4op) != 0) ? + 4 : 2; + for(size_t op = 0; op < opsCount; op++) + { + Operator o = ops[op]; + auto it = std::find(operators.begin(), operators.end(), o); + if(it == operators.end()) + { + o.opId = operators.size(); + e.ops[op] = static_cast<int_fast32_t>(o.opId); + operators.push_back(o); + } + else + { + e.ops[op] = static_cast<int_fast32_t>(it->opId); + } + } + + auto it = std::find(instruments.begin(), instruments.end(), e); + if(it == instruments.end()) + { + e.instId = instruments.size(); + instruments.push_back(e); + } + else + { + e.instId = it->instId; + } + bank.instruments[patchId] = static_cast<int_fast32_t>(e.instId); +} + +void BanksDump::exportBanks(const std::string &outPath, const std::string &headerName) +{ + FILE *out = std::fopen(outPath.c_str(), "w"); + + std::fprintf(out, "/**********************************************************\n" + " This file is generated by `gen_adldata` automatically\n" + " Don't edit it directly!\n" + " To modify content of this file, modify banks\n" + " and re-run the `gen_adldata` build step.\n" + "***********************************************************/\n\n" + "#include \"%s\"\n\n\n", headerName.c_str()); + + std::fprintf(out, "const size_t g_embeddedBanksCount = %zu;\n\n", banks.size()); + std::fprintf(out, "const BanksDump::BankEntry g_embeddedBanks[] =\n" + "{\n"); + for(const BankEntry &be : banks) + { + std::fprintf(out, " {\n"); + std::fprintf(out, " 0x%04lX, %zu, %zu,", + be.bankSetup, + be.melodic.size(), + be.percussion.size()); + // Melodic banks + std::fprintf(out, " { "); + for(const size_t &me : be.melodic) + std::fprintf(out, "%zu, ", me); + std::fprintf(out, " },\n"); + + // Percussive banks + std::fprintf(out, " { "); + for(const size_t &me : be.percussion) + std::fprintf(out, "%zu, ", me); + std::fprintf(out, " }\n"); + + std::fprintf(out, " },\n"); + } + + std::fprintf(out, "}\n\n"); + + + std::fprintf(out, "const BanksDump::MidiBank g_embeddedBanksMidi[] =\n" + "{\n"); + for(const MidiBank &be : midiBanks) + { + std::fprintf(out, " {\n"); + std::fprintf(out, " %u, %u,", be.msb, be.lsb); + + std::fprintf(out, " { "); + for(size_t i = 0; i < 128; i++) + std::fprintf(out, "%ld, ", be.instruments[i]); + std::fprintf(out, " },\n"); + + std::fprintf(out, " },\n"); + } + std::fprintf(out, "}\n\n"); + + + std::fprintf(out, "const BanksDump::InstrumentEntry g_embeddedBanksInstruments[] =\n" + "{\n"); + for(const InstrumentEntry &be : instruments) + { + size_t opsCount = ((be.instFlags & InstrumentEntry::WOPL_Ins_4op) != 0 || + (be.instFlags & InstrumentEntry::WOPL_Ins_Pseudo4op) != 0) ? 4 : 2; + std::fprintf(out, " {\n"); + std::fprintf(out, " %u, %u, %d, %u, %lu, %d, %lu, %lu, %lu, ", + be.noteOffset1, + be.noteOffset2, + be.midiVelocityOffset, + be.percussionKeyNumber, + be.instFlags, + be.secondVoiceDetune, + be.fbConn, + be.delay_on_ms, + be.delay_off_ms); + + if(opsCount == 4) + std::fprintf(out, "{%ld, %ld, %ld, %ld}", + be.ops[0], be.ops[1], be.ops[2], be.ops[3]); + else + std::fprintf(out, "{%ld, %ld}", + be.ops[0], be.ops[1]); + + std::fprintf(out, " },\n"); + } + std::fprintf(out, "}\n\n"); + + std::fprintf(out, "const BanksDump::Operator g_embeddedBanksOperators[] =\n" + "{\n"); + for(const Operator &be : operators) + { + std::fprintf(out, " { %08lX, %02lX },\n", + be.d_E862, + be.d_40); + } + std::fprintf(out, "}\n\n"); + + std::fclose(out); +} diff --git a/utils/gen_adldata/progs_cache.h b/utils/gen_adldata/progs_cache.h index a6614b3..d115ddc 100644 --- a/utils/gen_adldata/progs_cache.h +++ b/utils/gen_adldata/progs_cache.h @@ -12,6 +12,10 @@ #include <vector> #include <limits> #include <cmath> +#include <cstdint> + +#include <cassert> + struct insdata { @@ -130,7 +134,7 @@ struct BanksDump { struct BankEntry { - uint_fast32_t bankId; + uint_fast32_t bankId = 0; /* Global OPL flags */ typedef enum WOPLFileFlags @@ -166,21 +170,68 @@ struct BanksDump SETUP_CMF = 0x0201 }; - uint_fast16_t bankSetup; // 0xAABB, AA - OPL flags, BB - Volume model + uint_fast16_t bankSetup = SETUP_Generic; // 0xAABB, AA - OPL flags, BB - Volume model std::vector<size_t> melodic; std::vector<size_t> percussion; + + explicit BankEntry() = default; + + BankEntry(const BankEntry &o) + { + bankId = o.bankId; + bankSetup = o.bankSetup; + melodic = o.melodic; + percussion = o.percussion; + } + + BankEntry(const BankEntry &&o) + { + bankId = std::move(o.bankId); + bankSetup = std::move(o.bankSetup); + melodic = std::move(o.melodic); + percussion = std::move(o.percussion); + } }; struct MidiBank { - uint_fast32_t midiBankId; - uint_fast8_t msb, lsb; - int_fast32_t instruments[128]; + uint_fast32_t midiBankId = 0; + uint_fast8_t msb = 0, lsb = 0; + int_fast32_t instruments[128]; + + MidiBank() + { + for(size_t i = 0; i < 128; i++) + instruments[i] = -1; + } + + MidiBank(const MidiBank &o) + { + midiBankId = 0; + msb = 0; + lsb = 0; + std::memcpy(instruments, o.instruments, sizeof(int_fast32_t) * 128); + } + + bool operator==(const MidiBank &o) + { + if(msb != o.msb) + return false; + if(lsb != o.lsb) + return false; + if(std::memcmp(instruments, o.instruments, sizeof(int_fast32_t) * 128) != 0) + return false; + return true; + } + bool operator!=(const MidiBank &o) + { + return !operator==(o); + } }; struct InstrumentEntry { - uint_fast32_t instId; + uint_fast32_t instId = 0; typedef enum WOPL_InstrumentFlags { @@ -214,34 +265,68 @@ struct BanksDump WOPL_RM_HiHat = 0x28 } WOPL_RhythmMode; - uint_fast8_t noteOffset1; - uint_fast8_t noteOffset2; - int_fast8_t midiVelocityOffset; - uint_fast8_t percussionKeyNumber; - uint_fast32_t instFlags; - double secondVoiceDetune; + uint_fast8_t noteOffset1 = 0; + uint_fast8_t noteOffset2 = 0; + int_fast8_t midiVelocityOffset = 0; + uint_fast8_t percussionKeyNumber = 0; + uint_fast32_t instFlags = 0; + int_fast8_t secondVoiceDetune = 0; /* 2op: modulator1, carrier1, feedback1 2vo: modulator1, carrier1, modulator2, carrier2, feedback(1+2) 4op: modulator1, carrier1, modulator2, carrier2, feedback1 */ //! Contains FeedBack-Connection for both operators 0xBBAA - AA - first, BB - second - int16_t fbConn; - size_t ops[5] = {-1, -1, -1, -1, -1}; - int64_t delay_on_ms; - int64_t delay_off_ms; + int_fast16_t fbConn = 0; + int_fast64_t delay_on_ms = 0; + int_fast64_t delay_off_ms = 0; + int_fast32_t ops[5] = {-1, -1, -1, -1, -1}; + + bool operator==(const InstrumentEntry &o) + { + return ( + (noteOffset1 == o.noteOffset1) && + (noteOffset2 == o.noteOffset2) && + (midiVelocityOffset == o.midiVelocityOffset) && + (percussionKeyNumber == o.percussionKeyNumber) && + (instFlags == o.instFlags) && + (secondVoiceDetune == o.secondVoiceDetune) && + (fbConn == o.fbConn) && + (delay_on_ms == o.delay_on_ms) && + (delay_off_ms == o.delay_off_ms) && + (std::memcmp(ops, o.ops, sizeof(int_fast32_t) * 5) == 0) + ); + } + bool operator!=(const InstrumentEntry &o) + { + return !operator==(o); + } }; struct Operator { - uint_fast32_t d_E862; - uint_fast32_t d_40; + uint_fast32_t opId = 0; + uint_fast32_t d_E862 = 0; + uint_fast32_t d_40 = 0; + bool operator==(const Operator &o) + { + return ((d_E862 == o.d_E862) && (d_40 == o.d_40)); + } + bool operator!=(const Operator &o) + { + return !operator==(o); + } }; std::vector<BankEntry> banks; std::vector<MidiBank> midiBanks; std::vector<InstrumentEntry> instruments; std::vector<Operator> operators; + + size_t initBank(size_t bankId, uint_fast16_t bankSetup); + void addMidiBank(size_t bankId, bool percussion, MidiBank b); + void addInstrument(MidiBank &bank, size_t patchId, InstrumentEntry e, Operator *ops); + void exportBanks(const std::string &outPath, const std::string &headerName = "adlmidi_db.h"); }; |