aboutsummaryrefslogtreecommitdiff
path: root/utils/gen_adldata/file_formats/load_jv.h
blob: a7ebf7bc290891a4dcbb22fc86d621058a0ae5d8 (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
#ifndef LOAD_JV_H
#define LOAD_JV_H

#include "../progs_cache.h"
#include "../midi_inst_list.h"

bool BankFormats::LoadJunglevision(BanksDump &db, const char *fn, unsigned bank, const std::string &bankTitle, 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);

    size_t bankDb = db.initBank(bank, bankTitle, BanksDump::BankEntry::SETUP_Win9X);
    BanksDump::MidiBank bnkMelodique;
    BanksDump::MidiBank bnkPercussion;

    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;

        bool isPercussion = ins_count >= 128;
        size_t patchId = (a < ins_count) ? (a + first_ins) : ((a - ins_count) + first_drum);
        BanksDump::MidiBank &bnk = isPercussion ? bnkPercussion : bnkMelodique;
        BanksDump::InstrumentEntry inst;
        BanksDump::Operator ops[5];

        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 = (data[offset] != 0);

        struct ins tmp2;
        tmp2.notenum  = data[offset + 1];
        tmp2.pseudo4op = false;
        tmp2.real4op = (data[offset] != 0);
        tmp2.voice2_fine_tune = 0.0;
        tmp2.midi_velocity_offset = 0;
        tmp2.rhythmModeDrum = 0;

        while(tmp2.notenum && tmp2.notenum < 20)
        {
            tmp2.notenum += 12;
            tmp[0].finetune -= 12;
            tmp[1].finetune -= 12;
        }

        if(data[offset] != 0)
            inst.instFlags |= BanksDump::InstrumentEntry::WOPL_Ins_4op;
        inst.percussionKeyNumber = data[offset + 1];
        inst.setFbConn(data[offset + 7], data[offset + 7 + 11]);
        db.toOps(tmp[0], ops, 0);
        db.toOps(tmp[1], ops, 2);

        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], 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);
        }
        db.addInstrument(bnk, patchId, inst, ops);
    }

    db.addMidiBank(bankDb, false, bnkMelodique);
    db.addMidiBank(bankDb, true, bnkPercussion);

    AdlBankSetup setup;
    setup.volumeModel = VOLUME_9X;
    setup.deepTremolo = true;
    setup.deepVibrato = true;
    setup.scaleModulators = false;
    SetBankSetup(bank, setup);

    return true;
}

#endif // LOAD_JV_H