/
mmio.c
360 lines (291 loc) · 8.77 KB
1
2
3
/* MikMod sound library
(c) 1998, 1999 Miodrag Vallat and others - see file AUTHORS for
complete list.
4
5
6
7
8
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.
9
10
11
12
13
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.
14
15
16
17
18
19
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.
*/
20
21
/*==============================================================================
22
23
$Id$
24
25
Portable file I/O routines
26
27
==============================================================================*/
28
29
/*
30
31
The way this module works:
32
33
34
35
36
37
38
39
40
41
42
- _mm_fopen will call the errorhandler [see mmerror.c] in addition to
setting _mm_errno on exit.
- _mm_iobase is for internal use. It is used by Player_LoadFP to
ensure that it works properly with wad files.
- _mm_read_I_* and _mm_read_M_* differ : the first is for reading data
written by a little endian (intel) machine, and the second is for reading
big endian (Mac, RISC, Alpha) machine data.
- _mm_write functions work the same as the _mm_read functions.
- _mm_read_string is for reading binary strings. It is basically the same
as an fread of bytes.
43
44
*/
45
46
47
48
49
/* FIXME
the _mm_iobase variable ought to be MREADER-specific. It will eventually
become a private field of the MREADER structure, but this will require a
soname version bump.
50
51
52
53
In the meantime, the drawback is that if you use the xxx_LoadFP functions,
you can't have several MREADER objects with different iobase values.
*/
54
55
56
57
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
58
59
60
#include <stdio.h>
#include <string.h>
61
62
#include "mikmod_internals.h"
63
64
#define COPY_BUFSIZE 1024
65
66
static long _mm_iobase=0,temp_iobase=0;
67
68
FILE* _mm_fopen(CHAR* fname,CHAR* attrib)
69
{
70
FILE *fp;
71
72
73
74
75
76
if(!(fp=fopen(fname,attrib))) {
_mm_errno = MMERR_OPENING_FILE;
if(_mm_errorhandler) _mm_errorhandler();
}
return fp;
77
78
}
79
BOOL _mm_FileExists(CHAR* fname)
80
{
81
FILE *fp;
82
83
84
if(!(fp=fopen(fname,"r"))) return 0;
fclose(fp);
85
86
return 1;
87
88
}
89
90
/* Sets the current file-position as the new _mm_iobase */
void _mm_iobase_setcur(MREADER* reader)
91
{
92
93
temp_iobase=_mm_iobase; /* store old value in case of revert */
_mm_iobase=reader->Tell(reader);
94
95
}
96
97
/* Reverts to the last known _mm_iobase value. */
void _mm_iobase_revert(void)
98
{
99
_mm_iobase=temp_iobase;
100
101
}
102
/*========== File Reader */
103
104
105
106
107
typedef struct MFILEREADER {
MREADER core;
FILE* file;
} MFILEREADER;
108
109
static BOOL _mm_FileReader_Eof(MREADER* reader)
110
{
111
return feof(((MFILEREADER*)reader)->file);
112
113
}
114
static BOOL _mm_FileReader_Read(MREADER* reader,void* ptr,size_t size)
115
{
116
return fread(ptr,size,1,((MFILEREADER*)reader)->file);
117
118
}
119
static int _mm_FileReader_Get(MREADER* reader)
120
{
121
return fgetc(((MFILEREADER*)reader)->file);
122
123
}
124
static BOOL _mm_FileReader_Seek(MREADER* reader,long offset,int whence)
125
{
126
127
return fseek(((MFILEREADER*)reader)->file,
(whence==SEEK_SET)?offset+_mm_iobase:offset,whence);
128
129
}
130
static long _mm_FileReader_Tell(MREADER* reader)
131
{
132
return ftell(((MFILEREADER*)reader)->file)-_mm_iobase;
133
134
}
135
MREADER *_mm_new_file_reader(FILE* fp)
136
{
137
138
139
140
141
142
143
144
145
146
MFILEREADER* reader=(MFILEREADER*)_mm_malloc(sizeof(MFILEREADER));
if (reader) {
reader->core.Eof =&_mm_FileReader_Eof;
reader->core.Read=&_mm_FileReader_Read;
reader->core.Get =&_mm_FileReader_Get;
reader->core.Seek=&_mm_FileReader_Seek;
reader->core.Tell=&_mm_FileReader_Tell;
reader->file=fp;
}
return (MREADER*)reader;
147
148
}
149
void _mm_delete_file_reader (MREADER* reader)
150
{
151
if(reader) free(reader);
152
153
}
154
/*========== File Writer */
155
156
157
158
159
typedef struct MFILEWRITER {
MWRITER core;
FILE* file;
} MFILEWRITER;
160
161
static BOOL _mm_FileWriter_Seek(MWRITER* writer,long offset,int whence)
162
{
163
return fseek(((MFILEWRITER*)writer)->file,offset,whence);
164
165
}
166
static long _mm_FileWriter_Tell(MWRITER* writer)
167
{
168
return ftell(((MFILEWRITER*)writer)->file);
169
170
}
171
static BOOL _mm_FileWriter_Write(MWRITER* writer,void* ptr,size_t size)
172
{
173
return (fwrite(ptr,size,1,((MFILEWRITER*)writer)->file)==size);
174
175
}
176
static BOOL _mm_FileWriter_Put(MWRITER* writer,int value)
177
{
178
return fputc(value,((MFILEWRITER*)writer)->file);
179
180
}
181
MWRITER *_mm_new_file_writer(FILE* fp)
182
{
183
184
185
186
187
188
189
190
191
MFILEWRITER* writer=(MFILEWRITER*)_mm_malloc(sizeof(MFILEWRITER));
if (writer) {
writer->core.Seek =&_mm_FileWriter_Seek;
writer->core.Tell =&_mm_FileWriter_Tell;
writer->core.Write=&_mm_FileWriter_Write;
writer->core.Put =&_mm_FileWriter_Put;
writer->file=fp;
}
return (MWRITER*) writer;
192
193
}
194
void _mm_delete_file_writer (MWRITER* writer)
195
{
196
if(writer) free (writer);
197
198
}
199
/*========== Write functions */
200
201
void _mm_write_string(CHAR* data,MWRITER* writer)
202
{
203
204
if(data)
_mm_write_UBYTES(data,strlen(data),writer);
205
206
}
207
void _mm_write_M_UWORD(UWORD data,MWRITER* writer)
208
{
209
210
_mm_write_UBYTE(data>>8,writer);
_mm_write_UBYTE(data&0xff,writer);
211
212
}
213
void _mm_write_I_UWORD(UWORD data,MWRITER* writer)
214
{
215
216
_mm_write_UBYTE(data&0xff,writer);
_mm_write_UBYTE(data>>8,writer);
217
218
}
219
void _mm_write_M_ULONG(ULONG data,MWRITER* writer)
220
{
221
222
_mm_write_M_UWORD(data>>16,writer);
_mm_write_M_UWORD(data&0xffff,writer);
223
224
}
225
void _mm_write_I_ULONG(ULONG data,MWRITER* writer)
226
{
227
228
_mm_write_I_UWORD(data&0xffff,writer);
_mm_write_I_UWORD(data>>16,writer);
229
230
}
231
void _mm_write_M_SWORD(SWORD data,MWRITER* writer)
232
{
233
_mm_write_M_UWORD((UWORD)data,writer);
234
235
}
236
void _mm_write_I_SWORD(SWORD data,MWRITER* writer)
237
{
238
_mm_write_I_UWORD((UWORD)data,writer);
239
240
}
241
void _mm_write_M_SLONG(SLONG data,MWRITER* writer)
242
{
243
_mm_write_M_ULONG((ULONG)data,writer);
244
245
}
246
void _mm_write_I_SLONG(SLONG data,MWRITER* writer)
247
{
248
_mm_write_I_ULONG((ULONG)data,writer);
249
250
}
251
252
253
254
255
256
#ifdef __STDC__
#define DEFINE_MULTIPLE_WRITE_FUNCTION(type_name,type) \
void _mm_write_##type_name##S (type *buffer,int number,MWRITER* writer) \
{ \
while(number-->0) \
_mm_write_##type_name(*(buffer++),writer); \
257
}
258
259
260
261
262
263
#else
#define DEFINE_MULTIPLE_WRITE_FUNCTION(type_name,type) \
void _mm_write_/**/type_name/**/S (type *buffer,int number,MWRITER* writer) \
{ \
while(number-->0) \
_mm_write_/**/type_name(*(buffer++),writer); \
264
}
265
#endif
266
267
268
269
270
DEFINE_MULTIPLE_WRITE_FUNCTION(M_SWORD,SWORD)
DEFINE_MULTIPLE_WRITE_FUNCTION(M_UWORD,UWORD)
DEFINE_MULTIPLE_WRITE_FUNCTION(I_SWORD,SWORD)
DEFINE_MULTIPLE_WRITE_FUNCTION(I_UWORD,UWORD)
271
272
273
274
275
276
277
DEFINE_MULTIPLE_WRITE_FUNCTION(M_SLONG,SLONG)
DEFINE_MULTIPLE_WRITE_FUNCTION(M_ULONG,ULONG)
DEFINE_MULTIPLE_WRITE_FUNCTION(I_SLONG,SLONG)
DEFINE_MULTIPLE_WRITE_FUNCTION(I_ULONG,ULONG)
/*========== Read functions */
278
279
int _mm_read_string(CHAR* buffer,int number,MREADER* reader)
280
{
281
return reader->Read(reader,buffer,number);
282
283
}
284
UWORD _mm_read_M_UWORD(MREADER* reader)
285
{
286
287
288
UWORD result=((UWORD)_mm_read_UBYTE(reader))<<8;
result|=_mm_read_UBYTE(reader);
return result;
289
290
}
291
UWORD _mm_read_I_UWORD(MREADER* reader)
292
{
293
294
295
UWORD result=_mm_read_UBYTE(reader);
result|=((UWORD)_mm_read_UBYTE(reader))<<8;
return result;
296
297
}
298
ULONG _mm_read_M_ULONG(MREADER* reader)
299
{
300
301
302
ULONG result=((ULONG)_mm_read_M_UWORD(reader))<<16;
result|=_mm_read_M_UWORD(reader);
return result;
303
304
}
305
ULONG _mm_read_I_ULONG(MREADER* reader)
306
{
307
308
309
ULONG result=_mm_read_I_UWORD(reader);
result|=((ULONG)_mm_read_I_UWORD(reader))<<16;
return result;
310
311
}
312
SWORD _mm_read_M_SWORD(MREADER* reader)
313
{
314
return((SWORD)_mm_read_M_UWORD(reader));
315
316
}
317
SWORD _mm_read_I_SWORD(MREADER* reader)
318
{
319
return((SWORD)_mm_read_I_UWORD(reader));
320
321
}
322
SLONG _mm_read_M_SLONG(MREADER* reader)
323
{
324
return((SLONG)_mm_read_M_ULONG(reader));
325
326
}
327
SLONG _mm_read_I_SLONG(MREADER* reader)
328
{
329
return((SLONG)_mm_read_I_ULONG(reader));
330
331
}
332
333
334
335
336
337
338
#ifdef __STDC__
#define DEFINE_MULTIPLE_READ_FUNCTION(type_name,type) \
int _mm_read_##type_name##S (type *buffer,int number,MREADER* reader) \
{ \
while(number-->0) \
*(buffer++)=_mm_read_##type_name(reader); \
return !reader->Eof(reader); \
339
}
340
341
342
343
344
345
346
347
348
#else
#define DEFINE_MULTIPLE_READ_FUNCTION(type_name,type) \
int _mm_read_/**/type_name/**/S (type *buffer,int number,MREADER* reader) \
{ \
while(number-->0) \
*(buffer++)=_mm_read_/**/type_name(reader); \
return !reader->Eof(reader); \
}
#endif
349
350
351
352
353
DEFINE_MULTIPLE_READ_FUNCTION(M_SWORD,SWORD)
DEFINE_MULTIPLE_READ_FUNCTION(M_UWORD,UWORD)
DEFINE_MULTIPLE_READ_FUNCTION(I_SWORD,SWORD)
DEFINE_MULTIPLE_READ_FUNCTION(I_UWORD,UWORD)
354
355
356
357
358
DEFINE_MULTIPLE_READ_FUNCTION(M_SLONG,SLONG)
DEFINE_MULTIPLE_READ_FUNCTION(M_ULONG,ULONG)
DEFINE_MULTIPLE_READ_FUNCTION(I_SLONG,SLONG)
DEFINE_MULTIPLE_READ_FUNCTION(I_ULONG,ULONG)
359
360
/* ex:set ts=4: */