aboutsummaryrefslogtreecommitdiff
path: root/engines
diff options
context:
space:
mode:
authorDavid Corrales2007-07-08 16:58:54 +0000
committerDavid Corrales2007-07-08 16:58:54 +0000
commit9bfe5d53540af7dc9bf0214202f4e35b272320ea (patch)
tree69dcaf6f735e9fd0913a3e2f163852d4b9af87e3 /engines
parent256e4d9521b79160d1f9ed670656097a96dc5a34 (diff)
parent17da12ca07a1f18f3fe1ef5b0c2c0cd9fd8359b4 (diff)
downloadscummvm-rg350-9bfe5d53540af7dc9bf0214202f4e35b272320ea.tar.gz
scummvm-rg350-9bfe5d53540af7dc9bf0214202f4e35b272320ea.tar.bz2
scummvm-rg350-9bfe5d53540af7dc9bf0214202f4e35b272320ea.zip
Merged the FSNode branch with trunk r27681:27969
svn-id: r27970
Diffstat (limited to 'engines')
-rw-r--r--engines/agi/agi.cpp2
-rw-r--r--engines/agi/agi.h12
-rw-r--r--engines/agi/cycle.cpp21
-rw-r--r--engines/agi/graphics.cpp161
-rw-r--r--engines/agi/graphics.h3
-rw-r--r--engines/agi/keyboard.cpp14
-rw-r--r--engines/agi/op_cmd.cpp12
-rw-r--r--engines/agi/picture.cpp4
-rw-r--r--engines/agi/saveload.cpp63
-rw-r--r--engines/agi/sprite.cpp13
-rw-r--r--engines/agi/words.cpp2
-rw-r--r--engines/agos/agos.cpp18
-rw-r--r--engines/agos/agos.h10
-rw-r--r--engines/agos/animation.cpp7
-rw-r--r--engines/agos/contain.cpp16
-rw-r--r--engines/agos/debugger.cpp2
-rw-r--r--engines/agos/detection_tables.h2
-rw-r--r--engines/agos/event.cpp5
-rw-r--r--engines/agos/input.cpp62
-rw-r--r--engines/agos/intern.h14
-rw-r--r--engines/agos/items.cpp28
-rw-r--r--engines/agos/menus.cpp4
-rw-r--r--engines/agos/oracle.cpp18
-rw-r--r--engines/agos/res.cpp54
-rw-r--r--engines/agos/rooms.cpp22
-rw-r--r--engines/agos/saveload.cpp54
-rw-r--r--engines/agos/script.cpp16
-rw-r--r--engines/agos/script_e1.cpp24
-rw-r--r--engines/agos/script_e2.cpp38
-rw-r--r--engines/agos/script_ff.cpp2
-rw-r--r--engines/agos/script_s1.cpp26
-rw-r--r--engines/agos/script_s2.cpp2
-rw-r--r--engines/agos/script_ww.cpp9
-rw-r--r--engines/agos/string.cpp10
-rw-r--r--engines/agos/vga.cpp53
-rw-r--r--engines/agos/vga.h16
-rw-r--r--engines/cine/various.cpp5
-rw-r--r--engines/cruise/saveload.cpp4
-rw-r--r--engines/engine.cpp23
-rw-r--r--engines/engine.h48
-rw-r--r--engines/gob/detection.cpp20
-rw-r--r--engines/gob/game.h16
-rw-r--r--engines/gob/goblin.h6
-rw-r--r--engines/gob/imd.h4
-rw-r--r--engines/gob/inter_v1.cpp7
-rw-r--r--engines/gob/map.h4
-rw-r--r--engines/gob/mult.h22
-rw-r--r--engines/gob/music.cpp6
-rw-r--r--engines/gob/saveload_v3.cpp5
-rw-r--r--engines/gob/scenery.h10
-rw-r--r--engines/gob/sound.cpp30
-rw-r--r--engines/gob/sound.h6
-rw-r--r--engines/gob/video.cpp2
-rw-r--r--engines/gob/video.h2
-rw-r--r--engines/kyra/gui.cpp6
-rw-r--r--engines/kyra/kyra.cpp24
-rw-r--r--engines/kyra/resource.cpp29
-rw-r--r--engines/kyra/scene.cpp10
-rw-r--r--engines/kyra/screen.cpp7
-rw-r--r--engines/kyra/script.cpp12
-rw-r--r--engines/kyra/script.h10
-rw-r--r--engines/kyra/script_v1.cpp4
-rw-r--r--engines/kyra/sound_digital.cpp2
-rw-r--r--engines/lure/res_struct.h40
-rw-r--r--engines/parallaction/animation.cpp10
-rw-r--r--engines/parallaction/archive.cpp8
-rw-r--r--engines/parallaction/callables.cpp2
-rw-r--r--engines/parallaction/defs.h1
-rw-r--r--engines/parallaction/dialogue.cpp343
-rw-r--r--engines/parallaction/disk.cpp123
-rw-r--r--engines/parallaction/disk.h11
-rw-r--r--engines/parallaction/graphics.cpp47
-rw-r--r--engines/parallaction/graphics.h9
-rw-r--r--engines/parallaction/location.cpp25
-rw-r--r--engines/parallaction/menu.cpp10
-rw-r--r--engines/parallaction/parallaction.cpp14
-rw-r--r--engines/parallaction/parallaction.h47
-rw-r--r--engines/parallaction/parser.cpp81
-rw-r--r--engines/parallaction/parser.h2
-rw-r--r--engines/parallaction/saveload.cpp32
-rw-r--r--engines/parallaction/zone.cpp31
-rw-r--r--engines/parallaction/zone.h7
-rw-r--r--engines/saga/actor.cpp13
-rw-r--r--engines/saga/actor.h3
-rw-r--r--engines/saga/animation.cpp12
-rw-r--r--engines/saga/detection_tables.h399
-rw-r--r--engines/saga/events.cpp1
-rw-r--r--engines/saga/gfx.h2
-rw-r--r--engines/saga/interface.cpp1
-rw-r--r--engines/saga/music.cpp58
-rw-r--r--engines/saga/music.h3
-rw-r--r--engines/saga/render.cpp6
-rw-r--r--engines/saga/render.h2
-rw-r--r--engines/saga/saga.h20
-rw-r--r--engines/saga/scene.cpp2
-rw-r--r--engines/saga/script.h2
-rw-r--r--engines/saga/sfuncs.cpp96
-rw-r--r--engines/saga/sndres.cpp42
-rw-r--r--engines/saga/sound.cpp35
-rw-r--r--engines/saga/sound.h8
-rw-r--r--engines/scumm/akos.cpp4
-rw-r--r--engines/scumm/base-costume.h2
-rw-r--r--engines/scumm/boxes.cpp2
-rw-r--r--engines/scumm/detection.cpp21
-rw-r--r--engines/scumm/dialogs.cpp32
-rw-r--r--engines/scumm/dialogs.h14
-rw-r--r--engines/scumm/file.cpp3
-rw-r--r--engines/scumm/he/intern_he.h2
-rw-r--r--engines/scumm/he/resource_he.h40
-rw-r--r--engines/scumm/imuse/instrument.cpp8
-rw-r--r--engines/scumm/input.cpp150
-rw-r--r--engines/scumm/intern.h4
-rw-r--r--engines/scumm/module.mk6
-rw-r--r--engines/scumm/object.h6
-rw-r--r--engines/scumm/player_v2.h2
-rw-r--r--engines/scumm/saveload.cpp7
-rw-r--r--engines/scumm/script.cpp32
-rw-r--r--engines/scumm/scumm-md5.h5
-rw-r--r--engines/scumm/scumm.cpp48
-rw-r--r--engines/scumm/scumm.h20
-rw-r--r--engines/scumm/smush/codec47.cpp19
-rw-r--r--engines/scumm/smush/codec47ARM.s372
-rw-r--r--engines/scumm/verbs.cpp14
-rw-r--r--engines/scumm/verbs.h12
-rw-r--r--engines/sky/music/mt32music.cpp4
-rw-r--r--engines/sky/sound.cpp4
-rw-r--r--engines/sky/struc.h8
-rw-r--r--engines/sword1/control.cpp9
-rw-r--r--engines/sword1/mouse.h2
-rw-r--r--engines/sword1/object.h10
-rw-r--r--engines/sword1/router.h4
-rw-r--r--engines/sword1/sound.cpp30
-rw-r--r--engines/sword1/sound.h3
-rw-r--r--engines/sword1/staticres.cpp2
-rw-r--r--engines/sword1/sword1.cpp20
-rw-r--r--engines/sword1/sworddefs.h10
-rw-r--r--engines/touche/ui.cpp10
137 files changed, 2526 insertions, 1106 deletions
diff --git a/engines/agi/agi.cpp b/engines/agi/agi.cpp
index 74795271fc..0839b7de99 100644
--- a/engines/agi/agi.cpp
+++ b/engines/agi/agi.cpp
@@ -334,7 +334,7 @@ void AgiEngine::replayImageStackCall(uint8 type, int16 p1, int16 p2, int16 p3,
case ADD_PIC:
debugC(8, kDebugLevelMain, "--- decoding picture %d ---", p1);
agiLoadResource(rPICTURE, p1);
- _picture->decodePicture(p1, p2);
+ _picture->decodePicture(p1, p2, p3 != 0);
break;
case ADD_VIEW:
agiLoadResource(rVIEW, p1);
diff --git a/engines/agi/agi.h b/engines/agi/agi.h
index 56ae1288b8..01db2acb23 100644
--- a/engines/agi/agi.h
+++ b/engines/agi/agi.h
@@ -247,6 +247,18 @@ enum {
};
/**
+ * Different monitor types.
+ * Used with AGI variable 26 i.e. vMonitor.
+ */
+enum AgiMonitorType {
+ kAgiMonitorCga = 0,
+ // kAgiMonitorTandy = 1, // Not sure about this
+ kAgiMonitorHercules = 2,
+ kAgiMonitorEga = 3
+ // kAgiMonitorVga = 4 // Not sure about this
+};
+
+/**
* AGI flags
*/
enum {
diff --git a/engines/agi/cycle.cpp b/engines/agi/cycle.cpp
index 22d2582021..bd8fcb0394 100644
--- a/engines/agi/cycle.cpp
+++ b/engines/agi/cycle.cpp
@@ -367,7 +367,26 @@ int AgiEngine::runGame() {
setvar(vComputer, 0); /* IBM PC (4 = Atari ST) */
setvar(vSoundgen, 1); /* IBM PC SOUND */
- setvar(vMonitor, 0x3); /* EGA monitor */
+
+ // Set monitor type (v26 i.e. vMonitor)
+ switch (_renderMode) {
+ case Common::kRenderCGA:
+ setvar(vMonitor, kAgiMonitorCga);
+ break;
+ case Common::kRenderHercG:
+ case Common::kRenderHercA:
+ setvar(vMonitor, kAgiMonitorHercules);
+ break;
+ // Don't know if Amiga AGI games use a different value than kAgiMonitorEga
+ // for vMonitor so I just use kAgiMonitorEga for them (As was done before too).
+ case Common::kRenderAmiga:
+ case Common::kRenderDefault:
+ case Common::kRenderEGA:
+ default:
+ setvar(vMonitor, kAgiMonitorEga);
+ break;
+ }
+
setvar(vMaxInputChars, 38);
_game.inputMode = INPUT_NONE;
_game.inputEnabled = 0;
diff --git a/engines/agi/graphics.cpp b/engines/agi/graphics.cpp
index 2d64a4352e..54f1783d83 100644
--- a/engines/agi/graphics.cpp
+++ b/engines/agi/graphics.cpp
@@ -624,8 +624,7 @@ int GfxMgr::keypress() {
/**
* Initialize the color palette
* This function initializes the color palette using the specified 16-color
- * RGB palette and creates 16 extra palette entries with translucent colors
- * for the interpreter console.
+ * RGB palette.
* @param p A pointer to the 16-color RGB palette.
*/
void GfxMgr::initPalette(uint8 *p) {
@@ -633,7 +632,6 @@ void GfxMgr::initPalette(uint8 *p) {
for (i = 0; i < 48; i++) {
_palette[i] = p[i];
- _palette[i + 48] = (p[i] + 0x30) >> 2;
}
}
@@ -642,13 +640,13 @@ void GfxMgr::gfxSetPalette() {
byte pal[256 * 4];
if (!(_vm->getFeatures() & (GF_AGI256 | GF_AGI256_2))) {
- for (i = 0; i < 32; i++) {
+ for (i = 0; i < 16; i++) {
pal[i * 4 + 0] = _palette[i * 3 + 0] << 2;
pal[i * 4 + 1] = _palette[i * 3 + 1] << 2;
pal[i * 4 + 2] = _palette[i * 3 + 2] << 2;
pal[i * 4 + 3] = 0;
}
- g_system->setPalette(pal, 0, 32);
+ g_system->setPalette(pal, 0, 16);
} else {
for (i = 0; i < 256; i++) {
pal[i * 4 + 0] = vgaPalette[i * 3 + 0];
@@ -715,19 +713,107 @@ void GfxMgr::gfxPutBlock(int x1, int y1, int x2, int y2) {
g_system->copyRectToScreen(_screen + y1 * 320 + x1, 320, x1, y1, x2 - x1 + 1, y2 - y1 + 1);
}
-static const byte mouseCursorArrow[] = {
- // This is the same arrow cursor that was later used in early SCI games
- 0x00, 0x00, 0x40, 0x00, 0x60, 0x00, 0x70, 0x00,
- 0x78, 0x00, 0x7C, 0x00, 0x7E, 0x00, 0x7F, 0x00,
- 0x7F, 0x80, 0x7F, 0xC0, 0x7C, 0x00, 0x46, 0x00,
- 0x06, 0x00, 0x03, 0x00, 0x03, 0x00, 0x01, 0x80,
- 0xC0, 0x00, 0xA0, 0x00, 0x90, 0x00, 0x88, 0x00,
- 0x84, 0x00, 0x82, 0x00, 0x81, 0x00, 0x80, 0x80,
- 0x80, 0x40, 0x80, 0x20, 0x82, 0x00, 0xA9, 0x00,
- 0xC9, 0x00, 0x04, 0x80, 0x04, 0x80, 0x02, 0x40
+/**
+ * A black and white SCI-style arrow cursor (11x16).
+ * 0 = Transparent.
+ * 1 = Black (#000000 in 24-bit RGB).
+ * 2 = White (#FFFFFF in 24-bit RGB).
+ */
+static const byte sciMouseCursor[] = {
+ 1,1,0,0,0,0,0,0,0,0,0,
+ 1,2,1,0,0,0,0,0,0,0,0,
+ 1,2,2,1,0,0,0,0,0,0,0,
+ 1,2,2,2,1,0,0,0,0,0,0,
+ 1,2,2,2,2,1,0,0,0,0,0,
+ 1,2,2,2,2,2,1,0,0,0,0,
+ 1,2,2,2,2,2,2,1,0,0,0,
+ 1,2,2,2,2,2,2,2,1,0,0,
+ 1,2,2,2,2,2,2,2,2,1,0,
+ 1,2,2,2,2,2,2,2,2,2,1,
+ 1,2,2,2,2,2,1,0,0,0,0,
+ 1,2,1,0,1,2,2,1,0,0,0,
+ 1,1,0,0,1,2,2,1,0,0,0,
+ 0,0,0,0,0,1,2,2,1,0,0,
+ 0,0,0,0,0,1,2,2,1,0,0,
+ 0,0,0,0,0,0,1,2,2,1,0
+};
+
+/**
+ * RGBA-palette for the black and white SCI-style arrow cursor.
+ */
+static const byte sciMouseCursorPalette[] = {
+ 0x00, 0x00, 0x00, 0x00, // Black
+ 0xFF, 0xFF, 0xFF, 0x00 // White
+};
+
+/**
+ * An Amiga-style arrow cursor (8x11).
+ * 0 = Transparent.
+ * 1 = Black (#000000 in 24-bit RGB).
+ * 2 = Red (#DE2021 in 24-bit RGB).
+ * 3 = Light red (#FFCFAD in 24-bit RGB).
+ */
+static const byte amigaMouseCursor[] = {
+ 2,3,1,0,0,0,0,0,
+ 2,2,3,1,0,0,0,0,
+ 2,2,2,3,1,0,0,0,
+ 2,2,2,2,3,1,0,0,
+ 2,2,2,2,2,3,1,0,
+ 2,2,2,2,2,2,3,1,
+ 2,0,2,2,3,1,0,0,
+ 0,0,0,2,3,1,0,0,
+ 0,0,0,2,2,3,1,0,
+ 0,0,0,0,2,3,1,0,
+ 0,0,0,0,2,2,3,1
+};
+
+/**
+ * RGBA-palette for the Amiga-style arrow cursor
+ * and the Amiga-style busy cursor.
+ */
+static const byte amigaMouseCursorPalette[] = {
+ 0x00, 0x00, 0x00, 0x00, // Black
+ 0xDE, 0x20, 0x21, 0x00, // Red
+ 0xFF, 0xCF, 0xAD, 0x00 // Light red
};
/**
+ * An Amiga-style busy cursor showing an hourglass (13x16).
+ * 0 = Transparent.
+ * 1 = Black (#000000 in 24-bit RGB).
+ * 2 = Red (#DE2021 in 24-bit RGB).
+ * 3 = Light red (#FFCFAD in 24-bit RGB).
+ */
+static const byte busyAmigaMouseCursor[] = {
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,
+ 1,2,2,2,2,2,2,2,2,2,2,2,1,
+ 1,2,2,2,2,2,2,2,2,2,2,2,1,
+ 0,1,3,3,3,3,3,3,3,3,3,1,0,
+ 0,0,1,3,3,3,3,3,3,3,1,0,0,
+ 0,0,0,1,3,3,3,3,3,1,0,0,0,
+ 0,0,0,0,1,3,3,3,1,0,0,0,0,
+ 0,0,0,0,0,1,3,1,0,0,0,0,0,
+ 0,0,0,0,0,1,3,1,0,0,0,0,0,
+ 0,0,0,0,1,2,3,2,1,0,0,0,0,
+ 0,0,0,1,2,2,3,2,2,1,0,0,0,
+ 0,0,1,2,2,2,3,2,2,2,1,0,0,
+ 0,1,2,2,2,3,3,3,2,2,2,1,0,
+ 1,3,3,3,3,3,3,3,3,3,3,3,1,
+ 1,3,3,3,3,3,3,3,3,3,3,3,1,
+ 1,1,1,1,1,1,1,1,1,1,1,1,1
+};
+
+void GfxMgr::setCursor(bool amigaStyleCursor) {
+ if (!amigaStyleCursor) {
+ CursorMan.replaceCursorPalette(sciMouseCursorPalette, 1, ARRAYSIZE(sciMouseCursorPalette) / 4);
+ CursorMan.replaceCursor(sciMouseCursor, 11, 16, 1, 1, 0);
+ } else { // amigaStyleCursor
+ CursorMan.replaceCursorPalette(amigaMouseCursorPalette, 1, ARRAYSIZE(amigaMouseCursorPalette) / 4);
+ CursorMan.replaceCursor(amigaMouseCursor, 8, 11, 1, 1, 0);
+ }
+}
+
+/**
* Initialize graphics device.
*
* @see deinit_video()
@@ -743,31 +829,7 @@ int GfxMgr::initVideo() {
gfxSetPalette();
- byte mouseCursor[16 * 16];
- const byte *src = mouseCursorArrow;
- for (int i = 0; i < 32; ++i) {
- int offs = i * 8;
- for (byte mask = 0x80; mask != 0; mask >>= 1) {
- if (src[0] & mask) {
- mouseCursor[offs] = 2;
- } else if (src[32] & mask) {
- mouseCursor[offs] = 0;
- } else {
- mouseCursor[offs] = 0xFF;
- }
- ++offs;
- }
- ++src;
- }
-
- const byte cursorPalette[] = {
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 255, 255, 255, 0
- };
-
- CursorMan.replaceCursorPalette(cursorPalette, 0, 3);
- CursorMan.replaceCursor(mouseCursor, 16, 16, 1, 1);
+ setCursor(_vm->_renderMode == Common::kRenderAmiga);
return errOK;
}
@@ -804,23 +866,26 @@ int GfxMgr::deinitMachine() {
* @param x x coordinate of the row start (AGI coord.)
* @param y y coordinate of the row start (AGI coord.)
* @param n number of pixels in the row
- * @param p pointer to the row start in the AGI screen
+ * @param p pointer to the row start in the AGI screen (Always use sbuf16c as base, not sbuf256c)
+ * FIXME: CGA rendering doesn't work correctly with AGI256 or AGI256-2.
*/
void GfxMgr::putPixelsA(int x, int y, int n, uint8 *p) {
+ const uint rShift = _vm->_debug.priority ? 4 : 0; // Priority information is in the top 4 bits of a byte taken from sbuf16c.
+
+ // Choose the correct screen to read from. If AGI256 or AGI256-2 is used and we're not trying to show the priority information,
+ // then choose the 256 color screen, otherwise choose the 16 color screen (Which also has the priority information).
+ p += _vm->getFeatures() & (GF_AGI256 | GF_AGI256_2) && !_vm->_debug.priority ? FROM_SBUF16_TO_SBUF256_OFFSET : 0;
+
if (_vm->_renderMode == Common::kRenderCGA) {
for (x *= 2; n--; p++, x += 2) {
register uint16 q = (cgaMap[(*p & 0xf0) >> 4] << 4) | cgaMap[*p & 0x0f];
- if (_vm->_debug.priority)
- q >>= 4;
- *(uint16 *)&_agiScreen[x + y * GFX_WIDTH] = q & 0x0f0f;
+ *(uint16 *)&_agiScreen[x + y * GFX_WIDTH] = (q >> rShift) & 0x0f0f;
}
} else {
- const uint16 mask = _vm->getFeatures() & (GF_AGI256 | GF_AGI256_2) ? 0xffff : 0x0f0f;
+ const uint16 mask = _vm->getFeatures() & (GF_AGI256 | GF_AGI256_2) && !_vm->_debug.priority ? 0xffff : 0x0f0f;
for (x *= 2; n--; p++, x += 2) {
register uint16 q = ((uint16) * p << 8) | *p;
- if (_vm->_debug.priority)
- q >>= 4;
- *(uint16 *)&_agiScreen[x + y * GFX_WIDTH] = q & mask;
+ *(uint16 *)&_agiScreen[x + y * GFX_WIDTH] = (q >> rShift) & mask;
}
}
}
diff --git a/engines/agi/graphics.h b/engines/agi/graphics.h
index cdbae8d6e6..b1f9c0e1d7 100644
--- a/engines/agi/graphics.h
+++ b/engines/agi/graphics.h
@@ -41,7 +41,7 @@ class GfxMgr {
private:
AgiEngine *_vm;
- uint8 _palette[32 * 3];
+ uint8 _palette[16 * 3];
uint8 *_agiScreen;
unsigned char *_screen;
@@ -87,6 +87,7 @@ public:
void putPixel(int, int, int);
void putBlock(int x1, int y1, int x2, int y2);
void gfxSetPalette();
+ void setCursor(bool amigaStyleCursor = false);
int keypress();
int getKey();
diff --git a/engines/agi/keyboard.cpp b/engines/agi/keyboard.cpp
index 17865e1f3a..3acc81ddff 100644
--- a/engines/agi/keyboard.cpp
+++ b/engines/agi/keyboard.cpp
@@ -29,6 +29,9 @@
#include "agi/graphics.h"
#include "agi/keyboard.h"
#include "agi/menu.h"
+#ifdef __DS__
+#include "wordcompletion.h"
+#endif
namespace Agi {
@@ -308,6 +311,9 @@ void AgiEngine::handleKeys(int key) {
debugC(3, kDebugLevelInput, "clear lines");
clearLines(l, l + 1, bg);
flushLines(l, l + 1);
+#ifdef __DS__
+ DS::findWordCompletions((char *) _game.inputBuffer);
+#endif
break;
case KEY_ESCAPE:
@@ -324,6 +330,10 @@ void AgiEngine::handleKeys(int key) {
_game.inputBuffer[--_game.cursorPos] = 0;
/* Print cursor */
_gfx->printCharacter(_game.cursorPos + 1, l, _game.cursorChar, fg, bg);
+
+#ifdef __DS__
+ DS::findWordCompletions((char *) _game.inputBuffer);
+#endif
break;
default:
/* Ignore invalid keystrokes */
@@ -337,6 +347,10 @@ void AgiEngine::handleKeys(int key) {
_game.inputBuffer[_game.cursorPos++] = key;
_game.inputBuffer[_game.cursorPos] = 0;
+#ifdef __DS__
+ DS::findWordCompletions((char *) _game.inputBuffer);
+#endif
+
/* echo */
_gfx->printCharacter(_game.cursorPos, l, _game.inputBuffer[_game.cursorPos - 1], fg, bg);
diff --git a/engines/agi/op_cmd.cpp b/engines/agi/op_cmd.cpp
index c51514f237..588ee1dd30 100644
--- a/engines/agi/op_cmd.cpp
+++ b/engines/agi/op_cmd.cpp
@@ -153,6 +153,18 @@ cmd(toggle_v) {
cmd(new_room) {
g_agi->newRoom(p0);
+
+ // WORKAROUND: Works around intro skipping bug (#1737343) in Gold Rush.
+ // Intro was skipped because the enter-keypress finalizing the entering
+ // of the copy protection string (Copy protection is in logic.128) was
+ // left over to the intro scene (Starts with room 73 i.e. logic.073).
+ // The intro scene checks for any keys pressed and if it finds any it
+ // jumps to the game's start (Room 1 i.e. logic.001). We clear the
+ // keyboard buffer when the intro sequence's first room (Room 73) is
+ // loaded so that no keys from the copy protection scene can be left
+ // over to cause the intro to skip to the game's start.
+ if (g_agi->getGameID() == GID_GOLDRUSH && p0 == 73)
+ game.keypress = 0;
}
cmd(new_room_f) {
diff --git a/engines/agi/picture.cpp b/engines/agi/picture.cpp
index cd8ef83de0..144e965465 100644
--- a/engines/agi/picture.cpp
+++ b/engines/agi/picture.cpp
@@ -652,7 +652,7 @@ int PictureMgr::decodePicture(int n, int clear, bool agi256) {
if (clear)
_vm->clearImageStack();
- _vm->recordImageStackCall(ADD_PIC, n, clear, 0, 0, 0, 0, 0);
+ _vm->recordImageStackCall(ADD_PIC, n, clear, agi256, 0, 0, 0, 0);
return errOK;
}
@@ -686,7 +686,7 @@ void PictureMgr::showPic() {
i = 0;
offset = _vm->_game.lineMinPrint * CHAR_LINES;
for (y = 0; y < _HEIGHT; y++) {
- _gfx->putPixelsA(0, y + offset, _WIDTH, &_vm->_game.sbuf[i]);
+ _gfx->putPixelsA(0, y + offset, _WIDTH, &_vm->_game.sbuf16c[i]);
i += _WIDTH;
}
diff --git a/engines/agi/saveload.cpp b/engines/agi/saveload.cpp
index ab5f818d17..9144dae96c 100644
--- a/engines/agi/saveload.cpp
+++ b/engines/agi/saveload.cpp
@@ -519,41 +519,48 @@ int AgiEngine::selectSlot() {
_gfx->drawButton(buttonX[i], buttonY, buttonText[i], 0, 0, MSG_BOX_TEXT, MSG_BOX_COLOUR);
AllowSyntheticEvents on(this);
+ int oldFirstSlot = _firstSlot + 1;
+ int oldActive = active + 1;
for (;;) {
- char dstr[64];
- for (i = 0; i < NUM_VISIBLE_SLOTS; i++) {
- sprintf(dstr, "[%2d. %-28.28s]", i + _firstSlot, desc[i]);
- printText(dstr, 0, hm + 1, vm + 4 + i,
- (40 - 2 * hm) - 1, i == active ? MSG_BOX_COLOUR : MSG_BOX_TEXT,
- i == active ? MSG_BOX_TEXT : MSG_BOX_COLOUR);
- }
+ int sbPos;
- char upArrow[] = "^";
- char downArrow[] = "v";
- char scrollBar[] = " ";
+ if (oldFirstSlot != _firstSlot || oldActive != active) {
+ char dstr[64];
+ for (i = 0; i < NUM_VISIBLE_SLOTS; i++) {
+ sprintf(dstr, "[%2d. %-28.28s]", i + _firstSlot, desc[i]);
+ printText(dstr, 0, hm + 1, vm + 4 + i,
+ (40 - 2 * hm) - 1, i == active ? MSG_BOX_COLOUR : MSG_BOX_TEXT,
+ i == active ? MSG_BOX_TEXT : MSG_BOX_COLOUR);
+ }
- int sbPos;
+ char upArrow[] = "^";
+ char downArrow[] = "v";
+ char scrollBar[] = " ";
+
+ // Use the extreme scrollbar positions only if the
+ // extreme slots are in sight.
+
+ if (_firstSlot == 0)
+ sbPos = 1;
+ else if (_firstSlot == NUM_SLOTS - NUM_VISIBLE_SLOTS)
+ sbPos = NUM_VISIBLE_SLOTS - 2;
+ else {
+ sbPos = 2 + (_firstSlot * (NUM_VISIBLE_SLOTS - 4)) / (NUM_SLOTS - NUM_VISIBLE_SLOTS - 1);
+ if (sbPos >= NUM_VISIBLE_SLOTS - 3)
+ sbPos = NUM_VISIBLE_SLOTS - 3;
+ }
- // Use the extreme scrollbar positions only if the extreme
- // slots are in sight.
-
- if (_firstSlot == 0)
- sbPos = 1;
- else if (_firstSlot == NUM_SLOTS - NUM_VISIBLE_SLOTS)
- sbPos = NUM_VISIBLE_SLOTS - 2;
- else {
- sbPos = 2 + (_firstSlot * (NUM_VISIBLE_SLOTS - 4)) / (NUM_SLOTS - NUM_VISIBLE_SLOTS - 1);
- if (sbPos >= NUM_VISIBLE_SLOTS - 3)
- sbPos = NUM_VISIBLE_SLOTS - 3;
- }
+ for (i = 1; i < NUM_VISIBLE_SLOTS - 1; i++)
+ printText(scrollBar, 35, hm + 1, vm + 4 + i, 1, MSG_BOX_COLOUR, 7, true);
- for (i = 1; i < NUM_VISIBLE_SLOTS - 1; i++)
- printText(scrollBar, 35, hm + 1, vm + 4 + i, 1, MSG_BOX_COLOUR, 7, true);
+ printText(upArrow, 35, hm + 1, vm + 4, 1, 8, 7);
+ printText(downArrow, 35, hm + 1, vm + 4 + NUM_VISIBLE_SLOTS - 1, 1, 8, 7);
+ printText(scrollBar, 35, hm + 1, vm + 4 + sbPos, 1, MSG_BOX_COLOUR, MSG_BOX_TEXT);
- printText(upArrow, 35, hm + 1, vm + 4, 1, 8, 7);
- printText(downArrow, 35, hm + 1, vm + 4 + NUM_VISIBLE_SLOTS - 1, 1, 8, 7);
- printText(scrollBar, 35, hm + 1, vm + 4 + sbPos, 1, MSG_BOX_COLOUR, MSG_BOX_TEXT);
+ oldActive = active;
+ oldFirstSlot = _firstSlot;
+ }
_gfx->pollTimer(); /* msdos driver -> does nothing */
key = doPollKeyboard();
diff --git a/engines/agi/sprite.cpp b/engines/agi/sprite.cpp
index 3d69968075..006e3dddee 100644
--- a/engines/agi/sprite.cpp
+++ b/engines/agi/sprite.cpp
@@ -215,7 +215,8 @@ void SpritesMgr::objsRestoreArea(Sprite *s) {
int y, offset;
int16 xPos = s->xPos, yPos = s->yPos;
int16 xSize = s->xSize, ySize = s->ySize;
- uint8 *p0, *q;
+ uint8 *q;
+ uint32 pos0;
if (xPos + xSize > _WIDTH)
xSize = _WIDTH - xPos;
@@ -236,14 +237,14 @@ void SpritesMgr::objsRestoreArea(Sprite *s) {
if (xSize <= 0 || ySize <= 0)
return;
- p0 = &_vm->_game.sbuf[xPos + yPos * _WIDTH];
+ pos0 = xPos + yPos * _WIDTH;
q = s->buffer;
offset = _vm->_game.lineMinPrint * CHAR_LINES;
for (y = 0; y < ySize; y++) {
- memcpy(p0, q, xSize);
- _gfx->putPixelsA(xPos, yPos + y + offset, xSize, p0);
+ memcpy(&_vm->_game.sbuf[pos0], q, xSize);
+ _gfx->putPixelsA(xPos, yPos + y + offset, xSize, &_vm->_game.sbuf16c[pos0]);
q += xSize;
- p0 += _WIDTH;
+ pos0 += _WIDTH;
}
}
@@ -728,7 +729,7 @@ void SpritesMgr::commitBlock(int x1, int y1, int x2, int y2) {
debugC(7, kDebugLevelSprites, "%d, %d, %d, %d", x1, y1, x2, y2);
w = x2 - x1 + 1;
- q = &_vm->_game.sbuf[x1 + _WIDTH * y1];
+ q = &_vm->_game.sbuf16c[x1 + _WIDTH * y1];
offset = _vm->_game.lineMinPrint * CHAR_LINES;
for (i = y1; i <= y2; i++) {
_gfx->putPixelsA(x1, i + offset, w, q);
diff --git a/engines/agi/words.cpp b/engines/agi/words.cpp
index 5fc3c3bca9..ed33b9463a 100644
--- a/engines/agi/words.cpp
+++ b/engines/agi/words.cpp
@@ -88,7 +88,7 @@ void AgiEngine::unloadWords() {
* Uses an algorithm hopefully like the one Sierra used. Returns the ID
* of the word and the length in flen. Returns -1 if not found.
*
- * Thomas Åkesson, November 2001
+ * Thomas Akesson, November 2001
*/
int AgiEngine::findWord(char *word, int *flen) {
int mchr = 0; /* matched chars */
diff --git a/engines/agos/agos.cpp b/engines/agos/agos.cpp
index c98257f028..ae7f692c3f 100644
--- a/engines/agos/agos.cpp
+++ b/engines/agos/agos.cpp
@@ -110,8 +110,6 @@ AGOSEngine::AGOSEngine(OSystem *syst)
_debugger = 0;
- _keyPressed = 0;
-
_gameFile = 0;
_opcode = 0;
@@ -746,10 +744,12 @@ void AGOSEngine_Simon2::setupGame() {
_tableIndexBase = 1580 / 4;
_textIndexBase = 1500 / 4;
_numVideoOpcodes = 75;
-#ifndef PALMOS_68K
- _vgaMemSize = 2000000;
-#else
+#if defined(__DS__)
+ _vgaMemSize = 1300000;
+#elif defined(PALMOS_68K)
_vgaMemSize = gVars->memory[kMemSimon2Games];
+#else
+ _vgaMemSize = 2000000;
#endif
_itemMemSize = 20000;
_tableMemSize = 100000;
@@ -958,8 +958,8 @@ GUI::Debugger *AGOSEngine::getDebugger() {
}
void AGOSEngine::pause() {
- _keyPressed = 1;
- _pause = 1;
+ _keyPressed.reset();
+ _pause = true;
bool ambient_status = _ambientPaused;
bool music_status = _musicPaused;
@@ -969,8 +969,8 @@ void AGOSEngine::pause() {
while (_pause) {
delay(1);
- if (_keyPressed == 'p')
- _pause = 0;
+ if (_keyPressed.keycode == Common::KEYCODE_p)
+ _pause = false;
}
_midi.pause(music_status);
diff --git a/engines/agos/agos.h b/engines/agos/agos.h
index e487c38cc7..d233d0bfeb 100644
--- a/engines/agos/agos.h
+++ b/engines/agos/agos.h
@@ -28,6 +28,7 @@
#include "engines/engine.h"
+#include "common/keyboard.h"
#include "common/rect.h"
#include "common/util.h"
@@ -216,7 +217,7 @@ protected:
const GameSpecificSettings *gss;
- byte _keyPressed;
+ Common::KeyState _keyPressed;
Common::File *_gameFile;
@@ -875,8 +876,8 @@ public:
void vc36_setWindowImage();
void vc38_ifVarNotZero();
void vc39_setVar();
- void vc40();
- void vc41();
+ void vc40_scrollRight();
+ void vc41_scrollLeft();
void vc42_delayIfNotEQ();
// Video Script Opcodes, Elvira 1
@@ -1316,7 +1317,9 @@ public:
void oe2_moveDirn();
void oe2_doClass();
void oe2_pObj();
+ void oe2_isCalled();
void oe2_loadGame();
+ void oe2_menu();
void oe2_drawItem();
void oe2_doTable();
void oe2_pauseGame();
@@ -1410,7 +1413,6 @@ public:
void oww_setLongText();
void oww_printLongText();
void oww_whereTo();
- void oww_menu();
void oww_textMenu();
void oww_pauseGame();
void oww_boxMessage();
diff --git a/engines/agos/animation.cpp b/engines/agos/animation.cpp
index 8748cff54e..8d5238259d 100644
--- a/engines/agos/animation.cpp
+++ b/engines/agos/animation.cpp
@@ -130,8 +130,11 @@ void MoviePlayer::play() {
return;
}
- if (!_fd) {
- return;
+ if (_omniTVFile) {
+ // Clear any paused OmniTV video
+ _mixer->stopHandle(_omniTVSound);
+ delete _omniTVFile;
+ _omniTVFile = 0;
}
_leftButtonDown = false;
diff --git a/engines/agos/contain.cpp b/engines/agos/contain.cpp
index b5ca344905..891ac36d30 100644
--- a/engines/agos/contain.cpp
+++ b/engines/agos/contain.cpp
@@ -34,8 +34,8 @@ int AGOSEngine::canPlace(Item *x, Item *y) {
Item *z = derefItem(x->parent);
if (getGameType() == GType_ELVIRA1) {
- SubPlayer *p = (SubPlayer *)findChildOfType(y, 3);
- SubContainer *c = (SubContainer *)findChildOfType(y, 7);
+ SubPlayer *p = (SubPlayer *)findChildOfType(y, kPlayerType);
+ SubContainer *c = (SubContainer *)findChildOfType(y, kContainerType);
int cap = 0;
int wt;
@@ -59,7 +59,7 @@ int AGOSEngine::canPlace(Item *x, Item *y) {
return -2; /* Too heavy */
}
} else {
- SubObject *o = (SubObject *)findChildOfType(y, 2);
+ SubObject *o = (SubObject *)findChildOfType(y, kObjectType);
int ct;
int cap = 0;
@@ -120,11 +120,11 @@ int AGOSEngine::sizeRec(Item *x, int d) {
}
int AGOSEngine::sizeOfRec(Item *i, int d) {
- SubObject *o = (SubObject *)findChildOfType(i, 2);
+ SubObject *o = (SubObject *)findChildOfType(i, kObjectType);
if (getGameType() == GType_ELVIRA1) {
- SubPlayer *p = (SubPlayer *)findChildOfType(i, 3);
- SubContainer *c = (SubContainer *)findChildOfType(i, 7);
+ SubPlayer *p = (SubPlayer *)findChildOfType(i, kPlayerType);
+ SubContainer *c = (SubContainer *)findChildOfType(i, kContainerType);
if ((c) && (c->flags & 1)) {
if (o)
@@ -174,10 +174,10 @@ int AGOSEngine::weightRec(Item *x, int d) {
}
int AGOSEngine::weightOf(Item *x) {
- SubObject *o = (SubObject *)findChildOfType(x, 2);
+ SubObject *o = (SubObject *)findChildOfType(x, kObjectType);
if (getGameType() == GType_ELVIRA1) {
- SubPlayer *p = (SubPlayer *)findChildOfType(x, 3);
+ SubPlayer *p = (SubPlayer *)findChildOfType(x, kPlayerType);
if (o)
return o->objectWeight;
if (p)
diff --git a/engines/agos/debugger.cpp b/engines/agos/debugger.cpp
index ce50460621..3fc5a1f967 100644
--- a/engines/agos/debugger.cpp
+++ b/engines/agos/debugger.cpp
@@ -174,7 +174,7 @@ bool Debugger::Cmd_SetObjectFlag(int argc, const char **argv) {
prop = atoi(argv[2]);
if (obj >= 1 && obj < _vm->_itemArraySize) {
- SubObject *o = (SubObject *)_vm->findChildOfType(_vm->derefItem(obj), 2);
+ SubObject *o = (SubObject *)_vm->findChildOfType(_vm->derefItem(obj), kObjectType);
if (o != NULL) {
if (o->objectFlags & (1 << prop) && prop < 16) {
uint offs = _vm->getOffsetOfChild2Param(o, 1 << prop);
diff --git a/engines/agos/detection_tables.h b/engines/agos/detection_tables.h
index cb6123dc54..5efcaa3b86 100644
--- a/engines/agos/detection_tables.h
+++ b/engines/agos/detection_tables.h
@@ -426,7 +426,7 @@ static const AGOSGameDescription gameDescriptions[] = {
{ "gamepc", GAME_BASEFILE, "4bf28ab00f5324fd938e632595742382", -1},
{ "icon.dat", GAME_ICONFILE, "83a7278bff55c82fbb3aef92981866c9", -1},
{ "menus.dat", GAME_MENUFILE, "a2fdc88a77c8bdffec6b36cbeda4d955", -1},
- { "start", GAME_RESTFILE, "4d380a35ba941d03ee5084c71d20055b", -1},
+ { "start", GAME_RESTFILE, "016107aced82d0cc5d758a9fba716270", -1},
{ "stripped.txt", GAME_STRFILE, "c3a8f644551a27c8a2fec0f8070b46b7", -1},
{ "tbllist", GAME_TBLFILE, "8252660df0edbdbc3e6377e155bbd0c5", -1},
{ NULL, 0, NULL, 0}
diff --git a/engines/agos/event.cpp b/engines/agos/event.cpp
index 32329f34d9..5c673de700 100644
--- a/engines/agos/event.cpp
+++ b/engines/agos/event.cpp
@@ -500,10 +500,7 @@ void AGOSEngine::delay(uint amount) {
}
// Make sure backspace works right (this fixes a small issue on OS X)
- if (event.kbd.keycode == Common::KEYCODE_BACKSPACE)
- _keyPressed = 8;
- else
- _keyPressed = (byte)event.kbd.ascii;
+ _keyPressed = event.kbd;
break;
case Common::EVENT_MOUSEMOVE:
break;
diff --git a/engines/agos/input.cpp b/engines/agos/input.cpp
index ef0791dc10..0f1c234b79 100644
--- a/engines/agos/input.cpp
+++ b/engines/agos/input.cpp
@@ -195,7 +195,8 @@ void AGOSEngine::waitForInput() {
_dragAccept = 1;
for (;;) {
- if ((getGameType() == GType_SIMON1 || getGameType() == GType_SIMON2) && _keyPressed == 35)
+ if ((getGameType() == GType_SIMON1 || getGameType() == GType_SIMON2) &&
+ _keyPressed.keycode == Common::KEYCODE_HASH)
displayBoxStars();
if (processSpecialKeys()) {
if ((getGameType() == GType_PP && getGameId() != GID_DIMP) ||
@@ -238,7 +239,6 @@ void AGOSEngine::waitForInput() {
_dragMode = 0;
_dragCount = 0;
_dragEnd = 0;
- continue;
}
} while (!_dragEnd);
@@ -472,39 +472,39 @@ bool AGOSEngine::processSpecialKeys() {
}
}
- switch (_keyPressed) {
- case 17: // Up
+ switch (_keyPressed.keycode) {
+ case Common::KEYCODE_UP:
if (getGameType() == GType_PP)
_verbHitArea = 302;
else if (getGameType() == GType_WW)
_verbHitArea = 239;
verbCode = true;
break;
- case 18: // Down
+ case Common::KEYCODE_DOWN:
if (getGameType() == GType_PP)
_verbHitArea = 304;
else if (getGameType() == GType_WW)
_verbHitArea = 241;
verbCode = true;
break;
- case 19: // Right
+ case Common::KEYCODE_RIGHT:
if (getGameType() == GType_PP)
_verbHitArea = 303;
else if (getGameType() == GType_WW)
_verbHitArea = 240;
verbCode = true;
break;
- case 20: // Left
+ case Common::KEYCODE_LEFT:
if (getGameType() == GType_PP)
_verbHitArea = 301;
else if (getGameType() == GType_WW)
_verbHitArea = 242;
verbCode = true;
break;
- case 27: // escape
+ case Common::KEYCODE_ESCAPE:
_exitCutscene = true;
break;
- case 59: // F1
+ case Common::KEYCODE_F1:
if (getGameType() == GType_SIMON2) {
vcWriteVar(5, 50);
vcWriteVar(86, 0);
@@ -513,7 +513,7 @@ bool AGOSEngine::processSpecialKeys() {
vcWriteVar(86, 0);
}
break;
- case 60: // F2
+ case Common::KEYCODE_F2:
if (getGameType() == GType_SIMON2) {
vcWriteVar(5, 75);
vcWriteVar(86, 1);
@@ -522,7 +522,7 @@ bool AGOSEngine::processSpecialKeys() {
vcWriteVar(86, 1);
}
break;
- case 61: // F3
+ case Common::KEYCODE_F3:
if (getGameType() == GType_SIMON2) {
vcWriteVar(5, 125);
vcWriteVar(86, 2);
@@ -531,19 +531,19 @@ bool AGOSEngine::processSpecialKeys() {
vcWriteVar(86, 2);
}
break;
- case 63: // F5
+ case Common::KEYCODE_F5:
if (getGameType() == GType_SIMON2 || getGameType() == GType_FF)
_exitCutscene = true;
break;
- case 65: // F7
+ case Common::KEYCODE_F7:
if (getGameType() == GType_FF && getBitFlag(76))
_variableArray[254] = 70;
break;
- case 67: // F9
+ case Common::KEYCODE_F9:
if (getGameType() == GType_FF)
setBitFlag(73, !getBitFlag(73));
break;
- case 37: // F12
+ case Common::KEYCODE_F12:
if (getGameType() == GType_PP && getGameId() != GID_DIMP) {
if (!getBitFlag(110)) {
setBitFlag(107, !getBitFlag(107));
@@ -551,73 +551,77 @@ bool AGOSEngine::processSpecialKeys() {
}
}
break;
- case 'p':
+ case Common::KEYCODE_p:
pause();
break;
- case 't':
+ case Common::KEYCODE_t:
if (getGameType() == GType_FF || (getGameType() == GType_SIMON2 && (getFeatures() & GF_TALKIE)) ||
((getFeatures() & GF_TALKIE) && _language != Common::EN_ANY && _language != Common::DE_DEU)) {
if (_speech)
_subtitles ^= 1;
}
break;
- case 'v':
+ case Common::KEYCODE_v:
if (getGameType() == GType_FF || (getGameType() == GType_SIMON2 && (getFeatures() & GF_TALKIE))) {
if (_subtitles)
_speech ^= 1;
}
- case '+':
+ case Common::KEYCODE_PLUS:
+ case Common::KEYCODE_KP_PLUS:
if (_midiEnabled) {
_midi.setVolume(_midi.getVolume() + 16);
}
_mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, _mixer->getVolumeForSoundType(Audio::Mixer::kMusicSoundType) + 16);
break;
- case '-':
+ case Common::KEYCODE_MINUS:
+ case Common::KEYCODE_KP_MINUS:
if (_midiEnabled) {
_midi.setVolume(_midi.getVolume() - 16);
}
_mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, _mixer->getVolumeForSoundType(Audio::Mixer::kMusicSoundType) - 16);
break;
- case 'm':
+ case Common::KEYCODE_m:
_musicPaused ^= 1;
if (_midiEnabled) {
_midi.pause(_musicPaused);
}
_mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, (_musicPaused) ? 0 : ConfMan.getInt("music_volume"));
break;
- case 's':
+ case Common::KEYCODE_s:
if (getGameId() == GID_SIMON1DOS) {
_midi._enable_sfx ^= 1;
} else {
_sound->effectsPause(_effectsPaused ^= 1);
}
break;
- case 'b':
+ case Common::KEYCODE_b:
_sound->ambientPause(_ambientPaused ^= 1);
break;
- case 'r':
+ case Common::KEYCODE_r:
if (_debugMode)
_startMainScript ^= 1;
break;
- case 'o':
+ case Common::KEYCODE_o:
if (_debugMode)
_continousMainScript ^= 1;
break;
- case 'a':
+ case Common::KEYCODE_a:
if (_debugMode)
_startVgaScript ^= 1;
break;
- case 'g':
+ case Common::KEYCODE_g:
if (_debugMode)
_continousVgaScript ^= 1;
break;
- case 'd':
+ case Common::KEYCODE_d:
if (_debugMode)
_dumpImages ^=1;
break;
+ default:
+ break;
}
- _keyPressed = 0;
+ _keyPressed.reset();
return verbCode;
}
diff --git a/engines/agos/intern.h b/engines/agos/intern.h
index a863dc7c0f..44d38fbeed 100644
--- a/engines/agos/intern.h
+++ b/engines/agos/intern.h
@@ -28,6 +28,20 @@
namespace AGOS {
+enum ChildType {
+ kRoomType = 1,
+ kObjectType = 2,
+ kPlayerType = 3,
+ kGenExitType = 4, // Elvira 1 specific
+ kSuperRoomType = 4, // Elvira 2 specific
+
+ kContainerType = 7,
+ kChainType = 8,
+ kUserFlagType = 9,
+
+ kInheritType = 255
+};
+
struct Child {
Child *next;
uint16 type;
diff --git a/engines/agos/items.cpp b/engines/agos/items.cpp
index a911bee5a5..9a46b6e8ac 100644
--- a/engines/agos/items.cpp
+++ b/engines/agos/items.cpp
@@ -66,7 +66,7 @@ bool AGOSEngine::hasIcon(Item *item) {
if (getGameType() == GType_ELVIRA1) {
return (getUserFlag(item, 7) != 0);
} else {
- SubObject *child = (SubObject *)findChildOfType(item, 2);
+ SubObject *child = (SubObject *)findChildOfType(item, kObjectType);
return (child && (child->objectFlags & kOFIcon) != 0);
}
}
@@ -75,7 +75,7 @@ uint AGOSEngine::itemGetIconNumber(Item *item) {
if (getGameType() == GType_ELVIRA1) {
return getUserFlag(item, 7);
} else {
- SubObject *child = (SubObject *)findChildOfType(item, 2);
+ SubObject *child = (SubObject *)findChildOfType(item, kObjectType);
uint offs;
if (child == NULL || !(child->objectFlags & kOFIcon))
@@ -97,7 +97,7 @@ void AGOSEngine::createPlayer() {
_currentPlayer->adjective = -1;
_currentPlayer->noun = 10000;
- p = (SubPlayer *)allocateChildBlock(_currentPlayer, 3, sizeof(SubPlayer));
+ p = (SubPlayer *)allocateChildBlock(_currentPlayer, kPlayerType, sizeof(SubPlayer));
if (p == NULL)
error("createPlayer: player create failure");
@@ -135,14 +135,14 @@ Child *AGOSEngine::findChildOfType(Item *i, uint type) {
int AGOSEngine::getUserFlag(Item *item, int a) {
SubUserFlag *subUserFlag;
- subUserFlag = (SubUserFlag *) findChildOfType(item, 9);
+ subUserFlag = (SubUserFlag *)findChildOfType(item, kUserFlagType);
if (subUserFlag == NULL)
return 0;
if (a < 0 || a > 7)
return 0;
- return subUserFlag->userFlags[a];
+ return subUserFlag->userFlags[a];
}
int AGOSEngine::getUserFlag1(Item *item, int a) {
@@ -151,7 +151,7 @@ int AGOSEngine::getUserFlag1(Item *item, int a) {
if (item == NULL || item == _dummyItem2 || item == _dummyItem3)
return -1;
- subUserFlag = (SubUserFlag *) findChildOfType(item, 9);
+ subUserFlag = (SubUserFlag *)findChildOfType(item, kUserFlagType);
if (subUserFlag == NULL)
return 0;
@@ -164,9 +164,9 @@ int AGOSEngine::getUserFlag1(Item *item, int a) {
void AGOSEngine::setUserFlag(Item *item, int a, int b) {
SubUserFlag *subUserFlag;
- subUserFlag = (SubUserFlag *) findChildOfType(item, 9);
+ subUserFlag = (SubUserFlag *)findChildOfType(item, kUserFlagType);
if (subUserFlag == NULL) {
- subUserFlag = (SubUserFlag *) allocateChildBlock(item, 9, sizeof(SubUserFlag));
+ subUserFlag = (SubUserFlag *)allocateChildBlock(item, kUserFlagType, sizeof(SubUserFlag));
}
if (a < 0 || a > 7)
@@ -178,7 +178,7 @@ void AGOSEngine::setUserFlag(Item *item, int a, int b) {
int AGOSEngine::getUserItem(Item *item, int n) {
SubUserFlag *subUserFlag;
- subUserFlag = (SubUserFlag *) findChildOfType(item, 9);
+ subUserFlag = (SubUserFlag *)findChildOfType(item, kUserFlagType);
if (subUserFlag == NULL)
return 0;
@@ -191,9 +191,9 @@ int AGOSEngine::getUserItem(Item *item, int n) {
void AGOSEngine::setUserItem(Item *item, int n, int m) {
SubUserFlag *subUserFlag;
- subUserFlag = (SubUserFlag *) findChildOfType(item, 9);
+ subUserFlag = (SubUserFlag *)findChildOfType(item, kUserFlagType);
if (subUserFlag == NULL) {
- subUserFlag = (SubUserFlag *) allocateChildBlock(item, 9, sizeof(SubUserFlag));
+ subUserFlag = (SubUserFlag *)allocateChildBlock(item, kUserFlagType, sizeof(SubUserFlag));
}
if (n == 0)
@@ -201,15 +201,15 @@ void AGOSEngine::setUserItem(Item *item, int n, int m) {
}
bool AGOSEngine::isRoom(Item *item) {
- return findChildOfType(item, 1) != NULL;
+ return findChildOfType(item, kRoomType) != NULL;
}
bool AGOSEngine::isObject(Item *item) {
- return findChildOfType(item, 2) != NULL;
+ return findChildOfType(item, kObjectType) != NULL;
}
bool AGOSEngine::isPlayer(Item *item) {
- return findChildOfType(item, 3) != NULL;
+ return findChildOfType(item, kPlayerType) != NULL;
}
uint AGOSEngine::getOffsetOfChild2Param(SubObject *child, uint prop) {
diff --git a/engines/agos/menus.cpp b/engines/agos/menus.cpp
index 6dd1a356d8..81df34c311 100644
--- a/engines/agos/menus.cpp
+++ b/engines/agos/menus.cpp
@@ -199,7 +199,7 @@ uint AGOSEngine::menuFor_e2(Item *item) {
if (item == NULL || item == _dummyItem2 || item == _dummyItem3)
return 0xFFFF;
- SubObject *subObject = (SubObject *)findChildOfType(item, 2);
+ SubObject *subObject = (SubObject *)findChildOfType(item, kObjectType);
if (subObject != NULL && subObject->objectFlags & kOFMenu) {
uint offs = getOffsetOfChild2Param(subObject, kOFMenu);
return subObject->objectFlagValue[offs];
@@ -216,7 +216,7 @@ uint AGOSEngine::menuFor_ww(Item *item, uint id) {
if (item == NULL || item == _dummyItem2 || item == _dummyItem3)
return _agosMenu;
- SubObject *subObject = (SubObject *)findChildOfType(item, 2);
+ SubObject *subObject = (SubObject *)findChildOfType(item, kObjectType);
if (subObject != NULL && subObject->objectFlags & kOFMenu) {
uint offs = getOffsetOfChild2Param(subObject, kOFMenu);
return subObject->objectFlagValue[offs];
diff --git a/engines/agos/oracle.cpp b/engines/agos/oracle.cpp
index 787596a966..c7ad0ee8b7 100644
--- a/engines/agos/oracle.cpp
+++ b/engines/agos/oracle.cpp
@@ -464,37 +464,37 @@ void AGOSEngine_Feeble::saveUserGame(int slot) {
windowPutChar(window, 0x7f);
for (;;) {
- _keyPressed = 0;
+ _keyPressed.reset();
delay(1);
- if (_keyPressed == 0 || _keyPressed >= 127)
+ if (_keyPressed.ascii == 0 || _keyPressed.ascii >= 127)
continue;
window->textColumn -= getFeebleFontSize(127);
name[len] = 0;
windowBackSpace(_windowArray[3]);
- if (_keyPressed == 27) {
- _variableArray[55] = _keyPressed;
+ if (_keyPressed.keycode == Common::KEYCODE_ESCAPE) {
+ _variableArray[55] = 27;
break;
}
- if (_keyPressed == 10 || _keyPressed == 13) {
+ if (_keyPressed.keycode == Common::KEYCODE_KP_ENTER || _keyPressed.keycode == Common::KEYCODE_RETURN) {
if (!saveGame(readVariable(55), name))
_variableArray[55] = (int16)0xFFFF;
else
_variableArray[55] = 0;
break;
}
- if (_keyPressed == 8 && len != 0) {
+ if (_keyPressed.keycode == Common::KEYCODE_BACKSPACE && len != 0) {
len--;
byte chr = name[len];
window->textColumn -= getFeebleFontSize(chr);
name[len] = 0;
windowBackSpace(_windowArray[3]);
}
- if (_keyPressed >= 32 && window->textColumn + 26 <= window->width) {
- name[len++] = _keyPressed;
- windowPutChar(_windowArray[3], _keyPressed);
+ if (_keyPressed.ascii >= 32 && window->textColumn + 26 <= window->width) {
+ name[len++] = _keyPressed.ascii;
+ windowPutChar(_windowArray[3], _keyPressed.ascii);
}
windowPutChar(window, 0x7f);
diff --git a/engines/agos/res.cpp b/engines/agos/res.cpp
index 394c4956ae..4898cc9a45 100644
--- a/engines/agos/res.cpp
+++ b/engines/agos/res.cpp
@@ -350,13 +350,13 @@ void AGOSEngine::readItemFromGamePc(Common::SeekableReadStream *in, Item *item)
}
void AGOSEngine::readItemChildren(Common::SeekableReadStream *in, Item *item, uint type) {
- if (type == 1) {
- SubRoom *subRoom = (SubRoom *)allocateChildBlock(item, 1, sizeof(SubRoom));
+ if (type == kRoomType) {
+ SubRoom *subRoom = (SubRoom *)allocateChildBlock(item, kRoomType, sizeof(SubRoom));
subRoom->roomShort = in->readUint32BE();
subRoom->roomLong = in->readUint32BE();
subRoom->flags = in->readUint16BE();
- } else if (type == 2) {
- SubObject *subObject = (SubObject *)allocateChildBlock(item, 2, sizeof(SubObject));
+ } else if (type == kObjectType) {
+ SubObject *subObject = (SubObject *)allocateChildBlock(item, kObjectType, sizeof(SubObject));
in->readUint32BE();
in->readUint32BE();
in->readUint32BE();
@@ -364,8 +364,8 @@ void AGOSEngine::readItemChildren(Common::SeekableReadStream *in, Item *item, ui
subObject->objectSize = in->readUint16BE();
subObject->objectWeight = in->readUint16BE();
subObject->objectFlags = in->readUint16BE();
- } else if (type == 4) {
- SubGenExit *genExit = (SubGenExit *)allocateChildBlock(item, 4, sizeof(SubGenExit));
+ } else if (type == kGenExitType) {
+ SubGenExit *genExit = (SubGenExit *)allocateChildBlock(item, kGenExitType, sizeof(SubGenExit));
genExit->dest[0] = (uint16)fileReadItemID(in);
genExit->dest[1] = (uint16)fileReadItemID(in);
genExit->dest[2] = (uint16)fileReadItemID(in);
@@ -378,14 +378,14 @@ void AGOSEngine::readItemChildren(Common::SeekableReadStream *in, Item *item, ui
fileReadItemID(in);
fileReadItemID(in);
fileReadItemID(in);
- } else if (type == 7) {
- SubContainer *container = (SubContainer *)allocateChildBlock(item, 7, sizeof(SubContainer));
+ } else if (type == kContainerType) {
+ SubContainer *container = (SubContainer *)allocateChildBlock(item, kContainerType, sizeof(SubContainer));
container->volume = in->readUint16BE();
container->flags = in->readUint16BE();
- } else if (type == 8) {
- SubChain *chain = (SubChain *)allocateChildBlock(item, 8, sizeof(SubChain));
+ } else if (type == kChainType) {
+ SubChain *chain = (SubChain *)allocateChildBlock(item, kChainType, sizeof(SubChain));
chain->chChained = (uint16)fileReadItemID(in);
- } else if (type == 9) {
+ } else if (type == kUserFlagType) {
setUserFlag(item, 0, in->readUint16BE());
setUserFlag(item, 1, in->readUint16BE());
setUserFlag(item, 2, in->readUint16BE());
@@ -394,13 +394,13 @@ void AGOSEngine::readItemChildren(Common::SeekableReadStream *in, Item *item, ui
setUserFlag(item, 5, in->readUint16BE());
setUserFlag(item, 6, in->readUint16BE());
setUserFlag(item, 7, in->readUint16BE());
- SubUserFlag *subUserFlag = (SubUserFlag *) findChildOfType(item, 9);
+ SubUserFlag *subUserFlag = (SubUserFlag *)findChildOfType(item, kUserFlagType);
subUserFlag->userItems[0] = (uint16)fileReadItemID(in);
fileReadItemID(in);
fileReadItemID(in);
fileReadItemID(in);
- } else if (type == 255) {
- SubInherit *inherit = (SubInherit *)allocateChildBlock(item, 255, sizeof(SubInherit));
+ } else if (type == kInheritType) {
+ SubInherit *inherit = (SubInherit *)allocateChildBlock(item, kInheritType, sizeof(SubInherit));
inherit->inMaster = (uint16)fileReadItemID(in);
} else {
error("readItemChildren: invalid type %d", type);
@@ -408,7 +408,7 @@ void AGOSEngine::readItemChildren(Common::SeekableReadStream *in, Item *item, ui
}
void AGOSEngine_Elvira2::readItemChildren(Common::SeekableReadStream *in, Item *item, uint type) {
- if (type == 1) {
+ if (type == kRoomType) {
uint fr1 = in->readUint16BE();
uint fr2 = in->readUint16BE();
uint i, size;
@@ -420,14 +420,14 @@ void AGOSEngine_Elvira2::readItemChildren(Common::SeekableReadStream *in, Item *
if (j & 3)
size += sizeof(subRoom->roomExit[0]);
- subRoom = (SubRoom *)allocateChildBlock(item, 1, size);
+ subRoom = (SubRoom *)allocateChildBlock(item, kRoomType, size);
subRoom->subroutine_id = fr1;
subRoom->roomExitStates = fr2;
for (i = k = 0, j = fr2; i != 6; i++, j >>= 2)
if (j & 3)
subRoom->roomExit[k++] = (uint16)fileReadItemID(in);
- } else if (type == 2) {
+ } else if (type == kObjectType) {
uint32 fr = in->readUint32BE();
uint i, k, size;
SubObject *subObject;
@@ -437,7 +437,7 @@ void AGOSEngine_Elvira2::readItemChildren(Common::SeekableReadStream *in, Item *
if (fr & (1 << i))
size += sizeof(subObject->objectFlagValue[0]);
- subObject = (SubObject *)allocateChildBlock(item, 2, size);
+ subObject = (SubObject *)allocateChildBlock(item, kObjectType, size);
subObject->objectFlags = fr;
k = 0;
@@ -450,7 +450,7 @@ void AGOSEngine_Elvira2::readItemChildren(Common::SeekableReadStream *in, Item *
if (getGameType() != GType_ELVIRA2)
subObject->objectName = (uint16)in->readUint32BE();
- } else if (type == 4) {
+ } else if (type == kSuperRoomType) {
assert(getGameType() == GType_ELVIRA2);
uint i, j, k, size;
@@ -467,7 +467,7 @@ void AGOSEngine_Elvira2::readItemChildren(Common::SeekableReadStream *in, Item *
for (i = 0; i != j; i++)
size += sizeof(subSuperRoom->roomExitStates[0]);
- subSuperRoom = (SubSuperRoom *)allocateChildBlock(item, 4, size);
+ subSuperRoom = (SubSuperRoom *)allocateChildBlock(item, kSuperRoomType, size);
subSuperRoom->subroutine_id = id;
subSuperRoom->roomX = x;
subSuperRoom->roomY = y;
@@ -475,20 +475,20 @@ void AGOSEngine_Elvira2::readItemChildren(Common::SeekableReadStream *in, Item *
for (i = k = 0; i != j; i++)
subSuperRoom->roomExitStates[k++] = in->readUint16BE();
- } else if (type == 7) {
- SubContainer *container = (SubContainer *)allocateChildBlock(item, 7, sizeof(SubContainer));
+ } else if (type == kContainerType) {
+ SubContainer *container = (SubContainer *)allocateChildBlock(item, kContainerType, sizeof(SubContainer));
container->volume = in->readUint16BE();
container->flags = in->readUint16BE();
- } else if (type == 8) {
- SubChain *chain = (SubChain *)allocateChildBlock(item, 8, sizeof(SubChain));
+ } else if (type == kChainType) {
+ SubChain *chain = (SubChain *)allocateChildBlock(item, kChainType, sizeof(SubChain));
chain->chChained = (uint16)fileReadItemID(in);
- } else if (type == 9) {
+ } else if (type == kUserFlagType) {
setUserFlag(item, 0, in->readUint16BE());
setUserFlag(item, 1, in->readUint16BE());
setUserFlag(item, 2, in->readUint16BE());
setUserFlag(item, 3, in->readUint16BE());
- } else if (type == 255) {
- SubInherit *inherit = (SubInherit *)allocateChildBlock(item, 255, sizeof(SubInherit));
+ } else if (type == kInheritType) {
+ SubInherit *inherit = (SubInherit *)allocateChildBlock(item, kInheritType, sizeof(SubInherit));
inherit->inMaster = (uint16)fileReadItemID(in);
} else {
error("readItemChildren: invalid type %d", type);
diff --git a/engines/agos/rooms.cpp b/engines/agos/rooms.cpp
index af1bd0fe93..5e612080df 100644
--- a/engines/agos/rooms.cpp
+++ b/engines/agos/rooms.cpp
@@ -49,7 +49,7 @@ uint16 AGOSEngine::getDoorState(Item *item, uint16 d) {
uint16 mask = 3;
uint16 n;
- SubRoom *subRoom = (SubRoom *)findChildOfType(item, 1);
+ SubRoom *subRoom = (SubRoom *)findChildOfType(item, kRoomType);
if (subRoom == NULL)
return 0;
@@ -66,7 +66,7 @@ uint16 AGOSEngine::getExitOf(Item *item, uint16 d) {
uint16 x;
uint16 y = 0;
- subRoom = (SubRoom *)findChildOfType(item, 1);
+ subRoom = (SubRoom *)findChildOfType(item, kRoomType);
if (subRoom == NULL)
return 0;
x = d;
@@ -93,7 +93,7 @@ void AGOSEngine::setDoorState(Item *i, uint16 d, uint16 n) {
uint16 d1;
uint16 y = 0;
- r = (SubRoom *)findChildOfType(i, 1);
+ r = (SubRoom *)findChildOfType(i, kRoomType);
if (r == NULL)
return;
d1 = d;
@@ -107,7 +107,7 @@ void AGOSEngine::setDoorState(Item *i, uint16 d, uint16 n) {
j = derefItem(r->roomExit[d1]);
if (j == NULL)
return;
- r1 = (SubRoom *)findChildOfType(j, 1);
+ r1 = (SubRoom *)findChildOfType(j, kRoomType);
if (r1 == NULL)
return;
d = getBackExit(d);
@@ -130,7 +130,7 @@ Item *AGOSEngine::getDoorOf(Item *i, uint16 d) {
SubGenExit *g;
Item *x;
- g = (SubGenExit *)findChildOfType(i, 4);
+ g = (SubGenExit *)findChildOfType(i, kGenExitType);
if (g == NULL)
return 0;
@@ -146,7 +146,7 @@ Item *AGOSEngine::getExitOf_e1(Item *item, uint16 d) {
SubGenExit *g;
Item *x;
- g = (SubGenExit *)findChildOfType(item, 4);
+ g = (SubGenExit *)findChildOfType(item, kGenExitType);
if (g == NULL)
return 0;
@@ -192,10 +192,10 @@ void AGOSEngine_Elvira2::moveDirn(Item *i, uint x) {
return;
p = derefItem(i->parent);
- if (findChildOfType(p, 4)) {
+ if (findChildOfType(p, kSuperRoomType)) {
n = getExitState(p, _superRoomNumber,x);
if (n == 1) {
- sr = (SubSuperRoom *)findChildOfType(p, 4);
+ sr = (SubSuperRoom *)findChildOfType(p, kSuperRoomType);
switch (x) {
case 0: a = -(sr->roomX); break;
case 1: a = 1; break;
@@ -319,7 +319,7 @@ uint16 AGOSEngine_Elvira2::getExitState(Item *i, uint16 x, uint16 d) {
uint16 mask = 3;
uint16 n;
- sr = (SubSuperRoom *)findChildOfType(i, 4);
+ sr = (SubSuperRoom *)findChildOfType(i, kSuperRoomType);
if (sr == NULL)
return 0;
@@ -331,7 +331,7 @@ uint16 AGOSEngine_Elvira2::getExitState(Item *i, uint16 x, uint16 d) {
}
void AGOSEngine_Elvira2::setExitState(Item *i, uint16 n, uint16 d, uint16 s) {
- SubSuperRoom *sr = (SubSuperRoom *)findChildOfType(i, 4);
+ SubSuperRoom *sr = (SubSuperRoom *)findChildOfType(i, kSuperRoomType);
if (sr)
changeExitStates(sr, n, d, s);
}
@@ -339,7 +339,7 @@ void AGOSEngine_Elvira2::setExitState(Item *i, uint16 n, uint16 d, uint16 s) {
void AGOSEngine_Elvira2::setSRExit(Item *i, int n, int d, uint16 s) {
uint16 mask = 3;
- SubSuperRoom *sr = (SubSuperRoom *)findChildOfType(i, 4);
+ SubSuperRoom *sr = (SubSuperRoom *)findChildOfType(i, kSuperRoomType);
if (sr) {
n--;
d <<= 1;
diff --git a/engines/agos/saveload.cpp b/engines/agos/saveload.cpp
index eb2266550a..32b767073a 100644
--- a/engines/agos/saveload.cpp
+++ b/engines/agos/saveload.cpp
@@ -257,12 +257,12 @@ restart:
for (;;) {
windowPutChar(window, 128);
- _keyPressed = 0;
+ _keyPressed.reset();
for (;;) {
delay(10);
- if (_keyPressed && _keyPressed < 128) {
- i = _keyPressed;
+ if (_keyPressed.ascii && _keyPressed.ascii < 128) {
+ i = _keyPressed.ascii;
break;
}
}
@@ -490,16 +490,16 @@ int AGOSEngine_Elvira2::userGameGetKey(bool *b, char *buf, uint maxChar) {
HitArea *ha;
*b = true;
- _keyPressed = 0;
+ _keyPressed.reset();
for (;;) {
_lastHitArea = NULL;
_lastHitArea3 = NULL;
do {
- if (_saveLoadEdit && _keyPressed && _keyPressed < maxChar) {
+ if (_saveLoadEdit && _keyPressed.ascii && _keyPressed.ascii < maxChar) {
*b = false;
- return _keyPressed;
+ return _keyPressed.ascii;
}
delay(10);
} while (_lastHitArea3 == 0);
@@ -759,16 +759,16 @@ int AGOSEngine_Simon1::userGameGetKey(bool *b, char *buf, uint maxChar) {
listSaveGames(buf);
}
- _keyPressed = 0;
+ _keyPressed.reset();
for (;;) {
_lastHitArea = NULL;
_lastHitArea3 = NULL;
do {
- if (_saveLoadEdit && _keyPressed && _keyPressed < maxChar) {
+ if (_saveLoadEdit && _keyPressed.ascii && _keyPressed.ascii < maxChar) {
*b = false;
- return _keyPressed;
+ return _keyPressed.ascii;
}
delay(10);
} while (_lastHitArea3 == 0);
@@ -999,13 +999,13 @@ bool AGOSEngine::loadGame(const char *filename, bool restartMode) {
item->state = f->readUint16BE();
item->classFlags = f->readUint16BE();
- SubObject *o = (SubObject *)findChildOfType(item, 2);
+ SubObject *o = (SubObject *)findChildOfType(item, kObjectType);
if (o) {
o->objectSize = f->readUint16BE();
o->objectWeight = f->readUint16BE();
}
- SubPlayer *p = (SubPlayer *)findChildOfType(item, 3);
+ SubPlayer *p = (SubPlayer *)findChildOfType(item, kPlayerType);
if (p) {
p->score = f->readUint32BE();
p->level = f->readUint16BE();
@@ -1014,7 +1014,7 @@ bool AGOSEngine::loadGame(const char *filename, bool restartMode) {
p->strength = f->readUint16BE();
}
- SubUserFlag *u = (SubUserFlag *) findChildOfType(item, 9);
+ SubUserFlag *u = (SubUserFlag *)findChildOfType(item, kUserFlagType);
if (u) {
for (i = 0; i != 8; i++) {
u->userFlags[i] = f->readUint16BE();
@@ -1083,13 +1083,13 @@ bool AGOSEngine::saveGame(uint slot, const char *caption) {
f->writeUint16BE(item->state);
f->writeUint16BE(item->classFlags);
- SubObject *o = (SubObject *)findChildOfType(item, 2);
+ SubObject *o = (SubObject *)findChildOfType(item, kObjectType);
if (o) {
f->writeUint16BE(o->objectSize);
f->writeUint16BE(o->objectWeight);
}
- SubPlayer *p = (SubPlayer *)findChildOfType(item, 3);
+ SubPlayer *p = (SubPlayer *)findChildOfType(item, kPlayerType);
if (p) {
f->writeUint32BE(p->score);
f->writeUint16BE(p->level);
@@ -1098,7 +1098,7 @@ bool AGOSEngine::saveGame(uint slot, const char *caption) {
f->writeUint16BE(p->strength);
}
- SubUserFlag *u = (SubUserFlag *) findChildOfType(item, 9);
+ SubUserFlag *u = (SubUserFlag *)findChildOfType(item, kUserFlagType);
if (u) {
for (i = 0; i != 8; i++) {
f->writeUint16BE(u->userFlags[i]);
@@ -1204,19 +1204,19 @@ bool AGOSEngine_Elvira2::loadGame(const char *filename, bool restartMode) {
item->state = f->readUint16BE();
item->classFlags = f->readUint16BE();
- SubRoom *r = (SubRoom *)findChildOfType(item, 1);
+ SubRoom *r = (SubRoom *)findChildOfType(item, kRoomType);
if (r) {
r->roomExitStates = f->readUint16BE();
}
- SubSuperRoom *sr = (SubSuperRoom *)findChildOfType(item, 4);
+ SubSuperRoom *sr = (SubSuperRoom *)findChildOfType(item, kSuperRoomType);
if (sr) {
uint16 n = sr->roomX * sr->roomY * sr->roomZ;
for (i = j = 0; i != n; i++)
sr->roomExitStates[j++] = f->readUint16BE();
}
- SubObject *o = (SubObject *)findChildOfType(item, 2);
+ SubObject *o = (SubObject *)findChildOfType(item, kObjectType);
if (o) {
o->objectFlags = f->readUint32BE();
i = o->objectFlags & 1;
@@ -1228,7 +1228,7 @@ bool AGOSEngine_Elvira2::loadGame(const char *filename, bool restartMode) {
}
}
- SubUserFlag *u = (SubUserFlag *) findChildOfType(item, 9);
+ SubUserFlag *u = (SubUserFlag *)findChildOfType(item, kUserFlagType);
if (u) {
for (i = 0; i != 4; i++) {
u->userFlags[i] = f->readUint16BE();
@@ -1283,9 +1283,12 @@ bool AGOSEngine_Elvira2::saveGame(uint slot, const char *caption) {
Common::OutSaveFile *f;
uint item_index, num_item, i, j;
TimeEvent *te;
- uint32 curTime = 0;
uint32 gsc = _gameStoppedClock;
+ uint32 curTime = 0;
+ if (getGameType() != GType_SIMON1 && getGameType() != GType_SIMON2)
+ curTime = time(NULL);
+
_lockWord |= 0x100;
f = _saveFileMan->openForSaving(genSaveName(slot));
@@ -1299,7 +1302,6 @@ bool AGOSEngine_Elvira2::saveGame(uint slot, const char *caption) {
// No caption
} else if (getGameType() == GType_FF) {
f->write(caption, 100);
- curTime = time(NULL);
} else if (getGameType() == GType_SIMON1 || getGameType() == GType_SIMON2) {
f->write(caption, 18);
} else {
@@ -1308,7 +1310,7 @@ bool AGOSEngine_Elvira2::saveGame(uint slot, const char *caption) {
f->writeUint32BE(_itemArrayInited - 1);
f->writeUint32BE(0xFFFFFFFF);
- f->writeUint32BE(0);
+ f->writeUint32BE(curTime);
f->writeUint32BE(0);
i = 0;
@@ -1345,19 +1347,19 @@ bool AGOSEngine_Elvira2::saveGame(uint slot, const char *caption) {
f->writeUint16BE(item->state);
f->writeUint16BE(item->classFlags);
- SubRoom *r = (SubRoom *)findChildOfType(item, 1);
+ SubRoom *r = (SubRoom *)findChildOfType(item, kRoomType);
if (r) {
f->writeUint16BE(r->roomExitStates);
}
- SubSuperRoom *sr = (SubSuperRoom *)findChildOfType(item, 4);
+ SubSuperRoom *sr = (SubSuperRoom *)findChildOfType(item, kSuperRoomType);
if (sr) {
uint16 n = sr->roomX * sr->roomY * sr->roomZ;
for (i = j = 0; i != n; i++)
f->writeUint16BE(sr->roomExitStates[j++]);
}
- SubObject *o = (SubObject *)findChildOfType(item, 2);
+ SubObject *o = (SubObject *)findChildOfType(item, kObjectType);
if (o) {
f->writeUint32BE(o->objectFlags);
i = o->objectFlags & 1;
@@ -1369,7 +1371,7 @@ bool AGOSEngine_Elvira2::saveGame(uint slot, const char *caption) {
}
}
- SubUserFlag *u = (SubUserFlag *)findChildOfType(item, 9);
+ SubUserFlag *u = (SubUserFlag *)findChildOfType(item, kUserFlagType);
if (u) {
for (i = 0; i != 4; i++) {
f->writeUint16BE(u->userFlags[i]);
diff --git a/engines/agos/script.cpp b/engines/agos/script.cpp
index c5cf6c5872..ace0b9d50f 100644
--- a/engines/agos/script.cpp
+++ b/engines/agos/script.cpp
@@ -206,7 +206,7 @@ void AGOSEngine::o_state() {
void AGOSEngine::o_oflag() {
// 28: item has prop
- SubObject *subObject = (SubObject *)findChildOfType(getNextItemPtr(), 2);
+ SubObject *subObject = (SubObject *)findChildOfType(getNextItemPtr(), kObjectType);
uint num = getVarOrByte();
setScriptCondition(subObject != NULL && (subObject->objectFlags & (1 << num)) != 0);
}
@@ -326,7 +326,7 @@ void AGOSEngine::o_goto() {
void AGOSEngine::o_oset() {
// 56: set child2 fr bit
- SubObject *subObject = (SubObject *)findChildOfType(getNextItemPtr(), 2);
+ SubObject *subObject = (SubObject *)findChildOfType(getNextItemPtr(), kObjectType);
int value = getVarOrByte();
if (subObject != NULL && value >= 16)
subObject->objectFlags |= (1 << value);
@@ -334,7 +334,7 @@ void AGOSEngine::o_oset() {
void AGOSEngine::o_oclear() {
// 57: clear child2 fr bit
- SubObject *subObject = (SubObject *)findChildOfType(getNextItemPtr(), 2);
+ SubObject *subObject = (SubObject *)findChildOfType(getNextItemPtr(), kObjectType);
int value = getVarOrByte();
if (subObject != NULL && value >= 16)
subObject->objectFlags &= ~(1 << value);
@@ -426,7 +426,7 @@ void AGOSEngine::o_if2() {
void AGOSEngine::o_isCalled() {
// 79: childstruct fr2 is
- SubObject *subObject = (SubObject *)findChildOfType(getNextItemPtr(), 2);
+ SubObject *subObject = (SubObject *)findChildOfType(getNextItemPtr(), kObjectType);
uint stringId = getNextStringID();
setScriptCondition((subObject != NULL) && subObject->objectName == stringId);
}
@@ -753,7 +753,7 @@ void AGOSEngine::o_setAdjNoun() {
void AGOSEngine::o_saveUserGame() {
// 132: save user game
if (getGameId() == GID_SIMON1CD32) {
- // The Amiga CD32 version of Simon the Sorcerer 1uses a single slot
+ // The Amiga CD32 version of Simon the Sorcerer 1 uses a single slot
if (!saveGame(0, "Default Saved Game")) {
vc33_setMouseOn();
fileError(_windowArray[5], true);
@@ -799,7 +799,7 @@ void AGOSEngine::o_freezeZones() {
freezeBottom();
if (!_copyProtection && !(getFeatures() & GF_TALKIE)) {
- if ((getGameType() == GType_SIMON1 && _subroutine == 2924) ||
+ if ((getGameType() == GType_SIMON1 && _subroutine == 2924) ||
(getGameType() == GType_SIMON2 && _subroutine == 1322)) {
_variableArray[134] = 3;
_variableArray[135] = 3;
@@ -985,10 +985,10 @@ Child *nextSub(Child *sub, int16 key) {
}
void AGOSEngine::synchChain(Item *i) {
- SubChain *c = (SubChain *)findChildOfType(i, 8);
+ SubChain *c = (SubChain *)findChildOfType(i, kChainType);
while (c) {
setItemState(derefItem(c->chChained), i->state);
- c = (SubChain *)nextSub((Child *)c, 8);
+ c = (SubChain *)nextSub((Child *)c, kChainType);
}
}
diff --git a/engines/agos/script_e1.cpp b/engines/agos/script_e1.cpp
index b003a7262f..5a1d7d104b 100644
--- a/engines/agos/script_e1.cpp
+++ b/engines/agos/script_e1.cpp
@@ -419,7 +419,7 @@ void AGOSEngine_Elvira1::oe1_notPresent() {
void AGOSEngine_Elvira1::oe1_worn() {
// 4: worn
Item *item = getNextItemPtr();
- SubObject *subObject = (SubObject *)findChildOfType(item, 2);
+ SubObject *subObject = (SubObject *)findChildOfType(item, kObjectType);
if (item->parent != getItem1ID() || subObject == NULL)
setScriptCondition(false);
@@ -430,7 +430,7 @@ void AGOSEngine_Elvira1::oe1_worn() {
void AGOSEngine_Elvira1::oe1_notWorn() {
// 5: not worn
Item *item = getNextItemPtr();
- SubObject *subObject = (SubObject *)findChildOfType(item, 2);
+ SubObject *subObject = (SubObject *)findChildOfType(item, kObjectType);
if (item->parent != getItem1ID() || subObject == NULL)
setScriptCondition(false);
@@ -532,7 +532,7 @@ void AGOSEngine_Elvira1::oe1_moveDirn() {
void AGOSEngine_Elvira1::oe1_score() {
// 90: score
- SubPlayer *p = (SubPlayer *) findChildOfType(me(), 3);
+ SubPlayer *p = (SubPlayer *)findChildOfType(me(), kPlayerType);
showMessageFormat("Your score is %ld.\n", p->score);
}
@@ -542,9 +542,9 @@ void AGOSEngine_Elvira1::oe1_look() {
if (i == NULL)
return;
- SubRoom *r = (SubRoom *)findChildOfType(i, 1);
- SubObject *o = (SubObject *)findChildOfType(i, 2);
- SubPlayer *p = (SubPlayer *)findChildOfType(i, 3);
+ SubRoom *r = (SubRoom *)findChildOfType(i, kRoomType);
+ SubObject *o = (SubObject *)findChildOfType(i, kObjectType);
+ SubPlayer *p = (SubPlayer *)findChildOfType(i, kPlayerType);
if (p == NULL)
return;
@@ -594,7 +594,7 @@ void AGOSEngine_Elvira1::oe1_doClass() {
void AGOSEngine_Elvira1::oe1_pObj() {
// 112: print object
- SubObject *subObject = (SubObject *)findChildOfType(getNextItemPtr(), 2);
+ SubObject *subObject = (SubObject *)findChildOfType(getNextItemPtr(), kObjectType);
getVarOrWord();
if (subObject != NULL)
@@ -624,7 +624,7 @@ void AGOSEngine_Elvira1::oe1_isCalled() {
void AGOSEngine_Elvira1::oe1_cFlag() {
// 162: check container flag
- SubContainer *c = (SubContainer *)findChildOfType(getNextItemPtr(), 7);
+ SubContainer *c = (SubContainer *)findChildOfType(getNextItemPtr(), kContainerType);
uint bit = getVarOrWord();
if (c == NULL)
@@ -678,7 +678,7 @@ void AGOSEngine_Elvira1::oe1_doorExit() {
int16 f = getVarOrWord();
int16 ct = 0;
- c = (SubChain *)findChildOfType(d, 8);
+ c = (SubChain *)findChildOfType(d, kChainType);
if (c)
a = derefItem(c->chChained);
while (ct < 6) {
@@ -986,7 +986,7 @@ void AGOSEngine_Elvira1::oe1_printMonsterHit() {
}
int16 AGOSEngine::levelOf(Item *item) {
- SubPlayer *p = (SubPlayer *) findChildOfType(item, 3);
+ SubPlayer *p = (SubPlayer *)findChildOfType(item, kPlayerType);
if (p == NULL)
return 0;
@@ -998,7 +998,7 @@ int16 AGOSEngine::moreText(Item *i) {
i = derefItem(i->next);
while (i) {
- o = (SubObject *)findChildOfType(i, 2);
+ o = (SubObject *)findChildOfType(i, kObjectType);
if ((o) && (o->objectFlags & 1))
goto l1;
if (i != me())
@@ -1014,7 +1014,7 @@ void AGOSEngine::lobjFunc(Item *i, const char *f) {
SubObject *o;
while (i) {
- o = (SubObject *)findChildOfType(i, 2);
+ o = (SubObject *)findChildOfType(i, kObjectType);
if ((o) && (o->objectFlags & 1))
goto l1;
if (i == me())
diff --git a/engines/agos/script_e2.cpp b/engines/agos/script_e2.cpp
index 00f0848ed9..77df3feecb 100644
--- a/engines/agos/script_e2.cpp
+++ b/engines/agos/script_e2.cpp
@@ -132,7 +132,7 @@ void AGOSEngine_Elvira2::setupOpcodes() {
OPCODE(o_when),
OPCODE(o_if1),
OPCODE(o_if2),
- OPCODE(oe1_isCalled),
+ OPCODE(oe2_isCalled),
/* 80 */
OPCODE(o_is),
OPCODE(o_invalid),
@@ -165,7 +165,7 @@ void AGOSEngine_Elvira2::setupOpcodes() {
OPCODE(o_cls),
/* 104 */
OPCODE(o_closeWindow),
- OPCODE(o_invalid),
+ OPCODE(oe2_menu),
OPCODE(o_invalid),
OPCODE(o_addBox),
/* 108 */
@@ -309,12 +309,19 @@ void AGOSEngine_Elvira2::oe2_doClass() {
void AGOSEngine_Elvira2::oe2_pObj() {
// 73: print object
- SubObject *subObject = (SubObject *)findChildOfType(getNextItemPtr(), 2);
+ SubObject *subObject = (SubObject *)findChildOfType(getNextItemPtr(), kObjectType);
if (subObject != NULL && subObject->objectFlags & kOFText)
showMessageFormat("%s\n", (const char *)getStringPtrByID(subObject->objectFlagValue[0])); // Difference
}
+void AGOSEngine_Elvira2::oe2_isCalled() {
+ // 79: childstruct fr2 is
+ Item *i = getNextItemPtr();
+ uint stringId = getNextStringID();
+ setScriptCondition(i->itemName == stringId);
+}
+
void AGOSEngine_Elvira2::oe2_loadGame() {
// 89: load game
uint16 stringId = getNextStringID();
@@ -326,6 +333,11 @@ void AGOSEngine_Elvira2::oe2_loadGame() {
}
}
+void AGOSEngine_Elvira2::oe2_menu() {
+ // 105: set agos menu
+ _agosMenu = getVarOrByte();
+}
+
void AGOSEngine_Elvira2::oe2_drawItem() {
// 113: draw item
Item *i = getNextItemPtr();
@@ -341,7 +353,7 @@ void AGOSEngine_Elvira2::oe2_doTable() {
// 143: start item sub
Item *i = getNextItemPtr();
- SubRoom *r = (SubRoom *)findChildOfType(i, 1);
+ SubRoom *r = (SubRoom *)findChildOfType(i, kRoomType);
if (r != NULL) {
Subroutine *sub = getSubroutineByID(r->subroutine_id);
if (sub) {
@@ -351,7 +363,7 @@ void AGOSEngine_Elvira2::oe2_doTable() {
}
if (getGameType() == GType_ELVIRA2) {
- SubSuperRoom *sr = (SubSuperRoom *)findChildOfType(i, 4);
+ SubSuperRoom *sr = (SubSuperRoom *)findChildOfType(i, kSuperRoomType);
if (sr != NULL) {
Subroutine *sub = getSubroutineByID(sr->subroutine_id);
if (sub) {
@@ -478,7 +490,7 @@ void AGOSEngine_Elvira2::oe2_bNotZero() {
void AGOSEngine_Elvira2::oe2_getOValue() {
// 157: get item int prop
Item *item = getNextItemPtr();
- SubObject *subObject = (SubObject *)findChildOfType(item, 2);
+ SubObject *subObject = (SubObject *)findChildOfType(item, kObjectType);
uint prop = getVarOrByte();
if (subObject != NULL && subObject->objectFlags & (1 << prop) && prop < 16) {
@@ -492,7 +504,7 @@ void AGOSEngine_Elvira2::oe2_getOValue() {
void AGOSEngine_Elvira2::oe2_setOValue() {
// 158: set item prop
Item *item = getNextItemPtr();
- SubObject *subObject = (SubObject *)findChildOfType(item, 2);
+ SubObject *subObject = (SubObject *)findChildOfType(item, kObjectType);
uint prop = getVarOrByte();
int value = getVarOrWord();
@@ -640,6 +652,16 @@ void AGOSEngine_Elvira2::oe2_isAdjNoun() {
// 179: item unk1 unk2 is
Item *item = getNextItemPtr();
int16 a = getNextWord(), b = getNextWord();
+
+ if (getGameType() == GType_ELVIRA2) {
+ // WORKAROUND: A NULL item can occur when interacting with Wine Bottles
+ if (item == NULL) {
+ warning("Please report where exactly this occurs in Elvira 2");
+ setScriptCondition(false);
+ return;
+ }
+ }
+
setScriptCondition(item->adjective == a && item->noun == b);
}
@@ -707,7 +729,7 @@ void AGOSEngine_Elvira2::printStats() {
if (val > 9999)
val = 9999;
writeChar(window, 30, y, 6, val / 100);
- writeChar(window, 32, y, 2, val / 10);
+ writeChar(window, 32, y, 2, val % 100);
mouseOn();
}
diff --git a/engines/agos/script_ff.cpp b/engines/agos/script_ff.cpp
index c3e6dc5192..8b7af31a66 100644
--- a/engines/agos/script_ff.cpp
+++ b/engines/agos/script_ff.cpp
@@ -528,7 +528,7 @@ void AGOSEngine_Feeble::off_screenTextPObj() {
TextLocation *tl = NULL;
char buf[256];
- SubObject *subObject = (SubObject *)findChildOfType(getNextItemPtr(), 2);
+ SubObject *subObject = (SubObject *)findChildOfType(getNextItemPtr(), kObjectType);
if (subObject != NULL && subObject->objectFlags & kOFText) {
string_ptr = (const char *)getStringPtrByID(subObject->objectFlagValue[0]);
tl = getTextLocation(vgaSpriteId);
diff --git a/engines/agos/script_s1.cpp b/engines/agos/script_s1.cpp
index 93b907e688..1a4f956b8b 100644
--- a/engines/agos/script_s1.cpp
+++ b/engines/agos/script_s1.cpp
@@ -311,29 +311,29 @@ void AGOSEngine_Simon1::os1_pauseGame() {
_system->setFeatureState(OSystem::kFeatureVirtualKeyboard, true);
// If all else fails, use English as fallback.
- byte keyYes = 'y';
- byte keyNo = 'n';
+ Common::KeyCode keyYes = Common::KEYCODE_y;
+ Common::KeyCode keyNo = Common::KEYCODE_n;
switch (_language) {
case Common::RU_RUS:
break;
case Common::PL_POL:
- keyYes = 't';
+ keyYes = Common::KEYCODE_t;
break;
case Common::HB_ISR:
- keyYes = 'f';
+ keyYes = Common::KEYCODE_f;
break;
case Common::ES_ESP:
- keyYes = 's';
+ keyYes = Common::KEYCODE_s;
break;
case Common::IT_ITA:
- keyYes = 's';
+ keyYes = Common::KEYCODE_s;
break;
case Common::FR_FRA:
- keyYes = 'o';
+ keyYes = Common::KEYCODE_o;
break;
case Common::DE_DEU:
- keyYes = 'j';
+ keyYes = Common::KEYCODE_j;
break;
default:
break;
@@ -343,17 +343,17 @@ void AGOSEngine_Simon1::os1_pauseGame() {
delay(1);
#ifdef _WIN32_WCE
if (isSmartphone()) {
- if (_keyPressed) {
- if (_keyPressed == 13)
+ if (_keyPressed.keycode) {
+ if (_keyPressed.keycode == Common::KEYCODE_RETURN)
shutdown();
else
break;
}
}
#endif
- if (_keyPressed == keyYes || _keyPressed == (keyYes - 32))
+ if (_keyPressed.keycode == keyYes)
shutdown();
- else if (_keyPressed == keyNo || _keyPressed == (keyNo - 32))
+ else if (_keyPressed.keycode == keyNo)
break;
}
@@ -419,7 +419,7 @@ void AGOSEngine_Simon1::os1_screenTextPObj() {
uint vgaSpriteId = getVarOrByte();
uint color = getVarOrByte();
- SubObject *subObject = (SubObject *)findChildOfType(getNextItemPtr(), 2);
+ SubObject *subObject = (SubObject *)findChildOfType(getNextItemPtr(), kObjectType);
if (getFeatures() & GF_TALKIE) {
if (subObject != NULL && subObject->objectFlags & kOFVoice) {
uint offs = getOffsetOfChild2Param(subObject, kOFVoice);
diff --git a/engines/agos/script_s2.cpp b/engines/agos/script_s2.cpp
index dfc1200d7c..00addce396 100644
--- a/engines/agos/script_s2.cpp
+++ b/engines/agos/script_s2.cpp
@@ -355,7 +355,7 @@ void AGOSEngine_Simon2::os2_screenTextPObj() {
uint vgaSpriteId = getVarOrByte();
uint color = getVarOrByte();
- SubObject *subObject = (SubObject *)findChildOfType(getNextItemPtr(), 2);
+ SubObject *subObject = (SubObject *)findChildOfType(getNextItemPtr(), kObjectType);
if (getFeatures() & GF_TALKIE) {
if (subObject != NULL && subObject->objectFlags & kOFVoice) {
uint speechId = subObject->objectFlagValue[getOffsetOfChild2Param(subObject, kOFVoice)];
diff --git a/engines/agos/script_ww.cpp b/engines/agos/script_ww.cpp
index 377b49ae3f..fc472fd3c3 100644
--- a/engines/agos/script_ww.cpp
+++ b/engines/agos/script_ww.cpp
@@ -167,7 +167,7 @@ void AGOSEngine_Waxworks::setupOpcodes() {
OPCODE(o_cls),
/* 104 */
OPCODE(o_closeWindow),
- OPCODE(oww_menu),
+ OPCODE(oe2_menu),
OPCODE(oww_textMenu),
OPCODE(o_addBox),
/* 108 */
@@ -355,11 +355,6 @@ void AGOSEngine_Waxworks::oww_whereTo() {
_objectItem = derefItem(getExitOf(i, d));
}
-void AGOSEngine_Waxworks::oww_menu() {
- // 105: set agos menu
- _agosMenu = getVarOrByte();
-}
-
void AGOSEngine_Waxworks::oww_textMenu() {
// 106: set text menu
byte slot = getVarOrByte();
@@ -419,7 +414,7 @@ void AGOSEngine_Waxworks::oww_printBox() {
void AGOSEngine_Waxworks::oww_boxPObj() {
// 188: print object name to box
- SubObject *subObject = (SubObject *)findChildOfType(getNextItemPtr(), 2);
+ SubObject *subObject = (SubObject *)findChildOfType(getNextItemPtr(), kObjectType);
if (subObject != NULL && subObject->objectFlags & kOFText)
boxTextMsg((const char *)getStringPtrByID(subObject->objectFlagValue[0]));
diff --git a/engines/agos/string.cpp b/engines/agos/string.cpp
index 483f101889..521a3ab6ea 100644
--- a/engines/agos/string.cpp
+++ b/engines/agos/string.cpp
@@ -274,7 +274,7 @@ bool AGOSEngine::printNameOf(Item *item, uint x, uint y) {
if (item == 0 || item == _dummyItem2 || item == _dummyItem3)
return false;
- subObject = (SubObject *)findChildOfType(item, 2);
+ subObject = (SubObject *)findChildOfType(item, kObjectType);
if (subObject == NULL)
return false;
@@ -370,10 +370,12 @@ void AGOSEngine::printScreenText(uint vgaSpriteId, uint color, const char *strin
if (y < 2)
y = 2;
- if (getGameType() == GType_SIMON1)
- animate(windowNum, 2, 199 + vgaSpriteId, x, y, 12);
- else
+ if (getGameType() == GType_SIMON1) {
+ uint16 id = 199 + vgaSpriteId;
+ animate(windowNum, id / 100, id, x, y, 12);
+ } else {
animate(windowNum, 2, vgaSpriteId, x, y, 12);
+ }
}
// The Feeble Files specific
diff --git a/engines/agos/vga.cpp b/engines/agos/vga.cpp
index 2b8f6d3a09..38c401a80d 100644
--- a/engines/agos/vga.cpp
+++ b/engines/agos/vga.cpp
@@ -70,8 +70,8 @@ void AGOSEngine::setupVideoOpcodes(VgaOpcodeProc *op) {
op[36] = &AGOSEngine::vc36_setWindowImage;
op[38] = &AGOSEngine::vc38_ifVarNotZero;
op[39] = &AGOSEngine::vc39_setVar;
- op[40] = &AGOSEngine::vc40;
- op[41] = &AGOSEngine::vc41;
+ op[40] = &AGOSEngine::vc40_scrollRight;
+ op[41] = &AGOSEngine::vc41_scrollLeft;
op[42] = &AGOSEngine::vc42_delayIfNotEQ;
op[43] = &AGOSEngine::vc43_ifBitSet;
op[44] = &AGOSEngine::vc44_ifBitClear;
@@ -124,8 +124,8 @@ void AGOSEngine_Elvira1::setupVideoOpcodes(VgaOpcodeProc *op) {
op[41] = &AGOSEngine::vc37_pokePalette;
op[51] = &AGOSEngine::vc38_ifVarNotZero;
op[52] = &AGOSEngine::vc39_setVar;
- op[53] = &AGOSEngine::vc40;
- op[54] = &AGOSEngine::vc41;
+ op[53] = &AGOSEngine::vc40_scrollRight;
+ op[54] = &AGOSEngine::vc41_scrollLeft;
op[56] = &AGOSEngine::vc42_delayIfNotEQ;
}
@@ -1257,57 +1257,38 @@ void AGOSEngine::vc39_setVar() {
vcWriteVar(var, value);
}
-void AGOSEngine::vc40() {
+void AGOSEngine::vc40_scrollRight() {
uint16 var = vcReadNextWord();
int16 value = vcReadVar(var) + vcReadNextWord();
if (getGameType() == GType_SIMON2 && var == 15 && !getBitFlag(80)) {
- int16 tmp;
- if (_scrollCount != 0) {
- if (_scrollCount >= 0)
- goto no_scroll;
+ if ((_scrollCount < 0) || (_scrollCount == 0 && _scrollFlag == 0)) {
_scrollCount = 0;
- } else {
- if (_scrollFlag != 0)
- goto no_scroll;
- }
-
- if (value - _scrollX >= 30) {
- _scrollCount = 20;
- tmp = _scrollXMax - _scrollX;
- if (tmp < 20)
- _scrollCount = tmp;
- addVgaEvent(6, SCROLL_EVENT, NULL, 0, 0);
+ if (value - _scrollX >= 30) {
+ _scrollCount = MIN(20, _scrollXMax - _scrollX);
+ addVgaEvent(6, SCROLL_EVENT, NULL, 0, 0);
+ }
}
}
-no_scroll:;
vcWriteVar(var, value);
}
-void AGOSEngine::vc41() {
+void AGOSEngine::vc41_scrollLeft() {
uint16 var = vcReadNextWord();
int16 value = vcReadVar(var) - vcReadNextWord();
if (getGameType() == GType_SIMON2 && var == 15 && !getBitFlag(80)) {
- if (_scrollCount != 0) {
- if (_scrollCount < 0)
- goto no_scroll;
- _scrollCount = 0;
- } else {
- if (_scrollFlag != 0)
- goto no_scroll;
- }
- if ((uint16)(value - _scrollX) < 11) {
- _scrollCount = -20;
- if (_scrollX < 20)
- _scrollCount = -_scrollX;
- addVgaEvent(6, SCROLL_EVENT, NULL, 0, 0);
+ if ((_scrollCount > 0) || (_scrollCount == 0 && _scrollFlag == 0)) {
+ _scrollCount = 0;
+ if ((uint16)(value - _scrollX) < 11) {
+ _scrollCount = -MIN(20, (int)_scrollX);
+ addVgaEvent(6, SCROLL_EVENT, NULL, 0, 0);
+ }
}
}
-no_scroll:;
vcWriteVar(var, value);
}
diff --git a/engines/agos/vga.h b/engines/agos/vga.h
index 37c5d37106..1994f59f7f 100644
--- a/engines/agos/vga.h
+++ b/engines/agos/vga.h
@@ -40,20 +40,20 @@ struct VgaFileHeader2_Feeble {
uint16 x_4;
uint16 animationTable;
uint16 x_5;
-};
+} PACKED_STRUCT;
struct ImageHeader_Feeble {
uint16 id;
uint16 x_1;
uint16 scriptOffs;
uint16 x_2;
-};
+} PACKED_STRUCT;
struct AnimationHeader_Feeble {
uint16 scriptOffs;
uint16 x_2;
uint16 id;
-};
+} PACKED_STRUCT;
// Simon 1/2
struct ImageHeader_Simon {
@@ -61,13 +61,13 @@ struct ImageHeader_Simon {
uint16 color;
uint16 x_2;
uint16 scriptOffs;
-};
+} PACKED_STRUCT;
struct AnimationHeader_Simon {
uint16 id;
uint16 x_2;
uint16 scriptOffs;
-};
+} PACKED_STRUCT;
// Elvira 1/2 and Waxworks
@@ -76,14 +76,14 @@ struct ImageHeader_WW {
uint16 color;
uint16 x_2;
uint16 scriptOffs;
-};
+} PACKED_STRUCT;
struct AnimationHeader_WW {
uint16 id;
uint16 x_1;
uint16 x_2;
uint16 scriptOffs;
-};
+} PACKED_STRUCT;
// Common
struct VgaFileHeader2_Common {
@@ -96,7 +96,7 @@ struct VgaFileHeader2_Common {
uint16 x_4;
uint16 animationTable;
uint16 x_5;
-};
+} PACKED_STRUCT;
#include "common/pack-end.h" // END STRUCT PACKING
diff --git a/engines/cine/various.cpp b/engines/cine/various.cpp
index 281c4807b8..49b10b6b14 100644
--- a/engines/cine/various.cpp
+++ b/engines/cine/various.cpp
@@ -2458,6 +2458,7 @@ void drawFailureMessage(byte cmd) {
void drawOverlays(void) {
overlayHeadElement *currentOverlay;
+ overlayHeadElement *nextOverlay;
backupOverlayPage();
@@ -2468,6 +2469,8 @@ void drawOverlays(void) {
currentOverlay = currentOverlay->next;
while (currentOverlay) {
+ nextOverlay = currentOverlay->next;
+
switch (currentOverlay->type) {
case 0: // sprite
{
@@ -2630,7 +2633,7 @@ void drawOverlays(void) {
}
}
- currentOverlay = currentOverlay->next;
+ currentOverlay = nextOverlay;
}
}
diff --git a/engines/cruise/saveload.cpp b/engines/cruise/saveload.cpp
index d6b2c9ec93..ffda142e66 100644
--- a/engines/cruise/saveload.cpp
+++ b/engines/cruise/saveload.cpp
@@ -177,12 +177,12 @@ int loadSavegameData(int saveGameIdx) {
fileHandle = fopen(buffer, "rb");
if (!fileHandle) {
- printInfoBlackBox("Sauvegarde non trouvée...");
+ printInfoBlackBox("Savegame not found...");
waitForPlayerInput();
return (-1);
}
- printInfoBlackBox("Chargement en cours...");
+ printInfoBlackBox("Loading in progress...");
fread(saveIdentBuffer, 6, 1, fileHandle);
diff --git a/engines/engine.cpp b/engines/engine.cpp
index 05e2235cc9..f2b7198510 100644
--- a/engines/engine.cpp
+++ b/engines/engine.cpp
@@ -54,7 +54,8 @@ Engine::Engine(OSystem *syst)
_eventMan(_system->getEventManager()),
_saveFileMan(_system->getSavefileManager()),
_targetName(ConfMan.getActiveDomainName()),
- _gameDataPath(ConfMan.get("path")) {
+ _gameDataPath(ConfMan.get("path")),
+ _pauseLevel(0) {
g_engine = this;
_autosavePeriod = ConfMan.getInt("autosave_period");
@@ -180,3 +181,23 @@ void Engine::GUIErrorMessage(const Common::String msg) {
GUI::MessageDialog dialog(msg);
dialog.runModal();
}
+
+void Engine::pauseEngine(bool pause) {
+ assert((pause && _pauseLevel >= 0) || (!pause && _pauseLevel));
+
+ if (pause)
+ _pauseLevel++;
+ else
+ _pauseLevel--;
+
+ if (_pauseLevel == 1) {
+ pauseEngineIntern(true);
+ } else if (_pauseLevel == 0) {
+ pauseEngineIntern(false);
+ }
+}
+
+void Engine::pauseEngineIntern(bool pause) {
+ // By default, just (un)pause all digital sounds
+ _mixer->pauseAll(pause);
+}
diff --git a/engines/engine.h b/engines/engine.h
index 7b40a377ef..f9aeb7718f 100644
--- a/engines/engine.h
+++ b/engines/engine.h
@@ -56,7 +56,18 @@ protected:
const Common::String _gameDataPath;
private:
+ /**
+ * The autosave interval, given in second. Used by shouldPerformAutoSave.
+ */
int _autosavePeriod;
+
+ /**
+ * The pause level, 0 means 'running', a positive value indicates
+ * how often the engine has been paused (and hence how often it has
+ * to be un-paused before it resumes running). This makes it possible
+ * to nest code which pauses the engine.
+ */
+ int _pauseLevel;
public:
Engine(OSystem *syst);
@@ -79,22 +90,49 @@ public:
/** Specific for each engine: prepare error string. */
virtual void errorString(const char *buf_input, char *buf_output);
+ /**
+ * Return the engine's debugger instance, if any. Used by error() to
+ * invoke the debugger when a severe error is reported.
+ */
+ virtual GUI::Debugger *getDebugger() { return 0; }
+
+ /**
+ * Pause or resume the engine. This should stop/resume any audio playback
+ * and other stuff. Called right before the system runs a global dialog
+ * (like a global pause, main menu, options or 'confirm exit' dialog).
+ *
+ * This is a convenience tracker which automatically keeps track on how
+ * often the engine has been paused, ensuring that after pausing an engine
+ * e.g. twice, it has to be unpaused twice before actuallying resuming.
+ *
+ * @param pause true to pause the engine, false to resume it
+ */
+ void pauseEngine(bool pause);
+
+ /**
+ * Return whether the engine is currently paused or not.
+ */
+ bool isPaused() const { return _pauseLevel != 0; }
+
+public:
+
+ /** Setup the backend's graphics mode. */
void initCommonGFX(bool defaultTo1XScaler);
/** On some systems, check if the game appears to be run from CD. */
void checkCD();
- /* Indicate if an autosave should be performed. */
+ /** Indicate whether an autosave should be performed. */
bool shouldPerformAutoSave(int lastSaveTime);
/** Initialized graphics and shows error message. */
void GUIErrorMessage(const Common::String msg);
-
+
/**
- * Return the engine's debugger instance, if any. Used by error() to
- * invoke the debugger when a severe error is reported.
+ * Actual implementation of pauseEngine by subclasses. See there
+ * for details.
*/
- virtual GUI::Debugger *getDebugger() { return 0; }
+ virtual void pauseEngineIntern(bool pause);
};
extern Engine *g_engine;
diff --git a/engines/gob/detection.cpp b/engines/gob/detection.cpp
index 9dfbf534d4..1c275185ca 100644
--- a/engines/gob/detection.cpp
+++ b/engines/gob/detection.cpp
@@ -757,14 +757,30 @@ static const GOBGameDescription gameDescriptions[] = {
{
"gob3",
"",
- AD_ENTRY1("intro.stk", "32b0f57f5ae79a9ae97e8011df38af42"),
- UNK_LANG,
+ AD_ENTRY1s("intro.stk", "32b0f57f5ae79a9ae97e8011df38af42", 157084),
+ EN_GRB,
kPlatformPC,
Common::ADGF_NO_FLAGS
},
GF_GOB3,
"intro"
},
+ { // Supplied by fac76 in bug report #1742716
+ {
+ "gob3",
+ "",
+ {
+ {"intro.stk", 0, "32b0f57f5ae79a9ae97e8011df38af42", 157084},
+ {"musmac1.mid", 0, "834e55205b710d0af5f14a6f2320dd8e", 8661},
+ {NULL, 0, NULL, 0}
+ },
+ EN_GRB,
+ kPlatformMacintosh,
+ Common::ADGF_NO_FLAGS
+ },
+ GF_GOB3,
+ "intro"
+ },
{
{
"gob3",
diff --git a/engines/gob/game.h b/engines/gob/game.h
index 4a1796c6d9..2181d219f2 100644
--- a/engines/gob/game.h
+++ b/engines/gob/game.h
@@ -48,7 +48,7 @@ public:
uint16 funcEnter;
uint16 funcLeave;
uint16 funcSub;
- };
+ } PACKED_STRUCT;
#define szGame_TotResItem (4 + 2 + 2 + 2)
struct TotResItem {
@@ -57,7 +57,7 @@ public:
int16 size;
int16 width;
int16 height;
- };
+ } PACKED_STRUCT;
#define szGame_TotResTable (2 + 1)
struct TotResTable {
@@ -65,7 +65,7 @@ public:
byte unknown;
TotResItem *items;
byte *dataPtr;
- };
+ } PACKED_STRUCT;
#define szGame_ExtItem (4 + 2 + 2 + 2)
struct ExtItem {
@@ -73,34 +73,34 @@ public:
uint16 size;
int16 width; // width & 0x7FFF: width, width & 0x8000: pack flag
int16 height; // not zero
- };
+ } PACKED_STRUCT;
#define szGame_ExtTable (2 + 1)
struct ExtTable {
int16 itemsCount;
byte unknown;
ExtItem* items;
- };
+ } PACKED_STRUCT;
#define szGame_TotTextItem (2 + 2)
struct TotTextItem {
int16 offset;
int16 size;
- };
+ } PACKED_STRUCT;
#define szGame_TotTextTable (2)
struct TotTextTable {
int16 itemsCount;
TotTextItem *items;
byte *dataPtr;
- };
+ } PACKED_STRUCT;
struct InputDesc {
int16 fontIndex;
int16 backColor;
int16 frontColor;
byte *ptr;
- };
+ } PACKED_STRUCT;
#include "common/pack-end.h" // END STRUCT PACKING
diff --git a/engines/gob/goblin.h b/engines/gob/goblin.h
index 61ac9dff5e..38c19a48d3 100644
--- a/engines/gob/goblin.h
+++ b/engines/gob/goblin.h
@@ -51,7 +51,7 @@ public:
int16 freq; // high/low byte * 100 - frequency
int16 repCount; // high/low byte - repeat count
int16 sndFrame;
- };
+ } PACKED_STRUCT;
typedef Gob_State *Gob_PState;
@@ -90,12 +90,12 @@ public:
char multObjIndex;
char unk14;
char visible;
- };
+ } PACKED_STRUCT;
struct Gob_Pos {
char x;
char y;
- };
+ } PACKED_STRUCT;
#include "common/pack-end.h" // END STRUCT PACKING
diff --git a/engines/gob/imd.h b/engines/gob/imd.h
index 3d04f18c6d..27d95cd579 100644
--- a/engines/gob/imd.h
+++ b/engines/gob/imd.h
@@ -41,7 +41,7 @@ public:
int16 top;
int16 right;
int16 bottom;
- };
+ } PACKED_STRUCT;
struct Imd {
int16 handle;
@@ -65,7 +65,7 @@ public:
int32 frameDataSize;
int32 vidBufferSize;
Video::Color *extraPalette;
- };
+ } PACKED_STRUCT;
#include "common/pack-end.h" // END STRUCT PACKING
diff --git a/engines/gob/inter_v1.cpp b/engines/gob/inter_v1.cpp
index fcf825b4c3..a3277047e7 100644
--- a/engines/gob/inter_v1.cpp
+++ b/engines/gob/inter_v1.cpp
@@ -1647,6 +1647,13 @@ bool Inter_v1::o1_keyFunc(OpFuncParams &params) {
lastCalled = now;
_noBusyWait = false;
+ // WORKAROUND for bug #1726130: Ween busy-waits in the intro for a counter
+ // to become 5000. We deliberately slow down busy-waiting, so we shorten
+ // the counting, too.
+ if (((_vm->_global->_inter_execPtr - _vm->_game->_totFileData) == 729) &&
+ (VAR(59) < 4000) && !scumm_stricmp(_vm->_game->_curTotFile, "intro5.tot"))
+ WRITE_VAR(59, 4000);
+
switch (cmd) {
case 0:
_vm->_draw->_showCursor &= ~2;
diff --git a/engines/gob/map.h b/engines/gob/map.h
index 9b45c5c04e..0e0a80aad3 100644
--- a/engines/gob/map.h
+++ b/engines/gob/map.h
@@ -51,7 +51,7 @@ public:
int16 x;
int16 y;
int16 notWalkable;
- };
+ } PACKED_STRUCT;
#define szMap_ItemPos 3
@@ -59,7 +59,7 @@ public:
int8 x;
int8 y;
int8 orient;
- };
+ } PACKED_STRUCT;
#include "common/pack-end.h" // END STRUCT PACKING
diff --git a/engines/gob/mult.h b/engines/gob/mult.h
index 194126cd8b..edfbb682ea 100644
--- a/engines/gob/mult.h
+++ b/engines/gob/mult.h
@@ -63,7 +63,7 @@ public:
int8 redrawAnimation;
int8 redrawLayer;
uint8 redrawFrame;
- };
+ } PACKED_STRUCT;
struct Mult_GobState {
int16 animation; // .
@@ -74,7 +74,7 @@ public:
int16 freq; // |- [1+]
int8 repCount; // |
uint8 speaker; // '
- };
+ } PACKED_STRUCT;
struct Mult_Object {
int32 *pPosX;
@@ -104,12 +104,12 @@ public:
int16 newTop;
int16 newRight;
int16 newBottom;
- };
+ } PACKED_STRUCT;
struct Mult_StaticKey {
int16 frame;
int16 layer;
- };
+ } PACKED_STRUCT;
struct Mult_AnimKey {
int16 frame;
@@ -117,14 +117,14 @@ public:
int16 posX;
int16 posY;
int16 order;
- };
+ } PACKED_STRUCT;
struct Mult_TextKey {
int16 frame;
int16 cmd;
char unknown[18];
byte script[6];
- };
+ } PACKED_STRUCT;
struct Mult_PalKey {
int16 frame;
@@ -133,14 +133,14 @@ public:
int16 unknown0;
int16 unknown1;
int8 subst[16][4];
- };
+ } PACKED_STRUCT;
struct Mult_PalFadeKey {
int16 frame;
int16 fade;
int16 palIndex;
int8 flag;
- };
+ } PACKED_STRUCT;
struct Mult_SndKey {
int16 frame;
@@ -150,7 +150,7 @@ public:
int16 repCount;
int16 resId;
int16 soundIndex;
- };
+ } PACKED_STRUCT;
struct Mult_ImdKey {
int16 frame;
@@ -162,7 +162,7 @@ public:
int16 lastFrame;
int8 palStart;
int8 palEnd;
- };
+ } PACKED_STRUCT;
struct Mult_Data {
int16 palFadeKeysCount;
@@ -212,7 +212,7 @@ public:
char *imdFiles;
char *somepointer10; // ?
byte *execPtr;
- };
+ } PACKED_STRUCT;
#include "common/pack-end.h" // END STRUCT PACKING
diff --git a/engines/gob/music.cpp b/engines/gob/music.cpp
index 6e678c103e..0f38827363 100644
--- a/engines/gob/music.cpp
+++ b/engines/gob/music.cpp
@@ -268,20 +268,20 @@ void Adlib::setKey(byte voice, byte note, bool on, bool spec) {
// 0x3A donne 0x2AF;
// 3A
// << 7 = 1D00
- // + E000 = FD00 négatif
+ // + E000 = FD00 negatif
// * 19 = xB500
// / 2000 = -2 => Ligne 17h, colonne -1
// 2E
// << 7 = 1700
- // + E000 = F700 négatif
+ // + E000 = F700 negatif
// * 19 = x1F00
// / 2000 =
short a;
short lin;
short col;
- a = (note << 7) + 0xE000; // Volontairement tronqué
+ a = (note << 7) + 0xE000; // Volontairement tronque
a = (short)((long)a * 25 / 0x2000);
if (a < 0) {
col = - ((24 - a) / 25);
diff --git a/engines/gob/saveload_v3.cpp b/engines/gob/saveload_v3.cpp
index 3f8aeb81bd..b376a8a75c 100644
--- a/engines/gob/saveload_v3.cpp
+++ b/engines/gob/saveload_v3.cpp
@@ -258,7 +258,10 @@ bool SaveLoad_v3::loadScreenshot(int16 dataVar, int32 size, int32 offset) {
}
in->seek(1040 + varSize * 2);
- return loadSprite(*in, size);
+
+ bool success = loadSprite(*in, size);
+ delete in;
+ return success;
} else
warning("Invalid attempt at loading a screenshot (%d, %d, %d, %d)",
diff --git a/engines/gob/scenery.h b/engines/gob/scenery.h
index 32ff727c46..acb7aecba7 100644
--- a/engines/gob/scenery.h
+++ b/engines/gob/scenery.h
@@ -38,7 +38,7 @@ public:
int16 right; //These are stored in Little Endian format
int16 top; //And should be converted by client code when accessed
int16 bottom; //i.e. use FROM_LE_16()
- };
+ } PACKED_STRUCT;
struct StaticPlane {
int8 pictIndex;
@@ -47,13 +47,13 @@ public:
int16 destX;
int16 destY;
int8 transp;
- };
+ } PACKED_STRUCT;
struct StaticLayer {
int16 backResId;
int16 planeCount;
StaticPlane *planes;
- };
+ } PACKED_STRUCT;
// Animations
@@ -63,7 +63,7 @@ public:
int8 destX;
int8 destY;
int8 notFinal;
- };
+ } PACKED_STRUCT;
struct AnimLayer {
int16 unknown0;
@@ -74,7 +74,7 @@ public:
int8 transp;
int16 framesCount;
AnimFramePiece *frames;
- };
+ } PACKED_STRUCT;
#include "common/pack-end.h" // END STRUCT PACKING
diff --git a/engines/gob/sound.cpp b/engines/gob/sound.cpp
index e3a4715920..b47e6795ac 100644
--- a/engines/gob/sound.cpp
+++ b/engines/gob/sound.cpp
@@ -35,8 +35,6 @@
namespace Gob {
-#define FRAC_BITS 16
-
void SoundDesc::set(SoundType type, SoundSource src,
byte *data, uint32 dSize) {
@@ -176,7 +174,6 @@ Snd::Snd(GobEngine *vm) : _vm(vm) {
_offset = 0;
_offsetFrac = 0;
_offsetInc = 0;
- _offsetIncFrac = 0;
_cur = 0;
_last = 0;
@@ -325,10 +322,7 @@ void Snd::setSample(SoundDesc &sndDesc, int16 repCount, int16 frequency,
_offset = 0;
_offsetFrac = 0;
-
- uint32 incr = (_freq << FRAC_BITS) / _rate;
- _offsetInc = incr >> FRAC_BITS;
- _offsetIncFrac = incr & ((1UL << FRAC_BITS) - 1);
+ _offsetInc = (_freq << FRAC_BITS) / _rate;
_last = _cur;
_cur = _data[0];
@@ -393,9 +387,6 @@ void Snd::checkEndSample() {
int Snd::readBuffer(int16 *buffer, const int numSamples) {
Common::StackLock slock(_mutex);
- int16 val;
- uint32 tmp, oldOffset;
-
for (int i = 0; i < numSamples; i++) {
if (!_data)
return i;
@@ -406,19 +397,18 @@ int Snd::readBuffer(int16 *buffer, const int numSamples) {
// Linear interpolation. See sound/rate.cpp
- val = (_last + (((_cur - _last) * _offsetFrac +
- (1UL << (FRAC_BITS - 1))) >> FRAC_BITS)) << 8;
- *buffer++ = (((int32) val) * _fadeVol) >> 16;
+ int32 val = (_last + (((_cur - _last) * _offsetFrac +
+ FRAC_HALF) >> FRAC_BITS)) << 8;
+ *buffer++ = (val * _fadeVol) >> 16;
- oldOffset = _offset;
-
- tmp = _offsetFrac + _offsetIncFrac;
- _offset += _offsetInc + (tmp >> FRAC_BITS);
- _offsetFrac = tmp & ((1UL << FRAC_BITS) - 1);
+ _offsetFrac += _offsetInc;
- if (oldOffset < _offset) {
+ // Was there an integral change?
+ if (fracToInt(_offsetFrac) > 0) {
_last = _cur;
- _cur = _data[oldOffset];
+ _cur = _data[_offset];
+ _offset += fracToInt(_offsetFrac);
+ _offsetFrac &= FRAC_LO_MASK;
}
if (_fade) {
diff --git a/engines/gob/sound.h b/engines/gob/sound.h
index 76b9f2b159..15909f5452 100644
--- a/engines/gob/sound.h
+++ b/engines/gob/sound.h
@@ -27,6 +27,7 @@
#define GOB_SOUND_H
#include "common/mutex.h"
+#include "common/frac.h"
#include "sound/audiostream.h"
#include "sound/mixer.h"
@@ -175,9 +176,8 @@ protected:
int32 _repCount;
uint32 _offset;
- uint32 _offsetFrac;
- uint32 _offsetInc;
- uint32 _offsetIncFrac;
+ frac_t _offsetFrac;
+ frac_t _offsetInc;
int16 _cur;
int16 _last;
diff --git a/engines/gob/video.cpp b/engines/gob/video.cpp
index 0bc87f42d5..6f88a5a993 100644
--- a/engines/gob/video.cpp
+++ b/engines/gob/video.cpp
@@ -235,7 +235,7 @@ void Video::drawLine(SurfaceDesc *dest, int16 x0, int16 y0, int16 x1,
/*
* The original's version of the Bresenham Algorithm was a bit "unclean"
- * and produced strange edges at 45°, 135°, 225° and 315°, so using the
+ * and produced strange edges at 45, 135, 225 and 315 degrees, so using the
* version found in the Wikipedia article about the
* "Bresenham's line algorithm" instead
*/
diff --git a/engines/gob/video.h b/engines/gob/video.h
index faa9555abb..51d02bd219 100644
--- a/engines/gob/video.h
+++ b/engines/gob/video.h
@@ -85,7 +85,7 @@ public:
byte red;
byte green;
byte blue;
- };
+ } PACKED_STRUCT;
#include "common/pack-end.h" // END STRUCT PACKING
diff --git a/engines/kyra/gui.cpp b/engines/kyra/gui.cpp
index 8cafb54fb8..6fc347158f 100644
--- a/engines/kyra/gui.cpp
+++ b/engines/kyra/gui.cpp
@@ -230,14 +230,14 @@ int KyraEngine::buttonAmuletCallback(Button *caller) {
drawJewelsFadeOutEnd(jewel);
_scriptInterpreter->initScript(_scriptClick, _scriptClickData);
- _scriptClick->variables[3] = 0;
- _scriptClick->variables[6] = jewel;
+ _scriptClick->regs[3] = 0;
+ _scriptClick->regs[6] = jewel;
_scriptInterpreter->startScript(_scriptClick, 4);
while (_scriptInterpreter->validScript(_scriptClick))
_scriptInterpreter->runScript(_scriptClick);
- if (_scriptClick->variables[3])
+ if (_scriptClick->regs[3])
return 1;
_unkAmuletVar = 1;
diff --git a/engines/kyra/kyra.cpp b/engines/kyra/kyra.cpp
index 249a5f6c21..1664ce144f 100644
--- a/engines/kyra/kyra.cpp
+++ b/engines/kyra/kyra.cpp
@@ -923,16 +923,16 @@ int KyraEngine::processInputHelper(int xpos, int ypos) {
int KyraEngine::clickEventHandler(int xpos, int ypos) {
debugC(9, kDebugLevelMain, "KyraEngine::clickEventHandler(%d, %d)", xpos, ypos);
_scriptInterpreter->initScript(_scriptClick, _scriptClickData);
- _scriptClick->variables[1] = xpos;
- _scriptClick->variables[2] = ypos;
- _scriptClick->variables[3] = 0;
- _scriptClick->variables[4] = _itemInHand;
+ _scriptClick->regs[1] = xpos;
+ _scriptClick->regs[2] = ypos;
+ _scriptClick->regs[3] = 0;
+ _scriptClick->regs[4] = _itemInHand;
_scriptInterpreter->startScript(_scriptClick, 1);
while (_scriptInterpreter->validScript(_scriptClick))
_scriptInterpreter->runScript(_scriptClick);
- return _scriptClick->variables[3];
+ return _scriptClick->regs[3];
}
void KyraEngine::updateMousePointer(bool forceUpdate) {
@@ -1068,10 +1068,10 @@ void KyraEngine::clickEventHandler2() {
Common::Point mouse = getMousePos();
_scriptInterpreter->initScript(_scriptClick, _scriptClickData);
- _scriptClick->variables[0] = _currentCharacter->sceneId;
- _scriptClick->variables[1] = mouse.x;
- _scriptClick->variables[2] = mouse.y;
- _scriptClick->variables[4] = _itemInHand;
+ _scriptClick->regs[0] = _currentCharacter->sceneId;
+ _scriptClick->regs[1] = mouse.x;
+ _scriptClick->regs[2] = mouse.y;
+ _scriptClick->regs[4] = _itemInHand;
_scriptInterpreter->startScript(_scriptClick, 6);
while (_scriptInterpreter->validScript(_scriptClick))
@@ -1132,9 +1132,9 @@ void KyraEngine::runNpcScript(int func) {
debugC(9, kDebugLevelMain, "KyraEngine::runNpcScript(%d)", func);
_scriptInterpreter->initScript(_npcScript, _npcScriptData);
_scriptInterpreter->startScript(_npcScript, func);
- _npcScript->variables[0] = _currentCharacter->sceneId;
- _npcScript->variables[4] = _itemInHand;
- _npcScript->variables[5] = func;
+ _npcScript->regs[0] = _currentCharacter->sceneId;
+ _npcScript->regs[4] = _itemInHand;
+ _npcScript->regs[5] = func;
while (_scriptInterpreter->validScript(_npcScript))
_scriptInterpreter->runScript(_npcScript);
diff --git a/engines/kyra/resource.cpp b/engines/kyra/resource.cpp
index 319845c22c..2425444be1 100644
--- a/engines/kyra/resource.cpp
+++ b/engines/kyra/resource.cpp
@@ -195,15 +195,22 @@ uint8 *Resource::fileData(const char *file, uint32 *size) const {
if (!(*cur)->isOpen())
continue;
- uint32 fileSize = (*cur)->getFileSize(fileHash);
- if (!fileSize)
- continue;
+ uint8* result = (*cur)->getFile(fileHash);
+
+ if (result) {
+ uint32 fileSize = (*cur)->getFileSize(fileHash);
+
+ if (!fileSize)
+ continue;
+
+ if (size)
+ *size = fileSize;
+
+ return result;
+ }
- if (size)
- *size = fileSize;
- return (*cur)->getFile(fileHash);
}
}
@@ -221,13 +228,15 @@ bool Resource::getFileHandle(const char *file, uint32 *size, Common::File &fileh
if (!(*start)->isOpen())
continue;
- *size = (*start)->getFileSize(fileHash);
+ if ((*start)->getFileHandle(fileHash, filehandle)) {
+
+ *size = (*start)->getFileSize(fileHash);
- if (!(*size))
- continue;
+ if (!(*size))
+ continue;
- if ((*start)->getFileHandle(fileHash, filehandle))
return true;
+ }
}
return false;
diff --git a/engines/kyra/scene.cpp b/engines/kyra/scene.cpp
index 2ba1870fcd..a92fd9ce7c 100644
--- a/engines/kyra/scene.cpp
+++ b/engines/kyra/scene.cpp
@@ -450,8 +450,8 @@ void KyraEngine::startSceneScript(int brandonAlive) {
_scriptInterpreter->unloadScript(_scriptClickData);
_scriptInterpreter->loadScript(fileNameBuffer, _scriptClickData, &_opcodes);
_scriptInterpreter->startScript(_scriptClick, 0);
- _scriptClick->variables[0] = _currentCharacter->sceneId;
- _scriptClick->variables[7] = brandonAlive;
+ _scriptClick->regs[0] = _currentCharacter->sceneId;
+ _scriptClick->regs[7] = brandonAlive;
while (_scriptInterpreter->validScript(_scriptClick))
_scriptInterpreter->runScript(_scriptClick);
@@ -620,8 +620,8 @@ void KyraEngine::initSceneData(int facing, int unk1, int brandonAlive) {
if (unk1 && brandonAlive == 0)
moveCharacterToPos(0, facing, xpos2, ypos2);
- _scriptClick->variables[4] = _itemInHand;
- _scriptClick->variables[7] = brandonAlive;
+ _scriptClick->regs[4] = _itemInHand;
+ _scriptClick->regs[7] = brandonAlive;
_scriptInterpreter->startScript(_scriptClick, 3);
while (_scriptInterpreter->validScript(_scriptClick))
_scriptInterpreter->runScript(_scriptClick);
@@ -852,7 +852,7 @@ void KyraEngine::initSceneScreen(int brandonAlive) {
if (!_scriptInterpreter->startScript(_scriptClick, 2))
error("Could not start script function 2 of scene script");
- _scriptClick->variables[7] = brandonAlive;
+ _scriptClick->regs[7] = brandonAlive;
while (_scriptInterpreter->validScript(_scriptClick))
_scriptInterpreter->runScript(_scriptClick);
diff --git a/engines/kyra/screen.cpp b/engines/kyra/screen.cpp
index 02eb1c9ea7..641a034eab 100644
--- a/engines/kyra/screen.cpp
+++ b/engines/kyra/screen.cpp
@@ -504,7 +504,12 @@ void Screen::copyToPage0(int y, int h, uint8 page, uint8 *seqBuf) {
dstPage += SCREEN_W;
}
addDirtyRect(0, y, SCREEN_W, h);
- clearOverlayRect(0, 0, y, SCREEN_W, h);
+ // This would remove the text in the end sequence of
+ // the FM-Towns version.
+ // Since this method is just used for the Seqplayer
+ // this shouldn't be a problem anywhere else, so it's
+ // safe to disable the call here.
+ //clearOverlayRect(0, 0, y, SCREEN_W, h);
}
void Screen::copyRegion(int x1, int y1, int x2, int y2, int w, int h, int srcPage, int dstPage, int flags) {
diff --git a/engines/kyra/script.cpp b/engines/kyra/script.cpp
index c2ec984d5c..b43cd3b471 100644
--- a/engines/kyra/script.cpp
+++ b/engines/kyra/script.cpp
@@ -49,12 +49,12 @@ ScriptHelper::ScriptHelper(KyraEngine *vm) : _vm(vm) {
COMMAND(c1_push),
// 0x04
COMMAND(c1_push),
- COMMAND(c1_pushVar),
+ COMMAND(c1_pushReg),
COMMAND(c1_pushBPNeg),
COMMAND(c1_pushBPAdd),
// 0x08
COMMAND(c1_popRetOrPos),
- COMMAND(c1_popVar),
+ COMMAND(c1_popReg),
COMMAND(c1_popBPNeg),
COMMAND(c1_popBPAdd),
// 0x0C
@@ -324,8 +324,8 @@ void ScriptHelper::c1_push(ScriptState* script) {
script->stack[--script->sp] = _parameter;
}
-void ScriptHelper::c1_pushVar(ScriptState* script) {
- script->stack[--script->sp] = script->variables[_parameter];
+void ScriptHelper::c1_pushReg(ScriptState* script) {
+ script->stack[--script->sp] = script->regs[_parameter];
}
void ScriptHelper::c1_pushBPNeg(ScriptState* script) {
@@ -359,8 +359,8 @@ void ScriptHelper::c1_popRetOrPos(ScriptState* script) {
}
}
-void ScriptHelper::c1_popVar(ScriptState* script) {
- script->variables[_parameter] = script->stack[script->sp++];
+void ScriptHelper::c1_popReg(ScriptState* script) {
+ script->regs[_parameter] = script->stack[script->sp++];
}
void ScriptHelper::c1_popBPNeg(ScriptState* script) {
diff --git a/engines/kyra/script.h b/engines/kyra/script.h
index dfca7700a1..5e43039110 100644
--- a/engines/kyra/script.h
+++ b/engines/kyra/script.h
@@ -70,8 +70,8 @@ struct ScriptState {
int16 retValue;
uint16 bp;
uint16 sp;
- int16 variables[30];
- int16 stack[61];
+ int16 regs[30]; // VM registers
+ int16 stack[61]; // VM stack
};
class ScriptHelper {
@@ -99,7 +99,7 @@ protected:
typedef void (ScriptHelper::*CommandProc)(ScriptState*);
struct CommandEntry {
CommandProc proc;
- const char* desc;
+ const char *desc;
};
const CommandEntry *_commands;
@@ -109,11 +109,11 @@ private:
void c1_pushRetOrPos(ScriptState*);
void c1_push(ScriptState*);
//void c1_push(); same as 03
- void c1_pushVar(ScriptState*);
+ void c1_pushReg(ScriptState*);
void c1_pushBPNeg(ScriptState*);
void c1_pushBPAdd(ScriptState*);
void c1_popRetOrPos(ScriptState*);
- void c1_popVar(ScriptState*);
+ void c1_popReg(ScriptState*);
void c1_popBPNeg(ScriptState*);
void c1_popBPAdd(ScriptState*);
void c1_addSP(ScriptState*);
diff --git a/engines/kyra/script_v1.cpp b/engines/kyra/script_v1.cpp
index 8e604b972b..87123222fb 100644
--- a/engines/kyra/script_v1.cpp
+++ b/engines/kyra/script_v1.cpp
@@ -1379,8 +1379,8 @@ int KyraEngine_v1::o1_waitForConfirmationMouseClick(ScriptState *script) {
processButtonList(_buttonList);
_skipFlag = false;
Common::Point mouse = getMousePos();
- script->variables[1] = mouse.x;
- script->variables[2] = mouse.y;
+ script->regs[1] = mouse.x;
+ script->regs[2] = mouse.y;
return 0;
}
diff --git a/engines/kyra/sound_digital.cpp b/engines/kyra/sound_digital.cpp
index e2f92c9925..72d19ffd32 100644
--- a/engines/kyra/sound_digital.cpp
+++ b/engines/kyra/sound_digital.cpp
@@ -29,7 +29,7 @@
namespace Kyra {
-// Thanks to Torbjörn Andersson (eriktorbjorn) for his aud player on which
+// Thanks to Torbjorn Andersson (eriktorbjorn) for his aud player on which
// this code is based on
// TODO: cleanup of whole AUDStream
diff --git a/engines/lure/res_struct.h b/engines/lure/res_struct.h
index 59581b9c7d..b5e4aef724 100644
--- a/engines/lure/res_struct.h
+++ b/engines/lure/res_struct.h
@@ -47,7 +47,7 @@ struct VersionStructure {
uint16 id;
byte vMajor;
byte vMinor;
-};
+} PACKED_STRUCT;
struct FileEntry {
uint16 id;
@@ -55,7 +55,7 @@ struct FileEntry {
byte sizeExtension;
uint16 size;
uint16 offset;
-};
+} PACKED_STRUCT;
struct HotspotResource {
uint16 hotspotId;
@@ -91,7 +91,7 @@ struct HotspotResource {
uint16 delayCtr;
byte flags2;
byte hdrFlags;
-};
+} PACKED_STRUCT;
struct HotspotAnimResource {
uint16 animRecordId;
@@ -105,18 +105,18 @@ struct HotspotAnimResource {
uint8 downFrame;
uint8 leftFrame;
uint8 rightFrame;
-};
+} PACKED_STRUCT;
struct MovementResource {
uint16 frameNumber;
int16 xChange;
int16 yChange;
-};
+} PACKED_STRUCT;
struct RoomRect {
int16 xs, xe;
int16 ys, ye;
-};
+} PACKED_STRUCT;
struct RoomResource {
uint16 roomNumber;
@@ -133,7 +133,7 @@ struct RoomResource {
uint8 areaFlag;
RoomRect walkBounds;
uint16 numExits;
-};
+} PACKED_STRUCT;
struct RoomExitResource {
int16 xs, xe, ys, ye;
@@ -141,12 +141,12 @@ struct RoomExitResource {
uint8 newRoom;
uint8 direction;
int16 newRoomX, newRoomY;
-};
+} PACKED_STRUCT;
struct HotspotOverrideResource {
uint16 hotspotId;
int16 xs, xe, ys, ye;
-};
+} PACKED_STRUCT;
struct RoomExitHotspotResource {
uint16 hotspotId;
@@ -154,7 +154,7 @@ struct RoomExitHotspotResource {
int16 ys, ye;
uint16 cursorNum;
uint16 destRoomNumber;
-};
+} PACKED_STRUCT;
struct RoomExitJoinResource {
uint16 hotspot1Id;
@@ -168,41 +168,41 @@ struct RoomExitJoinResource {
uint8 h2OpenSound;
uint8 h2CloseSound;
byte blocked;
-};
+} PACKED_STRUCT;
struct HotspotActionResource {
byte action;
uint16 sequenceOffset;
-};
+} PACKED_STRUCT;
struct TalkHeaderResource {
uint16 hotspotId;
uint16 offset;
-};
+} PACKED_STRUCT;
struct TalkDataHeaderResource {
uint16 recordId;
uint16 listOffset;
uint16 responsesOffset;
-};
+} PACKED_STRUCT;
struct TalkDataResource {
uint16 preSequenceId;
uint16 descId;
uint16 postSequenceId;
-};
+} PACKED_STRUCT;
struct TalkResponseResource {
uint16 sequenceId1;
uint16 sequenceId2;
uint16 sequenceId3;
-};
+} PACKED_STRUCT;
struct RoomExitCoordinateResource {
int16 x;
int16 y;
uint16 roomNumber;
-};
+} PACKED_STRUCT;
#define ROOM_EXIT_COORDINATES_NUM_ENTRIES 6
#define ROOM_EXIT_COORDINATES_NUM_ROOMS 52
@@ -210,20 +210,20 @@ struct RoomExitCoordinateResource {
struct RoomExitCoordinateEntryResource {
uint8 roomIndex[ROOM_EXIT_COORDINATES_NUM_ROOMS];
RoomExitCoordinateResource entries[ROOM_EXIT_COORDINATES_NUM_ENTRIES];
-};
+} PACKED_STRUCT;
#define MAX_SCHEDULE_ENTRY_PARAMS 5
struct CharacterScheduleResource {
uint16 action;
uint16 params[MAX_SCHEDULE_ENTRY_PARAMS];
-};
+} PACKED_STRUCT;
struct RoomExitIndexedHotspotResource {
uint8 roomNumber;
uint8 hotspotIndex;
uint16 hotspotId;
-};
+} PACKED_STRUCT;
#include "common/pack-end.h" // END STRUCT PACKING
diff --git a/engines/parallaction/animation.cpp b/engines/parallaction/animation.cpp
index 33caaa1b58..d4f538c451 100644
--- a/engines/parallaction/animation.cpp
+++ b/engines/parallaction/animation.cpp
@@ -166,15 +166,19 @@ void jobDisplayAnimations(void *parm, Job *j) {
if ((v18->_flags & kFlagsActive) && ((v18->_flags & kFlagsRemove) == 0)) {
v14._width = v18->width();
v14._height = v18->height();
- v14._data0 = v18->getFrameData(v18->_frame);
-// v14._data1 = v18->_cnv->field_8[v18->_frame];
+
+ int16 frame = CLIP((int)v18->_frame, 0, v18->getFrameNum()-1);
+
+ v14._data0 = v18->getFrameData(frame);
+// v14._data1 = v18->_cnv->field_8[frame];
if (v18->_flags & kFlagsNoMasked)
_si = 3;
else
_si = _vm->_gfx->queryMask(v18->_top + v18->height());
- debugC(9, kDebugLocation, "jobDisplayAnimations(%s, x:%i, y:%i, z:%i, w:%i, h:%i, %p)", v18->_label._text, v18->_left, v18->_top, _si, v14._width, v14._height, v14._data0);
+ debugC(9, kDebugLocation, "jobDisplayAnimations(%s, x:%i, y:%i, z:%i, w:%i, h:%i, f:%i/%i, %p)", v18->_label._text, v18->_left, v18->_top, _si, v14._width, v14._height,
+ frame, v18->getFrameNum(), v14._data0);
_vm->_gfx->blitCnv(&v14, v18->_left, v18->_top, _si, Gfx::kBitBack);
}
diff --git a/engines/parallaction/archive.cpp b/engines/parallaction/archive.cpp
index b678b6df3c..9eef3f44e9 100644
--- a/engines/parallaction/archive.cpp
+++ b/engines/parallaction/archive.cpp
@@ -37,7 +37,7 @@ namespace Parallaction {
// Amiga version of Nippon Safes, and one archive ('fr') in the Amiga Demo of
// Nippon Safes used different internal offsets than all the other archives.
//
-// When an archive is opened in the Amiga demo, its size is checked against
+// When an archive is opened in the Amiga demo, its size is checked against
// SIZEOF_SMALL_ARCHIVE to detect when the smaller archive is used.
//
// When an archive is opened in Amiga multi-lingual version, the header is
@@ -72,6 +72,8 @@ void Archive::open(const char *file) {
if (!_archive.open(path))
error("archive '%s' not found", path);
+ _archiveName = file;
+
bool isSmallArchive = false;
if (_vm->getPlatform() == Common::kPlatformAmiga) {
if (_vm->getFeatures() & GF_DEMO) {
@@ -105,8 +107,12 @@ void Archive::close() {
resetArchivedFile();
_archive.close();
+ _archiveName.clear();
}
+Common::String Archive::name() const {
+ return _archiveName;
+}
bool Archive::openArchivedFile(const char *filename) {
debugC(3, kDebugDisk, "Archive::openArchivedFile(%s)", filename);
diff --git a/engines/parallaction/callables.cpp b/engines/parallaction/callables.cpp
index 1154250ffa..be92ca1daa 100644
--- a/engines/parallaction/callables.cpp
+++ b/engines/parallaction/callables.cpp
@@ -253,7 +253,7 @@ void _c_endComment(void *param) {
_vm->_gfx->floodFill(Gfx::kBitFront, r, 1);
_vm->_gfx->setFont(kFontDialogue);
- _vm->_gfx->displayWrappedString(_vm->_location._endComment, 3, 5, 130, 0);
+ _vm->_gfx->displayWrappedString(_vm->_location._endComment, 3, 5, 0, 130);
_vm->_gfx->updateScreen();
uint32 di = 0;
diff --git a/engines/parallaction/defs.h b/engines/parallaction/defs.h
index d7dc3388e7..c41130670e 100644
--- a/engines/parallaction/defs.h
+++ b/engines/parallaction/defs.h
@@ -28,6 +28,7 @@
#include "common/stdafx.h"
#include "common/list.h"
+#include "common/rect.h"
namespace Parallaction {
diff --git a/engines/parallaction/dialogue.cpp b/engines/parallaction/dialogue.cpp
index b3de3e5da3..7d2224164a 100644
--- a/engines/parallaction/dialogue.cpp
+++ b/engines/parallaction/dialogue.cpp
@@ -46,10 +46,6 @@ namespace Parallaction {
#define ANSWER_CHARACTER_X 10
#define ANSWER_CHARACTER_Y 80
-
-void enterDialogue();
-void exitDialogue();
-
int16 selectAnswer(Question *q, StaticCnv*);
int16 getHoverAnswer(int16 x, int16 y, Question *q);
@@ -62,110 +58,109 @@ int16 _answerBalloonH[10] = { 0 };
Dialogue *Parallaction::parseDialogue(Script &script) {
// printf("parseDialogue()\n");
- uint16 num_questions = 0;
- uint16 v50[20];
- Table _questions_names(20);
- Question *_questions[20];
+ uint16 numQuestions = 0;
- for (uint16 _si = 0; _si < 20; _si++) {
- v50[_si] = 0;
- }
+ Dialogue *dialogue = new Dialogue;
+
+ Table forwards(20);
fillBuffers(script, true);
while (scumm_stricmp(_tokens[0], "enddialogue")) {
if (scumm_stricmp(_tokens[0], "Question")) continue;
- _questions[num_questions] = new Dialogue;
- Dialogue *vB4 = _questions[num_questions];
+ Question *question = new Question;
+ dialogue->_questions[numQuestions] = question;
- _questions_names.addData(_tokens[1]);
+ forwards.addData(_tokens[1]);
- vB4->_text = parseDialogueString(script);
-// printf("Question: '%s'\n", vB4->_text);
+ question->_text = parseDialogueString(script);
fillBuffers(script, true);
- vB4->_mood = atoi(_tokens[0]);
+ question->_mood = atoi(_tokens[0]);
- uint16 _di = 0;
+ uint16 numAnswers = 0;
fillBuffers(script, true);
while (scumm_stricmp(_tokens[0], "endquestion")) { // parse answers
- vB4->_answers[_di] = new Answer;
+ Answer *answer = new Answer;
+ question->_answers[numAnswers] = answer;
if (_tokens[1][0]) {
- Table* v60 = _localFlagNames;
- uint16 v56 = 1;
+ Table* flagNames;
+ uint16 token;
if (!scumm_stricmp(_tokens[1], "global")) {
- v56 = 2;
- v60 = _globalTable;
- vB4->_answers[_di]->_yesFlags |= kFlagsGlobal;
+ token = 2;
+ flagNames = _globalTable;
+ answer->_yesFlags |= kFlagsGlobal;
+ } else {
+ token = 1;
+ flagNames = _localFlagNames;
}
do {
- if (!scumm_strnicmp(_tokens[v56], "no", 2)) {
- byte _al = v60->lookup(_tokens[v56]+2);
- vB4->_answers[_di]->_noFlags |= 1 << (_al - 1);
+ if (!scumm_strnicmp(_tokens[token], "no", 2)) {
+ byte _al = flagNames->lookup(_tokens[token]+2);
+ answer->_noFlags |= 1 << (_al - 1);
} else {
- byte _al = v60->lookup(_tokens[v56]);
- vB4->_answers[_di]->_yesFlags |= 1 << (_al - 1);
+ byte _al = flagNames->lookup(_tokens[token]);
+ answer->_yesFlags |= 1 << (_al - 1);
}
- v56++;
+ token++;
- } while (!scumm_stricmp(_tokens[v56++], "|"));
+ } while (!scumm_stricmp(_tokens[token++], "|"));
}
- vB4->_answers[_di]->_text = parseDialogueString(script);
-
-// printf("answer[%i]: '%s'\n", _di, vB4->_answers[_di]);
+ answer->_text = parseDialogueString(script);
fillBuffers(script, true);
- vB4->_answers[_di]->_mood = atoi(_tokens[0]);
- vB4->_answers[_di]->_following._name = parseDialogueString(script);
+ answer->_mood = atoi(_tokens[0]);
+ answer->_following._name = parseDialogueString(script);
fillBuffers(script, true);
if (!scumm_stricmp(_tokens[0], "commands")) {
- parseCommands(script, vB4->_answers[_di]->_commands);
+ parseCommands(script, answer->_commands);
fillBuffers(script, true);
}
- _di++;
+ numAnswers++;
}
fillBuffers(script, true);
- num_questions++;
+ numQuestions++;
}
- for (uint16 _si = 0; _si <num_questions; _si++) {
+ // link questions
+ byte v50[20];
+ memset(v50, 0, 20);
- for (uint16 v5A = 0; v5A < 5; v5A++) {
- if (_questions[_si]->_answers[v5A] == 0) continue;
+ for (uint16 i = 0; i < numQuestions; i++) {
+ Question *question = dialogue->_questions[i];
- int16 v58 = _questions_names.lookup(_questions[_si]->_answers[v5A]->_following._name);
- free(_questions[_si]->_answers[v5A]->_following._name);
+ for (uint16 j = 0; j < NUM_ANSWERS; j++) {
+ Answer *answer = question->_answers[j];
+ if (answer == 0) continue;
- if (v58 == -1) {
- _questions[_si]->_answers[v5A]->_following._question = 0;
- } else {
- _questions[_si]->_answers[v5A]->_following._question = _questions[v58-1];
+ int16 index = forwards.lookup(answer->_following._name);
+ free(answer->_following._name);
+
+ if (index == -1)
+ answer->_following._question = 0;
+ else
+ answer->_following._question = dialogue->_questions[index - 1];
- if (v50[v58]) {
- _questions[_si]->_answers[v5A]->_mood |= 0x10;
- }
- v50[v58] = 1;
- }
}
}
- return _questions[0];
+ return dialogue;
}
@@ -183,7 +178,7 @@ char *Parallaction::parseDialogueString(Script &script) {
} while (strlen(vD0) == 0);
vD0[strlen(vD0)-1] = '\0'; // deletes the trailing '0xA'
- // this is critical for Gfx::displayBalloonString to work properly
+ // this is critical for Gfx::displayWrappedString to work properly
char *vCC = (char*)malloc(strlen(vD0)+1);
strcpy(vCC, vD0);
@@ -191,23 +186,71 @@ char *Parallaction::parseDialogueString(Script &script) {
return vCC;
}
-uint16 Parallaction::askDialoguePassword(Dialogue *q, StaticCnv *face) {
+class DialogueManager {
+
+ Parallaction *_vm;
+ SpeakData *_data;
+ Dialogue *_dialogue;
+
+ bool _askPassword;
+
+ bool isNpc;
+ Cnv *_questioner;
+ Cnv *_answerer;
+
+ Question *_q;
+
+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() {
+ if (isNpc) {
+ delete _questioner;
+ }
+ }
+
+ void run();
+
+protected:
+ void clear() {
+ _vm->_gfx->copyScreen(Gfx::kBitBack, Gfx::kBitFront);
+ }
+
+ void displayQuestion();
+ bool displayAnswers();
+ bool displayAnswer(uint16 i);
+
+ uint16 getAnswer();
+ int16 selectAnswer();
+ uint16 askPassword();
+ int16 getHoverAnswer(int16 x, int16 y);
+
+};
+
+uint16 DialogueManager::askPassword() {
debugC(1, kDebugDialogue, "checkDialoguePassword()");
char password[100];
uint16 passwordLen = 0;
while (true) {
+ clear();
+
strcpy(password, ".......");
- _gfx->copyScreen(Gfx::kBitBack, Gfx::kBitFront);
Common::Rect r(_answerBalloonW[0], _answerBalloonH[0]);
r.moveTo(_answerBalloonX[0], _answerBalloonY[0]);
- _gfx->drawBalloon(r, 1);
- _gfx->displayWrappedString(q->_answers[0]->_text, _answerBalloonX[0], _answerBalloonY[0], MAX_BALLOON_WIDTH, 3);
- _gfx->flatBlitCnv(face, ANSWER_CHARACTER_X, ANSWER_CHARACTER_Y, Gfx::kBitFront);
- _gfx->displayBalloonString(_answerBalloonX[0] + 5, _answerBalloonY[0] + _answerBalloonH[0] - 15, "> ", 0);
+ _vm->_gfx->drawBalloon(r, 1);
+ _vm->_gfx->displayWrappedString(_q->_answers[0]->_text, _answerBalloonX[0], _answerBalloonY[0], 3, MAX_BALLOON_WIDTH);
+ _vm->_gfx->flatBlitCnv(_answerer, 0, ANSWER_CHARACTER_X, ANSWER_CHARACTER_Y, Gfx::kBitFront);
+ _vm->_gfx->displayString(_answerBalloonX[0] + 5, _answerBalloonY[0] + _answerBalloonH[0] - 15, "> ", 0);
+ _vm->_gfx->updateScreen();
Common::Event e;
while (e.kbd.ascii != Common::KEYCODE_RETURN && passwordLen < MAX_PASSWORD_LENGTH) {
@@ -223,15 +266,15 @@ uint16 Parallaction::askDialoguePassword(Dialogue *q, StaticCnv *face) {
passwordLen++;
password[passwordLen] = '\0';
- _gfx->displayBalloonString(_answerBalloonX[0] + 5, _answerBalloonY[0] + _answerBalloonH[0] - 15, password, 0);
- _gfx->updateScreen();
+ _vm->_gfx->displayString(_answerBalloonX[0] + 10, _answerBalloonY[0] + _answerBalloonH[0] - 15, password, 0);
+ _vm->_gfx->updateScreen();
g_system->delayMillis(20);
}
- if ((!scumm_stricmp(_characterName, _doughName) && !scumm_strnicmp(password, "1732461", 7)) ||
- (!scumm_stricmp(_characterName, _donnaName) && !scumm_strnicmp(password, "1622", 4)) ||
- (!scumm_stricmp(_characterName, _dinoName) && !scumm_strnicmp(password, "179", 3))) {
+ if ((!scumm_stricmp(_vm->_characterName, _doughName) && !scumm_strnicmp(password, "1732461", 7)) ||
+ (!scumm_stricmp(_vm->_characterName, _donnaName) && !scumm_strnicmp(password, "1622", 4)) ||
+ (!scumm_stricmp(_vm->_characterName, _dinoName) && !scumm_strnicmp(password, "179", 3))) {
break;
@@ -243,165 +286,135 @@ uint16 Parallaction::askDialoguePassword(Dialogue *q, StaticCnv *face) {
}
-bool _askPassword;
-bool Parallaction::displayAnswer(Dialogue *q, uint16 i) {
- uint32 v28 = _localFlags[_currentLocationIndex];
- if (q->_answers[i]->_yesFlags & kFlagsGlobal)
+bool DialogueManager::displayAnswer(uint16 i) {
+
+ uint32 v28 = _localFlags[_vm->_currentLocationIndex];
+ if (_q->_answers[i]->_yesFlags & kFlagsGlobal)
v28 = _commandFlags | kFlagsGlobal;
// display suitable answers
- if (((q->_answers[i]->_yesFlags & v28) == q->_answers[i]->_yesFlags) && ((q->_answers[i]->_noFlags & ~v28) == q->_answers[i]->_noFlags)) {
+ if (((_q->_answers[i]->_yesFlags & v28) == _q->_answers[i]->_yesFlags) && ((_q->_answers[i]->_noFlags & ~v28) == _q->_answers[i]->_noFlags)) {
- _gfx->getStringExtent(q->_answers[i]->_text, MAX_BALLOON_WIDTH, &_answerBalloonW[i], &_answerBalloonH[i]);
+ _vm->_gfx->getStringExtent(_q->_answers[i]->_text, MAX_BALLOON_WIDTH, &_answerBalloonW[i], &_answerBalloonH[i]);
Common::Rect r(_answerBalloonW[i], _answerBalloonH[i]);
r.moveTo(_answerBalloonX[i], _answerBalloonY[i]);
- _gfx->drawBalloon(r, 1);
+ _vm->_gfx->drawBalloon(r, 1);
_answerBalloonY[i+1] = 10 + _answerBalloonY[i] + _answerBalloonH[i];
- _askPassword = _gfx->displayWrappedString(q->_answers[i]->_text, _answerBalloonX[i], _answerBalloonY[i], MAX_BALLOON_WIDTH, 3);
+ _askPassword = _vm->_gfx->displayWrappedString(_q->_answers[i]->_text, _answerBalloonX[i], _answerBalloonY[i], 3, MAX_BALLOON_WIDTH);
return true;
}
+ _answerBalloonY[i+1] = _answerBalloonY[i];
+ _answerBalloonY[i] = SKIPPED_ANSWER;
+
return false;
}
-bool Parallaction::displayAnswers(Dialogue *q) {
+bool DialogueManager::displayAnswers() {
bool displayed = false;
uint16 i = 0;
- while (i < NUM_ANSWERS && q->_answers[i]) {
- if (displayAnswer(q, i)) {
+ while (i < NUM_ANSWERS && _q->_answers[i]) {
+ if (displayAnswer(i))
displayed = true;
- } else {
- _answerBalloonY[i+1] = _answerBalloonY[i];
- _answerBalloonY[i] = SKIPPED_ANSWER;
- }
+
i++;
}
- _gfx->updateScreen();
+ _vm->_gfx->updateScreen();
return displayed;
}
-void Parallaction::displayQuestion(Dialogue *q, Cnv *cnv) {
+void DialogueManager::displayQuestion() {
int16 w = 0, h = 0;
- if (!scumm_stricmp(q->_text, "NULL")) return;
-
- StaticCnv face;
- face._width = cnv->_width;
- face._height = cnv->_height;
- face._data0 = cnv->getFramePtr(q->_mood & 0xF);
- face._data1 = NULL; // cnv->field_8[v60->_mood & 0xF];
+ if (!scumm_stricmp(_q->_text, "NULL")) return;
- _gfx->flatBlitCnv(&face, QUESTION_CHARACTER_X, QUESTION_CHARACTER_Y, Gfx::kBitFront);
- _gfx->getStringExtent(q->_text, MAX_BALLOON_WIDTH, &w, &h);
+ _vm->_gfx->flatBlitCnv(_questioner, _q->_mood & 0xF, QUESTION_CHARACTER_X, QUESTION_CHARACTER_Y, Gfx::kBitFront);
+ _vm->_gfx->getStringExtent(_q->_text, MAX_BALLOON_WIDTH, &w, &h);
Common::Rect r(w, h);
r.moveTo(QUESTION_BALLOON_X, QUESTION_BALLOON_Y);
- _gfx->drawBalloon(r, q->_mood & 0x10);
- _gfx->displayWrappedString(q->_text, QUESTION_BALLOON_X, QUESTION_BALLOON_Y, MAX_BALLOON_WIDTH, 0);
- _gfx->updateScreen();
+ _vm->_gfx->drawBalloon(r, _q->_mood & 0x10);
+ _vm->_gfx->displayWrappedString(_q->_text, QUESTION_BALLOON_X, QUESTION_BALLOON_Y, 0, MAX_BALLOON_WIDTH);
+ _vm->_gfx->updateScreen();
waitUntilLeftClick();
- _gfx->copyScreen(Gfx::kBitBack, Gfx::kBitFront);
+ clear();
return;
}
-uint16 Parallaction::getDialogueAnswer(Dialogue *q, Cnv *cnv) {
+uint16 DialogueManager::getAnswer() {
uint16 answer = 0;
- StaticCnv face;
- face._width = cnv->_width;
- face._height = cnv->_height;
- face._data0 = cnv->getFramePtr(0);
- face._data1 = NULL; // cnv->field_8[0];
-
- _gfx->flatBlitCnv(&face, ANSWER_CHARACTER_X, ANSWER_CHARACTER_Y, Gfx::kBitFront);
-
if (_askPassword == false) {
- answer = selectAnswer(q, &face);
+ answer = selectAnswer();
} else {
- answer = askDialoguePassword(q, &face);
+ answer = askPassword();
}
- _gfx->copyScreen(Gfx::kBitBack, Gfx::kBitFront); // erase answer screen
+ clear();
debugC(1, kDebugDialogue, "runDialogue: user selected answer #%i", answer);
return answer;
}
-void Parallaction::runDialogue(SpeakData *data) {
- debugC(1, kDebugDialogue, "runDialogue: starting dialogue '%s'", data->_name);
-
- enterDialogue();
-
- _gfx->setFont(kFontDialogue);
-
- bool isNpc = scumm_stricmp(data->_name, "yourself") && data->_name[0] != '\0';
- Cnv *face = isNpc ? _disk->loadTalk(data->_name) : _char._talk;
+void DialogueManager::run() {
_askPassword = false;
CommandList *cmdlist = NULL;
- uint16 answer;
- Dialogue *q = data->_dialogue;
- while (q) {
+ _q = _dialogue->_questions[0];
+ int16 answer;
+
+ while (_q) {
answer = 0;
- displayQuestion(q, face);
- if (q->_answers[0] == NULL) break;
+ displayQuestion();
+ if (_q->_answers[0] == NULL) break;
_answerBalloonY[0] = 10;
- if (scumm_stricmp(q->_answers[0]->_text, "NULL")) {
- if (!displayAnswers(q)) break;
- answer = getDialogueAnswer(q, _char._talk);
- cmdlist = &q->_answers[answer]->_commands;
+ if (scumm_stricmp(_q->_answers[0]->_text, "NULL")) {
+ if (!displayAnswers()) break;
+ answer = getAnswer();
+ cmdlist = &_q->_answers[answer]->_commands;
}
- q = q->_answers[answer]->_following._question;
+ _q = _q->_answers[answer]->_following._question;
}
- debugC(1, kDebugDialogue, "runDialogue: out of dialogue loop");
-
- _gfx->copyScreen(Gfx::kBitBack, Gfx::kBitFront);
-
- if (isNpc) {
- delete face;
- }
+ clear();
- exitDialogue();
if (cmdlist)
- runCommands(*cmdlist);
-
- return;
+ _vm->runCommands(*cmdlist);
}
-int16 Parallaction::selectAnswer(Question *q, StaticCnv *cnv) {
+int16 DialogueManager::selectAnswer() {
int16 numAvailableAnswers = 0;
int16 _si = 0;
int16 _di = 0;
int16 i = 0;
- for (; q->_answers[i]; i++) {
+ for (; _q->_answers[i]; i++) {
if (_answerBalloonY[i] == SKIPPED_ANSWER) continue;
_di = i;
@@ -410,11 +423,9 @@ int16 Parallaction::selectAnswer(Question *q, StaticCnv *cnv) {
_answerBalloonY[i] = 2000;
if (numAvailableAnswers == 1) {
- _gfx->displayWrappedString(q->_answers[_di]->_text, _answerBalloonX[_di], _answerBalloonY[_di], MAX_BALLOON_WIDTH, 0);
- cnv->_data0 = _char._talk->getFramePtr(q->_answers[_di]->_mood & 0xF);
-// cnv->_data1 = _char._talk->field_8[q->_answers[_di]->_mood & 0xF];
- _gfx->flatBlitCnv(cnv, ANSWER_CHARACTER_X, ANSWER_CHARACTER_Y, Gfx::kBitFront);
- _gfx->updateScreen();
+ _vm->_gfx->displayWrappedString(_q->_answers[_di]->_text, _answerBalloonX[_di], _answerBalloonY[_di], 0, MAX_BALLOON_WIDTH);
+ _vm->_gfx->flatBlitCnv(_answerer, _q->_answers[_di]->_mood & 0xF, ANSWER_CHARACTER_X, ANSWER_CHARACTER_Y, Gfx::kBitFront);
+ _vm->_gfx->updateScreen();
waitUntilLeftClick();
return _di;
}
@@ -424,20 +435,18 @@ int16 Parallaction::selectAnswer(Question *q, StaticCnv *cnv) {
_mouseButtons = kMouseNone;
while (_mouseButtons != kMouseLeftUp) {
- updateInput();
- _si = getHoverAnswer(_mousePos.x, _mousePos.y, q);
+ _vm->updateInput();
+ _si = getHoverAnswer(_vm->_mousePos.x, _vm->_mousePos.y);
if (_si != v2) {
if (v2 != -1)
- _gfx->displayWrappedString(q->_answers[v2]->_text, _answerBalloonX[v2], _answerBalloonY[v2], MAX_BALLOON_WIDTH, 3);
+ _vm->_gfx->displayWrappedString(_q->_answers[v2]->_text, _answerBalloonX[v2], _answerBalloonY[v2], 3, MAX_BALLOON_WIDTH);
- _gfx->displayWrappedString(q->_answers[_si]->_text, _answerBalloonX[_si], _answerBalloonY[_si], MAX_BALLOON_WIDTH, 0);
- cnv->_data0 = _char._talk->getFramePtr(q->_answers[_si]->_mood & 0xF);
-// cnv->_data1 = _char._talk->field_8[q->_answers[_si]->_mood & 0xF];
- _gfx->flatBlitCnv(cnv, ANSWER_CHARACTER_X, ANSWER_CHARACTER_Y, Gfx::kBitFront);
+ _vm->_gfx->displayWrappedString(_q->_answers[_si]->_text, _answerBalloonX[_si], _answerBalloonY[_si], 0, MAX_BALLOON_WIDTH);
+ _vm->_gfx->flatBlitCnv(_answerer, _q->_answers[_si]->_mood & 0xF, ANSWER_CHARACTER_X, ANSWER_CHARACTER_Y, Gfx::kBitFront);
}
- _gfx->updateScreen();
+ _vm->_gfx->updateScreen();
g_system->delayMillis(30);
v2 = _si;
}
@@ -449,13 +458,13 @@ int16 Parallaction::selectAnswer(Question *q, StaticCnv *cnv) {
//
// finds out which answer is currently selected
//
-int16 getHoverAnswer(int16 x, int16 y, Question *q) {
+int16 DialogueManager::getHoverAnswer(int16 x, int16 y) {
int16 top = 1000;
int16 bottom = 1000;
for (int16 _si = 0; _si < NUM_ANSWERS; _si++) {
- if (q->_answers[_si] == NULL) break;
+ if (_q->_answers[_si] == NULL) break;
if (_answerBalloonY[_si] != SKIPPED_ANSWER) {
top = _answerBalloonY[_si];
@@ -476,21 +485,21 @@ int16 getHoverAnswer(int16 x, int16 y, Question *q) {
}
-void Parallaction::enterDialogue() {
- showCursor(false);
-
- return;
-}
+void Parallaction::runDialogue(SpeakData *data) {
+ debugC(1, kDebugDialogue, "runDialogue: starting dialogue '%s'", data->_name);
-// rebuilds inventory
-//
-void Parallaction::exitDialogue() {
+ _gfx->setFont(kFontDialogue);
- refreshInventory(_characterName);
+ if (_vm->getPlatform() == Common::kPlatformPC)
+ showCursor(false);
+ DialogueManager man(this, data);
+ man.run();
+
+ refreshInventory(_characterName);
showCursor(true);
-
+
return;
}
@@ -503,12 +512,8 @@ Answer::Answer() {
}
Answer::~Answer() {
- if (_mood & 0x10)
- delete _following._question;
-
if (_text)
free(_text);
-
}
Question::Question() {
diff --git a/engines/parallaction/disk.cpp b/engines/parallaction/disk.cpp
index 7b11fbbbed..2e6d9e4820 100644
--- a/engines/parallaction/disk.cpp
+++ b/engines/parallaction/disk.cpp
@@ -26,6 +26,8 @@
#include "common/stdafx.h"
#include "graphics/iff.h"
+#include "graphics/surface.h"
+
#include "parallaction/parallaction.h"
@@ -90,8 +92,10 @@ void Disk::errorFileNotFound(const char *s) {
}
-void Disk::selectArchive(const char *name) {
- _resArchive.open(name);
+Common::String Disk::selectArchive(const Common::String& name) {
+ Common::String oldName = _resArchive.name();
+ _resArchive.open(name.c_str());
+ return oldName;
}
void Disk::setLanguage(uint16 language) {
@@ -691,33 +695,106 @@ AmigaDisk::~AmigaDisk() {
#define NUM_PLANES 5
-// FIXME: no mask is loaded
-void AmigaDisk::unpackBitmap(byte *dst, byte *src, uint16 numFrames, uint16 planeSize) {
+/*
+ unpackFrame transforms images from 5-bitplanes format to
+ 8-bit color-index mode
+*/
+void AmigaDisk::unpackFrame(byte *dst, byte *src, uint16 planeSize) {
byte s0, s1, s2, s3, s4, mask, t0, t1, t2, t3, t4;
- for (uint32 i = 0; i < numFrames; i++) {
- for (uint32 j = 0; j < planeSize; j++) {
- s0 = src[j];
- s1 = src[j+planeSize];
- s2 = src[j+planeSize*2];
- s3 = src[j+planeSize*3];
- s4 = src[j+planeSize*4];
-
- for (uint32 k = 0; k < 8; k++) {
- mask = 1 << (7 - k);
- t0 = (s0 & mask ? 1 << 0 : 0);
- t1 = (s1 & mask ? 1 << 1 : 0);
- t2 = (s2 & mask ? 1 << 2 : 0);
- t3 = (s3 & mask ? 1 << 3 : 0);
- t4 = (s4 & mask ? 1 << 4 : 0);
- *dst++ = t0 | t1 | t2 | t3 | t4;
+ for (uint32 j = 0; j < planeSize; j++) {
+ s0 = src[j];
+ s1 = src[j+planeSize];
+ s2 = src[j+planeSize*2];
+ s3 = src[j+planeSize*3];
+ s4 = src[j+planeSize*4];
+
+ for (uint32 k = 0; k < 8; k++) {
+ mask = 1 << (7 - k);
+ t0 = (s0 & mask ? 1 << 0 : 0);
+ t1 = (s1 & mask ? 1 << 1 : 0);
+ t2 = (s2 & mask ? 1 << 2 : 0);
+ t3 = (s3 & mask ? 1 << 3 : 0);
+ t4 = (s4 & mask ? 1 << 4 : 0);
+ *dst++ = t0 | t1 | t2 | t3 | t4;
+ }
+
+ }
+
+}
+
+/*
+ patchFrame applies DLTA data (dlta) to specified buffer (dst)
+*/
+void AmigaDisk::patchFrame(byte *dst, byte *dlta, uint16 bytesPerPlane, uint16 height) {
+
+ uint32 *dataIndex = (uint32*)dlta;
+ uint32 *ofslenIndex = (uint32*)dlta + 8;
+
+ uint16 *base = (uint16*)dlta;
+ uint16 wordsPerLine = bytesPerPlane >> 1;
+
+ for (uint j = 0; j < NUM_PLANES; j++) {
+ uint16 *dst16 = (uint16*)(dst + j * bytesPerPlane * height);
+
+ uint16 *data = base + READ_BE_UINT32(dataIndex);
+ dataIndex++;
+ uint16 *ofslen = base + READ_BE_UINT32(ofslenIndex);
+ ofslenIndex++;
+
+ while (*ofslen != 0xFFFF) {
+
+ uint16 ofs = READ_BE_UINT16(ofslen);
+ ofslen++;
+ uint16 size = READ_BE_UINT16(ofslen);
+ ofslen++;
+
+ while (size > 0) {
+ dst16[ofs] ^= *data++;
+ ofs += wordsPerLine;
+ size--;
}
}
- src += planeSize * NUM_PLANES;
}
+
+}
+
+// FIXME: no mask is loaded
+void AmigaDisk::unpackBitmap(byte *dst, byte *src, uint16 numFrames, uint16 bytesPerPlane, uint16 height) {
+
+ byte *baseFrame = src;
+ byte *tempBuffer = 0;
+
+ uint16 planeSize = bytesPerPlane * height;
+
+ for (uint32 i = 0; i < numFrames; i++) {
+ if (READ_BE_UINT32(src) == MKID_BE('DLTA')) {
+
+ uint size = READ_BE_UINT32(src + 4);
+
+ if (tempBuffer == 0)
+ tempBuffer = (byte*)malloc(planeSize * NUM_PLANES);
+
+ memcpy(tempBuffer, baseFrame, planeSize * NUM_PLANES);
+
+ patchFrame(tempBuffer, src + 8, bytesPerPlane, height);
+ unpackFrame(dst, tempBuffer, planeSize);
+
+ src += (size + 8);
+ dst += planeSize * 8;
+ } else {
+ unpackFrame(dst, src, planeSize);
+ src += planeSize * NUM_PLANES;
+ dst += planeSize * 8;
+ }
+ }
+
+ if (tempBuffer)
+ free(tempBuffer);
+
}
StaticCnv* AmigaDisk::makeStaticCnv(Common::SeekableReadStream &stream) {
@@ -737,7 +814,7 @@ StaticCnv* AmigaDisk::makeStaticCnv(Common::SeekableReadStream &stream) {
uint32 decsize = width * height;
byte *data = (byte*)calloc(decsize, 1);
- unpackBitmap(data, buf, 1, height * bytesPerPlane);
+ unpackBitmap(data, buf, 1, bytesPerPlane, height);
free(buf);
@@ -767,7 +844,7 @@ Cnv* AmigaDisk::makeCnv(Common::SeekableReadStream &stream) {
uint32 decsize = numFrames * width * height;
byte *data = (byte*)calloc(decsize, 1);
- unpackBitmap(data, buf, numFrames, height * bytesPerPlane);
+ unpackBitmap(data, buf, numFrames, bytesPerPlane, height);
free(buf);
diff --git a/engines/parallaction/disk.h b/engines/parallaction/disk.h
index bfef6d81df..14ea4f0e16 100644
--- a/engines/parallaction/disk.h
+++ b/engines/parallaction/disk.h
@@ -60,6 +60,7 @@ protected:
uint32 _fileCursor;
uint32 _fileEndOffset;
+ Common::String _archiveName;
char _archiveDir[MAX_ARCHIVE_ENTRIES][32];
uint32 _archiveLenghts[MAX_ARCHIVE_ENTRIES];
uint32 _archiveOffsets[MAX_ARCHIVE_ENTRIES];
@@ -74,9 +75,11 @@ protected:
public:
Archive();
- void open(const char *file);
+ void open(const char* file);
void close();
+ Common::String name() const;
+
bool openArchivedFile(const char *name);
void closeArchivedFile();
@@ -103,7 +106,7 @@ public:
Disk(Parallaction *vm);
virtual ~Disk();
- void selectArchive(const char *name);
+ Common::String selectArchive(const Common::String &name);
void setLanguage(uint16 language);
virtual Script* loadLocation(const char *name) = 0;
@@ -163,7 +166,9 @@ class AmigaDisk : public Disk {
protected:
Cnv* makeCnv(Common::SeekableReadStream &stream);
StaticCnv* makeStaticCnv(Common::SeekableReadStream &stream);
- void unpackBitmap(byte *dst, byte *src, uint16 numFrames, uint16 planeSize);
+ void patchFrame(byte *dst, byte *dlta, uint16 bytesPerPlane, uint16 height);
+ void unpackFrame(byte *dst, byte *src, uint16 planeSize);
+ void unpackBitmap(byte *dst, byte *src, uint16 numFrames, uint16 bytesPerPlane, uint16 height);
Common::SeekableReadStream *openArchivedFile(const char* name, bool errorOnFileNotFound = false);
Font *createFont(const char *name, Common::SeekableReadStream &stream);
void loadMask(const char *name);
diff --git a/engines/parallaction/graphics.cpp b/engines/parallaction/graphics.cpp
index aab35f8562..59645381b6 100644
--- a/engines/parallaction/graphics.cpp
+++ b/engines/parallaction/graphics.cpp
@@ -306,8 +306,6 @@ void Gfx::floodFill(Gfx::Buffers buffer, const Common::Rect& r, byte color) {
d += SCREEN_WIDTH;
}
- if (buffer == kBitFront) updateScreen();
-
return;
}
@@ -350,8 +348,6 @@ void Gfx::flatBlit(const Common::Rect& r, byte *data, Gfx::Buffers buffer) {
d += (SCREEN_WIDTH - q.width());
}
- if (buffer == kBitFront) updateScreen();
-
return;
}
@@ -389,8 +385,6 @@ void Gfx::blit(const Common::Rect& r, uint16 z, byte *data, Gfx::Buffers buffer)
d += (SCREEN_WIDTH - q.right + q.left);
}
- if (buffer == kBitFront) updateScreen();
-
return;
}
@@ -480,6 +474,18 @@ void Gfx::setMousePointer(int16 index) {
//
// Cnv management
//
+void Gfx::flatBlitCnv(Cnv *cnv, uint16 frame, int16 x, int16 y, Gfx::Buffers buffer) {
+
+ StaticCnv scnv;
+
+ scnv._width = cnv->_width;
+ scnv._height = cnv->_height;
+ scnv._data0 = cnv->getFramePtr(frame);
+ scnv._data1 = NULL; // _questioner->field_8[v60->_mood & 0xF];
+
+ flatBlitCnv(&scnv, x, y, buffer);
+}
+
void Gfx::flatBlitCnv(StaticCnv *cnv, int16 x, int16 y, Gfx::Buffers buffer) {
Common::Rect r(cnv->_width, cnv->_height);
r.moveTo(x, y);
@@ -577,30 +583,19 @@ void Gfx::makeCnvFromString(StaticCnv *cnv, char *text) {
}
-void Gfx::displayString(uint16 x, uint16 y, const char *text) {
- assert(_font == _fonts[kFontMenu]);
-
+void Gfx::displayString(uint16 x, uint16 y, const char *text, byte color) {
byte *dst = _buffers[kBitFront] + x + y*SCREEN_WIDTH;
- _font->setColor(1);
+ _font->setColor(color);
_font->drawString(dst, SCREEN_WIDTH, text);
}
void Gfx::displayCenteredString(uint16 y, const char *text) {
uint16 x = (SCREEN_WIDTH - getStringWidth(text)) / 2;
- displayString(x, y, text);
-}
-
-void Gfx::displayBalloonString(uint16 x, uint16 y, const char *text, byte color) {
- assert(_font == _fonts[kFontDialogue]);
-
- byte *dst = _buffers[kBitFront] + x + y*SCREEN_WIDTH;
-
- _font->setColor(color);
- _font->drawString(dst, SCREEN_WIDTH, text);
+ displayString(x, y, text, 1);
}
-bool Gfx::displayWrappedString(char *text, uint16 x, uint16 y, uint16 maxwidth, byte color) {
-// printf("Gfx::displayWrappedString(%s, %i, %i, %i, %i)...", text, x, y, maxwidth, color);
+bool Gfx::displayWrappedString(char *text, uint16 x, uint16 y, byte color, uint16 wrapwidth) {
+// printf("Gfx::displayWrappedString(%s, %i, %i, %i, %i)...", text, x, y, color, wrapwidth);
uint16 lines = 0;
bool rv = false;
@@ -613,10 +608,10 @@ bool Gfx::displayWrappedString(char *text, uint16 x, uint16 y, uint16 maxwidth,
while (strlen(text) > 0) {
- text = parseNextToken(text, token, 40, " ");
+ text = parseNextToken(text, token, 40, " ", true);
linewidth += getStringWidth(token);
- if (linewidth > maxwidth) {
+ if (linewidth > wrapwidth) {
// wrap line
lines++;
rx = x + 10; // x
@@ -630,7 +625,7 @@ bool Gfx::displayWrappedString(char *text, uint16 x, uint16 y, uint16 maxwidth,
if (!scumm_stricmp(token, "%p")) {
rv = true;
} else
- displayBalloonString(rx, ry, token, color);
+ displayString(rx, ry, token, color);
rx += getStringWidth(token) + getStringWidth(" ");
linewidth += getStringWidth(" ");
@@ -658,7 +653,7 @@ void Gfx::getStringExtent(char *text, uint16 maxwidth, int16* width, int16* heig
while (strlen(text) != 0) {
- text = parseNextToken(text, token, 40, " ");
+ text = parseNextToken(text, token, 40, " ", true);
w += getStringWidth(token);
if (w > maxwidth) {
diff --git a/engines/parallaction/graphics.h b/engines/parallaction/graphics.h
index 1f0c467293..d535d3cf05 100644
--- a/engines/parallaction/graphics.h
+++ b/engines/parallaction/graphics.h
@@ -67,7 +67,7 @@ struct PaletteFxRange {
byte _first;
byte _last;
-};
+} PACKED_STRUCT;
#include "common/pack-end.h" // END STRUCT PACKING
@@ -165,10 +165,9 @@ public:
// dialogue and text
void drawBalloon(const Common::Rect& r, uint16 arg_8);
- void displayBalloonString(uint16 x, uint16 y, const char *text, byte color);
- void displayString(uint16 x, uint16 y, const char *text);
+ void displayString(uint16 x, uint16 y, const char *text, byte color);
void displayCenteredString(uint16 y, const char *text);
- bool displayWrappedString(char *text, uint16 x, uint16 y, uint16 maxwidth, byte color);
+ bool displayWrappedString(char *text, uint16 x, uint16 y, byte color, uint16 wrapwidth = SCREEN_WIDTH);
uint16 getStringWidth(const char *text);
void getStringExtent(char *text, uint16 maxwidth, int16* width, int16* height);
@@ -204,6 +203,8 @@ public:
// DOS version didn't make use of it, but it is probably needed for Amiga stuff.
void flatBlitCnv(StaticCnv *cnv, int16 x, int16 y, Gfx::Buffers buffer);
void blitCnv(StaticCnv *cnv, int16 x, int16 y, uint16 z, Gfx::Buffers buffer);
+ void flatBlitCnv(Cnv *cnv, uint16 frame, int16 x, int16 y, Gfx::Buffers buffer);
+
// palette
void setPalette(Palette palette, uint32 first = FIRST_BASE_COLOR, uint32 num = BASE_PALETTE_COLORS);
diff --git a/engines/parallaction/location.cpp b/engines/parallaction/location.cpp
index 4d8efa3255..3c54460692 100644
--- a/engines/parallaction/location.cpp
+++ b/engines/parallaction/location.cpp
@@ -38,6 +38,7 @@ void Parallaction::parseLocation(const char *filename) {
_gfx->setFont(kFontLabel);
Script *_locationScript = _disk->loadLocation(filename);
+ _hasLocationSound = false;
fillBuffers(*_locationScript, true);
while (scumm_stricmp(_tokens[0], "ENDLOCATION")) {
@@ -140,16 +141,15 @@ void Parallaction::parseLocation(const char *filename) {
parseAnimation(*_locationScript, _animations, _tokens[1]);
}
if (!scumm_stricmp(_tokens[0], "SOUND")) {
- strcpy(_soundFile, _tokens[1]);
+ if (getPlatform() == Common::kPlatformAmiga) {
+ strcpy(_locationSound, _tokens[1]);
+ _hasLocationSound = true;
+ }
}
if (!scumm_stricmp(_tokens[0], "MUSIC")) {
if (getPlatform() == Common::kPlatformAmiga)
_soundMan->setMusicFile(_tokens[1]);
}
- if (!scumm_stricmp(_tokens[0], "SOUND")) {
-// if (getPlatform() == Common::kPlatformAmiga)
-// _soundMan->loadSfx(_tokens[1], atoi(_tokens[2]));
- }
fillBuffers(*_locationScript, true);
}
@@ -182,14 +182,14 @@ void Parallaction::freeLocation() {
if (_localFlagNames)
delete _localFlagNames;
-
+
// HACK: prevents leakage. A routine like this
// should allocate memory at all, though.
if ((_engineFlags & kEngineQuit) == 0) {
_localFlagNames = new Table(120);
_localFlagNames->addData("visited");
}
-
+
_location._walkNodes.clear();
// TODO (LIST): helperNode should be rendered useless by the use of a Common::List<>
@@ -379,11 +379,11 @@ void Parallaction::changeLocation(char *location) {
runJobs();
_gfx->swapBuffers();
}
-
+
if (_location._comment) {
doLocationEnterTransition();
}
-
+
runJobs();
_gfx->swapBuffers();
@@ -392,7 +392,8 @@ void Parallaction::changeLocation(char *location) {
runCommands(_location._aCommands);
}
-// _soundMan->playSfx(0);
+ if (_hasLocationSound)
+ _soundMan->playSfx(_locationSound, 0, true);
debugC(1, kDebugLocation, "changeLocation() done");
@@ -416,7 +417,7 @@ void Parallaction::doLocationEnterTransition() {
debugC(3, kDebugLocation, "skipping location transition");
return; // visited
}
-
+
byte pal[PALETTE_SIZE];
_gfx->buildBWPalette(pal);
_gfx->setPalette(pal);
@@ -437,7 +438,7 @@ void Parallaction::doLocationEnterTransition() {
_gfx->floodFill(Gfx::kBitFront, r, 0);
r.grow(-1);
_gfx->floodFill(Gfx::kBitFront, r, 1);
- _gfx->displayWrappedString(_location._comment, 3, 5, 130, 0);
+ _gfx->displayWrappedString(_location._comment, 3, 5, 0, 130);
_gfx->updateScreen();
waitUntilLeftClick();
diff --git a/engines/parallaction/menu.cpp b/engines/parallaction/menu.cpp
index b1b6fb44c8..427f24a467 100644
--- a/engines/parallaction/menu.cpp
+++ b/engines/parallaction/menu.cpp
@@ -201,7 +201,7 @@ uint16 Menu::chooseLanguage() {
_vm->_gfx->setPalette(_vm->_gfx->_palette);
_vm->_gfx->copyScreen(Gfx::kBitBack, Gfx::kBitFront);
- _vm->_gfx->displayString(60, 30, "SELECT LANGUAGE");
+ _vm->_gfx->displayString(60, 30, "SELECT LANGUAGE", 1);
_vm->_gfx->copyScreen(Gfx::kBitFront, Gfx::kBitBack);
_vm->_gfx->copyScreen(Gfx::kBitBack, Gfx::kBit2);
@@ -287,10 +287,10 @@ uint16 Menu::selectGame() {
if (_si != 0) {
// load a game
- _vm->_gfx->displayString(60, 30, loadGameMsg[_language]);
+ _vm->_gfx->displayString(60, 30, loadGameMsg[_language], 1);
} else {
// new game
- _vm->_gfx->displayString(60, 30, newGameMsg[_language]);
+ _vm->_gfx->displayString(60, 30, newGameMsg[_language], 1);
}
_vm->_gfx->updateScreen();
@@ -353,7 +353,7 @@ void Menu::selectCharacter() {
askPassword = false;
_di = 0;
- _vm->_gfx->displayString(60, 30, introMsg1[_language]); // displays message
+ _vm->_gfx->displayString(60, 30, introMsg1[_language], 1); // displays message
_vm->_gfx->copyScreen(Gfx::kBitFront, Gfx::kBitBack);
_donna_points = 0;
@@ -415,7 +415,7 @@ void Menu::selectCharacter() {
if (askPassword == false) break;
_vm->_gfx->copyScreen(Gfx::kBit2, Gfx::kBitFront);
- _vm->_gfx->displayString(60, 30, introMsg2[_language]);
+ _vm->_gfx->displayString(60, 30, introMsg2[_language], 1);
_vm->_gfx->updateScreen();
g_system->delayMillis(2000);
diff --git a/engines/parallaction/parallaction.cpp b/engines/parallaction/parallaction.cpp
index e0291c5a2a..c830b575a9 100644
--- a/engines/parallaction/parallaction.cpp
+++ b/engines/parallaction/parallaction.cpp
@@ -84,7 +84,6 @@ Command * _forwardedCommands[20] = {
char _forwardedAnimationNames[20][20];
uint16 _numForwards = 0;
-char _soundFile[20];
uint32 _commandFlags = 0;
uint16 _introSarcData3 = 200;
@@ -158,6 +157,8 @@ int Parallaction::init() {
_localFlagNames = NULL;
initResources();
+ _hasLocationSound = false;
+
_skipMenu = false;
_transCurrentHoverItem = 0;
@@ -369,6 +370,9 @@ void Parallaction::runGame() {
if (_location._comment)
doLocationEnterTransition();
+ if (_hasLocationSound)
+ _soundMan->playSfx(_locationSound, 0, true);
+
changeCursor(kCursorArrow);
if (_location._aCommands.size() > 0)
@@ -759,10 +763,13 @@ void Parallaction::changeCharacter(const char *name) {
// character for sanity before memory is freed
freeCharacter();
- _disk->selectArchive((_vm->getPlatform() == Common::kPlatformAmiga) ? "disk0" : "disk1");
+ Common::String oldArchive = _disk->selectArchive((_vm->getFeatures() & GF_LANG_MULT) ? "disk1" : "disk0");
_vm->_char._ani._cnv = _disk->loadFrames(fullName);
if (!IS_DUMMY_CHARACTER(name)) {
+ if (_vm->getPlatform() == Common::kPlatformAmiga && (_vm->getFeatures() & GF_LANG_MULT))
+ _disk->selectArchive("disk0");
+
_vm->_char._head = _disk->loadHead(baseName);
_vm->_char._talk = _disk->loadTalk(baseName);
_vm->_char._objs = _disk->loadObjects(baseName);
@@ -774,6 +781,9 @@ void Parallaction::changeCharacter(const char *name) {
if (!(getFeatures() & GF_DEMO))
parseLocation("common");
}
+
+ if (!oldArchive.empty())
+ _disk->selectArchive(oldArchive);
}
strcpy(_characterName1, fullName);
diff --git a/engines/parallaction/parallaction.h b/engines/parallaction/parallaction.h
index 38db16ce99..561b15acc9 100644
--- a/engines/parallaction/parallaction.h
+++ b/engines/parallaction/parallaction.h
@@ -27,8 +27,7 @@
#define PARALLACTION_H
#include "common/str.h"
-#include "gui/dialog.h"
-#include "gui/widget.h"
+
#include "engines/engine.h"
@@ -62,7 +61,7 @@ enum {
enum {
GF_DEMO = 1 << 0,
GF_LANG_EN = 1 << 1,
- GF_LANG_FR = 1 << 2,
+ GF_LANG_FR = 1 << 2,
GF_LANG_DE = 1 << 3,
GF_LANG_IT = 1 << 4,
GF_LANG_MULT = 1 << 5
@@ -177,7 +176,6 @@ extern uint32 _localFlags[];
extern Command *_forwardedCommands[];
extern char _forwardedAnimationNames[][20];
extern uint16 _numForwards;
-extern char _soundFile[];
extern char _slideText[][40];
extern uint16 _introSarcData3; // sarcophagus stuff to be saved
extern uint16 _introSarcData2; // sarcophagus stuff to be saved
@@ -398,7 +396,7 @@ protected: // data
bool _skipMenu;
bool _mouseHidden;
-
+
// input-only
InputData _input;
bool _actionAfterWalk; // actived when the character needs to move before taking an action
@@ -417,6 +415,9 @@ protected: // data
Common::String _saveFileName;
+ bool _hasLocationSound;
+ char _locationSound[50];
+
protected: // members
bool detectGame(void);
@@ -461,15 +462,6 @@ protected: // members
void freeCharacter();
- uint16 askDialoguePassword(Dialogue *q, StaticCnv *face);
- bool displayAnswer(Dialogue *q, uint16 i);
- bool displayAnswers(Dialogue *q);
- void displayQuestion(Dialogue *q, Cnv *cnv);
- uint16 getDialogueAnswer(Dialogue *q, Cnv *cnv);
- int16 selectAnswer(Question *q, StaticCnv *cnv);
- void enterDialogue();
- void exitDialogue();
-
int addInventoryItem(uint16 item);
void dropItem(uint16 item);
int16 pickupItem(Zone *z);
@@ -480,33 +472,6 @@ protected: // members
// FIXME: remove global
extern Parallaction *_vm;
-class SaveLoadChooser : public GUI::Dialog {
- typedef Common::String String;
- typedef Common::StringList StringList;
-protected:
- GUI::ListWidget *_list;
- GUI::ButtonWidget *_chooseButton;
- GUI::GraphicsWidget *_gfxWidget;
- GUI::StaticTextWidget *_date;
- GUI::StaticTextWidget *_time;
- GUI::StaticTextWidget *_playtime;
- GUI::ContainerWidget *_container;
- Parallaction *_vm;
-
- uint8 _fillR, _fillG, _fillB;
-
-public:
- SaveLoadChooser(const String &title, const String &buttonLabel, Parallaction *engine);
- ~SaveLoadChooser();
-
- virtual void handleCommand(GUI::CommandSender *sender, uint32 cmd, uint32 data);
- const String &getResultString() const;
- void setList(const StringList& list);
- int runModal();
-
- virtual void reflowLayout();
-};
-
} // namespace Parallaction
diff --git a/engines/parallaction/parser.cpp b/engines/parallaction/parser.cpp
index f044e6c3c7..44aae6c1cc 100644
--- a/engines/parallaction/parser.cpp
+++ b/engines/parallaction/parser.cpp
@@ -119,24 +119,72 @@ void clearTokens() {
}
-// looks for next token in a string
//
-// scans 's' until one of the stop-chars in 'brk' is found
-// builds a token and return the part of the string which hasn't been parsed
-
-char *parseNextToken(char *s, char *tok, uint16 count, const char *brk) {
-
- while (*s != '\0') {
+// Scans 's' until one of the stop-chars in 'brk' is found, building a token.
+// If the routine encounters quotes, it will extract the contained text and
+// make a proper token. When scanning inside quotes, 'brk' is ignored and
+// only newlines are considered stop-chars.
+//
+// The routine returns the unparsed portion of the input string 's'.
+//
+char *parseNextToken(char *s, char *tok, uint16 count, const char *brk, bool ignoreQuotes) {
+
+ enum STATES { NORMAL, QUOTED };
+
+ STATES state = NORMAL;
+
+ char *t = s;
+
+ while (count > 0) {
+
+ switch (state) {
+ case NORMAL:
+ if (*s == '\0') {
+ *tok = '\0';
+ return s;
+ }
+
+ if (strchr(brk, *s)) {
+ *tok = '\0';
+ return ++s;
+ }
+
+ if (*s == '"') {
+ if (ignoreQuotes) {
+ *tok++ = *s++;
+ count--;
+ } else {
+ state = QUOTED;
+ s++;
+ }
+ } else {
+ *tok++ = *s++;
+ count--;
+ }
+ break;
- if (brk[0] == *s) break;
- if (brk[1] == *s) break;
- if (brk[2] == *s) break;
+ case QUOTED:
+ if (*s == '\0') {
+ *tok = '\0';
+ return s;
+ }
+ if (*s == '"' || *s == '\n' || *s == '\t') {
+ *tok = '\0';
+ return ++s;
+ }
+
+ *tok++ = *s++;
+ count--;
+ break;
+ }
- *tok++ = *s++;
}
*tok = '\0';
- return s;
+ warning("token was truncated from line '%s'", t);
+
+ return tok;
+
}
uint16 fillTokens(char* line) {
@@ -144,15 +192,6 @@ uint16 fillTokens(char* line) {
uint16 i = 0;
while (strlen(line) > 0 && i < 20) {
line = parseNextToken(line, _tokens[i], 40, " \t\n");
- if (_tokens[i][0] == '"' && _tokens[i][strlen(_tokens[i]) - 1] != '"') {
-
- line = parseNextToken(line, _tokens[i+1], 40, "\"");
- strcat(_tokens[i], _tokens[i+1]);
- _tokens[i][0] = ' ';
- line++;
-
- }
-
line = Common::ltrim(line);
i++;
}
diff --git a/engines/parallaction/parser.h b/engines/parallaction/parser.h
index e27095bd16..aa3929a52c 100644
--- a/engines/parallaction/parser.h
+++ b/engines/parallaction/parser.h
@@ -33,7 +33,7 @@
namespace Parallaction {
uint16 fillBuffers(Common::SeekableReadStream &stream, bool errorOnEOF = false);
-char *parseNextToken(char *s, char *tok, uint16 count, const char *brk);
+char *parseNextToken(char *s, char *tok, uint16 count, const char *brk, bool ignoreQuotes = false);
extern char _tokens[][40];
diff --git a/engines/parallaction/saveload.cpp b/engines/parallaction/saveload.cpp
index f1dc53539d..2a9431ef94 100644
--- a/engines/parallaction/saveload.cpp
+++ b/engines/parallaction/saveload.cpp
@@ -26,6 +26,7 @@
#include "common/stdafx.h"
#include "common/savefile.h"
+#include "gui/dialog.h"
#include "gui/widget.h"
#include "gui/ListWidget.h"
#include "gui/message.h"
@@ -48,6 +49,37 @@ namespace Parallaction {
extern char _gameNames[][20];
+
+class SaveLoadChooser : public GUI::Dialog {
+ typedef Common::String String;
+ typedef Common::StringList StringList;
+protected:
+ GUI::ListWidget *_list;
+ GUI::ButtonWidget *_chooseButton;
+ GUI::GraphicsWidget *_gfxWidget;
+ GUI::StaticTextWidget *_date;
+ GUI::StaticTextWidget *_time;
+ GUI::StaticTextWidget *_playtime;
+ GUI::ContainerWidget *_container;
+ Parallaction *_vm;
+
+ uint8 _fillR, _fillG, _fillB;
+
+public:
+ SaveLoadChooser(const String &title, const String &buttonLabel, Parallaction *engine);
+ ~SaveLoadChooser();
+
+ virtual void handleCommand(GUI::CommandSender *sender, uint32 cmd, uint32 data);
+ const String &getResultString() const;
+ void setList(const StringList& list);
+ int runModal();
+
+ virtual void reflowLayout();
+};
+
+
+
+
void Parallaction::doLoadGame(uint16 slot) {
_introSarcData3 = 200;
diff --git a/engines/parallaction/zone.cpp b/engines/parallaction/zone.cpp
index 7d74a6a59f..d9bd36a1f5 100644
--- a/engines/parallaction/zone.cpp
+++ b/engines/parallaction/zone.cpp
@@ -216,22 +216,13 @@ void Parallaction::parseZoneTypeBlock(Script &script, Zone *z) {
strcpy(vC8, _tokens[1]);
- StaticCnv vE0;
u->door->_cnv = _disk->loadFrames(vC8);
-
- vE0._width = u->door->_cnv->_width;
- vE0._height = u->door->_cnv->_height;
-
uint16 _ax = (z->_flags & kFlagsClosed ? 0 : 1);
- vE0._data0 = u->door->_cnv->getFramePtr(_ax);
-
-// _ax = (z->_flags & kFlagsClosed ? 0 : 1);
-// vE0._data1 = doorcnv->field_8[_ax];
- u->door->_background = (byte*)malloc(vE0._width*vE0._height);
+ u->door->_background = (byte*)malloc(u->door->_cnv->_width * u->door->_cnv->_height);
_gfx->backupDoorBackground(u->door, z->_left, z->_top);
- _gfx->flatBlitCnv(&vE0, z->_left, z->_top, Gfx::kBitBack);
+ _gfx->flatBlitCnv(u->door->_cnv, _ax, z->_left, z->_top, Gfx::kBitBack);
}
if (!scumm_stricmp(_tokens[0], "startpos")) {
@@ -304,21 +295,15 @@ void Parallaction::parseZoneTypeBlock(Script &script, Zone *z) {
void Parallaction::displayCharacterComment(ExamineData *data) {
if (data->_description == NULL) return;
- StaticCnv v3C;
- v3C._width = _char._talk->_width;
- v3C._height = _char._talk->_height;
- v3C._data0 = _char._talk->getFramePtr(0);
- v3C._data1 = NULL; //_talk->field_8[0];
-
_gfx->setFont(kFontDialogue);
- _gfx->flatBlitCnv(&v3C, 190, 80, Gfx::kBitFront);
+ _gfx->flatBlitCnv(_char._talk, 0, 190, 80, Gfx::kBitFront);
int16 v26, v28;
_gfx->getStringExtent(data->_description, 130, &v28, &v26);
Common::Rect r(v28, v26);
r.moveTo(140, 10);
_gfx->drawBalloon(r, 0);
- _gfx->displayWrappedString(data->_description, 140, 10, 130, 0);
+ _gfx->displayWrappedString(data->_description, 140, 10, 0, 130);
_gfx->updateScreen();
@@ -359,7 +344,7 @@ void Parallaction::displayItemComment(ExamineData *data) {
r.moveTo(0, 90);
_gfx->drawBalloon(r, 0);
_gfx->flatBlitCnv(_vm->_char._head, 100, 152, Gfx::kBitFront);
- _gfx->displayWrappedString(data->_description, 0, 90, 130, 0);
+ _gfx->displayWrappedString(data->_description, 0, 90, 0, 130);
jobEraseAnimations((void*)1, NULL);
_gfx->updateScreen();
@@ -441,10 +426,8 @@ void jobToggleDoor(void *parm, Job *j) {
uint16 _ax = (z->_flags & kFlagsClosed ? 0 : 1);
- v14._data0 = z->u.door->_cnv->getFramePtr(_ax);
-
- _vm->_gfx->flatBlitCnv(&v14, z->_left, z->_top, Gfx::kBitBack);
- _vm->_gfx->flatBlitCnv(&v14, z->_left, z->_top, Gfx::kBit2);
+ _vm->_gfx->flatBlitCnv(z->u.door->_cnv, _ax, z->_left, z->_top, Gfx::kBitBack);
+ _vm->_gfx->flatBlitCnv(z->u.door->_cnv, _ax, z->_left, z->_top, Gfx::kBit2);
}
count++;
diff --git a/engines/parallaction/zone.h b/engines/parallaction/zone.h
index 9cc0fd6767..634a1364aa 100644
--- a/engines/parallaction/zone.h
+++ b/engines/parallaction/zone.h
@@ -68,7 +68,8 @@ enum ZoneFlags {
};
-#define NUM_ANSWERS 5
+#define NUM_QUESTIONS 20
+#define NUM_ANSWERS 5
struct Command;
struct Question;
@@ -97,7 +98,9 @@ struct Question {
~Question();
};
-typedef Question Dialogue;
+struct Dialogue {
+ Question *_questions[NUM_QUESTIONS];
+};
struct GetData { // size = 24
uint32 _icon;
diff --git a/engines/saga/actor.cpp b/engines/saga/actor.cpp
index e0e9415cab..d7882a78fd 100644
--- a/engines/saga/actor.cpp
+++ b/engines/saga/actor.cpp
@@ -268,6 +268,8 @@ Actor::Actor(SagaEngine *vm) : _vm(vm) {
_pathRect.top = _vm->getDisplayInfo().pathStartY;
_pathRect.bottom = _vm->_scene->getHeight();
+ _showActors = true;
+
// Get actor resource file context
_actorContext = _vm->_resource->getContext(GAME_RESOURCEFILE);
if (_actorContext == NULL) {
@@ -1130,7 +1132,7 @@ void Actor::handleSpeech(int msec) {
}
if (_activeSpeech.stringsCount == 0) {
- _vm->_script->wakeUpThreadsDelayed(kWaitTypeSpeech, ticksToMSec(kScriptTimeTicksPerSecond / 3));
+ _vm->_script->wakeUpThreadsDelayed(kWaitTypeSpeech, _vm->ticksToMSec(kScriptTimeTicksPerSecond / 3));
}
return;
@@ -1808,6 +1810,10 @@ void Actor::drawActors() {
return;
}
+ if (!_showActors) {
+ return;
+ }
+
CommonObjectOrderList::iterator drawOrderIterator;
CommonObjectDataPointer drawObject;
int frameNumber;
@@ -2349,6 +2355,11 @@ void Actor::simulSpeech(const char *string, uint16 *actorIds, int actorIdsCount,
}
void Actor::abortAllSpeeches() {
+ // WORKAROUND: Don't abort speeches in scene 31 (tree with beehive). This prevents the
+ // making fire animation from breaking
+ if (_vm->getGameType() == GType_ITE && _vm->_scene->currentSceneNumber() == 31)
+ return;
+
abortSpeech();
if (_vm->_script->_abortEnabled)
diff --git a/engines/saga/actor.h b/engines/saga/actor.h
index 1557abffb9..b9ec62337c 100644
--- a/engines/saga/actor.h
+++ b/engines/saga/actor.h
@@ -612,6 +612,8 @@ public:
void freeObjList();
void loadObjList(int objectCount, int objectsResourceID);
+ void showActors(bool flag) { _showActors = flag; }
+
/*
uint16 _currentFrameIndex;
void frameTest() {
@@ -712,6 +714,7 @@ private:
int _xCellCount;
int _yCellCount;
Rect _pathRect;
+ bool _showActors;
PathDirectionData *_pathDirectionList;
int _pathDirectionListCount;
diff --git a/engines/saga/animation.cpp b/engines/saga/animation.cpp
index 59c3339c9b..d29fc6ebe6 100644
--- a/engines/saga/animation.cpp
+++ b/engines/saga/animation.cpp
@@ -445,6 +445,18 @@ void Anim::play(uint16 animId, int vectorTime, bool playing) {
if (anim->completed < anim->cycles) {
frame = anim->currentFrame;
+
+ // WORKAROUND for a buggy animation in IHNM. Animation 0 in scene 67 (the mob of angry prisoners) should
+ // start from frame 0, not frame 1. Frame 0 is the background of the animation (the mob of prisoners), whereas
+ // the rest of the frames are their animated arms. Therefore, in order for the prisoners to appear correctly,
+ // frame 0 should be displayed as the first frame, but anim->currentframe is set to 1, which means that the
+ // prisoners will never be shown. In the original, the prisoners (first frame in the animation) are shown a
+ // bit after the animation is started (which is wrong again, but not that apparent), whereas in ScummVM the
+ // first frame is never shown. Therefore, make sure that for this animation, frame 0 is shown first
+ if (_vm->getGameType() == GType_IHNM && _vm->_scene->currentChapterNumber() == 4 &&
+ _vm->_scene->currentSceneNumber() == 67 && animId == 0 && anim->completed == 1)
+ frame = 0;
+
// FIXME: if start > 0, then this works incorrectly
decodeFrame(anim, anim->frameOffsets[frame], displayBuffer, _vm->getDisplayWidth() * _vm->getDisplayHeight());
_vm->_frameCount++;
diff --git a/engines/saga/detection_tables.h b/engines/saga/detection_tables.h
index 631a1a4e83..da06255a82 100644
--- a/engines/saga/detection_tables.h
+++ b/engines/saga/detection_tables.h
@@ -481,6 +481,37 @@ static const SAGAGameDescription gameDescriptions[] = {
ITEMacPatch_Files,
},
+ // Inherit the earth - MAC CD Wyrmkeep version (compressed sound)
+ {
+ {
+ "ite",
+ "Wyrmkeep CD",
+ {
+ {"ite.rsc", GAME_RESOURCEFILE, "4f7fa11c5175980ed593392838523060", -1},
+ {"scripts.rsc", GAME_SCRIPTFILE, "adf1f46c1d0589083996a7060c798ad0", -1},
+ {"sounds.cmp", GAME_SOUNDFILE, NULL, -1},
+ {"inherit the earth voices.cmp",GAME_VOICEFILE, NULL, -1},
+ {"music.cmp", GAME_MUSICFILE, NULL, -1},
+ { NULL, 0, NULL, 0}
+ },
+ Common::EN_ANY,
+ Common::kPlatformMacintosh,
+ Common::ADGF_NO_FLAGS
+ },
+ GType_ITE,
+ GID_ITE_MACCD,
+ GF_BIG_ENDIAN_DATA | GF_WYRMKEEP | GF_CD_FX | GF_COMPRESSED_SOUNDS,
+ ITE_DEFAULT_SCENE,
+ &ITE_Resources,
+ ARRAYSIZE(ITEWINDEMO_GameFonts),
+ ITEWINDEMO_GameFonts,
+ &ITEMACCD_GameSound,
+ &ITEMACCD_GameSound,
+ &ITEMACCD_GameMusic,
+ ARRAYSIZE(ITEMacPatch_Files),
+ ITEMacPatch_Files,
+ },
+
// Inherit the earth - Linux Demo version
// Note: it should be before GID_ITE_WINDEMO2 version
{
@@ -640,6 +671,42 @@ static const SAGAGameDescription gameDescriptions[] = {
NULL,
},
+ // Inherit the earth - Wyrmkeep combined Windows/Mac/Linux CD (compressed sound)
+
+ // version is different from the other Wyrmkeep re-releases in that it does
+ // not have any substitute files. Presumably the ite.rsc file has been
+ // modified to include the Wyrmkeep changes. The resource files are little-
+ // endian, except for the voice file which is big-endian.
+ {
+ {
+ "ite",
+ "Multi-OS CD Version",
+ {
+ {"ite.rsc", GAME_RESOURCEFILE, "a6433e34b97b15e64fe8214651012db9", -1},
+ {"scripts.rsc", GAME_SCRIPTFILE, "a891405405edefc69c9d6c420c868b84", -1},
+ {"sounds.cmp", GAME_SOUNDFILE, NULL, -1},
+ {"inherit the earth voices.cmp",GAME_VOICEFILE | GAME_SWAPENDIAN, NULL, -1},
+ {"music.cmp", GAME_MUSICFILE, NULL, -1},
+ { NULL, 0, NULL, 0}
+ },
+ Common::EN_ANY,
+ Common::kPlatformUnknown,
+ Common::ADGF_NO_FLAGS
+ },
+ GType_ITE,
+ GID_ITE_MULTICD,
+ GF_WYRMKEEP | GF_CD_FX | GF_COMPRESSED_SOUNDS,
+ ITE_DEFAULT_SCENE,
+ &ITE_Resources,
+ ARRAYSIZE(ITECD_GameFonts),
+ ITECD_GameFonts,
+ &ITEMACCD_GameSound,
+ &ITECD_GameSound,
+ &ITEMACCD_GameMusic,
+ 0,
+ NULL,
+ },
+
// Inherit the earth - Wyrmkeep Linux CD version
{
{
@@ -671,6 +738,37 @@ static const SAGAGameDescription gameDescriptions[] = {
ITELinPatch_Files,
},
+ // Inherit the earth - Wyrmkeep Linux CD version (compressed sound)
+ {
+ {
+ "ite",
+ "CD Version",
+ {
+ {"ite.rsc", GAME_RESOURCEFILE, "8f4315a9bb10ec839253108a032c8b54", -1},
+ {"scripts.rsc", GAME_SCRIPTFILE, "a891405405edefc69c9d6c420c868b84", -1},
+ {"sounds.cmp", GAME_SOUNDFILE, NULL, -1},
+ {"voices.cmp", GAME_VOICEFILE, NULL, -1},
+ {"music.cmp", GAME_MUSICFILE, NULL, -1},
+ { NULL, 0, NULL, 0}
+ },
+ Common::EN_ANY,
+ Common::kPlatformLinux,
+ Common::ADGF_NO_FLAGS
+ },
+ GType_ITE,
+ GID_ITE_LINCD,
+ GF_WYRMKEEP | GF_CD_FX | GF_COMPRESSED_SOUNDS,
+ ITE_DEFAULT_SCENE,
+ &ITE_Resources,
+ ARRAYSIZE(ITECD_GameFonts),
+ ITECD_GameFonts,
+ &ITECD_GameSound,
+ &ITECD_GameSound,
+ &ITEMACCD_GameMusic,
+ ARRAYSIZE(ITELinPatch_Files),
+ ITELinPatch_Files,
+ },
+
// Inherit the earth - Wyrmkeep Windows CD version
{
{
@@ -701,6 +799,36 @@ static const SAGAGameDescription gameDescriptions[] = {
ITEWinPatch1_Files,
},
+ // Inherit the earth - Wyrmkeep Windows CD version (compressed sound)
+ {
+ {
+ "ite",
+ "CD Version",
+ {
+ {"ite.rsc", GAME_RESOURCEFILE, "8f4315a9bb10ec839253108a032c8b54", -1},
+ {"scripts.rsc", GAME_SCRIPTFILE, "a891405405edefc69c9d6c420c868b84", -1},
+ {"sounds.cmp", GAME_SOUNDFILE, NULL, -1},
+ {"voices.cmp", GAME_VOICEFILE, NULL, -1},
+ { NULL, 0, NULL, 0}
+ },
+ Common::EN_ANY,
+ Common::kPlatformWindows,
+ Common::ADGF_NO_FLAGS
+ },
+ GType_ITE,
+ GID_ITE_WINCD,
+ GF_WYRMKEEP | GF_CD_FX | GF_COMPRESSED_SOUNDS,
+ ITE_DEFAULT_SCENE,
+ &ITE_Resources,
+ ARRAYSIZE(ITECD_GameFonts),
+ ITECD_GameFonts,
+ &ITECD_GameSound,
+ &ITECD_GameSound,
+ NULL,
+ ARRAYSIZE(ITEWinPatch1_Files),
+ ITEWinPatch1_Files,
+ },
+
// Inherit the earth - DOS CD version
{
{
@@ -731,6 +859,36 @@ static const SAGAGameDescription gameDescriptions[] = {
NULL,
},
+ // Inherit the earth - DOS CD version (compressed sound)
+ {
+ {
+ "ite",
+ "CD Version",
+ {
+ {"ite.rsc", GAME_RESOURCEFILE, "8f4315a9bb10ec839253108a032c8b54", -1},
+ {"scripts.rsc", GAME_SCRIPTFILE, "50a0d2d7003c926a3832d503c8534e90", -1},
+ {"sounds.cmp", GAME_SOUNDFILE, NULL, -1},
+ {"voices.cmp", GAME_VOICEFILE, NULL, -1},
+ { NULL, 0, NULL, 0}
+ },
+ Common::EN_ANY,
+ Common::kPlatformPC,
+ Common::ADGF_NO_FLAGS
+ },
+ GType_ITE,
+ GID_ITE_CD_G,
+ GF_CD_FX | GF_COMPRESSED_SOUNDS,
+ ITE_DEFAULT_SCENE,
+ &ITE_Resources,
+ ARRAYSIZE(ITECD_GameFonts),
+ ITECD_GameFonts,
+ &ITECD_GameSound,
+ &ITECD_GameSound,
+ NULL,
+ 0,
+ NULL,
+ },
+
// Inherit the earth - DOS CD version with digital music
{
{
@@ -762,6 +920,37 @@ static const SAGAGameDescription gameDescriptions[] = {
NULL,
},
+ // Inherit the earth - DOS CD version with digital music (compressed sound)
+ {
+ {
+ "ite",
+ "CD Version",
+ {
+ {"ite.rsc", GAME_RESOURCEFILE, "8f4315a9bb10ec839253108a032c8b54", -1},
+ {"scripts.rsc", GAME_SCRIPTFILE, "50a0d2d7003c926a3832d503c8534e90", -1},
+ {"sounds.cmp", GAME_SOUNDFILE, NULL, -1},
+ {"voices.cmp", GAME_VOICEFILE, NULL, -1},
+ {"music.cmp", GAME_MUSICFILE, NULL, -1},
+ { NULL, 0, NULL, 0}
+ },
+ Common::EN_ANY,
+ Common::kPlatformPC,
+ Common::ADGF_NO_FLAGS
+ },
+ GType_ITE,
+ GID_ITE_CD_G2,
+ GF_CD_FX | GF_COMPRESSED_SOUNDS,
+ ITE_DEFAULT_SCENE,
+ &ITE_Resources,
+ ARRAYSIZE(ITECD_GameFonts),
+ ITECD_GameFonts,
+ &ITECD_GameSound,
+ &ITECD_GameSound,
+ &ITEMACCD_GameMusic,
+ 0,
+ NULL,
+ },
+
// Inherit the earth - DOS CD German version
// reported by mld. Bestsellergamers cover disk
{
@@ -793,6 +982,37 @@ static const SAGAGameDescription gameDescriptions[] = {
NULL,
},
+ // Inherit the earth - DOS CD German version (compressed sound)
+ // reported by mld. Bestsellergamers cover disk
+ {
+ {
+ "ite",
+ "CD Version",
+ {
+ {"ite.rsc", GAME_RESOURCEFILE, "869fc23c8f38f575979ec67152914fee", -1},
+ {"scripts.rsc", GAME_SCRIPTFILE, "a891405405edefc69c9d6c420c868b84", -1},
+ {"sounds.cmp", GAME_SOUNDFILE, NULL, -1},
+ {"voices.cmp", GAME_VOICEFILE, NULL, -1},
+ { NULL, 0, NULL, 0}
+ },
+ Common::DE_DEU,
+ Common::kPlatformPC,
+ Common::ADGF_NO_FLAGS
+ },
+ GType_ITE,
+ GID_ITE_CD_DE,
+ GF_CD_FX | GF_COMPRESSED_SOUNDS,
+ ITE_DEFAULT_SCENE,
+ &ITE_Resources,
+ ARRAYSIZE(ITECD_GameFonts),
+ ITECD_GameFonts,
+ &ITECD_GameSound,
+ &ITECD_GameSound,
+ NULL,
+ 0,
+ NULL,
+ },
+
// Inherit the earth - DOS CD German version with digital music
{
{
@@ -824,6 +1044,37 @@ static const SAGAGameDescription gameDescriptions[] = {
NULL,
},
+ // Inherit the earth - DOS CD German version with digital music (compressed sound)
+ {
+ {
+ "ite",
+ "CD Version",
+ {
+ {"ite.rsc", GAME_RESOURCEFILE, "869fc23c8f38f575979ec67152914fee", -1},
+ {"scripts.rsc", GAME_SCRIPTFILE, "a891405405edefc69c9d6c420c868b84", -1},
+ {"sounds.cmp", GAME_SOUNDFILE, NULL, -1},
+ {"voices.cmp", GAME_VOICEFILE, NULL, -1},
+ {"music.cmp", GAME_MUSICFILE, NULL, -1},
+ { NULL, 0, NULL, 0}
+ },
+ Common::DE_DEU,
+ Common::kPlatformPC,
+ Common::ADGF_NO_FLAGS
+ },
+ GType_ITE,
+ GID_ITE_CD_DE2,
+ GF_CD_FX | GF_COMPRESSED_SOUNDS,
+ ITE_DEFAULT_SCENE,
+ &ITE_Resources,
+ ARRAYSIZE(ITECD_GameFonts),
+ ITECD_GameFonts,
+ &ITECD_GameSound,
+ &ITECD_GameSound,
+ &ITEMACCD_GameMusic,
+ 0,
+ NULL,
+ },
+
// Inherit the earth - CD version
{
{
@@ -854,6 +1105,36 @@ static const SAGAGameDescription gameDescriptions[] = {
NULL,
},
+ // Inherit the earth - CD version (compressed sound)
+ {
+ {
+ "ite",
+ "CD Version",
+ {
+ {"ite.rsc", GAME_RESOURCEFILE, "8f4315a9bb10ec839253108a032c8b54", -1},
+ {"scripts.rsc", GAME_SCRIPTFILE, "a891405405edefc69c9d6c420c868b84", -1},
+ {"sounds.cmp", GAME_SOUNDFILE, NULL, -1},
+ {"voices.cmp", GAME_VOICEFILE, NULL, -1},
+ { NULL, 0, NULL, 0}
+ },
+ Common::EN_ANY,
+ Common::kPlatformPC,
+ Common::ADGF_NO_FLAGS
+ },
+ GType_ITE,
+ GID_ITE_CD,
+ GF_CD_FX | GF_COMPRESSED_SOUNDS,
+ ITE_DEFAULT_SCENE,
+ &ITE_Resources,
+ ARRAYSIZE(ITECD_GameFonts),
+ ITECD_GameFonts,
+ &ITECD_GameSound,
+ &ITECD_GameSound,
+ NULL,
+ 0,
+ NULL,
+ },
+
// Inherit the earth - German Floppy version
{
{
@@ -883,6 +1164,35 @@ static const SAGAGameDescription gameDescriptions[] = {
NULL,
},
+ // Inherit the earth - German Floppy version (compressed sound)
+ {
+ {
+ "ite",
+ "Floppy",
+ {
+ {"ite.rsc", GAME_RESOURCEFILE, "869fc23c8f38f575979ec67152914fee", -1},
+ {"scripts.rsc", GAME_SCRIPTFILE, "516f7330f8410057b834424ea719d1ef", -1},
+ {"voices.cmp", GAME_SOUNDFILE | GAME_VOICEFILE, NULL, -1},
+ { NULL, 0, NULL, 0}
+ },
+ Common::DE_DEU,
+ Common::kPlatformPC,
+ Common::ADGF_NO_FLAGS
+ },
+ GType_ITE,
+ GID_ITE_DISK_DE,
+ GF_COMPRESSED_SOUNDS,
+ ITE_DEFAULT_SCENE,
+ &ITE_Resources,
+ ARRAYSIZE(ITEDISK_GameFonts),
+ ITEDISK_GameFonts,
+ &ITEDISK_GameSound,
+ &ITEDISK_GameSound,
+ NULL,
+ 0,
+ NULL,
+ },
+
// Inherit the earth - German Floppy version with digital music
{
{
@@ -913,6 +1223,36 @@ static const SAGAGameDescription gameDescriptions[] = {
NULL,
},
+ // Inherit the earth - German Floppy version with digital music (compressed sound)
+ {
+ {
+ "ite",
+ "Floppy",
+ {
+ {"ite.rsc", GAME_RESOURCEFILE, "869fc23c8f38f575979ec67152914fee", -1},
+ {"scripts.rsc", GAME_SCRIPTFILE, "516f7330f8410057b834424ea719d1ef", -1},
+ {"voices.cmp", GAME_SOUNDFILE | GAME_VOICEFILE, NULL, -1},
+ {"music.cmp", GAME_MUSICFILE, NULL, -1},
+ { NULL, 0, NULL, 0}
+ },
+ Common::DE_DEU,
+ Common::kPlatformPC,
+ Common::ADGF_NO_FLAGS
+ },
+ GType_ITE,
+ GID_ITE_DISK_DE2,
+ GF_COMPRESSED_SOUNDS,
+ ITE_DEFAULT_SCENE,
+ &ITE_Resources,
+ ARRAYSIZE(ITEDISK_GameFonts),
+ ITEDISK_GameFonts,
+ &ITEDISK_GameSound,
+ &ITEDISK_GameSound,
+ &ITEMACCD_GameMusic,
+ 0,
+ NULL,
+ },
+
// Inherit the earth - Disk version
{
{
@@ -942,6 +1282,35 @@ static const SAGAGameDescription gameDescriptions[] = {
NULL,
},
+ // Inherit the earth - Disk version (compressed sound)
+ {
+ {
+ "ite",
+ "Floppy",
+ {
+ {"ite.rsc", GAME_RESOURCEFILE, "8f4315a9bb10ec839253108a032c8b54", -1},
+ {"scripts.rsc", GAME_SCRIPTFILE, "516f7330f8410057b834424ea719d1ef", -1},
+ {"voices.cmp", GAME_SOUNDFILE | GAME_VOICEFILE, NULL, -1},
+ { NULL, 0, NULL, 0}
+ },
+ Common::EN_ANY,
+ Common::kPlatformPC,
+ Common::ADGF_NO_FLAGS
+ },
+ GType_ITE,
+ GID_ITE_DISK_G,
+ GF_COMPRESSED_SOUNDS,
+ ITE_DEFAULT_SCENE,
+ &ITE_Resources,
+ ARRAYSIZE(ITEDISK_GameFonts),
+ ITEDISK_GameFonts,
+ &ITEDISK_GameSound,
+ &ITEDISK_GameSound,
+ NULL,
+ 0,
+ NULL,
+ },
+
// Inherit the earth - Disk version with digital music
{
{
@@ -972,6 +1341,36 @@ static const SAGAGameDescription gameDescriptions[] = {
NULL,
},
+ // Inherit the earth - Disk version with digital music (compressed sound)
+ {
+ {
+ "ite",
+ "Floppy",
+ {
+ {"ite.rsc", GAME_RESOURCEFILE, "8f4315a9bb10ec839253108a032c8b54", -1},
+ {"scripts.rsc", GAME_SCRIPTFILE, "516f7330f8410057b834424ea719d1ef", -1},
+ {"voices.cmp", GAME_SOUNDFILE | GAME_VOICEFILE, NULL, -1},
+ {"music.cmp", GAME_MUSICFILE, NULL, -1},
+ { NULL, 0, NULL, 0}
+ },
+ Common::EN_ANY,
+ Common::kPlatformPC,
+ Common::ADGF_NO_FLAGS
+ },
+ GType_ITE,
+ GID_ITE_DISK_G2,
+ GF_COMPRESSED_SOUNDS,
+ ITE_DEFAULT_SCENE,
+ &ITE_Resources,
+ ARRAYSIZE(ITEDISK_GameFonts),
+ ITEDISK_GameFonts,
+ &ITEDISK_GameSound,
+ &ITEDISK_GameSound,
+ &ITEMACCD_GameMusic,
+ 0,
+ NULL,
+ },
+
// I Have No Mouth And I Must Scream - Demo version
{
{
diff --git a/engines/saga/events.cpp b/engines/saga/events.cpp
index 191ea4ed61..b93c6017c7 100644
--- a/engines/saga/events.cpp
+++ b/engines/saga/events.cpp
@@ -341,6 +341,7 @@ int Events::handleOneShot(Event *event) {
_vm->_gfx->setPalette(palPointer);
}
}
+ _vm->_actor->showActors(true);
}
break;
case kAnimEvent:
diff --git a/engines/saga/gfx.h b/engines/saga/gfx.h
index 8658e6d992..0fa7aab742 100644
--- a/engines/saga/gfx.h
+++ b/engines/saga/gfx.h
@@ -85,7 +85,7 @@ struct PalEntry {
byte red;
byte green;
byte blue;
-};
+} PACKED_STRUCT;
#include "common/pack-end.h" // END STRUCT PACKING
diff --git a/engines/saga/interface.cpp b/engines/saga/interface.cpp
index 03fc0beb7a..55b2b0a996 100644
--- a/engines/saga/interface.cpp
+++ b/engines/saga/interface.cpp
@@ -1478,6 +1478,7 @@ void Interface::setOption(PanelButton *panelButton) {
case kTextLoad:
if (_vm->getSaveFilesCount() > 0) {
if (_vm->isSaveListFull() || (_optionSaveFileTitleNumber > 0)) {
+ debug(1, "Loading save game %d", _vm->getSaveFile(_optionSaveFileTitleNumber)->slotNumber);
fileName = _vm->calcSaveFileName(_vm->getSaveFile(_optionSaveFileTitleNumber)->slotNumber);
setMode(kPanelMain);
_vm->load(fileName);
diff --git a/engines/saga/music.cpp b/engines/saga/music.cpp
index 27729247ef..71b6964530 100644
--- a/engines/saga/music.cpp
+++ b/engines/saga/music.cpp
@@ -354,7 +354,7 @@ bool Music::isPlaying() {
void Music::play(uint32 resourceId, MusicFlags flags) {
Audio::AudioStream *audioStream = NULL;
MidiParser *parser;
- ResourceContext *context;
+ ResourceContext *context = NULL;
byte *resourceData;
size_t resourceSize;
uint32 loopStart;
@@ -413,7 +413,61 @@ void Music::play(uint32 resourceId, MusicFlags flags) {
loopStart = 4 * 18727;
}
- audioStream = new RAWInputStream(_vm, _musicContext, resourceId - 9, flags == MUSIC_LOOP, loopStart);
+ if (!(_vm->getFeatures() & GF_COMPRESSED_SOUNDS)) {
+ // uncompressed digital music
+ audioStream = new RAWInputStream(_vm, _musicContext, resourceId - 9, flags == MUSIC_LOOP, loopStart);
+ } else {
+ // compressed digital music
+ ResourceData * musicResourceData;
+ Common::File *_file;
+ byte compressedHeader[10];
+ GameSoundTypes soundType;
+
+ musicResourceData = _vm->_resource->getResourceData(_musicContext, resourceId - 9);
+ _file = _musicContext->getFile(musicResourceData);
+
+ if (_vm->getMusicInfo() == NULL) {
+ error("RAWInputStream() wrong musicInfo");
+ }
+
+ _file->seek((long)musicResourceData->offset, SEEK_SET);
+
+ _file->read(compressedHeader, 9);
+
+ if (compressedHeader[0] == char(0)) {
+ soundType = kSoundMP3;
+ } else if (compressedHeader[0] == char(1)) {
+ soundType = kSoundOGG;
+ } else if (compressedHeader[0] == char(2)) {
+ soundType = kSoundFLAC;
+ }
+
+ switch (soundType) {
+#ifdef USE_MAD
+ case kSoundMP3:
+ debug(1, "Playing MP3 compressed digital music");
+ audioStream = Audio::makeMP3Stream(_file, musicResourceData->size);
+ break;
+#endif
+#ifdef USE_VORBIS
+ case kSoundOGG:
+ debug(1, "Playing OGG compressed digital music");
+ audioStream = Audio::makeVorbisStream(_file, musicResourceData->size);
+ break;
+#endif
+#ifdef USE_FLAC
+ case kSoundFLAC:
+ debug(1, "Playing FLAC compressed digital music");
+ audioStream = Audio::makeFlacStream(_file, musicResourceData->size);
+ break;
+#endif
+ default:
+ // Unknown compression
+ error("Trying to play a compressed digital music, but the compression is not known");
+ break;
+ }
+
+ }
}
}
}
diff --git a/engines/saga/music.h b/engines/saga/music.h
index 125c85aa9b..96d8608bcd 100644
--- a/engines/saga/music.h
+++ b/engines/saga/music.h
@@ -31,6 +31,9 @@
#include "sound/audiocd.h"
#include "sound/mididrv.h"
#include "sound/midiparser.h"
+#include "sound/mp3.h"
+#include "sound/vorbis.h"
+#include "sound/flac.h"
namespace Saga {
diff --git a/engines/saga/render.cpp b/engines/saga/render.cpp
index 4e5d98bbf9..16536f762e 100644
--- a/engines/saga/render.cpp
+++ b/engines/saga/render.cpp
@@ -77,7 +77,7 @@ void Render::drawScene() {
assert(_initialized);
- _frameCount++;
+ _renderedFrameCount++;
backBufferSurface = _vm->_gfx->getBackBuffer();
@@ -183,8 +183,8 @@ void Render::fpsTimerCallback(void *refCon) {
}
void Render::fpsTimer(void) {
- _fps = _frameCount;
- _frameCount = 0;
+ _fps = _renderedFrameCount;
+ _renderedFrameCount = 0;
}
} // End of namespace Saga
diff --git a/engines/saga/render.h b/engines/saga/render.h
index c97de8efc9..4c6e3ee5b1 100644
--- a/engines/saga/render.h
+++ b/engines/saga/render.h
@@ -85,7 +85,7 @@ private:
Surface _backGroundSurface;
unsigned int _fps;
- unsigned int _frameCount;
+ unsigned int _renderedFrameCount;
uint32 _flags;
};
diff --git a/engines/saga/saga.h b/engines/saga/saga.h
index 9532d2fd56..844a738418 100644
--- a/engines/saga/saga.h
+++ b/engines/saga/saga.h
@@ -152,7 +152,8 @@ enum GameFeatures {
GF_BIG_ENDIAN_DATA = 1 << 0,
GF_WYRMKEEP = 1 << 1,
GF_CD_FX = 1 << 2,
- GF_SCENE_SUBSTITUTES = 1 << 3
+ GF_SCENE_SUBSTITUTES = 1 << 3,
+ GF_COMPRESSED_SOUNDS = 1 << 4
};
enum VerbTypeIds {
@@ -224,7 +225,10 @@ enum GameSoundTypes {
kSoundVOX = 1,
kSoundVOC = 2,
kSoundWAV = 3,
- kSoundMacPCM = 4
+ kSoundMacPCM = 4,
+ kSoundMP3 = 5,
+ kSoundOGG = 6,
+ kSoundFLAC = 7
};
enum TextStringIds {
@@ -335,6 +339,7 @@ enum GameObjectTypes {
enum ScriptTimings {
kScriptTimeTicksPerSecond = (728L/10L),
+ kScriptTimeTicksPerSecondIHNM = 72,
kRepeatSpeedTicks = (728L/10L)/3,
kNormalFadeDuration = 320, // 64 steps, 5 msec each
kQuickFadeDuration = 64, // 64 steps, 1 msec each
@@ -455,10 +460,6 @@ struct SaveGameHeader {
char name[SAVE_TITLE_SIZE];
};
-inline int ticksToMSec(int tick) {
- return tick * 1000 / kScriptTimeTicksPerSecond;
-}
-
inline int clamp(int minValue, int value, int maxValue) {
if (value <= minValue) {
return minValue;
@@ -591,6 +592,13 @@ public:
return _leftMouseButtonPressed || _rightMouseButtonPressed;
}
+ inline int ticksToMSec(int tick) {
+ if (getGameType() == GType_ITE)
+ return tick * 1000 / kScriptTimeTicksPerSecond;
+ else
+ return tick * 1000 / kScriptTimeTicksPerSecondIHNM;
+ }
+
private:
uint _saveFilesMaxCount;
uint _saveFilesCount;
diff --git a/engines/saga/scene.cpp b/engines/saga/scene.cpp
index 84d1b45114..362b212b14 100644
--- a/engines/saga/scene.cpp
+++ b/engines/saga/scene.cpp
@@ -570,6 +570,8 @@ void Scene::loadScene(LoadSceneParams *loadSceneParams) {
_chapterPointsChanged = false;
+ _vm->_actor->showActors(false);
+
if ((_vm->getGameType() == GType_IHNM) && (loadSceneParams->chapter != NO_CHAPTER_CHANGE)) {
if (loadSceneParams->loadFlag != kLoadBySceneNumber) {
error("loadScene wrong usage");
diff --git a/engines/saga/script.h b/engines/saga/script.h
index ec3a7e1cf4..5adfb6181a 100644
--- a/engines/saga/script.h
+++ b/engines/saga/script.h
@@ -598,7 +598,7 @@ private:
void sfClearGlobalFlag(SCRIPTFUNC_PARAMS);
void sfTestGlobalFlag(SCRIPTFUNC_PARAMS);
void sfSetPoints(SCRIPTFUNC_PARAMS);
- void sf103(SCRIPTFUNC_PARAMS);
+ void sfQueueMusic(SCRIPTFUNC_PARAMS);
void sfDisableAbortSpeeches(SCRIPTFUNC_PARAMS);
void SF_stub(const char *name, ScriptThread *thread, int nArgs);
diff --git a/engines/saga/sfuncs.cpp b/engines/saga/sfuncs.cpp
index e713326661..4954188a6e 100644
--- a/engines/saga/sfuncs.cpp
+++ b/engines/saga/sfuncs.cpp
@@ -240,7 +240,7 @@ static const ScriptFunctionDescription IHNMscriptFunctionsList[IHNM_SCRIPT_FUNCT
OPCODE(sfSetSpeechBox),
OPCODE(sfDebugShowData),
OPCODE(sfWaitFramesEsc),
- OPCODE(sf103),
+ OPCODE(sfQueueMusic),
OPCODE(sfDisableAbortSpeeches)
};
if (_vm->getGameType() == GType_IHNM)
@@ -266,7 +266,7 @@ void Script::sfWait(SCRIPTFUNC_PARAMS) {
time = thread->pop();
if (!_skipSpeeches) {
- thread->waitDelay(ticksToMSec(time)); // put thread to sleep
+ thread->waitDelay(_vm->ticksToMSec(time)); // put thread to sleep
}
}
@@ -437,7 +437,7 @@ void Script::sfStartBgdAnim(SCRIPTFUNC_PARAMS) {
int16 cycles = thread->pop();
_vm->_anim->setCycles(animId, cycles);
- _vm->_anim->setFrameTime(animId, ticksToMSec(kRepeatSpeedTicks));
+ _vm->_anim->setFrameTime(animId, _vm->ticksToMSec(kRepeatSpeedTicks));
_vm->_anim->play(animId, 0);
debug(1, "sfStartBgdAnim(%d, %d)", animId, cycles);
@@ -548,23 +548,30 @@ void Script::sfScriptGotoScene(SCRIPTFUNC_PARAMS) {
sceneNumber = thread->pop();
entrance = thread->pop();
- if (_vm->getGameType() == GType_IHNM)
+ if (_vm->getGameType() == GType_IHNM) {
transition = thread->pop();
- if (sceneNumber < 0) {
- if (_vm->getGameType() == GType_ITE) {
- _vm->shutDown();
- return;
- }
+ _vm->_gfx->setCursor(kCursorBusy);
}
- if (_vm->getGameType() == GType_IHNM) {
- warning("FIXME: implement sfScriptGotoScene differences for IHNM");
+ if ((_vm->getGameType() == GType_ITE && sceneNumber < 0) ||
+ (_vm->getGameType() == GType_IHNM && sceneNumber == 0)) {
+ // TODO: set creditsFlag to true for IHNM
+ _vm->shutDown();
+ return;
+ }
+ if (_vm->getGameType() == GType_IHNM) {
// Since it doesn't look like the IHNM scripts remove the
// cutaway after the intro, this is probably the best place to
// to it.
- _vm->_anim->clearCutaway();
+ Event event;
+ event.type = kEvTImmediate;
+ event.code = kCutawayEvent;
+ event.op = kEventClear;
+ event.time = 0;
+ event.duration = 0;
+ _vm->_events->queue(&event);
}
// It is possible to leave scene when converse panel is on,
@@ -574,6 +581,7 @@ void Script::sfScriptGotoScene(SCRIPTFUNC_PARAMS) {
_vm->_interface->setMode(kPanelMain);
}
+ // changeScene calls loadScene which calls setVerb. setVerb resets all pending objects and object flags
if (sceneNumber == -1 && _vm->getGameType() == GType_IHNM) {
// TODO: This is used to return back to the character selection screen in IHNM.
// However, it seems more than this is needed, AM's speech is wrong and no actors
@@ -583,10 +591,19 @@ void Script::sfScriptGotoScene(SCRIPTFUNC_PARAMS) {
_vm->_scene->changeScene(sceneNumber, entrance, (sceneNumber == ITE_SCENE_ENDCREDIT1) ? kTransitionFade : kTransitionNoFade);
}
- //TODO: placard stuff
+ if (_vm->_interface->getMode() == kPanelPlacard ||
+ _vm->_interface->getMode() == kPanelCutaway ||
+ _vm->_interface->getMode() == kPanelVideo) {
+ _vm->_gfx->showCursor(true);
+ _vm->_interface->setMode(kPanelMain);
+ }
+
_pendingVerb = _vm->_script->getVerbType(kVerbNone);
_currentObject[0] = _currentObject[1] = ID_NOTHING;
- showVerb();
+ showVerb(); // calls setStatusText("")
+
+ if (_vm->getGameType() == GType_IHNM)
+ _vm->_gfx->setCursor(kCursorNormal);
}
// Script function #17 (0x11)
@@ -684,7 +701,7 @@ void Script::sfSetBgdAnimSpeed(SCRIPTFUNC_PARAMS) {
int16 animId = thread->pop();
int16 speed = thread->pop();
- _vm->_anim->setFrameTime(animId, ticksToMSec(speed));
+ _vm->_anim->setFrameTime(animId, _vm->ticksToMSec(speed));
debug(1, "sfSetBgdAnimSpeed(%d, %d)", animId, speed);
}
@@ -712,7 +729,7 @@ void Script::sfStartBgdAnimSpeed(SCRIPTFUNC_PARAMS) {
int16 speed = thread->pop();
_vm->_anim->setCycles(animId, cycles);
- _vm->_anim->setFrameTime(animId, ticksToMSec(speed));
+ _vm->_anim->setFrameTime(animId, _vm->ticksToMSec(speed));
_vm->_anim->play(animId, 0);
debug(1, "sfStartBgdAnimSpeed(%d, %d, %d)", animId, cycles, speed);
@@ -1008,7 +1025,13 @@ void Script::sfCycleFrames(SCRIPTFUNC_PARAMS) {
actor->_actorFlags |= kActorRandom;
}
if (flags & kCycleReverse) {
- actor->_actorFlags |= kActorBackwards;
+ if (_vm->getGameType() == GType_IHNM &&
+ _vm->_scene->currentChapterNumber() == 2 && _vm->_scene->currentSceneNumber() == 41) {
+ // Prevent Benny from walking backwards after talking to the child via the monitor. This occurs in the
+ // original as well, and is fixed by not setting the kActorBackwards flag at this point
+ } else {
+ actor->_actorFlags |= kActorBackwards;
+ }
}
actor->_cycleFrameSequence = cycleFrameSequence;
@@ -1075,7 +1098,7 @@ void Script::sfChainBgdAnim(SCRIPTFUNC_PARAMS) {
if (speed >= 0) {
_vm->_anim->setCycles(animId, cycles);
_vm->_anim->stop(animId);
- _vm->_anim->setFrameTime(animId, ticksToMSec(speed));
+ _vm->_anim->setFrameTime(animId, _vm->ticksToMSec(speed));
}
_vm->_anim->link(animId1, animId);
@@ -2108,8 +2131,41 @@ void Script::sfWaitFramesEsc(SCRIPTFUNC_PARAMS) {
thread->_returnValue = _vm->_framesEsc;
}
-void Script::sf103(SCRIPTFUNC_PARAMS) {
- SF_stub("sf103", thread, nArgs);
+void Script::sfQueueMusic(SCRIPTFUNC_PARAMS) {
+ int16 param1 = thread->pop();
+ int16 param2 = thread->pop();
+ Event event;
+
+ if (param1 < 0) {
+ _vm->_music->stop();
+ return;
+ }
+
+ if (param1 >= _vm->_music->_songTableLen) {
+ warning("sfQueueMusic: Wrong song number (%d > %d)", param1, _vm->_music->_songTableLen - 1);
+ } else {
+ _vm->_music->setVolume(-1, 1);
+ event.type = kEvTOneshot;
+ event.code = kMusicEvent;
+ event.param = _vm->_music->_songTable[param1];
+ event.param2 = param2 ? MUSIC_LOOP : MUSIC_NORMAL;
+ event.op = kEventPlay;
+ event.time = _vm->ticksToMSec(500); // I find the delay in the original to be too long, so I've set it to
+ // wait for half the time, which sounds better when chapter points
+ // change
+ // FIXME: If this is too short for other cases apart from chapter
+ // point change, set it back to 1000
+
+ _vm->_events->queue(&event);
+
+ if (!_vm->_scene->haveChapterPointsChanged()) {
+ _vm->_scene->setCurrentMusicTrack(param1);
+ _vm->_scene->setCurrentMusicRepeat(param2);
+ } else {
+ // Don't save this music track when saving in IHNM
+ _vm->_scene->setChapterPointsChanged(false);
+ }
+ }
}
void Script::sfDisableAbortSpeeches(SCRIPTFUNC_PARAMS) {
diff --git a/engines/saga/sndres.cpp b/engines/saga/sndres.cpp
index c0442c75de..ceb1ebf630 100644
--- a/engines/saga/sndres.cpp
+++ b/engines/saga/sndres.cpp
@@ -156,7 +156,6 @@ bool SndRes::load(ResourceContext *context, uint32 resourceId, SoundBuffer &buff
return false;
}
-
_vm->_resource->loadResource(context, resourceId, soundResource, soundResourceLength);
if ((context->fileType & GAME_VOICEFILE) != 0) {
@@ -175,9 +174,20 @@ bool SndRes::load(ResourceContext *context, uint32 resourceId, SoundBuffer &buff
if (soundResourceLength >= 8) {
if (!memcmp(soundResource, "Creative", 8)) {
resourceType = kSoundVOC;
- } else if (!memcmp(soundResource, "RIFF", 4) != 0) {
+ } else if (!memcmp(soundResource, "RIFF", 4) != 0) {
resourceType = kSoundWAV;
+ }
+
+ if (_vm->getFeatures() & GF_COMPRESSED_SOUNDS) {
+ if (soundResource[0] == char(0)) {
+ resourceType = kSoundMP3;
+ } else if (soundResource[0] == char(1)) {
+ resourceType = kSoundOGG;
+ } else if (soundResource[0] == char(2)) {
+ resourceType = kSoundFLAC;
+ }
}
+
}
@@ -266,6 +276,29 @@ bool SndRes::load(ResourceContext *context, uint32 resourceId, SoundBuffer &buff
}
free(soundResource);
break;
+ case kSoundMP3:
+ case kSoundOGG:
+ case kSoundFLAC:
+ ResourceData *resourceData;
+ resourceData = _vm->_resource->getResourceData(context, resourceId);
+
+ // Read compressed sfx header
+ readS.seek(1); // Skip compression identifier byte
+ buffer.frequency = readS.readUint16LE();
+ buffer.originalSize = readS.readUint32LE();
+ buffer.sampleBits = readS.readByte();
+ buffer.stereo = (readS.readByte() == char(0)) ? false : true;
+
+ buffer.size = soundResourceLength;
+ buffer.soundType = resourceType;
+ buffer.soundFile = context->getFile(resourceData);
+ buffer.fileOffset = resourceData->offset + 9; // skip compressed sfx header: byte + uint16 + uint32 + byte + byte
+
+ buffer.buffer = NULL;
+
+ result = true;
+ free(soundResource);
+ break;
default:
error("SndRes::load Unknown sound type");
}
@@ -286,7 +319,10 @@ int SndRes::getVoiceLength(uint32 resourceId) {
return -1;
}
- msDouble = (double)buffer.size;
+ if (!(_vm->getFeatures() & GF_COMPRESSED_SOUNDS))
+ msDouble = (double)buffer.size;
+ else
+ msDouble = (double)buffer.originalSize;
if (buffer.sampleBits == 16) {
msDouble /= 2.0;
}
diff --git a/engines/saga/sound.cpp b/engines/saga/sound.cpp
index a4ce79b9c4..6c2516c8a3 100644
--- a/engines/saga/sound.cpp
+++ b/engines/saga/sound.cpp
@@ -80,7 +80,40 @@ void Sound::playSoundBuffer(Audio::SoundHandle *handle, SoundBuffer &buffer, int
if (!buffer.isSigned)
flags |= Audio::Mixer::FLAG_UNSIGNED;
- _mixer->playRaw(Audio::Mixer::kSFXSoundType, handle, buffer.buffer, buffer.size, buffer.frequency, flags, -1, volume);
+ if (!(_vm->getFeatures() & GF_COMPRESSED_SOUNDS)) {
+ _mixer->playRaw(Audio::Mixer::kSFXSoundType, handle, buffer.buffer, buffer.size, buffer.frequency, flags, -1, volume);
+ } else {
+ buffer.soundFile->seek((long)buffer.fileOffset, SEEK_SET);
+ Audio::AudioStream *stream = NULL;
+
+ switch (buffer.soundType) {
+#ifdef USE_MAD
+ case kSoundMP3:
+ debug(1, "Playing MP3 compressed sound");
+ stream = Audio::makeMP3Stream(buffer.soundFile, buffer.size);
+ break;
+#endif
+#ifdef USE_VORBIS
+ case kSoundOGG:
+ debug(1, "Playing OGG compressed sound");
+ stream = Audio::makeVorbisStream(buffer.soundFile, buffer.size);
+ break;
+#endif
+#ifdef USE_FLAC
+ case kSoundFLAC:
+ debug(1, "Playing FLAC compressed sound");
+ stream = Audio::makeFlacStream(buffer.soundFile, buffer.size);
+ break;
+#endif
+ default:
+ // Unknown compression
+ error("Trying to play a compressed sound, but the compression is not known");
+ break;
+ }
+
+ if (stream != NULL)
+ _mixer->playInputStream(Audio::Mixer::kSFXSoundType, handle, stream, -1, volume, 0, true, false);
+ }
}
void Sound::playSound(SoundBuffer &buffer, int volume, bool loop) {
diff --git a/engines/saga/sound.h b/engines/saga/sound.h
index 3abea583ba..961f8eba56 100644
--- a/engines/saga/sound.h
+++ b/engines/saga/sound.h
@@ -28,7 +28,11 @@
#ifndef SAGA_SOUND_H
#define SAGA_SOUND_H
+#include "common/file.h"
#include "sound/mixer.h"
+#include "sound/mp3.h"
+#include "sound/vorbis.h"
+#include "sound/flac.h"
namespace Saga {
@@ -46,7 +50,11 @@ struct SoundBuffer {
byte *buffer;
size_t size;
+ size_t originalSize;
bool isBigEndian;
+ GameSoundTypes soundType;
+ Common::File *soundFile;
+ size_t fileOffset;
};
enum sndHandleType {
diff --git a/engines/scumm/akos.cpp b/engines/scumm/akos.cpp
index 2a51464341..c8667d7ab2 100644
--- a/engines/scumm/akos.cpp
+++ b/engines/scumm/akos.cpp
@@ -47,12 +47,12 @@ struct AkosHeader {
uint16 num_anims;
uint16 unk_3;
uint16 codec;
-};
+} PACKED_STRUCT;
struct AkosOffset {
uint32 akcd; // offset into the akcd data
uint16 akci; // offset into the akci data
-};
+} PACKED_STRUCT;
#include "common/pack-end.h" // END STRUCT PACKING
diff --git a/engines/scumm/base-costume.h b/engines/scumm/base-costume.h
index e6ef618a3e..155bbff97f 100644
--- a/engines/scumm/base-costume.h
+++ b/engines/scumm/base-costume.h
@@ -37,7 +37,7 @@ struct CostumeInfo {
uint16 width, height;
int16 rel_x, rel_y;
int16 move_x, move_y;
-};
+} PACKED_STRUCT;
#include "common/pack-end.h" // END STRUCT PACKING
diff --git a/engines/scumm/boxes.cpp b/engines/scumm/boxes.cpp
index 424e5d891e..e79cea4359 100644
--- a/engines/scumm/boxes.cpp
+++ b/engines/scumm/boxes.cpp
@@ -80,7 +80,7 @@ struct Box { /* Internal walkbox file format */
uint32 unk3;
} v8;
};
-};
+} PACKED_STRUCT;
#include "common/pack-end.h" // END STRUCT PACKING
diff --git a/engines/scumm/detection.cpp b/engines/scumm/detection.cpp
index 8624f80fe7..e9430337ff 100644
--- a/engines/scumm/detection.cpp
+++ b/engines/scumm/detection.cpp
@@ -765,19 +765,22 @@ PluginError Engine_SCUMM_create(OSystem *syst, Engine **engine) {
// narrow down the list a bit more.
if (results.size() > 1 && ConfMan.hasKey("platform")) {
Common::Platform platform = Common::parsePlatform(ConfMan.get("platform"));
+ Common::List<DetectorResult> tmp;
+
+ // Copy only those candidates which match the platform setting
for (Common::List<DetectorResult>::iterator x = results.begin(); x != results.end(); ) {
- if (x->game.platform != platform) {
- x = results.erase(x);
- } else {
- ++x;
+ if (x->game.platform == platform) {
+ tmp.push_back(*x);
}
}
- }
- // If we narrowed it down too much, abort
- if (results.empty()) {
- warning("Engine_SCUMM_create: Game data inconsistent with platform override");
- return kNoGameDataFoundError;
+ // If we narrowed it down too much, print a warning, else use the list
+ // we just computed as new candidates list.
+ if (tmp.empty()) {
+ warning("Engine_SCUMM_create: Game data inconsistent with platform override");
+ } else {
+ results = tmp;
+ }
}
// Still no unique match found -> print a warning
diff --git a/engines/scumm/dialogs.cpp b/engines/scumm/dialogs.cpp
index 85a7a4b675..16fe72531b 100644
--- a/engines/scumm/dialogs.cpp
+++ b/engines/scumm/dialogs.cpp
@@ -825,26 +825,26 @@ PauseDialog::PauseDialog(ScummEngine *scumm, int res)
: InfoDialog(scumm, res) {
}
-void PauseDialog::handleKeyDown(uint16 ascii, int keycode, int modifiers) {
- if (ascii == ' ') // Close pause dialog if space key is pressed
+void PauseDialog::handleKeyDown(Common::KeyState state) {
+ if (state.ascii == ' ') // Close pause dialog if space key is pressed
close();
else
- ScummDialog::handleKeyDown(ascii, keycode, modifiers);
+ ScummDialog::handleKeyDown(state);
}
ConfirmDialog::ConfirmDialog(ScummEngine *scumm, int res)
: InfoDialog(scumm, res) {
}
-void ConfirmDialog::handleKeyDown(uint16 ascii, int keycode, int modifiers) {
- if (tolower(ascii) == 'n') {
+void ConfirmDialog::handleKeyDown(Common::KeyState state) {
+ if (state.keycode == Common::KEYCODE_n) {
setResult(0);
close();
- } else if (tolower(ascii) == 'y') {
+ } else if (state.keycode == Common::KEYCODE_y) {
setResult(1);
close();
} else
- ScummDialog::handleKeyDown(ascii, keycode, modifiers);
+ ScummDialog::handleKeyDown(state);
}
#pragma mark -
@@ -892,11 +892,11 @@ void ValueDisplayDialog::reflowLayout() {
_h = height;
}
-void ValueDisplayDialog::handleKeyDown(uint16 ascii, int keycode, int modifiers) {
- if (ascii == _incKey || ascii == _decKey) {
- if (ascii == _incKey && _value < _max)
+void ValueDisplayDialog::handleKeyDown(Common::KeyState state) {
+ if (state.ascii == _incKey || state.ascii == _decKey) {
+ if (state.ascii == _incKey && _value < _max)
_value++;
- else if (ascii == _decKey && _value > _min)
+ else if (state.ascii == _decKey && _value > _min)
_value--;
setResult(_value);
@@ -924,8 +924,8 @@ void SubtitleSettingsDialog::handleTickle() {
close();
}
-void SubtitleSettingsDialog::handleKeyDown(uint16 ascii, int keycode, int modifiers) {
- if (keycode == 't' && modifiers == Common::KBD_CTRL) {
+void SubtitleSettingsDialog::handleKeyDown(Common::KeyState state) {
+ if (state.keycode == 't' && state.flags == Common::KBD_CTRL) {
cycleValue();
reflowLayout();
@@ -959,11 +959,11 @@ Indy3IQPointsDialog::Indy3IQPointsDialog(ScummEngine *scumm, char* text)
: InfoDialog(scumm, text) {
}
-void Indy3IQPointsDialog::handleKeyDown(uint16 ascii, int keycode, int modifiers) {
- if (ascii == 'i')
+void Indy3IQPointsDialog::handleKeyDown(Common::KeyState state) {
+ if (state.ascii == 'i')
close();
else
- ScummDialog::handleKeyDown(ascii, keycode, modifiers);
+ ScummDialog::handleKeyDown(state);
}
} // End of namespace Scumm
diff --git a/engines/scumm/dialogs.h b/engines/scumm/dialogs.h
index b69e989f8a..23c63d8992 100644
--- a/engines/scumm/dialogs.h
+++ b/engines/scumm/dialogs.h
@@ -169,8 +169,8 @@ public:
setResult(0);
close();
}
- virtual void handleKeyDown(uint16 ascii, int keycode, int modifiers) {
- setResult(ascii);
+ virtual void handleKeyDown(Common::KeyState state) {
+ setResult(state.ascii);
close();
}
@@ -189,7 +189,7 @@ protected:
class PauseDialog : public InfoDialog {
public:
PauseDialog(ScummEngine *scumm, int res);
- virtual void handleKeyDown(uint16 ascii, int keycode, int modifiers);
+ virtual void handleKeyDown(Common::KeyState state);
};
/**
@@ -199,7 +199,7 @@ public:
class ConfirmDialog : public InfoDialog {
public:
ConfirmDialog(ScummEngine *scumm, int res);
- virtual void handleKeyDown(uint16 ascii, int keycode, int modifiers);
+ virtual void handleKeyDown(Common::KeyState state);
};
/**
@@ -216,7 +216,7 @@ public:
virtual void handleMouseDown(int x, int y, int button, int clickCount) {
close();
}
- virtual void handleKeyDown(uint16 ascii, int keycode, int modifiers);
+ virtual void handleKeyDown(Common::KeyState state);
virtual void reflowLayout();
@@ -247,7 +247,7 @@ public:
virtual void handleMouseDown(int x, int y, int button, int clickCount) {
close();
}
- virtual void handleKeyDown(uint16 ascii, int keycode, int modifiers);
+ virtual void handleKeyDown(Common::KeyState state);
protected:
int _value;
uint32 _timer;
@@ -259,7 +259,7 @@ protected:
class Indy3IQPointsDialog : public InfoDialog {
public:
Indy3IQPointsDialog(ScummEngine *scumm, char* text);
- virtual void handleKeyDown(uint16 ascii, int keycode, int modifiers);
+ virtual void handleKeyDown(Common::KeyState state);
};
} // End of namespace Scumm
diff --git a/engines/scumm/file.cpp b/engines/scumm/file.cpp
index 3ab3e1a2e0..2c7f9ead5b 100644
--- a/engines/scumm/file.cpp
+++ b/engines/scumm/file.cpp
@@ -1257,10 +1257,11 @@ struct _lfl_index {
uint16 script_addr[200];
byte sound_lfl[100];
uint16 sound_addr[100];
-} lfl_index;
+} PACKED_STRUCT;
#include "common/pack-end.h" // END STRUCT PACKING
+_lfl_index lfl_index;
bool ScummNESFile::generateResource(int res) {
const LFL *lfl = &lfls[res - 1];
diff --git a/engines/scumm/he/intern_he.h b/engines/scumm/he/intern_he.h
index 54eb470c26..84ad8adb3b 100644
--- a/engines/scumm/he/intern_he.h
+++ b/engines/scumm/he/intern_he.h
@@ -250,7 +250,7 @@ protected:
int32 dim2start; //0C
int32 dim2end; //10
byte data[1]; //14
- };
+ } PACKED_STRUCT;
#include "common/pack-end.h" // END STRUCT PACKING
diff --git a/engines/scumm/he/resource_he.h b/engines/scumm/he/resource_he.h
index 757cf13b7c..d7f4d99754 100644
--- a/engines/scumm/he/resource_he.h
+++ b/engines/scumm/he/resource_he.h
@@ -172,7 +172,7 @@ class Win32ResExtractor : public ResExtractor {
byte *memory;
byte *first_resource;
int total_size;
- };
+ } PACKED_STRUCT;
struct WinResource {
char id[256];
@@ -183,7 +183,7 @@ class Win32ResExtractor : public ResExtractor {
bool is_directory;
char *get_resource_id_quoted();
- };
+ } PACKED_STRUCT;
struct Win32IconResDir {
@@ -191,12 +191,12 @@ class Win32ResExtractor : public ResExtractor {
byte height;
byte color_count;
byte reserved;
- };
+ } PACKED_STRUCT;
struct Win32CursorDir {
uint16 width;
uint16 height;
- };
+ } PACKED_STRUCT;
struct Win32CursorIconDirEntry {
union {
@@ -207,14 +207,14 @@ class Win32ResExtractor : public ResExtractor {
uint16 bit_count;
uint32 bytes_in_res;
uint16 res_id;
- };
+ } PACKED_STRUCT;
struct Win32CursorIconDir {
uint16 reserved;
uint16 type;
uint16 count;
Win32CursorIconDirEntry entries[1];
- };
+ } PACKED_STRUCT;
struct Win32CursorIconFileDirEntry {
byte width;
@@ -225,14 +225,14 @@ class Win32ResExtractor : public ResExtractor {
uint16 hotspot_y;
uint32 dib_size;
uint32 dib_offset;
- };
+ } PACKED_STRUCT;
struct Win32CursorIconFileDir {
uint16 reserved;
uint16 type;
uint16 count;
Win32CursorIconFileDirEntry entries[1];
- };
+ } PACKED_STRUCT;
struct Win32BitmapInfoHeader {
uint32 size;
@@ -246,25 +246,25 @@ class Win32ResExtractor : public ResExtractor {
int32 y_pels_per_meter;
uint32 clr_used;
uint32 clr_important;
- };
+ } PACKED_STRUCT;
struct Win32RGBQuad {
byte blue;
byte green;
byte red;
byte reserved;
- };
+ } PACKED_STRUCT;
struct Win32ImageResourceDirectoryEntry {
uint32 name;
uint32 offset_to_data;
- };
+ } PACKED_STRUCT;
struct Win16NETypeInfo {
uint16 type_id;
uint16 count;
uint32 resloader; // FARPROC16 - smaller? uint16?
- };
+ } PACKED_STRUCT;
struct DOSImageHeader {
uint16 magic;
@@ -286,7 +286,7 @@ class Win32ResExtractor : public ResExtractor {
uint16 oeminfo;
uint16 res2[10];
uint32 lfanew;
- };
+ } PACKED_STRUCT;
struct Win32ImageFileHeader {
uint16 machine;
@@ -296,12 +296,12 @@ class Win32ResExtractor : public ResExtractor {
uint32 number_of_symbols;
uint16 size_of_optional_header;
uint16 characteristics;
- };
+ } PACKED_STRUCT;
struct Win32ImageDataDirectory {
uint32 virtual_address;
uint32 size;
- };
+ } PACKED_STRUCT;
struct Win32ImageOptionalHeader {
uint16 magic;
@@ -335,13 +335,13 @@ class Win32ResExtractor : public ResExtractor {
uint32 loader_flags;
uint32 number_of_rva_and_sizes;
Win32ImageDataDirectory data_directory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];
- };
+ } PACKED_STRUCT;
struct Win32ImageNTHeaders {
uint32 signature;
Win32ImageFileHeader file_header;
Win32ImageOptionalHeader optional_header;
- };
+ } PACKED_STRUCT;
struct Win32ImageSectionHeader {
byte name[IMAGE_SIZEOF_SHORT_NAME];
@@ -357,14 +357,14 @@ class Win32ResExtractor : public ResExtractor {
uint16 number_of_relocations;
uint16 number_of_linenumbers;
uint32 characteristics;
- };
+ } PACKED_STRUCT;
struct Win32ImageResourceDataEntry {
uint32 offset_to_data;
uint32 size;
uint32 code_page;
uint32 resource_handle;
- };
+ } PACKED_STRUCT;
struct Win32ImageResourceDirectory {
uint32 characteristics;
@@ -373,7 +373,7 @@ class Win32ResExtractor : public ResExtractor {
uint16 minor_version;
uint16 number_of_named_entries;
uint16 number_of_id_entries;
- };
+ } PACKED_STRUCT;
#include "common/pack-end.h" // END STRUCT PACKING
diff --git a/engines/scumm/imuse/instrument.cpp b/engines/scumm/imuse/instrument.cpp
index 23b325c20b..b6ed064bc9 100644
--- a/engines/scumm/imuse/instrument.cpp
+++ b/engines/scumm/imuse/instrument.cpp
@@ -149,7 +149,7 @@ private:
#include "common/pack-start.h" // START STRUCT PACKING
- struct {
+ struct AdlibInstrument {
byte flags_1;
byte oplvl_1;
byte atdec_1;
@@ -166,10 +166,12 @@ private:
byte flags_b;
struct { byte a,b,c,d,e,f,g,h; } extra_b;
byte duration;
- } _instrument;
+ } PACKED_STRUCT;
#include "common/pack-end.h" // END STRUCT PACKING
+ AdlibInstrument _instrument;
+
public:
Instrument_Adlib(const byte *data);
Instrument_Adlib(Serializer *s);
@@ -241,7 +243,7 @@ private:
byte tva_env_sustain_level;
} partial[4];
byte checksum;
- };
+ } PACKED_STRUCT;
#include "common/pack-end.h" // END STRUCT PACKING
diff --git a/engines/scumm/input.cpp b/engines/scumm/input.cpp
index 2d7401fe57..ffcb7d03f2 100644
--- a/engines/scumm/input.cpp
+++ b/engines/scumm/input.cpp
@@ -75,83 +75,53 @@ void ScummEngine::parseEvents() {
sprintf(_saveLoadName, "Quicksave %d", _saveLoadSlot);
_saveLoadFlag = (event.kbd.flags == Common::KBD_ALT) ? 1 : 2;
_saveTemporaryState = false;
- } else if (event.kbd.flags == Common::KBD_CTRL) {
- if (event.kbd.keycode == 'f')
- _fastMode ^= 1;
- else if (event.kbd.keycode == 'g')
- _fastMode ^= 2;
- else if (event.kbd.keycode == 'd')
- _debugger->attach();
- else if (event.kbd.keycode == 's')
- _res->resourceStats();
- else
- _keyPressed = event.kbd; // Normal key press, pass on to the game.
- } else if (event.kbd.flags & Common::KBD_ALT) {
- // Handle KBD_ALT combos. We know that the result must be 273 for Alt-W
- // because that's what MI2 looks for in its "instant win" cheat.
-
- // FIXME: Handle this specific property of MI2 inside processKeyboard ?
- _keyPressed = event.kbd;
- _keyPressed.ascii = event.kbd.keycode + 154;
+ } else if (event.kbd.flags == Common::KBD_CTRL && event.kbd.keycode == 'f') {
+ _fastMode ^= 1;
+ } else if (event.kbd.flags == Common::KBD_CTRL && event.kbd.keycode == 'g') {
+ _fastMode ^= 2;
+ } else if ((event.kbd.flags == Common::KBD_CTRL && event.kbd.keycode == 'd') ||
+ event.kbd.ascii == '~' || event.kbd.ascii == '#') {
+ _debugger->attach();
+ } else if (event.kbd.flags == Common::KBD_CTRL && event.kbd.keycode == 's') {
+ _res->resourceStats();
} else {
// Normal key press, pass on to the game.
_keyPressed = event.kbd;
}
- if (event.kbd.keycode >= Common::KEYCODE_UP && event.kbd.keycode <= Common::KEYCODE_LEFT) {
- if (_game.id == GID_MONKEY && _game.platform == Common::kPlatformSegaCD) {
- _keyPressed = event.kbd;
- _keyPressed.ascii = event.kbd.ascii - Common::KEYCODE_UP + 54;
- } else if (_game.version < 7) {
- // FIXME: Handle this specific property inside processKeyboard ?
-
- // Don't let game see arrow keys. This fixes bug with up arrow (273)
- // corresponding to the "instant win" cheat in MI2 mentioned above.
- //
- // This is not applicable to V7+ games, which need to see the arrow keys,
- // too, else certain things (derby scene, asterorid lander) won't work.
- _keyPressed.reset();
- }
- }
-
if (_game.heversion >= 80) {
// Keyboard is controlled via variable
- int _keyState = 0;
+ int keyState = 0;
if (event.kbd.keycode == Common::KEYCODE_LEFT) // Left
- _keyState = 1;
+ keyState = 1;
if (event.kbd.keycode == Common::KEYCODE_RIGHT) // Right
- _keyState |= 2;
+ keyState |= 2;
if (event.kbd.keycode == Common::KEYCODE_UP) // Up
- _keyState |= 4;
+ keyState |= 4;
if (event.kbd.keycode == Common::KEYCODE_DOWN) // Down
- _keyState |= 8;
+ keyState |= 8;
if (event.kbd.flags == Common::KBD_SHIFT)
- _keyState |= 16;
+ keyState |= 16;
if (event.kbd.flags == Common::KBD_CTRL)
- _keyState |= 32;
+ keyState |= 32;
- VAR(VAR_KEY_STATE) = _keyState;
+ VAR(VAR_KEY_STATE) = keyState;
}
- // FIXME: There is a discrepancy between EVENT_KEYDOWN and EVENT_KEYUP here:
- // For EVENT_KEYDOWN, we use _keyPressed.keycode, which has potentially been
- // modified, while for EVENT_KEYUP we use the unfiltered event.kbd.keycode.
- // This could lead problems (like a key becoming 'stuck').
-
- // FIXME #2: We are mixing ascii and keycode values here. We probably should
- // be using keycodes, but at least INSANE checks for "Shift-V" by looking for
- // the 'V' key being pressed. It would be easy to solve that by also storing the
- // the modifier flags. However, since getKeyState() is also called by scripts,
- // we have to be very careful with semantic changes.
- // Nevertheless, it's bad to rely on "ascii" holdoing keycode values for special
- // keys (like the function keys), so this should be fixed.
-
+ // FIXME: We are using ASCII values to index the _keyDownMap here,
+ // yet later one code which checks _keyDownMap will use KEYCODEs
+ // to do so. That is, we are mixing ascii and keycode values here,
+ // which is bad. We probably should be only using keycodes, but at
+ // least INSANE checks for "Shift-V" by looking for the 'V' key
+ // being pressed. It would be easy to solve that by also storing
+ // the modifier flags. However, since getKeyState() is also called
+ // by scripts, we have to be careful with semantic changes.
if (_keyPressed.ascii >= 512)
debugC(DEBUG_GENERAL, "_keyPressed > 512 (%d)", _keyPressed.ascii);
else
@@ -159,11 +129,9 @@ void ScummEngine::parseEvents() {
break;
case Common::EVENT_KEYUP:
- // FIXME: for some reason Common::KBD_ALT is set sometimes
- // possible to a bug in sdl-common.cpp
- if (event.kbd.ascii >= 512)
+ if (event.kbd.ascii >= 512) {
debugC(DEBUG_GENERAL, "keyPressed > 512 (%d)", event.kbd.ascii);
- else {
+ } else {
_keyDownMap[event.kbd.ascii] = false;
// Due to some weird bug with capslock key pressed
@@ -173,6 +141,8 @@ void ScummEngine::parseEvents() {
// both upper and lower letters are unpressed on keyup event
//
// Fixes bug #1709430: "FT: CAPSLOCK + V enables cheating for all fights"
+ //
+ // Fingolfin remarks: This wouldn't be a problem if we used keycodes.
_keyDownMap[toupper(event.kbd.ascii)] = false;
}
break;
@@ -204,24 +174,21 @@ void ScummEngine::parseEvents() {
_rightBtnPressed &= ~msDown;
break;
- // The following two cases enable dialog choices to be
- // scrolled through in the SegaCD version of MI
- // as nothing else uses the wheel don't bother
- // checking the gameid. Values are taken from script-14.
-
+ // The following two cases enable dialog choices to be scrolled
+ // through in the SegaCD version of MI. Values are taken from script-14.
+ // See bug report #1193185 for details.
case Common::EVENT_WHEELDOWN:
- _keyPressed = Common::KeyState(Common::KEYCODE_7, 55); // '7'
+ if (_game.id == GID_MONKEY && _game.platform == Common::kPlatformSegaCD)
+ _keyPressed = Common::KeyState(Common::KEYCODE_7, 55); // '7'
break;
case Common::EVENT_WHEELUP:
- _keyPressed = Common::KeyState(Common::KEYCODE_6, 54); // '6'
+ if (_game.id == GID_MONKEY && _game.platform == Common::kPlatformSegaCD)
+ _keyPressed = Common::KeyState(Common::KEYCODE_6, 54); // '6'
break;
case Common::EVENT_QUIT:
- if (ConfMan.getBool("confirm_exit"))
- confirmExitDialog();
- else
- _quit = true;
+ _quit = true;
break;
default:
@@ -446,11 +413,6 @@ void ScummEngine_v2::processKeyboard(Common::KeyState lastKeyHit) {
// Fall back to default behavior
ScummEngine::processKeyboard(lastKeyHit);
- // Store the input type. So far we can't distinguish
- // between 1, 3 and 5.
- // 1) Verb 2) Scene 3) Inv. 4) Key
- // 5) Sentence Bar
-
if (VAR_KEYPRESS != 0xFF && _mouseAndKeyboardStat) { // Key Input
if (315 <= _mouseAndKeyboardStat && _mouseAndKeyboardStat <= 323) {
// Convert F-Keys for V1/V2 games (they start at 1)
@@ -503,12 +465,6 @@ void ScummEngine::processKeyboard(Common::KeyState lastKeyHit) {
if (_game.id == GID_CMI)
mainmenuKeyEnabled = true;
-/*
- FIXME: We also used to force-enable F5 in Sam&Max and HE >= 72 games -- why?
- if ((_game.version <= 3) || (_game.id == GID_SAMNMAX) || (_game.id == GID_CMI) || (_game.heversion >= 72))
- mainmenuKeyEnabled = true;
-*/
-
if (mainmenuKeyEnabled && (lastKeyHit.keycode == Common::KEYCODE_F5 && lastKeyHit.flags == 0)) {
if (VAR_SAVELOAD_SCRIPT != 0xFF && _currentRoom != 0)
runScript(VAR(VAR_SAVELOAD_SCRIPT), 0, 0, 0);
@@ -569,15 +525,35 @@ void ScummEngine::processKeyboard(Common::KeyState lastKeyHit) {
if (VAR_CHARINC != 0xFF)
VAR(VAR_CHARINC) = _defaultTalkDelay;
- } else if (lastKeyHit.ascii == '~' || lastKeyHit.ascii == '#') { // Debug console
- _debugger->attach();
-
} else {
- // FIXME: Possibly convert even more keycode/ascii pairs to their SCUMM counterparts?
- if (lastKeyHit.keycode >= Common::KEYCODE_F1 && lastKeyHit.keycode <= Common::KEYCODE_F9)
+
+ if (lastKeyHit.keycode >= Common::KEYCODE_F1 &&
+ lastKeyHit.keycode <= Common::KEYCODE_F9) {
_mouseAndKeyboardStat = lastKeyHit.keycode - Common::KEYCODE_F1 + 315;
- else
+
+ } else if (_game.id == GID_MONKEY2 && (lastKeyHit.flags & Common::KBD_ALT)) {
+ // Handle KBD_ALT combos in MI2. We know that the result must be 273 for Alt-W
+ // because that's what MI2 looks for in its "instant win" cheat.
+ _mouseAndKeyboardStat = lastKeyHit.keycode + 154;
+
+ } else if (lastKeyHit.keycode >= Common::KEYCODE_UP &&
+ lastKeyHit.keycode <= Common::KEYCODE_LEFT) {
+ if (_game.id == GID_MONKEY && _game.platform == Common::kPlatformSegaCD) {
+ // Map arrow keys to number keys in the SEGA version of MI to support
+ // scrolling to conversation choices. See bug report #1193185 for details.
+ _mouseAndKeyboardStat = lastKeyHit.keycode - Common::KEYCODE_UP + 54;
+ } else if (_game.version >= 7) {
+ // Don't let pre-V7 game see arrow keys. This fixes bug with up arrow (273)
+ // corresponding to the "instant win" cheat in MI2 mentioned above.
+ //
+ // This is not applicable to V7+ games, which need to see the arrow keys,
+ // too, else certain things (derby scene, asterorid lander) won't work.
+ _mouseAndKeyboardStat = lastKeyHit.ascii;
+ }
+
+ } else {
_mouseAndKeyboardStat = lastKeyHit.ascii;
+ }
}
}
diff --git a/engines/scumm/intern.h b/engines/scumm/intern.h
index 008c2995e5..6723081dfe 100644
--- a/engines/scumm/intern.h
+++ b/engines/scumm/intern.h
@@ -313,7 +313,7 @@ protected:
virtual void readGlobalObjects();
virtual void loadCharset(int no);
- virtual void runInputScript(int a, int cmd, int mode);
+ virtual void runInputScript(int clickArea, int val, int mode);
virtual void runInventoryScript(int i);
virtual int getVar();
@@ -554,7 +554,7 @@ protected:
int16 type;
int16 dim2;
byte data[1];
- };
+ } PACKED_STRUCT;
#include "common/pack-end.h" // END STRUCT PACKING
diff --git a/engines/scumm/module.mk b/engines/scumm/module.mk
index d7b858a312..d8ef669410 100644
--- a/engines/scumm/module.mk
+++ b/engines/scumm/module.mk
@@ -82,6 +82,12 @@ MODULE_OBJS += \
smush/saud_channel.o \
smush/smush_mixer.o \
smush/smush_font.o
+
+ifdef USE_ARM_SMUSH_ASM
+MODULE_OBJS += \
+ smush/codec47ARM.o
+endif
+
endif
ifndef DISABLE_HE
diff --git a/engines/scumm/object.h b/engines/scumm/object.h
index bf38d42289..f27e6a501e 100644
--- a/engines/scumm/object.h
+++ b/engines/scumm/object.h
@@ -91,7 +91,7 @@ struct RoomHeader {
uint32 transparency;
} v8;
};
-};
+} PACKED_STRUCT;
struct CodeHeader {
union {
@@ -123,7 +123,7 @@ struct CodeHeader {
} v7;
};
-};
+} PACKED_STRUCT;
struct ImageHeader { /* file format */
union {
@@ -172,7 +172,7 @@ struct ImageHeader { /* file format */
} hotspot[15];
} v8;
};
-};
+} PACKED_STRUCT;
#include "common/pack-end.h" // END STRUCT PACKING
diff --git a/engines/scumm/player_v2.h b/engines/scumm/player_v2.h
index 43771d295f..cd88d57602 100644
--- a/engines/scumm/player_v2.h
+++ b/engines/scumm/player_v2.h
@@ -61,7 +61,7 @@ struct channel_data {
uint16 unknown[4]; // 38 - 44
uint16 music_timer; // 46
uint16 music_script_nr; // 48
-};
+} PACKED_STRUCT;
#include "common/pack-end.h" // END STRUCT PACKING
diff --git a/engines/scumm/saveload.cpp b/engines/scumm/saveload.cpp
index 9578b05c1f..9d0d0ad654 100644
--- a/engines/scumm/saveload.cpp
+++ b/engines/scumm/saveload.cpp
@@ -200,8 +200,6 @@ bool ScummEngine::loadState(int slot, bool compat) {
_engineStartTime = _system->getMillis() / 1000;
}
- _dialogStartTime = _system->getMillis() / 1000;
-
// Due to a bug in scummvm up to and including 0.3.0, save games could be saved
// in the V8/V9 format but were tagged with a V7 mark. Ouch. So we just pretend V7 == V8 here
if (hdr.ver == VER(7))
@@ -213,7 +211,7 @@ bool ScummEngine::loadState(int slot, bool compat) {
// state for temporary state saves - such as certain cutscenes in DOTT,
// FOA, Sam and Max, etc.
//
- // Thusly, we should probably not stop music when restoring from one of
+ // Thus, we should probably not stop music when restoring from one of
// these saves. This change stops the Mole Man theme from going quiet in
// Sam & Max when Doug tells you about the Ball of Twine, as mentioned in
// patch #886058.
@@ -378,9 +376,6 @@ bool ScummEngine::loadState(int slot, bool compat) {
_sound->pauseSounds(false);
- _engineStartTime += _system->getMillis() / 1000 - _dialogStartTime;
- _dialogStartTime = 0;
-
return true;
}
diff --git a/engines/scumm/script.cpp b/engines/scumm/script.cpp
index 46e4e64347..cc56adf622 100644
--- a/engines/scumm/script.cpp
+++ b/engines/scumm/script.cpp
@@ -1156,39 +1156,39 @@ void ScummEngine::checkAndRunSentenceScript() {
runScript(sentenceScript, 0, 0, localParamList);
}
-void ScummEngine_v2::runInputScript(int a, int cmd, int mode) {
+void ScummEngine_v2::runInputScript(int clickArea, int val, int mode) {
int args[24];
int verbScript;
verbScript = 4;
- VAR(VAR_CLICK_AREA) = a;
- switch (a) {
- case 1: // Verb clicked
- VAR(VAR_CLICK_VERB) = cmd;
+ VAR(VAR_CLICK_AREA) = clickArea;
+ switch (clickArea) {
+ case kVerbClickArea: // Verb clicked
+ VAR(VAR_CLICK_VERB) = val;
break;
- case 3: // Inventory clicked
- VAR(VAR_CLICK_OBJECT) = cmd;
+ case kInventoryClickArea: // Inventory clicked
+ VAR(VAR_CLICK_OBJECT) = val;
break;
}
memset(args, 0, sizeof(args));
- args[0] = a;
- args[1] = cmd;
+ args[0] = clickArea;
+ args[1] = val;
args[2] = mode;
if (verbScript)
runScript(verbScript, 0, 0, args);
}
-void ScummEngine::runInputScript(int a, int cmd, int mode) {
+void ScummEngine::runInputScript(int clickArea, int val, int mode) {
int args[24];
int verbScript;
verbScript = VAR(VAR_VERB_SCRIPT);
memset(args, 0, sizeof(args));
- args[0] = a;
- args[1] = cmd;
+ args[0] = clickArea;
+ args[1] = val;
args[2] = mode;
// All HE 72+ games but only some HE 71 games.
if (_game.heversion >= 71) {
@@ -1198,18 +1198,18 @@ void ScummEngine::runInputScript(int a, int cmd, int mode) {
// Macintosh verison of indy3ega used different interface, so adjust values.
if (_game.id == GID_INDY3 && _game.platform == Common::kPlatformMacintosh) {
- if (a == 1 && (cmd >= 101 && cmd <= 108)) {
- if (cmd == 107) {
+ if (clickArea == kVerbClickArea && (val >= 101 && val <= 108)) {
+ if (val == 107) {
VAR(67) -= 2;
inventoryScript();
return;
- } else if (cmd == 108) {
+ } else if (val == 108) {
VAR(67) += 2;
inventoryScript();
return;
} else {
args[0] = 3;
- args[1] = VAR(83 + (cmd - 101));
+ args[1] = VAR(83 + (val - 101));
}
}
}
diff --git a/engines/scumm/scumm-md5.h b/engines/scumm/scumm-md5.h
index 840940caa3..cd48ef4d02 100644
--- a/engines/scumm/scumm-md5.h
+++ b/engines/scumm/scumm-md5.h
@@ -1,5 +1,5 @@
/*
- This file was generated by the md5table tool on Fri Jun 08 10:51:50 2007
+ This file was generated by the md5table tool on Mon Jul 2 22:44:41 2007
DO NOT EDIT MANUALLY!
*/
@@ -254,6 +254,7 @@ static const MD5Table md5table[] = {
{ "6886e5d08cee329b1f2e743ae2e3ceed", "monkey2", "", "", 11135, Common::DE_DEU, Common::kPlatformPC },
{ "695fe0b3963333b7e15b37514db3c745", "thinkerk", "", "Demo", 29789, Common::EN_USA, Common::kPlatformUnknown },
{ "697c9b7c55a05d8199c48b48e379d2c8", "puttmoon", "", "", -1, Common::HB_ISR, Common::kPlatformPC },
+ { "69d70269fafc4445adbb0d223e4f9a3f", "indy3", "EGA", "EGA", 5361, Common::EN_ANY, Common::kPlatformPC },
{ "69ea626f1f87eecb78ea0d6c6b983a1d", "monkey2", "", "", -1, Common::IT_ITA, Common::kPlatformPC },
{ "69ffe29185b8d71f09f6199f8b2a87cb", "lost", "HE 100", "", -1, Common::RU_RUS, Common::kPlatformWindows },
{ "6a30a07f353a75cdc602db27d73e1b42", "puttputt", "HE 70", "", -1, Common::EN_ANY, Common::kPlatformWindows },
@@ -486,7 +487,7 @@ static const MD5Table md5table[] = {
{ "d8d07efcb88f396bee0b402b10c3b1c9", "maniac", "NES", "", -1, Common::EN_USA, Common::kPlatformNES },
{ "d917f311a448e3cc7239c31bddb00dd2", "samnmax", "", "CD", 9080, Common::EN_ANY, Common::kPlatformUnknown },
{ "d9d0dd93d16ab4dec55cabc2b86bbd17", "samnmax", "", "Demo", 6478, Common::EN_ANY, Common::kPlatformPC },
- { "da09e666fc8f5b78d7b0ac65d1a3b56e", "monkey2", "", "", -1, Common::EN_ANY, Common::kPlatformFMTowns },
+ { "da09e666fc8f5b78d7b0ac65d1a3b56e", "monkey2", "", "", 11135, Common::EN_ANY, Common::kPlatformFMTowns },
{ "da6269b18fcb08189c0aa9c95533cce2", "monkey", "CD", "CD", 8955, Common::IT_ITA, Common::kPlatformPC },
{ "da669b20271b85182e9c17a2a37ea02e", "monkey2", "", "", -1, Common::DE_DEU, Common::kPlatformAmiga },
{ "db21a6e338fe3b70c2723b6530865bf2", "PuttTime", "HE 85", "", -1, Common::FR_FRA, Common::kPlatformUnknown },
diff --git a/engines/scumm/scumm.cpp b/engines/scumm/scumm.cpp
index 4b3a365394..2140b15544 100644
--- a/engines/scumm/scumm.cpp
+++ b/engines/scumm/scumm.cpp
@@ -120,7 +120,7 @@ ScummEngine::ScummEngine(OSystem *syst, const DetectorResult &dr)
_gdi = new Gdi(this);
}
_res = new ResourceManager(this);
-
+
// Convert MD5 checksum back into a digest
for (int i = 0; i < 16; ++i) {
char tmpStr[3] = "00";
@@ -2236,31 +2236,39 @@ void ScummEngine::startManiac() {
#pragma mark --- GUI ---
#pragma mark -
-int ScummEngine::runDialog(Dialog &dialog) {
- _dialogStartTime = _system->getMillis() / 1000;
-
- // Pause sound & video
- bool old_soundsPaused = _sound->_soundsPaused;
- _sound->pauseSounds(true);
+void ScummEngine::pauseEngineIntern(bool pause) {
+ if (pause) {
+ // Record start of the pause, so that we can later
+ // adjust _engineStartTime accordingly.
+ _pauseStartTime = _system->getMillis();
- bool visible = CursorMan.isVisible();
+ // Pause sound & video
+ _oldSoundsPaused = _sound->_soundsPaused;
+ _sound->pauseSounds(true);
+
+ } else {
+ // Update the screen to make it less likely that the player will see a
+ // brief cursor palette glitch when the GUI is disabled.
+ _system->updateScreen();
- // Open & run the dialog
- int result = dialog.runModal();
+ // Resume sound & video
+ _sound->pauseSounds(_oldSoundsPaused);
- // Restore old cursor
- updateCursor();
- CursorMan.showMouse(visible);
+ // Adjust engine start time
+ _engineStartTime += (_system->getMillis() - _pauseStartTime) / 1000;
+ _pauseStartTime = 0;
+ }
+}
- // Update the screen to make it less likely that the player will see a
- // brief cursor palette glitch when the GUI is disabled.
- _system->updateScreen();
+int ScummEngine::runDialog(Dialog &dialog) {
+ // Pause engine
+ pauseEngine(true);
- // Resume sound & video
- _sound->pauseSounds(old_soundsPaused);
+ // Open & run the dialog
+ int result = dialog.runModal();
- _engineStartTime += (_system->getMillis() / 1000) - _dialogStartTime;
- _dialogStartTime = 0;
+ // Resume engine
+ pauseEngine(false);
// Return the result
return result;
diff --git a/engines/scumm/scumm.h b/engines/scumm/scumm.h
index 8c8124714d..4146846856 100644
--- a/engines/scumm/scumm.h
+++ b/engines/scumm/scumm.h
@@ -406,9 +406,6 @@ class ScummEngine : public Engine {
friend class CharsetRenderer;
friend class ResourceManager;
- GUI::Debugger *getDebugger();
- void errorString(const char *buf_input, char *buf_output);
-
public:
/* Put often used variables at the top.
* That results in a shorter form of the opcode
@@ -437,17 +434,20 @@ public:
protected:
VirtualMachineState vm;
+
+ bool _oldSoundsPaused;
public:
// Constructor / Destructor
ScummEngine(OSystem *syst, const DetectorResult &dr);
virtual ~ScummEngine();
- /** Startup function, main loop. */
- int go();
-
- // Init functions
- int init();
+ // Engine APIs
+ virtual int init();
+ virtual int go();
+ virtual void errorString(const char *buf_input, char *buf_output);
+ virtual GUI::Debugger *getDebugger();
+ virtual void pauseEngineIntern(bool pause);
protected:
virtual void setupScumm();
@@ -638,7 +638,7 @@ protected:
void saveInfos(Common::OutSaveFile* file);
int32 _engineStartTime;
- int32 _dialogStartTime;
+ int32 _pauseStartTime;
protected:
/* Script VM - should be in Script class */
@@ -863,7 +863,7 @@ protected:
void verbMouseOver(int verb);
int findVerbAtPos(int x, int y) const;
virtual void drawVerb(int verb, int mode);
- virtual void runInputScript(int a, int cmd, int mode);
+ virtual void runInputScript(int clickArea, int val, int mode);
void restoreVerbBG(int verb);
void drawVerbBitmap(int verb, int x, int y);
int getVerbSlot(int id, int mode) const;
diff --git a/engines/scumm/smush/codec47.cpp b/engines/scumm/smush/codec47.cpp
index 34d61d1c8a..6904e96c11 100644
--- a/engines/scumm/smush/codec47.cpp
+++ b/engines/scumm/smush/codec47.cpp
@@ -342,6 +342,24 @@ void Codec47Decoder::makeTables47(int width) {
} while (c < 32768);
}
+#ifdef USE_ARM_SMUSH_ASM
+
+extern "C" void ARM_Smush_decode2( byte *dst,
+ const byte *src,
+ int width,
+ int height,
+ const byte *param_ptr,
+ int16 *_table,
+ byte *_tableBig,
+ int32 offset1,
+ int32 offset2,
+ byte *_tableSmall);
+
+#define decode2(SRC,DST,WIDTH,HEIGHT,PARAM) \
+ ARM_Smush_decode2(SRC,DST,WIDTH,HEIGHT,PARAM,_table,_tableBig, \
+ _offset1,_offset2,_tableSmall)
+
+#else
void Codec47Decoder::level3(byte *d_dst) {
int32 tmp;
byte code = *_d_src++;
@@ -503,6 +521,7 @@ void Codec47Decoder::decode2(byte *dst, const byte *src, int width, int height,
dst += next_line;
} while (--bh);
}
+#endif
Codec47Decoder::Codec47Decoder(int width, int height) {
_width = width;
diff --git a/engines/scumm/smush/codec47ARM.s b/engines/scumm/smush/codec47ARM.s
new file mode 100644
index 0000000000..d96049a32c
--- /dev/null
+++ b/engines/scumm/smush/codec47ARM.s
@@ -0,0 +1,372 @@
+@ ScummVM - Graphic Adventure Engine
+@
+@ ScummVM is the legal property of its developers, whose names
+@ are too numerous to list here. Please refer to the COPYRIGHT
+@ file distributed with this source distribution.
+@
+@ This program is free software@ you can redistribute it and/or
+@ modify it under the terms of the GNU General Public License
+@ as published by the Free Software Foundation@ either version 2
+@ of the License, or (at your option) any later version.
+@
+@ This program is distributed in the hope that it will be useful,
+@ but WITHOUT ANY WARRANTY@ without even the implied warranty of
+@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+@ GNU General Public License for more details.
+@
+@ You should have received a copy of the GNU General Public License
+@ along with this program@ if not, write to the Free Software
+@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+@
+@ $URL:$
+@ $Id:$
+@
+@ @author Robin Watts (robin@wss.co.uk)
+@
+@ This file, provides an ARM optimised version of sections of codec47.cpp.
+@ The algorithm is essentially the same as that within codec47.cpp
+@ so to understand this file you should understand codec47.cpp first.
+
+ .text
+
+ .global ARM_Smush_decode2
+
+ARM_Smush_decode2:
+ @ r0 = dst
+ @ r1 = src
+ @ r2 = width
+ @ r3 = height
+ @ r4 = param
+ @ <> = _table
+ @ <> = _tableBig
+ @ <> = _offset1
+ @ <> = _offset2
+ @ <> = _tableSmall
+ STMFD r13!,{r2,r4-r11,R14}
+
+ LDR r4,[r13,#(9+1)*4] @ r4 = param
+ @ stall
+ @ stall
+ SUB r4,r4,#0xF8
+
+ @ r0 = dst
+ @ r1 = _d_src
+ @ r2 = _d_pitch
+ @ r3 = height
+ @ r4 = param
+ ADD r7,r2,#7 @ r14 = bw
+ MOV r7,r7,LSR #3
+y_loop:
+x_loop:
+ @ LEVEL 1
+ LDRB r6,[r1],#1 @ r6 = *_d_src++
+ @ stall
+ @ stall
+ CMP r6,#0xF8
+ BLT level1codeSMALL
+ CMP r6,#0xFC
+ BLT level1codeMID
+ BEQ level1codeFC
+ CMP r6,#0xFE
+ BGT level1codeFF
+ BEQ level1codeFE
+level1codeFD:
+ LDRB r6,[r1],#1 @ r6 = tmp = *_d_src++
+ LDR r8,[r13,#(9+1+2)*4] @ r8 = _tableBig
+ @ stall
+ ADD r12,r6,r6,LSL #1 @ r12= tmp*3
+ ADD r6,r6,r12,LSL #5 @ r6 = tmp*97
+ ADD r8,r8,r6,LSL #2 @ r8 = _tableBig + tmp*388
+ LDRB r9,[r8,#384] @ r9 = l = tmp_ptr[384]
+ LDRB r6,[r1],#1 @ r6 = val = *_d_src++
+ ADD r12,r8,#384 @ r12= &tmp_ptr[384]
+ @ I don't really believe the next 2 lines are necessary, but...
+ CMP r9,#0
+ BEQ level1codeFD_over1
+level1codeFD_loop1:
+ LDRB r10,[r8],#1
+ LDRB r11,[r8],#1
+ SUBS r9,r9,#1
+ ADD r10,r10,r0
+ STRB r6,[r10,r11,LSL #8] @ *(_d_dst + (*tmp_ptr2++)) = val
+ BGT level1codeFD_loop1
+level1codeFD_over1:
+ LDRB r9,[r12,#1] @ r9 = l = tmp_ptr[385]
+ LDRB r6,[r1],#1 @ r6 = val = *_d_src++
+ SUB r12,r12,#384-128 @ r12= &tmp_ptr[128]
+ @ I don't really believe the next 2 lines are necessary, but...
+ CMP r9,#0
+ BEQ level1codeFD_over2
+level1codeFD_loop2:
+ LDRB r10,[r12],#1
+ LDRB r11,[r12],#1
+ SUBS r9,r9,#1
+ ADD r10,r10,r0
+ STRB r6,[r10,r11,LSL #8] @ *(_d_dst + (*tmp_ptr2++)) = val
+ BGT level1codeFD_loop2
+level1codeFD_over2:
+level1_end:
+
+ ADD r0,r0,#8
+ SUBS r7,r7,#1
+ BGT x_loop
+
+ ADD r7,r2,#7
+ MOV r7,r7,LSR #3
+ ADD r0,r0,r2,LSL #3
+ SUB r0,r0,r7,LSL #3 @ r0 = dst += next_line
+ SUBS r3,r3,#8 @ if (--bh > 0)
+ BGT y_loop @ loop back
+
+ LDMFD r13!,{r2,r4-r11,PC}
+
+level1codeSMALL:
+ LDR r8,[r13,#(9+1+1)*4] @ r8 = _table
+ LDR r9,[r13,#(9+1+3)*4] @ r9 = _offset1
+ MOV r6,r6,LSL #1 @ r6 = code<<1
+ LDRSH r8,[r8,r6] @ tmp2 = _table[code]
+level1codeFC:
+ @ EQ => FC
+ LDREQ r9,[r13,#(9+1+4)*4] @ r9 = _offset2
+ MOVEQ r8,#0
+ SUB r11,r2,#7 @ r11 = _d_pitch-7
+ ADD r9,r9,r0 @ tmp2 = _d_dst+_offset
+ ADD r8,r8,r9 @ tmp2 = _d_dst+_table[code]+_offset
+ @ r8 = &_dst[tmp2]
+ MOV r12,#8
+level1codeSMALL_loop:
+ LDRB r5, [r8],#1 @ r5 = d_dst[tmp2]
+ LDRB r6, [r8],#1 @ r10 = d_dst[tmp2]
+ LDRB r9, [r8],#1 @ r10 = d_dst[tmp2]
+ LDRB r10,[r8],#1 @ r10 = d_dst[tmp2]
+ STRB r5, [r0],#1 @ d_dst[0] = r5
+ STRB r6, [r0],#1 @ d_dst[1] = r6
+ STRB r9, [r0],#1 @ d_dst[2] = r9
+ STRB r10,[r0],#1 @ d_dst[3] = r10
+ LDRB r5, [r8],#1 @ r5 = d_dst[tmp2]
+ LDRB r6, [r8],#1 @ r10 = d_dst[tmp2]
+ LDRB r9, [r8],#1 @ r10 = d_dst[tmp2]
+ LDRB r10,[r8],r11 @ r10 = d_dst[tmp2]
+ STRB r5, [r0],#1 @ d_dst[4] = r5
+ STRB r6, [r0],#1 @ d_dst[5] = r6
+ STRB r9, [r0],#1 @ d_dst[6] = r9
+ STRB r10,[r0],r11 @ d_dst[7] = r10 d_dst += d_pitch
+ SUBS r12,r12,#1
+ BGT level1codeSMALL_loop
+ SUB r0,r0,r2,LSL #3 @ revert d_dst
+ B level1_end
+
+level1codeMID:
+ @ LT => F8<=code<FC case
+ @ EQ => FE case
+ LDRB r6,[r4,r6] @ r6 = t = _paramPtr[code]
+level1codeFE:
+ LDREQB r6,[r1],#1 @ r6 = t = *_d_src++
+ MOV r12,#8
+ SUB r11,r2,#7 @ r11 = _d_pitch-7
+level1codeMID_loop:
+ STRB r6,[r0],#1
+ STRB r6,[r0],#1
+ STRB r6,[r0],#1
+ STRB r6,[r0],#1
+ STRB r6,[r0],#1
+ STRB r6,[r0],#1
+ STRB r6,[r0],#1
+ STRB r6,[r0],r11
+ SUBS r12,r12,#1
+ BGT level1codeMID_loop
+ SUB r0,r0,r2,LSL #3 @ revert d_dst
+ B level1_end
+
+level1codeFF:
+ BL level2
+ ADD r0,r0,#4
+ BL level2
+ ADD r0,r0,r2,LSL #2
+ SUB r0,r0,#4
+ BL level2
+ ADD r0,r0,#4
+ BL level2
+ SUB r0,r0,#4
+ SUB r0,r0,r2,LSL #2
+ B level1_end
+
+level2:
+ @ r0 = _d_dst
+ @ r1 = _d_src
+ @ r2 = _d_pitch
+ @ r3 = PRESERVE
+ @ r4 = param
+ @ r7 = PRESERVE
+ @ r14= return address
+ LDRB r6,[r1],#1 @ r6 = *_d_src++
+ @ stall
+ @ stall
+ CMP r6,#0xF8
+ BLT level2codeSMALL
+ CMP r6,#0xFC
+ BLT level2codeMID
+ BEQ level2codeFC
+ CMP r6,#0xFE
+ BGT level2codeFF
+ BEQ level2codeFE
+level2codeFD:
+ LDRB r6,[r1],#1 @ r6 = tmp = *_d_src++
+ LDR r8,[r13,#(9+1+5)*4] @ r8 = _tableSmall
+ @ stall
+ @ stall
+ ADD r8,r8,r6,LSL #7 @ r8 = _tableSmall + tmp*128
+ LDRB r9,[r8,#96] @ r9 = l = tmp_ptr[96]
+ LDRB r6,[r1],#1 @ r6 = val = *_d_src++
+ ADD r12,r8,#32 @ r12 = tmp_ptr + 32
+ @ I don't really believe the next 2 lines are necessary, but...
+ CMP r9,#0
+ BEQ level2codeFD_over1
+level2codeFD_loop1:
+ LDRB r10,[r8],#1
+ LDRB r11,[r8],#1
+ SUBS r9,r9,#1
+ ADD r10,r10,r0
+ STRB r6,[r10,r11,LSL #8] @ *(_d_dst + (*tmp_ptr2++)) = val
+ BGT level2codeFD_loop1
+level2codeFD_over1:
+ LDRB r9,[r12,#97-32] @ r9 = l = tmp_ptr[97]
+ LDRB r6,[r1],#1 @ r6 = val = *_d_src++
+ @ I don't really believe the next 2 lines are necessary, but...
+ CMP r9,#0
+ MOVEQ PC,R14
+level2codeFD_loop2:
+ LDRB r10,[r12],#1
+ LDRB r11,[r12],#1
+ SUBS r9,r9,#1
+ ADD r10,r10,r0
+ STRB r6,[r10,r11,LSL #8] @ *(_d_dst + (*tmp_ptr2++)) = val
+ BGT level2codeFD_loop2
+
+ MOV PC,R14
+
+level2codeSMALL:
+ LDR r8,[r13,#(9+1+1)*4] @ r8 = _table
+ LDR r9,[r13,#(9+1+3)*4] @ r9 = _offset1
+ MOV r6,r6,LSL #1 @ r6 = code<<1
+ LDRSH r8,[r8,r6] @ tmp2 = _table[code]
+level2codeFC:
+ @ EQ => FC
+ LDREQ r9,[r13,#(9+1+4)*4] @ r9 = _offset2
+ MOVEQ r8,#0
+ SUB r11,r2,#3 @ r11 = _d_pitch-3
+ ADD r9,r9,r0 @ tmp2 = _d_dst + _table[code]
+ ADD r8,r8,r9 @ tmp2 = _d_dst+_table[code]+_offset1
+ @ r8 = &_dst[tmp2]
+ MOV r12,#4
+level2codeSMALL_loop:
+ LDRB r5, [r8],#1 @ r5 = d_dst[tmp2]
+ LDRB r6, [r8],#1 @ r10 = d_dst[tmp2]
+ LDRB r9, [r8],#1 @ r10 = d_dst[tmp2]
+ LDRB r10,[r8],r11 @ r10 = d_dst[tmp2]
+ STRB r5, [r0],#1 @ d_dst[4] = r5
+ STRB r6, [r0],#1 @ d_dst[5] = r6
+ STRB r9, [r0],#1 @ d_dst[6] = r9
+ STRB r10,[r0],r11 @ d_dst[7] = r10 d_dst += d_pitch
+ SUBS r12,r12,#1
+ BGT level2codeSMALL_loop
+ SUB r0,r0,r2,LSL #2 @ revert d_dst
+ MOV PC,R14
+
+level2codeMID:
+ @ LT => F8<=code<FC case
+ @ EQ => FE case
+ LDRB r6,[r4,r6] @ r6 = t = _paramPtr[code]
+level2codeFE:
+ LDREQB r6,[r1],#1 @ r6 = t = *_d_src++
+ MOV r12,#4
+ SUB r11,r2,#3 @ r11 = _d_pitch-7
+level2codeMID_loop:
+ STRB r6,[r0],#1
+ STRB r6,[r0],#1
+ STRB r6,[r0],#1
+ STRB r6,[r0],r11
+ SUBS r12,r12,#1
+ BGT level2codeMID_loop
+ SUB r0,r0,r2,LSL #2 @ revert d_dst
+ MOV PC,R14
+
+level2codeFF:
+ MOV r5,r14
+ BL level3
+ ADD r0,r0,#2
+ BL level3
+ ADD r0,r0,r2,LSL #1
+ SUB r0,r0,#2
+ BL level3
+ ADD r0,r0,#2
+ BL level3
+ SUB r0,r0,#2
+ SUB r0,r0,r2,LSL #1
+ MOV PC,R5
+
+level3:
+ @ r0 = _d_dst
+ @ r1 = _d_src
+ @ r2 = _d_pitch
+ @ r3 = PRESERVE
+ @ r4 = param
+ @ r5 = preserve
+ @ r7 = PRESERVE
+ @ r14= return address
+ LDRB r6,[r1],#1 @ r6 = code = *_d_src++
+ @ stall
+ @ stall
+ CMP r6,#0xF8
+ BLT level3codeSMALL
+ CMP r6,#0xFC
+ BLT level3codeMID
+ BEQ level3codeFC
+ CMP r6,#0xFE
+ BGT level3codeFF
+level3codeFE:
+ LDRB r6,[r1],#1 @ r6 = t = *_d_src++
+level3codeMID:
+ @ LT => F8<=code<FC case
+ @ EQ => FE case
+ LDRLTB r6,[r4,r6] @ r6 = t = _paramPtr[code]
+ @ stall
+ @ stall
+ STRB r6,[r0,#1]
+ STRB r6,[r0],r2
+ STRB r6,[r0,#1]
+ STRB r6,[r0],-r2
+ MOV PC,R14
+
+level3codeFF:
+ LDRB r6,[r1],#1
+ LDRB r9,[r1],#1
+ LDRB r10,[r1],#1
+ LDRB r11,[r1],#1
+ STRB r9, [r0,#1]
+ STRB r6, [r0],r2
+ STRB r11,[r0,#1]
+ STRB r10,[r0],-r2
+ MOV PC,R14
+
+level3codeSMALL:
+ LDR r8,[r13,#(9+1+1)*4] @ r8 = _table
+ LDR r9,[r13,#(9+1+3)*4] @ r9 = _offset1
+ MOV r6,r6,LSL #1 @ r6 = code<<1
+ LDRSH r8,[r8,r6] @ tmp2 = _table[code]
+level3codeFC:
+ @ EQ => FC
+ LDREQ r9,[r13,#(9+1+4)*4] @ r9 = _offset2
+ MOVEQ r8,#0
+ ADD r9,r9,r0 @ tmp2 = _d_dst+offset
+ ADD r8,r8,r9 @ tmp2 = _d_dst+_table[code]+_offset
+ @ r8 = &_dst[tmp2]
+ LDRB r6, [r8,#1] @ r6 = d_dst[tmp2+1]
+ LDRB r9, [r8],r2 @ r9 = d_dst[tmp2+0]
+ LDRB r10,[r8,#1] @ r10= d_dst[tmp2+dst+1]
+ LDRB r11,[r8],-r2 @ r11= d_dst[tmp2+dst]
+ STRB r6, [r0,#1] @ d_dst[1 ] = r6
+ STRB r9, [r0],r2 @ d_dst[0 ] = r9
+ STRB r10,[r0,#1] @ d_dst[dst+1] = r10
+ STRB r11,[r0],-r2 @ d_dst[dst ] = r11
+ MOV PC,R14
diff --git a/engines/scumm/verbs.cpp b/engines/scumm/verbs.cpp
index edd8004d30..56ee454240 100644
--- a/engines/scumm/verbs.cpp
+++ b/engines/scumm/verbs.cpp
@@ -385,7 +385,7 @@ void ScummEngine_v2::checkV2Inventory(int x, int y) {
runObject(_activeInventory, _activeVerb);
}
} else {
- runInputScript(3, object, 0);
+ runInputScript(kInventoryClickArea, object, 0);
}
}
}
@@ -537,7 +537,7 @@ void ScummEngine::checkExecVerbs() {
if (vs->verbid && vs->saveid == 0 && vs->curmode == 1) {
if (_mouseAndKeyboardStat == vs->key) {
// Trigger verb as if the user clicked it
- runInputScript(1, vs->verbid, 1);
+ runInputScript(kVerbClickArea, vs->verbid, 1);
return;
}
}
@@ -580,14 +580,14 @@ void ScummEngine::checkExecVerbs() {
// Check if person is available (see script 23 from ZAK_FM-TOWNS and script 4 from ZAK_PC).
// Zak: Var[144 Bit 15], Annie: Var[145 Bit 0], Melissa: Var[145 Bit 1], Leslie: Var[145 Bit 2]
if (!readVar(0x890E + fKey)) {
- runInputScript(1, 36 + fKey, 0);
+ runInputScript(kVerbClickArea, 36 + fKey, 0);
}
}
return;
}
// Generic keyboard input
- runInputScript(4, _mouseAndKeyboardStat, 1);
+ runInputScript(kKeyClickArea, _mouseAndKeyboardStat, 1);
} else if (_mouseAndKeyboardStat & MBS_MOUSE_MASK) {
VirtScreen *zone = findVirtScreen(_mouse.y);
byte code = _mouseAndKeyboardStat & MBS_LEFT_CLICK ? 1 : 2;
@@ -600,7 +600,7 @@ void ScummEngine::checkExecVerbs() {
if (_game.version <= 2 && zone->number == kVerbVirtScreen && _mouse.y <= zone->topline + 8) {
// Click into V2 sentence line
- runInputScript(5, 0, 0);
+ runInputScript(kSentenceClickArea, 0, 0);
} else if (_game.version <= 2 && zone->number == kVerbVirtScreen && _mouse.y > zone->topline + inventoryArea) {
// Click into V2 inventory
((ScummEngine_v2 *)this)->checkV2Inventory(_mouse.x, _mouse.y);
@@ -608,10 +608,10 @@ void ScummEngine::checkExecVerbs() {
over = findVerbAtPos(_mouse.x, _mouse.y);
if (over != 0) {
// Verb was clicked
- runInputScript(1, _verbs[over].verbid, code);
+ runInputScript(kVerbClickArea, _verbs[over].verbid, code);
} else {
// Scene was clicked
- runInputScript((zone->number == kMainVirtScreen) ? 2 : 1, 0, code);
+ runInputScript((zone->number == kMainVirtScreen) ? kSceneClickArea : kVerbClickArea, 0, code);
}
}
}
diff --git a/engines/scumm/verbs.h b/engines/scumm/verbs.h
index 47fa98a9de..96a49a7ced 100644
--- a/engines/scumm/verbs.h
+++ b/engines/scumm/verbs.h
@@ -30,6 +30,18 @@
namespace Scumm {
+/**
+ * The area in which some click (or key press) occured and which is passed
+ * to the input script.
+ */
+enum ClickArea {
+ kVerbClickArea = 1,
+ kSceneClickArea = 2,
+ kInventoryClickArea = 3,
+ kKeyClickArea = 4,
+ kSentenceClickArea = 5
+};
+
enum {
kTextVerbType = 0,
kImageVerbType = 1
diff --git a/engines/sky/music/mt32music.cpp b/engines/sky/music/mt32music.cpp
index 4f816c6856..2be19a0651 100644
--- a/engines/sky/music/mt32music.cpp
+++ b/engines/sky/music/mt32music.cpp
@@ -120,7 +120,7 @@ bool MT32Music::processPatchSysEx(uint8 *sysExData) {
crc -= sysExBuf[cnt];
sysExBuf[14] = crc & 0x7F; // crc
_midiDrv->sysEx(sysExBuf, 15);
- g_system->delayMillis(5);
+ g_system->delayMillis(40);
return true;
}
@@ -170,7 +170,7 @@ void MT32Music::startDriver(void) {
sendBuf[len] = crc & 0x7F;
len++;
_midiDrv->sysEx(sendBuf, len);
- g_system->delayMillis (5);
+ g_system->delayMillis(40);
}
while (processPatchSysEx(sysExData))
diff --git a/engines/sky/sound.cpp b/engines/sky/sound.cpp
index cf769cb3e9..c0dc227718 100644
--- a/engines/sky/sound.cpp
+++ b/engines/sky/sound.cpp
@@ -46,13 +46,13 @@ struct RoomList {
uint8 room;
uint8 adlibVolume;
uint8 rolandVolume;
-};
+} PACKED_STRUCT;
struct Sfx {
uint8 soundNo;
uint8 flags;
RoomList roomList[10];
-};
+} PACKED_STRUCT;
#include "common/pack-end.h" // END STRUCT PACKING
diff --git a/engines/sky/struc.h b/engines/sky/struc.h
index 25f0b3d772..cd7155f282 100644
--- a/engines/sky/struc.h
+++ b/engines/sky/struc.h
@@ -55,7 +55,7 @@ struct dataFileHeader {
int16 s_offset_x;
int16 s_offset_y;
uint16 s_compressed_size;
-};
+} PACKED_STRUCT;
struct TurnTable {
uint16 turnTableUp[5];
@@ -63,7 +63,7 @@ struct TurnTable {
uint16 turnTableLeft[5];
uint16 turnTableRight[5];
uint16 turnTableTalk[5];
-};
+} PACKED_STRUCT;
struct MegaSet {
uint16 gridWidth; // 0
@@ -82,7 +82,7 @@ struct MegaSet {
uint16 standRightId; // 11
uint16 standTalkId; // 12
uint16 turnTableId; // 13
-};
+} PACKED_STRUCT;
struct Compact {
uint16 logic; // 0: Entry in logic table to run (byte as <256entries in logic table
@@ -165,7 +165,7 @@ struct Compact {
MegaSet megaSet1; //
MegaSet megaSet2; //
MegaSet megaSet3; //
-};
+} PACKED_STRUCT;
#include "common/pack-end.h" // END STRUCT PACKING
diff --git a/engines/sword1/control.cpp b/engines/sword1/control.cpp
index 1ebfaedb2e..c5b968aabe 100644
--- a/engines/sword1/control.cpp
+++ b/engines/sword1/control.cpp
@@ -650,14 +650,7 @@ bool Control::getConfirm(const uint8 *title) {
}
bool Control::keyAccepted(uint16 ascii) {
- // this routine needs changes for Czech keys... No idea how to do that, though.
- // FIXME: It is not a good idea to put non-ASCII chars into a C source file,
- // since there is no way to specify which encoding you are using.
- // It is better to encode them as hex/octal. Although in this particular
- // case, it seems questionable to do this at all, since we currently
- // do not at all specify which encoding keyboard events use, so this
- // check here is probably not portable anyway...
- static const char allowedSpecials[] = "éèáàúùäöüÄÖÜß,.:-()?! \"\'";
+ static const char allowedSpecials[] = ",.:-()?! \"\'";
if (((ascii >= 'A') && (ascii <= 'Z')) ||
((ascii >= 'a') && (ascii <= 'z')) ||
((ascii >= '0') && (ascii <= '9')) ||
diff --git a/engines/sword1/mouse.h b/engines/sword1/mouse.h
index 92b26c3573..f2c800d63b 100644
--- a/engines/sword1/mouse.h
+++ b/engines/sword1/mouse.h
@@ -60,7 +60,7 @@ struct MousePtr {
uint16 hotSpotX;
uint16 hotSpotY;
uint8 dummyData[0x30];
-};
+} PACKED_STRUCT;
#include "common/pack-end.h" // END STRUCT PACKING
diff --git a/engines/sword1/object.h b/engines/sword1/object.h
index ba65002918..87cbce7b84 100644
--- a/engines/sword1/object.h
+++ b/engines/sword1/object.h
@@ -40,7 +40,7 @@ namespace Sword1 {
struct OEventSlot { //receiving event list in the compact -
int32 o_event; //array of these with O_TOTAL_EVENTS elements
int32 o_event_script;
-}; // size = 2*int32 = 8 bytes
+} PACKED_STRUCT; // size = 2*int32 = 8 bytes
#define TOTAL_script_levels 5
@@ -48,12 +48,12 @@ struct ScriptTree { //this is a logic tree, used by OBJECTs
int32 o_script_level; //logic level
int32 o_script_id[TOTAL_script_levels]; //script id's (are unique to each level)
int32 o_script_pc[TOTAL_script_levels]; //pc of script for each (if script_manager)
-}; // size = 11*int32 = 44 bytes
+} PACKED_STRUCT; // size = 11*int32 = 44 bytes
struct TalkOffset {
int32 x;
int32 y;
-}; // size = 2*int32 = 8 bytes
+} PACKED_STRUCT; // size = 2*int32 = 8 bytes
struct WalkData {
int32 frame;
@@ -61,7 +61,7 @@ struct WalkData {
int32 y;
int32 step;
int32 dir;
-}; // size = 5*int32 = 20 bytes
+} PACKED_STRUCT; // size = 5*int32 = 20 bytes
struct Object {
int32 o_type; // 0 broad description of type - object, floor, etc.
@@ -119,7 +119,7 @@ struct Object {
WalkData o_route[O_WALKANIM_SIZE]; // 340 size = 600*20 bytes = 12000
// mega size = 12340 bytes (+ 8 byte offset table + 20 byte header = 12368)
-};
+} PACKED_STRUCT;
#include "common/pack-end.h" // END STRUCT PACKING
diff --git a/engines/sword1/router.h b/engines/sword1/router.h
index 67be8d0593..60456cc5c8 100644
--- a/engines/sword1/router.h
+++ b/engines/sword1/router.h
@@ -44,7 +44,7 @@ struct BarData {
int16 dx; // x2 - x1
int16 dy; // y2 - y1
int32 co; // co = (y1*dx) - (x1*dy) from an equation for a line y*dx = x*dy + co
-};
+} PACKED_STRUCT;
struct NodeData {
int16 x;
@@ -52,7 +52,7 @@ struct NodeData {
int16 level;
int16 prev;
int16 dist;
-};
+} PACKED_STRUCT;
#include "common/pack-end.h" // END STRUCT PACKING
diff --git a/engines/sword1/sound.cpp b/engines/sword1/sound.cpp
index 4d8601a0d8..492672fad8 100644
--- a/engines/sword1/sound.cpp
+++ b/engines/sword1/sound.cpp
@@ -33,6 +33,7 @@
#include "sword1/logic.h"
#include "sword1/sword1.h"
+#include "sound/flac.h"
#include "sound/mp3.h"
#include "sound/vorbis.h"
#include "sound/wave.h"
@@ -197,10 +198,10 @@ bool Sound::startSpeech(uint16 roomNo, uint16 localNo) {
if (data)
_mixer->playRaw(Audio::Mixer::kSpeechSoundType, &_speechHandle, data, size, 11025, SPEECH_FLAGS, SOUND_SPEECH_ID, speechVol, speechPan);
}
-#ifdef USE_MAD
- else if (_cowMode == CowMp3) {
+#ifdef USE_FLAC
+ else if (_cowMode == CowFlac) {
_cowFile.seek(index);
- _mixer->playInputStream(Audio::Mixer::kSpeechSoundType, &_speechHandle, Audio::makeMP3Stream(&_cowFile, sampleSize), SOUND_SPEECH_ID, speechVol, speechPan);
+ _mixer->playInputStream(Audio::Mixer::kSpeechSoundType, &_speechHandle, Audio::makeFlacStream(&_cowFile, sampleSize), SOUND_SPEECH_ID, speechVol, speechPan);
// with compressed audio, we can't calculate the wave volume.
// so default to talking.
for (int cnt = 0; cnt < 480; cnt++)
@@ -212,6 +213,19 @@ bool Sound::startSpeech(uint16 roomNo, uint16 localNo) {
else if (_cowMode == CowVorbis) {
_cowFile.seek(index);
_mixer->playInputStream(Audio::Mixer::kSpeechSoundType, &_speechHandle, Audio::makeVorbisStream(&_cowFile, sampleSize), SOUND_SPEECH_ID, speechVol, speechPan);
+ // with compressed audio, we can't calculate the wave volume.
+ // so default to talking.
+ for (int cnt = 0; cnt < 480; cnt++)
+ _waveVolume[cnt] = true;
+ _waveVolPos = 0;
+ }
+#endif
+#ifdef USE_MAD
+ else if (_cowMode == CowMp3) {
+ _cowFile.seek(index);
+ _mixer->playInputStream(Audio::Mixer::kSpeechSoundType, &_speechHandle, Audio::makeMP3Stream(&_cowFile, sampleSize), SOUND_SPEECH_ID, speechVol, speechPan);
+ // with compressed audio, we can't calculate the wave volume.
+ // so default to talking.
for (int cnt = 0; cnt < 480; cnt++)
_waveVolume[cnt] = true;
_waveVolPos = 0;
@@ -332,6 +346,16 @@ void Sound::initCowSystem(void) {
/* look for speech1/2.clu in the data dir
and speech/speech.clu (running from cd or using cd layout)
*/
+#ifdef USE_FLAC
+ if (!_cowFile.isOpen()) {
+ sprintf(cowName, "SPEECH%d.CLF", SwordEngine::_systemVars.currentCD);
+ _cowFile.open(cowName);
+ if (_cowFile.isOpen()) {
+ debug(1, "Using Flac compressed Speech Cluster");
+ _cowMode = CowFlac;
+ }
+ }
+#endif
#ifdef USE_VORBIS
if (!_cowFile.isOpen()) {
sprintf(cowName, "SPEECH%d.CLV", SwordEngine::_systemVars.currentCD);
diff --git a/engines/sword1/sound.h b/engines/sword1/sound.h
index fb608a9631..fafc9c2d06 100644
--- a/engines/sword1/sound.h
+++ b/engines/sword1/sound.h
@@ -66,8 +66,9 @@ class ResMan;
enum CowMode {
CowWave = 0,
- CowMp3,
+ CowFlac,
CowVorbis,
+ CowMp3,
CowDemo
};
diff --git a/engines/sword1/staticres.cpp b/engines/sword1/staticres.cpp
index 366e2c7608..08e6a108c4 100644
--- a/engines/sword1/staticres.cpp
+++ b/engines/sword1/staticres.cpp
@@ -5158,7 +5158,7 @@ const FxDef Sound::_fxList[312] = {
},
},
//------------------------
- // 198 Ambient sound for Montfauçon Square
+ // 198 Ambient sound for Montfaucon Square
{
FX_MONTAMB, // sampleId
FX_LOOP, // type
diff --git a/engines/sword1/sword1.cpp b/engines/sword1/sword1.cpp
index d899d25df5..b5152f33bc 100644
--- a/engines/sword1/sword1.cpp
+++ b/engines/sword1/sword1.cpp
@@ -355,14 +355,18 @@ const CdFile SwordEngine::_pcCdFileList[] = {
{ "cows.mad", FLAG_DEMO },
{ "speech1.clu", FLAG_SPEECH1 },
{ "speech2.clu", FLAG_SPEECH2 }
-#ifdef USE_MAD
- ,{ "speech1.cl3", FLAG_SPEECH1 },
- { "speech2.cl3", FLAG_SPEECH2 }
+#ifdef USE_FLAC
+ ,{ "speech1.clf", FLAG_SPEECH1 },
+ { "speech2.clf", FLAG_SPEECH2 }
#endif
#ifdef USE_VORBIS
,{ "speech1.clv", FLAG_SPEECH1 },
{ "speech2.clv", FLAG_SPEECH2 }
#endif
+#ifdef USE_MAD
+ ,{ "speech1.cl3", FLAG_SPEECH1 },
+ { "speech2.cl3", FLAG_SPEECH2 }
+#endif
};
const CdFile SwordEngine::_macCdFileList[] = {
@@ -383,14 +387,18 @@ const CdFile SwordEngine::_macCdFileList[] = {
{ "text.clm", FLAG_CD1 | FLAG_DEMO },
{ "speech1.clu", FLAG_SPEECH1 },
{ "speech2.clu", FLAG_SPEECH2 }
-#ifdef USE_MAD
- ,{ "speech1.cl3", FLAG_SPEECH1 },
- { "speech2.cl3", FLAG_SPEECH2 }
+#ifdef USE_FLAC
+ ,{ "speech1.clf", FLAG_SPEECH1 },
+ { "speech2.clf", FLAG_SPEECH2 }
#endif
#ifdef USE_VORBIS
,{ "speech1.clv", FLAG_SPEECH1 },
{ "speech2.clv", FLAG_SPEECH2 }
#endif
+#ifdef USE_MAD
+ ,{ "speech1.cl3", FLAG_SPEECH1 },
+ { "speech2.cl3", FLAG_SPEECH2 }
+#endif
};
diff --git a/engines/sword1/sworddefs.h b/engines/sword1/sworddefs.h
index aedc38ef7e..e90eafe825 100644
--- a/engines/sword1/sworddefs.h
+++ b/engines/sword1/sworddefs.h
@@ -100,7 +100,7 @@ struct Header {
uint32 comp_length;
char compression[4];
uint32 decomp_length;
-};
+} PACKED_STRUCT;
struct FrameHeader {
uint8 runTimeComp[4];
@@ -115,25 +115,25 @@ struct ParallaxHeader {
char type[16];
uint16 sizeX;
uint16 sizeY;
-};
+} PACKED_STRUCT;
struct AnimUnit {
uint32 animX;
uint32 animY;
uint32 animFrame;
-};
+} PACKED_STRUCT;
struct AnimSet {
uint32 cdt;
uint32 spr;
-};
+} PACKED_STRUCT;
struct WalkGridHeader {
int32 scaleA;
int32 scaleB;
int32 numBars;
int32 numNodes;
-};
+} PACKED_STRUCT;
#include "common/pack-end.h" // END STRUCT PACKING
diff --git a/engines/touche/ui.cpp b/engines/touche/ui.cpp
index ef8f5a0d7d..15dc64aaf2 100644
--- a/engines/touche/ui.cpp
+++ b/engines/touche/ui.cpp
@@ -381,6 +381,11 @@ void ToucheEngine::handleOptions(int forceDisplay) {
}
}
}
+ if (doRedraw) {
+ redrawMenu(&menuData);
+ updateScreenArea(90, 102, 460, 196);
+ doRedraw = false;
+ }
Common::Event event;
while (_eventMan->pollEvent(event)) {
const Button *button = 0;
@@ -419,11 +424,6 @@ void ToucheEngine::handleOptions(int forceDisplay) {
break;
}
}
- if (doRedraw) {
- redrawMenu(&menuData);
- updateScreenArea(90, 102, 460, 196);
- doRedraw = false;
- }
_system->updateScreen();
_system->delayMillis(10);
}