~ubuntu-branches/ubuntu/hardy/libmodplug/hardy

« back to all changes in this revision

Viewing changes to src/load_dsm.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Zed Pobre
  • Date: 2004-09-10 14:05:53 UTC
  • Revision ID: james.westby@ubuntu.com-20040910140553-3lxaulb7xmwa8fsl
Tags: upstream-0.7
ImportĀ upstreamĀ versionĀ 0.7

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * This source code is public domain.
 
3
 *
 
4
 * Authors: Olivier Lapicque <olivierl@jps.net>
 
5
*/
 
6
 
 
7
//////////////////////////////////////////////
 
8
// DSIK Internal Format (DSM) module loader //
 
9
//////////////////////////////////////////////
 
10
#include "stdafx.h"
 
11
#include "sndfile.h"
 
12
 
 
13
#pragma pack(1)
 
14
 
 
15
#define DSMID_RIFF      0x46464952      // "RIFF"
 
16
#define DSMID_DSMF      0x464d5344      // "DSMF"
 
17
#define DSMID_SONG      0x474e4f53      // "SONG"
 
18
#define DSMID_INST      0x54534e49      // "INST"
 
19
#define DSMID_PATT      0x54544150      // "PATT"
 
20
 
 
21
 
 
22
typedef struct DSMNOTE
 
23
{
 
24
        BYTE note,ins,vol,cmd,inf;
 
25
} DSMNOTE;
 
26
 
 
27
 
 
28
typedef struct DSMINST
 
29
{
 
30
        DWORD id_INST;
 
31
        DWORD inst_len;
 
32
        CHAR filename[13];
 
33
        BYTE flags;
 
34
        BYTE flags2;
 
35
        BYTE volume;
 
36
        DWORD length;
 
37
        DWORD loopstart;
 
38
        DWORD loopend;
 
39
        DWORD reserved1;
 
40
        WORD c2spd;
 
41
        WORD reserved2;
 
42
        CHAR samplename[28];
 
43
} DSMINST;
 
44
 
 
45
 
 
46
typedef struct DSMFILEHEADER
 
47
{
 
48
        DWORD id_RIFF;  // "RIFF"
 
49
        DWORD riff_len;
 
50
        DWORD id_DSMF;  // "DSMF"
 
51
        DWORD id_SONG;  // "SONG"
 
52
        DWORD song_len;
 
53
} DSMFILEHEADER;
 
54
 
 
55
 
 
56
typedef struct DSMSONG
 
57
{
 
58
        CHAR songname[28];
 
59
        WORD reserved1;
 
60
        WORD flags;
 
61
        DWORD reserved2;
 
62
        WORD numord;
 
63
        WORD numsmp;
 
64
        WORD numpat;
 
65
        WORD numtrk;
 
66
        BYTE globalvol;
 
67
        BYTE mastervol;
 
68
        BYTE speed;
 
69
        BYTE bpm;
 
70
        BYTE panpos[16];
 
71
        BYTE orders[128];
 
72
} DSMSONG;
 
73
 
 
74
typedef struct DSMPATT
 
75
{
 
76
        DWORD id_PATT;
 
77
        DWORD patt_len;
 
78
        BYTE dummy1;
 
79
        BYTE dummy2;
 
80
} DSMPATT;
 
81
 
 
82
#pragma pack()
 
83
 
 
84
 
 
85
BOOL CSoundFile::ReadDSM(LPCBYTE lpStream, DWORD dwMemLength)
 
86
//-----------------------------------------------------------
 
