comparison playercode/load_far.c @ 4:5d614bcc4287

Initial entry of mikmod into the CVS tree.
author darius
date Fri, 23 Jan 1998 16:05:08 +0000
parents
children
comparison
equal deleted inserted replaced
3:71e20a32bd84 4:5d614bcc4287
1 /*
2
3 Name: LOAD_FAR.C
4
5 Description:
6 Farandole (FAR) module loader
7
8 Portability:
9 All systems - all compilers (hopefully)
10
11 If this module is found to not be portable to any particular platform,
12 please contact Jake Stine at dracoirs@epix.net (see MIKMOD.TXT for
13 more information on contacting the author).
14 */
15
16 #include <string.h>
17 #include "mikmod.h"
18
19
20 typedef struct FARSAMPLE
21 { CHAR samplename[32];
22 ULONG length;
23 UBYTE finetune;
24 UBYTE volume;
25 ULONG reppos;
26 ULONG repend;
27 UBYTE type;
28 UBYTE loop;
29 } FARSAMPLE;
30
31
32
33 typedef struct FARHEADER1
34 { UBYTE id[4]; // file magic
35 CHAR songname[40]; // songname
36 CHAR blah[3]; // 13,10,26
37 UWORD headerlen; // remaining length of header in bytes
38 UBYTE version;
39 UBYTE onoff[16];
40 UBYTE edit1[9];
41 UBYTE speed;
42 UBYTE panning[16];
43 UBYTE edit2[4];
44 UWORD stlen;
45 } FARHEADER1;
46
47
48 typedef struct FARHEADER2
49 { UBYTE orders[256];
50 UBYTE numpat;
51 UBYTE snglen;
52 UBYTE loopto;
53 UWORD patsiz[256];
54 } FARHEADER2;
55
56
57 typedef struct FARNOTE
58 { UBYTE note,ins,vol,eff;
59 } FARNOTE;
60
61
62
63 static CHAR FAR_Version[] = "Farandole";
64 static FARHEADER1 *mh1 = NULL;
65 static FARHEADER2 *mh2 = NULL;
66 static FARNOTE *pat = NULL;
67
68
69 BOOL FAR_Test(void)
70 {
71 UBYTE id[4];
72
73 if(!_mm_read_UBYTES(id,4,modfp)) return 0;
74 return(!memcmp(id,"FAR=",4));
75 }
76
77
78 BOOL FAR_Init(void)
79 {
80 if(!(mh1 = (FARHEADER1 *)_mm_malloc(sizeof(FARHEADER1)))) return 0;
81 if(!(mh2 = (FARHEADER2 *)_mm_malloc(sizeof(FARHEADER2)))) return 0;
82 if(!(pat = (FARNOTE *)_mm_malloc(16*256*sizeof(FARNOTE)))) return 0;
83
84 return 1;
85 }
86
87
88 void FAR_Cleanup(void)
89 {
90 if(mh1!=NULL) free(mh1);
91 if(mh2!=NULL) free(mh2);
92 if(pat!=NULL) free(pat);
93
94 mh1 = NULL;
95 mh2 = NULL;
96 pat = NULL;
97 }
98
99
100 UBYTE *FAR_ConvertTrack(FARNOTE *n,int rows)
101 {
102 int t;
103
104 UniReset();
105
106 for(t=0; t<rows; t++)
107 { if(n->note)
108 { UniInstrument(n->ins);
109 UniNote(n->note+23+12);
110 }
111
112 if(n->vol&0xf) UniPTEffect(0xc,(n->vol&0xf)<<2);
113 switch(n->eff>>4)
114 { case 0xf:
115 UniPTEffect(0xf,n->eff&0xf);
116 break;
117
118 // others not yet implemented
119 }
120
121 UniNewline();
122 n+=16;
123 }
124 return UniDup();
125 }
126
127
128 BOOL FAR_Load(void)
129 {
130 int t,u,tracks=0;
131 SAMPLE *q;
132 FARSAMPLE s;
133 FARNOTE *crow;
134 UBYTE smap[8];
135
136 // try to read module header (first part)
137 _mm_read_UBYTES(mh1->id,4,modfp);
138 _mm_read_SBYTES(mh1->songname,40,modfp);
139 _mm_read_SBYTES(mh1->blah,3,modfp);
140 mh1->headerlen = _mm_read_I_UWORD (modfp);
141 mh1->version = _mm_read_UBYTE (modfp);
142 _mm_read_UBYTES(mh1->onoff,16,modfp);
143 _mm_read_UBYTES(mh1->edit1,9,modfp);
144 mh1->speed = _mm_read_UBYTE(modfp);
145 _mm_read_UBYTES(mh1->panning,16,modfp);
146 _mm_read_UBYTES(mh1->edit2,4,modfp);
147 mh1->stlen = _mm_read_I_UWORD (modfp);
148
149
150 // init modfile data
151
152 of.modtype = strdup(FAR_Version);
153 of.songname = DupStr(mh1->songname,40);
154 of.numchn = 16;
155 of.initspeed = mh1->speed;
156 of.inittempo = 99;
157
158 for(t=0; t<16; t++) of.panning[t] = mh1->panning[t]<<4;
159
160 // read songtext into comment field
161 if(!ReadComment(mh1->stlen)) return 0;
162
163 // try to read module header (second part)
164 _mm_read_UBYTES(mh2->orders,256,modfp);
165 mh2->numpat = _mm_read_UBYTE(modfp);
166 mh2->snglen = _mm_read_UBYTE(modfp);
167 mh2->loopto = _mm_read_UBYTE(modfp);
168 _mm_read_I_UWORDS(mh2->patsiz,256,modfp);
169
170 // of.numpat=mh2->numpat;
171 of.numpos = mh2->snglen;
172 if(!AllocPositions(of.numpos)) return 0;
173 for(t=0; t<of.numpos; t++)
174 { if(mh2->orders[t]==0xff) break;
175 of.positions[t] = mh2->orders[t];
176 }
177
178 // count number of patterns stored in file
179 of.numpat = 0;
180 for(t=0; t<256; t++)
181 if(mh2->patsiz[t]) if((t+1)>of.numpat) of.numpat=t+1;
182
183 of.numtrk = of.numpat*of.numchn;
184
185 // seek across eventual new data
186 _mm_fseek(modfp,mh1->headerlen-(869+mh1->stlen),SEEK_CUR);
187
188 // alloc track and pattern structures
189 if(!AllocTracks()) return 0;
190 if(!AllocPatterns()) return 0;
191
192 for(t=0; t<of.numpat; t++)
193 { UBYTE rows=0,tempo;
194
195 memset(pat,0,16*256*sizeof(FARNOTE));
196 if(mh2->patsiz[t])
197 { rows = _mm_read_UBYTE(modfp);
198 tempo = _mm_read_UBYTE(modfp);
199
200 crow = pat;
201 for(u=mh2->patsiz[t]-2; u; u--, crow++)
202 { crow->note = _mm_read_UBYTE(modfp);
203 crow->ins = _mm_read_UBYTE(modfp);
204 crow->vol = _mm_read_UBYTE(modfp);
205 crow->eff = _mm_read_UBYTE(modfp);
206 }
207
208 if(feof(modfp))
209 { _mm_errno = MMERR_LOADING_PATTERN;
210 return 0;
211 }
212
213 of.pattrows[t] = rows+2;
214 crow = pat;
215 for(u=16; u; u--)
216 if(!(of.tracks[tracks++] = FAR_ConvertTrack(crow,rows+2))) return 0;
217 }
218 }
219
220 // read sample map
221 if(!_mm_read_UBYTES(smap,8,modfp))
222 { _mm_errno = MMERR_LOADING_HEADER;
223 return 0;
224 }
225
226 // count number of samples used
227 of.numins = 0;
228 for(t=0; t<64; t++)
229 if(smap[t>>3] & (1 << (t&7))) of.numins++;
230 of.numsmp = of.numins;
231
232 // alloc sample structs
233 if(!AllocSamples()) return 0;
234 q = of.samples;
235
236 for(t=0; t<64; t++)
237 { if(smap[t>>3] & (1 << (t&7)))
238 { _mm_read_SBYTES(s.samplename,32,modfp);
239 s.length = _mm_read_I_ULONG(modfp);
240 s.finetune = _mm_read_UBYTE(modfp);
241 s.volume = _mm_read_UBYTE(modfp);
242 s.reppos = _mm_read_I_ULONG(modfp);
243 s.repend = _mm_read_I_ULONG(modfp);
244 s.type = _mm_read_UBYTE(modfp);
245 s.loop = _mm_read_UBYTE(modfp);
246
247 q->samplename = DupStr(s.samplename,32);
248 q->length = s.length;
249 q->loopstart = s.reppos;
250 q->loopend = s.repend;
251 q->volume = 64;
252 q->speed = 8363;
253
254 q->flags=SF_SIGNED;
255 if(s.type&1) q->flags|=SF_16BITS;
256 if(s.loop) q->flags|=SF_LOOP;
257
258 q->seekpos = _mm_ftell(modfp);
259 _mm_fseek(modfp,q->length,SEEK_CUR);
260 }
261 q++;
262 }
263 return 1;
264 }
265
266
267 CHAR *FAR_LoadTitle(void)
268 {
269 CHAR s[40];
270
271 _mm_fseek(modfp,4,SEEK_SET);
272 if(!fread(s,40,1,modfp)) return NULL;
273
274 return(DupStr(s,40));
275 }
276
277
278 MLOADER load_far =
279 { NULL,
280 "FAR",
281 "Portable FAR loader v0.1",
282 FAR_Init,
283 FAR_Test,
284 FAR_Load,
285 FAR_Cleanup,
286 FAR_LoadTitle
287 };
288