aboutsummaryrefslogtreecommitdiff
path: root/scumm/util.cpp
diff options
context:
space:
mode:
authorMax Horn2004-12-17 22:27:15 +0000
committerMax Horn2004-12-17 22:27:15 +0000
commitb93dd59a44f73f744bbf3d0d60e0ce509667eccc (patch)
tree6bc844d730e28eaf62592d9647343035cc5ba00e /scumm/util.cpp
parent79ce4de9423797abb768657942e6af425a2e84ea (diff)
downloadscummvm-rg350-b93dd59a44f73f744bbf3d0d60e0ce509667eccc.tar.gz
scummvm-rg350-b93dd59a44f73f744bbf3d0d60e0ce509667eccc.tar.bz2
scummvm-rg350-b93dd59a44f73f744bbf3d0d60e0ce509667eccc.zip
Reduce code size of resource.cpp to help PalmOS port, by moving util code to a new file util.cpp and sound resource code to sound.cpp
svn-id: r16105
Diffstat (limited to 'scumm/util.cpp')
-rw-r--r--scumm/util.cpp272
1 files changed, 272 insertions, 0 deletions
diff --git a/scumm/util.cpp b/scumm/util.cpp
new file mode 100644
index 0000000000..e1710d24c8
--- /dev/null
+++ b/scumm/util.cpp
@@ -0,0 +1,272 @@
+/* ScummVM - Scumm Interpreter
+ * Copyright (C) 2002-2004 The ScummVM project
+ *
+ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * $Header$
+ *
+ */
+
+#include "scumm/util.h"
+
+namespace Scumm {
+
+#pragma mark -
+#pragma mark --- ScummFile ---
+#pragma mark -
+
+
+ScummFile::ScummFile() : _encbyte(0), _subFileStart(0), _subFileLen(0) {
+}
+
+void ScummFile::setEnc(byte value) {
+ _encbyte = value;
+}
+
+void ScummFile::setSubfileRange(uint32 start, uint32 len) {
+ // TODO: Add sanity checks
+ const uint32 fileSize = File::size();
+ assert(start <= fileSize);
+ assert(start + len <= fileSize);
+ _subFileStart = start;
+ _subFileLen = len;
+ seek(0, SEEK_SET);
+}
+
+void ScummFile::resetSubfile() {
+ _subFileStart = 0;
+ _subFileLen = 0;
+ seek(0, SEEK_SET);
+}
+
+bool ScummFile::open(const char *filename, AccessMode mode) {
+ if (File::open(filename, mode)) {
+ resetSubfile();
+ return true;
+ } else {
+ return false;
+ }
+}
+
+bool ScummFile::openSubFile(const char *filename) {
+ assert(isOpen());
+
+ // Disable the XOR encryption and reset any current subfile range
+ setEnc(0);
+ resetSubfile();
+
+ // Read in the filename table and look for the specified file
+
+ unsigned long file_off, file_len;
+ char file_name[0x20+1];
+ unsigned long i;
+
+ // Get the length of the data file to use for consistency checks
+ const uint32 data_file_len = size();
+
+ // Read offset and length to the file records */
+ const uint32 file_record_off = readUint32BE();
+ const uint32 file_record_len = readUint32BE();
+
+ // Do a quick check to make sure the offset and length are good
+ if (file_record_off + file_record_len > data_file_len) {
+ return false;
+ }
+
+ // Do a little consistancy check on file_record_length
+ if (file_record_len % 0x28) {
+ return false;
+ }
+
+ // Scan through the files
+ for (i = 0; i < file_record_len; i += 0x28) {
+ // read a file record
+ seek(file_record_off + i, SEEK_SET);
+ file_off = readUint32BE();
+ file_len = readUint32BE();
+ read(file_name, 0x20);
+ file_name[0x20] = 0;
+
+ assert(file_name[0]);
+ //debug(7, " extracting \'%s\'", file_name);
+
+ // Consistency check. make sure the file data is in the file
+ if (file_off + file_len > data_file_len) {
+ return false;
+ }
+
+ if (scumm_stricmp(file_name, filename) == 0) {
+ // We got a match!
+ setSubfileRange(file_off, file_len);
+ return true;
+ }
+ }
+
+ return false;
+}
+
+
+bool ScummFile::eof() {
+ return _subFileLen ? (pos() >= _subFileLen) : File::eof();
+}
+
+uint32 ScummFile::pos() {
+ return File::pos() - _subFileStart;
+}
+
+uint32 ScummFile::size() {
+ return _subFileLen ? _subFileLen : File::size();
+}
+
+void ScummFile::seek(int32 offs, int whence) {
+ if (_subFileLen) {
+ // Constrain the seek to the subfile
+ switch (whence) {
+ case SEEK_END:
+ offs = _subFileStart + _subFileLen - offs;
+ break;
+ case SEEK_SET:
+ offs += _subFileStart;
+ break;
+ case SEEK_CUR:
+ offs += File::pos();
+ break;
+ }
+ assert((int32)_subFileStart <= offs && offs <= (int32)(_subFileStart + _subFileLen));
+ whence = SEEK_SET;
+ }
+ File::seek(offs, whence);
+}
+
+uint32 ScummFile::read(void *ptr, uint32 len) {
+ uint32 realLen;
+
+ if (_subFileLen) {
+ // Limit the amount we read by the subfile boundaries.
+ const uint32 curPos = pos();
+ assert(_subFileLen >= curPos);
+ uint32 newPos = curPos + len;
+ if (newPos > _subFileLen) {
+ len = _subFileLen - curPos;
+ _ioFailed = true;
+ }
+ }
+
+ realLen = File::read(ptr, len);
+
+
+ // If an encryption byte was specified, XOR the data we just read by it.
+ // This simple kind of "encryption" was used by some of the older SCUMM
+ // games.
+ if (_encbyte) {
+ byte *p = (byte *)ptr;
+ byte *end = p + realLen;
+ while (p < end)
+ *p++ ^= _encbyte;
+ }
+
+ return realLen;
+}
+
+uint32 ScummFile::write(const void *, uint32) {
+ error("ScummFile does not support writing!");
+}
+
+#pragma mark -
+#pragma mark --- Utilities ---
+#pragma mark -
+
+void checkRange(int max, int min, int no, const char *str) {
+ if (no < min || no > max) {
+ char buf[256];
+ snprintf(buf, sizeof(buf), str, no);
+ error("Value %d is out of bounds (%d,%d) (%s)", no, min, max, buf);
+ }
+}
+
+/**
+ * Convert an old style direction to a new style one (angle),
+ */
+int newDirToOldDir(int dir) {
+ if (dir >= 71 && dir <= 109)
+ return 1;
+ if (dir >= 109 && dir <= 251)
+ return 2;
+ if (dir >= 251 && dir <= 289)
+ return 0;
+ return 3;
+}
+
+/**
+ * Convert an new style (angle) direction to an old style one.
+ */
+int oldDirToNewDir(int dir) {
+ assert(0 <= dir && dir <= 3);
+ const int new_dir_table[4] = { 270, 90, 180, 0 };
+ return new_dir_table[dir];
+}
+
+/**
+ * Convert an angle to a simple direction.
+ */
+int toSimpleDir(int dirType, int dir) {
+ if (dirType) {
+ const int16 directions[] = { 22, 72, 107, 157, 202, 252, 287, 337 };
+ for (int i = 0; i < 7; i++)
+ if (dir >= directions[i] && dir <= directions[i+1])
+ return i+1;
+ } else {
+ const int16 directions[] = { 71, 109, 251, 289 };
+ for (int i = 0; i < 3; i++)
+ if (dir >= directions[i] && dir <= directions[i+1])
+ return i+1;
+ }
+
+ return 0;
+}
+
+/**
+ * Convert a simple direction to an angle.
+ */
+int fromSimpleDir(int dirType, int dir) {
+ if (dirType)
+ return dir * 45;
+ else
+ return dir * 90;
+}
+
+/**
+ * Normalize the given angle - that means, ensure it is positive, and
+ * change it to the closest multiple of 45 degree by abusing toSimpleDir.
+ */
+int normalizeAngle(int angle) {
+ int temp;
+
+ temp = (angle + 360) % 360;
+
+ return toSimpleDir(1, temp) * 45;
+}
+
+const char *tag2str(uint32 tag) {
+ static char str[5];
+ str[0] = (char)(tag >> 24);
+ str[1] = (char)(tag >> 16);
+ str[2] = (char)(tag >> 8);
+ str[3] = (char)tag;
+ str[4] = '\0';
+ return str;
+}
+
+} // End of namespace Scumm