00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #include "stdafx.h"
00012 #include "sndfile.h"
00013
00015
00016
00017 #ifdef WIN32
00018 #pragma warning(disable:4244)
00019 #endif
00020
00021 #pragma pack(1)
00022 typedef struct tagXMFILEHEADER
00023 {
00024 DWORD size;
00025 WORD norder;
00026 WORD restartpos;
00027 WORD channels;
00028 WORD patterns;
00029 WORD instruments;
00030 WORD flags;
00031 WORD speed;
00032 WORD tempo;
00033 BYTE order[256];
00034 } Q_PACKED XMFILEHEADER;
00035
00036
00037 typedef struct tagXMINSTRUMENTHEADER
00038 {
00039 DWORD size;
00040 CHAR name[22];
00041 BYTE type;
00042 BYTE samples;
00043 BYTE samplesh;
00044 } Q_PACKED XMINSTRUMENTHEADER;
00045
00046
00047 typedef struct tagXMSAMPLEHEADER
00048 {
00049 DWORD shsize;
00050 BYTE snum[96];
00051 WORD venv[24];
00052 WORD penv[24];
00053 BYTE vnum, pnum;
00054 BYTE vsustain, vloops, vloope, psustain, ploops, ploope;
00055 BYTE vtype, ptype;
00056 BYTE vibtype, vibsweep, vibdepth, vibrate;
00057 WORD volfade;
00058 WORD res;
00059 BYTE reserved1[20];
00060 } Q_PACKED XMSAMPLEHEADER;
00061
00062 typedef struct tagXMSAMPLESTRUCT
00063 {
00064 DWORD samplen;
00065 DWORD loopstart;
00066 DWORD looplen;
00067 BYTE vol;
00068 signed char finetune;
00069 BYTE type;
00070 BYTE pan;
00071 signed char relnote;
00072 BYTE res;
00073 char name[22];
00074 } Q_PACKED XMSAMPLESTRUCT;
00075
00076 typedef struct tagXMPATTERNHEADER
00077 {
00078 DWORD size;
00079 BYTE packing;
00080 WORD rows;
00081 WORD packsize;
00082 } Q_PACKED XMPATTERNHEADER;
00083
00084 #pragma pack()
00085
00086
00087 BOOL CSoundFile::ReadXM(const BYTE *lpStream, DWORD dwMemLength)
00088
00089 {
00090 XMSAMPLEHEADER xmsh;
00091 XMSAMPLESTRUCT xmss;
00092 DWORD dwMemPos, dwHdrSize;
00093 WORD norders=0, restartpos=0, channels=0, patterns=0, instruments=0;
00094 WORD xmflags=0, deftempo=125, defspeed=6;
00095 BOOL InstUsed[256];
00096 BYTE channels_used[MAX_CHANNELS];
00097 BYTE pattern_map[256];
00098 BOOL samples_used[MAX_SAMPLES];
00099 UINT unused_samples;
00100
00101 m_nChannels = 0;
00102 if ((!lpStream) || (dwMemLength < 0x200)) return FALSE;
00103 if (strnicmp((LPCSTR)lpStream, "Extended Module", 15)) return FALSE;
00104
00105 memcpy(m_szNames[0], lpStream+17, 20);
00106 dwHdrSize = bswapLE32(*((DWORD *)(lpStream+60)));
00107 norders = bswapLE16(*((WORD *)(lpStream+64)));
00108 if ((!norders) || (norders > MAX_ORDERS)) return FALSE;
00109 restartpos = bswapLE16(*((WORD *)(lpStream+66)));
00110 channels = bswapLE16(*((WORD *)(lpStream+68)));
00111 if ((!channels) || (channels > 64)) return FALSE;
00112 m_nType = MOD_TYPE_XM;
00113 m_nMinPeriod = 27;
00114 m_nMaxPeriod = 54784;
00115 m_nChannels = channels;
00116 if (restartpos < norders) m_nRestartPos = restartpos;
00117 patterns = bswapLE16(*((WORD *)(lpStream+70)));
00118 if (patterns > 256) patterns = 256;
00119 instruments = bswapLE16(*((WORD *)(lpStream+72)));
00120 if (instruments >= MAX_INSTRUMENTS) instruments = MAX_INSTRUMENTS-1;
00121 m_nInstruments = instruments;
00122 m_nSamples = 0;
00123 memcpy(&xmflags, lpStream+74, 2);
00124 xmflags = bswapLE16(xmflags);
00125 if (xmflags & 1) m_dwSongFlags |= SONG_LINEARSLIDES;
00126 if (xmflags & 0x1000) m_dwSongFlags |= SONG_EXFILTERRANGE;
00127 defspeed = bswapLE16(*((WORD *)(lpStream+76)));
00128 deftempo = bswapLE16(*((WORD *)(lpStream+78)));
00129 if ((deftempo >= 32) && (deftempo < 256)) m_nDefaultTempo = deftempo;
00130 if ((defspeed > 0) && (defspeed < 40)) m_nDefaultSpeed = defspeed;
00131 memcpy(Order, lpStream+80, norders);
00132 memset(InstUsed, 0, sizeof(InstUsed));
00133 if (patterns > MAX_PATTERNS)
00134 {
00135 UINT i, j;
00136 for (i=0; i<norders; i++)
00137 {
00138 if (Order[i] < patterns) InstUsed[Order[i]] = TRUE;
00139 }
00140 j = 0;
00141 for (i=0; i<256; i++)
00142 {
00143 if (InstUsed[i]) pattern_map[i] = j++;
00144 }
00145 for (i=0; i<256; i++)
00146 {
00147 if (!InstUsed[i])
00148 {
00149 pattern_map[i] = (j < MAX_PATTERNS) ? j : 0xFE;
00150 j++;
00151 }
00152 }
00153 for (i=0; i<norders; i++)
00154 {
00155 Order[i] = pattern_map[Order[i]];
00156 }
00157 } else
00158 {
00159 for (UINT i=0; i<256; i++) pattern_map[i] = i;
00160 }
00161 memset(InstUsed, 0, sizeof(InstUsed));
00162 dwMemPos = dwHdrSize + 60;
00163 if (dwMemPos + 8 >= dwMemLength) return TRUE;
00164
00165 memset(channels_used, 0, sizeof(channels_used));
00166 for (UINT ipat=0; ipat<patterns; ipat++)
00167 {
00168 UINT ipatmap = pattern_map[ipat];
00169 DWORD dwSize = 0;
00170 WORD rows=64, packsize=0;
00171 XMPATTERNHEADER *patternHeader = (XMPATTERNHEADER *)(lpStream+dwMemPos);
00172
00173 dwSize = bswapLE32(patternHeader->size);
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183 rows = bswapLE16(patternHeader->rows);
00184 if ((!rows) || (rows > 256)) rows = 64;
00185
00186 packsize = bswapLE16(patternHeader->packsize);
00187 if (dwMemPos + dwSize + 4 > dwMemLength) return TRUE;
00188 dwMemPos += dwSize;
00189 if (dwMemPos + packsize + 4 > dwMemLength) return TRUE;
00190 MODCOMMAND *p;
00191 if (ipatmap < MAX_PATTERNS)
00192 {
00193 PatternSize[ipatmap] = rows;
00194 if ((Patterns[ipatmap] = AllocatePattern(rows, m_nChannels)) == NULL) return TRUE;
00195 if (!packsize) continue;
00196 p = Patterns[ipatmap];
00197 } else p = NULL;
00198 const BYTE *src = lpStream+dwMemPos;
00199 UINT j=0;
00200 for (UINT row=0; row<rows; row++)
00201 {
00202 for (UINT chn=0; chn<m_nChannels; chn++)
00203 {
00204 if ((p) && (j < packsize))
00205 {
00206 BYTE b = src[j++];
00207 UINT vol = 0;
00208 if (b & 0x80)
00209 {
00210 if (b & 1) p->note = src[j++];
00211 if (b & 2) p->instr = src[j++];
00212 if (b & 4) vol = src[j++];
00213 if (b & 8) p->command = src[j++];
00214 if (b & 16) p->param = src[j++];
00215 } else
00216 {
00217 p->note = b;
00218 p->instr = src[j++];
00219 vol = src[j++];
00220 p->command = src[j++];
00221 p->param = src[j++];
00222 }
00223 if (p->note == 97) p->note = 0xFF; else
00224 if ((p->note) && (p->note < 97)) p->note += 12;
00225 if (p->note) channels_used[chn] = 1;
00226 if (p->command | p->param) ConvertModCommand(p);
00227 if (p->instr == 0xff) p->instr = 0;
00228 if (p->instr) InstUsed[p->instr] = TRUE;
00229 if ((vol >= 0x10) && (vol <= 0x50))
00230 {
00231 p->volcmd = VOLCMD_VOLUME;
00232 p->vol = vol - 0x10;
00233 } else
00234 if (vol >= 0x60)
00235 {
00236 UINT v = vol & 0xF0;
00237 vol &= 0x0F;
00238 p->vol = vol;
00239 switch(v)
00240 {
00241
00242 case 0x60: p->volcmd = VOLCMD_VOLSLIDEDOWN; break;
00243
00244 case 0x70: p->volcmd = VOLCMD_VOLSLIDEUP; break;
00245
00246 case 0x80: p->volcmd = VOLCMD_FINEVOLDOWN; break;
00247
00248 case 0x90: p->volcmd = VOLCMD_FINEVOLUP; break;
00249
00250 case 0xA0: p->volcmd = VOLCMD_VIBRATOSPEED; break;
00251
00252 case 0xB0: p->volcmd = VOLCMD_VIBRATO; break;
00253
00254 case 0xC0: p->volcmd = VOLCMD_PANNING; p->vol = (vol << 2) + 2; break;
00255
00256 case 0xD0: p->volcmd = VOLCMD_PANSLIDELEFT; break;
00257
00258 case 0xE0: p->volcmd = VOLCMD_PANSLIDERIGHT; break;
00259
00260 case 0xF0: p->volcmd = VOLCMD_TONEPORTAMENTO; break;
00261 }
00262 }
00263 p++;
00264 } else
00265 if (j < packsize)
00266 {
00267 BYTE b = src[j++];
00268 if (b & 0x80)
00269 {
00270 if (b & 1) j++;
00271 if (b & 2) j++;
00272 if (b & 4) j++;
00273 if (b & 8) j++;
00274 if (b & 16) j++;
00275 } else j += 4;
00276 } else break;
00277 }
00278 }
00279 dwMemPos += packsize;
00280 }
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290 memset(samples_used, 0, sizeof(samples_used));
00291 unused_samples = 0;
00292
00293 for (UINT iIns=1; iIns<=instruments; iIns++)
00294 {
00295 XMINSTRUMENTHEADER *pih;
00296 BYTE flags[32];
00297 DWORD samplesize[32];
00298 UINT samplemap[32];
00299 WORD nsamples;
00300
00301 if (dwMemPos + sizeof(XMINSTRUMENTHEADER) >= dwMemLength) return TRUE;
00302 pih = (XMINSTRUMENTHEADER *)(lpStream+dwMemPos);
00303 if (dwMemPos + bswapLE32(pih->size) > dwMemLength) return TRUE;
00304 if ((Headers[iIns] = new INSTRUMENTHEADER) == NULL) continue;
00305 memset(Headers[iIns], 0, sizeof(INSTRUMENTHEADER));
00306 memcpy(Headers[iIns]->name, pih->name, 22);
00307 if ((nsamples = pih->samples) > 0)
00308 {
00309 if (dwMemPos + sizeof(XMSAMPLEHEADER) > dwMemLength) return TRUE;
00310 memcpy(&xmsh, lpStream+dwMemPos+sizeof(XMINSTRUMENTHEADER), sizeof(XMSAMPLEHEADER));
00311 xmsh.shsize = bswapLE32(xmsh.shsize);
00312 for (int i = 0; i < 24; ++i) {
00313 xmsh.venv[i] = bswapLE16(xmsh.venv[i]);
00314 xmsh.penv[i] = bswapLE16(xmsh.penv[i]);
00315 }
00316 xmsh.volfade = bswapLE16(xmsh.volfade);
00317 xmsh.res = bswapLE16(xmsh.res);
00318 dwMemPos += bswapLE32(pih->size);
00319 } else
00320 {
00321 if (bswapLE32(pih->size)) dwMemPos += bswapLE32(pih->size);
00322 else dwMemPos += sizeof(XMINSTRUMENTHEADER);
00323 continue;
00324 }
00325 memset(samplemap, 0, sizeof(samplemap));
00326 if (nsamples > 32) return TRUE;
00327 UINT newsamples = m_nSamples;
00328 for (UINT nmap=0; nmap<nsamples; nmap++)
00329 {
00330 UINT n = m_nSamples+nmap+1;
00331 if (n >= MAX_SAMPLES)
00332 {
00333 n = m_nSamples;
00334 while (n > 0)
00335 {
00336 if (!Ins[n].pSample)
00337 {
00338 for (UINT xmapchk=0; xmapchk < nmap; xmapchk++)
00339 {
00340 if (samplemap[xmapchk] == n) goto alreadymapped;
00341 }
00342 for (UINT clrs=1; clrs<iIns; clrs++) if (Headers[clrs])
00343 {
00344 INSTRUMENTHEADER *pks = Headers[clrs];
00345 for (UINT ks=0; ks<128; ks++)
00346 {
00347 if (pks->Keyboard[ks] == n) pks->Keyboard[ks] = 0;
00348 }
00349 }
00350 break;
00351 }
00352 alreadymapped:
00353 n--;
00354 }
00355 #ifndef FASTSOUNDLIB
00356
00357 if (!n)
00358 {
00359 if (!unused_samples)
00360 {
00361 unused_samples = DetectUnusedSamples(samples_used);
00362 if (!unused_samples) unused_samples = 0xFFFF;
00363 }
00364 if ((unused_samples) && (unused_samples != 0xFFFF))
00365 {
00366 for (UINT iext=m_nSamples; iext>=1; iext--) if (!samples_used[iext])
00367 {
00368 unused_samples--;
00369 samples_used[iext] = TRUE;
00370 DestroySample(iext);
00371 n = iext;
00372 for (UINT mapchk=0; mapchk<nmap; mapchk++)
00373 {
00374 if (samplemap[mapchk] == n) samplemap[mapchk] = 0;
00375 }
00376 for (UINT clrs=1; clrs<iIns; clrs++) if (Headers[clrs])
00377 {
00378 INSTRUMENTHEADER *pks = Headers[clrs];
00379 for (UINT ks=0; ks<128; ks++)
00380 {
00381 if (pks->Keyboard[ks] == n) pks->Keyboard[ks] = 0;
00382 }
00383 }
00384 memset(&Ins[n], 0, sizeof(Ins[0]));
00385 break;
00386 }
00387 }
00388 }
00389 #endif // FASTSOUNDLIB
00390 }
00391 if (newsamples < n) newsamples = n;
00392 samplemap[nmap] = n;
00393 }
00394 m_nSamples = newsamples;
00395
00396 INSTRUMENTHEADER *penv = Headers[iIns];
00397 penv->nMidiProgram = pih->type;
00398 penv->nFadeOut = xmsh.volfade;
00399 penv->nPan = 128;
00400 penv->nPPC = 5*12;
00401 if (xmsh.vtype & 1) penv->dwFlags |= ENV_VOLUME;
00402 if (xmsh.vtype & 2) penv->dwFlags |= ENV_VOLSUSTAIN;
00403 if (xmsh.vtype & 4) penv->dwFlags |= ENV_VOLLOOP;
00404 if (xmsh.ptype & 1) penv->dwFlags |= ENV_PANNING;
00405 if (xmsh.ptype & 2) penv->dwFlags |= ENV_PANSUSTAIN;
00406 if (xmsh.ptype & 4) penv->dwFlags |= ENV_PANLOOP;
00407 if (xmsh.vnum > 12) xmsh.vnum = 12;
00408 if (xmsh.pnum > 12) xmsh.pnum = 12;
00409 penv->nVolEnv = xmsh.vnum;
00410 if (!xmsh.vnum) penv->dwFlags &= ~ENV_VOLUME;
00411 if (!xmsh.pnum) penv->dwFlags &= ~ENV_PANNING;
00412 penv->nPanEnv = xmsh.pnum;
00413 penv->nVolSustainBegin = penv->nVolSustainEnd = xmsh.vsustain;
00414 if (xmsh.vsustain >= 12) penv->dwFlags &= ~ENV_VOLSUSTAIN;
00415 penv->nVolLoopStart = xmsh.vloops;
00416 penv->nVolLoopEnd = xmsh.vloope;
00417 if (penv->nVolLoopEnd >= 12) penv->nVolLoopEnd = 0;
00418 if (penv->nVolLoopStart >= penv->nVolLoopEnd) penv->dwFlags &= ~ENV_VOLLOOP;
00419 penv->nPanSustainBegin = penv->nPanSustainEnd = xmsh.psustain;
00420 if (xmsh.psustain >= 12) penv->dwFlags &= ~ENV_PANSUSTAIN;
00421 penv->nPanLoopStart = xmsh.ploops;
00422 penv->nPanLoopEnd = xmsh.ploope;
00423 if (penv->nPanLoopEnd >= 12) penv->nPanLoopEnd = 0;
00424 if (penv->nPanLoopStart >= penv->nPanLoopEnd) penv->dwFlags &= ~ENV_PANLOOP;
00425 penv->nGlobalVol = 64;
00426 for (UINT ienv=0; ienv<12; ienv++)
00427 {
00428 penv->VolPoints[ienv] = (WORD)xmsh.venv[ienv*2];
00429 penv->VolEnv[ienv] = (BYTE)xmsh.venv[ienv*2+1];
00430 penv->PanPoints[ienv] = (WORD)xmsh.penv[ienv*2];
00431 penv->PanEnv[ienv] = (BYTE)xmsh.penv[ienv*2+1];
00432 if (ienv)
00433 {
00434 if (penv->VolPoints[ienv] < penv->VolPoints[ienv-1])
00435 {
00436 penv->VolPoints[ienv] &= 0xFF;
00437 penv->VolPoints[ienv] += penv->VolPoints[ienv-1] & 0xFF00;
00438 if (penv->VolPoints[ienv] < penv->VolPoints[ienv-1]) penv->VolPoints[ienv] += 0x100;
00439 }
00440 if (penv->PanPoints[ienv] < penv->PanPoints[ienv-1])
00441 {
00442 penv->PanPoints[ienv] &= 0xFF;
00443 penv->PanPoints[ienv] += penv->PanPoints[ienv-1] & 0xFF00;
00444 if (penv->PanPoints[ienv] < penv->PanPoints[ienv-1]) penv->PanPoints[ienv] += 0x100;
00445 }
00446 }
00447 }
00448 for (UINT j=0; j<96; j++)
00449 {
00450 penv->NoteMap[j+12] = j+1+12;
00451 if (xmsh.snum[j] < nsamples)
00452 penv->Keyboard[j+12] = samplemap[xmsh.snum[j]];
00453 }
00454
00455 for (UINT ins=0; ins<nsamples; ins++)
00456 {
00457 if ((dwMemPos + sizeof(xmss) > dwMemLength)
00458 || (dwMemPos + xmsh.shsize > dwMemLength)) return TRUE;
00459 memcpy(&xmss, lpStream+dwMemPos, sizeof(xmss));
00460 xmss.samplen = bswapLE32(xmss.samplen);
00461 xmss.loopstart = bswapLE32(xmss.loopstart);
00462 xmss.looplen = bswapLE32(xmss.looplen);
00463 dwMemPos += xmsh.shsize;
00464 flags[ins] = (xmss.type & 0x10) ? RS_PCM16D : RS_PCM8D;
00465 if (xmss.type & 0x20) flags[ins] = (xmss.type & 0x10) ? RS_STPCM16D : RS_STPCM8D;
00466 samplesize[ins] = xmss.samplen;
00467 if (!samplemap[ins]) continue;
00468 if (xmss.type & 0x10)
00469 {
00470 xmss.looplen >>= 1;
00471 xmss.loopstart >>= 1;
00472 xmss.samplen >>= 1;
00473 }
00474 if (xmss.type & 0x20)
00475 {
00476 xmss.looplen >>= 1;
00477 xmss.loopstart >>= 1;
00478 xmss.samplen >>= 1;
00479 }
00480 if (xmss.samplen > MAX_SAMPLE_LENGTH) xmss.samplen = MAX_SAMPLE_LENGTH;
00481 if (xmss.loopstart >= xmss.samplen) xmss.type &= ~3;
00482 xmss.looplen += xmss.loopstart;
00483 if (xmss.looplen > xmss.samplen) xmss.looplen = xmss.samplen;
00484 if (!xmss.looplen) xmss.type &= ~3;
00485 UINT imapsmp = samplemap[ins];
00486 memcpy(m_szNames[imapsmp], xmss.name, 22);
00487 m_szNames[imapsmp][22] = 0;
00488 MODINSTRUMENT *pins = &Ins[imapsmp];
00489 pins->nLength = (xmss.samplen > MAX_SAMPLE_LENGTH) ? MAX_SAMPLE_LENGTH : xmss.samplen;
00490 pins->nLoopStart = xmss.loopstart;
00491 pins->nLoopEnd = xmss.looplen;
00492 if (pins->nLoopEnd > pins->nLength) pins->nLoopEnd = pins->nLength;
00493 if (pins->nLoopStart >= pins->nLoopEnd)
00494 {
00495 pins->nLoopStart = pins->nLoopEnd = 0;
00496 }
00497 if (xmss.type & 3) pins->uFlags |= CHN_LOOP;
00498 if (xmss.type & 2) pins->uFlags |= CHN_PINGPONGLOOP;
00499 pins->nVolume = xmss.vol << 2;
00500 if (pins->nVolume > 256) pins->nVolume = 256;
00501 pins->nGlobalVol = 64;
00502 if ((xmss.res == 0xAD) && (!(xmss.type & 0x30)))
00503 {
00504 flags[ins] = RS_ADPCM4;
00505 samplesize[ins] = (samplesize[ins]+1)/2 + 16;
00506 }
00507 pins->nFineTune = xmss.finetune;
00508 pins->RelativeTone = (int)xmss.relnote;
00509 pins->nPan = xmss.pan;
00510 pins->uFlags |= CHN_PANNING;
00511 pins->nVibType = xmsh.vibtype;
00512 pins->nVibSweep = xmsh.vibsweep;
00513 pins->nVibDepth = xmsh.vibdepth;
00514 pins->nVibRate = xmsh.vibrate;
00515 memcpy(pins->name, xmss.name, 22);
00516 pins->name[21] = 0;
00517 }
00518 #if 0
00519 if ((xmsh.reserved2 > nsamples) && (xmsh.reserved2 <= 16))
00520 {
00521 dwMemPos += (((UINT)xmsh.reserved2) - nsamples) * xmsh.shsize;
00522 }
00523 #endif
00524 for (UINT ismpd=0; ismpd<nsamples; ismpd++)
00525 {
00526 if ((samplemap[ismpd]) && (samplesize[ismpd]) && (dwMemPos < dwMemLength))
00527 {
00528 ReadSample(&Ins[samplemap[ismpd]], flags[ismpd], (LPSTR)(lpStream + dwMemPos), dwMemLength - dwMemPos);
00529 }
00530 dwMemPos += samplesize[ismpd];
00531 if (dwMemPos >= dwMemLength) break;
00532 }
00533 }
00534
00535 if ((dwMemPos + 8 < dwMemLength) && (bswapLE32(*((DWORD *)(lpStream+dwMemPos))) == 0x74786574))
00536 {
00537 UINT len = *((DWORD *)(lpStream+dwMemPos+4));
00538 dwMemPos += 8;
00539 if ((dwMemPos + len <= dwMemLength) && (len < 16384))
00540 {
00541 m_lpszSongComments = new char[len+1];
00542 if (m_lpszSongComments)
00543 {
00544 memcpy(m_lpszSongComments, lpStream+dwMemPos, len);
00545 m_lpszSongComments[len] = 0;
00546 }
00547 dwMemPos += len;
00548 }
00549 }
00550
00551 if ((dwMemPos + 8 < dwMemLength) && (bswapLE32(*((DWORD *)(lpStream+dwMemPos))) == 0x4944494D))
00552 {
00553 UINT len = *((DWORD *)(lpStream+dwMemPos+4));
00554 dwMemPos += 8;
00555 if (len == sizeof(MODMIDICFG))
00556 {
00557 memcpy(&m_MidiCfg, lpStream+dwMemPos, len);
00558 m_dwSongFlags |= SONG_EMBEDMIDICFG;
00559 }
00560 }
00561
00562 if ((dwMemPos + 8 < dwMemLength) && (bswapLE32(*((DWORD *)(lpStream+dwMemPos))) == 0x4d414e50))
00563 {
00564 UINT len = *((DWORD *)(lpStream+dwMemPos+4));
00565 dwMemPos += 8;
00566 if ((dwMemPos + len <= dwMemLength) && (len <= MAX_PATTERNS*MAX_PATTERNNAME) && (len >= MAX_PATTERNNAME))
00567 {
00568 m_lpszPatternNames = new char[len];
00569
00570 if (m_lpszPatternNames)
00571 {
00572 m_nPatternNames = len / MAX_PATTERNNAME;
00573 memcpy(m_lpszPatternNames, lpStream+dwMemPos, len);
00574 }
00575 dwMemPos += len;
00576 }
00577 }
00578
00579 if ((dwMemPos + 8 < dwMemLength) && (bswapLE32(*((DWORD *)(lpStream+dwMemPos))) == 0x4d414e43))
00580 {
00581 UINT len = *((DWORD *)(lpStream+dwMemPos+4));
00582 dwMemPos += 8;
00583 if ((dwMemPos + len <= dwMemLength) && (len <= MAX_BASECHANNELS*MAX_CHANNELNAME))
00584 {
00585 UINT n = len / MAX_CHANNELNAME;
00586 for (UINT i=0; i<n; i++)
00587 {
00588 memcpy(ChnSettings[i].szName, (lpStream+dwMemPos+i*MAX_CHANNELNAME), MAX_CHANNELNAME);
00589 ChnSettings[i].szName[MAX_CHANNELNAME-1] = 0;
00590 }
00591 dwMemPos += len;
00592 }
00593 }
00594
00595 if (dwMemPos + 8 < dwMemLength)
00596 {
00597 dwMemPos += LoadMixPlugins(lpStream+dwMemPos, dwMemLength-dwMemPos);
00598 }
00599 return TRUE;
00600 }
00601
00602
00603 #ifndef MODPLUG_NO_FILESAVE
00604
00605 BOOL CSoundFile::SaveXM(LPCSTR lpszFileName, UINT nPacking)
00606
00607 {
00608 BYTE s[64*64*5];
00609 XMFILEHEADER header;
00610 XMINSTRUMENTHEADER xmih;
00611 XMSAMPLEHEADER xmsh;
00612 XMSAMPLESTRUCT xmss;
00613 BYTE smptable[32];
00614 BYTE xmph[9];
00615 FILE *f;
00616 int i;
00617
00618 if ((!m_nChannels) || (!lpszFileName)) return FALSE;
00619 if ((f = fopen(lpszFileName, "wb")) == NULL) return FALSE;
00620 fwrite("Extended Module: ", 17, 1, f);
00621 fwrite(m_szNames[0], 20, 1, f);
00622 s[0] = 0x1A;
00623 lstrcpy((LPSTR)&s[1], (nPacking) ? "MOD Plugin packed " : "FastTracker v2.00 ");
00624 s[21] = 0x04;
00625 s[22] = 0x01;
00626 fwrite(s, 23, 1, f);
00627
00628 memset(&header, 0, sizeof(header));
00629 header.size = sizeof(XMFILEHEADER);
00630 header.norder = 0;
00631 header.restartpos = m_nRestartPos;
00632 header.channels = m_nChannels;
00633 header.patterns = 0;
00634 for (i=0; i<MAX_ORDERS; i++)
00635 {
00636 if (Order[i] == 0xFF) break;
00637 header.norder++;
00638 if ((Order[i] >= header.patterns) && (Order[i] < MAX_PATTERNS)) header.patterns = Order[i]+1;
00639 }
00640 header.instruments = m_nInstruments;
00641 if (!header.instruments) header.instruments = m_nSamples;
00642 header.flags = (m_dwSongFlags & SONG_LINEARSLIDES) ? 0x01 : 0x00;
00643 if (m_dwSongFlags & SONG_EXFILTERRANGE) header.flags |= 0x1000;
00644 header.tempo = m_nDefaultTempo;
00645 header.speed = m_nDefaultSpeed;
00646 memcpy(header.order, Order, header.norder);
00647 fwrite(&header, 1, sizeof(header), f);
00648
00649 for (i=0; i<header.patterns; i++) if (Patterns[i])
00650 {
00651 MODCOMMAND *p = Patterns[i];
00652 UINT len = 0;
00653
00654 memset(&xmph, 0, sizeof(xmph));
00655 xmph[0] = 9;
00656 xmph[5] = (BYTE)(PatternSize[i] & 0xFF);
00657 xmph[6] = (BYTE)(PatternSize[i] >> 8);
00658 for (UINT j=m_nChannels*PatternSize[i]; j; j--,p++)
00659 {
00660 UINT note = p->note;
00661 UINT param = ModSaveCommand(p, TRUE);
00662 UINT command = param >> 8;
00663 param &= 0xFF;
00664 if (note >= 0xFE) note = 97; else
00665 if ((note <= 12) || (note > 96+12)) note = 0; else
00666 note -= 12;
00667 UINT vol = 0;
00668 if (p->volcmd)
00669 {
00670 UINT volcmd = p->volcmd;
00671 switch(volcmd)
00672 {
00673 case VOLCMD_VOLUME: vol = 0x10 + p->vol; break;
00674 case VOLCMD_VOLSLIDEDOWN: vol = 0x60 + (p->vol & 0x0F); break;
00675 case VOLCMD_VOLSLIDEUP: vol = 0x70 + (p->vol & 0x0F); break;
00676 case VOLCMD_FINEVOLDOWN: vol = 0x80 + (p->vol & 0x0F); break;
00677 case VOLCMD_FINEVOLUP: vol = 0x90 + (p->vol & 0x0F); break;
00678 case VOLCMD_VIBRATOSPEED: vol = 0xA0 + (p->vol & 0x0F); break;
00679 case VOLCMD_VIBRATO: vol = 0xB0 + (p->vol & 0x0F); break;
00680 case VOLCMD_PANNING: vol = 0xC0 + (p->vol >> 2); if (vol > 0xCF) vol = 0xCF; break;
00681 case VOLCMD_PANSLIDELEFT: vol = 0xD0 + (p->vol & 0x0F); break;
00682 case VOLCMD_PANSLIDERIGHT: vol = 0xE0 + (p->vol & 0x0F); break;
00683 case VOLCMD_TONEPORTAMENTO: vol = 0xF0 + (p->vol & 0x0F); break;
00684 }
00685 }
00686 if ((note) && (p->instr) && (vol > 0x0F) && (command) && (param))
00687 {
00688 s[len++] = note;
00689 s[len++] = p->instr;
00690 s[len++] = vol;
00691 s[len++] = command;
00692 s[len++] = param;
00693 } else
00694 {
00695 BYTE b = 0x80;
00696 if (note) b |= 0x01;
00697 if (p->instr) b |= 0x02;
00698 if (vol >= 0x10) b |= 0x04;
00699 if (command) b |= 0x08;
00700 if (param) b |= 0x10;
00701 s[len++] = b;
00702 if (b & 1) s[len++] = note;
00703 if (b & 2) s[len++] = p->instr;
00704 if (b & 4) s[len++] = vol;
00705 if (b & 8) s[len++] = command;
00706 if (b & 16) s[len++] = param;
00707 }
00708 if (len > sizeof(s) - 5) break;
00709 }
00710 xmph[7] = (BYTE)(len & 0xFF);
00711 xmph[8] = (BYTE)(len >> 8);
00712 fwrite(xmph, 1, 9, f);
00713 fwrite(s, 1, len, f);
00714 } else
00715 {
00716 memset(&xmph, 0, sizeof(xmph));
00717 xmph[0] = 9;
00718 xmph[5] = (BYTE)(PatternSize[i] & 0xFF);
00719 xmph[6] = (BYTE)(PatternSize[i] >> 8);
00720 fwrite(xmph, 1, 9, f);
00721 }
00722
00723 for (i=1; i<=header.instruments; i++)
00724 {
00725 MODINSTRUMENT *pins;
00726 BYTE flags[32];
00727
00728 memset(&xmih, 0, sizeof(xmih));
00729 memset(&xmsh, 0, sizeof(xmsh));
00730 xmih.size = sizeof(xmih) + sizeof(xmsh);
00731 memcpy(xmih.name, m_szNames[i], 22);
00732 xmih.type = 0;
00733 xmih.samples = 0;
00734 if (m_nInstruments)
00735 {
00736 INSTRUMENTHEADER *penv = Headers[i];
00737 if (penv)
00738 {
00739 memcpy(xmih.name, penv->name, 22);
00740 xmih.type = penv->nMidiProgram;
00741 xmsh.volfade = penv->nFadeOut;
00742 xmsh.vnum = (BYTE)penv->nVolEnv;
00743 xmsh.pnum = (BYTE)penv->nPanEnv;
00744 if (xmsh.vnum > 12) xmsh.vnum = 12;
00745 if (xmsh.pnum > 12) xmsh.pnum = 12;
00746 for (UINT ienv=0; ienv<12; ienv++)
00747 {
00748 xmsh.venv[ienv*2] = penv->VolPoints[ienv];
00749 xmsh.venv[ienv*2+1] = penv->VolEnv[ienv];
00750 xmsh.penv[ienv*2] = penv->PanPoints[ienv];
00751 xmsh.penv[ienv*2+1] = penv->PanEnv[ienv];
00752 }
00753 if (penv->dwFlags & ENV_VOLUME) xmsh.vtype |= 1;
00754 if (penv->dwFlags & ENV_VOLSUSTAIN) xmsh.vtype |= 2;
00755 if (penv->dwFlags & ENV_VOLLOOP) xmsh.vtype |= 4;
00756 if (penv->dwFlags & ENV_PANNING) xmsh.ptype |= 1;
00757 if (penv->dwFlags & ENV_PANSUSTAIN) xmsh.ptype |= 2;
00758 if (penv->dwFlags & ENV_PANLOOP) xmsh.ptype |= 4;
00759 xmsh.vsustain = (BYTE)penv->nVolSustainBegin;
00760 xmsh.vloops = (BYTE)penv->nVolLoopStart;
00761 xmsh.vloope = (BYTE)penv->nVolLoopEnd;
00762 xmsh.psustain = (BYTE)penv->nPanSustainBegin;
00763 xmsh.ploops = (BYTE)penv->nPanLoopStart;
00764 xmsh.ploope = (BYTE)penv->nPanLoopEnd;
00765 for (UINT j=0; j<96; j++) if (penv->Keyboard[j+12])
00766 {
00767 UINT k;
00768 for (k=0; k<xmih.samples; k++) if (smptable[k] == penv->Keyboard[j+12]) break;
00769 if (k == xmih.samples)
00770 {
00771 smptable[xmih.samples++] = penv->Keyboard[j+12];
00772 }
00773 if (xmih.samples >= 32) break;
00774 xmsh.snum[j] = k;
00775 }
00776
00777 }
00778 } else
00779 {
00780 xmih.samples = 1;
00781
00782 smptable[0] = i;
00783 }
00784 xmsh.shsize = (xmih.samples) ? 40 : 0;
00785 fwrite(&xmih, 1, sizeof(xmih), f);
00786 if (smptable[0])
00787 {
00788 MODINSTRUMENT *pvib = &Ins[smptable[0]];
00789 xmsh.vibtype = pvib->nVibType;
00790 xmsh.vibsweep = pvib->nVibSweep;
00791 xmsh.vibdepth = pvib->nVibDepth;
00792 xmsh.vibrate = pvib->nVibRate;
00793 }
00794 fwrite(&xmsh, 1, xmih.size - sizeof(xmih), f);
00795 if (!xmih.samples) continue;
00796 for (UINT ins=0; ins<xmih.samples; ins++)
00797 {
00798 memset(&xmss, 0, sizeof(xmss));
00799 if (smptable[ins]) memcpy(xmss.name, m_szNames[smptable[ins]], 22);
00800 pins = &Ins[smptable[ins]];
00801 xmss.samplen = pins->nLength;
00802 xmss.loopstart = pins->nLoopStart;
00803 xmss.looplen = pins->nLoopEnd - pins->nLoopStart;
00804 xmss.vol = pins->nVolume / 4;
00805 xmss.finetune = (char)pins->nFineTune;
00806 xmss.type = 0;
00807 if (pins->uFlags & CHN_LOOP) xmss.type = (pins->uFlags & CHN_PINGPONGLOOP) ? 2 : 1;
00808 flags[ins] = RS_PCM8D;
00809 #ifndef NO_PACKING
00810 if (nPacking)
00811 {
00812 if ((!(pins->uFlags & (CHN_16BIT|CHN_STEREO)))
00813 && (CanPackSample(pins->pSample, pins->nLength, nPacking)))
00814 {
00815 flags[ins] = RS_ADPCM4;
00816 xmss.res = 0xAD;
00817 }
00818 } else
00819 #endif
00820 {
00821 if (pins->uFlags & CHN_16BIT)
00822 {
00823 flags[ins] = RS_PCM16D;
00824 xmss.type |= 0x10;
00825 xmss.looplen *= 2;
00826 xmss.loopstart *= 2;
00827 xmss.samplen *= 2;
00828 }
00829 if (pins->uFlags & CHN_STEREO)
00830 {
00831 flags[ins] = (pins->uFlags & CHN_16BIT) ? RS_STPCM16D : RS_STPCM8D;
00832 xmss.type |= 0x20;
00833 xmss.looplen *= 2;
00834 xmss.loopstart *= 2;
00835 xmss.samplen *= 2;
00836 }
00837 }
00838 xmss.pan = 255;
00839 if (pins->nPan < 256) xmss.pan = (BYTE)pins->nPan;
00840 xmss.relnote = (signed char)pins->RelativeTone;
00841 fwrite(&xmss, 1, xmsh.shsize, f);
00842 }
00843 for (UINT ismpd=0; ismpd<xmih.samples; ismpd++)
00844 {
00845 pins = &Ins[smptable[ismpd]];
00846 if (pins->pSample)
00847 {
00848 #ifndef NO_PACKING
00849 if ((flags[ismpd] == RS_ADPCM4) && (xmih.samples>1)) CanPackSample(pins->pSample, pins->nLength, nPacking);
00850 #endif // NO_PACKING
00851 WriteSample(f, pins, flags[ismpd]);
00852 }
00853 }
00854 }
00855
00856 if ((m_lpszSongComments) && (m_lpszSongComments[0]))
00857 {
00858 DWORD d = 0x74786574;
00859 fwrite(&d, 1, 4, f);
00860 d = strlen(m_lpszSongComments);
00861 fwrite(&d, 1, 4, f);
00862 fwrite(m_lpszSongComments, 1, d, f);
00863 }
00864
00865 if (m_dwSongFlags & SONG_EMBEDMIDICFG)
00866 {
00867 DWORD d = 0x4944494D;
00868 fwrite(&d, 1, 4, f);
00869 d = sizeof(MODMIDICFG);
00870 fwrite(&d, 1, 4, f);
00871 fwrite(&m_MidiCfg, 1, sizeof(MODMIDICFG), f);
00872 }
00873
00874 if ((m_nPatternNames) && (m_lpszPatternNames))
00875 {
00876 DWORD dwLen = m_nPatternNames * MAX_PATTERNNAME;
00877 while ((dwLen >= MAX_PATTERNNAME) && (!m_lpszPatternNames[dwLen-MAX_PATTERNNAME])) dwLen -= MAX_PATTERNNAME;
00878 if (dwLen >= MAX_PATTERNNAME)
00879 {
00880 DWORD d = 0x4d414e50;
00881 fwrite(&d, 1, 4, f);
00882 fwrite(&dwLen, 1, 4, f);
00883 fwrite(m_lpszPatternNames, 1, dwLen, f);
00884 }
00885 }
00886
00887 {
00888 UINT nChnNames = 0;
00889 for (UINT inam=0; inam<m_nChannels; inam++)
00890 {
00891 if (ChnSettings[inam].szName[0]) nChnNames = inam+1;
00892 }
00893
00894 if (nChnNames)
00895 {
00896 DWORD dwLen = nChnNames * MAX_CHANNELNAME;
00897 DWORD d = 0x4d414e43;
00898 fwrite(&d, 1, 4, f);
00899 fwrite(&dwLen, 1, 4, f);
00900 for (UINT inam=0; inam<nChnNames; inam++)
00901 {
00902 fwrite(ChnSettings[inam].szName, 1, MAX_CHANNELNAME, f);
00903 }
00904 }
00905 }
00906
00907 SaveMixPlugins(f);
00908 fclose(f);
00909 return TRUE;
00910 }
00911
00912 #endif // MODPLUG_NO_FILESAVE