aboutsummaryrefslogtreecommitdiff
path: root/utils/gen_adldata/file_formats/load_ea.h
blob: 5e5711eba44a2f55345cc72e007a95b07e92210c (plain)
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