1 /* MikMod sound library
\r
2 (c) 1998, 1999, 2000 Miodrag Vallat and others - see file AUTHORS for
\r
5 This library is free software; you can redistribute it and/or modify
\r
6 it under the terms of the GNU Library General Public License as
\r
7 published by the Free Software Foundation; either version 2 of
\r
8 the License, or (at your option) any later version.
\r
10 This program is distributed in the hope that it will be useful,
\r
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
\r
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
\r
13 GNU Library General Public License for more details.
\r
15 You should have received a copy of the GNU Library General Public
\r
16 License along with this library; if not, write to the Free Software
\r
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
\r
21 /*==============================================================================
\r
23 $Id: mmio.c,v 1.2 2004/02/06 19:29:05 raph Exp $
\r
25 Portable file I/O routines
\r
27 ==============================================================================*/
\r
31 The way this module works:
\r
33 - _mm_fopen will call the errorhandler [see mmerror.c] in addition to
\r
34 setting _mm_errno on exit.
\r
35 - _mm_iobase is for internal use. It is used by Player_LoadFP to
\r
36 ensure that it works properly with wad files.
\r
37 - _mm_read_I_* and _mm_read_M_* differ : the first is for reading data
\r
38 written by a little endian (intel) machine, and the second is for reading
\r
39 big endian (Mac, RISC, Alpha) machine data.
\r
40 - _mm_write functions work the same as the _mm_read functions.
\r
41 - _mm_read_string is for reading binary strings. It is basically the same
\r
42 as an fread of bytes.
\r
47 the _mm_iobase variable ought to be MREADER-specific. It will eventually
\r
48 become a private field of the MREADER structure, but this will require a
\r
49 soname version bump.
\r
51 In the meantime, the drawback is that if you use the xxx_LoadFP functions,
\r
52 you can't have several MREADER objects with different iobase values.
\r
55 #ifdef HAVE_CONFIG_H
\r
59 #ifdef HAVE_UNISTD_H
\r
66 #include "mikmod_internals.h"
\r
68 #define COPY_BUFSIZE 1024
\r
70 static long _mm_iobase=0,temp_iobase=0;
\r
73 int _mm_fopen(CHAR* fname,int attrib)
\r
77 fp=rb->open(fname,attrib);
\r
80 _mm_errno = MMERR_OPENING_FILE;
\r
81 if(_mm_errorhandler) _mm_errorhandler();
\r
86 BOOL _mm_FileExists(CHAR* fname)
\r
90 if(!(fp=rb->open(fname, O_RDONLY))) return 0;
\r
96 int _mm_fclose(int fp)
\r
98 return rb->close(fp);
\r
101 /* Sets the current file-position as the new _mm_iobase */
\r
102 void _mm_iobase_setcur(MREADER* reader)
\r
104 temp_iobase=_mm_iobase; /* store old value in case of revert */
\r
105 _mm_iobase=reader->Tell(reader);
\r
108 /* Reverts to the last known _mm_iobase value. */
\r
109 void _mm_iobase_revert(void)
\r
111 _mm_iobase=temp_iobase;
\r
114 /*========== File Reader */
\r
116 typedef struct MFILEREADER {
\r
122 static BOOL _mm_FileReader_Eof(MREADER* reader)
\r
125 if ((lseek(((MFILEREADER*)reader)->file, 0, SEEK_CUR)-_mm_iobase) < filesize(((MFILEREADER*)reader)->file))
\r
130 return ((MFILEREADER*)reader)->waseof;
\r
133 static BOOL _mm_FileReader_Read(MREADER* reader,void* ptr,size_t size)
\r
136 tempb = rb->read(((MFILEREADER*)reader)->file, ptr, size);
\r
137 //printf("(**) READ: %i\n", tempb);
\r
141 printf("Read: count: %i newpos: %i return: %i\n", size, lseek(((MFILEREADER*)reader)->file-_mm_iobase, 0, SEEK_CUR), tempb);
\r
144 if ((tempb < 1) && size > 0)
\r
147 ((MFILEREADER*)reader)->waseof = 1;
\r
151 ((MFILEREADER*)reader)->waseof = 0;
\r
156 static int _mm_FileReader_Get(MREADER* reader)
\r
159 if ((rb->read(((MFILEREADER*)reader)->file, &buf, 1) > 0) == 1)
\r
161 ((MFILEREADER*)reader)->waseof = 0;
\r
162 //printf("Get: newpos: %i _mm_iobase: %i\n", lseek(((MFILEREADER*)reader)->file-_mm_iobase, 0, SEEK_CUR), _mm_iobase);
\r
167 ((MFILEREADER*)reader)->waseof = 1;
\r
168 //printf("Get: newpos: %i _mm_iobase: %i\n", lseek(((MFILEREADER*)reader)->file-_mm_iobase, 0, SEEK_CUR), _mm_iobase);
\r
173 static BOOL _mm_FileReader_Seek(MREADER* reader,long offset,int whence)
\r
177 tempb = rb->lseek(((MFILEREADER*)reader)->file,
\r
178 (whence==SEEK_SET)?offset+_mm_iobase:offset,whence);
\r
179 ((MFILEREADER*)reader)->waseof = 0;
\r
180 //printf("(**) SEEK: %i\n", tempb);
\r
183 //printf("Seek: count: %i newpos: %i return: %i\n", offset, lseek(((MFILEREADER*)reader)->file-_mm_iobase, 0, SEEK_CUR), tempb);
\r
192 static long _mm_FileReader_Tell(MREADER* reader)
\r
194 return rb->lseek(((MFILEREADER*)reader)->file, 0, SEEK_CUR)-_mm_iobase;
\r
197 MREADER *_mm_new_file_reader(int fp)
\r
199 MFILEREADER* reader=(MFILEREADER*)_mm_malloc(sizeof(MFILEREADER));
\r
201 reader->core.Eof =&_mm_FileReader_Eof;
\r
202 reader->core.Read=&_mm_FileReader_Read;
\r
203 reader->core.Get =&_mm_FileReader_Get;
\r
204 reader->core.Seek=&_mm_FileReader_Seek;
\r
205 reader->core.Tell=&_mm_FileReader_Tell;
\r
207 reader->waseof = 0;
\r
209 return (MREADER*)reader;
\r
212 void _mm_delete_file_reader (MREADER* reader)
\r
214 if(reader) free(reader);
\r
217 /*========== File Writer */
\r
219 typedef struct MFILEWRITER {
\r
224 static BOOL _mm_FileWriter_Seek(MWRITER* writer,long offset,int whence)
\r
226 return rb->lseek(((MFILEWRITER*)writer)->file,offset,whence);
\r
229 static long _mm_FileWriter_Tell(MWRITER* writer)
\r
231 return rb->lseek(((MFILEREADER*)writer)->file, 0, SEEK_CUR);
\r
234 static BOOL _mm_FileWriter_Write(MWRITER* writer,void* ptr,size_t size)
\r
236 return (rb->write(((MFILEWRITER*)writer)->file, ptr, size)==size);
\r
239 static BOOL _mm_FileWriter_Put(MWRITER* writer,int value)
\r
242 if (rb->write(((MFILEWRITER*)writer)->file, &buf, 1))
\r
248 MWRITER *_mm_new_file_writer(int fp)
\r
250 MFILEWRITER* writer=(MFILEWRITER*)_mm_malloc(sizeof(MFILEWRITER));
\r
252 writer->core.Seek =&_mm_FileWriter_Seek;
\r
253 writer->core.Tell =&_mm_FileWriter_Tell;
\r
254 writer->core.Write=&_mm_FileWriter_Write;
\r
255 writer->core.Put =&_mm_FileWriter_Put;
\r
258 return (MWRITER*) writer;
\r
261 void _mm_delete_file_writer (MWRITER* writer)
\r
263 if(writer) free (writer);
\r
266 /*========== Write functions */
\r
268 void _mm_write_string(CHAR* data,MWRITER* writer)
\r
271 _mm_write_UBYTES(data,strlen(data),writer);
\r
274 void _mm_write_M_UWORD(UWORD data,MWRITER* writer)
\r
276 _mm_write_UBYTE(data>>8,writer);
\r
277 _mm_write_UBYTE(data&0xff,writer);
\r
280 void _mm_write_I_UWORD(UWORD data,MWRITER* writer)
\r
282 _mm_write_UBYTE(data&0xff,writer);
\r
283 _mm_write_UBYTE(data>>8,writer);
\r
286 void _mm_write_M_ULONG(ULONG data,MWRITER* writer)
\r
288 _mm_write_M_UWORD((UWORD)(data>>16),writer);
\r
289 _mm_write_M_UWORD((UWORD)(data&0xffff),writer);
\r
292 void _mm_write_I_ULONG(ULONG data,MWRITER* writer)
\r
294 _mm_write_I_UWORD((UWORD)(data&0xffff),writer);
\r
295 _mm_write_I_UWORD((UWORD)(data>>16),writer);
\r
298 void _mm_write_M_SWORD(SWORD data,MWRITER* writer)
\r
300 _mm_write_M_UWORD((UWORD)data,writer);
\r
303 void _mm_write_I_SWORD(SWORD data,MWRITER* writer)
\r
305 _mm_write_I_UWORD((UWORD)data,writer);
\r
308 void _mm_write_M_SLONG(SLONG data,MWRITER* writer)
\r
310 _mm_write_M_ULONG((ULONG)data,writer);
\r
313 void _mm_write_I_SLONG(SLONG data,MWRITER* writer)
\r
315 _mm_write_I_ULONG((ULONG)data,writer);
\r
318 #if defined __STDC__ || defined _MSC_VER || defined MPW_C
\r
319 #define DEFINE_MULTIPLE_WRITE_FUNCTION(type_name,type) \
\r
320 void _mm_write_##type_name##S (type *buffer,int number,MWRITER* writer) \
\r
322 while(number-->0) \
\r
323 _mm_write_##type_name(*(buffer++),writer); \
\r
326 #define DEFINE_MULTIPLE_WRITE_FUNCTION(type_name,type) \
\r
327 void _mm_write_/**/type_name/**/S (type *buffer,int number,MWRITER* writer) \
\r
329 while(number-->0) \
\r
330 _mm_write_/**/type_name(*(buffer++),writer); \
\r
334 DEFINE_MULTIPLE_WRITE_FUNCTION(M_SWORD,SWORD)
\r
335 DEFINE_MULTIPLE_WRITE_FUNCTION(M_UWORD,UWORD)
\r
336 DEFINE_MULTIPLE_WRITE_FUNCTION(I_SWORD,SWORD)
\r
337 DEFINE_MULTIPLE_WRITE_FUNCTION(I_UWORD,UWORD)
\r
339 DEFINE_MULTIPLE_WRITE_FUNCTION(M_SLONG,SLONG)
\r
340 DEFINE_MULTIPLE_WRITE_FUNCTION(M_ULONG,ULONG)
\r
341 DEFINE_MULTIPLE_WRITE_FUNCTION(I_SLONG,SLONG)
\r
342 DEFINE_MULTIPLE_WRITE_FUNCTION(I_ULONG,ULONG)
\r
344 /*========== Read functions */
\r
346 int _mm_read_string(CHAR* buffer,int number,MREADER* reader)
\r
348 return reader->Read(reader,buffer,number);
\r
351 UWORD _mm_read_M_UWORD(MREADER* reader)
\r
353 UWORD result=((UWORD)_mm_read_UBYTE(reader))<<8;
\r
354 result|=_mm_read_UBYTE(reader);
\r
358 UWORD _mm_read_I_UWORD(MREADER* reader)
\r
360 UWORD result=_mm_read_UBYTE(reader);
\r
361 result|=((UWORD)_mm_read_UBYTE(reader))<<8;
\r
365 ULONG _mm_read_M_ULONG(MREADER* reader)
\r
367 ULONG result=((ULONG)_mm_read_M_UWORD(reader))<<16;
\r
368 result|=_mm_read_M_UWORD(reader);
\r
372 ULONG _mm_read_I_ULONG(MREADER* reader)
\r
374 ULONG result=_mm_read_I_UWORD(reader);
\r
375 result|=((ULONG)_mm_read_I_UWORD(reader))<<16;
\r
379 SWORD _mm_read_M_SWORD(MREADER* reader)
\r
381 return((SWORD)_mm_read_M_UWORD(reader));
\r
384 SWORD _mm_read_I_SWORD(MREADER* reader)
\r
386 return((SWORD)_mm_read_I_UWORD(reader));
\r
389 SLONG _mm_read_M_SLONG(MREADER* reader)
\r
391 return((SLONG)_mm_read_M_ULONG(reader));
\r
394 SLONG _mm_read_I_SLONG(MREADER* reader)
\r
396 return((SLONG)_mm_read_I_ULONG(reader));
\r
399 #if defined __STDC__ || defined _MSC_VER || defined MPW_C
\r
400 #define DEFINE_MULTIPLE_READ_FUNCTION(type_name,type) \
\r
401 int _mm_read_##type_name##S (type *buffer,int number,MREADER* reader) \
\r
403 while(number-->0) \
\r
404 *(buffer++)=_mm_read_##type_name(reader); \
\r
405 return !reader->Eof(reader); \
\r
408 #define DEFINE_MULTIPLE_READ_FUNCTION(type_name,type) \
\r
409 int _mm_read_/**/type_name/**/S (type *buffer,int number,MREADER* reader) \
\r
411 while(number-->0) \
\r
412 *(buffer++)=_mm_read_/**/type_name(reader); \
\r
413 return !reader->Eof(reader); \
\r
417 DEFINE_MULTIPLE_READ_FUNCTION(M_SWORD,SWORD)
\r
418 DEFINE_MULTIPLE_READ_FUNCTION(M_UWORD,UWORD)
\r
419 DEFINE_MULTIPLE_READ_FUNCTION(I_SWORD,SWORD)
\r
420 DEFINE_MULTIPLE_READ_FUNCTION(I_UWORD,UWORD)
\r
422 DEFINE_MULTIPLE_READ_FUNCTION(M_SLONG,SLONG)
\r
423 DEFINE_MULTIPLE_READ_FUNCTION(M_ULONG,ULONG)
\r
424 DEFINE_MULTIPLE_READ_FUNCTION(I_SLONG,SLONG)
\r
425 DEFINE_MULTIPLE_READ_FUNCTION(I_ULONG,ULONG)
\r