diff options
author | Alexey Yakovenko <wakeroid@gmail.com> | 2009-12-19 15:46:14 +0100 |
---|---|---|
committer | Alexey Yakovenko <wakeroid@gmail.com> | 2009-12-19 15:46:14 +0100 |
commit | 3f060fbd1ded8236ad27988173011ef9e9298a20 (patch) | |
tree | c7575a02421c08ad0a83fb21ece5d412d40e43dd /plugins/adplug/libbinio | |
parent | 25f13980b6f30093f80174c8055cc42a47772d0d (diff) |
adplug plugin WIP (insert works)
Diffstat (limited to 'plugins/adplug/libbinio')
-rw-r--r-- | plugins/adplug/libbinio/binfile.cpp | 247 | ||||
-rw-r--r-- | plugins/adplug/libbinio/binfile.h | 110 | ||||
-rw-r--r-- | plugins/adplug/libbinio/binio.cpp | 640 | ||||
-rw-r--r-- | plugins/adplug/libbinio/binio.h | 175 | ||||
-rw-r--r-- | plugins/adplug/libbinio/binstr.cpp | 114 | ||||
-rw-r--r-- | plugins/adplug/libbinio/binstr.h | 66 | ||||
-rw-r--r-- | plugins/adplug/libbinio/binwrap.cpp | 132 | ||||
-rw-r--r-- | plugins/adplug/libbinio/binwrap.h | 92 |
8 files changed, 1576 insertions, 0 deletions
diff --git a/plugins/adplug/libbinio/binfile.cpp b/plugins/adplug/libbinio/binfile.cpp new file mode 100644 index 00000000..446f899f --- /dev/null +++ b/plugins/adplug/libbinio/binfile.cpp @@ -0,0 +1,247 @@ +/* + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser 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 + * + * binfile.h - Binary file I/O + * Copyright (C) 2002, 2003 Simon Peter <dn.tlp@gmx.net> + */ + +#include <stdio.h> +#include <errno.h> + +#include "binfile.h" + +/***** binfbase *****/ + +binfbase::binfbase() + : f(NULL) +{ +} + +binfbase::~binfbase() +{ + if(f != NULL) close(); +} + +void binfbase::close() +{ + if(f != NULL) { + if(fclose(f) == EOF) err |= Fatal; else f = NULL; + } else + err |= NotOpen; +} + +void binfbase::seek(long pos, Offset offs) +{ + int error; + + if(f == NULL) { err |= NotOpen; return; } + + switch(offs) { + case Set: error = fseek(f, pos, SEEK_SET); break; + case Add: error = fseek(f, pos, SEEK_CUR); break; + case End: error = fseek(f, pos, SEEK_END); break; + } + + if(error == -1) err |= Fatal; +} + +long binfbase::pos() +{ + long pos; + + if(f == NULL) { err |= NotOpen; return 0; } + + pos = ftell(f); + + if(pos == -1) { + err |= Fatal; + return 0; + } else + return pos; +} + +/***** binifstream *****/ + +binifstream::binifstream() +{ +} + +binifstream::binifstream(const char *filename, const Mode mode) +{ + open(filename, mode); +} + +#if BINIO_ENABLE_STRING +binifstream::binifstream(const std::string &filename, const Mode mode) +{ + open(filename, mode); +} +#endif + +binifstream::~binifstream() +{ +} + +void binifstream::open(const char *filename, const Mode mode) +{ + f = fopen(filename, "rb"); + + if(f == NULL) + switch(errno) { + case ENOENT: err |= NotFound; break; + case EACCES: err |= Denied; break; + default: err |= NotOpen; break; + } +} + +#if BINIO_ENABLE_STRING +void binifstream::open(const std::string &filename, const Mode mode) +{ + open(filename.c_str(), mode); +} +#endif + +binifstream::Byte binifstream::getByte() +{ + int read; + + if(f != NULL) { + read = fgetc(f); + if(read == EOF) err |= Eof; + return (Byte)read; + } else { + err |= NotOpen; + return 0; + } +} + +/***** binofstream *****/ + +binofstream::binofstream() +{ +} + +binofstream::binofstream(const char *filename, const Mode mode) +{ + open(filename, mode); +} + +#if BINIO_ENABLE_STRING +binofstream::binofstream(const std::string &filename, const Mode mode) +{ + open(filename, mode); +} +#endif + +binofstream::~binofstream() +{ +} + +void binofstream::open(const char *filename, const Mode mode) +{ + char *modestr = "wb"; + + // Check if append mode is desired + if(mode & Append) modestr = "ab"; + + f = fopen(filename, modestr); + + if(f == NULL) + switch(errno) { + case EEXIST: + case EACCES: + case EROFS: + err |= Denied; + break; + case ENOENT: err |= NotFound; break; + default: err |= NotOpen; break; + } +} + +#if BINIO_ENABLE_STRING +void binofstream::open(const std::string &filename, const Mode mode) +{ + open(filename.c_str(), mode); +} +#endif + +void binofstream::putByte(Byte b) +{ + if(f == NULL) { err |= NotOpen; return; } + + if(fputc(b, f) == EOF) + err |= Fatal; +} + +/***** binfstream *****/ + +binfstream::binfstream() +{ +} + +binfstream::binfstream(const char *filename, const Mode mode) +{ + open(filename, mode); +} + +#if BINIO_ENABLE_STRING +binfstream::binfstream(const std::string &filename, const Mode mode) +{ + open(filename, mode); +} +#endif + +binfstream::~binfstream() +{ +} + +void binfstream::open(const char *filename, const Mode mode) +{ + char *modestr = "w+b"; // Create & at beginning + int ferror = 0; + + // Apply desired mode + if(mode & NoCreate) { + if(!(mode & Append)) + modestr[0] = 'r'; // NoCreate & at beginning + } else + if(mode & Append) // Create & append + modestr[0] = 'a'; + + f = fopen(filename, modestr); + + // NoCreate & append (emulated -- not possible with standard C fopen()) + if(f != NULL && (mode & Append) && (mode & NoCreate)) + ferror = fseek(f, 0, SEEK_END); + + if(f == NULL || ferror == -1) { + switch(errno) { + case EEXIST: + case EACCES: + case EROFS: + err |= Denied; + break; + case ENOENT: err |= NotFound; break; + default: err |= NotOpen; break; + } + } +} + +#if BINIO_ENABLE_STRING +void binfstream::open(const std::string &filename, const Mode mode) +{ + open(filename.c_str(), mode); +} +#endif diff --git a/plugins/adplug/libbinio/binfile.h b/plugins/adplug/libbinio/binfile.h new file mode 100644 index 00000000..ad24baee --- /dev/null +++ b/plugins/adplug/libbinio/binfile.h @@ -0,0 +1,110 @@ +/* + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser 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 + * + * binfile.h - Binary file I/O + * Copyright (C) 2002, 2003 Simon Peter <dn.tlp@gmx.net> + */ + +#ifndef H_BINIO_BINFILE +#define H_BINIO_BINFILE + +#include <stdio.h> + +#include "binio.h" + +class binfbase: virtual public binio +{ +public: + typedef enum { + Append = 1 << 0, + NoCreate = 1 << 1 + } ModeFlags; + + typedef int Mode; + + binfbase(); + virtual ~binfbase(); + + virtual void open(const char *filename, const Mode mode) = 0; +#if BINIO_ENABLE_STRING + virtual void open(const std::string &filename, const Mode mode) = 0; +#endif + void close(); + + virtual void seek(long pos, Offset offs = Set); + virtual long pos(); + +protected: + FILE *f; +}; + +class binifstream: public binistream, virtual public binfbase +{ +public: + binifstream(); + binifstream(const char *filename, const Mode mode = NoCreate); +#if BINIO_ENABLE_STRING + binifstream(const std::string &filename, const Mode mode = NoCreate); +#endif + + virtual ~binifstream(); + + virtual void open(const char *filename, const Mode mode = NoCreate); +#if BINIO_ENABLE_STRING + virtual void open(const std::string &filename, const Mode mode = NoCreate); +#endif + +protected: + virtual Byte getByte(); +}; + +class binofstream: public binostream, virtual public binfbase +{ +public: + binofstream(); + binofstream(const char *filename, const Mode mode = 0); +#if BINIO_ENABLE_STRING + binofstream(const std::string &filename, const Mode mode = 0); +#endif + + virtual ~binofstream(); + + virtual void open(const char *filename, const Mode mode = 0); +#if BINIO_ENABLE_STRING + virtual void open(const std::string &filename, const Mode mode = 0); +#endif + +protected: + virtual void putByte(Byte b); +}; + +class binfstream: public binifstream, public binofstream +{ +public: + binfstream(); + binfstream(const char *filename, const Mode mode = 0); +#if BINIO_ENABLE_STRING + binfstream(const std::string &filename, const Mode mode = 0); +#endif + + virtual ~binfstream(); + + virtual void open(const char *filename, const Mode mode = 0); +#if BINIO_ENABLE_STRING + virtual void open(const std::string &filename, const Mode mode = 0); +#endif +}; + +#endif diff --git a/plugins/adplug/libbinio/binio.cpp b/plugins/adplug/libbinio/binio.cpp new file mode 100644 index 00000000..75489788 --- /dev/null +++ b/plugins/adplug/libbinio/binio.cpp @@ -0,0 +1,640 @@ +/* + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser 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 + * + * binio.cpp - Binary stream I/O classes + * Copyright (C) 2002, 2003 Simon Peter <dn.tlp@gmx.net> + */ + +#include <string.h> + +#include "binio.h" + +#if BINIO_WITH_MATH + +#include <math.h> + +#ifdef __QNXNTO__ + #define pow std::powf +#endif // __QNXNTO__ + +// If 'math.h' doesn't define HUGE_VAL, we try to use HUGE instead. +#ifndef HUGE_VAL +# define HUGE_VAL HUGE +#endif + +#endif + +/***** Defines *****/ + +#if BINIO_ENABLE_STRING +// String buffer size for std::string readString() method +#define STRINGBUFSIZE 256 +#endif + +/***** binio *****/ + +const binio::Flags binio::system_flags = binio::detect_system_flags(); + +const binio::Flags binio::detect_system_flags() +{ + Flags f = 0; + + // Endian test + union { + int word; + Byte byte; + } endian_test; + + endian_test.word = 1; + if(endian_test.byte != 1) f |= BigEndian; + + // IEEE-754 floating-point test + float fl = 6.5; + Byte *dat = (Byte *)&fl; + + if(sizeof(float) == 4 && sizeof(double) == 8) + if(f & BigEndian) { + if(dat[0] == 0x40 && dat[1] == 0xD0 && !dat[2] && !dat[3]) + f |= FloatIEEE; + } else + if(dat[3] == 0x40 && dat[2] == 0xD0 && !dat[1] && !dat[0]) + f |= FloatIEEE; + + return f; +} + +binio::binio() + : my_flags(system_flags), err(NoError) +{ +} + +binio::~binio() +{ +} + +void binio::setFlag(Flag f, bool set) +{ + if(set) + my_flags |= f; + else + my_flags &= !f; +} + +bool binio::getFlag(Flag f) +{ + return (my_flags & f ? true : false); +} + +binio::Error binio::error() +{ + Error e = err; + + err = NoError; + return e; +} + +bool binio::eof() +{ + return (err & Eof ? true : false); +} + +/***** binistream *****/ + +binistream::binistream() +{ +} + +binistream::~binistream() +{ +} + +binistream::Int binistream::readInt(unsigned int size) +{ + unsigned int i; + Int val = 0, in; + + // Check if 'size' doesn't exceed our system's biggest type. + if(size > sizeof(Int)) { + err |= Unsupported; + return 0; + } + + for(i = 0; i < size; i++) { + in = getByte(); + if(getFlag(BigEndian)) + val <<= 8; + else + in <<= i * 8; + val |= in; + } + + return val; +} + +binistream::Float binistream::readFloat(FType ft) +{ + if(getFlag(FloatIEEE)) { // Read IEEE-754 floating-point value + unsigned int i, size; + Byte in[8]; + bool swap; + + // Determine appropriate size for given type. + switch(ft) { + case Single: size = 4; break; // 32 bits + case Double: size = 8; break; // 64 bits + } + + // Determine byte ordering, depending on what we do next + if(system_flags & FloatIEEE) + swap = getFlag(BigEndian) ^ (system_flags & BigEndian); + else + swap = !getFlag(BigEndian); + + // Read the float byte by byte, converting endianess + for(i = 0; i < size; i++) + if(swap) + in[size - i - 1] = getByte(); + else + in[i] = getByte(); + + if(system_flags & FloatIEEE) { + // Compatible system, let the hardware do the conversion + switch(ft) { + case Single: return *(float *)in; + case Double: return *(double *)in; + } + } else { // Incompatible system, convert manually + switch(ft) { + case Single: return ieee_single2float(in); + case Double: return ieee_double2float(in); + } + } + } + + // User tried to read a (yet) unsupported floating-point type. Bail out. + err |= Unsupported; return 0.0; +} + +binistream::Float binistream::ieee_single2float(Byte *data) +{ + signed int sign = data[0] >> 7 ? -1 : 1; + unsigned int exp = ((data[0] << 1) & 0xff) | ((data[1] >> 7) & 1), + fracthi7 = data[1] & 0x7f; + Float fract = fracthi7 * 65536.0 + data[2] * 256.0 + data[3]; + + // Signed and unsigned zero + if(!exp && !fracthi7 && !data[2] && !data[3]) return sign * 0.0; + + // Signed and unsigned infinity (maybe unsupported on non-IEEE systems) + if(exp == 255) + if(!fracthi7 && !data[2] && !data[3]) { +#ifdef HUGE_VAL + if(sign == -1) return -HUGE_VAL; else return HUGE_VAL; +#else + err |= Unsupported; + if(sign == -1) return -1.0; else return 1.0; +#endif + } else { // Not a number (maybe unsupported on non-IEEE systems) +#ifdef NAN + return NAN; +#else + err |= Unsupported; return 0.0; +#endif + } + + if(!exp) // Unnormalized float values + return sign * pow(2, -126) * fract * pow(2, -23); + else // Normalized float values + return sign * pow(2, exp - 127) * (fract * pow(2, -23) + 1); + + err |= Fatal; return 0.0; +} + +binistream::Float binistream::ieee_double2float(Byte *data) +{ + signed int sign = data[0] >> 7 ? -1 : 1; + unsigned int exp = ((unsigned int)(data[0] & 0x7f) << 4) | (data[1] >> 4), + fracthi4 = data[1] & 0xf; + Float fract = fracthi4 * pow(2, 48) + data[2] * pow(2, 40) + data[3] * + pow(2, 32) + data[4] * pow(2, 24) + data[5] * pow(2, 16) + data[6] * + pow(2, 8) + data[7]; + + // Signed and unsigned zero + if(!exp && !fracthi4 && !data[2] && !data[3] && !data[4] && !data[5] && + !data[6] && !data[7]) return sign * 0.0; + + // Signed and unsigned infinity (maybe unsupported on non-IEEE systems) + if(exp == 2047) + if(!fracthi4 && !data[2] && !data[3] && !data[4] && !data[5] && !data[6] && + !data[7]) { +#ifdef HUGE_VAL + if(sign == -1) return -HUGE_VAL; else return HUGE_VAL; +#else + err |= Unsupported; + if(sign == -1) return -1.0; else return 1.0; +#endif + } else { // Not a number (maybe unsupported on non-IEEE systems) +#ifdef NAN + return NAN; +#else + err |= Unsupported; return 0.0; +#endif + } + + if(!exp) // Unnormalized float values + return sign * pow(2, -1022) * fract * pow(2, -52); + else // Normalized float values + return sign * pow(2, exp - 1023) * (fract * pow(2, -52) + 1); + + err |= Fatal; return 0.0; +} + +#if !BINIO_WITH_MATH +binio::Float binio::pow(Float base, signed int exp) +/* Our own, stripped-down version of pow() for not having to depend on 'math.h'. + * This one handles float values for the base and an integer exponent, both + * positive and negative. + */ +{ + int i; + Float val = base; + + if(!exp) return 1.0; + + for(i = 1; i < (exp < 0 ? -exp : exp); i++) + val *= base; + + if(exp < 0) val = 1.0 / val; + + return val; +} +#endif + +unsigned long binistream::readString(char *str, unsigned long maxlen) +{ + unsigned long i; + + for(i = 0; i < maxlen; i++) { + str[i] = (char)getByte(); + if(err) { str[i] = '\0'; return i; } + } + + return maxlen; +} + +unsigned long binistream::readString(char *str, unsigned long maxlen, + const char delim) +{ + unsigned long i; + + for(i = 0; i < maxlen; i++) { + str[i] = (char)getByte(); + if(str[i] == delim || err) { str[i] = '\0'; return i; } + } + + str[maxlen] = '\0'; + return maxlen; +} + +#if BINIO_ENABLE_STRING +std::string binistream::readString(const char delim) +{ + char buf[STRINGBUFSIZE + 1]; + std::string tempstr; + unsigned long read; + + do { + read = readString(buf, STRINGBUFSIZE, delim); + tempstr.append(buf, read); + } while(read == STRINGBUFSIZE); + + return tempstr; +} +#endif + +binistream::Int binistream::peekInt(unsigned int size) +{ + Int val = readInt(size); + if(!err) seek(-(long)size, Add); + return val; +} + +binistream::Float binistream::peekFloat(FType ft) +{ + Float val = readFloat(ft); + + if(!err) + switch(ft) { + case Single: seek(-4, Add); break; + case Double: seek(-8, Add); break; + } + + return val; +} + +bool binistream::ateof() +{ + Error olderr = err; // Save current error state + bool eof_then; + + peekInt(1); + eof_then = eof(); // Get error state of next byte + err = olderr; // Restore original error state + return eof_then; +} + +void binistream::ignore(unsigned long amount) +{ + unsigned long i; + + for(i = 0; i < amount; i++) + getByte(); +} + +/***** binostream *****/ + +binostream::binostream() +{ +} + +binostream::~binostream() +{ +} + +void binostream::writeInt(Int val, unsigned int size) +{ + unsigned int i; + + // Check if 'size' doesn't exceed our system's biggest type. + if(size > sizeof(Int)) { err |= Unsupported; return; } + + for(i = 0; i < size; i++) { + if(getFlag(BigEndian)) + putByte((val >> (size - i - 1) * 8) & 0xff); + else { + putByte(val & 0xff); + val >>= 8; + } + } +} + +void binostream::writeFloat(Float f, FType ft) +{ + if(getFlag(FloatIEEE)) { // Write IEEE-754 floating-point value + unsigned int i, size; + Byte *out; + bool swap; + + if(system_flags & FloatIEEE) { + // compatible system, let the hardware do the conversion + float outf = f; + double outd = f; + + // Hardware could be big or little endian, convert appropriately + swap = getFlag(BigEndian) ^ (system_flags & BigEndian); + + // Determine appropriate size for given type and convert by hardware + switch(ft) { + case Single: size = 4; out = (Byte *)&outf; break; // 32 bits + case Double: size = 8; out = (Byte *)&outd; break; // 64 bits + } + } else { +#if BINIO_WITH_MATH + // incompatible system, do the conversion manually + Byte buf[8]; + + // Our own value is always big endian, just check whether we have to + // convert for a different stream format. + swap = !getFlag(BigEndian); + + // Convert system's float to requested IEEE-754 float + switch(ft) { + case Single: size = 4; float2ieee_single(f, buf); break; + case Double: size = 8; float2ieee_double(f, buf); break; + } + + out = buf; // Make the value ready for writing +#else + // No necessary support routines to do the conversion, bail out! + err |= Unsupported; return; +#endif + } + + // Write the float byte by byte, converting endianess + if(swap) out += size - 1; + for(i = 0; i < size; i++) { + putByte(*out); + if(swap) out--; else out++; + } + + return; // We're done. + } + + // User tried to write an unsupported floating-point type. Bail out. + err |= Unsupported; +} + +#ifdef BINIO_WITH_MATH + +/* + * Single and double floating-point to IEEE-754 equivalent conversion functions + * courtesy of Ken Turkowski. + * + * Copyright (C) 1989-1991 Ken Turkowski. <turk@computer.org> + * + * All rights reserved. + * + * Warranty Information + * Even though I have reviewed this software, I make no warranty + * or representation, either express or implied, with respect to this + * software, its quality, accuracy, merchantability, or fitness for a + * particular purpose. As a result, this software is provided "as is," + * and you, its user, are assuming the entire risk as to its quality + * and accuracy. + * + * This code may be used and freely distributed as long as it includes + * this copyright notice and the above warranty information. + */ + +/**************************************************************** + * The following two routines make up for deficiencies in many + * compilers to convert properly between unsigned integers and + * floating-point. Some compilers which have this bug are the + * THINK_C compiler for the Macintosh and the C compiler for the + * Silicon Graphics MIPS-based Iris. + ****************************************************************/ + +#ifdef applec /* The Apple C compiler works */ +# define FloatToUnsigned(f) ((unsigned long)(f)) +#else +# define FloatToUnsigned(f) ((unsigned long)(((long)((f) - 2147483648.0)) + 2147483647L + 1)) +#endif + +#define SEXP_MAX 255 +#define SEXP_OFFSET 127 +#define SEXP_SIZE 8 +#define SEXP_POSITION (32-SEXP_SIZE-1) + +void binostream::float2ieee_single(Float num, Byte *bytes) +{ + long sign; + register long bits; + + if (num < 0) { /* Can't distinguish a negative zero */ + sign = 0x80000000; + num *= -1; + } else { + sign = 0; + } + + if (num == 0) { + bits = 0; + } else { + Float fMant; + int expon; + + fMant = frexp(num, &expon); + + if ((expon > (SEXP_MAX-SEXP_OFFSET+1)) || !(fMant < 1)) { + /* NaN's and infinities fail second test */ + bits = sign | 0x7F800000; /* +/- infinity */ + } + + else { + long mantissa; + + if (expon < -(SEXP_OFFSET-2)) { /* Smaller than normalized */ + int shift = (SEXP_POSITION+1) + (SEXP_OFFSET-2) + expon; + if (shift < 0) { /* Way too small: flush to zero */ + bits = sign; + } + else { /* Nonzero denormalized number */ + mantissa = (long)(fMant * (1L << shift)); + bits = sign | mantissa; + } + } + + else { /* Normalized number */ + mantissa = (long)floor(fMant * (1L << (SEXP_POSITION+1))); + mantissa -= (1L << SEXP_POSITION); /* Hide MSB */ + bits = sign | ((long)((expon + SEXP_OFFSET - 1)) << SEXP_POSITION) | mantissa; + } + } + } + + bytes[0] = bits >> 24; /* Copy to byte string */ + bytes[1] = bits >> 16; + bytes[2] = bits >> 8; + bytes[3] = bits; +} + +#define DEXP_MAX 2047 +#define DEXP_OFFSET 1023 +#define DEXP_SIZE 11 +#define DEXP_POSITION (32-DEXP_SIZE-1) + +void binostream::float2ieee_double(Float num, Byte *bytes) +{ + long sign; + long first, second; + + if (num < 0) { /* Can't distinguish a negative zero */ + sign = 0x80000000; + num *= -1; + } else { + sign = 0; + } + + if (num == 0) { + first = 0; + second = 0; + } else { + Float fMant, fsMant; + int expon; + + fMant = frexp(num, &expon); + + if ((expon > (DEXP_MAX-DEXP_OFFSET+1)) || !(fMant < 1)) { + /* NaN's and infinities fail second test */ + first = sign | 0x7FF00000; /* +/- infinity */ + second = 0; + } + + else { + long mantissa; + + if (expon < -(DEXP_OFFSET-2)) { /* Smaller than normalized */ + int shift = (DEXP_POSITION+1) + (DEXP_OFFSET-2) + expon; + if (shift < 0) { /* Too small for something in the MS word */ + first = sign; + shift += 32; + if (shift < 0) { /* Way too small: flush to zero */ + second = 0; + } + else { /* Pretty small demorn */ + second = FloatToUnsigned(floor(ldexp(fMant, shift))); + } + } + else { /* Nonzero denormalized number */ + fsMant = ldexp(fMant, shift); + mantissa = (long)floor(fsMant); + first = sign | mantissa; + second = FloatToUnsigned(floor(ldexp(fsMant - mantissa, 32))); + } + } + + else { /* Normalized number */ + fsMant = ldexp(fMant, DEXP_POSITION+1); + mantissa = (long)floor(fsMant); + mantissa -= (1L << DEXP_POSITION); /* Hide MSB */ + fsMant -= (1L << DEXP_POSITION); + first = sign | ((long)((expon + DEXP_OFFSET - 1)) << DEXP_POSITION) | mantissa; + second = FloatToUnsigned(floor(ldexp(fsMant - mantissa, 32))); + } + } + } + + bytes[0] = first >> 24; + bytes[1] = first >> 16; + bytes[2] = first >> 8; + bytes[3] = first; + bytes[4] = second >> 24; + bytes[5] = second >> 16; + bytes[6] = second >> 8; + bytes[7] = second; +} + +#endif // BINIO_WITH_MATH + +unsigned long binostream::writeString(const char *str, unsigned long amount) +{ + unsigned int i; + + if(!amount) amount = strlen(str); + + for(i = 0; i < amount; i++) { + putByte(str[i]); + if(err) return i; + } + + return amount; +} + +#if BINIO_ENABLE_STRING +unsigned long binostream::writeString(const std::string &str) +{ + return writeString(str.c_str()); +} +#endif diff --git a/plugins/adplug/libbinio/binio.h b/plugins/adplug/libbinio/binio.h new file mode 100644 index 00000000..31bcfac6 --- /dev/null +++ b/plugins/adplug/libbinio/binio.h @@ -0,0 +1,175 @@ +/* -*-C++-*- + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser 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 + * + * binio.h - Binary stream I/O classes + * Copyright (C) 2002, 2003 Simon Peter <dn.tlp@gmx.net> + */ + +#ifndef H_BINIO_BINIO +#define H_BINIO_BINIO + +/***** Configuration *****/ + +// BINIO_ENABLE_STRING - Build std::string supporting methods +// +// Set to 1 to build std::string supporting methods. You need the STL to +// do this. +#define BINIO_ENABLE_STRING 1 + +// BINIO_ENABLE_IOSTREAM - Build iostream wrapper classes +// +// Set to 1 to build the iostream wrapper classes. You need the standard +// C++ library to do this. +#define BINIO_ENABLE_IOSTREAM 1 + +// BINIO_ISO_STDLIB - Build with ISO C++ standard library compliance +// +// Set to 1 to build for the ISO standard C++ library (i.e. namespaces, STL and +// templatized iostream). Set to 0 to build for the traditional C++ library. +#define BINIO_ISO_STDLIB 1 + +// BINIO_WITH_MATH - Build with 'math.h' dependency to allow float conversions +// +// Set to 1 to also build routines that depend on the 'math.h' standard C header +// file (this sometimes also implies a 'libm' or 'libmath' dependency). These +// routines are needed in order to write IEEE-754 floating-point numbers on a +// system that doesn't support this format natively. For only reading these +// numbers, however, these routines are not needed. If set to 0, writing +// IEEE-754 numbers on an incompatible system will be disabled. +#define BINIO_WITH_MATH 1 + +/***** Implementation *****/ + +// Disable annoying multiple inheritance compiler warning on MSVC6 +#ifdef _MSC_VER +# pragma warning(disable: 4250) +#endif + +#if BINIO_ENABLE_STRING +#include <string> +#endif + +class binio +{ +public: + typedef enum { + BigEndian = 1 << 0, + FloatIEEE = 1 << 1 + } Flag; + + typedef enum { + NoError = 0, + Fatal = 1 << 0, + Unsupported = 1 << 1, + NotOpen = 1 << 2, + Denied = 1 << 3, + NotFound = 1 << 4, + Eof = 1 << 5 + } ErrorCode; + + typedef enum { Set, Add, End } Offset; + typedef enum { Single, Double } FType; + typedef int Error; + + binio(); + virtual ~binio(); + + void setFlag(Flag f, bool set = true); + bool getFlag(Flag f); + + Error error(); + bool eof(); + + virtual void seek(long, Offset = Set) = 0; + virtual long pos() = 0; + +protected: + typedef long long Int; + typedef long double Float; + typedef unsigned char Byte; // has to be unsigned! + + typedef int Flags; + + Flags my_flags; + static const Flags system_flags; + Error err; + + // Some math.h emulation functions... +#if !BINIO_WITH_MATH + Float pow(Float base, signed int exp); + Float ldexp(Float x, signed int exp) { return x * pow(2, exp); } +#endif + +private: + static const Flags detect_system_flags(); +}; + +class binistream: virtual public binio +{ +public: + binistream(); + virtual ~binistream(); + + Int readInt(unsigned int size); + Float readFloat(FType ft); + unsigned long readString(char *str, unsigned long amount); + unsigned long readString(char *str, unsigned long maxlen, const char delim); +#if BINIO_ENABLE_STRING + std::string readString(const char delim = '\0'); +#endif + + Int peekInt(unsigned int size); + Float peekFloat(FType ft); + + bool ateof(); + void ignore(unsigned long amount = 1); + +protected: + virtual Byte getByte() = 0; + +private: + Float ieee_single2float(Byte *data); + Float ieee_double2float(Byte *data); +}; + +class binostream: virtual public binio +{ +public: + binostream(); + virtual ~binostream(); + + void writeInt(Int val, unsigned int size); + void writeFloat(Float f, FType ft); + unsigned long writeString(const char *str, unsigned long amount = 0); +#if BINIO_ENABLE_STRING + unsigned long writeString(const std::string &str); +#endif + +protected: + virtual void putByte(Byte) = 0; + +private: + void float2ieee_single(Float f, Byte *data); + void float2ieee_double(Float f, Byte *data); +}; + +class binstream: public binistream, public binostream +{ +public: + binstream(); + virtual ~binstream(); +}; + +#endif diff --git a/plugins/adplug/libbinio/binstr.cpp b/plugins/adplug/libbinio/binstr.cpp new file mode 100644 index 00000000..0e3a9f86 --- /dev/null +++ b/plugins/adplug/libbinio/binstr.cpp @@ -0,0 +1,114 @@ +/* + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser 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 + * + * binstr.cpp - Binary I/O on standard C strings in memory + * Copyright (C) 2003 Simon Peter <dn.tlp@gmx.net> + */ + +#include "binstr.h" + +/***** binsbase *****/ + +binsbase::binsbase(void *str, unsigned long len) + : data((Byte *)str), spos((Byte *)str), length(len) +{ +} + +binsbase::~binsbase() +{ +} + +void binsbase::seek(long p, Offset offs) +{ + switch(offs) { + case Set: spos = data + p; break; + case Add: spos += p; break; + case End: spos = data + length - 1 + p; break; + } + + // Seek before start of data + if(spos < data) { + err |= Eof; + spos = data; + return; + } + + // Seek after end of data + if(spos - data >= length) { + err |= Eof; + spos = data + length - 1; + } +} + +long binsbase::pos() +{ + return (long)(spos - data); +} + +/***** binisstream *****/ + +binisstream::binisstream(void *str, unsigned long len) + : binsbase(str, len) +{ +} + +binisstream::~binisstream() +{ +} + +binisstream::Byte binisstream::getByte() +{ + Byte in = 0; + + if(spos - data >= length) + err |= Eof; + else { + in = *spos; + spos++; + } + + return in; +} + +/***** binosstream *****/ + +binosstream::binosstream(void *str, unsigned long len) + : binsbase(str, len) +{ +} + +binosstream::~binosstream() +{ +} + +void binosstream::putByte(Byte b) +{ + *spos = b; + spos++; + + if(spos - data >= length) + spos = data + length - 1; +} + +/***** binsstream *****/ + +binsstream::binsstream(void *str, unsigned long len) + : binsbase(str, len), binisstream(str, len), binosstream(str, len) +{ +} + +binsstream::~binsstream() +{ +} diff --git a/plugins/adplug/libbinio/binstr.h b/plugins/adplug/libbinio/binstr.h new file mode 100644 index 00000000..33e4b12c --- /dev/null +++ b/plugins/adplug/libbinio/binstr.h @@ -0,0 +1,66 @@ +/* + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser 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 + * + * binstr.h - Binary I/O on standard C strings in memory + * Copyright (C) 2003 Simon Peter <dn.tlp@gmx.net> + */ + +#ifndef H_BINIO_BINSTR +#define H_BINIO_BINSTR + +#include "binio.h" + +class binsbase: virtual public binio +{ +public: + binsbase(void *str, unsigned long len); + virtual ~binsbase(); + + virtual void seek(long p, Offset offs = Set); + virtual long pos(); + +protected: + Byte *data, *spos; + long length; +}; + +class binisstream: public binistream, virtual public binsbase +{ +public: + binisstream(void *str, unsigned long len); + virtual ~binisstream(); + +protected: + virtual Byte getByte(); +}; + +class binosstream: public binostream, virtual public binsbase +{ +public: + binosstream(void *str, unsigned long len); + virtual ~binosstream(); + +protected: + virtual void putByte(Byte b); +}; + +class binsstream: public binisstream, public binosstream +{ +public: + binsstream(void *str, unsigned long len); + virtual ~binsstream(); +}; + +#endif diff --git a/plugins/adplug/libbinio/binwrap.cpp b/plugins/adplug/libbinio/binwrap.cpp new file mode 100644 index 00000000..740ee982 --- /dev/null +++ b/plugins/adplug/libbinio/binwrap.cpp @@ -0,0 +1,132 @@ +/* + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser 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 + * + * binwrap.cpp - Binary I/O wrapper, using standard iostreams library + * Copyright (C) 2002, 2003 Simon Peter <dn.tlp@gmx.net> + */ + +#include <stdio.h> +#include "binwrap.h" + +#if BINIO_ENABLE_IOSTREAM + +/***** biniwstream *****/ + +biniwstream::biniwstream(istream *istr) + : in(istr) +{ +} + +biniwstream::~biniwstream() +{ +} + +void biniwstream::seek(long pos, Offset offs) +{ + if(!in) { err = NotOpen; return; } + + switch(offs) { + case Set: in->seekg(pos, ios::beg); break; + case Add: in->seekg(pos, ios::cur); break; + case End: in->seekg(pos, ios::end); break; + } +} + +biniwstream::Byte biniwstream::getByte() +{ + if(!in) { err = NotOpen; return 0; } + + int i = in->get(); + if(i == EOF) err |= Eof; + return (Byte)i; +} + +long biniwstream::pos() +{ + if(!in) { err = NotOpen; return 0; } + return (long)in->tellg(); +} + +/***** binowstream *****/ + +binowstream::binowstream(ostream *ostr) + : out(ostr) +{ +} + +binowstream::~binowstream() +{ +} + +void binowstream::seek(long pos, Offset offs) +{ + if(!out) { err = NotOpen; return; } + + switch(offs) { + case Set: out->seekp(pos, ios::beg); break; + case Add: out->seekp(pos, ios::cur); break; + case End: out->seekp(pos, ios::end); break; + } +} + +void binowstream::putByte(binio::Byte b) +{ + if(!out) { err = NotOpen; return; } + out->put((char)b); +} + +long binowstream::pos() +{ + if(!out) { err = NotOpen; return 0; } + return (long)out->tellp(); +} + +/***** binwstream *****/ + +binwstream::binwstream(iostream *str) + : biniwstream(str), binowstream(str), io(str) +{ +} + +binwstream::~binwstream() +{ +} + +void binwstream::seek(long pos, Offset offs) +{ + biniwstream::seek(pos, offs); + binowstream::seek(pos, offs); +} + +long binwstream::pos() +{ + if(!io) { err = NotOpen; return 0; } + return (long)io->tellg(); +} + +binwstream::Byte binwstream::getByte() +{ + Byte in = biniwstream::getByte(); + binowstream::seek(biniwstream::pos(), Set); // sync stream position + return in; +} + +void binwstream::putByte(Byte b) +{ + binowstream::putByte(b); + biniwstream::seek(binowstream::pos(), Set); // sync stream position +} + +#endif diff --git a/plugins/adplug/libbinio/binwrap.h b/plugins/adplug/libbinio/binwrap.h new file mode 100644 index 00000000..74b009f6 --- /dev/null +++ b/plugins/adplug/libbinio/binwrap.h @@ -0,0 +1,92 @@ +/* + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser 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 + * + * binwrap.h - Binary I/O wrapper, using standard iostreams library + * Copyright (C) 2002, 2003 Simon Peter <dn.tlp@gmx.net> + */ + +#ifndef H_BINIO_BINWRAP +#define H_BINIO_BINWRAP + +#include "binio.h" + +#if BINIO_ENABLE_IOSTREAM + +#if BINIO_ISO_STDLIB +#include <iostream> + +using std::iostream; +using std::ostream; +using std::istream; +using std::ios; +using std::streambuf; +#else + +#include <iostream.h> + +#endif + +class biniwstream: public binistream +{ +public: + biniwstream(istream *istr); + virtual ~biniwstream(); + + virtual void seek(long pos, Offset offs = Set); + virtual long pos(); + +protected: + virtual Byte getByte(); + +private: + istream *in; +}; + +class binowstream: public binostream +{ +public: + binowstream(ostream *ostr); + virtual ~binowstream(); + + virtual void seek(long pos, Offset offs = Set); + virtual long pos(); + +protected: + virtual void putByte(Byte b); + +private: + ostream *out; +}; + +class binwstream: public biniwstream, public binowstream +{ +public: + binwstream(iostream *str); + virtual ~binwstream(); + + virtual void seek(long pos, Offset offs = Set); + virtual long pos(); + +protected: + virtual Byte getByte(); + virtual void putByte(Byte b); + +private: + iostream *io; +}; + +#endif + +#endif |