added an old version of mikmod for dos
[dosdemo] / libs / oldmik / src / load_mtm.c
1 /*
2
3 Name:
4 LOAD_MTM.C
5
6 Description:
7 MTM 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 /**************************************************************************
20 **************************************************************************/
21
22
23 typedef struct MTMSAMPLE{
24         char  samplename[22];
25         ULONG length;
26         ULONG reppos;
27         ULONG repend;
28         UBYTE finetune;
29         UBYTE volume;
30         UBYTE attribute;
31 } MTMSAMPLE;
32
33
34
35 typedef struct MTMHEADER{
36         UBYTE id[3];                            /* MTM file marker */
37         UBYTE version;                          /* upper major, lower nibble minor version number */
38         char  songname[20];                     /* ASCIIZ songname */
39         UWORD numtracks;                        /* number of tracks saved */
40         UBYTE lastpattern;                      /* last pattern number saved */
41         UBYTE lastorder;                        /* last order number to play (songlength-1) */
42         UWORD commentsize;                      /* length of comment field */
43         UBYTE numsamples;                       /* number of samples saved */
44         UBYTE attribute;                        /* attribute byte (unused) */
45         UBYTE beatspertrack;            /* */
46         UBYTE numchannels;                      /* number of channels used */
47         UBYTE panpos[32];                       /* voice pan positions */
48 } MTMHEADER;
49
50
51 typedef struct MTMNOTE{
52         UBYTE a,b,c;
53 } MTMNOTE;
54
55
56 /**************************************************************************
57 **************************************************************************/
58
59
60
61 static MTMHEADER *mh;
62 MTMNOTE *mtmtrk;
63 UWORD pat[32];
64
65 char MTM_Version[]="MTM";
66
67
68
69 BOOL MTM_Test(void)
70 {
71         char id[3];
72         if(!fread(id,3,1,modfp)) return 0;
73         if(!memcmp(id,"MTM",3)) return 1;
74         return 0;
75 }
76
77
78 BOOL MTM_Init(void)
79 {
80         mtmtrk=NULL;
81         mh=NULL;
82
83         if(!(mtmtrk=(MTMNOTE *)MyCalloc(64,sizeof(MTMNOTE)))) return 0;
84         if(!(mh=(MTMHEADER *)MyCalloc(1,sizeof(MTMHEADER)))) return 0;
85
86         return 1;
87 }
88
89
90 void MTM_Cleanup(void)
91 {
92         if(mtmtrk!=NULL) free(mtmtrk);
93         if(mh!=NULL) free(mh);
94 }
95
96
97
98 UBYTE *MTM_Convert(void)
99 {
100         int t;
101         UBYTE a,b,c,inst,note,eff,dat;
102
103         UniReset();
104         for(t=0;t<64;t++){
105
106                 a=mtmtrk[t].a;
107                 b=mtmtrk[t].b;
108                 c=mtmtrk[t].c;
109
110                 inst=((a&0x3)<<4)|(b>>4);
111                 note=a>>2;
112
113                 eff=b&0xf;
114                 dat=c;
115
116
117                 if(inst!=0){
118                         UniInstrument(inst-1);
119                 }
120
121                 if(note!=0){
122                         UniNote(note+24);
123                 }
124
125                 /* mtm bug bugfix: when the effect is volslide,
126                    slide-up _always_ overrides slide-dn. */
127
128                 if(eff==0xa && dat&0xf0) dat&=0xf0;
129
130                 UniPTEffect(eff,dat);
131                 UniNewline();
132         }
133         return UniDup();
134 }
135
136
137 BOOL MTM_Load(void)
138 {
139         MTMSAMPLE s;
140         INSTRUMENT *d;
141         SAMPLE *q;
142
143         int t,u;
144
145         /* try to read module header */
146
147         _mm_read_UBYTES(mh->id,3,modfp);
148         mh->version             =_mm_read_UBYTE(modfp);
149         _mm_read_str(mh->songname,20,modfp);
150         mh->numtracks   =_mm_read_I_UWORD(modfp);
151         mh->lastpattern =_mm_read_UBYTE(modfp);
152         mh->lastorder   =_mm_read_UBYTE(modfp);
153         mh->commentsize =_mm_read_I_UWORD(modfp);
154         mh->numsamples  =_mm_read_UBYTE(modfp);
155         mh->attribute   =_mm_read_UBYTE(modfp);
156         mh->beatspertrack=_mm_read_UBYTE(modfp);
157         mh->numchannels =_mm_read_UBYTE(modfp);
158         _mm_read_UBYTES(mh->panpos,32,modfp);
159
160         if(feof(modfp)){
161                 myerr=ERROR_LOADING_HEADER;
162                 return 0;
163         }
164
165         /* set module variables */
166
167         of.initspeed=6;
168         of.inittempo=125;
169         of.modtype=strdup(MTM_Version);
170         of.numchn=mh->numchannels;
171         of.numtrk=mh->numtracks+1;                              /* get number of channels */
172         of.songname=DupStr(mh->songname,20);    /* make a cstr of songname */
173         of.numpos=mh->lastorder+1;              /* copy the songlength */
174         of.numpat=mh->lastpattern+1;
175         for(t=0;t<32;t++) of.panning[t]=mh->panpos[t]<<4;
176
177         of.numins=mh->numsamples;
178         if(!AllocInstruments()) return 0;
179
180         d=of.instruments;
181
182         for(t=0;t<of.numins;t++){
183
184                 d->numsmp=1;
185                 if(!AllocSamples(d)) return 0;
186                 q=d->samples;
187
188                 /* try to read sample info */
189
190                 _mm_read_str(s.samplename,22,modfp);
191                 s.length        =_mm_read_I_ULONG(modfp);
192                 s.reppos        =_mm_read_I_ULONG(modfp);
193                 s.repend        =_mm_read_I_ULONG(modfp);
194                 s.finetune      =_mm_read_UBYTE(modfp);
195                 s.volume        =_mm_read_UBYTE(modfp);
196                 s.attribute     =_mm_read_UBYTE(modfp);
197
198                 if(feof(modfp)){
199                         myerr=ERROR_LOADING_SAMPLEINFO;
200                         return 0;
201                 }
202
203                 d->insname=DupStr(s.samplename,22);
204                 q->seekpos=0;
205                 q->c2spd=finetune[s.finetune];
206                 q->length=s.length;
207                 q->loopstart=s.reppos;
208                 q->loopend=s.repend;
209                 q->volume=s.volume;
210
211                 q->flags=0;
212
213                 if(s.repend-s.reppos>2) q->flags|=SF_LOOP;      /* <- 1.00 bugfix */
214
215                 if(s.attribute&1){
216
217                         /* If the sample is 16-bits, convert the length
218                            and replen byte-values into sample-values */
219
220                         q->flags|=SF_16BITS;
221                         q->length>>=1;
222                         q->loopstart>>=1;
223                         q->loopend>>=1;
224                 }
225
226                 d++;
227         }
228
229         _mm_read_UBYTES(of.positions,128,modfp);
230
231         if(feof(modfp)){
232                 myerr=ERROR_LOADING_HEADER;
233                 return 0;
234         }
235
236         if(!AllocTracks()) return 0;
237         if(!AllocPatterns()) return 0;
238
239         of.tracks[0]=MTM_Convert();             /* track 0 is empty */
240
241         for(t=1;t<of.numtrk;t++){
242                 int s;
243
244                 for(s=0;s<64;s++){
245                         mtmtrk[s].a=_mm_read_UBYTE(modfp);
246                         mtmtrk[s].b=_mm_read_UBYTE(modfp);
247                         mtmtrk[s].c=_mm_read_UBYTE(modfp);
248                 }
249
250                 if(feof(modfp)){
251                         myerr="Error loading track";
252                         return 0;
253                 }
254
255                 if(!(of.tracks[t]=MTM_Convert())) return 0;
256         }
257
258         for(t=0;t<of.numpat;t++){
259
260                 _mm_read_I_UWORDS(pat,32,modfp);
261
262                 for(u=0;u<of.numchn;u++){
263                         of.patterns[((long)t*of.numchn)+u]=pat[u];
264                 }
265         }
266
267         /* read comment field */
268
269         if(!ReadComment(mh->commentsize)) return 0;
270
271         return 1;
272 }
273
274
275
276 LOADER load_mtm={
277         NULL,
278         "MTM",
279         "Portable MTM loader v0.1",
280         MTM_Init,
281         MTM_Test,
282         MTM_Load,
283         MTM_Cleanup
284 };
285