Exemple #1
0
void KyraRpgEngine::releaseTempData() {
	for (int i = 0; i < 29; i++) {
		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] = 0;
		}
	}
}
Exemple #2
0
void KyraRpgEngine::generateTempData() {
	int l = _currentLevel - 1;
	if (_lvlTempData[l]) {
		delete[] _lvlTempData[l]->wallsXorData;
		delete[] _lvlTempData[l]->flags;
		releaseMonsterTempData(_lvlTempData[l]);
		releaseFlyingObjectTempData(_lvlTempData[l]);
		releaseWallOfForceTempData(_lvlTempData[l]);
		delete _lvlTempData[l];
	}

	_lvlTempData[l] = new LevelTempData;

	_lvlTempData[l]->wallsXorData = new uint8[4096];
	_lvlTempData[l]->flags = new uint16[1024];

	const uint8 *p = getBlockFileData(_currentLevel);
	uint16 len = READ_LE_UINT16(p + 4);
	p += 6;

	memset(_lvlTempData[l]->wallsXorData, 0, 4096);
	memset(_lvlTempData[l]->flags, 0, 1024 * sizeof(uint16));
	uint8 *d = _lvlTempData[l]->wallsXorData;
	uint16 *df = _lvlTempData[l]->flags;

	for (int i = 0; i < 1024; i++) {
		for (int ii = 0; ii < 4; ii++)
			*d++ = p[i * len + ii] ^ _levelBlockProperties[i].walls[ii];
		*df++ = _levelBlockProperties[i].flags;
	}

	_lvlTempData[l]->monsters = generateMonsterTempData(_lvlTempData[l]);
	_lvlTempData[l]->flyingObjects = generateFlyingObjectTempData(_lvlTempData[l]);
	_lvlTempData[l]->wallsOfForce = generateWallOfForceTempData(_lvlTempData[l]);

	_hasTempDataFlags |= (1 << l);
}
Exemple #3
0
Common::Error EoBCoreEngine::loadGameState(int slot) {
	// Special slot id -1 for EOB1 party transfer
	const char *fileName = (slot == -1) ? _savegameFilename.c_str() : getSavegameFilename(slot);

	SaveHeader header;
	Common::InSaveFile *saveFile = openSaveForReading(fileName, header, (slot != -1));
	if (!saveFile)
		return Common::Error(Common::kReadingFailed);

	Common::SeekableSubReadStreamEndian in(saveFile, saveFile->pos(), saveFile->size(), !header.originalSave, DisposeAfterUse::YES);
	_loading = true;

	if (slot != -1)
		_screen->fadeToBlack(10);

	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 = in.readSint16BE();
		c->hitPointsMax = in.readSint16BE();
		c->armorClass = in.readSByte();
		c->disabledSlots = in.readByte();
		c->raceSex = in.readByte();
		c->cClass = in.readByte();
		c->alignment = in.readByte();
		c->portrait = in.readSByte();
		if (slot == -1 && c->portrait < 0)
			c->portrait = -c->portrait + 43;
		c->food = in.readByte();
		in.read(c->level, 3);
		for (int ii = 0; ii < 3; ii++)
			c->experience[ii] = in.readUint32BE();
		delete[] c->faceShape;
		c->faceShape = 0;
		in.read(c->mageSpells, 80);
		in.read(c->clericSpells, 80);
		c->mageSpellsAvailableFlags = in.readUint32BE();
		for (int ii = 0; ii < 27; ii++)
			c->inventory[ii] = in.readSint16BE();
		uint32 ct = _system->getMillis();
		for (int ii = 0; ii < 10; ii++) {
			c->timers[ii] = in.readUint32BE();
			if (c->timers[ii])
				c->timers[ii] += ct;
		}
		in.read(c->events, 10);
		in.read(c->effectsRemainder, 4);
		c->effectFlags = in.readUint32BE();
		c->damageTaken = in.readByte();
		in.read(c->slotStatus, 5);
	}

	setupCharacterTimers();

	_screen->loadShapeSetBitmap("CHARGENA", 3, 3);
	for (int i = 0; i < 6; i++) {
		EoBCharacter *c = &_characters[i];
		if (!c->flags || c->portrait < 0)
			continue;
		c->faceShape = _screen->encodeShape((c->portrait % 10) << 2, (c->portrait / 10) << 5, 4, 32, true);
	}

	_screen->loadShapeSetBitmap(_flags.gameID == GI_EOB2 ? "OUTPORTS" : "OUTTAKE", 3, 3);
	for (int i = 0; i < 6; i++) {
		EoBCharacter *c = &_characters[i];
		if (!c->flags || c->portrait >= 0)
			continue;
		c->faceShape = _screen->encodeShape((-(c->portrait + 1)) << 2, _flags.gameID == GI_EOB2 ? 0 : 160, 4, 32, true);
	}
	_screen->_curPage = 0;

	if (slot == -1) {
		// Skip all settings which aren't necessary for party transfer.
		// Jump directly to the items list.
		in.skip(108);
	} else {
		_currentLevel = in.readByte();
		_currentSub = in.readSByte();
		_currentBlock = in.readUint16BE();
		_currentDirection = in.readUint16BE();
		_itemInHand = in.readSint16BE();
		_hasTempDataFlags = in.readUint32BE();
		_partyEffectFlags = in.readUint32BE();

		_updateFlags = in.readUint16BE();
		_compassDirection = in.readUint16BE();
		_currentControlMode = in.readUint16BE();
		_updateCharNum = in.readUint16BE();
		_openBookSpellLevel = in.readSByte();
		_openBookSpellSelectedItem  = in.readSByte();
		_openBookSpellListOffset = in.readSByte();
		_openBookChar = in.readByte();
		_openBookType = in.readByte();
		_openBookCharBackup = in.readByte();
		_openBookTypeBackup = in.readByte();
		_activeSpellCharId = in.readByte();
		_activeSpellCharacterPos = in.readByte();
		_activeSpell = in.readByte();
		_returnAfterSpellCallback = in.readByte() ? true : false;

		_inf->loadState(in);
	}

	for (int i = 0; i < 600; 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.readSint16BE();
		t->next = in.readSint16BE();
		t->prev = in.readSint16BE();
		t->level = in.readByte();
		t->value = in.readSByte();
	}

	// No more data needed for party transfer
	if (slot == -1) {
		_loading = false;
		return Common::kNoError;
	}

	for (int i = 51; i < 65; i++) {
		EoBItemType *t = &_itemTypes[i];
		t->invFlags = in.readUint16BE();
		t->handFlags = in.readUint16BE();
		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.readUint16BE();
	}

	for (int i = 0; i < 18; i++) {
		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];
		EoBMonsterInPlay *lm = new EoBMonsterInPlay[30];
		l->monsters = lm;
		EoBFlyingObject *lf = new EoBFlyingObject[_numFlyingObjects];
		l->flyingObjects = lf;
		WallOfForce *lw = new WallOfForce[5];
		l->wallsOfForce = lw;

		in.read(l->wallsXorData, 4096);
		for (int ii = 0; ii < 1024; ii++)
			l->flags[ii] = in.readByte();

		for (int ii = 0; ii < 30; ii++) {
			EoBMonsterInPlay *m = &lm[ii];
			m->type = in.readByte();
			m->unit = in.readByte();
			m->block = in.readUint16BE();
			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.readSint16BE();
			m->hitPointsCur = in.readSint16BE();
			m->dest = in.readUint16BE();
			m->randItem = in.readUint16BE();
			m->fixedItem = in.readUint16BE();
			m->flags = in.readByte();
			m->idleAnimState = in.readByte();
			m->curRemoteWeapon = in.readByte();
			m->numRemoteAttacks = in.readByte();
			m->palette = in.readSByte();
			m->directionChanged = in.readByte();
			m->stepsTillRemoteAttack = in.readByte();
			m->sub = in.readByte();
		}

		for (int ii = 0; ii < _numFlyingObjects; ii++) {
			EoBFlyingObject *m = &lf[ii];
			m->enable = in.readByte();
			m->objectType = in.readByte();
			m->attackerId = in.readSint16BE();
			m->item = in.readSint16BE();
			m->curBlock = in.readUint16BE();
			m->u2 = in.readUint16BE();
			m->u1 = in.readByte();
			m->direction = in.readByte();
			m->distance = in.readByte();
			m->callBackIndex = in.readSByte();
			m->curPos = in.readByte();
			m->flags = in.readByte();
			m->unused = in.readByte();
		}

		for (int ii = 0; ii < 5; ii++) {
			WallOfForce *w = &lw[ii];
			w->block = in.readUint16BE();
			w->duration = in.readUint32BE();
		}
	}

	loadLevel(_currentLevel, _currentSub);
	_sceneUpdateRequired = true;
	_screen->setFont(Screen::FID_6_FNT);

	for (int i = 0; i < 6; i++) {
		for (int ii = 0; ii < 10; ii++) {
			if (_characters[i].events[ii] == -57)
				spellCallback_start_trueSeeing();
		}
	}

	_screen->setCurPage(0);
	gui_drawPlayField(false);

	if (_currentControlMode)
		_screen->copyRegion(176, 0, 0, 0, 144, 168, 0, 5, Screen::CR_NO_P_CHECK);

	_screen->setCurPage(0);
	gui_drawAllCharPortraitsWithStats();
	drawScene(1);

	if (_updateFlags) {
		_updateFlags = 0;
		useMagicBookOrSymbol(_openBookChar, _openBookType);
	}

	_screen->copyRegion(0, 120, 0, 0, 176, 24, 0, 12, Screen::CR_NO_P_CHECK);

	gui_toggleButtons();
	setHandItem(_itemInHand);

	while (!_screen->isMouseVisible())
		_screen->showMouse();

	_loading = false;
	_screen->fadeFromBlack(20);
	removeInputTop();

	return Common::kNoError;
}
Exemple #4
0
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 in.err() ? Common::String() : desc;
}