summaryrefslogtreecommitdiff
path: root/core/multimedia/opieplayer/modplug/load_xm.cpp
Unidiff
Diffstat (limited to 'core/multimedia/opieplayer/modplug/load_xm.cpp') (more/less context) (ignore whitespace changes)
-rw-r--r--core/multimedia/opieplayer/modplug/load_xm.cpp912
1 files changed, 912 insertions, 0 deletions
diff --git a/core/multimedia/opieplayer/modplug/load_xm.cpp b/core/multimedia/opieplayer/modplug/load_xm.cpp
new file mode 100644
index 0000000..171e5f6
--- a/dev/null
+++ b/core/multimedia/opieplayer/modplug/load_xm.cpp
@@ -0,0 +1,912 @@
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
14////////////////////////////////////////////////////////
15// FastTracker II XM file support
16
17#ifdef WIN32
18#pragma warning(disable:4244)
19#endif
20
21#pragma pack(1)
22typedef struct tagXMFILEHEADER
23{
24 DWORD size;
25 WORD norder;
26 WORD restartpos;
27 WORD channels;
28 WORD patterns;
29 WORD instruments;
30 WORD flags;
31 WORD speed;
32 WORD tempo;
33 BYTE order[256];
34} Q_PACKED XMFILEHEADER;
35
36
37typedef struct tagXMINSTRUMENTHEADER
38{
39 DWORD size;
40 CHAR name[22];
41 BYTE type;
42 BYTE samples;
43 BYTE samplesh;
44} Q_PACKED XMINSTRUMENTHEADER;
45
46
47typedef struct tagXMSAMPLEHEADER
48{
49 DWORD shsize;
50 BYTE snum[96];
51 WORD venv[24];
52 WORD penv[24];
53 BYTE vnum, pnum;
54 BYTE vsustain, vloops, vloope, psustain, ploops, ploope;
55 BYTE vtype, ptype;
56 BYTE vibtype, vibsweep, vibdepth, vibrate;
57 WORD volfade;
58 WORD res;
59 BYTE reserved1[20];
60} Q_PACKED XMSAMPLEHEADER;
61
62typedef struct tagXMSAMPLESTRUCT
63{
64 DWORD samplen;
65 DWORD loopstart;
66 DWORD looplen;
67 BYTE vol;
68 signed char finetune;
69 BYTE type;
70 BYTE pan;
71 signed char relnote;
72 BYTE res;
73 char name[22];
74} Q_PACKED XMSAMPLESTRUCT;
75
76typedef struct tagXMPATTERNHEADER
77{
78 DWORD size;
79 BYTE packing;
80 WORD rows;
81 WORD packsize;
82} Q_PACKED XMPATTERNHEADER;
83
84#pragma pack()
85
86
87BOOL CSoundFile::ReadXM(const BYTE *lpStream, DWORD dwMemLength)
88//--------------------------------------------------------------
89{
90 XMSAMPLEHEADER xmsh;
91 XMSAMPLESTRUCT xmss;
92 DWORD dwMemPos, dwHdrSize;
93 WORD norders=0, restartpos=0, channels=0, patterns=0, instruments=0;
94 WORD xmflags=0, deftempo=125, defspeed=6;
95 BOOL InstUsed[256];
96 BYTE channels_used[MAX_CHANNELS];
97 BYTE pattern_map[256];
98 BOOL samples_used[MAX_SAMPLES];
99 UINT unused_samples;
100
101 m_nChannels = 0;
102 if ((!lpStream) || (dwMemLength < 0x200)) return FALSE;
103 if (strnicmp((LPCSTR)lpStream, "Extended Module", 15)) return FALSE;
104
105 memcpy(m_szNames[0], lpStream+17, 20);
106 dwHdrSize = bswapLE32(*((DWORD *)(lpStream+60)));
107 norders = bswapLE16(*((WORD *)(lpStream+64)));
108 if ((!norders) || (norders > MAX_ORDERS)) return FALSE;
109 restartpos = bswapLE16(*((WORD *)(lpStream+66)));
110 channels = bswapLE16(*((WORD *)(lpStream+68)));
111 if ((!channels) || (channels > 64)) return FALSE;
112 m_nType = MOD_TYPE_XM;
113 m_nMinPeriod = 27;
114 m_nMaxPeriod = 54784;
115 m_nChannels = channels;
116 if (restartpos < norders) m_nRestartPos = restartpos;
117 patterns = bswapLE16(*((WORD *)(lpStream+70)));
118 if (patterns > 256) patterns = 256;
119 instruments = bswapLE16(*((WORD *)(lpStream+72)));
120 if (instruments >= MAX_INSTRUMENTS) instruments = MAX_INSTRUMENTS-1;
121 m_nInstruments = instruments;
122 m_nSamples = 0;
123 memcpy(&xmflags, lpStream+74, 2);
124 xmflags = bswapLE16(xmflags);
125 if (xmflags & 1) m_dwSongFlags |= SONG_LINEARSLIDES;
126 if (xmflags & 0x1000) m_dwSongFlags |= SONG_EXFILTERRANGE;
127 defspeed = bswapLE16(*((WORD *)(lpStream+76)));
128 deftempo = bswapLE16(*((WORD *)(lpStream+78)));
129 if ((deftempo >= 32) && (deftempo < 256)) m_nDefaultTempo = deftempo;
130 if ((defspeed > 0) && (defspeed < 40)) m_nDefaultSpeed = defspeed;
131 memcpy(Order, lpStream+80, norders);
132 memset(InstUsed, 0, sizeof(InstUsed));
133 if (patterns > MAX_PATTERNS)
134 {
135 UINT i, j;
136 for (i=0; i<norders; i++)
137 {
138 if (Order[i] < patterns) InstUsed[Order[i]] = TRUE;
139 }
140 j = 0;
141 for (i=0; i<256; i++)
142 {
143 if (InstUsed[i]) pattern_map[i] = j++;
144 }
145 for (i=0; i<256; i++)
146 {
147 if (!InstUsed[i])
148 {
149 pattern_map[i] = (j < MAX_PATTERNS) ? j : 0xFE;
150 j++;
151 }
152 }
153 for (i=0; i<norders; i++)
154 {
155 Order[i] = pattern_map[Order[i]];
156 }
157 } else
158 {
159 for (UINT i=0; i<256; i++) pattern_map[i] = i;
160 }
161 memset(InstUsed, 0, sizeof(InstUsed));
162 dwMemPos = dwHdrSize + 60;
163 if (dwMemPos + 8 >= dwMemLength) return TRUE;
164 // Reading patterns
165 memset(channels_used, 0, sizeof(channels_used));
166 for (UINT ipat=0; ipat<patterns; ipat++)
167 {
168 UINT ipatmap = pattern_map[ipat];
169 DWORD dwSize = 0;
170 WORD rows=64, packsize=0;
171 XMPATTERNHEADER *patternHeader = (XMPATTERNHEADER *)(lpStream+dwMemPos);
172 //dwSize = bswapLE32(*((DWORD *)(lpStream+dwMemPos)));
173 dwSize = bswapLE32(patternHeader->size);
174 /*
175 while ((dwMemPos + dwSize >= dwMemLength) || (dwSize & 0xFFFFFF00))
176 {
177 if (dwMemPos + 4 >= dwMemLength) break;
178 dwMemPos++;
179 dwSize = bswapLE32(*((DWORD *)(lpStream+dwMemPos)));
180 }
181 */
182 //rows = bswapLE16(*((WORD *)(lpStream+dwMemPos+5)));
183 rows = bswapLE16(patternHeader->rows);
184 if ((!rows) || (rows > 256)) rows = 64;
185 //packsize = bswapLE16(*((WORD *)(lpStream+dwMemPos+7)));
186 packsize = bswapLE16(patternHeader->packsize);
187 if (dwMemPos + dwSize + 4 > dwMemLength) return TRUE;
188 dwMemPos += dwSize;
189 if (dwMemPos + packsize + 4 > dwMemLength) return TRUE;
190 MODCOMMAND *p;
191 if (ipatmap < MAX_PATTERNS)
192 {
193 PatternSize[ipatmap] = rows;
194 if ((Patterns[ipatmap] = AllocatePattern(rows, m_nChannels)) == NULL) return TRUE;
195 if (!packsize) continue;
196 p = Patterns[ipatmap];
197 } else p = NULL;
198 const BYTE *src = lpStream+dwMemPos;
199 UINT j=0;
200 for (UINT row=0; row<rows; row++)
201 {
202 for (UINT chn=0; chn<m_nChannels; chn++)
203 {
204 if ((p) && (j < packsize))
205 {
206 BYTE b = src[j++];
207 UINT vol = 0;
208 if (b & 0x80)
209 {
210 if (b & 1) p->note = src[j++];
211 if (b & 2) p->instr = src[j++];
212 if (b & 4) vol = src[j++];
213 if (b & 8) p->command = src[j++];
214 if (b & 16) p->param = src[j++];
215 } else
216 {
217 p->note = b;
218 p->instr = src[j++];
219 vol = src[j++];
220 p->command = src[j++];
221 p->param = src[j++];
222 }
223 if (p->note == 97) p->note = 0xFF; else
224 if ((p->note) && (p->note < 97)) p->note += 12;
225 if (p->note) channels_used[chn] = 1;
226 if (p->command | p->param) ConvertModCommand(p);
227 if (p->instr == 0xff) p->instr = 0;
228 if (p->instr) InstUsed[p->instr] = TRUE;
229 if ((vol >= 0x10) && (vol <= 0x50))
230 {
231 p->volcmd = VOLCMD_VOLUME;
232 p->vol = vol - 0x10;
233 } else
234 if (vol >= 0x60)
235 {
236 UINT v = vol & 0xF0;
237 vol &= 0x0F;
238 p->vol = vol;
239 switch(v)
240 {
241 // 60-6F: Volume Slide Down
242 case 0x60:p->volcmd = VOLCMD_VOLSLIDEDOWN; break;
243 // 70-7F: Volume Slide Up:
244 case 0x70:p->volcmd = VOLCMD_VOLSLIDEUP; break;
245 // 80-8F: Fine Volume Slide Down
246 case 0x80:p->volcmd = VOLCMD_FINEVOLDOWN; break;
247 // 90-9F: Fine Volume Slide Up
248 case 0x90:p->volcmd = VOLCMD_FINEVOLUP; break;
249 // A0-AF: Set Vibrato Speed
250 case 0xA0:p->volcmd = VOLCMD_VIBRATOSPEED; break;
251 // B0-BF: Vibrato
252 case 0xB0:p->volcmd = VOLCMD_VIBRATO; break;
253 // C0-CF: Set Panning
254 case 0xC0:p->volcmd = VOLCMD_PANNING; p->vol = (vol << 2) + 2; break;
255 // D0-DF: Panning Slide Left
256 case 0xD0:p->volcmd = VOLCMD_PANSLIDELEFT; break;
257 // E0-EF: Panning Slide Right
258 case 0xE0:p->volcmd = VOLCMD_PANSLIDERIGHT; break;
259 // F0-FF: Tone Portamento
260 case 0xF0:p->volcmd = VOLCMD_TONEPORTAMENTO; break;
261 }
262 }
263 p++;
264 } else
265 if (j < packsize)
266 {
267 BYTE b = src[j++];
268 if (b & 0x80)
269 {
270 if (b & 1) j++;
271 if (b & 2) j++;
272 if (b & 4) j++;
273 if (b & 8) j++;
274 if (b & 16) j++;
275 } else j += 4;
276 } else break;
277 }
278 }
279 dwMemPos += packsize;
280 }
281 /*
282 // Wrong offset check
283 while (dwMemPos + 4 < dwMemLength)
284 {
285 DWORD d = bswapLE32(*((DWORD *)(lpStream+dwMemPos)));
286 if (d < 0x300) break;
287 dwMemPos++;
288 }
289 */
290 memset(samples_used, 0, sizeof(samples_used));
291 unused_samples = 0;
292 // Reading instruments
293 for (UINT iIns=1; iIns<=instruments; iIns++)
294 {
295 XMINSTRUMENTHEADER *pih;
296 BYTE flags[32];
297 DWORD samplesize[32];
298 UINT samplemap[32];
299 WORD nsamples;
300
301 if (dwMemPos + sizeof(XMINSTRUMENTHEADER) >= dwMemLength) return TRUE;
302 pih = (XMINSTRUMENTHEADER *)(lpStream+dwMemPos);
303 if (dwMemPos + bswapLE32(pih->size) > dwMemLength) return TRUE;
304 if ((Headers[iIns] = new INSTRUMENTHEADER) == NULL) continue;
305 memset(Headers[iIns], 0, sizeof(INSTRUMENTHEADER));
306 memcpy(Headers[iIns]->name, pih->name, 22);
307 if ((nsamples = pih->samples) > 0)
308 {
309 if (dwMemPos + sizeof(XMSAMPLEHEADER) > dwMemLength) return TRUE;
310 memcpy(&xmsh, lpStream+dwMemPos+sizeof(XMINSTRUMENTHEADER), sizeof(XMSAMPLEHEADER));
311 xmsh.shsize = bswapLE32(xmsh.shsize);
312 for (int i = 0; i < 24; ++i) {
313 xmsh.venv[i] = bswapLE16(xmsh.venv[i]);
314 xmsh.penv[i] = bswapLE16(xmsh.penv[i]);
315 }
316 xmsh.volfade = bswapLE16(xmsh.volfade);
317 xmsh.res = bswapLE16(xmsh.res);
318 dwMemPos += bswapLE32(pih->size);
319 } else
320 {
321 if (bswapLE32(pih->size)) dwMemPos += bswapLE32(pih->size);
322 else dwMemPos += sizeof(XMINSTRUMENTHEADER);
323 continue;
324 }
325 memset(samplemap, 0, sizeof(samplemap));
326 if (nsamples > 32) return TRUE;
327 UINT newsamples = m_nSamples;
328 for (UINT nmap=0; nmap<nsamples; nmap++)
329 {
330 UINT n = m_nSamples+nmap+1;
331 if (n >= MAX_SAMPLES)
332 {
333 n = m_nSamples;
334 while (n > 0)
335 {
336 if (!Ins[n].pSample)
337 {
338 for (UINT xmapchk=0; xmapchk < nmap; xmapchk++)
339 {
340 if (samplemap[xmapchk] == n) goto alreadymapped;
341 }
342 for (UINT clrs=1; clrs<iIns; clrs++) if (Headers[clrs])
343 {
344 INSTRUMENTHEADER *pks = Headers[clrs];
345 for (UINT ks=0; ks<128; ks++)
346 {
347 if (pks->Keyboard[ks] == n) pks->Keyboard[ks] = 0;
348 }
349 }
350 break;
351 }
352 alreadymapped:
353 n--;
354 }
355#ifndef FASTSOUNDLIB
356 // Damn! more than 200 samples: look for duplicates
357 if (!n)
358 {
359 if (!unused_samples)
360 {
361 unused_samples = DetectUnusedSamples(samples_used);
362 if (!unused_samples) unused_samples = 0xFFFF;
363 }
364 if ((unused_samples) && (unused_samples != 0xFFFF))
365 {
366 for (UINT iext=m_nSamples; iext>=1; iext--) if (!samples_used[iext])
367 {
368 unused_samples--;
369 samples_used[iext] = TRUE;
370 DestroySample(iext);
371 n = iext;
372 for (UINT mapchk=0; mapchk<nmap; mapchk++)
373 {
374 if (samplemap[mapchk] == n) samplemap[mapchk] = 0;
375 }
376 for (UINT clrs=1; clrs<iIns; clrs++) if (Headers[clrs])
377 {
378 INSTRUMENTHEADER *pks = Headers[clrs];
379 for (UINT ks=0; ks<128; ks++)
380 {
381 if (pks->Keyboard[ks] == n) pks->Keyboard[ks] = 0;
382 }
383 }
384 memset(&Ins[n], 0, sizeof(Ins[0]));
385 break;
386 }
387 }
388 }
389#endif // FASTSOUNDLIB
390 }
391 if (newsamples < n) newsamples = n;
392 samplemap[nmap] = n;
393 }
394 m_nSamples = newsamples;
395 // Reading Volume Envelope
396 INSTRUMENTHEADER *penv = Headers[iIns];
397 penv->nMidiProgram = pih->type;
398 penv->nFadeOut = xmsh.volfade;
399 penv->nPan = 128;
400 penv->nPPC = 5*12;
401 if (xmsh.vtype & 1) penv->dwFlags |= ENV_VOLUME;
402 if (xmsh.vtype & 2) penv->dwFlags |= ENV_VOLSUSTAIN;
403 if (xmsh.vtype & 4) penv->dwFlags |= ENV_VOLLOOP;
404 if (xmsh.ptype & 1) penv->dwFlags |= ENV_PANNING;
405 if (xmsh.ptype & 2) penv->dwFlags |= ENV_PANSUSTAIN;
406 if (xmsh.ptype & 4) penv->dwFlags |= ENV_PANLOOP;
407 if (xmsh.vnum > 12) xmsh.vnum = 12;
408 if (xmsh.pnum > 12) xmsh.pnum = 12;
409 penv->nVolEnv = xmsh.vnum;
410 if (!xmsh.vnum) penv->dwFlags &= ~ENV_VOLUME;
411 if (!xmsh.pnum) penv->dwFlags &= ~ENV_PANNING;
412 penv->nPanEnv = xmsh.pnum;
413 penv->nVolSustainBegin = penv->nVolSustainEnd = xmsh.vsustain;
414 if (xmsh.vsustain >= 12) penv->dwFlags &= ~ENV_VOLSUSTAIN;
415 penv->nVolLoopStart = xmsh.vloops;
416 penv->nVolLoopEnd = xmsh.vloope;
417 if (penv->nVolLoopEnd >= 12) penv->nVolLoopEnd = 0;
418 if (penv->nVolLoopStart >= penv->nVolLoopEnd) penv->dwFlags &= ~ENV_VOLLOOP;
419 penv->nPanSustainBegin = penv->nPanSustainEnd = xmsh.psustain;
420 if (xmsh.psustain >= 12) penv->dwFlags &= ~ENV_PANSUSTAIN;
421 penv->nPanLoopStart = xmsh.ploops;
422 penv->nPanLoopEnd = xmsh.ploope;
423 if (penv->nPanLoopEnd >= 12) penv->nPanLoopEnd = 0;
424 if (penv->nPanLoopStart >= penv->nPanLoopEnd) penv->dwFlags &= ~ENV_PANLOOP;
425 penv->nGlobalVol = 64;
426 for (UINT ienv=0; ienv<12; ienv++)
427 {
428 penv->VolPoints[ienv] = (WORD)xmsh.venv[ienv*2];
429 penv->VolEnv[ienv] = (BYTE)xmsh.venv[ienv*2+1];
430 penv->PanPoints[ienv] = (WORD)xmsh.penv[ienv*2];
431 penv->PanEnv[ienv] = (BYTE)xmsh.penv[ienv*2+1];
432 if (ienv)
433 {
434 if (penv->VolPoints[ienv] < penv->VolPoints[ienv-1])
435 {
436 penv->VolPoints[ienv] &= 0xFF;
437 penv->VolPoints[ienv] += penv->VolPoints[ienv-1] & 0xFF00;
438 if (penv->VolPoints[ienv] < penv->VolPoints[ienv-1]) penv->VolPoints[ienv] += 0x100;
439 }
440 if (penv->PanPoints[ienv] < penv->PanPoints[ienv-1])
441 {
442 penv->PanPoints[ienv] &= 0xFF;
443 penv->PanPoints[ienv] += penv->PanPoints[ienv-1] & 0xFF00;
444 if (penv->PanPoints[ienv] < penv->PanPoints[ienv-1]) penv->PanPoints[ienv] += 0x100;
445 }
446 }
447 }
448 for (UINT j=0; j<96; j++)
449 {
450 penv->NoteMap[j+12] = j+1+12;
451 if (xmsh.snum[j] < nsamples)
452 penv->Keyboard[j+12] = samplemap[xmsh.snum[j]];
453 }
454 // Reading samples
455 for (UINT ins=0; ins<nsamples; ins++)
456 {
457 if ((dwMemPos + sizeof(xmss) > dwMemLength)
458 || (dwMemPos + xmsh.shsize > dwMemLength)) return TRUE;
459 memcpy(&xmss, lpStream+dwMemPos, sizeof(xmss));
460 xmss.samplen = bswapLE32(xmss.samplen);
461 xmss.loopstart = bswapLE32(xmss.loopstart);
462 xmss.looplen = bswapLE32(xmss.looplen);
463 dwMemPos += xmsh.shsize;
464 flags[ins] = (xmss.type & 0x10) ? RS_PCM16D : RS_PCM8D;
465 if (xmss.type & 0x20) flags[ins] = (xmss.type & 0x10) ? RS_STPCM16D : RS_STPCM8D;
466 samplesize[ins] = xmss.samplen;
467 if (!samplemap[ins]) continue;
468 if (xmss.type & 0x10)
469 {
470 xmss.looplen >>= 1;
471 xmss.loopstart >>= 1;
472 xmss.samplen >>= 1;
473 }
474 if (xmss.type & 0x20)
475 {
476 xmss.looplen >>= 1;
477 xmss.loopstart >>= 1;
478 xmss.samplen >>= 1;
479 }
480 if (xmss.samplen > MAX_SAMPLE_LENGTH) xmss.samplen = MAX_SAMPLE_LENGTH;
481 if (xmss.loopstart >= xmss.samplen) xmss.type &= ~3;
482 xmss.looplen += xmss.loopstart;
483 if (xmss.looplen > xmss.samplen) xmss.looplen = xmss.samplen;
484 if (!xmss.looplen) xmss.type &= ~3;
485 UINT imapsmp = samplemap[ins];
486 memcpy(m_szNames[imapsmp], xmss.name, 22);
487 m_szNames[imapsmp][22] = 0;
488 MODINSTRUMENT *pins = &Ins[imapsmp];
489 pins->nLength = (xmss.samplen > MAX_SAMPLE_LENGTH) ? MAX_SAMPLE_LENGTH : xmss.samplen;
490 pins->nLoopStart = xmss.loopstart;
491 pins->nLoopEnd = xmss.looplen;
492 if (pins->nLoopEnd > pins->nLength) pins->nLoopEnd = pins->nLength;
493 if (pins->nLoopStart >= pins->nLoopEnd)
494 {
495 pins->nLoopStart = pins->nLoopEnd = 0;
496 }
497 if (xmss.type & 3) pins->uFlags |= CHN_LOOP;
498 if (xmss.type & 2) pins->uFlags |= CHN_PINGPONGLOOP;
499 pins->nVolume = xmss.vol << 2;
500 if (pins->nVolume > 256) pins->nVolume = 256;
501 pins->nGlobalVol = 64;
502 if ((xmss.res == 0xAD) && (!(xmss.type & 0x30)))
503 {
504 flags[ins] = RS_ADPCM4;
505 samplesize[ins] = (samplesize[ins]+1)/2 + 16;
506 }
507 pins->nFineTune = xmss.finetune;
508 pins->RelativeTone = (int)xmss.relnote;
509 pins->nPan = xmss.pan;
510 pins->uFlags |= CHN_PANNING;
511 pins->nVibType = xmsh.vibtype;
512 pins->nVibSweep = xmsh.vibsweep;
513 pins->nVibDepth = xmsh.vibdepth;
514 pins->nVibRate = xmsh.vibrate;
515 memcpy(pins->name, xmss.name, 22);
516 pins->name[21] = 0;
517 }
518#if 0
519 if ((xmsh.reserved2 > nsamples) && (xmsh.reserved2 <= 16))
520 {
521 dwMemPos += (((UINT)xmsh.reserved2) - nsamples) * xmsh.shsize;
522 }
523#endif
524 for (UINT ismpd=0; ismpd<nsamples; ismpd++)
525 {
526 if ((samplemap[ismpd]) && (samplesize[ismpd]) && (dwMemPos < dwMemLength))
527 {
528 ReadSample(&Ins[samplemap[ismpd]], flags[ismpd], (LPSTR)(lpStream + dwMemPos), dwMemLength - dwMemPos);
529 }
530 dwMemPos += samplesize[ismpd];
531 if (dwMemPos >= dwMemLength) break;
532 }
533 }
534 // Read song comments: "TEXT"
535 if ((dwMemPos + 8 < dwMemLength) && (bswapLE32(*((DWORD *)(lpStream+dwMemPos))) == 0x74786574))
536 {
537 UINT len = *((DWORD *)(lpStream+dwMemPos+4));
538 dwMemPos += 8;
539 if ((dwMemPos + len <= dwMemLength) && (len < 16384))
540 {
541 m_lpszSongComments = new char[len+1];
542 if (m_lpszSongComments)
543 {
544 memcpy(m_lpszSongComments, lpStream+dwMemPos, len);
545 m_lpszSongComments[len] = 0;
546 }
547 dwMemPos += len;
548 }
549 }
550 // Read midi config: "MIDI"
551 if ((dwMemPos + 8 < dwMemLength) && (bswapLE32(*((DWORD *)(lpStream+dwMemPos))) == 0x4944494D))
552 {
553 UINT len = *((DWORD *)(lpStream+dwMemPos+4));
554 dwMemPos += 8;
555 if (len == sizeof(MODMIDICFG))
556 {
557 memcpy(&m_MidiCfg, lpStream+dwMemPos, len);
558 m_dwSongFlags |= SONG_EMBEDMIDICFG;
559 }
560 }
561 // Read pattern names: "PNAM"
562 if ((dwMemPos + 8 < dwMemLength) && (bswapLE32(*((DWORD *)(lpStream+dwMemPos))) == 0x4d414e50))
563 {
564 UINT len = *((DWORD *)(lpStream+dwMemPos+4));
565 dwMemPos += 8;
566 if ((dwMemPos + len <= dwMemLength) && (len <= MAX_PATTERNS*MAX_PATTERNNAME) && (len >= MAX_PATTERNNAME))
567 {
568 m_lpszPatternNames = new char[len];
569
570 if (m_lpszPatternNames)
571 {
572 m_nPatternNames = len / MAX_PATTERNNAME;
573 memcpy(m_lpszPatternNames, lpStream+dwMemPos, len);
574 }
575 dwMemPos += len;
576 }
577 }
578 // Read channel names: "CNAM"
579 if ((dwMemPos + 8 < dwMemLength) && (bswapLE32(*((DWORD *)(lpStream+dwMemPos))) == 0x4d414e43))
580 {
581 UINT len = *((DWORD *)(lpStream+dwMemPos+4));
582 dwMemPos += 8;
583 if ((dwMemPos + len <= dwMemLength) && (len <= MAX_BASECHANNELS*MAX_CHANNELNAME))
584 {
585 UINT n = len / MAX_CHANNELNAME;
586 for (UINT i=0; i<n; i++)
587 {
588 memcpy(ChnSettings[i].szName, (lpStream+dwMemPos+i*MAX_CHANNELNAME), MAX_CHANNELNAME);
589 ChnSettings[i].szName[MAX_CHANNELNAME-1] = 0;
590 }
591 dwMemPos += len;
592 }
593 }
594 // Read mix plugins information
595 if (dwMemPos + 8 < dwMemLength)
596 {
597 dwMemPos += LoadMixPlugins(lpStream+dwMemPos, dwMemLength-dwMemPos);
598 }
599 return TRUE;
600}
601
602
603#ifndef MODPLUG_NO_FILESAVE
604
605BOOL CSoundFile::SaveXM(LPCSTR lpszFileName, UINT nPacking)
606//---------------------------------------------------------
607{
608 BYTE s[64*64*5];
609 XMFILEHEADER header;
610 XMINSTRUMENTHEADER xmih;
611 XMSAMPLEHEADER xmsh;
612 XMSAMPLESTRUCT xmss;
613 BYTE smptable[32];
614 BYTE xmph[9];
615 FILE *f;
616 int i;
617
618 if ((!m_nChannels) || (!lpszFileName)) return FALSE;
619 if ((f = fopen(lpszFileName, "wb")) == NULL) return FALSE;
620 fwrite("Extended Module: ", 17, 1, f);
621 fwrite(m_szNames[0], 20, 1, f);
622 s[0] = 0x1A;
623 lstrcpy((LPSTR)&s[1], (nPacking) ? "MOD Plugin packed " : "FastTracker v2.00 ");
624 s[21] = 0x04;
625 s[22] = 0x01;
626 fwrite(s, 23, 1, f);
627 // Writing song header
628 memset(&header, 0, sizeof(header));
629 header.size = sizeof(XMFILEHEADER);
630 header.norder = 0;
631 header.restartpos = m_nRestartPos;
632 header.channels = m_nChannels;
633 header.patterns = 0;
634 for (i=0; i<MAX_ORDERS; i++)
635 {
636 if (Order[i] == 0xFF) break;
637 header.norder++;
638 if ((Order[i] >= header.patterns) && (Order[i] < MAX_PATTERNS)) header.patterns = Order[i]+1;
639 }
640 header.instruments = m_nInstruments;
641 if (!header.instruments) header.instruments = m_nSamples;
642 header.flags = (m_dwSongFlags & SONG_LINEARSLIDES) ? 0x01 : 0x00;
643 if (m_dwSongFlags & SONG_EXFILTERRANGE) header.flags |= 0x1000;
644 header.tempo = m_nDefaultTempo;
645 header.speed = m_nDefaultSpeed;
646 memcpy(header.order, Order, header.norder);
647 fwrite(&header, 1, sizeof(header), f);
648 // Writing patterns
649 for (i=0; i<header.patterns; i++) if (Patterns[i])
650 {
651 MODCOMMAND *p = Patterns[i];
652 UINT len = 0;
653
654 memset(&xmph, 0, sizeof(xmph));
655 xmph[0] = 9;
656 xmph[5] = (BYTE)(PatternSize[i] & 0xFF);
657 xmph[6] = (BYTE)(PatternSize[i] >> 8);
658 for (UINT j=m_nChannels*PatternSize[i]; j; j--,p++)
659 {
660 UINT note = p->note;
661 UINT param = ModSaveCommand(p, TRUE);
662 UINT command = param >> 8;
663 param &= 0xFF;
664 if (note >= 0xFE) note = 97; else
665 if ((note <= 12) || (note > 96+12)) note = 0; else
666 note -= 12;
667 UINT vol = 0;
668 if (p->volcmd)
669 {
670 UINT volcmd = p->volcmd;
671 switch(volcmd)
672 {
673 case VOLCMD_VOLUME: vol = 0x10 + p->vol; break;
674 case VOLCMD_VOLSLIDEDOWN:vol = 0x60 + (p->vol & 0x0F); break;
675 case VOLCMD_VOLSLIDEUP: vol = 0x70 + (p->vol & 0x0F); break;
676 case VOLCMD_FINEVOLDOWN:vol = 0x80 + (p->vol & 0x0F); break;
677 case VOLCMD_FINEVOLUP: vol = 0x90 + (p->vol & 0x0F); break;
678 case VOLCMD_VIBRATOSPEED:vol = 0xA0 + (p->vol & 0x0F); break;
679 case VOLCMD_VIBRATO: vol = 0xB0 + (p->vol & 0x0F); break;
680 case VOLCMD_PANNING: vol = 0xC0 + (p->vol >> 2); if (vol > 0xCF) vol = 0xCF; break;
681 case VOLCMD_PANSLIDELEFT:vol = 0xD0 + (p->vol & 0x0F); break;
682 case VOLCMD_PANSLIDERIGHT:vol = 0xE0 + (p->vol & 0x0F); break;
683 case VOLCMD_TONEPORTAMENTO:vol = 0xF0 + (p->vol & 0x0F); break;
684 }
685 }
686 if ((note) && (p->instr) && (vol > 0x0F) && (command) && (param))
687 {
688 s[len++] = note;
689 s[len++] = p->instr;
690 s[len++] = vol;
691 s[len++] = command;
692 s[len++] = param;
693 } else
694 {
695 BYTE b = 0x80;
696 if (note) b |= 0x01;
697 if (p->instr) b |= 0x02;
698 if (vol >= 0x10) b |= 0x04;
699 if (command) b |= 0x08;
700 if (param) b |= 0x10;
701 s[len++] = b;
702 if (b & 1) s[len++] = note;
703 if (b & 2) s[len++] = p->instr;
704 if (b & 4) s[len++] = vol;
705 if (b & 8) s[len++] = command;
706 if (b & 16) s[len++] = param;
707 }
708 if (len > sizeof(s) - 5) break;
709 }
710 xmph[7] = (BYTE)(len & 0xFF);
711 xmph[8] = (BYTE)(len >> 8);
712 fwrite(xmph, 1, 9, f);
713 fwrite(s, 1, len, f);
714 } else
715 {
716 memset(&xmph, 0, sizeof(xmph));
717 xmph[0] = 9;
718 xmph[5] = (BYTE)(PatternSize[i] & 0xFF);
719 xmph[6] = (BYTE)(PatternSize[i] >> 8);
720 fwrite(xmph, 1, 9, f);
721 }
722 // Writing instruments
723 for (i=1; i<=header.instruments; i++)
724 {
725 MODINSTRUMENT *pins;
726 BYTE flags[32];
727
728 memset(&xmih, 0, sizeof(xmih));
729 memset(&xmsh, 0, sizeof(xmsh));
730 xmih.size = sizeof(xmih) + sizeof(xmsh);
731 memcpy(xmih.name, m_szNames[i], 22);
732 xmih.type = 0;
733 xmih.samples = 0;
734 if (m_nInstruments)
735 {
736 INSTRUMENTHEADER *penv = Headers[i];
737 if (penv)
738 {
739 memcpy(xmih.name, penv->name, 22);
740 xmih.type = penv->nMidiProgram;
741 xmsh.volfade = penv->nFadeOut;
742 xmsh.vnum = (BYTE)penv->nVolEnv;
743 xmsh.pnum = (BYTE)penv->nPanEnv;
744 if (xmsh.vnum > 12) xmsh.vnum = 12;
745 if (xmsh.pnum > 12) xmsh.pnum = 12;
746 for (UINT ienv=0; ienv<12; ienv++)
747 {
748 xmsh.venv[ienv*2] = penv->VolPoints[ienv];
749 xmsh.venv[ienv*2+1] = penv->VolEnv[ienv];
750 xmsh.penv[ienv*2] = penv->PanPoints[ienv];
751 xmsh.penv[ienv*2+1] = penv->PanEnv[ienv];
752 }
753 if (penv->dwFlags & ENV_VOLUME) xmsh.vtype |= 1;
754 if (penv->dwFlags & ENV_VOLSUSTAIN) xmsh.vtype |= 2;
755 if (penv->dwFlags & ENV_VOLLOOP) xmsh.vtype |= 4;
756 if (penv->dwFlags & ENV_PANNING) xmsh.ptype |= 1;
757 if (penv->dwFlags & ENV_PANSUSTAIN) xmsh.ptype |= 2;
758 if (penv->dwFlags & ENV_PANLOOP) xmsh.ptype |= 4;
759 xmsh.vsustain = (BYTE)penv->nVolSustainBegin;
760 xmsh.vloops = (BYTE)penv->nVolLoopStart;
761 xmsh.vloope = (BYTE)penv->nVolLoopEnd;
762 xmsh.psustain = (BYTE)penv->nPanSustainBegin;
763 xmsh.ploops = (BYTE)penv->nPanLoopStart;
764 xmsh.ploope = (BYTE)penv->nPanLoopEnd;
765 for (UINT j=0; j<96; j++) if (penv->Keyboard[j+12])
766 {
767 UINT k;
768 for (k=0; k<xmih.samples; k++)if (smptable[k] == penv->Keyboard[j+12]) break;
769 if (k == xmih.samples)
770 {
771 smptable[xmih.samples++] = penv->Keyboard[j+12];
772 }
773 if (xmih.samples >= 32) break;
774 xmsh.snum[j] = k;
775 }
776 // xmsh.reserved2 = xmih.samples;
777 }
778 } else
779 {
780 xmih.samples = 1;
781 // xmsh.reserved2 = 1;
782 smptable[0] = i;
783 }
784 xmsh.shsize = (xmih.samples) ? 40 : 0;
785 fwrite(&xmih, 1, sizeof(xmih), f);
786 if (smptable[0])
787 {
788 MODINSTRUMENT *pvib = &Ins[smptable[0]];
789 xmsh.vibtype = pvib->nVibType;
790 xmsh.vibsweep = pvib->nVibSweep;
791 xmsh.vibdepth = pvib->nVibDepth;
792 xmsh.vibrate = pvib->nVibRate;
793 }
794 fwrite(&xmsh, 1, xmih.size - sizeof(xmih), f);
795 if (!xmih.samples) continue;
796 for (UINT ins=0; ins<xmih.samples; ins++)
797 {
798 memset(&xmss, 0, sizeof(xmss));
799 if (smptable[ins]) memcpy(xmss.name, m_szNames[smptable[ins]], 22);
800 pins = &Ins[smptable[ins]];
801 xmss.samplen = pins->nLength;
802 xmss.loopstart = pins->nLoopStart;
803 xmss.looplen = pins->nLoopEnd - pins->nLoopStart;
804 xmss.vol = pins->nVolume / 4;
805 xmss.finetune = (char)pins->nFineTune;
806 xmss.type = 0;
807 if (pins->uFlags & CHN_LOOP) xmss.type = (pins->uFlags & CHN_PINGPONGLOOP) ? 2 : 1;
808 flags[ins] = RS_PCM8D;
809#ifndef NO_PACKING
810 if (nPacking)
811 {
812 if ((!(pins->uFlags & (CHN_16BIT|CHN_STEREO)))
813 && (CanPackSample(pins->pSample, pins->nLength, nPacking)))
814 {
815 flags[ins] = RS_ADPCM4;
816 xmss.res = 0xAD;
817 }
818 } else
819#endif
820 {
821 if (pins->uFlags & CHN_16BIT)
822 {
823 flags[ins] = RS_PCM16D;
824 xmss.type |= 0x10;
825 xmss.looplen *= 2;
826 xmss.loopstart *= 2;
827 xmss.samplen *= 2;
828 }
829 if (pins->uFlags & CHN_STEREO)
830 {
831 flags[ins] = (pins->uFlags & CHN_16BIT) ? RS_STPCM16D : RS_STPCM8D;
832 xmss.type |= 0x20;
833 xmss.looplen *= 2;
834 xmss.loopstart *= 2;
835 xmss.samplen *= 2;
836 }
837 }
838 xmss.pan = 255;
839 if (pins->nPan < 256) xmss.pan = (BYTE)pins->nPan;
840 xmss.relnote = (signed char)pins->RelativeTone;
841 fwrite(&xmss, 1, xmsh.shsize, f);
842 }
843 for (UINT ismpd=0; ismpd<xmih.samples; ismpd++)
844 {
845 pins = &Ins[smptable[ismpd]];
846 if (pins->pSample)
847 {
848#ifndef NO_PACKING
849 if ((flags[ismpd] == RS_ADPCM4) && (xmih.samples>1)) CanPackSample(pins->pSample, pins->nLength, nPacking);
850#endif // NO_PACKING
851 WriteSample(f, pins, flags[ismpd]);
852 }
853 }
854 }
855 // Writing song comments
856 if ((m_lpszSongComments) && (m_lpszSongComments[0]))
857 {
858 DWORD d = 0x74786574;
859 fwrite(&d, 1, 4, f);
860 d = strlen(m_lpszSongComments);
861 fwrite(&d, 1, 4, f);
862 fwrite(m_lpszSongComments, 1, d, f);
863 }
864 // Writing midi cfg
865 if (m_dwSongFlags & SONG_EMBEDMIDICFG)
866 {
867 DWORD d = 0x4944494D;
868 fwrite(&d, 1, 4, f);
869 d = sizeof(MODMIDICFG);
870 fwrite(&d, 1, 4, f);
871 fwrite(&m_MidiCfg, 1, sizeof(MODMIDICFG), f);
872 }
873 // Writing Pattern Names
874 if ((m_nPatternNames) && (m_lpszPatternNames))
875 {
876 DWORD dwLen = m_nPatternNames * MAX_PATTERNNAME;
877 while ((dwLen >= MAX_PATTERNNAME) && (!m_lpszPatternNames[dwLen-MAX_PATTERNNAME])) dwLen -= MAX_PATTERNNAME;
878 if (dwLen >= MAX_PATTERNNAME)
879 {
880 DWORD d = 0x4d414e50;
881 fwrite(&d, 1, 4, f);
882 fwrite(&dwLen, 1, 4, f);
883 fwrite(m_lpszPatternNames, 1, dwLen, f);
884 }
885 }
886 // Writing Channel Names
887 {
888 UINT nChnNames = 0;
889 for (UINT inam=0; inam<m_nChannels; inam++)
890 {
891 if (ChnSettings[inam].szName[0]) nChnNames = inam+1;
892 }
893 // Do it!
894 if (nChnNames)
895 {
896 DWORD dwLen = nChnNames * MAX_CHANNELNAME;
897 DWORD d = 0x4d414e43;
898 fwrite(&d, 1, 4, f);
899 fwrite(&dwLen, 1, 4, f);
900 for (UINT inam=0; inam<nChnNames; inam++)
901 {
902 fwrite(ChnSettings[inam].szName, 1, MAX_CHANNELNAME, f);
903 }
904 }
905 }
906 // Save mix plugins information
907 SaveMixPlugins(f);
908 fclose(f);
909 return TRUE;
910}
911
912#endif // MODPLUG_NO_FILESAVE