Mercurial > ~darius > hgwebdir.cgi > mikmod
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 |