Files
scummvm-cursorfix/engines/tot/resources.cpp
2026-02-02 04:50:13 +01:00

394 lines
12 KiB
C++

/* 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 <http://www.gnu.org/licenses/>.
*
*/
#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