1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
|
#ifndef LOAD_EA_H
#define LOAD_EA_H
#include "../progs_cache.h"
#include "../midi_inst_list.h"
bool BankFormats::LoadEA(BanksDump &db, const char *fn, unsigned bank,
const std::string &bankTitle, const char *prefix)
{
FILE *fp = std::fopen(fn, "rb");
if(!fp)
return false;
size_t bankDb = db.initBank(bank, bankTitle, BanksDump::BankEntry::SETUP_CMF);
BanksDump::MidiBank bnkMelodic = db.midiBanks[db.banks[0].melodic[0]];
BanksDump::MidiBank bnkPercussion = db.midiBanks[db.banks[0].percussion[0]];
// Copy all instruments from bank 0
// for(unsigned gmno = 0; gmno < 128; ++gmno)
// progs[bank][gmno] = progs[0][gmno];
// for(unsigned gmno = 35; gmno < 80; ++gmno)
// progs[bank][0x80 + gmno] = progs[0][0x80 + gmno];
uint16_t sources[20 + 8];
// Copy also the unused instruments
sources[20] = 0x245;
sources[21] = 0x24F;
sources[22] = 0x263;
sources[23] = 0x277;
sources[24] = 0x281;
sources[25] = 0x28B;
sources[26] = 0x29F;
sources[27] = 0x2A9;
for(unsigned gmno = 0; gmno < 20; ++gmno)
{
std::fseek(fp, 0x150 + gmno, SEEK_SET);
uint8_t bytes[3] = {0};
if(std::fread(bytes, 1, 1, fp) != 1)
{
std::fclose(fp);
return false;
}
long insno = (long)bytes[0];
std::fseek(fp, 0x187 + insno * 2, SEEK_SET);
if(std::fread(bytes, 1, 2, fp) != 2)
{
std::fclose(fp);
return false;
}
uint16_t offset = (uint16_t)bytes[0];
offset += bytes[1] * 256;
sources[gmno] = offset;
}
for(unsigned gmno = 0; gmno < 20 + 8; ++gmno)
{
unsigned int offset = sources[gmno];
std::fseek(fp, (long)offset, SEEK_SET);
uint8_t bytes[10];
if(std::fread(bytes, 1, 10, fp) != 10)
{
std::fclose(fp);
return false;
}
BanksDump::InstrumentEntry inst;
BanksDump::Operator ops[5];
InstBuffer tmp;
tmp.data[0] = bytes[0]; // reg 0x20: modulator AM/VIG/EG/KSR
tmp.data[8] = bytes[1]; // reg 0x40: modulator ksl/attenuation
tmp.data[2] = bytes[2]; // reg 0x60: modulator attack/decay
tmp.data[4] = bytes[3]; // reg 0x80: modulator sustain/release
tmp.data[1] = bytes[4]; // reg 0x20: carrier AM/VIG/EG/KSR
tmp.data[9] = bytes[5]; // reg 0x40: carrier ksl/attenuation
tmp.data[3] = bytes[6]; // reg 0x60: carrier attack/decay
tmp.data[5] = bytes[7]; // reg 0x80: carrier sustain/release
// bytes[1] will be written directly to register 0x40
// bytes[5] will be written directly to register 0x43
// When touching volume, register 0x43 <- bytes[5] - midivolume/4
tmp.data[10] = bytes[8]; // reg 0xC0 (feedback and connection)
tmp.data[6] = 0; // reg 0xE0: modulator, never seems to be set
tmp.data[7] = 0; // reg 0xE0: carrier, never seems to be set
db.toOps(tmp.d, ops, 0);
inst.setFbConn(bytes[8]);
inst.noteOffset1 = int8_t(bytes[9] + 12);
std::string name;
char name2[512];
if(gmno < 20)
{
snprintf(name2, 512, "%sM%u", prefix, gmno);
}
else
{
snprintf(name2, 512, "%sunk%04X", prefix, offset);
}
db.addInstrument(bnkMelodic, gmno, inst, ops, fn);
if(gmno == 10)
{
inst.percussionKeyNumber = 0x49;
db.addInstrument(bnkPercussion, 0x36, inst, ops, fn);
}
if(gmno == 18)
{
inst.percussionKeyNumber = 0x17;
db.addInstrument(bnkPercussion, 0x2A, inst, ops, fn);
}
if(gmno == 16)
{
inst.percussionKeyNumber = 0x0C;
db.addInstrument(bnkPercussion, 0x24, inst, ops, fn);
}
if(gmno == 17)
{
inst.percussionKeyNumber = 0x01;
db.addInstrument(bnkPercussion, 0x26, inst, ops, fn);
}
}
std::fclose(fp);
db.addMidiBank(bankDb, false, bnkMelodic);
db.addMidiBank(bankDb, true, bnkPercussion);
return true;
}
#endif // LOAD_EA_H
|