Add "MikMod for Rockbox 0.1" from 2007-06-29
[mikmod-rockbox.git] / apps / plugins / mikmod / mmio / mmio.c
1 /*      MikMod sound library\r
2         (c) 1998, 1999, 2000 Miodrag Vallat and others - see file AUTHORS for\r
3         complete list.\r
4 \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
9  \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
14  \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
18         02111-1307, USA.\r
19 */\r
20 \r
21 /*==============================================================================\r
22 \r
23   $Id: mmio.c,v 1.2 2004/02/06 19:29:05 raph Exp $\r
24 \r
25   Portable file I/O routines\r
26 \r
27 ==============================================================================*/\r
28 \r
29 /*\r
30 \r
31         The way this module works:\r
32 \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
43 \r
44 */\r
45 \r
46 /* FIXME\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
50 \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
53 */\r
54 \r
55 #ifdef HAVE_CONFIG_H\r
56 #include "config.h"\r
57 #endif\r
58 \r
59 #ifdef HAVE_UNISTD_H\r
60 #include <unistd.h>\r
61 #endif\r
62 \r
63 #include <stdio.h>\r
64 #include <string.h>\r
65 \r
66 #include "mikmod_internals.h"\r
67 \r
68 #define COPY_BUFSIZE  1024\r
69 \r
70 static long _mm_iobase=0,temp_iobase=0;\r
71 \r
72 \r
73 int _mm_fopen(CHAR* fname,int attrib)\r
74 {\r
75         int fp;\r
76 \r
77         fp=rb->open(fname,attrib);\r
78         if(fp == -1) {\r
79                 fp = 0;\r
80                 _mm_errno = MMERR_OPENING_FILE;\r
81                 if(_mm_errorhandler) _mm_errorhandler();\r
82         }\r
83         return fp;\r
84 }\r
85 \r
86 BOOL _mm_FileExists(CHAR* fname)\r
87 {\r
88         int fp;\r
89 \r
90         if(!(fp=rb->open(fname, O_RDONLY))) return 0;\r
91         rb->close(fp);\r
92 \r
93         return 1;\r
94 }\r
95 \r
96 int _mm_fclose(int fp)\r
97 {\r
98         return rb->close(fp);\r
99 }\r
100 \r
101 /* Sets the current file-position as the new _mm_iobase */\r
102 void _mm_iobase_setcur(MREADER* reader)\r
103 {\r
104         temp_iobase=_mm_iobase;  /* store old value in case of revert */\r
105         _mm_iobase=reader->Tell(reader);\r
106 }\r
107 \r
108 /* Reverts to the last known _mm_iobase value. */\r
109 void _mm_iobase_revert(void)\r
110 {\r
111         _mm_iobase=temp_iobase;\r
112 }\r
113 \r
114 /*========== File Reader */\r
115 \r
116 typedef struct MFILEREADER {\r
117         MREADER core;\r
118         int   file;\r
119         int   waseof;\r
120 } MFILEREADER;\r
121 \r
122 static BOOL _mm_FileReader_Eof(MREADER* reader)\r
123 {\r
124         /*\r
125         if ((lseek(((MFILEREADER*)reader)->file, 0, SEEK_CUR)-_mm_iobase) < filesize(((MFILEREADER*)reader)->file))\r
126                 return 0;\r
127         else\r
128                 return 1;\r
129         */\r
130         return ((MFILEREADER*)reader)->waseof;\r
131 }\r
132 \r
133 static BOOL _mm_FileReader_Read(MREADER* reader,void* ptr,size_t size)\r
134 {\r
135         int tempb;\r
136         tempb = rb->read(((MFILEREADER*)reader)->file, ptr, size);\r
137         //printf("(**) READ: %i\n", tempb);\r
138         /*\r
139         if (tempb != size)\r
140         {\r
141                 printf("Read: count: %i  newpos: %i  return: %i\n", size, lseek(((MFILEREADER*)reader)->file-_mm_iobase, 0, SEEK_CUR), tempb);\r
142         }\r
143         */\r
144         if ((tempb < 1) && size > 0)\r
145         {\r
146                 tempb = 0;\r
147                 ((MFILEREADER*)reader)->waseof = 1;\r
148         }\r
149         else\r
150         {\r
151                 ((MFILEREADER*)reader)->waseof = 0;\r
152         }\r
153         return tempb;\r
154 }\r
155 \r
156 static int _mm_FileReader_Get(MREADER* reader)\r
157 {\r
158         char buf;\r
159         if ((rb->read(((MFILEREADER*)reader)->file, &buf, 1) > 0) == 1)\r
160         {\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
163                 return buf;\r
164         }\r
165         else\r
166         {\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
169                 return EOF;\r
170         }\r
171 }\r
172 \r
173 static BOOL _mm_FileReader_Seek(MREADER* reader,long offset,int whence)\r
174 {\r
175         long tempb;\r
176 \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
181         if (tempb < 0)\r
182         {\r
183                 //printf("Seek: count: %i  newpos: %i  return: %i\n", offset, lseek(((MFILEREADER*)reader)->file-_mm_iobase, 0, SEEK_CUR), tempb);\r
184                 return 1;\r
185         }\r
186         else\r
187         {\r
188                 return 0;\r
189         }\r
190 }\r
191 \r
192 static long _mm_FileReader_Tell(MREADER* reader)\r
193 {\r
194         return rb->lseek(((MFILEREADER*)reader)->file, 0, SEEK_CUR)-_mm_iobase;\r
195 }\r
196 \r
197 MREADER *_mm_new_file_reader(int fp)\r
198 {\r
199         MFILEREADER* reader=(MFILEREADER*)_mm_malloc(sizeof(MFILEREADER));\r
200         if (reader) {\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
206                 reader->file=fp;\r
207                 reader->waseof = 0;\r
208         }\r
209         return (MREADER*)reader;\r
210 }\r
211 \r
212 void _mm_delete_file_reader (MREADER* reader)\r
213 {\r
214         if(reader) free(reader);\r
215 }\r
216 \r
217 /*========== File Writer */\r
218 \r
219 typedef struct MFILEWRITER {\r
220         MWRITER core;\r
221         int   file;\r
222 } MFILEWRITER;\r
223 \r
224 static BOOL _mm_FileWriter_Seek(MWRITER* writer,long offset,int whence)\r
225 {\r
226         return rb->lseek(((MFILEWRITER*)writer)->file,offset,whence);\r
227 }\r
228 \r
229 static long _mm_FileWriter_Tell(MWRITER* writer)\r
230 {\r
231         return rb->lseek(((MFILEREADER*)writer)->file, 0, SEEK_CUR);\r
232 }\r
233 \r
234 static BOOL _mm_FileWriter_Write(MWRITER* writer,void* ptr,size_t size)\r
235 {\r
236         return (rb->write(((MFILEWRITER*)writer)->file, ptr, size)==size);\r
237 }\r
238 \r
239 static BOOL _mm_FileWriter_Put(MWRITER* writer,int value)\r
240 {\r
241         char buf = value;\r
242         if (rb->write(((MFILEWRITER*)writer)->file, &buf, 1))\r
243                 return 0;\r
244         else\r
245                 return -1;\r
246 }\r
247 \r
248 MWRITER *_mm_new_file_writer(int fp)\r
249 {\r
250         MFILEWRITER* writer=(MFILEWRITER*)_mm_malloc(sizeof(MFILEWRITER));\r
251         if (writer) {\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
256                 writer->file=fp;\r
257         }\r
258         return (MWRITER*) writer;\r
259 }\r
260 \r
261 void _mm_delete_file_writer (MWRITER* writer)\r
262 {\r
263         if(writer) free (writer);\r
264 }\r
265 \r
266 /*========== Write functions */\r
267 \r
268 void _mm_write_string(CHAR* data,MWRITER* writer)\r
269 {\r
270         if(data)\r
271                 _mm_write_UBYTES(data,strlen(data),writer);\r
272 }\r
273 \r
274 void _mm_write_M_UWORD(UWORD data,MWRITER* writer)\r
275 {\r
276         _mm_write_UBYTE(data>>8,writer);\r
277         _mm_write_UBYTE(data&0xff,writer);\r
278 }\r
279 \r
280 void _mm_write_I_UWORD(UWORD data,MWRITER* writer)\r
281 {\r
282         _mm_write_UBYTE(data&0xff,writer);\r
283         _mm_write_UBYTE(data>>8,writer);\r
284 }\r
285 \r
286 void _mm_write_M_ULONG(ULONG data,MWRITER* writer)\r
287 {\r
288         _mm_write_M_UWORD((UWORD)(data>>16),writer);\r
289         _mm_write_M_UWORD((UWORD)(data&0xffff),writer);\r
290 }\r
291 \r
292 void _mm_write_I_ULONG(ULONG data,MWRITER* writer)\r
293 {\r
294         _mm_write_I_UWORD((UWORD)(data&0xffff),writer);\r
295         _mm_write_I_UWORD((UWORD)(data>>16),writer);\r
296 }\r
297 \r
298 void _mm_write_M_SWORD(SWORD data,MWRITER* writer)\r
299 {\r
300         _mm_write_M_UWORD((UWORD)data,writer);\r
301 }\r
302 \r
303 void _mm_write_I_SWORD(SWORD data,MWRITER* writer)\r
304 {\r
305         _mm_write_I_UWORD((UWORD)data,writer);\r
306 }\r
307 \r
308 void _mm_write_M_SLONG(SLONG data,MWRITER* writer)\r
309 {\r
310         _mm_write_M_ULONG((ULONG)data,writer);\r
311 }\r
312 \r
313 void _mm_write_I_SLONG(SLONG data,MWRITER* writer)\r
314 {\r
315         _mm_write_I_ULONG((ULONG)data,writer);\r
316 }\r
317 \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
321 {                                                                                                                                                       \\r
322         while(number-->0)                                                                                                               \\r
323                 _mm_write_##type_name(*(buffer++),writer);                                                      \\r
324 }\r
325 #else\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
328 {                                                                                                                                                       \\r
329         while(number-->0)                                                                                                               \\r
330                 _mm_write_/**/type_name(*(buffer++),writer);                                            \\r
331 }\r
332 #endif\r
333 \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
338 \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
343 \r
344 /*========== Read functions */\r
345 \r
346 int _mm_read_string(CHAR* buffer,int number,MREADER* reader)\r
347 {\r
348         return reader->Read(reader,buffer,number);\r
349 }\r
350 \r
351 UWORD _mm_read_M_UWORD(MREADER* reader)\r
352 {\r
353         UWORD result=((UWORD)_mm_read_UBYTE(reader))<<8;\r
354         result|=_mm_read_UBYTE(reader);\r
355         return result;\r
356 }\r
357 \r
358 UWORD _mm_read_I_UWORD(MREADER* reader)\r
359 {\r
360         UWORD result=_mm_read_UBYTE(reader);\r
361         result|=((UWORD)_mm_read_UBYTE(reader))<<8;\r
362         return result;\r
363 }\r
364 \r
365 ULONG _mm_read_M_ULONG(MREADER* reader)\r
366 {\r
367         ULONG result=((ULONG)_mm_read_M_UWORD(reader))<<16;\r
368         result|=_mm_read_M_UWORD(reader);\r
369         return result;\r
370 }\r
371 \r
372 ULONG _mm_read_I_ULONG(MREADER* reader)\r
373 {\r
374         ULONG result=_mm_read_I_UWORD(reader);\r
375         result|=((ULONG)_mm_read_I_UWORD(reader))<<16;\r
376         return result;\r
377 }\r
378 \r
379 SWORD _mm_read_M_SWORD(MREADER* reader)\r
380 {\r
381         return((SWORD)_mm_read_M_UWORD(reader));\r
382 }\r
383 \r
384 SWORD _mm_read_I_SWORD(MREADER* reader)\r
385 {\r
386         return((SWORD)_mm_read_I_UWORD(reader));\r
387 }\r
388 \r
389 SLONG _mm_read_M_SLONG(MREADER* reader)\r
390 {\r
391         return((SLONG)_mm_read_M_ULONG(reader));\r
392 }\r
393 \r
394 SLONG _mm_read_I_SLONG(MREADER* reader)\r
395 {\r
396         return((SLONG)_mm_read_I_ULONG(reader));\r
397 }\r
398 \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
402 {                                                                                                                                                       \\r
403         while(number-->0)                                                                                                               \\r
404                 *(buffer++)=_mm_read_##type_name(reader);                                                       \\r
405         return !reader->Eof(reader);                                                                                    \\r
406 }\r
407 #else\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
410 {                                                                                                                                                       \\r
411         while(number-->0)                                                                                                               \\r
412                 *(buffer++)=_mm_read_/**/type_name(reader);                                                     \\r
413         return !reader->Eof(reader);                                                                                    \\r
414 }\r
415 #endif\r
416 \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
421 \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
426 \r
427 /* ex:set ts=4: */\r