summaryrefslogtreecommitdiff
path: root/plugins/adplug/libbinio
diff options
context:
space:
mode:
authorGravatar Alexey Yakovenko <wakeroid@gmail.com>2009-12-19 15:46:14 +0100
committerGravatar Alexey Yakovenko <wakeroid@gmail.com>2009-12-19 15:46:14 +0100
commit3f060fbd1ded8236ad27988173011ef9e9298a20 (patch)
treec7575a02421c08ad0a83fb21ece5d412d40e43dd /plugins/adplug/libbinio
parent25f13980b6f30093f80174c8055cc42a47772d0d (diff)
adplug plugin WIP (insert works)
Diffstat (limited to 'plugins/adplug/libbinio')
-rw-r--r--plugins/adplug/libbinio/binfile.cpp247
-rw-r--r--plugins/adplug/libbinio/binfile.h110
-rw-r--r--plugins/adplug/libbinio/binio.cpp640
-rw-r--r--plugins/adplug/libbinio/binio.h175
-rw-r--r--plugins/adplug/libbinio/binstr.cpp114
-rw-r--r--plugins/adplug/libbinio/binstr.h66
-rw-r--r--plugins/adplug/libbinio/binwrap.cpp132
-rw-r--r--plugins/adplug/libbinio/binwrap.h92
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