00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #include "stdafx.h"
00012 #include "sndfile.h"
00013
00014
00015
00016 #ifdef MED_LOG
00017 extern void Log(LPCSTR s, ...);
00018 #endif
00019
00021
00022
00023
00024 #define MMD_FLAG_FILTERON 0x1
00025 #define MMD_FLAG_JUMPINGON 0x2
00026 #define MMD_FLAG_JUMP8TH 0x4
00027 #define MMD_FLAG_INSTRSATT 0x8 // instruments are attached (this is a module)
00028 #define MMD_FLAG_VOLHEX 0x10
00029 #define MMD_FLAG_STSLIDE 0x20 // SoundTracker mode for slides
00030 #define MMD_FLAG_8CHANNEL 0x40 // OctaMED 8 channel song
00031 #define MMD_FLAG_SLOWHQ 0x80 // HQ slows playing speed (V2-V4 compatibility)
00032
00033 #define MMD_FLAG2_BMASK 0x1F
00034 #define MMD_FLAG2_BPM 0x20
00035 #define MMD_FLAG2_MIX 0x80 // uses Mixing (V7+)
00036
00037 #define MMD_FLAG3_STEREO 0x1 // mixing in Stereo mode
00038 #define MMD_FLAG3_FREEPAN 0x2 // free panning
00039 #define MMD_FLAG3_GM 0x4 // module designed for GM/XG compatibility
00040
00041
00042
00043 #define MMDTAG_END 0
00044 #define MMDTAG_PTR 0x80000000 // data needs relocation
00045 #define MMDTAG_MUSTKNOW 0x40000000 // loader must fail if this isn't recognized
00046 #define MMDTAG_MUSTWARN 0x20000000 // loader must warn if this isn't recognized
00047
00048
00049
00050
00051 #define MMDTAG_EXP_NUMFXGROUPS 1
00052 #define MMDTAG_TRK_NAME (MMDTAG_PTR|1) // trackinfo tags
00053 #define MMDTAG_TRK_NAMELEN 2 // namelen includes zero term.
00054 #define MMDTAG_TRK_FXGROUP 3
00055
00056 #define MMDTAG_FX_ECHOTYPE 1
00057 #define MMDTAG_FX_ECHOLEN 2
00058 #define MMDTAG_FX_ECHODEPTH 3
00059 #define MMDTAG_FX_STEREOSEP 4
00060 #define MMDTAG_FX_GROUPNAME (MMDTAG_PTR|5) // the Global Effects group shouldn't have name saved!
00061 #define MMDTAG_FX_GRPNAMELEN 6 // namelen includes zero term.
00062
00063 #pragma pack(1)
00064
00065 typedef struct tagMEDMODULEHEADER
00066 {
00067 DWORD id;
00068 DWORD modlen;
00069 DWORD song;
00070 WORD psecnum;
00071 WORD pseq;
00072 DWORD blockarr;
00073 DWORD mmdflags;
00074 DWORD smplarr;
00075 DWORD reserved;
00076 DWORD expdata;
00077 DWORD reserved2;
00078 WORD pstate;
00079 WORD pblock;
00080 WORD pline;
00081 WORD pseqnum;
00082 WORD actplayline;
00083 BYTE counter;
00084 BYTE extra_songs;
00085 } Q_PACKED MEDMODULEHEADER;
00086
00087
00088 typedef struct tagMMD0SAMPLE
00089 {
00090 WORD rep, replen;
00091 BYTE midich;
00092 BYTE midipreset;
00093 BYTE svol;
00094 signed char strans;
00095 } Q_PACKED MMD0SAMPLE;
00096
00097
00098
00099 typedef struct tagMMDSAMPLEHEADER
00100 {
00101 DWORD length;
00102 WORD type;
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112 WORD packtype;
00113 WORD subtype;
00114
00115
00116
00117
00118 BYTE commonflags;
00119 BYTE packerflags;
00120 ULONG leftchlen;
00121 ULONG rightchlen;
00122 BYTE SampleData[1];
00123 } Q_PACKED MMDSAMPLEHEADER;
00124
00125
00126
00127 typedef struct tagMMD0SONGHEADER
00128 {
00129 MMD0SAMPLE sample[63];
00130 WORD numblocks;
00131 WORD songlen;
00132 BYTE playseq[256];
00133 WORD deftempo;
00134 signed char playtransp;
00135 BYTE flags;
00136 BYTE flags2;
00137 BYTE tempo2;
00138 BYTE trkvol[16];
00139 BYTE mastervol;
00140 BYTE numsamples;
00141 } Q_PACKED MMD0SONGHEADER;
00142
00143
00144
00145 typedef struct tagMMD2SONGHEADER
00146 {
00147 MMD0SAMPLE sample[63];
00148 WORD numblocks;
00149 WORD numsections;
00150 DWORD playseqtable;
00151 DWORD sectiontable;
00152 DWORD trackvols;
00153 WORD numtracks;
00154 WORD numpseqs;
00155 DWORD trackpans;
00156 LONG flags3;
00157 WORD voladj;
00158 WORD channels;
00159 BYTE mix_echotype;
00160 BYTE mix_echodepth;
00161 WORD mix_echolen;
00162 signed char mix_stereosep;
00163 BYTE pad0[223];
00164 WORD deftempo;
00165 signed char playtransp;
00166 BYTE flags;
00167 BYTE flags2;
00168 BYTE tempo2;
00169 BYTE pad1[16];
00170 BYTE mastervol;
00171 BYTE numsamples;
00172 } Q_PACKED MMD2SONGHEADER;
00173
00174
00175
00176
00177
00178
00179
00180
00181 typedef struct tagMMD0BLOCK
00182 {
00183 BYTE numtracks;
00184 BYTE lines;
00185 } Q_PACKED MMD0BLOCK;
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195 typedef struct tagMMD1BLOCK
00196 {
00197 WORD numtracks;
00198 WORD lines;
00199 DWORD info;
00200 } Q_PACKED MMD1BLOCK;
00201
00202
00203 typedef struct tagMMD1BLOCKINFO
00204 {
00205 DWORD hlmask;
00206 DWORD blockname;
00207 DWORD blocknamelen;
00208 DWORD pagetable;
00209 DWORD cmdexttable;
00210 DWORD reserved[4];
00211 } Q_PACKED MMD1BLOCKINFO;
00212
00213
00214
00215
00216 typedef struct tagMMD2PLAYSEQ
00217 {
00218 CHAR name[32];
00219 DWORD command_offs;
00220 DWORD reserved;
00221 WORD length;
00222 WORD seq[512];
00223 } Q_PACKED MMD2PLAYSEQ;
00224
00225
00226
00227
00228
00229 typedef struct tagMMDCOMMAND
00230 {
00231 WORD offset;
00232 BYTE cmdnumber;
00233 BYTE extra_count;
00234 BYTE extra_bytes[4];
00235 } Q_PACKED MMDCOMMAND;
00236
00237
00238 typedef struct tagMMD0EXP
00239 {
00240 DWORD nextmod;
00241 DWORD exp_smp;
00242 WORD s_ext_entries;
00243 WORD s_ext_entrsz;
00244 DWORD annotxt;
00245 DWORD annolen;
00246 DWORD iinfo;
00247 WORD i_ext_entries;
00248 WORD i_ext_entrsz;
00249 DWORD jumpmask;
00250 DWORD rgbtable;
00251 BYTE channelsplit[4];
00252 DWORD n_info;
00253 DWORD songname;
00254 DWORD songnamelen;
00255 DWORD dumps;
00256 DWORD mmdinfo;
00257 DWORD mmdrexx;
00258 DWORD mmdcmd3x;
00259 DWORD trackinfo_ofs;
00260 DWORD effectinfo_ofs;
00261 DWORD tag_end;
00262 } Q_PACKED MMD0EXP;
00263
00264 #pragma pack()
00265
00266
00267
00268 static void MedConvert(MODCOMMAND *p, const MMD0SONGHEADER *pmsh)
00269
00270 {
00271 const BYTE bpmvals[9] = { 179,164,152,141,131,123,116,110,104};
00272
00273 UINT command = p->command;
00274 UINT param = p->param;
00275 switch(command)
00276 {
00277 case 0x00: if (param) command = CMD_ARPEGGIO; else command = 0; break;
00278 case 0x01: command = CMD_PORTAMENTOUP; break;
00279 case 0x02: command = CMD_PORTAMENTODOWN; break;
00280 case 0x03: command = CMD_TONEPORTAMENTO; break;
00281 case 0x04: command = CMD_VIBRATO; break;
00282 case 0x05: command = CMD_TONEPORTAVOL; break;
00283 case 0x06: command = CMD_VIBRATOVOL; break;
00284 case 0x07: command = CMD_TREMOLO; break;
00285 case 0x0A: if (param & 0xF0) param &= 0xF0; command = CMD_VOLUMESLIDE; if (!param) command = 0; break;
00286 case 0x0B: command = CMD_POSITIONJUMP; break;
00287 case 0x0C: command = CMD_VOLUME;
00288 if (pmsh->flags & MMD_FLAG_VOLHEX)
00289 {
00290 if (param < 0x80)
00291 {
00292 param = (param+1) / 2;
00293 } else command = 0;
00294 } else
00295 {
00296 if (param <= 0x99)
00297 {
00298 param = (param >> 4)*10+((param & 0x0F) % 10);
00299 if (param > 64) param = 64;
00300 } else command = 0;
00301 }
00302 break;
00303 case 0x09: command = (param < 0x20) ? CMD_SPEED : CMD_TEMPO; break;
00304 case 0x0D: if (param & 0xF0) param &= 0xF0; command = CMD_VOLUMESLIDE; if (!param) command = 0; break;
00305 case 0x0F:
00306
00307 if (!param) command = CMD_PATTERNBREAK; else
00308
00309 if (param <= 0xF0)
00310 {
00311 if (pmsh->flags & MMD_FLAG_8CHANNEL)
00312 {
00313 param = (param > 10) ? 99 : bpmvals[param-1];
00314 } else
00315
00316 if (param <= 0x0A)
00317 {
00318 command = CMD_SPEED;
00319 } else
00320
00321 if (!(pmsh->flags2 & MMD_FLAG2_BPM))
00322 {
00323 param = _muldiv(param, 5*715909, 2*474326);
00324 }
00325
00326 if (param > 0x0A)
00327 {
00328 command = CMD_TEMPO;
00329 if (param < 0x21) param = 0x21;
00330 if (param > 240) param = 240;
00331 }
00332 } else
00333 switch(param)
00334 {
00335
00336 case 0xF1:
00337 command = CMD_MODCMDEX;
00338 param = 0x93;
00339 break;
00340
00341 case 0xF2:
00342 command = CMD_MODCMDEX;
00343 param = 0xD3;
00344 break;
00345
00346 case 0xF3:
00347 command = CMD_MODCMDEX;
00348 param = 0x92;
00349 break;
00350
00351 case 0xF4:
00352 command = CMD_MODCMDEX;
00353 param = 0xD2;
00354 break;
00355
00356 case 0xF5:
00357 command = CMD_MODCMDEX;
00358 param = 0xD4;
00359 break;
00360
00361 case 0xF8:
00362 command = CMD_MODCMDEX;
00363 param = 0x00;
00364 break;
00365
00366 case 0xF9:
00367 command = CMD_MODCMDEX;
00368 param = 0x01;
00369 break;
00370
00371 case 0xFD:
00372 command = CMD_TONEPORTAMENTO;
00373 param = 0xFF;
00374 break;
00375
00376 case 0xFE:
00377 command = CMD_SPEED;
00378 param = 0;
00379 break;
00380
00381 case 0xFF:
00382 command = CMD_MODCMDEX;
00383 param = 0xC0;
00384 break;
00385 default:
00386 #ifdef MED_LOG
00387 Log("Unknown Fxx command: cmd=0x%02X param=0x%02X\n", command, param);
00388 #endif
00389 param = command = 0;
00390 }
00391 break;
00392
00393 case 0x11:
00394 command = CMD_MODCMDEX;
00395 if (param > 0x0F) param = 0x0F;
00396 param |= 0x10;
00397 break;
00398
00399 case 0x12:
00400 command = CMD_MODCMDEX;
00401 if (param > 0x0F) param = 0x0F;
00402 param |= 0x20;
00403 break;
00404
00405 case 0x14:
00406 command = CMD_VIBRATO;
00407 break;
00408
00409 case 0x15:
00410 command = CMD_MODCMDEX;
00411 param &= 0x0F;
00412 param |= 0x50;
00413 break;
00414
00415 case 0x16:
00416 command = CMD_MODCMDEX;
00417 if (param > 0x0F) param = 0x0F;
00418 param |= 0x60;
00419 break;
00420
00421 case 0x18:
00422 command = CMD_MODCMDEX;
00423 if (param > 0x0F) param = 0x0F;
00424 param |= 0xC0;
00425 break;
00426
00427 case 0x19:
00428 command = CMD_OFFSET;
00429 break;
00430
00431 case 0x1A:
00432 command = CMD_MODCMDEX;
00433 if (param > 0x0F) param = 0x0F;
00434 param |= 0xA0;
00435 break;
00436
00437 case 0x1B:
00438 command = CMD_MODCMDEX;
00439 if (param > 0x0F) param = 0x0F;
00440 param |= 0xB0;
00441 break;
00442
00443 case 0x1D:
00444 command = CMD_PATTERNBREAK;
00445 break;
00446
00447 case 0x1E:
00448 command = CMD_MODCMDEX;
00449 if (param > 0x0F) param = 0x0F;
00450 param |= 0xE0;
00451 break;
00452
00453 case 0x1F:
00454 command = CMD_RETRIG;
00455 param &= 0x0F;
00456 break;
00457
00458 case 0x2E:
00459 command = CMD_MODCMDEX;
00460 param = ((param + 0x10) & 0xFF) >> 1;
00461 if (param > 0x0F) param = 0x0F;
00462 param |= 0x80;
00463 break;
00464 default:
00465 #ifdef MED_LOG
00466
00467 Log("Unknown command: cmd=0x%02X param=0x%02X\n", command, param);
00468 #endif
00469 command = param = 0;
00470 }
00471 p->command = command;
00472 p->param = param;
00473 }
00474
00475
00476 BOOL CSoundFile::ReadMed(const BYTE *lpStream, DWORD dwMemLength)
00477
00478 {
00479 const MEDMODULEHEADER *pmmh;
00480 const MMD0SONGHEADER *pmsh;
00481 const MMD2SONGHEADER *pmsh2;
00482 const MMD0EXP *pmex;
00483 DWORD dwBlockArr, dwSmplArr, dwExpData, wNumBlocks;
00484 LPDWORD pdwTable;
00485 CHAR version;
00486 UINT deftempo;
00487 int playtransp = 0;
00488
00489 if ((!lpStream) || (dwMemLength < 0x200)) return FALSE;
00490 pmmh = (MEDMODULEHEADER *)lpStream;
00491 if (((pmmh->id & 0x00FFFFFF) != 0x444D4D) || (!pmmh->song)) return FALSE;
00492
00493 DWORD dwSong = bswapBE32(pmmh->song);
00494 if ((dwSong >= dwMemLength) || (dwSong + sizeof(MMD0SONGHEADER) >= dwMemLength)) return FALSE;
00495 version = (signed char)((pmmh->id >> 24) & 0xFF);
00496 if ((version < '0') || (version > '3')) return FALSE;
00497 #ifdef MED_LOG
00498 Log("\nLoading MMD%c module (flags=0x%02X)...\n", version, bswapBE32(pmmh->mmdflags));
00499 Log(" modlen = %d\n", bswapBE32(pmmh->modlen));
00500 Log(" song = 0x%08X\n", bswapBE32(pmmh->song));
00501 Log(" psecnum = %d\n", bswapBE16(pmmh->psecnum));
00502 Log(" pseq = %d\n", bswapBE16(pmmh->pseq));
00503 Log(" blockarr = 0x%08X\n", bswapBE32(pmmh->blockarr));
00504 Log(" mmdflags = 0x%08X\n", bswapBE32(pmmh->mmdflags));
00505 Log(" smplarr = 0x%08X\n", bswapBE32(pmmh->smplarr));
00506 Log(" reserved = 0x%08X\n", bswapBE32(pmmh->reserved));
00507 Log(" expdata = 0x%08X\n", bswapBE32(pmmh->expdata));
00508 Log(" reserved2= 0x%08X\n", bswapBE32(pmmh->reserved2));
00509 Log(" pstate = %d\n", bswapBE16(pmmh->pstate));
00510 Log(" pblock = %d\n", bswapBE16(pmmh->pblock));
00511 Log(" pline = %d\n", bswapBE16(pmmh->pline));
00512 Log(" pseqnum = %d\n", bswapBE16(pmmh->pseqnum));
00513 Log(" actplayline=%d\n", bswapBE16(pmmh->actplayline));
00514 Log(" counter = %d\n", pmmh->counter);
00515 Log(" extra_songs = %d\n", pmmh->extra_songs);
00516 Log("\n");
00517 #endif
00518 m_nType = MOD_TYPE_MED;
00519 m_nSongPreAmp = 0x20;
00520 dwBlockArr = bswapBE32(pmmh->blockarr);
00521 dwSmplArr = bswapBE32(pmmh->smplarr);
00522 dwExpData = bswapBE32(pmmh->expdata);
00523 if ((dwExpData) && (dwExpData+sizeof(MMD0EXP) < dwMemLength))
00524 pmex = (MMD0EXP *)(lpStream+dwExpData);
00525 else
00526 pmex = NULL;
00527 pmsh = (MMD0SONGHEADER *)(lpStream + dwSong);
00528 pmsh2 = (MMD2SONGHEADER *)pmsh;
00529 #ifdef MED_LOG
00530 if (version < '2')
00531 {
00532 Log("MMD0 Header:\n");
00533 Log(" numblocks = %d\n", bswapBE16(pmsh->numblocks));
00534 Log(" songlen = %d\n", bswapBE16(pmsh->songlen));
00535 Log(" playseq = ");
00536 for (UINT idbg1=0; idbg1<16; idbg1++) Log("%2d, ", pmsh->playseq[idbg1]);
00537 Log("...\n");
00538 Log(" deftempo = 0x%04X\n", bswapBE16(pmsh->deftempo));
00539 Log(" playtransp = %d\n", (signed char)pmsh->playtransp);
00540 Log(" flags(1,2) = 0x%02X, 0x%02X\n", pmsh->flags, pmsh->flags2);
00541 Log(" tempo2 = %d\n", pmsh->tempo2);
00542 Log(" trkvol = ");
00543 for (UINT idbg2=0; idbg2<16; idbg2++) Log("0x%02X, ", pmsh->trkvol[idbg2]);
00544 Log("...\n");
00545 Log(" mastervol = 0x%02X\n", pmsh->mastervol);
00546 Log(" numsamples = %d\n", pmsh->numsamples);
00547 } else
00548 {
00549 Log("MMD2 Header:\n");
00550 Log(" numblocks = %d\n", bswapBE16(pmsh2->numblocks));
00551 Log(" numsections= %d\n", bswapBE16(pmsh2->numsections));
00552 Log(" playseqptr = 0x%04X\n", bswapBE32(pmsh2->playseqtable));
00553 Log(" sectionptr = 0x%04X\n", bswapBE32(pmsh2->sectiontable));
00554 Log(" trackvols = 0x%04X\n", bswapBE32(pmsh2->trackvols));
00555 Log(" numtracks = %d\n", bswapBE16(pmsh2->numtracks));
00556 Log(" numpseqs = %d\n", bswapBE16(pmsh2->numpseqs));
00557 Log(" trackpans = 0x%04X\n", bswapBE32(pmsh2->trackpans));
00558 Log(" flags3 = 0x%08X\n", bswapBE32(pmsh2->flags3));
00559 Log(" voladj = %d\n", bswapBE16(pmsh2->voladj));
00560 Log(" channels = %d\n", bswapBE16(pmsh2->channels));
00561 Log(" echotype = %d\n", pmsh2->mix_echotype);
00562 Log(" echodepth = %d\n", pmsh2->mix_echodepth);
00563 Log(" echolen = %d\n", bswapBE16(pmsh2->mix_echolen));
00564 Log(" stereosep = %d\n", (signed char)pmsh2->mix_stereosep);
00565 Log(" deftempo = 0x%04X\n", bswapBE16(pmsh2->deftempo));
00566 Log(" playtransp = %d\n", (signed char)pmsh2->playtransp);
00567 Log(" flags(1,2) = 0x%02X, 0x%02X\n", pmsh2->flags, pmsh2->flags2);
00568 Log(" tempo2 = %d\n", pmsh2->tempo2);
00569 Log(" mastervol = 0x%02X\n", pmsh2->mastervol);
00570 Log(" numsamples = %d\n", pmsh->numsamples);
00571 }
00572 Log("\n");
00573 #endif
00574 wNumBlocks = bswapBE16(pmsh->numblocks);
00575 m_nChannels = 4;
00576 m_nSamples = pmsh->numsamples;
00577 if (m_nSamples > 63) m_nSamples = 63;
00578
00579 m_nDefaultTempo = 125;
00580 deftempo = bswapBE16(pmsh->deftempo);
00581 if (!deftempo) deftempo = 125;
00582 if (pmsh->flags2 & MMD_FLAG2_BPM)
00583 {
00584 UINT tempo_tpl = (pmsh->flags2 & MMD_FLAG2_BMASK) + 1;
00585 if (!tempo_tpl) tempo_tpl = 4;
00586 deftempo *= tempo_tpl;
00587 deftempo /= 4;
00588 #ifdef MED_LOG
00589 Log("newtempo: %3d bpm (bpm=%3d lpb=%2d)\n", deftempo, bswapBE16(pmsh->deftempo), (pmsh->flags2 & MMD_FLAG2_BMASK)+1);
00590 #endif
00591 } else
00592 {
00593 deftempo = _muldiv(deftempo, 5*715909, 2*474326);
00594 #ifdef MED_LOG
00595 Log("oldtempo: %3d bpm (bpm=%3d)\n", deftempo, bswapBE16(pmsh->deftempo));
00596 #endif
00597 }
00598
00599 m_nDefaultSpeed = pmsh->tempo2;
00600 if (!m_nDefaultSpeed) m_nDefaultSpeed = 6;
00601 if (deftempo < 0x21) deftempo = 0x21;
00602 if (deftempo > 255)
00603 {
00604 while ((m_nDefaultSpeed > 3) && (deftempo > 260))
00605 {
00606 deftempo = (deftempo * (m_nDefaultSpeed - 1)) / m_nDefaultSpeed;
00607 m_nDefaultSpeed--;
00608 }
00609 if (deftempo > 255) deftempo = 255;
00610 }
00611 m_nDefaultTempo = deftempo;
00612
00613 for (UINT iSHdr=0; iSHdr<m_nSamples; iSHdr++)
00614 {
00615 MODINSTRUMENT *pins = &Ins[iSHdr+1];
00616 pins->nLoopStart = bswapBE16(pmsh->sample[iSHdr].rep) << 1;
00617 pins->nLoopEnd = pins->nLoopStart + (bswapBE16(pmsh->sample[iSHdr].replen) << 1);
00618 pins->nVolume = (pmsh->sample[iSHdr].svol << 2);
00619 pins->nGlobalVol = 64;
00620 if (pins->nVolume > 256) pins->nVolume = 256;
00621 pins->RelativeTone = -12 * pmsh->sample[iSHdr].strans;
00622 pins->nPan = 128;
00623 if (pins->nLoopEnd) pins->uFlags |= CHN_LOOP;
00624 }
00625
00626 if (!(pmsh->flags & 0x20)) m_dwSongFlags |= SONG_FASTVOLSLIDES;
00627
00628 if (version < '2')
00629 {
00630 UINT nbo = pmsh->songlen >> 8;
00631 if (nbo >= MAX_ORDERS) nbo = MAX_ORDERS-1;
00632 if (!nbo) nbo = 1;
00633 memcpy(Order, pmsh->playseq, nbo);
00634 playtransp = pmsh->playtransp;
00635 } else
00636 {
00637 UINT nOrders, nSections;
00638 UINT nTrks = bswapBE16(pmsh2->numtracks);
00639 if ((nTrks >= 4) && (nTrks <= 32)) m_nChannels = nTrks;
00640 DWORD playseqtable = bswapBE32(pmsh2->playseqtable);
00641 UINT numplayseqs = bswapBE16(pmsh2->numpseqs);
00642 if (!numplayseqs) numplayseqs = 1;
00643 nOrders = 0;
00644 nSections = bswapBE16(pmsh2->numsections);
00645 DWORD sectiontable = bswapBE32(pmsh2->sectiontable);
00646 if ((!nSections) || (!sectiontable) || (sectiontable >= dwMemLength-2)) nSections = 1;
00647 nOrders = 0;
00648 for (UINT iSection=0; iSection<nSections; iSection++)
00649 {
00650 UINT nplayseq = 0;
00651 if ((sectiontable) && (sectiontable < dwMemLength-2))
00652 {
00653 nplayseq = lpStream[sectiontable+1];
00654 sectiontable += 2;
00655 } else
00656 {
00657 nSections = 0;
00658 }
00659 UINT pseq = 0;
00660
00661 if ((playseqtable) && (playseqtable + nplayseq*4 < dwMemLength))
00662 {
00663 pseq = bswapBE32(((LPDWORD)(lpStream+playseqtable))[nplayseq]);
00664 }
00665 if ((pseq) && (pseq < dwMemLength - sizeof(MMD2PLAYSEQ)))
00666 {
00667 MMD2PLAYSEQ *pmps = (MMD2PLAYSEQ *)(lpStream + pseq);
00668 if (!m_szNames[0][0]) memcpy(m_szNames[0], pmps->name, 31);
00669 UINT n = bswapBE16(pmps->length);
00670 if (pseq+n <= dwMemLength)
00671 {
00672 for (UINT i=0; i<n; i++)
00673 {
00674 UINT seqval = pmps->seq[i] >> 8;
00675 if ((seqval < wNumBlocks) && (nOrders < MAX_ORDERS-1))
00676 {
00677 Order[nOrders++] = seqval;
00678 }
00679 }
00680 }
00681 }
00682 }
00683 playtransp = pmsh2->playtransp;
00684 while (nOrders < MAX_ORDERS) Order[nOrders++] = 0xFF;
00685 }
00686
00687 if (pmex)
00688 {
00689
00690 if ((m_nChannels == 4) && (pmsh->flags & 0x40))
00691 {
00692 for (UINT i8ch=0; i8ch<4; i8ch++)
00693 {
00694 if (pmex->channelsplit[i8ch]) m_nChannels++;
00695 }
00696 }
00697
00698 UINT annotxt = bswapBE32(pmex->annotxt);
00699 UINT annolen = bswapBE32(pmex->annolen);
00700 if ((annotxt) && (annolen) && (annotxt+annolen <= dwMemLength))
00701 {
00702 m_lpszSongComments = new char[annolen+1];
00703 memcpy(m_lpszSongComments, lpStream+annotxt, annolen);
00704 m_lpszSongComments[annolen] = 0;
00705 }
00706
00707 UINT songname = bswapBE32(pmex->songname);
00708 UINT songnamelen = bswapBE32(pmex->songnamelen);
00709 if ((songname) && (songnamelen) && (songname+songnamelen <= dwMemLength))
00710 {
00711 if (songnamelen > 31) songnamelen = 31;
00712 memcpy(m_szNames[0], lpStream+songname, songnamelen);
00713 }
00714
00715 DWORD smpinfoex = bswapBE32(pmex->iinfo);
00716 if (smpinfoex)
00717 {
00718 DWORD iinfoptr = bswapBE32(pmex->iinfo);
00719 UINT ientries = bswapBE16(pmex->i_ext_entries);
00720 UINT ientrysz = bswapBE16(pmex->i_ext_entrsz);
00721
00722 if ((iinfoptr) && (ientrysz < 256) && (iinfoptr + ientries*ientrysz < dwMemLength))
00723 {
00724 LPCSTR psznames = (LPCSTR)(lpStream + iinfoptr);
00725 UINT maxnamelen = ientrysz;
00726 if (maxnamelen > 32) maxnamelen = 32;
00727 for (UINT i=0; i<ientries; i++) if (i < m_nSamples)
00728 {
00729 lstrcpyn(m_szNames[i+1], psznames + i*ientrysz, maxnamelen);
00730 }
00731 }
00732 }
00733
00734 DWORD trackinfo_ofs = bswapBE32(pmex->trackinfo_ofs);
00735 if ((trackinfo_ofs) && (trackinfo_ofs + m_nChannels * 4 < dwMemLength))
00736 {
00737 DWORD *ptrktags = (DWORD *)(lpStream + trackinfo_ofs);
00738 for (UINT i=0; i<m_nChannels; i++)
00739 {
00740 DWORD trknameofs = 0, trknamelen = 0;
00741 DWORD trktagofs = bswapBE32(ptrktags[i]);
00742 if (trktagofs)
00743 {
00744 while (trktagofs+8 < dwMemLength)
00745 {
00746 DWORD ntag = bswapBE32(*(DWORD *)(lpStream + trktagofs));
00747 if (ntag == MMDTAG_END) break;
00748 DWORD tagdata = bswapBE32(*(DWORD *)(lpStream + trktagofs + 4));
00749 switch(ntag)
00750 {
00751 case MMDTAG_TRK_NAMELEN: trknamelen = tagdata; break;
00752 case MMDTAG_TRK_NAME: trknameofs = tagdata; break;
00753 }
00754 trktagofs += 8;
00755 }
00756 if (trknamelen > MAX_CHANNELNAME) trknamelen = MAX_CHANNELNAME;
00757 if ((trknameofs) && (trknameofs + trknamelen < dwMemLength))
00758 {
00759 lstrcpyn(ChnSettings[i].szName, (LPCSTR)(lpStream+trknameofs), MAX_CHANNELNAME);
00760 }
00761 }
00762 }
00763 }
00764 }
00765
00766 if (dwSmplArr > dwMemLength - 4*m_nSamples) return TRUE;
00767 pdwTable = (LPDWORD)(lpStream + dwSmplArr);
00768 for (UINT iSmp=0; iSmp<m_nSamples; iSmp++) if (pdwTable[iSmp])
00769 {
00770 UINT dwPos = bswapBE32(pdwTable[iSmp]);
00771 if ((dwPos >= dwMemLength) || (dwPos + sizeof(MMDSAMPLEHEADER) >= dwMemLength)) continue;
00772 MMDSAMPLEHEADER *psdh = (MMDSAMPLEHEADER *)(lpStream + dwPos);
00773 UINT len = bswapBE32(psdh->length);
00774 #ifdef MED_LOG
00775 Log("SampleData %d: stype=0x%02X len=%d\n", iSmp, bswapBE16(psdh->type), len);
00776 #endif
00777 if ((len > MAX_SAMPLE_LENGTH) || (dwPos + len + 6 > dwMemLength)) len = 0;
00778 UINT flags = RS_PCM8S, stype = bswapBE16(psdh->type);
00779 LPSTR psdata = (LPSTR)(lpStream + dwPos + 6);
00780 if (stype & 0x80)
00781 {
00782 psdata += (stype & 0x20) ? 14 : 6;
00783 } else
00784 {
00785 if (stype & 0x10)
00786 {
00787 Ins[iSmp+1].uFlags |= CHN_16BIT;
00788 len /= 2;
00789 flags = (stype & 0x20) ? RS_STPCM16M : RS_PCM16M;
00790 } else
00791 {
00792 flags = (stype & 0x20) ? RS_STPCM8S : RS_PCM8S;
00793 }
00794 if (stype & 0x20) len /= 2;
00795 }
00796 Ins[iSmp+1].nLength = len;
00797 ReadSample(&Ins[iSmp+1], flags, psdata, dwMemLength - dwPos - 6);
00798 }
00799
00800 if (wNumBlocks > MAX_PATTERNS) wNumBlocks = MAX_PATTERNS;
00801 if ((!dwBlockArr) || (dwBlockArr > dwMemLength - 4*wNumBlocks)) return TRUE;
00802 pdwTable = (LPDWORD)(lpStream + dwBlockArr);
00803 playtransp += (version == '3') ? 24 : 48;
00804 for (UINT iBlk=0; iBlk<wNumBlocks; iBlk++)
00805 {
00806 UINT dwPos = bswapBE32(pdwTable[iBlk]);
00807 if ((!dwPos) || (dwPos >= dwMemLength) || (dwPos >= dwMemLength - 8)) continue;
00808 UINT lines = 64, tracks = 4;
00809 if (version == '0')
00810 {
00811 const MMD0BLOCK *pmb = (const MMD0BLOCK *)(lpStream + dwPos);
00812 lines = pmb->lines + 1;
00813 tracks = pmb->numtracks;
00814 if (!tracks) tracks = m_nChannels;
00815 if ((Patterns[iBlk] = AllocatePattern(lines, m_nChannels)) == NULL) continue;
00816 PatternSize[iBlk] = lines;
00817 MODCOMMAND *p = Patterns[iBlk];
00818 LPBYTE s = (LPBYTE)(lpStream + dwPos + 2);
00819 UINT maxlen = tracks*lines*3;
00820 if (maxlen + dwPos > dwMemLength - 2) break;
00821 for (UINT y=0; y<lines; y++)
00822 {
00823 for (UINT x=0; x<tracks; x++, s+=3) if (x < m_nChannels)
00824 {
00825 BYTE note = s[0] & 0x3F;
00826 BYTE instr = s[1] >> 4;
00827 if (s[0] & 0x80) instr |= 0x10;
00828 if (s[0] & 0x40) instr |= 0x20;
00829 if ((note) && (note <= 132)) p->note = note + playtransp;
00830 p->instr = instr;
00831 p->command = s[1] & 0x0F;
00832 p->param = s[2];
00833
00834 MedConvert(p, pmsh);
00835 p++;
00836 }
00837
00838 }
00839 } else
00840 {
00841 MMD1BLOCK *pmb = (MMD1BLOCK *)(lpStream + dwPos);
00842 #ifdef MED_LOG
00843 Log("MMD1BLOCK: lines=%2d, tracks=%2d, offset=0x%04X\n",
00844 bswapBE16(pmb->lines), bswapBE16(pmb->numtracks), bswapBE32(pmb->info));
00845 #endif
00846 MMD1BLOCKINFO *pbi = NULL;
00847 BYTE *pcmdext = NULL;
00848 lines = (pmb->lines >> 8) + 1;
00849 tracks = pmb->numtracks >> 8;
00850 if (!tracks) tracks = m_nChannels;
00851 if ((Patterns[iBlk] = AllocatePattern(lines, m_nChannels)) == NULL) continue;
00852 PatternSize[iBlk] = (WORD)lines;
00853 DWORD dwBlockInfo = bswapBE32(pmb->info);
00854 if ((dwBlockInfo) && (dwBlockInfo < dwMemLength - sizeof(MMD1BLOCKINFO)))
00855 {
00856 pbi = (MMD1BLOCKINFO *)(lpStream + dwBlockInfo);
00857 #ifdef MED_LOG
00858 Log(" BLOCKINFO: blockname=0x%04X namelen=%d pagetable=0x%04X &cmdexttable=0x%04X\n",
00859 bswapBE32(pbi->blockname), bswapBE32(pbi->blocknamelen), bswapBE32(pbi->pagetable), bswapBE32(pbi->cmdexttable));
00860 #endif
00861 if ((pbi->blockname) && (pbi->blocknamelen))
00862 {
00863 DWORD nameofs = bswapBE32(pbi->blockname);
00864 UINT namelen = bswapBE32(pbi->blocknamelen);
00865 if ((nameofs < dwMemLength) && (nameofs+namelen < dwMemLength))
00866 {
00867 SetPatternName(iBlk, (LPCSTR)(lpStream+nameofs));
00868 }
00869 }
00870 if (pbi->cmdexttable)
00871 {
00872 DWORD cmdexttable = bswapBE32(pbi->cmdexttable);
00873 if (cmdexttable < dwMemLength - 4)
00874 {
00875 cmdexttable = bswapBE32(*(DWORD *)(lpStream + cmdexttable));
00876 if ((cmdexttable) && (cmdexttable <= dwMemLength - lines*tracks))
00877 {
00878 pcmdext = (BYTE *)(lpStream + cmdexttable);
00879 }
00880 }
00881 }
00882 }
00883 MODCOMMAND *p = Patterns[iBlk];
00884 LPBYTE s = (LPBYTE)(lpStream + dwPos + 8);
00885 UINT maxlen = tracks*lines*4;
00886 if (maxlen + dwPos > dwMemLength - 8) break;
00887 for (UINT y=0; y<lines; y++)
00888 {
00889 for (UINT x=0; x<tracks; x++, s+=4) if (x < m_nChannels)
00890 {
00891 BYTE note = s[0];
00892 if ((note) && (note <= 132))
00893 {
00894 int rnote = note + playtransp;
00895 if (rnote < 1) rnote = 1;
00896 if (rnote > 120) rnote = 120;
00897 p->note = (BYTE)rnote;
00898 }
00899 p->instr = s[1];
00900 p->command = s[2];
00901 p->param = s[3];
00902 if (pcmdext) p->vol = pcmdext[x];
00903 MedConvert(p, pmsh);
00904 p++;
00905 }
00906 if (pcmdext) pcmdext += tracks;
00907 }
00908 }
00909 }
00910
00911 for (UINT iCh=0; iCh<m_nChannels; iCh++)
00912 {
00913 ChnSettings[iCh].nPan = (((iCh&3) == 1) || ((iCh&3) == 2)) ? 0xC0 : 0x40;
00914 ChnSettings[iCh].nVolume = 64;
00915 }
00916 return TRUE;
00917 }
00918
00919