Mercurial > ~darius > hgwebdir.cgi > mikmod
diff mmio/mmio.c @ 10:55420dceb8e0
Initial entry of mikmod into the CVS tree.
author | darius |
---|---|
date | Fri, 23 Jan 1998 16:05:11 +0000 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mmio/mmio.c Fri Jan 23 16:05:11 1998 +0000 @@ -0,0 +1,455 @@ +/* + --> The MMIO Portable Input/Output functions + -> Divine Entertainment GameDev Libraries + + File: MMIO.C + + Description: + Miscellaneous I/O routines.. used to solve some portability issues + (like big/little endian machines and word alignment in structures ) + Also includes mikmod's ingenious error handling variable. + + Portability: + All systems - all compilers + + + ----------------------------------- + The way this module works - By Jake Stine [Air Richter] + + - _mm_fopen and _mm_copyfile 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 ML_LoadFP() to ensure that it + works properly with wad files. + + - _mm_read_I_UWORD and _mm_read_M_UWORD have distinct differences: + 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. +*/ + +#include "mmio.h" +#include <string.h> + +#define COPY_BUFSIZE 1024 + +static long _mm_iobase = 0, + temp_iobase = 0; + +UBYTE _mm_cpybuf[COPY_BUFSIZE]; + + +void StringWrite(CHAR *s, FILE *fp) +// Specialized file output procedure. Writes a UWORD length and then a +// string of the specified length (no NULL terminator) afterward. +{ + int slen; + + if(s==NULL) + { _mm_write_I_UWORD(0,fp); + } else + { _mm_write_I_UWORD(slen = strlen(s),fp); + _mm_write_UBYTES(s,slen,fp); + } +} + +CHAR *StringRead(FILE *fp) +// Reads strings written out by StringWrite above: a UWORD length followed +// by length characters. A NULL is added to the string after loading. +{ + CHAR *s; + UWORD len; + + len = _mm_read_I_UWORD(fp); + if(len==0) + { s = _mm_calloc(16, sizeof(CHAR)); + } else + { if((s = (CHAR *)_mm_malloc(len+1)) == NULL) return NULL; + _mm_read_UBYTES(s,len,fp); + s[len] = 0; + } + + return s; +} + + +FILE *_mm_fopen(CHAR *fname, CHAR *attrib) +{ + FILE *fp; + + if((fp=fopen(fname,attrib)) == NULL) + { _mm_errno = _mm_errno = MMERR_OPENING_FILE; + if(_mm_errorhandler!=NULL) _mm_errorhandler(); + } + return fp; +} + + +int _mm_fseek(FILE *stream, long offset, int whence) +{ + return fseek(stream,(whence==SEEK_SET) ? offset+_mm_iobase : offset, whence); +} + + +long _mm_ftell(FILE *stream) +{ + return ftell(stream)-_mm_iobase; +} + + +BOOL _mm_FileExists(CHAR *fname) +{ + FILE *fp; + + if((fp=fopen(fname,"r")) == NULL) return 0; + fclose(fp); + + return 1; +} + + +long _mm_flength(FILE *stream) +{ + long tmp,tmp2; + + tmp = ftell(stream); + fseek(stream,0,SEEK_END); + tmp2 = ftell(stream); + fseek(stream,tmp,SEEK_SET); + return tmp2-tmp; +} + + +long _mm_iobase_get(void) +{ + return _mm_iobase; +} + + +void _mm_iobase_set(long iobase) +{ + temp_iobase = _mm_iobase; // store old value in case of revert + _mm_iobase = iobase; +} + + +// Sets the current file-position as the new _mm_iobase +void _mm_iobase_setcur(FILE *fp) +{ + temp_iobase = _mm_iobase; // store old value in case of revert + _mm_iobase = ftell(fp); +} + + +// Reverts to the last known _mm_iobase value. +void _mm_iobase_revert(void) +{ + _mm_iobase = temp_iobase; +} + + +// Procedure: _mm_copyfile +// Copies a given number of bytes from the source file to the destination +// file. Returns 1 on error, and calls the _mm_errnohandler, if registered. +BOOL _mm_copyfile(FILE *fpi, FILE *fpo, ULONG len) +{ + ULONG todo; + + while(len) + { todo = (len > COPY_BUFSIZE) ? COPY_BUFSIZE : len; + if(!fread(_mm_cpybuf, todo, 1, fpi)) + { _mm_errno = _mm_errno = MMERR_END_OF_FILE; + if(_mm_errorhandler!=NULL) _mm_errorhandler(); + return 1; + } + if(!fwrite(_mm_cpybuf, todo, 1, fpo)) + { _mm_errno = _mm_errno = MMERR_DISK_FULL; + if(_mm_errorhandler!=NULL) _mm_errorhandler(); + return 1; + } + len -= todo; + } + + return 0; +} + + +void _mm_write_string(CHAR *data, FILE *fp) +{ + if(data!=NULL) + _mm_write_UBYTES(data, strlen(data), fp); +} + + +void _mm_fputs(FILE *fp, CHAR *data) +{ + if(data != NULL) + _mm_write_UBYTES(data, strlen(data), fp); + +#ifndef __UNIX__ + _mm_write_UBYTE(13,fp); +#endif + _mm_write_UBYTE(10,fp); +} + + + +/************* +// These have accompanying #define's in mmio.h + +void _mm_write_SBYTE(SBYTE data, FILE *fp) +{ + fputc(data,fp); +} + +void _mm_write_UBYTE(UBYTE data,FILE *fp) +{ + fputc(data,fp); +} +*/ + +#ifdef MM_BIG_ENDIAN + +// --> Big Endian Write Functions + +void _mm_write_M_UWORD(UWORD data,FILE *fp) +{ + _mm_write_UBYTE(data&0xff,fp); + _mm_write_UBYTE(data>>8,fp); +} + + +void _mm_write_I_UWORD(UWORD data,FILE *fp) +{ + _mm_write_UBYTE(data>>8,fp); + _mm_write_UBYTE(data&0xff,fp); +} + + +void _mm_write_M_ULONG(ULONG data,FILE *fp) +{ + _mm_write_M_UWORD(data&0xffff,fp); + _mm_write_M_UWORD(data>>16,fp); +} + + +void _mm_write_I_ULONG(ULONG data,FILE *fp) +{ + _mm_write_I_UWORD(data>>16,fp); + _mm_write_I_UWORD(data&0xffff,fp); +} + +#else + +// --> Little Endian Write Functions + +void _mm_write_M_UWORD(UWORD data,FILE *fp) +{ + _mm_write_UBYTE(data>>8,fp); + _mm_write_UBYTE(data&0xff,fp); +} + + +void _mm_write_I_UWORD(UWORD data,FILE *fp) +{ + _mm_write_UBYTE(data&0xff,fp); + _mm_write_UBYTE(data>>8,fp); +} + + +void _mm_write_M_ULONG(ULONG data,FILE *fp) +{ + _mm_write_M_UWORD(data>>16,fp); + _mm_write_M_UWORD(data&0xffff,fp); +} + + +void _mm_write_I_ULONG(ULONG data,FILE *fp) +{ + _mm_write_I_UWORD(data&0xffff,fp); + _mm_write_I_UWORD(data>>16,fp); +} + +#endif + + +void _mm_write_M_SWORD(SWORD data,FILE *fp) +{ + _mm_write_M_UWORD((UWORD)data,fp); +} + + +void _mm_write_I_SWORD(SWORD data,FILE *fp) +{ + _mm_write_I_UWORD((UWORD)data,fp); +} + + +void _mm_write_M_SLONG(SLONG data,FILE *fp) +{ + _mm_write_M_ULONG((ULONG)data,fp); +} + + +void _mm_write_I_SLONG(SLONG data,FILE *fp) +{ + _mm_write_I_ULONG((ULONG)data,fp); +} + + +#define DEFINE_MULTIPLE_WRITE_FUNCTION(type_name, type) \ +void \ +_mm_write_##type_name##S (type *buffer, int number, FILE *fp) \ +{ \ + while(number>0) \ + { _mm_write_##type_name(*(buffer++),fp); \ + number--; \ + } \ +} + +//DEFINE_MULTIPLE_WRITE_FUNCTION (SBYTE, SBYTE) +//DEFINE_MULTIPLE_WRITE_FUNCTION (UBYTE, UBYTE) + +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) + +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) + + +/********** +SBYTE _mm_read_SBYTE(FILE *fp) +{ + return(fgetc(fp)); +} + +UBYTE _mm_read_UBYTE(FILE *fp) +{ + return(fgetc(fp)); +} +**********/ + + +#ifdef MM_BIG_ENDIAN + +UWORD _mm_read_I_UWORD(FILE *fp) +{ + UWORD result=((UWORD)_mm_read_UBYTE(fp))<<8; + result|=_mm_read_UBYTE(fp); + return result; +} + +UWORD _mm_read_M_UWORD(FILE *fp) +{ + UWORD result=_mm_read_UBYTE(fp); + result|=((UWORD)_mm_read_UBYTE(fp))<<8; + return result; +} + +ULONG _mm_read_I_ULONG(FILE *fp) +{ + ULONG result=((ULONG)_mm_read_M_UWORD(fp))<<16; + result|=_mm_read_M_UWORD(fp); + return result; +} + +ULONG _mm_read_M_ULONG(FILE *fp) +{ + ULONG result=_mm_read_I_UWORD(fp); + result|=((ULONG)_mm_read_I_UWORD(fp))<<16; + return result; +} + +#else + +UWORD _mm_read_M_UWORD(FILE *fp) +{ + UWORD result=((UWORD)_mm_read_UBYTE(fp))<<8; + result|=_mm_read_UBYTE(fp); + return result; +} + +UWORD _mm_read_I_UWORD(FILE *fp) +{ + UWORD result=_mm_read_UBYTE(fp); + result|=((UWORD)_mm_read_UBYTE(fp))<<8; + return result; +} + +ULONG _mm_read_M_ULONG(FILE *fp) +{ + ULONG result=((ULONG)_mm_read_M_UWORD(fp))<<16; + result|=_mm_read_M_UWORD(fp); + return result; +} + +ULONG _mm_read_I_ULONG(FILE *fp) +{ + ULONG result=_mm_read_I_UWORD(fp); + result|=((ULONG)_mm_read_I_UWORD(fp))<<16; + return result; +} + +#endif + +SWORD _mm_read_M_SWORD(FILE *fp) +{ + return((SWORD)_mm_read_M_UWORD(fp)); +} + +SWORD _mm_read_I_SWORD(FILE *fp) +{ + return((SWORD)_mm_read_I_UWORD(fp)); +} + +SLONG _mm_read_M_SLONG(FILE *fp) +{ + return((SLONG)_mm_read_M_ULONG(fp)); +} + +SLONG _mm_read_I_SLONG(FILE *fp) +{ + return((SLONG)_mm_read_I_ULONG(fp)); +} + + +int _mm_read_string(CHAR *buffer, int number, FILE *fp) +{ + fread(buffer,1,number,fp); + return !feof(fp); +} + + + +#define DEFINE_MULTIPLE_READ_FUNCTION(type_name, type) \ +int \ +_mm_read_##type_name##S (type *buffer, int number, FILE *fp) \ +{ \ + while(number>0) \ + { *(buffer++)=_mm_read_##type_name(fp); \ + number--; \ + } \ + return !feof(fp); \ +} + +//DEFINE_MULTIPLE_READ_FUNCTION (SBYTE, SBYTE) +//DEFINE_MULTIPLE_READ_FUNCTION (UBYTE, UBYTE) + +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) + +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) +