/* ScummVM - Graphic Adventure Engine * * ScummVM is the legal property of its developers, whose names * are too numerous to list here. Please refer to the COPYRIGHT * file distributed with this source distribution. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * */ #include "allfiles.h" #include "moreio.h" #include "newfatal.h" #include "stringy.h" #include "sludge.h" #include "common/debug.h" #include "common/file.h" #if defined __unix__ && !(defined __APPLE__) #include #if __BYTE_ORDER == __BIG_ENDIAN #define __BIG_ENDIAN__ #endif #endif namespace Sludge { bool allowAnyFilename = true; int getch(Common::SeekableReadStream *stream) { return stream->readByte(); } void putch(int c, Common::WriteStream *stream) { stream->writeByte(c); } int get2bytes(Common::SeekableReadStream *stream) { int f1, f2; f1 = getch(stream); f2 = getch(stream); return (f1 * 256 + f2); } void put2bytes(int numtoput, Common::WriteStream *stream) { putch((char)(numtoput / 256), stream); putch((char)(numtoput % 256), stream); } void writeString(char *s, Common::WriteStream *stream) { int a, len = strlen(s); put2bytes(len, stream); for (a = 0; a < len; ++a) { putch(s[a] + 1, stream); } } char *readString(Common::SeekableReadStream *stream) { int a, len = get2bytes(stream); char *s = new char[len + 1]; if (!checkNew(s)) { return NULL; } for (a = 0; a < len; ++a) { s[a] = (char)(getch(stream) - 1); } s[len] = 0; debug(kSludgeDebugDataLoad, "Read string of length %i: %s", len, s); return s; } float floatSwap(float f) { union { float f; unsigned char b[4]; } dat1, dat2; dat1.f = f; dat2.b[0] = dat1.b[3]; dat2.b[1] = dat1.b[2]; dat2.b[2] = dat1.b[1]; dat2.b[3] = dat1.b[0]; return dat2.f; } float getFloat(Common::SeekableReadStream *stream) { float f; size_t bytes_read = stream->read(&f, sizeof(float)); //fread(& f, sizeof(float), 1, fp); if (bytes_read != sizeof(float) && stream->err()) { debug("Reading error in getFloat.\n"); } #ifdef __BIG_ENDIAN__ return floatSwap(f); #else return f; #endif } void putFloat(float f, Common::WriteStream *stream) { #ifdef __BIG_ENDIAN__ f = floatSwap(f); #endif stream->write(&f,sizeof(float)); //fwrite(& f, sizeof(float), 1, fp); } short shortSwap(short s) { unsigned char b1, b2; b1 = s & 255; b2 = (s >> 8) & 255; return (b1 << 8) + b2; } short getSigned(Common::SeekableReadStream *stream) { short f; size_t bytes_read = stream->read(&f, sizeof(short)); if (bytes_read != sizeof(short) && stream->err()) { debug("Reading error in getSigned.\n"); } #ifdef __BIG_ENDIAN__ f = shortSwap(f); #endif return f; } void putSigned(short f, Common::WriteStream *stream) { #ifdef __BIG_ENDIAN__ f = shortSwap(f); #endif stream->write(&f, sizeof(short)); } // The following two functions treat signed integers as unsigned. // That's done on purpose. int32_t get4bytes(Common::SeekableReadStream *stream) { int f1, f2, f3, f4; f1 = getch(stream); f2 = getch(stream); f3 = getch(stream); f4 = getch(stream); unsigned int x = f1 + f2 * 256 + f3 * 256 * 256 + f4 * 256 * 256 * 256; return x; } void put4bytes(unsigned int i, Common::WriteStream *stream) { unsigned char f1, f2, f3, f4; f4 = i / (256 * 256 * 256); i = i % (256 * 256 * 256); f3 = i / (256 * 256); i = i % (256 * 256); f2 = i / 256; f1 = i % 256; putch(f1, stream); putch(f2, stream); putch(f3, stream); putch(f4, stream); } char *encodeFilename(char *nameIn) { if (!nameIn) return NULL; if (allowAnyFilename) { char *newName = new char[strlen(nameIn) * 2 + 1]; if (!checkNew(newName)) return NULL; int i = 0; while (*nameIn) { switch (*nameIn) { case '<': newName[i++] = '_'; newName[i++] = 'L'; break; case '>': newName[i++] = '_'; newName[i++] = 'G'; break; case '|': newName[i++] = '_'; newName[i++] = 'P'; break; case '_': newName[i++] = '_'; newName[i++] = 'U'; break; case '\"': newName[i++] = '_'; newName[i++] = 'S'; break; case '\\': newName[i++] = '_'; newName[i++] = 'B'; break; case '/': newName[i++] = '_'; newName[i++] = 'F'; break; case ':': newName[i++] = '_'; newName[i++] = 'C'; break; case '*': newName[i++] = '_'; newName[i++] = 'A'; break; case '?': newName[i++] = '_'; newName[i++] = 'Q'; break; default: newName[i++] = *nameIn; break; } newName[i] = 0; nameIn ++; } return newName; } else { int a; for (a = 0; nameIn[a]; ++a) { #ifdef _WIN32 if (nameIn[a] == '/') nameIn[a] = '\\'; #else if (nameIn[a] == '\\') nameIn[a] = '/'; #endif } return copyString(nameIn); } } char *decodeFilename(char *nameIn) { if (allowAnyFilename) { char *newName = new char[strlen(nameIn) + 1]; if (!checkNew(newName)) return NULL; int i = 0; while (* nameIn) { if (* nameIn == '_') { nameIn ++; switch (* nameIn) { case 'L': newName[i] = '<'; nameIn ++; break; case 'G': newName[i] = '>'; nameIn ++; break; case 'P': newName[i] = '|'; nameIn ++; break; case 'U': newName[i] = '_'; nameIn ++; break; case 'S': newName[i] = '\"'; nameIn ++; break; case 'B': newName[i] = '\\'; nameIn ++; break; case 'F': newName[i] = '/'; nameIn ++; break; case 'C': newName[i] = ':'; nameIn ++; break; case 'A': newName[i] = '*'; nameIn ++; break; case 'Q': newName[i] = '?'; nameIn ++; break; default: newName[i] = '_'; } } else { newName[i] = *nameIn; nameIn ++; } i ++; } newName[i] = 0; return newName; } else { return copyString(nameIn); } } } // End of namespace Sludge