summaryrefslogtreecommitdiff
path: root/core/multimedia/opieplayer/modplug/load_med.cpp
Unidiff
Diffstat (limited to 'core/multimedia/opieplayer/modplug/load_med.cpp') (more/less context) (ignore whitespace changes)
-rw-r--r--core/multimedia/opieplayer/modplug/load_med.cpp919
1 files changed, 919 insertions, 0 deletions
diff --git a/core/multimedia/opieplayer/modplug/load_med.cpp b/core/multimedia/opieplayer/modplug/load_med.cpp
new file mode 100644
index 0000000..1a4b30c
--- a/dev/null
+++ b/core/multimedia/opieplayer/modplug/load_med.cpp
@@ -0,0 +1,919 @@
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//#define MED_LOG
15
16#ifdef MED_LOG
17extern void Log(LPCSTR s, ...);
18#endif
19
20//////////////////////////////////////////////////////////
21// OctaMed MED file support (import only)
22
23// flags
24 #define MMD_FLAG_FILTERON0x1
25 #define MMD_FLAG_JUMPINGON0x2
26 #define MMD_FLAG_JUMP8TH0x4
27 #define MMD_FLAG_INSTRSATT0x8 // instruments are attached (this is a module)
28 #define MMD_FLAG_VOLHEX 0x10
29 #define MMD_FLAG_STSLIDE0x20 // SoundTracker mode for slides
30 #define MMD_FLAG_8CHANNEL0x40 // OctaMED 8 channel song
31 #define MMD_FLAG_SLOWHQ 0x80 // HQ slows playing speed (V2-V4 compatibility)
32// flags2
33 #define MMD_FLAG2_BMASK 0x1F
34 #define MMD_FLAG2_BPM 0x20
35 #define MMD_FLAG2_MIX 0x80 // uses Mixing (V7+)
36// flags3:
37 #define MMD_FLAG3_STEREO 0x1// mixing in Stereo mode
38 #define MMD_FLAG3_FREEPAN 0x2// free panning
39 #define MMD_FLAG3_GM 0x4 // module designed for GM/XG compatibility
40
41
42// generic MMD tags
43 #define MMDTAG_END 0
44 #define MMDTAG_PTR 0x80000000// data needs relocation
45 #define MMDTAG_MUSTKNOW 0x40000000// loader must fail if this isn't recognized
46 #define MMDTAG_MUSTWARN 0x20000000// loader must warn if this isn't recognized
47
48// ExpData tags
49// # of effect groups, including the global group (will
50// override settings in MMDSong struct), default = 1
51 #define MMDTAG_EXP_NUMFXGROUPS1
52 #define MMDTAG_TRK_NAME (MMDTAG_PTR|1)// trackinfo tags
53 #define MMDTAG_TRK_NAMELEN 2 // namelen includes zero term.
54 #define MMDTAG_TRK_FXGROUP3
55// effectinfo tags
56 #define MMDTAG_FX_ECHOTYPE1
57 #define MMDTAG_FX_ECHOLEN2
58 #define MMDTAG_FX_ECHODEPTH3
59 #define MMDTAG_FX_STEREOSEP4
60 #define MMDTAG_FX_GROUPNAME (MMDTAG_PTR|5)// the Global Effects group shouldn't have name saved!
61 #define MMDTAG_FX_GRPNAMELEN 6// namelen includes zero term.
62
63#pragma pack(1)
64
65typedef struct tagMEDMODULEHEADER
66{
67 DWORD id; // MMD1-MMD3
68 DWORD modlen;// Size of file
69 DWORD song; // Position in file for this song
70 WORD psecnum;
71 WORD pseq;
72 DWORD blockarr;// Position in file for blocks
73 DWORD mmdflags;
74 DWORD smplarr;// Position in file for samples
75 DWORD reserved;
76 DWORD expdata;// Absolute offset in file for ExpData (0 if not present)
77 DWORD reserved2;
78 WORD pstate;
79 WORD pblock;
80 WORD pline;
81 WORD pseqnum;
82 WORD actplayline;
83 BYTE counter;
84 BYTE extra_songs;// # of songs - 1
85} Q_PACKED MEDMODULEHEADER;
86
87
88typedef struct tagMMD0SAMPLE
89{
90 WORD rep, replen;
91 BYTE midich;
92 BYTE midipreset;
93 BYTE svol;
94 signed char strans;
95} Q_PACKED MMD0SAMPLE;
96
97
98// Sample header is immediately followed by sample data...
99typedef struct tagMMDSAMPLEHEADER
100{
101 DWORD length; // length of *one* *unpacked* channel in *bytes*
102 WORD type;
103 // if non-negative
104 // bits 0-3 reserved for multi-octave instruments, not supported on the PC
105 // 0x10: 16 bit (otherwise 8 bit)
106 // 0x20: Stereo (otherwise mono)
107 // 0x40: Uses DeltaCode
108 // 0x80: Packed data
109 // -1: Synth
110 // -2: Hybrid
111 // if type indicates packed data, these fields follow, otherwise we go right to the data
112 WORD packtype;// Only 1 = ADPCM is supported
113 WORD subtype;// Packing subtype
114 // ADPCM subtype
115 // 1: g723_40
116 // 2: g721
117 // 3: g723_24
118 BYTE commonflags;// flags common to all packtypes (none defined so far)
119 BYTE packerflags;// flags for the specific packtype
120 ULONG leftchlen;// packed length of left channel in bytes
121 ULONG rightchlen;// packed length of right channel in bytes (ONLY PRESENT IN STEREO SAMPLES)
122 BYTE SampleData[1];// Sample Data
123} Q_PACKED MMDSAMPLEHEADER;
124
125
126// MMD0/MMD1 song header
127typedef struct tagMMD0SONGHEADER
128{
129 MMD0SAMPLE sample[63];
130 WORD numblocks; // # of blocks
131 WORD songlen; // # of entries used in playseq
132 BYTE playseq[256];// Play sequence
133 WORD deftempo; // BPM tempo
134 signed char playtransp;// Play transpose
135 BYTE flags; // 0x10: Hex Volumes | 0x20: ST/NT/PT Slides | 0x40: 8 Channels song
136 BYTE flags2; // [b4-b0]+1: Tempo LPB, 0x20: tempo mode, 0x80: mix_conv=on
137 BYTE tempo2; // tempo TPL
138 BYTE trkvol[16];// track volumes
139 BYTE mastervol; // master volume
140 BYTE numsamples;// # of samples (max=63)
141} Q_PACKED MMD0SONGHEADER;
142
143
144// MMD2/MMD3 song header
145typedef struct tagMMD2SONGHEADER
146{
147 MMD0SAMPLE sample[63];
148 WORD numblocks; // # of blocks
149 WORD numsections;// # of sections
150 DWORD playseqtable;// filepos of play sequence
151 DWORD sectiontable;// filepos of sections table (WORD array)
152 DWORD trackvols;// filepos of tracks volume (BYTE array)
153 WORD numtracks; // # of tracks (max 64)
154 WORD numpseqs; // # of play sequences
155 DWORD trackpans;// filepos of tracks pan values (BYTE array)
156 LONG flags3; // 0x1:stereo_mix, 0x2:free_panning, 0x4:GM/XG compatibility
157 WORD voladj; // vol_adjust (set to 100 if 0)
158 WORD channels; // # of channels (4 if =0)
159 BYTE mix_echotype;// 1:normal,2:xecho
160 BYTE mix_echodepth;// 1..6
161 WORD mix_echolen;// > 0
162 signed char mix_stereosep;// -4..4
163 BYTE pad0[223];
164 WORD deftempo; // BPM tempo
165 signed char playtransp;// play transpose
166 BYTE flags; // 0x1:filteron, 0x2:jumpingon, 0x4:jump8th, 0x8:instr_attached, 0x10:hex_vol, 0x20:PT_slides, 0x40:8ch_conv,0x80:hq slows playing speed
167 BYTE flags2; // 0x80:mix_conv=on, [b4-b0]+1:tempo LPB, 0x20:tempo_mode
168 BYTE tempo2; // tempo TPL
169 BYTE pad1[16];
170 BYTE mastervol; // master volume
171 BYTE numsamples;// # of samples (max 63)
172} Q_PACKED MMD2SONGHEADER;
173
174// For MMD0 the note information is held in 3 bytes, byte0, byte1, byte2. For reference we
175// number the bits in each byte 0..7, where 0 is the low bit.
176// The note is held as bits 5..0 of byte0
177// The instrument is encoded in 6 bits, bits 7 and 6 of byte0 and bits 7,6,5,4 of byte1
178// The command number is bits 3,2,1,0 of byte1, command data is in byte2:
179// For command 0, byte2 represents the second data byte, otherwise byte2
180// represents the first data byte.
181typedef struct tagMMD0BLOCK
182{
183 BYTE numtracks;
184 BYTE lines; // File value is 1 less than actual, so 0 -> 1 line
185 } Q_PACKED MMD0BLOCK; // BYTE data[lines+1][tracks][3];
186
187
188// For MMD1,MMD2,MMD3 the note information is carried in 4 bytes, byte0, byte1,
189// byte2 and byte3
190// The note is held as byte0 (values above 0x84 are ignored)
191// The instrument is held as byte1
192// The command number is held as byte2, command data is in byte3
193// For commands 0 and 0x19 byte3 represents the second data byte,
194// otherwise byte2 represents the first data byte.
195typedef struct tagMMD1BLOCK
196{
197 WORD numtracks;// Number of tracks, may be > 64, but then that data is skipped.
198 WORD lines; // Stored value is 1 less than actual, so 0 -> 1 line
199 DWORD info; // Offset of BlockInfo (if 0, no block_info is present)
200} Q_PACKED MMD1BLOCK;
201
202
203typedef struct tagMMD1BLOCKINFO
204{
205 DWORD hlmask; // Unimplemented - ignore
206 DWORD blockname;// file offset of block name
207 DWORD blocknamelen;// length of block name (including term. 0)
208 DWORD pagetable;// file offset of command page table
209 DWORD cmdexttable;// file offset of command extension table
210 DWORD reserved[4];// future expansion
211} Q_PACKED MMD1BLOCKINFO;
212
213
214// A set of play sequences is stored as an array of ULONG files offsets
215// Each offset points to the play sequence itself.
216typedef struct tagMMD2PLAYSEQ
217{
218 CHAR name[32];
219 DWORD command_offs;// filepos of command table
220 DWORD reserved;
221 WORD length;
222 WORD seq[512];// skip if > 0x8000
223} Q_PACKED MMD2PLAYSEQ;
224
225
226// A command table contains commands that effect a particular play sequence
227// entry. The only commands read in are STOP or POSJUMP, all others are ignored
228// POSJUMP is presumed to have extra bytes containing a WORD for the position
229typedef struct tagMMDCOMMAND
230{
231 WORD offset; // Offset within current sequence entry
232 BYTE cmdnumber; // STOP (537) or POSJUMP (538) (others skipped)
233 BYTE extra_count;
234 BYTE extra_bytes[4];// [extra_count];
235} Q_PACKED MMDCOMMAND; // Last entry has offset == 0xFFFF, cmd_number == 0 and 0 extrabytes
236
237
238typedef struct tagMMD0EXP
239{
240 DWORD nextmod; // File offset of next Hdr
241 DWORD exp_smp; // Pointer to extra instrument data
242 WORD s_ext_entries; // Number of extra instrument entries
243 WORD s_ext_entrsz; // Size of extra instrument data
244 DWORD annotxt;
245 DWORD annolen;
246 DWORD iinfo; // Instrument names
247 WORD i_ext_entries;
248 WORD i_ext_entrsz;
249 DWORD jumpmask;
250 DWORD rgbtable;
251 BYTE channelsplit[4];// Only used if 8ch_conv (extra channel for every nonzero entry)
252 DWORD n_info;
253 DWORD songname; // Song name
254 DWORD songnamelen;
255 DWORD dumps;
256 DWORD mmdinfo;
257 DWORD mmdrexx;
258 DWORD mmdcmd3x;
259 DWORD trackinfo_ofs;// ptr to song->numtracks ptrs to tag lists
260 DWORD effectinfo_ofs;// ptr to group ptrs
261 DWORD tag_end;
262} Q_PACKED MMD0EXP;
263
264#pragma pack()
265
266
267
268static void MedConvert(MODCOMMAND *p, const MMD0SONGHEADER *pmsh)
269//---------------------------------------------------------------
270{
271 const BYTE bpmvals[9] = { 179,164,152,141,131,123,116,110,104};
272
273 UINT command = p->command;
274 UINT param = p->param;
275 switch(command)
276 {
277 case 0x00:if (param) command = CMD_ARPEGGIO; else command = 0; break;
278 case 0x01:command = CMD_PORTAMENTOUP; break;
279 case 0x02:command = CMD_PORTAMENTODOWN; break;
280 case 0x03:command = CMD_TONEPORTAMENTO; break;
281 case 0x04:command = CMD_VIBRATO; break;
282 case 0x05:command = CMD_TONEPORTAVOL; break;
283 case 0x06:command = CMD_VIBRATOVOL; break;
284 case 0x07:command = CMD_TREMOLO; break;
285 case 0x0A:if (param & 0xF0) param &= 0xF0; command = CMD_VOLUMESLIDE; if (!param) command = 0; break;
286 case 0x0B:command = CMD_POSITIONJUMP; break;
287 case 0x0C:command = CMD_VOLUME;
288 if (pmsh->flags & MMD_FLAG_VOLHEX)
289 {
290 if (param < 0x80)
291 {
292 param = (param+1) / 2;
293 } else command = 0;
294 } else
295 {
296 if (param <= 0x99)
297 {
298 param = (param >> 4)*10+((param & 0x0F) % 10);
299 if (param > 64) param = 64;
300 } else command = 0;
301 }
302 break;
303 case 0x09:command = (param < 0x20) ? CMD_SPEED : CMD_TEMPO; break;
304 case 0x0D:if (param & 0xF0) param &= 0xF0; command = CMD_VOLUMESLIDE; if (!param) command = 0; break;
305 case 0x0F:// Set Tempo / Special
306 // F.00 = Pattern Break
307 if (!param) command = CMD_PATTERNBREAK;else
308 // F.01 - F.F0: Set tempo/speed
309 if (param <= 0xF0)
310 {
311 if (pmsh->flags & MMD_FLAG_8CHANNEL)
312 {
313 param = (param > 10) ? 99 : bpmvals[param-1];
314 } else
315 // F.01 - F.0A: Set Speed
316 if (param <= 0x0A)
317 {
318 command = CMD_SPEED;
319 } else
320 // Old tempo
321 if (!(pmsh->flags2 & MMD_FLAG2_BPM))
322 {
323 param = _muldiv(param, 5*715909, 2*474326);
324 }
325 // F.0B - F.F0: Set Tempo (assumes LPB=4)
326 if (param > 0x0A)
327 {
328 command = CMD_TEMPO;
329 if (param < 0x21) param = 0x21;
330 if (param > 240) param = 240;
331 }
332 } else
333 switch(param)
334 {
335 // F.F1: Retrig 2x
336 case 0xF1:
337 command = CMD_MODCMDEX;
338 param = 0x93;
339 break;
340 // F.F2: Note Delay 2x
341 case 0xF2:
342 command = CMD_MODCMDEX;
343 param = 0xD3;
344 break;
345 // F.F3: Retrig 3x
346 case 0xF3:
347 command = CMD_MODCMDEX;
348 param = 0x92;
349 break;
350 // F.F4: Note Delay 1/3
351 case 0xF4:
352 command = CMD_MODCMDEX;
353 param = 0xD2;
354 break;
355 // F.F5: Note Delay 2/3
356 case 0xF5:
357 command = CMD_MODCMDEX;
358 param = 0xD4;
359 break;
360 // F.F8: Filter Off
361 case 0xF8:
362 command = CMD_MODCMDEX;
363 param = 0x00;
364 break;
365 // F.F9: Filter On
366 case 0xF9:
367 command = CMD_MODCMDEX;
368 param = 0x01;
369 break;
370 // F.FD: Very fast tone-portamento
371 case 0xFD:
372 command = CMD_TONEPORTAMENTO;
373 param = 0xFF;
374 break;
375 // F.FE: End Song
376 case 0xFE:
377 command = CMD_SPEED;
378 param = 0;
379 break;
380 // F.FF: Note Cut
381 case 0xFF:
382 command = CMD_MODCMDEX;
383 param = 0xC0;
384 break;
385 default:
386#ifdef MED_LOG
387 Log("Unknown Fxx command: cmd=0x%02X param=0x%02X\n", command, param);
388#endif
389 param = command = 0;
390 }
391 break;
392 // 11.0x: Fine Slide Up
393 case 0x11:
394 command = CMD_MODCMDEX;
395 if (param > 0x0F) param = 0x0F;
396 param |= 0x10;
397 break;
398 // 12.0x: Fine Slide Down
399 case 0x12:
400 command = CMD_MODCMDEX;
401 if (param > 0x0F) param = 0x0F;
402 param |= 0x20;
403 break;
404 // 14.xx: Vibrato
405 case 0x14:
406 command = CMD_VIBRATO;
407 break;
408 // 15.xx: FineTune
409 case 0x15:
410 command = CMD_MODCMDEX;
411 param &= 0x0F;
412 param |= 0x50;
413 break;
414 // 16.xx: Pattern Loop
415 case 0x16:
416 command = CMD_MODCMDEX;
417 if (param > 0x0F) param = 0x0F;
418 param |= 0x60;
419 break;
420 // 18.xx: Note Cut
421 case 0x18:
422 command = CMD_MODCMDEX;
423 if (param > 0x0F) param = 0x0F;
424 param |= 0xC0;
425 break;
426 // 19.xx: Sample Offset
427 case 0x19:
428 command = CMD_OFFSET;
429 break;
430 // 1A.0x: Fine Volume Up
431 case 0x1A:
432 command = CMD_MODCMDEX;
433 if (param > 0x0F) param = 0x0F;
434 param |= 0xA0;
435 break;
436 // 1B.0x: Fine Volume Down
437 case 0x1B:
438 command = CMD_MODCMDEX;
439 if (param > 0x0F) param = 0x0F;
440 param |= 0xB0;
441 break;
442 // 1D.xx: Pattern Break
443 case 0x1D:
444 command = CMD_PATTERNBREAK;
445 break;
446 // 1E.0x: Pattern Delay
447 case 0x1E:
448 command = CMD_MODCMDEX;
449 if (param > 0x0F) param = 0x0F;
450 param |= 0xE0;
451 break;
452 // 1F.xy: Retrig
453 case 0x1F:
454 command = CMD_RETRIG;
455 param &= 0x0F;
456 break;
457 // 2E.xx: set panning
458 case 0x2E:
459 command = CMD_MODCMDEX;
460 param = ((param + 0x10) & 0xFF) >> 1;
461 if (param > 0x0F) param = 0x0F;
462 param |= 0x80;
463 break;
464 default:
465#ifdef MED_LOG
466 // 0x2E ?
467 Log("Unknown command: cmd=0x%02X param=0x%02X\n", command, param);
468#endif
469 command = param = 0;
470 }
471 p->command = command;
472 p->param = param;
473}
474
475
476BOOL CSoundFile::ReadMed(const BYTE *lpStream, DWORD dwMemLength)
477//---------------------------------------------------------------
478{
479 const MEDMODULEHEADER *pmmh;
480 const MMD0SONGHEADER *pmsh;
481 const MMD2SONGHEADER *pmsh2;
482 const MMD0EXP *pmex;
483 DWORD dwBlockArr, dwSmplArr, dwExpData, wNumBlocks;
484 LPDWORD pdwTable;
485 CHAR version;
486 UINT deftempo;
487 int playtransp = 0;
488
489 if ((!lpStream) || (dwMemLength < 0x200)) return FALSE;
490 pmmh = (MEDMODULEHEADER *)lpStream;
491 if (((pmmh->id & 0x00FFFFFF) != 0x444D4D) || (!pmmh->song)) return FALSE;
492 // Check for 'MMDx'
493 DWORD dwSong = bswapBE32(pmmh->song);
494 if ((dwSong >= dwMemLength) || (dwSong + sizeof(MMD0SONGHEADER) >= dwMemLength)) return FALSE;
495 version = (signed char)((pmmh->id >> 24) & 0xFF);
496 if ((version < '0') || (version > '3')) return FALSE;
497#ifdef MED_LOG
498 Log("\nLoading MMD%c module (flags=0x%02X)...\n", version, bswapBE32(pmmh->mmdflags));
499 Log(" modlen = %d\n", bswapBE32(pmmh->modlen));
500 Log(" song = 0x%08X\n", bswapBE32(pmmh->song));
501 Log(" psecnum = %d\n", bswapBE16(pmmh->psecnum));
502 Log(" pseq = %d\n", bswapBE16(pmmh->pseq));
503 Log(" blockarr = 0x%08X\n", bswapBE32(pmmh->blockarr));
504 Log(" mmdflags = 0x%08X\n", bswapBE32(pmmh->mmdflags));
505 Log(" smplarr = 0x%08X\n", bswapBE32(pmmh->smplarr));
506 Log(" reserved = 0x%08X\n", bswapBE32(pmmh->reserved));
507 Log(" expdata = 0x%08X\n", bswapBE32(pmmh->expdata));
508 Log(" reserved2= 0x%08X\n", bswapBE32(pmmh->reserved2));
509 Log(" pstate = %d\n", bswapBE16(pmmh->pstate));
510 Log(" pblock = %d\n", bswapBE16(pmmh->pblock));
511 Log(" pline = %d\n", bswapBE16(pmmh->pline));
512 Log(" pseqnum = %d\n", bswapBE16(pmmh->pseqnum));
513 Log(" actplayline=%d\n", bswapBE16(pmmh->actplayline));
514 Log(" counter = %d\n", pmmh->counter);
515 Log(" extra_songs = %d\n", pmmh->extra_songs);
516 Log("\n");
517#endif
518 m_nType = MOD_TYPE_MED;
519 m_nSongPreAmp = 0x20;
520 dwBlockArr = bswapBE32(pmmh->blockarr);
521 dwSmplArr = bswapBE32(pmmh->smplarr);
522 dwExpData = bswapBE32(pmmh->expdata);
523 if ((dwExpData) && (dwExpData+sizeof(MMD0EXP) < dwMemLength))
524 pmex = (MMD0EXP *)(lpStream+dwExpData);
525 else
526 pmex = NULL;
527 pmsh = (MMD0SONGHEADER *)(lpStream + dwSong);
528 pmsh2 = (MMD2SONGHEADER *)pmsh;
529#ifdef MED_LOG
530 if (version < '2')
531 {
532 Log("MMD0 Header:\n");
533 Log(" numblocks = %d\n", bswapBE16(pmsh->numblocks));
534 Log(" songlen = %d\n", bswapBE16(pmsh->songlen));
535 Log(" playseq = ");
536 for (UINT idbg1=0; idbg1<16; idbg1++) Log("%2d, ", pmsh->playseq[idbg1]);
537 Log("...\n");
538 Log(" deftempo = 0x%04X\n", bswapBE16(pmsh->deftempo));
539 Log(" playtransp = %d\n", (signed char)pmsh->playtransp);
540 Log(" flags(1,2) = 0x%02X, 0x%02X\n", pmsh->flags, pmsh->flags2);
541 Log(" tempo2 = %d\n", pmsh->tempo2);
542 Log(" trkvol = ");
543 for (UINT idbg2=0; idbg2<16; idbg2++) Log("0x%02X, ", pmsh->trkvol[idbg2]);
544 Log("...\n");
545 Log(" mastervol = 0x%02X\n", pmsh->mastervol);
546 Log(" numsamples = %d\n", pmsh->numsamples);
547 } else
548 {
549 Log("MMD2 Header:\n");
550 Log(" numblocks = %d\n", bswapBE16(pmsh2->numblocks));
551 Log(" numsections= %d\n", bswapBE16(pmsh2->numsections));
552 Log(" playseqptr = 0x%04X\n", bswapBE32(pmsh2->playseqtable));
553 Log(" sectionptr = 0x%04X\n", bswapBE32(pmsh2->sectiontable));
554 Log(" trackvols = 0x%04X\n", bswapBE32(pmsh2->trackvols));
555 Log(" numtracks = %d\n", bswapBE16(pmsh2->numtracks));
556 Log(" numpseqs = %d\n", bswapBE16(pmsh2->numpseqs));
557 Log(" trackpans = 0x%04X\n", bswapBE32(pmsh2->trackpans));
558 Log(" flags3 = 0x%08X\n", bswapBE32(pmsh2->flags3));
559 Log(" voladj = %d\n", bswapBE16(pmsh2->voladj));
560 Log(" channels = %d\n", bswapBE16(pmsh2->channels));
561 Log(" echotype = %d\n", pmsh2->mix_echotype);
562 Log(" echodepth = %d\n", pmsh2->mix_echodepth);
563 Log(" echolen = %d\n", bswapBE16(pmsh2->mix_echolen));
564 Log(" stereosep = %d\n", (signed char)pmsh2->mix_stereosep);
565 Log(" deftempo = 0x%04X\n", bswapBE16(pmsh2->deftempo));
566 Log(" playtransp = %d\n", (signed char)pmsh2->playtransp);
567 Log(" flags(1,2) = 0x%02X, 0x%02X\n", pmsh2->flags, pmsh2->flags2);
568 Log(" tempo2 = %d\n", pmsh2->tempo2);
569 Log(" mastervol = 0x%02X\n", pmsh2->mastervol);
570 Log(" numsamples = %d\n", pmsh->numsamples);
571 }
572 Log("\n");
573#endif
574 wNumBlocks = bswapBE16(pmsh->numblocks);
575 m_nChannels = 4;
576 m_nSamples = pmsh->numsamples;
577 if (m_nSamples > 63) m_nSamples = 63;
578 // Tempo
579 m_nDefaultTempo = 125;
580 deftempo = bswapBE16(pmsh->deftempo);
581 if (!deftempo) deftempo = 125;
582 if (pmsh->flags2 & MMD_FLAG2_BPM)
583 {
584 UINT tempo_tpl = (pmsh->flags2 & MMD_FLAG2_BMASK) + 1;
585 if (!tempo_tpl) tempo_tpl = 4;
586 deftempo *= tempo_tpl;
587 deftempo /= 4;
588 #ifdef MED_LOG
589 Log("newtempo: %3d bpm (bpm=%3d lpb=%2d)\n", deftempo, bswapBE16(pmsh->deftempo), (pmsh->flags2 & MMD_FLAG2_BMASK)+1);
590 #endif
591 } else
592 {
593 deftempo = _muldiv(deftempo, 5*715909, 2*474326);
594 #ifdef MED_LOG
595 Log("oldtempo: %3d bpm (bpm=%3d)\n", deftempo, bswapBE16(pmsh->deftempo));
596 #endif
597 }
598 // Speed
599 m_nDefaultSpeed = pmsh->tempo2;
600 if (!m_nDefaultSpeed) m_nDefaultSpeed = 6;
601 if (deftempo < 0x21) deftempo = 0x21;
602 if (deftempo > 255)
603 {
604 while ((m_nDefaultSpeed > 3) && (deftempo > 260))
605 {
606 deftempo = (deftempo * (m_nDefaultSpeed - 1)) / m_nDefaultSpeed;
607 m_nDefaultSpeed--;
608 }
609 if (deftempo > 255) deftempo = 255;
610 }
611 m_nDefaultTempo = deftempo;
612 // Reading Samples
613 for (UINT iSHdr=0; iSHdr<m_nSamples; iSHdr++)
614 {
615 MODINSTRUMENT *pins = &Ins[iSHdr+1];
616 pins->nLoopStart = bswapBE16(pmsh->sample[iSHdr].rep) << 1;
617 pins->nLoopEnd = pins->nLoopStart + (bswapBE16(pmsh->sample[iSHdr].replen) << 1);
618 pins->nVolume = (pmsh->sample[iSHdr].svol << 2);
619 pins->nGlobalVol = 64;
620 if (pins->nVolume > 256) pins->nVolume = 256;
621 pins->RelativeTone = -12 * pmsh->sample[iSHdr].strans;
622 pins->nPan = 128;
623 if (pins->nLoopEnd) pins->uFlags |= CHN_LOOP;
624 }
625 // Common Flags
626 if (!(pmsh->flags & 0x20)) m_dwSongFlags |= SONG_FASTVOLSLIDES;
627 // Reading play sequence
628 if (version < '2')
629 {
630 UINT nbo = pmsh->songlen >> 8;
631 if (nbo >= MAX_ORDERS) nbo = MAX_ORDERS-1;
632 if (!nbo) nbo = 1;
633 memcpy(Order, pmsh->playseq, nbo);
634 playtransp = pmsh->playtransp;
635 } else
636 {
637 UINT nOrders, nSections;
638 UINT nTrks = bswapBE16(pmsh2->numtracks);
639 if ((nTrks >= 4) && (nTrks <= 32)) m_nChannels = nTrks;
640 DWORD playseqtable = bswapBE32(pmsh2->playseqtable);
641 UINT numplayseqs = bswapBE16(pmsh2->numpseqs);
642 if (!numplayseqs) numplayseqs = 1;
643 nOrders = 0;
644 nSections = bswapBE16(pmsh2->numsections);
645 DWORD sectiontable = bswapBE32(pmsh2->sectiontable);
646 if ((!nSections) || (!sectiontable) || (sectiontable >= dwMemLength-2)) nSections = 1;
647 nOrders = 0;
648 for (UINT iSection=0; iSection<nSections; iSection++)
649 {
650 UINT nplayseq = 0;
651 if ((sectiontable) && (sectiontable < dwMemLength-2))
652 {
653 nplayseq = lpStream[sectiontable+1];
654 sectiontable += 2; // WORDs
655 } else
656 {
657 nSections = 0;
658 }
659 UINT pseq = 0;
660
661 if ((playseqtable) && (playseqtable + nplayseq*4 < dwMemLength))
662 {
663 pseq = bswapBE32(((LPDWORD)(lpStream+playseqtable))[nplayseq]);
664 }
665 if ((pseq) && (pseq < dwMemLength - sizeof(MMD2PLAYSEQ)))
666 {
667 MMD2PLAYSEQ *pmps = (MMD2PLAYSEQ *)(lpStream + pseq);
668 if (!m_szNames[0][0]) memcpy(m_szNames[0], pmps->name, 31);
669 UINT n = bswapBE16(pmps->length);
670 if (pseq+n <= dwMemLength)
671 {
672 for (UINT i=0; i<n; i++)
673 {
674 UINT seqval = pmps->seq[i] >> 8;
675 if ((seqval < wNumBlocks) && (nOrders < MAX_ORDERS-1))
676 {
677 Order[nOrders++] = seqval;
678 }
679 }
680 }
681 }
682 }
683 playtransp = pmsh2->playtransp;
684 while (nOrders < MAX_ORDERS) Order[nOrders++] = 0xFF;
685 }
686 // Reading Expansion structure
687 if (pmex)
688 {
689 // Channel Split
690 if ((m_nChannels == 4) && (pmsh->flags & 0x40))
691 {
692 for (UINT i8ch=0; i8ch<4; i8ch++)
693 {
694 if (pmex->channelsplit[i8ch]) m_nChannels++;
695 }
696 }
697 // Song Comments
698 UINT annotxt = bswapBE32(pmex->annotxt);
699 UINT annolen = bswapBE32(pmex->annolen);
700 if ((annotxt) && (annolen) && (annotxt+annolen <= dwMemLength))
701 {
702 m_lpszSongComments = new char[annolen+1];
703 memcpy(m_lpszSongComments, lpStream+annotxt, annolen);
704 m_lpszSongComments[annolen] = 0;
705 }
706 // Song Name
707 UINT songname = bswapBE32(pmex->songname);
708 UINT songnamelen = bswapBE32(pmex->songnamelen);
709 if ((songname) && (songnamelen) && (songname+songnamelen <= dwMemLength))
710 {
711 if (songnamelen > 31) songnamelen = 31;
712 memcpy(m_szNames[0], lpStream+songname, songnamelen);
713 }
714 // Sample Names
715 DWORD smpinfoex = bswapBE32(pmex->iinfo);
716 if (smpinfoex)
717 {
718 DWORD iinfoptr = bswapBE32(pmex->iinfo);
719 UINT ientries = bswapBE16(pmex->i_ext_entries);
720 UINT ientrysz = bswapBE16(pmex->i_ext_entrsz);
721
722 if ((iinfoptr) && (ientrysz < 256) && (iinfoptr + ientries*ientrysz < dwMemLength))
723 {
724 LPCSTR psznames = (LPCSTR)(lpStream + iinfoptr);
725 UINT maxnamelen = ientrysz;
726 if (maxnamelen > 32) maxnamelen = 32;
727 for (UINT i=0; i<ientries; i++) if (i < m_nSamples)
728 {
729 lstrcpyn(m_szNames[i+1], psznames + i*ientrysz, maxnamelen);
730 }
731 }
732 }
733 // Track Names
734 DWORD trackinfo_ofs = bswapBE32(pmex->trackinfo_ofs);
735 if ((trackinfo_ofs) && (trackinfo_ofs + m_nChannels * 4 < dwMemLength))
736 {
737 DWORD *ptrktags = (DWORD *)(lpStream + trackinfo_ofs);
738 for (UINT i=0; i<m_nChannels; i++)
739 {
740 DWORD trknameofs = 0, trknamelen = 0;
741 DWORD trktagofs = bswapBE32(ptrktags[i]);
742 if (trktagofs)
743 {
744 while (trktagofs+8 < dwMemLength)
745 {
746 DWORD ntag = bswapBE32(*(DWORD *)(lpStream + trktagofs));
747 if (ntag == MMDTAG_END) break;
748 DWORD tagdata = bswapBE32(*(DWORD *)(lpStream + trktagofs + 4));
749 switch(ntag)
750 {
751 case MMDTAG_TRK_NAMELEN:trknamelen = tagdata; break;
752 case MMDTAG_TRK_NAME: trknameofs = tagdata; break;
753 }
754 trktagofs += 8;
755 }
756 if (trknamelen > MAX_CHANNELNAME) trknamelen = MAX_CHANNELNAME;
757 if ((trknameofs) && (trknameofs + trknamelen < dwMemLength))
758 {
759 lstrcpyn(ChnSettings[i].szName, (LPCSTR)(lpStream+trknameofs), MAX_CHANNELNAME);
760 }
761 }
762 }
763 }
764 }
765 // Reading samples
766 if (dwSmplArr > dwMemLength - 4*m_nSamples) return TRUE;
767 pdwTable = (LPDWORD)(lpStream + dwSmplArr);
768 for (UINT iSmp=0; iSmp<m_nSamples; iSmp++) if (pdwTable[iSmp])
769 {
770 UINT dwPos = bswapBE32(pdwTable[iSmp]);
771 if ((dwPos >= dwMemLength) || (dwPos + sizeof(MMDSAMPLEHEADER) >= dwMemLength)) continue;
772 MMDSAMPLEHEADER *psdh = (MMDSAMPLEHEADER *)(lpStream + dwPos);
773 UINT len = bswapBE32(psdh->length);
774 #ifdef MED_LOG
775 Log("SampleData %d: stype=0x%02X len=%d\n", iSmp, bswapBE16(psdh->type), len);
776 #endif
777 if ((len > MAX_SAMPLE_LENGTH) || (dwPos + len + 6 > dwMemLength)) len = 0;
778 UINT flags = RS_PCM8S, stype = bswapBE16(psdh->type);
779 LPSTR psdata = (LPSTR)(lpStream + dwPos + 6);
780 if (stype & 0x80)
781 {
782 psdata += (stype & 0x20) ? 14 : 6;
783 } else
784 {
785 if (stype & 0x10)
786 {
787 Ins[iSmp+1].uFlags |= CHN_16BIT;
788 len /= 2;
789 flags = (stype & 0x20) ? RS_STPCM16M : RS_PCM16M;
790 } else
791 {
792 flags = (stype & 0x20) ? RS_STPCM8S : RS_PCM8S;
793 }
794 if (stype & 0x20) len /= 2;
795 }
796 Ins[iSmp+1].nLength = len;
797 ReadSample(&Ins[iSmp+1], flags, psdata, dwMemLength - dwPos - 6);
798 }
799 // Reading patterns (blocks)
800 if (wNumBlocks > MAX_PATTERNS) wNumBlocks = MAX_PATTERNS;
801 if ((!dwBlockArr) || (dwBlockArr > dwMemLength - 4*wNumBlocks)) return TRUE;
802 pdwTable = (LPDWORD)(lpStream + dwBlockArr);
803 playtransp += (version == '3') ? 24 : 48;
804 for (UINT iBlk=0; iBlk<wNumBlocks; iBlk++)
805 {
806 UINT dwPos = bswapBE32(pdwTable[iBlk]);
807 if ((!dwPos) || (dwPos >= dwMemLength) || (dwPos >= dwMemLength - 8)) continue;
808 UINT lines = 64, tracks = 4;
809 if (version == '0')
810 {
811 const MMD0BLOCK *pmb = (const MMD0BLOCK *)(lpStream + dwPos);
812 lines = pmb->lines + 1;
813 tracks = pmb->numtracks;
814 if (!tracks) tracks = m_nChannels;
815 if ((Patterns[iBlk] = AllocatePattern(lines, m_nChannels)) == NULL) continue;
816 PatternSize[iBlk] = lines;
817 MODCOMMAND *p = Patterns[iBlk];
818 LPBYTE s = (LPBYTE)(lpStream + dwPos + 2);
819 UINT maxlen = tracks*lines*3;
820 if (maxlen + dwPos > dwMemLength - 2) break;
821 for (UINT y=0; y<lines; y++)
822 {
823 for (UINT x=0; x<tracks; x++, s+=3) if (x < m_nChannels)
824 {
825 BYTE note = s[0] & 0x3F;
826 BYTE instr = s[1] >> 4;
827 if (s[0] & 0x80) instr |= 0x10;
828 if (s[0] & 0x40) instr |= 0x20;
829 if ((note) && (note <= 132)) p->note = note + playtransp;
830 p->instr = instr;
831 p->command = s[1] & 0x0F;
832 p->param = s[2];
833 // if (!iBlk) Log("%02X.%02X.%02X | ", s[0], s[1], s[2]);
834 MedConvert(p, pmsh);
835 p++;
836 }
837 //if (!iBlk) Log("\n");
838 }
839 } else
840 {
841 MMD1BLOCK *pmb = (MMD1BLOCK *)(lpStream + dwPos);
842 #ifdef MED_LOG
843 Log("MMD1BLOCK: lines=%2d, tracks=%2d, offset=0x%04X\n",
844 bswapBE16(pmb->lines), bswapBE16(pmb->numtracks), bswapBE32(pmb->info));
845 #endif
846 MMD1BLOCKINFO *pbi = NULL;
847 BYTE *pcmdext = NULL;
848 lines = (pmb->lines >> 8) + 1;
849 tracks = pmb->numtracks >> 8;
850 if (!tracks) tracks = m_nChannels;
851 if ((Patterns[iBlk] = AllocatePattern(lines, m_nChannels)) == NULL) continue;
852 PatternSize[iBlk] = (WORD)lines;
853 DWORD dwBlockInfo = bswapBE32(pmb->info);
854 if ((dwBlockInfo) && (dwBlockInfo < dwMemLength - sizeof(MMD1BLOCKINFO)))
855 {
856 pbi = (MMD1BLOCKINFO *)(lpStream + dwBlockInfo);
857 #ifdef MED_LOG
858 Log(" BLOCKINFO: blockname=0x%04X namelen=%d pagetable=0x%04X &cmdexttable=0x%04X\n",
859 bswapBE32(pbi->blockname), bswapBE32(pbi->blocknamelen), bswapBE32(pbi->pagetable), bswapBE32(pbi->cmdexttable));
860 #endif
861 if ((pbi->blockname) && (pbi->blocknamelen))
862 {
863 DWORD nameofs = bswapBE32(pbi->blockname);
864 UINT namelen = bswapBE32(pbi->blocknamelen);
865 if ((nameofs < dwMemLength) && (nameofs+namelen < dwMemLength))
866 {
867 SetPatternName(iBlk, (LPCSTR)(lpStream+nameofs));
868 }
869 }
870 if (pbi->cmdexttable)
871 {
872 DWORD cmdexttable = bswapBE32(pbi->cmdexttable);
873 if (cmdexttable < dwMemLength - 4)
874 {
875 cmdexttable = bswapBE32(*(DWORD *)(lpStream + cmdexttable));
876 if ((cmdexttable) && (cmdexttable <= dwMemLength - lines*tracks))
877 {
878 pcmdext = (BYTE *)(lpStream + cmdexttable);
879 }
880 }
881 }
882 }
883 MODCOMMAND *p = Patterns[iBlk];
884 LPBYTE s = (LPBYTE)(lpStream + dwPos + 8);
885 UINT maxlen = tracks*lines*4;
886 if (maxlen + dwPos > dwMemLength - 8) break;
887 for (UINT y=0; y<lines; y++)
888 {
889 for (UINT x=0; x<tracks; x++, s+=4) if (x < m_nChannels)
890 {
891 BYTE note = s[0];
892 if ((note) && (note <= 132))
893 {
894 int rnote = note + playtransp;
895 if (rnote < 1) rnote = 1;
896 if (rnote > 120) rnote = 120;
897 p->note = (BYTE)rnote;
898 }
899 p->instr = s[1];
900 p->command = s[2];
901 p->param = s[3];
902 if (pcmdext) p->vol = pcmdext[x];
903 MedConvert(p, pmsh);
904 p++;
905 }
906 if (pcmdext) pcmdext += tracks;
907 }
908 }
909 }
910 // Setup channel pan positions
911 for (UINT iCh=0; iCh<m_nChannels; iCh++)
912 {
913 ChnSettings[iCh].nPan = (((iCh&3) == 1) || ((iCh&3) == 2)) ? 0xC0 : 0x40;
914 ChnSettings[iCh].nVolume = 64;
915 }
916 return TRUE;
917}
918
919