aboutsummaryrefslogtreecommitdiff
path: root/utils/gen_adldata/file_formats
diff options
context:
space:
mode:
Diffstat (limited to 'utils/gen_adldata/file_formats')
-rw-r--r--utils/gen_adldata/file_formats/common.h28
-rw-r--r--utils/gen_adldata/file_formats/load_ail.h102
-rw-r--r--utils/gen_adldata/file_formats/load_bisqwit.h53
-rw-r--r--utils/gen_adldata/file_formats/load_bnk.h152
-rw-r--r--utils/gen_adldata/file_formats/load_bnk2.h102
-rw-r--r--utils/gen_adldata/file_formats/load_ibk.h72
-rw-r--r--utils/gen_adldata/file_formats/load_jv.h105
-rw-r--r--utils/gen_adldata/file_formats/load_op2.h148
-rw-r--r--utils/gen_adldata/file_formats/load_tmb.h68
-rw-r--r--utils/gen_adldata/file_formats/load_wopl.h265
10 files changed, 1095 insertions, 0 deletions
diff --git a/utils/gen_adldata/file_formats/common.h b/utils/gen_adldata/file_formats/common.h
new file mode 100644
index 0000000..d06059e
--- /dev/null
+++ b/utils/gen_adldata/file_formats/common.h
@@ -0,0 +1,28 @@
+#ifndef COMMON_H
+#define COMMON_H
+
+#include <stdint.h>
+
+inline uint16_t toUint16BE(const uint8_t *arr)
+{
+ uint16_t num = arr[1];
+ num |= ((arr[0] << 8) & 0xFF00);
+ return num;
+}
+
+inline int16_t toSint16BE(const uint8_t *arr)
+{
+ int16_t num = *reinterpret_cast<const int8_t *>(&arr[0]);
+ num *= 1 << 8;
+ num |= arr[1];
+ return num;
+}
+
+inline uint16_t toUint16LE(const uint8_t *arr)
+{
+ uint16_t num = arr[0];
+ num |= ((arr[1] << 8) & 0xFF00);
+ return num;
+}
+
+#endif // COMMON_H
diff --git a/utils/gen_adldata/file_formats/load_ail.h b/utils/gen_adldata/file_formats/load_ail.h
new file mode 100644
index 0000000..4c6c482
--- /dev/null
+++ b/utils/gen_adldata/file_formats/load_ail.h
@@ -0,0 +1,102 @@
+#ifndef LOAD_AIL_H
+#define LOAD_AIL_H
+
+#include "../progs_cache.h"
+#include "../midi_inst_list.h"
+
+static bool LoadMiles(const char *fn, unsigned bank, const char *prefix)
+{
+ #ifdef HARD_BANKS
+ writeIni("AIL", fn, prefix, bank, INI_Both);
+ #endif
+ FILE *fp = std::fopen(fn, "rb");
+ if(!fp)
+ return false;
+ std::fseek(fp, 0, SEEK_END);
+ std::vector<unsigned char> data(size_t(std::ftell(fp)));
+ std::rewind(fp);
+ if(std::fread(&data[0], 1, data.size(), fp) != data.size())
+ {
+ std::fclose(fp);
+ return false;
+ }
+ std::fclose(fp);
+
+ for(unsigned a = 0; a < 2000; ++a)
+ {
+ unsigned gm_patch = data[a * 6 + 0];
+ unsigned gm_bank = data[a * 6 + 1];
+ unsigned offset = *(unsigned *)&data[a * 6 + 2];
+
+ if(gm_patch == 0xFF)
+ break;
+
+ int gmno = gm_bank == 0x7F ? int(gm_patch + 0x80) : int(gm_patch);
+ int midi_index = gmno < 128 ? gmno
+ : gmno < 128 + 35 ? -1
+ : gmno < 128 + 88 ? gmno - 35
+ : -1;
+ unsigned length = data[offset] + data[offset + 1] * 256;
+ signed char notenum = ((signed char)data[offset + 2]);
+
+ /*printf("%02X %02X %08X ", gmnumber,gmnumber2, offset);
+ for(unsigned b=0; b<length; ++b)
+ {
+ if(b > 3 && (b-3)%11 == 0) printf("\n ");
+ printf("%02X ", data[offset+b]);
+ }
+ printf("\n");*/
+
+ if(gm_bank != 0 && gm_bank != 0x7F)
+ continue;
+
+ char name2[512];
+ sprintf(name2, "%s%c%u", prefix,
+ (gmno < 128 ? 'M' : 'P'), gmno & 127);
+
+ insdata tmp[200];
+
+ const unsigned inscount = (length - 3) / 11;
+ for(unsigned i = 0; i < inscount; ++i)
+ {
+ unsigned o = offset + 3 + i * 11;
+ tmp[i].finetune = (gmno < 128 && i == 0) ? notenum : 0;
+ tmp[i].diff = false;
+ tmp[i].data[0] = data[o + 0]; // 20
+ tmp[i].data[8] = data[o + 1]; // 40 (vol)
+ tmp[i].data[2] = data[o + 2]; // 60
+ tmp[i].data[4] = data[o + 3]; // 80
+ tmp[i].data[6] = data[o + 4]; // E0
+ tmp[i].data[1] = data[o + 6]; // 23
+ tmp[i].data[9] = data[o + 7]; // 43 (vol)
+ tmp[i].data[3] = data[o + 8]; // 63
+ tmp[i].data[5] = data[o + 9]; // 83
+ tmp[i].data[7] = data[o + 10]; // E3
+
+ unsigned fb_c = data[offset + 3 + 5];
+ tmp[i].data[10] = uint8_t(fb_c);
+ if(i == 1)
+ {
+ tmp[0].data[10] = fb_c & 0x0F;
+ tmp[1].data[10] = uint8_t((fb_c & 0x0E) | (fb_c >> 7));
+ }
+ }
+ if(inscount == 1)
+ tmp[1] = tmp[0];
+
+ if(inscount <= 2)
+ {
+ struct ins tmp2;
+ tmp2.notenum = gmno < 128 ? 0 : (unsigned char)notenum;
+ tmp2.pseudo4op = false;
+ tmp2.voice2_fine_tune = 0.0;
+ std::string name;
+ if(midi_index >= 0) name = std::string(1, '\377') + MidiInsName[midi_index];
+ size_t resno = InsertIns(tmp[0], tmp[1], tmp2, name, name2);
+ SetBank(bank, (unsigned int)gmno, resno);
+ }
+ }
+ return true;
+}
+
+#endif // LOAD_AIL_H
diff --git a/utils/gen_adldata/file_formats/load_bisqwit.h b/utils/gen_adldata/file_formats/load_bisqwit.h
new file mode 100644
index 0000000..4928efa
--- /dev/null
+++ b/utils/gen_adldata/file_formats/load_bisqwit.h
@@ -0,0 +1,53 @@
+#ifndef LOAD_BISQWIT_H
+#define LOAD_BISQWIT_H
+
+#include "../progs_cache.h"
+#include "../midi_inst_list.h"
+
+static bool LoadBisqwit(const char *fn, unsigned bank, const char *prefix)
+{
+ #ifdef HARD_BANKS
+ writeIni("Bisqwit", fn, prefix, bank, INI_Both);
+ #endif
+ FILE *fp = std::fopen(fn, "rb");
+ if(!fp)
+ return false;
+
+ for(uint32_t a = 0; a < 256; ++a)
+ {
+ //unsigned offset = a * 25;
+ uint32_t gmno = a;
+ int32_t midi_index = gmno < 128 ? int32_t(gmno)
+ : gmno < 128 + 35 ? -1
+ : gmno < 128 + 88 ? int32_t(gmno - 35)
+ : -1;
+
+ struct ins tmp2;
+ tmp2.notenum = (uint8_t)std::fgetc(fp);
+ tmp2.pseudo4op = false;
+ tmp2.voice2_fine_tune = 0.0;
+
+ insdata tmp[2];
+ for(int side = 0; side < 2; ++side)
+ {
+ tmp[side].finetune = (int8_t)std::fgetc(fp);
+ tmp[side].diff = false;
+ if(std::fread(tmp[side].data, 1, 11, fp) != 11)
+ return false;
+ }
+
+ std::string name;
+ if(midi_index >= 0) name = std::string(1, '\377') + MidiInsName[midi_index];
+
+ char name2[512];
+ sprintf(name2, "%s%c%u", prefix,
+ (gmno < 128 ? 'M' : 'P'), gmno & 127);
+
+ size_t resno = InsertIns(tmp[0], tmp[1], tmp2, name, name2);
+ SetBank(bank, gmno, resno);
+ }
+ std::fclose(fp);
+ return true;
+}
+
+#endif // LOAD_BISQWIT_H
diff --git a/utils/gen_adldata/file_formats/load_bnk.h b/utils/gen_adldata/file_formats/load_bnk.h
new file mode 100644
index 0000000..79ce5f5
--- /dev/null
+++ b/utils/gen_adldata/file_formats/load_bnk.h
@@ -0,0 +1,152 @@
+#ifndef LOAD_BNK_H
+#define LOAD_BNK_H
+
+#include "../progs_cache.h"
+
+#include <cstdio>
+#include <cstdint>
+#include <string>
+
+static bool LoadBNK(const char *fn, unsigned bank, const char *prefix, bool is_fat, bool percussive)
+{
+ #ifdef HARD_BANKS
+ writeIni("HMI", fn, prefix, bank, percussive ? INI_Drums : INI_Melodic);
+ #endif
+ FILE *fp = std::fopen(fn, "rb");
+ if(!fp)
+ return false;
+ std::fseek(fp, 0, SEEK_END);
+ std::vector<unsigned char> data(size_t(std::ftell(fp)));
+ std::rewind(fp);
+ if(std::fread(&data[0], 1, data.size(), fp) != data.size())
+ {
+ std::fclose(fp);
+ return false;
+ }
+ std::fclose(fp);
+
+ /*printf("%s:\n", fn);*/
+ //unsigned short version = *(short*)&data[0]; // major,minor (2 bytes)
+ // "ADLIB-" (6 bytes)
+ uint16_t entries_used = *(uint16_t *)&data[8]; // entries used
+ //unsigned short total_entries = *(short*)&data[10]; // total entries
+ unsigned name_offset = *(unsigned *)&data[12]; // name_offset
+ unsigned data_offset = *(unsigned *)&data[16]; // data_offset
+ // 16..23: 8 byte sof filler
+ /*printf("version=%u %u %u %u %u\n",
+ version, entries_used,total_entries,name_offset,data_offset);*/
+
+ for(unsigned n = 0; n < entries_used; ++n)
+ {
+ const size_t offset1 = name_offset + n * 12;
+
+ unsigned short data_index = data[offset1 + 0] + data[offset1 + 1] * 256;
+ unsigned char usage_flag = data[offset1 + 2];
+ std::string name;
+ for(unsigned p = 0; p < 9; ++p)
+ {
+ if(data[offset1 + 3 + p] == '\0') break;
+ name += char(data[offset1 + 3 + p]);
+ }
+
+ const size_t offset2 = data_offset + data_index * 30;
+ //const unsigned char mode = data[offset2+0];
+ const unsigned char voice_num = data[offset2 + 1];
+ const unsigned char *op1 = &data[offset2 + 2]; // 13 bytes
+ const unsigned char *op2 = &data[offset2 + 15];
+ const unsigned char waveform_mod = data[offset2 + 28];
+ const unsigned char waveform_car = data[offset2 + 29];
+
+ /*printf("%5d %3d %8s mode=%02X voice=%02X: ", data_index,usage_flag, name.c_str(),
+ mode,voice_num);*/
+
+ int gmno = int(is_fat
+ ? ((n & 127) + percussive * 128)
+ : (n + percussive * 128));
+
+ if(is_fat && percussive)
+ {
+ if(name[2] == 'O'
+ || name[2] == 'S')
+ {
+ gmno = 128 + std::stoi(name.substr(3));
+ }
+ }
+
+ char name2[512];
+ if(is_fat)
+ sprintf(name2, "%s%c%u", prefix, percussive ? 'P' : 'M', gmno & 127);
+ else
+ sprintf(name2, "%s%u", prefix, n);
+
+ insdata tmp;
+ tmp.data[0] = uint8_t(
+ (op1[ 9] << 7) // TREMOLO FLAG
+ + (op1[10] << 6) // VIBRATO FLAG
+ + (op1[ 5] << 5) // SUSTAIN FLAG
+ + (op1[11] << 4) // SCALING FLAG
+ + op1[ 1]); // FREQMUL
+
+ tmp.data[1] = uint8_t((op2[ 9] << 7)
+ + (op2[10] << 6)
+ + (op2[ 5] << 5)
+ + (op2[11] << 4)
+ + op2[ 1]);
+ tmp.data[2] = op1[3] * 0x10 + op1[6]; // ATTACK, DECAY
+ tmp.data[3] = op2[3] * 0x10 + op2[6];
+ tmp.data[4] = op1[4] * 0x10 + op1[7]; // SUSTAIN, RELEASE
+ tmp.data[5] = op2[4] * 0x10 + op2[7];
+ tmp.data[6] = waveform_mod;
+ tmp.data[7] = waveform_car;
+ tmp.data[8] = op1[0] * 0x40 + op1[8]; // KSL , LEVEL
+ tmp.data[9] = op2[0] * 0x40 + op2[8]; // KSL , LEVEL
+ tmp.data[10] = op1[2] * 2 + op1[12]; // FEEDBACK, ADDITIVEFLAG
+ tmp.finetune = 0;
+ tmp.diff = false;
+ // Note: op2[2] and op2[12] are unused and contain garbage.
+ ins tmp2;
+ tmp2.notenum = is_fat ? voice_num : (percussive ? usage_flag : 0);
+ tmp2.pseudo4op = false;
+ tmp2.voice2_fine_tune = 0.0;
+
+ if(is_fat) tmp.data[10] ^= 1;
+
+ size_t resno = InsertIns(tmp, tmp, tmp2, std::string(1, '\377') + name, name2);
+
+ if(!is_fat)
+ {
+ SetBank(bank, (unsigned int)gmno, resno);
+ }
+ else
+ {
+ if(name[2] == 'O' || name[1] == 'M') SetBank(bank + 0, (unsigned int)gmno, resno);
+ if(name[2] == 'S' || name[1] == 'M') SetBank(bank + 1, (unsigned int)gmno, resno);
+ }
+
+ /*
+ for(unsigned p=0; p<30; ++p)
+ {
+ unsigned char value = data[offset2+p];
+ if(value > maxvalues[p]) maxvalues[p] = value;
+
+ #define dot(maxval) if(value<=maxval) printf("."); else printf("?[%u]%X",p,value);
+
+ {
+ //if(p==6 || p==7 || p==19||p==20) value=15-value;
+
+ if(p==4 || p==10 || p==17 || p==23)// || p==25)
+ printf(" %2X", value);
+ else
+ printf(" %X", value);
+ }
+ nl:;
+ //if(p == 12) printf("\n%*s", 22, "");
+ //if(p == 25) printf("\n%*s", 22, "");
+ }
+ printf("\n");
+ */
+ }
+ return true;
+}
+
+#endif // LOAD_BNK_H
diff --git a/utils/gen_adldata/file_formats/load_bnk2.h b/utils/gen_adldata/file_formats/load_bnk2.h
new file mode 100644
index 0000000..202402c
--- /dev/null
+++ b/utils/gen_adldata/file_formats/load_bnk2.h
@@ -0,0 +1,102 @@
+#ifndef LOAD_BNK2_H
+#define LOAD_BNK2_H
+
+#include "../progs_cache.h"
+
+static bool LoadBNK2(const char *fn, unsigned bank, const char *prefix,
+ const std::string &melo_filter,
+ const std::string &perc_filter)
+{
+ #ifdef HARD_BANKS
+ writeIni("AdLibGold", fn, prefix, bank, INI_Both, melo_filter.c_str(), perc_filter.c_str());
+ #endif
+ FILE *fp = std::fopen(fn, "rb");
+ if(!fp)
+ return false;
+ std::fseek(fp, 0, SEEK_END);
+ std::vector<unsigned char> data(size_t(std::ftell(fp)));
+ std::rewind(fp);
+ if(std::fread(&data[0], 1, data.size(), fp) != data.size())
+ {
+ std::fclose(fp);
+ return false;
+ }
+ std::fclose(fp);
+
+ unsigned short ins_entries = *(unsigned short *)&data[28 + 2 + 10];
+ unsigned char *records = &data[48];
+
+ for(unsigned n = 0; n < ins_entries; ++n)
+ {
+ const size_t offset1 = n * 28;
+ int used = records[offset1 + 15];
+ //int attrib = *(int*)&records[offset1 + 16];
+ int offset2 = *(int *)&records[offset1 + 20];
+ if(used == 0) continue;
+
+ std::string name;
+ for(unsigned p = 0; p < 12; ++p)
+ {
+ if(records[offset1 + 3 + p] == '\0') break;
+ name += char(records[offset1 + 3 + p]);
+ }
+
+ int gmno = 0;
+ if(name.substr(0, melo_filter.size()) == melo_filter)
+ gmno = std::stoi(name.substr(melo_filter.size()));
+ else if(name.substr(0, perc_filter.size()) == perc_filter)
+ gmno = std::stoi(name.substr(perc_filter.size())) + 128;
+ else
+ continue;
+
+ const unsigned char *insdata = &data[size_t(offset2)];
+ const unsigned char *ops[4] = { insdata + 0, insdata + 6, insdata + 12, insdata + 18 };
+ unsigned char C4xxxFFFC = insdata[24];
+ unsigned char xxP24NNN = insdata[25];
+ unsigned char TTTTTTTT = insdata[26];
+ //unsigned char xxxxxxxx = insdata[27];
+
+ char name2[512];
+ sprintf(name2, "%s%c%u", prefix, (gmno & 128) ? 'P' : 'M', gmno & 127);
+
+ struct insdata tmp[2];
+ for(unsigned a = 0; a < 2; ++a)
+ {
+ tmp[a].data[0] = ops[a * 2 + 0][0];
+ tmp[a].data[1] = ops[a * 2 + 1][0];
+ tmp[a].data[2] = ops[a * 2 + 0][2];
+ tmp[a].data[3] = ops[a * 2 + 1][2];
+ tmp[a].data[4] = ops[a * 2 + 0][3];
+ tmp[a].data[5] = ops[a * 2 + 1][3];
+ tmp[a].data[6] = ops[a * 2 + 0][4] & 0x07;
+ tmp[a].data[7] = ops[a * 2 + 1][4] & 0x07;
+ tmp[a].data[8] = ops[a * 2 + 0][1];
+ tmp[a].data[9] = ops[a * 2 + 1][1];
+ tmp[a].finetune = (int8_t)TTTTTTTT;
+ tmp[a].diff = false;
+ }
+ tmp[0].data[10] = C4xxxFFFC & 0x0F;
+ tmp[1].data[10] = (tmp[0].data[10] & 0x0E) | (C4xxxFFFC >> 7);
+
+ ins tmp2;
+ tmp2.notenum = (gmno & 128) ? 35 : 0;
+ tmp2.pseudo4op = false;
+ tmp2.voice2_fine_tune = 0.0;
+
+ if(xxP24NNN & 8)
+ {
+ // dual-op
+ size_t resno = InsertIns(tmp[0], tmp[1], tmp2, std::string(1, '\377') + name, name2);
+ SetBank(bank, (unsigned int)gmno, resno);
+ }
+ else
+ {
+ // single-op
+ size_t resno = InsertIns(tmp[0], tmp[0], tmp2, std::string(1, '\377') + name, name2);
+ SetBank(bank, (unsigned int)gmno, resno);
+ }
+ }
+ return true;
+}
+
+#endif // LOAD_BNK2_H
diff --git a/utils/gen_adldata/file_formats/load_ibk.h b/utils/gen_adldata/file_formats/load_ibk.h
new file mode 100644
index 0000000..6370ad0
--- /dev/null
+++ b/utils/gen_adldata/file_formats/load_ibk.h
@@ -0,0 +1,72 @@
+#ifndef LOAD_IBK_H
+#define LOAD_IBK_H
+
+#include "../progs_cache.h"
+
+static bool LoadIBK(const char *fn, unsigned bank, const char *prefix, bool percussive)
+{
+ #ifdef HARD_BANKS
+ writeIni("IBK", fn, prefix, bank, percussive ? INI_Drums : INI_Melodic);
+ #endif
+ FILE *fp = std::fopen(fn, "rb");
+ if(!fp)
+ return false;
+ std::fseek(fp, 0, SEEK_END);
+ std::vector<unsigned char> data(size_t(std::ftell(fp)));
+ std::rewind(fp);
+ if(std::fread(&data[0], 1, data.size(), fp) != data.size())
+ {
+ std::fclose(fp);
+ return false;
+ }
+ std::fclose(fp);
+
+ unsigned offs1_base = 0x804, offs1_len = 9;
+ unsigned offs2_base = 0x004, offs2_len = 16;
+
+ for(unsigned a = 0; a < 128; ++a)
+ {
+ unsigned offset1 = offs1_base + a * offs1_len;
+ unsigned offset2 = offs2_base + a * offs2_len;
+
+ std::string name;
+ for(unsigned p = 0; p < 9; ++p)
+ if(data[offset1] != '\0')
+ name += char(data[offset1 + p]);
+
+ int gmno = int(a + 128 * percussive);
+ /*int midi_index = gmno < 128 ? gmno
+ : gmno < 128+35 ? -1
+ : gmno < 128+88 ? gmno-35
+ : -1;*/
+ char name2[512];
+ sprintf(name2, "%s%c%u", prefix,
+ (gmno < 128 ? 'M' : 'P'), gmno & 127);
+
+ insdata tmp;
+ tmp.data[0] = data[offset2 + 0];
+ tmp.data[1] = data[offset2 + 1];
+ tmp.data[8] = data[offset2 + 2];
+ tmp.data[9] = data[offset2 + 3];
+ tmp.data[2] = data[offset2 + 4];
+ tmp.data[3] = data[offset2 + 5];
+ tmp.data[4] = data[offset2 + 6];
+ tmp.data[5] = data[offset2 + 7];
+ tmp.data[6] = data[offset2 + 8];
+ tmp.data[7] = data[offset2 + 9];
+ tmp.data[10] = data[offset2 + 10];
+ // [+11] seems to be used also, what is it for?
+ tmp.finetune = 0;
+ tmp.diff = false;
+ struct ins tmp2;
+ tmp2.notenum = gmno < 128 ? 0 : 35;
+ tmp2.pseudo4op = false;
+ tmp2.voice2_fine_tune = 0.0;
+
+ size_t resno = InsertIns(tmp, tmp, tmp2, std::string(1, '\377') + name, name2);
+ SetBank(bank, (unsigned int)gmno, resno);
+ }
+ return true;
+}
+
+#endif // LOAD_IBK_H
diff --git a/utils/gen_adldata/file_formats/load_jv.h b/utils/gen_adldata/file_formats/load_jv.h
new file mode 100644
index 0000000..f35de03
--- /dev/null
+++ b/utils/gen_adldata/file_formats/load_jv.h
@@ -0,0 +1,105 @@
+#ifndef LOAD_JV_H
+#define LOAD_JV_H
+
+#include "../progs_cache.h"
+#include "../midi_inst_list.h"
+
+static bool LoadJunglevision(const char *fn, unsigned bank, const char *prefix)
+{
+ #ifdef HARD_BANKS
+ writeIni("Junglevision", fn, prefix, bank, INI_Both);
+ #endif
+ FILE *fp = std::fopen(fn, "rb");
+ if(!fp)
+ return false;
+ std::fseek(fp, 0, SEEK_END);
+ std::vector<unsigned char> data(size_t(std::ftell(fp)));
+ std::rewind(fp);
+ if(std::fread(&data[0], 1, data.size(), fp) != data.size())
+ {
+ std::fclose(fp);
+ return false;
+ }
+ std::fclose(fp);
+
+ uint16_t ins_count = uint16_t(data[0x20] + (data[0x21] << 8));
+ uint16_t drum_count = uint16_t(data[0x22] + (data[0x23] << 8));
+ uint16_t first_ins = uint16_t(data[0x24] + (data[0x25] << 8));
+ uint16_t first_drum = uint16_t(data[0x26] + (data[0x27] << 8));
+
+ unsigned total_ins = ins_count + drum_count;
+
+ for(unsigned a = 0; a < total_ins; ++a)
+ {
+ unsigned offset = 0x28 + a * 0x18;
+ unsigned gmno = (a < ins_count) ? (a + first_ins) : (a + first_drum);
+ int midi_index = gmno < 128 ? int(gmno)
+ : gmno < 128 + 35 ? -1
+ : gmno < 128 + 88 ? int(gmno - 35)
+ : -1;
+
+ insdata tmp[2];
+
+ tmp[0].data[0] = data[offset + 2];
+ tmp[0].data[1] = data[offset + 8];
+ tmp[0].data[2] = data[offset + 4];
+ tmp[0].data[3] = data[offset + 10];
+ tmp[0].data[4] = data[offset + 5];
+ tmp[0].data[5] = data[offset + 11];
+ tmp[0].data[6] = data[offset + 6];
+ tmp[0].data[7] = data[offset + 12];
+ tmp[0].data[8] = data[offset + 3];
+ tmp[0].data[9] = data[offset + 9];
+ tmp[0].data[10] = data[offset + 7] & 0x0F;//~0x30;
+ tmp[0].finetune = 0;
+ tmp[0].diff = false;
+
+ tmp[1].data[0] = data[offset + 2 + 11];
+ tmp[1].data[1] = data[offset + 8 + 11];
+ tmp[1].data[2] = data[offset + 4 + 11];
+ tmp[1].data[3] = data[offset + 10 + 11];
+ tmp[1].data[4] = data[offset + 5 + 11];
+ tmp[1].data[5] = data[offset + 11 + 11];
+ tmp[1].data[6] = data[offset + 6 + 11];
+ tmp[1].data[7] = data[offset + 12 + 11];
+ tmp[1].data[8] = data[offset + 3 + 11];
+ tmp[1].data[9] = data[offset + 9 + 11];
+ tmp[1].data[10] = data[offset + 7 + 11] & 0x0F;//~0x30;
+ tmp[1].finetune = 0;
+ tmp[1].diff = false;
+
+ struct ins tmp2;
+ tmp2.notenum = data[offset + 1];
+ tmp2.pseudo4op = false;
+ tmp2.voice2_fine_tune = 0.0;
+
+ while(tmp2.notenum && tmp2.notenum < 20)
+ {
+ tmp2.notenum += 12;
+ tmp[0].finetune -= 12;
+ tmp[1].finetune -= 12;
+ }
+
+ std::string name;
+ if(midi_index >= 0) name = std::string(1, '\377') + MidiInsName[midi_index];
+
+ char name2[512];
+ sprintf(name2, "%s%c%u", prefix,
+ (gmno < 128 ? 'M' : 'P'), gmno & 127);
+
+ if(!data[offset])
+ {
+ size_t resno = InsertIns(tmp[0], tmp[0], tmp2, name, name2);
+ SetBank(bank, gmno, resno);
+ }
+ else // Double instrument
+ {
+ size_t resno = InsertIns(tmp[0], tmp[1], tmp2, name, name2);
+ SetBank(bank, gmno, resno);
+ }
+ }
+ return true;
+}
+
+#endif // LOAD_JV_H
+
diff --git a/utils/gen_adldata/file_formats/load_op2.h b/utils/gen_adldata/file_formats/load_op2.h
new file mode 100644
index 0000000..30a118f
--- /dev/null
+++ b/utils/gen_adldata/file_formats/load_op2.h
@@ -0,0 +1,148 @@
+#ifndef LOAD_OP2_H
+#define LOAD_OP2_H
+
+#include "../progs_cache.h"
+
+#pragma pack(push, 1)
+struct Doom_OPL2instrument
+{
+ unsigned char trem_vibr_1; /* OP 1: tremolo/vibrato/sustain/KSR/multi */
+ unsigned char att_dec_1; /* OP 1: attack rate/decay rate */
+ unsigned char sust_rel_1; /* OP 1: sustain level/release rate */
+ unsigned char wave_1; /* OP 1: waveform select */
+ unsigned char scale_1; /* OP 1: key scale level */
+ unsigned char level_1; /* OP 1: output level */
+ unsigned char feedback; /* feedback/AM-FM (both operators) */
+ unsigned char trem_vibr_2; /* OP 2: tremolo/vibrato/sustain/KSR/multi */
+ unsigned char att_dec_2; /* OP 2: attack rate/decay rate */
+ unsigned char sust_rel_2; /* OP 2: sustain level/release rate */
+ unsigned char wave_2; /* OP 2: waveform select */
+ unsigned char scale_2; /* OP 2: key scale level */
+ unsigned char level_2; /* OP 2: output level */
+ unsigned char unused;
+ short basenote; /* base note offset */
+} __attribute__((packed));
+#pragma pack(pop)
+
+struct Doom_opl_instr
+{
+ unsigned short flags;
+#define FL_FIXED_PITCH 0x0001 // note has fixed pitch (drum note)
+#define FL_UNKNOWN 0x0002 // ??? (used in instrument #65 only)
+#define FL_DOUBLE_VOICE 0x0004 // use two voices instead of one
+
+ unsigned char finetune;
+ unsigned char note;
+ struct Doom_OPL2instrument patchdata[2];
+} __attribute__((packed));
+
+
+static bool LoadDoom(const char *fn, unsigned bank, const char *prefix)
+{
+ #ifdef HARD_BANKS
+ writeIni("OP2", fn, prefix, bank, INI_Both);
+ #endif
+ FILE *fp = std::fopen(fn, "rb");
+ if(!fp)
+ return false;
+ std::fseek(fp, 0, SEEK_END);
+ std::vector<unsigned char> data(size_t(std::ftell(fp)));
+ std::rewind(fp);
+
+ if(std::fread(&data[0], 1, data.size(), fp) != data.size())
+ {
+ std::fclose(fp);
+ return false;
+ }
+ std::fclose(fp);
+
+ for(unsigned a = 0; a < 175; ++a)
+ {
+ const size_t offset1 = 0x18A4 + a * 32;
+ const size_t offset2 = 8 + a * 36;
+
+ std::string name;
+ for(unsigned p = 0; p < 32; ++p)
+ if(data[offset1] != '\0')
+ name += char(data[offset1 + p]);
+
+ //printf("%3d %3d %3d %8s: ", a,b,c, name.c_str());
+ int gmno = int(a < 128 ? a : ((a | 128) + 35));
+
+ char name2[512];
+ sprintf(name2, "%s%c%u", prefix, (gmno < 128 ? 'M' : 'P'), gmno & 127);
+
+ Doom_opl_instr &ins = *(Doom_opl_instr *) &data[offset2];
+
+ insdata tmp[2];
+ tmp[0].diff = false;
+ tmp[1].diff = true;
+ for(unsigned index = 0; index < 2; ++index)
+ {
+ const Doom_OPL2instrument &src = ins.patchdata[index];
+ tmp[index].data[0] = src.trem_vibr_1;
+ tmp[index].data[1] = src.trem_vibr_2;
+ tmp[index].data[2] = src.att_dec_1;
+ tmp[index].data[3] = src.att_dec_2;
+ tmp[index].data[4] = src.sust_rel_1;
+ tmp[index].data[5] = src.sust_rel_2;
+ tmp[index].data[6] = src.wave_1;
+ tmp[index].data[7] = src.wave_2;
+ tmp[index].data[8] = src.scale_1 | src.level_1;
+ tmp[index].data[9] = src.scale_2 | src.level_2;
+ tmp[index].data[10] = src.feedback;
+ tmp[index].finetune = int8_t(src.basenote + 12);
+ }
+ struct ins tmp2;
+ tmp2.notenum = ins.note;
+ tmp2.pseudo4op = false;
+ tmp2.voice2_fine_tune = 0.0;
+ while(tmp2.notenum && tmp2.notenum < 20)
+ {
+ tmp2.notenum += 12;
+ tmp[0].finetune -= 12;
+ tmp[1].finetune -= 12;
+ }
+
+ if(!(ins.flags & 4))
+ {
+ size_t resno = InsertIns(tmp[0], tmp[0], tmp2, std::string(1, '\377') + name, name2);
+ SetBank(bank, (unsigned int)gmno, resno);
+ }
+ else // Double instrument
+ {
+ tmp2.pseudo4op = true;
+ tmp2.voice2_fine_tune = (((double)ins.finetune - 128.0) * 15.625) / 1000.0;
+ if(ins.finetune == 129)
+ tmp2.voice2_fine_tune = 0.000025;
+ else if(ins.finetune == 127)
+ tmp2.voice2_fine_tune = -0.000025;
+ //printf("/*DOOM FINE TUNE (flags %000X instrument is %d) IS %d -> %lf*/\n", ins.flags, a, ins.finetune, tmp2.fine_tune);
+ size_t resno = InsertIns(tmp[0], tmp[1], tmp2, std::string(1, '\377') + name, name2);
+ SetBank(bank, (unsigned int)gmno, resno);
+ }
+
+ /*const Doom_OPL2instrument& A = ins.patchdata[0];
+ const Doom_OPL2instrument& B = ins.patchdata[1];
+ printf(
+ "flags:%04X fine:%02X note:%02X\n"
+ "{t:%02X a:%02X s:%02X w:%02X s:%02X l:%02X f:%02X\n"
+ " t:%02X a:%02X s:%02X w:%02X s:%02X l:%02X ?:%02X base:%d}\n"
+ "{t:%02X a:%02X s:%02X w:%02X s:%02X l:%02X f:%02X\n"
+ " t:%02X a:%02X s:%02X w:%02X s:%02X l:%02X ?:%02X base:%d} ",
+ ins.flags, ins.finetune, ins.note,
+ A.trem_vibr_1, A.att_dec_1, A.sust_rel_1,
+ A.wave_1, A.scale_1, A.level_1, A.feedback,
+ A.trem_vibr_2, A.att_dec_2, A.sust_rel_2,
+ A.wave_2, A.scale_2, A.level_2, A.unused, A.basenote,
+ B.trem_vibr_1, B.att_dec_1, B.sust_rel_1,
+ B.wave_1, B.scale_1, B.level_1, B.feedback,
+ B.trem_vibr_2, B.att_dec_2, B.sust_rel_2,
+ B.wave_2, B.scale_2, B.level_2, B.unused, B.basenote);
+ printf(" %s VS %s\n", name.c_str(), MidiInsName[a]);
+ printf("------------------------------------------------------------\n");*/
+ }
+ return true;
+}
+
+#endif // LOAD_OP2_H
diff --git a/utils/gen_adldata/file_formats/load_tmb.h b/utils/gen_adldata/file_formats/load_tmb.h
new file mode 100644
index 0000000..c5a3f60
--- /dev/null
+++ b/utils/gen_adldata/file_formats/load_tmb.h
@@ -0,0 +1,68 @@
+#ifndef LOAD_TMB_H
+#define LOAD_TMB_H
+
+#include "../progs_cache.h"
+#include "../midi_inst_list.h"
+
+static bool LoadTMB(const char *fn, unsigned bank, const char *prefix)
+{
+ #ifdef HARD_BANKS
+ writeIni("TMB", fn, prefix, bank, INI_Both);
+ #endif
+ FILE *fp = std::fopen(fn, "rb");
+ if(!fp)
+ return false;
+ std::fseek(fp, 0, SEEK_END);
+ std::vector<unsigned char> data(size_t(std::ftell(fp)));
+ std::rewind(fp);
+ if(std::fread(&data[0], 1, data.size(), fp) != data.size())
+ {
+ std::fclose(fp);
+ return false;
+ }
+ std::fclose(fp);
+
+ for(unsigned a = 0; a < 256; ++a)
+ {
+ unsigned offset = a * 0x0D;
+ unsigned gmno = a;
+ int midi_index = gmno < 128 ? int(gmno)
+ : gmno < 128 + 35 ? -1
+ : gmno < 128 + 88 ? int(gmno - 35)
+ : -1;
+
+ insdata tmp;
+
+ tmp.data[0] = data[offset + 0];
+ tmp.data[1] = data[offset + 1];
+ tmp.data[2] = data[offset + 4];
+ tmp.data[3] = data[offset + 5];
+ tmp.data[4] = data[offset + 6];
+ tmp.data[5] = data[offset + 7];
+ tmp.data[6] = data[offset + 8];
+ tmp.data[7] = data[offset + 9];
+ tmp.data[8] = data[offset + 2];
+ tmp.data[9] = data[offset + 3];
+ tmp.data[10] = data[offset + 10];
+ tmp.finetune = 0; //data[offset + 12];
+ tmp.diff = false;
+
+ struct ins tmp2;
+ tmp2.notenum = data[offset + 11];
+ tmp2.pseudo4op = false;
+ tmp2.voice2_fine_tune = 0.0;
+
+ std::string name;
+ if(midi_index >= 0) name = std::string(1, '\377') + MidiInsName[midi_index];
+
+ char name2[512];
+ sprintf(name2, "%s%c%u", prefix,
+ (gmno < 128 ? 'M' : 'P'), gmno & 127);
+
+ size_t resno = InsertIns(tmp, tmp, tmp2, name, name2);
+ SetBank(bank, gmno, resno);
+ }
+ return true;
+}
+
+#endif // LOAD_TMB_H
diff --git a/utils/gen_adldata/file_formats/load_wopl.h b/utils/gen_adldata/file_formats/load_wopl.h
new file mode 100644
index 0000000..300a3a0
--- /dev/null
+++ b/utils/gen_adldata/file_formats/load_wopl.h
@@ -0,0 +1,265 @@
+#ifndef LOAD_WOPL_H
+#define LOAD_WOPL_H
+
+#include "../progs_cache.h"
+#include "../midi_inst_list.h"
+#include "common.h"
+
+static uint8_t wopl_latest_version = 2;
+
+static bool LoadWopl(const char *fn, unsigned bank, const char *prefix)
+{
+ FILE *fp = std::fopen(fn, "rb");
+ if(!fp)
+ {
+ std::fprintf(stderr, "WOPL: CAN'T OPEN FILE %s\n", fn);
+ std::fflush(stderr);
+ return false;
+ }
+ std::fseek(fp, 0, SEEK_END);
+ std::vector<unsigned char> data(size_t(std::ftell(fp)));
+ std::rewind(fp);
+ if(std::fread(&data[0], 1, data.size(), fp) != data.size())
+ {
+ std::fclose(fp);
+ std::fprintf(stderr, "WOPL: CAN'T READ FILE %s\n", fn);
+ std::fflush(stderr);
+ return false;
+ }
+ std::fclose(fp);
+
+ if(data.size() < 19) // Smaller than header size
+ {
+ std::fprintf(stderr, "WOPL: Too small header %s\n", fn);
+ std::fflush(stderr);
+ return false;
+ }
+
+ uint16_t version = toUint16LE((const uint8_t *)data.data() + 11);
+ if(version > wopl_latest_version)
+ {
+ std::fprintf(stderr, "WOPL: Version %d is not supported (latest %d) %s\n", version, wopl_latest_version, fn);
+ std::fflush(stderr);
+ return false;
+ }
+
+ uint16_t mbanks_count = toUint16BE((const uint8_t *)data.data() + 0x0d);
+ uint16_t pbanks_count = toUint16BE((const uint8_t *)data.data() + 0x0f);
+
+ // Validate file format by size calculation
+ if(version == 1)
+ {
+ //Header size + melodic banks + percussion banks
+ if(data.size() < size_t(19 + (62 * 128 * mbanks_count) + (62 * 128 * pbanks_count)))
+ {
+ std::fprintf(stderr, "WOPL: Version 1 size calculation failed %s\n", fn);
+ std::fflush(stderr);
+ return false;
+ }
+ }
+ else if(version >= 2)
+ {
+ //Header size + melodic bank meta data + percussion bank meta data + melodic banks + percussion banks
+ if(data.size() < size_t(19 + (34 * mbanks_count) + (34 * pbanks_count) + (62 * 128 * mbanks_count) + (62 * 128 * pbanks_count)))
+ {
+ std::fprintf(stderr, "WOPL: Version %d size calculation failed %s\n", version, fn);
+ std::fflush(stderr);
+ return false;
+ }
+ }
+
+ uint32_t melodic_offset = 0;
+ uint32_t percussion_offset = 0;
+ if(version < 2)
+ melodic_offset = 0x13;
+ else
+ melodic_offset = 0x13 + 34 * mbanks_count + 34 * pbanks_count;
+
+ percussion_offset = melodic_offset + (62 * 128 * mbanks_count);
+
+ for(uint32_t mbank = 0; mbank < 1; mbank++) // only first melodic bank (Until multi-banks support will be implemented)
+ {
+ uint32_t bank_offset = melodic_offset + (mbank * 62 * 128);
+
+ for(unsigned i = 0; i < 128; i++)
+ {
+ uint32_t offset = bank_offset + uint32_t(i * 62);
+ std::string name;
+ insdata tmp[2];
+
+ name.resize(32);
+ std::memcpy(&name[0], data.data() + offset, 32);
+ name.resize(std::strlen(&name[0]));
+
+ tmp[0].data[0] = data[offset + 42 + 5];
+ tmp[0].data[1] = data[offset + 42 + 0];
+ tmp[0].data[2] = data[offset + 42 + 7];
+ tmp[0].data[3] = data[offset + 42 + 2];
+ tmp[0].data[4] = data[offset + 42 + 8];
+ tmp[0].data[5] = data[offset + 42 + 3];
+ tmp[0].data[6] = data[offset + 42 + 9];
+ tmp[0].data[7] = data[offset + 42 + 4];
+ tmp[0].data[8] = data[offset + 42 + 6];
+ tmp[0].data[9] = data[offset + 42 + 1];
+ tmp[0].data[10] = data[offset + 40];
+
+ tmp[1].data[0] = data[offset + 52 + 5];
+ tmp[1].data[1] = data[offset + 52 + 0];
+ tmp[1].data[2] = data[offset + 52 + 7];
+ tmp[1].data[3] = data[offset + 52 + 2];
+ tmp[1].data[4] = data[offset + 52 + 8];
+ tmp[1].data[5] = data[offset + 52 + 3];
+ tmp[1].data[6] = data[offset + 52 + 9];
+ tmp[1].data[7] = data[offset + 52 + 4];
+ tmp[1].data[8] = data[offset + 52 + 6];
+ tmp[1].data[9] = data[offset + 52 + 1];
+ tmp[1].data[10] = data[offset + 41];
+
+ tmp[0].finetune = int8_t(toSint16BE((const uint8_t *)data.data() + offset + 32));
+ tmp[1].finetune = int8_t(toSint16BE((const uint8_t *)data.data() + offset + 34));
+
+ uint8_t flags = data[offset + 39];
+
+ struct ins tmp2;
+ tmp2.notenum = 0;
+ tmp2.pseudo4op = (flags & 0x02) != 0;
+ tmp2.voice2_fine_tune = 0;
+ tmp[0].diff = false;
+ tmp[1].diff = tmp2.pseudo4op;
+
+ int8_t fine_tune = (int8_t)data[offset + 37];
+ if(fine_tune != 0)
+ {
+ if(fine_tune == 1)
+ tmp2.voice2_fine_tune = 0.000025;
+ else if(fine_tune == -1)
+ tmp2.voice2_fine_tune = -0.000025;
+ else
+ tmp2.voice2_fine_tune = ((fine_tune * 15.625) / 1000.0);
+ }
+
+ if(name.empty())
+ name = std::string(1, '\377') + MidiInsName[i];
+ else
+ name.insert(0, 1, '\377');
+
+ char name2[512];
+ sprintf(name2, "%sM%u", prefix, i);
+
+ if((flags & 0x03) == 0)
+ {
+ size_t resno = InsertIns(tmp[0], tmp[0], tmp2, name, name2);
+ SetBank(bank, i, resno);
+ }
+ else
+ {
+ size_t resno = InsertIns(tmp[0], tmp[1], tmp2, name, name2);
+ SetBank(bank, i, resno);
+ }
+ }
+ }
+
+ for(uint32_t pbank = 0; pbank < 1; pbank++) // only first percussion bank (Until multi-banks support will be implemented)
+ {
+ uint32_t bank_offset = percussion_offset + (pbank * 62 * 128);
+
+ for(uint32_t i = 0; i < 128; i++)
+ {
+ uint32_t offset = bank_offset + (i * 62);
+ std::string name;
+ insdata tmp[2];
+
+ name.resize(32);
+ std::memcpy(&name[0], data.data() + offset, 32);
+ name.resize(std::strlen(&name[0]));
+/*
+ WOPL's
+
+ 0 AM/Vib/Env/Ksr/FMult characteristics
+ 1 Key Scale Level / Total level register data
+ 2 Attack / Decay
+ 3 Systain and Release register data
+ 4 Wave form
+
+ 5 AM/Vib/Env/Ksr/FMult characteristics
+ 6 Key Scale Level / Total level register data
+ 7 Attack / Decay
+ 8 Systain and Release register data
+ 9 Wave form
+*/
+ tmp[0].data[0] = data[offset + 42 + 5];//AMVIB op1
+ tmp[0].data[1] = data[offset + 42 + 0];//AMVIB op2
+ tmp[0].data[2] = data[offset + 42 + 7];//AtDec op1
+ tmp[0].data[3] = data[offset + 42 + 2];//AtDec op2
+ tmp[0].data[4] = data[offset + 42 + 8];//SusRel op1
+ tmp[0].data[5] = data[offset + 42 + 3];//SusRel op2
+ tmp[0].data[6] = data[offset + 42 + 9];//Wave op1
+ tmp[0].data[7] = data[offset + 42 + 4];//Wave op2
+ tmp[0].data[8] = data[offset + 42 + 6];//KSL op1
+ tmp[0].data[9] = data[offset + 42 + 1];//KSL op2
+ tmp[0].data[10] = data[offset + 40];
+
+ tmp[1].data[0] = data[offset + 52 + 5];
+ tmp[1].data[1] = data[offset + 52 + 0];
+ tmp[1].data[2] = data[offset + 52 + 7];
+ tmp[1].data[3] = data[offset + 52 + 2];
+ tmp[1].data[4] = data[offset + 52 + 8];
+ tmp[1].data[5] = data[offset + 52 + 3];
+ tmp[1].data[6] = data[offset + 52 + 9];
+ tmp[1].data[7] = data[offset + 52 + 4];
+ tmp[1].data[8] = data[offset + 52 + 6];
+ tmp[1].data[9] = data[offset + 52 + 1];
+ tmp[1].data[10] = data[offset + 41];
+
+ tmp[0].finetune = int8_t(toSint16BE((const uint8_t *)data.data() + offset + 32));
+ tmp[1].finetune = int8_t(toSint16BE((const uint8_t *)data.data() + offset + 34));
+ uint8_t flags = data[offset + 39];
+
+ struct ins tmp2;
+ tmp2.notenum = data[offset + 38];
+ tmp2.pseudo4op = (flags & 0x02) != 0;
+ tmp2.voice2_fine_tune = 0;
+ tmp[0].diff = false;
+ tmp[1].diff = tmp2.pseudo4op;
+
+ int8_t fine_tune = (int8_t)data[offset + 37];
+ if(fine_tune != 0)
+ {
+ if(fine_tune == 1)
+ tmp2.voice2_fine_tune = 0.000025;
+ else if(fine_tune == -1)
+ tmp2.voice2_fine_tune = -0.000025;
+ else
+ tmp2.voice2_fine_tune = ((fine_tune * 15.625) / 1000.0);
+ }
+
+ uint32_t gmno = i + 128;
+ int midi_index = (gmno < (128 + 35)) ? -1
+ : (gmno < (128 + 88)) ? int(gmno) - 35
+ : -1;
+
+ if(name.empty() && (midi_index >= 0))
+ name = std::string(1, '\377') + MidiInsName[midi_index];
+ if(!name.empty())
+ name.insert(0, 1, '\377');
+
+ char name2[512];
+ sprintf(name2, "%sP%u", prefix, gmno & 127);
+
+ if((flags & 0x03) == 0)
+ {
+ size_t resno = InsertIns(tmp[0], tmp[0], tmp2, name, name2);
+ SetBank(bank, gmno, resno);
+ }
+ else
+ {
+ size_t resno = InsertIns(tmp[0], tmp[1], tmp2, name, name2);
+ SetBank(bank, gmno, resno);
+ }
+ }
+ }
+ return true;
+}
+
+
+#endif // LOAD_WOPL_H