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