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_far.c,v 1.3 2005/04/07 19:57:38 realtech Exp $
25 Farandole (FAR) module loader
27 ==============================================================================*/
43 #include "mikmod_internals.h"
46 extern int fprintf(FILE *, const char *, ...);
49 /*========== Module structure */
51 typedef struct FARHEADER1
{
52 UBYTE id
[4]; /* file magic */
53 CHAR songname
[40]; /* songname */
54 CHAR blah
[3]; /* 13,10,26 */
55 UWORD headerlen
; /* remaining length of header in bytes */
65 typedef struct FARHEADER2
{
73 typedef struct FARSAMPLE
{
84 typedef struct FARNOTE
{
85 UBYTE note
,ins
,vol
,eff
;
88 /*========== Loader variables */
90 static CHAR FAR_Version
[] = "Farandole";
91 static FARHEADER1
*mh1
= NULL
;
92 static FARHEADER2
*mh2
= NULL
;
93 static FARNOTE
*pat
= NULL
;
95 static unsigned char FARSIG
[4+3]={'F','A','R',0xfe,13,10,26};
97 /*========== Loader code */
99 static int FAR_Test(void)
103 if(!_mm_read_UBYTES(id
,47,modreader
)) return 0;
104 if((memcmp(id
,FARSIG
,4))||(memcmp(id
+44,FARSIG
+4,3))) return 0;
108 static int FAR_Init(void)
110 if(!(mh1
= (FARHEADER1
*)MikMod_malloc(sizeof(FARHEADER1
)))) return 0;
111 if(!(mh2
= (FARHEADER2
*)MikMod_malloc(sizeof(FARHEADER2
)))) return 0;
112 if(!(pat
= (FARNOTE
*)MikMod_malloc(256*16*4*sizeof(FARNOTE
)))) return 0;
117 static void FAR_Cleanup(void)
124 static UBYTE
*FAR_ConvertTrack(FARNOTE
* n
,int rows
)
129 for(t
=0;t
<rows
;t
++) {
131 UniInstrument(n
->ins
);
132 UniNote(n
->note
+3*OCTAVE
-1);
134 if (n
->vol
&0xf) UniPTEffect(0xc,(n
->vol
&0xf)<<2);
137 case 0x3: /* porta to note */
138 UniPTEffect(0x3,(n
->eff
&0xf)<<4);
140 case 0x4: /* retrigger */
141 UniPTEffect(0x0e, 0x90 | (n
->eff
& 0x0f));
143 case 0x5: /* set vibrato depth */
146 case 0x6: /* vibrato */
147 UniPTEffect(0x4,((n
->eff
&0xf)<<4)|vibdepth
);
149 case 0x7: /* volume slide up */
150 UniPTEffect(0xa,(n
->eff
&0xf)<<4);
152 case 0x8: /* volume slide down */
153 UniPTEffect(0xa,n
->eff
&0xf);
155 case 0xb: /* panning */
156 UniPTEffect(0xe,0x80|(n
->eff
&0xf));
158 case 0xf: /* set speed */
159 UniPTEffect(0xf,n
->eff
&0xf);
162 /* others not yet implemented */
165 fprintf(stderr
,"\rFAR: unsupported effect %02X\n",n
->eff
);
176 static int FAR_Load(int curious
)
185 /* try to read module header (first part) */
186 _mm_read_UBYTES(mh1
->id
,4,modreader
);
187 _mm_read_SBYTES(mh1
->songname
,40,modreader
);
188 _mm_read_SBYTES(mh1
->blah
,3,modreader
);
189 mh1
->headerlen
= _mm_read_I_UWORD (modreader
);
190 mh1
->version
= _mm_read_UBYTE (modreader
);
191 _mm_read_UBYTES(mh1
->onoff
,16,modreader
);
192 _mm_read_UBYTES(mh1
->edit1
,9,modreader
);
193 mh1
->speed
= _mm_read_UBYTE(modreader
);
194 _mm_read_UBYTES(mh1
->panning
,16,modreader
);
195 _mm_read_UBYTES(mh1
->edit2
,4,modreader
);
196 mh1
->stlen
= _mm_read_I_UWORD (modreader
);
198 /* init modfile data */
199 of
.modtype
= StrDup(FAR_Version
);
200 of
.songname
= DupStr(mh1
->songname
,40,1);
202 of
.initspeed
= mh1
->speed
;
205 of
.flags
|= UF_PANNING
;
206 for(t
=0;t
<16;t
++) of
.panning
[t
]=mh1
->panning
[t
]<<4;
208 /* read songtext into comment field */
210 if (!ReadLinedComment(mh1
->stlen
, 66)) return 0;
212 /* try to read module header (second part) */
213 _mm_read_UBYTES(mh2
->orders
,256,modreader
);
214 mh2
->numpat
= _mm_read_UBYTE(modreader
);
215 mh2
->snglen
= _mm_read_UBYTE(modreader
);
216 mh2
->loopto
= _mm_read_UBYTE(modreader
);
217 _mm_read_I_UWORDS(mh2
->patsiz
,256,modreader
);
219 of
.numpos
= mh2
->snglen
;
220 if(!AllocPositions(of
.numpos
)) return 0;
221 for(t
=0;t
<of
.numpos
;t
++) {
222 if(mh2
->orders
[t
]==0xff) break;
223 of
.positions
[t
] = mh2
->orders
[t
];
226 /* count number of patterns stored in file */
230 if((t
+1)>of
.numpat
) of
.numpat
=t
+1;
231 of
.numtrk
= of
.numpat
*of
.numchn
;
233 /* seek across eventual new data */
234 _mm_fseek(modreader
,mh1
->headerlen
-(869+mh1
->stlen
),SEEK_CUR
);
236 /* alloc track and pattern structures */
237 if(!AllocTracks()) return 0;
238 if(!AllocPatterns()) return 0;
240 for(t
=0;t
<of
.numpat
;t
++) {
241 UBYTE rows
=0/* ,tempo */;
243 memset(pat
,0,256*16*4*sizeof(FARNOTE
));
245 rows
= _mm_read_UBYTE(modreader
);
246 /* tempo = */ (void)_mm_read_UBYTE(modreader
);
249 /* file often allocates 64 rows even if there are less in pattern */
250 if (mh2
->patsiz
[t
]<2+(rows
*16*4)) {
251 _mm_errno
= MMERR_LOADING_PATTERN
;
254 for(u
=(mh2
->patsiz
[t
]-2)/4;u
;u
--,crow
++) {
255 crow
->note
= _mm_read_UBYTE(modreader
);
256 crow
->ins
= _mm_read_UBYTE(modreader
);
257 crow
->vol
= _mm_read_UBYTE(modreader
);
258 crow
->eff
= _mm_read_UBYTE(modreader
);
261 if(_mm_eof(modreader
)) {
262 _mm_errno
= MMERR_LOADING_PATTERN
;
267 of
.pattrows
[t
] = rows
;
268 for(u
=16;u
;u
--,crow
++)
269 if(!(of
.tracks
[tracks
++]=FAR_ConvertTrack(crow
,rows
))) {
270 _mm_errno
=MMERR_LOADING_PATTERN
;
277 /* read sample map */
278 if(!_mm_read_UBYTES(smap
,8,modreader
)) {
279 _mm_errno
= MMERR_LOADING_HEADER
;
283 /* count number of samples used */
286 if(smap
[t
>>3]&(1<<(t
&7))) of
.numins
=t
+1;
287 of
.numsmp
= of
.numins
;
289 /* alloc sample structs */
290 if(!AllocSamples()) return 0;
293 for(t
=0;t
<of
.numsmp
;t
++) {
295 q
->flags
= SF_SIGNED
;
296 if(smap
[t
>>3]&(1<<(t
&7))) {
297 _mm_read_SBYTES(s
.samplename
,32,modreader
);
298 s
.length
= _mm_read_I_ULONG(modreader
);
299 s
.finetune
= _mm_read_UBYTE(modreader
);
300 s
.volume
= _mm_read_UBYTE(modreader
);
301 s
.reppos
= _mm_read_I_ULONG(modreader
);
302 s
.repend
= _mm_read_I_ULONG(modreader
);
303 s
.type
= _mm_read_UBYTE(modreader
);
304 s
.loop
= _mm_read_UBYTE(modreader
);
306 q
->samplename
= DupStr(s
.samplename
,32,1);
307 q
->length
= s
.length
;
308 q
->loopstart
= s
.reppos
;
309 q
->loopend
= s
.repend
;
310 q
->volume
= s
.volume
<<2;
312 if(s
.type
&1) q
->flags
|=SF_16BITS
;
313 if(s
.loop
&8) q
->flags
|=SF_LOOP
;
315 q
->seekpos
= _mm_ftell(modreader
);
316 _mm_fseek(modreader
,q
->length
,SEEK_CUR
);
318 q
->samplename
= DupStr(NULL
,0,0);
324 static CHAR
*FAR_LoadTitle(void)
328 _mm_fseek(modreader
,4,SEEK_SET
);
329 if(!_mm_read_UBYTES(s
,40,modreader
)) return NULL
;
331 return(DupStr(s
,40,1));
334 /*========== Loader information */
336 MIKMODAPI MLOADER load_far
={
339 "FAR (Farandole Composer)",