added an old version of mikmod for dos
[dosdemo] / libs / oldmik / src / load_ult.c
1 /*
2
3 Name:
4 LOAD_ULT.C
5
6 Description:
7 Ultratracker (ULT) module loader
8
9 Portability:
10 All systems - all compilers (hopefully)
11
12 */
13 #include <stdio.h>
14 #include <stdlib.h>
15 #include <string.h>
16 #include <ctype.h>
17 #include "mikmod.h"
18
19 #define ULTS_16BITS     4
20 #define ULTS_LOOP       8
21 #define ULTS_REVERSE    16
22
23
24 /* Raw ULT header struct: */
25
26 typedef struct ULTHEADER{
27         char  id[15];
28         char  songtitle[32];
29         UBYTE reserved;
30 } ULTHEADER;
31
32
33 /* Raw ULT sampleinfo struct: */
34
35 typedef struct ULTSAMPLE{
36         char  samplename[32];
37         char  dosname[12];
38         SLONG  loopstart;
39         SLONG  loopend;
40         SLONG  sizestart;
41         SLONG  sizeend;
42         UBYTE volume;
43         UBYTE flags;
44         SWORD  finetune;
45 } ULTSAMPLE;
46
47
48 typedef struct ULTEVENT{
49         UBYTE note,sample,eff,dat1,dat2;
50 } ULTEVENT;
51
52
53 char *ULT_Version[]={
54         "Ultra Tracker V1.3",
55         "Ultra Tracker V1.4",
56         "Ultra Tracker V1.5",
57         "Ultra Tracker V1.6"
58 };
59
60
61 BOOL ULT_Test(void)
62 {
63         char id[15];
64
65         if(!fread(&id,15,1,modfp)) return 0;
66         return(!strncmp(id,"MAS_UTrack_V00",14));
67 }
68
69
70 BOOL ULT_Init(void)
71 {
72         return 1;
73 }
74
75
76 void ULT_Cleanup(void)
77 {
78 }
79
80 ULTEVENT ev;
81
82
83
84 int ReadUltEvent(ULTEVENT *event)
85 {
86         UBYTE flag,rep=1;
87
88         flag=_mm_read_UBYTE(modfp);
89
90         if(flag==0xfc){
91                 fread(&rep,1,1,modfp);
92                 event->note     =_mm_read_UBYTE(modfp);
93         }
94         else{
95                 event->note=flag;
96         }
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
108
109 BOOL ULT_Load(void)
110 {
111         int t,u,tracks=0;
112         INSTRUMENT *d;
113         SAMPLE *q;
114         ULTSAMPLE s;
115         ULTHEADER mh;
116         UBYTE nos,noc,nop;
117
118         /* try to read module header */
119
120         _mm_read_str(mh.id,15,modfp);
121         _mm_read_str(mh.songtitle,32,modfp);
122         mh.reserved=_mm_read_UBYTE(modfp);
123
124         if(feof(modfp)){
125                 myerr=ERROR_LOADING_HEADER;
126                 return 0;
127         }
128
129         if(mh.id[14]<'1' || mh.id[14]>'4'){
130                 printf("This version is not yet supported\n");
131                 return 0;
132         }
133
134         of.modtype=strdup(ULT_Version[mh.id[14]-'1']);
135         of.initspeed=6;
136         of.inittempo=125;
137
138         /* read songtext */
139
140         if(!ReadComment((UWORD)mh.reserved*32)) return 0;
141
142         nos=_mm_read_UBYTE(modfp);
143
144         if(feof(modfp)){
145                 myerr=ERROR_LOADING_HEADER;
146                 return 0;
147         }
148
149         of.songname=DupStr(mh.songtitle,32);
150         of.numins=nos;
151
152         if(!AllocInstruments()) return 0;
153
154         d=of.instruments;
155
156         for(t=0;t<nos;t++){
157
158                 d->numsmp=1;
159                 if(!AllocSamples(d)) return 0;
160                 q=d->samples;
161
162                 /* try to read sample info */
163
164                 _mm_read_str(s.samplename,32,modfp);
165                 _mm_read_str(s.dosname,12,modfp);
166                 s.loopstart     =_mm_read_I_ULONG(modfp);
167                 s.loopend       =_mm_read_I_ULONG(modfp);
168                 s.sizestart     =_mm_read_I_ULONG(modfp);
169                 s.sizeend       =_mm_read_I_ULONG(modfp);
170                 s.volume        =_mm_read_UBYTE(modfp);
171                 s.flags         =_mm_read_UBYTE(modfp);
172                 s.finetune      =_mm_read_I_SWORD(modfp);
173
174                 if(feof(modfp)){
175                         myerr=ERROR_LOADING_SAMPLEINFO;
176                         return 0;
177                 }
178
179                 d->insname=DupStr(s.samplename,32);
180
181                 q->seekpos=0;
182
183                 q->c2spd=8363;
184
185                 if(mh.id[14]>='4'){
186                         _mm_read_I_UWORD(modfp);        /* read 1.6 extra info(??) word */
187                         q->c2spd=s.finetune;
188                 }
189
190                 q->length=s.sizeend-s.sizestart;
191                 q->volume=s.volume>>2;
192                 q->loopstart=s.loopstart;
193                 q->loopend=s.loopend;
194
195                 q->flags=SF_SIGNED;
196
197                 if(s.flags&ULTS_LOOP){
198                         q->flags|=SF_LOOP;
199                 }
200
201                 if(s.flags&ULTS_16BITS){
202                         q->flags|=SF_16BITS;
203                         q->loopstart>>=1;
204                         q->loopend>>=1;
205                 }
206
207 /*      printf("Sample %d %s length %ld\n",t,d->samplename,d->length); */
208                 d++;
209         }
210
211         _mm_read_UBYTES(of.positions,256,modfp);
212
213         for(t=0;t<256;t++){
214                 if(of.positions[t]==255) break;
215         }
216         of.numpos=t;
217
218         noc=_mm_read_UBYTE(modfp);
219         nop=_mm_read_UBYTE(modfp);
220
221         of.numchn=noc+1;
222         of.numpat=nop+1;
223         of.numtrk=of.numchn*of.numpat;
224
225         if(!AllocTracks()) return 0;
226         if(!AllocPatterns()) return 0;
227
228         for(u=0;u<of.numchn;u++){
229                 for(t=0;t<of.numpat;t++){
230                         of.patterns[(t*of.numchn)+u]=tracks++;
231                 }
232         }
233
234         /* read pan position table for v1.5 and higher */
235
236         if(mh.id[14]>='3'){
237                 for(t=0;t<of.numchn;t++) of.panning[t]=_mm_read_UBYTE(modfp)<<4;
238         }
239
240
241         for(t=0;t<of.numtrk;t++){
242                 int rep,s,done;
243
244                 UniReset();
245                 done=0;
246
247                 while(done<64){
248
249                         rep=ReadUltEvent(&ev);
250
251                         if(feof(modfp)){
252                                 myerr=ERROR_LOADING_TRACK;
253                                 return 0;
254                         }
255
256 /*                      printf("rep %d: n %d i %d e %x d1 %d d2 %d \n",rep,ev.note,ev.sample,ev.eff,ev.dat1,ev.dat2); */
257
258
259                         for(s=0;s<rep;s++){
260                                 UBYTE eff;
261
262
263                                 if(ev.sample){
264                                         UniInstrument(ev.sample-1);
265                                 }
266
267                                 if(ev.note){
268                                         UniNote(ev.note+23);
269                                 }
270
271                                 eff=ev.eff>>4;
272
273
274                                 /*
275                                         ULT panning effect fixed by Alexander Kerkhove :
276                                 */
277
278
279                                 if(eff==0xc) UniPTEffect(eff,ev.dat2>>2);
280                                 else if(eff==0xb) UniPTEffect(8,ev.dat2*0xf);
281                                 else UniPTEffect(eff,ev.dat2);
282
283                                 eff=ev.eff&0xf;
284
285                                 if(eff==0xc) UniPTEffect(eff,ev.dat1>>2);
286                                 else if(eff==0xb) UniPTEffect(8,ev.dat1*0xf);
287                                 else UniPTEffect(eff,ev.dat1);
288
289                                 UniNewline();
290                                 done++;
291                         }
292                 }
293 /*              printf("----------------"); */
294
295                 if(!(of.tracks[t]=UniDup())) return 0;
296         }
297
298 /*      printf("%d channels %d patterns\n",of.numchn,of.numpat); */
299 /*      printf("Song %32.32s: There's %d samples\n",mh.songtitle,nos); */
300         return 1;
301 }
302
303
304
305 LOADER load_ult={
306         NULL,
307         "ULT",
308         "Portable ULT loader v0.1",
309         ULT_Init,
310         ULT_Test,
311         ULT_Load,
312         ULT_Cleanup
313 };