comparison playercode/load_dsm.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_DSM.C
4
5 Description:
6 DSIK Internal Format (DSM) 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 DSMNOTE
21 { UBYTE note,ins,vol,cmd,inf;
22 } DSMNOTE;
23
24
25 typedef struct DSMINST
26 { CHAR filename[13];
27 UWORD flags;
28 UBYTE volume;
29 ULONG length;
30 ULONG loopstart;
31 ULONG loopend;
32 ULONG reserved1;
33 UWORD c2spd;
34 UWORD reserved2;
35 CHAR samplename[28];
36 } DSMINST;
37
38
39 typedef struct DSMSONG
40 { CHAR songname[28];
41 UWORD reserved1;
42 UWORD flags;
43 ULONG reserved2;
44 UWORD numord;
45 UWORD numsmp;
46 UWORD numpat;
47 UWORD numtrk;
48 UBYTE globalvol;
49 UBYTE mastervol;
50 UBYTE speed;
51 UBYTE bpm;
52 UBYTE panpos[16];
53 UBYTE orders[128];
54 } DSMSONG;
55
56
57
58 static CHAR *SONGID = "SONG";
59 static CHAR *INSTID = "INST";
60 static CHAR *PATTID = "PATT";
61
62
63 static UBYTE blockid[4];
64 static ULONG blockln;
65 static ULONG blocklp;
66 static DSMSONG *mh = NULL;
67 static DSMNOTE *dsmbuf = NULL;
68
69 static CHAR DSM_Version[] = "DSIK DSM-format";
70
71
72 BOOL DSM_Test(void)
73 {
74 UBYTE id[12];
75
76 if(_mm_read_UBYTES((UBYTE *)id,12,modfp)) return 0;
77 if(!memcmp(id,"RIFF",4) && !memcmp(&id[8],"DSMF",4)) return 1;
78
79 return 0;
80 }
81
82
83 BOOL DSM_Init(void)
84 {
85 if(!(dsmbuf=(DSMNOTE *)_mm_malloc(16*64*sizeof(DSMNOTE)))) return 0;
86 if(!(mh=(DSMSONG *)_mm_calloc(1,sizeof(DSMSONG)))) return 0;
87 return 1;
88 }
89
90
91 void DSM_Cleanup(void)
92 {
93 if(dsmbuf!=NULL) free(dsmbuf);
94 if(mh!=NULL) free(mh);
95
96 dsmbuf = NULL;
97 mh = NULL;
98 }
99
100
101 BOOL GetBlockHeader(void)
102 {
103 // make sure we're at the right position for reading the
104 // next riff block, no matter how many bytes read
105
106 _mm_fseek(modfp, blocklp+blockln, SEEK_SET);
107
108 while(1)
109 { _mm_read_UBYTES(blockid,4,modfp);
110 blockln = _mm_read_I_ULONG(modfp);
111 if(feof(modfp))
112 { _mm_errno = MMERR_LOADING_HEADER;
113 return 0;
114 }
115
116 if(memcmp(blockid,SONGID,4) && memcmp(blockid,INSTID,4) && memcmp(blockid,PATTID,4))
117 { //printf("Skipping unknown block type %4.4s\n",&blockid);
118 _mm_fseek(modfp, blockln, SEEK_CUR);
119 } else break;
120 }
121
122 blocklp = _mm_ftell(modfp);
123 return 1;
124 }
125
126
127 BOOL DSM_ReadPattern(void)
128 {
129 int row=0,flag;
130 DSMNOTE *n;
131
132 // clear pattern data
133 memset(dsmbuf,255,16*64*sizeof(DSMNOTE));
134 _mm_read_UBYTE(modfp);
135 _mm_read_UBYTE(modfp);
136
137 while(row<64)
138 { flag = _mm_read_UBYTE(modfp);
139 if(feof(modfp))
140 { _mm_errno = MMERR_LOADING_PATTERN;
141 return 0;
142 }
143
144 if(flag)
145 { n = &dsmbuf[((flag&0xf)*64)+row];
146 if(flag&0x80) n->note = _mm_read_UBYTE(modfp);
147 if(flag&0x40) n->ins = _mm_read_UBYTE(modfp);
148 if(flag&0x20) n->vol = _mm_read_UBYTE(modfp);
149 if(flag&0x10)
150 { n->cmd = _mm_read_UBYTE(modfp);
151 n->inf = _mm_read_UBYTE(modfp);
152 }
153 } else row++;
154 }
155 return 1;
156 }
157
158
159 UBYTE *DSM_ConvertTrack(DSMNOTE *tr)
160 {
161 int t;
162 UBYTE note,ins,vol,cmd,inf;
163
164 UniReset();
165 for(t=0; t<64; t++)
166 { note = tr[t].note;
167 ins = tr[t].ins;
168 vol = tr[t].vol;
169 cmd = tr[t].cmd;
170 inf = tr[t].inf;
171
172 if(ins!=0 && ins!=255) UniInstrument(ins-1);
173 if(note!=255) UniNote(note-1); // <- normal note
174 if(vol<65) UniPTEffect(0xc,vol);
175
176 if(cmd!=255)
177 { if(cmd==0x8)
178 { if(inf<=0x80)
179 { inf = (inf<0x80) ? inf<<1 : 255;
180 UniPTEffect(cmd,inf);
181 }
182 } else if(cmd==0xb)
183 { if(inf<=0x7f) UniPTEffect(cmd,inf);
184 } else
185 { // Convert pattern jump from Dec to Hex
186 if(cmd == 0xd)
187 inf = (((inf&0xf0)>>4)*10)+(inf&0xf);
188 UniPTEffect(cmd,inf);
189 }
190 }
191 UniNewline();
192 }
193 return UniDup();
194 }
195
196
197 BOOL DSM_Load(void)
198 {
199 int t;
200 DSMINST s;
201 SAMPLE *q;
202 int cursmp = 0, curpat = 0, track = 0;
203
204 blocklp = 0;
205 blockln = 12;
206
207 if(!GetBlockHeader()) return 0;
208 if(memcmp(blockid,SONGID,4))
209 { _mm_errno = MMERR_LOADING_HEADER;
210 return 0;
211 }
212
213 _mm_read_UBYTES(mh->songname,28,modfp);
214 mh->reserved1 = _mm_read_I_UWORD(modfp);
215 mh->flags = _mm_read_I_UWORD(modfp);
216 mh->reserved2 = _mm_read_I_ULONG(modfp);
217 mh->numord = _mm_read_I_UWORD(modfp);
218 mh->numsmp = _mm_read_I_UWORD(modfp);
219 mh->numpat = _mm_read_I_UWORD(modfp);
220 mh->numtrk = _mm_read_I_UWORD(modfp);
221 mh->globalvol = _mm_read_UBYTE(modfp);
222 mh->mastervol = _mm_read_UBYTE(modfp);
223 mh->speed = _mm_read_UBYTE(modfp);
224 mh->bpm = _mm_read_UBYTE(modfp);
225 _mm_read_UBYTES(mh->panpos,16,modfp);
226 _mm_read_UBYTES(mh->orders,128,modfp);
227
228 // set module variables
229 of.initspeed = mh->speed;
230 of.inittempo = mh->bpm;
231 of.modtype = strdup(DSM_Version);
232 of.numchn = mh->numtrk;
233 of.numpat = mh->numpat;
234 of.numtrk = of.numchn*of.numpat;
235 of.songname = DupStr(mh->songname,28); // make a cstr of songname
236
237 for(t=0; t<16; t++)
238 of.panning[t] = mh->panpos[t]<0x80 ? (mh->panpos[t]<<1) : 255;
239
240 if(!AllocPositions(mh->numord)) return 0;
241 of.numpos = 0;
242 for(t=0; t<mh->numord; t++)
243 { of.positions[of.numpos] = mh->orders[t];
244 if(mh->orders[t]<254) of.numpos++;
245 }
246
247 of.numins = of.numsmp = mh->numsmp;
248
249 if(!AllocSamples()) return 0;
250 if(!AllocTracks()) return 0;
251 if(!AllocPatterns()) return 0;
252
253 while(cursmp<of.numins || curpat<of.numpat)
254 { if(!GetBlockHeader()) return 0;
255 if(!memcmp(blockid,INSTID,4) && cursmp<of.numins)
256 { q = &of.samples[cursmp];
257
258 // try to read sample info
259 _mm_read_UBYTES(s.filename,13,modfp);
260 s.flags = _mm_read_I_UWORD(modfp);
261 s.volume = _mm_read_UBYTE(modfp);
262 s.length = _mm_read_I_ULONG(modfp);
263 s.loopstart = _mm_read_I_ULONG(modfp);
264 s.loopend = _mm_read_I_ULONG(modfp);
265 s.reserved1 = _mm_read_I_ULONG(modfp);
266 s.c2spd = _mm_read_I_UWORD(modfp);
267 s.reserved2 = _mm_read_I_UWORD(modfp);
268 _mm_read_UBYTES(s.samplename,28,modfp);
269
270 q->samplename= DupStr(s.samplename,28);
271 q->seekpos = _mm_ftell(modfp);
272 q->speed = s.c2spd;
273 q->length = s.length;
274 q->loopstart = s.loopstart;
275 q->loopend = s.loopend;
276 q->volume = s.volume;
277
278 if(s.flags&1) q->flags|=SF_LOOP;
279 if(s.flags&2) q->flags|=SF_SIGNED;
280 cursmp++;
281 } else if(!memcmp(blockid,PATTID,4) && curpat<of.numpat)
282 { DSM_ReadPattern();
283 for(t=0; t<of.numchn; t++)
284 if(!(of.tracks[track++] = DSM_ConvertTrack(&dsmbuf[t*64]))) return 0;
285 curpat++;
286 }
287 }
288
289 return 1;
290 }
291
292
293 CHAR *DSM_LoadTitle(void)
294 {
295 CHAR s[28];
296
297 _mm_fseek(modfp,12,SEEK_SET);
298 if(!fread(s,28,1,modfp)) return NULL;
299
300 return(DupStr(s,28));
301 }
302
303
304 MLOADER load_dsm =
305 { NULL,
306 "DSM",
307 "Portable DSM loader v0.1",
308 DSM_Init,
309 DSM_Test,
310 DSM_Load,
311 DSM_Cleanup,
312 DSM_LoadTitle
313 };
314