Skip to content

Latest commit

 

History

History
301 lines (248 loc) · 7.48 KB

munitrk.c

File metadata and controls

301 lines (248 loc) · 7.48 KB
 
Dec 27, 1999
Dec 27, 1999
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
/* MikMod sound library
(c) 1998, 1999 Miodrag Vallat and others - see file AUTHORS for
complete list.
This library is free software; you can redistribute it and/or modify
it under the terms of the GNU Library General Public License as
published by the Free Software Foundation; either version 2 of
the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
02111-1307, USA.
Oct 21, 1999
Oct 21, 1999
19
20
*/
Dec 27, 1999
Dec 27, 1999
21
/*==============================================================================
Oct 21, 1999
Oct 21, 1999
22
Dec 27, 1999
Dec 27, 1999
23
$Id$
Oct 21, 1999
Oct 21, 1999
24
Dec 27, 1999
Dec 27, 1999
25
All routines dealing with the manipulation of UNITRK streams
Oct 21, 1999
Oct 21, 1999
26
Dec 27, 1999
Dec 27, 1999
27
==============================================================================*/
Oct 21, 1999
Oct 21, 1999
28
Dec 27, 1999
Dec 27, 1999
29
30
31
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
Oct 21, 1999
Oct 21, 1999
32
Feb 11, 2000
Feb 11, 2000
33
34
#include <string.h>
Dec 27, 1999
Dec 27, 1999
35
#include "mikmod_internals.h"
Oct 21, 1999
Oct 21, 1999
36
37
Dec 27, 1999
Dec 27, 1999
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
/* Unibuffer chunk size */
#define BUFPAGE 128
UWORD unioperands[UNI_LAST]={
0, /* not used */
1, /* UNI_NOTE */
1, /* UNI_INSTRUMENT */
1, /* UNI_PTEFFECT0 */
1, /* UNI_PTEFFECT1 */
1, /* UNI_PTEFFECT2 */
1, /* UNI_PTEFFECT3 */
1, /* UNI_PTEFFECT4 */
1, /* UNI_PTEFFECT5 */
1, /* UNI_PTEFFECT6 */
1, /* UNI_PTEFFECT7 */
1, /* UNI_PTEFFECT8 */
1, /* UNI_PTEFFECT9 */
1, /* UNI_PTEFFECTA */
1, /* UNI_PTEFFECTB */
1, /* UNI_PTEFFECTC */
1, /* UNI_PTEFFECTD */
1, /* UNI_PTEFFECTE */
1, /* UNI_PTEFFECTF */
1, /* UNI_S3MEFFECTA */
1, /* UNI_S3MEFFECTD */
1, /* UNI_S3MEFFECTE */
1, /* UNI_S3MEFFECTF */
1, /* UNI_S3MEFFECTI */
1, /* UNI_S3MEFFECTQ */
1, /* UNI_S3MEFFECTR */
1, /* UNI_S3MEFFECTT */
1, /* UNI_S3MEFFECTU */
0, /* UNI_KEYOFF */
1, /* UNI_KEYFADE */
2, /* UNI_VOLEFFECTS */
1, /* UNI_XMEFFECT4 */
1, /* UNI_XMEFFECTA */
1, /* UNI_XMEFFECTE1 */
1, /* UNI_XMEFFECTE2 */
1, /* UNI_XMEFFECTEA */
1, /* UNI_XMEFFECTEB */
1, /* UNI_XMEFFECTG */
1, /* UNI_XMEFFECTH */
1, /* UNI_XMEFFECTL */
1, /* UNI_XMEFFECTP */
1, /* UNI_XMEFFECTX1 */
1, /* UNI_XMEFFECTX2 */
1, /* UNI_ITEFFECTG */
1, /* UNI_ITEFFECTH */
1, /* UNI_ITEFFECTI */
1, /* UNI_ITEFFECTM */
1, /* UNI_ITEFFECTN */
1, /* UNI_ITEFFECTP */
1, /* UNI_ITEFFECTT */
1, /* UNI_ITEFFECTU */
1, /* UNI_ITEFFECTW */
1, /* UNI_ITEFFECTY */
2, /* UNI_ITEFFECTZ */
1, /* UNI_ITEFFECTS0 */
2, /* UNI_ULTEFFECT9 */
2, /* UNI_MEDSPEED */
0, /* UNI_MEDEFFECTF1 */
0, /* UNI_MEDEFFECTF2 */
Dec 19, 2001
Dec 19, 2001
101
102
0, /* UNI_MEDEFFECTF3 */
1 /* UNI_XMEFFECTZ */
Dec 27, 1999
Dec 27, 1999
103
};
Oct 21, 1999
Oct 21, 1999
104
Dec 27, 1999
Dec 27, 1999
105
106
/* Sparse description of the internal module format
------------------------------------------------
Oct 21, 1999
Oct 21, 1999
107
Dec 27, 1999
Dec 27, 1999
108
109
110
A UNITRK stream is an array of bytes representing a single track of a pattern.
It's made up of 'repeat/length' bytes, opcodes and operands (sort of a assembly
language):
Oct 21, 1999
Oct 21, 1999
111
Dec 27, 1999
Dec 27, 1999
112
113
114
115
rrrlllll
[REP/LEN][OPCODE][OPERAND][OPCODE][OPERAND] [REP/LEN][OPCODE][OPERAND]..
^ ^ ^
|-------ROWS 0 - 0+REP of a track---------| |-------ROWS xx - xx+REP of a track...
Oct 21, 1999
Oct 21, 1999
116
Dec 27, 1999
Dec 27, 1999
117
118
119
120
The rep/len byte contains the number of bytes in the current row, _including_
the length byte itself (So the LENGTH byte of row 0 in the previous example
would have a value of 5). This makes it easy to search through a stream for a
particular row. A track is concluded by a 0-value length byte.
Oct 21, 1999
Oct 21, 1999
121
Dec 27, 1999
Dec 27, 1999
122
123
The upper 3 bits of the rep/len byte contain the number of times -1 this row
is repeated for this track. (so a value of 7 means this row is repeated 8 times)
Oct 21, 1999
Oct 21, 1999
124
Dec 27, 1999
Dec 27, 1999
125
126
127
128
Opcodes can range from 1 to 255 but currently only opcodes 1 to 52 are being
used. Each opcode can have a different number of operands. You can find the
number of operands to a particular opcode by using the opcode as an index into
the 'unioperands' table.
Oct 21, 1999
Oct 21, 1999
129
Dec 27, 1999
Dec 27, 1999
130
*/
Oct 21, 1999
Oct 21, 1999
131
Dec 27, 1999
Dec 27, 1999
132
/*========== Reading routines */
Oct 21, 1999
Oct 21, 1999
133
Dec 27, 1999
Dec 27, 1999
134
135
136
static UBYTE *rowstart; /* startadress of a row */
static UBYTE *rowend; /* endaddress of a row (exclusive) */
static UBYTE *rowpc; /* current unimod(tm) programcounter */
Oct 21, 1999
Oct 21, 1999
137
138
Dec 27, 1999
Dec 27, 1999
139
void UniSetRow(UBYTE* t)
Oct 21, 1999
Oct 21, 1999
140
{
Dec 27, 1999
Dec 27, 1999
141
142
143
rowstart = t;
rowpc = rowstart;
rowend = t?rowstart+(*(rowpc++)&0x1f):t;
Oct 21, 1999
Oct 21, 1999
144
145
146
147
}
UBYTE UniGetByte(void)
{
Dec 27, 1999
Dec 27, 1999
148
return (rowpc<rowend)?*(rowpc++):0;
Oct 21, 1999
Oct 21, 1999
149
150
}
Dec 27, 1999
Dec 27, 1999
151
152
153
154
UWORD UniGetWord(void)
{
return ((UWORD)UniGetByte()<<8)|UniGetByte();
}
Oct 21, 1999
Oct 21, 1999
155
156
157
void UniSkipOpcode(UBYTE op)
{
Dec 27, 1999
Dec 27, 1999
158
159
if(op<UNI_LAST) {
UWORD t=unioperands[op];
Oct 21, 1999
Oct 21, 1999
160
Dec 27, 1999
Dec 27, 1999
161
162
163
while(t--) UniGetByte();
}
}
Oct 21, 1999
Oct 21, 1999
164
Dec 27, 1999
Dec 27, 1999
165
166
167
/* Finds the address of row number 'row' in the UniMod(tm) stream 't' returns
NULL if the row can't be found. */
UBYTE *UniFindRow(UBYTE* t,UWORD row)
Oct 21, 1999
Oct 21, 1999
168
{
Dec 27, 1999
Dec 27, 1999
169
170
171
172
173
174
175
176
177
178
179
180
UBYTE c,l;
if(t)
while(1) {
c = *t; /* get rep/len byte */
if(!c) return NULL; /* zero ? -> end of track.. */
l = (c>>5)+1; /* extract repeat value */
if(l>row) break; /* reached wanted row? -> return pointer */
row -= l; /* haven't reached row yet.. update row */
t += c&0x1f; /* point t to the next row */
}
return t;
Oct 21, 1999
Oct 21, 1999
181
182
}
Dec 27, 1999
Dec 27, 1999
183
/*========== Writing routines */
Oct 21, 1999
Oct 21, 1999
184
Dec 27, 1999
Dec 27, 1999
185
186
static UBYTE *unibuf; /* pointer to the temporary unitrk buffer */
static UWORD unimax; /* buffer size */
Oct 21, 1999
Oct 21, 1999
187
Dec 27, 1999
Dec 27, 1999
188
189
190
static UWORD unipc; /* buffer cursor */
static UWORD unitt; /* current row index */
static UWORD lastp; /* previous row index */
Oct 21, 1999
Oct 21, 1999
191
192
/* Resets index-pointers to create a new track. */
Dec 27, 1999
Dec 27, 1999
193
void UniReset(void)
Oct 21, 1999
Oct 21, 1999
194
{
Dec 27, 1999
Dec 27, 1999
195
196
197
198
unitt = 0; /* reset index to rep/len byte */
unipc = 1; /* first opcode will be written to index 1 */
lastp = 0; /* no previous row yet */
unibuf[0] = 0; /* clear rep/len byte */
Oct 21, 1999
Oct 21, 1999
199
200
}
Dec 27, 1999
Dec 27, 1999
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
/* Expands the buffer */
static BOOL UniExpand(int wanted)
{
if ((unipc+wanted)>=unimax) {
UBYTE *newbuf;
/* Expand the buffer by BUFPAGE bytes */
newbuf=(UBYTE*)realloc(unibuf,(unimax+BUFPAGE)*sizeof(UBYTE));
/* Check if realloc succeeded */
if(newbuf) {
unibuf = newbuf;
unimax+=BUFPAGE;
return 1;
} else
return 0;
}
return 1;
}
Oct 21, 1999
Oct 21, 1999
220
221
/* Appends one byte of data to the current row of a track. */
Dec 27, 1999
Dec 27, 1999
222
void UniWriteByte(UBYTE data)
Oct 21, 1999
Oct 21, 1999
223
{
Dec 27, 1999
Dec 27, 1999
224
225
226
if (UniExpand(1))
/* write byte to current position and update */
unibuf[unipc++]=data;
Oct 21, 1999
Oct 21, 1999
227
228
}
Dec 27, 1999
Dec 27, 1999
229
void UniWriteWord(UWORD data)
Oct 21, 1999
Oct 21, 1999
230
{
Dec 27, 1999
Dec 27, 1999
231
232
233
234
if (UniExpand(2)) {
unibuf[unipc++]=data>>8;
unibuf[unipc++]=data&0xff;
}
Oct 21, 1999
Oct 21, 1999
235
236
}
Dec 27, 1999
Dec 27, 1999
237
static BOOL MyCmp(UBYTE* a,UBYTE* b,UWORD l)
Oct 21, 1999
Oct 21, 1999
238
{
Dec 27, 1999
Dec 27, 1999
239
UWORD t;
Oct 21, 1999
Oct 21, 1999
240
Dec 27, 1999
Dec 27, 1999
241
242
243
for(t=0;t<l;t++)
if(*(a++)!=*(b++)) return 0;
return 1;
Oct 21, 1999
Oct 21, 1999
244
245
}
Dec 27, 1999
Dec 27, 1999
246
247
248
/* Closes the current row of a unitrk stream (updates the rep/len byte) and sets
pointers to start a new row. */
void UniNewline(void)
Oct 21, 1999
Oct 21, 1999
249
{
Dec 27, 1999
Dec 27, 1999
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
UWORD n,l,len;
n = (unibuf[lastp]>>5)+1; /* repeat of previous row */
l = (unibuf[lastp]&0x1f); /* length of previous row */
len = unipc-unitt; /* length of current row */
/* Now, check if the previous and the current row are identical.. when they
are, just increase the repeat field of the previous row */
if(n<8 && len==l && MyCmp(&unibuf[lastp+1],&unibuf[unitt+1],len-1)) {
unibuf[lastp]+=0x20;
unipc = unitt+1;
} else {
if (UniExpand(unitt-unipc)) {
/* current and previous row aren't equal... update the pointers */
unibuf[unitt] = len;
lastp = unitt;
unitt = unipc++;
}
}
Oct 21, 1999
Oct 21, 1999
270
271
}
Dec 27, 1999
Dec 27, 1999
272
273
274
/* Terminates the current unitrk stream and returns a pointer to a copy of the
stream. */
UBYTE* UniDup(void)
Oct 21, 1999
Oct 21, 1999
275
{
Dec 27, 1999
Dec 27, 1999
276
UBYTE *d;
Oct 21, 1999
Oct 21, 1999
277
Dec 27, 1999
Dec 27, 1999
278
279
if (!UniExpand(unitt-unipc)) return NULL;
unibuf[unitt] = 0;
Oct 21, 1999
Oct 21, 1999
280
Dec 27, 1999
Dec 27, 1999
281
282
if(!(d=(UBYTE *)_mm_malloc(unipc))) return NULL;
memcpy(d,unibuf,unipc);
Oct 21, 1999
Oct 21, 1999
283
Dec 27, 1999
Dec 27, 1999
284
285
return d;
}
Oct 21, 1999
Oct 21, 1999
286
287
288
BOOL UniInit(void)
{
Dec 27, 1999
Dec 27, 1999
289
unimax = BUFPAGE;
Oct 21, 1999
Oct 21, 1999
290
Dec 27, 1999
Dec 27, 1999
291
292
if(!(unibuf=(UBYTE*)_mm_malloc(unimax*sizeof(UBYTE)))) return 0;
return 1;
Oct 21, 1999
Oct 21, 1999
293
294
295
296
}
void UniCleanup(void)
{
Dec 27, 1999
Dec 27, 1999
297
298
if(unibuf) free(unibuf);
unibuf = NULL;
Oct 21, 1999
Oct 21, 1999
299
300
}
Dec 27, 1999
Dec 27, 1999
301
/* ex:set ts=4: */