aboutsummaryrefslogtreecommitdiff
path: root/engines
diff options
context:
space:
mode:
Diffstat (limited to 'engines')
-rw-r--r--engines/agos/agos.h2
-rw-r--r--engines/agos/gfx.cpp129
-rw-r--r--engines/cine/cine.h2
-rw-r--r--engines/cine/gfx.cpp4
-rw-r--r--engines/cine/prc.cpp9
-rw-r--r--engines/cine/prc.h2
-rw-r--r--engines/cine/script_fw.cpp14
-rw-r--r--engines/cine/texte.cpp10
-rw-r--r--engines/cine/texte.h5
-rw-r--r--engines/cine/various.cpp55
-rw-r--r--engines/kyra/kyra_v1.cpp2
-rw-r--r--engines/kyra/sound_towns.cpp6
-rw-r--r--engines/kyra/staticres.cpp12
-rw-r--r--engines/lure/luredefs.h2
-rw-r--r--engines/lure/res_struct.cpp6
-rw-r--r--engines/parallaction/callables_ns.cpp1
-rw-r--r--engines/parallaction/dialogue.cpp389
-rw-r--r--engines/parallaction/exec_ns.cpp17
-rw-r--r--engines/parallaction/gfxbase.cpp3
-rw-r--r--engines/parallaction/graphics.cpp10
-rw-r--r--engines/parallaction/graphics.h2
-rw-r--r--engines/parallaction/input.cpp55
-rw-r--r--engines/parallaction/input.h11
-rw-r--r--engines/parallaction/parallaction.cpp42
-rw-r--r--engines/parallaction/parallaction.h14
-rw-r--r--engines/parallaction/parallaction_br.cpp12
-rw-r--r--engines/parallaction/parallaction_ns.cpp6
-rw-r--r--engines/parallaction/walk.cpp1
-rw-r--r--engines/queen/graphics.cpp11
-rw-r--r--engines/queen/graphics.h4
-rw-r--r--engines/queen/sound.cpp15
-rw-r--r--engines/queen/sound.h1
-rw-r--r--engines/scumm/detection.cpp2
-rw-r--r--engines/scumm/dialogs.cpp27
-rw-r--r--engines/scumm/dialogs.h2
-rw-r--r--engines/scumm/imuse_digi/dimuse_sndmgr.cpp6
-rw-r--r--engines/sword2/music.cpp21
-rw-r--r--engines/sword2/sound.h2
38 files changed, 583 insertions, 331 deletions
diff --git a/engines/agos/agos.h b/engines/agos/agos.h
index fe1d36f281..49b4478ec7 100644
--- a/engines/agos/agos.h
+++ b/engines/agos/agos.h
@@ -1076,6 +1076,8 @@ protected:
virtual void drawImage(VC10_state *state);
void drawBackGroundImage(VC10_state *state);
void drawVertImage(VC10_state *state);
+ void drawVertImageCompressed(VC10_state *state);
+ void drawVertImageUncompressed(VC10_state *state);
void setMoveRect(uint16 x, uint16 y, uint16 width, uint16 height);
diff --git a/engines/agos/gfx.cpp b/engines/agos/gfx.cpp
index 9d3dea3ee1..25a4b919f4 100644
--- a/engines/agos/gfx.cpp
+++ b/engines/agos/gfx.cpp
@@ -744,10 +744,6 @@ void AGOSEngine_Simon1::drawImage(VC10_state *state) {
}
void AGOSEngine::drawBackGroundImage(VC10_state *state) {
- const byte *src;
- byte *dst;
- uint h, i;
-
state->width = _screenWidth;
if (_window3Flag == 1) {
state->width = 0;
@@ -755,15 +751,19 @@ void AGOSEngine::drawBackGroundImage(VC10_state *state) {
state->y_skip = 0;
}
- src = state->srcPtr + (state->width * state->y_skip) + (state->x_skip * 8);
- dst = state->surf_addr;
+ const byte* src = state->srcPtr + (state->width * state->y_skip) + (state->x_skip * 8);
+ byte* dst = state->surf_addr;
state->draw_width *= 2;
- h = state->draw_height;
+ uint h = state->draw_height;
+ const uint w = state->draw_width;
+ const byte paletteMod = state->paletteMod;
do {
- for (i = 0; i != state->draw_width; i++)
- dst[i] = src[i] + state->paletteMod;
+ for (uint i = 0; i != w; i+=2) {
+ dst[i] = src[i] + paletteMod;
+ dst[i+1] = src[i+1] + paletteMod;
+ }
dst += state->surf_pitch;
src += state->width;
} while (--h);
@@ -771,63 +771,86 @@ void AGOSEngine::drawBackGroundImage(VC10_state *state) {
void AGOSEngine::drawVertImage(VC10_state *state) {
if (state->flags & kDFCompressed) {
- uint w, h;
- byte *src, *dst, *dstPtr;
+ drawVertImageCompressed(state);
+ } else {
+ drawVertImageUncompressed(state);
+ }
+}
- state->x_skip *= 4; /* reached */
+void AGOSEngine::drawVertImageUncompressed(VC10_state *state) {
+ assert ((state->flags & kDFCompressed) == 0) ;
- state->dl = state->width;
- state->dh = state->height;
+ const byte *src;
+ byte *dst;
+ uint count;
- vc10_skip_cols(state);
+ src = state->srcPtr + (state->width * state->y_skip) * 8;
+ dst = state->surf_addr;
+ state->x_skip *= 4;
- dstPtr = state->surf_addr;
- if (!(state->flags & kDFNonTrans) && (state->flags & 0x40)) { /* reached */
- dstPtr += vcReadVar(252);
- }
- w = 0;
- do {
+ do {
+ for (count = 0; count != state->draw_width; count++) {
byte color;
+ color = (src[count + state->x_skip] / 16) + state->paletteMod;
+ if ((state->flags & kDFNonTrans) || color)
+ dst[count * 2] = color | state->palette;
+ color = (src[count + state->x_skip] & 15) + state->paletteMod;
+ if ((state->flags & kDFNonTrans) || color)
+ dst[count * 2 + 1] = color | state->palette;
+ }
+ dst += state->surf_pitch;
+ src += state->width * 8;
+ } while (--state->draw_height);
+}
- src = vc10_depackColumn(state);
- dst = dstPtr;
+void AGOSEngine::drawVertImageCompressed(VC10_state *state) {
+ assert (state->flags & kDFCompressed) ;
+ uint w, h;
+
+ state->x_skip *= 4; /* reached */
- h = 0;
+ state->dl = state->width;
+ state->dh = state->height;
+
+ vc10_skip_cols(state);
+
+ byte *dstPtr = state->surf_addr;
+ if (!(state->flags & kDFNonTrans) && (state->flags & 0x40)) { /* reached */
+ dstPtr += vcReadVar(252);
+ }
+ w = 0;
+ do {
+ byte color;
+
+ const byte *src = vc10_depackColumn(state);
+ byte *dst = dstPtr;
+
+ h = 0;
+ if (state->flags & kDFNonTrans) {
+ do {
+ byte colors = *src;
+ color = (colors / 16);
+ dst[0] = color | state->palette;
+ color = (colors & 15);
+ dst[1] = color | state->palette;
+ dst += state->surf_pitch;
+ src++;
+ } while (++h != state->draw_height);
+ } else {
do {
- color = (*src / 16);
- if ((state->flags & kDFNonTrans) || color != 0)
+ byte colors = *src;
+ color = (colors / 16);
+ if (color != 0)
dst[0] = color | state->palette;
- color = (*src & 15);
- if ((state->flags & kDFNonTrans) || color != 0)
+ color = (colors & 15);
+ if (color != 0)
dst[1] = color | state->palette;
dst += state->surf_pitch;
src++;
} while (++h != state->draw_height);
- dstPtr += 2;
- } while (++w != state->draw_width);
- } else {
- const byte *src;
- byte *dst;
- uint count;
-
- src = state->srcPtr + (state->width * state->y_skip) * 8;
- dst = state->surf_addr;
- state->x_skip *= 4;
-
- do {
- for (count = 0; count != state->draw_width; count++) {
- byte color;
- color = (src[count + state->x_skip] / 16) + state->paletteMod;
- if ((state->flags & kDFNonTrans) || color)
- dst[count * 2] = color | state->palette;
- color = (src[count + state->x_skip] & 15) + state->paletteMod;
- if ((state->flags & kDFNonTrans) || color)
- dst[count * 2 + 1] = color | state->palette;
- }
- dst += state->surf_pitch;
- src += state->width * 8;
- } while (--state->draw_height);
- }
+ }
+ dstPtr += 2;
+ } while (++w != state->draw_width);
}
void AGOSEngine::drawImage(VC10_state *state) {
diff --git a/engines/cine/cine.h b/engines/cine/cine.h
index 710840c17e..06f2dfd982 100644
--- a/engines/cine/cine.h
+++ b/engines/cine/cine.h
@@ -94,6 +94,7 @@ public:
Common::StringList _volumeResourceFiles;
StringPtrHashMap _volumeEntriesMap;
+ TextHandler _textHandler;
private:
void initialize(void);
@@ -107,6 +108,7 @@ private:
extern CineEngine *g_cine;
#define BOOT_PRC_NAME "AUTO00.PRC"
+#define COPY_PROT_FAIL_PRC_NAME "L201.ANI"
enum {
VAR_MOUSE_X_MODE = 253,
diff --git a/engines/cine/gfx.cpp b/engines/cine/gfx.cpp
index 2b7f3b8890..1f868ccb75 100644
--- a/engines/cine/gfx.cpp
+++ b/engines/cine/gfx.cpp
@@ -337,7 +337,7 @@ int FWRenderer::drawChar(char character, int x, int y) {
x += 5;
} else if ((width = fontParamTable[(unsigned char)character].characterWidth)) {
idx = fontParamTable[(unsigned char)character].characterIdx;
- drawSpriteRaw(textTable[idx][0], textTable[idx][1], 16, 8, _backBuffer, x, y);
+ drawSpriteRaw(g_cine->_textHandler.textTable[idx][0], g_cine->_textHandler.textTable[idx][1], 16, 8, _backBuffer, x, y);
x += width + 1;
}
@@ -938,7 +938,7 @@ int OSRenderer::drawChar(char character, int x, int y) {
x += 5;
} else if ((width = fontParamTable[(unsigned char)character].characterWidth)) {
idx = fontParamTable[(unsigned char)character].characterIdx;
- drawSpriteRaw2(textTable[idx][0], 0, 16, 8, _backBuffer, x, y);
+ drawSpriteRaw2(g_cine->_textHandler.textTable[idx][0], 0, 16, 8, _backBuffer, x, y);
x += width + 1;
}
diff --git a/engines/cine/prc.cpp b/engines/cine/prc.cpp
index 42dcf1b491..657edf96af 100644
--- a/engines/cine/prc.cpp
+++ b/engines/cine/prc.cpp
@@ -41,8 +41,9 @@ ScriptList objectScripts;
/*! \todo Is script size of 0 valid?
* \todo Fix script dump code
+ * @return Was the loading successful?
*/
-void loadPrc(const char *pPrcName) {
+bool loadPrc(const char *pPrcName) {
byte i;
uint16 numScripts;
byte *scriptPtr, *dataPtr;
@@ -53,11 +54,11 @@ void loadPrc(const char *pPrcName) {
scriptTable.clear();
// This is copy protection. Used to hang the machine
- if (!scumm_stricmp(pPrcName, "L201.ANI")) {
+ if (!scumm_stricmp(pPrcName, COPY_PROT_FAIL_PRC_NAME)) {
Common::Event event;
event.type = Common::EVENT_RTL;
g_system->getEventManager()->pushEvent(event);
- return;
+ return false;
}
checkDataDisk(-1);
@@ -110,6 +111,8 @@ void loadPrc(const char *pPrcName) {
}
}
#endif
+
+ return true;
}
} // End of namespace Cine
diff --git a/engines/cine/prc.h b/engines/cine/prc.h
index f5129d28b1..05bb240372 100644
--- a/engines/cine/prc.h
+++ b/engines/cine/prc.h
@@ -31,7 +31,7 @@ namespace Cine {
extern ScriptList globalScripts;
extern ScriptList objectScripts;
-void loadPrc(const char *pPrcName);
+bool loadPrc(const char *pPrcName);
} // End of namespace Cine
diff --git a/engines/cine/script_fw.cpp b/engines/cine/script_fw.cpp
index 148e673095..54a4976000 100644
--- a/engines/cine/script_fw.cpp
+++ b/engines/cine/script_fw.cpp
@@ -1019,6 +1019,20 @@ int FWScript::o1_divVar() {
}
int FWScript::o1_compareVar() {
+ // WORKAROUND: A workaround for a script bug in script file CODE2.PRC
+ // in at least some of the Amiga and Atari ST versions of Future Wars.
+ // Fixes bug #2016647 (FW: crash with italian amiga version). A local
+ // variable 251 is compared against value 0 although it's quite apparent
+ // from the context in the script that instead global variable 251 should
+ // be compared against value 0. So looks like someone made a typo when
+ // making the scripts. Therefore we change that particular comparison
+ // from using the local variable 251 to using the global variable 251.
+ if (g_cine->getGameType() == Cine::GType_FW && scumm_stricmp(currentPrcName, "CODE2.PRC") == 0 &&
+ (g_cine->getPlatform() == Common::kPlatformAmiga || g_cine->getPlatform() == Common::kPlatformAtariST) &&
+ _script.getByte(_pos) == 251 && _script.getByte(_pos + 1) == 0 && _script.getWord(_pos + 2) == 0) {
+ return o1_compareGlobalVar();
+ }
+
byte varIdx = getNextByte();
byte varType = getNextByte();
diff --git a/engines/cine/texte.cpp b/engines/cine/texte.cpp
index 9b4b83f420..e4fd334926 100644
--- a/engines/cine/texte.cpp
+++ b/engines/cine/texte.cpp
@@ -31,8 +31,6 @@ namespace Cine {
byte *textDataPtr;
-byte textTable[256][2][16 * 8];
-
const char **failureMessages;
const CommandeType *defaultActionCommand;
const CommandeType *systemMenu;
@@ -77,14 +75,14 @@ void loadTextData(const char *pFileName, byte *pDestinationBuffer) {
loadRelatedPalette(pFileName);
for (i = 0; i < numCharacters; i++) {
- gfxConvertSpriteToRaw(textTable[i][0], tempBuffer, 16, 8);
- generateMask(textTable[i][0], textTable[i][1], 16 * 8, 0);
+ gfxConvertSpriteToRaw(g_cine->_textHandler.textTable[i][0], tempBuffer, 16, 8);
+ generateMask(g_cine->_textHandler.textTable[i][0], g_cine->_textHandler.textTable[i][1], 16 * 8, 0);
tempBuffer += dataSize;
}
} else {
for (i = 0; i < 90; i++) {
- gfxConvertSpriteToRaw(textTable[i][0], tempBuffer, 8, 8);
- generateMask(textTable[i][0], textTable[i][1], 8 * 8, 0);
+ gfxConvertSpriteToRaw(g_cine->_textHandler.textTable[i][0], tempBuffer, 8, 8);
+ generateMask(g_cine->_textHandler.textTable[i][0], g_cine->_textHandler.textTable[i][1], 8 * 8, 0);
tempBuffer += 0x40;
}
}
diff --git a/engines/cine/texte.h b/engines/cine/texte.h
index ae82832aea..f471c3c49e 100644
--- a/engines/cine/texte.h
+++ b/engines/cine/texte.h
@@ -34,7 +34,10 @@ namespace Cine {
typedef char CommandeType[20];
extern byte *textDataPtr;
-extern byte textTable[256][2][16 * 8];
+
+struct TextHandler {
+ byte textTable[256][2][16 * 8];
+};
extern const char **failureMessages;
extern const CommandeType *defaultActionCommand;
diff --git a/engines/cine/various.cpp b/engines/cine/various.cpp
index 46168b306c..b70201ce99 100644
--- a/engines/cine/various.cpp
+++ b/engines/cine/various.cpp
@@ -464,17 +464,26 @@ bool CineEngine::makeLoad(char *saveName) {
broken = brokenSave(*fHandle);
+ // At savefile position 0x0000:
currentDisk = fHandle->readUint16BE();
+ // At 0x0002:
fHandle->read(currentPartName, 13);
+ // At 0x000F:
fHandle->read(currentDatName, 13);
+ // At 0x001C:
saveVar2 = fHandle->readSint16BE();
+ // At 0x001E:
fHandle->read(currentPrcName, 13);
+ // At 0x002B:
fHandle->read(currentRelName, 13);
+ // At 0x0038:
fHandle->read(currentMsgName, 13);
+ // At 0x0045:
fHandle->read(bgName, 13);
+ // At 0x0052:
fHandle->read(currentCtName, 13);
checkDataDisk(currentDisk);
@@ -499,52 +508,84 @@ bool CineEngine::makeLoad(char *saveName) {
loadCtFW(currentCtName);
}
+ // At 0x005F:
fHandle->readUint16BE();
+ // At 0x0061:
fHandle->readUint16BE();
+ // At 0x0063:
for (i = 0; i < 255; i++) {
+ // At 0x0063 + i * 32 + 0:
objectTable[i].x = fHandle->readSint16BE();
+ // At 0x0063 + i * 32 + 2:
objectTable[i].y = fHandle->readSint16BE();
+ // At 0x0063 + i * 32 + 4:
objectTable[i].mask = fHandle->readUint16BE();
+ // At 0x0063 + i * 32 + 6:
objectTable[i].frame = fHandle->readSint16BE();
+ // At 0x0063 + i * 32 + 8:
objectTable[i].costume = fHandle->readSint16BE();
+ // At 0x0063 + i * 32 + 10:
fHandle->read(objectTable[i].name, 20);
+ // At 0x0063 + i * 32 + 30:
objectTable[i].part = fHandle->readUint16BE();
}
+ // At 0x2043 (i.e. 0x0063 + 255 * 32):
renderer->restorePalette(*fHandle);
+ // At 0x2083 (i.e. 0x2043 + 16 * 2 * 2):
globalVars.load(*fHandle, NUM_MAX_VAR - 1);
+ // At 0x2281 (i.e. 0x2083 + 255 * 2):
for (i = 0; i < 16; i++) {
+ // At 0x2281 + i * 2:
zoneData[i] = fHandle->readUint16BE();
}
+ // At 0x22A1 (i.e. 0x2281 + 16 * 2):
for (i = 0; i < 4; i++) {
+ // At 0x22A1 + i * 2:
commandVar3[i] = fHandle->readUint16BE();
}
+ // At 0x22A9 (i.e. 0x22A1 + 4 * 2):
fHandle->read(commandBuffer, 0x50);
renderer->setCommand(commandBuffer);
+ // At 0x22F9 (i.e. 0x22A9 + 0x50):
renderer->_cmdY = fHandle->readUint16BE();
+ // At 0x22FB:
bgVar0 = fHandle->readUint16BE();
+ // At 0x22FD:
allowPlayerInput = fHandle->readUint16BE();
+ // At 0x22FF:
playerCommand = fHandle->readSint16BE();
+ // At 0x2301:
commandVar1 = fHandle->readSint16BE();
+ // At 0x2303:
isDrawCommandEnabled = fHandle->readUint16BE();
+ // At 0x2305:
var5 = fHandle->readUint16BE();
+ // At 0x2307:
var4 = fHandle->readUint16BE();
+ // At 0x2309:
var3 = fHandle->readUint16BE();
+ // At 0x230B:
var2 = fHandle->readUint16BE();
+ // At 0x230D:
commandVar2 = fHandle->readSint16BE();
+ // At 0x230F:
renderer->_messageBg = fHandle->readUint16BE();
+ // At 0x2311:
fHandle->readUint16BE();
+ // At 0x2313:
fHandle->readUint16BE();
+ // At 0x2315:
loadResourcesFromSave(*fHandle, broken);
// TODO: handle screen params (really required ?)
@@ -1516,12 +1557,22 @@ void mainLoopSub6(void) {
void checkForPendingDataLoad(void) {
if (newPrcName[0] != 0) {
- loadPrc(newPrcName);
+ bool loadPrcOk = loadPrc(newPrcName);
strcpy(currentPrcName, newPrcName);
strcpy(newPrcName, "");
- addScriptToList0(1);
+ // Check that the loading of the script file was successful before
+ // trying to add script 1 from it to the global scripts list. This
+ // fixes a crash when failing copy protection in Amiga or Atari ST
+ // versions of Future Wars.
+ if (loadPrcOk) {
+ addScriptToList0(1);
+ } else if (scumm_stricmp(currentPrcName, COPY_PROT_FAIL_PRC_NAME)) {
+ // We only show an error here for other files than the file that
+ // is loaded if copy protection fails (i.e. L201.ANI).
+ warning("checkForPendingDataLoad: loadPrc(%s) failed", currentPrcName);
+ }
}
if (newRelName[0] != 0) {
diff --git a/engines/kyra/kyra_v1.cpp b/engines/kyra/kyra_v1.cpp
index cc97f43a05..6121f6979c 100644
--- a/engines/kyra/kyra_v1.cpp
+++ b/engines/kyra/kyra_v1.cpp
@@ -112,7 +112,7 @@ int KyraEngine_v1::init() {
_sound = new SoundTownsPC98_v2(this, _mixer);
} else if (_flags.platform == Common::kPlatformPC98) {
if (_flags.gameID == GI_KYRA1)
- _sound = new SoundPC98(this, _mixer);
+ _sound = new SoundTowns/*SoundPC98*/(this, _mixer);
else
_sound = new SoundTownsPC98_v2(this, _mixer);
} else if (midiDriver == MD_ADLIB) {
diff --git a/engines/kyra/sound_towns.cpp b/engines/kyra/sound_towns.cpp
index e96cef735c..0f2b916c9d 100644
--- a/engines/kyra/sound_towns.cpp
+++ b/engines/kyra/sound_towns.cpp
@@ -2363,7 +2363,7 @@ TownsPC98_OpnDriver::TownsPC98_OpnDriver(Audio::Mixer *mixer, OpnType type) :
_numSSG(type == OD_TOWNS ? 0 : 3), _hasADPCM(type == OD_TYPE86 ? true : false),
_numChan(type == OD_TYPE26 ? 3 : 6), _hasStereo(type == OD_TYPE26 ? false : true) {
setTempo(84);
- _baserate = (3579545.0 / (double)getRate()) / 144.0;
+ _baserate = (double)getRate() / 10368.0;
}
TownsPC98_OpnDriver::~TownsPC98_OpnDriver() {
@@ -3095,8 +3095,8 @@ SoundTownsPC98_v2::~SoundTownsPC98_v2() {
}
bool SoundTownsPC98_v2::init() {
- _driver = new TownsPC98_OpnDriver(_mixer, _vm->gameFlags().platform == Common::kPlatformPC98 ?
- TownsPC98_OpnDriver::OD_TYPE86 : TownsPC98_OpnDriver::OD_TOWNS);
+ _driver = new TownsPC98_OpnDriver(_mixer, /*_vm->gameFlags().platform == Common::kPlatformPC98 ?
+ TownsPC98_OpnDriver::OD_TYPE86 :*/ TownsPC98_OpnDriver::OD_TOWNS);
_useFmSfx = _vm->gameFlags().platform == Common::kPlatformPC98 ? true : false;
_vm->checkCD();
// FIXME: While checking for 'track1.XXX(X)' looks like
diff --git a/engines/kyra/staticres.cpp b/engines/kyra/staticres.cpp
index 4f577c1d1e..c05795dacd 100644
--- a/engines/kyra/staticres.cpp
+++ b/engines/kyra/staticres.cpp
@@ -1034,8 +1034,10 @@ void KyraEngine_LoK::initStaticResource() {
}
// audio data tables
+#if 0
static const char *tIntro98[] = { "intro%d.dat" };
static const char *tIngame98[] = { "kyram%d.dat" };
+#endif
static const AudioDataStruct soundData_PC[] = {
{ _soundFilesIntro, _soundFilesIntroSize, 0, 0 },
@@ -1049,18 +1051,20 @@ void KyraEngine_LoK::initStaticResource() {
{ 0, 0, 0, 0}
};
+#if 0
static const AudioDataStruct soundData_PC98[] = {
{ tIntro98, 1, 0, 0 },
{ tIngame98, 1, 0, 0 },
{ 0, 0, 0, 0}
};
+#endif
if (_flags.platform == Common::kPlatformPC)
_soundData = soundData_PC;
else if (_flags.platform == Common::kPlatformFMTowns)
_soundData = soundData_TOWNS;
else if (_flags.platform == Common::kPlatformPC98)
- _soundData = soundData_PC98;
+ _soundData = soundData_TOWNS/*soundData_PC98*/;
}
@@ -1259,9 +1263,11 @@ void KyraEngine_HoF::initStaticResource() {
static const char *fmtMusicFileListFinale[] = { "finale%d.twn" };
static const char *fmtMusicFileListIngame[] = { "km%02d.twn" };
+#if 0
static const char *pc98MusicFileListIntro[] = { "intro%d.86" };
static const char *pc98MusicFileListFinale[] = { "finale%d.86" };
static const char *pc98MusicFileListIngame[] = { "km%02d.86" };
+#endif
static const AudioDataStruct soundData_PC[] = {
{ _musicFileListIntro, _musicFileListIntroSize, 0, 0 },
@@ -1275,18 +1281,20 @@ void KyraEngine_HoF::initStaticResource() {
{ fmtMusicFileListFinale, 1, _cdaTrackTableFinale, _cdaTrackTableFinaleSize >> 1 }
};
+#if 0
static const AudioDataStruct soundData_PC98[] = {
{ pc98MusicFileListIntro, 1, 0, 0 },
{ pc98MusicFileListIngame, 1, 0, 0 },
{ pc98MusicFileListFinale, 1, 0, 0 }
};
+#endif
if (_flags.platform == Common::kPlatformPC)
_soundData = soundData_PC;
else if (_flags.platform == Common::kPlatformFMTowns)
_soundData = soundData_TOWNS;
else if (_flags.platform == Common::kPlatformPC98)
- _soundData = soundData_PC98;
+ _soundData = soundData_TOWNS/*soundData_PC98*/;
// setup sequence data
_sequences = _staticres->loadHofSequenceData(k2SeqplaySeqData, tmpSize);
diff --git a/engines/lure/luredefs.h b/engines/lure/luredefs.h
index 603102a099..922e1207d0 100644
--- a/engines/lure/luredefs.h
+++ b/engines/lure/luredefs.h
@@ -36,7 +36,7 @@ namespace Lure {
#define LURE_DAT_MAJOR 1
#define LURE_DAT_MINOR 29
#define LURE_MIN_SAVEGAME_MINOR 25
-#define LURE_SAVEGAME_MINOR 32
+#define LURE_SAVEGAME_MINOR 33
#define LURE_DEBUG 1
diff --git a/engines/lure/res_struct.cpp b/engines/lure/res_struct.cpp
index de09f982d1..92cea948f9 100644
--- a/engines/lure/res_struct.cpp
+++ b/engines/lure/res_struct.cpp
@@ -456,6 +456,8 @@ void HotspotData::saveToStream(WriteStream *stream) {
stream->writeSint16LE(startY);
stream->writeUint16LE(roomNumber);
stream->writeByte(layer);
+ stream->writeUint16LE(walkX);
+ stream->writeUint16LE(walkY);
stream->writeUint16LE(width);
stream->writeUint16LE(height);
@@ -503,6 +505,10 @@ void HotspotData::loadFromStream(ReadStream *stream) {
uint8 saveVersion = LureEngine::getReference().saveVersion();
if (saveVersion >= 29)
layer = stream->readByte();
+ if (saveVersion >= 33) {
+ walkX = stream->readUint16LE();
+ walkY = stream->readUint16LE();
+ }
width = stream->readUint16LE();
height = stream->readUint16LE();
diff --git a/engines/parallaction/callables_ns.cpp b/engines/parallaction/callables_ns.cpp
index 7c053715f6..ed60a193ce 100644
--- a/engines/parallaction/callables_ns.cpp
+++ b/engines/parallaction/callables_ns.cpp
@@ -424,6 +424,7 @@ void Parallaction_ns::_c_testResult(void *parm) {
}
_inTestResult = true;
+ _gfx->freeLabels();
_gfx->updateScreen();
_disk->selectArchive("disk1");
diff --git a/engines/parallaction/dialogue.cpp b/engines/parallaction/dialogue.cpp
index a771f960a9..96491bf084 100644
--- a/engines/parallaction/dialogue.cpp
+++ b/engines/parallaction/dialogue.cpp
@@ -42,13 +42,23 @@ namespace Parallaction {
#define ANSWER_CHARACTER_X 10
#define ANSWER_CHARACTER_Y 80
+
class DialogueManager {
+ enum {
+ RUN_QUESTION,
+ RUN_ANSWER,
+ NEXT_QUESTION,
+ NEXT_ANSWER,
+ DIALOGUE_OVER
+ } _state;
+
Parallaction *_vm;
- SpeakData *_data;
Dialogue *_dialogue;
bool _askPassword;
+ int _passwordLen;
+ bool _passwordChanged;
bool isNpc;
GfxObj *_questioner;
@@ -59,93 +69,70 @@ class DialogueManager {
uint16 _visAnswers[5];
int _numVisAnswers;
+ int _answerId;
+
+ int _selection, _oldSelection;
+
+ uint32 _mouseButtons;
+ Common::Point _mousePos;
+ bool _isKeyDown;
+ uint16 _downKey;
+
+
public:
- DialogueManager(Parallaction *vm, SpeakData *data) : _vm(vm), _data(data) {
- _dialogue = _data->_dialogue;
- isNpc = scumm_stricmp(_data->_name, "yourself") && _data->_name[0] != '\0';
- _questioner = isNpc ? _vm->_disk->loadTalk(_data->_name) : _vm->_char._talk;
- _answerer = _vm->_char._talk;
- }
+ DialogueManager(Parallaction *vm, ZonePtr z);
+ ~DialogueManager();
- ~DialogueManager() {
- if (isNpc) {
- delete _questioner;
- }
+ bool isOver() {
+ return _state == DIALOGUE_OVER;
}
-
void run();
+ ZonePtr _z;
+ CommandList *_cmdList;
+
protected:
- void displayQuestion();
+ bool displayQuestion();
bool displayAnswers();
bool displayAnswer(uint16 i);
- uint16 getAnswer();
- int16 selectAnswer();
- uint16 askPassword();
+ int16 selectAnswer1();
+ int16 selectAnswerN();
+ int16 askPassword();
int16 getHoverAnswer(int16 x, int16 y);
-};
-
-uint16 DialogueManager::askPassword() {
- debugC(3, kDebugExec, "checkDialoguePassword()");
+ void runQuestion();
+ void runAnswer();
+ void nextQuestion();
+ void nextAnswer();
- uint16 passwordLen = 0;
- _password[0] = '\0';
-
- _vm->_balloonMan->setDialogueBalloon(_q->_answers[0]->_text, 1, 3);
- int id = _vm->_gfx->setItem(_answerer, ANSWER_CHARACTER_X, ANSWER_CHARACTER_Y);
- _vm->_gfx->setItemFrame(id, 0);
-
- Common::Event e;
- bool changed = true; // force first refresh
-
- while (true) {
- e.kbd.ascii = 0;
-
- if (g_system->getEventManager()->pollEvent(e)) {
- if ((e.type == Common::EVENT_KEYDOWN) && isdigit(e.kbd.ascii)) {
- _password[passwordLen] = e.kbd.ascii;
- passwordLen++;
- _password[passwordLen] = '\0';
- changed = true;
- }
- }
-
- if (changed) {
- _vm->_balloonMan->setBalloonText(0, _q->_answers[0]->_text, 3);
- _vm->_gfx->updateScreen();
- changed = false;
- }
-
- if ((passwordLen == MAX_PASSWORD_LENGTH) || (e.kbd.ascii == Common::KEYCODE_RETURN)) {
-
- if ((!scumm_stricmp(_vm->_char.getBaseName(), _doughName) && !scumm_strnicmp(_password, "1732461", 7)) ||
- (!scumm_stricmp(_vm->_char.getBaseName(), _donnaName) && !scumm_strnicmp(_password, "1622", 4)) ||
- (!scumm_stricmp(_vm->_char.getBaseName(), _dinoName) && !scumm_strnicmp(_password, "179", 3))) {
+ bool checkPassword();
+ void resetPassword();
+ void accumPassword(uint16 ascii);
+};
- break;
+DialogueManager::DialogueManager(Parallaction *vm, ZonePtr z) : _vm(vm), _z(z) {
+ _dialogue = _z->u.speak->_dialogue;
+ isNpc = scumm_stricmp(_z->u.speak->_name, "yourself") && _z->u.speak->_name[0] != '\0';
+ _questioner = isNpc ? _vm->_disk->loadTalk(_z->u.speak->_name) : _vm->_char._talk;
+ _answerer = _vm->_char._talk;
- } else {
- passwordLen = 0;
- _password[0] = '\0';
- changed = true;
- }
+ _askPassword = false;
+ _q = _dialogue->_questions[0];
- }
+ _cmdList = 0;
+ _answerId = 0;
- g_system->delayMillis(20);
+ _state = displayQuestion() ? RUN_QUESTION : NEXT_ANSWER;
+}
+DialogueManager::~DialogueManager() {
+ if (isNpc) {
+ delete _questioner;
}
-
- _vm->hideDialogueStuff();
-
- return 0;
-
+ _z = nullZonePtr;
}
-
-
bool DialogueManager::displayAnswer(uint16 i) {
Answer *a = _q->_answers[i];
@@ -161,7 +148,7 @@ bool DialogueManager::displayAnswer(uint16 i) {
assert(id >= 0);
_visAnswers[id] = i;
- _askPassword = (strstr(a->_text, "%p") != NULL);
+ _askPassword = (strstr(a->_text, "%P") != NULL);
_numVisAnswers++;
return true;
@@ -178,134 +165,244 @@ bool DialogueManager::displayAnswers() {
displayAnswer(i);
}
+ if (_askPassword) {
+ resetPassword();
+// _vm->_balloonMan->setDialogueBalloon(_q->_answers[0]->_text, 1, 3);
+ int id = _vm->_gfx->setItem(_answerer, ANSWER_CHARACTER_X, ANSWER_CHARACTER_Y);
+ _vm->_gfx->setItemFrame(id, 0);
+ } else
+ if (_numVisAnswers == 1) {
+ int id = _vm->_gfx->setItem(_answerer, ANSWER_CHARACTER_X, ANSWER_CHARACTER_Y);
+ _vm->_gfx->setItemFrame(id, _q->_answers[0]->_mood & 0xF);
+ _vm->_balloonMan->setBalloonText(0, _q->_answers[_visAnswers[0]]->_text, 0);
+ } else
+ if (_numVisAnswers > 1) {
+ int id = _vm->_gfx->setItem(_answerer, ANSWER_CHARACTER_X, ANSWER_CHARACTER_Y);
+ _vm->_gfx->setItemFrame(id, _q->_answers[_visAnswers[0]]->_mood & 0xF);
+ _oldSelection = -1;
+ _selection = 0;
+ }
+
return _numVisAnswers > 0;
}
-void DialogueManager::displayQuestion() {
-
- if (!scumm_stricmp(_q->_text, "NULL")) return;
+bool DialogueManager::displayQuestion() {
+ if (!scumm_stricmp(_q->_text, "NULL")) return false;
_vm->_balloonMan->setSingleBalloon(_q->_text, QUESTION_BALLOON_X, QUESTION_BALLOON_Y, _q->_mood & 0x10, 0);
int id = _vm->_gfx->setItem(_questioner, QUESTION_CHARACTER_X, QUESTION_CHARACTER_Y);
_vm->_gfx->setItemFrame(id, _q->_mood & 0xF);
- _vm->_gfx->updateScreen();
- _vm->_input->waitUntilLeftClick();
- _vm->hideDialogueStuff();
+ return true;
+}
- return;
+
+bool DialogueManager::checkPassword() {
+ return ((!scumm_stricmp(_vm->_char.getBaseName(), _doughName) && !scumm_strnicmp(_password, "1732461", 7)) ||
+ (!scumm_stricmp(_vm->_char.getBaseName(), _donnaName) && !scumm_strnicmp(_password, "1622", 4)) ||
+ (!scumm_stricmp(_vm->_char.getBaseName(), _dinoName) && !scumm_strnicmp(_password, "179", 3)));
}
-uint16 DialogueManager::getAnswer() {
+void DialogueManager::resetPassword() {
+ _passwordLen = 0;
+ _password[0] = '\0';
+ _passwordChanged = true;
+}
- uint16 answer = 0;
+void DialogueManager::accumPassword(uint16 ascii) {
+ if (!isdigit(ascii)) {
+ return;
+ }
- if (_askPassword == false) {
- answer = selectAnswer();
- } else {
- answer = askPassword();
+ _password[_passwordLen] = ascii;
+ _passwordLen++;
+ _password[_passwordLen] = '\0';
+ _passwordChanged = true;
+}
+
+int16 DialogueManager::askPassword() {
+
+ if (_isKeyDown) {
+ accumPassword(_downKey);
+ }
+
+ if (_passwordChanged) {
+ _vm->_balloonMan->setBalloonText(0, _q->_answers[0]->_text, 3);
+ _passwordChanged = false;
}
- debugC(3, kDebugExec, "runDialogue: user selected answer #%i", answer);
+ if ((_passwordLen == MAX_PASSWORD_LENGTH) || ((_isKeyDown) && (_downKey == Common::KEYCODE_RETURN))) {
+ if (checkPassword()) {
+ return 0;
+ } else {
+ resetPassword();
+ }
+ }
- return answer;
+ return -1;
}
-void DialogueManager::run() {
+int16 DialogueManager::selectAnswer1() {
- _askPassword = false;
- CommandList *cmdlist = NULL;
+ if (_mouseButtons == kMouseLeftUp) {
+ return 0;
+ }
- _q = _dialogue->_questions[0];
- int16 answer;
+ return -1;
+}
- while (_q) {
+int16 DialogueManager::selectAnswerN() {
- answer = 0;
+ _selection = _vm->_balloonMan->hitTestDialogueBalloon(_mousePos.x, _mousePos.y);
- displayQuestion();
+ if (_selection != _oldSelection) {
+ if (_oldSelection != -1) {
+ _vm->_balloonMan->setBalloonText(_oldSelection, _q->_answers[_visAnswers[_oldSelection]]->_text, 3);
+ }
if (_vm->quit())
- return;
+ return -1;
+
+ if (_selection != -1) {
+ _vm->_balloonMan->setBalloonText(_selection, _q->_answers[_visAnswers[_selection]]->_text, 0);
+ _vm->_gfx->setItemFrame(0, _q->_answers[_visAnswers[_selection]]->_mood & 0xF);
+ }
+ }
- if (_q->_answers[0] == NULL) break;
+ _oldSelection = _selection;
- if (scumm_stricmp(_q->_answers[0]->_text, "NULL")) {
- if (!displayAnswers()) break;
- answer = getAnswer();
+ if ((_mouseButtons == kMouseLeftUp) && (_selection != -1)) {
+ return _visAnswers[_selection];
+ }
- if (_vm->quit())
- return;
+ return -1;
+}
- cmdlist = &_q->_answers[answer]->_commands;
- }
+void DialogueManager::runQuestion() {
+ debugC(9, kDebugDialogue, "runQuestion\n");
- _q = _q->_answers[answer]->_following._question;
+ if (_mouseButtons == kMouseLeftUp) {
+ _vm->hideDialogueStuff();
+ _state = NEXT_ANSWER;
}
- if (cmdlist)
- _vm->_cmdExec->run(*cmdlist);
-
}
-int16 DialogueManager::selectAnswer() {
- int16 numAvailableAnswers = _numVisAnswers;
+void DialogueManager::nextAnswer() {
+ debugC(9, kDebugDialogue, "nextAnswer\n");
+
+ if (_q->_answers[0] == NULL) {
+ _state = DIALOGUE_OVER;
+ return;
+ }
+
+ if (!scumm_stricmp(_q->_answers[0]->_text, "NULL")) {
+ _answerId = 0;
+ _state = NEXT_QUESTION;
+ return;
+ }
- int id = _vm->_gfx->setItem(_answerer, ANSWER_CHARACTER_X, ANSWER_CHARACTER_Y);
- _vm->_gfx->setItemFrame(id, _q->_answers[0]->_mood & 0xF);
+ _state = displayAnswers() ? RUN_ANSWER : DIALOGUE_OVER;
+}
+
+void DialogueManager::runAnswer() {
+ debugC(9, kDebugDialogue, "runAnswer\n");
- if (numAvailableAnswers == 1) {
- _vm->_balloonMan->setBalloonText(0, _q->_answers[0]->_text, 0);
- _vm->_input->waitUntilLeftClick();
+ if (_askPassword) {
+ _answerId = askPassword();
+ } else
+ if (_numVisAnswers == 1) {
+ _answerId = selectAnswer1();
+ } else {
+ _answerId = selectAnswerN();
+ }
+
+ if (_answerId != -1) {
+ _cmdList = &_q->_answers[_answerId]->_commands;
_vm->hideDialogueStuff();
- return 0;
+ _state = NEXT_QUESTION;
}
+}
- int oldSelection = -1;
- int selection = 0;
-
- uint32 event;
- Common::Point p;
- while (!_vm->quit()) {
-
- _vm->_input->readInput();
- _vm->_input->getCursorPos(p);
- event = _vm->_input->getLastButtonEvent();
- selection = _vm->_balloonMan->hitTestDialogueBalloon(p.x, p.y);
-
- if (selection != oldSelection) {
- if (oldSelection != -1) {
- _vm->_balloonMan->setBalloonText(oldSelection, _q->_answers[_visAnswers[oldSelection]]->_text, 3);
- }
-
- if (selection != -1) {
- _vm->_balloonMan->setBalloonText(selection, _q->_answers[_visAnswers[selection]]->_text, 0);
- _vm->_gfx->setItemFrame(0, _q->_answers[_visAnswers[selection]]->_mood & 0xF);
- }
- }
+void DialogueManager::nextQuestion() {
+ debugC(9, kDebugDialogue, "nextQuestion\n");
+
+ _q = _q->_answers[_answerId]->_following._question;
+ if (_q == 0) {
+ _state = DIALOGUE_OVER;
+ } else {
+ _state = displayQuestion() ? RUN_QUESTION : NEXT_ANSWER;
+ }
+}
+
+void DialogueManager::run() {
+
+ // cache event data
+ _mouseButtons = _vm->_input->getLastButtonEvent();
+ _vm->_input->getCursorPos(_mousePos);
+ _isKeyDown = _vm->_input->getLastKeyDown(_downKey);
- if ((selection != -1) && (event == kMouseLeftUp)) {
- break;
+ switch (_state) {
+ case RUN_QUESTION:
+ runQuestion();
+ break;
+
+ case NEXT_ANSWER:
+ nextAnswer();
+ break;
+
+ case NEXT_QUESTION:
+ nextQuestion();
+ break;
+
+ case RUN_ANSWER:
+ runAnswer();
+ break;
+
+ case DIALOGUE_OVER:
+ if (_cmdList) {
+ _vm->_cmdExec->run(*_cmdList);
}
+ break;
- _vm->_gfx->updateScreen();
- g_system->delayMillis(20);
+ default:
+ error("unknown state in DialogueManager");
- oldSelection = selection;
}
- _vm->hideDialogueStuff();
+}
- return _visAnswers[selection];
+void Parallaction::enterDialogueMode(ZonePtr z) {
+ debugC(1, kDebugDialogue, "Parallaction::enterDialogueMode(%s)", z->u.speak->_name);
+ _dialogueMan = new DialogueManager(this, z);
+ _input->_inputMode = Input::kInputModeDialogue;
}
+void Parallaction::exitDialogueMode() {
+ debugC(1, kDebugDialogue, "Parallaction::exitDialogueMode()");
+ _input->_inputMode = Input::kInputModeGame;
-void Parallaction::runDialogue(SpeakData *data) {
- debugC(1, kDebugExec, "runDialogue: starting dialogue '%s'", data->_name);
+ // The current instance of _dialogueMan must be destroyed before the zone commands
+ // are executed, because they may create another instance of _dialogueMan that
+ // overwrite the current one. This would cause headaches (and it did, actually).
+ ZonePtr z = _dialogueMan->_z;
+ delete _dialogueMan;
+ _dialogueMan = 0;
- DialogueManager man(this, data);
- man.run();
+ _cmdExec->run(z->_commands, z);
+}
+
+void Parallaction::runDialogueFrame() {
+ if (_input->_inputMode != Input::kInputModeDialogue) {
+ return;
+ }
+
+ _dialogueMan->run();
+
+ if (_dialogueMan->isOver()) {
+ exitDialogueMode();
+ }
return;
}
diff --git a/engines/parallaction/exec_ns.cpp b/engines/parallaction/exec_ns.cpp
index c77c70cd6e..913e7ae648 100644
--- a/engines/parallaction/exec_ns.cpp
+++ b/engines/parallaction/exec_ns.cpp
@@ -224,7 +224,11 @@ DECLARE_COMMAND_OPCODE(start) {
DECLARE_COMMAND_OPCODE(speak) {
- _vm->_activeZone = _ctxt.cmd->u._zone;
+ if ((_ctxt.cmd->u._zone->_type & 0xFFFF) == kZoneSpeak) {
+ _vm->enterDialogueMode(_ctxt.cmd->u._zone);
+ } else {
+ _vm->_activeZone = _ctxt.cmd->u._zone;
+ }
}
@@ -322,6 +326,7 @@ DECLARE_COMMAND_OPCODE(stop) {
void Parallaction_ns::drawAnimations() {
+ debugC(9, kDebugExec, "Parallaction_ns::drawAnimations()\n");
uint16 layer = 0;
@@ -362,6 +367,8 @@ void Parallaction_ns::drawAnimations() {
}
}
+ debugC(9, kDebugExec, "Parallaction_ns::drawAnimations done()\n");
+
return;
}
@@ -417,7 +424,6 @@ label1:
return;
}
-
void CommandExec::run(CommandList& list, ZonePtr z) {
if (list.size() == 0) {
debugC(3, kDebugExec, "runCommands: nothing to do");
@@ -542,11 +548,8 @@ uint16 Parallaction::runZone(ZonePtr z) {
break;
case kZoneSpeak:
- runDialogue(z->u.speak);
- if (_vm->quit())
- return 0;
- break;
-
+ enterDialogueMode(z);
+ return 0;
}
debugC(3, kDebugExec, "runZone completed");
diff --git a/engines/parallaction/gfxbase.cpp b/engines/parallaction/gfxbase.cpp
index 9e7eb12ed8..e8250ac8fd 100644
--- a/engines/parallaction/gfxbase.cpp
+++ b/engines/parallaction/gfxbase.cpp
@@ -267,9 +267,6 @@ void Gfx::drawWrappedText(Font *font, Graphics::Surface* surf, char *text, byte
}
-// this is the maximum size of an unpacked frame in BRA
-byte _unpackedBitmap[640*401];
-
#if 0
void Gfx::unpackBlt(const Common::Rect& r, byte *data, uint size, Graphics::Surface *surf, uint16 z, byte transparentColor) {
diff --git a/engines/parallaction/graphics.cpp b/engines/parallaction/graphics.cpp
index 32d0e303eb..9b9ea8605a 100644
--- a/engines/parallaction/graphics.cpp
+++ b/engines/parallaction/graphics.cpp
@@ -33,6 +33,11 @@
namespace Parallaction {
+// this is the size of the receiving buffer for unpacked frames,
+// since BRA uses some insanely big animations.
+#define MAXIMUM_UNPACKED_BITMAP_SIZE 640*401
+
+
void Gfx::registerVar(const Common::String &name, int32 initialValue) {
if (_vars.contains(name)) {
warning("Variable '%s' already registered, ignoring initial value.\n", name.c_str());
@@ -752,6 +757,9 @@ Gfx::Gfx(Parallaction* vm) :
_halfbrite = false;
_hbCircleRadius = 0;
+ _unpackedBitmap = new byte[MAXIMUM_UNPACKED_BITMAP_SIZE];
+ assert(_unpackedBitmap);
+
registerVar("background_mode", 1);
_varBackgroundMode = 1;
@@ -769,6 +777,8 @@ Gfx::~Gfx() {
freeBackground();
freeLabels();
+ delete []_unpackedBitmap;
+
return;
}
diff --git a/engines/parallaction/graphics.h b/engines/parallaction/graphics.h
index 09f4b2f244..a7242ba6f4 100644
--- a/engines/parallaction/graphics.h
+++ b/engines/parallaction/graphics.h
@@ -547,6 +547,8 @@ public:
uint _screenX; // scrolling position
uint _screenY;
+ byte *_unpackedBitmap;
+
protected:
Parallaction* _vm;
bool _halfbrite;
diff --git a/engines/parallaction/input.cpp b/engines/parallaction/input.cpp
index e57b95678f..d625199e2b 100644
--- a/engines/parallaction/input.cpp
+++ b/engines/parallaction/input.cpp
@@ -42,12 +42,14 @@ uint16 Input::readInput() {
uint16 KeyDown = 0;
_mouseButtons = kMouseNone;
+ _lastKeyDownAscii = -1;
Common::EventManager *eventMan = _vm->_system->getEventManager();
while (eventMan->pollEvent(e)) {
switch (e.type) {
case Common::EVENT_KEYDOWN:
+ _lastKeyDownAscii = e.kbd.ascii;
if (e.kbd.flags == Common::KBD_CTRL && e.kbd.keycode == 'd')
_vm->_debugger->attach();
if (_vm->getFeatures() & GF_DEMO) break;
@@ -97,6 +99,11 @@ uint16 Input::readInput() {
}
+bool Input::getLastKeyDown(uint16 &ascii) {
+ ascii = _lastKeyDownAscii;
+ return (_lastKeyDownAscii != -1);
+}
+
// FIXME: see comment for readInput()
void Input::waitForButtonEvent(uint32 buttonEventMask, int32 timeout) {
@@ -192,11 +199,38 @@ InputData* Input::updateInput() {
case kInputModeGame:
updateGameInput();
break;
+
+ case kInputModeDialogue:
+ readInput();
+ break;
}
return &_inputData;
}
+void Input::trackMouse(ZonePtr z) {
+ if ((z != _hoverZone) && (_hoverZone)) {
+ stopHovering();
+ return;
+ }
+
+ if (!z) {
+ return;
+ }
+
+ if ((!_hoverZone) && ((z->_flags & kFlagsNoName) == 0)) {
+ _hoverZone = z;
+ _vm->_gfx->showFloatingLabel(_hoverZone->_label);
+ return;
+ }
+}
+
+void Input::stopHovering() {
+ _hoverZone = nullZonePtr;
+ _vm->_gfx->hideFloatingLabel();
+}
+
+
bool Input::translateGameInput() {
if ((_engineFlags & kEnginePauseJobs) || (_engineFlags & kEngineInventory)) {
@@ -231,23 +265,10 @@ bool Input::translateGameInput() {
return true;
}
- if ((z != _hoverZone) && (_hoverZone)) {
- _hoverZone = nullZonePtr;
- _inputData._event = kEvExitZone;
- return true;
- }
-
- if (!z) {
- _inputData._event = kEvNone;
- return true;
- }
-
- if ((!_hoverZone) && ((z->_flags & kFlagsNoName) == 0)) {
- _hoverZone = z;
- _inputData._event = kEvEnterZone;
- _inputData._label = z->_label;
- return true;
- }
+ trackMouse(z);
+ if (!z) {
+ return true;
+ }
if ((_mouseButtons == kMouseLeftUp) && ((_activeItem._id != 0) || ((z->_type & 0xFFFF) == kZoneCommand))) {
diff --git a/engines/parallaction/input.h b/engines/parallaction/input.h
index e06fe96705..f260352dba 100644
--- a/engines/parallaction/input.h
+++ b/engines/parallaction/input.h
@@ -66,6 +66,7 @@ class Input {
Common::Point _mousePos;
uint16 _mouseButtons;
+ int32 _lastKeyDownAscii;
bool _mouseHidden;
ZonePtr _hoverZone;
@@ -73,7 +74,8 @@ class Input {
public:
enum {
kInputModeGame = 0,
- kInputModeComment = 1
+ kInputModeComment = 1,
+ kInputModeDialogue = 2
};
@@ -99,14 +101,13 @@ public:
uint16 readInput();
InputData* updateInput();
+ void trackMouse(ZonePtr z);
void waitUntilLeftClick();
void waitForButtonEvent(uint32 buttonEventMask, int32 timeout = -1);
uint32 getLastButtonEvent() { return _mouseButtons; }
+ bool getLastKeyDown(uint16 &ascii);
- void stopHovering() {
- _hoverZone = nullZonePtr;
- }
-
+ void stopHovering();
};
} // namespace Parallaction
diff --git a/engines/parallaction/parallaction.cpp b/engines/parallaction/parallaction.cpp
index c998e26024..fff50b48df 100644
--- a/engines/parallaction/parallaction.cpp
+++ b/engines/parallaction/parallaction.cpp
@@ -164,6 +164,11 @@ void Parallaction::updateView() {
}
+void Parallaction::hideDialogueStuff() {
+ _gfx->freeItems();
+ _balloonMan->freeBalloons();
+}
+
void Parallaction::freeCharacter() {
debugC(1, kDebugExec, "freeCharacter()");
@@ -297,16 +302,6 @@ void Parallaction::showLocationComment(const char *text, bool end) {
void Parallaction::processInput(InputData *data) {
switch (data->_event) {
- case kEvEnterZone:
- debugC(2, kDebugInput, "processInput: kEvEnterZone");
- _gfx->showFloatingLabel(data->_label);
- break;
-
- case kEvExitZone:
- debugC(2, kDebugInput, "processInput: kEvExitZone");
- _gfx->hideFloatingLabel();
- break;
-
case kEvAction:
debugC(2, kDebugInput, "processInput: kEvAction");
_input->stopHovering();
@@ -317,7 +312,6 @@ void Parallaction::processInput(InputData *data) {
case kEvOpenInventory:
_input->stopHovering();
- _gfx->hideFloatingLabel();
if (hitZone(kZoneYou, data->_mousePos.x, data->_mousePos.y) == 0) {
setArrowCursor();
}
@@ -367,25 +361,29 @@ void Parallaction::processInput(InputData *data) {
void Parallaction::runGame() {
InputData *data = _input->updateInput();
- if (data->_event != kEvNone) {
- processInput(data);
- }
-
if (_vm->quit())
return;
- runPendingZones();
+ if (_input->_inputMode == Input::kInputModeDialogue) {
+ runDialogueFrame();
+ } else {
+ if (data->_event != kEvNone) {
+ processInput(data);
+ }
- if (_vm->quit())
- return;
+ if (_vm->quit())
+ return;
- if (_engineFlags & kEngineChangeLocation) {
- changeLocation(_location._name);
- }
+ runPendingZones();
if (_vm->quit())
return;
+ if (_engineFlags & kEngineChangeLocation) {
+ changeLocation(_location._name);
+ }
+ }
+
_gfx->beginFrame();
if (_input->_inputMode == Input::kInputModeGame) {
@@ -400,7 +398,6 @@ void Parallaction::runGame() {
// change this to endFrame?
updateView();
-
}
@@ -668,6 +665,7 @@ void Parallaction::beep() {
}
void Parallaction::scheduleLocationSwitch(const char *location) {
+ debugC(9, kDebugExec, "scheduleLocationSwitch(%s)\n", location);
strcpy(_location._name, location);
_engineFlags |= kEngineChangeLocation;
}
diff --git a/engines/parallaction/parallaction.h b/engines/parallaction/parallaction.h
index a90f8c4f48..115099addd 100644
--- a/engines/parallaction/parallaction.h
+++ b/engines/parallaction/parallaction.h
@@ -113,8 +113,6 @@ enum EngineFlags {
enum {
kEvNone = 0,
- kEvEnterZone = 1,
- kEvExitZone = 2,
kEvAction = 3,
kEvOpenInventory = 4,
kEvCloseInventory = 5,
@@ -164,6 +162,7 @@ class Debugger;
class Gfx;
class SoundMan;
class Input;
+class DialogueManager;
struct Location {
@@ -281,8 +280,6 @@ public:
uint16 runZone(ZonePtr z);
void freeZones();
- void runDialogue(SpeakData*);
-
AnimationPtr findAnimation(const char *name);
void freeAnimations();
@@ -425,10 +422,11 @@ public:
void setupBalloonManager();
- void hideDialogueStuff() {
- _gfx->freeItems();
- _balloonMan->freeBalloons();
- }
+ void hideDialogueStuff();
+ DialogueManager *_dialogueMan;
+ void enterDialogueMode(ZonePtr z);
+ void exitDialogueMode();
+ void runDialogueFrame();
};
diff --git a/engines/parallaction/parallaction_br.cpp b/engines/parallaction/parallaction_br.cpp
index 090184e9fe..0c8058e4bd 100644
--- a/engines/parallaction/parallaction_br.cpp
+++ b/engines/parallaction/parallaction_br.cpp
@@ -212,13 +212,21 @@ void Parallaction_br::runPendingZones() {
if (_activeZone) {
z = _activeZone; // speak Zone or sound
_activeZone = nullZonePtr;
- runZone(z); // FIXME: BRA doesn't handle sound yet
+ if ((z->_type & 0xFFFF) == kZoneSpeak) {
+ enterDialogueMode(z);
+ } else {
+ runZone(z); // FIXME: BRA doesn't handle sound yet
+ }
}
if (_activeZone2) {
z = _activeZone2; // speak Zone or sound
_activeZone2 = nullZonePtr;
- runZone(z);
+ if ((z->_type & 0xFFFF) == kZoneSpeak) {
+ enterDialogueMode(z);
+ } else {
+ runZone(z); // FIXME: BRA doesn't handle sound yet
+ }
}
}
diff --git a/engines/parallaction/parallaction_ns.cpp b/engines/parallaction/parallaction_ns.cpp
index e5baf1864d..e8264238a1 100644
--- a/engines/parallaction/parallaction_ns.cpp
+++ b/engines/parallaction/parallaction_ns.cpp
@@ -191,7 +191,7 @@ void Parallaction_ns::setArrowCursor() {
debugC(1, kDebugInput, "setting mouse cursor to arrow");
// this stuff is needed to avoid artifacts with labels and selected items when switching cursors
- _gfx->hideFloatingLabel();
+ _input->stopHovering();
_input->_activeItem._id = 0;
_system->setMouseCursor(_mouseArrow, MOUSEARROW_WIDTH, MOUSEARROW_HEIGHT, 0, 0, 0);
@@ -302,12 +302,11 @@ void Parallaction_ns::changeLocation(char *location) {
_soundMan->playLocationMusic(location);
- _gfx->hideFloatingLabel();
+ _input->stopHovering();
_gfx->freeLabels();
_zoneTrap = nullZonePtr;
- _input->stopHovering();
if (_engineFlags & kEngineBlockInput) {
setArrowCursor();
}
@@ -420,6 +419,7 @@ void Parallaction_ns::changeCharacter(const char *name) {
Common::String oldArchive = _disk->selectArchive((getFeatures() & GF_DEMO) ? "disk0" : "disk1");
_char._ani->gfxobj = _gfx->loadAnim(_char.getFullName());
_char._ani->gfxobj->setFlags(kGfxObjCharacter);
+ _char._ani->gfxobj->clearFlags(kGfxObjNormal);
if (!_char.dummy()) {
if (getPlatform() == Common::kPlatformAmiga) {
diff --git a/engines/parallaction/walk.cpp b/engines/parallaction/walk.cpp
index 40dfddb903..a717b615e6 100644
--- a/engines/parallaction/walk.cpp
+++ b/engines/parallaction/walk.cpp
@@ -354,6 +354,7 @@ void Parallaction_ns::walk(Character &character) {
if (newPos == curPos) {
debugC(1, kDebugWalk, "walk was blocked by an unforeseen obstacle");
finalizeWalk(character);
+ targetPos = newPos; // when walking is interrupted, targetPos must be hacked so that a still frame can be selected
}
}
diff --git a/engines/queen/graphics.cpp b/engines/queen/graphics.cpp
index f863f7663c..6d0a11ccfe 100644
--- a/engines/queen/graphics.cpp
+++ b/engines/queen/graphics.cpp
@@ -1175,15 +1175,8 @@ BamScene::BamScene(QueenEngine *vm)
}
void BamScene::playSfx() {
- // Don't try to play all the sounds. This is only necessary for the
- // fight bam, in which the number of 'sfx bam frames' is too much
- // important / too much closer. The original game does not have
- // this problem since its playSfx() function returns immediately
- // if a sound is already being played.
- if (_lastSoundIndex == 0 || _index - _lastSoundIndex >= SFX_SKIP) {
- _vm->sound()->playSfx(_vm->logic()->currentRoomSfx());
- _lastSoundIndex = _index;
- }
+ _vm->sound()->playSfx(_vm->logic()->currentRoomSfx());
+ _lastSoundIndex = _index;
}
void BamScene::prepareAnimation() {
diff --git a/engines/queen/graphics.h b/engines/queen/graphics.h
index 6f00111635..7eadf9a191 100644
--- a/engines/queen/graphics.h
+++ b/engines/queen/graphics.h
@@ -248,10 +248,6 @@ public:
F_REQ_STOP = 2
};
- enum {
- SFX_SKIP = 8
- };
-
uint16 _flag, _index;
private:
diff --git a/engines/queen/sound.cpp b/engines/queen/sound.cpp
index d17a73c90b..9cdd971857 100644
--- a/engines/queen/sound.cpp
+++ b/engines/queen/sound.cpp
@@ -227,11 +227,6 @@ void PCSound::setVolume(int vol) {
_music->setVolume(vol);
}
-void PCSound::waitFinished(bool isSpeech) {
- while (_mixer->isSoundHandleActive(isSpeech ? _speechHandle : _sfxHandle))
- _vm->input()->delay(10);
-}
-
void PCSound::playSound(const char *base, bool isSpeech) {
char name[13];
strcpy(name, base);
@@ -241,7 +236,13 @@ void PCSound::playSound(const char *base, bool isSpeech) {
name[i] = '0';
}
strcat(name, ".SB");
- waitFinished(isSpeech);
+ if (isSpeech) {
+ while (_mixer->isSoundHandleActive(_speechHandle)) {
+ _vm->input()->delay(10);
+ }
+ } else {
+ _mixer->stopHandle(_sfxHandle);
+ }
uint32 size;
Common::File *f = _vm->resource()->findSound(name, &size);
if (f) {
@@ -253,6 +254,8 @@ void PCSound::playSound(const char *base, bool isSpeech) {
}
void SBSound::playSoundData(Common::File *f, uint32 size, Audio::SoundHandle *soundHandle) {
+ // In order to simplify the code, we don't parse the .sb header but hard-code the
+ // values. Refer to tracker item #1876741 for details on the format/fields.
int headerSize;
f->seek(2, SEEK_CUR);
uint16 version = f->readUint16LE();
diff --git a/engines/queen/sound.h b/engines/queen/sound.h
index c2c1481cc6..331034f746 100644
--- a/engines/queen/sound.h
+++ b/engines/queen/sound.h
@@ -143,7 +143,6 @@ public:
void setVolume(int vol);
protected:
- void waitFinished(bool isSpeech);
void playSound(const char *base, bool isSpeech);
virtual void playSoundData(Common::File *f, uint32 size, Audio::SoundHandle *soundHandle) = 0;
diff --git a/engines/scumm/detection.cpp b/engines/scumm/detection.cpp
index 753ad45212..68d3010199 100644
--- a/engines/scumm/detection.cpp
+++ b/engines/scumm/detection.cpp
@@ -949,7 +949,7 @@ SaveStateList ScummMetaEngine::listSaves(const char *target) const {
sort(filenames.begin(), filenames.end()); // Sort (hopefully ensuring we are sorted numerically..)
SaveStateList saveList;
- for (Common::StringList::const_iterator file = filenames.begin(); file != filenames.end(); file++) {
+ for (Common::StringList::const_iterator file = filenames.begin(); file != filenames.end(); ++file) {
// Obtain the last 2 digits of the filename, since they correspond to the save slot
int slotNum = atoi(file->c_str() + file->size() - 2);
diff --git a/engines/scumm/dialogs.cpp b/engines/scumm/dialogs.cpp
index 310cfc50a6..cb9113fe65 100644
--- a/engines/scumm/dialogs.cpp
+++ b/engines/scumm/dialogs.cpp
@@ -297,7 +297,7 @@ void SaveLoadChooser::handleCommand(CommandSender *sender, uint32 cmd, uint32 da
break;
case GUI::kListSelectionChangedCmd: {
if (_gfxWidget) {
- updateInfos();
+ updateInfos(true);
}
if (_saveMode) {
@@ -350,7 +350,7 @@ void SaveLoadChooser::reflowLayout() {
_fillR = g_gui.evaluator()->getVar("scummsaveload_thumbnail.fillR");
_fillG = g_gui.evaluator()->getVar("scummsaveload_thumbnail.fillG");
_fillB = g_gui.evaluator()->getVar("scummsaveload_thumbnail.fillB");
- updateInfos();
+ updateInfos(false);
} else {
_container->setFlags(GUI::WIDGET_INVISIBLE);
_gfxWidget->setFlags(GUI::WIDGET_INVISIBLE);
@@ -362,7 +362,7 @@ void SaveLoadChooser::reflowLayout() {
Dialog::reflowLayout();
}
-void SaveLoadChooser::updateInfos() {
+void SaveLoadChooser::updateInfos(bool redraw) {
int selItem = _list->getSelected();
Graphics::Surface *thumb;
thumb = _vm->loadThumbnailFromSlot(_saveMode ? selItem + 1 : selItem);
@@ -376,7 +376,8 @@ void SaveLoadChooser::updateInfos() {
}
delete thumb;
- _gfxWidget->draw();
+ if (redraw)
+ _gfxWidget->draw();
InfoStuff infos;
memset(&infos, 0, sizeof(InfoStuff));
@@ -386,12 +387,14 @@ void SaveLoadChooser::updateInfos() {
(infos.date >> 24) & 0xFF, (infos.date >> 16) & 0xFF,
infos.date & 0xFFFF);
_date->setLabel(buffer);
- _date->draw();
+ if (redraw)
+ _date->draw();
snprintf(buffer, 32, "Time: %.2d:%.2d",
(infos.time >> 8) & 0xFF, infos.time & 0xFF);
_time->setLabel(buffer);
- _time->draw();
+ if (redraw)
+ _time->draw();
int minutes = infos.playtime / 60;
int hours = minutes / 60;
@@ -400,19 +403,23 @@ void SaveLoadChooser::updateInfos() {
snprintf(buffer, 32, "Playtime: %.2d:%.2d",
hours & 0xFF, minutes & 0xFF);
_playtime->setLabel(buffer);
- _playtime->draw();
+ if (redraw)
+ _playtime->draw();
} else {
snprintf(buffer, 32, "No date saved");
_date->setLabel(buffer);
- _date->draw();
+ if (redraw)
+ _date->draw();
snprintf(buffer, 32, "No time saved");
_time->setLabel(buffer);
- _time->draw();
+ if (redraw)
+ _time->draw();
snprintf(buffer, 32, "No playtime saved");
_playtime->setLabel(buffer);
- _playtime->draw();
+ if (redraw)
+ _playtime->draw();
}
}
diff --git a/engines/scumm/dialogs.h b/engines/scumm/dialogs.h
index 192bb8d0e1..3837787a3b 100644
--- a/engines/scumm/dialogs.h
+++ b/engines/scumm/dialogs.h
@@ -69,7 +69,7 @@ protected:
uint8 _fillR, _fillG, _fillB;
- void updateInfos();
+ void updateInfos(bool redraw);
public:
SaveLoadChooser(const String &title, const String &buttonLabel, bool saveMode, ScummEngine *engine);
~SaveLoadChooser();
diff --git a/engines/scumm/imuse_digi/dimuse_sndmgr.cpp b/engines/scumm/imuse_digi/dimuse_sndmgr.cpp
index 1511b9aefc..b18b0ba70f 100644
--- a/engines/scumm/imuse_digi/dimuse_sndmgr.cpp
+++ b/engines/scumm/imuse_digi/dimuse_sndmgr.cpp
@@ -102,10 +102,10 @@ void ImuseDigiSndMgr::prepareSoundFromRMAP(Common::File *file, SoundDesc *sound,
int32 version = file->readUint32BE();
if (version != 3) {
if (version == 2) {
- warning("ImuseDigiSndMgr::prepareSoundFromRMAP: Wrong version of compressed *.bun file, expected 3, but it's 2.");
- warning("Suggested to recompress with latest tool from daily builds.");
+ warning("ImuseDigiSndMgr::prepareSoundFromRMAP: Wrong version of compressed *.bun file, expected 3, but it's 2");
+ warning("Suggested to recompress with latest tool from daily builds");
} else
- error("ImuseDigiSndMgr::prepareSoundFromRMAP: Wrong version number, expected 3, but it's: %d.", version);
+ error("ImuseDigiSndMgr::prepareSoundFromRMAP: Wrong version number, expected 3, but it's: %d", version);
}
sound->bits = file->readUint32BE();
sound->freq = file->readUint32BE();
diff --git a/engines/sword2/music.cpp b/engines/sword2/music.cpp
index fd72ba8d52..3b5a09578b 100644
--- a/engines/sword2/music.cpp
+++ b/engines/sword2/music.cpp
@@ -52,9 +52,11 @@ namespace Sword2 {
static Audio::AudioStream *makeCLUStream(Common::File *fp, int size);
static Audio::AudioStream *getAudioStream(SoundFileHandle *fh, const char *base, int cd, uint32 id, uint32 *numSamples) {
- debug(3, "Playing %s from CD %d", base, cd);
+ bool alreadyOpen;
if (!fh->file.isOpen()) {
+ alreadyOpen = false;
+
struct {
const char *ext;
int mode;
@@ -75,16 +77,14 @@ static Audio::AudioStream *getAudioStream(SoundFileHandle *fh, const char *base,
char filename[20];
for (int i = 0; i < ARRAYSIZE(file_types); i++) {
- Common::File f;
-
sprintf(filename, "%s%d.%s", base, cd, file_types[i].ext);
- if (f.open(filename)) {
+ if (Common::File::exists(filename)) {
soundMode = file_types[i].mode;
break;
}
sprintf(filename, "%s.%s", base, file_types[i].ext);
- if (f.open(filename)) {
+ if (Common::File::exists(filename)) {
soundMode = file_types[i].mode;
break;
}
@@ -105,7 +105,8 @@ static Audio::AudioStream *getAudioStream(SoundFileHandle *fh, const char *base,
fh->idxTab = NULL;
}
}
- }
+ } else
+ alreadyOpen = true;
uint32 entrySize = (fh->fileType == kCLUMode) ? 2 : 3;
@@ -134,7 +135,13 @@ static Audio::AudioStream *getAudioStream(SoundFileHandle *fh, const char *base,
*numSamples = len;
if (!pos || !len) {
- fh->file.close();
+ // We couldn't find the sound. Possibly as a result of a bad
+ // installation (e.g. using the music file from CD 2 as the
+ // first music file). Don't close the file if it was already
+ // open though, because something is playing from it.
+ warning("getAudioStream: Could not find %s ID %d! Possibly the wrong file", base, id);
+ if (!alreadyOpen)
+ fh->file.close();
return NULL;
}
diff --git a/engines/sword2/sound.h b/engines/sword2/sound.h
index 70bae6f851..b89ef8f12b 100644
--- a/engines/sword2/sound.h
+++ b/engines/sword2/sound.h
@@ -106,7 +106,7 @@ private:
void refill();
inline bool eosIntern() const {
- return _pos >= _bufferEnd;
+ return !_file->isOpen() || _pos >= _bufferEnd;
}
public: