/* 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 3 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, see . * */ #include "common/debug.h" #include "common/textconsole.h" #include "common/str.h" #include "common/stream.h" #include "dgds/includes.h" #include "dgds/resource.h" #include "dgds/parser.h" #include "dgds/scripts.h" #include "dgds/ttm.h" #include "dgds/ads.h" namespace Dgds { DgdsParser::DgdsParser(ResourceManager *resman, Decompressor *decompressor) : _resman(resman), _decompressor(decompressor), _bytesRead(0) { } bool DgdsParser::parse(ParserData *data, const Common::String &filename) { DGDS_EX ex; _filename = filename; Common::SeekableReadStream *resStream = _resman->getResource(filename); if (!resStream) { error("Couldn't open script file '%s'", filename.c_str()); return false; } uint32 dot = _filename.find('.'); if (dot != Common::String::npos) { ex = MKTAG24(toupper(_filename[dot + 1]), toupper(_filename[dot + 2]), toupper(_filename[dot + 3])); } else { ex = 0; } DgdsChunkReader chunk(resStream); while (chunk.readNextHeader(ex, _filename)) { bool stop; if (chunk.isContainer()) { stop = handleChunk(chunk, data); } else { chunk.readContent(_decompressor); stop = handleChunk(chunk, data); } if (stop) break; } delete resStream; return true; } Common::HashMap DgdsParser::readTags(Common::SeekableReadStream *stream) { Common::HashMap tags; uint16 count = stream->readUint16LE(); debug(1, " %u tags:", count); for (uint16 i = 0; i < count; i++) { uint16 idx = stream->readUint16LE(); const Common::String tagVal = stream->readString(); debug(1, " %2u: %2u, \"%s\"", i, idx, tagVal.c_str()); // TODO: How to handle when these IDs overlap? (eg, see // BBEDROOM.TTM in RotD) if (!tags.contains(idx)) tags[idx] = tagVal; } return tags; } bool TTMParser::handleChunk(DgdsChunkReader &chunk, ParserData *data) { TTMEnviro *scriptData = static_cast(data); switch (chunk.getId()) { case ID_TTI: // Ignore containers break; case ID_TT3: // Make a memory read stream from the chunk data scriptData->scr = chunk.makeMemoryStream(); break; case ID_TAG: scriptData->_tags = readTags(chunk.getContent()); break; case ID_VER: // Version - ignore break; case ID_PAG: if (chunk.getSize() != 2) { warning("unspected PAG chunk size %d in %s", chunk.getSize(), _filename.c_str()); break; } scriptData->_totalFrames = chunk.getContent()->readUint16LE(); scriptData->_frameOffsets.resize(scriptData->_totalFrames + 1, -1); break; default: debug("TTMParser: Unexpected chunk '%s' of size %d found in file '%s'", tag2str(chunk.getId()), chunk.getSize(), _filename.c_str()); //chunk._contentStream->skip(chunk._size); break; } return false; } bool ADSParser::handleChunk(DgdsChunkReader &chunk, ParserData *data) { ADSData *scriptData = static_cast(data); Common::SeekableReadStream *chunkStream = chunk.getContent(); switch (chunk.getId()) { case EX_ADS: case ID_TTI: // Ignore containers break; case ID_RES: { uint16 count = chunkStream->readUint16LE(); for (uint16 i = 0; i < count; i++) { uint16 idx = chunkStream->readUint16LE(); //assert(idx == (i + 1)); // not true in Willy Beamish. if (idx > scriptData->_scriptNames.size()) scriptData->_scriptNames.resize(idx); scriptData->_scriptNames[idx - 1] = chunkStream->readString(); } } break; case ID_SCR: scriptData->scr = chunk.makeMemoryStream(); break; case ID_TAG: scriptData->_tags = readTags(chunkStream); break; case ID_VER: // Version - ignore break; default: warning("ADSParser: Unexpected chunk '%s' of size %d found in file '%s'", tag2str(chunk.getId()), chunk.getSize(), _filename.c_str()); break; } return false; } } // End of namespace Dgds