10
|
1 /*
|
|
2 --> The MMIO Portable Input/Output functions
|
|
3 -> Divine Entertainment GameDev Libraries
|
|
4
|
|
5 File: MMIO.C
|
|
6
|
|
7 Description:
|
|
8 Miscellaneous I/O routines.. used to solve some portability issues
|
|
9 (like big/little endian machines and word alignment in structures )
|
|
10 Also includes mikmod's ingenious error handling variable.
|
|
11
|
|
12 Portability:
|
|
13 All systems - all compilers
|
|
14
|
|
15
|
|
16 -----------------------------------
|
|
17 The way this module works - By Jake Stine [Air Richter]
|
|
18
|
|
19 - _mm_fopen and _mm_copyfile will call the errorhandler [see mmerror.c] in
|
|
20 addition to setting _mm_errno on exit.
|
|
21
|
|
22 - _mm_iobase is for internal use. It is used by ML_LoadFP() to ensure that it
|
|
23 works properly with wad files.
|
|
24
|
|
25 - _mm_read_I_UWORD and _mm_read_M_UWORD have distinct differences:
|
|
26 the first is for reading data written by a little endian (intel) machine,
|
|
27 and the second is for reading big endian (Mac, RISC, Alpha) machine data.
|
|
28
|
|
29 - _mm_write functions work the same as the _mm_read functions.
|
|
30
|
|
31 - _mm_read_string is for reading binary strings. It is basically the same
|
|
32 as an fread of bytes.
|
|
33 */
|
|
34
|
|
35 #include "mmio.h"
|
|
36 #include <string.h>
|
|
37
|
|
38 #define COPY_BUFSIZE 1024
|
|
39
|
|
40 static long _mm_iobase = 0,
|
|
41 temp_iobase = 0;
|
|
42
|
|
43 UBYTE _mm_cpybuf[COPY_BUFSIZE];
|
|
44
|
|
45
|
|
46 void StringWrite(CHAR *s, FILE *fp)
|
|
47 // Specialized file output procedure. Writes a UWORD length and then a
|
|
48 // string of the specified length (no NULL terminator) afterward.
|
|
49 {
|
|
50 int slen;
|
|
51
|
|
52 if(s==NULL)
|
|
53 { _mm_write_I_UWORD(0,fp);
|
|
54 } else
|
|
55 { _mm_write_I_UWORD(slen = strlen(s),fp);
|
|
56 _mm_write_UBYTES(s,slen,fp);
|
|
57 }
|
|
58 }
|
|
59
|
|
60 CHAR *StringRead(FILE *fp)
|
|
61 // Reads strings written out by StringWrite above: a UWORD length followed
|
|
62 // by length characters. A NULL is added to the string after loading.
|
|
63 {
|
|
64 CHAR *s;
|
|
65 UWORD len;
|
|
66
|
|
67 len = _mm_read_I_UWORD(fp);
|
|
68 if(len==0)
|
|
69 { s = _mm_calloc(16, sizeof(CHAR));
|
|
70 } else
|
|
71 { if((s = (CHAR *)_mm_malloc(len+1)) == NULL) return NULL;
|
|
72 _mm_read_UBYTES(s,len,fp);
|
|
73 s[len] = 0;
|
|
74 }
|
|
75
|
|
76 return s;
|
|
77 }
|
|
78
|
|
79
|
|
80 FILE *_mm_fopen(CHAR *fname, CHAR *attrib)
|
|
81 {
|
|
82 FILE *fp;
|
|
83
|
|
84 if((fp=fopen(fname,attrib)) == NULL)
|
|
85 { _mm_errno = _mm_errno = MMERR_OPENING_FILE;
|
|
86 if(_mm_errorhandler!=NULL) _mm_errorhandler();
|
|
87 }
|
|
88 return fp;
|
|
89 }
|
|
90
|
|
91
|
|
92 int _mm_fseek(FILE *stream, long offset, int whence)
|
|
93 {
|
|
94 return fseek(stream,(whence==SEEK_SET) ? offset+_mm_iobase : offset, whence);
|
|
95 }
|
|
96
|
|
97
|
|
98 long _mm_ftell(FILE *stream)
|
|
99 {
|
|
100 return ftell(stream)-_mm_iobase;
|
|
101 }
|
|
102
|
|
103
|
|
104 BOOL _mm_FileExists(CHAR *fname)
|
|
105 {
|
|
106 FILE *fp;
|
|
107
|
|
108 if((fp=fopen(fname,"r")) == NULL) return 0;
|
|
109 fclose(fp);
|
|
110
|
|
111 return 1;
|
|
112 }
|
|
113
|
|
114
|
|
115 long _mm_flength(FILE *stream)
|
|
116 {
|
|
117 long tmp,tmp2;
|
|
118
|
|
119 tmp = ftell(stream);
|
|
120 fseek(stream,0,SEEK_END);
|
|
121 tmp2 = ftell(stream);
|
|
122 fseek(stream,tmp,SEEK_SET);
|
|
123 return tmp2-tmp;
|
|
124 }
|
|
125
|
|
126
|
|
127 long _mm_iobase_get(void)
|
|
128 {
|
|
129 return _mm_iobase;
|
|
130 }
|
|
131
|
|
132
|
|
133 void _mm_iobase_set(long iobase)
|
|
134 {
|
|
135 temp_iobase = _mm_iobase; // store old value in case of revert
|
|
136 _mm_iobase = iobase;
|
|
137 }
|
|
138
|
|
139
|
|
140 // Sets the current file-position as the new _mm_iobase
|
|
141 void _mm_iobase_setcur(FILE *fp)
|
|
142 {
|
|
143 temp_iobase = _mm_iobase; // store old value in case of revert
|
|
144 _mm_iobase = ftell(fp);
|
|
145 }
|
|
146
|
|
147
|
|
148 // Reverts to the last known _mm_iobase value.
|
|
149 void _mm_iobase_revert(void)
|
|
150 {
|
|
151 _mm_iobase = temp_iobase;
|
|
152 }
|
|
153
|
|
154
|
|
155 // Procedure: _mm_copyfile
|
|
156 // Copies a given number of bytes from the source file to the destination
|
|
157 // file. Returns 1 on error, and calls the _mm_errnohandler, if registered.
|
|
158 BOOL _mm_copyfile(FILE *fpi, FILE *fpo, ULONG len)
|
|
159 {
|
|
160 ULONG todo;
|
|
161
|
|
162 while(len)
|
|
163 { todo = (len > COPY_BUFSIZE) ? COPY_BUFSIZE : len;
|
|
164 if(!fread(_mm_cpybuf, todo, 1, fpi))
|
|
165 { _mm_errno = _mm_errno = MMERR_END_OF_FILE;
|
|
166 if(_mm_errorhandler!=NULL) _mm_errorhandler();
|
|
167 return 1;
|
|
168 }
|
|
169 if(!fwrite(_mm_cpybuf, todo, 1, fpo))
|
|
170 { _mm_errno = _mm_errno = MMERR_DISK_FULL;
|
|
171 if(_mm_errorhandler!=NULL) _mm_errorhandler();
|
|
172 return 1;
|
|
173 }
|
|
174 len -= todo;
|
|
175 }
|
|
176
|
|
177 return 0;
|
|
178 }
|
|
179
|
|
180
|
|
181 void _mm_write_string(CHAR *data, FILE *fp)
|
|
182 {
|
|
183 if(data!=NULL)
|
|
184 _mm_write_UBYTES(data, strlen(data), fp);
|
|
185 }
|
|
186
|
|
187
|
|
188 void _mm_fputs(FILE *fp, CHAR *data)
|
|
189 {
|
|
190 if(data != NULL)
|
|
191 _mm_write_UBYTES(data, strlen(data), fp);
|
|
192
|
|
193 #ifndef __UNIX__
|
|
194 _mm_write_UBYTE(13,fp);
|
|
195 #endif
|
|
196 _mm_write_UBYTE(10,fp);
|
|
197 }
|
|
198
|
|
199
|
|
200
|
|
201 /*************
|
|
202 // These have accompanying #define's in mmio.h
|
|
203
|
|
204 void _mm_write_SBYTE(SBYTE data, FILE *fp)
|
|
205 {
|
|
206 fputc(data,fp);
|
|
207 }
|
|
208
|
|
209 void _mm_write_UBYTE(UBYTE data,FILE *fp)
|
|
210 {
|
|
211 fputc(data,fp);
|
|
212 }
|
|
213 */
|
|
214
|
|
215 #ifdef MM_BIG_ENDIAN
|
|
216
|
|
217 // --> Big Endian Write Functions
|
|
218
|
|
219 void _mm_write_M_UWORD(UWORD data,FILE *fp)
|
|
220 {
|
|
221 _mm_write_UBYTE(data&0xff,fp);
|
|
222 _mm_write_UBYTE(data>>8,fp);
|
|
223 }
|
|
224
|
|
225
|
|
226 void _mm_write_I_UWORD(UWORD data,FILE *fp)
|
|
227 {
|
|
228 _mm_write_UBYTE(data>>8,fp);
|
|
229 _mm_write_UBYTE(data&0xff,fp);
|
|
230 }
|
|
231
|
|
232
|
|
233 void _mm_write_M_ULONG(ULONG data,FILE *fp)
|
|
234 {
|
|
235 _mm_write_M_UWORD(data&0xffff,fp);
|
|
236 _mm_write_M_UWORD(data>>16,fp);
|
|
237 }
|
|
238
|
|
239
|
|
240 void _mm_write_I_ULONG(ULONG data,FILE *fp)
|
|
241 {
|
|
242 _mm_write_I_UWORD(data>>16,fp);
|
|
243 _mm_write_I_UWORD(data&0xffff,fp);
|
|
244 }
|
|
245
|
|
246 #else
|
|
247
|
|
248 // --> Little Endian Write Functions
|
|
249
|
|
250 void _mm_write_M_UWORD(UWORD data,FILE *fp)
|
|
251 {
|
|
252 _mm_write_UBYTE(data>>8,fp);
|
|
253 _mm_write_UBYTE(data&0xff,fp);
|
|
254 }
|
|
255
|
|
256
|
|
257 void _mm_write_I_UWORD(UWORD data,FILE *fp)
|
|
258 {
|
|
259 _mm_write_UBYTE(data&0xff,fp);
|
|
260 _mm_write_UBYTE(data>>8,fp);
|
|
261 }
|
|
262
|
|
263
|
|
264 void _mm_write_M_ULONG(ULONG data,FILE *fp)
|
|
265 {
|
|
266 _mm_write_M_UWORD(data>>16,fp);
|
|
267 _mm_write_M_UWORD(data&0xffff,fp);
|
|
268 }
|
|
269
|
|
270
|
|
271 void _mm_write_I_ULONG(ULONG data,FILE *fp)
|
|
272 {
|
|
273 _mm_write_I_UWORD(data&0xffff,fp);
|
|
274 _mm_write_I_UWORD(data>>16,fp);
|
|
275 }
|
|
276
|
|
277 #endif
|
|
278
|
|
279
|
|
280 void _mm_write_M_SWORD(SWORD data,FILE *fp)
|
|
281 {
|
|
282 _mm_write_M_UWORD((UWORD)data,fp);
|
|
283 }
|
|
284
|
|
285
|
|
286 void _mm_write_I_SWORD(SWORD data,FILE *fp)
|
|
287 {
|
|
288 _mm_write_I_UWORD((UWORD)data,fp);
|
|
289 }
|
|
290
|
|
291
|
|
292 void _mm_write_M_SLONG(SLONG data,FILE *fp)
|
|
293 {
|
|
294 _mm_write_M_ULONG((ULONG)data,fp);
|
|
295 }
|
|
296
|
|
297
|
|
298 void _mm_write_I_SLONG(SLONG data,FILE *fp)
|
|
299 {
|
|
300 _mm_write_I_ULONG((ULONG)data,fp);
|
|
301 }
|
|
302
|
|
303
|
|
304 #define DEFINE_MULTIPLE_WRITE_FUNCTION(type_name, type) \
|
|
305 void \
|
|
306 _mm_write_##type_name##S (type *buffer, int number, FILE *fp) \
|
|
307 { \
|
|
308 while(number>0) \
|
|
309 { _mm_write_##type_name(*(buffer++),fp); \
|
|
310 number--; \
|
|
311 } \
|
|
312 }
|
|
313
|
|
314 //DEFINE_MULTIPLE_WRITE_FUNCTION (SBYTE, SBYTE)
|
|
315 //DEFINE_MULTIPLE_WRITE_FUNCTION (UBYTE, UBYTE)
|
|
316
|
|
317 DEFINE_MULTIPLE_WRITE_FUNCTION (M_SWORD, SWORD)
|
|
318 DEFINE_MULTIPLE_WRITE_FUNCTION (M_UWORD, UWORD)
|
|
319 DEFINE_MULTIPLE_WRITE_FUNCTION (I_SWORD, SWORD)
|
|
320 DEFINE_MULTIPLE_WRITE_FUNCTION (I_UWORD, UWORD)
|
|
321
|
|
322 DEFINE_MULTIPLE_WRITE_FUNCTION (M_SLONG, SLONG)
|
|
323 DEFINE_MULTIPLE_WRITE_FUNCTION (M_ULONG, ULONG)
|
|
324 DEFINE_MULTIPLE_WRITE_FUNCTION (I_SLONG, SLONG)
|
|
325 DEFINE_MULTIPLE_WRITE_FUNCTION (I_ULONG, ULONG)
|
|
326
|
|
327
|
|
328 /**********
|
|
329 SBYTE _mm_read_SBYTE(FILE *fp)
|
|
330 {
|
|
331 return(fgetc(fp));
|
|
332 }
|
|
333
|
|
334 UBYTE _mm_read_UBYTE(FILE *fp)
|
|
335 {
|
|
336 return(fgetc(fp));
|
|
337 }
|
|
338 **********/
|
|
339
|
|
340
|
|
341 #ifdef MM_BIG_ENDIAN
|
|
342
|
|
343 UWORD _mm_read_I_UWORD(FILE *fp)
|
|
344 {
|
|
345 UWORD result=((UWORD)_mm_read_UBYTE(fp))<<8;
|
|
346 result|=_mm_read_UBYTE(fp);
|
|
347 return result;
|
|
348 }
|
|
349
|
|
350 UWORD _mm_read_M_UWORD(FILE *fp)
|
|
351 {
|
|
352 UWORD result=_mm_read_UBYTE(fp);
|
|
353 result|=((UWORD)_mm_read_UBYTE(fp))<<8;
|
|
354 return result;
|
|
355 }
|
|
356
|
|
357 ULONG _mm_read_I_ULONG(FILE *fp)
|
|
358 {
|
|
359 ULONG result=((ULONG)_mm_read_M_UWORD(fp))<<16;
|
|
360 result|=_mm_read_M_UWORD(fp);
|
|
361 return result;
|
|
362 }
|
|
363
|
|
364 ULONG _mm_read_M_ULONG(FILE *fp)
|
|
365 {
|
|
366 ULONG result=_mm_read_I_UWORD(fp);
|
|
367 result|=((ULONG)_mm_read_I_UWORD(fp))<<16;
|
|
368 return result;
|
|
369 }
|
|
370
|
|
371 #else
|
|
372
|
|
373 UWORD _mm_read_M_UWORD(FILE *fp)
|
|
374 {
|
|
375 UWORD result=((UWORD)_mm_read_UBYTE(fp))<<8;
|
|
376 result|=_mm_read_UBYTE(fp);
|
|
377 return result;
|
|
378 }
|
|
379
|
|
380 UWORD _mm_read_I_UWORD(FILE *fp)
|
|
381 {
|
|
382 UWORD result=_mm_read_UBYTE(fp);
|
|
383 result|=((UWORD)_mm_read_UBYTE(fp))<<8;
|
|
384 return result;
|
|
385 }
|
|
386
|
|
387 ULONG _mm_read_M_ULONG(FILE *fp)
|
|
388 {
|
|
389 ULONG result=((ULONG)_mm_read_M_UWORD(fp))<<16;
|
|
390 result|=_mm_read_M_UWORD(fp);
|
|
391 return result;
|
|
392 }
|
|
393
|
|
394 ULONG _mm_read_I_ULONG(FILE *fp)
|
|
395 {
|
|
396 ULONG result=_mm_read_I_UWORD(fp);
|
|
397 result|=((ULONG)_mm_read_I_UWORD(fp))<<16;
|
|
398 return result;
|
|
399 }
|
|
400
|
|
401 #endif
|
|
402
|
|
403 SWORD _mm_read_M_SWORD(FILE *fp)
|
|
404 {
|
|
405 return((SWORD)_mm_read_M_UWORD(fp));
|
|
406 }
|
|
407
|
|
408 SWORD _mm_read_I_SWORD(FILE *fp)
|
|
409 {
|
|
410 return((SWORD)_mm_read_I_UWORD(fp));
|
|
411 }
|
|
412
|
|
413 SLONG _mm_read_M_SLONG(FILE *fp)
|
|
414 {
|
|
415 return((SLONG)_mm_read_M_ULONG(fp));
|
|
416 }
|
|
417
|
|
418 SLONG _mm_read_I_SLONG(FILE *fp)
|
|
419 {
|
|
420 return((SLONG)_mm_read_I_ULONG(fp));
|
|
421 }
|
|
422
|
|
423
|
|
424 int _mm_read_string(CHAR *buffer, int number, FILE *fp)
|
|
425 {
|
|
426 fread(buffer,1,number,fp);
|
|
427 return !feof(fp);
|
|
428 }
|
|
429
|
|
430
|
|
431
|
|
432 #define DEFINE_MULTIPLE_READ_FUNCTION(type_name, type) \
|
|
433 int \
|
|
434 _mm_read_##type_name##S (type *buffer, int number, FILE *fp) \
|
|
435 { \
|
|
436 while(number>0) \
|
|
437 { *(buffer++)=_mm_read_##type_name(fp); \
|
|
438 number--; \
|
|
439 } \
|
|
440 return !feof(fp); \
|
|
441 }
|
|
442
|
|
443 //DEFINE_MULTIPLE_READ_FUNCTION (SBYTE, SBYTE)
|
|
444 //DEFINE_MULTIPLE_READ_FUNCTION (UBYTE, UBYTE)
|
|
445
|
|
446 DEFINE_MULTIPLE_READ_FUNCTION (M_SWORD, SWORD)
|
|
447 DEFINE_MULTIPLE_READ_FUNCTION (M_UWORD, UWORD)
|
|
448 DEFINE_MULTIPLE_READ_FUNCTION (I_SWORD, SWORD)
|
|
449 DEFINE_MULTIPLE_READ_FUNCTION (I_UWORD, UWORD)
|
|
450
|
|
451 DEFINE_MULTIPLE_READ_FUNCTION (M_SLONG, SLONG)
|
|
452 DEFINE_MULTIPLE_READ_FUNCTION (M_ULONG, ULONG)
|
|
453 DEFINE_MULTIPLE_READ_FUNCTION (I_SLONG, SLONG)
|
|
454 DEFINE_MULTIPLE_READ_FUNCTION (I_ULONG, ULONG)
|
|
455
|