aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--backends/fs/windows/windows-fs.cpp3
-rw-r--r--backends/platform/symbian/README25
-rw-r--r--backends/platform/symbian/src/SymbianActions.cpp18
-rw-r--r--backends/platform/wii/Makefile6
-rw-r--r--backends/platform/wii/gx_supp.cpp47
-rw-r--r--backends/platform/wii/gx_supp.h7
-rw-r--r--backends/platform/wii/osystem.cpp28
-rw-r--r--backends/platform/wii/osystem.h3
-rw-r--r--backends/platform/wii/osystem_gfx.cpp75
-rw-r--r--backends/platform/wince/CEActionsPocket.cpp8
-rw-r--r--backends/platform/wince/CEActionsSmartphone.cpp8
-rw-r--r--backends/platform/wince/CEkeys/EventsBuffer.cpp3
-rw-r--r--backends/platform/wince/wince-sdl.cpp22
-rw-r--r--dists/wii/READMII19
-rw-r--r--engines/agi/sound.cpp23
-rw-r--r--engines/agi/sound.h1
-rw-r--r--engines/cine/cine.cpp12
-rw-r--r--engines/cine/gfx.cpp143
-rw-r--r--engines/cine/gfx.h6
-rw-r--r--engines/cine/main_loop.cpp8
-rw-r--r--engines/cine/msg.cpp45
-rw-r--r--engines/cine/pal.cpp36
-rw-r--r--engines/cine/pal.h2
-rw-r--r--engines/cine/part.cpp53
-rw-r--r--engines/cine/part.h6
-rw-r--r--engines/cine/sound.cpp1
-rw-r--r--engines/cine/texte.cpp186
-rw-r--r--engines/cine/texte.h24
-rw-r--r--engines/cine/various.cpp145
-rw-r--r--engines/cine/various.h5
-rw-r--r--engines/gob/mult_v2.cpp9
-rw-r--r--engines/kyra/detection.cpp127
-rw-r--r--engines/kyra/lol.cpp7
-rw-r--r--engines/kyra/resource.cpp135
-rw-r--r--engines/parallaction/balloons.cpp512
-rw-r--r--engines/parallaction/callables_br.cpp2
-rw-r--r--engines/parallaction/callables_ns.cpp44
-rw-r--r--engines/parallaction/debug.cpp20
-rw-r--r--engines/parallaction/dialogue.cpp2
-rw-r--r--engines/parallaction/disk.h2
-rw-r--r--engines/parallaction/disk_br.cpp23
-rw-r--r--engines/parallaction/exec.h2
-rw-r--r--engines/parallaction/exec_br.cpp88
-rw-r--r--engines/parallaction/exec_ns.cpp166
-rw-r--r--engines/parallaction/graphics.cpp8
-rw-r--r--engines/parallaction/graphics.h40
-rw-r--r--engines/parallaction/objects.cpp81
-rw-r--r--engines/parallaction/objects.h128
-rw-r--r--engines/parallaction/parallaction.cpp39
-rw-r--r--engines/parallaction/parallaction.h14
-rw-r--r--engines/parallaction/parallaction_br.cpp6
-rw-r--r--engines/parallaction/parallaction_ns.cpp14
-rw-r--r--engines/parallaction/parser.cpp2
-rw-r--r--engines/parallaction/parser.h7
-rw-r--r--engines/parallaction/parser_br.cpp111
-rw-r--r--engines/parallaction/parser_ns.cpp61
-rw-r--r--engines/parallaction/saveload.cpp8
-rw-r--r--engines/parallaction/walk.cpp8
-rw-r--r--engines/scumm/boxes.cpp20
-rw-r--r--engines/scumm/detection.cpp7
-rw-r--r--engines/scumm/script_v5.cpp2
61 files changed, 1621 insertions, 1042 deletions
diff --git a/backends/fs/windows/windows-fs.cpp b/backends/fs/windows/windows-fs.cpp
index 77530c6073..2105317a96 100644
--- a/backends/fs/windows/windows-fs.cpp
+++ b/backends/fs/windows/windows-fs.cpp
@@ -227,8 +227,7 @@ WindowsFilesystemNode::WindowsFilesystemNode(const String &p, const bool current
char path[MAX_PATH];
GetCurrentDirectory(MAX_PATH, path);
_path = path;
- }
- else {
+ } else {
assert(p.size() > 0);
_path = p;
}
diff --git a/backends/platform/symbian/README b/backends/platform/symbian/README
index 8ab729a4d0..db46dae8de 100644
--- a/backends/platform/symbian/README
+++ b/backends/platform/symbian/README
@@ -1,11 +1,11 @@
ScummVM - ScummVM ported to EPOC/SymbianOS
- Copyright (C) 2003-2005 Andreas 'Sprawl' Karlsson
- Copyright (C) 2007 Lars 'AnotherGuest' Persson
- Copyright (C) 2007 Jurgen 'SumthinWicked' Braam
- Copyright (C) 2007 ScummVM Team
+ Copyright (C) 2008 ScummVM Team
+ Copyright (C) 2003-2008 Lars 'AnotherGuest' Persson
+ Copyright (C) 2002008 Jurgen 'SumthinWicked' Braam
+ Copyright (C) 2003-2005 Andreas 'Sprawl' Karlsson
$Id$
@@ -13,21 +13,21 @@ About ScummVM
--------------
The original ports (uptil 0.7.1) were made by Andreas Karlsson and Lars Persson.
The main transition to 0.8.0CVS and all relevant changes were done by Jurgen Braam.
- Jurgen and Lars have successfully transfered all needed changes into CVS, with additional helpful tools for Symbian OS
+ Jurgen and Lars have successfully transfered all needed changes into CVS/SVN, with additional helpful tools for Symbian OS
- Release version: 0.10.0
+ Release version: 0.12.0
* This version is only supported on Symbian OS 9 devices due to compiler constraints for older devices. (That means UIQ3 and S60V3 devices)
- * Updated to SDL version 1.2.11 (previous version used was 1.2.8)
+ * Updated to SDL version 1.2.13 (previous version used was 1.2.2)
* Information about S60 devices can be found here http://wiki.scummvm.org/index.php/SymbianOS_S60
* Information about UIQ devices can be found here http://wiki.scummvm.org/index.php/SymbianOS_UIQ
* Best source of general information is the ScummVM forum, http://forums.scummvm.org
- * SVN builds (not frequently updated) can be found at http://anotherguest.k0.se
+ * SVN builds (not frequently updated) can be found at http://www.anotherguest.se
Games supported
---------------
The Symbian port of ScummVM supports all but Sword1 & 2 games. Some games might not run properly due to screenresolution or memory constraints.
-
+ Minimum free memory requirement is about 12MB to be able to start and run ScummVM, this is enough for most older games, but newer more resource hungry games, might require more.
Building ScummVM
---------------------
@@ -38,7 +38,7 @@ Building ScummVM
Lets just say the framework needs quite some time to set up and takes a while
to get used to. If you choose to continue you will need the following items:
- - UIQ 3.0 SDK (To build for UIQ3 devices)
+ - UIQ 3.x SDK (To build for UIQ3 devices)(Build scripts in SDK need tweaking in order to build scummvm since Symbian OS GCCE never builds as large projects as ScummVM before)
- UIQ 2.1 SDK (To build for UIQ2 devices);
http://www.symbian.com/developer/sdks_uiq.asp
@@ -72,8 +72,7 @@ Building ScummVM
http://flac.sourceforge.net/
- libmpeg2, a free MPEG-2 video stream decoder
- http://libmpeg2.sourceforge.net/
-
+ http://libmpeg2.sourceforge.net
Compiling ScummVM
-----------------
@@ -89,7 +88,7 @@ Building ScummVM
PETRAN.EXE will be the executable that is started.
- SDL: the latest version of SDL at this point in time is 1.2.12. This version
+ SDL: the latest version of SDL at this point in time is 1.2.13. This version
works great for compiling on other platforms.
zlib: the zlib-x.x.x.tar.gz does not come with UIQ .mpp build files, that's why
diff --git a/backends/platform/symbian/src/SymbianActions.cpp b/backends/platform/symbian/src/SymbianActions.cpp
index da127eaec6..60e402632f 100644
--- a/backends/platform/symbian/src/SymbianActions.cpp
+++ b/backends/platform/symbian/src/SymbianActions.cpp
@@ -129,12 +129,12 @@ void SymbianActions::initInstanceGame() {
bool is_simon = (strncmp(gameid.c_str(), "simon", 5) == 0);
bool is_sword1 = (gameid == "sword1");
bool is_sword2 = (strcmp(gameid.c_str(), "sword2") == 0);
- bool is_sky = (strncmp(gameid.c_str(), "sky", 3) == 0);
- bool is_saga = (gameid == "saga");
+ bool is_queen = (gameid == "queen");
+ bool is_sky = (gameid == "sky");
bool is_comi = (strncmp(gameid.c_str(), "comi", 4) == 0);
- bool is_queen = (strncmp(gameid.c_str(), "queen", 5) == 0);
bool is_gob = (strncmp(gameid.c_str(), "gob", 3) == 0);
- bool is_kyra = (gameid == "kyra1");
+ bool is_saga = (gameid == "saga");
+ bool is_kyra = (strncmp(gameid.c_str(), "kyra",4) == 0);
bool is_samnmax = (gameid == "samnmax");
bool is_cine = (gameid == "cine");
bool is_touche = (gameid == "touche");
@@ -142,6 +142,7 @@ void SymbianActions::initInstanceGame() {
bool is_parallaction = (gameid == "parallaction");
bool is_lure = (gameid == "lure");
bool is_feeble = (gameid == "feeble");
+ bool is_drascula = (strncmp(gameid.c_str(), "drascula",8) == 0);
Actions::initInstanceGame();
@@ -152,16 +153,16 @@ void SymbianActions::initInstanceGame() {
// Save
- if (is_simon || is_sword2 || is_gob || is_kyra || is_touche)
+ if (is_simon || is_sword2 || is_gob || is_kyra || is_touche || is_feeble)
_action_enabled[ACTION_SAVE] = false;
else {
_action_enabled[ACTION_SAVE] = true;
if (is_queen) {
- _key_action[ACTION_SAVE].setKey(Common::ASCII_F5, Common::KEYCODE_F5); // F1 key for FOTAQ
+ _key_action[ACTION_SAVE].setKey(Common::ASCII_F1, Common::KEYCODE_F1); // F1 key for FOTAQ
} else if (is_sky) {
_key_action[ACTION_SAVE].setKey(Common::ASCII_F5, Common::KEYCODE_F5);
- } else if (is_cine) {
+ } else if (is_cine || is_drascula) {
_key_action[ACTION_SAVE].setKey(Common::ASCII_F10, Common::KEYCODE_F10); // F10
} else if (is_agi) {
_key_action[ACTION_SAVE].setKey(Common::ASCII_ESCAPE, Common::KEYCODE_ESCAPE);
@@ -177,7 +178,8 @@ void SymbianActions::initInstanceGame() {
// Skip text
if (!is_cine && !is_parallaction)
_action_enabled[ACTION_SKIP_TEXT] = true;
- if (is_simon || is_sky || is_sword2 || is_queen || is_sword1 || is_gob || is_saga || is_kyra || is_touche || is_lure || is_feeble)
+ if (is_simon || is_sky || is_sword2 || is_queen || is_sword1 || is_gob ||
+ is_saga || is_kyra || is_touche || is_lure || is_feeble || is_drascula)
_key_action[ACTION_SKIP_TEXT].setKey(Common::KEYCODE_ESCAPE, Common::KEYCODE_ESCAPE); // Escape key
else {
_key_action[ACTION_SKIP_TEXT].setKey(SDLK_PERIOD);
diff --git a/backends/platform/wii/Makefile b/backends/platform/wii/Makefile
index d17a7cb41e..90ebcccb66 100644
--- a/backends/platform/wii/Makefile
+++ b/backends/platform/wii/Makefile
@@ -154,8 +154,10 @@ distclean: distclean-wii
distclean-wii:
@-$(RM) dist
-ifeq ($(GAMECUBE),1)
upload:
+ifeq ($(GAMECUBE),1)
+ $(DEVKITPPC)/bin/geckoupload $(TARGET).dol
+else
$(DEVKITPPC)/bin/wiiload $(TARGET).dol
endif
@@ -167,6 +169,7 @@ else
$(CP) $(TARGET).dol dist/scummvm/boot.dol
$(CP) $(DISTPATH)/meta.xml dist/scummvm/
$(CP) $(DISTPATH)/icon.png dist/scummvm/
+endif
$(CP) $(DISTPATH)/READMII dist/scummvm/
$(CP) $(srcdir)/AUTHORS dist/scummvm/
$(CP) $(srcdir)/COPYING dist/scummvm/
@@ -175,5 +178,4 @@ else
$(CP) $(srcdir)/README dist/scummvm/
$(CP) $(DIST_FILES_THEMES) dist/scummvm/
$(CP) $(DIST_FILES_ENGINEDATA) dist/scummvm/
-endif
diff --git a/backends/platform/wii/gx_supp.cpp b/backends/platform/wii/gx_supp.cpp
index 4c7b8ed58a..436deddbb8 100644
--- a/backends/platform/wii/gx_supp.cpp
+++ b/backends/platform/wii/gx_supp.cpp
@@ -1,6 +1,7 @@
/****************************************************************************
* Generic GX Support for Emulators
* softdev 2007
+* dhewg 2008
*
* 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
@@ -21,12 +22,13 @@
* These are pretty standard functions to setup and use GX scaling.
****************************************************************************/
-#include <gccore.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <malloc.h>
+#include "gx_supp.h"
+
#define DEFAULT_FIFO_SIZE (256 * 1024)
#define HASPECT 320
@@ -39,18 +41,19 @@ extern "C" {
/*** 2D ***/
static u32 whichfb;
static u32 *xfb[2];
-static GXRModeObj *vmode;
+GXRModeObj *vmode = NULL;
/*** 3D GX ***/
static u8 *gp_fifo;
/*** Texture memory ***/
-static u8 *texturemem;
+static u8 *texturemem = NULL;
static u32 texturesize;
-GXTexObj texobj;
+static GXTexObj texobj;
static Mtx view;
static u16 vwidth, vheight, oldvwidth, oldvheight;
+static float tex_xT = 0.0f, tex_yT = 0.0f;
/* New texture based scaler */
typedef struct tagcamera {
@@ -74,6 +77,10 @@ static camera cam = {
void GX_InitVideo() {
vmode = VIDEO_GetPreferredMode(NULL);
+
+ vmode->viWidth = 678;
+ vmode->viXOrigin = (VI_MAX_WIDTH_PAL - 678) / 2;
+
VIDEO_Configure(vmode);
xfb[0] = (u32 *) MEM_K0_TO_K1 (SYS_AllocateFramebuffer(vmode));
@@ -93,6 +100,15 @@ void GX_InitVideo() {
VIDEO_WaitVSync();
}
+void GX_SetTexTrans(float xT, float yT) {
+ tex_xT = xT;
+ tex_yT = yT;
+}
+
+void GX_SetCamPosZ(float f) {
+ cam.pos.z = f;
+}
+
/****************************************************************************
* Scaler Support Functions
****************************************************************************/
@@ -128,7 +144,7 @@ static void draw_square(Mtx v) {
Mtx mv;
guMtxIdentity(m);
- guMtxTransApply(m, m, 0, 0, -100);
+ guMtxTransApply(m, m, tex_xT, tex_yT, -100);
guMtxConcat(v, m, mv);
GX_LoadPosMtxImm(mv, GX_PNMTX0);
@@ -144,9 +160,9 @@ static void draw_square(Mtx v) {
* StartGX
****************************************************************************/
void GX_Start(u16 width, u16 height, s16 haspect, s16 vaspect) {
+ static bool inited = false;
Mtx p;
-
- GX_AbortFrame();
+ GXColor gxbackground = { 0, 0, 0, 0xff };
/*** Set new aspect ***/
square[0] = square[9] = -haspect;
@@ -156,9 +172,20 @@ void GX_Start(u16 width, u16 height, s16 haspect, s16 vaspect) {
/*** Allocate 32byte aligned texture memory ***/
texturesize = (width * height) * 2;
+
+ if (texturemem)
+ free(texturemem);
+
texturemem = (u8 *) memalign(32, texturesize);
+ memset(texturemem, 0, texturesize);
- GXColor gxbackground = { 0, 0, 0, 0xff };
+ /*** Setup for first call to scaler ***/
+ oldvwidth = oldvheight = -1;
+
+ if (inited)
+ return;
+
+ inited = true;
/*** Clear out FIFO area ***/
memset(gp_fifo, 0, DEFAULT_FIFO_SIZE);
@@ -184,12 +211,8 @@ void GX_Start(u16 width, u16 height, s16 haspect, s16 vaspect) {
guPerspective(p, 60, 1.33f, 10.0f, 1000.0f);
GX_LoadProjectionMtx(p, GX_PERSPECTIVE);
- memset(texturemem, 0, texturesize);
GX_Flush();
-
- /*** Setup for first call to scaler ***/
- vwidth = vheight = -1;
}
/****************************************************************************
diff --git a/backends/platform/wii/gx_supp.h b/backends/platform/wii/gx_supp.h
index 9393e93a26..108a94f0e7 100644
--- a/backends/platform/wii/gx_supp.h
+++ b/backends/platform/wii/gx_supp.h
@@ -1,6 +1,7 @@
/****************************************************************************
* Generic GX Scaler
* softdev 2007
+* dhewg 2008
*
* 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
@@ -23,11 +24,17 @@
#ifndef _WII_GX_SUPP_H_
#define _WII_GX_SUPP_H_
+#include <gccore.h>
+
#ifdef __cplusplus
extern "C" {
#endif
+extern GXRModeObj *vmode;
+
void GX_InitVideo();
+void GX_SetTexTrans(float xT, float yT);
+void GX_SetCamPosZ(float f);
void GX_Start(u16 width, u16 height, s16 haspect, s16 vaspect);
void GX_Render(u16 width, u16 height, u8 *buffer, u16 pitch);
diff --git a/backends/platform/wii/osystem.cpp b/backends/platform/wii/osystem.cpp
index 3ec32126f0..505f93c820 100644
--- a/backends/platform/wii/osystem.cpp
+++ b/backends/platform/wii/osystem.cpp
@@ -19,8 +19,10 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-#include "osystem.h"
#include "backends/fs/wii/wii-fs-factory.h"
+#include "common/config-manager.h"
+
+#include "osystem.h"
#include <unistd.h>
@@ -51,7 +53,9 @@ OSystem_Wii::OSystem_Wii() :
_currentHeight(0),
_supportedGraphicsModes(NULL),
- _activeGraphicsMode(-1),
+ _activeGraphicsMode(0),
+
+ _fullscreen(false),
_mouseVisible(false),
_mouseX(0),
@@ -98,6 +102,8 @@ void OSystem_Wii::initBackend() {
_mixer = new Audio::MixerImpl(this);
_timer = new DefaultTimerManager();
+ _fullscreen = ConfMan.getBool("fullscreen");
+
initGfx();
initSfx();
initEvents();
@@ -112,14 +118,28 @@ void OSystem_Wii::quit() {
}
bool OSystem_Wii::hasFeature(Feature f) {
- return f == kFeatureCursorHasPalette;
+ return (f == kFeatureFullscreenMode) ||
+ (f == kFeatureCursorHasPalette);
}
void OSystem_Wii::setFeatureState(Feature f, bool enable) {
+ switch (f) {
+ case kFeatureFullscreenMode:
+ _fullscreen = enable;
+ setGraphicsMode(_activeGraphicsMode);
+ break;
+ default:
+ break;
+ }
}
bool OSystem_Wii::getFeatureState(Feature f) {
- return false;
+ switch (f) {
+ case kFeatureFullscreenMode:
+ return _fullscreen;
+ default:
+ return false;
+ }
}
uint32 OSystem_Wii::getMillis() {
diff --git a/backends/platform/wii/osystem.h b/backends/platform/wii/osystem.h
index 71bf9bce2e..94c0fa76b3 100644
--- a/backends/platform/wii/osystem.h
+++ b/backends/platform/wii/osystem.h
@@ -73,6 +73,8 @@ private:
OSystem::GraphicsMode *_supportedGraphicsModes;
s32 _activeGraphicsMode;
+ bool _fullscreen;
+
bool _mouseVisible;
s32 _mouseX, _mouseY;
u32 _mouseWidth, _mouseHeight;
@@ -110,7 +112,6 @@ public:
virtual bool getFeatureState(Feature f);
virtual const GraphicsMode *getSupportedGraphicsModes() const;
virtual int getDefaultGraphicsMode() const;
- bool setGraphicsMode(const char *name);
virtual bool setGraphicsMode(int mode);
virtual int getGraphicsMode() const;
virtual void initSize(uint width, uint height);
diff --git a/backends/platform/wii/osystem_gfx.cpp b/backends/platform/wii/osystem_gfx.cpp
index 1e54233c93..faad41d5f0 100644
--- a/backends/platform/wii/osystem_gfx.cpp
+++ b/backends/platform/wii/osystem_gfx.cpp
@@ -27,7 +27,12 @@
#define MAX_FPS 30
enum GraphicModeID {
- GM_DEFAULT
+ GM_DEFAULT = 0,
+ GM_OVERSCAN1,
+ GM_OVERSCAN2,
+ GM_OVERSCAN3,
+ GM_OVERSCAN4,
+ GM_OVERSCAN5
};
void OSystem_Wii::initGfx() {
@@ -42,6 +47,11 @@ void OSystem_Wii::initGfx() {
_overlayWidth = 640;
_overlayHeight = 480;
+#ifndef GAMECUBE
+ if (CONF_GetAspectRatio() && _fullscreen)
+ _overlayHeight = 360;
+#endif
+
_overlaySize = _overlayWidth * _overlayHeight * 2;
_overlayPixels = (OverlayColor *) memalign(32, _overlaySize);
@@ -51,17 +61,32 @@ void OSystem_Wii::initGfx() {
_cursorPalette = (u16 *) memalign(32, 256 * 2);
memset(_cursorPalette, 0, 256 * 2);
- _supportedGraphicsModes = new OSystem::GraphicsMode[2];
- _supportedGraphicsModes[0].name = strdup("gx");
- _supportedGraphicsModes[0].description = strdup("wii hardware scaler");
+ _supportedGraphicsModes = new OSystem::GraphicsMode[7];
+ _supportedGraphicsModes[0].name = strdup("standard");
+ _supportedGraphicsModes[0].description = strdup("standard");
_supportedGraphicsModes[0].id = GM_DEFAULT;
- _supportedGraphicsModes[1].name = 0;
- _supportedGraphicsModes[1].description = 0;
- _supportedGraphicsModes[1].id = 0;
-
- _texture = (u16 *) memalign(32, _overlaySize);
-
- GX_Start(_overlayWidth, _overlayHeight, 320, 240);
+ _supportedGraphicsModes[1].name = strdup("overscan1");
+ _supportedGraphicsModes[1].description = strdup("overscan 1");
+ _supportedGraphicsModes[1].id = GM_OVERSCAN1;
+ _supportedGraphicsModes[2].name = strdup("overscan2");
+ _supportedGraphicsModes[2].description = strdup("overscan 2");
+ _supportedGraphicsModes[2].id = GM_OVERSCAN2;
+ _supportedGraphicsModes[3].name = strdup("overscan3");
+ _supportedGraphicsModes[3].description = strdup("overscan 3");
+ _supportedGraphicsModes[3].id = GM_OVERSCAN3;
+ _supportedGraphicsModes[4].name = strdup("overscan4");
+ _supportedGraphicsModes[4].description = strdup("overscan 4");
+ _supportedGraphicsModes[4].id = GM_OVERSCAN4;
+ _supportedGraphicsModes[5].name = strdup("overscan5");
+ _supportedGraphicsModes[5].description = strdup("overscan 5");
+ _supportedGraphicsModes[5].id = GM_OVERSCAN5;
+ _supportedGraphicsModes[6].name = 0;
+ _supportedGraphicsModes[6].description = 0;
+ _supportedGraphicsModes[6].id = 0;
+
+ _texture = (u16 *) memalign(32, 640 * 480 * 2);
+
+ setGraphicsMode(_activeGraphicsMode);
}
void OSystem_Wii::deinitGfx() {
@@ -111,13 +136,24 @@ int OSystem_Wii::getDefaultGraphicsMode() const {
return GM_DEFAULT;
}
-bool OSystem_Wii::setGraphicsMode(const char *mode) {
- setGraphicsMode(GM_DEFAULT);
+bool OSystem_Wii::setGraphicsMode(int mode) {
+ s16 xar, yar;
- return true;
-}
+ printf("setGraphicsMode %d\n", mode);
+
+ xar = vmode->viWidth / 2;
+ yar = vmode->xfbHeight / 2;
+
+#ifndef GAMECUBE
+ if (CONF_GetAspectRatio() && !_fullscreen)
+ xar /= 1.33f;
+#endif
+
+ GX_SetCamPosZ(400 - mode * 10);
+ GX_Start(640, 480, xar, yar);
+
+ _activeGraphicsMode = mode;
-bool OSystem_Wii::setGraphicsMode(int mode) {
return true;
}
@@ -129,6 +165,8 @@ void OSystem_Wii::initSize(uint width, uint height) {
if (_gameWidth != width || _gameHeight != height) {
printf("initSize %u %u\n", width, height);
+ assert((width <= 640) && (height <= 480));
+
_gameWidth = width;
_gameHeight = height;
@@ -136,12 +174,15 @@ void OSystem_Wii::initSize(uint width, uint height) {
free(_gamePixels);
_gamePixels = (u8 *) memalign(32, _gameWidth * _gameHeight);
+ memset(_gamePixels, 0, _gameWidth * _gameHeight);
if (!_overlayVisible) {
_currentWidth = _gameWidth;
_currentHeight = _gameHeight;
updateEventScreenResolution();
}
+
+ setGraphicsMode(_activeGraphicsMode);
}
}
@@ -320,6 +361,8 @@ void OSystem_Wii::unlockScreen() {
}
void OSystem_Wii::setShakePos(int shakeOffset) {
+ GX_SetTexTrans(0, (float) -shakeOffset * ((float) vmode->efbHeight /
+ (float) _currentHeight));
}
void OSystem_Wii::showOverlay() {
diff --git a/backends/platform/wince/CEActionsPocket.cpp b/backends/platform/wince/CEActionsPocket.cpp
index 95047ecf5c..3626c4c10b 100644
--- a/backends/platform/wince/CEActionsPocket.cpp
+++ b/backends/platform/wince/CEActionsPocket.cpp
@@ -215,7 +215,7 @@ CEActionsPocket::~CEActionsPocket() {
}
bool CEActionsPocket::perform(GUI::ActionType action, bool pushed) {
- static bool keydialogrunning = false;
+ static bool keydialogrunning = false, quitdialog = false;
if (!pushed) {
switch(action) {
@@ -292,12 +292,14 @@ bool CEActionsPocket::perform(GUI::ActionType action, bool pushed) {
_CESystem->move_cursor_right();
return true;
case POCKET_ACTION_QUIT:
- {
+ if (!quitdialog) {
+ quitdialog = true;
GUI::MessageDialog alert(" Are you sure you want to quit ? ", "Yes", "No");
if (alert.runModal() == GUI::kMessageOK)
_mainSystem->quit();
- return true;
+ quitdialog = false;
}
+ return true;
case POCKET_ACTION_BINDKEYS:
if (!keydialogrunning) {
keydialogrunning = true;
diff --git a/backends/platform/wince/CEActionsSmartphone.cpp b/backends/platform/wince/CEActionsSmartphone.cpp
index dbcddac98c..87f73f5a66 100644
--- a/backends/platform/wince/CEActionsSmartphone.cpp
+++ b/backends/platform/wince/CEActionsSmartphone.cpp
@@ -179,7 +179,7 @@ CEActionsSmartphone::~CEActionsSmartphone() {
}
bool CEActionsSmartphone::perform(GUI::ActionType action, bool pushed) {
- static bool keydialogrunning = false;
+ static bool keydialogrunning = false, quitdialog = false;
if (!pushed) {
switch (action) {
@@ -250,12 +250,14 @@ bool CEActionsSmartphone::perform(GUI::ActionType action, bool pushed) {
_CESystem->smartphone_rotate_display();
return true;
case SMARTPHONE_ACTION_QUIT:
- {
+ if (!quitdialog) {
+ quitdialog = true;
GUI::MessageDialog alert(" Are you sure you want to quit ? ", "Yes", "No");
if (alert.runModal() == GUI::kMessageOK)
_mainSystem->quit();
- return true;
+ quitdialog = false;
}
+ return true;
}
return false;
diff --git a/backends/platform/wince/CEkeys/EventsBuffer.cpp b/backends/platform/wince/CEkeys/EventsBuffer.cpp
index 92a21ab7ad..f31a77570f 100644
--- a/backends/platform/wince/CEkeys/EventsBuffer.cpp
+++ b/backends/platform/wince/CEkeys/EventsBuffer.cpp
@@ -36,9 +36,8 @@ namespace CEKEYS {
key->setKey(key->keycode());
ev.type = (pushed ? SDL_KEYDOWN : SDL_KEYUP);
- ev.key.keysym.mod = (SDLMod)key->flags();
+ ev.key.keysym.unicode = (SDLMod)key->flags(); // HACK: put the flags into the unused unicode field
ev.key.keysym.sym = (SDLKey)key->keycode();
- ev.key.keysym.unicode = key->keycode();
ev.key.keysym.mod = KMOD_RESERVED;
return (SDL_PushEvent(&ev) == 0);
}
diff --git a/backends/platform/wince/wince-sdl.cpp b/backends/platform/wince/wince-sdl.cpp
index 3f16b4fdd1..48f157f6ff 100644
--- a/backends/platform/wince/wince-sdl.cpp
+++ b/backends/platform/wince/wince-sdl.cpp
@@ -805,8 +805,16 @@ void OSystem_WINCE3::setupMixer() {
debug(1, "Sound opened OK, mixing at %d Hz", _sampleRate);
// Re-create mixer to match the output rate
+ int vol1 = _mixer->getVolumeForSoundType(Audio::Mixer::kPlainSoundType);
+ int vol2 = _mixer->getVolumeForSoundType(Audio::Mixer::kMusicSoundType);
+ int vol3 = _mixer->getVolumeForSoundType(Audio::Mixer::kSFXSoundType);
+ int vol4 = _mixer->getVolumeForSoundType(Audio::Mixer::kSpeechSoundType);
delete(_mixer);
_mixer = new Audio::MixerImpl(this);
+ _mixer->setVolumeForSoundType(Audio::Mixer::kPlainSoundType, vol1);
+ _mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, vol2);
+ _mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, vol3);
+ _mixer->setVolumeForSoundType(Audio::Mixer::kSpeechSoundType, vol4);
_mixer->setOutputRate(_sampleRate);
_mixer->setReady(true);
SDL_PauseAudio(0);
@@ -2254,15 +2262,18 @@ bool OSystem_WINCE3::pollEvent(Common::Event &event) {
_lastKeyPressed = 0;
event.type = Common::EVENT_PREDICTIVE_DIALOG;
return true;
- }
-
- event.type = Common::EVENT_KEYDOWN;
+ } event.type = Common::EVENT_KEYDOWN;
if (!_unfilteredkeys)
event.kbd.keycode = (Common::KeyCode)ev.key.keysym.sym;
else
event.kbd.keycode = (Common::KeyCode)mapKeyCE(ev.key.keysym.sym, ev.key.keysym.mod, ev.key.keysym.unicode, _unfilteredkeys);
event.kbd.ascii = mapKeyCE(ev.key.keysym.sym, ev.key.keysym.mod, ev.key.keysym.unicode, _unfilteredkeys);
+ if (ev.key.keysym.mod == KMOD_RESERVED && ev.key.keysym.unicode == KMOD_SHIFT) {
+ event.kbd.ascii ^= 0x20;
+ event.kbd.flags = Common::KBD_SHIFT;
+ }
+
return true;
case SDL_KEYUP:
@@ -2290,6 +2301,11 @@ bool OSystem_WINCE3::pollEvent(Common::Event &event) {
event.kbd.keycode = (Common::KeyCode)mapKeyCE(ev.key.keysym.sym, ev.key.keysym.mod, ev.key.keysym.unicode, _unfilteredkeys);
event.kbd.ascii = mapKeyCE(ev.key.keysym.sym, ev.key.keysym.mod, ev.key.keysym.unicode, _unfilteredkeys);
+ if (ev.key.keysym.mod == KMOD_RESERVED && ev.key.keysym.unicode == KMOD_SHIFT) {
+ event.kbd.ascii ^= 0x20;
+ event.kbd.flags = Common::KBD_SHIFT;
+ }
+
return true;
case SDL_MOUSEMOTION:
diff --git a/dists/wii/READMII b/dists/wii/READMII
index 87efe21d68..c0c67eafd7 100644
--- a/dists/wii/READMII
+++ b/dists/wii/READMII
@@ -1,5 +1,5 @@
-Wii port of ScummVM README
---------------------------
+Wii/Gamecube port of ScummVM README
+-----------------------------------
features not compiled in:
- the AGI game engine
@@ -66,6 +66,21 @@ CONTROLS
dpad left: "y"
dpad right: "n"
+DISPLAY SETUP
+
+ "Graphics mode"
+ you can choose between multiple overscan options to adjust the screen size
+ used for drawing. select a higher overscan mode to get rid of black
+ borders or choose a lower overscan mode if parts of the picture get cropped
+
+ "Fullscreen mode"
+ If your wii is set to 16:9, this will stretch the picture to fullscreen.
+ Turning this option off results in black borders on the left and right
+ sides, but the aspect ratio will be kept. This option has no effect on 4:3
+ displays
+
+ you have to restart scummvm after changing one of these options
+
THANKS
shagkur and WinterMute, for devkitppc/libogc and the coorperation
diff --git a/engines/agi/sound.cpp b/engines/agi/sound.cpp
index 77f79272f8..9fe8fbf41a 100644
--- a/engines/agi/sound.cpp
+++ b/engines/agi/sound.cpp
@@ -435,13 +435,10 @@ void IIgsMidiChannel::stopSounds() {
_gsChannels.clear();
}
-static int16 *buffer;
-
int SoundMgr::initSound() {
int r = -1;
- buffer = _sndBuffer = (int16 *)calloc(2, BUFFER_SIZE);
-
+ memset(_sndBuffer, 0, BUFFER_SIZE << 1);
_env = false;
switch (_vm->_soundemu) {
@@ -478,7 +475,6 @@ int SoundMgr::initSound() {
void SoundMgr::deinitSound() {
debugC(3, kDebugLevelSound, "()");
_mixer->stopHandle(_soundHandle);
- free(_sndBuffer);
}
void SoundMgr::stopNote(int i) {
@@ -1185,7 +1181,7 @@ bool SoundMgr::loadInstruments() {
return _gsSound.loadWaveFile(waveFsnode->getPath(), *exeInfo) && _gsSound.loadInstrumentHeaders(exeFsnode->getPath(), *exeInfo);
}
-static void fillAudio(void *udata, int16 *stream, uint len) {
+void SoundMgr::fillAudio(void *udata, int16 *stream, uint len) {
SoundMgr *soundMgr = (SoundMgr *)udata;
uint32 p = 0;
static uint32 n = 0, s = 0;
@@ -1193,32 +1189,34 @@ static void fillAudio(void *udata, int16 *stream, uint len) {
len <<= 2;
debugC(5, kDebugLevelSound, "(%p, %p, %d)", (void *)udata, (void *)stream, len);
- memcpy(stream, (uint8 *)buffer + s, p = n);
+ memcpy(stream, (uint8 *)_sndBuffer + s, p = n);
for (n = 0, len -= p; n < len; p += n, len -= n) {
soundMgr->playSound();
n = soundMgr->mixSound() << 1;
if (len < n) {
- memcpy((uint8 *)stream + p, buffer, len);
+ memcpy((uint8 *)stream + p, _sndBuffer, len);
s = len;
n -= s;
return;
} else {
- memcpy((uint8 *)stream + p, buffer, n);
+ memcpy((uint8 *)stream + p, _sndBuffer, n);
}
}
soundMgr->playSound();
n = soundMgr->mixSound() << 1;
- memcpy((uint8 *)stream + p, buffer, s = len);
+ memcpy((uint8 *)stream + p, _sndBuffer, s = len);
n -= s;
}
-SoundMgr::SoundMgr(AgiBase *agi, Audio::Mixer *pMixer) {
+SoundMgr::SoundMgr(AgiBase *agi, Audio::Mixer *pMixer) : _chn() {
_vm = agi;
_mixer = pMixer;
_sampleRate = pMixer->getOutputRate();
_endflag = -1;
_playingSound = -1;
- _sndBuffer = 0;
+ _env = false;
+ _playing = false;
+ _sndBuffer = (int16 *)calloc(2, BUFFER_SIZE);
_waveform = 0;
}
@@ -1231,6 +1229,7 @@ void SoundMgr::setVolume(uint8 volume) {
}
SoundMgr::~SoundMgr() {
+ free(_sndBuffer);
}
} // End of namespace Agi
diff --git a/engines/agi/sound.h b/engines/agi/sound.h
index f1c2782421..a1f079891f 100644
--- a/engines/agi/sound.h
+++ b/engines/agi/sound.h
@@ -472,6 +472,7 @@ private:
const int16 *_waveform;
void premixerCall(int16 *buf, uint len);
+ void fillAudio(void *udata, int16 *stream, uint len);
public:
void unloadSound(int);
diff --git a/engines/cine/cine.cpp b/engines/cine/cine.cpp
index c30cac63a5..ea4b2512f5 100644
--- a/engines/cine/cine.cpp
+++ b/engines/cine/cine.cpp
@@ -68,14 +68,9 @@ CineEngine::CineEngine(OSystem *syst, const CINEGameDescription *gameDesc) : Eng
CineEngine::~CineEngine() {
if (g_cine->getGameType() == Cine::GType_OS) {
- freePoldatDat();
freeErrmessDat();
}
Common::clearAllSpecialDebugLevels();
-
- free(palPtr);
- free(partBuffer);
- free(textDataPtr);
}
int CineEngine::init() {
@@ -152,15 +147,16 @@ void CineEngine::initialize() {
}
collisionPage = new byte[320 * 200];
- textDataPtr = (byte *)malloc(8000);
- partBuffer = (PartBuffer *)malloc(NUM_MAX_PARTDATA * sizeof(PartBuffer));
+ // Clear part buffer as there's nothing loaded into it yet.
+ // Its size will change when loading data into it with the loadPart function.
+ partBuffer.clear();
if (g_cine->getGameType() == Cine::GType_OS) {
readVolCnf();
}
- loadTextData("texte.dat", textDataPtr);
+ loadTextData("texte.dat");
if (g_cine->getGameType() == Cine::GType_OS && !(g_cine->getFeatures() & GF_DEMO)) {
loadPoldatDat("poldat.dat");
diff --git a/engines/cine/gfx.cpp b/engines/cine/gfx.cpp
index c6c5faf464..cb900e8850 100644
--- a/engines/cine/gfx.cpp
+++ b/engines/cine/gfx.cpp
@@ -31,6 +31,7 @@
#include "common/endian.h"
#include "common/system.h"
+#include "common/events.h"
#include "graphics/cursorman.h"
@@ -91,7 +92,7 @@ static const byte cursorPalette[] = {
*/
FWRenderer::FWRenderer() : _background(NULL), _palette(NULL), _cmd(""),
_cmdY(0), _messageBg(0), _backBuffer(new byte[_screenSize]),
- _activeLowPal(NULL), _changePal(0) {
+ _activeLowPal(NULL), _changePal(0), _showCollisionPage(false) {
assert(_backBuffer);
@@ -125,6 +126,7 @@ void FWRenderer::clear() {
_cmdY = 0;
_messageBg = 0;
_changePal = 0;
+ _showCollisionPage = false;
}
/*! \brief Draw 1bpp sprite using selected color
@@ -225,14 +227,18 @@ void FWRenderer::drawCommand() {
* \param x Top left message box corner coordinate
* \param y Top left message box corner coordinate
* \param width Message box width
- * \param color Message box background color
+ * \param color Message box background color (Or if negative draws only the text)
+ * \note Negative colors are used in Operation Stealth's timed cutscenes
+ * (e.g. when first meeting The Movement for the Liberation of Santa Paragua).
*/
-void FWRenderer::drawMessage(const char *str, int x, int y, int width, byte color) {
+void FWRenderer::drawMessage(const char *str, int x, int y, int width, int color) {
int i, tx, ty, tw;
int line = 0, words = 0, cw = 0;
int space = 0, extraSpace = 0;
- drawPlainBox(x, y, width, 4, color);
+ if (color >= 0) {
+ drawPlainBox(x, y, width, 4, color);
+ }
tx = x + 4;
ty = str[0] ? y - 5 : y + 4;
tw = width - 8;
@@ -252,7 +258,9 @@ void FWRenderer::drawMessage(const char *str, int x, int y, int width, byte colo
}
ty += 9;
- drawPlainBox(x, ty, width, 9, color);
+ if (color >= 0) {
+ drawPlainBox(x, ty, width, 9, color);
+ }
tx = x + 4;
}
@@ -269,8 +277,10 @@ void FWRenderer::drawMessage(const char *str, int x, int y, int width, byte colo
}
ty += 9;
- drawPlainBox(x, ty, width, 4, color);
- drawDoubleBorder(x, y, width, ty - y + 4, 2);
+ if (color >= 0) {
+ drawPlainBox(x, ty, width, 4, color);
+ drawDoubleBorder(x, y, width, ty - y + 4, 2);
+ }
}
/*! \brief Draw rectangle on screen
@@ -279,54 +289,44 @@ void FWRenderer::drawMessage(const char *str, int x, int y, int width, byte colo
* \param width Rectangle width (Negative values draw the box horizontally flipped)
* \param height Rectangle height (Negative values draw the box vertically flipped)
* \param color Fill color
- * \note Rectangle's drawn width is always at least one.
- * \note Rectangle's drawn height is always at least one.
+ * \note An on-screen rectangle's drawn width is always at least one.
+ * \note An on-screen rectangle's drawn height is always at least one.
*/
void FWRenderer::drawPlainBox(int x, int y, int width, int height, byte color) {
- int i;
+ // Make width's and height's absolute values at least one
+ // which forces this function to always draw something if the
+ // drawing position is inside screen bounds. This fixes at least
+ // the showing of the oxygen gauge meter in Operation Stealth's
+ // first arcade sequence where this function is called with a
+ // height of zero.
+ if (width == 0) {
+ width = 1;
+ }
+ if (height == 0) {
+ height = 1;
+ }
// Handle horizontally flipped boxes
if (width < 0) {
- x += width;
width = ABS(width);
+ x -= width;
}
// Handle vertically flipped boxes
if (height < 0) {
- y += height;
height = ABS(height);
+ y -= height;
}
- // Handle horizontal boundaries
- if (x < 0) {
- width += x; // Remove invisible columns
- x = 0; // Start drawing at the screen's left border
- } else if (x > 319) {
- // Nothing left to draw as we're over the screen's right border
- width = 0;
- }
-
- // Handle vertical boundaries
- if (y < 0) {
- height += y; // Remove invisible rows
- y = 0; // Start drawing at the screen's top border
- } else if (y > 199) {
- // Nothing left to draw as we're below the screen's bottom border
- height = 0;
- }
+ // Clip the rectangle to screen dimensions
+ Common::Rect boxRect(x, y, x + width, y + height);
+ Common::Rect screenRect(320, 200);
+ boxRect.clip(screenRect);
- // Make width and height at least one
- // which forces this function to always draw something.
- // This fixes at least the showing of the oxygen gauge meter in
- // Operation Stealth's first arcade sequence where this function
- // is called with a height of zero.
- width = MAX(1, width);
- height = MAX(1, height);
-
- // Draw the filled rectangle
- byte *dest = _backBuffer + y * 320 + x;
- for (i = 0; i < height; i++) {
- memset(dest + i * 320, color, width);
+ // Draw the filled rectangle
+ byte *dest = _backBuffer + boxRect.top * 320 + boxRect.left;
+ for (int i = 0; i < boxRect.height(); i++) {
+ memset(dest + i * 320, color, boxRect.width());
}
}
@@ -366,8 +366,8 @@ int FWRenderer::drawChar(char character, int x, int y) {
if (character == ' ') {
x += 5;
- } else if ((width = fontParamTable[(unsigned char)character].characterWidth)) {
- idx = fontParamTable[(unsigned char)character].characterIdx;
+ } else if ((width = g_cine->_textHandler.fontParamTable[(unsigned char)character].characterWidth)) {
+ idx = g_cine->_textHandler.fontParamTable[(unsigned char)character].characterIdx;
drawSpriteRaw(g_cine->_textHandler.textTable[idx][0], g_cine->_textHandler.textTable[idx][1], 16, 8, _backBuffer, x, y);
x += width + 1;
}
@@ -513,16 +513,28 @@ void FWRenderer::drawFrame() {
blit();
}
+/*!
+ * \brief Turn on or off the showing of the collision page.
+ * If turned on the blitting routine shows the collision page instead of the back buffer.
+ * \note Useful for debugging collision page related problems.
+ */
+void FWRenderer::showCollisionPage(bool state) {
+ _showCollisionPage = state;
+}
+
/*! \brief Update screen
*/
void FWRenderer::blit() {
- g_system->copyRectToScreen(_backBuffer, 320, 0, 0, 320, 200);
+ // Show the back buffer or the collision page. Normally the back
+ // buffer but showing the collision page is useful for debugging.
+ byte *source = (_showCollisionPage ? collisionPage : _backBuffer);
+ g_system->copyRectToScreen(source, 320, 0, 0, 320, 200);
}
/*! \brief Set player command string
* \param cmd New command string
*/
-void FWRenderer::setCommand(const char *cmd) {
+void FWRenderer::setCommand(Common::String cmd) {
_cmd = cmd;
}
@@ -1023,8 +1035,8 @@ int OSRenderer::drawChar(char character, int x, int y) {
if (character == ' ') {
x += 5;
- } else if ((width = fontParamTable[(unsigned char)character].characterWidth)) {
- idx = fontParamTable[(unsigned char)character].characterIdx;
+ } else if ((width = g_cine->_textHandler.fontParamTable[(unsigned char)character].characterWidth)) {
+ idx = g_cine->_textHandler.fontParamTable[(unsigned char)character].characterIdx;
drawSpriteRaw2(g_cine->_textHandler.textTable[idx][0], 0, 16, 8, _backBuffer, x, y);
x += width + 1;
}
@@ -1063,10 +1075,11 @@ void OSRenderer::drawBackground() {
* \todo Add handling of type 22 overlays
*/
void OSRenderer::renderOverlay(const Common::List<overlay>::iterator &it) {
- int len;
+ int len, idx, width, height;
objectStruct *obj;
AnimData *sprite;
byte *mask;
+ byte color;
switch (it->type) {
// color sprite
@@ -1096,6 +1109,19 @@ void OSRenderer::renderOverlay(const Common::List<overlay>::iterator &it) {
}
break;
+ // action failure message
+ case 3:
+ idx = it->objIdx * 4 + g_cine->_rnd.getRandomNumber(3);
+ len = strlen(failureMessages[idx]);
+ _messageLen += len;
+ width = 6 * len + 20;
+ width = width > 300 ? 300 : width;
+
+ // The used color here differs from Future Wars
+ drawMessage(failureMessages[idx], (320 - width) / 2, 80, width, _messageBg);
+ waitForPlayerClick = 1;
+ break;
+
// bitmap
case 4:
if (objectTable[it->objIdx].frame >= 0) {
@@ -1117,26 +1143,25 @@ void OSRenderer::renderOverlay(const Common::List<overlay>::iterator &it) {
maskBgOverlay(_bgTable[it->x].bg, sprite->data(), sprite->_realWidth, sprite->_height, _backBuffer, obj->x, obj->y);
break;
- // FIXME: Looking at Operation Stealth's disassembly I can't find any codepath that
- // will draw a type 21 overlay. But looking at the first arcade sequence's scripts
- // it looks like the oxygen gauge meter is implemented using a type 21 overlay.
- // So for the time being I'm simply drawing type 21 overlays as type 22 overlays
- // and hoping for the best.
- // TODO: Check how the original game looks under DOSBox to see if the oxygen gauge works in it
+ // FIXME: Implement correct drawing of type 21 overlays.
+ // Type 21 overlays aren't just filled rectangles, I found their drawing routine
+ // from Operation Stealth's drawSprite routine. So they're likely some kind of sprites
+ // and it's just a coincidence that the oxygen meter during the first arcade sequence
+ // works even somehow currently. I tried the original under DOSBox and the oxygen gauge
+ // is a long red bar that gets shorter as the air runs out.
case 21:
// A filled rectangle:
- case 22: {
+ case 22:
// TODO: Check it this implementation really works correctly (Some things might be wrong, needs testing).
assert(it->objIdx < NUM_MAX_OBJECT);
obj = &objectTable[it->objIdx];
- byte color = obj->part & 0x0F;
- int width = obj->frame;
- int height = obj->costume;
+ color = obj->part & 0x0F;
+ width = obj->frame;
+ height = obj->costume;
drawPlainBox(obj->x, obj->y, width, height, color);
debug(5, "renderOverlay: type=%d, x=%d, y=%d, width=%d, height=%d, color=%d",
it->type, obj->x, obj->y, width, height, color);
break;
- }
// something else
default:
diff --git a/engines/cine/gfx.h b/engines/cine/gfx.h
index 078954e3b9..c07214028c 100644
--- a/engines/cine/gfx.h
+++ b/engines/cine/gfx.h
@@ -62,13 +62,14 @@ protected:
byte *_backBuffer; ///< Screen backbuffer
uint16 *_activeLowPal; ///< Active 16 color palette
int _changePal; ///< Load active palette to video backend on next frame
+ bool _showCollisionPage; ///< Should we show the collision page instead of the back buffer? Used for debugging.
void fillSprite(const objectStruct &obj, uint8 color = 0);
void drawMaskedSprite(const objectStruct &obj, const byte *mask);
virtual void drawSprite(const objectStruct &obj);
void drawCommand();
- void drawMessage(const char *str, int x, int y, int width, byte color);
+ void drawMessage(const char *str, int x, int y, int width, int color);
void drawPlainBox(int x, int y, int width, int height, byte color);
void drawBorder(int x, int y, int width, int height, byte color);
void drawDoubleBorder(int x, int y, int width, int height, byte color);
@@ -94,7 +95,7 @@ public:
void drawFrame();
void blit();
- void setCommand(const char *cmd);
+ void setCommand(Common::String cmd);
virtual void incrustMask(const objectStruct &obj, uint8 color = 0);
virtual void incrustSprite(const objectStruct &obj);
@@ -124,6 +125,7 @@ public:
void drawInputBox(const char *info, const char *input, int cursor, int x, int y, int width);
virtual void fadeToBlack();
+ void showCollisionPage(bool state);
};
/*! \brief Operation Stealth renderer
diff --git a/engines/cine/main_loop.cpp b/engines/cine/main_loop.cpp
index 3b0dc80bfb..04c6f5c769 100644
--- a/engines/cine/main_loop.cpp
+++ b/engines/cine/main_loop.cpp
@@ -121,6 +121,9 @@ static void processEvent(Common::Event &event) {
g_cine->makeSystemMenu();
}
break;
+ case Common::KEYCODE_F11:
+ renderer->showCollisionPage(true);
+ break;
case Common::KEYCODE_MINUS:
case Common::KEYCODE_KP_MINUS:
g_cine->modifyGameSpeed(-1); // Slower
@@ -164,6 +167,9 @@ static void processEvent(Common::Event &event) {
break;
case Common::EVENT_KEYUP:
switch (event.kbd.keycode) {
+ case Common::KEYCODE_F11:
+ renderer->showCollisionPage(false);
+ break;
case Common::KEYCODE_KP5: // Emulated left mouse button click
case Common::KEYCODE_LEFT: // Left
case Common::KEYCODE_KP4: // Left
@@ -276,7 +282,7 @@ void CineEngine::mainLoop(int bootScriptIdx) {
menuCommandLen = 0;
playerCommand = -1;
- strcpy(commandBuffer, "");
+ commandBuffer = "";
globalVars[VAR_MOUSE_X_POS] = 0;
globalVars[VAR_MOUSE_Y_POS] = 0;
diff --git a/engines/cine/msg.cpp b/engines/cine/msg.cpp
index 55eb627309..c826db3bf3 100644
--- a/engines/cine/msg.cpp
+++ b/engines/cine/msg.cpp
@@ -34,29 +34,40 @@ namespace Cine {
Common::StringList messageTable;
void loadMsg(char *pMsgName) {
- int i, count, len;
- byte *ptr, *dataPtr;
- const char *messagePtr;
+ uint32 sourceSize;
checkDataDisk(-1);
-
messageTable.clear();
-
- ptr = dataPtr = readBundleFile(findFileInBundle(pMsgName));
+ byte *dataPtr = readBundleFile(findFileInBundle(pMsgName), &sourceSize);
setMouseCursor(MOUSE_CURSOR_DISK);
- count = READ_BE_UINT16(ptr);
- ptr += 2;
-
- messagePtr = (const char*)(ptr + 2 * count);
-
- for (i = 0; i < count; i++) {
- len = READ_BE_UINT16(ptr);
- ptr += 2;
-
- messageTable.push_back(messagePtr);
- messagePtr += len;
+ uint count = READ_BE_UINT16(dataPtr);
+ uint messageLenPos = 2;
+ uint messageDataPos = messageLenPos + 2 * count;
+
+ // Read in the messages
+ for (uint i = 0; i < count; i++) {
+ // Read message's length
+ uint messageLen = READ_BE_UINT16(dataPtr + messageLenPos);
+ messageLenPos += 2;
+
+ // Store the read message.
+ // This code works around input data that has empty strings residing outside the input
+ // buffer (e.g. message indexes 58-254 in BATEAU.MSG in PROCS08 in Operation Stealth).
+ if (messageDataPos < sourceSize) {
+ messageTable.push_back((const char *)(dataPtr + messageDataPos));
+ } else {
+ if (messageLen > 0) { // Only warn about overflowing non-empty strings
+ warning("loadMsg(%s): message (%d. / %d) is overflowing the input buffer. Replacing it with an empty string", pMsgName, i + 1, count);
+ } else {
+ debugC(5, kCineDebugPart, "loadMsg(%s): empty message (%d. / %d) resides outside input buffer", pMsgName, i + 1, count);
+ }
+ // Message resides outside the input buffer so we replace it with an empty string
+ messageTable.push_back("");
+ }
+ // Jump to the next message
+ messageDataPos += messageLen;
}
free(dataPtr);
diff --git a/engines/cine/pal.cpp b/engines/cine/pal.cpp
index 3e6f5adf40..7f6307c640 100644
--- a/engines/cine/pal.cpp
+++ b/engines/cine/pal.cpp
@@ -28,10 +28,7 @@
namespace Cine {
-uint16 palEntriesCount;
-
-PalEntry *palPtr = NULL;
-
+Common::Array<PalEntry> palArray;
static byte paletteBuffer1[16];
static byte paletteBuffer2[16];
@@ -41,27 +38,20 @@ void loadPal(const char *fileName) {
removeExtention(buffer, fileName);
strcat(buffer, ".PAL");
-
- if (palPtr) {
- free(palPtr);
- palPtr = NULL;
- }
-
- palEntriesCount = 0;
+ palArray.clear();
Common::File palFileHandle;
if (!palFileHandle.open(buffer))
error("loadPal(): Cannot open file %s", fileName);
- palEntriesCount = palFileHandle.readUint16LE();
+ uint16 palEntriesCount = palFileHandle.readUint16LE();
palFileHandle.readUint16LE(); // entry size
- palPtr = (PalEntry *)malloc(palEntriesCount * sizeof(PalEntry));
- assert(palPtr);
- for (int i = 0; i < palEntriesCount; ++i) {
- palFileHandle.read(palPtr[i].name, 10);
- palFileHandle.read(palPtr[i].pal1, 16);
- palFileHandle.read(palPtr[i].pal2, 16);
+ palArray.resize(palEntriesCount);
+ for (uint i = 0; i < palArray.size(); ++i) {
+ palFileHandle.read(palArray[i].name, 10);
+ palFileHandle.read(palArray[i].pal1, 16);
+ palFileHandle.read(palArray[i].pal2, 16);
}
palFileHandle.close();
}
@@ -81,8 +71,8 @@ int16 findPaletteFromName(const char *fileName) {
position++;
}
- for (i = 0; i < palEntriesCount; i++) {
- if (!strcmp(buffer, palPtr[i].name)) {
+ for (i = 0; i < palArray.size(); i++) {
+ if (!strcmp(buffer, palArray[i].name)) {
return i;
}
}
@@ -105,9 +95,9 @@ void loadRelatedPalette(const char *fileName) {
paletteBuffer1[i] = paletteBuffer2[i] = (i << 4) + i;
}
} else {
- assert(paletteIndex < palEntriesCount);
- memcpy(paletteBuffer1, palPtr[paletteIndex].pal1, 16);
- memcpy(paletteBuffer2, palPtr[paletteIndex].pal2, 16);
+ assert(paletteIndex < (int32)palArray.size());
+ memcpy(paletteBuffer1, palArray[paletteIndex].pal1, 16);
+ memcpy(paletteBuffer2, palArray[paletteIndex].pal2, 16);
}
}
diff --git a/engines/cine/pal.h b/engines/cine/pal.h
index 768cf0d27d..819680973c 100644
--- a/engines/cine/pal.h
+++ b/engines/cine/pal.h
@@ -34,7 +34,7 @@ struct PalEntry {
byte pal2[16];
};
-extern PalEntry *palPtr;
+extern Common::Array<PalEntry> palArray;
void loadPal(const char *fileName);
diff --git a/engines/cine/part.cpp b/engines/cine/part.cpp
index d605bdd623..657471be4e 100644
--- a/engines/cine/part.cpp
+++ b/engines/cine/part.cpp
@@ -31,13 +31,10 @@
namespace Cine {
-uint16 numElementInPart;
-
-PartBuffer *partBuffer;
+Common::Array<PartBuffer> partBuffer;
void loadPart(const char *partName) {
- memset(partBuffer, 0, sizeof(PartBuffer) * NUM_MAX_PARTDATA);
- numElementInPart = 0;
+ partBuffer.clear();
g_cine->_partFileHandle.close();
@@ -48,13 +45,14 @@ void loadPart(const char *partName) {
setMouseCursor(MOUSE_CURSOR_DISK);
- numElementInPart = g_cine->_partFileHandle.readUint16BE();
+ uint16 numElementInPart = g_cine->_partFileHandle.readUint16BE();
+ partBuffer.resize(numElementInPart);
g_cine->_partFileHandle.readUint16BE(); // entry size
if (currentPartName != partName)
strcpy(currentPartName, partName);
- for (uint16 i = 0; i < numElementInPart; i++) {
+ for (uint16 i = 0; i < partBuffer.size(); i++) {
g_cine->_partFileHandle.read(partBuffer[i].partName, 14);
partBuffer[i].offset = g_cine->_partFileHandle.readUint32BE();
partBuffer[i].packedSize = g_cine->_partFileHandle.readUint32BE();
@@ -190,7 +188,7 @@ void CineEngine::readVolCnf() {
int16 findFileInBundle(const char *fileName) {
if (g_cine->getGameType() == Cine::GType_OS) {
// look first in currently loaded resource file
- for (int i = 0; i < numElementInPart; i++) {
+ for (uint i = 0; i < partBuffer.size(); i++) {
if (!scumm_stricmp(fileName, partBuffer[i].partName)) {
return i;
}
@@ -204,7 +202,7 @@ int16 findFileInBundle(const char *fileName) {
const char *part = (*it)._value;
loadPart(part);
}
- for (int i = 0; i < numElementInPart; i++) {
+ for (uint i = 0; i < partBuffer.size(); i++) {
if (!scumm_stricmp(fileName, partBuffer[i].partName)) {
return i;
}
@@ -212,26 +210,35 @@ int16 findFileInBundle(const char *fileName) {
return -1;
}
-void readFromPart(int16 idx, byte *dataPtr) {
+void readFromPart(int16 idx, byte *dataPtr, uint32 maxSize) {
setMouseCursor(MOUSE_CURSOR_DISK);
g_cine->_partFileHandle.seek(partBuffer[idx].offset, SEEK_SET);
- g_cine->_partFileHandle.read(dataPtr, partBuffer[idx].packedSize);
+ g_cine->_partFileHandle.read(dataPtr, MIN(partBuffer[idx].packedSize, maxSize));
}
-byte *readBundleFile(int16 foundFileIdx) {
- assert(foundFileIdx >= 0 && foundFileIdx < numElementInPart);
+byte *readBundleFile(int16 foundFileIdx, uint32 *size) {
+ assert(foundFileIdx >= 0 && foundFileIdx < (int32)partBuffer.size());
+ bool error = false;
byte *dataPtr = (byte *)calloc(partBuffer[foundFileIdx].unpackedSize, 1);
- if (partBuffer[foundFileIdx].unpackedSize != partBuffer[foundFileIdx].packedSize) {
- byte *unpackBuffer = (byte *)malloc(partBuffer[foundFileIdx].packedSize);
- readFromPart(foundFileIdx, unpackBuffer);
+ readFromPart(foundFileIdx, dataPtr, partBuffer[foundFileIdx].unpackedSize);
+ if (partBuffer[foundFileIdx].unpackedSize > partBuffer[foundFileIdx].packedSize) {
CineUnpacker cineUnpacker;
- if (!cineUnpacker.unpack(unpackBuffer, partBuffer[foundFileIdx].packedSize, dataPtr, partBuffer[foundFileIdx].unpackedSize)) {
- warning("Error unpacking '%s' from bundle file '%s'", partBuffer[foundFileIdx].partName, currentPartName);
- }
- free(unpackBuffer);
- } else {
- readFromPart(foundFileIdx, dataPtr);
+ error = !cineUnpacker.unpack(dataPtr, partBuffer[foundFileIdx].packedSize, dataPtr, partBuffer[foundFileIdx].unpackedSize);
+ } else if (partBuffer[foundFileIdx].unpackedSize < partBuffer[foundFileIdx].packedSize) {
+ // Unpacked size of a file should never be less than its packed size
+ error = true;
+ } else { // partBuffer[foundFileIdx].unpackedSize == partBuffer[foundFileIdx].packedSize
+ debugC(5, kCineDebugPart, "Loaded non-compressed file '%s' from bundle file '%s'", partBuffer[foundFileIdx].partName, currentPartName);
+ }
+
+ if (error) {
+ warning("Error unpacking '%s' from bundle file '%s'", partBuffer[foundFileIdx].partName, currentPartName);
+ }
+
+ // Set the size variable if a pointer to it has been given
+ if (size != NULL) {
+ *size = partBuffer[foundFileIdx].unpackedSize;
}
return dataPtr;
@@ -300,7 +307,7 @@ void dumpBundle(const char *fileName) {
strcpy(tmpPart, currentPartName);
loadPart(fileName);
- for (int i = 0; i < numElementInPart; i++) {
+ for (uint i = 0; i < partBuffer.size(); i++) {
byte *data = readBundleFile(i);
debug(0, "%s", partBuffer[i].partName);
diff --git a/engines/cine/part.h b/engines/cine/part.h
index 72dc944db3..755f843b4a 100644
--- a/engines/cine/part.h
+++ b/engines/cine/part.h
@@ -37,16 +37,16 @@ struct PartBuffer {
#define NUM_MAX_PARTDATA 255
-extern PartBuffer *partBuffer;
+extern Common::Array<PartBuffer> partBuffer;
void loadPart(const char *partName);
void closePart(void);
int16 findFileInBundle(const char *fileName);
-void readFromPart(int16 idx, byte *dataPtr);
+void readFromPart(int16 idx, byte *dataPtr, uint32 maxSize);
-byte *readBundleFile(int16 foundFileIdx);
+byte *readBundleFile(int16 foundFileIdx, uint32 *size = NULL);
byte *readBundleSoundFile(const char *entryName, uint32 *size = 0);
byte *readFile(const char *filename, bool crypted = false);
diff --git a/engines/cine/sound.cpp b/engines/cine/sound.cpp
index f26032fe98..3618350476 100644
--- a/engines/cine/sound.cpp
+++ b/engines/cine/sound.cpp
@@ -604,6 +604,7 @@ bool PCSoundFxPlayer::load(const char *song) {
_instrumentsData[i] = NULL;
char instrument[64];
+ memset(instrument, 0, 64); // Clear the data first
memcpy(instrument, _sfxData + 20 + i * 30, 12);
instrument[63] = '\0';
diff --git a/engines/cine/texte.cpp b/engines/cine/texte.cpp
index e4fd334926..33c16159ec 100644
--- a/engines/cine/texte.cpp
+++ b/engines/cine/texte.cpp
@@ -29,70 +29,53 @@
namespace Cine {
-byte *textDataPtr;
-
const char **failureMessages;
const CommandeType *defaultActionCommand;
const CommandeType *systemMenu;
const CommandeType *confirmMenu;
const char **otherMessages;
-const char *commandPrepositionOn;
+const char *defaultCommandPreposition;
+const char **commandPrepositionTable;
void generateMask(const byte *sprite, byte *mask, uint16 size, byte transparency);
-void loadTextData(const char *pFileName, byte *pDestinationBuffer) {
- Common::File pFileHandle;
- uint16 entrySize;
- uint16 numEntry;
- uint16 i;
- byte *tempBuffer;
- uint16 dataSize;
-
- assert(pFileName);
- assert(pDestinationBuffer);
+void loadTextData(const char *filename) {
+ Common::File fileHandle;
+ assert(filename);
- if (!pFileHandle.open(pFileName))
- error("loadTextData(): Cannot open file %s", pFileName);
+ if (!fileHandle.open(filename))
+ error("loadTextData(): Cannot open file %s", filename);
- entrySize = pFileHandle.readUint16BE();
- numEntry = pFileHandle.readUint16BE();
+ uint entrySize = fileHandle.readUint16BE();
+ uint numEntry = fileHandle.readUint16BE();
- dataSize = numEntry * entrySize;
- pFileHandle.read(pDestinationBuffer, numEntry * entrySize);
-
- tempBuffer = pDestinationBuffer;
+ uint sourceSize = numEntry * entrySize;
+ Common::Array<byte> source;
+ source.resize(sourceSize);
+ fileHandle.read(source.begin(), sourceSize);
+ const int fontHeight = 8;
+ const int fontWidth = (g_cine->getGameType() == Cine::GType_FW) ? 16 : 8;
+ uint numCharacters;
+ uint bytesPerCharacter;
if (g_cine->getGameType() == Cine::GType_FW) {
- int numCharacters;
- if (g_cine->getFeatures() & GF_ALT_FONT) {
- numCharacters = 85;
- } else {
- numCharacters = 78;
- }
-
- dataSize = dataSize / numCharacters;
-
- loadRelatedPalette(pFileName);
-
- for (i = 0; i < numCharacters; i++) {
- gfxConvertSpriteToRaw(g_cine->_textHandler.textTable[i][0], tempBuffer, 16, 8);
- generateMask(g_cine->_textHandler.textTable[i][0], g_cine->_textHandler.textTable[i][1], 16 * 8, 0);
- tempBuffer += dataSize;
- }
+ numCharacters = (g_cine->getFeatures() & GF_ALT_FONT) ? 85 : 78;
+ bytesPerCharacter = sourceSize / numCharacters; // TODO: Check if this could be replaced with fontWidth * fontHeight
+ loadRelatedPalette(filename);
} else {
- for (i = 0; i < 90; i++) {
- gfxConvertSpriteToRaw(g_cine->_textHandler.textTable[i][0], tempBuffer, 8, 8);
- generateMask(g_cine->_textHandler.textTable[i][0], g_cine->_textHandler.textTable[i][1], 8 * 8, 0);
- tempBuffer += 0x40;
- }
+ numCharacters = 90;
+ bytesPerCharacter = fontWidth * fontHeight;
}
- pFileHandle.close();
-}
+ for (uint i = 0; i < numCharacters; i++) {
+ gfxConvertSpriteToRaw(g_cine->_textHandler.textTable[i][0], &source[i * bytesPerCharacter], fontWidth, fontHeight);
+ generateMask(g_cine->_textHandler.textTable[i][0], g_cine->_textHandler.textTable[i][1], fontWidth * fontHeight, 0);
+ }
-const CharacterEntry *fontParamTable;
+ fileHandle.close();
+}
-const CharacterEntry fontParamTable_standard[256] = {
+static const CharacterEntry fontParamTable_standard[NUM_FONT_CHARS] = {
{ 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0},
{ 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0},
{ 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0},
@@ -129,7 +112,7 @@ const CharacterEntry fontParamTable_standard[256] = {
{ 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}
};
-const CharacterEntry fontParamTable_alt[256] = {
+static const CharacterEntry fontParamTable_alt[NUM_FONT_CHARS] = {
{ 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0},
{ 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0},
{ 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}, { 0, 0},
@@ -208,6 +191,16 @@ void initLanguage(Common::Language lang) {
"NOACTION"
};
+ static const char *commandPrepositionTable_EN[] = {
+ "", // EXAMINE
+ "", // TAKE
+ "", // INVENTORY
+ "on", // USE
+ "", // OPERATE
+ "to", // SPEAK
+ "" // NOACTION
+ };
+
static const CommandeType systemMenu_EN[] = {
"Pause",
"Restart Game",
@@ -223,9 +216,8 @@ void initLanguage(Common::Language lang) {
"PAUSE",
"Loading | %s",
"Loading canceled ...",
- "No baclup in the drive...",
- "Please enter the backup name",
- "on"
+ "No backup in the drive...",
+ "Please enter the backup name"
};
static const CommandeType confirmMenu_EN[] = {
@@ -276,6 +268,16 @@ void initLanguage(Common::Language lang) {
"NOACTION"
};
+ static const char *commandPrepositionTable_FR[] = {
+ "", // EXAMINER
+ "", // PRENDRE
+ "", // INVENTAIRE
+ "sur", // UTILISER
+ "", // ACTIONNER
+ "a", // PARLER
+ "" // NOACTION
+ };
+
static const CommandeType systemMenu_FR[] = {
"Pause",
"Nouvelle partie",
@@ -297,8 +299,7 @@ void initLanguage(Common::Language lang) {
"Sauvegarde de | %s",
"Sauvegarde Annul\x82""e ...",
"Aucune sauvegarde dans le lecteur ...",
- "Veuillez entrer le Nom de la Sauvegarde .",
- "sur"
+ "Veuillez entrer le Nom de la Sauvegarde ."
};
static const char *failureMessages_ES[] = {
@@ -344,6 +345,16 @@ void initLanguage(Common::Language lang) {
"NOACTION"
};
+ static const char *commandPrepositionTable_ES[] = {
+ "", // EXAMINAR
+ "", // COGER
+ "", // INVENTARIO
+ "donde", // USAR
+ "", // ACCIONAR
+ "a", // HABLAR
+ "" // NOACTION
+ };
+
static const CommandeType systemMenu_ES[] = {
"Pause",
"Nueva partida",
@@ -365,8 +376,7 @@ void initLanguage(Common::Language lang) {
"Gabacion de| %s",
"Rrabacion anulada",
"No hay partidas grabadas en este disco...",
- "Teclea el nombre de la partida grabada",
- "donde"
+ "Teclea el nombre de la partida grabada"
};
static const char *failureMessages_DE[] = {
@@ -403,15 +413,25 @@ void initLanguage(Common::Language lang) {
};
static const CommandeType defaultActionCommand_DE[] = {
- "Pr\x81""fe",
+ "Pr\x81""fe", // FIXME? The third letter should be Latin Small Letter U with diaeresis
"Nimm",
"Bestand",
"Benutze",
- "Bet\x84tige",
+ "Bet\x84tige", // FIXME? The fourth letter should be Latin Small Letter A with diaeresis
"Sprich",
"NOACTION"
};
+ static const char *commandPrepositionTable_DE[] = {
+ "", // Prufe
+ "", // Nimm
+ "", // Bestand
+ "gegen", // Benutze
+ "", // Betatige
+ "a", // Sprich
+ "" // NOACTION
+ };
+
static const CommandeType systemMenu_DE[] = {
"Pause",
"Spiel Neu Starten",
@@ -433,8 +453,7 @@ void initLanguage(Common::Language lang) {
"Er L\x84""dt | %s",
"Ladevorgang Abgebrochen...",
"Kein Backup im Laufwerk...",
- "Geben Sie den Namen|der Sicherungsdiskette ein",
- "gegen"
+ "Geben Sie den Namen|der Sicherungsdiskette ein"
};
static const char *failureMessages_IT[] = {
@@ -480,6 +499,16 @@ void initLanguage(Common::Language lang) {
"NOACTION"
};
+ static const char *commandPrepositionTable_IT[] = {
+ "", // ESAMINARE
+ "", // PRENDERE
+ "", // INVENTARIO
+ "su", // UTILIZZARE
+ "", // AZIONARE
+ "a", // PARLARE
+ "" // NOACTION
+ };
+
static const CommandeType systemMenu_IT[] = {
"Pausa",
"Parte nuova",
@@ -501,8 +530,7 @@ void initLanguage(Common::Language lang) {
"Caricamento di| %s",
"Caricamento annullato...",
"Nessun salvataggio su questo disco...",
- "Vogliate accedere con il nome del salvataggio",
- "su"
+ "Vogliate accedere con il nome del salvataggio"
};
switch (lang) {
@@ -512,7 +540,8 @@ void initLanguage(Common::Language lang) {
systemMenu = systemMenu_FR;
confirmMenu = confirmMenu_FR;
otherMessages = otherMessages_FR;
- commandPrepositionOn = otherMessages_FR[7];
+ defaultCommandPreposition = commandPrepositionTable_FR[3];
+ commandPrepositionTable = commandPrepositionTable_FR;
break;
case Common::ES_ESP:
@@ -521,7 +550,8 @@ void initLanguage(Common::Language lang) {
systemMenu = systemMenu_ES;
confirmMenu = confirmMenu_ES;
otherMessages = otherMessages_ES;
- commandPrepositionOn = otherMessages_ES[7];
+ defaultCommandPreposition = commandPrepositionTable_ES[3];
+ commandPrepositionTable = commandPrepositionTable_ES;
break;
case Common::DE_DEU:
@@ -530,7 +560,8 @@ void initLanguage(Common::Language lang) {
systemMenu = systemMenu_DE;
confirmMenu = confirmMenu_DE;
otherMessages = otherMessages_DE;
- commandPrepositionOn = otherMessages_DE[7];
+ defaultCommandPreposition = commandPrepositionTable_DE[3];
+ commandPrepositionTable = commandPrepositionTable_DE;
break;
case Common::IT_ITA:
@@ -539,7 +570,8 @@ void initLanguage(Common::Language lang) {
systemMenu = systemMenu_IT;
confirmMenu = confirmMenu_IT;
otherMessages = otherMessages_IT;
- commandPrepositionOn = otherMessages_IT[7];
+ defaultCommandPreposition = commandPrepositionTable_IT[3];
+ commandPrepositionTable = commandPrepositionTable_IT;
break;
default:
@@ -548,14 +580,17 @@ void initLanguage(Common::Language lang) {
systemMenu = systemMenu_EN;
confirmMenu = confirmMenu_EN;
otherMessages = otherMessages_EN;
- commandPrepositionOn = otherMessages_EN[7];
+ defaultCommandPreposition = commandPrepositionTable_EN[3];
+ commandPrepositionTable = commandPrepositionTable_EN;
break;
}
if (g_cine->getFeatures() & GF_ALT_FONT) {
- fontParamTable = fontParamTable_alt;
+ // Copy alternative font parameter table to the current font parameter table
+ Common::copy(fontParamTable_alt, fontParamTable_alt + NUM_FONT_CHARS, g_cine->_textHandler.fontParamTable);
} else {
- fontParamTable = fontParamTable_standard;
+ // Copy standard font parameter to the current font parameter table
+ Common::copy(fontParamTable_standard, fontParamTable_standard + NUM_FONT_CHARS, g_cine->_textHandler.fontParamTable);
}
}
@@ -590,25 +625,16 @@ void loadPoldatDat(const char *fname) {
in.open(fname);
if (in.isOpen()) {
- CharacterEntry *ptr = (CharacterEntry *)malloc(sizeof(CharacterEntry) * 256);
-
- for (int i = 0; i < 256; i++) {
- ptr[i].characterIdx = (int)in.readByte();
- ptr[i].characterWidth = (int)in.readByte();
+ for (int i = 0; i < NUM_FONT_CHARS; i++) {
+ g_cine->_textHandler.fontParamTable[i].characterIdx = in.readByte();
+ g_cine->_textHandler.fontParamTable[i].characterWidth = in.readByte();
}
- fontParamTable = ptr;
-
in.close();
} else {
error("Cannot open file %s for reading", fname);
}
}
-void freePoldatDat() {
- free(const_cast<Cine::CharacterEntry *>(fontParamTable));
- fontParamTable = 0;
-}
-
/*! \brief Fit a substring of text into one line of fixed width text box
* \param str Text to fit
* \param maxWidth Text box width
@@ -633,7 +659,7 @@ int fitLine(const char *str, int maxWidth, int &words, int &width) {
bkpWidth = width;
bkpLen = i + 1;
} else {
- charWidth = fontParamTable[(unsigned char)str[i]].characterWidth + 1;
+ charWidth = g_cine->_textHandler.fontParamTable[(unsigned char)str[i]].characterWidth + 1;
width += charWidth;
}
diff --git a/engines/cine/texte.h b/engines/cine/texte.h
index f471c3c49e..bc4beac492 100644
--- a/engines/cine/texte.h
+++ b/engines/cine/texte.h
@@ -33,10 +33,17 @@ namespace Cine {
typedef char CommandeType[20];
-extern byte *textDataPtr;
+// Number of characters in a font
+#define NUM_FONT_CHARS 256
+
+struct CharacterEntry {
+ byte characterIdx;
+ byte characterWidth;
+};
struct TextHandler {
- byte textTable[256][2][16 * 8];
+ byte textTable[NUM_FONT_CHARS][2][16 * 8];
+ CharacterEntry fontParamTable[NUM_FONT_CHARS];
};
extern const char **failureMessages;
@@ -44,20 +51,13 @@ extern const CommandeType *defaultActionCommand;
extern const CommandeType *systemMenu;
extern const CommandeType *confirmMenu;
extern const char **otherMessages;
-extern const char *commandPrepositionOn;
-
-struct CharacterEntry {
- byte characterIdx;
- byte characterWidth;
-};
-
-extern const CharacterEntry *fontParamTable;
+extern const char *defaultCommandPreposition;
+extern const char **commandPrepositionTable;
-void loadTextData(const char *pFileName, byte *pDestinationBuffer);
+void loadTextData(const char *filename);
void loadErrmessDat(const char *fname);
void freeErrmessDat(void);
void loadPoldatDat(const char *fname);
-void freePoldatDat(void);
int fitLine(const char *ptr, int maxWidth, int &words, int &width);
diff --git a/engines/cine/various.cpp b/engines/cine/various.cpp
index 2fe2701e52..5e4c0eee30 100644
--- a/engines/cine/various.cpp
+++ b/engines/cine/various.cpp
@@ -77,7 +77,7 @@ byte _danKeysPressed;
int16 playerCommand;
-char commandBuffer[80];
+Common::String commandBuffer;
char currentPrcName[20];
char currentRelName[20];
char currentObjectName[20];
@@ -316,6 +316,18 @@ void saveCommandVariables(Common::OutSaveFile &out) {
}
}
+/*! \brief Save the 80 bytes long command buffer padded to that length with zeroes. */
+void saveCommandBuffer(Common::OutSaveFile &out) {
+ // Let's make sure there's space for the trailing zero
+ // (That's why we subtract one from the maximum command buffer size here).
+ uint32 size = MIN<uint32>(commandBuffer.size(), kMaxCommandBufferSize - 1);
+ out.write(commandBuffer.c_str(), size);
+ // Write the rest as zeroes (Here we also write the string's trailing zero)
+ for (uint i = 0; i < kMaxCommandBufferSize - size; i++) {
+ out.writeByte(0);
+ }
+}
+
void saveAnimDataTable(Common::OutSaveFile &out) {
out.writeUint16BE(NUM_MAX_ANIMDATA); // Entry count
out.writeUint16BE(0x1E); // Entry size
@@ -633,7 +645,7 @@ void CineEngine::resetEngine() {
playerCommand = -1;
isDrawCommandEnabled = 0;
- strcpy(commandBuffer, "");
+ commandBuffer = "";
globalVars[VAR_MOUSE_X_POS] = 0;
globalVars[VAR_MOUSE_Y_POS] = 0;
@@ -834,7 +846,10 @@ bool CineEngine::loadTempSaveOS(Common::SeekableReadStream &in) {
globalVars.load(in, NUM_MAX_VAR);
loadZoneData(in);
loadCommandVariables(in);
- in.read(commandBuffer, 0x50);
+ char tempCommandBuffer[kMaxCommandBufferSize];
+ in.read(tempCommandBuffer, kMaxCommandBufferSize);
+ commandBuffer = tempCommandBuffer;
+ renderer->setCommand(commandBuffer);
loadZoneQuery(in);
// TODO: Use the loaded string (Current music name (String, 13 bytes)).
@@ -971,7 +986,9 @@ bool CineEngine::loadPlainSaveFW(Common::SeekableReadStream &in, CineSaveGameFor
loadCommandVariables(in);
// At 0x22A9 (i.e. 0x22A1 + 4 * 2):
- in.read(commandBuffer, 0x50);
+ char tempCommandBuffer[kMaxCommandBufferSize];
+ in.read(tempCommandBuffer, kMaxCommandBufferSize);
+ commandBuffer = tempCommandBuffer;
renderer->setCommand(commandBuffer);
// At 0x22F9 (i.e. 0x22A9 + 0x50):
@@ -1119,7 +1136,7 @@ void CineEngine::makeSaveFW(Common::OutSaveFile &out) {
globalVars.save(out, NUM_MAX_VAR);
saveZoneData(out);
saveCommandVariables(out);
- out.write(commandBuffer, 0x50);
+ saveCommandBuffer(out);
out.writeUint16BE(renderer->_cmdY);
out.writeUint16BE(bgVar0);
@@ -1334,7 +1351,7 @@ void CineEngine::makeSaveOS(Common::OutSaveFile &out) {
globalVars.save(out, NUM_MAX_VAR);
saveZoneData(out);
saveCommandVariables(out);
- out.write(commandBuffer, 0x50);
+ saveCommandBuffer(out);
saveZoneQuery(out);
// FIXME: Save a proper name here, saving an empty string currently.
@@ -1397,19 +1414,38 @@ void drawDoubleMessageBox(int16 x, int16 y, int16 width, int16 currentY, int16 c
}
void processInventory(int16 x, int16 y) {
- int16 listSize = buildObjectListCommand(-2);
uint16 button;
+ int menuWidth;
+ int listSize;
+ int commandParam;
+
+ if (g_cine->getGameType() == Cine::GType_FW) {
+ menuWidth = 140;
+ commandParam = -2;
+ } else { // Operation Stealth
+ menuWidth = 160;
+ commandParam = -3;
+ }
+
+ listSize = buildObjectListCommand(commandParam);
if (!listSize)
return;
- renderer->drawMenu(objectListCommand, listSize, x, y, 140, -1);
+ renderer->drawMenu(objectListCommand, listSize, x, y, menuWidth, -1);
renderer->blit();
do {
manageEvents();
getMouseData(mouseUpdateStatus, &button, &dummyU16, &dummyU16);
} while (!button);
+
+ do {
+ manageEvents();
+ getMouseData(mouseUpdateStatus, &button, &dummyU16, &dummyU16);
+ } while (button);
+
+ // TODO: Both Future Wars and Operation Stealth call showMouse, drawMouse or something similar here.
}
int16 buildObjectListCommand(int16 param) {
@@ -1453,6 +1489,8 @@ int16 selectSubObject(int16 x, int16 y, int16 param) {
return objListTab[selectedObject];
}
+// TODO: Make separate functions for Future Wars's and Operation Stealth's version of this function, this is getting too messy
+// TODO: Add support for using the different prepositions for different verbs (Doesn't work currently)
void makeCommandLine(void) {
uint16 x, y;
@@ -1460,9 +1498,9 @@ void makeCommandLine(void) {
commandVar2 = -10;
if (playerCommand != -1) {
- strcpy(commandBuffer, defaultActionCommand[playerCommand]);
+ commandBuffer = defaultActionCommand[playerCommand];
} else {
- strcpy(commandBuffer, "");
+ commandBuffer = "";
}
if ((playerCommand != -1) && (choiceResultTable[playerCommand] == 2)) { // need object selection ?
@@ -1477,8 +1515,12 @@ void makeCommandLine(void) {
}
if (si < 0) {
- playerCommand = -1;
- strcpy(commandBuffer, "");
+ if (g_cine->getGameType() == Cine::GType_OS) {
+ canUseOnObject = 0;
+ } else { // Future Wars
+ playerCommand = -1;
+ commandBuffer = "";
+ }
} else {
if (g_cine->getGameType() == Cine::GType_OS) {
if (si >= 8000) {
@@ -1491,23 +1533,28 @@ void makeCommandLine(void) {
commandVar3[0] = si;
commandVar1 = 1;
-
- strcat(commandBuffer, " ");
- strcat(commandBuffer, objectTable[commandVar3[0]].name);
- strcat(commandBuffer, " ");
- strcat(commandBuffer, commandPrepositionOn);
+ commandBuffer += " ";
+ commandBuffer += objectTable[commandVar3[0]].name;
+ commandBuffer += " ";
+ if (g_cine->getGameType() == Cine::GType_OS) {
+ commandBuffer += commandPrepositionTable[playerCommand];
+ } else { // Future Wars
+ commandBuffer += defaultCommandPreposition;
+ }
}
- } else {
+ }
+
+ if (g_cine->getGameType() == Cine::GType_OS || !(playerCommand != -1 && choiceResultTable[playerCommand] == 2)) {
if (playerCommand == 2) {
getMouseData(mouseUpdateStatus, &dummyU16, &x, &y);
processInventory(x, y + 8);
playerCommand = -1;
commandVar1 = 0;
- strcpy(commandBuffer, "");
+ commandBuffer = "";
}
}
- if (g_cine->getGameType() == Cine::GType_OS) {
+ if (g_cine->getGameType() == Cine::GType_OS && playerCommand != 2) {
if (playerCommand != -1 && canUseOnObject != 0) { // call use on sub object
int16 si;
@@ -1515,34 +1562,37 @@ void makeCommandLine(void) {
si = selectSubObject(x, y + 8, -subObjectUseTable[playerCommand]);
- if (si) {
+ if (si >= 0) {
if (si >= 8000) {
si -= 8000;
}
commandVar3[commandVar1] = si;
-
commandVar1++;
-
- // TODO: add command message draw
+ commandBuffer += " ";
+ commandBuffer += objectTable[si].name;
}
+ }
- isDrawCommandEnabled = 1;
+ isDrawCommandEnabled = 1;
- if (playerCommand != -1 && choiceResultTable[playerCommand] == commandVar1) {
- SelectedObjStruct obj;
- obj.idx = commandVar3[0];
- obj.param = commandVar3[1];
- int16 di = getRelEntryForObject(playerCommand, commandVar1, &obj);
+ if (playerCommand != -1 && choiceResultTable[playerCommand] == commandVar1) {
+ SelectedObjStruct obj;
+ obj.idx = commandVar3[0];
+ obj.param = commandVar3[1];
+ int16 di = getRelEntryForObject(playerCommand, commandVar1, &obj);
- if (di != -1) {
- runObjectScript(di);
- }
- }
+ if (di != -1) {
+ runObjectScript(di);
+ } // TODO: else addFailureMessage(playerCommand)
+
+ playerCommand = -1;
+ commandVar1 = 0;
+ commandBuffer = "";
}
}
- if (!disableSystemMenu) {
+ if (g_cine->getGameType() == Cine::GType_OS || !disableSystemMenu) {
isDrawCommandEnabled = 1;
renderer->setCommand(commandBuffer);
}
@@ -1759,8 +1809,9 @@ uint16 executePlayerInput(void) {
commandVar3[commandVar1] = si;
commandVar1++;
- strcat(commandBuffer, " ");
- strcat(commandBuffer, objectTable[si].name);
+ commandBuffer += " ";
+ commandBuffer += objectTable[si].name;
+
isDrawCommandEnabled = 1;
@@ -1782,8 +1833,8 @@ uint16 executePlayerInput(void) {
playerCommand = -1;
commandVar1 = 0;
- strcpy(commandBuffer, "");
- renderer->setCommand("");
+ commandBuffer = "";
+ renderer->setCommand(commandBuffer);
}
} else {
globalVars[VAR_MOUSE_X_POS] = mouseX;
@@ -1804,13 +1855,7 @@ uint16 executePlayerInput(void) {
if (commandVar2 != objIdx) {
if (objIdx != -1) {
- char command[256];
-
- strcpy(command, commandBuffer);
- strcat(command, " ");
- strcat(command, objectTable[objIdx].name);
-
- renderer->setCommand(command);
+ renderer->setCommand(commandBuffer + " " + objectTable[objIdx].name);
} else {
isDrawCommandEnabled = 1;
}
@@ -1986,6 +2031,14 @@ uint16 executePlayerInput(void) {
}
}
+ // Update Operation Stealth specific global variables.
+ // This fixes swimming at the bottom of the ocean after
+ // having been thrown into it with the girl.
+ if (g_cine->getGameType() == Cine::GType_OS) {
+ globalVars[251] = globalVars[VAR_MOUSE_X_POS];
+ globalVars[252] = globalVars[VAR_MOUSE_Y_POS];
+ }
+
return var_5E;
}
diff --git a/engines/cine/various.h b/engines/cine/various.h
index 926a1821d9..b841908c65 100644
--- a/engines/cine/various.h
+++ b/engines/cine/various.h
@@ -33,6 +33,9 @@
namespace Cine {
+// Maximum size of the command buffer including the trailing zero
+#define kMaxCommandBufferSize 80
+
void initLanguage(Common::Language lang);
int16 makeMenuChoice(const CommandeType commandList[], uint16 height, uint16 X, uint16 Y, uint16 width, bool recheckValue = false);
@@ -85,7 +88,7 @@ extern byte _danKeysPressed;
extern int16 playerCommand;
-extern char commandBuffer[80];
+extern Common::String commandBuffer;
extern char currentPrcName[20];
extern char currentRelName[20];
diff --git a/engines/gob/mult_v2.cpp b/engines/gob/mult_v2.cpp
index 20a81174e5..6bd4ddb625 100644
--- a/engines/gob/mult_v2.cpp
+++ b/engines/gob/mult_v2.cpp
@@ -510,10 +510,11 @@ void Mult_v2::playMultInit() {
if (!_animSurf) {
int16 width, height;
- for (int i = 0; i < _objCount; i++) {
- delete _objects[i].pPosX;
- delete _objects[i].pPosY;
- }
+ if (_objects)
+ for (int i = 0; i < _objCount; i++) {
+ delete _objects[i].pPosX;
+ delete _objects[i].pPosY;
+ }
delete[] _objects;
diff --git a/engines/kyra/detection.cpp b/engines/kyra/detection.cpp
index 78b0863ac5..f5b3f582f4 100644
--- a/engines/kyra/detection.cpp
+++ b/engines/kyra/detection.cpp
@@ -67,11 +67,14 @@ namespace {
#define KYRA3_CD_FAN_FLAGS(x, y) FLAGS_FAN(x, y, false, false, true, false, true, false, Kyra::GI_KYRA3)
#define LOL_CD_FLAGS FLAGS(false, false, true, false, false, false, Kyra::GI_LOL)
+#define LOL_FLOPPY_FLAGS FLAGS(false, false, false, false, false, false, Kyra::GI_LOL)
+#define LOL_FLOPPY_CMP_FLAGS FLAGS(false, false, false, false, false, true, Kyra::GI_LOL)
#define LOL_PC98_FLAGS FLAGS(false, false, false, false, false, false, Kyra::GI_LOL)
#define LOL_PC98_SJIS_FLAGS FLAGS(false, false, false, true, false, false, Kyra::GI_LOL)
#define LOL_DEMO_FLAGS FLAGS(true, false, false, false, false, false, Kyra::GI_KYRA2)
const KYRAGameDescription adGameDescs[] = {
+ /* disable these targets until they get supported
{
{
"kyra1",
@@ -83,6 +86,7 @@ const KYRAGameDescription adGameDescs[] = {
},
KYRA1_FLOPPY_CMP_FLAGS
},
+
{
{
"kyra1",
@@ -94,6 +98,8 @@ const KYRAGameDescription adGameDescs[] = {
},
KYRA1_FLOPPY_CMP_FLAGS
},
+ */
+
{
{
"kyra1",
@@ -460,6 +466,42 @@ const KYRAGameDescription adGameDescs[] = {
KYRA2_CD_FAN_FLAGS(Common::IT_ITA, Common::EN_ANY)
},
+ {
+ {
+ "kyra2",
+ "CD",
+ AD_ENTRY1("FATE.PAK", "39772ff82e42c4c520050518deb82e64"),
+ Common::IT_ITA,
+ Common::kPlatformPC,
+ Common::ADGF_DROPLANGUAGE | Common::ADGF_CD
+ },
+ KYRA2_CD_FAN_FLAGS(Common::IT_ITA, Common::EN_ANY)
+ },
+
+ {
+ {
+ "kyra2",
+ "CD",
+ AD_ENTRY1("FATE.PAK", "39772ff82e42c4c520050518deb82e64"),
+ Common::DE_DEU,
+ Common::kPlatformPC,
+ Common::ADGF_DROPLANGUAGE | Common::ADGF_CD
+ },
+ KYRA2_CD_FAN_FLAGS(Common::IT_ITA, Common::EN_ANY)
+ },
+
+ {
+ {
+ "kyra2",
+ "CD",
+ AD_ENTRY1("FATE.PAK", "39772ff82e42c4c520050518deb82e64"),
+ Common::FR_FRA,
+ Common::kPlatformPC,
+ Common::ADGF_DROPLANGUAGE | Common::ADGF_CD
+ },
+ KYRA2_CD_FAN_FLAGS(Common::IT_ITA, Common::EN_ANY)
+ },
+
{ // Interactive Demo
{
"kyra2",
@@ -649,6 +691,53 @@ const KYRAGameDescription adGameDescs[] = {
KYRA3_CD_INS_FLAGS
},
+ // Mac version
+ {
+ {
+ "kyra3",
+ 0,
+ {
+ { "ONETIME.PAK", 0, "3833ff312757b8e6147f464cca0a6587", -1 },
+ { "AUD.PAK", 0, 0, -1 },
+ { 0, 0, 0, 0 }
+ },
+ Common::EN_ANY,
+ Common::kPlatformMacintosh,
+ Common::ADGF_DROPLANGUAGE
+ },
+ KYRA3_CD_INS_FLAGS
+ },
+ {
+ {
+ "kyra3",
+ 0,
+ {
+ { "ONETIME.PAK", 0, "3833ff312757b8e6147f464cca0a6587", -1 },
+ { "AUD.PAK", 0, 0, -1 },
+ { 0, 0, 0, 0 }
+ },
+ Common::DE_DEU,
+ Common::kPlatformMacintosh,
+ Common::ADGF_DROPLANGUAGE
+ },
+ KYRA3_CD_INS_FLAGS
+ },
+ {
+ {
+ "kyra3",
+ 0,
+ {
+ { "ONETIME.PAK", 0, "3833ff312757b8e6147f464cca0a6587", -1 },
+ { "AUD.PAK", 0, 0, -1 },
+ { 0, 0, 0, 0 }
+ },
+ Common::FR_FRA,
+ Common::kPlatformMacintosh,
+ Common::ADGF_DROPLANGUAGE
+ },
+ KYRA3_CD_INS_FLAGS
+ },
+
// Spanish fan translation, see fr#1994040 "KYRA3: Add support for Spanish fan translation"
{
{
@@ -696,7 +785,7 @@ const KYRAGameDescription adGameDescs[] = {
KYRA3_CD_FAN_FLAGS(Common::ES_ESP, Common::EN_ANY)
},
- // Itlian fan translation, see fr#2003504 "KYRA: add support for Italian version of Kyrandia 2&3"
+ // Italian fan translation, see fr#2003504 "KYRA: add support for Italian version of Kyrandia 2&3"
{
{
"kyra3",
@@ -839,8 +928,40 @@ const KYRAGameDescription adGameDescs[] = {
},
LOL_CD_FLAGS
},
-
- /*{
+
+ {
+ {
+ "lol",
+ 0,
+ {
+ { "WESTWOOD.1", 0, "3c61cb7de5b2ec452f5851f5075207ee", -1 },
+ { 0, 0, 0, 0 }
+ },
+ Common::DE_DEU,
+ Common::kPlatformPC,
+ Common::ADGF_NO_FLAGS
+ },
+ LOL_FLOPPY_CMP_FLAGS
+ },
+
+ {
+ {
+ "lol",
+ "Extracted",
+ {
+ { "GENERAL.PAK", 0, "996e66e81054d36249907a1d8158da3d", -1 },
+ { "CHAPTER7.PAK", 0, "cabee57f00d6d84b65a732b6868a4959", -1 },
+ { 0, 0, 0, 0 }
+ },
+ Common::DE_DEU,
+ Common::kPlatformPC,
+ Common::ADGF_NO_FLAGS
+ },
+ LOL_FLOPPY_FLAGS
+ },
+
+ /* disable these targets until they get supported
+ {
{
"lol",
0,
diff --git a/engines/kyra/lol.cpp b/engines/kyra/lol.cpp
index 2011f65b3e..b9cb7bcc0b 100644
--- a/engines/kyra/lol.cpp
+++ b/engines/kyra/lol.cpp
@@ -255,11 +255,14 @@ void LoLEngine::setupPrologueData(bool load) {
"xxx/intro9.pak"
};
- char filename[32];
+ char filepath[32];
+ char *filename = filepath;
for (uint i = 0; i < ARRAYSIZE(fileList); ++i) {
strcpy(filename, fileList[i]);
memcpy(filename, _languageExt[_lang], 3);
-
+ if (!_flags.isTalkie)
+ filename += 4;
+
if (load) {
if (!_res->loadPakFile(filename))
error("Couldn't load file: '%s'", filename);
diff --git a/engines/kyra/resource.cpp b/engines/kyra/resource.cpp
index 91150ad354..5da6bb3873 100644
--- a/engines/kyra/resource.cpp
+++ b/engines/kyra/resource.cpp
@@ -103,6 +103,9 @@ bool Resource::reset() {
return true;
} else if (_vm->game() == GI_LOL) {
+ if (_vm->gameFlags().useInstallerPackage)
+ tryLoadCompFiles();
+
return true;
}
@@ -181,8 +184,14 @@ bool Resource::loadPakFile(const Common::String &filename) {
for (ResArchiveLoader::FileList::iterator i = files.begin(); i != files.end(); ++i) {
iter = _map.find(i->filename);
if (iter == _map.end()) {
+ // We do an internal check for a file in gamepath with same filename to
+ // allow overwriting files inside archives with plain files inside the
+ // game directory
+ checkFile(i->filename);
+
// A new file entry, so we just insert it into the file map.
- _map[i->filename] = i->entry;
+ if (_map.find(i->filename) == _map.end())
+ _map[i->filename] = i->entry;
} else if (!iter->_value.parent.empty()) {
if (!iter->_value.parent.equalsIgnoreCase(filename)) {
ResFileMap::iterator oldParent = _map.find(iter->_value.parent);
@@ -350,7 +359,17 @@ bool Resource::loadFileToBuf(const char *file, void *buf, uint32 maxSize) {
Common::SeekableReadStream *Resource::getFileStream(const Common::String &file) {
CompFileMap::iterator compEntry;
- if (Common::File::exists(file)) {
+ if ((compEntry = _compFiles.find(file)) != _compFiles.end())
+ return new Common::MemoryReadStream(compEntry->_value.data, compEntry->_value.size, false);
+
+ if (!isAccessable(file))
+ return 0;
+
+ ResFileMap::const_iterator iter = _map.find(file);
+ if (iter == _map.end())
+ return 0;
+
+ if (iter->_value.parent.empty()) {
Common::File *stream = new Common::File();
if (!stream->open(file)) {
delete stream;
@@ -358,28 +377,15 @@ Common::SeekableReadStream *Resource::getFileStream(const Common::String &file)
error("Couldn't open file '%s'", file.c_str());
}
return stream;
- } else if ((compEntry = _compFiles.find(file)) != _compFiles.end()) {
- return new Common::MemoryReadStream(compEntry->_value.data, compEntry->_value.size, false);
} else {
- if (!isAccessable(file))
- return 0;
-
- ResFileMap::const_iterator iter = _map.find(file);
- if (iter == _map.end())
- return 0;
+ Common::SeekableReadStream *parent = getFileStream(iter->_value.parent);
+ assert(parent);
- if (!iter->_value.parent.empty()) {
- Common::SeekableReadStream *parent = getFileStream(iter->_value.parent);
- assert(parent);
-
- ResFileMap::const_iterator parentIter = _map.find(iter->_value.parent);
- const ResArchiveLoader *loader = getLoader(parentIter->_value.type);
- assert(loader);
+ ResFileMap::const_iterator parentIter = _map.find(iter->_value.parent);
+ const ResArchiveLoader *loader = getLoader(parentIter->_value.type);
+ assert(loader);
- return loader->loadFileFromArchive(file, parent, iter->_value);
- } else {
- error("Couldn't open file '%s'", file.c_str());
- }
+ return loader->loadFileFromArchive(file, parent, iter->_value);
}
return 0;
@@ -411,7 +417,19 @@ void Resource::checkFile(const Common::String &file) {
if (_map.find(file) == _map.end()) {
CompFileMap::const_iterator iter;
- if (Common::File::exists(file)) {
+ if ((iter = _compFiles.find(file)) != _compFiles.end()) {
+ ResFileEntry entry;
+ entry.parent = "";
+ entry.size = iter->_value.size;
+ entry.mounted = false;
+ entry.preload = false;
+ entry.prot = false;
+ entry.type = ResFileEntry::kAutoDetect;
+ entry.offset = 0;
+ _map[file] = entry;
+
+ detectFileTypes();
+ } else if (Common::File::exists(file)) {
Common::File temp;
if (temp.open(file)) {
ResFileEntry entry;
@@ -427,18 +445,6 @@ void Resource::checkFile(const Common::String &file) {
detectFileTypes();
}
- } else if ((iter = _compFiles.find(file)) != _compFiles.end()) {
- ResFileEntry entry;
- entry.parent = "";
- entry.size = iter->_value.size;
- entry.mounted = false;
- entry.preload = false;
- entry.prot = false;
- entry.type = ResFileEntry::kAutoDetect;
- entry.offset = 0;
- _map[file] = entry;
-
- detectFileTypes();
}
}
}
@@ -1257,10 +1263,17 @@ uint8 FileExpander::calcCmdAndIndex(const uint8 *tbl, int16 &para) {
class CompLoaderInsHof : public CompArchiveLoader {
public:
- bool checkForFiles() const;
- bool loadFile(CompFileMap &loadTo) const;
+ CompLoaderInsHof() {
+ _fileExtP = "%03d";
+ _checkFile1 = "WESTWOOD.001";
+ _checkFile2 = "WESTWOOD.002";
+ _containerOffset = 6;
+ }
-private:
+ virtual bool checkForFiles() const;
+ virtual bool loadFile(CompFileMap &loadTo) const;
+
+protected:
struct Archive {
Common::String filename;
uint32 firstFile;
@@ -1269,10 +1282,25 @@ private:
uint32 endOffset;
uint32 totalSize;
};
+
+ const char *_fileExtP;
+ const char *_checkFile1;
+ const char *_checkFile2;
+ uint8 _containerOffset;
+};
+
+class CompLoaderInsLol : public CompLoaderInsHof {
+public:
+ CompLoaderInsLol() {
+ _fileExtP = "%d";
+ _checkFile1 = "WESTWOOD.1";
+ _checkFile2 = "WESTWOOD.2";
+ _containerOffset = 0;
+ }
};
bool CompLoaderInsHof::checkForFiles() const {
- return (Common::File::exists("WESTWOOD.001") && Common::File::exists("WESTWOOD.002"));
+ return (Common::File::exists(_checkFile1) && Common::File::exists(_checkFile2));
}
bool CompLoaderInsHof::loadFile(CompFileMap &loadTo) const {
@@ -1294,7 +1322,7 @@ bool CompLoaderInsHof::loadFile(CompFileMap &loadTo) const {
Common::List<Archive> archives;
for (int8 currentFile = 1; currentFile; currentFile++) {
- sprintf(filenameExt, "%03d", currentFile);
+ sprintf(filenameExt, _fileExtP, currentFile);
filenameTemp = filenameBase + Common::String(filenameExt);
if (!tmpFile.open(filenameTemp)) {
@@ -1310,9 +1338,9 @@ bool CompLoaderInsHof::loadFile(CompFileMap &loadTo) const {
if (startFile) {
size -= 4;
if (fileId == currentFile) {
- size -= 6;
- pos += 6;
- tmpFile.seek(6, SEEK_CUR);
+ size -= _containerOffset;
+ pos += _containerOffset;
+ tmpFile.seek(_containerOffset, SEEK_CUR);
} else {
size = size + 1 - pos;
}
@@ -1356,6 +1384,7 @@ bool CompLoaderInsHof::loadFile(CompFileMap &loadTo) const {
uint8 *outbuffer = 0;
uint32 inPart1 = 0;
uint32 inPart2 = 0;
+ uint8 compressionType = 0;
Common::String entryStr;
pos = 0;
@@ -1367,7 +1396,7 @@ bool CompLoaderInsHof::loadFile(CompFileMap &loadTo) const {
for (Common::List<Archive>::iterator a = archives.begin(); a != archives.end(); ++a) {
startFile = true;
for (uint32 i = a->firstFile; i != (a->lastFile + 1); i++) {
- sprintf(filenameExt, "%03d", i);
+ sprintf(filenameExt, _fileExtP, i);
filenameTemp = a->filename + Common::String(filenameExt);
if (!tmpFile.open(filenameTemp)) {
@@ -1390,7 +1419,12 @@ bool CompLoaderInsHof::loadFile(CompFileMap &loadTo) const {
tmpFile.seek(1);
tmpFile.read(inbuffer + inPart1, inPart2);
inPart2 = 0;
- exp.process(outbuffer, inbuffer, outsize, insize);
+
+ if (compressionType > 0)
+ exp.process(outbuffer, inbuffer, outsize, insize);
+ else
+ memcpy(outbuffer, inbuffer, outsize);
+
delete[] inbuffer;
inbuffer = 0;
newEntry.data = outbuffer;
@@ -1419,7 +1453,7 @@ bool CompLoaderInsHof::loadFile(CompFileMap &loadTo) const {
}
}
- sprintf(filenameExt, "%03d", i + 1);
+ sprintf(filenameExt, _fileExtP, i + 1);
filenameTemp = a->filename + Common::String(filenameExt);
Common::File tmpFile2;
@@ -1435,8 +1469,7 @@ bool CompLoaderInsHof::loadFile(CompFileMap &loadTo) const {
uint32 id = READ_LE_UINT32(hdr);
if (id == 0x04034B50) {
- if (hdr[8] != 8)
- error("compression type not implemented");
+ compressionType = hdr[8];
insize = READ_LE_UINT32(hdr + 18);
outsize = READ_LE_UINT32(hdr + 22);
@@ -1464,7 +1497,12 @@ bool CompLoaderInsHof::loadFile(CompFileMap &loadTo) const {
} else {
tmpFile.read(inbuffer, insize);
inPart2 = 0;
- exp.process(outbuffer, inbuffer, outsize, insize);
+
+ if (compressionType > 0)
+ exp.process(outbuffer, inbuffer, outsize, insize);
+ else
+ memcpy(outbuffer, inbuffer, outsize);
+
delete[] inbuffer;
inbuffer = 0;
newEntry.data = outbuffer;
@@ -1498,6 +1536,7 @@ void Resource::initializeLoaders() {
_loaders.push_back(LoaderList::value_type(new ResLoaderTlk()));
_compLoaders.push_back(CompLoaderList::value_type(new CompLoaderInsHof()));
+ _compLoaders.push_back(CompLoaderList::value_type(new CompLoaderInsLol()));
}
const ResArchiveLoader *Resource::getLoader(ResFileEntry::kType type) const {
diff --git a/engines/parallaction/balloons.cpp b/engines/parallaction/balloons.cpp
index bbd8bc9ca7..222954ec3a 100644
--- a/engines/parallaction/balloons.cpp
+++ b/engines/parallaction/balloons.cpp
@@ -30,6 +30,183 @@
namespace Parallaction {
+class WrappedLineFormatter {
+
+protected:
+ Common::String _line;
+ Font *_font;
+ uint16 _lines, _lineWidth;
+
+ virtual void setup() = 0;
+ virtual void action() = 0;
+ virtual void end() = 0;
+ virtual Common::String expand(const Common::String &token) { return token; }
+
+ void textAccum(const Common::String &token, uint16 width) {
+ if (token.empty()) {
+ return;
+ }
+
+ _lineWidth += width;
+ _line += token;
+ }
+
+ void textNewLine() {
+ _lines++;
+ _lineWidth = 0;
+ _line.clear();
+ }
+
+public:
+ WrappedLineFormatter(Font *font) : _font(font) { }
+ virtual ~WrappedLineFormatter() { }
+
+ virtual void calc(const char *text, uint16 maxwidth) {
+ setup();
+
+ _lineWidth = 0;
+ _line.clear();
+ _lines = 0;
+
+ Common::StringTokenizer tokenizer(text, " ");
+ Common::String token;
+ Common::String blank(" ");
+
+ uint16 blankWidth = _font->getStringWidth(" ");
+ uint16 tokenWidth = 0;
+
+ while (!tokenizer.empty()) {
+ token = tokenizer.nextToken();
+ token = expand(token);
+
+ if (token == '/') {
+ tokenWidth = 0;
+ action();
+ textNewLine();
+ } else {
+ // todo: expand '%'
+ tokenWidth = _font->getStringWidth(token.c_str());
+
+ if (_lineWidth == 0) {
+ textAccum(token, tokenWidth);
+ } else {
+ if (_lineWidth + blankWidth + tokenWidth <= maxwidth) {
+ textAccum(blank, blankWidth);
+ textAccum(token, tokenWidth);
+ } else {
+ action();
+ textNewLine();
+ textAccum(token, tokenWidth);
+ }
+ }
+ }
+ }
+
+ end();
+ }
+};
+
+class StringExtent_NS : public WrappedLineFormatter {
+
+ uint _width, _height;
+
+protected:
+ virtual Common::String expand(const Common::String &token) {
+ if (token.compareToIgnoreCase("%p") == 0) {
+ return Common::String("/");
+ }
+
+ return token;
+ }
+
+ virtual void setup() {
+ _width = _height = 0;
+
+ _line.clear();
+ _lines = 0;
+ _width = 0;
+ }
+
+ virtual void action() {
+ if (_lineWidth > _width) {
+ _width = _lineWidth;
+ }
+ _height = _lines * _font->height();
+ }
+
+ virtual void end() {
+ action();
+ }
+
+public:
+ StringExtent_NS(Font *font) : WrappedLineFormatter(font) { }
+
+ uint width() const { return _width; }
+ uint height() const { return _height; }
+};
+
+
+class StringWriter_NS : public WrappedLineFormatter {
+
+ uint _width, _height;
+ byte _color;
+
+ Graphics::Surface *_surf;
+
+protected:
+ virtual Common::String expand(const Common::String& token) {
+ if (token.compareToIgnoreCase("%p") == 0) {
+ Common::String t(".......");
+ for (int i = 0; _password[i]; i++) {
+ t.setChar(_password[i], i);
+ }
+ return Common::String("> ") + t;
+ } else
+ if (token.compareToIgnoreCase("%s") == 0) {
+ char buf[20];
+ sprintf(buf, "%i", _score);
+ return Common::String(buf);
+ }
+
+ return token;
+ }
+
+ virtual void setup() {
+ }
+
+ virtual void action() {
+ if (_line.empty()) {
+ return;
+ }
+ uint16 rx = 10;
+ uint16 ry = 4 + _lines * _font->height(); // y
+
+ byte *dst = (byte*)_surf->getBasePtr(rx, ry);
+ _font->setColor(_color);
+ _font->drawString(dst, _surf->w, _line.c_str());
+ }
+
+ virtual void end() {
+ action();
+ }
+
+public:
+ StringWriter_NS(Font *font) : WrappedLineFormatter(font) { }
+
+ void write(const char *text, uint maxWidth, byte color, Graphics::Surface *surf) {
+ StringExtent_NS se(_font);
+ se.calc(text, maxWidth);
+ _width = se.width() + 10;
+ _height = se.height() + 20;
+ _color = color;
+ _surf = surf;
+
+ calc(text, maxWidth);
+ }
+
+};
+
+
#define BALLOON_TRANSPARENT_COLOR_NS 2
#define BALLOON_TRANSPARENT_COLOR_BR 0
@@ -78,8 +255,6 @@ class BalloonManager_ns : public BalloonManager {
uint _numBalloons;
- void getStringExtent(Font *font, char *text, uint16 maxwidth, int16* width, int16* height);
- void drawWrappedText(Font *font, Graphics::Surface* surf, char *text, byte color, int16 wrapwidth);
int createBalloon(int16 w, int16 h, int16 winding, uint16 borderThickness);
Balloon *getBalloon(uint id);
@@ -152,12 +327,16 @@ int BalloonManager_ns::setSingleBalloon(char *text, uint16 x, uint16 y, uint16 w
int16 w, h;
- getStringExtent(_vm->_dialogueFont, text, MAX_BALLOON_WIDTH, &w, &h);
+ StringExtent_NS se(_vm->_dialogueFont);
+ se.calc(text, MAX_BALLOON_WIDTH);
+ w = se.width() + 14;
+ h = se.height() + 20;
int id = createBalloon(w+5, h, winding, 1);
Balloon *balloon = &_intBalloons[id];
- drawWrappedText(_vm->_dialogueFont, balloon->surface, text, textColor, MAX_BALLOON_WIDTH);
+ StringWriter_NS sw(_vm->_dialogueFont);
+ sw.write(text, MAX_BALLOON_WIDTH, textColor, balloon->surface);
// TODO: extract some text to make a name for obj
balloon->obj = _gfx->registerBalloon(new SurfaceToFrames(balloon->surface), 0);
@@ -172,12 +351,17 @@ int BalloonManager_ns::setDialogueBalloon(char *text, uint16 winding, byte textC
int16 w, h;
- getStringExtent(_vm->_dialogueFont, text, MAX_BALLOON_WIDTH, &w, &h);
+ StringExtent_NS se(_vm->_dialogueFont);
+ se.calc(text, MAX_BALLOON_WIDTH);
+ w = se.width() + 14;
+ h = se.height() + 20;
+
int id = createBalloon(w+5, h, winding, 1);
Balloon *balloon = &_intBalloons[id];
- drawWrappedText(_vm->_dialogueFont, balloon->surface, text, textColor, MAX_BALLOON_WIDTH);
+ StringWriter_NS sw(_vm->_dialogueFont);
+ sw.write(text, MAX_BALLOON_WIDTH, textColor, balloon->surface);
// TODO: extract some text to make a name for obj
balloon->obj = _gfx->registerBalloon(new SurfaceToFrames(balloon->surface), 0);
@@ -196,7 +380,9 @@ int BalloonManager_ns::setDialogueBalloon(char *text, uint16 winding, byte textC
void BalloonManager_ns::setBalloonText(uint id, char *text, byte textColor) {
Balloon *balloon = getBalloon(id);
balloon->surface->fillRect(balloon->innerBox, 1);
- drawWrappedText(_vm->_dialogueFont, balloon->surface, text, textColor, MAX_BALLOON_WIDTH);
+
+ StringWriter_NS sw(_vm->_dialogueFont);
+ sw.write(text, MAX_BALLOON_WIDTH, textColor, balloon->surface);
}
@@ -204,11 +390,15 @@ int BalloonManager_ns::setLocationBalloon(char *text, bool endGame) {
int16 w, h;
- getStringExtent(_vm->_dialogueFont, text, MAX_BALLOON_WIDTH, &w, &h);
+ StringExtent_NS se(_vm->_dialogueFont);
+ se.calc(text, MAX_BALLOON_WIDTH);
+ w = se.width() + 14;
+ h = se.height() + 20;
int id = createBalloon(w+(endGame ? 5 : 10), h+5, -1, BALLOON_TRANSPARENT_COLOR_NS);
Balloon *balloon = &_intBalloons[id];
- drawWrappedText(_vm->_dialogueFont, balloon->surface, text, 0, MAX_BALLOON_WIDTH);
+ StringWriter_NS sw(_vm->_dialogueFont);
+ sw.write(text, MAX_BALLOON_WIDTH, 0, balloon->surface);
// TODO: extract some text to make a name for obj
balloon->obj = _gfx->registerBalloon(new SurfaceToFrames(balloon->surface), 0);
@@ -245,110 +435,99 @@ void BalloonManager_ns::freeBalloons() {
_numBalloons = 0;
}
-// TODO: get rid of parseNextToken from here. Use the
-// StringTokenizer instead.
-void BalloonManager_ns::drawWrappedText(Font *font, Graphics::Surface* surf, char *text, byte color, int16 wrapwidth) {
- uint16 lines = 0;
- uint16 linewidth = 0;
- uint16 rx = 10;
- uint16 ry = 4;
- uint16 blankWidth = font->getStringWidth(" ");
- uint16 tokenWidth = 0;
- char token[MAX_TOKEN_LEN];
- if (wrapwidth == -1)
- wrapwidth = _vm->_screenWidth;
- while (strlen(text) > 0) {
- text = parseNextToken(text, token, MAX_TOKEN_LEN, " ", true);
- if (!scumm_stricmp(token, "%p")) {
- lines++;
- rx = 10;
- ry = 4 + lines*10; // y
- strcpy(token, "> .......");
- strncpy(token+2, _password, strlen(_password));
- tokenWidth = font->getStringWidth(token);
- } else {
- tokenWidth = font->getStringWidth(token);
- linewidth += tokenWidth;
-
- if (linewidth > wrapwidth) {
- // wrap line
- lines++;
- rx = 10; // x
- ry = 4 + lines*10; // y
- linewidth = tokenWidth;
- }
+class StringExtent_BR : public WrappedLineFormatter {
- if (!scumm_stricmp(token, "%s")) {
- sprintf(token, "%d", _score);
- }
+ uint _width, _height;
- }
+protected:
+ virtual void setup() {
+ _width = _height = 0;
- _gfx->drawText(font, surf, rx, ry, token, color);
+ _line.clear();
+ _lines = 0;
+ _width = 0;
+ }
- rx += tokenWidth + blankWidth;
- linewidth += blankWidth;
+ virtual void action() {
+ if (_lineWidth > _width) {
+ _width = _lineWidth;
+ }
+ _height = _lines * _font->height();
+ }
- text = Common::ltrim(text);
+ virtual void end() {
+ action();
}
-}
+public:
+ StringExtent_BR(Font *font) : WrappedLineFormatter(font) { }
-// TODO: get rid of parseNextToken from here. Use the
-// StringTokenizer instead.
-void BalloonManager_ns::getStringExtent(Font *font, char *text, uint16 maxwidth, int16* width, int16* height) {
+ uint width() const { return _width; }
+ uint height() const { return _height; }
+};
- uint16 lines = 0;
- uint16 w = 0;
- *width = 0;
- uint16 blankWidth = font->getStringWidth(" ");
- uint16 tokenWidth = 0;
+class StringWriter_BR : public WrappedLineFormatter {
- char token[MAX_TOKEN_LEN];
+ uint _width, _height;
+ byte _color;
+ uint _x, _y;
- while (strlen(text) != 0) {
+ Graphics::Surface *_surf;
- text = parseNextToken(text, token, MAX_TOKEN_LEN, " ", true);
- tokenWidth = font->getStringWidth(token);
+protected:
+ StringWriter_BR(Font *font, byte color) : WrappedLineFormatter(font) {
- w += tokenWidth;
+ }
- if (!scumm_stricmp(token, "%p")) {
- lines++;
- } else {
- if (w > maxwidth) {
- w -= tokenWidth;
- lines++;
- if (w > *width)
- *width = w;
+ virtual void setup() {
+ }
- w = tokenWidth;
- }
+ virtual void action() {
+ if (_line.empty()) {
+ return;
}
+ uint16 rx = _x + (_surf->w - _lineWidth) / 2;
+ uint16 ry = _y + _lines * _font->height(); // y
- w += blankWidth;
- text = Common::ltrim(text);
+ byte *dst = (byte*)_surf->getBasePtr(rx, ry);
+ _font->setColor(_color);
+ _font->drawString(dst, _surf->w, _line.c_str());
}
- if (*width < w) *width = w;
- *width += 10;
+ virtual void end() {
+ action();
+ }
- *height = lines * 10 + 20;
+public:
+ StringWriter_BR(Font *font) : WrappedLineFormatter(font) { }
- return;
-}
+ void write(const char *text, uint maxWidth, byte color, Graphics::Surface *surf) {
+ maxWidth = 216;
+
+ StringExtent_BR se(_font);
+ se.calc(text, maxWidth);
+ _width = se.width() + 10;
+ _height = se.height() + 12;
+ _color = color;
+ _surf = surf;
+ _x = 0;
+ _y = (_surf->h - _height) / 2;
+ calc(text, maxWidth);
+ }
+
+};
@@ -370,29 +549,12 @@ class BalloonManager_br : public BalloonManager {
Frames *_rightBalloon;
void cacheAnims();
- void getStringExtent(Font *font, const char *text, uint16 maxwidth, int16* width, int16* height);
void drawWrappedText(Font *font, Graphics::Surface* surf, char *text, byte color, int16 wrapwidth);
int createBalloon(int16 w, int16 h, int16 winding, uint16 borderThickness);
Balloon *getBalloon(uint id);
Graphics::Surface *expandBalloon(Frames *data, int frameNum);
- void textSetupRendering(const Common::String &text, Graphics::Surface *dest, Font *font, byte color);
- void textEmitCenteredLine();
- void textAccum(const Common::String &token, uint16 width);
- void textNewLine();
-
- Common::String _textLine;
- Graphics::Surface *_textSurf;
- Font *_textFont;
- uint16 _textX, _textY;
- byte _textColor;
- uint16 _textLines, _textWidth;
-
- void extentSetup(Font *font, int16 *width, int16 *height);
- void extentAction();
-
- int16 *_extentWidth, *_extentHeight;
-
+ StringWriter_BR _writer;
public:
BalloonManager_br(Disk *disk, Gfx *gfx);
@@ -451,7 +613,7 @@ int BalloonManager_br::setSingleBalloon(char *text, uint16 x, uint16 y, uint16 w
balloon->surface = expandBalloon(src, srcFrame);
src->getRect(srcFrame, balloon->box);
- drawWrappedText(_vm->_dialogueFont, balloon->surface, text, textColor, MAX_BALLOON_WIDTH);
+ _writer.write(text, MAX_BALLOON_WIDTH, textColor, balloon->surface);
// TODO: extract some text to make a name for obj
balloon->obj = _gfx->registerBalloon(new SurfaceToFrames(balloon->surface), 0);
@@ -487,7 +649,7 @@ int BalloonManager_br::setDialogueBalloon(char *text, uint16 winding, byte textC
balloon->surface = expandBalloon(src, srcFrame);
src->getRect(srcFrame, balloon->box);
- drawWrappedText(_vm->_dialogueFont, balloon->surface, text, textColor, MAX_BALLOON_WIDTH);
+ _writer.write(text, MAX_BALLOON_WIDTH, textColor, balloon->surface);
// TODO: extract some text to make a name for obj
balloon->obj = _gfx->registerBalloon(new SurfaceToFrames(balloon->surface), 0);
@@ -558,155 +720,9 @@ void BalloonManager_br::cacheAnims() {
}
-void BalloonManager_br::extentSetup(Font *font, int16 *width, int16 *height) {
- _extentWidth = width;
- _extentHeight = height;
-
- _textLine.clear();
- _textLines = 0;
- _textWidth = 0;
- _textFont = font;
-}
-
-void BalloonManager_br::extentAction() {
- if (_textWidth > *_extentWidth) {
- *_extentWidth = _textWidth;
- }
- *_extentHeight = _textLines * _textFont->height();
-}
-
-void BalloonManager_br::textSetupRendering(const Common::String &text, Graphics::Surface *dest, Font *font, byte color) {
- uint16 maxWidth = 216;
-
- int16 w, h;
- getStringExtent(font, text.c_str(), maxWidth, &w, &h);
-
- w += 10;
- h += 12;
-
- _textLine.clear();
- _textSurf = dest;
- _textFont = font;
- _textX = 0;
- _textY = (_textSurf->h - h) / 2;
- _textColor = color;
- _textLines = 0;
- _textWidth = 0;
-}
-
-void BalloonManager_br::textEmitCenteredLine() {
- if (_textLine.empty()) {
- return;
- }
- uint16 rx = _textX + (_textSurf->w - _textWidth) / 2;
- uint16 ry = _textY + _textLines * _textFont->height(); // y
- _gfx->drawText(_textFont, _textSurf, rx, ry, _textLine.c_str(), _textColor);
-}
-
-void BalloonManager_br::textAccum(const Common::String &token, uint16 width) {
- if (token.empty()) {
- return;
- }
-
- _textWidth += width;
- _textLine += token;
-}
-
-void BalloonManager_br::textNewLine() {
- _textLines++;
- _textWidth = 0;
- _textLine.clear();
-}
-
-
-// TODO: really, base this and getStringExtent on some kind of LineTokenizer, instead of
-// repeating the algorithm and changing a couple of lines.
-void BalloonManager_br::drawWrappedText(Font *font, Graphics::Surface* surf, char *text, byte color, int16 wrapWidth) {
- textSetupRendering(text, surf, font, color);
-
- wrapWidth = 216;
-
- Common::StringTokenizer tokenizer(text, " ");
- Common::String token;
- Common::String blank(" ");
-
- uint16 blankWidth = font->getStringWidth(" ");
- uint16 tokenWidth = 0;
-
- while (!tokenizer.empty()) {
- token = tokenizer.nextToken();
-
- if (token == '/') {
- tokenWidth = 0;
- textEmitCenteredLine();
- textNewLine();
- } else {
- // todo: expand '%'
- tokenWidth = font->getStringWidth(token.c_str());
-
- if (_textWidth == 0) {
- textAccum(token, tokenWidth);
- } else {
- if (_textWidth + blankWidth + tokenWidth <= wrapWidth) {
- textAccum(blank, blankWidth);
- textAccum(token, tokenWidth);
- } else {
- textEmitCenteredLine();
- textNewLine();
- textAccum(token, tokenWidth);
- }
- }
- }
- }
-
- textEmitCenteredLine();
-}
-
-
-
-void BalloonManager_br::getStringExtent(Font *font, const char *text, uint16 maxwidth, int16* width, int16* height) {
- extentSetup(font, width, height);
-
- Common::StringTokenizer tokenizer(text, " ");
- Common::String token;
- Common::String blank(" ");
-
- uint16 blankWidth = font->getStringWidth(" ");
- uint16 tokenWidth = 0;
-
- while (!tokenizer.empty()) {
- token = tokenizer.nextToken();
-
- if (token == '/') {
- tokenWidth = 0;
- extentAction();
- textNewLine();
- } else {
- // todo: expand '%'
- tokenWidth = font->getStringWidth(token.c_str());
-
- if (_textWidth == 0) {
- textAccum(token, tokenWidth);
- } else {
- if (_textWidth + blankWidth + tokenWidth <= maxwidth) {
- textAccum(blank, blankWidth);
- textAccum(token, tokenWidth);
- } else {
- extentAction();
- textNewLine();
- textAccum(token, tokenWidth);
- }
- }
- }
- }
-
- extentAction();
-}
-
-
-
-BalloonManager_br::BalloonManager_br(Disk *disk, Gfx *gfx) : _numBalloons(0), _disk(disk), _gfx(gfx), _leftBalloon(0), _rightBalloon(0) {
+BalloonManager_br::BalloonManager_br(Disk *disk, Gfx *gfx) : _numBalloons(0), _disk(disk), _gfx(gfx),
+ _leftBalloon(0), _rightBalloon(0), _writer(_vm->_dialogueFont) {
}
BalloonManager_br::~BalloonManager_br() {
diff --git a/engines/parallaction/callables_br.cpp b/engines/parallaction/callables_br.cpp
index 628ba0c1f1..a4aec8e93e 100644
--- a/engines/parallaction/callables_br.cpp
+++ b/engines/parallaction/callables_br.cpp
@@ -41,7 +41,7 @@ void Parallaction_br::_c_ferrcycle(void*) {
}
void Parallaction_br::_c_lipsinc(void*) {
- warning("Parallaction_br::_c_lipsinc() not yet implemented");
+ warning("Unexpected lipsinc routine call! Please notify the team!");
}
void Parallaction_br::_c_albcycle(void*) {
diff --git a/engines/parallaction/callables_ns.cpp b/engines/parallaction/callables_ns.cpp
index 761e11dc7d..0f89ca22d1 100644
--- a/engines/parallaction/callables_ns.cpp
+++ b/engines/parallaction/callables_ns.cpp
@@ -211,21 +211,17 @@ void Parallaction_ns::_c_moveSarc(void *parm) {
}
}
- _introSarcData1 = _introSarcData3 - _moveSarcZone1->_left;
- a->_z = _introSarcData3;
- a->_frame = _moveSarcZone1->_top - (_introSarcData1 / 20);
- _introSarcData3 = _moveSarcZone1->_left;
+ _introSarcData1 = _introSarcData3 - _moveSarcZone1->getX();
+ a->setZ(_introSarcData3);
+ a->setF(_moveSarcZone1->getY() - (_introSarcData1 / 20));
+ _introSarcData3 = _moveSarcZone1->getX();
if (_introSarcData1 > 0) {
- a->_left = _introSarcData1 / 2;
+ a->setX(_introSarcData1 / 2);
+ a->setY(2);
} else {
- a->_left = -_introSarcData1 / 2;
- }
-
- if (_introSarcData1 > 0) {
- a->_top = 2;
- } else {
- a->_top = -2;
+ a->setX(-_introSarcData1 / 2);
+ a->setY(-2);
}
return;
@@ -236,11 +232,11 @@ void Parallaction_ns::_c_moveSarc(void *parm) {
_moveSarcZone1->translate(_introSarcData1, -_introSarcData1 / 20);
_moveSarcZone0->translate(_introSarcData1, -_introSarcData1 / 20);
- if (_moveSarcZones[0]->_left == 35 &&
- _moveSarcZones[1]->_left == 68 &&
- _moveSarcZones[2]->_left == 101 &&
- _moveSarcZones[3]->_left == 134 &&
- _moveSarcZones[4]->_left == 167) {
+ if (_moveSarcZones[0]->getX() == 35 &&
+ _moveSarcZones[1]->getX() == 68 &&
+ _moveSarcZones[2]->getX() == 101 &&
+ _moveSarcZones[3]->getX() == 134 &&
+ _moveSarcZones[4]->getX() == 167) {
a = findAnimation("finito");
@@ -261,7 +257,7 @@ void Parallaction_ns::_c_contaFoglie(void *parm) {
if (num_foglie != 6)
return;
- _commandFlags |= 0x1000;
+ _globalFlags |= 0x1000;
return;
}
@@ -482,8 +478,8 @@ void Parallaction_ns::_c_sketch(void *parm) {
Graphics::drawLine(oldx, oldy, newx, newy, 0, zeroMask, &_gfx->_backgroundInfo);
- _rightHandAnim->_left = newx;
- _rightHandAnim->_top = newy - 20;
+ _rightHandAnim->setX(newx);
+ _rightHandAnim->setY(newy - 20);
index++;
@@ -496,10 +492,10 @@ void Parallaction_ns::_c_sketch(void *parm) {
void Parallaction_ns::_c_shade(void *parm) {
Common::Rect r(
- _rightHandAnim->_left - 36,
- _rightHandAnim->_top - 36,
- _rightHandAnim->_left,
- _rightHandAnim->_top
+ _rightHandAnim->getX() - 36,
+ _rightHandAnim->getY() - 36,
+ _rightHandAnim->getX(),
+ _rightHandAnim->getY()
);
uint16 _di = r.left/4 + r.top * _gfx->_backgroundInfo->mask.internalWidth;
diff --git a/engines/parallaction/debug.cpp b/engines/parallaction/debug.cpp
index f57976594e..0ff38913f7 100644
--- a/engines/parallaction/debug.cpp
+++ b/engines/parallaction/debug.cpp
@@ -101,14 +101,14 @@ bool Debugger::Cmd_Locations(int argc, const char **argv) {
bool Debugger::Cmd_GlobalFlags(int argc, const char **argv) {
- uint32 flags = _commandFlags;
+ uint32 flags = _globalFlags;
DebugPrintf("+------------------------------+---------+\n"
"| flag name | value |\n"
"+------------------------------+---------+\n");
- for (uint i = 0; i < _vm->_globalTable->count(); i++) {
+ for (uint i = 0; i < _vm->_globalFlagsNames->count(); i++) {
const char *value = ((flags & (1 << i)) == 0) ? "OFF" : "ON";
- DebugPrintf("|%-30s| %-6s|\n", _vm->_globalTable->item(i), value);
+ DebugPrintf("|%-30s| %-6s|\n", _vm->_globalFlagsNames->item(i), value);
}
DebugPrintf("+------------------------------+---------+\n");
@@ -157,7 +157,7 @@ bool Debugger::Cmd_Zones(int argc, const char **argv) {
"+--------------------+---+---+---+---+--------+--------+\n");
for ( ; b != e; b++) {
ZonePtr z = *b;
- DebugPrintf("|%-20s|%3i|%3i|%3i|%3i|%8x|%8x|\n", z->_name, z->_left, z->_top, z->_right, z->_bottom, z->_type, z->_flags );
+ DebugPrintf("|%-20s|%3i|%3i|%3i|%3i|%8x|%8x|\n", z->_name, z->getX(), z->getY(), z->getX() + z->width(), z->getY() + z->height(), z->_type, z->_flags );
}
DebugPrintf("+--------------------+---+---+---+---+--------+--------+\n");
@@ -175,7 +175,7 @@ bool Debugger::Cmd_Animations(int argc, const char **argv) {
"+--------------------+---+---+---+---+--------+--------+\n");
for ( ; b != e; b++) {
AnimationPtr a = *b;
- DebugPrintf("|%-20s|%3i|%3i|%3i|%3i|%8x|%8x|\n", a->_name, a->_left, a->_top, a->_z, a->_frame, a->_type, a->_flags );
+ DebugPrintf("|%-20s|%3i|%3i|%3i|%3i|%8x|%8x|\n", a->_name, a->getX(), a->getY(), a->getZ(), a->getF(), a->_type, a->_flags );
}
DebugPrintf("+--------------------+---+---+---+---+--------+--------+\n");
@@ -187,19 +187,19 @@ bool Debugger::Cmd_GfxObjects(int argc, const char **argv) {
const char *objType[] = { "DOOR", "GET", "ANIM" };
- DebugPrintf("+--------------------+-----+-----+-----+-----+--------+--------+\n"
- "| name | x | y | z | f | type | visi |\n"
- "+--------------------+-----+-----+-----+-----+--------+--------+\n");
+ DebugPrintf("+--------------------+-----+-----+-----+-------+-----+--------+--------+\n"
+ "| name | x | y | z | layer | f | type | visi |\n"
+ "+--------------------+-----+-----+-----+-------+-----+--------+--------+\n");
GfxObjList::iterator b = _vm->_gfx->_gfxobjList.begin();
GfxObjList::iterator e = _vm->_gfx->_gfxobjList.end();
for ( ; b != e; b++) {
GfxObj *obj = *b;
- DebugPrintf("|%-20s|%5i|%5i|%5i|%5i|%8s|%8x|\n", obj->getName(), obj->x, obj->y, obj->z, obj->frame, objType[obj->type], obj->isVisible() );
+ DebugPrintf("|%-20s|%5i|%5i|%5i|%7i|%5i|%8s|%8x|\n", obj->getName(), obj->x, obj->y, obj->z, obj->layer, obj->frame, objType[obj->type], obj->isVisible() );
}
- DebugPrintf("+--------------------+-----+-----+-----+-----+--------+--------+\n");
+ DebugPrintf("+--------------------+-----+-----+-----+-------+-----+--------+--------+\n");
return true;
}
diff --git a/engines/parallaction/dialogue.cpp b/engines/parallaction/dialogue.cpp
index 4f2343be64..c94db751e7 100644
--- a/engines/parallaction/dialogue.cpp
+++ b/engines/parallaction/dialogue.cpp
@@ -168,7 +168,7 @@ bool DialogueManager::displayAnswer(uint16 i) {
uint32 flags = _vm->getLocationFlags();
if (a->_yesFlags & kFlagsGlobal)
- flags = _commandFlags | kFlagsGlobal;
+ flags = _globalFlags | kFlagsGlobal;
// display suitable answers
if (((a->_yesFlags & flags) == a->_yesFlags) && ((a->_noFlags & ~flags) == a->_noFlags)) {
diff --git a/engines/parallaction/disk.h b/engines/parallaction/disk.h
index 341229a649..2923f239d4 100644
--- a/engines/parallaction/disk.h
+++ b/engines/parallaction/disk.h
@@ -69,6 +69,7 @@ public:
virtual Table* loadTable(const char* name) = 0;
virtual Common::SeekableReadStream* loadMusic(const char* name) = 0;
virtual Common::ReadStream* loadSound(const char* name) = 0;
+ virtual void loadMask(const char *name, MaskBuffer &buffer) { }
};
@@ -248,6 +249,7 @@ public:
Table* loadTable(const char* name);
Common::SeekableReadStream* loadMusic(const char* name);
Common::ReadStream* loadSound(const char* name);
+ void loadMask(const char *name, MaskBuffer &buffer);
};
class DosDemo_br : public DosDisk_br {
diff --git a/engines/parallaction/disk_br.cpp b/engines/parallaction/disk_br.cpp
index 11f67a2d58..f52567bea2 100644
--- a/engines/parallaction/disk_br.cpp
+++ b/engines/parallaction/disk_br.cpp
@@ -357,6 +357,29 @@ void DosDisk_br::loadSlide(BackgroundInfo& info, const char *name) {
return;
}
+void DosDisk_br::loadMask(const char *name, MaskBuffer &buffer) {
+ if (!name) {
+ return;
+ }
+
+ Common::String filepath;
+ FilesystemNode node;
+ Common::File stream;
+
+ filepath = Common::String(name) + ".msk";
+ node = _mskDir.getChild(filepath);
+ if (!node.exists()) {
+ errorFileNotFound(_mskDir, filepath);
+ }
+ stream.open(node);
+
+ // NOTE: info.width and info.height are only valid if the background graphics
+ // have already been loaded
+ buffer.bigEndian = false;
+ stream.read(buffer.data, buffer.size);
+ stream.close();
+}
+
void DosDisk_br::loadScenery(BackgroundInfo& info, const char *name, const char *mask, const char* path) {
debugC(5, kDebugDisk, "DosDisk_br::loadScenery");
diff --git a/engines/parallaction/exec.h b/engines/parallaction/exec.h
index 22e75744f1..4239857ec0 100644
--- a/engines/parallaction/exec.h
+++ b/engines/parallaction/exec.h
@@ -84,8 +84,6 @@ class CommandExec_ns : public CommandExec {
Parallaction_ns *_vm;
protected:
- void updateGetZone(ZonePtr z, bool visible);
-
DECLARE_UNQUALIFIED_COMMAND_OPCODE(invalid);
DECLARE_UNQUALIFIED_COMMAND_OPCODE(set);
DECLARE_UNQUALIFIED_COMMAND_OPCODE(clear);
diff --git a/engines/parallaction/exec_br.cpp b/engines/parallaction/exec_br.cpp
index 0b7400f0f7..fe7b1b2903 100644
--- a/engines/parallaction/exec_br.cpp
+++ b/engines/parallaction/exec_br.cpp
@@ -97,8 +97,9 @@ void Parallaction_br::setupSubtitles(char *s, char *s2, int y) {
} else {
_subtitle[1] = -1;
}
-
+#if 0 // disabled because no references to lip sync has been found in the scripts
_subtitleLipSync = 0;
+#endif
}
void Parallaction_br::clearSubtitles() {
@@ -122,48 +123,23 @@ DECLARE_COMMAND_OPCODE(location) {
DECLARE_COMMAND_OPCODE(open) {
warning("Parallaction_br::cmdOp_open command not yet implemented");
- _ctxt.cmd->u._zone->_flags &= ~kFlagsClosed;
- if (_ctxt.cmd->u._zone->u.door->gfxobj) {
- _vm->updateDoor(_ctxt.cmd->u._zone);
- }
+ _vm->updateDoor(_ctxt.cmd->u._zone, false);
}
DECLARE_COMMAND_OPCODE(close) {
warning("Parallaction_br::cmdOp_close not yet implemented");
- _ctxt.cmd->u._zone->_flags |= kFlagsClosed;
- if (_ctxt.cmd->u._zone->u.door->gfxobj) {
- _vm->updateDoor(_ctxt.cmd->u._zone);
- }
+ _vm->updateDoor(_ctxt.cmd->u._zone, true);
}
DECLARE_COMMAND_OPCODE(on) {
- CommandData *data = &_ctxt.cmd->u;
- ZonePtr z = data->_zone;
-
- if (z) {
- z->_flags |= kFlagsActive;
- z->_flags &= ~kFlagsRemove;
-
- if ((z->_type & 0xFFFF) & kZoneGet) {
- _vm->_gfx->showGfxObj(z->u.get->gfxobj, true);
- }
- }
+ _vm->showZone(_ctxt.cmd->u._zone, true);
}
DECLARE_COMMAND_OPCODE(off) {
- CommandData *data = &_ctxt.cmd->u;
- ZonePtr z = data->_zone;
-
- if (z) {
- z->_flags |= kFlagsRemove;
-
- if ((z->_type & 0xFFFF) & kZoneGet) {
- _vm->_gfx->showGfxObj(z->u.get->gfxobj, false);
- }
- }
+ _vm->showZone(_ctxt.cmd->u._zone, false);
}
@@ -335,42 +311,18 @@ DECLARE_COMMAND_OPCODE(offsave) {
DECLARE_INSTRUCTION_OPCODE(on) {
- InstructionPtr inst = *_ctxt.inst;
- ZonePtr z = inst->_z;
-
- if (z) {
- z->_flags |= kFlagsActive;
- z->_flags &= ~kFlagsRemove;
-
- if ((z->_type & 0xFFFF) & kZoneGet) {
- _vm->_gfx->showGfxObj(z->u.get->gfxobj, true);
- }
- }
+ _vm->showZone((*_ctxt.inst)->_z, true);
}
DECLARE_INSTRUCTION_OPCODE(off) {
- InstructionPtr inst = *_ctxt.inst;
- ZonePtr z = inst->_z;
-
- if (z) {
- z->_flags |= kFlagsRemove;
-
- if ((z->_type & 0xFFFF) & kZoneGet) {
- _vm->_gfx->showGfxObj(z->u.get->gfxobj, false);
- }
- }
+ _vm->showZone((*_ctxt.inst)->_z, false);
}
DECLARE_INSTRUCTION_OPCODE(set) {
InstructionPtr inst = *_ctxt.inst;
-
- int16 rvalue = inst->_opB.getRValue();
- int16* lvalue = inst->_opA.getLValue();
-
- *lvalue = rvalue;
-
+ inst->_opA.setValue(inst->_opB.getValue());
}
@@ -378,7 +330,7 @@ DECLARE_INSTRUCTION_OPCODE(set) {
DECLARE_INSTRUCTION_OPCODE(inc) {
InstructionPtr inst = *_ctxt.inst;
- int16 rvalue = inst->_opB.getRValue();
+ int16 rvalue = inst->_opB.getValue();
if (inst->_flags & kInstMod) { // mod
int16 _bx = (rvalue > 0 ? rvalue : -rvalue);
@@ -387,32 +339,30 @@ DECLARE_INSTRUCTION_OPCODE(inc) {
rvalue = (rvalue > 0 ? 1 : -1);
}
- int16 *lvalue = inst->_opA.getLValue();
+ int16 lvalue = inst->_opA.getValue();
switch (inst->_index) {
case INST_INC:
- *lvalue += rvalue;
+ lvalue += rvalue;
break;
case INST_DEC:
- *lvalue -= rvalue;
+ lvalue -= rvalue;
break;
case INST_MUL:
- *lvalue *= rvalue;
+ lvalue *= rvalue;
break;
case INST_DIV:
- *lvalue /= rvalue;
+ lvalue /= rvalue;
break;
default:
error("This should never happen. Report immediately");
}
- if (inst->_opA._flags & kParaLocal) {
- inst->_opA._local->wrap();
- }
+ inst->_opA.setValue(lvalue);
}
@@ -445,11 +395,7 @@ DECLARE_INSTRUCTION_OPCODE(move) {
DECLARE_INSTRUCTION_OPCODE(color) {
InstructionPtr inst = *_ctxt.inst;
-
- int16 entry = inst->_opB.getRValue();
-
- _vm->_gfx->_palette.setEntry(entry, inst->_colors[0], inst->_colors[1], inst->_colors[2]);
-
+ _vm->_gfx->_palette.setEntry(inst->_opB.getValue(), inst->_colors[0], inst->_colors[1], inst->_colors[2]);
}
diff --git a/engines/parallaction/exec_ns.cpp b/engines/parallaction/exec_ns.cpp
index 2235c4e98e..30790a346f 100644
--- a/engines/parallaction/exec_ns.cpp
+++ b/engines/parallaction/exec_ns.cpp
@@ -80,7 +80,7 @@ DECLARE_INSTRUCTION_OPCODE(off) {
DECLARE_INSTRUCTION_OPCODE(loop) {
InstructionPtr inst = *_ctxt.inst;
- _ctxt.program->_loopCounter = inst->_opB.getRValue();
+ _ctxt.program->_loopCounter = inst->_opB.getValue();
_ctxt.program->_loopStart = _ctxt.ip;
}
@@ -93,7 +93,7 @@ DECLARE_INSTRUCTION_OPCODE(endloop) {
DECLARE_INSTRUCTION_OPCODE(inc) {
InstructionPtr inst = *_ctxt.inst;
- int16 _si = inst->_opB.getRValue();
+ int16 _si = inst->_opB.getValue();
if (inst->_flags & kInstMod) { // mod
int16 _bx = (_si > 0 ? _si : -_si);
@@ -102,29 +102,22 @@ DECLARE_INSTRUCTION_OPCODE(inc) {
_si = (_si > 0 ? 1 : -1);
}
- int16* lvalue = inst->_opA.getLValue();
+ int16 lvalue = inst->_opA.getValue();
if (inst->_index == INST_INC) {
- *lvalue += _si;
+ lvalue += _si;
} else {
- *lvalue -= _si;
+ lvalue -= _si;
}
- if (inst->_opA._flags & kParaLocal) {
- inst->_opA._local->wrap();
- }
+ inst->_opA.setValue(lvalue);
}
DECLARE_INSTRUCTION_OPCODE(set) {
InstructionPtr inst = *_ctxt.inst;
-
- int16 _si = inst->_opB.getRValue();
- int16 *lvalue = inst->_opA.getLValue();
-
- *lvalue = _si;
-
+ inst->_opA.setValue(inst->_opB.getValue());
}
@@ -133,10 +126,10 @@ DECLARE_INSTRUCTION_OPCODE(put) {
Graphics::Surface v18;
v18.w = inst->_a->width();
v18.h = inst->_a->height();
- v18.pixels = inst->_a->getFrameData(inst->_a->_frame);
+ v18.pixels = inst->_a->getFrameData(inst->_a->getF());
- int16 x = inst->_opA.getRValue();
- int16 y = inst->_opB.getRValue();
+ int16 x = inst->_opA.getValue();
+ int16 y = inst->_opB.getValue();
bool mask = (inst->_flags & kInstMaskedPut) == kInstMaskedPut;
_vm->_gfx->patchBackground(v18, x, y, mask);
@@ -176,8 +169,8 @@ DECLARE_INSTRUCTION_OPCODE(sound) {
DECLARE_INSTRUCTION_OPCODE(move) {
InstructionPtr inst = (*_ctxt.inst);
- int16 x = inst->_opA.getRValue();
- int16 y = inst->_opB.getRValue();
+ int16 x = inst->_opA.getValue();
+ int16 y = inst->_opB.getValue();
_vm->_char.scheduleWalk(x, y);
}
@@ -203,7 +196,7 @@ DECLARE_COMMAND_OPCODE(invalid) {
DECLARE_COMMAND_OPCODE(set) {
if (_ctxt.cmd->u._flags & kFlagsGlobal) {
_ctxt.cmd->u._flags &= ~kFlagsGlobal;
- _commandFlags |= _ctxt.cmd->u._flags;
+ _globalFlags |= _ctxt.cmd->u._flags;
} else {
_vm->setLocationFlags(_ctxt.cmd->u._flags);
}
@@ -213,7 +206,7 @@ DECLARE_COMMAND_OPCODE(set) {
DECLARE_COMMAND_OPCODE(clear) {
if (_ctxt.cmd->u._flags & kFlagsGlobal) {
_ctxt.cmd->u._flags &= ~kFlagsGlobal;
- _commandFlags &= ~_ctxt.cmd->u._flags;
+ _globalFlags &= ~_ctxt.cmd->u._flags;
} else {
_vm->clearLocationFlags(_ctxt.cmd->u._flags);
}
@@ -246,48 +239,47 @@ DECLARE_COMMAND_OPCODE(location) {
DECLARE_COMMAND_OPCODE(open) {
- _ctxt.cmd->u._zone->_flags &= ~kFlagsClosed;
- if (_ctxt.cmd->u._zone->u.door->gfxobj) {
- _vm->updateDoor(_ctxt.cmd->u._zone);
- }
+ _vm->updateDoor(_ctxt.cmd->u._zone, false);
}
DECLARE_COMMAND_OPCODE(close) {
- _ctxt.cmd->u._zone->_flags |= kFlagsClosed;
- if (_ctxt.cmd->u._zone->u.door->gfxobj) {
- _vm->updateDoor(_ctxt.cmd->u._zone);
- }
+ _vm->updateDoor(_ctxt.cmd->u._zone, true);
}
-void CommandExec_ns::updateGetZone(ZonePtr z, bool visible) {
+void Parallaction::showZone(ZonePtr z, bool visible) {
if (!z) {
return;
}
+ if (visible) {
+ z->_flags &= ~kFlagsRemove;
+ z->_flags |= kFlagsActive;
+ } else {
+ z->_flags |= kFlagsRemove;
+ }
+
if ((z->_type & 0xFFFF) == kZoneGet) {
- _vm->_gfx->showGfxObj(z->u.get->gfxobj, visible);
+ _gfx->showGfxObj(z->u.get->gfxobj, visible);
+
+ GetData *data = z->u.get;
+ if (data->hasMask && _gfx->_backgroundInfo->hasMask) {
+ if (visible) {
+ _gfx->_backgroundInfo->mask.bltOr(data->gfxobj->x, data->gfxobj->y, data->_mask[0], 0, 0, data->_mask->w, data->_mask->h);
+ } else {
+ _gfx->_backgroundInfo->mask.bltCopy(data->gfxobj->x, data->gfxobj->y, data->_mask[1], 0, 0, data->_mask->w, data->_mask->h);
+ }
+ }
}
}
DECLARE_COMMAND_OPCODE(on) {
- ZonePtr z = _ctxt.cmd->u._zone;
-
- if (z) {
- z->_flags &= ~kFlagsRemove;
- z->_flags |= kFlagsActive;
- updateGetZone(z, true);
- }
+ _vm->showZone(_ctxt.cmd->u._zone, true);
}
DECLARE_COMMAND_OPCODE(off) {
- ZonePtr z = _ctxt.cmd->u._zone;
-
- if (z) {
- _ctxt.cmd->u._zone->_flags |= kFlagsRemove;
- updateGetZone(z, false);
- }
+ _vm->showZone(_ctxt.cmd->u._zone, false);
}
@@ -299,7 +291,7 @@ DECLARE_COMMAND_OPCODE(call) {
DECLARE_COMMAND_OPCODE(toggle) {
if (_ctxt.cmd->u._flags & kFlagsGlobal) {
_ctxt.cmd->u._flags &= ~kFlagsGlobal;
- _commandFlags ^= _ctxt.cmd->u._flags;
+ _globalFlags ^= _ctxt.cmd->u._flags;
} else {
_vm->toggleLocationFlags(_ctxt.cmd->u._flags);
}
@@ -346,23 +338,31 @@ void Parallaction_ns::drawAnimations() {
if ((anim->_flags & kFlagsActive) && ((anim->_flags & kFlagsRemove) == 0)) {
if (anim->_flags & kFlagsNoMasked)
- layer = 3;
- else
- layer = _gfx->_backgroundInfo->getLayer(anim->_top + anim->height());
+ layer = LAYER_FOREGROUND;
+ else {
+ if (getGameType() == GType_Nippon) {
+ // Layer in NS depends on where the animation is on the screen, for each animation.
+ layer = _gfx->_backgroundInfo->getLayer(anim->getFrameY() + anim->height());
+ } else {
+ // Layer in BRA is calculated from Z value. For characters it is the same as NS,
+ // but other animations can have Z set from scripts independently from their
+ // position on the screen.
+ layer = _gfx->_backgroundInfo->getLayer(anim->getZ());
+ }
+ }
if (obj) {
_gfx->showGfxObj(obj, true);
- obj->frame = anim->_frame;
- obj->x = anim->_left;
- obj->y = anim->_top;
- obj->z = anim->_z;
+ obj->frame = anim->getF();
+ obj->x = anim->getX();
+ obj->y = anim->getY();
+ obj->z = anim->getZ();
obj->layer = layer;
}
}
if (((anim->_flags & kFlagsActive) == 0) && (anim->_flags & kFlagsRemove)) {
anim->_flags &= ~kFlagsRemove;
- anim->_oldPos.x = -1000;
}
if ((anim->_flags & kFlagsActive) && (anim->_flags & kFlagsRemove)) {
@@ -419,7 +419,7 @@ void ProgramExec::runScripts(ProgramList::iterator first, ProgramList::iterator
AnimationPtr a = (*it)->_anim;
if (a->_flags & kFlagsCharacter)
- a->_z = a->_top + a->height();
+ a->setZ(a->getFrameY() + a->height());
if ((a->_flags & kFlagsActing) == 0)
continue;
@@ -427,7 +427,7 @@ void ProgramExec::runScripts(ProgramList::iterator first, ProgramList::iterator
runScript(*it, a);
if (a->_flags & kFlagsCharacter)
- a->_z = a->_top + a->height();
+ a->setZ(a->getFrameY() + a->height());
}
_modCounter++;
@@ -453,7 +453,7 @@ void CommandExec::runList(CommandList::iterator first, CommandList::iterator las
break;
if (cmd->_flagsOn & kFlagsGlobal) {
- useFlags = _commandFlags | kFlagsGlobal;
+ useFlags = _globalFlags | kFlagsGlobal;
useLocalFlags = false;
} else {
useFlags = _vm->getLocationFlags();
@@ -606,7 +606,7 @@ void Parallaction::runCommentFrame() {
}
-uint16 Parallaction::runZone(ZonePtr z) {
+void Parallaction::runZone(ZonePtr z) {
debugC(3, kDebugExec, "runZone (%s)", z->_name);
uint16 subtype = z->_type & 0xFFFF;
@@ -616,20 +616,15 @@ uint16 Parallaction::runZone(ZonePtr z) {
case kZoneExamine:
enterCommentMode(z);
- return 0;
+ return;
case kZoneGet:
- if (z->_flags & kFlagsFixed) break;
- if (pickupItem(z) != 0) {
- return 1;
- }
- z->_flags |= kFlagsRemove;
+ pickupItem(z);
break;
case kZoneDoor:
if (z->_flags & kFlagsLocked) break;
- z->_flags ^= kFlagsClosed;
- updateDoor(z);
+ updateDoor(z, !(z->_flags & kFlagsClosed));
break;
case kZoneHear:
@@ -638,23 +633,24 @@ uint16 Parallaction::runZone(ZonePtr z) {
case kZoneSpeak:
enterDialogueMode(z);
- return 0;
+ return;
}
debugC(3, kDebugExec, "runZone completed");
_cmdExec->run(z->_commands, z);
- return 0;
+ return;
}
//
// ZONE TYPE: DOOR
//
-void Parallaction::updateDoor(ZonePtr z) {
+void Parallaction::updateDoor(ZonePtr z, bool close) {
+ z->_flags = close ? (z->_flags |= kFlagsClosed) : (z->_flags &= ~kFlagsClosed);
if (z->u.door->gfxobj) {
- uint frame = (z->_flags & kFlagsClosed ? 0 : 1);
+ uint frame = (close ? 0 : 1);
// z->u.door->gfxobj->setFrame(frame);
z->u.door->gfxobj->frame = frame;
}
@@ -668,13 +664,17 @@ void Parallaction::updateDoor(ZonePtr z) {
// ZONE TYPE: GET
//
-int16 Parallaction::pickupItem(ZonePtr z) {
- int r = addInventoryItem(z->u.get->_icon);
- if (r != -1) {
- _gfx->showGfxObj(z->u.get->gfxobj, false);
+bool Parallaction::pickupItem(ZonePtr z) {
+ if (z->_flags & kFlagsFixed) {
+ return false;
+ }
+
+ int slot = addInventoryItem(z->u.get->_icon);
+ if (slot != -1) {
+ showZone(z, false);
}
- return (r == -1);
+ return (slot != -1);
}
@@ -693,7 +693,7 @@ ZonePtr Parallaction::hitZone(uint32 type, uint16 x, uint16 y) {
if (z->_flags & kFlagsRemove) continue;
Common::Rect r;
- z->getRect(r);
+ z->getBox(r);
r.right++; // adjust border because Common::Rect doesn't include bottom-right edge
r.bottom++;
@@ -702,7 +702,7 @@ ZonePtr Parallaction::hitZone(uint32 type, uint16 x, uint16 y) {
if (!r.contains(_si, _di)) {
// out of Zone, so look for special values
- if ((z->_left == -2) || (z->_left == -3)) {
+ if ((z->getX() == -2) || (z->getX() == -3)) {
// WORKAROUND: this huge condition is needed because we made TypeData a collection of structs
// instead of an union. So, merge->_obj1 and get->_icon were just aliases in the original engine,
@@ -721,15 +721,15 @@ ZonePtr Parallaction::hitZone(uint32 type, uint16 x, uint16 y) {
}
}
- if (z->_left != -1)
+ if (z->getX() != -1)
continue;
- if (_si < _char._ani->_left)
+ if (_si < _char._ani->getFrameX())
continue;
- if (_si > (_char._ani->_left + _char._ani->width()))
+ if (_si > (_char._ani->getFrameX() + _char._ani->width()))
continue;
- if (_di < _char._ani->_top)
+ if (_di < _char._ani->getFrameY())
continue;
- if (_di > (_char._ani->_top + _char._ani->height()))
+ if (_di > (_char._ani->getFrameY() + _char._ani->height()))
continue;
}
@@ -751,8 +751,8 @@ ZonePtr Parallaction::hitZone(uint32 type, uint16 x, uint16 y) {
AnimationPtr a = *ait;
_a = (a->_flags & kFlagsActive) ? 1 : 0; // _a: active Animation
- _e = ((_si >= a->_left + a->width()) || (_si <= a->_left)) ? 0 : 1; // _e: horizontal range
- _f = ((_di >= a->_top + a->height()) || (_di <= a->_top)) ? 0 : 1; // _f: vertical range
+ _e = ((_si >= a->getFrameX() + a->width()) || (_si <= a->getFrameX())) ? 0 : 1; // _e: horizontal range
+ _f = ((_di >= a->getFrameY() + a->height()) || (_di <= a->getFrameY())) ? 0 : 1; // _f: vertical range
_b = ((type != 0) || (a->_type == kZoneYou)) ? 0 : 1; // _b: (no type specified) AND (Animation is not the character)
_c = (a->_type & 0xFFFF0000) ? 0 : 1; // _c: Animation is not an object
diff --git a/engines/parallaction/graphics.cpp b/engines/parallaction/graphics.cpp
index c19d6ae5e5..1c2cb58b5b 100644
--- a/engines/parallaction/graphics.cpp
+++ b/engines/parallaction/graphics.cpp
@@ -377,6 +377,12 @@ void Gfx::beginFrame() {
*data++ = _backgroundInfo->mask.getValue(x, y);
}
}
+#if 1
+ Common::DumpFile dump;
+ dump.open("maskdump.bin");
+ dump.write(_bitmapMask.pixels, _bitmapMask.w * _bitmapMask.h);
+ dump.close();
+#endif
break;
}
}
@@ -441,7 +447,7 @@ void Gfx::updateScreen() {
for (; b != e; b++) {
ZonePtr z = *b;
if (z->_type & kZonePath) {
- surf->frameRect(Common::Rect(z->_left, z->_top, z->_right, z->_bottom), 2);
+ surf->frameRect(Common::Rect(z->getX(), z->getY(), z->getX() + z->width(), z->getY() + z->height()), 2);
}
}
g_system->unlockScreen();
diff --git a/engines/parallaction/graphics.h b/engines/parallaction/graphics.h
index 23b4569c6a..471f71dfa8 100644
--- a/engines/parallaction/graphics.h
+++ b/engines/parallaction/graphics.h
@@ -209,6 +209,42 @@ public:
return (m >> n) & 3;
}
+ inline byte* getPtr(uint16 x, uint16 y) const {
+ return data + (x >> 2) + y * internalWidth;
+ }
+
+ void bltOr(uint16 dx, uint16 dy, const MaskBuffer &src, uint16 sx, uint16 sy, uint width, uint height) {
+ assert((width <= w) && (width <= src.w) && (height <= h) && (height <= src.h));
+
+ byte *s = src.getPtr(sx, sy);
+ byte *d = getPtr(dx, dy);
+
+ // this code assumes buffers are aligned on 4-pixels boundaries, as the original does
+ uint16 linewidth = width >> 2;
+ for (uint16 i = 0; i < height; i++) {
+ for (uint16 j = 0; j < linewidth; j++) {
+ *d++ |= *s++;
+ }
+ d += internalWidth - linewidth;
+ s += src.internalWidth - linewidth;
+ }
+ }
+
+ void bltCopy(uint16 dx, uint16 dy, const MaskBuffer &src, uint16 sx, uint16 sy, uint width, uint height) {
+ assert((width <= w) && (width <= src.w) && (height <= h) && (height <= src.h));
+
+ byte *s = src.getPtr(sx, sy);
+ byte *d = getPtr(dx, dy);
+
+ // this code assumes buffers are aligned on 4-pixels boundaries, as the original does
+ for (uint16 i = 0; i < height; i++) {
+ memcpy(d, s, (width >> 2));
+ d += internalWidth;
+ s += src.internalWidth;
+ }
+ }
+
+
};
@@ -419,7 +455,9 @@ struct BackgroundInfo {
int layers[4];
PaletteFxRange ranges[6];
- BackgroundInfo() : x(0), y(0), width(0), height(0) {
+ bool hasMask;
+
+ BackgroundInfo() : x(0), y(0), width(0), height(0), hasMask(false) {
layers[0] = layers[1] = layers[2] = layers[3] = 0;
memset(ranges, 0, sizeof(ranges));
}
diff --git a/engines/parallaction/objects.cpp b/engines/parallaction/objects.cpp
index c387484de7..d2332643ed 100644
--- a/engines/parallaction/objects.cpp
+++ b/engines/parallaction/objects.cpp
@@ -71,6 +71,20 @@ uint16 Animation::height() const {
return r.height();
}
+int16 Animation::getFrameX() const {
+ if (!gfxobj) return _left;
+ Common::Rect r;
+ gfxobj->getRect(_frame, r);
+ return r.left + _left;
+}
+
+int16 Animation::getFrameY() const {
+ if (!gfxobj) return _top;
+ Common::Rect r;
+ gfxobj->getRect(_frame, r);
+ return r.top + _top;
+}
+
uint16 Animation::getFrameNum() const {
if (!gfxobj) return 0;
return gfxobj->getNum();
@@ -115,24 +129,29 @@ int16 Program::addLocal(const char *name, int16 value, int16 min, int16 max) {
assert(_numLocals < NUM_LOCALS);
strcpy(_localNames[_numLocals], name);
- _locals[_numLocals]._value = value;
-
- _locals[_numLocals]._min = min;
- _locals[_numLocals]._max = max;
+ _locals[_numLocals].setRange(min, max);
+ _locals[_numLocals].setValue(value);
return _numLocals++;
}
-void LocalVariable::wrap() {
+void LocalVariable::setValue(int16 value) {
+ if (value >= _max)
+ value = _min;
+ if (value < _min)
+ value = _max - 1;
- if (_value >= _max)
- _value = _min;
- if (_value < _min)
- _value = _max - 1;
+ _value = value;
+}
- return;
+void LocalVariable::setRange(int16 min, int16 max) {
+ _max = max;
+ _min = min;
}
+int16 LocalVariable::getValue() const {
+ return _value;
+}
Zone::Zone() {
@@ -193,13 +212,6 @@ Zone::~Zone() {
free(_linkedName);
}
-void Zone::getRect(Common::Rect& r) const {
- r.left = _left;
- r.right = _right;
- r.top = _top;
- r.bottom = _bottom;
-}
-
void Zone::translate(int16 x, int16 y) {
_left += x;
_right += x;
@@ -273,18 +285,18 @@ Instruction::~Instruction() {
free(_text2);
}
-int16 ScriptVar::getRValue() {
+int16 ScriptVar::getValue() {
if (_flags & kParaImmediate) {
return _value;
}
if (_flags & kParaLocal) {
- return _local->_value;
+ return _local->getValue();
}
if (_flags & kParaField) {
- return *_pvalue;
+ return _field->getValue();
}
if (_flags & kParaRandom) {
@@ -296,27 +308,33 @@ int16 ScriptVar::getRValue() {
return 0;
}
-int16* ScriptVar::getLValue() {
+void ScriptVar::setValue(int16 value) {
+ if ((_flags & kParaLValue) == 0) {
+ error("Only l-value can be set");
+ }
if (_flags & kParaLocal) {
- return &_local->_value;
+ _local->setValue(value);
}
if (_flags & kParaField) {
- return _pvalue;
+ _field->setValue(value);
}
- error("Parameter is not an l-value");
-
}
void ScriptVar::setLocal(LocalVariable *local) {
_local = local;
- _flags |= kParaLocal;
+ _flags |= (kParaLocal | kParaLValue);
}
-void ScriptVar::setField(int16 *field) {
- _pvalue = field;
+void ScriptVar::setField(Animation *anim, AnimationField::AccessorFunc accessor, AnimationField::MutatorFunc mutator) {
+ _field = new AnimationField(anim, accessor, mutator);
+ _flags |= (kParaField | kParaLValue);
+}
+
+void ScriptVar::setField(Animation *anim, AnimationField::AccessorFunc accessor) {
+ _field = new AnimationField(anim, accessor);
_flags |= kParaField;
}
@@ -335,9 +353,14 @@ ScriptVar::ScriptVar() {
_flags = 0;
_local = 0;
_value = 0;
- _pvalue = 0;
+ _field = 0;
}
+ScriptVar::~ScriptVar() {
+ delete _field;
+}
+
+
Table::Table(uint32 size) : _size(size), _used(0), _disposeMemory(true) {
_data = (char**)calloc(size, sizeof(char*));
}
diff --git a/engines/parallaction/objects.h b/engines/parallaction/objects.h
index 7e7a811ba6..f66e602f68 100644
--- a/engines/parallaction/objects.h
+++ b/engines/parallaction/objects.h
@@ -198,11 +198,14 @@ struct GetData { // size = 24
byte *_backup;
uint16 field_14; // unused
uint16 field_16; // unused
+ MaskBuffer _mask[2];
+ bool hasMask;
GetData() {
_icon = 0;
_backup = NULL;
gfxobj = NULL;
+ hasMask = false;
}
};
struct SpeakData { // size = 36
@@ -297,17 +300,19 @@ struct TypeData {
#define ZONENAME_LENGTH 32
struct Zone {
- char _name[ZONENAME_LENGTH];
-
+protected:
int16 _left;
int16 _top;
int16 _right;
int16 _bottom;
+
+public:
+ char _name[ZONENAME_LENGTH];
+
uint32 _type;
uint32 _flags;
uint _label;
- uint16 field_2C; // unused
- uint16 field_2E; // unused
+
TypeData u;
CommandList _commands;
Common::Point _moveTo;
@@ -320,32 +325,101 @@ struct Zone {
Zone();
virtual ~Zone();
- void getRect(Common::Rect& r) const;
void translate(int16 x, int16 y);
virtual uint16 width() const;
virtual uint16 height() const;
+
+ void setBox(int16 left, int16 top, int16 right, int16 bottom) {
+ setX(left);
+ setY(top);
+ _right = right;
+ _bottom = bottom;
+ }
+
+ void getBox(Common::Rect& r) {
+ r.left = getX();
+ r.right = getX() + width();
+ r.top = getY();
+ r.bottom = getY() + height();
+ }
+
+
+ // getters/setters
+ virtual int16 getX() { return _left; }
+ virtual void setX(int16 value) { _left = value; }
+
+ virtual int16 getY() { return _top; }
+ virtual void setY(int16 value) { _top = value; }
};
struct LocalVariable {
+protected:
int16 _value;
int16 _min;
int16 _max;
+public:
+
LocalVariable() {
_value = 0;
_min = -10000;
_max = 10000;
}
- void wrap();
+ void setRange(int16 min, int16 max);
+
+ int16 getValue() const;
+ void setValue(int16 value);
};
+
enum ParaFlags {
kParaImmediate = 1, // instruction is using an immediate parameter
kParaLocal = 2, // instruction is using a local variable
kParaField = 0x10, // instruction is using an animation's field
- kParaRandom = 0x100
+ kParaRandom = 0x100,
+
+ kParaLValue = 0x20
+};
+
+
+struct AnimationField {
+ typedef Common::Functor0Mem<int16, Animation> Accessor;
+ typedef Common::Functor1Mem<int16, void, Animation> Mutator;
+
+ typedef Accessor::FuncType AccessorFunc;
+ typedef Mutator::FuncType MutatorFunc;
+
+protected:
+ Accessor *_accessor;
+ Mutator *_mutator;
+
+public:
+ AnimationField(Animation* instance, AccessorFunc accessor, MutatorFunc mutator) {
+ _accessor = new Accessor(instance, accessor);
+ _mutator = new Mutator(instance, mutator);
+ }
+
+ AnimationField(Animation* instance, AccessorFunc accessor) {
+ _accessor = new Accessor(instance, accessor);
+ _mutator = 0;
+ }
+
+ ~AnimationField() {
+ delete _accessor;
+ delete _mutator;
+ }
+
+ int16 getValue() const {
+ assert(_accessor);
+ return _accessor->operator()();
+ }
+
+ void setValue(int16 value) {
+ assert(_mutator);
+ _mutator->operator()(value);
+ }
};
@@ -353,16 +427,18 @@ struct ScriptVar {
uint32 _flags;
int16 _value;
- int16* _pvalue;
LocalVariable* _local;
+ AnimationField* _field;
ScriptVar();
+ ~ScriptVar();
- int16 getRValue();
- int16* getLValue();
+ int16 getValue();
+ void setValue(int16 value);
void setLocal(LocalVariable *local);
- void setField(int16 *field);
+ void setField(Animation *anim, AnimationField::AccessorFunc accessor, AnimationField::MutatorFunc mutator);
+ void setField(Animation *anim, AnimationField::AccessorFunc accessor);
void setImmediate(int16 value);
void setRandom(int16 seed);
};
@@ -430,19 +506,13 @@ typedef Common::SharedPtr<Program> ProgramPtr;
typedef Common::List<ProgramPtr> ProgramList;
struct Animation : public Zone {
+protected:
+ int16 _frame;
+ int16 _z;
+public:
- Common::Point _oldPos;
GfxObj *gfxobj;
char *_scriptName;
- int16 _frame;
- uint16 field_50; // unused
- int16 _z;
- uint16 field_54; // unused
- uint16 field_56; // unused
- uint16 field_58; // unused
- uint16 field_5A; // unused
- uint16 field_5C; // unused
- uint16 field_5E; // unused
Animation();
virtual ~Animation();
@@ -452,6 +522,22 @@ struct Animation : public Zone {
byte* getFrameData(uint32 index) const;
void validateScriptVars();
+
+ int16 getFrameX() const;
+ int16 getFrameY() const;
+
+ // getters/setters used by scripts
+ int16 getX() { return _left; }
+ void setX(int16 value) { _left = value; }
+
+ int16 getY() { return _top; }
+ void setY(int16 value) { _top = value; }
+
+ int16 getZ() { return _z; }
+ void setZ(int16 value) { _z = value; }
+
+ int16 getF() { return _frame; }
+ void setF(int16 value) { _frame = value; }
};
class Table {
diff --git a/engines/parallaction/parallaction.cpp b/engines/parallaction/parallaction.cpp
index 6a61087804..afa246a9f8 100644
--- a/engines/parallaction/parallaction.cpp
+++ b/engines/parallaction/parallaction.cpp
@@ -53,7 +53,7 @@ uint32 _engineFlags = 0;
uint16 _score = 1;
char _password[8];
-uint32 _commandFlags = 0;
+uint32 _globalFlags = 0;
// private stuff
@@ -85,7 +85,7 @@ Parallaction::Parallaction(OSystem *syst, const PARALLACTIONGameDescription *gam
Parallaction::~Parallaction() {
delete _debugger;
- delete _globalTable;
+ delete _globalFlagsNames;
delete _callableNames;
delete _cmdExec;
delete _programExec;
@@ -114,7 +114,7 @@ int Parallaction::init() {
_engineFlags = 0;
_objectsNames = NULL;
- _globalTable = NULL;
+ _globalFlagsNames = NULL;
_location._hasSound = false;
_baseTime = 0;
_numLocations = 0;
@@ -360,9 +360,9 @@ void Parallaction::runGame() {
if (_input->_inputMode == Input::kInputModeGame) {
_programExec->runScripts(_location._programs.begin(), _location._programs.end());
- _char._ani->_z = _char._ani->height() + _char._ani->_top;
+ _char._ani->setZ(_char._ani->height() + _char._ani->getFrameY());
if (_char._ani->gfxobj) {
- _char._ani->gfxobj->z = _char._ani->_z;
+ _char._ani->gfxobj->z = _char._ani->getZ();
}
_char._walker->walk();
drawAnimations();
@@ -460,7 +460,8 @@ void Parallaction::freeZones() {
// NOTE : this condition has been relaxed compared to the original, to allow the engine
// to retain special - needed - zones that were lost across location switches.
ZonePtr z = *it;
- if (((z->_top == -1) || (z->_left == -2)) && ((_vm->_quit) == 0)) {
+
+ if (((z->getY() == -1) || (z->getX() == -2)) && ((_vm->quit()) == 0)) {
debugC(2, kDebugExec, "freeZones preserving zone '%s'", z->_name);
it++;
} else {
@@ -523,12 +524,10 @@ Character::Character(Parallaction *vm) : _vm(vm), _ani(new Animation) {
_dummy = false;
- _ani->_left = 150;
- _ani->_top = 100;
- _ani->_z = 10;
- _ani->_oldPos.x = -1000;
- _ani->_oldPos.y = -1000;
- _ani->_frame = 0;
+ _ani->setX(150);
+ _ani->setY(100);
+ _ani->setZ(10);
+ _ani->setF(0);
_ani->_flags = kFlagsActive | kFlagsNoName;
_ani->_type = kZoneYou;
strncpy(_ani->_name, "yourself", ZONENAME_LENGTH);
@@ -555,18 +554,18 @@ Character::~Character() {
void Character::getFoot(Common::Point &foot) {
Common::Rect rect;
- _ani->gfxobj->getRect(_ani->_frame, rect);
+ _ani->gfxobj->getRect(_ani->getF(), rect);
- foot.x = _ani->_left + (rect.left + rect.width() / 2);
- foot.y = _ani->_top + (rect.top + rect.height());
+ foot.x = _ani->getX() + (rect.left + rect.width() / 2);
+ foot.y = _ani->getY() + (rect.top + rect.height());
}
void Character::setFoot(const Common::Point &foot) {
Common::Rect rect;
- _ani->gfxobj->getRect(_ani->_frame, rect);
+ _ani->gfxobj->getRect(_ani->getF(), rect);
- _ani->_left = foot.x - (rect.left + rect.width() / 2);
- _ani->_top = foot.y - (rect.top + rect.height());
+ _ani->setX(foot.x - (rect.left + rect.width() / 2));
+ _ani->setY(foot.y - (rect.top + rect.height()));
}
#if 0
@@ -690,7 +689,7 @@ void Character::updateDirection(const Common::Point& pos, const Common::Point& t
_step++;
if (dist.x == 0 && dist.y == 0) {
- _ani->_frame = frames->stillFrame[_direction];
+ _ani->setF(frames->stillFrame[_direction]);
return;
}
@@ -700,7 +699,7 @@ void Character::updateDirection(const Common::Point& pos, const Common::Point& t
dist.y = -dist.y;
_direction = (dist.x > dist.y) ? ((to.x > pos.x) ? WALK_LEFT : WALK_RIGHT) : ((to.y > pos.y) ? WALK_DOWN : WALK_UP);
- _ani->_frame = frames->firstWalkFrame[_direction] + (_step / frames->frameRepeat[_direction]) % frames->numWalkFrames[_direction];
+ _ani->setF(frames->firstWalkFrame[_direction] + (_step / frames->frameRepeat[_direction]) % frames->numWalkFrames[_direction]);
}
diff --git a/engines/parallaction/parallaction.h b/engines/parallaction/parallaction.h
index 2a32904d63..eb7ab2e54b 100644
--- a/engines/parallaction/parallaction.h
+++ b/engines/parallaction/parallaction.h
@@ -135,7 +135,7 @@ extern uint16 _score;
extern uint16 _language;
extern uint32 _engineFlags;
extern char _saveData1[];
-extern uint32 _commandFlags;
+extern uint32 _globalFlags;
extern const char *_dinoName;
extern const char *_donnaName;
extern const char *_doughName;
@@ -269,7 +269,7 @@ public:
ZonePtr findZone(const char *name);
ZonePtr hitZone(uint32 type, uint16 x, uint16 y);
- uint16 runZone(ZonePtr z);
+ void runZone(ZonePtr z);
void freeZones();
AnimationPtr findAnimation(const char *name);
@@ -278,7 +278,7 @@ public:
void setBackground(const char *background, const char *mask, const char *path);
void freeBackground();
- Table *_globalTable;
+ Table *_globalFlagsNames;
Table *_objectsNames;
Table *_callableNames;
Table *_localFlagNames;
@@ -361,7 +361,7 @@ protected: // members
void freeCharacter();
- int16 pickupItem(ZonePtr z);
+ bool pickupItem(ZonePtr z);
void clearSet(OpcodeSet &opcodes);
@@ -377,7 +377,7 @@ public:
virtual void parseLocation(const char* name) = 0;
- void updateDoor(ZonePtr z);
+ void updateDoor(ZonePtr z, bool close);
virtual void drawAnimations() = 0;
@@ -431,6 +431,8 @@ public:
void setInternLanguage(uint id);
uint getInternLanguage();
+
+ void showZone(ZonePtr z, bool visible);
};
@@ -630,8 +632,10 @@ public:
int _part;
int _progress;
+#if 0 // disabled since I couldn't find any references to lip sync in the scripts
int16 _lipSyncVal;
uint _subtitleLipSync;
+#endif
int _subtitleY;
int _subtitle[2];
diff --git a/engines/parallaction/parallaction_br.cpp b/engines/parallaction/parallaction_br.cpp
index f4329edf74..e65faaeda2 100644
--- a/engines/parallaction/parallaction_br.cpp
+++ b/engines/parallaction/parallaction_br.cpp
@@ -193,7 +193,7 @@ void Parallaction_br::initPart() {
memset(_counters, 0, ARRAYSIZE(_counters));
- _globalTable = _disk->loadTable("global");
+ _globalFlagsNames = _disk->loadTable("global");
_objectsNames = _disk->loadTable("objects");
_countersNames = _disk->loadTable("counters");
@@ -208,11 +208,11 @@ void Parallaction_br::initPart() {
void Parallaction_br::freePart() {
- delete _globalTable;
+ delete _globalFlagsNames;
delete _objectsNames;
delete _countersNames;
- _globalTable = 0;
+ _globalFlagsNames = 0;
_objectsNames = 0;
_countersNames = 0;
}
diff --git a/engines/parallaction/parallaction_ns.cpp b/engines/parallaction/parallaction_ns.cpp
index f3c2656001..eab08142d4 100644
--- a/engines/parallaction/parallaction_ns.cpp
+++ b/engines/parallaction/parallaction_ns.cpp
@@ -220,7 +220,7 @@ void Parallaction_ns::callFunction(uint index, void* parm) {
int Parallaction_ns::go() {
renameOldSavefiles();
- _globalTable = _disk->loadTable("global");
+ _globalFlagsNames = _disk->loadTable("global");
// If requested, load a savegame instead of showing the intro
if (ConfMan.hasKey("save_slot")) {
@@ -338,14 +338,10 @@ void Parallaction_ns::changeLocation(char *location) {
strcpy(_saveData1, locname.location());
parseLocation(_saveData1);
- _char._ani->_oldPos.x = -1000;
- _char._ani->_oldPos.y = -1000;
-
- _char._ani->field_50 = 0;
if (_location._startPosition.x != -1000) {
- _char._ani->_left = _location._startPosition.x;
- _char._ani->_top = _location._startPosition.y;
- _char._ani->_frame = _location._startFrame;
+ _char._ani->setX(_location._startPosition.x);
+ _char._ani->setY(_location._startPosition.y);
+ _char._ani->setF(_location._startFrame);
_location._startPosition.y = -1000;
_location._startPosition.x = -1000;
}
@@ -458,7 +454,7 @@ void Parallaction_ns::cleanupGame() {
// this code saves main character animation from being removed from the following code
_location._animations.remove(_char._ani);
_numLocations = 0;
- _commandFlags = 0;
+ _globalFlags = 0;
memset(_localFlags, 0, sizeof(_localFlags));
memset(_locationNames, 0, sizeof(_locationNames));
diff --git a/engines/parallaction/parser.cpp b/engines/parallaction/parser.cpp
index 97caa9dc6c..8e30a631e4 100644
--- a/engines/parallaction/parser.cpp
+++ b/engines/parallaction/parser.cpp
@@ -93,7 +93,7 @@ void Script::skip(const char* endToken) {
//
// The routine returns the unparsed portion of the input string 's'.
//
-char *parseNextToken(char *s, char *tok, uint16 count, const char *brk, bool ignoreQuotes) {
+char *Script::parseNextToken(char *s, char *tok, uint16 count, const char *brk, bool ignoreQuotes) {
enum STATES { NORMAL, QUOTED };
diff --git a/engines/parallaction/parser.h b/engines/parallaction/parser.h
index 7e7937fb19..e622bfd81f 100644
--- a/engines/parallaction/parser.h
+++ b/engines/parallaction/parser.h
@@ -32,8 +32,6 @@
namespace Parallaction {
-char *parseNextToken(char *s, char *tok, uint16 count, const char *brk, bool ignoreQuotes = false);
-
#define MAX_TOKEN_LEN 50
extern int _numTokens;
extern char _tokens[][MAX_TOKEN_LEN];
@@ -46,6 +44,7 @@ class Script {
void clearTokens();
uint16 fillTokens(char* line);
+ char *parseNextToken(char *s, char *tok, uint16 count, const char *brk, bool ignoreQuotes = false);
public:
Script(Common::ReadStream *, bool _disposeSource = false);
@@ -132,9 +131,6 @@ protected:
// BRA specific
int numZones;
BackgroundInfo *info;
- char *bgName;
- char *maskName;
- char *pathName;
char *characterName;
} ctxt;
@@ -307,6 +303,7 @@ protected:
virtual void parseZoneTypeBlock(ZonePtr z);
void parsePathData(ZonePtr z);
+ void parseGetData(ZonePtr z);
public:
LocationParser_br(Parallaction_br *vm) : LocationParser_ns((Parallaction_ns*)vm), _vm(vm) {
diff --git a/engines/parallaction/parser_br.cpp b/engines/parallaction/parser_br.cpp
index dee08485fb..20800abc33 100644
--- a/engines/parallaction/parser_br.cpp
+++ b/engines/parallaction/parser_br.cpp
@@ -316,7 +316,6 @@ DECLARE_LOCATION_PARSER(location) {
debugC(7, kDebugParser, "LOCATION_PARSER(location) ");
strcpy(_vm->_location._name, _tokens[1]);
- ctxt.bgName = strdup(_tokens[1]);
bool flip = false;
int nextToken;
@@ -331,15 +330,17 @@ DECLARE_LOCATION_PARSER(location) {
// TODO: handle background horizontal flip (via a context parameter)
if (_tokens[nextToken][0] != '\0') {
- _vm->_char._ani->_left = atoi(_tokens[nextToken]);
+ _vm->_char._ani->setX(atoi(_tokens[nextToken]));
nextToken++;
- _vm->_char._ani->_top = atoi(_tokens[nextToken]);
+ _vm->_char._ani->setY(atoi(_tokens[nextToken]));
nextToken++;
}
if (_tokens[nextToken][0] != '\0') {
- _vm->_char._ani->_frame = atoi(_tokens[nextToken]);
+ _vm->_char._ani->setF(atoi(_tokens[nextToken]));
}
+
+ _vm->_disk->loadScenery(*ctxt.info, _tokens[1], 0, 0);
}
@@ -465,17 +466,20 @@ DECLARE_LOCATION_PARSER(null) {
DECLARE_LOCATION_PARSER(mask) {
debugC(7, kDebugParser, "LOCATION_PARSER(mask) ");
- ctxt.maskName = strdup(_tokens[1]);
- ctxt.info->layers[0] = atoi(_tokens[2]);
- ctxt.info->layers[1] = atoi(_tokens[3]);
- ctxt.info->layers[2] = atoi(_tokens[4]);
+ ctxt.info->layers[0] = 0;
+ ctxt.info->layers[1] = atoi(_tokens[2]);
+ ctxt.info->layers[2] = atoi(_tokens[3]);
+ ctxt.info->layers[3] = atoi(_tokens[4]);
+
+ _vm->_disk->loadScenery(*ctxt.info, 0, _tokens[1], 0);
+ ctxt.info->hasMask = true;
}
DECLARE_LOCATION_PARSER(path) {
debugC(7, kDebugParser, "LOCATION_PARSER(path) ");
- ctxt.pathName = strdup(_tokens[1]);
+ _vm->_disk->loadScenery(*ctxt.info, 0, 0, _tokens[1]);
}
@@ -716,10 +720,7 @@ DECLARE_ZONE_PARSER(limits) {
ctxt.z->_linkedAnim = _vm->findAnimation(_tokens[1]);
ctxt.z->_linkedName = strdup(_tokens[1]);
} else {
- ctxt.z->_left = atoi(_tokens[1]);
- ctxt.z->_top = atoi(_tokens[2]);
- ctxt.z->_right = atoi(_tokens[3]);
- ctxt.z->_bottom = atoi(_tokens[4]);
+ ctxt.z->setBox(atoi(_tokens[1]), atoi(_tokens[2]), atoi(_tokens[3]), atoi(_tokens[4]));
}
}
@@ -770,6 +771,49 @@ void LocationParser_br::parsePathData(ZonePtr z) {
z->u.path = data;
}
+void LocationParser_br::parseGetData(ZonePtr z) {
+
+ GetData *data = new GetData;
+
+ do {
+
+ if (!scumm_stricmp(_tokens[0], "file")) {
+
+ GfxObj *obj = _vm->_gfx->loadGet(_tokens[1]);
+ obj->frame = 0;
+ obj->x = z->getX();
+ obj->y = z->getY();
+ data->gfxobj = obj;
+ }
+
+ if (!scumm_stricmp(_tokens[0], "mask")) {
+ if (ctxt.info->hasMask) {
+ Common::Rect rect;
+ data->gfxobj->getRect(0, rect);
+ data->_mask[0].create(rect.width(), rect.height());
+ _vm->_disk->loadMask(_tokens[1], data->_mask[0]);
+ data->_mask[1].create(rect.width(), rect.height());
+ data->_mask[1].bltCopy(0, 0, ctxt.info->mask, data->gfxobj->x, data->gfxobj->y, data->_mask->w, data->_mask->h);
+ data->hasMask = true;
+ } else {
+ warning("Mask for zone '%s' ignored, since background doesn't have one", z->_name);
+ }
+ }
+
+ if (!scumm_stricmp(_tokens[0], "path")) {
+
+ }
+
+ if (!scumm_stricmp(_tokens[0], "icon")) {
+ data->_icon = 4 + _vm->_objectsNames->lookup(_tokens[1]);
+ }
+
+ _script->readLineToken(true);
+ } while (scumm_stricmp(_tokens[0], "endzone"));
+
+ z->u.get = data;
+}
+
void LocationParser_br::parseZoneTypeBlock(ZonePtr z) {
debugC(7, kDebugParser, "parseZoneTypeBlock(name: %s, type: %x)", z->_name, z->_type);
@@ -824,10 +868,10 @@ DECLARE_ANIM_PARSER(file) {
DECLARE_ANIM_PARSER(position) {
debugC(7, kDebugParser, "ANIM_PARSER(position) ");
- ctxt.a->_left = atoi(_tokens[1]);
- ctxt.a->_top = atoi(_tokens[2]);
- ctxt.a->_z = atoi(_tokens[3]);
- ctxt.a->_frame = atoi(_tokens[4]);
+ ctxt.a->setX(atoi(_tokens[1]));
+ ctxt.a->setY(atoi(_tokens[2]));
+ ctxt.a->setZ(atoi(_tokens[3]));
+ ctxt.a->setF(atoi(_tokens[4]));
}
@@ -843,15 +887,14 @@ DECLARE_ANIM_PARSER(moveto) {
DECLARE_ANIM_PARSER(endanimation) {
debugC(7, kDebugParser, "ANIM_PARSER(endanimation) ");
-
+#if 0
+ // I have disabled the following code since it seems useless.
+ // I will remove it after mask processing is done.
if (ctxt.a->gfxobj) {
ctxt.a->_right = ctxt.a->width();
ctxt.a->_bottom = ctxt.a->height();
}
-
- ctxt.a->_oldPos.x = -1000;
- ctxt.a->_oldPos.y = -1000;
-
+#endif
ctxt.a->_flags |= 0x1000000;
_parser->popTables();
@@ -994,16 +1037,16 @@ void ProgramParser_br::parseRValue(ScriptVar &v, const char *str) {
a = AnimationPtr(ctxt.a);
if (str[0] == 'X') {
- v.setField(&a->_left);
+ v.setField(a.get(), &Animation::getX);
} else
if (str[0] == 'Y') {
- v.setField(&a->_top);
+ v.setField(a.get(), &Animation::getY);
} else
if (str[0] == 'Z') {
- v.setField(&a->_z);
+ v.setField(a.get(), &Animation::getZ);
} else
if (str[0] == 'F') {
- v.setField(&a->_frame);
+ v.setField(a.get(), &Animation::getF);
} else
if (str[0] == 'N') {
v.setImmediate(a->getFrameNum());
@@ -1012,7 +1055,10 @@ void ProgramParser_br::parseRValue(ScriptVar &v, const char *str) {
v.setRandom(atoi(&str[1]));
} else
if (str[0] == 'L') {
+#if 0 // disabled because no references to lip sync has been found in the scripts
v.setField(&_vm->_lipSyncVal);
+#endif
+ warning("Lip sync instruction encountered! Please notify the team!");
}
}
@@ -1192,26 +1238,25 @@ void LocationParser_br::parse(Script *script) {
Script *script2 = new Script(getStream(list), true);
ctxt.numZones = 0;
- ctxt.bgName = 0;
- ctxt.maskName = 0;
- ctxt.pathName = 0;
ctxt.characterName = 0;
ctxt.info = new BackgroundInfo;
LocationParser_ns::parse(script2);
- _vm->_disk->loadScenery(*ctxt.info, ctxt.bgName, ctxt.maskName, ctxt.pathName);
_vm->_gfx->setBackground(kBackgroundLocation, ctxt.info);
_vm->_pathBuffer = &ctxt.info->path;
+ ZoneList::iterator it = _vm->_location._zones.begin();
+ for ( ; it != _vm->_location._zones.end(); it++) {
+ bool visible = ((*it)->_flags & kFlagsRemove) == 0;
+ _vm->showZone((*it), visible);
+ }
+
if (ctxt.characterName) {
_vm->changeCharacter(ctxt.characterName);
}
- free(ctxt.bgName);
- free(ctxt.maskName);
- free(ctxt.pathName);
free(ctxt.characterName);
delete script2;
diff --git a/engines/parallaction/parser_ns.cpp b/engines/parallaction/parser_ns.cpp
index ad0f714fdc..4b90e2364f 100644
--- a/engines/parallaction/parser_ns.cpp
+++ b/engines/parallaction/parser_ns.cpp
@@ -221,9 +221,6 @@ DECLARE_ANIM_PARSER(type) {
}
}
- ctxt.a->_oldPos.x = -1000;
- ctxt.a->_oldPos.y = -1000;
-
ctxt.a->_flags |= 0x1000000;
_parser->popTables();
@@ -267,9 +264,9 @@ DECLARE_ANIM_PARSER(file) {
DECLARE_ANIM_PARSER(position) {
debugC(7, kDebugParser, "ANIM_PARSER(position) ");
- ctxt.a->_left = atoi(_tokens[1]);
- ctxt.a->_top = atoi(_tokens[2]);
- ctxt.a->_z = atoi(_tokens[3]);
+ ctxt.a->setX(atoi(_tokens[1]));
+ ctxt.a->setY(atoi(_tokens[2]));
+ ctxt.a->setZ(atoi(_tokens[3]));
}
@@ -284,10 +281,6 @@ DECLARE_ANIM_PARSER(moveto) {
DECLARE_ANIM_PARSER(endanimation) {
debugC(7, kDebugParser, "ANIM_PARSER(endanimation) ");
-
- ctxt.a->_oldPos.x = -1000;
- ctxt.a->_oldPos.y = -1000;
-
ctxt.a->_flags |= 0x1000000;
_parser->popTables();
@@ -523,7 +516,7 @@ DECLARE_INSTRUCTION_PARSER(defLocal) {
}
ctxt.inst->_opA.setLocal(&ctxt.locals[index]);
- ctxt.inst->_opB.setImmediate(ctxt.locals[index]._value);
+ ctxt.inst->_opB.setImmediate(ctxt.locals[index].getValue());
ctxt.inst->_index = INST_SET;
}
@@ -558,16 +551,16 @@ void ProgramParser_ns::parseRValue(ScriptVar &v, const char *str) {
}
if (str[0] == 'X') {
- v.setField(&a->_left);
+ v.setField(a.get(), &Animation::getX);
} else
if (str[0] == 'Y') {
- v.setField(&a->_top);
+ v.setField(a.get(), &Animation::getY);
} else
if (str[0] == 'Z') {
- v.setField(&a->_z);
+ v.setField(a.get(), &Animation::getZ);
} else
if (str[0] == 'F') {
- v.setField(&a->_frame);
+ v.setField(a.get(), &Animation::getF);
}
}
@@ -588,16 +581,16 @@ void ProgramParser_ns::parseLValue(ScriptVar &v, const char *str) {
}
if (str[0] == 'X') {
- v.setField(&a->_left);
+ v.setField(a.get(), &Animation::getX, &Animation::setX);
} else
if (str[0] == 'Y') {
- v.setField(&a->_top);
+ v.setField(a.get(), &Animation::getY, &Animation::setY);
} else
if (str[0] == 'Z') {
- v.setField(&a->_z);
+ v.setField(a.get(), &Animation::getZ, &Animation::setZ);
} else
if (str[0] == 'F') {
- v.setField(&a->_frame);
+ v.setField(a.get(), &Animation::getF, &Animation::setF);
}
}
@@ -608,7 +601,7 @@ DECLARE_COMMAND_PARSER(flags) {
createCommand(_parser->_lookup);
- if (_vm->_globalTable->lookup(_tokens[1]) == Table::notFound) {
+ if (_vm->_globalFlagsNames->lookup(_tokens[1]) == Table::notFound) {
do {
char _al = _vm->_localFlagNames->lookup(_tokens[ctxt.nextToken]);
ctxt.nextToken++;
@@ -618,7 +611,7 @@ DECLARE_COMMAND_PARSER(flags) {
} else {
ctxt.cmd->u._flags |= kFlagsGlobal;
do {
- char _al = _vm->_globalTable->lookup(_tokens[1]);
+ char _al = _vm->_globalFlagsNames->lookup(_tokens[1]);
ctxt.nextToken++;
ctxt.cmd->u._flags |= 1 << (_al - 1);
} while (!scumm_stricmp(_tokens[ctxt.nextToken++], "|"));
@@ -759,11 +752,11 @@ void LocationParser_ns::parseCommandFlags() {
cmd->_flagsOn |= kFlagsEnter;
} else
if (!scumm_strnicmp(_tokens[_si], "no", 2)) {
- byte _al = _vm->_globalTable->lookup(&_tokens[_si][2]);
+ byte _al = _vm->_globalFlagsNames->lookup(&_tokens[_si][2]);
assert(_al != Table::notFound);
cmd->_flagsOff |= 1 << (_al - 1);
} else {
- byte _al = _vm->_globalTable->lookup(_tokens[_si]);
+ byte _al = _vm->_globalFlagsNames->lookup(_tokens[_si]);
assert(_al != Table::notFound);
cmd->_flagsOn |= 1 << (_al - 1);
}
@@ -880,7 +873,7 @@ Answer *LocationParser_ns::parseAnswer() {
if (!scumm_stricmp(_tokens[1], "global")) {
token = 2;
- flagNames = _vm->_globalTable;
+ flagNames = _vm->_globalFlagsNames;
answer->_yesFlags |= kFlagsGlobal;
} else {
token = 1;
@@ -992,12 +985,12 @@ DECLARE_LOCATION_PARSER(location) {
_vm->switchBackground(_vm->_location._name, mask);
if (_tokens[2][0] != '\0') {
- _vm->_char._ani->_left = atoi(_tokens[2]);
- _vm->_char._ani->_top = atoi(_tokens[3]);
+ _vm->_char._ani->setX(atoi(_tokens[2]));
+ _vm->_char._ani->setY(atoi(_tokens[3]));
}
if (_tokens[4][0] != '\0') {
- _vm->_char._ani->_frame = atoi(_tokens[4]);
+ _vm->_char._ani->setF(atoi(_tokens[4]));
}
}
@@ -1316,11 +1309,7 @@ DECLARE_ZONE_PARSER(endzone) {
DECLARE_ZONE_PARSER(limits) {
debugC(7, kDebugParser, "ZONE_PARSER(limits) ");
-
- ctxt.z->_left = atoi(_tokens[1]);
- ctxt.z->_top = atoi(_tokens[2]);
- ctxt.z->_right = atoi(_tokens[3]);
- ctxt.z->_bottom = atoi(_tokens[4]);
+ ctxt.z->setBox(atoi(_tokens[1]), atoi(_tokens[2]), atoi(_tokens[3]), atoi(_tokens[4]));
}
@@ -1411,8 +1400,8 @@ void LocationParser_ns::parseGetData(ZonePtr z) {
GfxObj *obj = _vm->_gfx->loadGet(_tokens[1]);
obj->frame = 0;
- obj->x = z->_left;
- obj->y = z->_top;
+ obj->x = z->getX();
+ obj->y = z->getY();
_vm->_gfx->showGfxObj(obj, visible);
data->gfxobj = obj;
@@ -1474,8 +1463,8 @@ void LocationParser_ns::parseDoorData(ZonePtr z) {
GfxObj *obj = _vm->_gfx->loadDoor(_tokens[1]);
obj->frame = frame;
- obj->x = z->_left;
- obj->y = z->_top;
+ obj->x = z->getX();
+ obj->y = z->getY();
_vm->_gfx->showGfxObj(obj, true);
data->gfxobj = obj;
diff --git a/engines/parallaction/saveload.cpp b/engines/parallaction/saveload.cpp
index 86700d6bb1..ed3812e5be 100644
--- a/engines/parallaction/saveload.cpp
+++ b/engines/parallaction/saveload.cpp
@@ -125,7 +125,7 @@ void Parallaction_ns::doLoadGame(uint16 slot) {
_score = atoi(s);
f->readLine(s, 15);
- _commandFlags = atoi(s);
+ _globalFlags = atoi(s);
f->readLine(s, 15);
@@ -209,13 +209,13 @@ void Parallaction_ns::doSaveGame(uint16 slot, const char* name) {
sprintf(s, "%s\n", _saveData1);
f->writeString(s);
- sprintf(s, "%d\n", _char._ani->_left);
+ sprintf(s, "%d\n", _char._ani->getX());
f->writeString(s);
- sprintf(s, "%d\n", _char._ani->_top);
+ sprintf(s, "%d\n", _char._ani->getY());
f->writeString(s);
sprintf(s, "%d\n", _score);
f->writeString(s);
- sprintf(s, "%u\n", _commandFlags);
+ sprintf(s, "%u\n", _globalFlags);
f->writeString(s);
sprintf(s, "%d\n", _numLocations);
diff --git a/engines/parallaction/walk.cpp b/engines/parallaction/walk.cpp
index bf8f423fd5..5fd67d26dc 100644
--- a/engines/parallaction/walk.cpp
+++ b/engines/parallaction/walk.cpp
@@ -479,7 +479,7 @@ void PathWalker_BR::finalizeWalk() {
_char.setFoot(foot);
#endif
- _ch->_ani->_frame = _dirFrame; // temporary solution
+ _ch->_ani->setF(_dirFrame); // temporary solution
#if 0
// TODO: support scrolling ;)
@@ -515,7 +515,7 @@ void PathWalker_BR::walk() {
GfxObj *obj = _ch->_ani->gfxobj;
Common::Rect rect;
- obj->getRect(_ch->_ani->_frame, rect);
+ obj->getRect(_ch->_ani->getF(), rect);
uint scale;
if (rect.bottom > _vm->_location._zeta0) {
@@ -609,11 +609,11 @@ void PathWalker_BR::walk() {
if (_fieldC) {
debugC(9, kDebugWalk, "PathWalker_BR::walk, foot moved from (%i, %i) to (%i, %i)\n", _startFoot.x, _startFoot.y, newpos.x, newpos.y);
- _ch->_ani->_frame = walkFrame + _dirFrame + 1;
+ _ch->_ani->setF(walkFrame + _dirFrame + 1);
_startFoot.x = newpos.x;
_startFoot.y = newpos.y;
_ch->setFoot(_startFoot);
- _ch->_ani->_z = newpos.y;
+ _ch->_ani->setZ(newpos.y);
}
if (_fieldC || !_ch->_walkPath.empty()) {
diff --git a/engines/scumm/boxes.cpp b/engines/scumm/boxes.cpp
index 0fa8b579ca..1e632a034e 100644
--- a/engines/scumm/boxes.cpp
+++ b/engines/scumm/boxes.cpp
@@ -544,8 +544,8 @@ bool ScummEngine::checkXYInBoxBounds(int boxnum, int x, int y) {
// Corner case: If the box is a simple line segment, we consider the
// point to be contained "in" (or rather, lying on) the line if it
// is very close to its projection to the line segment.
- if (box.ul == box.ur && box.lr == box.ll ||
- box.ul == box.ll && box.ur == box.lr) {
+ if ((box.ul == box.ur && box.lr == box.ll) ||
+ (box.ul == box.ll && box.ur == box.lr)) {
Common::Point tmp;
tmp = closestPtOnLine(box.ul, box.lr, p);
@@ -803,8 +803,8 @@ bool Actor::findPathTowards(byte box1nr, byte box2nr, byte box3nr, Common::Point
}
if (box1.ul.y > box2.ur.y || box2.ul.y > box1.ur.y ||
- (box1.ur.y == box2.ul.y || box2.ur.y == box1.ul.y) &&
- box1.ul.y != box1.ur.y && box2.ul.y != box2.ur.y) {
+ ((box1.ur.y == box2.ul.y || box2.ur.y == box1.ul.y) &&
+ box1.ul.y != box1.ur.y && box2.ul.y != box2.ur.y)) {
if (flag & 1)
SWAP(box1.ul.y, box1.ur.y);
if (flag & 2)
@@ -858,8 +858,8 @@ bool Actor::findPathTowards(byte box1nr, byte box2nr, byte box3nr, Common::Point
}
if (box1.ul.x > box2.ur.x || box2.ul.x > box1.ur.x ||
- (box1.ur.x == box2.ul.x || box2.ur.x == box1.ul.x) &&
- box1.ul.x != box1.ur.x && box2.ul.x != box2.ur.x) {
+ ((box1.ur.x == box2.ul.x || box2.ur.x == box1.ul.x) &&
+ box1.ul.x != box1.ur.x && box2.ul.x != box2.ur.x)) {
if (flag & 1)
SWAP(box1.ul.x, box1.ur.x);
if (flag & 2)
@@ -1074,8 +1074,8 @@ bool ScummEngine::areBoxesNeighbours(int box1nr, int box2nr) {
}
if (box.ur.y < box2.ul.y ||
box.ul.y > box2.ur.y ||
- (box.ul.y == box2.ur.y ||
- box.ur.y == box2.ul.y) && box2.ur.y != box2.ul.y && box.ul.y != box.ur.y) {
+ ((box.ul.y == box2.ur.y ||
+ box.ur.y == box2.ul.y) && box2.ur.y != box2.ul.y && box.ul.y != box.ur.y)) {
} else {
return true;
}
@@ -1103,8 +1103,8 @@ bool ScummEngine::areBoxesNeighbours(int box1nr, int box2nr) {
}
if (box.ur.x < box2.ul.x ||
box.ul.x > box2.ur.x ||
- (box.ul.x == box2.ur.x ||
- box.ur.x == box2.ul.x) && box2.ur.x != box2.ul.x && box.ul.x != box.ur.x) {
+ ((box.ul.x == box2.ur.x ||
+ box.ur.x == box2.ul.x) && box2.ur.x != box2.ul.x && box.ul.x != box.ur.x)) {
} else {
return true;
diff --git a/engines/scumm/detection.cpp b/engines/scumm/detection.cpp
index 0622e3c5fe..0cc0f3aa1c 100644
--- a/engines/scumm/detection.cpp
+++ b/engines/scumm/detection.cpp
@@ -828,9 +828,10 @@ PluginError ScummMetaEngine::createInstance(OSystem *syst, Engine **engine) cons
// unknown MD5, or with a medium debug level in case of a known MD5 (for
// debugging purposes).
if (!findInMD5Table(res.md5.c_str())) {
- printf("Your game version appears to be unknown. Please, report the following\n");
- printf("data to the ScummVM team along with name of the game you tried to add\n");
- printf("and its version/language/etc.:\n");
+ printf("Your game version appears to be unknown. If this is *NOT* a fan-modified\n");
+ printf("version (in particular, not a fan-made translation), please, report the\n");
+ printf("following data to the ScummVM team along with name of the game you tried\n");
+ printf("to add and its version/language/etc.:\n");
printf(" SCUMM gameid '%s', file '%s', MD5 '%s'\n\n",
res.game.gameid,
diff --git a/engines/scumm/script_v5.cpp b/engines/scumm/script_v5.cpp
index 1d90b5e4af..c5c055249e 100644
--- a/engines/scumm/script_v5.cpp
+++ b/engines/scumm/script_v5.cpp
@@ -1402,7 +1402,7 @@ void ScummEngine_v5::o5_ifClassOfIs() {
while ((_opcode = fetchScriptByte()) != 0xFF) {
cls = getVarOrDirectWord(PARAM_1);
b = getClass(act, cls);
- if (cls & 0x80 && !b || !(cls & 0x80) && b)
+ if (((cls & 0x80) && !b) || (!(cls & 0x80) && b))
cond = false;
}
if (cond)