/* 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 "tot/tot.h" #include "tot/util.h" namespace Tot { void TotEngine::readBitmap(int32 bitmapPosition, byte *buf, uint bitmapSize, uint error) { Common::File bitmapFile; if (!bitmapFile.open("BITMAPS.DAT")) { showError(error); } bitmapFile.seek(bitmapPosition); bitmapFile.read(buf, bitmapSize); bitmapFile.close(); } void TotEngine::loadCharAnimation() { Common::File characterFile; _cpCounter = _cpCounter2; if (!characterFile.open("PERSONAJ.SPT")) showError(265); _mainCharFrameSize = characterFile.readUint16LE(); for (int i = 0; i < 4; i++) for (int j = 0; j < kWalkFrameCount; j++) { if (g_engine->_mainCharAnimation.bitmap[i][j]) free(g_engine->_mainCharAnimation.bitmap[i][j]); _mainCharAnimation.bitmap[i][j] = (byte *)malloc(_mainCharFrameSize); characterFile.read(_mainCharAnimation.bitmap[i][j], _mainCharFrameSize); } for (int i = 0; i < 4; i++) for (int j = kWalkFrameCount; j < (kWalkFrameCount + 10 * 3); j++) { if (g_engine->_mainCharAnimation.bitmap[i][j]) free(g_engine->_mainCharAnimation.bitmap[i][j]); _mainCharAnimation.bitmap[i][j] = (byte *)malloc(_mainCharFrameSize); characterFile.read(_mainCharAnimation.bitmap[i][j], _mainCharFrameSize); } characterFile.close(); } void TotEngine::readTextFile() { if (!_verbFile.open("CONVERSA.TXT")) { showError(313); } } TextEntry TotEngine::readTextRegister(uint numRegister) { _verbFile.seek(numRegister * kVerbRegSize); return readTextRegister(); } TextEntry TotEngine::readTextRegister() { TextEntry regmht; // Since the text is encrypted it's safer to save the size as reported by // the pascal string, because the encrypter character might be the termination // character byte size = _verbFile.readByte(); _verbFile.seek(-1, SEEK_CUR); regmht.text = _verbFile.readPascalString(false); _verbFile.skip(255 - size); regmht.continued = _verbFile.readByte(); regmht.response = _verbFile.readUint16LE(); regmht.pointer = _verbFile.readSint32LE(); return regmht; } void TotEngine::readConversationFile() { Common::File conversationFile; if (!conversationFile.open(Common::Path(Common::String("CONVERSA.TRE")))) { showError(314); } int64 fileSize = conversationFile.size(); byte *buf = (byte *)malloc(fileSize); conversationFile.read(buf, fileSize); _conversationData = new Common::MemorySeekableReadWriteStream(buf, fileSize, DisposeAfterUse::YES); conversationFile.close(); } void saveDoorMetadata(DoorRegistry doors, Common::SeekableWriteStream *out) { out->writeUint16LE(doors.nextScene); out->writeUint16LE(doors.exitPosX); out->writeUint16LE(doors.exitPosY); out->writeByte(doors.openclosed); out->writeByte(doors.doorcode); } void savePoint(Common::Point point, Common::SeekableWriteStream *out) { out->writeUint16LE(point.x); out->writeUint16LE(point.y); } void saveBitmapRegister(RoomBitmapRegister bitmap, Common::SeekableWriteStream *out) { out->writeSint32LE(bitmap.bitmapPointer); out->writeUint16LE(bitmap.bitmapSize); out->writeUint16LE(bitmap.coordx); out->writeUint16LE(bitmap.coordy); out->writeUint16LE(bitmap.depth); } void saveRoomObjectList(RoomObjectListEntry objectList, Common::SeekableWriteStream *out) { out->writeUint16LE(objectList.fileIndex); out->writeByte(objectList.objectName.size()); int paddingSize = 20 - objectList.objectName.size(); if (paddingSize < 20) { out->writeString(objectList.objectName); } if (paddingSize > 0) { char *padding = (char *)calloc(paddingSize, 1); out->write(padding, paddingSize); free(padding); } } void saveRoom(RoomFileRegister *room, Common::SeekableWriteStream *out) { out->writeUint16LE(room->code); out->writeUint32LE(room->roomImagePointer); out->writeUint16LE(room->roomImageSize); out->write(room->walkAreasGrid, 40 * 28); out->write(room->mouseGrid, 40 * 28); // read puntos for (int i = 0; i < 9; i++) { for (int j = 0; j < 30; j++) { for (int k = 0; k < 5; k++) { savePoint(room->trajectories[i][j][k], out); } } } for (int i = 0; i < 5; i++) { saveDoorMetadata(room->doors[i], out); } for (int i = 0; i < 15; i++) { saveBitmapRegister(room->screenLayers[i], out); } for (int i = 0; i < 51; i++) { saveRoomObjectList(*room->screenObjectIndex[i], out); } out->writeByte(room->animationFlag); out->writeByte(room->animationName.size()); out->writeString(room->animationName); int paddingSize = 8 - room->animationName.size(); if (paddingSize > 0) { char *padding = (char *)calloc(paddingSize, 1); // 8 max char name out->write(padding, paddingSize); free(padding); } out->writeByte(room->paletteAnimationFlag); out->writeUint16LE(room->palettePointer); for (int i = 0; i < 300; i++) { savePoint(room->secondaryAnimTrajectory[i], out); } out->write(room->secondaryAnimDirections, 600); out->writeUint16LE(room->secondaryTrajectoryLength); } void TotEngine::saveRoomData(RoomFileRegister *room, Common::SeekableWriteStream *out) { _rooms->seek(room->code * kRoomRegSize, SEEK_SET); saveRoom(room, out); } void TotEngine::readObject(Common::SeekableReadStream *stream, uint itemPos, ScreenObject *thisRegObj) { stream->seek(itemPos * kItemRegSize); thisRegObj->code = stream->readUint16LE(); thisRegObj->height = stream->readByte(); thisRegObj->name = stream->readPascalString(); stream->skip(kObjectNameLength - thisRegObj->name.size()); thisRegObj->lookAtTextRef = stream->readUint16LE(); thisRegObj->beforeUseTextRef = stream->readUint16LE(); thisRegObj->afterUseTextRef = stream->readUint16LE(); thisRegObj->pickTextRef = stream->readUint16LE(); thisRegObj->useTextRef = stream->readUint16LE(); thisRegObj->speaking = stream->readByte(); thisRegObj->openable = stream->readByte(); thisRegObj->closeable = stream->readByte(); stream->read(thisRegObj->used, 8); thisRegObj->pickupable = stream->readByte(); thisRegObj->useWith = stream->readUint16LE(); thisRegObj->replaceWith = stream->readUint16LE(); thisRegObj->depth = stream->readByte(); thisRegObj->bitmapPointer = stream->readUint32LE(); thisRegObj->bitmapSize = stream->readUint16LE(); thisRegObj->rotatingObjectAnimation = stream->readUint32LE(); thisRegObj->rotatingObjectPalette = stream->readUint16LE(); thisRegObj->dropOverlayX = stream->readUint16LE(); thisRegObj->dropOverlayY = stream->readUint16LE(); thisRegObj->dropOverlay = stream->readUint32LE(); thisRegObj->dropOverlaySize = stream->readUint16LE(); thisRegObj->objectIconBitmap = stream->readUint16LE(); thisRegObj->xgrid1 = stream->readByte(); thisRegObj->ygrid1 = stream->readByte(); thisRegObj->xgrid2 = stream->readByte(); thisRegObj->ygrid2 = stream->readByte(); stream->read(thisRegObj->walkAreasPatch, 100); stream->read(thisRegObj->mouseGridPatch, 100); } void TotEngine::readObject(uint itemPosition) { if(_curObject != nullptr) { delete _curObject; _curObject = nullptr; } _curObject = new ScreenObject(); readObject(_sceneObjectsData, itemPosition, _curObject); } void TotEngine::updateObject(uint itemPosition) { _curObject->used[0] = 9; _sceneObjectsData->seek(itemPosition); saveObject(_curObject, _sceneObjectsData); } /** * Object files contain a single register per object, with a set of 8 flags, to mark them as used in each save. */ void TotEngine::initializeObjectFile() { Common::File objFile; if (!objFile.open(Common::Path("OBJETOS.DAT"))) { showError(261); } delete (_sceneObjectsData); byte *objectData = (byte *)malloc(objFile.size()); objFile.read(objectData, objFile.size()); _sceneObjectsData = new Common::MemorySeekableReadWriteStream(objectData, objFile.size(), DisposeAfterUse::NO); objFile.close(); } void TotEngine::saveObjectsData(ScreenObject *object, Common::SeekableWriteStream *out) { out->writeUint16LE(object->code); out->writeByte(object->height); out->writeByte(object->name.size()); out->writeString(object->name); int paddingSize = kObjectNameLength - object->name.size(); if (paddingSize > 0) { char *padding = (char *)calloc(paddingSize, 1); // 8 max char name out->write(padding, paddingSize); free(padding); } out->writeUint16LE(object->lookAtTextRef); out->writeUint16LE(object->beforeUseTextRef); out->writeUint16LE(object->afterUseTextRef); out->writeUint16LE(object->pickTextRef); out->writeUint16LE(object->useTextRef); out->writeByte(object->speaking); out->writeByte(object->openable); out->writeByte(object->closeable); out->write(object->used, 8); out->writeByte(object->pickupable); out->writeUint16LE(object->useWith); out->writeUint16LE(object->replaceWith); out->writeByte(object->depth); out->writeUint32LE(object->bitmapPointer); out->writeUint16LE(object->bitmapSize); out->writeUint16LE(object->rotatingObjectAnimation); out->writeUint16LE(object->rotatingObjectPalette); out->writeUint16LE(object->dropOverlayX); out->writeUint16LE(object->dropOverlayY); out->writeUint32LE(object->dropOverlay); out->writeUint16LE(object->dropOverlaySize); out->writeUint16LE(object->objectIconBitmap); out->writeByte(object->xgrid1); out->writeByte(object->ygrid1); out->writeByte(object->xgrid2); out->writeByte(object->ygrid2); out->write(object->walkAreasPatch, 100); out->write(object->mouseGridPatch, 100); } void TotEngine::saveObject(ScreenObject *object, Common::SeekableWriteStream *out) { _sceneObjectsData->seek(object->code * kItemRegSize, SEEK_SET); saveObjectsData(object, out); } DoorRegistry readDoorMetadata(Common::SeekableReadStream *in) { DoorRegistry doorMetadata; doorMetadata.nextScene = in->readUint16LE(); doorMetadata.exitPosX = in->readUint16LE(); doorMetadata.exitPosY = in->readUint16LE(); doorMetadata.openclosed = in->readByte(); doorMetadata.doorcode = in->readByte(); return doorMetadata; } Common::Point readPoint(Common::SeekableReadStream *in) { Common::Point point; point.x = in->readUint16LE(); point.y = in->readUint16LE(); return point; } RoomBitmapRegister readAuxBitmaps(Common::SeekableReadStream *in) { RoomBitmapRegister bitmapMetadata = RoomBitmapRegister(); bitmapMetadata.bitmapPointer = in->readSint32LE(); bitmapMetadata.bitmapSize = in->readUint16LE(); bitmapMetadata.coordx = in->readUint16LE(); bitmapMetadata.coordy = in->readUint16LE(); bitmapMetadata.depth = in->readUint16LE(); return bitmapMetadata; } RoomObjectListEntry *readRoomObjects(Common::SeekableReadStream *in) { RoomObjectListEntry *objectMetadata = new RoomObjectListEntry(); objectMetadata->fileIndex = in->readUint16LE(); objectMetadata->objectName = in->readPascalString(); in->skip(20 - objectMetadata->objectName.size()); return objectMetadata; } RoomFileRegister *TotEngine::readScreenDataFile(Common::SeekableReadStream *in) { RoomFileRegister *screenData = new RoomFileRegister(); screenData->code = in->readUint16LE(); screenData->roomImagePointer = in->readUint32LE(); screenData->roomImageSize = in->readUint16LE(); in->read(screenData->walkAreasGrid, 40 * 28); in->read(screenData->mouseGrid, 40 * 28); for (int i = 0; i < 9; i++) { for (int j = 0; j < 30; j++) { for (int k = 0; k < 5; k++) { screenData->trajectories[i][j][k] = readPoint(in); } } } for (int i = 0; i < 5; i++) { screenData->doors[i] = readDoorMetadata(in); } for (int i = 0; i < 15; i++) { screenData->screenLayers[i] = readAuxBitmaps(in); } for (int i = 0; i < 51; i++) { screenData->screenObjectIndex[i] = readRoomObjects(in); } screenData->animationFlag = in->readByte(); screenData->animationName = in->readPascalString(); in->skip(8 - screenData->animationName.size()); screenData->paletteAnimationFlag = in->readByte(); screenData->palettePointer = in->readUint16LE(); for (int i = 0; i < 300; i++) { screenData->secondaryAnimTrajectory[i] = readPoint(in); } in->read(screenData->secondaryAnimDirections, 600); screenData->secondaryTrajectoryLength = in->readUint16LE(); return screenData; } } // End of namespace Tot