summaryrefslogtreecommitdiff
path: root/core/multimedia/opieplayer/modplug/load_it.cpp
Unidiff
Diffstat (limited to 'core/multimedia/opieplayer/modplug/load_it.cpp') (more/less context) (ignore whitespace changes)
-rw-r--r--core/multimedia/opieplayer/modplug/load_it.cpp1415
1 files changed, 1415 insertions, 0 deletions
diff --git a/core/multimedia/opieplayer/modplug/load_it.cpp b/core/multimedia/opieplayer/modplug/load_it.cpp
new file mode 100644
index 0000000..006b746
--- a/dev/null
+++ b/core/multimedia/opieplayer/modplug/load_it.cpp
@@ -0,0 +1,1415 @@
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 * Adam Goode <adam@evdebs.org> (endian and char fixes for PPC)
9*/
10
11#include "stdafx.h"
12#include "sndfile.h"
13#include "it_defs.h"
14
15#ifdef WIN32
16#pragma warning(disable:4244)
17#endif
18
19const BYTE autovibit2xm[8] =
20{ 0, 3, 1, 4, 2, 0, 0, 0 };
21
22const BYTE autovibxm2it[8] =
23{ 0, 2, 4, 1, 3, 0, 0, 0 };
24
25//////////////////////////////////////////////////////////
26// Impulse Tracker IT file support (import only)
27
28
29static inline UINT ConvertVolParam(UINT value)
30//--------------------------------------------
31{
32 return (value > 9) ? 9 : value;
33}
34
35
36BOOL CSoundFile::ITInstrToMPT(const void *p, INSTRUMENTHEADER *penv, UINT trkvers)
37//--------------------------------------------------------------------------------
38{
39 if (trkvers < 0x0200)
40 {
41 const ITOLDINSTRUMENT *pis = (const ITOLDINSTRUMENT *)p;
42 memcpy(penv->name, pis->name, 26);
43 memcpy(penv->filename, pis->filename, 12);
44 penv->nFadeOut = bswapLE16(pis->fadeout) << 6;
45 penv->nGlobalVol = 64;
46 for (UINT j=0; j<120; j++)
47 {
48 UINT note = pis->keyboard[j*2];
49 UINT ins = pis->keyboard[j*2+1];
50 if (ins < MAX_SAMPLES) penv->Keyboard[j] = ins;
51 if (note < 128) penv->NoteMap[j] = note+1;
52 else if (note >= 0xFE) penv->NoteMap[j] = note;
53 }
54 if (pis->flags & 0x01) penv->dwFlags |= ENV_VOLUME;
55 if (pis->flags & 0x02) penv->dwFlags |= ENV_VOLLOOP;
56 if (pis->flags & 0x04) penv->dwFlags |= ENV_VOLSUSTAIN;
57 penv->nVolLoopStart = pis->vls;
58 penv->nVolLoopEnd = pis->vle;
59 penv->nVolSustainBegin = pis->sls;
60 penv->nVolSustainEnd = pis->sle;
61 penv->nVolEnv = 25;
62 for (UINT ev=0; ev<25; ev++)
63 {
64 if ((penv->VolPoints[ev] = pis->nodes[ev*2]) == 0xFF)
65 {
66 penv->nVolEnv = ev;
67 break;
68 }
69 penv->VolEnv[ev] = pis->nodes[ev*2+1];
70 }
71 penv->nNNA = pis->nna;
72 penv->nDCT = pis->dnc;
73 penv->nPan = 0x80;
74 } else
75 {
76 const ITINSTRUMENT *pis = (const ITINSTRUMENT *)p;
77 memcpy(penv->name, pis->name, 26);
78 memcpy(penv->filename, pis->filename, 12);
79 penv->nMidiProgram = pis->mpr;
80 penv->nMidiChannel = pis->mch;
81 penv->wMidiBank = bswapLE16(pis->mbank);
82 penv->nFadeOut = bswapLE16(pis->fadeout) << 5;
83 penv->nGlobalVol = pis->gbv >> 1;
84 if (penv->nGlobalVol > 64) penv->nGlobalVol = 64;
85 for (UINT j=0; j<120; j++)
86 {
87 UINT note = pis->keyboard[j*2];
88 UINT ins = pis->keyboard[j*2+1];
89 if (ins < MAX_SAMPLES) penv->Keyboard[j] = ins;
90 if (note < 128) penv->NoteMap[j] = note+1;
91 else if (note >= 0xFE) penv->NoteMap[j] = note;
92 }
93 // Volume Envelope
94 if (pis->volenv.flags & 1) penv->dwFlags |= ENV_VOLUME;
95 if (pis->volenv.flags & 2) penv->dwFlags |= ENV_VOLLOOP;
96 if (pis->volenv.flags & 4) penv->dwFlags |= ENV_VOLSUSTAIN;
97 if (pis->volenv.flags & 8) penv->dwFlags |= ENV_VOLCARRY;
98 penv->nVolEnv = pis->volenv.num;
99 if (penv->nVolEnv > 25) penv->nVolEnv = 25;
100
101 penv->nVolLoopStart = pis->volenv.lpb;
102 penv->nVolLoopEnd = pis->volenv.lpe;
103 penv->nVolSustainBegin = pis->volenv.slb;
104 penv->nVolSustainEnd = pis->volenv.sle;
105 // Panning Envelope
106 if (pis->panenv.flags & 1) penv->dwFlags |= ENV_PANNING;
107 if (pis->panenv.flags & 2) penv->dwFlags |= ENV_PANLOOP;
108 if (pis->panenv.flags & 4) penv->dwFlags |= ENV_PANSUSTAIN;
109 if (pis->panenv.flags & 8) penv->dwFlags |= ENV_PANCARRY;
110 penv->nPanEnv = pis->panenv.num;
111 if (penv->nPanEnv > 25) penv->nPanEnv = 25;
112 penv->nPanLoopStart = pis->panenv.lpb;
113 penv->nPanLoopEnd = pis->panenv.lpe;
114 penv->nPanSustainBegin = pis->panenv.slb;
115 penv->nPanSustainEnd = pis->panenv.sle;
116 // Pitch Envelope
117 if (pis->pitchenv.flags & 1) penv->dwFlags |= ENV_PITCH;
118 if (pis->pitchenv.flags & 2) penv->dwFlags |= ENV_PITCHLOOP;
119 if (pis->pitchenv.flags & 4) penv->dwFlags |= ENV_PITCHSUSTAIN;
120 if (pis->pitchenv.flags & 8) penv->dwFlags |= ENV_PITCHCARRY;
121 if (pis->pitchenv.flags & 0x80) penv->dwFlags |= ENV_FILTER;
122 penv->nPitchEnv = pis->pitchenv.num;
123 if (penv->nPitchEnv > 25) penv->nPitchEnv = 25;
124 penv->nPitchLoopStart = pis->pitchenv.lpb;
125 penv->nPitchLoopEnd = pis->pitchenv.lpe;
126 penv->nPitchSustainBegin = pis->pitchenv.slb;
127 penv->nPitchSustainEnd = pis->pitchenv.sle;
128 // Envelopes Data
129 for (UINT ev=0; ev<25; ev++)
130 {
131 penv->VolEnv[ev] = pis->volenv.data[ev*3];
132 penv->VolPoints[ev] = (pis->volenv.data[ev*3+2] << 8) | (pis->volenv.data[ev*3+1]);
133 penv->PanEnv[ev] = pis->panenv.data[ev*3] + 32;
134 penv->PanPoints[ev] = (pis->panenv.data[ev*3+2] << 8) | (pis->panenv.data[ev*3+1]);
135 penv->PitchEnv[ev] = pis->pitchenv.data[ev*3] + 32;
136 penv->PitchPoints[ev] = (pis->pitchenv.data[ev*3+2] << 8) | (pis->pitchenv.data[ev*3+1]);
137 }
138 penv->nNNA = pis->nna;
139 penv->nDCT = pis->dct;
140 penv->nDNA = pis->dca;
141 penv->nPPS = pis->pps;
142 penv->nPPC = pis->ppc;
143 penv->nIFC = pis->ifc;
144 penv->nIFR = pis->ifr;
145 penv->nVolSwing = pis->rv;
146 penv->nPanSwing = pis->rp;
147 penv->nPan = (pis->dfp & 0x7F) << 2;
148 if (penv->nPan > 256) penv->nPan = 128;
149 if (pis->dfp < 0x80) penv->dwFlags |= ENV_SETPANNING;
150 }
151 if ((penv->nVolLoopStart >= 25) || (penv->nVolLoopEnd >= 25)) penv->dwFlags &= ~ENV_VOLLOOP;
152 if ((penv->nVolSustainBegin >= 25) || (penv->nVolSustainEnd >= 25)) penv->dwFlags &= ~ENV_VOLSUSTAIN;
153 return TRUE;
154}
155
156
157BOOL CSoundFile::ReadIT(const BYTE *lpStream, DWORD dwMemLength)
158//--------------------------------------------------------------
159{
160 ITFILEHEADER pifh = *(ITFILEHEADER *)lpStream;
161 DWORD dwMemPos = sizeof(ITFILEHEADER);
162 DWORD inspos[MAX_INSTRUMENTS];
163 DWORD smppos[MAX_SAMPLES];
164 DWORD patpos[MAX_PATTERNS];
165 BYTE chnmask[64], channels_used[64];
166 MODCOMMAND lastvalue[64];
167
168 pifh.id = bswapLE32(pifh.id);
169 pifh.reserved1 = bswapLE16(pifh.reserved1);
170 pifh.ordnum = bswapLE16(pifh.ordnum);
171 pifh.insnum = bswapLE16(pifh.insnum);
172 pifh.smpnum = bswapLE16(pifh.smpnum);
173 pifh.patnum = bswapLE16(pifh.patnum);
174 pifh.cwtv = bswapLE16(pifh.cwtv);
175 pifh.cmwt = bswapLE16(pifh.cmwt);
176 pifh.flags = bswapLE16(pifh.flags);
177 pifh.special = bswapLE16(pifh.special);
178 pifh.msglength = bswapLE16(pifh.msglength);
179 pifh.msgoffset = bswapLE32(pifh.msgoffset);
180 pifh.reserved2 = bswapLE32(pifh.reserved2);
181
182 if ((!lpStream) || (dwMemLength < 0x100)) return FALSE;
183 if ((pifh.id != 0x4D504D49) || (pifh.insnum >= MAX_INSTRUMENTS)
184 || (!pifh.smpnum) || (pifh.smpnum >= MAX_INSTRUMENTS) || (!pifh.ordnum)) return FALSE;
185 if (dwMemPos + pifh.ordnum + pifh.insnum*4
186 + pifh.smpnum*4 + pifh.patnum*4 > dwMemLength) return FALSE;
187 m_nType = MOD_TYPE_IT;
188 if (pifh.flags & 0x08) m_dwSongFlags |= SONG_LINEARSLIDES;
189 if (pifh.flags & 0x10) m_dwSongFlags |= SONG_ITOLDEFFECTS;
190 if (pifh.flags & 0x20) m_dwSongFlags |= SONG_ITCOMPATMODE;
191 if (pifh.flags & 0x80) m_dwSongFlags |= SONG_EMBEDMIDICFG;
192 if (pifh.flags & 0x1000) m_dwSongFlags |= SONG_EXFILTERRANGE;
193 memcpy(m_szNames[0], pifh.songname, 26);
194 m_szNames[0][26] = 0;
195 // Global Volume
196 if (pifh.globalvol)
197 {
198 m_nDefaultGlobalVolume = pifh.globalvol << 1;
199 if (!m_nDefaultGlobalVolume) m_nDefaultGlobalVolume = 256;
200 if (m_nDefaultGlobalVolume > 256) m_nDefaultGlobalVolume = 256;
201 }
202 if (pifh.speed) m_nDefaultSpeed = pifh.speed;
203 if (pifh.tempo) m_nDefaultTempo = pifh.tempo;
204 m_nSongPreAmp = pifh.mv & 0x7F;
205 // Reading Channels Pan Positions
206 for (int ipan=0; ipan<64; ipan++) if (pifh.chnpan[ipan] != 0xFF)
207 {
208 ChnSettings[ipan].nVolume = pifh.chnvol[ipan];
209 ChnSettings[ipan].nPan = 128;
210 if (pifh.chnpan[ipan] & 0x80) ChnSettings[ipan].dwFlags |= CHN_MUTE;
211 UINT n = pifh.chnpan[ipan] & 0x7F;
212 if (n <= 64) ChnSettings[ipan].nPan = n << 2;
213 if (n == 100) ChnSettings[ipan].dwFlags |= CHN_SURROUND;
214 }
215 if (m_nChannels < 4) m_nChannels = 4;
216 // Reading Song Message
217 if ((pifh.special & 0x01) && (pifh.msglength) && (pifh.msgoffset + pifh.msglength < dwMemLength))
218 {
219 m_lpszSongComments = new char[pifh.msglength+1];
220 if (m_lpszSongComments)
221 {
222 memcpy(m_lpszSongComments, lpStream+pifh.msgoffset, pifh.msglength);
223 m_lpszSongComments[pifh.msglength] = 0;
224 }
225 }
226 // Reading orders
227 UINT nordsize = pifh.ordnum;
228 if (nordsize > MAX_ORDERS) nordsize = MAX_ORDERS;
229 memcpy(Order, lpStream+dwMemPos, nordsize);
230 dwMemPos += pifh.ordnum;
231 // Reading Instrument Offsets
232 memset(inspos, 0, sizeof(inspos));
233 UINT inspossize = pifh.insnum;
234 if (inspossize > MAX_INSTRUMENTS) inspossize = MAX_INSTRUMENTS;
235 inspossize <<= 2;
236 memcpy(inspos, lpStream+dwMemPos, inspossize);
237 for (UINT j=0; j < (inspossize>>2); j++)
238 {
239 inspos[j] = bswapLE32(inspos[j]);
240 }
241 dwMemPos += pifh.insnum * 4;
242 // Reading Samples Offsets
243 memset(smppos, 0, sizeof(smppos));
244 UINT smppossize = pifh.smpnum;
245 if (smppossize > MAX_SAMPLES) smppossize = MAX_SAMPLES;
246 smppossize <<= 2;
247 memcpy(smppos, lpStream+dwMemPos, smppossize);
248 for (UINT j=0; j < (smppossize>>2); j++)
249 {
250 smppos[j] = bswapLE32(smppos[j]);
251 }
252 dwMemPos += pifh.smpnum * 4;
253 // Reading Patterns Offsets
254 memset(patpos, 0, sizeof(patpos));
255 UINT patpossize = pifh.patnum;
256 if (patpossize > MAX_PATTERNS) patpossize = MAX_PATTERNS;
257 patpossize <<= 2;
258 memcpy(patpos, lpStream+dwMemPos, patpossize);
259 for (UINT j=0; j < (patpossize>>2); j++)
260 {
261 patpos[j] = bswapLE32(patpos[j]);
262 }
263 dwMemPos += pifh.patnum * 4;
264 // Reading IT Extra Info
265 if (dwMemPos + 2 < dwMemLength)
266 {
267 UINT nflt = bswapLE16(*((WORD *)(lpStream + dwMemPos)));
268 dwMemPos += 2;
269 if (dwMemPos + nflt * 8 < dwMemLength) dwMemPos += nflt * 8;
270 }
271 // Reading Midi Output & Macros
272 if (m_dwSongFlags & SONG_EMBEDMIDICFG)
273 {
274 if (dwMemPos + sizeof(MODMIDICFG) < dwMemLength)
275 {
276 memcpy(&m_MidiCfg, lpStream+dwMemPos, sizeof(MODMIDICFG));
277 dwMemPos += sizeof(MODMIDICFG);
278 }
279 }
280 // Read pattern names: "PNAM"
281 if ((dwMemPos + 8 < dwMemLength) && (bswapLE32(*((DWORD *)(lpStream+dwMemPos))) == 0x4d414e50))
282 {
283 UINT len = bswapLE32(*((DWORD *)(lpStream+dwMemPos+4)));
284 dwMemPos += 8;
285 if ((dwMemPos + len <= dwMemLength) && (len <= MAX_PATTERNS*MAX_PATTERNNAME) && (len >= MAX_PATTERNNAME))
286 {
287 m_lpszPatternNames = new char[len];
288 if (m_lpszPatternNames)
289 {
290 m_nPatternNames = len / MAX_PATTERNNAME;
291 memcpy(m_lpszPatternNames, lpStream+dwMemPos, len);
292 }
293 dwMemPos += len;
294 }
295 }
296 // 4-channels minimum
297 m_nChannels = 4;
298 // Read channel names: "CNAM"
299 if ((dwMemPos + 8 < dwMemLength) && (bswapLE32(*((DWORD *)(lpStream+dwMemPos))) == 0x4d414e43))
300 {
301 UINT len = bswapLE32(*((DWORD *)(lpStream+dwMemPos+4)));
302 dwMemPos += 8;
303 if ((dwMemPos + len <= dwMemLength) && (len <= 64*MAX_CHANNELNAME))
304 {
305 UINT n = len / MAX_CHANNELNAME;
306 if (n > m_nChannels) m_nChannels = n;
307 for (UINT i=0; i<n; i++)
308 {
309 memcpy(ChnSettings[i].szName, (lpStream+dwMemPos+i*MAX_CHANNELNAME), MAX_CHANNELNAME);
310 ChnSettings[i].szName[MAX_CHANNELNAME-1] = 0;
311 }
312 dwMemPos += len;
313 }
314 }
315 // Read mix plugins information
316 if (dwMemPos + 8 < dwMemLength)
317 {
318 dwMemPos += LoadMixPlugins(lpStream+dwMemPos, dwMemLength-dwMemPos);
319 }
320 // Checking for unused channels
321 UINT npatterns = pifh.patnum;
322 if (npatterns > MAX_PATTERNS) npatterns = MAX_PATTERNS;
323 for (UINT patchk=0; patchk<npatterns; patchk++)
324 {
325 memset(chnmask, 0, sizeof(chnmask));
326 if ((!patpos[patchk]) || ((DWORD)patpos[patchk] + 4 >= dwMemLength)) continue;
327 UINT len = bswapLE16(*((WORD *)(lpStream+patpos[patchk])));
328 UINT rows = bswapLE16(*((WORD *)(lpStream+patpos[patchk]+2)));
329 if ((rows < 4) || (rows > 256)) continue;
330 if (patpos[patchk]+8+len > dwMemLength) continue;
331 UINT i = 0;
332 const BYTE *p = lpStream+patpos[patchk]+8;
333 UINT nrow = 0;
334 while (nrow<rows)
335 {
336 if (i >= len) break;
337 BYTE b = p[i++];
338 if (!b)
339 {
340 nrow++;
341 continue;
342 }
343 UINT ch = b & 0x7F;
344 if (ch) ch = (ch - 1) & 0x3F;
345 if (b & 0x80)
346 {
347 if (i >= len) break;
348 chnmask[ch] = p[i++];
349 }
350 // Channel used
351 if (chnmask[ch] & 0x0F)
352 {
353 if ((ch >= m_nChannels) && (ch < 64)) m_nChannels = ch+1;
354 }
355 // Note
356 if (chnmask[ch] & 1) i++;
357 // Instrument
358 if (chnmask[ch] & 2) i++;
359 // Volume
360 if (chnmask[ch] & 4) i++;
361 // Effect
362 if (chnmask[ch] & 8) i += 2;
363 if (i >= len) break;
364 }
365 }
366 // Reading Instruments
367 m_nInstruments = 0;
368 if (pifh.flags & 0x04) m_nInstruments = pifh.insnum;
369 if (m_nInstruments >= MAX_INSTRUMENTS) m_nInstruments = MAX_INSTRUMENTS-1;
370 for (UINT nins=0; nins<m_nInstruments; nins++)
371 {
372 if ((inspos[nins] > 0) && (inspos[nins] < dwMemLength - sizeof(ITOLDINSTRUMENT)))
373 {
374 INSTRUMENTHEADER *penv = new INSTRUMENTHEADER;
375 if (!penv) continue;
376 Headers[nins+1] = penv;
377 memset(penv, 0, sizeof(INSTRUMENTHEADER));
378 ITInstrToMPT(lpStream + inspos[nins], penv, pifh.cmwt);
379 }
380 }
381 // Reading Samples
382 m_nSamples = pifh.smpnum;
383 if (m_nSamples >= MAX_SAMPLES) m_nSamples = MAX_SAMPLES-1;
384 for (UINT nsmp=0; nsmp<pifh.smpnum; nsmp++) if ((smppos[nsmp]) && (smppos[nsmp] + sizeof(ITSAMPLESTRUCT) <= dwMemLength))
385 {
386 ITSAMPLESTRUCT pis = *(ITSAMPLESTRUCT *)(lpStream+smppos[nsmp]);
387 pis.id = bswapLE32(pis.id);
388 pis.length = bswapLE32(pis.length);
389 pis.loopbegin = bswapLE32(pis.loopbegin);
390 pis.loopend = bswapLE32(pis.loopend);
391 pis.C5Speed = bswapLE32(pis.C5Speed);
392 pis.susloopbegin = bswapLE32(pis.susloopbegin);
393 pis.susloopend = bswapLE32(pis.susloopend);
394 pis.samplepointer = bswapLE32(pis.samplepointer);
395
396 if (pis.id == 0x53504D49)
397 {
398 MODINSTRUMENT *pins = &Ins[nsmp+1];
399 memcpy(pins->name, pis.filename, 12);
400 pins->uFlags = 0;
401 pins->nLength = 0;
402 pins->nLoopStart = pis.loopbegin;
403 pins->nLoopEnd = pis.loopend;
404 pins->nSustainStart = pis.susloopbegin;
405 pins->nSustainEnd = pis.susloopend;
406 pins->nC4Speed = pis.C5Speed;
407 if (!pins->nC4Speed) pins->nC4Speed = 8363;
408 if (pis.C5Speed < 256) pins->nC4Speed = 256;
409 pins->nVolume = pis.vol << 2;
410 if (pins->nVolume > 256) pins->nVolume = 256;
411 pins->nGlobalVol = pis.gvl;
412 if (pins->nGlobalVol > 64) pins->nGlobalVol = 64;
413 if (pis.flags & 0x10) pins->uFlags |= CHN_LOOP;
414 if (pis.flags & 0x20) pins->uFlags |= CHN_SUSTAINLOOP;
415 if (pis.flags & 0x40) pins->uFlags |= CHN_PINGPONGLOOP;
416 if (pis.flags & 0x80) pins->uFlags |= CHN_PINGPONGSUSTAIN;
417 pins->nPan = (pis.dfp & 0x7F) << 2;
418 if (pins->nPan > 256) pins->nPan = 256;
419 if (pis.dfp & 0x80) pins->uFlags |= CHN_PANNING;
420 pins->nVibType = autovibit2xm[pis.vit & 7];
421 pins->nVibRate = pis.vis;
422 pins->nVibDepth = pis.vid & 0x7F;
423 pins->nVibSweep = (pis.vir + 3) / 4;
424 if ((pis.samplepointer) && (pis.samplepointer < dwMemLength) && (pis.length))
425 {
426 pins->nLength = pis.length;
427 if (pins->nLength > MAX_SAMPLE_LENGTH) pins->nLength = MAX_SAMPLE_LENGTH;
428 UINT flags = (pis.cvt & 1) ? RS_PCM8S : RS_PCM8U;
429 if (pis.flags & 2)
430 {
431 flags += 5;
432 if (pis.flags & 4) flags |= RSF_STEREO;
433 pins->uFlags |= CHN_16BIT;
434 // IT 2.14 16-bit packed sample ?
435 if (pis.flags & 8) flags = ((pifh.cmwt >= 0x215) && (pis.cvt & 4)) ? RS_IT21516 : RS_IT21416;
436 } else
437 {
438 if (pis.flags & 4) flags |= RSF_STEREO;
439 if (pis.cvt == 0xFF) flags = RS_ADPCM4; else
440 // IT 2.14 8-bit packed sample ?
441 if (pis.flags & 8) flags =((pifh.cmwt >= 0x215) && (pis.cvt & 4)) ? RS_IT2158 : RS_IT2148;
442 }
443 ReadSample(&Ins[nsmp+1], flags, (LPSTR)(lpStream+pis.samplepointer), dwMemLength - pis.samplepointer);
444 }
445 }
446 memcpy(m_szNames[nsmp+1], pis.name, 26);
447 }
448 // Reading Patterns
449 for (UINT npat=0; npat<npatterns; npat++)
450 {
451 if ((!patpos[npat]) || ((DWORD)patpos[npat] + 4 >= dwMemLength))
452 {
453 PatternSize[npat] = 64;
454 Patterns[npat] = AllocatePattern(64, m_nChannels);
455 continue;
456 }
457
458 UINT len = bswapLE16(*((WORD *)(lpStream+patpos[npat])));
459 UINT rows = bswapLE16(*((WORD *)(lpStream+patpos[npat]+2)));
460 if ((rows < 4) || (rows > 256)) continue;
461 if (patpos[npat]+8+len > dwMemLength) continue;
462 PatternSize[npat] = rows;
463 if ((Patterns[npat] = AllocatePattern(rows, m_nChannels)) == NULL) continue;
464 memset(lastvalue, 0, sizeof(lastvalue));
465 memset(chnmask, 0, sizeof(chnmask));
466 MODCOMMAND *m = Patterns[npat];
467 UINT i = 0;
468 const BYTE *p = lpStream+patpos[npat]+8;
469 UINT nrow = 0;
470 while (nrow<rows)
471 {
472 if (i >= len) break;
473 BYTE b = p[i++];
474 if (!b)
475 {
476 nrow++;
477 m+=m_nChannels;
478 continue;
479 }
480 UINT ch = b & 0x7F;
481 if (ch) ch = (ch - 1) & 0x3F;
482 if (b & 0x80)
483 {
484 if (i >= len) break;
485 chnmask[ch] = p[i++];
486 }
487 if ((chnmask[ch] & 0x10) && (ch < m_nChannels))
488 {
489 m[ch].note = lastvalue[ch].note;
490 }
491 if ((chnmask[ch] & 0x20) && (ch < m_nChannels))
492 {
493 m[ch].instr = lastvalue[ch].instr;
494 }
495 if ((chnmask[ch] & 0x40) && (ch < m_nChannels))
496 {
497 m[ch].volcmd = lastvalue[ch].volcmd;
498 m[ch].vol = lastvalue[ch].vol;
499 }
500 if ((chnmask[ch] & 0x80) && (ch < m_nChannels))
501 {
502 m[ch].command = lastvalue[ch].command;
503 m[ch].param = lastvalue[ch].param;
504 }
505 if (chnmask[ch] & 1)// Note
506 {
507 if (i >= len) break;
508 UINT note = p[i++];
509 if (ch < m_nChannels)
510 {
511 if (note < 0x80) note++;
512 m[ch].note = note;
513 lastvalue[ch].note = note;
514 channels_used[ch] = TRUE;
515 }
516 }
517 if (chnmask[ch] & 2)
518 {
519 if (i >= len) break;
520 UINT instr = p[i++];
521 if (ch < m_nChannels)
522 {
523 m[ch].instr = instr;
524 lastvalue[ch].instr = instr;
525 }
526 }
527 if (chnmask[ch] & 4)
528 {
529 if (i >= len) break;
530 UINT vol = p[i++];
531 if (ch < m_nChannels)
532 {
533 // 0-64: Set Volume
534 if (vol <= 64) { m[ch].volcmd = VOLCMD_VOLUME; m[ch].vol = vol; } else
535 // 128-192: Set Panning
536 if ((vol >= 128) && (vol <= 192)) { m[ch].volcmd = VOLCMD_PANNING; m[ch].vol = vol - 128; } else
537 // 65-74: Fine Volume Up
538 if (vol < 75) { m[ch].volcmd = VOLCMD_FINEVOLUP; m[ch].vol = vol - 65; } else
539 // 75-84: Fine Volume Down
540 if (vol < 85) { m[ch].volcmd = VOLCMD_FINEVOLDOWN; m[ch].vol = vol - 75; } else
541 // 85-94: Volume Slide Up
542 if (vol < 95) { m[ch].volcmd = VOLCMD_VOLSLIDEUP; m[ch].vol = vol - 85; } else
543 // 95-104: Volume Slide Down
544 if (vol < 105) { m[ch].volcmd = VOLCMD_VOLSLIDEDOWN; m[ch].vol = vol - 95; } else
545 // 105-114: Pitch Slide Up
546 if (vol < 115) { m[ch].volcmd = VOLCMD_PORTADOWN; m[ch].vol = vol - 105; } else
547 // 115-124: Pitch Slide Down
548 if (vol < 125) { m[ch].volcmd = VOLCMD_PORTAUP; m[ch].vol = vol - 115; } else
549 // 193-202: Portamento To
550 if ((vol >= 193) && (vol <= 202)) { m[ch].volcmd = VOLCMD_TONEPORTAMENTO; m[ch].vol = vol - 193; } else
551 // 203-212: Vibrato
552 if ((vol >= 203) && (vol <= 212)) { m[ch].volcmd = VOLCMD_VIBRATOSPEED; m[ch].vol = vol - 203; }
553 lastvalue[ch].volcmd = m[ch].volcmd;
554 lastvalue[ch].vol = m[ch].vol;
555 }
556 }
557 // Reading command/param
558 if (chnmask[ch] & 8)
559 {
560 if (i > len - 2) break;
561 UINT cmd = p[i++];
562 UINT param = p[i++];
563 if (ch < m_nChannels)
564 {
565 if (cmd)
566 {
567 m[ch].command = cmd;
568 m[ch].param = param;
569 S3MConvert(&m[ch], TRUE);
570 lastvalue[ch].command = m[ch].command;
571 lastvalue[ch].param = m[ch].param;
572 }
573 }
574 }
575 }
576 }
577 for (UINT ncu=0; ncu<MAX_BASECHANNELS; ncu++)
578 {
579 if (ncu>=m_nChannels)
580 {
581 ChnSettings[ncu].nVolume = 64;
582 ChnSettings[ncu].dwFlags &= ~CHN_MUTE;
583 }
584 }
585 m_nMinPeriod = 8;
586 m_nMaxPeriod = 0xF000;
587 return TRUE;
588}
589
590
591#ifndef MODPLUG_NO_FILESAVE
592//#define SAVEITTIMESTAMP
593#pragma warning(disable:4100)
594
595BOOL CSoundFile::SaveIT(LPCSTR lpszFileName, UINT nPacking)
596//---------------------------------------------------------
597{
598 DWORD dwPatNamLen, dwChnNamLen;
599 ITFILEHEADER header;
600 ITINSTRUMENT iti;
601 ITSAMPLESTRUCT itss;
602 BYTE smpcount[MAX_SAMPLES];
603 DWORD inspos[MAX_INSTRUMENTS];
604 DWORD patpos[MAX_PATTERNS];
605 DWORD smppos[MAX_SAMPLES];
606 DWORD dwPos = 0, dwHdrPos = 0, dwExtra = 2;
607 WORD patinfo[4];
608 BYTE chnmask[64];
609 BYTE buf[512];
610 MODCOMMAND lastvalue[64];
611 FILE *f;
612
613
614 if ((!lpszFileName) || ((f = fopen(lpszFileName, "wb")) == NULL)) return FALSE;
615 memset(inspos, 0, sizeof(inspos));
616 memset(patpos, 0, sizeof(patpos));
617 memset(smppos, 0, sizeof(smppos));
618 // Writing Header
619 memset(&header, 0, sizeof(header));
620 dwPatNamLen = 0;
621 dwChnNamLen = 0;
622 header.id = 0x4D504D49;
623 lstrcpyn(header.songname, m_szNames[0], 27);
624 header.reserved1 = 0x1004;
625 header.ordnum = 0;
626 while ((header.ordnum < MAX_ORDERS) && (Order[header.ordnum] < 0xFF)) header.ordnum++;
627 if (header.ordnum < MAX_ORDERS) Order[header.ordnum++] = 0xFF;
628 header.insnum = m_nInstruments;
629 header.smpnum = m_nSamples;
630 header.patnum = MAX_PATTERNS;
631 while ((header.patnum > 0) && (!Patterns[header.patnum-1])) header.patnum--;
632 header.cwtv = 0x217;
633 header.cmwt = 0x200;
634 header.flags = 0x0001;
635 header.special = 0x0006;
636 if (m_nInstruments) header.flags |= 0x04;
637 if (m_dwSongFlags & SONG_LINEARSLIDES) header.flags |= 0x08;
638 if (m_dwSongFlags & SONG_ITOLDEFFECTS) header.flags |= 0x10;
639 if (m_dwSongFlags & SONG_ITCOMPATMODE) header.flags |= 0x20;
640 if (m_dwSongFlags & SONG_EXFILTERRANGE) header.flags |= 0x1000;
641 header.globalvol = m_nDefaultGlobalVolume >> 1;
642 header.mv = m_nSongPreAmp;
643 if (header.mv < 0x20) header.mv = 0x20;
644 if (header.mv > 0x7F) header.mv = 0x7F;
645 header.speed = m_nDefaultSpeed;
646 header.tempo = m_nDefaultTempo;
647 header.sep = 128;
648 dwHdrPos = sizeof(header) + header.ordnum;
649 // Channel Pan and Volume
650 memset(header.chnpan, 0xFF, 64);
651 memset(header.chnvol, 64, 64);
652 for (UINT ich=0; ich<m_nChannels; ich++)
653 {
654 header.chnpan[ich] = ChnSettings[ich].nPan >> 2;
655 if (ChnSettings[ich].dwFlags & CHN_SURROUND) header.chnpan[ich] = 100;
656 header.chnvol[ich] = ChnSettings[ich].nVolume;
657 if (ChnSettings[ich].dwFlags & CHN_MUTE) header.chnpan[ich] |= 0x80;
658 if (ChnSettings[ich].szName[0])
659 {
660 dwChnNamLen = (ich+1) * MAX_CHANNELNAME;
661 }
662 }
663 if (dwChnNamLen) dwExtra += dwChnNamLen + 8;
664#ifdef SAVEITTIMESTAMP
665 dwExtra += 8; // Time Stamp
666#endif
667 if (m_dwSongFlags & SONG_EMBEDMIDICFG)
668 {
669 header.flags |= 0x80;
670 header.special |= 0x08;
671 dwExtra += sizeof(MODMIDICFG);
672 }
673 // Pattern Names
674 if ((m_nPatternNames) && (m_lpszPatternNames))
675 {
676 dwPatNamLen = m_nPatternNames * MAX_PATTERNNAME;
677 while ((dwPatNamLen >= MAX_PATTERNNAME) && (!m_lpszPatternNames[dwPatNamLen-MAX_PATTERNNAME])) dwPatNamLen -= MAX_PATTERNNAME;
678 if (dwPatNamLen < MAX_PATTERNNAME) dwPatNamLen = 0;
679 if (dwPatNamLen) dwExtra += dwPatNamLen + 8;
680 }
681 // Mix Plugins
682 dwExtra += SaveMixPlugins(NULL, TRUE);
683 // Comments
684 if (m_lpszSongComments)
685 {
686 header.special |= 1;
687 header.msglength = strlen(m_lpszSongComments)+1;
688 header.msgoffset = dwHdrPos + dwExtra + header.insnum*4 + header.patnum*4 + header.smpnum*4;
689 }
690 // Write file header
691 fwrite(&header, 1, sizeof(header), f);
692 fwrite(Order, 1, header.ordnum, f);
693 if (header.insnum) fwrite(inspos, 4, header.insnum, f);
694 if (header.smpnum) fwrite(smppos, 4, header.smpnum, f);
695 if (header.patnum) fwrite(patpos, 4, header.patnum, f);
696 // Writing editor history information
697 {
698#ifdef SAVEITTIMESTAMP
699 SYSTEMTIME systime;
700 FILETIME filetime;
701 WORD timestamp[4];
702 WORD nInfoEx = 1;
703 memset(timestamp, 0, sizeof(timestamp));
704 fwrite(&nInfoEx, 1, 2, f);
705 GetSystemTime(&systime);
706 SystemTimeToFileTime(&systime, &filetime);
707 FileTimeToDosDateTime(&filetime, &timestamp[0], &timestamp[1]);
708 fwrite(timestamp, 1, 8, f);
709#else
710 WORD nInfoEx = 0;
711 fwrite(&nInfoEx, 1, 2, f);
712#endif
713 }
714 // Writing midi cfg
715 if (header.flags & 0x80)
716 {
717 fwrite(&m_MidiCfg, 1, sizeof(MODMIDICFG), f);
718 }
719 // Writing pattern names
720 if (dwPatNamLen)
721 {
722 DWORD d = 0x4d414e50;
723 fwrite(&d, 1, 4, f);
724 fwrite(&dwPatNamLen, 1, 4, f);
725 fwrite(m_lpszPatternNames, 1, dwPatNamLen, f);
726 }
727 // Writing channel Names
728 if (dwChnNamLen)
729 {
730 DWORD d = 0x4d414e43;
731 fwrite(&d, 1, 4, f);
732 fwrite(&dwChnNamLen, 1, 4, f);
733 UINT nChnNames = dwChnNamLen / MAX_CHANNELNAME;
734 for (UINT inam=0; inam<nChnNames; inam++)
735 {
736 fwrite(ChnSettings[inam].szName, 1, MAX_CHANNELNAME, f);
737 }
738 }
739 // Writing mix plugins info
740 SaveMixPlugins(f, FALSE);
741 // Writing song message
742 dwPos = dwHdrPos + dwExtra + (header.insnum + header.smpnum + header.patnum) * 4;
743 if (header.special & 1)
744 {
745 dwPos += strlen(m_lpszSongComments) + 1;
746 fwrite(m_lpszSongComments, 1, strlen(m_lpszSongComments)+1, f);
747 }
748 // Writing instruments
749 for (UINT nins=1; nins<=header.insnum; nins++)
750 {
751 memset(&iti, 0, sizeof(iti));
752 iti.id = 0x49504D49;// "IMPI"
753 iti.trkvers = 0x211;
754 if (Headers[nins])
755 {
756 INSTRUMENTHEADER *penv = Headers[nins];
757 memset(smpcount, 0, sizeof(smpcount));
758 memcpy(iti.filename, penv->filename, 12);
759 memcpy(iti.name, penv->name, 26);
760 iti.mbank = penv->wMidiBank;
761 iti.mpr = penv->nMidiProgram;
762 iti.mch = penv->nMidiChannel;
763 iti.nna = penv->nNNA;
764 iti.dct = penv->nDCT;
765 iti.dca = penv->nDNA;
766 iti.fadeout = penv->nFadeOut >> 5;
767 iti.pps = penv->nPPS;
768 iti.ppc = penv->nPPC;
769 iti.gbv = (BYTE)(penv->nGlobalVol << 1);
770 iti.dfp = (BYTE)penv->nPan >> 2;
771 if (!(penv->dwFlags & ENV_SETPANNING)) iti.dfp |= 0x80;
772 iti.rv = penv->nVolSwing;
773 iti.rp = penv->nPanSwing;
774 iti.ifc = penv->nIFC;
775 iti.ifr = penv->nIFR;
776 iti.nos = 0;
777 for (UINT i=0; i<120; i++) if (penv->Keyboard[i] < MAX_SAMPLES)
778 {
779 UINT smp = penv->Keyboard[i];
780 if ((smp) && (!smpcount[smp]))
781 {
782 smpcount[smp] = 1;
783 iti.nos++;
784 }
785 iti.keyboard[i*2] = penv->NoteMap[i] - 1;
786 iti.keyboard[i*2+1] = smp;
787 }
788 // Writing Volume envelope
789 if (penv->dwFlags & ENV_VOLUME) iti.volenv.flags |= 0x01;
790 if (penv->dwFlags & ENV_VOLLOOP) iti.volenv.flags |= 0x02;
791 if (penv->dwFlags & ENV_VOLSUSTAIN) iti.volenv.flags |= 0x04;
792 if (penv->dwFlags & ENV_VOLCARRY) iti.volenv.flags |= 0x08;
793 iti.volenv.num = (BYTE)penv->nVolEnv;
794 iti.volenv.lpb = (BYTE)penv->nVolLoopStart;
795 iti.volenv.lpe = (BYTE)penv->nVolLoopEnd;
796 iti.volenv.slb = penv->nVolSustainBegin;
797 iti.volenv.sle = penv->nVolSustainEnd;
798 // Writing Panning envelope
799 if (penv->dwFlags & ENV_PANNING) iti.panenv.flags |= 0x01;
800 if (penv->dwFlags & ENV_PANLOOP) iti.panenv.flags |= 0x02;
801 if (penv->dwFlags & ENV_PANSUSTAIN) iti.panenv.flags |= 0x04;
802 if (penv->dwFlags & ENV_PANCARRY) iti.panenv.flags |= 0x08;
803 iti.panenv.num = (BYTE)penv->nPanEnv;
804 iti.panenv.lpb = (BYTE)penv->nPanLoopStart;
805 iti.panenv.lpe = (BYTE)penv->nPanLoopEnd;
806 iti.panenv.slb = penv->nPanSustainBegin;
807 iti.panenv.sle = penv->nPanSustainEnd;
808 // Writing Pitch Envelope
809 if (penv->dwFlags & ENV_PITCH) iti.pitchenv.flags |= 0x01;
810 if (penv->dwFlags & ENV_PITCHLOOP) iti.pitchenv.flags |= 0x02;
811 if (penv->dwFlags & ENV_PITCHSUSTAIN) iti.pitchenv.flags |= 0x04;
812 if (penv->dwFlags & ENV_PITCHCARRY) iti.pitchenv.flags |= 0x08;
813 if (penv->dwFlags & ENV_FILTER) iti.pitchenv.flags |= 0x80;
814 iti.pitchenv.num = (BYTE)penv->nPitchEnv;
815 iti.pitchenv.lpb = (BYTE)penv->nPitchLoopStart;
816 iti.pitchenv.lpe = (BYTE)penv->nPitchLoopEnd;
817 iti.pitchenv.slb = (BYTE)penv->nPitchSustainBegin;
818 iti.pitchenv.sle = (BYTE)penv->nPitchSustainEnd;
819 // Writing Envelopes data
820 for (UINT ev=0; ev<25; ev++)
821 {
822 iti.volenv.data[ev*3] = penv->VolEnv[ev];
823 iti.volenv.data[ev*3+1] = penv->VolPoints[ev] & 0xFF;
824 iti.volenv.data[ev*3+2] = penv->VolPoints[ev] >> 8;
825 iti.panenv.data[ev*3] = penv->PanEnv[ev] - 32;
826 iti.panenv.data[ev*3+1] = penv->PanPoints[ev] & 0xFF;
827 iti.panenv.data[ev*3+2] = penv->PanPoints[ev] >> 8;
828 iti.pitchenv.data[ev*3] = penv->PitchEnv[ev] - 32;
829 iti.pitchenv.data[ev*3+1] = penv->PitchPoints[ev] & 0xFF;
830 iti.pitchenv.data[ev*3+2] = penv->PitchPoints[ev] >> 8;
831 }
832 } else
833 // Save Empty Instrument
834 {
835 for (UINT i=0; i<120; i++) iti.keyboard[i*2] = i;
836 iti.ppc = 5*12;
837 iti.gbv = 128;
838 iti.dfp = 0x20;
839 iti.ifc = 0xFF;
840 }
841 if (!iti.nos) iti.trkvers = 0;
842 // Writing instrument
843 inspos[nins-1] = dwPos;
844 dwPos += sizeof(ITINSTRUMENT);
845 fwrite(&iti, 1, sizeof(ITINSTRUMENT), f);
846 }
847 // Writing sample headers
848 memset(&itss, 0, sizeof(itss));
849 for (UINT hsmp=0; hsmp<header.smpnum; hsmp++)
850 {
851 smppos[hsmp] = dwPos;
852 dwPos += sizeof(ITSAMPLESTRUCT);
853 fwrite(&itss, 1, sizeof(ITSAMPLESTRUCT), f);
854 }
855 // Writing Patterns
856 for (UINT npat=0; npat<header.patnum; npat++)
857 {
858 DWORD dwPatPos = dwPos;
859 UINT len;
860 if (!Patterns[npat]) continue;
861 patpos[npat] = dwPos;
862 patinfo[0] = 0;
863 patinfo[1] = PatternSize[npat];
864 patinfo[2] = 0;
865 patinfo[3] = 0;
866 // Check for empty pattern
867 if (PatternSize[npat] == 64)
868 {
869 MODCOMMAND *pzc = Patterns[npat];
870 UINT nz = PatternSize[npat] * m_nChannels;
871 for (UINT iz=0; iz<nz; iz++)
872 {
873 if ((pzc[iz].note) || (pzc[iz].instr)
874 || (pzc[iz].volcmd) || (pzc[iz].command)) break;
875 }
876 if (iz == nz)
877 {
878 patpos[npat] = 0;
879 continue;
880 }
881 }
882 fwrite(patinfo, 8, 1, f);
883 dwPos += 8;
884 memset(chnmask, 0xFF, sizeof(chnmask));
885 memset(lastvalue, 0, sizeof(lastvalue));
886 MODCOMMAND *m = Patterns[npat];
887 for (UINT row=0; row<PatternSize[npat]; row++)
888 {
889 len = 0;
890 for (UINT ch=0; ch<m_nChannels; ch++, m++)
891 {
892 BYTE b = 0;
893 UINT command = m->command;
894 UINT param = m->param;
895 UINT vol = 0xFF;
896 UINT note = m->note;
897 if (note) b |= 1;
898 if ((note) && (note < 0xFE)) note--;
899 if (m->instr) b |= 2;
900 if (m->volcmd)
901 {
902 UINT volcmd = m->volcmd;
903 switch(volcmd)
904 {
905 case VOLCMD_VOLUME: vol = m->vol; if (vol > 64) vol = 64; break;
906 case VOLCMD_PANNING: vol = m->vol + 128; if (vol > 192) vol = 192; break;
907 case VOLCMD_VOLSLIDEUP: vol = 85 + ConvertVolParam(m->vol); break;
908 case VOLCMD_VOLSLIDEDOWN:vol = 95 + ConvertVolParam(m->vol); break;
909 case VOLCMD_FINEVOLUP: vol = 65 + ConvertVolParam(m->vol); break;
910 case VOLCMD_FINEVOLDOWN:vol = 75 + ConvertVolParam(m->vol); break;
911 case VOLCMD_VIBRATO: vol = 203; break;
912 case VOLCMD_VIBRATOSPEED:vol = 203 + ConvertVolParam(m->vol); break;
913 case VOLCMD_TONEPORTAMENTO:vol = 193 + ConvertVolParam(m->vol); break;
914 case VOLCMD_PORTADOWN: vol = 105 + ConvertVolParam(m->vol); break;
915 case VOLCMD_PORTAUP: vol = 115 + ConvertVolParam(m->vol); break;
916 default: vol = 0xFF;
917 }
918 }
919 if (vol != 0xFF) b |= 4;
920 if (command)
921 {
922 S3MSaveConvert(&command, &param, TRUE);
923 if (command) b |= 8;
924 }
925 // Packing information
926 if (b)
927 {
928 // Same note ?
929 if (b & 1)
930 {
931 if ((note == lastvalue[ch].note) && (lastvalue[ch].volcmd & 1))
932 {
933 b &= ~1;
934 b |= 0x10;
935 } else
936 {
937 lastvalue[ch].note = note;
938 lastvalue[ch].volcmd |= 1;
939 }
940 }
941 // Same instrument ?
942 if (b & 2)
943 {
944 if ((m->instr == lastvalue[ch].instr) && (lastvalue[ch].volcmd & 2))
945 {
946 b &= ~2;
947 b |= 0x20;
948 } else
949 {
950 lastvalue[ch].instr = m->instr;
951 lastvalue[ch].volcmd |= 2;
952 }
953 }
954 // Same volume column byte ?
955 if (b & 4)
956 {
957 if ((vol == lastvalue[ch].vol) && (lastvalue[ch].volcmd & 4))
958 {
959 b &= ~4;
960 b |= 0x40;
961 } else
962 {
963 lastvalue[ch].vol = vol;
964 lastvalue[ch].volcmd |= 4;
965 }
966 }
967 // Same command / param ?
968 if (b & 8)
969 {
970 if ((command == lastvalue[ch].command) && (param == lastvalue[ch].param) && (lastvalue[ch].volcmd & 8))
971 {
972 b &= ~8;
973 b |= 0x80;
974 } else
975 {
976 lastvalue[ch].command = command;
977 lastvalue[ch].param = param;
978 lastvalue[ch].volcmd |= 8;
979 }
980 }
981 if (b != chnmask[ch])
982 {
983 chnmask[ch] = b;
984 buf[len++] = (ch+1) | 0x80;
985 buf[len++] = b;
986 } else
987 {
988 buf[len++] = ch+1;
989 }
990 if (b & 1) buf[len++] = note;
991 if (b & 2) buf[len++] = m->instr;
992 if (b & 4) buf[len++] = vol;
993 if (b & 8)
994 {
995 buf[len++] = command;
996 buf[len++] = param;
997 }
998 }
999 }
1000 buf[len++] = 0;
1001 dwPos += len;
1002 patinfo[0] += len;
1003 fwrite(buf, 1, len, f);
1004 }
1005 fseek(f, dwPatPos, SEEK_SET);
1006 fwrite(patinfo, 8, 1, f);
1007 fseek(f, dwPos, SEEK_SET);
1008 }
1009 // Writing Sample Data
1010 for (UINT nsmp=1; nsmp<=header.smpnum; nsmp++)
1011 {
1012 MODINSTRUMENT *psmp = &Ins[nsmp];
1013 memset(&itss, 0, sizeof(itss));
1014 memcpy(itss.filename, psmp->name, 12);
1015 memcpy(itss.name, m_szNames[nsmp], 26);
1016 itss.id = 0x53504D49;
1017 itss.gvl = (BYTE)psmp->nGlobalVol;
1018 if (m_nInstruments)
1019 {
1020 for (UINT iu=1; iu<=m_nInstruments; iu++) if (Headers[iu])
1021 {
1022 INSTRUMENTHEADER *penv = Headers[iu];
1023 for (UINT ju=0; ju<128; ju++) if (penv->Keyboard[ju] == nsmp)
1024 {
1025 itss.flags = 0x01;
1026 break;
1027 }
1028 }
1029 } else
1030 {
1031 itss.flags = 0x01;
1032 }
1033 if (psmp->uFlags & CHN_LOOP) itss.flags |= 0x10;
1034 if (psmp->uFlags & CHN_SUSTAINLOOP) itss.flags |= 0x20;
1035 if (psmp->uFlags & CHN_PINGPONGLOOP) itss.flags |= 0x40;
1036 if (psmp->uFlags & CHN_PINGPONGSUSTAIN) itss.flags |= 0x80;
1037 itss.C5Speed = psmp->nC4Speed;
1038 if (!itss.C5Speed) itss.C5Speed = 8363;
1039 itss.length = psmp->nLength;
1040 itss.loopbegin = psmp->nLoopStart;
1041 itss.loopend = psmp->nLoopEnd;
1042 itss.susloopbegin = psmp->nSustainStart;
1043 itss.susloopend = psmp->nSustainEnd;
1044 itss.vol = psmp->nVolume >> 2;
1045 itss.dfp = psmp->nPan >> 2;
1046 itss.vit = autovibxm2it[psmp->nVibType & 7];
1047 itss.vis = psmp->nVibRate;
1048 itss.vid = psmp->nVibDepth;
1049 itss.vir = (psmp->nVibSweep < 64) ? psmp->nVibSweep * 4 : 255;
1050 if (psmp->uFlags & CHN_PANNING) itss.dfp |= 0x80;
1051 if ((psmp->pSample) && (psmp->nLength)) itss.cvt = 0x01;
1052 UINT flags = RS_PCM8S;
1053#ifndef NO_PACKING
1054 if (nPacking)
1055 {
1056 if ((!(psmp->uFlags & (CHN_16BIT|CHN_STEREO)))
1057 && (CanPackSample(psmp->pSample, psmp->nLength, nPacking)))
1058 {
1059 flags = RS_ADPCM4;
1060 itss.cvt = 0xFF;
1061 }
1062 } else
1063#endif // NO_PACKING
1064 {
1065 if (psmp->uFlags & CHN_STEREO)
1066 {
1067 flags = RS_STPCM8S;
1068 itss.flags |= 0x04;
1069 }
1070 if (psmp->uFlags & CHN_16BIT)
1071 {
1072 itss.flags |= 0x02;
1073 flags = (psmp->uFlags & CHN_STEREO) ? RS_STPCM16S : RS_PCM16S;
1074 }
1075 }
1076 itss.samplepointer = dwPos;
1077 fseek(f, smppos[nsmp-1], SEEK_SET);
1078 fwrite(&itss, 1, sizeof(ITSAMPLESTRUCT), f);
1079 fseek(f, dwPos, SEEK_SET);
1080 if ((psmp->pSample) && (psmp->nLength))
1081 {
1082 dwPos += WriteSample(f, psmp, flags);
1083 }
1084 }
1085 // Updating offsets
1086 fseek(f, dwHdrPos, SEEK_SET);
1087 if (header.insnum) fwrite(inspos, 4, header.insnum, f);
1088 if (header.smpnum) fwrite(smppos, 4, header.smpnum, f);
1089 if (header.patnum) fwrite(patpos, 4, header.patnum, f);
1090 fclose(f);
1091 return TRUE;
1092}
1093
1094#pragma warning(default:4100)
1095#endif // MODPLUG_NO_FILESAVE
1096
1097//////////////////////////////////////////////////////////////////////////////
1098// IT 2.14 compression
1099
1100DWORD ITReadBits(DWORD &bitbuf, UINT &bitnum, LPBYTE &ibuf, CHAR n)
1101//-----------------------------------------------------------------
1102{
1103 DWORD retval = 0;
1104 UINT i = n;
1105
1106 if (n > 0)
1107 {
1108 do
1109 {
1110 if (!bitnum)
1111 {
1112 bitbuf = *ibuf++;
1113 bitnum = 8;
1114 }
1115 retval >>= 1;
1116 retval |= bitbuf << 31;
1117 bitbuf >>= 1;
1118 bitnum--;
1119 i--;
1120 } while (i);
1121 i = n;
1122 }
1123 return (retval >> (32-i));
1124}
1125
1126#define IT215_SUPPORT
1127void ITUnpack8Bit(signed char *pSample, DWORD dwLen, LPBYTE lpMemFile, DWORD dwMemLength, BOOL b215)
1128//-------------------------------------------------------------------------------------------
1129{
1130 signed char *pDst = pSample;
1131 LPBYTE pSrc = lpMemFile;
1132 DWORD wHdr = 0;
1133 DWORD wCount = 0;
1134 DWORD bitbuf = 0;
1135 UINT bitnum = 0;
1136 BYTE bLeft = 0, bTemp = 0, bTemp2 = 0;
1137
1138 while (dwLen)
1139 {
1140 if (!wCount)
1141 {
1142 wCount = 0x8000;
1143 wHdr = bswapLE16(*((LPWORD)pSrc));
1144 pSrc += 2;
1145 bLeft = 9;
1146 bTemp = bTemp2 = 0;
1147 bitbuf = bitnum = 0;
1148 }
1149 DWORD d = wCount;
1150 if (d > dwLen) d = dwLen;
1151 // Unpacking
1152 DWORD dwPos = 0;
1153 do
1154 {
1155 WORD wBits = (WORD)ITReadBits(bitbuf, bitnum, pSrc, bLeft);
1156 if (bLeft < 7)
1157 {
1158 DWORD i = 1 << (bLeft-1);
1159 DWORD j = wBits & 0xFFFF;
1160 if (i != j) goto UnpackByte;
1161 wBits = (WORD)(ITReadBits(bitbuf, bitnum, pSrc, 3) + 1) & 0xFF;
1162 bLeft = ((BYTE)wBits < bLeft) ? (BYTE)wBits : (BYTE)((wBits+1) & 0xFF);
1163 goto Next;
1164 }
1165 if (bLeft < 9)
1166 {
1167 WORD i = (0xFF >> (9 - bLeft)) + 4;
1168 WORD j = i - 8;
1169 if ((wBits <= j) || (wBits > i)) goto UnpackByte;
1170 wBits -= j;
1171 bLeft = ((BYTE)(wBits & 0xFF) < bLeft) ? (BYTE)(wBits & 0xFF) : (BYTE)((wBits+1) & 0xFF);
1172 goto Next;
1173 }
1174 if (bLeft >= 10) goto SkipByte;
1175 if (wBits >= 256)
1176 {
1177 bLeft = (BYTE)(wBits + 1) & 0xFF;
1178 goto Next;
1179 }
1180 UnpackByte:
1181 if (bLeft < 8)
1182 {
1183 BYTE shift = 8 - bLeft;
1184 signed char c = (signed char)(wBits << shift);
1185 c >>= shift;
1186 wBits = (WORD)c;
1187 }
1188 wBits += bTemp;
1189 bTemp = (BYTE)wBits;
1190 bTemp2 += bTemp;
1191#ifdef IT215_SUPPORT
1192 pDst[dwPos] = (b215) ? bTemp2 : bTemp;
1193#else
1194 pDst[dwPos] = bTemp;
1195#endif
1196 SkipByte:
1197 dwPos++;
1198 Next:
1199 if (pSrc >= lpMemFile+dwMemLength+1) return;
1200 } while (dwPos < d);
1201 // Move On
1202 wCount -= d;
1203 dwLen -= d;
1204 pDst += d;
1205 }
1206}
1207
1208
1209void ITUnpack16Bit(signed char *pSample, DWORD dwLen, LPBYTE lpMemFile, DWORD dwMemLength, BOOL b215)
1210//--------------------------------------------------------------------------------------------
1211{
1212 signed short *pDst = (signed short *)pSample;
1213 LPBYTE pSrc = lpMemFile;
1214 DWORD wHdr = 0;
1215 DWORD wCount = 0;
1216 DWORD bitbuf = 0;
1217 UINT bitnum = 0;
1218 BYTE bLeft = 0;
1219 signed short wTemp = 0, wTemp2 = 0;
1220
1221 while (dwLen)
1222 {
1223 if (!wCount)
1224 {
1225 wCount = 0x4000;
1226 wHdr = bswapLE16(*((LPWORD)pSrc));
1227 pSrc += 2;
1228 bLeft = 17;
1229 wTemp = wTemp2 = 0;
1230 bitbuf = bitnum = 0;
1231 }
1232 DWORD d = wCount;
1233 if (d > dwLen) d = dwLen;
1234 // Unpacking
1235 DWORD dwPos = 0;
1236 do
1237 {
1238 DWORD dwBits = ITReadBits(bitbuf, bitnum, pSrc, bLeft);
1239 if (bLeft < 7)
1240 {
1241 DWORD i = 1 << (bLeft-1);
1242 DWORD j = dwBits;
1243 if (i != j) goto UnpackByte;
1244 dwBits = ITReadBits(bitbuf, bitnum, pSrc, 4) + 1;
1245 bLeft = ((BYTE)(dwBits & 0xFF) < bLeft) ? (BYTE)(dwBits & 0xFF) : (BYTE)((dwBits+1) & 0xFF);
1246 goto Next;
1247 }
1248 if (bLeft < 17)
1249 {
1250 DWORD i = (0xFFFF >> (17 - bLeft)) + 8;
1251 DWORD j = (i - 16) & 0xFFFF;
1252 if ((dwBits <= j) || (dwBits > (i & 0xFFFF))) goto UnpackByte;
1253 dwBits -= j;
1254 bLeft = ((BYTE)(dwBits & 0xFF) < bLeft) ? (BYTE)(dwBits & 0xFF) : (BYTE)((dwBits+1) & 0xFF);
1255 goto Next;
1256 }
1257 if (bLeft >= 18) goto SkipByte;
1258 if (dwBits >= 0x10000)
1259 {
1260 bLeft = (BYTE)(dwBits + 1) & 0xFF;
1261 goto Next;
1262 }
1263 UnpackByte:
1264 if (bLeft < 16)
1265 {
1266 BYTE shift = 16 - bLeft;
1267 signed short c = (signed short)(dwBits << shift);
1268 c >>= shift;
1269 dwBits = (DWORD)c;
1270 }
1271 dwBits += wTemp;
1272 wTemp = (signed short)dwBits;
1273 wTemp2 += wTemp;
1274#ifdef IT215_SUPPORT
1275 pDst[dwPos] = (b215) ? wTemp2 : wTemp;
1276#else
1277 pDst[dwPos] = wTemp;
1278#endif
1279 SkipByte:
1280 dwPos++;
1281 Next:
1282 if (pSrc >= lpMemFile+dwMemLength+1) return;
1283 } while (dwPos < d);
1284 // Move On
1285 wCount -= d;
1286 dwLen -= d;
1287 pDst += d;
1288 if (pSrc >= lpMemFile+dwMemLength) break;
1289 }
1290}
1291
1292
1293UINT CSoundFile::SaveMixPlugins(FILE *f, BOOL bUpdate)
1294//----------------------------------------------------
1295{
1296 DWORD chinfo[64];
1297 CHAR s[32];
1298 DWORD nPluginSize;
1299 UINT nTotalSize = 0;
1300 UINT nChInfo = 0;
1301
1302 for (UINT i=0; i<MAX_MIXPLUGINS; i++)
1303 {
1304 PSNDMIXPLUGIN p = &m_MixPlugins[i];
1305 if ((p->Info.dwPluginId1) || (p->Info.dwPluginId2))
1306 {
1307 nPluginSize = sizeof(SNDMIXPLUGININFO)+4; // plugininfo+4 (datalen)
1308 if ((p->pMixPlugin) && (bUpdate))
1309 {
1310 p->pMixPlugin->SaveAllParameters();
1311 }
1312 if (p->pPluginData)
1313 {
1314 nPluginSize += p->nPluginDataSize;
1315 }
1316 if (f)
1317 {
1318 s[0] = 'F';
1319 s[1] = 'X';
1320 s[2] = '0' + (i/10);
1321 s[3] = '0' + (i%10);
1322 fwrite(s, 1, 4, f);
1323 fwrite(&nPluginSize, 1, 4, f);
1324 fwrite(&p->Info, 1, sizeof(SNDMIXPLUGININFO), f);
1325 fwrite(&m_MixPlugins[i].nPluginDataSize, 1, 4, f);
1326 if (m_MixPlugins[i].pPluginData)
1327 {
1328 fwrite(m_MixPlugins[i].pPluginData, 1, m_MixPlugins[i].nPluginDataSize, f);
1329 }
1330 }
1331 nTotalSize += nPluginSize + 8;
1332 }
1333 }
1334 for (UINT j=0; j<m_nChannels; j++)
1335 {
1336 if (j < 64)
1337 {
1338 if ((chinfo[j] = ChnSettings[j].nMixPlugin) != 0)
1339 {
1340 nChInfo = j+1;
1341 }
1342 }
1343 }
1344 if (nChInfo)
1345 {
1346 if (f)
1347 {
1348 nPluginSize = 0x58464843;
1349 fwrite(&nPluginSize, 1, 4, f);
1350 nPluginSize = nChInfo*4;
1351 fwrite(&nPluginSize, 1, 4, f);
1352 fwrite(chinfo, 1, nPluginSize, f);
1353 }
1354 nTotalSize += nChInfo*4 + 8;
1355 }
1356 return nTotalSize;
1357}
1358
1359
1360UINT CSoundFile::LoadMixPlugins(const void *pData, UINT nLen)
1361//-----------------------------------------------------------
1362{
1363 const BYTE *p = (const BYTE *)pData;
1364 UINT nPos = 0;
1365
1366 while (nPos+8 < nLen)
1367 {
1368 DWORD nPluginSize;
1369 UINT nPlugin;
1370
1371 nPluginSize = bswapLE32(*(DWORD *)(p+nPos+4));
1372 if (nPluginSize > nLen-nPos-8) break;;
1373 if ((bswapLE32(*(DWORD *)(p+nPos))) == 0x58464843)
1374 {
1375 for (UINT ch=0; ch<64; ch++) if (ch*4 < nPluginSize)
1376 {
1377 ChnSettings[ch].nMixPlugin = bswapLE32(*(DWORD *)(p+nPos+8+ch*4));
1378 }
1379 } else
1380 {
1381 if ((p[nPos] != 'F') || (p[nPos+1] != 'X')
1382 || (p[nPos+2] < '0') || (p[nPos+3] < '0'))
1383 {
1384 break;
1385 }
1386 nPlugin = (p[nPos+2]-'0')*10 + (p[nPos+3]-'0');
1387 if ((nPlugin < MAX_MIXPLUGINS) && (nPluginSize >= sizeof(SNDMIXPLUGININFO)+4))
1388 {
1389 DWORD dwExtra = bswapLE32(*(DWORD *)(p+nPos+8+sizeof(SNDMIXPLUGININFO)));
1390 m_MixPlugins[nPlugin].Info = *(const SNDMIXPLUGININFO *)(p+nPos+8);
1391 m_MixPlugins[nPlugin].Info.dwPluginId1 = bswapLE32(m_MixPlugins[nPlugin].Info.dwPluginId1);
1392 m_MixPlugins[nPlugin].Info.dwPluginId2 = bswapLE32(m_MixPlugins[nPlugin].Info.dwPluginId2);
1393 m_MixPlugins[nPlugin].Info.dwInputRouting = bswapLE32(m_MixPlugins[nPlugin].Info.dwInputRouting);
1394 m_MixPlugins[nPlugin].Info.dwOutputRouting = bswapLE32(m_MixPlugins[nPlugin].Info.dwOutputRouting);
1395 for (UINT j=0; j<4; j++)
1396 {
1397 m_MixPlugins[nPlugin].Info.dwReserved[j] = bswapLE32(m_MixPlugins[nPlugin].Info.dwReserved[j]);
1398 }
1399 if ((dwExtra) && (dwExtra <= nPluginSize-sizeof(SNDMIXPLUGININFO)-4))
1400 {
1401 m_MixPlugins[nPlugin].nPluginDataSize = 0;
1402 m_MixPlugins[nPlugin].pPluginData = new signed char [dwExtra];
1403 if (m_MixPlugins[nPlugin].pPluginData)
1404 {
1405 m_MixPlugins[nPlugin].nPluginDataSize = dwExtra;
1406 memcpy(m_MixPlugins[nPlugin].pPluginData, p+nPos+8+sizeof(SNDMIXPLUGININFO)+4, dwExtra);
1407 }
1408 }
1409 }
1410 }
1411 nPos += nPluginSize + 8;
1412 }
1413 return nPos;
1414}
1415