Mercurial > ~darius > hgwebdir.cgi > mikmod
comparison playercode/load_ult.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_ULT.C | |
4 | |
5 Description: | |
6 Ultratracker (ULT) 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 | |
17 #include <string.h> | |
18 #include "mikmod.h" | |
19 | |
20 | |
21 #define ULTS_16BITS 4 | |
22 #define ULTS_LOOP 8 | |
23 #define ULTS_REVERSE 16 | |
24 | |
25 | |
26 // Raw ULT header struct: | |
27 | |
28 typedef struct ULTHEADER | |
29 { CHAR id[16]; | |
30 CHAR songtitle[32]; | |
31 UBYTE reserved; | |
32 } ULTHEADER; | |
33 | |
34 | |
35 // Raw ULT sampleinfo struct: | |
36 | |
37 typedef struct ULTSAMPLE | |
38 { CHAR samplename[32]; | |
39 CHAR dosname[12]; | |
40 SLONG loopstart; | |
41 SLONG loopend; | |
42 SLONG sizestart; | |
43 SLONG sizeend; | |
44 UBYTE volume; | |
45 UBYTE flags; | |
46 SWORD finetune; | |
47 } ULTSAMPLE; | |
48 | |
49 | |
50 typedef struct ULTEVENT | |
51 { UBYTE note,sample,eff,dat1,dat2; | |
52 } ULTEVENT; | |
53 | |
54 | |
55 CHAR *ULT_Version[]= | |
56 { "Ultra Tracker V1.3", | |
57 "Ultra Tracker V1.4", | |
58 "Ultra Tracker V1.5", | |
59 "Ultra Tracker V1.6" | |
60 }; | |
61 | |
62 | |
63 BOOL ULT_Test(void) | |
64 { | |
65 CHAR id[16]; | |
66 | |
67 if(!_mm_read_string(id,15,modfp)) return 0; | |
68 return(!strncmp(id,"MAS_UTrack_V00",14)); | |
69 } | |
70 | |
71 | |
72 BOOL ULT_Init(void) | |
73 { | |
74 return 1; | |
75 } | |
76 | |
77 | |
78 void ULT_Cleanup(void) | |
79 { | |
80 } | |
81 | |
82 ULTEVENT ev; | |
83 | |
84 | |
85 | |
86 int ReadUltEvent(ULTEVENT *event) | |
87 { | |
88 UBYTE flag,rep=1; | |
89 | |
90 flag = _mm_read_UBYTE(modfp); | |
91 | |
92 if(flag==0xfc) | |
93 { rep = _mm_read_UBYTE(modfp); | |
94 event->note =_mm_read_UBYTE(modfp); | |
95 } else | |
96 event->note = flag; | |
97 | |
98 event->sample =_mm_read_UBYTE(modfp); | |
99 event->eff =_mm_read_UBYTE(modfp); | |
100 event->dat1 =_mm_read_UBYTE(modfp); | |
101 event->dat2 =_mm_read_UBYTE(modfp); | |
102 | |
103 return rep; | |
104 } | |
105 | |
106 | |
107 BOOL ULT_Load(void) | |
108 { | |
109 int t,u,tracks=0; | |
110 SAMPLE *q; | |
111 ULTSAMPLE s; | |
112 ULTHEADER mh; | |
113 UBYTE nos,noc,nop; | |
114 | |
115 // try to read module header | |
116 | |
117 _mm_read_string(mh.id,15,modfp); | |
118 _mm_read_string(mh.songtitle,32,modfp); | |
119 mh.reserved = _mm_read_UBYTE(modfp); | |
120 | |
121 if(feof(modfp)) | |
122 { _mm_errno = MMERR_LOADING_HEADER; | |
123 return 0; | |
124 } | |
125 | |
126 if(mh.id[14]<'1' || mh.id[14]>'4') | |
127 { _mm_errno = MMERR_NOT_A_MODULE; | |
128 return 0; | |
129 } | |
130 | |
131 of.modtype = strdup(ULT_Version[mh.id[14]-'1']); | |
132 of.initspeed = 6; | |
133 of.inittempo = 125; | |
134 | |
135 // read songtext | |
136 | |
137 if(!ReadComment((UWORD)mh.reserved*32)) return 0; | |
138 | |
139 nos = _mm_read_UBYTE(modfp); | |
140 | |
141 if(feof(modfp)) | |
142 { _mm_errno = MMERR_LOADING_HEADER; | |
143 return 0; | |
144 } | |
145 | |
146 of.songname = DupStr(mh.songtitle,32); | |
147 of.numins = nos; | |
148 | |
149 if(!AllocSamples()) return 0; | |
150 | |
151 q = of.samples; | |
152 | |
153 for(t=0; t<nos; t++) | |
154 { // try to read sample info | |
155 | |
156 _mm_read_string(s.samplename,32,modfp); | |
157 _mm_read_string(s.dosname,12,modfp); | |
158 s.loopstart =_mm_read_I_ULONG(modfp); | |
159 s.loopend =_mm_read_I_ULONG(modfp); | |
160 s.sizestart =_mm_read_I_ULONG(modfp); | |
161 s.sizeend =_mm_read_I_ULONG(modfp); | |
162 s.volume =_mm_read_UBYTE(modfp); | |
163 s.flags =_mm_read_UBYTE(modfp); | |
164 s.finetune =_mm_read_I_SWORD(modfp); | |
165 | |
166 if(feof(modfp)) | |
167 { _mm_errno = MMERR_LOADING_SAMPLEINFO; | |
168 return 0; | |
169 } | |
170 | |
171 q->samplename = DupStr(s.samplename,32); | |
172 q->speed = 8363; | |
173 | |
174 if(mh.id[14]>='4') | |
175 { _mm_read_I_UWORD(modfp); // read 1.6 extra info(??) word | |
176 q->speed=s.finetune; | |
177 } | |
178 | |
179 q->length = s.sizeend-s.sizestart; | |
180 q->volume = s.volume>>2; | |
181 q->loopstart = s.loopstart; | |
182 q->loopend = s.loopend; | |
183 | |
184 q->flags = SF_SIGNED; | |
185 | |
186 if(s.flags&ULTS_LOOP) | |
187 q->flags|=SF_LOOP; | |
188 | |
189 if(s.flags&ULTS_16BITS) | |
190 { q->flags|=SF_16BITS; | |
191 q->loopstart>>=1; | |
192 q->loopend>>=1; | |
193 } | |
194 | |
195 q++; | |
196 } | |
197 | |
198 if(!AllocPositions(256)) return 0; | |
199 for(t=0; t<256; t++) | |
200 of.positions[t] = _mm_read_UBYTE(modfp); | |
201 for(t=0; t<256; t++) | |
202 if(of.positions[t]==255) break; | |
203 | |
204 of.numpos = t; | |
205 | |
206 noc = _mm_read_UBYTE(modfp); | |
207 nop = _mm_read_UBYTE(modfp); | |
208 | |
209 of.numchn = noc+1; | |
210 of.numpat = nop+1; | |
211 of.numtrk = of.numchn*of.numpat; | |
212 | |
213 if(!AllocTracks()) return 0; | |
214 if(!AllocPatterns()) return 0; | |
215 | |
216 for(u=0; u<of.numchn; u++) | |
217 { for(t=0; t<of.numpat; t++) | |
218 of.patterns[(t*of.numchn)+u]=tracks++; | |
219 } | |
220 | |
221 // read pan position table for v1.5 and higher | |
222 | |
223 if(mh.id[14]>='3') | |
224 for(t=0; t<of.numchn; t++) of.panning[t]=_mm_read_UBYTE(modfp)<<4; | |
225 | |
226 for(t=0; t<of.numtrk; t++) | |
227 { int rep,s,done; | |
228 | |
229 UniReset(); | |
230 done=0; | |
231 | |
232 while(done<64) | |
233 { rep=ReadUltEvent(&ev); | |
234 | |
235 if(feof(modfp)) | |
236 { _mm_errno = MMERR_LOADING_TRACK; | |
237 return 0; | |
238 } | |
239 | |
240 for(s=0; s<rep; s++) | |
241 { UBYTE eff; | |
242 | |
243 if(ev.sample) UniInstrument(ev.sample-1); | |
244 if(ev.note) UniNote(ev.note+23); | |
245 | |
246 eff = ev.eff>>4; | |
247 | |
248 // ULT panning effect fixed by Alexander Kerkhove : | |
249 | |
250 if(eff==0xc) UniPTEffect(eff,ev.dat2>>2); | |
251 else if(eff==0xb) UniPTEffect(8,ev.dat2*0xf); | |
252 else UniPTEffect(eff,ev.dat2); | |
253 | |
254 eff=ev.eff&0xf; | |
255 | |
256 if(eff==0xc) UniPTEffect(eff,ev.dat1>>2); | |
257 else if(eff==0xb) UniPTEffect(8,ev.dat1*0xf); | |
258 else UniPTEffect(eff,ev.dat1); | |
259 | |
260 UniNewline(); | |
261 done++; | |
262 } | |
263 } | |
264 if(!(of.tracks[t]=UniDup())) return 0; | |
265 } | |
266 | |
267 return 1; | |
268 } | |
269 | |
270 | |
271 CHAR *ULT_LoadTitle(void) | |
272 { | |
273 CHAR s[32]; | |
274 | |
275 _mm_fseek(modfp,15,SEEK_SET); | |
276 if(!fread(s,32,1,modfp)) return NULL; | |
277 | |
278 return(DupStr(s,32)); | |
279 } | |
280 | |
281 | |
282 MLOADER load_ult = | |
283 { NULL, | |
284 "ULT", | |
285 "Portable ULT loader v0.1", | |
286 ULT_Init, | |
287 ULT_Test, | |
288 ULT_Load, | |
289 ULT_Cleanup, | |
290 ULT_LoadTitle | |
291 }; | |
292 |