aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohannes Schickel2009-08-13 15:55:12 +0000
committerJohannes Schickel2009-08-13 15:55:12 +0000
commit4afa6d18a4d08dcf903bb9a2973ed0b1123e1c6c (patch)
tree91575290d6fdcb0ff19c8459271b93ff61ae799e
parente9767a80ce6d41d762cc029a40b98a9850fe02bd (diff)
downloadscummvm-rg350-4afa6d18a4d08dcf903bb9a2973ed0b1123e1c6c.tar.gz
scummvm-rg350-4afa6d18a4d08dcf903bb9a2973ed0b1123e1c6c.tar.bz2
scummvm-rg350-4afa6d18a4d08dcf903bb9a2973ed0b1123e1c6c.zip
Implemented support for the "Lore of the Lands" special of Lands of Lore CD.
svn-id: r43349
-rw-r--r--dists/engine-data/kyra.datbin257348 -> 257836 bytes
-rw-r--r--engines/kyra/lol.h34
-rw-r--r--engines/kyra/resource.h22
-rw-r--r--engines/kyra/sequences_lol.cpp274
-rw-r--r--engines/kyra/staticres.cpp44
-rw-r--r--tools/create_kyradat/create_kyradat.cpp4
-rw-r--r--tools/create_kyradat/create_kyradat.h2
-rw-r--r--tools/create_kyradat/lol_cd.h8
-rw-r--r--tools/create_kyradat/misc.h6
9 files changed, 354 insertions, 40 deletions
diff --git a/dists/engine-data/kyra.dat b/dists/engine-data/kyra.dat
index da57e2ce2a..eb3ff24c2a 100644
--- a/dists/engine-data/kyra.dat
+++ b/dists/engine-data/kyra.dat
Binary files differ
diff --git a/engines/kyra/lol.h b/engines/kyra/lol.h
index 06950779b1..1c89a7a1eb 100644
--- a/engines/kyra/lol.h
+++ b/engines/kyra/lol.h
@@ -301,6 +301,7 @@ friend class GUI_LoL;
friend class TextDisplayer_LoL;
friend class TIMInterpreter_LoL;
friend class Debugger_LoL;
+friend class HistoryPlayer;
public:
LoLEngine(OSystem *system, const GameFlags &flags);
~LoLEngine();
@@ -1124,14 +1125,14 @@ private:
uint16 _dmScaleH;
int _lastMouseRegion;
- int _seqWindowX1, _seqWindowY1, _seqWindowX2, _seqWindowY2, _seqTrigger;
- int _spsWindowX, _spsWindowY, _spsWindowW, _spsWindowH;
+ int _seqWindowX1, _seqWindowY1, _seqWindowX2, _seqWindowY2, _seqTrigger;
+ int _spsWindowX, _spsWindowY, _spsWindowW, _spsWindowH;
uint8 *_tempBuffer5120;
- const char *const * _levelDatList;
+ const char * const *_levelDatList;
int _levelDatListSize;
- const char *const * _levelShpList;
+ const char * const *_levelShpList;
int _levelShpListSize;
const int8 *_dscUnk1;
@@ -1476,6 +1477,31 @@ private:
LevelTempData *_lvlTempData[29];
};
+class HistoryPlayer {
+public:
+ HistoryPlayer(LoLEngine *vm);
+ ~HistoryPlayer();
+
+ void play();
+private:
+ OSystem *_system;
+ LoLEngine *_vm;
+ Screen *_screen;
+
+ int _x, _y, _width, _height;
+ int _frame;
+ Movie *_wsa;
+
+ void loadWsa(const char *filename);
+ void playWsa(bool direction);
+ void restoreWsaBkgd();
+
+ Movie *_fireWsa;
+ int _fireFrame;
+ uint32 _nextFireTime;
+ void updateFire();
+};
+
} // end of namespace Kyra
#endif
diff --git a/engines/kyra/resource.h b/engines/kyra/resource.h
index 07fb2e05b7..3dc6c5ff2f 100644
--- a/engines/kyra/resource.h
+++ b/engines/kyra/resource.h
@@ -282,16 +282,18 @@ enum kKyraResources {
kLolButtonList7,
kLolButtonList8,
- lolLegendData,
- lolMapCursorOvl,
- lolMapStringId,
- //lolMapPal,
-
- lolSpellbookAnim,
- lolSpellbookCoords,
- lolHealShapeFrames,
- lolLightningDefs,
- lolFireballCoords,
+ kLolLegendData,
+ kLolMapCursorOvl,
+ kLolMapStringId,
+ //kLolMapPal,
+
+ kLolSpellbookAnim,
+ kLolSpellbookCoords,
+ kLolHealShapeFrames,
+ kLolLightningDefs,
+ kLolFireballCoords,
+
+ kLolHistory,
#endif // ENABLE_LOL
kMaxResIDs
diff --git a/engines/kyra/sequences_lol.cpp b/engines/kyra/sequences_lol.cpp
index 5826b2b09e..ae23d130ef 100644
--- a/engines/kyra/sequences_lol.cpp
+++ b/engines/kyra/sequences_lol.cpp
@@ -89,8 +89,10 @@ int LoLEngine::processPrologue() {
showIntro();
break;
- case 2: // "Lore of the Lands" (only CD version)
- break;
+ case 2: { // "Lore of the Lands" (only CD version)
+ HistoryPlayer history(this);
+ history.play();
+ } break;
case 3: // Load game
if (_gui->runMenu(_gui->_loadMenu))
@@ -121,7 +123,8 @@ void LoLEngine::setupPrologueData(bool load) {
static const char * const fileListCD[] = {
"GENERAL.PAK", "INTROVOC.PAK", "STARTUP.PAK", "INTRO1.PAK",
"INTRO2.PAK", "INTRO3.PAK", "INTRO4.PAK", "INTRO5.PAK",
- "INTRO6.PAK", "INTRO7.PAK", "INTRO8.PAK", "INTRO9.PAK", 0
+ "INTRO6.PAK", "INTRO7.PAK", "INTRO8.PAK", "INTRO9.PAK",
+ "HISTORY.PAK", 0
};
static const char * const fileListFloppyExtracted[] = {
@@ -683,6 +686,271 @@ void LoLEngine::showStarcraftLogo() {
delete ci;
}
+// history player
+
+HistoryPlayer::HistoryPlayer(LoLEngine *vm) : _system(vm->_system), _vm(vm), _screen(vm->screen()) {
+ _x = _y = _width = _height = 0;
+ _frame = _fireFrame = 0;
+ _nextFireTime = 0;
+
+ _wsa = new WSAMovie_v2(vm);
+ assert(_wsa);
+ _fireWsa = new WSAMovie_v2(vm);
+ assert(_fireWsa);
+}
+
+HistoryPlayer::~HistoryPlayer() {
+ delete _wsa;
+ delete _fireWsa;
+}
+
+void HistoryPlayer::play() {
+ int dataSize = 0;
+ const char *data = (const char *)_vm->staticres()->loadRawData(kLolHistory, dataSize);
+
+ if (!data)
+ error("Could not load history data");
+
+ _screen->loadFont(Screen::FID_9_FNT, "FONT9P.FNT");
+
+ Palette pal(256);
+ pal.fill(0, 256, 0);
+ _screen->fadePalette(pal, 0x1E);
+
+ _screen->loadBitmap("BACKGND.CPS", 8, 8, &pal);
+ _screen->copyRegion(0, 0, 0, 0, 320, 200, 8, 0, Screen::CR_NO_P_CHECK);
+ _screen->copyRegion(0, 0, 0, 0, 320, 200, 8, 2, Screen::CR_NO_P_CHECK);
+ _screen->updateScreen();
+
+ _screen->fadePalette(pal, 0x82);
+
+ _screen->copyRegion(_x, _y, _x, _y, _width, _height, 2, 0);
+ _screen->updateScreen();
+
+ pal.fill(0, 256, 0);
+ _screen->setFont(Screen::FID_9_FNT);
+
+ char tempWsaFilename[16];
+ char voiceFilename[13];
+ // the 'a' *has* to be lowercase
+ strncpy(voiceFilename, "PS_1a", sizeof(voiceFilename));
+
+ int part = 0;
+ Sound *sound = _vm->sound();
+
+ Common::Functor0Mem<void, HistoryPlayer> palFade(this, &HistoryPlayer::updateFire);
+
+ for (; voiceFilename[3] <= '9' && !_vm->shouldQuit() && !_vm->skipFlag(); ++voiceFilename[3], voiceFilename[4] = 'a') {
+ while (!_vm->shouldQuit() && !_vm->skipFlag()) {
+ if (!sound->voiceFileIsPresent(voiceFilename))
+ break;
+
+ if (data[part * 15] == voiceFilename[3] && data[part * 15 + 1] == voiceFilename[4]) {
+ switch (part) {
+ case 0:
+ loadWsa(&data[part * 15 + 2]);
+ playWsa(true);
+ sound->voicePlay(voiceFilename);
+ break;
+
+ case 1: case 2: case 8:
+ case 16: case 25:
+ sound->voicePlay(voiceFilename);
+ playWsa(true);
+ break;
+
+ case 3: case 7: case 10:
+ case 17: case 23: case 26:
+ sound->voicePlay(voiceFilename);
+ playWsa(true);
+ restoreWsaBkgd();
+ loadWsa(&data[part * 15 + 2]);
+ playWsa(true);
+ break;
+
+ case 6:
+ sound->voicePlay(voiceFilename);
+ playWsa(false);
+ restoreWsaBkgd();
+ loadWsa(&data[part * 15 + 2]);
+ playWsa(true);
+ _vm->delayWithTicks(30);
+ playWsa(true);
+ break;
+
+ case 9:
+ sound->voicePlay(voiceFilename);
+ loadWsa(&data[part * 15 + 2]);
+ playWsa(true);
+ break;
+
+ case 22:
+ playWsa(false);
+ restoreWsaBkgd();
+ loadWsa(&data[part * 15 + 2]);
+ _vm->delayWithTicks(30);
+ sound->voicePlay(voiceFilename);
+ playWsa(true);
+
+ strcpy(tempWsaFilename, &data[part * 15]);
+
+ for (int i = 1; i < 4 && !_vm->shouldQuit(); ++i) {
+ uint32 nextTime = _system->getMillis() + 30 * _vm->tickLength();
+ tempWsaFilename[8] = 'a' + i;
+
+ loadWsa(&tempWsaFilename[2]);
+ _vm->delayUntil(nextTime);
+
+ playWsa(true);
+ }
+
+ tempWsaFilename[8] = 'e';
+ loadWsa(&tempWsaFilename[2]);
+ break;
+
+ case 29:
+ sound->voicePlay(voiceFilename);
+ playWsa(false);
+ restoreWsaBkgd();
+ loadWsa(&data[part * 15 + 2]);
+
+ _fireWsa->open("FIRE.WSA", 0, 0);
+ playWsa(true);
+ _fireFrame = 0;
+
+ for (int i = 0; i < 12 && !_vm->shouldQuit(); ++i, ++_fireFrame) {
+ uint32 nextTime = _system->getMillis() + 3 * _vm->tickLength();
+
+ if (_fireFrame > 4)
+ _fireFrame = 0;
+
+ _fireWsa->displayFrame(_fireFrame, 0, 75, 51, 0, 0, 0);
+ _screen->updateScreen();
+ _vm->delayUntil(nextTime);
+ }
+
+ _screen->loadPalette("DRACPAL.PAL", pal);
+ _screen->fadePalette(pal, 0x78, &palFade);
+
+ while (sound->voiceIsPlaying() && !_vm->shouldQuit()) {
+ uint32 nextTime = _system->getMillis() + 3 * _vm->tickLength();
+
+ ++_fireFrame;
+ if (_fireFrame > 4)
+ _fireFrame = 0;
+
+ _fireWsa->displayFrame(_fireFrame, 0, 75, 51, 0, 0, 0);
+ _screen->updateScreen();
+ _vm->delayUntil(nextTime);
+ }
+
+ _fireFrame = 0;
+ for (int i = 0; i < 10; ++i, ++_fireFrame) {
+ uint32 nextTime = _system->getMillis() + 3 * _vm->tickLength();
+
+ if (_fireFrame > 4)
+ _fireFrame = 0;
+
+ _fireWsa->displayFrame(_fireFrame, 0, 75, 51, 0, 0, 0);
+ _screen->updateScreen();
+ _vm->delayUntil(nextTime);
+ }
+
+ break;
+
+ default:
+ sound->voicePlay(voiceFilename);
+ playWsa(false);
+ restoreWsaBkgd();
+ loadWsa(&data[part * 15 + 2]);
+ playWsa(true);
+ break;
+ }
+
+ ++part;
+ } else {
+ sound->voicePlay(voiceFilename);
+ }
+
+ while (sound->voiceIsPlaying() && !_vm->shouldQuit() && !_vm->skipFlag())
+ _vm->delay(10);
+
+ if (_vm->skipFlag()) {
+ sound->voiceStop();
+ _vm->resetSkipFlag();
+ }
+
+ ++voiceFilename[4];
+ }
+
+ if (_vm->skipFlag())
+ _vm->resetSkipFlag();
+ }
+
+ if (_vm->skipFlag())
+ _vm->resetSkipFlag();
+
+ pal.fill(0, 256, 63);
+ if (_fireWsa->opened())
+ _screen->fadePalette(pal, 0x3C, &palFade);
+ else
+ _screen->fadePalette(pal, 0x3C);
+
+ _screen->clearPage(0);
+ pal.fill(0, 256, 0);
+ _screen->fadePalette(pal, 0x3C);
+}
+
+void HistoryPlayer::loadWsa(const char *filename) {
+ if (_wsa->opened())
+ _wsa->close();
+
+ Palette pal(256);
+ if (!_wsa->open(filename, 3, &pal))
+ error("Could not load WSA file: '%s'", filename);
+ _screen->setScreenPalette(pal);
+
+ _x = _wsa->xAdd();
+ _y = _wsa->yAdd();
+ _width = _wsa->width();
+ _height = _wsa->height();
+ _frame = 1;
+}
+
+void HistoryPlayer::playWsa(bool direction) {
+ const int tickLength = _vm->tickLength();
+
+ for (int i = 0; i < 15 && !_vm->shouldQuit(); ++i) {
+ uint32 nextTime = _system->getMillis() + 3 * tickLength;
+
+ _wsa->displayFrame(_frame, 2, 0, 0, 0, 0, 0);
+ _screen->copyRegion(_x, _y, _x, _y, _width, _height, 2, 0);
+ _screen->updateScreen();
+ _vm->delayUntil(nextTime);
+
+ if (direction)
+ ++_frame;
+ else
+ --_frame;
+ }
+}
+
+void HistoryPlayer::restoreWsaBkgd() {
+ _screen->copyRegion(_x, _y, _x, _y, _width, _height, 8, 0);
+ _screen->copyRegion(_x, _y, _x, _y, _width, _height, 8, 2);
+ _screen->updateScreen();
+}
+
+void HistoryPlayer::updateFire() {
+ if (_system->getMillis() > _nextFireTime) {
+ _fireWsa->displayFrame(_fireFrame, 0, 75, 51, 0, 0, 0);
+ _fireFrame = (_fireFrame + 1) % 5;
+ _nextFireTime = _system->getMillis() + 4 * _vm->tickLength();
+ }
+
+ _screen->updateScreen();
+}
+
// outro
void LoLEngine::setupEpilogueData(bool load) {
diff --git a/engines/kyra/staticres.cpp b/engines/kyra/staticres.cpp
index 866a39b921..51288f31df 100644
--- a/engines/kyra/staticres.cpp
+++ b/engines/kyra/staticres.cpp
@@ -44,7 +44,7 @@
namespace Kyra {
-#define RESFILE_VERSION 49
+#define RESFILE_VERSION 50
namespace {
bool checkKyraDat(Common::SeekableReadStream *file) {
@@ -444,16 +444,18 @@ bool StaticResource::init() {
{ kLolButtonList7, kLolRawDataBe16, "BUTTON7.LST" },
{ kLolButtonList8, kLolRawDataBe16, "BUTTON84.LST" },
- { lolLegendData, kRawData, "MAPLGND.DEF" },
- { lolMapCursorOvl, kRawData, "MAPCURSOR.PAL" },
- { lolMapStringId, kLolRawDataBe16, "MAPSTRID.LST" },
- //{ lolMapPal, kRawData, "MAP.PAL" },
+ { kLolLegendData, kRawData, "MAPLGND.DEF" },
+ { kLolMapCursorOvl, kRawData, "MAPCURSOR.PAL" },
+ { kLolMapStringId, kLolRawDataBe16, "MAPSTRID.LST" },
+ //{ kLolMapPal, kRawData, "MAP.PAL" },
- { lolSpellbookAnim, kRawData, "MBOOKA.DEF" },
- { lolSpellbookCoords, kRawData, "MBOOKC.DEF" },
- { lolHealShapeFrames, kRawData, "MHEAL.SHP" },
- { lolLightningDefs, kRawData, "MLGHTNG.DEF" },
- { lolFireballCoords, kLolRawDataBe16, "MFIREBLL.DEF" },
+ { kLolSpellbookAnim, kRawData, "MBOOKA.DEF" },
+ { kLolSpellbookCoords, kRawData, "MBOOKC.DEF" },
+ { kLolHealShapeFrames, kRawData, "MHEAL.SHP" },
+ { kLolLightningDefs, kRawData, "MLGHTNG.DEF" },
+ { kLolFireballCoords, kLolRawDataBe16, "MFIREBLL.DEF" },
+
+ { kLolHistory, kRawData, "HISTORY.FLS" },
{ 0, 0, 0 }
};
@@ -1875,10 +1877,10 @@ void LoLEngine::initStaticResource() {
_buttonList7 = (const int16 *)_staticres->loadRawDataBe16(kLolButtonList7, _buttonList7Size);
_buttonList8 = (const int16 *)_staticres->loadRawDataBe16(kLolButtonList8, _buttonList8Size);
- _autoMapStrings = _staticres->loadRawDataBe16(lolMapStringId, _autoMapStringsSize);
+ _autoMapStrings = _staticres->loadRawDataBe16(kLolMapStringId, _autoMapStringsSize);
int tmpSize = 0;
- const uint8 *tmp = _staticres->loadRawData(lolLegendData, tmpSize);
+ const uint8 *tmp = _staticres->loadRawData(kLolLegendData, tmpSize);
tmpSize /= 5;
if (tmp) {
_defaultLegendData = new MapLegendData[tmpSize];
@@ -1889,19 +1891,19 @@ void LoLEngine::initStaticResource() {
_defaultLegendData[i].stringId = READ_LE_UINT16(tmp);
tmp += 2;
}
- _staticres->unloadId(lolLegendData);
+ _staticres->unloadId(kLolLegendData);
}
- tmp = _staticres->loadRawData(lolMapCursorOvl, tmpSize);
+ tmp = _staticres->loadRawData(kLolMapCursorOvl, tmpSize);
_mapCursorOverlay = new uint8[tmpSize];
memcpy(_mapCursorOverlay, tmp, tmpSize);
- _staticres->unloadId(lolMapCursorOvl);
+ _staticres->unloadId(kLolMapCursorOvl);
- _updateSpellBookCoords = _staticres->loadRawData(lolSpellbookCoords, _updateSpellBookCoordsSize);
- _updateSpellBookAnimData = _staticres->loadRawData(lolSpellbookAnim, _updateSpellBookAnimDataSize);
- _healShapeFrames = _staticres->loadRawData(lolHealShapeFrames, _healShapeFramesSize);
+ _updateSpellBookCoords = _staticres->loadRawData(kLolSpellbookCoords, _updateSpellBookCoordsSize);
+ _updateSpellBookAnimData = _staticres->loadRawData(kLolSpellbookAnim, _updateSpellBookAnimDataSize);
+ _healShapeFrames = _staticres->loadRawData(kLolHealShapeFrames, _healShapeFramesSize);
- tmp = _staticres->loadRawData(lolLightningDefs, tmpSize);
+ tmp = _staticres->loadRawData(kLolLightningDefs, tmpSize);
if (tmp) {
_lightningProps = new LightningProperty[5];
for (int i = 0; i < 5; i++) {
@@ -1909,10 +1911,10 @@ void LoLEngine::initStaticResource() {
_lightningProps[i].frameDiv = tmp[(i << 2) + 1];
_lightningProps[i].sfxId = READ_LE_UINT16(&tmp[(i << 2) + 2]);
}
- _staticres->unloadId(lolLightningDefs);
+ _staticres->unloadId(kLolLightningDefs);
}
- _fireBallCoords = (const int16*)_staticres->loadRawDataBe16(lolFireballCoords, _fireBallCoordsSize);
+ _fireBallCoords = (const int16*)_staticres->loadRawDataBe16(kLolFireballCoords, _fireBallCoordsSize);
_buttonCallbacks.clear();
_buttonCallbacks.reserve(95);
diff --git a/tools/create_kyradat/create_kyradat.cpp b/tools/create_kyradat/create_kyradat.cpp
index 780282bab2..011550d1cd 100644
--- a/tools/create_kyradat/create_kyradat.cpp
+++ b/tools/create_kyradat/create_kyradat.cpp
@@ -31,7 +31,7 @@
#include "md5.h"
enum {
- kKyraDatVersion = 49,
+ kKyraDatVersion = 50,
kIndexSize = 12
};
@@ -347,6 +347,8 @@ const ExtractFilename extractFilenames[] = {
{ lolLightningDefs, kTypeRawData, "MLGHTNG.DEF" },
{ lolFireballCoords, lolTypeRaw16, "MFIREBLL.DEF" },
+ { lolHistory, kTypeRawData, "HISTORY.FLS" },
+
{ -1, 0, 0 }
};
diff --git a/tools/create_kyradat/create_kyradat.h b/tools/create_kyradat/create_kyradat.h
index 13f6966f83..e7aa292265 100644
--- a/tools/create_kyradat/create_kyradat.h
+++ b/tools/create_kyradat/create_kyradat.h
@@ -257,6 +257,8 @@ enum kExtractID {
lolLightningDefs,
lolFireballCoords,
+ lolHistory,
+
kMaxResIDs
};
diff --git a/tools/create_kyradat/lol_cd.h b/tools/create_kyradat/lol_cd.h
index fa36d1b91d..dfdd5e1bc3 100644
--- a/tools/create_kyradat/lol_cd.h
+++ b/tools/create_kyradat/lol_cd.h
@@ -1,3 +1,8 @@
+const ExtractEntry lolCDFile1E[] = {
+ { lolHistory, 0x1FAA0, 0x1FC71 },
+ { -1, 0, 0 }
+};
+
const ExtractEntry lolCDFile2[] = {
{ lolCharacterDefs, 0x00029D60, 0x0002A1F2 },
{ lolIngameSfxFiles, 0x0002A330, 0x0002AC22 },
@@ -84,6 +89,7 @@ const ExtractEntry lolCDFile2[] = {
};
const Game lolGames[] = {
- { kLol, EN_ANY, kLolCD, "263998ec600afca1cc7b935c473df670", lolCDFile2},
+ { kLol, EN_ANY, kLolCD, "9d1778314de80598c0b0d032e2a1a1cf", lolCDFile1E },
+ { kLol, EN_ANY, kLolCD, "263998ec600afca1cc7b935c473df670", lolCDFile2 },
GAME_DUMMY_ENTRY
};
diff --git a/tools/create_kyradat/misc.h b/tools/create_kyradat/misc.h
index 1dac208ade..1117ad1d05 100644
--- a/tools/create_kyradat/misc.h
+++ b/tools/create_kyradat/misc.h
@@ -481,6 +481,11 @@ const int kyra3Need[] = {
-1
};
+const int lolCDFile1ENeed[] = {
+ lolHistory,
+ -1
+};
+
const int lolCDFile2Need[] = {
lolCharacterDefs,
lolIngameSfxFiles,
@@ -604,6 +609,7 @@ const GameNeed gameNeedTable[] = {
{ kKyra3, -1, kyra3Need },
+ { kLol, kLolCD, lolCDFile1ENeed },
{ kLol, kLolCD, lolCDFile2Need },
{ -1, -1, 0 }