aboutsummaryrefslogtreecommitdiff
path: root/engines
diff options
context:
space:
mode:
authorathrxx2012-01-15 01:13:03 +0100
committerathrxx2012-01-15 13:36:50 +0100
commitd355c536c4d3dea4ff61288d8ac85ab071451825 (patch)
treeb9abfc0c50583fd395d0712513f52e9f47b7c8a5 /engines
parente73984631083a29c072c3bc2191eefbc0d36b9cd (diff)
downloadscummvm-rg350-d355c536c4d3dea4ff61288d8ac85ab071451825.tar.gz
scummvm-rg350-d355c536c4d3dea4ff61288d8ac85ab071451825.tar.bz2
scummvm-rg350-d355c536c4d3dea4ff61288d8ac85ab071451825.zip
KYRA: (EOB) - add support for original save game files
The engine will try to import original save game files once per target (especially the "Quick Start Party"). Afterwards the user can manually import save files with the debug console.
Diffstat (limited to 'engines')
-rw-r--r--engines/kyra/debugger.cpp31
-rw-r--r--engines/kyra/debugger.h3
-rw-r--r--engines/kyra/eobcommon.cpp14
-rw-r--r--engines/kyra/eobcommon.h11
-rw-r--r--engines/kyra/saveload_eob.cpp382
-rw-r--r--engines/kyra/scene_eob.cpp76
-rw-r--r--engines/kyra/script_eob.cpp14
-rw-r--r--engines/kyra/script_eob.h3
8 files changed, 497 insertions, 37 deletions
diff --git a/engines/kyra/debugger.cpp b/engines/kyra/debugger.cpp
index 6514984b93..2c9f9f2eea 100644
--- a/engines/kyra/debugger.cpp
+++ b/engines/kyra/debugger.cpp
@@ -29,6 +29,9 @@
#include "kyra/eobcommon.h"
#include "common/system.h"
+#include "common/config-manager.h"
+
+#include "gui/message.h"
namespace Kyra {
@@ -477,6 +480,34 @@ Debugger_LoL::Debugger_LoL(LoLEngine *vm) : Debugger(vm), _vm(vm) {
#ifdef ENABLE_EOB
Debugger_EoB::Debugger_EoB(EoBCoreEngine *vm) : Debugger(vm), _vm(vm) {
}
+
+void Debugger_EoB::initialize() {
+ DCmd_Register("import_savefile", WRAP_METHOD(Debugger_EoB, cmd_importSaveFile));
+}
+
+bool Debugger_EoB::cmd_importSaveFile(int argc, const char **argv) {
+ if (argc == 3) {
+ int slot = atoi(argv[1]);
+ if (slot < -1 || slot > 989) {
+ DebugPrintf("slot must be between (including) -1 and 989 \n");
+ return true;
+ }
+
+ ::GUI::MessageDialog dialog("Your current game (if any) will be lost if you continue. Make sure to save your game first.\n\n", "Continue", "Cancel");
+ if (!dialog.runModal()) {
+ DebugPrintf("Cancelled.\n");
+ return true;
+ }
+
+ DebugPrintf(_vm->importOriginalSaveFile(slot, argv[2]) ? "Success.\n" : "Failure.\n");
+ _vm->loadItemDefs();
+ } else {
+ DebugPrintf("Syntax: import_savefile <dest slot> <source file>\n (Imports source save game file to dest slot.)\n import_savefile -1\n (Imports all original save game files found and pushs them to the top of the save game list.)\n\n");
+ }
+
+ return true;
+}
+
#endif // ENABLE_EOB
} // End of namespace Kyra
diff --git a/engines/kyra/debugger.h b/engines/kyra/debugger.h
index 77f1a9a550..2b1dcbe505 100644
--- a/engines/kyra/debugger.h
+++ b/engines/kyra/debugger.h
@@ -115,8 +115,11 @@ class Debugger_EoB : public Debugger {
public:
Debugger_EoB(EoBCoreEngine *vm);
+ virtual void initialize();
protected:
EoBCoreEngine *_vm;
+
+ bool cmd_importSaveFile(int argc, const char **argv);
};
#endif // ENABLE_EOB
diff --git a/engines/kyra/eobcommon.cpp b/engines/kyra/eobcommon.cpp
index e45bad6d72..8e99c6f1b3 100644
--- a/engines/kyra/eobcommon.cpp
+++ b/engines/kyra/eobcommon.cpp
@@ -371,7 +371,7 @@ Common::Error EoBCoreEngine::init() {
assert(_sound);
_sound->init();
- // Setup volume settings
+ // Setup volume settings (and read in all ConfigManager settings)
syncSoundSettings();
_res = new Resource(this);
@@ -492,6 +492,8 @@ Common::Error EoBCoreEngine::init() {
}
Common::Error EoBCoreEngine::go() {
+ _debugger->initialize();
+
_txt->removePageBreakFlag();
_screen->loadPalette("palette.col", _screen->getPalette(0));
_screen->setScreenPalette(_screen->getPalette(0));
@@ -500,6 +502,13 @@ Common::Error EoBCoreEngine::go() {
loadItemsAndDecorationsShapes();
_screen->setMouseCursor(0, 0, _itemIconShapes[0]);
+ // Import original save game files (especially the "Quick Start Party")
+ if (ConfMan.getBool("importOrigSaves")) {
+ importOriginalSaveFile(-1);
+ ConfMan.setBool("importOrigSaves", false);
+ ConfMan.flushToDisk();
+ }
+
loadItemDefs();
int action = 0;
@@ -550,6 +559,7 @@ Common::Error EoBCoreEngine::go() {
void EoBCoreEngine::registerDefaultSettings() {
KyraEngine_v1::registerDefaultSettings();
ConfMan.registerDefault("hpbargraphs", true);
+ ConfMan.registerDefault("importOrigSaves", true);
}
void EoBCoreEngine::readSettings() {
@@ -912,7 +922,7 @@ Common::String EoBCoreEngine::getCharStrength(int str, int strExt) {
return _strenghtStr;
}
-int EoBCoreEngine::testCharacter(int index, int flags) {
+int EoBCoreEngine::testCharacter(int16 index, int flags) {
if (index == -1)
return 0;
diff --git a/engines/kyra/eobcommon.h b/engines/kyra/eobcommon.h
index 851c52076b..f17cf05ee5 100644
--- a/engines/kyra/eobcommon.h
+++ b/engines/kyra/eobcommon.h
@@ -242,6 +242,7 @@ class EoBInfProcessor;
class EoBCoreEngine : public KyraRpgEngine {
friend class TextDisplayer_rpg;
friend class GUI_EoB;
+friend class Debugger_EoB;
friend class EoBInfProcessor;
friend class DarkmoonSequenceHelper;
friend class CharacterGenerator;
@@ -365,7 +366,7 @@ protected:
int getCharacterClassType(int cclass, int levelIndex);
int getModifiedHpLimits(int hpModifier, int constModifier, int level, bool mode);
Common::String getCharStrength(int str, int strExt);
- int testCharacter(int index, int flags);
+ int testCharacter(int16 index, int flags);
int getNextValidCharIndex(int curCharIndex, int searchStep);
void recalcArmorClass(int index);
@@ -573,11 +574,13 @@ protected:
// Level
void loadLevel(int level, int sub);
+ void readLevelFileData(int level);
Common::String initLevelData(int sub);
void addLevelItems();
void loadVcnData(const char *file, const char * /*nextFile*/);
void loadBlockProperties(const char *mazFile);
- const uint8 *getBlockFileData(int levelIndex);
+ const uint8 *getBlockFileData(int levelIndex = 0);
+ Common::String getBlockFileName(int levelIndex, int sub);
const uint8 *getBlockFileData(const char *mazFile);
void loadDecorations(const char *cpsFile, const char *decFile);
void assignWallsAndDecorations(int wallIndex, int vmpIndex, int decDataIndex, int specialType, int flags);
@@ -831,6 +834,10 @@ protected:
Common::Error loadGameState(int slot);
Common::Error saveGameStateIntern(int slot, const char *saveName, const Graphics::Surface *thumbnail);
+ // Default parameters will import all present original save files and push them to the top of the save dialog.
+ bool importOriginalSaveFile(int destSlot, const char *sourceFile = 0);
+ Common::String readOriginalSaveFile(Common::String &file);
+
void *generateMonsterTempData(LevelTempData *tmp);
void restoreMonsterTempData(LevelTempData *tmp);
void releaseMonsterTempData(LevelTempData *tmp);
diff --git a/engines/kyra/saveload_eob.cpp b/engines/kyra/saveload_eob.cpp
index ef5e8dc7a4..4edd46ffa2 100644
--- a/engines/kyra/saveload_eob.cpp
+++ b/engines/kyra/saveload_eob.cpp
@@ -28,6 +28,10 @@
#include "common/system.h"
#include "common/savefile.h"
#include "common/substream.h"
+#include "common/config-manager.h"
+#include "common/translation.h"
+
+#include "gui/message.h"
namespace Kyra {
@@ -134,7 +138,7 @@ Common::Error EoBCoreEngine::loadGameState(int slot) {
_updateFlags = in.readUint16BE();
_compassDirection = in.readUint16BE();
_currentControlMode = in.readUint16BE();
- _updateCharNum = in.readUint16BE();
+ _updateCharNum = in.readSint16BE();
_openBookSpellLevel = in.readSByte();
_openBookSpellSelectedItem = in.readSByte();
_openBookSpellListOffset = in.readSByte();
@@ -395,7 +399,7 @@ Common::Error EoBCoreEngine::saveGameStateIntern(int slot, const char *saveName,
out->writeUint16BE(_updateFlags);
out->writeUint16BE(_compassDirection);
out->writeUint16BE(_currentControlMode);
- out->writeUint16BE(_updateCharNum);
+ out->writeSint16BE(_updateCharNum);
out->writeSByte(_openBookSpellLevel);
out->writeSByte(_openBookSpellSelectedItem);
out->writeSByte(_openBookSpellListOffset);
@@ -524,6 +528,380 @@ Common::Error EoBCoreEngine::saveGameStateIntern(int slot, const char *saveName,
return Common::kNoError;
}
+bool EoBCoreEngine::importOriginalSaveFile(int destSlot, const char *sourceFile) {
+ Common::Array<Common::String> origFiles;
+
+ if (sourceFile) {
+ // If a source file is specified via the console command we just check whether it exists.
+ if (Common::File::exists(sourceFile))
+ origFiles.push_back(sourceFile);
+ else
+ return false;
+ } else {
+ // Check for original save files in the game path (usually at least the "Quick Start Party" file will be present).
+ int numMax = (_flags.gameID == GI_EOB1) ? 1 : 6;
+ const char *pattern = (_flags.gameID == GI_EOB1) ? "EOBDATA.SAV" : "EOBDATA%d.SAV";
+ for (int i = 0; i < numMax; ++i) {
+ Common::String temp = Common::String::format(pattern, i);
+ Common::SeekableReadStream *fs = _res->createReadStream(temp);
+ if (fs) {
+ Common::String dsc;
+ if (_flags.gameID == GI_EOB2) {
+ char descStr[20];
+ fs->read(descStr, 20);
+ dsc = Common::String::format("(\"%s\")", descStr).c_str();
+ }
+
+ delete fs;
+ ::GUI::MessageDialog dialog(Common::String::format(_("The following original save game file has been found in your game path:\n\n%s %s\n\nDo you wish to use this save game file with ScummVM?\n\n"), temp.c_str(), dsc.c_str()), _("Yes"), _("No"));
+ if (dialog.runModal())
+ origFiles.push_back(temp);
+ }
+ }
+ }
+
+ int numFilesFound = origFiles.size();
+ if (!numFilesFound)
+ return false;
+
+ int moveUpSlots = 0;
+ _gui->updateSaveSlotsList(_targetName, true);
+
+ // Check whether ScummVM save files exist and how many slots they need to be moved up to make space for the original save files
+ if (destSlot == -1) {
+ for (int i = 0; i < numFilesFound; ++i) {
+ if (Common::find(_gui->_saveSlots.begin(), _gui->_saveSlots.end(), i) != _gui->_saveSlots.end())
+ moveUpSlots++;
+ }
+ }
+
+ // "move up" existing save files
+ if (moveUpSlots) {
+ Common::sort(_gui->_saveSlots.begin(), _gui->_saveSlots.end(), Common::Greater<int>());
+ for (Common::Array<int>::iterator i = _gui->_saveSlots.begin(); i != _gui->_saveSlots.end(); ++i) {
+ int newIndex = *i + moveUpSlots;
+
+ if (*i >= 990) {
+ // Skip quick save slots
+ continue;
+ } else if (*i >= (990 - moveUpSlots)) {
+ // Try to squeeze occupied slots together by finding and occupying empty slots before the current one if necessary
+ int missingSlots = moveUpSlots - (989 - *i);
+ int missingLeft = missingSlots;
+ int missingLast = missingLeft;
+ Common::Array<int>::iterator squeezeStart = i + 1;
+
+ for (; squeezeStart != _gui->_saveSlots.end() && missingLeft; ++squeezeStart) {
+ int diff = *(squeezeStart - 1) - *squeezeStart - 1;
+ missingLast = MIN(missingLeft, diff);
+ missingLeft -= missingLast;
+ }
+
+ // This will probably never happen, since we do have 990 save slots
+ if (missingLeft)
+ warning("%d original save files could not be converted due to missing save game slots", missingLeft);
+
+ int indexS = *(squeezeStart - 2) - missingLast;
+ for (Common::Array<int>::iterator ii = squeezeStart - 2; ii != i - 1; --ii)
+ _saveFileMan->renameSavefile(getSavegameFilename(*ii), getSavegameFilename(indexS++));
+
+ int newPos = *i -= (missingSlots - missingLeft);
+
+ _gui->updateSaveSlotsList(_targetName, true);
+ Common::sort(_gui->_saveSlots.begin(), _gui->_saveSlots.end(), Common::Greater<int>());
+ i = Common::find(_gui->_saveSlots.begin(), _gui->_saveSlots.end(), newPos);
+ if (i == _gui->_saveSlots.end())
+ error("EoBCoreEngine::importOriginalSaveFile(): Unknown error");
+ newIndex = *i + moveUpSlots;
+ }
+
+ _saveFileMan->renameSavefile(getSavegameFilename(*i), getSavegameFilename(newIndex));
+ }
+ }
+
+ int curSlot = MAX(destSlot, 0);
+
+ if (destSlot != -1) {
+ if (Common::find(_gui->_saveSlots.begin(), _gui->_saveSlots.end(), destSlot) != _gui->_saveSlots.end()) {
+ ::GUI::MessageDialog dialog(Common::String::format(_("A save game file was found in the specified slot %d. Overwrite?\n\n"), destSlot), _("Yes"), _("No"));
+ if (!dialog.runModal())
+ return false;
+ }
+ }
+
+ for (Common::Array<Common::String>::iterator i = origFiles.begin(); i != origFiles.end(); ++i) {
+ Common::String desc = readOriginalSaveFile(*i);
+ if (desc.empty()) {
+ warning("Unable to import original save file '%s'", i->c_str());
+ } else {
+ // We can't make thumbnails here, since we do not want to load all the level data, monsters, etc. for each save we convert.
+ // Instead, we use an empty surface to avoid that createThumbnailFromScreen() makes a completely pointless thumbnail from
+ // whatever screen that is currently shown when this function is called.
+ Graphics::Surface dummy;
+ saveGameStateIntern(curSlot++, desc.c_str(), &dummy);
+ warning("Imported original save file '%s' ('%s')", i->c_str(), desc.c_str());
+ }
+ }
+
+ _currentLevel = 0;
+ _currentSub = 0;
+ _currentBlock = 0;
+ _currentDirection = 0;
+ _itemInHand = 0;
+ _hasTempDataFlags = 0;
+ _partyEffectFlags = 0;
+ memset(_characters, 0, sizeof(EoBCharacter) * 6);
+ _inf->reset();
+
+ if (destSlot == -1 && curSlot) {
+ ::GUI::MessageDialog dialog(_("One or more original save game files have been successfully imported into\nScummVM. If you want to manually import original save game files later you will\nneed to open the ScummVM debug console and use the command 'import_savefile'.\n\n"));
+ dialog.runModal();
+ }
+
+ return true;
+}
+
+Common::String EoBCoreEngine::readOriginalSaveFile(Common::String &file) {
+ Common::String desc;
+
+ Common::SeekableReadStream *fs = _res->createReadStream(file);
+ if (!fs)
+ return desc;
+
+ Common::SeekableSubReadStreamEndian in(fs, 0, fs->size(), _flags.platform == Common::kPlatformAmiga, DisposeAfterUse::YES);
+
+ if (_flags.gameID == GI_EOB1) {
+ // Nothing to read here for EOB 1. Original EOB 1 has
+ // only one save slot without save file description.
+ desc = "<IMPORTED GAME>";
+ } else {
+ char tempStr[20];
+ in.read(tempStr, 20);
+ desc = tempStr;
+ }
+
+ for (int i = 0; i < 6; i++) {
+ EoBCharacter *c = &_characters[i];
+ c->id = in.readByte();
+ c->flags = in.readByte();
+ in.read(c->name, 11);
+ c->strengthCur = in.readSByte();
+ c->strengthMax = in.readSByte();
+ c->strengthExtCur = in.readSByte();
+ c->strengthExtMax = in.readSByte();
+ c->intelligenceCur = in.readSByte();
+ c->intelligenceMax = in.readSByte();
+ c->wisdomCur = in.readSByte();
+ c->wisdomMax = in.readSByte();
+ c->dexterityCur = in.readSByte();
+ c->dexterityMax = in.readSByte();
+ c->constitutionCur = in.readSByte();
+ c->constitutionMax = in.readSByte();
+ c->charismaCur = in.readSByte();
+ c->charismaMax = in.readSByte();
+ c->hitPointsCur = (_flags.gameID == GI_EOB1) ? in.readSByte() : in.readSint16();
+ c->hitPointsMax = (_flags.gameID == GI_EOB1) ? in.readSByte() : in.readSint16();
+ c->armorClass = in.readSByte();
+ c->disabledSlots = in.readByte();
+ c->raceSex = in.readByte();
+ c->cClass = in.readByte();
+ c->alignment = in.readByte();
+ c->portrait = in.readSByte();
+ c->food = in.readByte();
+ in.read(c->level, 3);
+ for (int ii = 0; ii < 3; ii++)
+ c->experience[ii] = in.readUint32();
+ in.skip(4);
+ delete[] c->faceShape;
+ c->faceShape = 0;
+ in.read(c->mageSpells, (_flags.gameID == GI_EOB1) ? 30 :80);
+ in.read(c->clericSpells, (_flags.gameID == GI_EOB1) ? 30 : 80);
+ c->mageSpellsAvailableFlags = in.readUint32();
+ for (int ii = 0; ii < 27; ii++)
+ c->inventory[ii] = in.readSint16();
+ uint32 ct = _system->getMillis();
+ for (int ii = 0; ii < 10; ii++) {
+ c->timers[ii] = in.readUint32() * _tickLength;
+ if (c->timers[ii])
+ c->timers[ii] += ct;
+ }
+ in.read(c->events, 10);
+ in.read(c->effectsRemainder, 4);
+ c->effectFlags = in.readUint32();
+ if (c->effectFlags && _flags.gameID == GI_EOB1) {
+ warning("EoBCoreEngine::readOriginalSaveFile(): Unhandled character effect flags encountered in original EOB1 save file '%s' ('%s')", file.c_str(), desc.c_str());
+ c->effectFlags = 0;
+ }
+ c->damageTaken = in.readByte();
+ in.read(c->slotStatus, 5);
+ in.skip(6);
+ }
+
+ setupCharacterTimers();
+
+ _currentLevel = in.readUint16();
+ _currentSub = (_flags.gameID == GI_EOB1) ? 0 : in.readSint16();
+ _currentBlock = in.readUint16();
+ _currentDirection = in.readUint16();
+ _itemInHand = in.readSint16();
+ _hasTempDataFlags = (_flags.gameID == GI_EOB1) ? in.readUint16() : in.readUint32();
+ _partyEffectFlags = (_flags.gameID == GI_EOB1) ? in.readUint16() : in.readUint32();
+ if (_partyEffectFlags && _flags.gameID == GI_EOB1) {
+ warning("EoBCoreEngine::readOriginalSaveFile(): Unhandled party effect flags encountered in original EOB1 save file '%s' ('%s')", file.c_str(), desc.c_str());
+ _partyEffectFlags = 0;
+ }
+ if (_flags.gameID == GI_EOB2)
+ in.skip(1);
+
+ _inf->loadState(in, true);
+
+ int numItems = (_flags.gameID == GI_EOB1) ? 500 : 600;
+ for (int i = 0; i < numItems; i++) {
+ EoBItem *t = &_items[i];
+ t->nameUnid = in.readByte();
+ t->nameId = in.readByte();
+ t->flags = in.readByte();
+ t->icon = in.readSByte();
+ t->type = in.readSByte();
+ t->pos = in.readSByte();
+ t->block = in.readSint16();
+ t->next = in.readSint16();
+ t->prev = in.readSint16();
+ t->level = in.readByte();
+ t->value = in.readSByte();
+ }
+
+ int numParts = (_flags.gameID == GI_EOB1) ? 13 : 18;
+ int partSize = (_flags.gameID == GI_EOB1) ? 2040 : 2130;
+ uint32 nextPart = in.pos();
+ uint8 *cmpData = new uint8[1200];
+
+ for (int i = 0; i < numParts; i++) {
+ in.seek(nextPart);
+ nextPart += partSize;
+
+ if (!(_hasTempDataFlags & (1 << i)))
+ continue;
+
+ if (_lvlTempData[i]) {
+ delete[] _lvlTempData[i]->wallsXorData;
+ delete[] _lvlTempData[i]->flags;
+ releaseMonsterTempData(_lvlTempData[i]);
+ releaseFlyingObjectTempData(_lvlTempData[i]);
+ releaseWallOfForceTempData(_lvlTempData[i]);
+ delete _lvlTempData[i];
+ }
+
+ _lvlTempData[i] = new LevelTempData;
+ LevelTempData *l = _lvlTempData[i];
+ l->wallsXorData = new uint8[4096];
+ l->flags = new uint16[1024];
+ memset(l->flags, 0, 1024 * sizeof(uint16));
+ EoBMonsterInPlay *lm = new EoBMonsterInPlay[30];
+ l->monsters = lm;
+ EoBFlyingObject *lf = new EoBFlyingObject[_numFlyingObjects];
+ memset(lf, 0, _numFlyingObjects * sizeof(EoBFlyingObject));
+ l->flyingObjects = lf;
+ WallOfForce *lw = new WallOfForce[5];
+ memset(lw, 0, 5 * sizeof(WallOfForce));
+ l->wallsOfForce = lw;
+
+ in.read(cmpData, 1200);
+ _screen->decodeFrame4(cmpData, l->wallsXorData, 4096);
+ _curBlockFile = getBlockFileName(i + 1, 0);
+ const uint8 *p = getBlockFileData();
+ uint16 len = READ_LE_UINT16(p + 4);
+ p += 6;
+
+ uint8 *d = l->wallsXorData;
+ for (int ii = 0; ii < 1024; ii++) {
+ for (int iii = 0; iii < 4; iii++)
+ *d++ ^= p[ii * len + iii];
+ }
+
+ for (int ii = 0; ii < 30; ii++) {
+ EoBMonsterInPlay *m = &lm[ii];
+ m->type = in.readByte();
+ m->unit = in.readByte();
+ m->block = in.readUint16();
+ m->pos = in.readByte();
+ m->dir = in.readSByte();
+ m->animStep = in.readByte();
+ m->shpIndex = in.readByte();
+ m->mode = in.readSByte();
+ m->f_9 = in.readSByte();
+ m->curAttackFrame = in.readSByte();
+ m->spellStatusLeft = in.readSByte();
+ m->hitPointsMax = in.readSint16();
+ m->hitPointsCur = in.readSint16();
+ m->dest = in.readUint16();
+ m->randItem = in.readUint16();
+ m->fixedItem = in.readUint16();
+ m->flags = in.readByte();
+ m->idleAnimState = in.readByte();
+
+ if (_flags.gameID == GI_EOB1)
+ m->stepsTillRemoteAttack = in.readByte();
+ else
+ m->curRemoteWeapon = in.readByte();
+
+ m->numRemoteAttacks = in.readByte();
+ m->palette = in.readSByte();
+
+ if (_flags.gameID == GI_EOB1) {
+ in.skip(1);
+ } else {
+ m->directionChanged = in.readByte();
+ m->stepsTillRemoteAttack = in.readByte();
+ m->sub = in.readByte();
+ }
+
+ _levelBlockProperties[m->block].flags++;
+ }
+
+ if (_flags.gameID == GI_EOB1)
+ continue;
+
+ for (int ii = 0; ii < 5; ii++) {
+ WallOfForce *w = &lw[ii];
+ w->block = in.readUint16();
+ w->duration = in.readUint32();
+ }
+ }
+
+ delete[] cmpData;
+
+ restoreBlockTempData(_currentLevel);
+
+ in.skip(3);
+
+ delete[] _itemTypes;
+ _itemTypes = new EoBItemType[65];
+ memset(_itemTypes, 0, sizeof(EoBItemType) * 65);
+
+ if (_flags.gameID == GI_EOB1)
+ return desc;
+
+ for (int i = 51; i < 65; i++) {
+ EoBItemType *t = &_itemTypes[i];
+ t->invFlags = in.readUint16();
+ t->handFlags = in.readUint16();
+ t->armorClass = in.readSByte();
+ t->allowedClasses = in.readSByte();
+ t->requiredHands = in.readSByte();
+ t->dmgNumDiceS = in.readSByte();
+ t->dmgNumPipsS = in.readSByte();
+ t->dmgIncS = in.readSByte();
+ t->dmgNumDiceL = in.readSByte();
+ t->dmgNumPipsL = in.readSByte();
+ t->dmgIncL = in.readSByte();
+ t->unk1 = in.readByte();
+ t->extraProperties = in.readUint16();
+ }
+
+ return desc;
+}
+
void *EoBCoreEngine::generateMonsterTempData(LevelTempData *tmp) {
EoBMonsterInPlay *m = new EoBMonsterInPlay[30];
memcpy(m, _monsters, sizeof(EoBMonsterInPlay) * 30);
diff --git a/engines/kyra/scene_eob.cpp b/engines/kyra/scene_eob.cpp
index 982191b359..3d615e966a 100644
--- a/engines/kyra/scene_eob.cpp
+++ b/engines/kyra/scene_eob.cpp
@@ -38,31 +38,7 @@ void EoBCoreEngine::loadLevel(int level, int sub) {
_currentSub = sub;
uint32 end = _system->getMillis() + 500;
- Common::String file;
- Common::SeekableReadStream *s = 0;
- static const char *suffix[] = { "INF", "DRO", "ELO", 0 };
-
- for (const char *const *sf = suffix; *sf && !s; sf++) {
- file = Common::String::format("LEVEL%d.%s", level, *sf);
- s = _res->createReadStream(file);
- }
-
- if (!s)
- error("Failed to load level file LEVEL%d.INF/DRO/ELO", level);
-
- if (s->readUint16LE() + 2 == s->size()) {
- if (s->readUint16LE() == 4) {
- delete s;
- s = 0;
- _screen->loadBitmap(file.c_str(), 5, 5, 0);
- }
- }
-
- if (s) {
- s->seek(0);
- _screen->loadFileDataToPage(s, 5, 15000);
- delete s;
- }
+ readLevelFileData(level);
Common::String gfxFile;
// Work around for issue with corrupt (incomplete) monster property data
@@ -121,6 +97,34 @@ void EoBCoreEngine::loadLevel(int level, int sub) {
_screen->setCurPage(0);
}
+void EoBCoreEngine::readLevelFileData(int level) {
+ Common::String file;
+ Common::SeekableReadStream *s = 0;
+ static const char *suffix[] = { "INF", "DRO", "ELO", 0 };
+
+ for (const char *const *sf = suffix; *sf && !s; sf++) {
+ file = Common::String::format("LEVEL%d.%s", level, *sf);
+ s = _res->createReadStream(file);
+ }
+
+ if (!s)
+ error("Failed to load level file LEVEL%d.INF/DRO/ELO", level);
+
+ if (s->readUint16LE() + 2 == s->size()) {
+ if (s->readUint16LE() == 4) {
+ delete s;
+ s = 0;
+ _screen->loadBitmap(file.c_str(), 5, 5, 0);
+ }
+ }
+
+ if (s) {
+ s->seek(0);
+ _screen->loadFileDataToPage(s, 5, 15000);
+ delete s;
+ }
+}
+
Common::String EoBCoreEngine::initLevelData(int sub) {
const uint8 *data = _screen->getCPagePtr(5) + 2;
const uint8 *pos = data;
@@ -300,9 +304,29 @@ const uint8 *EoBCoreEngine::getBlockFileData(int) {
return _screen->getCPagePtr(14);
}
+Common::String EoBCoreEngine::getBlockFileName(int levelIndex, int sub) {
+ readLevelFileData(levelIndex);
+ const uint8 *data = _screen->getCPagePtr(5) + 2;
+ const uint8 *pos = data;
+
+ for (int i = 0; i < sub; i++)
+ pos = data + READ_LE_UINT16(pos);
+
+ pos += 2;
+
+ if (*pos++ == 0xEC || _flags.gameID == GI_EOB1) {
+ if (_flags.gameID == GI_EOB1)
+ pos -= 3;
+
+ return Common::String((const char *)pos);
+ }
+
+ return Common::String();
+}
+
const uint8 *EoBCoreEngine::getBlockFileData(const char *mazFile) {
_curBlockFile = mazFile;
- return getBlockFileData(0);
+ return getBlockFileData();
}
void EoBCoreEngine::loadDecorations(const char *cpsFile, const char *decFile) {
diff --git a/engines/kyra/script_eob.cpp b/engines/kyra/script_eob.cpp
index 267966dde2..c07c41f706 100644
--- a/engines/kyra/script_eob.cpp
+++ b/engines/kyra/script_eob.cpp
@@ -214,10 +214,11 @@ bool EoBInfProcessor::preventRest() const {
return _preventRest ? true : false;
}
-void EoBInfProcessor::loadState(Common::SeekableSubReadStreamEndian &in) {
- _preventRest = in.readByte();
- for (int i = 0; i < 18; i++)
- _flagTable[i] = in.readUint32BE();
+void EoBInfProcessor::loadState(Common::SeekableSubReadStreamEndian &in, bool origFile) {
+ _preventRest = (_vm->game() == GI_EOB1 && origFile) ? 0 : in.readByte();
+ int numFlags = (_vm->game() == GI_EOB1 && origFile) ? 13 : 18;
+ for (int i = 0; i < numFlags; i++)
+ _flagTable[i] = in.readUint32();
}
void EoBInfProcessor::saveState(Common::OutSaveFile *out) {
@@ -226,6 +227,11 @@ void EoBInfProcessor::saveState(Common::OutSaveFile *out) {
out->writeUint32BE(_flagTable[i]);
}
+void EoBInfProcessor::reset() {
+ _preventRest = 0;
+ memset(_flagTable, 0, 18 * sizeof(uint32));
+}
+
const char *EoBInfProcessor::getString(uint16 index) {
if (index == 0xffff)
return 0;
diff --git a/engines/kyra/script_eob.h b/engines/kyra/script_eob.h
index 66323d6846..391791522a 100644
--- a/engines/kyra/script_eob.h
+++ b/engines/kyra/script_eob.h
@@ -47,8 +47,9 @@ public:
bool checkFlags(uint32 flags) const;
bool preventRest() const;
- void loadState(Common::SeekableSubReadStreamEndian &in);
+ void loadState(Common::SeekableSubReadStreamEndian &in, bool origFile = false);
void saveState(Common::OutSaveFile *out);
+ void reset();
private:
const char *getString(uint16 index);