scummvm/engines/efh/files.cpp

392 lines
13 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 "common/config-manager.h"
#include "efh/efh.h"
namespace Efh {
int32 EfhEngine::readFileToBuffer(const Common::Path &filename, uint8 *destBuffer) {
debugC(1, kDebugUtils, "readFileToBuffer %s", filename.toString().c_str());
Common::File f;
if (!f.open(filename))
error("Unable to find file %s", filename.toString().c_str());
int size = f.size();
return f.read(destBuffer, size);
}
void EfhEngine::readAnimInfo() {
debugC(6, kDebugEngine, "readAnimInfo");
Common::Path fileName("animinfo");
Common::File f;
if (!f.open(fileName))
error("Unable to find file %s", fileName.toString().c_str());
for (int i = 0; i < 100; ++i) {
for (int id = 0; id < 15; ++id) {
Common::String txtBuffer = "->";
for (int frameId = 0; frameId < 4; ++frameId) {
_animInfo[i]._frameList[id]._subFileId[frameId] = f.readByte();
txtBuffer += Common::String::format(" %d", _animInfo[i]._frameList[id]._subFileId[frameId]);
}
debugC(6, kDebugEngine, "%s", txtBuffer.c_str());
}
Common::String debugStr = "";
for (int id = 0; id < 10; ++id) {
_animInfo[i]._posY[id] = f.readByte();
debugStr += Common::String::format("%d ", _animInfo[i]._posY[id]);
}
debugC(6, kDebugEngine, "%s", debugStr.c_str());
debugStr = "";
for (int id = 0; id < 10; ++id) {
_animInfo[i]._posX[id] = f.readUint16LE();
debugStr += Common::String::format("%d ", _animInfo[i]._posX[id]);
}
debugC(6, kDebugEngine, "%s", debugStr.c_str());
debugC(6, kDebugEngine, "---------");
}
}
void EfhEngine::findMapFile(int16 mapId) {
debugC(7, kDebugEngine, "findMapFile %d", mapId);
if (!_introDoneFl)
return;
Common::Path fileName(Common::String::format("map.%d", mapId));
Common::File f;
// The original was checking for the file and eventually asking to change floppies
if (!f.open(fileName))
error("File not found: %s", fileName.toString().c_str());
f.close();
}
void EfhEngine::rImageFile(const Common::Path &filename, uint8 *targetBuffer, uint8 **subFilesArray, uint8 *packedBuffer) {
debugC(1, kDebugUtils, "rImageFile %s", filename.toString().c_str());
readFileToBuffer(filename, packedBuffer);
uint32 size = uncompressBuffer(packedBuffer, targetBuffer);
if (ConfMan.getBool("dump_scripts")) {
// dump a decompressed image file
Common::DumpFile dump;
dump.open(filename.append(".dump"));
dump.write(targetBuffer, size);
dump.flush();
dump.close();
// End of dump
}
// TODO: Refactoring: once uncompressed, the container contains for each image its width, its height, and raw data (4 Bpp)
// => Write a class to handle that more properly
uint8 *ptr = targetBuffer;
uint16 counter = 0;
while (READ_LE_INT16(ptr) != 0 && !shouldQuitGame()) {
subFilesArray[counter] = ptr;
++counter;
int16 imageWidth = READ_LE_INT16(ptr);
ptr += 2;
int16 imageHeight = READ_LE_INT16(ptr);
ptr += 2;
ptr += (imageWidth * imageHeight);
}
}
void EfhEngine::readImpFile(int16 id, bool techMapFl) {
debugC(6, kDebugEngine, "readImpFile %d %s", id, techMapFl ? "True" : "False");
Common::Path fileName(Common::String::format("imp.%d", id));
if (techMapFl)
readFileToBuffer(fileName, _imp1);
else
readFileToBuffer(fileName, _imp2);
decryptImpFile(techMapFl);
}
void EfhEngine::readItems() {
debugC(7, kDebugEngine, "readItems");
Common::Path fileName("items");
Common::File f;
if (!f.open(fileName))
error("Unable to find file %s", fileName.toString().c_str());
for (int i = 0; i < 300; ++i) {
for (uint idx = 0; idx < 15; ++idx)
_items[i]._name[idx] = f.readByte();
_items[i]._damage = f.readByte();
_items[i]._defense = f.readByte();
_items[i]._attacks = f.readByte();
_items[i]._uses = f.readByte();
_items[i]._agilityModifier = f.readByte();
_items[i]._range = f.readByte();
_items[i]._attackType = f.readByte();
_items[i]._specialEffect = f.readByte();
_items[i]._defenseType = f.readByte();
_items[i]._exclusiveType = f.readByte();
_items[i]._field19_mapPosX_or_maxDeltaPoints = f.readByte();
_items[i]._mapPosY = f.readByte();
debugC(7, kDebugEngine, "%s\t%x\t%x\t%x\t%x\t%x\t%x\t%x\t%x\t%x\t%x\t%x\t%x", _items[i]._name, _items[i]._damage, _items[i]._defense, _items[i]._attacks, _items[i]._uses, _items[i]._agilityModifier, _items[i]._range, _items[i]._attackType, _items[i]._specialEffect, _items[i]._defenseType, _items[i]._exclusiveType, _items[i]._field19_mapPosX_or_maxDeltaPoints, _items[i]._mapPosY);
}
}
void EfhEngine::loadNewPortrait() {
debugC(7, kDebugEngine, "loadNewPortrait");
static int16 const unkConstRelatedToAnimImageSetId[19] = {0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2};
_unkRelatedToAnimImageSetId = unkConstRelatedToAnimImageSetId[_techId];
if (_currentAnimImageSetId == 200 + _unkRelatedToAnimImageSetId)
return;
findMapFile(_techId);
_currentAnimImageSetId = 200 + _unkRelatedToAnimImageSetId;
int imageSetId = _unkRelatedToAnimImageSetId + 13;
loadImageSet(imageSetId, _portraitBuf, _portraitSubFilesArray, _decompBuf);
}
void EfhEngine::loadAnimImageSet() {
debugC(3, kDebugEngine, "loadAnimImageSet");
if (_currentAnimImageSetId == _animImageSetId || _animImageSetId == 0xFF)
return;
findMapFile(_techId);
_unkAnimRelatedIndex = 0;
_currentAnimImageSetId = _animImageSetId;
int16 animSetId = _animImageSetId + 17;
loadImageSet(animSetId, _portraitBuf, _portraitSubFilesArray, _decompBuf);
}
void EfhEngine::loadHistory() {
debugC(2, kDebugEngine, "loadHistory");
Common::Path fileName("history");
readFileToBuffer(fileName, _history);
}
void EfhEngine::loadTechMapImp(int16 fileId) {
debugC(3, kDebugEngine, "loadTechMapImp %d", fileId);
if (fileId == 0xFF)
return;
_techId = fileId;
findMapFile(_techId);
// The original was loading the specific tech.%d and map.%d files.
// This is gone in our implementation as we pre-load all the files to save them inside the savegames
// This is not present in the original.
// The purpose is to properly load the misc map data in arrays in order to use them without being a pain afterwards
loadMapArrays(_techId);
loadImageSetToTileBank(0, _mapBitmapRefArr[_techId]._setId1);
loadImageSetToTileBank(1, _mapBitmapRefArr[_techId]._setId2);
initMapMonsters();
readImpFile(_techId, true);
displayAnimFrames(0xFE, false);
}
void EfhEngine::loadPlacesFile(uint16 fullPlaceId, bool forceReloadFl) {
debugC(2, kDebugEngine, "loadPlacesFile %d %s", fullPlaceId, forceReloadFl ? "True" : "False");
if (fullPlaceId == 0xFF)
return;
findMapFile(_techId);
_fullPlaceId = fullPlaceId;
uint16 minPlace = _lastMainPlaceId * 20;
uint16 maxPlace = minPlace + 19;
if (_fullPlaceId < minPlace || _fullPlaceId > maxPlace || forceReloadFl) {
_lastMainPlaceId = _fullPlaceId / 20;
Common::Path fileName(Common::String::format("places.%d", _lastMainPlaceId));
readFileToBuffer(fileName, _decompBuf);
uncompressBuffer(_decompBuf, _places);
}
copyCurrentPlaceToBuffer(_fullPlaceId % 20);
}
void EfhEngine::readTileFact() {
debugC(7, kDebugEngine, "readTileFact");
Common::Path fileName("tilefact");
Common::File f;
if (!f.open(fileName))
error("Unable to find file %s", fileName.toString().c_str());
for (int i = 0; i < 432; ++i) {
_tileFact[i]._status = f.readByte();
_tileFact[i]._tileId = f.readByte();
}
}
void EfhEngine::loadNPCS() {
debugC(7, kDebugEngine, "loadNPCS");
Common::Path fileName("npcs");
Common::File f;
if (!f.open(fileName))
error("Unable to find file %s", fileName.toString().c_str());
for (int i = 0; i < 99; ++i) {
for (int idx = 0; idx < 11; ++idx)
_npcBuf[i]._name[idx] = f.readByte();
_npcBuf[i].fieldB_textId = f.readByte();
_npcBuf[i].field_C = f.readByte();
_npcBuf[i].field_D = f.readByte();
_npcBuf[i].fieldE_textId = f.readByte();
_npcBuf[i].field_F = f.readByte();
_npcBuf[i].field_10 = f.readByte();
_npcBuf[i].field11_NpcId = f.readByte();
_npcBuf[i].field12_textId = f.readUint16LE();
_npcBuf[i].field14_textId = f.readUint16LE();
_npcBuf[i]._xp = f.readUint32LE();
for (int idx = 0; idx < 15; ++idx) {
_npcBuf[i]._activeScore[idx] = f.readByte();
}
for (int idx = 0; idx < 11; ++idx) {
_npcBuf[i]._passiveScore[idx] = f.readByte();
}
for (int idx = 0; idx < 11; ++idx) {
_npcBuf[i]._infoScore[idx] = f.readByte();
}
_npcBuf[i].field_3F = f.readByte();
_npcBuf[i].field_40 = f.readByte();
for (int idx = 0; idx < 10; ++idx) {
_npcBuf[i]._inventory[idx]._ref = f.readSint16LE();
_npcBuf[i]._inventory[idx]._stat1 = f.readByte();
_npcBuf[i]._inventory[idx]._curHitPoints = f.readByte();
}
_npcBuf[i]._possessivePronounSHL6 = f.readByte();
_npcBuf[i]._speed = f.readByte();
_npcBuf[i].field_6B = f.readByte();
_npcBuf[i].field_6C = f.readByte();
_npcBuf[i].field_6D = f.readByte();
_npcBuf[i]._defaultDefenseItemId = f.readByte();
_npcBuf[i].field_6F = f.readByte();
_npcBuf[i].field_70 = f.readByte();
_npcBuf[i].field_71 = f.readByte();
_npcBuf[i].field_72 = f.readByte();
_npcBuf[i].field_73 = f.readByte();
_npcBuf[i]._hitPoints = f.readSint16LE();
_npcBuf[i]._maxHP = f.readSint16LE();
_npcBuf[i].field_78 = f.readByte();
_npcBuf[i].field_79 = f.readUint16LE();
_npcBuf[i].field_7B = f.readUint16LE();
_npcBuf[i].field_7D = f.readByte();
_npcBuf[i].field_7E = f.readByte();
_npcBuf[i].field_7F = f.readByte();
_npcBuf[i].field_80 = f.readByte();
_npcBuf[i].field_81 = f.readByte();
_npcBuf[i].field_82 = f.readByte();
_npcBuf[i].field_83 = f.readByte();
_npcBuf[i].field_84 = f.readByte();
_npcBuf[i].field_85 = f.readByte();
}
}
/**
* Pre-Loads MAP and TECH files.
* This is required in order to implement a clean savegame feature
*/
void EfhEngine::preLoadMaps() {
Common::DumpFile dump;
if (ConfMan.getBool("dump_scripts"))
dump.open("efhMaps.dump");
for (int idx = 0; idx < 19; ++idx) {
Common::Path fileName(Common::String::format("tech.%d", idx));
readFileToBuffer(fileName, _decompBuf);
uncompressBuffer(_decompBuf, _techDataArr[idx]);
fileName = Common::Path(Common::String::format("map.%d", idx));
readFileToBuffer(fileName, _decompBuf);
uncompressBuffer(_decompBuf, _mapArr[idx]);
_mapBitmapRefArr[idx]._setId1 = _mapArr[idx][0];
_mapBitmapRefArr[idx]._setId2 = _mapArr[idx][1];
uint8 *mapSpecialTilePtr = &_mapArr[idx][2];
for (int i = 0; i < 100; ++i) {
_mapSpecialTiles[idx][i]._placeId = mapSpecialTilePtr[9 * i];
_mapSpecialTiles[idx][i]._posX = mapSpecialTilePtr[9 * i + 1];
_mapSpecialTiles[idx][i]._posY = mapSpecialTilePtr[9 * i + 2];
_mapSpecialTiles[idx][i]._triggerType = mapSpecialTilePtr[9 * i + 3];
_mapSpecialTiles[idx][i]._triggerValue = mapSpecialTilePtr[9 * i + 4];
_mapSpecialTiles[idx][i]._field5_textId = READ_LE_UINT16(&mapSpecialTilePtr[9 * i + 5]);
_mapSpecialTiles[idx][i]._field7_textId = READ_LE_UINT16(&mapSpecialTilePtr[9 * i + 7]);
if (ConfMan.getBool("dump_scripts") && _mapSpecialTiles[idx][i]._placeId != 0xFF) {
// dump a decoded version of the maps
Common::String buffer = Common::String::format("[%d][%d] _ placeId: 0x%02X _pos: %d, %d _triggerType: 0x%02X (%d), triggerId: %d, _field5/7: %d %d\n"
, idx, i, _mapSpecialTiles[idx][i]._placeId, _mapSpecialTiles[idx][i]._posX, _mapSpecialTiles[idx][i]._posX, _mapSpecialTiles[idx][i]._triggerType
, _mapSpecialTiles[idx][i]._triggerType, _mapSpecialTiles[idx][i]._triggerValue, _mapSpecialTiles[idx][i]._field5_textId, _mapSpecialTiles[idx][i]._field7_textId);
dump.write(buffer.c_str(), buffer.size());
}
}
uint8 *mapMonstersPtr = &_mapArr[idx][902];
for (int i = 0; i < 64; ++i) {
_mapMonsters[idx][i]._possessivePronounSHL6 = mapMonstersPtr[29 * i];
_mapMonsters[idx][i]._npcId = mapMonstersPtr[29 * i + 1];
_mapMonsters[idx][i]._fullPlaceId = mapMonstersPtr[29 * i + 2];
_mapMonsters[idx][i]._posX = mapMonstersPtr[29 * i + 3];
_mapMonsters[idx][i]._posY = mapMonstersPtr[29 * i + 4];
_mapMonsters[idx][i]._weaponItemId = mapMonstersPtr[29 * i + 5];
_mapMonsters[idx][i]._maxDamageAbsorption = mapMonstersPtr[29 * i + 6];
_mapMonsters[idx][i]._monsterRef = mapMonstersPtr[29 * i + 7];
_mapMonsters[idx][i]._additionalInfo = mapMonstersPtr[29 * i + 8];
_mapMonsters[idx][i]._talkTextId = mapMonstersPtr[29 * i + 9];
_mapMonsters[idx][i]._groupSize = mapMonstersPtr[29 * i + 10];
for (int j = 0; j < 9; ++j)
_mapMonsters[idx][i]._hitPoints[j] = READ_LE_INT16(&mapMonstersPtr[29 * i + 11 + j * 2]);
}
uint8 *mapPtr = &_mapArr[idx][2758];
for (int i = 0; i < 64; ++i) {
for (int j = 0; j < 64; ++j)
_mapGameMaps[idx][i][j] = *mapPtr++;
}
}
if (ConfMan.getBool("dump_scripts")) {
dump.flush();
dump.close();
}
}
} // End of namespace Efh