87
{
 
88
        DSMFILEHEADER *pfh = (DSMFILEHEADER *)lpStream;
 
89
        DSMSONG *psong;
 
90
        DWORD dwMemPos;
 
91
        UINT nPat, nSmp;
 
92
 
 
93
        if ((!lpStream) || (dwMemLength < 1024) || (pfh->id_RIFF != DSMID_RIFF)
 
94
         || (pfh->riff_len + 8 > dwMemLength) || (pfh->riff_len < 1024)
 
95
         || (pfh->id_DSMF != DSMID_DSMF) || (pfh->id_SONG != DSMID_SONG)
 
96
         || (pfh->song_len > dwMemLength)) return FALSE;
 
97
        psong = (DSMSONG *)(lpStream + sizeof(DSMFILEHEADER));
 
98
        dwMemPos = sizeof(DSMFILEHEADER) + pfh->song_len;
 
99
        m_nType = MOD_TYPE_DSM;
 
100
        m_nChannels = psong->numtrk;
 
101
        if (m_nChannels < 4) m_nChannels = 4;
 
102
        if (m_nChannels > 16) m_nChannels = 16;
 
103
        m_nSamples = psong->numsmp;
 
104
        if (m_nSamples > MAX_SAMPLES) m_nSamples = MAX_SAMPLES;
 
105
        m_nDefaultSpeed = psong->speed;
 
106
        m_nDefaultTempo = psong->bpm;
 
107
        m_nDefaultGlobalVolume = psong->globalvol << 2;
 
108
        if ((!m_nDefaultGlobalVolume) || (m_nDefaultGlobalVolume > 256)) m_nDefaultGlobalVolume = 256;
 
109
        m_nSongPreAmp = psong->mastervol & 0x7F;
 
110
        for (UINT iOrd=0; iOrd<MAX_ORDERS; iOrd++)
 
111
        {
 
112
                Order[iOrd] = (BYTE)((iOrd < psong->numord) ? psong->orders[iOrd] : 0xFF);
 
113
        }
 
114
        for (UINT iPan=0; iPan<16; iPan++)
 
115
        {
 
116
                ChnSettings[iPan].nPan = 0x80;
 
117
                if (psong->panpos[iPan] <= 0x80)
 
118
                {
 
119
                        ChnSettings[iPan].nPan = psong->panpos[iPan] << 1;
 
120
                }
 
121
        }
 
122
        memcpy(m_szNames[0], psong->songname, 28);
 
123
        nPat = 0;
 
124
        nSmp = 1;
 
125
        while (dwMemPos < dwMemLength - 8)
 
126
        {
 
127
                DSMPATT *ppatt = (DSMPATT *)(lpStream + dwMemPos);
 
128
                DSMINST *pins = (DSMINST *)(lpStream+dwMemPos);
 
129
                // Reading Patterns
 
130
                if (ppatt->id_PATT == DSMID_PATT)
 
131
                {
 
132
                        dwMemPos += 8;
 
133
                        if (dwMemPos + ppatt->patt_len >= dwMemLength) break;
 
134
                        DWORD dwPos = dwMemPos;
 
135
                        dwMemPos += ppatt->patt_len;
 
136
                        MODCOMMAND *m = AllocatePattern(64, m_nChannels);
 
137
                        if (!m) break;
 
138
                        PatternSize[nPat] = 64;
 
139
                        Patterns[nPat] = m;
 
140
                        UINT row = 0;
 
141
                        while ((row < 64) && (dwPos + 2 <= dwMemPos))
 
142
                        {
 
143
                                UINT flag = lpStream[dwPos++];
 
144
                                if (flag)
 
145
                                {
 
146
                                        UINT ch = (flag & 0x0F) % m_nChannels;
 
147
                                        if (flag & 0x80)
 
148
                                        {
 
149
                                                UINT note = lpStream[dwPos++];
 
150
                                                if (note)
 
151
                                                {
 
152
                                                        if (note <= 12*9) note += 12;
 
153
                                                        m[ch].note = (BYTE)note;
 
154
                                                }
 
155
                                        }
 
156
                                        if (flag & 0x40)
 
157
                                        {
 
158
                                                m[ch].instr = lpStream[dwPos++];
 
159
                                        }
 
160
                                        if (flag & 0x20)
 
161
                                        {
 
162
                                                m[ch].volcmd = VOLCMD_VOLUME;
 
163
                                                m[ch].vol = lpStream[dwPos++];
 
164
                                        }
 
165
                                        if (flag & 0x10)
 
166
                                        {
 
167
                                                UINT command = lpStream[dwPos++];
 
168
                                                UINT param = lpStream[dwPos++];
 
169
                                                switch(command)
 
170
                                                {
 
171
                                                // 4-bit Panning
 
172
                                                case 0x08:
 
173
                                                        switch(param & 0xF0)
 
174
                                                        {
 
175
                                                        case 0x00: param <<= 4; break;
 
176
                                                        case 0x10: command = 0x0A; param = (param & 0x0F) << 4; break;
 
177
                                                        case 0x20: command = 0x0E; param = (param & 0x0F) | 0xA0; break;
 
178
                                                        case 0x30: command = 0x0E; param = (param & 0x0F) | 0x10; break;
 
179
                                                        case 0x40: command = 0x0E; param = (param & 0x0F) | 0x20; break;
 
180
                                                        default: command = 0;
 
181
                                                        }
 
182
                                                        break;
 
183
                                                // Portamentos
 
184
                                                case 0x11:
 
185
                                                case 0x12:
 
186
                                                        command &= 0x0F;
 
187
                                                        break;
 
188
                                                // 3D Sound (?)
 
189
                                                case 0x13:
 
190
                                                        command = 'X' - 55;
 
191
                                                        param = 0x91;
 
192
                                                        break;
 
193
                                                default:
 
194
                                                        // Volume + Offset (?)
 
195
                                                        command = ((command & 0xF0) == 0x20) ? 0x09 : 0;
 
196
                                                }
 
197
                                                m[ch].command = (BYTE)command;
 
198
                                                m[ch].param = (BYTE)param;
 
199
                                                if (command) ConvertModCommand(&m[ch]);
 
200
                                        }
 
201
                                } else
 
202
                                {
 
203
                                        m += m_nChannels;
 
204
                                        row++;
 
205
                                }
 
206
                        }
 
207
                        nPat++;
 
208
                } else
 
209
                // Reading Samples
 
210
                if ((nSmp <= m_nSamples) && (pins->id_INST == DSMID_INST))
 
211
                {
 
212
                        if (dwMemPos + pins->inst_len >= dwMemLength - 8) break;
 
213
                        DWORD dwPos = dwMemPos + sizeof(DSMINST);
 
214
                        dwMemPos += 8 + pins->inst_len;
 
215
                        memcpy(m_szNames[nSmp], pins->samplename, 28);
 
216
                        MODINSTRUMENT *psmp = &Ins[nSmp];
 
217
                        memcpy(psmp->name, pins->filename, 13);
 
218
                        psmp->nGlobalVol = 64;
 
219
                        psmp->nC4Speed = pins->c2spd;
 
220
                        psmp->uFlags = (WORD)((pins->flags & 1) ? CHN_LOOP : 0);
 
221
                        psmp->nLength = pins->length;
 
222
                        psmp->nLoopStart = pins->loopstart;
 
223
                        psmp->nLoopEnd = pins->loopend;
 
224
                        psmp->nVolume = (WORD)(pins->volume << 2);
 
225
                        if (psmp->nVolume > 256) psmp->nVolume = 256;
 
226
                        UINT smptype = (pins->flags & 2) ? RS_PCM8S : RS_PCM8U;
 
227
                        ReadSample(psmp, smptype, (LPCSTR)(lpStream+dwPos), dwMemLength - dwPos);
 
228
                        nSmp++;
 
229
                } else
 
230
                {
 
231
                        break;
 
232
                }
 
233
        }
 
234
        return TRUE;
 
235
}
 
236