KYRA: (LOL) - add support for loading original DOS version save files
This commit is contained in:
parent
a2b553a017
commit
3adc1ab467
3 changed files with 148 additions and 71 deletions
2
NEWS
2
NEWS
|
@ -9,6 +9,8 @@ For a more comprehensive changelog of the latest experimental code, see:
|
|||
KYRA:
|
||||
- Fixed bug in the original Lands of Lore GUI which made ScummVM error out
|
||||
in the case the user did not have a contiguous save slot usage.
|
||||
- Add support for original DOS Lands of Lore save files (also applies to save
|
||||
files made with the GOG release)
|
||||
|
||||
SCI:
|
||||
- Fixed race condition in SCI1.1 palette changes. This fixes an error in
|
||||
|
|
|
@ -54,7 +54,7 @@ KyraEngine_v1::kReadSaveHeaderError KyraEngine_v1::readSaveHeader(Common::Seekab
|
|||
header.gameID = in->readByte();
|
||||
} else {
|
||||
// try checking for original save header
|
||||
const int descriptionSize[2] = { 30, 80 };
|
||||
const int descriptionSize[3] = { 30, 80, 60 };
|
||||
char descriptionBuffer[81];
|
||||
|
||||
bool saveOk = false;
|
||||
|
@ -78,6 +78,16 @@ KyraEngine_v1::kReadSaveHeaderError KyraEngine_v1::readSaveHeader(Common::Seekab
|
|||
header.description = descriptionBuffer;
|
||||
header.gameID = GI_KYRA3;
|
||||
break;
|
||||
} else if (type == MKTAG('C','D','0','4')) {
|
||||
header.version = in->readUint32BE();
|
||||
// We don't check the minor version, since the original doesn't do that either and it isn't required.
|
||||
if (header.version != MKTAG(' ','C','D','1'))
|
||||
continue;
|
||||
saveOk = true;
|
||||
header.description = descriptionBuffer;
|
||||
header.gameID = GI_LOL;
|
||||
in->seek(6, SEEK_CUR);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
|
||||
#include "common/savefile.h"
|
||||
#include "common/substream.h"
|
||||
#include "common/memstream.h"
|
||||
|
||||
#include "graphics/scaler.h"
|
||||
|
||||
|
@ -44,6 +45,9 @@ Common::Error LoLEngine::loadGameState(int slot) {
|
|||
return Common::kNoError;
|
||||
}
|
||||
|
||||
if (header.originalSave)
|
||||
warning("Trying to load savegame from original interpreter, while this is possible, it is not officially supported");
|
||||
|
||||
_screen->fadeClearSceneWindow(10);
|
||||
completeDoorOperations();
|
||||
_screen->fillRect(112, 0, 287, 119, 0, 0);
|
||||
|
@ -53,38 +57,40 @@ Common::Error LoLEngine::loadGameState(int slot) {
|
|||
|
||||
for (int i = 0; i < 4; i++) {
|
||||
LoLCharacter *c = &_characters[i];
|
||||
c->flags = in.readUint16BE();
|
||||
c->flags = in.readUint16();
|
||||
in.read(c->name, 11);
|
||||
c->raceClassSex = in.readByte();
|
||||
c->id = in.readSint16BE();
|
||||
c->id = in.readSint16();
|
||||
c->curFaceFrame = in.readByte();
|
||||
c->tempFaceFrame = in.readByte();
|
||||
c->screamSfx = in.readByte();
|
||||
if (header.originalSave)
|
||||
in.skip(4);
|
||||
for (int ii = 0; ii < 8; ii++)
|
||||
c->itemsMight[ii] = in.readUint16BE();
|
||||
c->itemsMight[ii] = in.readUint16();
|
||||
for (int ii = 0; ii < 8; ii++)
|
||||
c->protectionAgainstItems[ii] = in.readUint16BE();
|
||||
c->itemProtection = in.readUint16BE();
|
||||
c->hitPointsCur = in.readSint16BE();
|
||||
c->hitPointsMax = in.readUint16BE();
|
||||
c->magicPointsCur = in.readSint16BE();
|
||||
c->magicPointsMax = in.readUint16BE();
|
||||
c->protectionAgainstItems[ii] = in.readUint16();
|
||||
c->itemProtection = in.readUint16();
|
||||
c->hitPointsCur = in.readSint16();
|
||||
c->hitPointsMax = in.readUint16();
|
||||
c->magicPointsCur = in.readSint16();
|
||||
c->magicPointsMax = in.readUint16();
|
||||
c->field_41 = in.readByte();
|
||||
c->damageSuffered = in.readUint16BE();
|
||||
c->weaponHit = in.readUint16BE();
|
||||
c->totalMightModifier = in.readUint16BE();
|
||||
c->totalProtectionModifier = in.readUint16BE();
|
||||
c->might = in.readUint16BE();
|
||||
c->protection = in.readUint16BE();
|
||||
c->nextAnimUpdateCountdown = in.readSint16BE();
|
||||
c->damageSuffered = in.readUint16();
|
||||
c->weaponHit = in.readUint16();
|
||||
c->totalMightModifier = in.readUint16();
|
||||
c->totalProtectionModifier = in.readUint16();
|
||||
c->might = in.readUint16();
|
||||
c->protection = in.readUint16();
|
||||
c->nextAnimUpdateCountdown = in.readSint16();
|
||||
for (int ii = 0; ii < 11; ii++)
|
||||
c->items[ii] = in.readUint16BE();
|
||||
c->items[ii] = in.readUint16();
|
||||
for (int ii = 0; ii < 3; ii++)
|
||||
c->skillLevels[ii] = in.readByte();
|
||||
for (int ii = 0; ii < 3; ii++)
|
||||
c->skillModifiers[ii] = in.readSByte();
|
||||
for (int ii = 0; ii < 3; ii++)
|
||||
c->experiencePts[ii] = in.readUint32BE();
|
||||
c->experiencePts[ii] = in.readUint32();
|
||||
for (int ii = 0; ii < 5; ii++)
|
||||
c->characterUpdateEvents[ii] = in.readByte();
|
||||
for (int ii = 0; ii < 5; ii++)
|
||||
|
@ -96,39 +102,48 @@ Common::Error LoLEngine::loadGameState(int slot) {
|
|||
}
|
||||
}
|
||||
|
||||
in.read(_wllBuffer4, 80);
|
||||
if (!header.originalSave)
|
||||
in.read(_wllBuffer4, 80);
|
||||
|
||||
_currentBlock = in.readUint16BE();
|
||||
_partyPosX = in.readUint16BE();
|
||||
_partyPosY = in.readUint16BE();
|
||||
_updateFlags = in.readUint16BE();
|
||||
_currentBlock = in.readUint16();
|
||||
_partyPosX = in.readUint16();
|
||||
_partyPosY = in.readUint16();
|
||||
_updateFlags = in.readUint16();
|
||||
_scriptDirection = in.readByte();
|
||||
_selectedSpell = in.readByte();
|
||||
|
||||
if (header.originalSave)
|
||||
in.skip(2);
|
||||
|
||||
_sceneDefaultUpdate = in.readByte();
|
||||
_compassBroken = in.readByte();
|
||||
_drainMagic = in.readByte();
|
||||
_currentDirection = in.readUint16BE();
|
||||
_compassDirection = in.readUint16BE();
|
||||
_currentDirection = in.readUint16();
|
||||
_compassDirection = in.readUint16();
|
||||
_selectedCharacter = in.readSByte();
|
||||
|
||||
if (header.originalSave)
|
||||
in.skip(1);
|
||||
|
||||
_currentLevel = in.readByte();
|
||||
for (int i = 0; i < 48; i++)
|
||||
_inventory[i] = in.readSint16BE();
|
||||
_inventoryCurItem = in.readSint16BE();
|
||||
_itemInHand = in.readSint16BE();
|
||||
_lastMouseRegion = in.readSint16BE();
|
||||
_inventory[i] = in.readSint16();
|
||||
_inventoryCurItem = in.readSint16();
|
||||
_itemInHand = in.readSint16();
|
||||
_lastMouseRegion = in.readSint16();
|
||||
|
||||
if (header.version <= 15) {
|
||||
if (header.originalSave || header.version <= 15) {
|
||||
uint16 flags[40];
|
||||
memset(flags, 0, sizeof(flags));
|
||||
|
||||
if (header.version == 14) {
|
||||
for (int i = 0; i < 16; i++)
|
||||
flags[i] = in.readUint16BE();
|
||||
flags[26] = in.readUint16BE();
|
||||
flags[36] = in.readUint16BE();
|
||||
} else if (header.version == 15) {
|
||||
flags[i] = in.readUint16();
|
||||
flags[26] = in.readUint16();
|
||||
flags[36] = in.readUint16();
|
||||
} else if (header.originalSave || header.version == 15) {
|
||||
for (int i = 0; i < 40; i++)
|
||||
flags[i] = in.readUint16BE();
|
||||
flags[i] = in.readUint16();
|
||||
}
|
||||
|
||||
memset(_flagsTable, 0, sizeof(_flagsTable));
|
||||
|
@ -139,37 +154,56 @@ Common::Error LoLEngine::loadGameState(int slot) {
|
|||
}
|
||||
}
|
||||
} else {
|
||||
uint32 flagsSize = in.readUint32BE();
|
||||
uint32 flagsSize = in.readUint32();
|
||||
assert(flagsSize <= sizeof(_flagsTable));
|
||||
in.read(_flagsTable, flagsSize);
|
||||
}
|
||||
|
||||
if (header.originalSave)
|
||||
in.skip(120);
|
||||
|
||||
for (int i = 0; i < 24; i++)
|
||||
_globalScriptVars[i] = in.readUint16BE();
|
||||
_globalScriptVars[i] = in.readUint16();
|
||||
|
||||
if (header.originalSave)
|
||||
in.skip(152);
|
||||
|
||||
_brightness = in.readByte();
|
||||
_lampOilStatus = in.readByte();
|
||||
_lampEffect = in.readSByte();
|
||||
_credits = in.readUint16BE();
|
||||
|
||||
if (header.originalSave)
|
||||
in.skip(1);
|
||||
|
||||
_credits = in.readUint16();
|
||||
for (int i = 0; i < 8; i++)
|
||||
_globalScriptVars2[i] = in.readUint16BE();
|
||||
_globalScriptVars2[i] = in.readUint16();
|
||||
in.read(_availableSpells, 7);
|
||||
_hasTempDataFlags = in.readUint32BE();
|
||||
_hasTempDataFlags = in.readUint32();
|
||||
|
||||
uint8 *origCmp = 0;
|
||||
if (header.originalSave) {
|
||||
in.skip(6);
|
||||
origCmp = new uint8[2496];
|
||||
}
|
||||
|
||||
for (int i = 0; i < 400; i++) {
|
||||
ItemInPlay *t = &_itemsInPlay[i];
|
||||
t->nextAssignedObject = in.readUint16BE();
|
||||
t->nextDrawObject = in.readUint16BE();
|
||||
t->nextAssignedObject = in.readUint16();
|
||||
t->nextDrawObject = in.readUint16();
|
||||
t->flyingHeight = in.readByte();
|
||||
t->block = in.readUint16BE();
|
||||
t->x = in.readUint16BE();
|
||||
t->y = in.readUint16BE();
|
||||
t->block = in.readUint16();
|
||||
t->x = in.readUint16();
|
||||
t->y = in.readUint16();
|
||||
t->level = in.readSByte();
|
||||
t->itemPropertyIndex = in.readUint16BE();
|
||||
t->shpCurFrame_flg = in.readUint16BE();
|
||||
t->destDirection = in.readByte();
|
||||
t->hitOffsX = in.readSByte();
|
||||
t->hitOffsY = in.readSByte();
|
||||
t->currentSubFrame = in.readByte();
|
||||
t->itemPropertyIndex = in.readUint16();
|
||||
t->shpCurFrame_flg = in.readUint16();
|
||||
if (!header.originalSave) {
|
||||
t->destDirection = in.readByte();
|
||||
t->hitOffsX = in.readSByte();
|
||||
t->hitOffsY = in.readSByte();
|
||||
t->currentSubFrame = in.readByte();
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < 1024; i++) {
|
||||
|
@ -179,8 +213,13 @@ Common::Error LoLEngine::loadGameState(int slot) {
|
|||
}
|
||||
|
||||
for (int i = 0; i < 29; i++) {
|
||||
if (!(_hasTempDataFlags & (1 << i)))
|
||||
if (!(_hasTempDataFlags & (1 << i))) {
|
||||
if (header.originalSave) {
|
||||
if (in.size() - in.pos() >= 2500)
|
||||
in.skip(2500);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (_lvlTempData[i]) {
|
||||
delete[] _lvlTempData[i]->wallsXorData;
|
||||
|
@ -196,21 +235,36 @@ Common::Error LoLEngine::loadGameState(int slot) {
|
|||
_lvlTempData[i]->monsters = new MonsterInPlay[30];
|
||||
_lvlTempData[i]->flyingObjects = new FlyingObject[8];
|
||||
LevelTempData *l = _lvlTempData[i];
|
||||
|
||||
uint32 next = in.pos() + 2500;
|
||||
|
||||
in.read(l->wallsXorData, 4096);
|
||||
in.read(l->flags, 1024);
|
||||
if (header.originalSave) {
|
||||
in.skip(4);
|
||||
in.read(origCmp, in.readUint16());
|
||||
_screen->decodeFrame4(origCmp, _tempBuffer5120, 5120);
|
||||
memcpy(l->wallsXorData, _tempBuffer5120, 4096);
|
||||
for (int ii = 0; ii < 1024; ii++)
|
||||
l->flags[ii] = _tempBuffer5120[4096 + ii];
|
||||
} else {
|
||||
in.read(l->wallsXorData, 4096);
|
||||
for (int ii = 0; ii < 1024; ii++)
|
||||
l->flags[ii] = in.readByte();
|
||||
}
|
||||
|
||||
if (header.originalSave)
|
||||
l->monsterDifficulty = in.readUint16();
|
||||
|
||||
for (int ii = 0; ii < 30; ii++) {
|
||||
MonsterInPlay *m = &l->monsters[ii];
|
||||
m->nextAssignedObject = in.readUint16BE();
|
||||
m->nextDrawObject = in.readUint16BE();
|
||||
m->nextAssignedObject = in.readUint16();
|
||||
m->nextDrawObject = in.readUint16();
|
||||
m->flyingHeight = in.readByte();
|
||||
m->block = in.readUint16BE();
|
||||
m->x = in.readUint16BE();
|
||||
m->y = in.readUint16BE();
|
||||
m->block = in.readUint16();
|
||||
m->x = in.readUint16();
|
||||
m->y = in.readUint16();
|
||||
m->shiftStep = in.readSByte();
|
||||
m->destX = in.readUint16BE();
|
||||
m->destY = in.readUint16BE();
|
||||
m->destX = in.readUint16();
|
||||
m->destY = in.readUint16();
|
||||
m->destDirection = in.readByte();
|
||||
m->hitOffsX = in.readSByte();
|
||||
m->hitOffsY = in.readSByte();
|
||||
|
@ -220,15 +274,19 @@ Common::Error LoLEngine::loadGameState(int slot) {
|
|||
m->id = in.readByte();
|
||||
m->direction = in.readByte();
|
||||
m->facing = in.readByte();
|
||||
m->flags = in.readUint16BE();
|
||||
m->damageReceived = in.readUint16BE();
|
||||
m->hitPoints = in.readSint16BE();
|
||||
m->flags = in.readUint16();
|
||||
m->damageReceived = in.readUint16();
|
||||
m->hitPoints = in.readSint16();
|
||||
m->speedTick = in.readByte();
|
||||
m->type = in.readByte();
|
||||
|
||||
if (header.originalSave)
|
||||
in.skip(4);
|
||||
|
||||
m->numDistAttacks = in.readByte();
|
||||
m->curDistWeapon = in.readByte();
|
||||
m->distAttackTick = in.readSByte();
|
||||
m->assignedItems = in.readUint16BE();
|
||||
m->assignedItems = in.readUint16();
|
||||
m->properties = &_monsterProperties[m->type];
|
||||
in.read(m->equipmentShapes, 4);
|
||||
}
|
||||
|
@ -237,10 +295,10 @@ Common::Error LoLEngine::loadGameState(int slot) {
|
|||
FlyingObject *m = &l->flyingObjects[ii];
|
||||
m->enable = in.readByte();
|
||||
m->objectType = in.readByte();
|
||||
m->attackerId = in.readUint16BE();
|
||||
m->item = in.readSint16BE();
|
||||
m->x = in.readUint16BE();
|
||||
m->y = in.readUint16BE();
|
||||
m->attackerId = in.readUint16();
|
||||
m->item = in.readSint16();
|
||||
m->x = in.readUint16();
|
||||
m->y = in.readUint16();
|
||||
m->flyingHeight = in.readByte();
|
||||
m->direction = in.readByte();
|
||||
m->distance = in.readByte();
|
||||
|
@ -249,9 +307,15 @@ Common::Error LoLEngine::loadGameState(int slot) {
|
|||
m->flags = in.readByte();
|
||||
m->wallFlags = in.readByte();
|
||||
}
|
||||
l->monsterDifficulty = in.readByte();
|
||||
|
||||
if (header.originalSave)
|
||||
in.seek(next, SEEK_SET);
|
||||
else
|
||||
l->monsterDifficulty = in.readByte();
|
||||
}
|
||||
|
||||
delete[] origCmp;
|
||||
|
||||
calcCharPortraitXpos();
|
||||
memset(_moneyColumnHeight, 0, sizeof(_moneyColumnHeight));
|
||||
int t = _credits;
|
||||
|
@ -365,6 +429,7 @@ Common::Error LoLEngine::saveGameStateIntern(int slot, const char *saveName, con
|
|||
out->writeSByte(t->level);
|
||||
out->writeUint16BE(t->itemPropertyIndex);
|
||||
out->writeUint16BE(t->shpCurFrame_flg);
|
||||
|
||||
out->writeByte(t->destDirection);
|
||||
out->writeSByte(t->hitOffsX);
|
||||
out->writeSByte(t->hitOffsY);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue