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