1 /* MikMod sound library
2 (c) 1998, 1999, 2000, 2001, 2002 Miodrag Vallat and others - see file
3 AUTHORS for complete list.
5 This library is free software; you can redistribute it and/or modify
6 it under the terms of the GNU Library General Public License as
7 published by the Free Software Foundation; either version 2 of
8 the License, or (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU Library General Public License for more details.
15 You should have received a copy of the GNU Library General Public
16 License along with this library; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
21 /*==============================================================================
23 $Id: load_m15.c,v 1.3 2005/04/07 19:57:38 realtech Exp $
25 15 instrument MOD loader
26 Also supports Ultimate Sound Tracker (old M15 format)
28 ==============================================================================*/
45 #include "mikmod_internals.h"
48 extern int fprintf(FILE *, const char *, ...);
51 /*========== Module Structure */
53 typedef struct MSAMPINFO
{
54 CHAR samplename
[23]; /* 22 in module, 23 in memory */
62 typedef struct MODULEHEADER
{
63 CHAR songname
[21]; /* the songname.., 20 in module, 21 in memory */
64 MSAMPINFO samples
[15]; /* all sampleinfo */
65 UBYTE songlength
; /* number of patterns used */
66 UBYTE magic1
; /* should be 127 */
67 UBYTE positions
[128]; /* which pattern to play at pos */
70 typedef struct MODNOTE
{
74 /*========== Loader variables */
76 static MODULEHEADER
*mh
= NULL
;
77 static MODNOTE
*patbuf
= NULL
;
78 static int ust_loader
= 0; /* if TRUE, load as an ust module. */
80 /* known file formats which can confuse the loader */
82 static char *signatures
[REJECT
]={
83 "CAKEWALK", /* cakewalk midi files */
84 "SZDD" /* Microsoft compressed files */
86 static int siglen
[REJECT
]={8,4};
88 /*========== Loader code */
90 static int LoadModuleHeader(MODULEHEADER
*mh
)
94 _mm_read_string(mh
->songname
,20,modreader
);
95 mh
->songname
[20]=0; /* just in case */
97 /* sanity check : title should contain printable characters and a bunch
100 if((mh
->songname
[t
])&&(mh
->songname
[t
]<32)) return 0;
101 for(t
=0;(mh
->songname
[t
])&&(t
<20);t
++);
102 if(t
<20) for(;t
<20;t
++) if(mh
->songname
[t
]) return 0;
105 MSAMPINFO
*s
=&mh
->samples
[t
];
107 _mm_read_string(s
->samplename
,22,modreader
);
108 s
->samplename
[22]=0; /* just in case */
109 s
->length
=_mm_read_M_UWORD(modreader
);
110 s
->finetune
=_mm_read_UBYTE(modreader
);
111 s
->volume
=_mm_read_UBYTE(modreader
);
112 s
->reppos
=_mm_read_M_UWORD(modreader
);
113 s
->replen
=_mm_read_M_UWORD(modreader
);
115 /* sanity check : sample title should contain printable characters and
116 a bunch of null chars */
118 if((s
->samplename
[u
])&&(s
->samplename
[u
]</*32*/14)) return 0;
119 for(u
=0;(s
->samplename
[u
])&&(u
<20);u
++);
120 if(u
<20) for(;u
<20;u
++) if(s
->samplename
[u
]) return 0;
122 /* sanity check : finetune values */
123 if(s
->finetune
>>4) return 0;
126 mh
->songlength
=_mm_read_UBYTE(modreader
);
127 mh
->magic1
=_mm_read_UBYTE(modreader
); /* should be 127 */
129 /* sanity check : no more than 128 positions, restart position in range */
130 if((!mh
->songlength
)||(mh
->songlength
>128)) return 0;
131 /* values encountered so far are 0x6a and 0x78 */
132 if(((mh
->magic1
&0xf8)!=0x78)&&(mh
->magic1
!=0x6a)&&(mh
->magic1
>mh
->songlength
)) return 0;
134 _mm_read_UBYTES(mh
->positions
,128,modreader
);
136 /* sanity check : pattern range is 0..63 */
138 if(mh
->positions
[t
]>63) return 0;
140 return(!_mm_eof(modreader
));
143 /* Checks the patterns in the modfile for UST / 15-inst indications.
144 For example, if an effect 3xx is found, it is assumed that the song
145 is 15-inst. If a 1xx effect has dat greater than 0x20, it is UST.
147 Returns: 0 indecisive; 1 = UST; 2 = 15-inst */
148 static int CheckPatternType(int numpat
)
153 for(t
=0;t
<numpat
*(64U*4);t
++) {
154 /* Load the pattern into the temp buffer and scan it */
155 (void)_mm_read_UBYTE(modreader
);(void)_mm_read_UBYTE(modreader
);
156 eff
= _mm_read_UBYTE(modreader
);
157 dat
= _mm_read_UBYTE(modreader
);
161 if(dat
>0x1f) return 1;
162 if(dat
<0x3) return 2;
165 if(dat
>0x1f) return 1;
177 static int M15_Test(void)
183 if(!LoadModuleHeader(&mh
)) return 0;
185 /* reject other file types */
186 for(t
=0;t
<REJECT
;t
++)
187 if(!memcmp(mh
.songname
,signatures
[t
],siglen
[t
])) return 0;
189 if(mh
.magic1
>127) return 0;
190 if((!mh
.songlength
)||(mh
.songlength
>mh
.magic1
)) return 0;
193 /* all finetunes should be zero */
194 if(mh
.samples
[t
].finetune
) return 0;
196 /* all volumes should be <= 64 */
197 if(mh
.samples
[t
].volume
>64) return 0;
199 /* all instrument names should begin with s, st-, or a number */
200 if((mh
.samples
[t
].samplename
[0]=='s')||
201 (mh
.samples
[t
].samplename
[0]=='S')) {
202 if((memcmp(mh
.samples
[t
].samplename
,"st-",3)) &&
203 (memcmp(mh
.samples
[t
].samplename
,"ST-",3)) &&
204 (*mh
.samples
[t
].samplename
))
207 if(!isdigit((int)mh
.samples
[t
].samplename
[0]))
210 if(mh
.samples
[t
].length
>4999||mh
.samples
[t
].reppos
>9999) {
212 if(mh
.samples
[t
].length
>32768) return 0;
215 /* if loop information is incorrect as words, but correct as bytes,
216 this is likely to be an ust-style module */
217 if((mh
.samples
[t
].reppos
+mh
.samples
[t
].replen
>mh
.samples
[t
].length
)&&
218 (mh
.samples
[t
].reppos
+mh
.samples
[t
].replen
<(mh
.samples
[t
].length
<<1))){
223 if(!ust_loader
) return 1;
226 for(numpat
=0,t
=0;t
<mh
.songlength
;t
++)
227 if(mh
.positions
[t
]>numpat
)
228 numpat
= mh
.positions
[t
];
230 switch(CheckPatternType(numpat
)) {
231 case 0: /* indecisive, so check more clues... */
243 static int M15_Init(void)
245 if(!(mh
=(MODULEHEADER
*)MikMod_malloc(sizeof(MODULEHEADER
)))) return 0;
249 static void M15_Cleanup(void)
256 Old (amiga) noteinfo:
258 _____byte 1_____ byte2_ _____byte 3_____ byte4_
260 0000 0000-00000000 0000 0000-00000000
262 Upper four 12 bits for Lower four Effect command.
263 bits of sam- note period. bits of sam-
264 ple number. ple number.
267 static UBYTE
M15_ConvertNote(MODNOTE
* n
, UBYTE lasteffect
)
269 UBYTE instrument
,effect
,effdat
,note
;
273 /* decode the 4 bytes that make up a single note */
274 instrument
= n
->c
>>4;
275 period
= (((UWORD
)n
->a
&0xf)<<8)+n
->b
;
279 /* Convert the period to a note number */
282 for(note
=0;note
<7*OCTAVE
;note
++)
283 if(period
>=npertab
[note
]) break;
284 if(note
==7*OCTAVE
) note
=0;
289 /* if instrument does not exist, note cut */
290 if((instrument
>15)||(!mh
->samples
[instrument
-1].length
)) {
292 if(effect
==0xc) effect
=effdat
=0;
294 /* if we had a note, then change instrument... */
296 UniInstrument(instrument
-1);
297 /* ...otherwise, only adjust volume... */
299 /* ...unless an effect was specified, which forces a new note
302 UniInstrument(instrument
-1);
305 UniPTEffect(0xc,mh
->samples
[instrument
-1].volume
&0x7f);
310 UniNote(note
+2*OCTAVE
-1);
314 /* Convert pattern jump from Dec to Hex */
316 effdat
=(((effdat
&0xf0)>>4)*10)+(effdat
&0xf);
318 /* Volume slide, up has priority */
319 if((effect
==0xa)&&(effdat
&0xf)&&(effdat
&0xf0))
322 /* Handle ``heavy'' volumes correctly */
323 if ((effect
== 0xc) && (effdat
> 0x40))
332 UniPTEffect(0,effdat
);
335 if(effdat
&0xf) UniPTEffect(1,effdat
&0xf);
336 else if(effdat
>>2) UniPTEffect(2,effdat
>>2);
339 UniPTEffect(effect
,effdat
);
343 /* An isolated 100, 200 or 300 effect should be ignored (no
344 "standalone" porta memory in mod files). However, a sequence
345 such as 1XX, 100, 100, 100 is fine. */
346 if ((!effdat
) && ((effect
== 1)||(effect
== 2)||(effect
==3)) &&
347 (lasteffect
< 0x10) && (effect
!= lasteffect
))
350 UniPTEffect(effect
,effdat
);
353 of
.flags
|= UF_PANNING
;
358 static UBYTE
*M15_ConvertTrack(MODNOTE
* n
)
361 UBYTE lasteffect
= 0x10; /* non existant effect */
365 lasteffect
= M15_ConvertNote(n
,lasteffect
);
372 /* Loads all patterns of a modfile and converts them into the 3 byte format. */
373 static int M15_LoadPatterns(void)
378 if(!AllocPatterns()) return 0;
379 if(!AllocTracks()) return 0;
381 /* Allocate temporary buffer for loading and converting the patterns */
382 if(!(patbuf
=(MODNOTE
*)MikMod_calloc(64U*4,sizeof(MODNOTE
)))) return 0;
384 for(t
=0;t
<of
.numpat
;t
++) {
385 /* Load the pattern into the temp buffer and convert it */
386 for(s
=0;s
<(64U*4);s
++) {
387 patbuf
[s
].a
=_mm_read_UBYTE(modreader
);
388 patbuf
[s
].b
=_mm_read_UBYTE(modreader
);
389 patbuf
[s
].c
=_mm_read_UBYTE(modreader
);
390 patbuf
[s
].d
=_mm_read_UBYTE(modreader
);
394 if(!(of
.tracks
[tracks
++]=M15_ConvertTrack(patbuf
+s
))) return 0;
399 static int M15_Load(int curious
)
405 /* try to read module header */
406 if(!LoadModuleHeader(mh
)) {
407 _mm_errno
= MMERR_LOADING_HEADER
;
412 of
.modtype
= StrDup("Ultimate Soundtracker");
414 of
.modtype
= StrDup("Soundtracker");
416 /* set module variables */
420 of
.songname
= DupStr(mh
->songname
,21,1);
421 of
.numpos
= mh
->songlength
;
424 /* Count the number of patterns */
426 for(t
=0;t
<of
.numpos
;t
++)
427 if(mh
->positions
[t
]>of
.numpat
)
428 of
.numpat
=mh
->positions
[t
];
429 /* since some old modules embed extra patterns, we have to check the
430 whole list to get the samples' file offsets right - however we can find
431 garbage here, so check carefully */
433 for(t
=of
.numpos
;t
<128;t
++)
434 if(mh
->positions
[t
]>=0x80) scan
=0;
436 for(t
=of
.numpos
;t
<128;t
++) {
437 if(mh
->positions
[t
]>of
.numpat
)
438 of
.numpat
=mh
->positions
[t
];
439 if((curious
)&&(mh
->positions
[t
])) of
.numpos
=t
+1;
442 of
.numtrk
= of
.numpat
*of
.numchn
;
444 if(!AllocPositions(of
.numpos
)) return 0;
445 for(t
=0;t
<of
.numpos
;t
++)
446 of
.positions
[t
]=mh
->positions
[t
];
448 /* Finally, init the sampleinfo structures */
449 of
.numins
=of
.numsmp
=15;
450 if(!AllocSamples()) return 0;
455 for(t
=0;t
<of
.numins
;t
++) {
456 /* convert the samplename */
457 q
->samplename
= DupStr(s
->samplename
,23,1);
459 /* init the sampleinfo variables and convert the size pointers */
460 q
->speed
= finetune
[s
->finetune
&0xf];
461 q
->volume
= s
->volume
;
463 q
->loopstart
= s
->reppos
;
465 q
->loopstart
= s
->reppos
<<1;
466 q
->loopend
= q
->loopstart
+(s
->replen
<<1);
467 q
->length
= s
->length
<<1;
469 q
->flags
= SF_SIGNED
;
470 if(ust_loader
) q
->flags
|= SF_UST_LOOP
;
471 if(s
->replen
>2) q
->flags
|= SF_LOOP
;
477 if(!M15_LoadPatterns()) return 0;
483 static CHAR
*M15_LoadTitle(void)
487 _mm_fseek(modreader
,0,SEEK_SET
);
488 if(!_mm_read_UBYTES(s
,20,modreader
)) return NULL
;
489 s
[20]=0; /* just in case */
490 return(DupStr(s
,21,1));
493 /*========== Loader information */
495 MIKMODAPI MLOADER load_m15
={
497 "15-instrument module",
498 "MOD (15 instrument)",