comparison src/modplug/load_mt2.cxx @ 136:6b5a52635b3b trunk

[svn] - like with so many other things, modplug is now maintained by us.
author nenolod
date Sun, 29 Oct 2006 01:04:52 -0700
parents
children 032053ca08ab 3673c7ec4ea2
comparison
equal deleted inserted replaced
135:33d24bd94ccc 136:6b5a52635b3b
1 #include "stdafx.h"
2 #include "sndfile.h"
3
4 //#define MT2DEBUG
5
6 #pragma pack(1)
7
8 typedef struct _MT2FILEHEADER
9 {
10 DWORD dwMT20; // 0x3032544D "MT20"
11 DWORD dwSpecial;
12 WORD wVersion;
13 CHAR szTrackerName[32]; // "MadTracker 2.0"
14 CHAR szSongName[64];
15 WORD nOrders;
16 WORD wRestart;
17 WORD wPatterns;
18 WORD wChannels;
19 WORD wSamplesPerTick;
20 BYTE bTicksPerLine;
21 BYTE bLinesPerBeat;
22 DWORD fulFlags; // b0=packed patterns
23 WORD wInstruments;
24 WORD wSamples;
25 BYTE Orders[256];
26 } MT2FILEHEADER;
27
28 typedef struct _MT2PATTERN
29 {
30 WORD wLines;
31 DWORD wDataLen;
32 } MT2PATTERN;
33
34 typedef struct _MT2COMMAND
35 {
36 BYTE note; // 0=nothing, 97=note off
37 BYTE instr;
38 BYTE vol;
39 BYTE pan;
40 BYTE fxcmd;
41 BYTE fxparam1;
42 BYTE fxparam2;
43 } MT2COMMAND;
44
45 typedef struct _MT2DRUMSDATA
46 {
47 WORD wDrumPatterns;
48 WORD wDrumSamples[8];
49 BYTE DrumPatternOrder[256];
50 } MT2DRUMSDATA;
51
52 typedef struct _MT2AUTOMATION
53 {
54 DWORD dwFlags;
55 DWORD dwEffectId;
56 DWORD nEnvPoints;
57 } MT2AUTOMATION;
58
59 typedef struct _MT2INSTRUMENT
60 {
61 CHAR szName[32];
62 DWORD dwDataLen;
63 WORD wSamples;
64 BYTE GroupsMapping[96];
65 BYTE bVibType;
66 BYTE bVibSweep;
67 BYTE bVibDepth;
68 BYTE bVibRate;
69 WORD wFadeOut;
70 WORD wNNA;
71 WORD wInstrFlags;
72 WORD wEnvFlags1;
73 WORD wEnvFlags2;
74 } MT2INSTRUMENT;
75
76 typedef struct _MT2ENVELOPE
77 {
78 BYTE nFlags;
79 BYTE nPoints;
80 BYTE nSustainPos;
81 BYTE nLoopStart;
82 BYTE nLoopEnd;
83 BYTE bReserved[3];
84 BYTE EnvData[64];
85 } MT2ENVELOPE;
86
87 typedef struct _MT2SYNTH
88 {
89 BYTE nSynthId;
90 BYTE nFxId;
91 WORD wCutOff;
92 BYTE nResonance;
93 BYTE nAttack;
94 BYTE nDecay;
95 BYTE bReserved[25];
96 } MT2SYNTH;
97
98 typedef struct _MT2SAMPLE
99 {
100 CHAR szName[32];
101 DWORD dwDataLen;
102 DWORD dwLength;
103 DWORD dwFrequency;
104 BYTE nQuality;
105 BYTE nChannels;
106 BYTE nFlags;
107 BYTE nLoop;
108 DWORD dwLoopStart;
109 DWORD dwLoopEnd;
110 WORD wVolume;
111 BYTE nPan;
112 BYTE nBaseNote;
113 WORD wSamplesPerBeat;
114 } MT2SAMPLE;
115
116 typedef struct _MT2GROUP
117 {
118 BYTE nSmpNo;
119 BYTE nVolume; // 0-128
120 BYTE nFinePitch;
121 BYTE Reserved[5];
122 } MT2GROUP;
123
124 #pragma pack()
125
126
127 static VOID ConvertMT2Command(CSoundFile *that, MODCOMMAND *m, MT2COMMAND *p)
128 //---------------------------------------------------------------------------
129 {
130 // Note
131 m->note = 0;
132 if (p->note) m->note = (p->note > 96) ? 0xFF : p->note+12;
133 // Instrument
134 m->instr = p->instr;
135 // Volume Column
136 if ((p->vol >= 0x10) && (p->vol <= 0x90))
137 {
138 m->volcmd = VOLCMD_VOLUME;
139 m->vol = (p->vol - 0x10) >> 1;
140 } else
141 if ((p->vol >= 0xA0) && (p->vol <= 0xAF))
142 {
143 m->volcmd = VOLCMD_VOLSLIDEDOWN;
144 m->vol = (p->vol & 0x0f);
145 } else
146 if ((p->vol >= 0xB0) && (p->vol <= 0xBF))
147 {
148 m->volcmd = VOLCMD_VOLSLIDEUP;
149 m->vol = (p->vol & 0x0f);
150 } else
151 if ((p->vol >= 0xC0) && (p->vol <= 0xCF))
152 {
153 m->volcmd = VOLCMD_FINEVOLDOWN;
154 m->vol = (p->vol & 0x0f);
155 } else
156 if ((p->vol >= 0xD0) && (p->vol <= 0xDF))
157 {
158 m->volcmd = VOLCMD_FINEVOLUP;
159 m->vol = (p->vol & 0x0f);
160 } else
161 {
162 m->volcmd = 0;
163 m->vol = 0;
164 }
165 // Effects
166 m->command = 0;
167 m->param = 0;
168 if ((p->fxcmd) || (p->fxparam1) || (p->fxparam2))
169 {
170 if (!p->fxcmd)
171 {
172 m->command = p->fxparam2;
173 m->param = p->fxparam1;
174 that->ConvertModCommand(m);
175 } else
176 {
177 // TODO: MT2 Effects
178 }
179 }
180 }
181
182
183 BOOL CSoundFile::ReadMT2(LPCBYTE lpStream, DWORD dwMemLength)
184 //-----------------------------------------------------------
185 {
186 MT2FILEHEADER *pfh = (MT2FILEHEADER *)lpStream;
187 DWORD dwMemPos, dwDrumDataPos, dwExtraDataPos;
188 UINT nDrumDataLen, nExtraDataLen;
189 MT2DRUMSDATA *pdd;
190 MT2INSTRUMENT *InstrMap[255];
191 MT2SAMPLE *SampleMap[256];
192
193 if ((!lpStream) || (dwMemLength < sizeof(MT2FILEHEADER))
194 || (pfh->dwMT20 != 0x3032544D)
195 || (pfh->wVersion < 0x0200) || (pfh->wVersion >= 0x0300)
196 || (pfh->wChannels < 4) || (pfh->wChannels > 64)) return FALSE;
197 pdd = NULL;
198 m_nType = MOD_TYPE_MT2;
199 m_nChannels = pfh->wChannels;
200 m_nRestartPos = pfh->wRestart;
201 m_nDefaultSpeed = pfh->bTicksPerLine;
202 m_nDefaultTempo = 125;
203 if ((pfh->wSamplesPerTick > 100) && (pfh->wSamplesPerTick < 5000))
204 {
205 m_nDefaultTempo = 110250 / pfh->wSamplesPerTick;
206 }
207 for (UINT iOrd=0; iOrd<MAX_ORDERS; iOrd++)
208 {
209 Order[iOrd] = (BYTE)((iOrd < pfh->nOrders) ? pfh->Orders[iOrd] : 0xFF);
210 }
211 memcpy(m_szNames[0], pfh->szSongName, 32);
212 m_szNames[0][31] = 0;
213 dwMemPos = sizeof(MT2FILEHEADER);
214 nDrumDataLen = *(WORD *)(lpStream + dwMemPos);
215 dwDrumDataPos = dwMemPos + 2;
216 if (nDrumDataLen >= 2) pdd = (MT2DRUMSDATA *)(lpStream+dwDrumDataPos);
217 dwMemPos += 2 + nDrumDataLen;
218 #ifdef MT2DEBUG
219
220 Log("MT2 v%03X: \"%s\" (flags=%04X)\n", pfh->wVersion, m_szNames[0], pfh->fulFlags);
221 Log("%d Channels, %d Patterns, %d Instruments, %d Samples\n", pfh->wChannels, pfh->wPatterns, pfh->wInstruments, pfh->wSamples);
222 Log("Drum Data: %d bytes @%04X\n", nDrumDataLen, dwDrumDataPos);
223 #endif
224 if (dwMemPos >= dwMemLength-12) return TRUE;
225 if (!*(DWORD *)(lpStream+dwMemPos)) dwMemPos += 4;
226 if (!*(DWORD *)(lpStream+dwMemPos)) dwMemPos += 4;
227 nExtraDataLen = *(DWORD *)(lpStream+dwMemPos);
228 dwExtraDataPos = dwMemPos + 4;
229 dwMemPos += 4;
230 #ifdef MT2DEBUG
231 Log("Extra Data: %d bytes @%04X\n", nExtraDataLen, dwExtraDataPos);
232 #endif
233 if (dwMemPos + nExtraDataLen >= dwMemLength) return TRUE;
234 while (dwMemPos+8 < dwExtraDataPos + nExtraDataLen)
235 {
236 DWORD dwId = *(DWORD *)(lpStream+dwMemPos);
237 DWORD dwLen = *(DWORD *)(lpStream+dwMemPos+4);
238 dwMemPos += 8;
239 if (dwMemPos + dwLen > dwMemLength) return TRUE;
240 #ifdef MT2DEBUG
241 CHAR s[5];
242 memcpy(s, &dwId, 4);
243 s[4] = 0;
244 Log("pos=0x%04X: %s: %d bytes\n", dwMemPos-8, s, dwLen);
245 #endif
246 switch(dwId)
247 {
248 // MSG
249 case 0x0047534D:
250 if ((dwLen > 3) && (!m_lpszSongComments))
251 {
252 DWORD nTxtLen = dwLen;
253 if (nTxtLen > 32000) nTxtLen = 32000;
254 m_lpszSongComments = new char[nTxtLen]; // changed from CHAR
255 if (m_lpszSongComments)
256 {
257 memcpy(m_lpszSongComments, lpStream+dwMemPos+1, nTxtLen-1);
258 m_lpszSongComments[nTxtLen-1] = 0;
259 }
260 }
261 break;
262 // SUM -> author name (or "Unregistered")
263 // TMAP
264 // TRKS
265 case 0x534b5254:
266 break;
267 }
268 dwMemPos += dwLen;
269 }
270 // Load Patterns
271 dwMemPos = dwExtraDataPos + nExtraDataLen;
272 for (UINT iPat=0; iPat<pfh->wPatterns; iPat++) if (dwMemPos < dwMemLength-6)
273 {
274 MT2PATTERN *pmp = (MT2PATTERN *)(lpStream+dwMemPos);
275 UINT wDataLen = (pmp->wDataLen + 1) & ~1;
276 dwMemPos += 6;
277 if (dwMemPos + wDataLen > dwMemLength) break;
278 UINT nLines = pmp->wLines;
279 if ((iPat < MAX_PATTERNS) && (nLines > 0) && (nLines <= 256))
280 {
281 #ifdef MT2DEBUG
282 Log("Pattern #%d @%04X: %d lines, %d bytes\n", iPat, dwMemPos-6, nLines, pmp->wDataLen);
283 #endif
284 PatternSize[iPat] = nLines;
285 Patterns[iPat] = AllocatePattern(nLines, m_nChannels);
286 if (!Patterns[iPat]) return TRUE;
287 MODCOMMAND *m = Patterns[iPat];
288 UINT len = wDataLen;
289 if (pfh->fulFlags & 1) // Packed Patterns
290 {
291 BYTE *p = (BYTE *)(lpStream+dwMemPos);
292 UINT pos = 0, row=0, ch=0;
293 while (pos < len)
294 {
295 MT2COMMAND cmd;
296 UINT infobyte = p[pos++];
297 UINT rptcount = 0;
298 if (infobyte == 0xff)
299 {
300 rptcount = p[pos++];
301 infobyte = p[pos++];
302 #if 0
303 Log("(%d.%d) FF(%02X).%02X\n", row, ch, rptcount, infobyte);
304 } else
305 {
306 Log("(%d.%d) %02X\n", row, ch, infobyte);
307 #endif
308 }
309 if (infobyte & 0x7f)
310 {
311 UINT patpos = row*m_nChannels+ch;
312 cmd.note = cmd.instr = cmd.vol = cmd.pan = cmd.fxcmd = cmd.fxparam1 = cmd.fxparam2 = 0;
313 if (infobyte & 1) cmd.note = p[pos++];
314 if (infobyte & 2) cmd.instr = p[pos++];
315 if (infobyte & 4) cmd.vol = p[pos++];
316 if (infobyte & 8) cmd.pan = p[pos++];
317 if (infobyte & 16) cmd.fxcmd = p[pos++];
318 if (infobyte & 32) cmd.fxparam1 = p[pos++];
319 if (infobyte & 64) cmd.fxparam2 = p[pos++];
320 #ifdef MT2DEBUG
321 if (cmd.fxcmd)
322 {
323 Log("(%d.%d) MT2 FX=%02X.%02X.%02X\n", row, ch, cmd.fxcmd, cmd.fxparam1, cmd.fxparam2);
324 }
325 #endif
326 ConvertMT2Command(this, &m[patpos], &cmd);
327 }
328 row += rptcount+1;
329 while (row >= nLines) { row-=nLines; ch++; }
330 if (ch >= m_nChannels) break;
331 }
332 } else
333 {
334 MT2COMMAND *p = (MT2COMMAND *)(lpStream+dwMemPos);
335 UINT n = 0;
336 while ((len > sizeof(MT2COMMAND)) && (n < m_nChannels*nLines))
337 {
338 ConvertMT2Command(this, m, p);
339 len -= sizeof(MT2COMMAND);
340 n++;
341 p++;
342 m++;
343 }
344 }
345 }
346 dwMemPos += wDataLen;
347 }
348 // Skip Drum Patterns
349 if (pdd)
350 {
351 #ifdef MT2DEBUG
352 Log("%d Drum Patterns at offset 0x%08X\n", pdd->wDrumPatterns, dwMemPos);
353 #endif
354 for (UINT iDrm=0; iDrm<pdd->wDrumPatterns; iDrm++)
355 {
356 if (dwMemPos > dwMemLength-2) return TRUE;
357 UINT nLines = *(WORD *)(lpStream+dwMemPos);
358 #ifdef MT2DEBUG
359 if (nLines != 64) Log("Drum Pattern %d: %d Lines @%04X\n", iDrm, nLines, dwMemPos);
360 #endif
361 dwMemPos += 2 + nLines * 32;
362 }
363 }
364 // Automation
365 if (pfh->fulFlags & 2)
366 {
367 #ifdef MT2DEBUG
368 Log("Automation at offset 0x%08X\n", dwMemPos);
369 #endif
370 UINT nAutoCount = m_nChannels;
371 if (pfh->fulFlags & 0x10) nAutoCount++; // Master Automation
372 if ((pfh->fulFlags & 0x08) && (pdd)) nAutoCount += 8; // Drums Automation
373 nAutoCount *= pfh->wPatterns;
374 for (UINT iAuto=0; iAuto<nAutoCount; iAuto++)
375 {
376 if (dwMemPos+12 >= dwMemLength) return TRUE;
377 MT2AUTOMATION *pma = (MT2AUTOMATION *)(lpStream+dwMemPos);
378 dwMemPos += (pfh->wVersion <= 0x201) ? 4 : 8;
379 for (UINT iEnv=0; iEnv<14; iEnv++)
380 {
381 if (pma->dwFlags & (1 << iEnv))
382 {
383 #ifdef MT2DEBUG
384 UINT nPoints = *(DWORD *)(lpStream+dwMemPos);
385 Log(" Env[%d/%d] %04X @%04X: %d points\n", iAuto, nAutoCount, 1 << iEnv, dwMemPos-8, nPoints);
386 #endif
387 dwMemPos += 260;
388 }
389 }
390 }
391 }
392 // Load Instruments
393 #ifdef MT2DEBUG
394 Log("Loading instruments at offset 0x%08X\n", dwMemPos);
395 #endif
396 memset(InstrMap, 0, sizeof(InstrMap));
397 m_nInstruments = (pfh->wInstruments < MAX_INSTRUMENTS) ? pfh->wInstruments : MAX_INSTRUMENTS-1;
398 for (UINT iIns=1; iIns<=255; iIns++)
399 {
400 if (dwMemPos+36 > dwMemLength) return TRUE;
401 MT2INSTRUMENT *pmi = (MT2INSTRUMENT *)(lpStream+dwMemPos);
402 INSTRUMENTHEADER *penv = NULL;
403 if (iIns <= m_nInstruments)
404 {
405 penv = new INSTRUMENTHEADER;
406 Headers[iIns] = penv;
407 if (penv)
408 {
409 memset(penv, 0, sizeof(INSTRUMENTHEADER));
410 memcpy(penv->name, pmi->szName, 32);
411 penv->nGlobalVol = 64;
412 penv->nPan = 128;
413 for (UINT i=0; i<120; i++)
414 {
415 penv->NoteMap[i] = i+1;
416 }
417 }
418 }
419 #ifdef MT2DEBUG
420 if (iIns <= pfh->wInstruments) Log(" Instrument #%d at offset %04X: %d bytes\n", iIns, dwMemPos, pmi->dwDataLen);
421 #endif
422 if (((LONG)pmi->dwDataLen > 0) && (dwMemPos + pmi->dwDataLen + 40 <= dwMemLength))
423 {
424 InstrMap[iIns-1] = pmi;
425 if (penv)
426 {
427 penv->nFadeOut = pmi->wFadeOut;
428 penv->nNNA = pmi->wNNA & 3;
429 penv->nDCT = (pmi->wNNA>>8) & 3;
430 penv->nDNA = (pmi->wNNA>>12) & 3;
431 MT2ENVELOPE *pehdr[4];
432 WORD *pedata[4];
433 if (pfh->wVersion <= 0x201)
434 {
435 DWORD dwEnvPos = dwMemPos + sizeof(MT2INSTRUMENT) - 4;
436 pehdr[0] = (MT2ENVELOPE *)(lpStream+dwEnvPos);
437 pehdr[1] = (MT2ENVELOPE *)(lpStream+dwEnvPos+8);
438 pehdr[2] = pehdr[3] = NULL;
439 pedata[0] = (WORD *)(lpStream+dwEnvPos+16);
440 pedata[1] = (WORD *)(lpStream+dwEnvPos+16+64);
441 pedata[2] = pedata[3] = NULL;
442 } else
443 {
444 DWORD dwEnvPos = dwMemPos + sizeof(MT2INSTRUMENT);
445 for (UINT i=0; i<4; i++)
446 {
447 if (pmi->wEnvFlags1 & (1<<i))
448 {
449 pehdr[i] = (MT2ENVELOPE *)(lpStream+dwEnvPos);
450 pedata[i] = (WORD *)pehdr[i]->EnvData;
451 dwEnvPos += sizeof(MT2ENVELOPE);
452 } else
453 {
454 pehdr[i] = NULL;
455 pedata[i] = NULL;
456 }
457 }
458 }
459 // Load envelopes
460 for (UINT iEnv=0; iEnv<4; iEnv++) if (pehdr[iEnv])
461 {
462 MT2ENVELOPE *pme = pehdr[iEnv];
463 WORD *pEnvPoints = NULL;
464 BYTE *pEnvData = NULL;
465 #ifdef MT2DEBUG
466 Log(" Env %d.%d @%04X: %d points\n", iIns, iEnv, (UINT)(((BYTE *)pme)-lpStream), pme->nPoints);
467 #endif
468 switch(iEnv)
469 {
470 // Volume Envelope
471 case 0:
472 if (pme->nFlags & 1) penv->dwFlags |= ENV_VOLUME;
473 if (pme->nFlags & 2) penv->dwFlags |= ENV_VOLSUSTAIN;
474 if (pme->nFlags & 4) penv->dwFlags |= ENV_VOLLOOP;
475 penv->nVolEnv = (pme->nPoints > 16) ? 16 : pme->nPoints;
476 penv->nVolSustainBegin = penv->nVolSustainEnd = pme->nSustainPos;
477 penv->nVolLoopStart = pme->nLoopStart;
478 penv->nVolLoopEnd = pme->nLoopEnd;
479 pEnvPoints = penv->VolPoints;
480 pEnvData = penv->VolEnv;
481 break;
482
483 // Panning Envelope
484 case 1:
485 if (pme->nFlags & 1) penv->dwFlags |= ENV_PANNING;
486 if (pme->nFlags & 2) penv->dwFlags |= ENV_PANSUSTAIN;
487 if (pme->nFlags & 4) penv->dwFlags |= ENV_PANLOOP;
488 penv->nPanEnv = (pme->nPoints > 16) ? 16 : pme->nPoints;
489 penv->nPanSustainBegin = penv->nPanSustainEnd = pme->nSustainPos;
490 penv->nPanLoopStart = pme->nLoopStart;
491 penv->nPanLoopEnd = pme->nLoopEnd;
492 pEnvPoints = penv->PanPoints;
493 pEnvData = penv->PanEnv;
494 break;
495
496 // Pitch/Filter envelope
497 default:
498 if (pme->nFlags & 1) penv->dwFlags |= (iEnv==3) ? (ENV_PITCH|ENV_FILTER) : ENV_PITCH;
499 if (pme->nFlags & 2) penv->dwFlags |= ENV_PITCHSUSTAIN;
500 if (pme->nFlags & 4) penv->dwFlags |= ENV_PITCHLOOP;
501 penv->nPitchEnv = (pme->nPoints > 16) ? 16 : pme->nPoints;
502 penv->nPitchSustainBegin = penv->nPitchSustainEnd = pme->nSustainPos;
503 penv->nPitchLoopStart = pme->nLoopStart;
504 penv->nPitchLoopEnd = pme->nLoopEnd;
505 pEnvPoints = penv->PitchPoints;
506 pEnvData = penv->PitchEnv;
507 }
508 // Envelope data
509 if ((pEnvPoints) && (pEnvData) && (pedata[iEnv]))
510 {
511 WORD *psrc = pedata[iEnv];
512 for (UINT i=0; i<16; i++)
513 {
514 pEnvPoints[i] = psrc[i*2];
515 pEnvData[i] = (BYTE)psrc[i*2+1];
516 }
517 }
518 }
519 }
520 dwMemPos += pmi->dwDataLen + 36;
521 if (pfh->wVersion > 0x201) dwMemPos += 4; // ?
522 } else
523 {
524 dwMemPos += 36;
525 }
526 }
527 #ifdef MT2DEBUG
528 Log("Loading samples at offset 0x%08X\n", dwMemPos);
529 #endif
530 memset(SampleMap, 0, sizeof(SampleMap));
531 m_nSamples = (pfh->wSamples < MAX_SAMPLES) ? pfh->wSamples : MAX_SAMPLES-1;
532 for (UINT iSmp=1; iSmp<=256; iSmp++)
533 {
534 if (dwMemPos+36 > dwMemLength) return TRUE;
535 MT2SAMPLE *pms = (MT2SAMPLE *)(lpStream+dwMemPos);
536 #ifdef MT2DEBUG
537 if (iSmp <= m_nSamples) Log(" Sample #%d at offset %04X: %d bytes\n", iSmp, dwMemPos, pms->dwDataLen);
538 #endif
539 if (iSmp < MAX_SAMPLES)
540 {
541 memcpy(m_szNames[iSmp], pms->szName, 32);
542 }
543 if (pms->dwDataLen > 0)
544 {
545 SampleMap[iSmp-1] = pms;
546 if (iSmp < MAX_SAMPLES)
547 {
548 MODINSTRUMENT *psmp = &Ins[iSmp];
549 psmp->nGlobalVol = 64;
550 psmp->nVolume = (pms->wVolume >> 7);
551 psmp->nPan = (pms->nPan == 0x80) ? 128 : (pms->nPan^0x80);
552 psmp->nLength = pms->dwLength;
553 psmp->nC4Speed = pms->dwFrequency;
554 psmp->nLoopStart = pms->dwLoopStart;
555 psmp->nLoopEnd = pms->dwLoopEnd;
556 FrequencyToTranspose(psmp);
557 psmp->RelativeTone -= pms->nBaseNote - 49;
558 psmp->nC4Speed = TransposeToFrequency(psmp->RelativeTone, psmp->nFineTune);
559 if (pms->nQuality == 2) { psmp->uFlags |= CHN_16BIT; psmp->nLength >>= 1; }
560 if (pms->nChannels == 2) { psmp->nLength >>= 1; }
561 if (pms->nLoop == 1) psmp->uFlags |= CHN_LOOP;
562 if (pms->nLoop == 2) psmp->uFlags |= CHN_LOOP|CHN_PINGPONGLOOP;
563 }
564 dwMemPos += pms->dwDataLen + 36;
565 } else
566 {
567 dwMemPos += 36;
568 }
569 }
570 #ifdef MT2DEBUG
571 Log("Loading groups at offset 0x%08X\n", dwMemPos);
572 #endif
573 for (UINT iMap=0; iMap<255; iMap++) if (InstrMap[iMap])
574 {
575 if (dwMemPos+8 > dwMemLength) return TRUE;
576 MT2INSTRUMENT *pmi = InstrMap[iMap];
577 INSTRUMENTHEADER *penv = NULL;
578 if (iMap<m_nInstruments) penv = Headers[iMap+1];
579 for (UINT iGrp=0; iGrp<pmi->wSamples; iGrp++)
580 {
581 if (penv)
582 {
583 MT2GROUP *pmg = (MT2GROUP *)(lpStream+dwMemPos);
584 for (UINT i=0; i<96; i++)
585 {
586 if (pmi->GroupsMapping[i] == iGrp)
587 {
588 UINT nSmp = pmg->nSmpNo+1;
589 penv->Keyboard[i+12] = (BYTE)nSmp;
590 if (nSmp <= m_nSamples)
591 {
592 Ins[nSmp].nVibType = pmi->bVibType;
593 Ins[nSmp].nVibSweep = pmi->bVibSweep;
594 Ins[nSmp].nVibDepth = pmi->bVibDepth;
595 Ins[nSmp].nVibRate = pmi->bVibRate;
596 }
597 }
598 }
599 }
600 dwMemPos += 8;
601 }
602 }
603 #ifdef MT2DEBUG
604 Log("Loading sample data at offset 0x%08X\n", dwMemPos);
605 #endif
606 for (UINT iData=0; iData<256; iData++) if ((iData < m_nSamples) && (SampleMap[iData]))
607 {
608 MT2SAMPLE *pms = SampleMap[iData];
609 MODINSTRUMENT *psmp = &Ins[iData+1];
610 if (!(pms->nFlags & 5))
611 {
612 if (psmp->nLength > 0)
613 {
614 #ifdef MT2DEBUG
615 Log(" Reading sample #%d at offset 0x%04X (len=%d)\n", iData+1, dwMemPos, psmp->nLength);
616 #endif
617 UINT rsflags;
618
619 if (pms->nChannels == 2)
620 rsflags = (psmp->uFlags & CHN_16BIT) ? RS_STPCM16D : RS_STPCM8D;
621 else
622 rsflags = (psmp->uFlags & CHN_16BIT) ? RS_PCM16D : RS_PCM8D;
623
624 dwMemPos += ReadSample(psmp, rsflags, (LPCSTR)(lpStream+dwMemPos), dwMemLength-dwMemPos);
625 }
626 } else
627 if (dwMemPos+4 < dwMemLength)
628 {
629 UINT nNameLen = *(DWORD *)(lpStream+dwMemPos);
630 dwMemPos += nNameLen + 16;
631 }
632 if (dwMemPos+4 >= dwMemLength) break;
633 }
634 return TRUE;
635 }