/* ScummVM - Scumm Interpreter * Copyright (C) 2003 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 "queen/queen.h" #include "queen/resource.h" namespace Queen { #define DEMO_JAS_VERSION_OFFSET 0x119A8 #define JAS_VERSION_OFFSET 0x12484 static const char *dataFilename = "queen.1"; Resource::Resource(char *datafilePath) { _datafilePath = datafilePath; _resourceFile = new File(); _resourceFile->open(dataFilename, _datafilePath); if (_resourceFile->isOpen() == false) error("Could not open resource file '%s%s'", _datafilePath, dataFilename); //detect game version based on resource file size. //we try to verify that it is indeed the version we think it is later on switch(_resourceFile->size()) { case 3724538: _gameVersion = &_gameVersionPE100v1; break; case 3732177: _gameVersion = &_gameVersionPE100v2; break; case 22677657: _gameVersion = &_gameVersionPEM10; break; case 190787021: _gameVersion = &_gameVersionCEM10; break; default: error("Unknown/unsupported FOTAQ version"); } debug(5, "Detected game version: %s, which has %d resource entries", _gameVersion->versionString, _gameVersion->resourceEntries); if (strcmp(_gameVersion->versionString, JASVersion())) error("Verifying game version failed! (expected: '%s', found: '%s')", _gameVersion->versionString, JASVersion()); } Resource::~Resource() { _resourceFile->close(); } int32 Resource::resourceIndex(const char *filename) { char entryName[14]; char *ptr = entryName; assert(strlen(filename)); strcpy(entryName, filename); do *ptr = toupper(*ptr); while (*ptr++); uint32 low = 0; uint32 high = _gameVersion->resourceEntries - 1; if (!strcmp(entryName, _gameVersion->resourceTable[low].filename)) return low; if (!strcmp(entryName, _gameVersion->resourceTable[high].filename)) return high; //Use simple binary search to locate file for(;;) { uint32 cur = (low + high) / 2; int32 diff = strcmp(entryName, _gameVersion->resourceTable[cur].filename); if (!diff) return cur; if ((cur == low) || (cur == high)) break; if (diff > 0) low = cur; else high = cur; } error("Couldn't find file '%s'", entryName); return -1; } uint32 Resource::fileSize(const char *filename) { return _gameVersion->resourceTable[resourceIndex(filename)].size; } uint32 Resource::fileOffset(const char *filename) { return _gameVersion->resourceTable[resourceIndex(filename)].offset; } uint8 *Resource::loadFile(const char *filename, uint32 skipBytes) { uint32 size = fileSize(filename); byte *mem = new byte[size]; // skip 'skipBytes' bytes (useful for headers) _resourceFile->seek(fileOffset(filename) + skipBytes, SEEK_SET); _resourceFile->read(mem, size - skipBytes); return mem; } bool Resource::exists(const char *filename) { return resourceIndex(filename) >= 0; } const char *Resource::JASVersion() { static char versionStr[6]; if (_gameVersion->isDemo) _resourceFile->seek(fileOffset("QUEEN.JAS") + DEMO_JAS_VERSION_OFFSET, SEEK_SET ); else _resourceFile->seek(fileOffset("QUEEN.JAS") + JAS_VERSION_OFFSET, SEEK_SET); _resourceFile->read(versionStr, 6); return versionStr; } bool Resource::isDemo() { return _gameVersion->isDemo; } } // End of namespace Queen