aboutsummaryrefslogtreecommitdiff
path: root/engines
diff options
context:
space:
mode:
Diffstat (limited to 'engines')
-rw-r--r--engines/agi/agi.cpp34
-rw-r--r--engines/agi/agi.h135
-rw-r--r--engines/agi/console.h1
-rw-r--r--engines/agi/detection.cpp109
-rw-r--r--engines/agi/font.h518
-rw-r--r--engines/agi/global.cpp6
-rw-r--r--engines/agi/graphics.cpp16
-rw-r--r--engines/agi/graphics.h9
-rw-r--r--engines/agi/loader_v2.cpp (renamed from engines/agi/agi_v2.cpp)10
-rw-r--r--engines/agi/loader_v3.cpp (renamed from engines/agi/agi_v3.cpp)8
-rw-r--r--engines/agi/module.mk9
-rw-r--r--engines/agi/picture.cpp635
-rw-r--r--engines/agi/picture.h89
-rw-r--r--engines/agi/preagi.cpp253
-rw-r--r--engines/agi/preagi.h99
-rw-r--r--engines/agi/preagi_common.cpp211
-rw-r--r--engines/agi/preagi_common.h (renamed from engines/parallaction/commands.h)60
-rw-r--r--engines/agi/preagi_mickey.cpp2215
-rw-r--r--engines/agi/preagi_mickey.h809
-rw-r--r--engines/agi/preagi_troll.cpp502
-rw-r--r--engines/agi/preagi_troll.h197
-rw-r--r--engines/agi/preagi_winnie.cpp1127
-rw-r--r--engines/agi/preagi_winnie.h352
-rw-r--r--engines/agi/predictive.cpp3
-rw-r--r--engines/agi/saveload.cpp2
-rw-r--r--engines/agi/sound.cpp1249
-rw-r--r--engines/agi/sound.h323
-rw-r--r--engines/agi/text.cpp2
-rw-r--r--engines/agos/agos.cpp70
-rw-r--r--engines/agos/charset.cpp53
-rw-r--r--engines/agos/cursor.cpp13
-rw-r--r--engines/agos/detection.cpp67
-rw-r--r--engines/agos/detection_tables.h29
-rw-r--r--engines/agos/draw.cpp4
-rw-r--r--engines/agos/gfx.cpp2
-rw-r--r--engines/agos/intern.h5
-rw-r--r--engines/cine/sound.cpp4
-rw-r--r--engines/cine/sound.h4
-rw-r--r--engines/cruise/actor.cpp25
-rw-r--r--engines/cruise/actor.h4
-rw-r--r--engines/cruise/background.cpp7
-rw-r--r--engines/cruise/background.h4
-rw-r--r--engines/cruise/backgroundIncrust.cpp10
-rw-r--r--engines/cruise/backgroundIncrust.h4
-rw-r--r--engines/cruise/cell.cpp4
-rw-r--r--engines/cruise/cell.h4
-rw-r--r--engines/cruise/cruise.cpp4
-rw-r--r--engines/cruise/cruise.h4
-rw-r--r--engines/cruise/cruise_main.cpp433
-rw-r--r--engines/cruise/cruise_main.h4
-rw-r--r--engines/cruise/ctp.cpp13
-rw-r--r--engines/cruise/ctp.h4
-rw-r--r--engines/cruise/dataLoader.cpp4
-rw-r--r--engines/cruise/dataLoader.h4
-rw-r--r--engines/cruise/decompiler.cpp170
-rw-r--r--engines/cruise/delphine-unpack.cpp4
-rw-r--r--engines/cruise/detection.cpp4
-rw-r--r--engines/cruise/font.cpp7
-rw-r--r--engines/cruise/font.h4
-rw-r--r--engines/cruise/fontCharacterTable.cpp4
-rw-r--r--engines/cruise/fontCharacterTable.h4
-rw-r--r--engines/cruise/function.cpp29
-rw-r--r--engines/cruise/function.h4
-rw-r--r--engines/cruise/gfxModule.cpp10
-rw-r--r--engines/cruise/gfxModule.h4
-rw-r--r--engines/cruise/linker.cpp64
-rw-r--r--engines/cruise/linker.h4
-rw-r--r--engines/cruise/mainDraw.cpp54
-rw-r--r--engines/cruise/mainDraw.h4
-rw-r--r--engines/cruise/menu.cpp13
-rw-r--r--engines/cruise/menu.h4
-rw-r--r--engines/cruise/mouse.cpp4
-rw-r--r--engines/cruise/mouse.h4
-rw-r--r--engines/cruise/object.cpp4
-rw-r--r--engines/cruise/object.h4
-rw-r--r--engines/cruise/overlay.cpp25
-rw-r--r--engines/cruise/overlay.h4
-rw-r--r--engines/cruise/perso.cpp4
-rw-r--r--engines/cruise/perso.h4
-rw-r--r--engines/cruise/polys.cpp4
-rw-r--r--engines/cruise/polys.h4
-rw-r--r--engines/cruise/saveload.cpp4
-rw-r--r--engines/cruise/saveload.h4
-rw-r--r--engines/cruise/script.cpp16
-rw-r--r--engines/cruise/script.h4
-rw-r--r--engines/cruise/stack.cpp4
-rw-r--r--engines/cruise/stack.h4
-rw-r--r--engines/cruise/stringSupport.cpp4
-rw-r--r--engines/cruise/stringSupport.h4
-rw-r--r--engines/cruise/various.cpp4
-rw-r--r--engines/cruise/various.h4
-rw-r--r--engines/cruise/vars.cpp4
-rw-r--r--engines/cruise/vars.h4
-rw-r--r--engines/cruise/volume.cpp4
-rw-r--r--engines/cruise/volume.h4
-rw-r--r--engines/drascula/drascula.cpp4095
-rw-r--r--engines/drascula/drascula.h97
-rw-r--r--engines/engine.cpp2
-rw-r--r--engines/gob/cdrom.cpp75
-rw-r--r--engines/gob/cdrom.h7
-rw-r--r--engines/gob/coktelvideo.cpp47
-rw-r--r--engines/gob/dataio.cpp33
-rw-r--r--engines/gob/detection.cpp13
-rw-r--r--engines/gob/driver_vga.cpp21
-rw-r--r--engines/gob/game_v1.cpp17
-rw-r--r--engines/gob/game_v2.cpp2
-rw-r--r--engines/gob/gob.cpp4
-rw-r--r--engines/gob/init.cpp19
-rw-r--r--engines/gob/init_v3.cpp4
-rw-r--r--engines/gob/inter_v2.cpp5
-rw-r--r--engines/gob/map.cpp2
-rw-r--r--engines/gob/map.h26
-rw-r--r--engines/gob/map_v1.cpp5
-rw-r--r--engines/gob/map_v2.cpp12
-rw-r--r--engines/gob/map_v4.cpp158
-rw-r--r--engines/gob/module.mk1
-rw-r--r--engines/gob/mult_v2.cpp27
-rw-r--r--engines/gob/saveload.cpp8
-rw-r--r--engines/gob/saveload.h3
-rw-r--r--engines/gob/saveload_v2.cpp17
-rw-r--r--engines/gob/saveload_v3.cpp37
-rw-r--r--engines/gob/video.cpp8
-rw-r--r--engines/gob/video.h1
-rw-r--r--engines/gob/videoplayer.cpp20
-rw-r--r--engines/kyra/detection.cpp386
-rw-r--r--engines/kyra/gui_v1.cpp8
-rw-r--r--engines/kyra/kyra.cpp9
-rw-r--r--engines/kyra/kyra_v1.cpp6
-rw-r--r--engines/kyra/kyra_v1.h4
-rw-r--r--engines/kyra/kyra_v2.cpp4
-rw-r--r--engines/kyra/kyra_v2.h4
-rw-r--r--engines/kyra/kyra_v3.cpp4
-rw-r--r--engines/kyra/kyra_v3.h4
-rw-r--r--engines/kyra/resource.cpp2
-rw-r--r--engines/kyra/saveload_v1.cpp8
-rw-r--r--engines/kyra/scene.cpp20
-rw-r--r--engines/kyra/scene_v1.cpp6
-rw-r--r--engines/kyra/script.cpp2
-rw-r--r--engines/kyra/script_v1.cpp2
-rw-r--r--engines/kyra/seqplayer.cpp2
-rw-r--r--engines/kyra/sequences_v1.cpp10
-rw-r--r--engines/kyra/sound_v1.cpp4
-rw-r--r--engines/kyra/staticres.cpp4
-rw-r--r--engines/kyra/text_v1.cpp6
-rw-r--r--engines/lure/animseq.cpp8
-rw-r--r--engines/lure/detection.cpp9
-rw-r--r--engines/lure/disk.cpp20
-rw-r--r--engines/lure/fights.cpp13
-rw-r--r--engines/lure/game.cpp253
-rw-r--r--engines/lure/game.h11
-rw-r--r--engines/lure/hotspots.cpp244
-rw-r--r--engines/lure/hotspots.h4
-rw-r--r--engines/lure/intro.cpp61
-rw-r--r--engines/lure/lure.cpp15
-rw-r--r--engines/lure/lure.h1
-rw-r--r--engines/lure/luredefs.h15
-rw-r--r--engines/lure/menu.cpp3
-rw-r--r--engines/lure/res.cpp33
-rw-r--r--engines/lure/res.h3
-rw-r--r--engines/lure/res_struct.cpp134
-rw-r--r--engines/lure/res_struct.h77
-rw-r--r--engines/lure/room.cpp31
-rw-r--r--engines/lure/screen.cpp16
-rw-r--r--engines/lure/screen.h4
-rw-r--r--engines/lure/scripts.cpp79
-rw-r--r--engines/lure/scripts.h10
-rw-r--r--engines/lure/sound.cpp592
-rw-r--r--engines/lure/sound.h121
-rw-r--r--engines/lure/surface.cpp147
-rw-r--r--engines/lure/surface.h5
-rw-r--r--engines/parallaction/animation.cpp683
-rw-r--r--engines/parallaction/callables_ns.cpp99
-rw-r--r--engines/parallaction/commands.cpp351
-rw-r--r--engines/parallaction/debug.cpp4
-rw-r--r--engines/parallaction/detection.cpp39
-rw-r--r--engines/parallaction/dialogue.cpp180
-rw-r--r--engines/parallaction/disk.h90
-rw-r--r--engines/parallaction/disk_br.cpp279
-rw-r--r--engines/parallaction/disk_ns.cpp225
-rw-r--r--engines/parallaction/exec_br.cpp588
-rw-r--r--engines/parallaction/exec_ns.cpp925
-rw-r--r--engines/parallaction/font.cpp167
-rw-r--r--engines/parallaction/graphics.cpp703
-rw-r--r--engines/parallaction/graphics.h206
-rw-r--r--engines/parallaction/inventory.cpp28
-rw-r--r--engines/parallaction/inventory.h2
-rw-r--r--engines/parallaction/location.cpp466
-rw-r--r--engines/parallaction/menu.cpp41
-rw-r--r--engines/parallaction/module.mk13
-rw-r--r--engines/parallaction/objects.cpp408
-rw-r--r--engines/parallaction/objects.h (renamed from engines/parallaction/zone.h)209
-rw-r--r--engines/parallaction/parallaction.cpp538
-rw-r--r--engines/parallaction/parallaction.h698
-rw-r--r--engines/parallaction/parallaction_br.cpp323
-rw-r--r--engines/parallaction/parallaction_ns.cpp328
-rw-r--r--engines/parallaction/parser.cpp38
-rw-r--r--engines/parallaction/parser.h3
-rw-r--r--engines/parallaction/parser_br.cpp935
-rw-r--r--engines/parallaction/parser_ns.cpp1494
-rw-r--r--engines/parallaction/saveload.cpp21
-rw-r--r--engines/parallaction/sound.cpp12
-rw-r--r--engines/parallaction/sound.h4
-rw-r--r--engines/parallaction/staticres.cpp142
-rw-r--r--engines/parallaction/walk.cpp117
-rw-r--r--engines/parallaction/walk.h34
-rw-r--r--engines/parallaction/zone.cpp690
-rw-r--r--engines/queen/cutaway.cpp8
-rw-r--r--engines/queen/display.cpp30
-rw-r--r--engines/queen/display.h3
-rw-r--r--engines/queen/graphics.cpp28
-rw-r--r--engines/queen/graphics.h8
-rw-r--r--engines/queen/musicdata.cpp35
-rw-r--r--engines/queen/resource.cpp16
-rw-r--r--engines/queen/resource.h2
-rw-r--r--engines/queen/restables.cpp3
-rw-r--r--engines/queen/sound.cpp7
-rw-r--r--engines/queen/sound.h9
-rw-r--r--engines/queen/talk.cpp19
-rw-r--r--engines/queen/talk.h14
-rw-r--r--engines/saga/actor.cpp1966
-rw-r--r--engines/saga/actor.h33
-rw-r--r--engines/saga/actor_walk.cpp1942
-rw-r--r--engines/saga/animation.cpp332
-rw-r--r--engines/saga/animation.h25
-rw-r--r--engines/saga/console.cpp96
-rw-r--r--engines/saga/console.h6
-rw-r--r--engines/saga/detection.cpp18
-rw-r--r--engines/saga/detection_tables.h364
-rw-r--r--engines/saga/displayinfo.h31
-rw-r--r--engines/saga/events.cpp38
-rw-r--r--engines/saga/events.h27
-rw-r--r--engines/saga/font.cpp26
-rw-r--r--engines/saga/font.h7
-rw-r--r--engines/saga/gfx.cpp80
-rw-r--r--engines/saga/gfx.h1
-rw-r--r--engines/saga/ihnm_introproc.cpp530
-rw-r--r--engines/saga/input.cpp4
-rw-r--r--engines/saga/interface.cpp286
-rw-r--r--engines/saga/interface.h9
-rw-r--r--engines/saga/ite_introproc.cpp41
-rw-r--r--engines/saga/itedata.h3
-rw-r--r--engines/saga/module.mk1
-rw-r--r--engines/saga/music.cpp17
-rw-r--r--engines/saga/music.h3
-rw-r--r--engines/saga/palanim.cpp2
-rw-r--r--engines/saga/render.cpp9
-rw-r--r--engines/saga/render.h9
-rw-r--r--engines/saga/rscfile.cpp19
-rw-r--r--engines/saga/saga.cpp11
-rw-r--r--engines/saga/saga.h10
-rw-r--r--engines/saga/sagaresnames.h4
-rw-r--r--engines/saga/saveload.cpp27
-rw-r--r--engines/saga/scene.cpp132
-rw-r--r--engines/saga/scene.h14
-rw-r--r--engines/saga/script.cpp14
-rw-r--r--engines/saga/script.h3
-rw-r--r--engines/saga/sfuncs.cpp703
-rw-r--r--engines/saga/sndres.cpp9
-rw-r--r--engines/scumm/actor.cpp12
-rw-r--r--engines/scumm/akos.cpp28
-rw-r--r--engines/scumm/base-costume.cpp4
-rw-r--r--engines/scumm/base-costume.h7
-rw-r--r--engines/scumm/camera.cpp2
-rw-r--r--engines/scumm/charset.cpp43
-rw-r--r--engines/scumm/costume.cpp17
-rw-r--r--engines/scumm/cursor.cpp2
-rw-r--r--engines/scumm/debugger.cpp2
-rw-r--r--engines/scumm/detection.cpp23
-rw-r--r--engines/scumm/detection.h4
-rw-r--r--engines/scumm/detection_tables.h9
-rw-r--r--engines/scumm/dialogs.cpp23
-rw-r--r--engines/scumm/file.cpp1286
-rw-r--r--engines/scumm/file.h44
-rw-r--r--engines/scumm/file_nes.cpp1317
-rw-r--r--engines/scumm/file_nes.h81
-rw-r--r--engines/scumm/gfx.cpp84
-rw-r--r--engines/scumm/gfx.h2
-rw-r--r--engines/scumm/he/animation_he.cpp2
-rw-r--r--engines/scumm/he/floodfill_he.cpp2
-rw-r--r--engines/scumm/he/script_v60he.cpp4
-rw-r--r--engines/scumm/he/sprite_he.cpp2
-rw-r--r--engines/scumm/he/wiz_he.cpp6
-rw-r--r--engines/scumm/imuse_digi/dimuse.h11
-rw-r--r--engines/scumm/imuse_digi/dimuse_codecs.cpp17
-rw-r--r--engines/scumm/imuse_digi/dimuse_tables.cpp38
-rw-r--r--engines/scumm/input.cpp7
-rw-r--r--engines/scumm/insane/insane.cpp2
-rw-r--r--engines/scumm/insane/insane_scenes.cpp5
-rw-r--r--engines/scumm/module.mk1
-rw-r--r--engines/scumm/object.cpp57
-rw-r--r--engines/scumm/player_v2.cpp38
-rw-r--r--engines/scumm/player_v2a.cpp34
-rw-r--r--engines/scumm/resource.cpp2
-rw-r--r--engines/scumm/saveload.cpp2
-rw-r--r--engines/scumm/script_v0.cpp10
-rw-r--r--engines/scumm/script_v2.cpp22
-rw-r--r--engines/scumm/script_v5.cpp4
-rw-r--r--engines/scumm/script_v6.cpp2
-rw-r--r--engines/scumm/scumm-md5.h15
-rw-r--r--engines/scumm/scumm.cpp14
-rw-r--r--engines/scumm/scumm.h3
-rw-r--r--engines/scumm/smush/codec47.cpp17
-rw-r--r--engines/scumm/smush/smush_player.cpp12
-rw-r--r--engines/scumm/string.cpp6
-rw-r--r--engines/scumm/thumbnail.cpp2
-rw-r--r--engines/scumm/verbs.cpp16
-rw-r--r--engines/sky/hufftext.cpp41
-rw-r--r--engines/sky/text.h13
-rw-r--r--engines/sword1/logic.cpp3
-rw-r--r--engines/sword1/router.cpp114
-rw-r--r--engines/sword1/sound.h6
-rw-r--r--engines/sword1/staticres.cpp18
-rw-r--r--engines/touche/detection.cpp4
-rw-r--r--engines/touche/touche.cpp22
314 files changed, 26826 insertions, 12307 deletions
diff --git a/engines/agi/agi.cpp b/engines/agi/agi.cpp
index 1c1c53dee7..bc3cd86e7c 100644
--- a/engines/agi/agi.cpp
+++ b/engines/agi/agi.cpp
@@ -46,8 +46,6 @@
#include "agi/menu.h"
#include "agi/sound.h"
-
-
namespace Agi {
static uint32 g_tickTimer;
@@ -370,7 +368,7 @@ int AgiEngine::agiInit() {
memset(&_game.views[i], 0, sizeof(struct AgiView));
memset(&_game.pictures[i], 0, sizeof(struct AgiPicture));
memset(&_game.logics[i], 0, sizeof(struct AgiLogic));
- memset(&_game.sounds[i], 0, sizeof(struct AgiSound));
+ memset(&_game.sounds[i], 0, sizeof(class AgiSound *)); // _game.sounds contains pointers now
memset(&_game.dirView[i], 0, sizeof(struct AgiDir));
memset(&_game.dirPic[i], 0, sizeof(struct AgiDir));
memset(&_game.dirLogic[i], 0, sizeof(struct AgiDir));
@@ -495,7 +493,7 @@ int AgiEngine::agiDetectGame() {
assert(_gameDescription != NULL);
- if(getVersion() <= 0x2999) {
+ if (getVersion() <= 0x2999) {
_loader = new AgiLoader_v2(this);
} else {
_loader = new AgiLoader_v3(this);
@@ -521,6 +519,7 @@ int AgiEngine::agiLoadResource(int r, int n) {
int i;
i = _loader->loadResource(r, n);
+
return i;
}
@@ -602,7 +601,11 @@ AgiButtonStyle::AgiButtonStyle(Common::RenderMode renderMode) {
setAmigaStyle(renderMode == Common::kRenderAmiga);
}
-AgiEngine::AgiEngine(OSystem *syst) : Engine(syst) {
+AgiBase::AgiBase(OSystem *syst) : Engine(syst) {
+
+}
+
+AgiEngine::AgiEngine(OSystem *syst) : AgiBase(syst) {
// Setup mixer
if (!_mixer->isReady()) {
@@ -677,13 +680,20 @@ void AgiEngine::initialize() {
// drivers, and I'm not sure what they are. For now, they might
// as well be called "PC Speaker" and "Not PC Speaker".
- switch (MidiDriver::detectMusicDriver(MDT_PCSPK)) {
- case MD_PCSPK:
- _soundemu = SOUND_EMU_PC;
- break;
- default:
- _soundemu = SOUND_EMU_NONE;
- break;
+ // If used platform is Apple IIGS then we must use Apple IIGS sound emulation
+ // because Apple IIGS AGI games use only Apple IIGS specific sound resources.
+ if (ConfMan.hasKey("platform") &&
+ Common::parsePlatform(ConfMan.get("platform")) == Common::kPlatformApple2GS) {
+ _soundemu = SOUND_EMU_APPLE2GS;
+ } else {
+ switch (MidiDriver::detectMusicDriver(MDT_PCSPK)) {
+ case MD_PCSPK:
+ _soundemu = SOUND_EMU_PC;
+ break;
+ default:
+ _soundemu = SOUND_EMU_NONE;
+ break;
+ }
}
if (ConfMan.hasKey("render_mode")) {
diff --git a/engines/agi/agi.h b/engines/agi/agi.h
index f37b61478e..dfe149de4f 100644
--- a/engines/agi/agi.h
+++ b/engines/agi/agi.h
@@ -45,8 +45,6 @@ typedef signed int Err;
* Version and other definitions
*/
-#define USE_IIGS_SOUND
-
#define TITLE "AGI engine"
#define DIR_ "dir"
@@ -88,6 +86,29 @@ typedef signed int Err;
#define ADD_PIC 1
#define ADD_VIEW 2
+enum AgiGameID {
+ GID_AGIDEMO,
+ GID_BC,
+ GID_DDP,
+ GID_GOLDRUSH,
+ GID_KQ1,
+ GID_KQ2,
+ GID_KQ3,
+ GID_KQ4,
+ GID_LSL1,
+ GID_MH1,
+ GID_MH2,
+ GID_MIXEDUP,
+ GID_PQ1,
+ GID_SQ1,
+ GID_SQ2,
+ GID_XMASCARD,
+ GID_FANMADE,
+ GID_MICKEY, // PreAGI
+ GID_WINNIE, // PreAGI
+ GID_TROLL // PreAGI
+};
+
} // End of namespace Agi
/* AGI resources */
@@ -100,8 +121,9 @@ typedef signed int Err;
namespace Agi {
enum AgiGameType {
+ GType_PreAGI = 0,
GType_V2 = 1,
- GType_V3
+ GType_V3 = 2
};
enum AgiGameFeatures {
@@ -116,26 +138,6 @@ enum AgiGameFeatures {
GF_ESCPAUSE = (1 << 8)
};
-enum AgiGameID {
- GID_AGIDEMO,
- GID_BC,
- GID_DDP,
- GID_GOLDRUSH,
- GID_KQ1,
- GID_KQ2,
- GID_KQ3,
- GID_KQ4,
- GID_LSL1,
- GID_MH1,
- GID_MH2,
- GID_MIXEDUP,
- GID_PQ1,
- GID_SQ1,
- GID_SQ2,
- GID_XMASCARD,
- GID_FANMADE // TODO: Should this be extended to include all fanmade games?
-};
-
struct AGIGameDescription;
enum {
@@ -527,7 +529,7 @@ struct AgiGame {
AgiPicture pictures[MAX_DIRS]; /**< AGI picture resources */
AgiLogic logics[MAX_DIRS]; /**< AGI logic resources */
AgiView views[MAX_DIRS]; /**< AGI view resources */
- AgiSound sounds[MAX_DIRS]; /**< AGI sound resources */
+ AgiSound *sounds[MAX_DIRS]; /**< Pointers to AGI sound resources */
/* view table */
VtEntry viewTable[MAX_VIEWTABLE];
@@ -538,10 +540,6 @@ struct AgiGame {
};
class AgiLoader {
-private:
- int intVersion;
- AgiEngine *_vm;
-
public:
AgiLoader() {}
@@ -644,7 +642,50 @@ struct StringData {
#define KEY_QUEUE_SIZE 16
-class AgiEngine : public ::Engine {
+class AgiBase : public ::Engine {
+public:
+ AgiButtonStyle _defaultButtonStyle;
+ AgiButtonStyle _buttonStyle;
+ Common::RenderMode _renderMode;
+ volatile uint32 _clockCount;
+ AgiDebug _debug;
+ AgiGame _game;
+ Common::RandomSource *_rnd;
+
+ virtual void agiTimerLow() = 0;
+ virtual int agiGetKeypressLow() = 0;
+ virtual int agiIsKeypressLow() = 0;
+
+ AgiBase(OSystem *syst);
+
+ #define INITIAL_IMAGE_STACK_SIZE 32
+
+ int _stackSize;
+ ImageStackElement *_imageStack;
+ int _imageStackPointer;
+
+ virtual void clearImageStack() = 0;
+ virtual void recordImageStackCall(uint8 type, int16 p1, int16 p2, int16 p3,
+ int16 p4, int16 p5, int16 p6, int16 p7) = 0;
+ virtual void replayImageStackCall(uint8 type, int16 p1, int16 p2, int16 p3,
+ int16 p4, int16 p5, int16 p6, int16 p7) = 0;
+ virtual void releaseImageStack() = 0;
+
+ int _soundemu;
+
+ int getflag(int);
+ void setflag(int, int);
+ void flipflag(int);
+
+ const AGIGameDescription *_gameDescription;
+ uint32 getGameID() const;
+ uint32 getFeatures() const;
+ uint16 getVersion() const;
+ uint16 getGameType() const;
+ Common::Platform getPlatform() const;
+};
+
+class AgiEngine : public AgiBase {
int _gameId;
protected:
@@ -662,12 +703,6 @@ public:
return _gameId;
}
- const AGIGameDescription *_gameDescription;
- uint32 getGameID() const;
- uint32 getFeatures() const;
- uint16 getVersion() const;
- Common::Platform getPlatform() const;
-
private:
int _keyQueue[KEY_QUEUE_SIZE];
@@ -685,15 +720,10 @@ private:
int _firstSlot;
public:
- AgiGame _game;
AgiObject *_objects; /* objects in the game */
StringData _stringdata;
- AgiLoader *_loader; /* loader */
-
- Common::RandomSource *_rnd;
-
const char *getSavegameFilename(int num);
void getSavegameDescription(int num, char *buf, bool showEmpty = true);
int selectSlot();
@@ -704,14 +734,10 @@ public:
int loadGameDialog();
int loadGameSimple();
- volatile uint32 _clockCount;
-
uint8 *_intobj;
int _oldMode;
Menu* _menu;
- AgiButtonStyle _buttonStyle;
- AgiButtonStyle _defaultButtonStyle;
char _lastSentence[40];
@@ -719,12 +745,7 @@ public:
GfxMgr *_gfx;
SoundMgr *_sound;
PictureMgr *_picture;
-
- #define INITIAL_IMAGE_STACK_SIZE 32
-
- int _stackSize;
- ImageStackElement *_imageStack;
- int _imageStackPointer;
+ AgiLoader *_loader; /* loader */
void clearImageStack();
void recordImageStackCall(uint8 type, int16 p1, int16 p2, int16 p3,
@@ -733,10 +754,6 @@ public:
int16 p4, int16 p5, int16 p6, int16 p7);
void releaseImageStack();
- AgiDebug _debug;
- Common::RenderMode _renderMode;
- int _soundemu;
-
int _keyControl;
int _keyAlt;
@@ -752,18 +769,15 @@ public:
int agiUnloadResource(int, int);
void agiUnloadResources();
- void agiTimerLow();
- int agiGetKeypressLow();
- int agiIsKeypressLow();
+ virtual void agiTimerLow();
+ virtual int agiGetKeypressLow();
+ virtual int agiIsKeypressLow();
static void agiTimerFunctionLow(void *refCon);
void initPriTable();
void newInputMode(int);
void oldInputMode();
- int getflag(int);
- void setflag(int, int);
- void flipflag(int);
int getvar(int);
void setvar(int, int);
void decrypt(uint8 * mem, int len);
@@ -811,7 +825,6 @@ public:
int decodeLogic(int);
void unloadLogic(int);
int runLogic(int);
-
void debugConsole(int, int, const char *);
int testIfCode(int);
void executeAgiCommand(uint8, uint8 *);
diff --git a/engines/agi/console.h b/engines/agi/console.h
index ad955d51ae..a6994ce922 100644
--- a/engines/agi/console.h
+++ b/engines/agi/console.h
@@ -31,6 +31,7 @@
namespace Agi {
class AgiEngine;
+class PreAgiEngine;
struct AgiDebug {
int enabled;
diff --git a/engines/agi/detection.cpp b/engines/agi/detection.cpp
index 79e3be3238..afd61ae765 100644
--- a/engines/agi/detection.cpp
+++ b/engines/agi/detection.cpp
@@ -28,9 +28,11 @@
#include "base/plugins.h"
#include "common/advancedDetector.h"
+#include "common/config-manager.h"
#include "common/file.h"
#include "agi/agi.h"
+#include "agi/preagi.h"
#include "agi/wagparser.h"
@@ -45,22 +47,26 @@ struct AGIGameDescription {
uint16 version;
};
-uint32 AgiEngine::getGameID() const {
+uint32 AgiBase::getGameID() const {
return _gameDescription->gameID;
}
-uint32 AgiEngine::getFeatures() const {
+uint32 AgiBase::getFeatures() const {
return _gameDescription->features;
}
-Common::Platform AgiEngine::getPlatform() const {
+Common::Platform AgiBase::getPlatform() const {
return _gameDescription->desc.platform;
}
-uint16 AgiEngine::getVersion() const {
+uint16 AgiBase::getVersion() const {
return _gameDescription->version;
}
+uint16 AgiBase::getGameType() const {
+ return _gameDescription->gameType;
+}
+
}
static const PlainGameDescriptor agiGames[] = {
@@ -76,6 +82,7 @@ static const PlainGameDescriptor agiGames[] = {
{"kq3", "King's Quest III: To Heir Is Human"},
{"kq4", "King's Quest IV: The Perils of Rosella"},
{"lsl1", "Leisure Suit Larry in the Land of the Lounge Lizards"},
+ {"mickey", "Mickey\'s Space Adventure"},
{"mixedup", "Mixed-Up Mother Goose"},
{"mh1", "Manhunter 1: New York"},
{"mh2", "Manhunter 2: San Francisco"},
@@ -87,6 +94,8 @@ static const PlainGameDescriptor agiGames[] = {
{"sq2", "Space Quest II: Vohaul's Revenge"},
{"sqx", "Space Quest X: The Lost Chapter"},
{"tetris", "AGI Tetris"},
+ {"troll", "Troll\'s Tale"},
+ {"winnie", "Winnie the Pooh in the Hundred Acre Wood"},
{"xmascard", "Xmas Card"},
{0, 0}
@@ -1114,6 +1123,23 @@ static const AGIGameDescription gameDescriptions[] = {
0x3149,
},
+ {
+ // Mickey's Space Adventure
+ // Preagi game
+ {
+ "mickey",
+ "",
+ AD_ENTRY1("1.pic", "b6ec04c91a05df374792872c4d4ce66d"),
+ Common::EN_ANY,
+ Common::kPlatformPC,
+ Common::ADGF_NO_FLAGS
+ },
+ GID_MICKEY,
+ GType_PreAGI,
+ 0,
+ 0x0000,
+ },
+
#if 0
{
// Mixed-Up Mother Goose (Amiga) 1.1
@@ -1590,6 +1616,39 @@ static const AGIGameDescription gameDescriptions[] = {
0x2936,
},
+ {
+ // Troll's Tale
+ // preagi game
+ {
+ "troll",
+ "",
+ AD_ENTRY1s("troll.exe", "c594b4d6791e9580d8d5dc9d71760027", 59120),
+ Common::EN_ANY,
+ Common::kPlatformPC,
+ Common::ADGF_NO_FLAGS
+ },
+ GID_TROLL,
+ GType_PreAGI,
+ 0,
+ 0x0000,
+ },
+
+ {
+ // Winnie the Pooh in the Hundred Acre Wood
+ // preagi game
+ {
+ "winnie",
+ "",
+ AD_ENTRY1("title.pic", "2e7900c1ccaa7671d65405f6d1efed30"),
+ Common::EN_ANY,
+ Common::kPlatformPC,
+ Common::ADGF_NO_FLAGS
+ },
+ GID_WINNIE,
+ GType_PreAGI,
+ 0,
+ 0x0000,
+ },
{
// Xmas Card 1986 (PC) [AGI 2.272]
@@ -1865,8 +1924,13 @@ Common::EncapsulatedADGameDesc fallbackDetector(const FSList *fslist) {
// Use the current directory for searching if fslist == NULL
if (fslist == NULL) {
- FilesystemNode fsCurrentDir(".");
- fslistCurrentDir.push_back(fsCurrentDir);
+ Common::String path = ConfMan.get("path").c_str();
+
+ if (path.empty())
+ path = ".";
+
+ FilesystemNode fsCurrentDir(path);
+ fsCurrentDir.getChildren(fslistCurrentDir, FilesystemNode::kListFilesOnly);
fslist = &fslistCurrentDir;
}
@@ -2027,9 +2091,31 @@ static const Common::ADParams detectionParams = {
Common::kADFlagAugmentPreferredTarget
};
-ADVANCED_DETECTOR_DEFINE_PLUGIN(AGI, Agi::AgiEngine, detectionParams);
+bool engineCreateAgi(OSystem *syst, Engine **engine, Common::EncapsulatedADGameDesc encapsulatedDesc) {
+ const Agi::AGIGameDescription *gd = (const Agi::AGIGameDescription *)(encapsulatedDesc.realDesc);
+ bool res = true;
+
+ switch (gd->gameType) {
+ case Agi::GType_PreAGI:
+ *engine = new Agi::PreAgiEngine(syst);
+ break;
+ case Agi::GType_V2:
+ *engine = new Agi::AgiEngine(syst);
+ break;
+ case Agi::GType_V3:
+ *engine = new Agi::AgiEngine(syst);
+ break;
+ default:
+ res = false;
+ error("AGI engine: unknown gameType");
+ }
+
+ return res;
+}
-REGISTER_PLUGIN(AGI, "AGI v2 + v3 Engine", "Sierra AGI Engine (C) Sierra On-Line Software");
+ADVANCED_DETECTOR_DEFINE_PLUGIN_WITH_COMPLEX_CREATION(AGI, engineCreateAgi, detectionParams);
+
+REGISTER_PLUGIN(AGI, "AGI preAGI + v2 + v3 Engine", "Sierra AGI Engine (C) Sierra On-Line Software");
namespace Agi {
@@ -2040,5 +2126,12 @@ bool AgiEngine::initGame() {
return (_gameDescription != 0);
}
+bool PreAgiEngine::initGame() {
+ Common::EncapsulatedADGameDesc encapsulatedDesc = Common::AdvancedDetector::detectBestMatchingGame(detectionParams);
+ _gameDescription = (const AGIGameDescription *)(encapsulatedDesc.realDesc);
+
+ return (_gameDescription != 0);
+}
+
} // End of namespace Agi
diff --git a/engines/agi/font.h b/engines/agi/font.h
index 12b36f2520..1bf61878ec 100644
--- a/engines/agi/font.h
+++ b/engines/agi/font.h
@@ -294,6 +294,524 @@ static const uint8 curFont[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x7E, 0x00
};
+static const uint8 mickey_fontdata[] = {
+ 0x00, 0x36, 0x7F, 0x7F, 0x3E, 0x1C, 0x08, 0x00,
+ 0x00, 0x00, 0x3F, 0x20, 0x2F, 0x28, 0x28, 0x28,
+ 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28,
+ 0x28, 0x28, 0x2F, 0x20, 0x2F, 0x28, 0x28, 0x28,
+ 0x28, 0x28, 0x2F, 0x20, 0x3F, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0xFF, 0x00, 0xEF, 0x28, 0x28, 0x28,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x28, 0x28, 0xEF, 0x00, 0xEF, 0x28, 0x28, 0x28,
+ 0x28, 0x28, 0xEF, 0x00, 0xFF, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0xF8, 0x08, 0xE8, 0x28, 0x28, 0x28,
+ 0x28, 0x28, 0xE8, 0x08, 0xE8, 0x28, 0x28, 0x28,
+ 0x28, 0x28, 0xE8, 0x08, 0xF8, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x10, 0x10, 0x10,
+ 0x10, 0x10, 0xFF, 0x00, 0xFF, 0x10, 0x10, 0x10,
+ 0x10, 0x10, 0xFF, 0x00, 0xFF, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00,
+ 0x10, 0x10, 0x10, 0xFF, 0x10, 0x10, 0x10, 0x10,
+ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+ 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F,
+ 0x18, 0x18, 0x18, 0x1F, 0x1F, 0x00, 0x00, 0x00,
+ 0x78, 0x60, 0x78, 0x60, 0x7E, 0x18, 0x1E, 0x00,
+ 0x00, 0x18, 0x3C, 0x7E, 0x18, 0x18, 0x18, 0x00,
+ 0x00, 0x18, 0x18, 0x18, 0x7E, 0x3C, 0x18, 0x00,
+ 0x00, 0x18, 0x30, 0x7E, 0x30, 0x18, 0x00, 0x00,
+ 0x00, 0x18, 0x0C, 0x7E, 0x0C, 0x18, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x18, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x00,
+ 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x66, 0xFF, 0x66, 0x66, 0xFF, 0x66, 0x00,
+ 0x18, 0x3E, 0x60, 0x3C, 0x06, 0x7C, 0x18, 0x00,
+ 0x00, 0x66, 0x6C, 0x18, 0x30, 0x66, 0x46, 0x00,
+ 0x1C, 0x36, 0x1C, 0x38, 0x6F, 0x66, 0x3B, 0x00,
+ 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x0E, 0x1C, 0x18, 0x18, 0x18, 0x1C, 0x0E, 0x00,
+ 0x70, 0x38, 0x18, 0x18, 0x18, 0x38, 0x70, 0x00,
+ 0x00, 0x66, 0x3C, 0xFF, 0x3C, 0x66, 0x00, 0x00,
+ 0x00, 0x18, 0x18, 0x7E, 0x18, 0x18, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x30,
+ 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00,
+ 0x02, 0x06, 0x0C, 0x18, 0x30, 0x60, 0x40, 0x00,
+ 0x3C, 0x66, 0x6E, 0x7E, 0x76, 0x66, 0x3C, 0x00,
+ 0x18, 0x38, 0x18, 0x18, 0x18, 0x18, 0x7E, 0x00,
+ 0x3C, 0x66, 0x06, 0x0C, 0x18, 0x30, 0x7E, 0x00,
+ 0x7E, 0x0C, 0x18, 0x0C, 0x06, 0x66, 0x3C, 0x00,
+ 0x0C, 0x1C, 0x3C, 0x6C, 0x6C, 0x7E, 0x0C, 0x00,
+ 0x7E, 0x60, 0x7C, 0x06, 0x06, 0x66, 0x3C, 0x00,
+ 0x3C, 0x60, 0x60, 0x7C, 0x66, 0x66, 0x3C, 0x00,
+ 0x7E, 0x06, 0x0C, 0x18, 0x30, 0x30, 0x30, 0x00,
+ 0x3C, 0x66, 0x66, 0x3C, 0x66, 0x66, 0x3C, 0x00,
+ 0x3C, 0x66, 0x66, 0x3E, 0x06, 0x0C, 0x38, 0x00,
+ 0x00, 0x18, 0x18, 0x00, 0x00, 0x18, 0x18, 0x00,
+ 0x00, 0x18, 0x18, 0x00, 0x00, 0x18, 0x18, 0x30,
+ 0x06, 0x0C, 0x18, 0x30, 0x18, 0x0C, 0x06, 0x00,
+ 0x00, 0x00, 0x7E, 0x00, 0x00, 0x7E, 0x00, 0x00,
+ 0x60, 0x30, 0x18, 0x0C, 0x18, 0x30, 0x60, 0x00,
+ 0x3C, 0x66, 0x04, 0x0C, 0x18, 0x00, 0x18, 0x00,
+ 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x18, 0x3C, 0x66, 0x66, 0x7E, 0x66, 0x66, 0x00,
+ 0x7C, 0x66, 0x66, 0x7C, 0x66, 0x66, 0x7C, 0x00,
+ 0x3C, 0x66, 0x60, 0x60, 0x60, 0x66, 0x3C, 0x00,
+ 0x78, 0x6C, 0x66, 0x66, 0x66, 0x6C, 0x78, 0x00,
+ 0x7E, 0x60, 0x60, 0x7C, 0x60, 0x60, 0x7E, 0x00,
+ 0x7E, 0x60, 0x60, 0x7C, 0x60, 0x60, 0x60, 0x00,
+ 0x3E, 0x60, 0x60, 0x6E, 0x66, 0x66, 0x3E, 0x00,
+ 0x66, 0x66, 0x66, 0x7E, 0x66, 0x66, 0x66, 0x00,
+ 0x7E, 0x18, 0x18, 0x18, 0x18, 0x18, 0x7E, 0x00,
+ 0x06, 0x06, 0x06, 0x06, 0x06, 0x66, 0x3C, 0x00,
+ 0x66, 0x6C, 0x78, 0x78, 0x6C, 0x66, 0x66, 0x00,
+ 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x7E, 0x00,
+ 0x63, 0x77, 0x7F, 0x6B, 0x63, 0x63, 0x63, 0x00,
+ 0x66, 0x76, 0x7E, 0x7E, 0x6E, 0x66, 0x66, 0x00,
+ 0x3C, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3C, 0x00,
+ 0x7C, 0x66, 0x66, 0x66, 0x7C, 0x60, 0x60, 0x00,
+ 0x3C, 0x66, 0x66, 0x66, 0x66, 0x6C, 0x36, 0x00,
+ 0x7C, 0x66, 0x66, 0x7C, 0x6C, 0x66, 0x66, 0x00,
+ 0x3C, 0x60, 0x60, 0x3C, 0x06, 0x06, 0x3C, 0x00,
+ 0x7E, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00,
+ 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x7E, 0x00,
+ 0x66, 0x66, 0x66, 0x66, 0x66, 0x3C, 0x18, 0x00,
+ 0x63, 0x63, 0x63, 0x6B, 0x7F, 0x77, 0x63, 0x00,
+ 0x66, 0x66, 0x3C, 0x3C, 0x66, 0x66, 0x66, 0x00,
+ 0x66, 0x66, 0x66, 0x3C, 0x18, 0x18, 0x18, 0x00,
+ 0x7E, 0x0C, 0x18, 0x30, 0x60, 0x60, 0x7E, 0x00,
+ 0x1E, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1E, 0x00,
+ 0x00, 0x40, 0x60, 0x30, 0x18, 0x0C, 0x06, 0x00,
+ 0x78, 0x18, 0x18, 0x18, 0x18, 0x18, 0x78, 0x00,
+ 0x00, 0x08, 0x1C, 0x36, 0x63, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00,
+ 0x00, 0x18, 0x3C, 0x7E, 0x7E, 0x3C, 0x18, 0x00,
+ 0x00, 0x00, 0x3C, 0x06, 0x3E, 0x66, 0x3E, 0x00,
+ 0x60, 0x60, 0x7C, 0x66, 0x66, 0x66, 0x7C, 0x00,
+ 0x00, 0x00, 0x3C, 0x60, 0x60, 0x60, 0x3C, 0x00,
+ 0x06, 0x06, 0x3E, 0x66, 0x66, 0x66, 0x3E, 0x00,
+ 0x00, 0x00, 0x3C, 0x66, 0x7E, 0x60, 0x3C, 0x00,
+ 0x0E, 0x18, 0x18, 0x3E, 0x18, 0x18, 0x18, 0x00,
+ 0x00, 0x00, 0x3E, 0x66, 0x66, 0x3E, 0x06, 0x7C,
+ 0x60, 0x60, 0x7C, 0x66, 0x66, 0x66, 0x66, 0x00,
+ 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x3C, 0x00,
+ 0x06, 0x00, 0x06, 0x06, 0x06, 0x06, 0x06, 0x3C,
+ 0x60, 0x60, 0x6C, 0x78, 0x6C, 0x66, 0x66, 0x00,
+ 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x00,
+ 0x00, 0x00, 0x66, 0x7F, 0x7F, 0x6B, 0x63, 0x00,
+ 0x00, 0x00, 0x7C, 0x66, 0x66, 0x66, 0x66, 0x00,
+ 0x00, 0x00, 0x3C, 0x66, 0x66, 0x66, 0x3C, 0x00,
+ 0x00, 0x00, 0x7C, 0x66, 0x66, 0x7C, 0x60, 0x60,
+ 0x00, 0x00, 0x3E, 0x66, 0x66, 0x3E, 0x06, 0x06,
+ 0x00, 0x00, 0x7C, 0x66, 0x60, 0x60, 0x60, 0x00,
+ 0x00, 0x00, 0x3E, 0x60, 0x3C, 0x06, 0x7C, 0x00,
+ 0x18, 0x18, 0x7E, 0x18, 0x18, 0x18, 0x0E, 0x00,
+ 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x3E, 0x00,
+ 0x00, 0x00, 0x66, 0x66, 0x66, 0x3C, 0x18, 0x00,
+ 0x00, 0x00, 0x63, 0x6B, 0x7F, 0x3E, 0x36, 0x00,
+ 0x00, 0x00, 0x66, 0x3C, 0x18, 0x3C, 0x66, 0x00,
+ 0x00, 0x00, 0x66, 0x66, 0x66, 0x3E, 0x0C, 0x78,
+ 0x00, 0x00, 0x7E, 0x0C, 0x18, 0x30, 0x7E, 0x00,
+ 0x00, 0x18, 0x3C, 0x7E, 0x7E, 0x18, 0x3C, 0x00,
+ 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+ 0x00, 0x7E, 0x78, 0x7C, 0x6E, 0x66, 0x06, 0x00,
+ 0x08, 0x18, 0x38, 0x78, 0x38, 0x18, 0x08, 0x00,
+ 0x10, 0x18, 0x1C, 0x1E, 0x1C, 0x18, 0x10, 0x00,
+ 0xFF, 0xC9, 0x80, 0x80, 0xC1, 0xE3, 0xF7, 0xFF,
+ 0xFF, 0xFF, 0xC0, 0xDF, 0xD0, 0xD7, 0xD7, 0xD7,
+ 0xD7, 0xD7, 0xD7, 0xD7, 0xD7, 0xD7, 0xD7, 0xD7,
+ 0xD7, 0xD7, 0xD0, 0xDF, 0xD0, 0xD7, 0xD7, 0xD7,
+ 0xD7, 0xD7, 0xD0, 0xDF, 0xC0, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0x00, 0xFF, 0x10, 0xD7, 0xD7, 0xD7,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xD7, 0xD7, 0x10, 0xFF, 0x10, 0xD7, 0xD7, 0xD7,
+ 0xD7, 0xD7, 0x10, 0xFF, 0x00, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0x07, 0xF7, 0x17, 0xD7, 0xD7, 0xD7,
+ 0xD7, 0xD7, 0x17, 0xF7, 0x17, 0xD7, 0xD7, 0xD7,
+ 0xD7, 0xD7, 0x17, 0xF7, 0x07, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0x00, 0xFF, 0x00, 0xEF, 0xEF, 0xEF,
+ 0xEF, 0xEF, 0x00, 0xFF, 0x00, 0xEF, 0xEF, 0xEF,
+ 0xEF, 0xEF, 0x00, 0xFF, 0x00, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xEF, 0xEF, 0xEF, 0x00, 0xEF, 0xEF, 0xEF, 0xEF,
+ 0xEF, 0xEF, 0xEF, 0xEF, 0xEF, 0xEF, 0xEF, 0xEF,
+ 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0,
+ 0x18, 0x18, 0x18, 0x1F, 0x1F, 0x00, 0x00, 0x00,
+ 0x78, 0x60, 0x78, 0x60, 0x7E, 0x18, 0x1E, 0x00,
+ 0x00, 0x18, 0x3C, 0x7E, 0x18, 0x18, 0x18, 0x00,
+ 0x00, 0x18, 0x18, 0x18, 0x7E, 0x3C, 0x18, 0x00,
+ 0x00, 0x18, 0x30, 0x7E, 0x30, 0x18, 0x00, 0x00,
+ 0x00, 0x18, 0x0C, 0x7E, 0x0C, 0x18, 0x00, 0x00,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xE7, 0xE7, 0xE7, 0xE7, 0xFF, 0xE7, 0xE7, 0xFF,
+ 0x99, 0x99, 0x99, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0x99, 0x00, 0x99, 0x99, 0x00, 0x99, 0xFF,
+ 0xE7, 0xC1, 0x9F, 0xC3, 0xF9, 0x83, 0xE7, 0xFF,
+ 0xFF, 0x99, 0x93, 0xE7, 0xCF, 0x99, 0xB9, 0xFF,
+ 0xE3, 0xC9, 0xE3, 0xC7, 0x90, 0x99, 0xC4, 0xFF,
+ 0xE7, 0xE7, 0xE7, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xF1, 0xE3, 0xE7, 0xE7, 0xE7, 0xE3, 0xF1, 0xFF,
+ 0x8F, 0xC7, 0xE7, 0xE7, 0xE7, 0xC7, 0x8F, 0xFF,
+ 0xFF, 0x99, 0xC3, 0x00, 0xC3, 0x99, 0xFF, 0xFF,
+ 0xFF, 0xE7, 0xE7, 0x81, 0xE7, 0xE7, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE7, 0xE7, 0xCF,
+ 0xFF, 0xFF, 0xFF, 0x81, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE7, 0xE7, 0xFF,
+ 0xFD, 0xF9, 0xF3, 0xE7, 0xCF, 0x9F, 0xBF, 0xFF,
+ 0xC3, 0x99, 0x91, 0x81, 0x89, 0x99, 0xC3, 0xFF,
+ 0xE7, 0xC7, 0xE7, 0xE7, 0xE7, 0xE7, 0x81, 0xFF,
+ 0xC3, 0x99, 0xF9, 0xF3, 0xE7, 0xCF, 0x81, 0xFF,
+ 0x81, 0xF3, 0xE7, 0xF3, 0xF9, 0x99, 0xC3, 0xFF,
+ 0xF3, 0xE3, 0xC3, 0x93, 0x93, 0x81, 0xF3, 0xFF,
+ 0x81, 0x9F, 0x83, 0xF9, 0xF9, 0x99, 0xC3, 0xFF,
+ 0xC3, 0x9F, 0x9F, 0x83, 0x99, 0x99, 0xC3, 0xFF,
+ 0x81, 0xF9, 0xF3, 0xE7, 0xCF, 0xCF, 0xCF, 0xFF,
+ 0xC3, 0x99, 0x99, 0xC3, 0x99, 0x99, 0xC3, 0xFF,
+ 0xC3, 0x99, 0x99, 0xC1, 0xF9, 0xF3, 0xC7, 0xFF,
+ 0xFF, 0xE7, 0xE7, 0xFF, 0xFF, 0xE7, 0xE7, 0xFF,
+ 0xFF, 0xE7, 0xE7, 0xFF, 0xFF, 0xE7, 0xE7, 0xCF,
+ 0xF9, 0xF3, 0xE7, 0xCF, 0xE7, 0xF3, 0xF9, 0xFF,
+ 0xFF, 0xFF, 0x81, 0xFF, 0xFF, 0x81, 0xFF, 0xFF,
+ 0x9F, 0xCF, 0xE7, 0xF3, 0xE7, 0xCF, 0x9F, 0xFF,
+ 0xC3, 0x99, 0xFB, 0xF3, 0xE7, 0xFF, 0xE7, 0xFF,
+ 0xC3, 0x99, 0x99, 0x91, 0x91, 0x9F, 0xC1, 0xFF,
+ 0xE7, 0xC3, 0x99, 0x99, 0x81, 0x99, 0x99, 0xFF,
+ 0x83, 0x99, 0x99, 0x83, 0x99, 0x99, 0x83, 0xFF,
+ 0xC3, 0x99, 0x9F, 0x9F, 0x9F, 0x99, 0xC3, 0xFF,
+ 0x87, 0x93, 0x99, 0x99, 0x99, 0x93, 0x87, 0xFF,
+ 0x81, 0x9F, 0x9F, 0x83, 0x9F, 0x9F, 0x81, 0xFF,
+ 0x81, 0x9F, 0x9F, 0x83, 0x9F, 0x9F, 0x9F, 0xFF,
+ 0xC1, 0x9F, 0x9F, 0x91, 0x99, 0x99, 0xC1, 0xFF,
+ 0x99, 0x99, 0x99, 0x81, 0x99, 0x99, 0x99, 0xFF,
+ 0x81, 0xE7, 0xE7, 0xE7, 0xE7, 0xE7, 0x81, 0xFF,
+ 0xF9, 0xF9, 0xF9, 0xF9, 0xF9, 0x99, 0xC3, 0xFF,
+ 0x99, 0x93, 0x87, 0x87, 0x93, 0x99, 0x99, 0xFF,
+ 0x9F, 0x9F, 0x9F, 0x9F, 0x9F, 0x9F, 0x81, 0xFF,
+ 0x9C, 0x88, 0x80, 0x94, 0x9C, 0x9C, 0x9C, 0xFF,
+ 0x99, 0x89, 0x81, 0x81, 0x91, 0x99, 0x99, 0xFF,
+ 0xC3, 0x99, 0x99, 0x99, 0x99, 0x99, 0xC3, 0xFF,
+ 0x83, 0x99, 0x99, 0x99, 0x83, 0x9F, 0x9F, 0xFF,
+ 0xC3, 0x99, 0x99, 0x99, 0x99, 0x93, 0xC9, 0xFF,
+ 0x83, 0x99, 0x99, 0x83, 0x93, 0x99, 0x99, 0xFF,
+ 0xC3, 0x9F, 0x9F, 0xC3, 0xF9, 0xF9, 0xC3, 0xFF,
+ 0x81, 0xE7, 0xE7, 0xE7, 0xE7, 0xE7, 0xE7, 0xFF,
+ 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x81, 0xFF,
+ 0x99, 0x99, 0x99, 0x99, 0x99, 0xC3, 0xE7, 0xFF,
+ 0x9C, 0x9C, 0x9C, 0x94, 0x80, 0x88, 0x9C, 0xFF,
+ 0x99, 0x99, 0xC3, 0xC3, 0x99, 0x99, 0x99, 0xFF,
+ 0x99, 0x99, 0x99, 0xC3, 0xE7, 0xE7, 0xE7, 0xFF,
+ 0x81, 0xF3, 0xE7, 0xCF, 0x9F, 0x9F, 0x81, 0xFF,
+ 0xE1, 0xE7, 0xE7, 0xE7, 0xE7, 0xE7, 0xE1, 0xFF,
+ 0xFF, 0xBF, 0x9F, 0xCF, 0xE7, 0xF3, 0xF9, 0xFF,
+ 0x87, 0xE7, 0xE7, 0xE7, 0xE7, 0xE7, 0x87, 0xFF,
+ 0xFF, 0xF7, 0xE3, 0xC9, 0x9C, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0xFF,
+ 0x00, 0x18, 0x3C, 0x7E, 0x7E, 0x3C, 0x18, 0x00,
+ 0xFF, 0xFF, 0xC3, 0xF9, 0xC1, 0x99, 0xC1, 0xFF,
+ 0x9F, 0x9F, 0x83, 0x99, 0x99, 0x99, 0x83, 0xFF,
+ 0xFF, 0xFF, 0xC3, 0x9F, 0x9F, 0x9F, 0xC3, 0xFF,
+ 0xF9, 0xF9, 0xC1, 0x99, 0x99, 0x99, 0xC1, 0xFF,
+ 0xFF, 0xFF, 0xC3, 0x99, 0x81, 0x9F, 0xC3, 0xFF,
+ 0xF1, 0xE7, 0xE7, 0xC1, 0xE7, 0xE7, 0xE7, 0xFF,
+ 0xFF, 0xFF, 0xC1, 0x99, 0x99, 0xC1, 0xF9, 0x83,
+ 0x9F, 0x9F, 0x83, 0x99, 0x99, 0x99, 0x99, 0xFF,
+ 0xE7, 0xFF, 0xC7, 0xE7, 0xE7, 0xE7, 0xC3, 0xFF,
+ 0xF9, 0xFF, 0xF9, 0xF9, 0xF9, 0xF9, 0xF9, 0xC3,
+ 0x9F, 0x9F, 0x93, 0x87, 0x93, 0x99, 0x99, 0xFF,
+ 0xC7, 0xE7, 0xE7, 0xE7, 0xE7, 0xE7, 0xC3, 0xFF,
+ 0xFF, 0xFF, 0x99, 0x80, 0x80, 0x94, 0x9C, 0xFF,
+ 0xFF, 0xFF, 0x83, 0x99, 0x99, 0x99, 0x99, 0xFF,
+ 0xFF, 0xFF, 0xC3, 0x99, 0x99, 0x99, 0xC3, 0xFF,
+ 0xFF, 0xFF, 0x83, 0x99, 0x99, 0x83, 0x9F, 0x9F,
+ 0xFF, 0xFF, 0xC1, 0x99, 0x99, 0xC1, 0xF9, 0xF9,
+ 0xFF, 0xFF, 0x83, 0x99, 0x9F, 0x9F, 0x9F, 0xFF,
+ 0xFF, 0xFF, 0xC1, 0x9F, 0xC3, 0xF9, 0x83, 0xFF,
+ 0xE7, 0xE7, 0x81, 0xE7, 0xE7, 0xE7, 0xF1, 0xFF,
+ 0xFF, 0xFF, 0x99, 0x99, 0x99, 0x99, 0xC1, 0xFF,
+ 0xFF, 0xFF, 0x99, 0x99, 0x99, 0xC3, 0xE7, 0xFF,
+ 0xFF, 0xFF, 0x9C, 0x94, 0x80, 0xC1, 0xC9, 0xFF,
+ 0xFF, 0xFF, 0x99, 0xC3, 0xE7, 0xC3, 0x99, 0xFF,
+ 0xFF, 0xFF, 0x99, 0x99, 0x99, 0xC1, 0xF3, 0x87,
+ 0xFF, 0xFF, 0x81, 0xF3, 0xE7, 0xCF, 0x81, 0xFF,
+ 0x00, 0x18, 0x3C, 0x7E, 0x7E, 0x18, 0x3C, 0x00,
+ 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+ 0x00, 0x7E, 0x78, 0x7C, 0x6E, 0x66, 0x06, 0x00,
+ 0x08, 0x18, 0x38, 0x78, 0x38, 0x18, 0x08, 0x00,
+ 0x10, 0x18, 0x1C, 0x1E, 0x1C, 0x18, 0x10, 0x00,
+};
+
+static const uint8 ibm_fontdata[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x7E, 0x81, 0xA5, 0x81, 0xBD, 0x99, 0x81, 0x7E,
+ 0x7E, 0xFF, 0xDB, 0xFF, 0xC3, 0xE7, 0xFF, 0x7E,
+ 0x6C, 0xFE, 0xFE, 0xFE, 0x7C, 0x38, 0x10, 0x00,
+ 0x10, 0x38, 0x7C, 0xFE, 0x7C, 0x38, 0x10, 0x00,
+ 0x38, 0x7C, 0x38, 0xFE, 0xFE, 0x7C, 0x38, 0x7C,
+ 0x10, 0x10, 0x38, 0x7C, 0xFE, 0x7C, 0x38, 0x7C,
+ 0x00, 0x00, 0x18, 0x3C, 0x3C, 0x18, 0x00, 0x00,
+ 0xFF, 0xFF, 0xE7, 0xC3, 0xC3, 0xE7, 0xFF, 0xFF,
+ 0x00, 0x3C, 0x66, 0x42, 0x42, 0x66, 0x3C, 0x00,
+ 0xFF, 0xC3, 0x99, 0xBD, 0xBD, 0x99, 0xC3, 0xFF,
+ 0x0F, 0x07, 0x0F, 0x7D, 0xCC, 0xCC, 0xCC, 0x78,
+ 0x3C, 0x66, 0x66, 0x66, 0x3C, 0x18, 0x7E, 0x18,
+ 0x3F, 0x33, 0x3F, 0x30, 0x30, 0x70, 0xF0, 0xE0,
+ 0x7F, 0x63, 0x7F, 0x63, 0x63, 0x67, 0xE6, 0xC0,
+ 0x99, 0x5A, 0x3C, 0xE7, 0xE7, 0x3C, 0x5A, 0x99,
+ 0x80, 0xE0, 0xF8, 0xFE, 0xF8, 0xE0, 0x80, 0x00,
+ 0x02, 0x0E, 0x3E, 0xFE, 0x3E, 0x0E, 0x02, 0x00,
+ 0x18, 0x3C, 0x7E, 0x18, 0x18, 0x7E, 0x3C, 0x18,
+ 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x66, 0x00,
+ 0x7F, 0xDB, 0xDB, 0x7B, 0x1B, 0x1B, 0x1B, 0x00,
+ 0x3E, 0x63, 0x38, 0x6C, 0x6C, 0x38, 0xCC, 0x78,
+ 0x00, 0x00, 0x00, 0x00, 0x7E, 0x7E, 0x7E, 0x00,
+ 0x18, 0x3C, 0x7E, 0x18, 0x7E, 0x3C, 0x18, 0xFF,
+ 0x18, 0x3C, 0x7E, 0x18, 0x18, 0x18, 0x18, 0x00,
+ 0x18, 0x18, 0x18, 0x18, 0x7E, 0x3C, 0x18, 0x00,
+ 0x00, 0x18, 0x0C, 0xFE, 0x0C, 0x18, 0x00, 0x00,
+ 0x00, 0x30, 0x60, 0xFE, 0x60, 0x30, 0x00, 0x00,
+ 0x00, 0x00, 0xC0, 0xC0, 0xC0, 0xFE, 0x00, 0x00,
+ 0x00, 0x24, 0x66, 0xFF, 0x66, 0x24, 0x00, 0x00,
+ 0x00, 0x18, 0x3C, 0x7E, 0xFF, 0xFF, 0x00, 0x00,
+ 0x00, 0xFF, 0xFF, 0x7E, 0x3C, 0x18, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x30, 0x78, 0x78, 0x30, 0x30, 0x00, 0x30, 0x00,
+ 0x6C, 0x6C, 0x6C, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x6C, 0x6C, 0xFE, 0x6C, 0xFE, 0x6C, 0x6C, 0x00,
+ 0x30, 0x7C, 0xC0, 0x78, 0x0C, 0xF8, 0x30, 0x00,
+ 0x00, 0xC6, 0xCC, 0x18, 0x30, 0x66, 0xC6, 0x00,
+ 0x38, 0x6C, 0x38, 0x76, 0xDC, 0xCC, 0x76, 0x00,
+ 0x60, 0x60, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x18, 0x30, 0x60, 0x60, 0x60, 0x30, 0x18, 0x00,
+ 0x60, 0x30, 0x18, 0x18, 0x18, 0x30, 0x60, 0x00,
+ 0x00, 0x66, 0x3C, 0xFF, 0x3C, 0x66, 0x00, 0x00,
+ 0x00, 0x30, 0x30, 0xFC, 0x30, 0x30, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 0x60,
+ 0x00, 0x00, 0x00, 0xFC, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 0x00,
+ 0x06, 0x0C, 0x18, 0x30, 0x60, 0xC0, 0x80, 0x00,
+ 0x7C, 0xC6, 0xCE, 0xDE, 0xF6, 0xE6, 0x7C, 0x00,
+ 0x30, 0x70, 0x30, 0x30, 0x30, 0x30, 0xFC, 0x00,
+ 0x78, 0xCC, 0x0C, 0x38, 0x60, 0xCC, 0xFC, 0x00,
+ 0x78, 0xCC, 0x0C, 0x38, 0x0C, 0xCC, 0x78, 0x00,
+ 0x1C, 0x3C, 0x6C, 0xCC, 0xFE, 0x0C, 0x1E, 0x00,
+ 0xFC, 0xC0, 0xF8, 0x0C, 0x0C, 0xCC, 0x78, 0x00,
+ 0x38, 0x60, 0xC0, 0xF8, 0xCC, 0xCC, 0x78, 0x00,
+ 0xFC, 0xCC, 0x0C, 0x18, 0x30, 0x30, 0x30, 0x00,
+ 0x78, 0xCC, 0xCC, 0x78, 0xCC, 0xCC, 0x78, 0x00,
+ 0x78, 0xCC, 0xCC, 0x7C, 0x0C, 0x18, 0x70, 0x00,
+ 0x00, 0x30, 0x30, 0x00, 0x00, 0x30, 0x30, 0x00,
+ 0x00, 0x30, 0x30, 0x00, 0x00, 0x30, 0x30, 0x60,
+ 0x18, 0x30, 0x60, 0xC0, 0x60, 0x30, 0x18, 0x00,
+ 0x00, 0x00, 0xFC, 0x00, 0x00, 0xFC, 0x00, 0x00,
+ 0x60, 0x30, 0x18, 0x0C, 0x18, 0x30, 0x60, 0x00,
+ 0x78, 0xCC, 0x0C, 0x18, 0x30, 0x00, 0x30, 0x00,
+ 0x7C, 0xC6, 0xDE, 0xDE, 0xDE, 0xC0, 0x78, 0x00,
+ 0x30, 0x78, 0xCC, 0xCC, 0xFC, 0xCC, 0xCC, 0x00,
+ 0xFC, 0x66, 0x66, 0x7C, 0x66, 0x66, 0xFC, 0x00,
+ 0x3C, 0x66, 0xC0, 0xC0, 0xC0, 0x66, 0x3C, 0x00,
+ 0xF8, 0x6C, 0x66, 0x66, 0x66, 0x6C, 0xF8, 0x00,
+ 0xFE, 0x62, 0x68, 0x78, 0x68, 0x62, 0xFE, 0x00,
+ 0xFE, 0x62, 0x68, 0x78, 0x68, 0x60, 0xF0, 0x00,
+ 0x3C, 0x66, 0xC0, 0xC0, 0xCE, 0x66, 0x3E, 0x00,
+ 0xCC, 0xCC, 0xCC, 0xFC, 0xCC, 0xCC, 0xCC, 0x00,
+ 0x78, 0x30, 0x30, 0x30, 0x30, 0x30, 0x78, 0x00,
+ 0x1E, 0x0C, 0x0C, 0x0C, 0xCC, 0xCC, 0x78, 0x00,
+ 0xE6, 0x66, 0x6C, 0x78, 0x6C, 0x66, 0xE6, 0x00,
+ 0xF0, 0x60, 0x60, 0x60, 0x62, 0x66, 0xFE, 0x00,
+ 0xC6, 0xEE, 0xFE, 0xFE, 0xD6, 0xC6, 0xC6, 0x00,
+ 0xC6, 0xE6, 0xF6, 0xDE, 0xCE, 0xC6, 0xC6, 0x00,
+ 0x38, 0x6C, 0xC6, 0xC6, 0xC6, 0x6C, 0x38, 0x00,
+ 0xFC, 0x66, 0x66, 0x7C, 0x60, 0x60, 0xF0, 0x00,
+ 0x78, 0xCC, 0xCC, 0xCC, 0xDC, 0x78, 0x1C, 0x00,
+ 0xFC, 0x66, 0x66, 0x7C, 0x6C, 0x66, 0xE6, 0x00,
+ 0x78, 0xCC, 0xE0, 0x70, 0x1C, 0xCC, 0x78, 0x00,
+ 0xFC, 0xB4, 0x30, 0x30, 0x30, 0x30, 0x78, 0x00,
+ 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xFC, 0x00,
+ 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0x78, 0x30, 0x00,
+ 0xC6, 0xC6, 0xC6, 0xD6, 0xFE, 0xEE, 0xC6, 0x00,
+ 0xC6, 0xC6, 0x6C, 0x38, 0x38, 0x6C, 0xC6, 0x00,
+ 0xCC, 0xCC, 0xCC, 0x78, 0x30, 0x30, 0x78, 0x00,
+ 0xFE, 0xC6, 0x8C, 0x18, 0x32, 0x66, 0xFE, 0x00,
+ 0x78, 0x60, 0x60, 0x60, 0x60, 0x60, 0x78, 0x00,
+ 0xC0, 0x60, 0x30, 0x18, 0x0C, 0x06, 0x02, 0x00,
+ 0x78, 0x18, 0x18, 0x18, 0x18, 0x18, 0x78, 0x00,
+ 0x10, 0x38, 0x6C, 0xC6, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF,
+ 0x30, 0x30, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x78, 0x0C, 0x7C, 0xCC, 0x76, 0x00,
+ 0xE0, 0x60, 0x60, 0x7C, 0x66, 0x66, 0xDC, 0x00,
+ 0x00, 0x00, 0x78, 0xCC, 0xC0, 0xCC, 0x78, 0x00,
+ 0x1C, 0x0C, 0x0C, 0x7C, 0xCC, 0xCC, 0x76, 0x00,
+ 0x00, 0x00, 0x78, 0xCC, 0xFC, 0xC0, 0x78, 0x00,
+ 0x38, 0x6C, 0x60, 0xF0, 0x60, 0x60, 0xF0, 0x00,
+ 0x00, 0x00, 0x76, 0xCC, 0xCC, 0x7C, 0x0C, 0xF8,
+ 0xE0, 0x60, 0x6C, 0x76, 0x66, 0x66, 0xE6, 0x00,
+ 0x30, 0x00, 0x70, 0x30, 0x30, 0x30, 0x78, 0x00,
+ 0x0C, 0x00, 0x0C, 0x0C, 0x0C, 0xCC, 0xCC, 0x78,
+ 0xE0, 0x60, 0x66, 0x6C, 0x78, 0x6C, 0xE6, 0x00,
+ 0x70, 0x30, 0x30, 0x30, 0x30, 0x30, 0x78, 0x00,
+ 0x00, 0x00, 0xCC, 0xFE, 0xFE, 0xD6, 0xC6, 0x00,
+ 0x00, 0x00, 0xF8, 0xCC, 0xCC, 0xCC, 0xCC, 0x00,
+ 0x00, 0x00, 0x78, 0xCC, 0xCC, 0xCC, 0x78, 0x00,
+ 0x00, 0x00, 0xDC, 0x66, 0x66, 0x7C, 0x60, 0xF0,
+ 0x00, 0x00, 0x76, 0xCC, 0xCC, 0x7C, 0x0C, 0x1E,
+ 0x00, 0x00, 0xDC, 0x76, 0x66, 0x60, 0xF0, 0x00,
+ 0x00, 0x00, 0x7C, 0xC0, 0x78, 0x0C, 0xF8, 0x00,
+ 0x10, 0x30, 0x7C, 0x30, 0x30, 0x34, 0x18, 0x00,
+ 0x00, 0x00, 0xCC, 0xCC, 0xCC, 0xCC, 0x76, 0x00,
+ 0x00, 0x00, 0xCC, 0xCC, 0xCC, 0x78, 0x30, 0x00,
+ 0x00, 0x00, 0xC6, 0xD6, 0xFE, 0xFE, 0x6C, 0x00,
+ 0x00, 0x00, 0xC6, 0x6C, 0x38, 0x6C, 0xC6, 0x00,
+ 0x00, 0x00, 0xCC, 0xCC, 0xCC, 0x7C, 0x0C, 0xF8,
+ 0x00, 0x00, 0xFC, 0x98, 0x30, 0x64, 0xFC, 0x00,
+ 0x1C, 0x30, 0x30, 0xE0, 0x30, 0x30, 0x1C, 0x00,
+ 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x00,
+ 0xE0, 0x30, 0x30, 0x1C, 0x30, 0x30, 0xE0, 0x00,
+ 0x76, 0xDC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x10, 0x38, 0x6C, 0xC6, 0xC6, 0xFE, 0x00,
+ 0x78, 0xCC, 0xC0, 0xCC, 0x78, 0x18, 0x0C, 0x78,
+ 0x00, 0xCC, 0x00, 0xCC, 0xCC, 0xCC, 0x7E, 0x00,
+ 0x1C, 0x00, 0x78, 0xCC, 0xFC, 0xC0, 0x78, 0x00,
+ 0x7E, 0xC3, 0x3C, 0x06, 0x3E, 0x66, 0x3F, 0x00,
+ 0xCC, 0x00, 0x78, 0x0C, 0x7C, 0xCC, 0x7E, 0x00,
+ 0xE0, 0x00, 0x78, 0x0C, 0x7C, 0xCC, 0x7E, 0x00,
+ 0x30, 0x30, 0x78, 0x0C, 0x7C, 0xCC, 0x7E, 0x00,
+ 0x00, 0x00, 0x78, 0xC0, 0xC0, 0x78, 0x0C, 0x38,
+ 0x7E, 0xC3, 0x3C, 0x66, 0x7E, 0x60, 0x3C, 0x00,
+ 0xCC, 0x00, 0x78, 0xCC, 0xFC, 0xC0, 0x78, 0x00,
+ 0xE0, 0x00, 0x78, 0xCC, 0xFC, 0xC0, 0x78, 0x00,
+ 0xCC, 0x00, 0x70, 0x30, 0x30, 0x30, 0x78, 0x00,
+ 0x7C, 0xC6, 0x38, 0x18, 0x18, 0x18, 0x3C, 0x00,
+ 0xE0, 0x00, 0x70, 0x30, 0x30, 0x30, 0x78, 0x00,
+ 0xC6, 0x38, 0x6C, 0xC6, 0xFE, 0xC6, 0xC6, 0x00,
+ 0x30, 0x30, 0x00, 0x78, 0xCC, 0xFC, 0xCC, 0x00,
+ 0x1C, 0x00, 0xFC, 0x60, 0x78, 0x60, 0xFC, 0x00,
+ 0x00, 0x00, 0x7F, 0x0C, 0x7F, 0xCC, 0x7F, 0x00,
+ 0x3E, 0x6C, 0xCC, 0xFE, 0xCC, 0xCC, 0xCE, 0x00,
+ 0x78, 0xCC, 0x00, 0x78, 0xCC, 0xCC, 0x78, 0x00,
+ 0x00, 0xCC, 0x00, 0x78, 0xCC, 0xCC, 0x78, 0x00,
+ 0x00, 0xE0, 0x00, 0x78, 0xCC, 0xCC, 0x78, 0x00,
+ 0x78, 0xCC, 0x00, 0xCC, 0xCC, 0xCC, 0x7E, 0x00,
+ 0x00, 0xE0, 0x00, 0xCC, 0xCC, 0xCC, 0x7E, 0x00,
+ 0x00, 0xCC, 0x00, 0xCC, 0xCC, 0x7C, 0x0C, 0xF8,
+ 0xC3, 0x18, 0x3C, 0x66, 0x66, 0x3C, 0x18, 0x00,
+ 0xCC, 0x00, 0xCC, 0xCC, 0xCC, 0xCC, 0x78, 0x00,
+ 0x18, 0x18, 0x7E, 0xC0, 0xC0, 0x7E, 0x18, 0x18,
+ 0x38, 0x6C, 0x64, 0xF0, 0x60, 0xE6, 0xFC, 0x00,
+ 0xCC, 0xCC, 0x78, 0xFC, 0x30, 0xFC, 0x30, 0x30,
+ 0xF8, 0xCC, 0xCC, 0xFA, 0xC6, 0xCF, 0xC6, 0xC7,
+ 0x0E, 0x1B, 0x18, 0x3C, 0x18, 0x18, 0xD8, 0x70,
+ 0x1C, 0x00, 0x78, 0x0C, 0x7C, 0xCC, 0x7E, 0x00,
+ 0x38, 0x00, 0x70, 0x30, 0x30, 0x30, 0x78, 0x00,
+ 0x00, 0x1C, 0x00, 0x78, 0xCC, 0xCC, 0x78, 0x00,
+ 0x00, 0x1C, 0x00, 0xCC, 0xCC, 0xCC, 0x7E, 0x00,
+ 0x00, 0xF8, 0x00, 0xF8, 0xCC, 0xCC, 0xCC, 0x00,
+ 0xFC, 0x00, 0xCC, 0xEC, 0xFC, 0xDC, 0xCC, 0x00,
+ 0x3C, 0x6C, 0x6C, 0x3E, 0x00, 0x7E, 0x00, 0x00,
+ 0x38, 0x6C, 0x6C, 0x38, 0x00, 0x7C, 0x00, 0x00,
+ 0x30, 0x00, 0x30, 0x60, 0xC0, 0xCC, 0x78, 0x00,
+ 0x00, 0x00, 0x00, 0xFC, 0xC0, 0xC0, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0xFC, 0x0C, 0x0C, 0x00, 0x00,
+ 0xC3, 0xC6, 0xCC, 0xDE, 0x33, 0x66, 0xCC, 0x0F,
+ 0xC3, 0xC6, 0xCC, 0xDB, 0x37, 0x6F, 0xCF, 0x03,
+ 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x18, 0x00,
+ 0x00, 0x33, 0x66, 0xCC, 0x66, 0x33, 0x00, 0x00,
+ 0x00, 0xCC, 0x66, 0x33, 0x66, 0xCC, 0x00, 0x00,
+ 0x22, 0x88, 0x22, 0x88, 0x22, 0x88, 0x22, 0x88,
+ 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA,
+ 0xDB, 0x77, 0xDB, 0xEE, 0xDB, 0x77, 0xDB, 0xEE,
+ 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+ 0x18, 0x18, 0x18, 0x18, 0xF8, 0x18, 0x18, 0x18,
+ 0x18, 0x18, 0xF8, 0x18, 0xF8, 0x18, 0x18, 0x18,
+ 0x36, 0x36, 0x36, 0x36, 0xF6, 0x36, 0x36, 0x36,
+ 0x00, 0x00, 0x00, 0x00, 0xFE, 0x36, 0x36, 0x36,
+ 0x00, 0x00, 0xF8, 0x18, 0xF8, 0x18, 0x18, 0x18,
+ 0x36, 0x36, 0xF6, 0x06, 0xF6, 0x36, 0x36, 0x36,
+ 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
+ 0x00, 0x00, 0xFE, 0x06, 0xF6, 0x36, 0x36, 0x36,
+ 0x36, 0x36, 0xF6, 0x06, 0xFE, 0x00, 0x00, 0x00,
+ 0x36, 0x36, 0x36, 0x36, 0xFE, 0x00, 0x00, 0x00,
+ 0x18, 0x18, 0xF8, 0x18, 0xF8, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xF8, 0x18, 0x18, 0x18,
+ 0x18, 0x18, 0x18, 0x18, 0x1F, 0x00, 0x00, 0x00,
+ 0x18, 0x18, 0x18, 0x18, 0xFF, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xFF, 0x18, 0x18, 0x18,
+ 0x18, 0x18, 0x18, 0x18, 0x1F, 0x18, 0x18, 0x18,
+ 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00,
+ 0x18, 0x18, 0x18, 0x18, 0xFF, 0x18, 0x18, 0x18,
+ 0x18, 0x18, 0x1F, 0x18, 0x1F, 0x18, 0x18, 0x18,
+ 0x36, 0x36, 0x36, 0x36, 0x37, 0x36, 0x36, 0x36,
+ 0x36, 0x36, 0x37, 0x30, 0x3F, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x3F, 0x30, 0x37, 0x36, 0x36, 0x36,
+ 0x36, 0x36, 0xF7, 0x00, 0xFF, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0xFF, 0x00, 0xF7, 0x36, 0x36, 0x36,
+ 0x36, 0x36, 0x37, 0x30, 0x37, 0x36, 0x36, 0x36,
+ 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x00, 0x00,
+ 0x36, 0x36, 0xF7, 0x00, 0xF7, 0x36, 0x36, 0x36,
+ 0x18, 0x18, 0xFF, 0x00, 0xFF, 0x00, 0x00, 0x00,
+ 0x36, 0x36, 0x36, 0x36, 0xFF, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x18, 0x18, 0x18,
+ 0x00, 0x00, 0x00, 0x00, 0xFF, 0x36, 0x36, 0x36,
+ 0x36, 0x36, 0x36, 0x36, 0x3F, 0x00, 0x00, 0x00,
+ 0x18, 0x18, 0x1F, 0x18, 0x1F, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x1F, 0x18, 0x1F, 0x18, 0x18, 0x18,
+ 0x00, 0x00, 0x00, 0x00, 0x3F, 0x36, 0x36, 0x36,
+ 0x36, 0x36, 0x36, 0x36, 0xFF, 0x36, 0x36, 0x36,
+ 0x18, 0x18, 0xFF, 0x18, 0xFF, 0x18, 0x18, 0x18,
+ 0x18, 0x18, 0x18, 0x18, 0xF8, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x1F, 0x18, 0x18, 0x18,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0,
+ 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x76, 0xDC, 0xC8, 0xDC, 0x76, 0x00,
+ 0x00, 0x78, 0xCC, 0xF8, 0xCC, 0xF8, 0xC0, 0xC0,
+ 0x00, 0xFC, 0xCC, 0xC0, 0xC0, 0xC0, 0xC0, 0x00,
+ 0x00, 0xFE, 0x6C, 0x6C, 0x6C, 0x6C, 0x6C, 0x00,
+ 0xFC, 0xCC, 0x60, 0x30, 0x60, 0xCC, 0xFC, 0x00,
+ 0x00, 0x00, 0x7E, 0xD8, 0xD8, 0xD8, 0x70, 0x00,
+ 0x00, 0x66, 0x66, 0x66, 0x66, 0x7C, 0x60, 0xC0,
+ 0x00, 0x76, 0xDC, 0x18, 0x18, 0x18, 0x18, 0x00,
+ 0xFC, 0x30, 0x78, 0xCC, 0xCC, 0x78, 0x30, 0xFC,
+ 0x38, 0x6C, 0xC6, 0xFE, 0xC6, 0x6C, 0x38, 0x00,
+ 0x38, 0x6C, 0xC6, 0xC6, 0x6C, 0x6C, 0xEE, 0x00,
+ 0x1C, 0x30, 0x18, 0x7C, 0xCC, 0xCC, 0x78, 0x00,
+ 0x00, 0x00, 0x7E, 0xDB, 0xDB, 0x7E, 0x00, 0x00,
+ 0x06, 0x0C, 0x7E, 0xDB, 0xDB, 0x7E, 0x60, 0xC0,
+ 0x38, 0x60, 0xC0, 0xF8, 0xC0, 0x60, 0x38, 0x00,
+ 0x78, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0x00,
+ 0x00, 0xFC, 0x00, 0xFC, 0x00, 0xFC, 0x00, 0x00,
+ 0x30, 0x30, 0xFC, 0x30, 0x30, 0x00, 0xFC, 0x00,
+ 0x60, 0x30, 0x18, 0x30, 0x60, 0x00, 0xFC, 0x00,
+ 0x18, 0x30, 0x60, 0x30, 0x18, 0x00, 0xFC, 0x00,
+ 0x0E, 0x1B, 0x1B, 0x18, 0x18, 0x18, 0x18, 0x18,
+ 0x18, 0x18, 0x18, 0x18, 0x18, 0xD8, 0xD8, 0x70,
+ 0x30, 0x30, 0x00, 0xFC, 0x00, 0x30, 0x30, 0x00,
+ 0x00, 0x76, 0xDC, 0x00, 0x76, 0xDC, 0x00, 0x00,
+ 0x38, 0x6C, 0x6C, 0x38, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00,
+ 0x0F, 0x0C, 0x0C, 0x0C, 0xEC, 0x6C, 0x3C, 0x1C,
+ 0x78, 0x6C, 0x6C, 0x6C, 0x6C, 0x00, 0x00, 0x00,
+ 0x70, 0x18, 0x30, 0x60, 0x78, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x3C, 0x3C, 0x3C, 0x3C, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
} // End of namespace Agi
#endif /* AGI_FONT_H */
diff --git a/engines/agi/global.cpp b/engines/agi/global.cpp
index 0baf8c259c..36cc547a8d 100644
--- a/engines/agi/global.cpp
+++ b/engines/agi/global.cpp
@@ -29,14 +29,14 @@
namespace Agi {
-int AgiEngine::getflag(int n) {
+int AgiBase::getflag(int n) {
uint8 *set = (uint8 *)&_game.flags;
set += n >> 3;
return (*set & (1 << (n & 0x07))) != 0;
}
-void AgiEngine::setflag(int n, int v) {
+void AgiBase::setflag(int n, int v) {
uint8 *set = (uint8 *)&_game.flags;
set += n >> 3;
@@ -46,7 +46,7 @@ void AgiEngine::setflag(int n, int v) {
*set &= ~(1 << (n & 0x07)); /* clear bit */
}
-void AgiEngine::flipflag(int n) {
+void AgiBase::flipflag(int n) {
uint8 *set = (uint8 *)&_game.flags;
set += n >> 3;
diff --git a/engines/agi/graphics.cpp b/engines/agi/graphics.cpp
index b6430e0f81..5af68e9b5e 100644
--- a/engines/agi/graphics.cpp
+++ b/engines/agi/graphics.cpp
@@ -532,7 +532,7 @@ static struct UpdateBlock update = {
MAX_INT, MAX_INT, 0, 0
};
-GfxMgr::GfxMgr(AgiEngine *vm) : _vm(vm) {
+GfxMgr::GfxMgr(AgiBase *vm) : _vm(vm) {
_shakeH = NULL;
_shakeV = NULL;
_agipalFileNum = 0;
@@ -612,11 +612,11 @@ void GfxMgr::shakeEnd() {
free(_shakeH);
}
-void GfxMgr::putTextCharacter(int l, int x, int y, unsigned int c, int fg, int bg, bool checkerboard) {
+void GfxMgr::putTextCharacter(int l, int x, int y, unsigned int c, int fg, int bg, bool checkerboard, const uint8 *font) {
int x1, y1, xx, yy, cc;
const uint8 *p;
- p = Agi::curFont + ((unsigned int)c * CHAR_LINES);
+ p = font + ((unsigned int)c * CHAR_LINES);
for (y1 = 0; y1 < CHAR_LINES; y1++) {
for (x1 = 0; x1 < CHAR_COLS; x1++) {
xx = x + x1;
@@ -1005,6 +1005,14 @@ void GfxMgr::setCursor(bool amigaStyleCursor) {
}
}
+void GfxMgr::setCursorPalette(bool amigaStyleCursor) {
+ if (!amigaStyleCursor) {
+ CursorMan.replaceCursorPalette(sciMouseCursorPalette, 1, ARRAYSIZE(sciMouseCursorPalette) / 4);
+ } else { // amigaStyleCursor
+ CursorMan.replaceCursorPalette(amigaMouseCursorPalette, 1, ARRAYSIZE(amigaMouseCursorPalette) / 4);
+ }
+}
+
/**
* Initialize graphics device.
*
@@ -1078,7 +1086,7 @@ void GfxMgr::putPixelsA(int x, int y, int n, uint8 *p) {
} else {
const uint16 mask = _vm->getFeatures() & (GF_AGI256 | GF_AGI256_2) && !_vm->_debug.priority ? 0xffff : 0x0f0f;
for (x *= 2; n--; p++, x += 2) {
- register uint16 q = ((uint16) * p << 8) | *p;
+ register uint16 q = ((uint16)*p << 8) | *p;
*(uint16 *)&_agiScreen[x + y * GFX_WIDTH] = (q >> rShift) & mask;
}
}
diff --git a/engines/agi/graphics.h b/engines/agi/graphics.h
index e06af90f5d..96b6247aeb 100644
--- a/engines/agi/graphics.h
+++ b/engines/agi/graphics.h
@@ -27,6 +27,7 @@
#define AGI_GRAPHICS_H
#include "common/stdafx.h"
+#include "agi/font.h"
namespace Agi {
@@ -39,7 +40,7 @@ class AgiEngine;
class GfxMgr {
private:
- AgiEngine *_vm;
+ AgiBase *_vm;
uint8 _palette[256 * 4];
uint8 *_agiScreen;
@@ -54,11 +55,11 @@ private:
void rawDrawButton(int x, int y, const char *s, int fgcolor, int bgcolor, bool border, int textOffset);
public:
- GfxMgr(AgiEngine *vm);
+ GfxMgr(AgiBase *vm);
void gfxPutBlock(int x1, int y1, int x2, int y2);
- void putTextCharacter(int, int, int, unsigned int, int, int, bool checkerboard = false);
+ void putTextCharacter(int, int, int, unsigned int, int, int, bool checkerboard = false, const uint8 *font = curFont);
void shakeScreen(int);
void shakeStart();
void shakeEnd();
@@ -88,10 +89,10 @@ public:
int getAGIPalFileNum();
void drawFrame(int x1, int y1, int x2, int y2, int c1, int c2);
- void putPixel(int, int, int);
void putBlock(int x1, int y1, int x2, int y2);
void gfxSetPalette();
void setCursor(bool amigaStyleCursor = false);
+ void setCursorPalette(bool amigaStylePalette = false);
int keypress();
int getKey();
diff --git a/engines/agi/agi_v2.cpp b/engines/agi/loader_v2.cpp
index 375bbec411..c0c6df2fcb 100644
--- a/engines/agi/agi_v2.cpp
+++ b/engines/agi/loader_v2.cpp
@@ -173,12 +173,6 @@ uint8 *AgiLoader_v2::loadVolRes(struct AgiDir *agid) {
abort();
}
} else {
-#if 0
- /* FIXME: call some panic handler instead of
- * deiniting directly
- */
- deinitVideoMode();
-#endif
report("Error: bad signature %04x\n", sig);
// fprintf (stderr, "ACK! BAD RESOURCE!!!\n");
return 0;
@@ -254,9 +248,9 @@ int AgiLoader_v2::loadResource(int t, int n) {
data = loadVolRes(&_vm->_game.dirSound[n]);
if (data != NULL) {
- _vm->_game.sounds[n].rdata = data;
+ // Freeing of the raw resource from memory is delegated to the createFromRawResource-function
+ _vm->_game.sounds[n] = AgiSound::createFromRawResource(data, _vm->_game.dirSound[n].len, n, *_vm->_sound);
_vm->_game.dirSound[n].flags |= RES_LOADED;
- _vm->_sound->decodeSound(n);
} else {
ec = errBadResource;
}
diff --git a/engines/agi/agi_v3.cpp b/engines/agi/loader_v3.cpp
index 69a8698ecb..362d778c66 100644
--- a/engines/agi/agi_v3.cpp
+++ b/engines/agi/loader_v3.cpp
@@ -228,10 +228,6 @@ uint8 *AgiLoader_v3::loadVolRes(AgiDir *agid) {
fp.read(&x, 7);
if (READ_BE_UINT16((uint8 *) x) != 0x1234) {
-#if 0
- /* FIXME */
- deinitVideoMode();
-#endif
debugC(3, kDebugLevelResources, "path = %s", path.c_str());
debugC(3, kDebugLevelResources, "offset = %d", agid->offset);
debugC(3, kDebugLevelResources, "x = %x %x", x[0], x[1]);
@@ -345,9 +341,9 @@ int AgiLoader_v3::loadResource(int t, int n) {
data = loadVolRes(&_vm->_game.dirSound[n]);
if (data != NULL) {
- _vm->_game.sounds[n].rdata = data;
+ // Freeing of the raw resource from memory is delegated to the createFromRawResource-function
+ _vm->_game.sounds[n] = AgiSound::createFromRawResource(data, _vm->_game.dirSound[n].len, n, *_vm->_sound);
_vm->_game.dirSound[n].flags |= RES_LOADED;
- _vm->_sound->decodeSound(n);
} else {
ec = errBadResource;
}
diff --git a/engines/agi/module.mk b/engines/agi/module.mk
index d74eba034a..e5e8555ba2 100644
--- a/engines/agi/module.mk
+++ b/engines/agi/module.mk
@@ -2,8 +2,6 @@ MODULE := engines/agi
MODULE_OBJS = \
agi.o \
- agi_v2.o \
- agi_v3.o \
checks.o \
console.o \
cycle.o \
@@ -13,6 +11,8 @@ MODULE_OBJS = \
id.o \
inv.o \
keyboard.o \
+ loader_v2.o \
+ loader_v3.o \
logic.o \
lzw.o \
menu.o \
@@ -22,6 +22,11 @@ MODULE_OBJS = \
op_dbg.o \
op_test.o \
picture.o \
+ preagi.o \
+ preagi_common.o \
+ preagi_mickey.o \
+ preagi_troll.o \
+ preagi_winnie.o \
predictive.o \
saveload.o \
sound.o \
diff --git a/engines/agi/picture.cpp b/engines/agi/picture.cpp
index 144e965465..006348f433 100644
--- a/engines/agi/picture.cpp
+++ b/engines/agi/picture.cpp
@@ -28,75 +28,45 @@
#include "agi/agi.h"
#include "agi/graphics.h"
+
namespace Agi {
-#define nextByte data[foffs++]
-
-static uint8 *data;
-static uint32 flen;
-static uint32 foffs;
-
-static uint8 patCode;
-static uint8 patNum;
-static uint8 priOn;
-static uint8 scrOn;
-static uint8 scrColour;
-static uint8 priColour;
-
-static uint8 circles[][15] = { /* agi circle bitmaps */
- {0x80},
- /* {0xfc}, */
- { 3 << 4 }, /* pattern data different from specs. fixes gold rush. does not seem to break any other v3 games */
- {0x5f, 0xf4},
- {0x66, 0xff, 0xf6, 0x60},
- {0x23, 0xbf, 0xff, 0xff, 0xee, 0x20},
- {0x31, 0xe7, 0x9e, 0xff, 0xff, 0xde, 0x79, 0xe3, 0x00},
- {0x38, 0xf9, 0xf3, 0xef, 0xff, 0xff, 0xff, 0xfe, 0xf9, 0xf3, 0xe3, 0x80},
- {0x18, 0x3c, 0x7e, 0x7e, 0x7e, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7e, 0x7e, 0x7e, 0x3c, 0x18}
-};
-
-static uint8 splatterMap[32] = { /* splatter brush bitmaps */
- 0x20, 0x94, 0x02, 0x24, 0x90, 0x82, 0xa4, 0xa2,
- 0x82, 0x09, 0x0a, 0x22, 0x12, 0x10, 0x42, 0x14,
- 0x91, 0x4a, 0x91, 0x11, 0x08, 0x12, 0x25, 0x10,
- 0x22, 0xa8, 0x14, 0x24, 0x00, 0x50, 0x24, 0x04
-};
-
-static uint8 splatterStart[128] = { /* starting bit position */
- 0x00, 0x18, 0x30, 0xc4, 0xdc, 0x65, 0xeb, 0x48,
- 0x60, 0xbd, 0x89, 0x05, 0x0a, 0xf4, 0x7d, 0x7d,
- 0x85, 0xb0, 0x8e, 0x95, 0x1f, 0x22, 0x0d, 0xdf,
- 0x2a, 0x78, 0xd5, 0x73, 0x1c, 0xb4, 0x40, 0xa1,
- 0xb9, 0x3c, 0xca, 0x58, 0x92, 0x34, 0xcc, 0xce,
- 0xd7, 0x42, 0x90, 0x0f, 0x8b, 0x7f, 0x32, 0xed,
- 0x5c, 0x9d, 0xc8, 0x99, 0xad, 0x4e, 0x56, 0xa6,
- 0xf7, 0x68, 0xb7, 0x25, 0x82, 0x37, 0x3a, 0x51,
- 0x69, 0x26, 0x38, 0x52, 0x9e, 0x9a, 0x4f, 0xa7,
- 0x43, 0x10, 0x80, 0xee, 0x3d, 0x59, 0x35, 0xcf,
- 0x79, 0x74, 0xb5, 0xa2, 0xb1, 0x96, 0x23, 0xe0,
- 0xbe, 0x05, 0xf5, 0x6e, 0x19, 0xc5, 0x66, 0x49,
- 0xf0, 0xd1, 0x54, 0xa9, 0x70, 0x4b, 0xa4, 0xe2,
- 0xe6, 0xe5, 0xab, 0xe4, 0xd2, 0xaa, 0x4c, 0xe3,
- 0x06, 0x6f, 0xc6, 0x4a, 0xa4, 0x75, 0x97, 0xe1
-};
+PictureMgr::PictureMgr(AgiBase *agi, GfxMgr *gfx) {
+ _vm = agi;
+ _gfx = gfx;
+
+ _data = NULL;
+ _flen = _foffs = 0;
+
+ _patCode = _patNum = _priOn = _scrOn = _scrColor = _priColor = 0;
+ _xOffset = _yOffset = 0;
+
+ _pictureVersion = AGIPIC_V2;
+ _minCommand = 0xf0;
+ _flags = 0;
+}
void PictureMgr::putVirtPixel(int x, int y) {
uint8 *p;
- if (x < 0 || y < 0 || x >= _WIDTH || y >= _HEIGHT)
+ x += _xOffset;
+ y += _yOffset;
+
+ if (x < 0 || y < 0 || x >= _width || y >= _height)
return;
- p = &_vm->_game.sbuf16c[y * _WIDTH + x];
+ p = &_vm->_game.sbuf16c[y * _width + x];
- if (priOn)
- *p = (priColour << 4) | (*p & 0x0f);
- if (scrOn)
- *p = scrColour | (*p & 0xf0);
+ if (_priOn)
+ *p = (_priColor << 4) | (*p & 0x0f);
+ if (_scrOn)
+ *p = _scrColor | (*p & 0xf0);
}
/* For the flood fill routines */
/* MH2 needs stack size > 300 */
+// FIXME: Consider using FixedStack<> or Stack<> from common/stack.h here
#define STACK_SIZE 512
static unsigned int stackPtr;
static uint16 stack[STACK_SIZE];
@@ -130,10 +100,10 @@ void PictureMgr::drawLine(int x1, int y1, int x2, int y2) {
/* CM: Do clipping */
#define clip(x, y) if((x)>=(y)) (x)=(y)
- clip(x1, _WIDTH - 1);
- clip(x2, _WIDTH - 1);
- clip(y1, _HEIGHT - 1);
- clip(y2, _HEIGHT - 1);
+ clip(x1, _width - 1);
+ clip(x2, _width - 1);
+ clip(y1, _height - 1);
+ clip(y2, _height - 1);
/* Vertical line */
@@ -219,13 +189,13 @@ void PictureMgr::drawLine(int x1, int y1, int x2, int y2) {
void PictureMgr::dynamicDrawLine() {
int x1, y1, disp, dx, dy;
- x1 = nextByte;
- y1 = nextByte;
+ x1 = nextByte();
+ y1 = nextByte();
putVirtPixel(x1, y1);
for (;;) {
- if ((disp = nextByte) >= 0xf0)
+ if ((disp = nextByte()) >= _minCommand)
break;
dx = ((disp & 0xf0) >> 4) & 0x0f;
@@ -240,7 +210,7 @@ void PictureMgr::dynamicDrawLine() {
x1 += dx;
y1 += dy;
}
- foffs--;
+ _foffs--;
}
/**************************************************************************
@@ -251,22 +221,22 @@ void PictureMgr::dynamicDrawLine() {
void PictureMgr::absoluteDrawLine() {
int x1, y1, x2, y2;
- x1 = nextByte;
- y1 = nextByte;
+ x1 = nextByte();
+ y1 = nextByte();
putVirtPixel(x1, y1);
for (;;) {
- if ((x2 = nextByte) >= 0xf0)
+ if ((x2 = nextByte()) >= _minCommand)
break;
- if ((y2 = nextByte) >= 0xf0)
+ if ((y2 = nextByte()) >= _minCommand)
break;
drawLine(x1, y1, x2, y2);
x1 = x2;
y1 = y2;
}
- foffs--;
+ _foffs--;
}
/**************************************************************************
@@ -275,21 +245,26 @@ void PictureMgr::absoluteDrawLine() {
INLINE int PictureMgr::isOkFillHere(int x, int y) {
uint8 p;
- if (x < 0 || x >= _WIDTH || y < 0 || y >= _HEIGHT)
+ if (x < 0 || x >= _width || y < 0 || y >= _height)
return false;
- if (!scrOn && !priOn)
+ if (!_scrOn && !_priOn)
return false;
- p = _vm->_game.sbuf16c[y * _WIDTH + x];
+ p = _vm->_game.sbuf16c[y * _width + x];
+
+ // FIXME: This overflows stack, but otherwise is a wild guess
+ // original has some checks against color 11 (0xB)
+ if (_pictureVersion == AGIPIC_V15 && 0)
+ return (p & 0x0f) == 0;
- if (!priOn && scrOn && scrColour != 15)
+ if (!_priOn && _scrOn && _scrColor != 15)
return (p & 0x0f) == 15;
- if (priOn && !scrOn && priColour != 4)
+ if (_priOn && !_scrOn && _priColor != 4)
return (p >> 4) == 4;
- return (scrOn && (p & 0x0f) == 15 && scrColour != 15);
+ return (_scrOn && (p & 0x0f) == 15 && _scrColor != 15);
}
/**************************************************************************
@@ -352,30 +327,39 @@ void PictureMgr::agiFill(unsigned int x, unsigned int y) {
**
** Draws an xCorner (drawing action 0xF5)
**************************************************************************/
-void PictureMgr::xCorner() {
+void PictureMgr::xCorner(bool skipOtherCoords) {
int x1, x2, y1, y2;
- x1 = nextByte;
- y1 = nextByte;
+ x1 = nextByte();
+ y1 = nextByte();
putVirtPixel(x1, y1);
for (;;) {
- x2 = nextByte;
+ x2 = nextByte();
- if (x2 >= 0xf0)
+ if (skipOtherCoords)
+ if (nextByte() >= _minCommand)
+ break;
+
+ if (x2 >= _minCommand)
break;
drawLine(x1, y1, x2, y1);
x1 = x2;
- y2 = nextByte;
- if (y2 >= 0xf0)
+ if (skipOtherCoords)
+ if (nextByte() >= _minCommand)
+ break;
+
+ y2 = nextByte();
+
+ if (y2 >= _minCommand)
break;
drawLine(x1, y1, x1, y2);
y1 = y2;
}
- foffs--;
+ _foffs--;
}
/**************************************************************************
@@ -383,31 +367,39 @@ void PictureMgr::xCorner() {
**
** Draws an yCorner (drawing action 0xF4)
**************************************************************************/
-void PictureMgr::yCorner() {
+void PictureMgr::yCorner(bool skipOtherCoords) {
int x1, x2, y1, y2;
- x1 = nextByte;
- y1 = nextByte;
+ x1 = nextByte();
+ y1 = nextByte();
putVirtPixel(x1, y1);
for (;;) {
- y2 = nextByte;
+ if (skipOtherCoords)
+ if (nextByte() >= _minCommand)
+ break;
+
+ y2 = nextByte();
- if (y2 >= 0xF0)
+ if (y2 >= _minCommand)
break;
drawLine(x1, y1, x1, y2);
y1 = y2;
- x2 = nextByte;
+ x2 = nextByte();
- if (x2 >= 0xf0)
+ if (x2 >= _minCommand)
break;
+ if (skipOtherCoords)
+ if (nextByte() >= _minCommand)
+ break;
+
drawLine(x1, y1, x2, y1);
x1 = x2;
}
- foffs--;
+ _foffs--;
}
/**************************************************************************
@@ -418,10 +410,14 @@ void PictureMgr::yCorner() {
void PictureMgr::fill() {
int x1, y1;
- while ((x1 = nextByte) < 0xF0 && (y1 = nextByte) < 0xf0)
+ if (_pictureVersion == AGIPIC_V15 && 0)
+ if (_scrColor == 0xf && !(_flags & kPicFTrollMode))
+ return;
+
+ while ((x1 = nextByte()) < _minCommand && (y1 = nextByte()) < _minCommand)
agiFill(x1, y1);
- foffs--;
+ _foffs--;
}
/**************************************************************************
@@ -431,43 +427,111 @@ void PictureMgr::fill() {
** on the pattern code.
**************************************************************************/
-int PictureMgr::plotPatternPoint(int x, int y, int bitpos) {
- if (patCode & 0x20) {
- if ((splatterMap[bitpos >> 3] >> (7 - (bitpos & 7))) & 1) {
- putVirtPixel(x, y);
- }
- bitpos++;
- if (bitpos == 0xff)
- bitpos = 0;
- } else
- putVirtPixel(x, y);
-
- return bitpos;
-}
-
void PictureMgr::plotPattern(int x, int y) {
- int32 circlePos = 0;
- uint32 x1, y1, pensize, bitpos = splatterStart[patNum];
-
- pensize = (patCode & 7);
-
- if (x < (int)pensize)
- x = pensize - 1;
- if (y < (int)pensize)
- y = pensize;
-
- for (y1 = y - pensize; y1 <= y + pensize; y1++) {
- for (x1 = x - (pensize + 1) / 2; x1 <= x + pensize / 2; x1++) {
- if (patCode & 0x10) { /* Square */
- bitpos = plotPatternPoint (x1, y1, bitpos);
- } else { /* Circle */
- if ((circles[patCode & 7][circlePos >> 3] >> (7 - (circlePos & 7))) & 1) {
- bitpos = plotPatternPoint(x1, y1, bitpos);
- }
- circlePos++;
+ static const uint16 binary_list[] = {0x8000, 0x4000, 0x2000, 0x1000, 0x800, 0x400, 0x200, 0x100,
+ 0x80, 0x40, 0x20, 0x10, 0x8, 0x4, 0x2, 0x1};
+
+ static const uint8 circle_list[] = {0, 1, 4, 9, 16, 25, 37, 50};
+
+ static const uint16 circle_data[] =
+ {0x8000,
+ 0xE000, 0xE000, 0xE000,
+ 0x7000, 0xF800, 0x0F800, 0x0F800, 0x7000,
+ 0x3800, 0x7C00, 0x0FE00, 0x0FE00, 0x0FE00, 0x7C00, 0x3800,
+ 0x1C00, 0x7F00, 0x0FF80, 0x0FF80, 0x0FF80, 0x0FF80, 0x0FF80, 0x7F00, 0x1C00,
+ 0x0E00, 0x3F80, 0x7FC0, 0x7FC0, 0x0FFE0, 0x0FFE0, 0x0FFE0, 0x7FC0, 0x7FC0, 0x3F80, 0x1F00, 0x0E00,
+ 0x0F80, 0x3FE0, 0x7FF0, 0x7FF0, 0x0FFF8, 0x0FFF8, 0x0FFF8, 0x0FFF8, 0x0FFF8, 0x7FF0, 0x7FF0, 0x3FE0, 0x0F80,
+ 0x07C0, 0x1FF0, 0x3FF8, 0x7FFC, 0x7FFC, 0x0FFFE, 0x0FFFE, 0x0FFFE, 0x0FFFE, 0x0FFFE, 0x7FFC, 0x7FFC, 0x3FF8, 0x1FF0, 0x07C0};
+
+ uint16 circle_word;
+ const uint16 *circle_ptr;
+ uint16 counter;
+ uint16 pen_width = 0;
+ int pen_final_x = 0;
+ int pen_final_y = 0;
+
+ uint8 t = 0;
+ uint8 temp8;
+ uint16 temp16;
+
+ int pen_x = x;
+ int pen_y = y;
+ uint16 texture_num = 0;
+ uint16 pen_size = (_patCode & 0x07);
+
+ circle_ptr = &circle_data[circle_list[pen_size]];
+
+ // setup the X position
+ // = pen_x - pen.size/2
+
+ pen_x = (pen_x * 2) - pen_size;
+ if (pen_x < 0) pen_x = 0;
+
+ temp16 = 320 - (2 * pen_size);
+ if (pen_x >= temp16)
+ pen_x = temp16;
+
+ pen_x /= 2;
+ pen_final_x = pen_x; // original starting point?? -> used in plotrelated
+
+ // Setup the Y Position
+ // = pen_y - pen.size
+ pen_y = pen_y - pen_size;
+ if (pen_y < 0) pen_y = 0;
+
+ temp16 = 167 - (2 * pen_size);
+ if (pen_y >= temp16)
+ pen_y = temp16;
+
+ pen_final_y = pen_y; // used in plotrelated
+
+ t = (uint8)(texture_num | 0x01); // even
+
+ // new purpose for temp16
+
+ temp16 =( pen_size<<1) +1; // pen size
+ pen_final_y += temp16; // the last row of this shape
+ temp16 = temp16 << 1;
+ pen_width = temp16; // width of shape?
+
+ bool circleCond;
+ int counterStep;
+ int ditherCond;
+
+ if (_flags & kPicFCircle)
+ _patCode |= 0x10;
+
+ if (_vm->getGameType() == GType_PreAGI) {
+ circleCond = ((_patCode & 0x10) == 0);
+ counterStep = 3;
+ ditherCond = 0x03;
+ } else {
+ circleCond = ((_patCode & 0x10) != 0);
+ counterStep = 4;
+ ditherCond = 0x02;
+ }
+
+ for (; pen_y < pen_final_y; pen_y++) {
+ circle_word = *circle_ptr++;
+
+ for (counter = 0; counter <= pen_width; counter += counterStep) {
+ if (circleCond || ((binary_list[counter>>1] & circle_word) != 0)) {
+ temp8 = t % 2;
+ t = t >> 1;
+ if (temp8 != 0)
+ t = t ^ 0xB8;
+
+ // == box plot, != circle plot
+ if ((_patCode & 0x20) == 0 || (t & 0x03) == ditherCond)
+ putVirtPixel(pen_x, pen_y);
}
+ pen_x++;
}
+
+ pen_x = pen_final_x;
}
+
+ return;
}
/**************************************************************************
@@ -479,97 +543,223 @@ void PictureMgr::plotBrush() {
int x1, y1;
for (;;) {
- if (patCode & 0x20) {
- if ((patNum = nextByte) >= 0xF0)
+ if (_patCode & 0x20) {
+ if ((_patNum = nextByte()) >= _minCommand)
break;
- patNum = (patNum >> 1) & 0x7f;
+ _patNum = (_patNum >> 1) & 0x7f;
}
- if ((x1 = nextByte) >= 0xf0)
+ if ((x1 = nextByte()) >= _minCommand)
break;
- if ((y1 = nextByte) >= 0xf0)
+ if ((y1 = nextByte()) >= _minCommand)
break;
plotPattern(x1, y1);
}
- foffs--;
+ _foffs--;
}
/**************************************************************************
-** fill
-**
-** AGI flood fill. (drawing action 0xF8)
+** Draw AGI picture
**************************************************************************/
void PictureMgr::drawPicture() {
uint8 act;
int drawing;
- patCode = 0;
- patNum = 0;
- priOn = scrOn = false;
- scrColour = 0xf;
- priColour = 0x4;
+ _patCode = 0;
+ _patNum = 0;
+ _priOn = _scrOn = false;
+ _scrColor = 0xf;
+ _priColor = 0x4;
drawing = 1;
- debugC(8, kDebugLevelMain, "Drawing picture");
- for (drawing = 1; drawing && foffs < flen;) {
- act = nextByte;
+ debugC(8, kDebugLevelMain, "Drawing v2 picture");
+ for (drawing = 1; drawing && _foffs < _flen;) {
+ act = nextByte();
+
+ if (_pictureVersion == AGIPIC_C64 && act >= 0xf0 && act <= 0xfe) {
+ _scrColor = act - 0xf0;
+ continue;
+ }
+
switch (act) {
- case 0xf0: /* set colour on screen */
- scrColour = nextByte;
- scrColour &= 0xF; /* for v3 drawing diff */
- scrOn = true;
+ case 0xe0: // x-corner (C64)
+ xCorner();
+ break;
+ case 0xe1: // y-corner (C64)
+ yCorner();
+ break;
+ case 0xe2: // dynamic draw lines (C64)
+ dynamicDrawLine();
+ break;
+ case 0xe3: // absolute draw lines (C64)
+ absoluteDrawLine();
break;
- case 0xf1: /* disable screen drawing */
- scrOn = false;
+ case 0xe4: // fill (C64)
+ _scrColor = nextByte();
+ _scrColor &= 0xF; /* for v3 drawing diff */
+ fill();
+ break;
+ case 0xe5: // enable screen drawing (C64)
+ _scrOn = true;
break;
- case 0xf2: /* set colour on priority */
- priColour = nextByte;
- priColour &= 0xf; /* for v3 drawing diff */
- priOn = true;
+ case 0xe6: // plot brush (C64)
+ _patCode = nextByte();
+ plotBrush();
break;
- case 0xf3: /* disable priority screen */
- priOn = false;
+ case 0xf0: // set colour on screen (AGI pic v2)
+ if (_pictureVersion == AGIPIC_V15)
+ break;
+
+ _scrColor = nextByte();
+ _scrColor &= 0xF; // for v3 drawing diff
+ _scrOn = true;
+ break;
+ case 0xf1:
+ if (_pictureVersion == AGIPIC_V1) {
+ _scrColor = nextByte();
+ _scrColor &= 0xF; // for v3 drawing diff
+ _scrOn = true;
+ _priOn = false;
+ } else if (_pictureVersion == AGIPIC_V15) { // set colour on screen
+ _scrColor = nextByte();
+ _scrColor &= 0xF;
+ _scrOn = true;
+ } else if (_pictureVersion == AGIPIC_V2) { // disable screen drawing
+ _scrOn = false;
+ }
+ break;
+ case 0xf2: // set colour on priority (AGI pic v2)
+ if (_pictureVersion == AGIPIC_V15)
+ break;
+
+ _priColor = nextByte();
+ _priColor &= 0xf; // for v3 drawing diff
+ _priOn = true;
+ break;
+ case 0xf3:
+ if (_pictureVersion == AGIPIC_V1) {
+ _scrColor = nextByte();
+ _scrColor &= 0xF; // for v3 drawing diff
+ _scrOn = true;
+ _priColor = nextByte();
+ _priColor &= 0xf; // for v3 drawing diff
+ _priOn = true;
+ }
+
+ if (_pictureVersion == AGIPIC_V15 && (_flags & kPicFf3Stop))
+ drawing = 0;
+
+ if (_pictureVersion == AGIPIC_V2) // disable priority screen
+ _priOn = false;
break;
- case 0xf4: /* y-corner */
+ case 0xf4: // y-corner
+ if (_pictureVersion == AGIPIC_V15)
+ break;
+
yCorner();
break;
- case 0xf5: /* x-corner */
+ case 0xf5: // x-corner
+ if (_pictureVersion == AGIPIC_V15)
+ break;
+
xCorner();
break;
- case 0xf6: /* absolute draw lines */
+ case 0xf6: // absolute draw lines
+ if (_pictureVersion == AGIPIC_V15)
+ break;
+
absoluteDrawLine();
break;
- case 0xf7: /* dynamic draw lines */
+ case 0xf7: // dynamic draw lines
+ if (_pictureVersion == AGIPIC_V15)
+ break;
+
dynamicDrawLine();
break;
- case 0xf8: /* fill */
- fill();
+ case 0xf8: // fill
+ if (_pictureVersion == AGIPIC_V15) {
+ yCorner(true);
+ } else if (_pictureVersion == AGIPIC_V2) {
+ fill();
+ }
break;
- case 0xf9: /* set pattern */
- patCode = nextByte;
+ case 0xf9: // set pattern
+ if (_pictureVersion == AGIPIC_V15) {
+ xCorner(true);
+ } else if (_pictureVersion == AGIPIC_V2) {
+ _patCode = nextByte();
+
+ if (_vm->getGameType() == GType_PreAGI)
+ plotBrush();
+ }
break;
- case 0xfA: /* plot brush */
- plotBrush();
+ case 0xfa: // plot brush
+ if (_pictureVersion == AGIPIC_V1) {
+ _scrOn = false;
+ _priOn = true;
+ absoluteDrawLine();
+ _scrOn = true;
+ _priOn = false;
+ } else if (_pictureVersion == AGIPIC_V15) {
+ absoluteDrawLine();
+ } else if (_pictureVersion == AGIPIC_V2) {
+ plotBrush();
+ }
break;
- case 0xFF: /* end of pic data */
- default:
+ case 0xfb:
+ if (_pictureVersion == AGIPIC_V1) {
+ dynamicDrawLine();
+ } else if (_pictureVersion == AGIPIC_V15) {
+ absoluteDrawLine();
+ }
+ break;
+ case 0xfc: // fill (AGI pic v1)
+ if (_pictureVersion == AGIPIC_V15)
+ break;
+
+ _scrColor = nextByte();
+ _scrColor &= 0xF;
+ _priColor = nextByte();
+ _priColor &= 0xf;
+ fill();
+ break;
+ case 0xfe: // fill (AGI pic v1.5)
+ _scrColor = nextByte();
+ _scrColor &= 0xF;
+ _scrOn = true;
+ fill();
+ break;
+ case 0xff: // end of pic data
drawing = 0;
break;
+ default:
+ warning("Unknown picture opcode (%x) at (%x)", act, _foffs - 1);
+ }
+ if ((_flags & kPicFStep) && _vm->getGameType() == GType_PreAGI) {
+ // FIXME: This is used by Mickey for the crystal animation, but
+ // currently it's very very very slow
+ /*
+ int storedXOffset = _xOffset;
+ int storedYOffset = _yOffset;
+ // FIXME: picture coordinates are correct for Mickey only
+ showPic(10, 0, _width, _height);
+ _gfx->doUpdate();
+ g_system->updateScreen();
+ _xOffset = storedXOffset;
+ _yOffset = storedYOffset;
+ g_system->delayMillis(25);
+ */
}
}
}
-/*
- * Public functions
- */
-
/**
- *
+ * convert AGI v3 format picture to AGI v2 format
*/
uint8 *PictureMgr::convertV3Pic(uint8 *src, uint32 len) {
uint8 d, old = 0, x, *in, *xdata, *out, mode = 0;
@@ -621,33 +811,36 @@ uint8 *PictureMgr::convertV3Pic(uint8 *src, uint32 len) {
* @param clear clear AGI screen before drawing
* @param agi256 load an AGI256 picture resource
*/
-int PictureMgr::decodePicture(int n, int clear, bool agi256) {
+int PictureMgr::decodePicture(int n, int clear, bool agi256, int pic_width, int pic_height) {
debugC(8, kDebugLevelResources, "(%d)", n);
- patCode = 0;
- patNum = 0;
- priOn = scrOn = false;
- scrColour = 0xF;
- priColour = 0x4;
+ _patCode = 0;
+ _patNum = 0;
+ _priOn = _scrOn = false;
+ _scrColor = 0xF;
+ _priColor = 0x4;
- data = _vm->_game.pictures[n].rdata;
- flen = _vm->_game.dirPic[n].len;
- foffs = 0;
+ _data = _vm->_game.pictures[n].rdata;
+ _flen = _vm->_game.dirPic[n].len;
+ _foffs = 0;
+
+ _width = pic_width;
+ _height = pic_height;
if (clear && !agi256) // 256 color pictures should always fill the whole screen, so no clearing for them.
- memset(_vm->_game.sbuf16c, 0x4f, _WIDTH * _HEIGHT); // Clear 16 color AGI screen (Priority 4, color white).
+ memset(_vm->_game.sbuf16c, 0x4f, _width * _height); // Clear 16 color AGI screen (Priority 4, color white).
if (!agi256) {
drawPicture(); // Draw 16 color picture.
} else {
- const uint32 maxFlen = _WIDTH * _HEIGHT;
- memcpy(_vm->_game.sbuf256c, data, MIN(flen, maxFlen)); // Draw 256 color picture.
+ const uint32 maxFlen = _width * _height;
+ memcpy(_vm->_game.sbuf256c, _data, MIN(_flen, maxFlen)); // Draw 256 color picture.
- if (flen < maxFlen) {
+ if (_flen < maxFlen) {
warning("Undersized AGI256 picture resource %d, using it anyway. Filling rest with white.", n);
- memset(_vm->_game.sbuf256c + flen, 0x0f, maxFlen - flen); // Fill missing area with white.
- } else if (flen > maxFlen)
- warning("Oversized AGI256 picture resource %d, decoding only %ux%u part of it", n, _WIDTH, _HEIGHT);
+ memset(_vm->_game.sbuf256c + _flen, 0x0f, maxFlen - _flen); // Fill missing area with white.
+ } else if (_flen > maxFlen)
+ warning("Oversized AGI256 picture resource %d, decoding only %ux%u part of it", n, _width, _height);
}
if (clear)
@@ -658,6 +851,40 @@ int PictureMgr::decodePicture(int n, int clear, bool agi256) {
}
/**
+ * Decode an AGI picture resource.
+ * This function decodes an AGI picture resource into the correct slot
+ * and draws it on the AGI screen, optionally clearing the screen before
+ * drawing.
+ * @param data the AGI Picture data
+ * @param length the size of the picture data buffer
+ * @param clear clear AGI screen before drawing
+ */
+int PictureMgr::decodePicture(byte* data, uint32 length, int clear, int pic_width, int pic_height) {
+ _patCode = 0;
+ _patNum = 0;
+ _priOn = _scrOn = false;
+ _scrColor = 0xF;
+ _priColor = 0x4;
+
+ _data = data;
+ _flen = length;
+ _foffs = 0;
+
+ _width = pic_width;
+ _height = pic_height;
+
+ if (clear) // 256 color pictures should always fill the whole screen, so no clearing for them.
+ memset(_vm->_game.sbuf16c, 0x4f, _width * _height); // Clear 16 color AGI screen (Priority 4, color white).
+
+ drawPicture(); // Draw 16 color picture.
+
+ free(_data);
+ _data = 0;
+
+ return errOK;
+}
+
+/**
* Unload an AGI picture resource.
* This function unloads an AGI picture resource and deallocates
* resource data.
@@ -677,20 +904,44 @@ int PictureMgr::unloadPicture(int n) {
* Show AGI picture.
* This function copies a ``hidden'' AGI picture to the output device.
*/
-void PictureMgr::showPic() {
- int i, y;
+void PictureMgr::showPic(int x, int y, int pic_width, int pic_height) {
+ int i, y1;
int offset;
+ _width = pic_width;
+ _height = pic_height;
debugC(8, kDebugLevelMain, "Show picture!");
i = 0;
offset = _vm->_game.lineMinPrint * CHAR_LINES;
- for (y = 0; y < _HEIGHT; y++) {
- _gfx->putPixelsA(0, y + offset, _WIDTH, &_vm->_game.sbuf16c[i]);
- i += _WIDTH;
+ for (y1 = y; y1 < y + _height; y1++) {
+ _gfx->putPixelsA(x, y1 + offset, _width, &_vm->_game.sbuf16c[i]);
+ i += _width;
}
_gfx->flushScreen();
}
+// preagi needed functions (for plotPattern)
+void PictureMgr::setPattern(uint8 code, uint8 num) {
+ _patCode = code;
+ _patNum = num;
+}
+
+void PictureMgr::setPictureVersion(AgiPictureVersion version) {
+ _pictureVersion = version;
+
+ if (version == AGIPIC_C64)
+ _minCommand = 0xe0;
+ else
+ _minCommand = 0xf0;
+}
+
+void PictureMgr::setPictureData(uint8 *data, int len) {
+ _data = data;
+ _flen = len;
+ _foffs = 0;
+ _flags = 0;
+}
+
} // End of namespace Agi
diff --git a/engines/agi/picture.h b/engines/agi/picture.h
index 0f8584f3b2..50689b5b3a 100644
--- a/engines/agi/picture.h
+++ b/engines/agi/picture.h
@@ -30,6 +30,9 @@
namespace Agi {
+#define _DEFAULT_WIDTH 160
+#define _DEFAULT_HEIGHT 168
+
/**
* AGI picture resource.
*/
@@ -38,11 +41,28 @@ struct AgiPicture {
uint8 *rdata; /**< raw vector image data */
};
-class AgiEngine;
+// AGI picture version
+enum AgiPictureVersion {
+ AGIPIC_C64,
+ AGIPIC_V1,
+ AGIPIC_V15,
+ AGIPIC_V2
+};
+
+enum AgiPictureFlags {
+ kPicFNone = (1 >> 0),
+ kPicFCircle = (1 >> 1),
+ kPicFStep = (1 >> 2),
+ kPicFf3Stop = (1 >> 3),
+ kPicFf3Cont = (1 >> 4),
+ kPicFTrollMode = (1 >> 5)
+};
+
+class AgiBase;
class GfxMgr;
class PictureMgr {
- AgiEngine *_vm;
+ AgiBase *_vm;
GfxMgr *_gfx;
private:
@@ -54,24 +74,69 @@ private:
INLINE int isOkFillHere(int x, int y);
void fillScanline(int x, int y);
void agiFill(unsigned int x, unsigned int y);
- void xCorner();
- void yCorner();
+ void xCorner(bool skipOtherCoords = false);
+ void yCorner(bool skipOtherCoords = false);
void fill();
int plotPatternPoint(int x, int y, int bitpos);
- void plotPattern(int x, int y);
void plotBrush();
- void drawPicture();
+
+ uint8 nextByte() { return _data[_foffs++]; }
public:
- PictureMgr(AgiEngine *agi, GfxMgr *gfx) {
- _vm = agi;
- _gfx = gfx;
- }
+ PictureMgr(AgiBase *agi, GfxMgr *gfx);
- int decodePicture(int n, int clear, bool agi256 = false);
+ int decodePicture(int n, int clear, bool agi256 = false, int pic_width = _DEFAULT_WIDTH, int pic_height = _DEFAULT_HEIGHT);
+ int decodePicture(byte* data, uint32 length, int clear, int pic_width = _DEFAULT_WIDTH, int pic_height = _DEFAULT_HEIGHT);
int unloadPicture(int);
- void showPic();
+ void drawPicture();
+ void showPic(int x = 0, int y = 0, int pic_width = _DEFAULT_WIDTH, int pic_height = _DEFAULT_HEIGHT);
uint8 *convertV3Pic(uint8 *src, uint32 len);
+
+ void plotPattern(int x, int y); // public because it's used directly by preagi
+
+ void setPattern(uint8 code, uint8 num);
+
+ void setPictureVersion(AgiPictureVersion version);
+ void setPictureData(uint8 *data, int len);
+
+ void setPictureFlags(int flags) { _flags = flags; }
+
+ void setOffset(int offX, int offY) {
+ _xOffset = offX;
+ _yOffset = offY;
+ }
+
+ void setDimensions(int w, int h) {
+ _width = w;
+ _height = h;
+ }
+
+ void putPixel(int x, int y, uint8 color) {
+ _scrColor = color;
+ _priOn = false;
+ _scrOn = true;
+ putVirtPixel(x, y);
+ }
+
+private:
+ uint8 *_data;
+ uint32 _flen;
+ uint32 _foffs;
+
+ uint8 _patCode;
+ uint8 _patNum;
+ uint8 _priOn;
+ uint8 _scrOn;
+ uint8 _scrColor;
+ uint8 _priColor;
+
+ uint8 _minCommand;
+
+ AgiPictureVersion _pictureVersion;
+ int _width, _height;
+ int _xOffset, _yOffset;
+
+ int _flags;
};
} // End of namespace Agi
diff --git a/engines/agi/preagi.cpp b/engines/agi/preagi.cpp
new file mode 100644
index 0000000000..b42948ccdb
--- /dev/null
+++ b/engines/agi/preagi.cpp
@@ -0,0 +1,253 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#include "common/stdafx.h"
+
+#include "common/events.h"
+#include "common/file.h"
+#include "common/savefile.h"
+#include "common/config-manager.h"
+
+#include "base/plugins.h"
+#include "base/version.h"
+
+#include "graphics/cursorman.h"
+
+#include "sound/mididrv.h"
+#include "sound/mixer.h"
+
+#include "agi/preagi.h"
+#include "agi/graphics.h"
+#include "agi/sprite.h"
+#include "agi/opcodes.h"
+#include "agi/keyboard.h"
+#include "agi/menu.h"
+#include "agi/sound.h"
+
+// preagi engines
+#include "agi/preagi_mickey.h"
+#include "agi/preagi_troll.h"
+#include "agi/preagi_winnie.h"
+
+namespace Agi {
+
+PreAgiEngine::PreAgiEngine(OSystem *syst) : AgiBase(syst) {
+
+ // Setup mixer
+ if (!_mixer->isReady()) {
+ warning("Sound initialization failed.");
+ }
+
+ _mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, ConfMan.getInt("sfx_volume"));
+ _mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, ConfMan.getInt("music_volume"));
+
+ /*
+ const GameSettings *g;
+
+ const char *gameid = ConfMan.get("gameid").c_str();
+ for (g = agiSettings; g->gameid; ++g)
+ if (!scumm_stricmp(g->gameid, gameid))
+ _gameId = g->id;
+ */
+
+ _rnd = new Common::RandomSource();
+
+ Common::addSpecialDebugLevel(kDebugLevelMain, "Main", "Generic debug level");
+ Common::addSpecialDebugLevel(kDebugLevelResources, "Resources", "Resources debugging");
+ Common::addSpecialDebugLevel(kDebugLevelSprites, "Sprites", "Sprites debugging");
+ Common::addSpecialDebugLevel(kDebugLevelInventory, "Inventory", "Inventory debugging");
+ Common::addSpecialDebugLevel(kDebugLevelInput, "Input", "Input events debugging");
+ Common::addSpecialDebugLevel(kDebugLevelMenu, "Menu", "Menu debugging");
+ Common::addSpecialDebugLevel(kDebugLevelScripts, "Scripts", "Scripts debugging");
+ Common::addSpecialDebugLevel(kDebugLevelSound, "Sound", "Sound debugging");
+ Common::addSpecialDebugLevel(kDebugLevelText, "Text", "Text output debugging");
+ Common::addSpecialDebugLevel(kDebugLevelSavegame, "Savegame", "Saving & restoring game debugging");
+
+ memset(&_game, 0, sizeof(struct AgiGame));
+ memset(&_debug, 0, sizeof(struct AgiDebug));
+ memset(&g_mouse, 0, sizeof(struct Mouse));
+
+/*
+ _game.clockEnabled = false;
+ _game.state = STATE_INIT;
+
+ _keyQueueStart = 0;
+ _keyQueueEnd = 0;
+
+ _keyControl = 0;
+ _keyAlt = 0;
+
+ _allowSynthetic = false;
+
+ g_tickTimer = 0;
+
+ _intobj = NULL;
+
+ _stackSize = 0;
+ _imageStack = NULL;
+ _imageStackPointer = 0;
+
+ _lastSentence[0] = 0;
+ memset(&_stringdata, 0, sizeof(struct StringData));
+
+ _objects = NULL;
+
+ _oldMode = -1;
+
+ _firstSlot = 0;
+*/
+}
+
+void PreAgiEngine::initialize() {
+ // TODO: Some sound emulation modes do not fit our current music
+ // drivers, and I'm not sure what they are. For now, they might
+ // as well be called "PC Speaker" and "Not PC Speaker".
+
+ switch (MidiDriver::detectMusicDriver(MDT_PCSPK)) {
+ case MD_PCSPK:
+ _soundemu = SOUND_EMU_PC;
+ break;
+ default:
+ _soundemu = SOUND_EMU_NONE;
+ break;
+ }
+
+ if (ConfMan.hasKey("render_mode")) {
+ _renderMode = Common::parseRenderMode(ConfMan.get("render_mode").c_str());
+ } else if (ConfMan.hasKey("platform")) {
+ switch (Common::parsePlatform(ConfMan.get("platform"))) {
+ case Common::kPlatformAmiga:
+ _renderMode = Common::kRenderAmiga;
+ break;
+ case Common::kPlatformPC:
+ _renderMode = Common::kRenderEGA;
+ break;
+ default:
+ _renderMode = Common::kRenderEGA;
+ break;
+ }
+ }
+
+ _gfx = new GfxMgr(this);
+ _sound = new SoundMgr(this, _mixer);
+ _picture = new PictureMgr(this, _gfx);
+ //_sprites = new SpritesMgr(this, _gfx);
+
+ _gfx->initMachine();
+
+ _game.gameFlags = 0;
+
+ _game.colorFg = 15;
+ _game.colorBg = 0;
+
+ _defaultColor = 0xF;
+
+ _game.name[0] = '\0';
+
+ _game.sbufOrig = (uint8 *)calloc(_WIDTH, _HEIGHT * 2); // Allocate space for two AGI screens vertically
+ _game.sbuf16c = _game.sbufOrig + SBUF16_OFFSET; // Make sbuf16c point to the 16 color (+control line & priority info) AGI screen
+ _game.sbuf = _game.sbuf16c; // Make sbuf point to the 16 color (+control line & priority info) AGI screen by default
+
+ _game.lineMinPrint = 0; // hardcoded
+
+ _gfx->initVideo();
+ _sound->initSound();
+
+ //_timer->installTimerProc(agiTimerFunctionLow, 10 * 1000, NULL);
+
+ _game.ver = -1; // Don't display the conf file warning
+
+ debugC(2, kDebugLevelMain, "Detect game");
+
+ /* clear all resources and events */
+ for (int i = 0; i < MAX_DIRS; i++) {
+ memset(&_game.pictures[i], 0, sizeof(struct AgiPicture));
+ memset(&_game.sounds[i], 0, sizeof(class AgiSound *)); // _game.sounds contains pointers now
+ memset(&_game.dirPic[i], 0, sizeof(struct AgiDir));
+ memset(&_game.dirSound[i], 0, sizeof(struct AgiDir));
+ }
+
+ debugC(2, kDebugLevelMain, "Init sound");
+}
+
+PreAgiEngine::~PreAgiEngine() {
+
+}
+
+int PreAgiEngine::init() {
+
+ // Detect game
+ if (!initGame()) {
+ GUIErrorMessage("No valid games were found in the specified directory.");
+ return -1;
+ }
+
+ // Initialize backend
+ _system->beginGFXTransaction();
+ initCommonGFX(false);
+ _system->initSize(320, 200);
+ _system->endGFXTransaction();
+
+ initialize();
+
+ _gfx->gfxSetPalette();
+
+ return 0;
+}
+
+int PreAgiEngine::go() {
+ setflag(fSoundOn, true); // enable sound
+
+ // run preagi engine main loop
+ switch (getGameID()) {
+ case GID_MICKEY:
+ {
+ Mickey *mickey = new Mickey(this);
+ mickey->init();
+ mickey->run();
+ }
+ break;
+ case GID_WINNIE:
+ {
+ Winnie *winnie = new Winnie(this);
+ winnie->init();
+ winnie->run();
+ }
+ break;
+ case GID_TROLL:
+ {
+ Troll *troll = new Troll(this);
+ troll->init();
+ troll->run();
+ }
+ break;
+ default:
+ error("Unknown preagi engine");
+ break;
+ }
+ return 0;
+}
+
+} // End of namespace Agi
diff --git a/engines/agi/preagi.h b/engines/agi/preagi.h
new file mode 100644
index 0000000000..50c68991c9
--- /dev/null
+++ b/engines/agi/preagi.h
@@ -0,0 +1,99 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#ifndef AGI_PREAGI_H
+#define AGI_PREAGI_H
+
+#include "agi/agi.h"
+#include "agi/preagi_common.h"
+
+namespace Agi {
+
+class PreAgiEngine : public AgiBase {
+ int _gameId;
+
+protected:
+ int init();
+ int go();
+ void shutdown();
+ void initialize();
+
+ bool initGame();
+
+public:
+ void agiTimerLow() {}
+ int agiGetKeypressLow() { return 0; }
+ int agiIsKeypressLow() { return 0; }
+
+ PreAgiEngine(OSystem *syst);
+ virtual ~PreAgiEngine();
+ int getGameId() {
+ return _gameId;
+ }
+
+ GfxMgr *_gfx;
+ SoundMgr *_sound;
+ PictureMgr *_picture;
+
+ void clearImageStack() {}
+ void recordImageStackCall(uint8 type, int16 p1, int16 p2, int16 p3,
+ int16 p4, int16 p5, int16 p6, int16 p7) {}
+ void replayImageStackCall(uint8 type, int16 p1, int16 p2, int16 p3,
+ int16 p4, int16 p5, int16 p6, int16 p7) {}
+ void releaseImageStack() {}
+
+ // Game
+ Common::String getTargetName() { return _targetName; }
+
+ // Screen
+ void clearScreen(int attr, bool overrideDefault = true);
+ void clearGfxScreen(int attr);
+ void setDefaultTextColor(int attr) { _defaultColor = attr; }
+
+ // Keyboard
+ int getSelection(SelectionTypes type);
+ bool waitAnyKeyChoice();
+ int rnd(int hi) { return (_rnd->getRandomNumber(hi) + 1); }
+
+ // Text
+ void drawStr(int row, int col, int attr, const char *buffer);
+ void drawStrMiddle(int row, int attr, const char *buffer);
+ void clearTextArea();
+ void clearRow(int row);
+ void XOR80(char *buffer);
+ void printStr(const char *szMsg);
+ void printStrXOR(char *szMsg);
+
+ // Saved Games
+ Common::SaveFileManager* getSaveFileMan() { return _saveFileMan; }
+
+private:
+ int _defaultColor;
+};
+
+} // End of namespace Agi
+
+
+#endif
diff --git a/engines/agi/preagi_common.cpp b/engines/agi/preagi_common.cpp
new file mode 100644
index 0000000000..9ad494e410
--- /dev/null
+++ b/engines/agi/preagi_common.cpp
@@ -0,0 +1,211 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#include "common/stdafx.h"
+#include "common/events.h"
+
+#include "agi/preagi.h"
+#include "agi/font.h"
+#include "agi/graphics.h"
+#include "agi/keyboard.h"
+
+#include "agi/preagi_common.h"
+
+namespace Agi {
+
+// Screen functions
+void PreAgiEngine::clearScreen(int attr, bool overrideDefault) {
+ if (overrideDefault)
+ _defaultColor = attr;
+
+ _gfx->clearScreen((attr & 0xF0) / 0x10);
+}
+
+void PreAgiEngine::clearGfxScreen(int attr) {
+ _gfx->drawRectangle(0, 0, GFX_WIDTH - 1, IDI_MAX_ROW_PIC * 8 -1, (attr & 0xF0) / 0x10);
+}
+
+// String functions
+
+void PreAgiEngine::drawStr(int row, int col, int attr, const char *buffer) {
+ int code;
+
+ if (attr == kColorDefault)
+ attr = _defaultColor;
+
+ for (int iChar = 0; iChar < (int)strlen(buffer); iChar++) {
+ code = buffer[iChar];
+
+ switch (code) {
+ case '\n':
+ case 0x8D:
+ if (++row == 200 / 8) return;
+ col = 0;
+ break;
+
+ case '|':
+ // swap attribute nibbles
+ break;
+
+ default:
+ _gfx->putTextCharacter(1, col * 8 , row * 8, static_cast<char>(code), attr & 0x0f, (attr & 0xf0) / 0x10, false, getGameID() == GID_MICKEY ? mickey_fontdata : ibm_fontdata);
+
+ if (++col == 320 / 8) {
+ col = 0;
+ if (++row == 200 / 8) return;
+ }
+ }
+ }
+}
+
+void PreAgiEngine::drawStrMiddle(int row, int attr, const char *buffer) {
+ int col = (25 / 2) - (strlen(buffer) / 2); // 25 = 320 / 8 (maximum column)
+ drawStr(row, col, attr, buffer);
+}
+
+void PreAgiEngine::clearTextArea() {
+ int start = IDI_MAX_ROW_PIC;
+
+ if (getGameID() == GID_TROLL)
+ start = 21;
+
+ for (int row = start; row < 200 / 8; row++) {
+ clearRow(row);
+ }
+}
+
+void PreAgiEngine::clearRow(int row) {
+ drawStr(row, 0, IDA_DEFAULT, " "); // 40 spaces
+}
+
+void PreAgiEngine::printStr(const char* szMsg) {
+ clearTextArea();
+ drawStr(21, 0, IDA_DEFAULT, szMsg);
+ _gfx->doUpdate();
+ _system->updateScreen();
+}
+
+void PreAgiEngine::XOR80(char *buffer) {
+ for (size_t i = 0; i < strlen(buffer); i++)
+ if (buffer[i] & 0x80)
+ buffer[i] ^= 0x80;
+}
+
+void PreAgiEngine::printStrXOR(char *szMsg) {
+ XOR80(szMsg);
+ printStr(szMsg);
+}
+
+// Input functions
+
+int PreAgiEngine::getSelection(SelectionTypes type) {
+ Common::Event event;
+
+ // Selection types:
+ // 0: Y/N
+ // 1: 1-9
+ for (;;) {
+ while (_eventMan->pollEvent(event)) {
+ switch(event.type) {
+ case Common::EVENT_QUIT:
+ _system->quit();
+ case Common::EVENT_LBUTTONUP:
+ if (type == kSelYesNo)
+ return 1;
+ case Common::EVENT_RBUTTONUP:
+ return 0;
+ case Common::EVENT_KEYDOWN:
+ switch (event.kbd.keycode) {
+ case Common::KEYCODE_y:
+ if (type == kSelYesNo)
+ return 1;
+ case Common::KEYCODE_n:
+ if (type == kSelYesNo)
+ return 0;
+ case Common::KEYCODE_ESCAPE:
+ if (type == kSelNumber)
+ return 0;
+ case Common::KEYCODE_1:
+ case Common::KEYCODE_2:
+ case Common::KEYCODE_3:
+ case Common::KEYCODE_4:
+ case Common::KEYCODE_5:
+ case Common::KEYCODE_6:
+ case Common::KEYCODE_7:
+ case Common::KEYCODE_8:
+ case Common::KEYCODE_9:
+ if (type == kSelNumber)
+ return event.kbd.keycode - Common::KEYCODE_1 + 1;
+ case Common::KEYCODE_SPACE:
+ if (type == kSelSpace)
+ return 1;
+ default:
+ if (type == kSelYesNo) {
+ return 2;
+ } else if (type == kSelNumber) {
+ return 10;
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ _system->updateScreen();
+ _system->delayMillis(10);
+ }
+ return 0;
+}
+
+bool PreAgiEngine::waitAnyKeyChoice() {
+ Common::Event event;
+
+ for (;;) {
+ while (_eventMan->pollEvent(event)) {
+ switch(event.type) {
+ case Common::EVENT_QUIT:
+ _system->quit();
+ case Common::EVENT_LBUTTONUP:
+ return true;
+ case Common::EVENT_RBUTTONUP:
+ return false;
+ case Common::EVENT_KEYDOWN:
+ switch (event.kbd.keycode) {
+ case Common::KEYCODE_ESCAPE: //Escape
+ return false;
+ default:
+ return true;
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ _system->updateScreen();
+ _system->delayMillis(10);
+ }
+}
+
+}
diff --git a/engines/parallaction/commands.h b/engines/agi/preagi_common.h
index 64510afc13..434bb685a6 100644
--- a/engines/parallaction/commands.h
+++ b/engines/agi/preagi_common.h
@@ -23,61 +23,27 @@
*
*/
-#ifndef PARALLACTION_COMMANDS_H
-#define PARALLACTION_COMMANDS_H
-#include "common/stdafx.h"
-#include "common/scummsys.h"
+#ifndef AGI_PREAGI_COMMON_H
+#define AGI_PREAGI_COMMON_H
-#include "parallaction/defs.h"
+namespace Agi {
-namespace Parallaction {
+// default attributes
+#define IDA_DEFAULT 0x0F
+#define IDA_DEFAULT_REV 0xF0
-enum CommandFlags {
- kFlagsVisited = 1,
- kFlagsExit = 0x10000000,
- kFlagsEnter = 0x20000000,
- kFlagsGlobal = 0x40000000
-};
-
-struct Zone;
-struct Animation;
-
-
-// TODO: turn this into a struct
-union CommandData {
- uint32 _flags;
- Animation * _animation;
- Zone* _zone;
- char* _string;
- uint16 _callable;
- uint16 _object;
- struct {
- int16 _x;
- int16 _y;
- } _move;
+#define kColorDefault 0x1337
- CommandData() {
- _flags = 0;
- }
+#define IDI_MAX_ROW_PIC 20
- ~CommandData() {
- }
+enum SelectionTypes {
+ kSelYesNo,
+ kSelNumber,
+ kSelSpace
};
-struct Command {
- uint16 _id;
- CommandData u;
- uint32 _flagsOn;
- uint32 _flagsOff;
-
- Command();
- ~Command();
-};
-
-typedef ManagedList<Command*> CommandList;
-
-} // namespace Parallaction
+} // End of namespace Agi
#endif
diff --git a/engines/agi/preagi_mickey.cpp b/engines/agi/preagi_mickey.cpp
new file mode 100644
index 0000000000..5215d90c21
--- /dev/null
+++ b/engines/agi/preagi_mickey.cpp
@@ -0,0 +1,2215 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#include "common/stdafx.h"
+#include "common/events.h"
+#include "common/savefile.h"
+
+#include "graphics/cursorman.h"
+
+#include "agi/preagi.h"
+#include "agi/preagi_common.h"
+#include "agi/preagi_mickey.h"
+#include "agi/graphics.h"
+
+#define IDI_SND_OSCILLATOR_FREQUENCY 1193180
+
+namespace Agi {
+
+int Mickey::getDat(int iRoom) {
+ if (((iRoom > 0) && (iRoom < 24)) || iRoom == 154 || iRoom == 155) return IDI_MSA_PLANET_EARTH;
+ if ((iRoom >= 30) && (iRoom <= 39)) return IDI_MSA_PLANET_VENUS;
+ if ((iRoom >= 40) && (iRoom <= 69)) return IDI_MSA_PLANET_NEPTUNE;
+ if ((iRoom >= 70) && (iRoom <= 82)) return IDI_MSA_PLANET_MERCURY;
+ if ((iRoom >= 83) && (iRoom <= 92)) return IDI_MSA_PLANET_SATURN;
+ if ((iRoom >= 93) && (iRoom <= 103)) return IDI_MSA_PLANET_PLUTO;
+ if ((iRoom >= 106) && (iRoom <= 120)) return IDI_MSA_PLANET_JUPITER;
+ if ((iRoom >= 121) && (iRoom <= 132)) return IDI_MSA_PLANET_MARS;
+ if ((iRoom >= 133) && (iRoom <= 145)) return IDI_MSA_PLANET_URANUS;
+ return IDI_MSA_PLANET_SPACESHIP;
+}
+
+void Mickey::readExe(int ofs, uint8 *buffer, long buflen) {
+ Common::File infile;
+ if (!infile.open(IDS_MSA_PATH_EXE))
+ return;
+ infile.seek(ofs, SEEK_SET);
+ infile.read(buffer, buflen);
+ infile.close();
+}
+
+void Mickey::getDatFileName(int iRoom, char *szFile) {
+ sprintf(szFile, IDS_MSA_PATH_DAT, IDS_MSA_NAME_DAT[getDat(iRoom)]);
+}
+
+void Mickey::readDatHdr(char *szFile, MSA_DAT_HEADER *hdr) {
+ Common::File infile;
+
+ if (!infile.open(szFile))
+ return;
+
+ hdr->filelen = infile.readByte();
+ hdr->filelen += infile.readByte() * 0x100;
+ for (int i = 0; i < IDI_MSA_MAX_ROOM; i++) {
+ hdr->ofsRoom[i] = infile.readByte();
+ hdr->ofsRoom[i] += infile.readByte() * 0x100;
+ }
+ for (int i = 0; i < IDI_MSA_MAX_ROOM; i++) {
+ hdr->ofsDesc[i] = infile.readByte();
+ hdr->ofsDesc[i] += infile.readByte() * 0x100;
+ }
+ for (int i = 0; i < IDI_MSA_MAX_ROOM; i++) {
+ hdr->ofsStr[i] = infile.readByte();
+ hdr->ofsStr[i] += infile.readByte() * 0x100;
+ }
+
+ infile.close();
+}
+
+void Mickey::readDesc(int iRoom, char *buffer, long buflen) {
+ MSA_DAT_HEADER hdr;
+ char szFile[256] = {0};
+
+ getDatFileName(iRoom, szFile);
+ readDatHdr(szFile, &hdr);
+
+ Common::File infile;
+
+ if (!infile.open(szFile))
+ return;
+
+ memset(buffer, 0, buflen);
+
+ infile.seek(hdr.ofsDesc[iRoom - 1] + IDI_MSA_OFS_DAT, SEEK_SET);
+ infile.read(buffer, buflen);
+ infile.close();
+}
+
+void Mickey::readMenu(int iRoom, char *buffer) {
+ MSA_DAT_HEADER hdr;
+ char szFile[256] = {0};
+
+ getDatFileName(iRoom, szFile);
+ readDatHdr(szFile, &hdr);
+
+ Common::File infile;
+
+ if (!infile.open(szFile))
+ return;
+
+ infile.seek(hdr.ofsRoom[iRoom - 1] + IDI_MSA_OFS_DAT, SEEK_SET);
+ infile.read((uint8 *)buffer, sizeof(MSA_MENU));
+ infile.close();
+}
+
+void Mickey::readDatStr(int iDat, int iStr, char *buffer, long buflen) {
+ MSA_DAT_HEADER hdr;
+ char szFile[256] = {0};
+
+ sprintf(szFile, IDS_MSA_PATH_DAT, IDS_MSA_NAME_DAT[iDat]);
+ readDatHdr(szFile, &hdr);
+
+ Common::File infile;
+
+ if (!infile.open(szFile))
+ return;
+
+ infile.seek(hdr.ofsStr[iStr] + IDI_MSA_OFS_DAT, SEEK_SET);
+ infile.read((uint8 *)buffer, buflen);
+ infile.close();
+}
+
+void Mickey::readOfsData(int offset, int iItem, uint8 *buffer, long buflen) {
+ uint16 ofs[256];
+
+ readExe(offset, buffer, buflen);
+ memcpy(ofs, buffer, sizeof(ofs));
+ for (int i = 0; i < 256; i++)
+ ofs[i] = buffer[i*2] + 256 * buffer[i*2+1];
+ readExe(ofs[iItem] + IDI_MSA_OFS_EXE, buffer, buflen);
+}
+
+// User Interface
+
+bool Mickey::chooseY_N(int ofsPrompt, bool fErrorMsg) {
+ printExeStr(ofsPrompt);
+
+ _vm->_gfx->doUpdate();
+ _vm->_system->updateScreen(); // TODO: this should go in the game's main loop
+
+ int a = _vm->getSelection(kSelYesNo);
+ for (;;) {
+ switch (a) {
+ case 0: return false;
+ case 1: return true;
+ default: if (fErrorMsg) {
+ printExeStr(IDO_MSA_PRESS_YES_OR_NO);
+ waitAnyKey();
+ printExeStr(ofsPrompt);
+ }
+ break;
+ }
+ a = _vm->getSelection(kSelYesNo);
+ }
+}
+
+int Mickey::choose1to9(int ofsPrompt) {
+ printExeStr(ofsPrompt);
+
+ _vm->_gfx->doUpdate();
+ _vm->_system->updateScreen(); // TODO: this should go in the game's main loop
+
+ int a = _vm->getSelection(kSelNumber);
+ for (;;) {
+ if (a == 10) {
+ printExeStr(IDO_MSA_PRESS_1_TO_9);
+ if (!_vm->waitAnyKeyChoice())
+ return 0;
+ printExeStr(ofsPrompt);
+ } else return a;
+ a = _vm->getSelection(kSelNumber);
+ }
+
+}
+
+void Mickey::printStr(char *buffer) {
+ int pc = 1;
+ int nRows, iCol, iRow;
+
+ nRows = *buffer + IDI_MSA_ROW_MENU_0;
+
+ _vm->clearTextArea();
+
+ for (iRow = IDI_MSA_ROW_MENU_0; iRow < nRows; iRow++) {
+ iCol = *(buffer + pc++);
+ _vm->drawStr(iRow, iCol, IDA_DEFAULT, buffer + pc);
+ pc += strlen(buffer + pc) + 1;
+ }
+}
+
+void Mickey::printExeStr(int ofs) {
+ uint8 buffer[256] = {0};
+
+ if (!ofs)
+ return;
+
+ readExe(ofs, buffer, sizeof(buffer));
+ printStr((char *)buffer);
+ //_vm->_gfx->doUpdate();
+ //_vm->_system->updateScreen(); // TODO: this should go in the game's main loop
+}
+
+void Mickey::printExeMsg(int ofs) {
+ if (!ofs)
+ return;
+ printExeStr(ofs);
+ waitAnyKeyAnim();
+}
+
+void Mickey::printDatStr(int iDat, int iStr) {
+ char *buffer = (char *)malloc(256);
+ readDatStr(iDat, iStr, buffer, 256);
+ printStr(buffer);
+ free(buffer);
+}
+
+void Mickey::printDesc(int iRoom) {
+ char *buffer = (char *)malloc(256);
+ readDesc(iRoom, buffer, 256);
+ printStr(buffer);
+ //_vm->_gfx->doUpdate();
+ //_vm->_system->updateScreen(); // TODO: this should go in the game's main loop
+ free(buffer);
+}
+
+void Mickey::drawMenu(MSA_MENU menu, int sel0, int sel1) {
+ int iWord;
+ int iRow;
+ int sel;
+ uint8 attr;
+
+ // draw menu
+
+ _vm->clearTextArea();
+
+ for (iRow = 0; iRow < 2; iRow++) {
+ for (iWord = 0; iWord < menu.row[iRow].count; iWord++) {
+ if (iRow)
+ sel = sel1;
+ else
+ sel = sel0;
+
+ if (iWord == sel)
+ attr = IDA_DEFAULT_REV;
+ else
+ attr = IDA_DEFAULT;
+
+ _vm->drawStr(IDI_MSA_ROW_MENU_0 + iRow, menu.row[iRow].entry[iWord].x0,
+ attr, (char *)menu.row[iRow].entry[iWord].szText);
+ }
+ }
+
+ _vm->_gfx->doUpdate();
+ _vm->_system->updateScreen(); // TODO: this should go in the game's main loop
+}
+
+void Mickey::getMouseMenuSelRow(MSA_MENU menu, int *sel0, int *sel1, int iRow, int x, int y) {
+ int iWord;
+ int *sel = 0;
+
+ switch(iRow) {
+ case 0:
+ if (y != IDI_MSA_ROW_MENU_0) return;
+ sel = sel0;
+ break;
+ case 1:
+ if (y != IDI_MSA_ROW_MENU_1) return;
+ sel = sel1;
+ break;
+ }
+
+ for (iWord = 0; iWord < menu.row[iRow].count; iWord++) {
+ if ((x >= menu.row[iRow].entry[iWord].x0) &&
+ (x < (int)(menu.row[iRow].entry[iWord].x0 +
+ strlen((char *)menu.row[iRow].entry[iWord].szText)))) {
+ *sel = iWord;
+ break;
+ }
+ }
+}
+
+bool Mickey::getMenuSelRow(MSA_MENU menu, int *sel0, int *sel1, int iRow) {
+ Common::Event event;
+ int *sel = 0;
+ int nWords;
+ int x, y;
+ int goIndex = -1, northIndex = -1, southIndex = -1, eastIndex = -1, westIndex = -1;
+
+ switch(iRow) {
+ case 0:
+ sel = sel0;
+ break;
+ case 1:
+ sel = sel1;
+ break;
+ }
+ nWords = menu.row[iRow].count;
+ clickToMove = false;
+
+ for (int i = 0; i <= menu.row[0].count; i++)
+ if (menu.row[0].entry[i].szText[0] == 71 && menu.row[0].entry[i].szText[1] == 79) // GO
+ goIndex = i;
+
+ if (goIndex >= 0) {
+ for (int j = 0; j <= menu.row[1].count; j++) {
+ if (menu.row[1].entry[j].szText[0] == 78 && menu.row[1].entry[j].szText[1] == 79 &&
+ menu.row[1].entry[j].szText[2] == 82 && menu.row[1].entry[j].szText[3] == 84 &&
+ menu.row[1].entry[j].szText[4] == 72)
+ northIndex = j;
+ if (menu.row[1].entry[j].szText[0] == 83 && menu.row[1].entry[j].szText[1] == 79 &&
+ menu.row[1].entry[j].szText[2] == 85 && menu.row[1].entry[j].szText[3] == 84 &&
+ menu.row[1].entry[j].szText[4] == 72)
+ southIndex = j;
+ if (menu.row[1].entry[j].szText[0] == 69 && menu.row[1].entry[j].szText[1] == 65 &&
+ menu.row[1].entry[j].szText[2] == 83 && menu.row[1].entry[j].szText[3] == 84)
+ eastIndex = j;
+ if (menu.row[1].entry[j].szText[0] == 87 && menu.row[1].entry[j].szText[1] == 69 &&
+ menu.row[1].entry[j].szText[2] == 83 && menu.row[1].entry[j].szText[3] == 84)
+ westIndex = j;
+ }
+ }
+
+ drawMenu(menu, *sel0, *sel1);
+
+ for (;;) {
+ while (_vm->_system->getEventManager()->pollEvent(event)) {
+ switch(event.type) {
+ case Common::EVENT_QUIT:
+ exit(0);
+ case Common::EVENT_MOUSEMOVE:
+ if (iRow < 2) {
+ x = event.mouse.x / 8;
+ y = event.mouse.y / 8;
+ // If the mouse hovers over the menu, refresh the menu
+ if ((iRow == 0 && y == IDI_MSA_ROW_MENU_0) || (iRow == 1 && y == IDI_MSA_ROW_MENU_1)) {
+ getMouseMenuSelRow(menu, sel0, sel1, iRow, x, y);
+ drawMenu(menu, *sel0, *sel1);
+ }
+
+ // Change cursor
+ if (northIndex >= 0 && (event.mouse.x >= 20 && event.mouse.x <= (IDI_MSA_PIC_WIDTH + 10) * 2) &&
+ (event.mouse.y >= 0 && event.mouse.y <= 10)) {
+ _vm->_gfx->setCursorPalette(true);
+ } else if (southIndex >= 0 && (event.mouse.x >= 20 && event.mouse.x <= (IDI_MSA_PIC_WIDTH + 10) * 2) &&
+ (event.mouse.y >= IDI_MSA_PIC_HEIGHT - 10 && event.mouse.y <= IDI_MSA_PIC_HEIGHT)) {
+ _vm->_gfx->setCursorPalette(true);
+ } else if (westIndex >= 0 && (event.mouse.y >= 0 && event.mouse.y <= IDI_MSA_PIC_HEIGHT) &&
+ (event.mouse.x >= 20 && event.mouse.x <= 30)) {
+ _vm->_gfx->setCursorPalette(true);
+ } else if (eastIndex >= 0 && (event.mouse.y >= 0 && event.mouse.y <= IDI_MSA_PIC_HEIGHT) &&
+ (event.mouse.x >= IDI_MSA_PIC_WIDTH * 2 && event.mouse.x <= (IDI_MSA_PIC_WIDTH + 10) * 2)) {
+ _vm->_gfx->setCursorPalette(true);
+ } else {
+ _vm->_gfx->setCursorPalette(false);
+ }
+ }
+ break;
+ case Common::EVENT_LBUTTONUP:
+ // Click to move
+ if (northIndex >= 0 && (event.mouse.x >= 20 && event.mouse.x <= (IDI_MSA_PIC_WIDTH + 10) * 2) &&
+ (event.mouse.y >= 0 && event.mouse.y <= 10)) {
+ *sel0 = goIndex; *sel1 = northIndex;
+ drawMenu(menu, *sel0, *sel1);
+ _vm->_gfx->setCursorPalette(false);
+ clickToMove = true;
+ } else if (southIndex >= 0 && (event.mouse.x >= 20 && event.mouse.x <= (IDI_MSA_PIC_WIDTH + 10) * 2) &&
+ (event.mouse.y >= IDI_MSA_PIC_HEIGHT - 10 && event.mouse.y <= IDI_MSA_PIC_HEIGHT)) {
+ *sel0 = goIndex; *sel1 = southIndex;
+ drawMenu(menu, *sel0, *sel1);
+ _vm->_gfx->setCursorPalette(false);
+ clickToMove = true;
+ } else if (westIndex >= 0 && (event.mouse.y >= 0 && event.mouse.y <= IDI_MSA_PIC_HEIGHT) &&
+ (event.mouse.x >= 20 && event.mouse.x <= 30)) {
+ *sel0 = goIndex; *sel1 = westIndex;
+ drawMenu(menu, *sel0, *sel1);
+ _vm->_gfx->setCursorPalette(false);
+ clickToMove = true;
+ } else if (eastIndex >= 0 && (event.mouse.y >= 0 && event.mouse.y <= IDI_MSA_PIC_HEIGHT) &&
+ (event.mouse.x >= IDI_MSA_PIC_WIDTH * 2 && event.mouse.x <= (IDI_MSA_PIC_WIDTH + 10) * 2)) {
+ *sel0 = goIndex; *sel1 = eastIndex;
+ drawMenu(menu, *sel0, *sel1);
+ _vm->_gfx->setCursorPalette(false);
+ clickToMove = true;
+ } else {
+ _vm->_gfx->setCursorPalette(false);
+ }
+ return true;
+ case Common::EVENT_RBUTTONUP:
+ *sel0 = 0; *sel1 = -1;
+ return false;
+ case Common::EVENT_WHEELUP:
+ if (iRow < 2) {
+ *sel -= 1;
+ if (*sel < 0) *sel = nWords - 1;
+ drawMenu(menu, *sel0, *sel1);
+ }
+ break;
+ case Common::EVENT_WHEELDOWN:
+ if (iRow < 2) {
+ *sel += 1;
+ if (*sel == nWords) *sel = 0;
+ drawMenu(menu, *sel0, *sel1);
+ }
+ break;
+ case Common::EVENT_KEYDOWN:
+ switch (event.kbd.keycode) {
+ case Common::KEYCODE_2:
+ hidden();
+ break;
+ case Common::KEYCODE_8:
+ if (event.kbd.flags & Common::KBD_CTRL) {
+ *sel0 = 0; *sel1 = -1; return false;
+ }
+ break;
+ case Common::KEYCODE_ESCAPE:
+ *sel0 = 0; *sel1 = -1; return false;
+ case Common::KEYCODE_s:
+ _vm->flipflag(fSoundOn);
+ break;
+ case Common::KEYCODE_c:
+ inventory();
+ drawRoom();
+ *sel0 = 0; *sel1 = -1; return false;
+ case Common::KEYCODE_b:
+ printRoomDesc();
+ drawMenu(menu, *sel0, *sel1);
+ *sel0 = 0; *sel1 = -1; return false;
+ case Common::KEYCODE_LEFT:
+ case Common::KEYCODE_KP4:
+ case Common::KEYCODE_4:
+ if (iRow < 2) {
+ *sel -= 1;
+ if (*sel < 0) *sel = nWords - 1;
+ drawMenu(menu, *sel0, *sel1);
+ }
+ break;
+ case Common::KEYCODE_RIGHT:
+ case Common::KEYCODE_SPACE:
+ case Common::KEYCODE_KP6:
+ case Common::KEYCODE_6:
+ if (iRow < 2) {
+ *sel += 1;
+ if (*sel == nWords) *sel = 0;
+ drawMenu(menu, *sel0, *sel1);
+ }
+ break;
+ case Common::KEYCODE_RETURN:
+ case Common::KEYCODE_KP_ENTER:
+ return true;
+ default:
+ break;
+ }
+ break;
+ default:
+ break;
+ }
+ animate();
+ drawMenu(menu, *sel0, *sel1);
+ }
+ animate();
+ drawMenu(menu, *sel0, *sel1);
+ }
+}
+
+void Mickey::getMenuSel(char *buffer, int *sel0, int *sel1) {
+ MSA_MENU menu;
+
+ memcpy(&menu, buffer, sizeof(MSA_MENU));
+
+ *sel0 = 0;
+ *sel1 = -1;
+
+ // Show the mouse cursor for the menu
+ CursorMan.showMouse(true);
+
+ for (;;) {
+ for (;;) {
+ if (getMenuSelRow(menu, sel0, sel1, 0)) {
+ if (clickToMove)
+ break;
+ *sel1 = 0;
+ if (getMenuSelRow(menu, sel0, sel1, 1)) {
+ break;
+ }
+ }
+ }
+ if (clickToMove || getMenuSelRow(menu, sel0, sel1, 2)) {
+ break;
+ }
+ }
+
+ // Menu selection made, hide the mouse cursor
+ CursorMan.showMouse(false);
+}
+
+void Mickey::centerMenu(MSA_MENU *menu) {
+ int iWord;
+ int iRow;
+ int w, x;
+
+ for (iRow = 0; iRow < 2; iRow++) {
+ w = 0;
+ for (iWord = 0; iWord < menu->row[iRow].count; iWord++) {
+ w += strlen((char *)menu->row[iRow].entry[iWord].szText);
+ }
+ w += menu->row[iRow].count - 1;
+ x = (40 - w) / 2; // FIX
+ for (iWord = 0; iWord < menu->row[iRow].count; iWord++) {
+ menu->row[iRow].entry[iWord].x0 = x;
+ x += strlen((char *)menu->row[iRow].entry[iWord].szText) + 1;
+ }
+ }
+}
+
+void Mickey::patchMenu(MSA_MENU *menu) {
+ uint8 buffer[512];
+ uint8 menubuf[sizeof(MSA_MENU)];
+ int nPatches;
+ int pBuf = 0;
+
+ // change planet name in ship airlock menu
+ if (game.iRoom == IDI_MSA_PIC_SHIP_AIRLOCK) {
+ strcpy((char *)menu->row[1].entry[2].szText, IDS_MSA_NAME_PLANET[game.iPlanet]);
+ }
+
+ // exit if fix unnecessary
+ if (!game.iRmMenu[game.iRoom]) {
+ centerMenu(menu);
+ return;
+ }
+
+ // copy menu to menubuf
+ memcpy(menubuf, menu, sizeof(menubuf));
+
+ // read patches
+ readOfsData(
+ IDOFS_MSA_MENU_PATCHES,
+ game.nRmMenu[game.iRoom] + game.iRmMenu[game.iRoom] - 1,
+ buffer, sizeof(buffer)
+ );
+
+ // get number of patches
+ nPatches = buffer[pBuf++];
+
+ // patch menubuf
+ for (int iPatch = 0; iPatch < nPatches; iPatch++) {
+ if (buffer[pBuf] > sizeof(menubuf)) {
+ // patch address out of bounds
+ }
+ menubuf[buffer[pBuf]] = buffer[pBuf + 1];
+ pBuf += 2;
+ }
+
+ // copy menubuf back to menu
+ memcpy(menu, menubuf, sizeof(MSA_MENU));
+
+ // center menu
+ centerMenu(menu);
+}
+
+void Mickey::printDatString(int iStr) {
+ printDatStr(getDat(game.iRoom), iStr);
+}
+
+void Mickey::printDatMessage(int iStr) {
+ printDatString(iStr);
+ //_vm->_gfx->doUpdate();
+ //_vm->_system->updateScreen(); // TODO: this should go in the game's main loop
+ waitAnyKeyAnim();
+}
+
+// Sound
+
+void Mickey::playNote(MSA_SND_NOTE note) {
+ // TODO
+ if (!note.counter) {
+ //_vm->_sound->playNote(1, 0, 160); // ScummVM
+ //playNote(1, 0, note.length / IDI_SND_TIMER_RESOLUTION); // TrollVM
+ } else {
+ //_vm->_sound->playNote(1, IDI_SND_OSCILLATOR_FREQUENCY / note.counter, 160); // ScummVM
+ //playNote(1, IDI_SND_OSCILLATOR_FREQUENCY / note.counter,
+ // note.length / IDI_SND_TIMER_RESOLUTION / IDI_SND_PITCH); // TrollVM
+ }
+}
+
+void Mickey::playSound(ENUM_MSA_SOUND iSound) {
+ if (!_vm->getflag(fSoundOn))
+ return;
+
+ Common::Event event;
+ MSA_SND_NOTE note;
+ uint8 *buffer = new uint8[1024];
+ int pBuf = 1;
+
+ switch(iSound) {
+ case IDI_MSA_SND_XL30:
+ for (int iNote = 0; iNote < 6; iNote++) {
+ note.counter = _vm->rnd(59600) + 59;
+ note.length = 4;
+ playNote(note);
+ }
+ break;
+ default:
+ readOfsData(IDOFS_MSA_SOUND_DATA, iSound, buffer, 1024);
+
+ for (;;) {
+ memcpy(&note, buffer + pBuf, sizeof(note));
+ if (!note.counter && !note.length)
+ break;
+
+ playNote(note);
+
+ pBuf += 3;
+
+ if (iSound == IDI_MSA_SND_THEME) {
+ while (_vm->_system->getEventManager()->pollEvent(event)) {
+ switch(event.type) {
+ case Common::EVENT_QUIT:
+ _vm->_system->quit();
+ case Common::EVENT_LBUTTONUP:
+ case Common::EVENT_RBUTTONUP:
+ case Common::EVENT_KEYDOWN:
+ delete [] buffer;
+ return;
+ default:
+ break;
+ }
+ }
+ }
+ }
+
+ break;
+ }
+
+ delete [] buffer;
+}
+
+void Mickey::debug() {
+ char szLine[41] = {0};
+
+ _vm->clearScreen(IDA_DEFAULT);
+
+ sprintf(szLine, IDS_MSA_DEBUG_ROOM, game.iRoom);
+ _vm->drawStr(5, 10, IDA_DEFAULT, szLine);
+
+ if (game.iRoom < IDI_MSA_MAX_PIC_ROOM) {
+ if (game.iRmObj[game.iRoom] != IDI_MSA_OBJECT_NONE) {
+ sprintf(szLine, IDS_MSA_DEBUG_OBJ, game.iRmObj[game.iRoom]);
+ _vm->drawStr(7, 10, IDA_DEFAULT, szLine);
+ }
+ } else {
+ sprintf(szLine, IDS_MSA_DEBUG_OBJ, 32);
+ _vm->drawStr(7, 10, IDA_DEFAULT, szLine);
+ }
+ _vm->_gfx->doUpdate();
+ _vm->_system->updateScreen(); // TODO: this should go in the game's main loop
+}
+
+// Graphics
+
+void Mickey::drawObj(ENUM_MSA_OBJECT iObj, int x0, int y0) {
+ uint8* buffer = new uint8[4096];
+ char szFile[255] = {0};
+ sprintf(szFile, IDS_MSA_PATH_OBJ, IDS_MSA_NAME_OBJ[iObj]);
+
+ Common::File file;
+ if (!file.open(szFile))
+ return;
+ uint32 size = file.size();
+ file.read(buffer, size);
+ file.close();
+
+ if (iObj == IDI_MSA_OBJECT_CRYSTAL)
+ _vm->_picture->setPictureFlags(kPicFStep);
+
+ _vm->_picture->setOffset(x0, y0);
+ _vm->_picture->decodePicture(buffer, size, false, IDI_MSA_PIC_WIDTH, IDI_MSA_PIC_HEIGHT);
+ _vm->_picture->setOffset(0, 0);
+ _vm->_picture->showPic(10, 0, IDI_MSA_PIC_WIDTH, IDI_MSA_PIC_HEIGHT);
+}
+
+void Mickey::drawPic(int iPic) {
+ uint8* buffer = new uint8[4096];
+ char szFile[255] = {0};
+ sprintf(szFile, IDS_MSA_PATH_PIC, iPic);
+
+ Common::File file;
+ if (!file.open(szFile))
+ return;
+ uint32 size = file.size();
+ file.read(buffer, size);
+ file.close();
+
+ // Note that decodePicture clears the screen
+ _vm->_picture->decodePicture(buffer, size, true, IDI_MSA_PIC_WIDTH, IDI_MSA_PIC_HEIGHT);
+ _vm->_picture->showPic(10, 0, IDI_MSA_PIC_WIDTH, IDI_MSA_PIC_HEIGHT);
+ //_vm->_gfx->doUpdate();
+ //_vm->_system->updateScreen(); // TODO: this should go in the game's main loop
+}
+
+void Mickey::drawRoomPicture() {
+ if (false) { // (getDebug()) { // TODO
+ drawPic(0);
+ debug();
+ } else {
+ if (game.iRoom == IDI_MSA_PIC_TITLE) {
+ drawPic(IDI_MSA_PIC_TITLE);
+ } else {
+ drawPic(game.iRmPic[game.iRoom]);
+ }
+ }
+}
+
+void Mickey::drawRoomObjects() {
+ if (game.iRoom >= IDI_MSA_MAX_PIC_ROOM)
+ return;
+
+ uint8 buffer[256];
+ int pBuf = 0;
+ int nObjs;
+
+ // draw ship control room window
+
+ if (game.iRoom == IDI_MSA_PIC_SHIP_CONTROLS) {
+ if (game.fFlying) {
+ drawObj(IDI_MSA_OBJECT_W_SPACE, 0, 0);
+ } else {
+ drawObj((ENUM_MSA_OBJECT)(IDI_MSA_OBJECT_W_EARTH + game.iPlanet), 0, 1);
+ }
+ }
+
+ // draw objects
+
+ if (game.iRmObj[game.iRoom] != IDI_MSA_OBJECT_NONE) {
+ readOfsData(IDO_MSA_ROOM_OBJECT_XY_OFFSETS,
+ game.iRmObj[game.iRoom], buffer, sizeof(buffer));
+
+ nObjs = buffer[pBuf++];
+
+ for (int iObj = 0; iObj < nObjs; iObj++) {
+ drawObj((ENUM_MSA_OBJECT)buffer[pBuf], buffer[pBuf + 1], buffer[pBuf + 2]);
+ pBuf += 3;
+ }
+ }
+}
+
+void Mickey::drawRoomAnimation() {
+ uint8 objLight[] = {
+ 0xF0, 1, 0xF9, 2, 43, 45, 0xFF
+ };
+
+ switch(game.iRoom) {
+ case IDI_MSA_PIC_EARTH_SHIP:
+ case IDI_MSA_PIC_VENUS_SHIP:
+ case IDI_MSA_PIC_NEPTUNE_SHIP:
+ case IDI_MSA_PIC_MERCURY_SHIP:
+ case IDI_MSA_PIC_SATURN_SHIP:
+ case IDI_MSA_PIC_PLUTO_SHIP:
+ case IDI_MSA_PIC_JUPITER_SHIP:
+ case IDI_MSA_PIC_MARS_SHIP:
+ case IDI_MSA_PIC_URANUS_SHIP:
+ case IDI_MSA_PIC_SHIP_VENUS:
+ case IDI_MSA_PIC_SHIP_NEPTUNE:
+ case IDI_MSA_PIC_SHIP_MERCURY:
+ case IDI_MSA_PIC_SHIP_SATURN:
+ case IDI_MSA_PIC_SHIP_PLUTO:
+ case IDI_MSA_PIC_SHIP_JUPITER:
+ case IDI_MSA_PIC_SHIP_MARS:
+ case IDI_MSA_PIC_SHIP_URANUS:
+ {
+ // draw blinking ship lights
+
+ uint8 iColor = 0;
+
+ _vm->_picture->setPattern(2, 0);
+
+ for (int i = 0; i < 12; i++) {
+ iColor = game.nFrame + i;
+ if (iColor > 15) iColor -= 15;
+
+ objLight[1] = iColor;
+ objLight[4] += 7;
+
+ _vm->_picture->setPictureData(objLight, ARRAYSIZE(objLight));
+ _vm->_picture->setPictureFlags(kPicFCircle);
+ _vm->_picture->drawPicture();
+ }
+ _vm->_picture->showPic(10, 0, IDI_MSA_PIC_WIDTH, IDI_MSA_PIC_HEIGHT);
+
+
+ game.nFrame--;
+ if (game.nFrame < 0) game.nFrame = 15;
+
+ playSound(IDI_MSA_SND_PRESS_BLUE);
+ }
+ break;
+
+ case IDI_MSA_PIC_SHIP_CONTROLS:
+
+ // draw XL30 screen
+
+ if (game.fAnimXL30) {
+ if (game.nFrame > 5) game.nFrame = 0;
+ drawObj((ENUM_MSA_OBJECT)(IDI_MSA_OBJECT_XL31 + game.nFrame), 0, 4);
+ game.nFrame++;
+ };
+
+ break;
+
+ default:
+
+ // draw crystal
+
+ if (game.iRoom == IDI_MSA_XTAL_ROOM_XY[game.iPlanet][0]) {
+ if (!game.fHasXtal) {
+ switch(game.iPlanet) {
+ case IDI_MSA_PLANET_VENUS:
+ if (game.iRmMenu[game.iRoom] != 2) break;
+ default:
+ drawObj(
+ IDI_MSA_OBJECT_CRYSTAL,
+ IDI_MSA_XTAL_ROOM_XY[game.iPlanet][1],
+ IDI_MSA_XTAL_ROOM_XY[game.iPlanet][2]
+ );
+ break;
+ }
+ }
+ }
+
+ break;
+ }
+}
+
+void Mickey::drawRoom() {
+ drawRoomPicture();
+ drawRoomObjects();
+ drawRoomAnimation();
+}
+
+const uint8 colorBCG[16][2] = {
+ { 0x00, 0x00 }, // 0 (black, black)
+ { 0, 0 },
+ { 0x00, 0x0D }, // 2 (black, purple)
+ { 0x00, 0xFF }, // 3 (black, white)
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0x0D, 0x00 }, // 8 (purple, black)
+ { 0, 0 },
+ { 0x0D, 0x0D }, // A (purple, purple)
+ { 0, 0 },
+ { 0xFF, 0x00 }, // C (white, black)
+ { 0, 0 },
+ { 0, 0 },
+ { 0xFF, 0xFF } // F (white, white)
+};
+
+void Mickey::drawLogo() {
+ char szFile[256] = {0};
+ uint8 *buffer = new uint8[16384];
+ const int w = 80;
+ const int h = 170;
+ uint8 bitmap[h][w];
+
+ // read in logos.bcg
+ sprintf(szFile, IDS_MSA_PATH_LOGO);
+ Common::File infile;
+ if (!infile.open(szFile))
+ return;
+ infile.read(buffer, infile.size());
+ infile.close();
+
+ // draw logo bitmap
+ memcpy(bitmap, buffer, sizeof(bitmap));
+
+ /*
+ // TODO: Show BCG picture
+ for (int y = 0; y < h; y++) {
+ for (int x = 0; x < w; x++) {
+ uint8 color = colorBCG[(bitmap[y][x] & 0xf0) / 0x10][0]; // background
+ uint8 color2 = colorBCG[(bitmap[y][x] & 0xf0) / 0x10][1]; // background
+ uint8 color3 = colorBCG[ bitmap[y][x] & 0x0f][0]; // foreground
+ uint8 color4 = colorBCG[ bitmap[y][x] & 0x0f][1]; // foreground
+
+ _vm->_picture->putPixel(x * 4, y, color);
+ _vm->_picture->putPixel(x * 4 + 1, y, color2);
+ _vm->_picture->putPixel(x * 4 + 2, y, color3);
+ _vm->_picture->putPixel(x * 4 + 3, y, color4);
+ _vm->_picture->putPixel(x * 4, y + 1, color);
+ _vm->_picture->putPixel(x * 4 + 1, y + 1, color2);
+ _vm->_picture->putPixel(x * 4 + 2, y + 1, color3);
+ _vm->_picture->putPixel(x * 4 + 3, y + 1, color4);
+ }
+ }
+
+ _vm->_picture->showPic(10, 0, IDI_MSA_PIC_WIDTH, IDI_MSA_PIC_HEIGHT);
+ */
+
+ //_vm->_gfx->doUpdate();
+ //_vm->_system->updateScreen(); // TODO: this should go in the game's main loop
+
+ delete [] buffer;
+}
+
+void Mickey::animate() {
+ _vm->_system->delayMillis(IDI_MSA_ANIM_DELAY);
+ drawRoomAnimation();
+}
+
+void Mickey::printRoomDesc() {
+ // print room description
+
+ printDesc(game.iRoom);
+ waitAnyKeyAnim();
+
+ // print extended room description
+
+ if (game.fRmTxt[game.iRoom]) {
+ printExeMsg(game.oRmTxt[game.iRoom] + IDI_MSA_OFS_EXE);
+ }
+}
+
+bool Mickey::loadGame() {
+ Common::InSaveFile *infile;
+ char szFile[256] = {0};
+ bool diskerror = true;
+ int sel;
+
+ while (diskerror) {
+ sel = choose1to9(IDO_MSA_LOAD_GAME[1]);
+ if (!sel)
+ return false;
+
+ // load game
+ sprintf(szFile, "%s.s%2d", _vm->getTargetName().c_str(), sel);
+ if (!(infile = _vm->getSaveFileMan()->openForLoading(szFile))) {
+ printExeStr(IDO_MSA_CHECK_DISK_DRIVE);
+ if (!_vm->waitAnyKeyChoice())
+ return false;
+ } else {
+ infile->read(&game, sizeof(MSA_GAME));
+ diskerror = false;
+ delete infile;
+ }
+ }
+
+ printExeMsg(IDO_MSA_LOAD_GAME[2]);
+ return true;
+}
+
+void Mickey::saveGame() {
+ Common::OutSaveFile* outfile;
+ char szFile[256] = {0};
+ bool diskerror = true;
+ int sel;
+
+ bool fOldDisk = chooseY_N(IDO_MSA_SAVE_GAME[0], false);
+
+ if (fOldDisk)
+ printExeStr(IDO_MSA_SAVE_GAME[1]);
+ else
+ printExeStr(IDO_MSA_SAVE_GAME[2]);
+
+ if (!_vm->waitAnyKeyChoice())
+ return;
+
+ while (diskerror) {
+ sel = choose1to9(IDO_MSA_SAVE_GAME[3]);
+ if (!sel)
+ return;
+
+ if (fOldDisk)
+ printExeStr(IDO_MSA_SAVE_GAME[5]);
+ else
+ printExeStr(IDO_MSA_SAVE_GAME[4]);
+
+ if (!_vm->waitAnyKeyChoice())
+ return;
+
+ // save game
+ sprintf(szFile, "%s.s%2d", _vm->getTargetName().c_str(), sel);
+ if (!(outfile = _vm->getSaveFileMan()->openForSaving(szFile))) {
+ printExeStr(IDO_MSA_CHECK_DISK_DRIVE);
+ if (!_vm->waitAnyKeyChoice())
+ return;
+ } else {
+ outfile->write(&game, sizeof(MSA_GAME));
+ diskerror = false;
+ delete outfile;
+ }
+ }
+
+ printExeMsg(IDO_MSA_SAVE_GAME[6]);
+}
+
+void Mickey::showPlanetInfo() {
+ for (int i = 0; i < IDI_MSA_MAX_PLANET_INFO; i++) {
+ printExeStr(IDO_MSA_PLANET_INFO[game.iPlanet][i]);
+ waitAnyKey();
+ }
+}
+
+void Mickey::printStory() {
+ char buffer[IDI_MSA_LEN_STORY] = {0};
+ char szLine[41] = {0};
+ int iRow;
+ int pBuf = 0;
+
+ readExe(IDO_MSA_GAME_STORY, (uint8 *)buffer, sizeof(buffer));
+
+ _vm->clearScreen(IDA_DEFAULT);
+ for (iRow = 0; iRow < 25; iRow++) {
+ strcpy(szLine, buffer + pBuf);
+ _vm->drawStr(iRow, 0, IDA_DEFAULT, szLine);
+ pBuf += strlen(szLine) + 1;
+ }
+ //_vm->_gfx->doUpdate();
+ //_vm->_system->updateScreen(); // TODO: this should go in the game's main loop
+ waitAnyKey();
+
+ _vm->clearScreen(IDA_DEFAULT);
+ for (iRow = 0; iRow < 21; iRow++) {
+ strcpy(szLine, buffer + pBuf);
+ _vm->drawStr(iRow, 0, IDA_DEFAULT, szLine);
+ pBuf += strlen(szLine) + 1;
+ }
+ //_vm->_gfx->doUpdate();
+ //_vm->_system->updateScreen(); // TODO: this should go in the game's main loop
+ waitAnyKey();
+
+ //Set back to black
+ _vm->_gfx->clearScreen(0);
+ //_vm->_gfx->doUpdate();
+ //_vm->_system->updateScreen(); // TODO: this should go in the game's main loop
+
+ drawRoom();
+ //_vm->_gfx->doUpdate();
+ //_vm->_system->updateScreen(); // TODO: this should go in the game's main loop
+
+ game.fStoryShown = true;
+}
+
+void Mickey::hidden() {
+ if (game.iRoom == IDI_MSA_PIC_MERCURY_CAVE_0) {
+ for (int i = 0; i < 5; i++) {
+ printExeMsg(IDO_MSA_HIDDEN_MSG[i]);
+ }
+ _vm->clearTextArea();
+ //_vm->_gfx->doUpdate();
+ //_vm->_system->updateScreen(); // TODO: this should go in the game's main loop
+ waitAnyKey();
+ }
+}
+
+int Mickey::getPlanet() {
+ if (!game.nButtons)
+ return -1;
+
+ for (int iPlanet = 0; iPlanet < IDI_MSA_MAX_DAT; iPlanet++) {
+ if (!strcmp(IDS_MSA_ADDR_PLANET[iPlanet], game.szAddr)) {
+ return iPlanet;
+ }
+ }
+
+ return -1;
+}
+
+void Mickey::pressOB(int iButton) {
+ char szButtons[12] = {0};
+
+ // check if too many buttons pressed
+ if (game.nButtons == IDI_MSA_MAX_BUTTON) {
+ game.nButtons = 0;
+ memset(game.szAddr, 0, sizeof(game.szAddr));
+ printExeMsg(IDO_MSA_TOO_MANY_BUTTONS_PRESSED);
+ return;
+ }
+
+ // add button press to address
+ game.nButtons++;
+ game.szAddr[game.nButtons - 1] = (char)iButton;
+
+ // format buttons string
+ for (int i = 0; i < IDI_MSA_MAX_BUTTON; i++) {
+ szButtons[i * 2] = game.szAddr[i];
+ if (game.szAddr[i + 1]) szButtons[(i * 2) + 1] = ',';
+ }
+
+ // print pressed buttons
+ printExeStr(IDO_MSA_MICKEY_HAS_PRESSED);
+ _vm->drawStr(IDI_MSA_ROW_BUTTONS, IDI_MSA_COL_BUTTONS, IDA_DEFAULT, szButtons);
+ //_vm->_gfx->doUpdate();
+ //_vm->_system->updateScreen(); // TODO: this should go in the game's main loop
+ waitAnyKey();
+}
+
+void Mickey::checkAirSupply(bool fSuit, int *iSupply) {
+ if (fSuit) {
+ *iSupply -= 1;
+ for (int i = 0; i < 4; i++) {
+ if (*iSupply == IDI_MSA_AIR_SUPPLY[i]) {
+ playSound(IDI_MSA_SND_XL30);
+ printExeMsg(IDO_MSA_XL30_SPEAKING);
+ printExeMsg(IDO_MSA_AIR_SUPPLY[i]);
+ if (i == 3) {
+ exit(0);
+ }
+ }
+ }
+ } else {
+ *iSupply = IDI_MSA_MAX_AIR_SUPPLY;
+ }
+}
+
+void Mickey::insertDisk(int iDisk) {
+ _vm->clearTextArea();
+ _vm->drawStr(IDI_MSA_ROW_INSERT_DISK, IDI_MSA_COL_INSERT_DISK, IDA_DEFAULT, (const char *)IDS_MSA_INSERT_DISK[iDisk]);
+ //_vm->_gfx->doUpdate();
+ //_vm->_system->updateScreen(); // TODO: this should go in the game's main loop
+ waitAnyKey();
+}
+
+void Mickey::gameOver() {
+ drawPic(IDI_MSA_PIC_EARTH_SHIP_LEAVING);
+ printExeMsg(IDO_MSA_GAME_OVER[3]);
+ playSound(IDI_MSA_SND_GAME_OVER);
+
+ if (game.fItemUsed[IDI_MSA_ITEM_LETTER]) {
+ drawPic(IDI_MSA_PIC_EARTH_MINNIE);
+ printExeMsg(IDO_MSA_GAME_OVER[4]);
+ printExeMsg(IDO_MSA_GAME_OVER[5]);
+ } else {
+ printExeMsg(IDO_MSA_GAME_OVER[6]);
+ printExeMsg(IDO_MSA_GAME_OVER[7]);
+ }
+
+ waitAnyKey();
+ exit(0);
+}
+
+void Mickey::flipSwitch() {
+ if (game.fHasXtal || game.nXtals) {
+ if (!game.fStoryShown) {
+ printStory();
+ randomize();
+ }
+
+ // activate screen animation
+ game.fAnimXL30 = true;
+
+ _vm->clearTextArea();
+ //_vm->_gfx->doUpdate();
+ //_vm->_system->updateScreen(); // TODO: this should go in the game's main loop
+ playSound(IDI_MSA_SND_XL30);
+ printExeMsg(IDO_MSA_XL30_SPEAKING);
+
+ if (game.fHasXtal) {
+ game.fHasXtal = false;
+ printExeMsg(IDO_MSA_CRYSTAL_PIECE_FOUND);
+ }
+
+ if (game.nXtals == IDI_MSA_MAX_PLANET) {
+ printExeMsg(IDO_MSA_GAME_OVER[0]);
+ printExeMsg(IDO_MSA_GAME_OVER[1]);
+ printExeMsg(IDO_MSA_GAME_OVER[2]);
+
+#if 0
+ // DEBUG
+ strcpy(game.szAddr, (char *)IDS_MSA_ADDR_PLANET[IDI_MSA_PLANET_EARTH]);
+ game.nButtons = strlen(game.szAddr);
+#endif
+
+ } else {
+ printExeStr(game.iClue[game.nXtals]);
+
+#if 0
+ // DEBUG
+ _vm->drawStr(24, 12, IDA_DEFAULT, (char *)IDS_MSA_NAME_PLANET_2[game.iPlanetXtal[game.nXtals]]);
+ _vm->drawStr(24, 22, IDA_DEFAULT, (char *)IDS_MSA_ADDR_PLANET[game.iPlanetXtal[game.nXtals]]);
+ strcpy(game.szAddr, (char *)IDS_MSA_ADDR_PLANET[game.iPlanetXtal[game.nXtals]]);
+ game.nButtons = strlen(game.szAddr);
+ _vm->_gfx->doUpdate();
+ _vm->_system->updateScreen(); // TODO: this should go in the game's main loop
+#endif
+
+ waitAnyKeyAnim();
+ }
+ } else {
+ printStory();
+ }
+}
+
+void Mickey::inventory() {
+ int iRow = IDI_MSA_ROW_INV_ITEMS;
+ char szCrystals[12] = {0};
+
+ sprintf(szCrystals, IDS_MSA_CRYSTALS, IDS_MSA_CRYSTAL_NO[game.nXtals]);
+
+ CursorMan.showMouse(false);
+
+ _vm->clearScreen(IDA_DEFAULT);
+ _vm->drawStr(IDI_MSA_ROW_INV_TITLE, IDI_MSA_COL_INV_TITLE, IDA_DEFAULT, IDS_MSA_INVENTORY);
+ _vm->drawStr(IDI_MSA_ROW_INV_CRYSTALS, IDI_MSA_COL_INV_ITEMS, IDA_DEFAULT, szCrystals);
+
+ for (int iItem = 0; iItem < IDI_MSA_MAX_ITEM; iItem++) {
+ if (game.fItem[game.iItem[iItem]] && (game.iItem[iItem] != IDI_MSA_OBJECT_NONE)) {
+ _vm->drawStr(iRow++, IDI_MSA_COL_INV_ITEMS, IDA_DEFAULT, (const char *)IDS_MSA_NAME_ITEM[game.iItem[iItem]]);
+ }
+ }
+
+ //_vm->_gfx->doUpdate();
+ //_vm->_system->updateScreen(); // TODO: this should go in the game's main loop
+ waitAnyKey();
+
+ _vm->clearScreen(IDA_DEFAULT);
+
+ CursorMan.showMouse(true);
+}
+
+void Mickey::randomize() {
+ int iPlanet = 0;
+ int iHint = 0;
+ bool done;
+
+ memset(game.iPlanetXtal, 0, sizeof(game.iPlanetXtal));
+ memset(game.iClue, 0, sizeof(game.iClue));
+
+ game.iPlanetXtal[0] = IDI_MSA_PLANET_EARTH;
+ game.iPlanetXtal[8] = IDI_MSA_PLANET_URANUS;
+
+ for (int i = 1; i < 9; i++) {
+ if (i == 8) {
+ iPlanet = IDI_MSA_PLANET_URANUS;
+ } else {
+ done = false;
+ while (!done) {
+ iPlanet = _vm->rnd(IDI_MSA_MAX_PLANET);
+ done = true;
+ for (int j = 0; j < IDI_MSA_MAX_PLANET; j++) {
+ if (game.iPlanetXtal[j] == iPlanet) {
+ done = false;
+ break;
+ }
+ }
+ }
+ }
+
+ game.iPlanetXtal[i] = iPlanet;
+
+ done = false;
+ while (!done) {
+ iHint = _vm->rnd(5);
+ done = true;
+ }
+
+ game.iClue[i] = IDO_MSA_NEXT_PIECE[iPlanet][iHint];
+ }
+}
+
+void Mickey::flashScreen() {
+ playSound(IDI_MSA_SND_PRESS_BLUE);
+
+ //Set screen to white
+ _vm->_gfx->clearScreen(15);
+ _vm->_gfx->doUpdate();
+ _vm->_system->updateScreen(); // TODO: this should go in the game's main loop
+
+ _vm->_system->delayMillis(IDI_MSA_ANIM_DELAY);
+
+ //Set back to black
+ _vm->_gfx->clearScreen(0);
+ _vm->_gfx->doUpdate();
+ _vm->_system->updateScreen(); // TODO: this should go in the game's main loop
+
+ drawRoom();
+ printDesc(game.iRoom);
+ _vm->_gfx->doUpdate();
+ _vm->_system->updateScreen(); // TODO: this should go in the game's main loop
+}
+
+void Mickey::intro() {
+ // draw sierra logo
+ drawLogo();
+ //waitAnyKey(); // Not in the original, but needed so that the logo is visible
+
+ // draw title picture
+ game.iRoom = IDI_MSA_PIC_TITLE;
+ drawRoom();
+
+ // show copyright and play theme
+ printExeMsg(IDO_MSA_COPYRIGHT);
+ playSound(IDI_MSA_SND_THEME);
+
+ // load game
+ game.fIntro = true;
+ if (chooseY_N(IDO_MSA_LOAD_GAME[0], true)) {
+ if (loadGame()) {
+ game.iPlanet = IDI_MSA_PLANET_EARTH;
+ game.fIntro = false;
+ game.iRoom = IDI_MSA_PIC_SHIP_CORRIDOR;
+ return;
+ }
+ }
+
+ // play spaceship landing scene
+ game.iPlanet = IDI_MSA_PLANET_EARTH;
+ game.iRoom = IDI_MSA_PIC_EARTH_ROAD_4;
+
+ drawRoom();
+ printRoomDesc();
+
+ playSound(IDI_MSA_SND_SHIP_LAND);
+
+ flashScreen();
+ flashScreen();
+ flashScreen();
+
+ printExeMsg(IDO_MSA_INTRO);
+}
+
+void Mickey::getItem(ENUM_MSA_ITEM iItem) {
+ game.fItem[iItem] = true;
+ game.iItem[game.nItems++] = iItem;
+ game.fRmTxt[game.iRoom] = 0;
+ playSound(IDI_MSA_SND_TAKE);
+ drawRoom();
+}
+
+void Mickey::getXtal(int iStr) {
+ game.fRmTxt[game.iRoom] = 0;
+ game.fHasXtal = true;
+ game.nXtals++;
+ playSound(IDI_MSA_SND_CRYSTAL);
+ drawRoom();
+ printDatMessage(iStr);
+}
+
+bool Mickey::parse(int cmd, int arg) {
+ switch(cmd) {
+
+ // BASIC
+
+ case IDI_MSA_ACTION_GOTO_ROOM:
+ game.iRoom = arg;
+ return true;
+ case IDI_MSA_ACTION_SHOW_INT_STR:
+ printExeMsg(IDO_MSA_ERROR[arg]);
+ break;
+ case IDI_MSA_ACTION_SHOW_DAT_STR:
+ printDatMessage(arg);
+ break;
+
+ // GENERAL
+
+ case IDI_MSA_ACTION_PLANET_INFO:
+ showPlanetInfo();
+ break;
+ case IDI_MSA_ACTION_SAVE_GAME:
+ saveGame();
+ break;
+ case IDI_MSA_ACTION_LOOK_MICKEY:
+ printExeMsg(IDO_MSA_YOU_CAN_SEE_MICKEY_ALREADY);
+ break;
+
+ // EARTH
+
+ case IDI_MSA_ACTION_GET_ROPE:
+ if (game.iRmMenu[game.iRoom] == 2) {
+ game.iRmObj[game.iRoom] = IDI_MSA_OBJECT_NONE;
+ game.iRmMenu[game.iRoom] = 3;
+ getItem(IDI_MSA_ITEM_ROPE);
+ printExeMsg(IDO_MSA_ERROR[7]);
+ } else {
+ game.iRmMenu[game.iRoom] = 1;
+ printDatMessage(11);
+ }
+ break;
+ case IDI_MSA_ACTION_UNTIE_ROPE:
+ game.iRmPic[game.iRoom] = IDI_MSA_PIC_EARTH_TIRE_SWING_1;
+ game.iRmObj[game.iRoom] = 0;
+ game.iRmMenu[game.iRoom] = 2;
+ drawRoom();
+ printDatMessage(12);
+ break;
+ case IDI_MSA_ACTION_GET_BONE:
+ game.iRmObj[game.iRoom] = IDI_MSA_OBJECT_NONE;
+ game.iRmMenu[game.iRoom] = 1;
+ getItem(IDI_MSA_ITEM_BONE);
+ printDatMessage(arg);
+ break;
+ case IDI_MSA_ACTION_GET_XTAL_EARTH:
+ game.iRmMenu[game.iRoom] = 1;
+ getXtal(arg);
+ break;
+ case IDI_MSA_ACTION_LOOK_DESK:
+ game.iRmMenu[game.iRoom] = 1;
+ game.iRmObj[game.iRoom] = 2;
+ drawRoom();
+ printDatMessage(arg);
+ break;
+ case IDI_MSA_ACTION_WRITE_LETTER:
+ game.iRmMenu[game.iRoom] = 3;
+ game.iRmMenu[IDI_MSA_PIC_EARTH_MAILBOX] = 1;
+ game.iRmObj[game.iRoom] = IDI_MSA_OBJECT_NONE;
+ getItem(IDI_MSA_ITEM_LETTER);
+ printDatMessage(arg);
+ break;
+ case IDI_MSA_ACTION_MAIL_LETTER:
+ game.fItemUsed[IDI_MSA_ITEM_LETTER] = true;
+ game.fItem[IDI_MSA_ITEM_LETTER] = false;
+ game.iRmMenu[game.iRoom] = 0;
+ printDatMessage(arg);
+ break;
+ case IDI_MSA_ACTION_OPEN_MAILBOX:
+ if (game.fItemUsed[IDI_MSA_ITEM_LETTER]) {
+ printDatMessage(110);
+ } else {
+ printDatMessage(arg);
+ }
+ break;
+ case IDI_MSA_ACTION_OPEN_CUPBOARD:
+ if (game.iRmMenu[game.iRoom]) {
+ if (game.iRmObj[game.iRoom] == IDI_MSA_OBJECT_NONE) {
+ printDatMessage(78);
+ } else {
+ printDatMessage(arg);
+ }
+ } else {
+ game.iRmMenu[game.iRoom] = 1;
+ game.iRmPic[game.iRoom] = IDI_MSA_PIC_EARTH_KITCHEN_1;
+ game.iRmObj[game.iRoom] = 3;
+ drawRoom();
+ printDatMessage(arg);
+ }
+ break;
+ case IDI_MSA_ACTION_GET_FLASHLIGHT:
+ if (game.fItem[IDI_MSA_ITEM_FLASHLIGHT]) {
+ printDatMessage(90);
+ } else {
+ game.iRmObj[game.iRoom] = IDI_MSA_OBJECT_NONE;
+ getItem(IDI_MSA_ITEM_FLASHLIGHT);
+ drawRoom();
+ printDatMessage(arg);
+ }
+ break;
+ case IDI_MSA_ACTION_OPEN_CABINET:
+ if (game.iRmMenu[game.iRoom]) {
+ printDatMessage(109);
+ } else {
+ game.iRmMenu[game.iRoom] = 1;
+ game.iRmPic[game.iRoom] = IDI_MSA_PIC_EARTH_GARAGE_1;
+ game.iRmObj[game.iRoom] = 15;
+ drawRoom();
+ printDatMessage(arg);
+ }
+ break;
+ case IDI_MSA_ACTION_GET_CROWBAR:
+ if (game.fItem[IDI_MSA_ITEM_CROWBAR]) {
+ printDatMessage(90);
+ } else {
+ game.iRmObj[game.iRoom]--;
+ getItem(IDI_MSA_ITEM_CROWBAR);
+ printDatMessage(arg);
+ }
+ break;
+ case IDI_MSA_ACTION_GET_WRENCH:
+ if (game.fItem[IDI_MSA_ITEM_WRENCH]) {
+ printDatMessage(90);
+ } else {
+ game.iRmObj[game.iRoom] -= 2;
+ getItem(IDI_MSA_ITEM_WRENCH);
+ printDatMessage(arg);
+ }
+ break;
+ case IDI_MSA_ACTION_OPEN_CLOSET:
+ if (game.iRmMenu[game.iRoom]) {
+ printDatMessage(99);
+ } else {
+ game.iRmMenu[game.iRoom] = 1;
+ game.iRmPic[game.iRoom] = IDI_MSA_PIC_EARTH_BEDROOM_1;
+ game.iRmObj[game.iRoom] = 7;
+ drawRoom();
+ printDatMessage(arg);
+ }
+ break;
+ case IDI_MSA_ACTION_GET_MATTRESS:
+ if (game.fItem[IDI_MSA_ITEM_MATTRESS]) {
+ printDatMessage(90);
+ } else {
+ game.iRmObj[game.iRoom]--;
+ getItem(IDI_MSA_ITEM_MATTRESS);
+ printDatMessage(arg);
+ }
+ break;
+ case IDI_MSA_ACTION_GET_SCARF:
+ if (game.fItem[IDI_MSA_ITEM_SCARF]) {
+ printDatMessage(90);
+ } else {
+ game.iRmObj[game.iRoom] -= 2;
+ getItem(IDI_MSA_ITEM_SCARF);
+ printDatMessage(arg);
+ }
+ break;
+ case IDI_MSA_ACTION_GET_SUNGLASSES:
+ if (game.fItem[IDI_MSA_ITEM_SUNGLASSES]) {
+ printDatMessage(90);
+ } else {
+ game.iRmObj[game.iRoom]--;
+ getItem(IDI_MSA_ITEM_SUNGLASSES);
+ printDatMessage(arg);
+ }
+ break;
+ case IDI_MSA_ACTION_GET_SCALE:
+ if (game.fItem[IDI_MSA_ITEM_SCALE]) {
+ printDatMessage(90);
+ } else {
+ game.iRmMenu[IDI_MSA_PIC_VENUS_WEIGH] = 1;
+ game.iRmMenu[IDI_MSA_PIC_NEPTUNE_WEIGH] = 1;
+ game.iRmMenu[IDI_MSA_PIC_MERCURY_WEIGH] = 1;
+ game.iRmMenu[IDI_MSA_PIC_SATURN_WEIGH] = 1;
+ game.iRmMenu[IDI_MSA_PIC_PLUTO_WEIGH] = 1;
+ game.iRmMenu[IDI_MSA_PIC_JUPITER_WEIGH] = 1;
+ game.iRmMenu[IDI_MSA_PIC_MARS_WEIGH] = 1;
+ game.iRmMenu[IDI_MSA_PIC_URANUS_WEIGH] = 1;
+ game.iRmObj[game.iRoom] -= 2;
+ getItem(IDI_MSA_ITEM_SCALE);
+ printDatMessage(arg);
+ }
+ break;
+ case IDI_MSA_ACTION_GOTO_SPACESHIP:
+ game.iRoom = IDI_MSA_PIC_SHIP_AIRLOCK;
+ if (game.iPlanet != IDI_MSA_PLANET_EARTH)
+ insertDisk(0);
+ return true;
+
+ // VENUS
+
+ case IDI_MSA_ACTION_DOWN_CHASM:
+ if (game.fItem[IDI_MSA_ITEM_ROPE]) {
+ game.iRmMenu[game.iRoom] = 1;
+ }
+ printDatMessage(arg);
+ break;
+ case IDI_MSA_ACTION_DOWN_ROPE:
+ if (game.fItemUsed[IDI_MSA_ITEM_ROPE]) {
+ game.iRoom = IDI_MSA_PIC_VENUS_PROBE;
+ return true;
+ } else {
+ printDatMessage(arg);
+ }
+ break;
+ case IDI_MSA_ACTION_USE_ROPE:
+ if (game.fItemUsed[IDI_MSA_ITEM_ROPE]) {
+ printDatMessage(22);
+ } else {
+ game.fItemUsed[IDI_MSA_ITEM_ROPE] = true;
+ game.fItem[IDI_MSA_ITEM_ROPE] = false;
+ game.iRmPic[game.iRoom] = IDI_MSA_PIC_VENUS_CHASM_1;
+ drawRoom();
+ printDatMessage(arg);
+ }
+ break;
+ case IDI_MSA_ACTION_OPEN_HATCH:
+ if (game.fItemUsed[IDI_MSA_ITEM_WRENCH]) {
+ if ((game.iRmMenu[game.iRoom] == 3) || (game.iRmPic[game.iRoom] == IDI_MSA_PIC_VENUS_PROBE_1))
+ printDatMessage(39);
+ else {
+ game.iRmMenu[game.iRoom] = 2;
+ game.iRmPic[game.iRoom] = IDI_MSA_PIC_VENUS_PROBE_1;
+ drawRoom();
+ printDatMessage(24);
+ }
+ } else {
+ if (game.fItem[IDI_MSA_ITEM_WRENCH]) {
+ game.iRmMenu[game.iRoom] = 1;
+ }
+ printDatMessage(arg);
+ }
+ break;
+ case IDI_MSA_ACTION_USE_WRENCH:
+ game.fItemUsed[IDI_MSA_ITEM_WRENCH] = true;
+ printDatString(arg);
+ if (game.iRmPic[game.iRoom] == IDI_MSA_PIC_VENUS_PROBE_1) {
+ _vm->clearRow(22);
+ }
+ //_vm->_gfx->doUpdate();
+ //_vm->_system->updateScreen(); // TODO: this should go in the game's main loop
+ waitAnyKey();
+ break;
+ case IDI_MSA_ACTION_GET_XTAL_VENUS:
+ game.iRmMenu[game.iRoom] = 3;
+ getXtal(arg);
+ break;
+
+ // TRITON (NEPTUNE)
+
+ case IDI_MSA_ACTION_LOOK_CASTLE:
+ if (!game.iRmMenu[game.iRoom]) {
+ game.iRmMenu[game.iRoom] = 1;
+ }
+ printDatMessage(arg);
+ break;
+ case IDI_MSA_ACTION_ENTER_OPENING:
+ if (game.fItemUsed[IDI_MSA_ITEM_CROWBAR]) {
+ game.iRoom = IDI_MSA_PIC_NEPTUNE_CASTLE_4;
+ return true;
+ } else {
+ if (game.fItem[IDI_MSA_ITEM_CROWBAR]) {
+ game.iRmMenu[game.iRoom] = 2;
+ }
+ printDatMessage(arg);
+ }
+ break;
+ case IDI_MSA_ACTION_USE_CROWBAR:
+ game.fItemUsed[IDI_MSA_ITEM_CROWBAR] = true;
+ game.iRmMenu[game.iRoom] = 1;
+ game.iRmPic[game.iRoom] = IDI_MSA_PIC_NEPTUNE_ENTRANCE_1;
+ drawRoom();
+ printDatMessage(arg);
+ break;
+ case IDI_MSA_ACTION_GET_XTAL_NEPTUNE:
+ if (game.fHasXtal) {
+ printDatMessage(71);
+ } else {
+ if (game.fItem[IDI_MSA_ITEM_SCARF]) {
+ game.iRmMenu[game.iRoom] = 1;
+ }
+ printDatMessage(arg);
+ }
+ break;
+ case IDI_MSA_ACTION_TALK_LEADER:
+ game.iRoom = IDI_MSA_PIC_NEPTUNE_ENTRYWAY;
+ printDatMessage(arg);
+ return true;
+ case IDI_MSA_ACTION_GIVE_SCARF:
+ game.iRmObj[game.iRoom] = 18;
+ getXtal(arg);
+ game.fItem[IDI_MSA_ITEM_SCARF] = false;
+ game.iRmMenu[game.iRoom] = 0;
+ game.iRmMenu[IDI_MSA_PIC_EARTH_BEDROOM] = 2;
+ game.iRoom = IDI_MSA_PIC_NEPTUNE_ENTRYWAY;
+ return true;
+
+ // MERCURY
+
+ case IDI_MSA_ACTION_GET_XTAL_MERCURY:
+ if (game.fHasXtal) {
+ game.iRmMenu[game.iRoom] = 2;
+ printDatMessage(32);
+ } else {
+ if (game.fItem[IDI_MSA_ITEM_SUNGLASSES]) {
+ game.iRmMenu[game.iRoom] = 1;
+ }
+ printDatMessage(arg);
+ }
+ break;
+ case IDI_MSA_ACTION_GIVE_SUNGLASSES:
+ game.iRmObj[game.iRoom] = 17;
+ game.iRmMenu[game.iRoom] = 2;
+ game.fItem[IDI_MSA_ITEM_SUNGLASSES] = false;
+ getXtal(arg);
+ break;
+
+ // TITAN (SATURN)
+
+ case IDI_MSA_ACTION_CROSS_LAKE:
+ if (game.fItem[IDI_MSA_ITEM_MATTRESS]) {
+ game.iRmMenu[IDI_MSA_PIC_SATURN_LAKE_0] = 1;
+ game.iRmMenu[IDI_MSA_PIC_SATURN_LAKE_1] = 1;
+ game.iRmMenu[IDI_MSA_PIC_SATURN_LAKE_2] = 1;
+ }
+ printDatMessage(arg);
+ break;
+ case IDI_MSA_ACTION_USE_MATTRESS:
+ game.iRoom = IDI_MSA_PIC_SATURN_ISLAND;
+ printDatMessage(arg);
+ return true;
+ case IDI_MSA_ACTION_GET_XTAL_SATURN:
+ if (game.fHasXtal) {
+ printDatMessage(29);
+ } else {
+ getXtal(arg);
+ }
+ break;
+ case IDI_MSA_ACTION_LEAVE_ISLAND:
+ game.iRoom = IDI_MSA_PIC_SATURN_LAKE_1;
+ printDatMessage(arg);
+ return true;
+
+ // PLUTO
+
+ case IDI_MSA_ACTION_GET_XTAL_PLUTO:
+ if (game.fHasXtal) {
+ printDatMessage(19);
+ } else {
+ if (game.fItem[IDI_MSA_ITEM_BONE]) {
+ game.iRmMenu[game.iRoom] = 1;
+ }
+ printDatMessage(arg);
+ }
+ break;
+ case IDI_MSA_ACTION_GIVE_BONE:
+ game.fItem[IDI_MSA_ITEM_BONE] = false;
+ game.iRmMenu[game.iRoom] = 0;
+ game.iRmObj[game.iRoom] = 16;
+ getXtal(arg);
+ break;
+
+ // IO (JUPITER)
+
+ case IDI_MSA_ACTION_GET_ROCK_0:
+ if (game.fItem[IDI_MSA_ITEM_ROCK]) {
+ printDatMessage(38);
+ } else {
+ game.iRmMenu[game.iRoom] = 1;
+ game.iRmObj[game.iRoom] = IDI_MSA_OBJECT_NONE;
+ getItem(IDI_MSA_ITEM_ROCK);
+ printDatMessage(arg);
+ }
+ break;
+ case IDI_MSA_ACTION_GET_ROCK_1:
+ if (game.fItem[IDI_MSA_ITEM_ROCK]) {
+ printDatMessage(38);
+ } else {
+ game.iRmMenu[game.iRoom] = 1;
+ game.iRmObj[game.iRoom] = IDI_MSA_OBJECT_NONE;
+ getItem(IDI_MSA_ITEM_ROCK);
+ printDatMessage(arg);
+ }
+ break;
+ case IDI_MSA_ACTION_GET_XTAL_JUPITER:
+ if (game.fHasXtal) {
+ printDatMessage(15);
+ } else {
+ switch (game.nRocks) {
+ case 0:
+ if (game.fItem[IDI_MSA_ITEM_ROCK]) {
+ game.iRmMenu[game.iRoom] = 1;
+ }
+ printDatMessage(arg);
+ break;
+ case 1:
+ if (game.fItem[IDI_MSA_ITEM_ROCK]) {
+ game.iRmMenu[game.iRoom] = 1;
+ }
+ printDatMessage(34);
+ break;
+ case 2:
+ getXtal(35);
+ break;
+ }
+ }
+ break;
+ case IDI_MSA_ACTION_THROW_ROCK:
+ game.fItem[IDI_MSA_ITEM_ROCK] = false;
+ game.nItems--;
+ game.iRmObj[game.iRoom]++;
+ game.iRmMenu[game.iRoom] = 0;
+ drawRoom();
+ if (game.nRocks) {
+ printDatMessage(37);
+ } else {
+ printDatMessage(arg);
+ }
+ game.nRocks++;
+ break;
+
+ // MARS
+
+ case IDI_MSA_ACTION_GO_TUBE:
+ if (game.fItem[IDI_MSA_ITEM_FLASHLIGHT]) {
+ game.iRmMenu[game.iRoom] = 1;
+ }
+ printDatMessage(arg);
+ break;
+ case IDI_MSA_ACTION_USE_FLASHLIGHT:
+ game.iRoom = IDI_MSA_PIC_MARS_TUBE_1;
+ printDatMessage(15);
+ return true;
+ case IDI_MSA_ACTION_PLUTO_DIG:
+ if (game.fHasXtal) {
+ printDatMessage(21);
+ } else {
+ getXtal(arg);
+ }
+ break;
+ case IDI_MSA_ACTION_GET_XTAL_MARS:
+ if (game.fHasXtal) {
+ printDatMessage(23);
+ } else {
+ printDatMessage(arg);
+ }
+ break;
+
+ // OBERON (URANUS)
+
+ case IDI_MSA_ACTION_ENTER_TEMPLE:
+ game.iRoom = IDI_MSA_PIC_URANUS_TEMPLE;
+ return true;
+ case IDI_MSA_ACTION_USE_CRYSTAL:
+ if (game.iRmMenu[game.iRoom]) {
+ printDatMessage(25);
+ } else {
+ game.iRmMenu[game.iRoom] = 1;
+ game.iRmPic[game.iRoom] = IDI_MSA_PIC_URANUS_TEMPLE_1;
+ drawRoom();
+ game.iRmPic[game.iRoom] = IDI_MSA_PIC_URANUS_TEMPLE;
+ printDatMessage(arg);
+ }
+ break;
+ case IDI_MSA_ACTION_OPEN_DOOR:
+ if (game.fTempleDoorOpen) {
+ printDatMessage(36);
+ } else {
+ game.fTempleDoorOpen = 1;
+ game.iRmPic[game.iRoom] = IDI_MSA_PIC_URANUS_TEMPLE_2;
+ drawRoom();
+ printDatMessage(arg);
+ }
+ break;
+ case IDI_MSA_ACTION_ENTER_DOOR:
+ if (game.fTempleDoorOpen) {
+ game.iRoom = IDI_MSA_PIC_URANUS_STEPS;
+ return true;
+ } else {
+ printDatMessage(arg);
+ }
+ break;
+ case IDI_MSA_ACTION_GET_XTAL_URANUS:
+ if (game.fHasXtal) {
+ printDatMessage(34);
+ } else {
+ if (game.fItem[IDI_MSA_ITEM_CROWBAR]) {
+ game.iRmMenu[game.iRoom] = 1;
+ }
+ printDatMessage(arg);
+ }
+ break;
+ case IDI_MSA_ACTION_USE_CROWBAR_1:
+ game.iRmMenu[game.iRoom] = 0;
+ getXtal(arg);
+ break;
+
+ // SPACESHIP
+
+ case IDI_MSA_ACTION_GO_NORTH:
+ if (game.fShipDoorOpen) {
+ if (game.fSuit) {
+ printDatMessage(45);
+ } else {
+ game.iRoom = IDI_MSA_PIC_SHIP_CORRIDOR;
+ return true;
+ }
+ } else {
+ printDatMessage(arg);
+ }
+ break;
+ case IDI_MSA_ACTION_GO_PLANET:
+ if (!game.fShipDoorOpen) {
+ if ((game.nXtals == IDI_MSA_MAX_PLANET) && (game.iPlanet == IDI_MSA_PLANET_EARTH))
+ gameOver();
+ if ((game.iPlanet == game.iPlanetXtal[game.nXtals]) || (game.iPlanet == IDI_MSA_PLANET_EARTH)) {
+ game.fHasXtal = false;
+ game.iRoom = IDI_MSA_HOME_PLANET[game.iPlanet];
+ if (game.iPlanet != IDI_MSA_PLANET_EARTH)
+ insertDisk(1);
+ return true;
+ } else {
+ game.iRoom = IDI_MSA_SHIP_PLANET[game.iPlanet];
+ return true;
+ }
+ } else {
+ printDatMessage(arg);
+ }
+ break;
+ case IDI_MSA_ACTION_PRESS_BUTTON:
+ if (game.fShipDoorOpen) { // inner door open
+ if (game.iPlanet && !game.fSuit) {
+ printDatMessage(arg);
+ } else {
+ game.fShipDoorOpen = false;
+ game.iRmPic[game.iRoom]--;
+ drawRoom();
+ printDatMessage(2);
+ }
+ } else {
+ game.fShipDoorOpen = true;
+ game.iRmPic[game.iRoom]++;
+ drawRoom();
+ printDatMessage(14);
+ }
+ break;
+ case IDI_MSA_ACTION_WEAR_SPACESUIT:
+ if (game.fSuit) {
+ if (game.fShipDoorOpen) {
+ game.fSuit = false;
+ game.iRmMenu[game.iRoom] = 0;
+ game.iRmPic[game.iRoom] -= 2;
+ drawRoom();
+ printDatMessage(13);
+ } else {
+ printDatMessage(3);
+ }
+ } else {
+ if (game.iPlanet) {
+ game.fSuit = true;
+ game.iRmMenu[game.iRoom] = 1;
+ game.iRmPic[game.iRoom] += 2;
+ drawRoom();
+ printDatMessage(arg);
+ } else {
+ printDatMessage(12);
+ }
+ }
+ break;
+ case IDI_MSA_ACTION_READ_GAUGE:
+ printDatString(arg);
+ _vm->drawStr(IDI_MSA_ROW_TEMPERATURE, IDI_MSA_COL_TEMPERATURE_C, IDA_DEFAULT,
+ (const char *)IDS_MSA_TEMP_C[game.iPlanet]);
+ _vm->drawStr(IDI_MSA_ROW_TEMPERATURE, IDI_MSA_COL_TEMPERATURE_F, IDA_DEFAULT,
+ (const char *)IDS_MSA_TEMP_F[game.iPlanet]);
+ //_vm->_gfx->doUpdate();
+ //_vm->_system->updateScreen(); // TODO: this should go in the game's main loop
+ waitAnyKey();
+ break;
+ case IDI_MSA_ACTION_PRESS_ORANGE:
+ if (game.fFlying) {
+ printDatMessage(4);
+ } else {
+ playSound(IDI_MSA_SND_PRESS_ORANGE);
+ printDatMessage(arg);
+ pressOB(IDI_MSA_BUTTON_ORANGE);
+ }
+ break;
+ case IDI_MSA_ACTION_PRESS_BLUE:
+ if (game.fFlying) {
+ printDatMessage(4);
+ } else {
+ playSound(IDI_MSA_SND_PRESS_BLUE);
+ printDatMessage(arg);
+ pressOB(IDI_MSA_BUTTON_BLUE);
+ }
+ break;
+ case IDI_MSA_ACTION_FLIP_SWITCH:
+ flipSwitch();
+ break;
+ case IDI_MSA_ACTION_PUSH_THROTTLE:
+ if (game.fFlying) {
+ game.fFlying = false;
+ game.nButtons = 0;
+ memset(game.szAddr, 0, sizeof(game.szAddr));
+ drawRoom();
+ printDatString(22);
+ _vm->drawStr(IDI_MSA_ROW_PLANET, IDI_MSA_COL_PLANET, IDA_DEFAULT,
+ (const char *)IDS_MSA_PLANETS[game.iPlanet]);
+ //_vm->_gfx->doUpdate();
+ //_vm->_system->updateScreen(); // TODO: this should go in the game's main loop
+ waitAnyKeyAnim();
+ showPlanetInfo();
+ } else {
+ printDatMessage(arg);
+ }
+ break;
+ case IDI_MSA_ACTION_PULL_THROTTLE:
+ if (game.fFlying) {
+ printDatMessage(18);
+ } else {
+ if (getPlanet() != -1) {
+ game.fFlying = true;
+ game.iPlanet = getPlanet();
+ drawRoom();
+ printDatMessage(16);
+ } else {
+ game.nButtons = 0;
+ memset(game.szAddr, 0, sizeof(game.szAddr));
+ printDatMessage(17);
+ }
+ }
+ break;
+ case IDI_MSA_ACTION_LEAVE_ROOM:
+ if (game.fFlying) {
+ printDatMessage(24);
+ } else {
+ game.iRoom = arg;
+ return true;
+ }
+ break;
+ case IDI_MSA_ACTION_OPEN_CABINET_1:
+ if (game.iRmMenu[game.iRoom]) {
+ printExeMsg(IDO_MSA_THE_CABINET_IS_ALREADY_OPEN);
+ } else {
+ game.iRmMenu[game.iRoom] = 1;
+ game.iRmPic[game.iRoom] = IDI_MSA_PIC_SHIP_KITCHEN_1;
+ drawRoom();
+ printDatMessage(arg);
+ }
+ break;
+ case IDI_MSA_ACTION_READ_MAP:
+ game.iRmPic[game.iRoom] = IDI_MSA_PIC_STAR_MAP;
+ drawRoom();
+ printDatMessage(46);
+ printDatMessage(47);
+ printDatMessage(48);
+ game.iRmPic[game.iRoom] = IDI_MSA_PIC_SHIP_BEDROOM;
+ drawRoom();
+ break;
+ case IDI_MSA_ACTION_GO_WEST:
+ game.nButtons = 0;
+ memset(game.szAddr, 0, sizeof(game.szAddr));
+ game.iRoom = arg;
+ return true;
+ }
+
+ return false;
+}
+
+void Mickey::gameLoop() {
+ char *buffer = new char[sizeof(MSA_MENU)];
+ MSA_MENU menu;
+ int iSel0, iSel1;
+ bool done;
+
+ for (;;) {
+ drawRoom();
+
+ if (game.fIntro) {
+ game.fIntro = false;
+ } else {
+ printRoomDesc();
+ }
+
+ if (game.iRoom == IDI_MSA_PIC_NEPTUNE_GUARD) {
+ game.iRoom = IDI_MSA_PIC_NEPTUNE_LEADER;
+ done = true;
+ } else {
+ done = false;
+ }
+
+ while (!done) {
+ checkAirSupply(game.fSuit, &game.nAir);
+ readMenu(game.iRoom, buffer);
+ memcpy(&menu, buffer, sizeof(MSA_MENU));
+ patchMenu(&menu);
+ memcpy(buffer, &menu, sizeof(MSA_MENU));
+ getMenuSel(buffer, &iSel0, &iSel1);
+ done = parse(menu.cmd[iSel0].data[iSel1], menu.arg[iSel0].data[iSel1]);
+ }
+
+ game.nFrame = 0;
+ }
+
+ delete [] buffer;
+}
+
+// Keyboard
+
+void Mickey::waitAnyKeyAnim() {
+ waitAnyKey(true);
+}
+
+void Mickey::waitAnyKey(bool anim) {
+ Common::Event event;
+
+ if (!anim) {
+ _vm->_gfx->doUpdate();
+ _vm->_system->updateScreen(); // TODO: this should go in the game's main loop
+ }
+
+ for (;;) {
+ while (_vm->_system->getEventManager()->pollEvent(event)) {
+ switch(event.type) {
+ case Common::EVENT_QUIT:
+ _vm->_system->quit();
+ case Common::EVENT_KEYDOWN:
+ case Common::EVENT_LBUTTONUP:
+ case Common::EVENT_RBUTTONUP:
+ return;
+ default:
+ break;
+ }
+ }
+ if (anim) {
+ animate();
+ _vm->_gfx->doUpdate();
+ _vm->_system->updateScreen(); // TODO: this should go in the game's main loop
+ }
+ }
+}
+
+// Debug
+
+void Mickey::debug_DrawObjs() {
+ char szTitle[14] = {0};
+
+ for (int iObj = 0; iObj < IDI_MSA_MAX_OBJ; iObj++) {
+ drawPic(0);
+ drawObj((ENUM_MSA_OBJECT)iObj, 0, 0);
+
+ _vm->clearTextArea();
+ sprintf(szTitle, "Object %d", iObj);
+ _vm->drawStrMiddle(22, IDA_DEFAULT, szTitle);
+ _vm->drawStrMiddle(23, IDA_DEFAULT, (const char *)IDS_MSA_NAME_OBJ[iObj]);
+ //_vm->_gfx->doUpdate();
+ //_vm->_system->updateScreen(); // TODO: this should go in the game's main loop
+ waitAnyKey();
+ }
+}
+
+void Mickey::debug_DrawPics(){
+ char szTitle[14] = {0};
+
+ for (int iPic = 1; iPic <= IDI_MSA_MAX_PIC; iPic++) {
+ drawPic(iPic);
+
+ _vm->clearTextArea();
+ sprintf(szTitle, "Picture %d", iPic);
+ _vm->drawStrMiddle(22, IDA_DEFAULT, szTitle);
+ //_vm->_gfx->doUpdate();
+ //_vm->_system->updateScreen(); // TODO: this should go in the game's main loop
+ waitAnyKey();
+ }
+}
+
+// Init
+
+void Mickey::initVars() {
+ uint8 buffer[512];
+
+ // clear game struct
+ memset(&game, 0, sizeof(game));
+ memset(&game.iItem, IDI_MSA_OBJECT_NONE, sizeof(game.iItem));
+ // read room extended desc flags
+ readExe(IDO_MSA_ROOM_TEXT, buffer, sizeof(buffer));
+ memcpy(game.fRmTxt, buffer, sizeof(game.fRmTxt));
+
+ // read room extended desc offsets
+ readExe(IDO_MSA_ROOM_TEXT_OFFSETS, buffer, sizeof(buffer));
+ memcpy(game.oRmTxt, buffer, sizeof(game.oRmTxt));
+ for (int i = 0; i < IDI_MSA_MAX_ROOM; i++)
+ game.oRmTxt[i] = buffer[i*2] + 256 * buffer[i*2+1];
+
+ // read room object indices
+ readExe(IDO_MSA_ROOM_OBJECT, buffer, sizeof(buffer));
+ memcpy(game.iRmObj, buffer, sizeof(game.iRmObj));
+
+ // read room picture indices
+ //readExe(IDO_MSA_ROOM_PICTURE, buffer, sizeof(buffer));
+ //memcpy(game.iRmPic, buffer, sizeof(game.iRmPic));
+
+ // read room menu patch indices
+ readExe(IDO_MSA_ROOM_MENU_FIX, buffer, sizeof(buffer));
+ memcpy(game.nRmMenu, buffer, sizeof(game.nRmMenu));
+
+ // set room picture indices
+ for (int i = 0; i < IDI_MSA_MAX_ROOM; i++) {
+ game.iRmPic[i] = i;
+ }
+ game.iRmPic[IDI_MSA_PIC_SHIP_AIRLOCK] = IDI_MSA_PIC_SHIP_AIRLOCK_0;
+
+#if 0
+ // DEBUG
+ game.iPlanet = IDI_MSA_PLANET_EARTH;
+ game.iRoom = IDI_MSA_PIC_SHIP_CONTROLS;
+ game.fHasXtal = true;
+ game.nXtals = 9;
+ game.fItemUsed[IDI_MSA_ITEM_LETTER] = true;
+
+#endif
+
+}
+
+void Mickey::initEngine() {
+ // PreAGI sets the screen params here, but we've already done that in the preagi class
+}
+
+Mickey::Mickey(PreAgiEngine *vm) : _vm(vm) {
+}
+
+Mickey::~Mickey() {
+}
+
+void Mickey::init() {
+ initEngine();
+ initVars();
+}
+
+void Mickey::run() {
+ intro();
+ gameLoop();
+ gameOver();
+}
+
+}
diff --git a/engines/agi/preagi_mickey.h b/engines/agi/preagi_mickey.h
new file mode 100644
index 0000000000..3b45fb8630
--- /dev/null
+++ b/engines/agi/preagi_mickey.h
@@ -0,0 +1,809 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#ifndef AGI_PREAGI_MICKEY_H
+#define AGI_PREAGI_MICKEY_H
+
+#include "agi/agi.h"
+
+namespace Agi {
+
+// strings
+
+#define IDS_MSA_PATH_DAT "dat/%s"
+#define IDS_MSA_PATH_OBJ "obj/%s.ooo"
+#define IDS_MSA_PATH_PIC "%d.pic"
+#define IDS_MSA_PATH_LOGO "logos.bcg"
+#define IDS_MSA_PATH_EXE "mickey.exe"
+
+#define IDS_MSA_INVENTORY "MICKEY IS CARRYING THE FOLLOWING:"
+#define IDS_MSA_CRYSTALS "%s CRYSTALS"
+
+const char IDS_MSA_CRYSTAL_NO[][3] = {
+ "NO", " 1", " 2", " 3", " 4", " 5", " 6", " 7", " 8", " 9"
+};
+const char IDS_MSA_TEMP_C[][5] = {
+ " 20 ", " 480", "-200", " 430", "-185", "-230", "-130", "-150", "-215"
+};
+const char IDS_MSA_TEMP_F[][5] = {
+ " 68 ", " 897", "-328", " 807", "-301", "-382", "-202", "-238", "-355"
+};
+const char IDS_MSA_PLANETS[][10] = {
+ "EARTH. ", "VENUS. ", "TRITON. ", "MERCURY.", "TITAN. ",
+ "PLUTO. ", "IO. ", "MARS. ", "OBERON. "
+};
+
+#define IDS_MSA_DEBUG_ROOM "Now in room #%d "
+#define IDS_MSA_DEBUG_OBJ "There is object #%d "
+
+// patch Mickey.exe offset 0x21E to value 0x01 to enable debug mode
+
+const char IDS_MSA_INSERT_DISK[][40] = {
+ "Please insert disk 1 and press any key", "Please insert disk 2 and press any key"
+};
+
+#define IDS_MSA_ERROR_EXE_NOT_FOUND "File 'mickey.exe' not found in folder 'mickey\'."
+
+// max values
+
+#define IDI_MSA_MAX_PLANET 9
+#define IDI_MSA_MAX_DAT 10
+#define IDI_MSA_MAX_OBJ 32
+#define IDI_MSA_MAX_PIC 240
+#define IDI_MSA_MAX_PIC_ROOM 224
+#define IDI_MSA_MAX_SOUND 8
+#define IDI_MSA_MAX_ROOM 160
+#define IDI_MSA_MAX_STR 160
+
+#define IDI_MSA_MAX_BUTTON 6
+#define IDI_MSA_MAX_ITEM 11
+#define IDI_MSA_MAX_HINT 20
+#define IDI_MSA_MAX_PLANET_INFO 4
+#define IDI_MSA_MAX_AIR_SUPPLY 50
+
+#define IDI_MSA_ANIM_DELAY 25
+
+#define IDI_MSA_LEN_STORY 1372
+
+// rows
+
+#define IDI_MSA_ROW_MENU_0 20
+#define IDI_MSA_ROW_MENU_1 21
+#define IDI_MSA_ROW_INV_TITLE 2
+#define IDI_MSA_ROW_INV_CRYSTALS 4
+#define IDI_MSA_ROW_INV_ITEMS 5
+#define IDI_MSA_ROW_TEMPERATURE 21
+#define IDI_MSA_ROW_PLANET 22
+#define IDI_MSA_ROW_BUTTONS 20
+#define IDI_MSA_ROW_INSERT_DISK 23
+
+#define IDI_MSA_COL_INV_TITLE 4
+#define IDI_MSA_COL_INV_ITEMS 15
+#define IDI_MSA_COL_TEMPERATURE_C 15
+#define IDI_MSA_COL_TEMPERATURE_F 23
+#define IDI_MSA_COL_PLANET 28
+#define IDI_MSA_COL_BUTTONS 22
+#define IDI_MSA_COL_INSERT_DISK 1
+
+// messages
+
+#define IDI_MSA_MSG_STAR_MAP_0 46
+#define IDI_MSA_MSG_STAR_MAP_1 47
+#define IDI_MSA_MSG_STAR_MAP_2 48
+#define IDI_MSA_MSG_SPACESUIT_WEAR 11
+#define IDI_MSA_MSG_SPACESUIT_REMOVE 13
+#define IDI_MSA_MSG_SPACESUIT_0 3
+#define IDI_MSA_MSG_SPACESUIT_CANT_WEAR_ON_EARTH 12
+#define IDI_MSA_MSG_SHIP_LAUNCH 16
+#define IDI_MSA_MSG_SHIP_LAND 22
+
+// screen
+
+#define IDI_MSA_PIC_WIDTH 140
+#define IDI_MSA_PIC_HEIGHT 159
+#define IDI_MSA_PIC_X0 10
+#define IDI_MSA_PIC_Y0 0
+#define IDI_MSA_PIC_FLAGS IDF_AGI_PIC_V2
+
+// pictures
+
+#define IDI_MSA_PIC_EARTH_TIRE_SWING 1
+#define IDI_MSA_PIC_EARTH_TIRE_SWING_1 200 // rope taken, swing on ground
+#define IDI_MSA_PIC_EARTH_DOGHOUSE 2
+#define IDI_MSA_PIC_EARTH_IN_DOGHOUSE 154
+#define IDI_MSA_PIC_EARTH_TREE 3
+#define IDI_MSA_PIC_EARTH_GARDEN 4
+#define IDI_MSA_PIC_EARTH_FRONT_HOUSE 5
+#define IDI_MSA_PIC_EARTH_HAMMOCK 6
+#define IDI_MSA_PIC_EARTH_BUTTERFLY 7
+#define IDI_MSA_PIC_EARTH_MAILBOX 8
+#define IDI_MSA_PIC_EARTH_ROAD_0 9
+#define IDI_MSA_PIC_EARTH_ROAD_1 10
+#define IDI_MSA_PIC_EARTH_ROAD_2 11
+#define IDI_MSA_PIC_EARTH_ROAD_3 12
+#define IDI_MSA_PIC_EARTH_ROAD_4 13 // starting room
+#define IDI_MSA_PIC_EARTH_ROAD_5 14
+#define IDI_MSA_PIC_EARTH_ROAD_6 15
+#define IDI_MSA_PIC_EARTH_ROAD_7 18
+#define IDI_MSA_PIC_EARTH_UNDER_TREE 16
+#define IDI_MSA_PIC_EARTH_UP_IN_TREE 155 // CRYSTAL
+#define IDI_MSA_PIC_EARTH_SHIP 17
+#define IDI_MSA_PIC_EARTH_LIVING_ROOM 19
+#define IDI_MSA_PIC_EARTH_KITCHEN 20
+#define IDI_MSA_PIC_EARTH_KITCHEN_1 159 // cupboard open
+#define IDI_MSA_PIC_EARTH_GARAGE 21
+#define IDI_MSA_PIC_EARTH_GARAGE_1 160 // cabinet open
+#define IDI_MSA_PIC_EARTH_BEDROOM 22
+#define IDI_MSA_PIC_EARTH_BEDROOM_1 161 // closet open
+#define IDI_MSA_PIC_EARTH_BATHROOM 23 // WEIGH MICKEY
+#define IDI_MSA_PIC_EARTH_SHIP_LEAVING 24
+#define IDI_MSA_PIC_EARTH_MINNIE 25
+
+#define IDI_MSA_PIC_SHIP_AIRLOCK 25
+#define IDI_MSA_PIC_SHIP_AIRLOCK_0 201 // door closed
+#define IDI_MSA_PIC_SHIP_AIRLOCK_1 202 // door open
+#define IDI_MSA_PIC_SHIP_AIRLOCK_2 203 // door closed, spacesuits on
+#define IDI_MSA_PIC_SHIP_AIRLOCK_3 204 // door open, spacesuits on
+#define IDI_MSA_PIC_SHIP_BEDROOM 29
+#define IDI_MSA_PIC_SHIP_CONTROLS 26
+#define IDI_MSA_PIC_SHIP_CORRIDOR 27
+#define IDI_MSA_PIC_SHIP_KITCHEN 28
+#define IDI_MSA_PIC_SHIP_KITCHEN_1 172 // cabinet open
+
+#define IDI_MSA_PIC_SHIP_VENUS 146
+#define IDI_MSA_PIC_SHIP_NEPTUNE 147
+#define IDI_MSA_PIC_SHIP_MERCURY 148
+#define IDI_MSA_PIC_SHIP_SATURN 149
+#define IDI_MSA_PIC_SHIP_PLUTO 150
+#define IDI_MSA_PIC_SHIP_JUPITER 151
+#define IDI_MSA_PIC_SHIP_MARS 152
+#define IDI_MSA_PIC_SHIP_URANUS 153
+
+#define IDI_MSA_PIC_VENUS_0 30
+#define IDI_MSA_PIC_VENUS_1 31
+#define IDI_MSA_PIC_VENUS_2 32
+#define IDI_MSA_PIC_VENUS_3 34
+#define IDI_MSA_PIC_VENUS_4 36
+#define IDI_MSA_PIC_VENUS_5 38
+#define IDI_MSA_PIC_VENUS_CHASM 35
+#define IDI_MSA_PIC_VENUS_CHASM_1 183 // rope lowered
+#define IDI_MSA_PIC_VENUS_PROBE 39 // CRYSTAL, USE WRENCH
+#define IDI_MSA_PIC_VENUS_PROBE_1 184 // hatch open
+#define IDI_MSA_PIC_VENUS_SHIP 33
+#define IDI_MSA_PIC_VENUS_WEIGH 37 // WEIGH MICKEY
+
+#define IDI_MSA_PIC_NEPTUNE_0 40
+#define IDI_MSA_PIC_NEPTUNE_1 42
+#define IDI_MSA_PIC_NEPTUNE_2 43
+#define IDI_MSA_PIC_NEPTUNE_3 44
+#define IDI_MSA_PIC_NEPTUNE_4 45
+#define IDI_MSA_PIC_NEPTUNE_5 48
+#define IDI_MSA_PIC_NEPTUNE_6 50
+#define IDI_MSA_PIC_NEPTUNE_7 52
+#define IDI_MSA_PIC_NEPTUNE_8 53
+#define IDI_MSA_PIC_NEPTUNE_9 54
+#define IDI_MSA_PIC_NEPTUNE_10 55
+#define IDI_MSA_PIC_NEPTUNE_11 56
+#define IDI_MSA_PIC_NEPTUNE_BABIES 61
+#define IDI_MSA_PIC_NEPTUNE_CASTLE_0 46
+#define IDI_MSA_PIC_NEPTUNE_CASTLE_1 51
+#define IDI_MSA_PIC_NEPTUNE_CASTLE_2 57
+#define IDI_MSA_PIC_NEPTUNE_CASTLE_3 58
+#define IDI_MSA_PIC_NEPTUNE_CASTLE_4 59
+#define IDI_MSA_PIC_NEPTUNE_CASTLE_5 60
+#define IDI_MSA_PIC_NEPTUNE_CASTLE_6 66
+#define IDI_MSA_PIC_NEPTUNE_CASTLE_7 67
+#define IDI_MSA_PIC_NEPTUNE_CASTLE_8 68
+#define IDI_MSA_PIC_NEPTUNE_EATING_AREA 62
+#define IDI_MSA_PIC_NEPTUNE_ENTRANCE 47
+#define IDI_MSA_PIC_NEPTUNE_ENTRANCE_1 185 // entrance open
+#define IDI_MSA_PIC_NEPTUNE_ENTRYWAY 63
+#define IDI_MSA_PIC_NEPTUNE_GUARD 69
+#define IDI_MSA_PIC_NEPTUNE_LEADER 64 // CRYSTAL, GIVE SCARF
+#define IDI_MSA_PIC_NEPTUNE_SHIP 49
+#define IDI_MSA_PIC_NEPTUNE_SLEEP_AREA 65
+#define IDI_MSA_PIC_NEPTUNE_WEIGH 41
+
+#define IDI_MSA_PIC_MERCURY_0 71
+#define IDI_MSA_PIC_MERCURY_1 73
+#define IDI_MSA_PIC_MERCURY_2 75
+#define IDI_MSA_PIC_MERCURY_3 77
+#define IDI_MSA_PIC_MERCURY_4 80
+#define IDI_MSA_PIC_MERCURY_ALIEN_0 72 // CRYSTAL, GIVE SUNGLASSES
+#define IDI_MSA_PIC_MERCURY_ALIEN_1 74
+#define IDI_MSA_PIC_MERCURY_ALIEN_2 81
+#define IDI_MSA_PIC_MERCURY_CAVE_0 70 // hidden feature, press '2' here
+#define IDI_MSA_PIC_MERCURY_CAVE_1 78
+#define IDI_MSA_PIC_MERCURY_CAVE_2 79
+#define IDI_MSA_PIC_MERCURY_SHIP 76
+#define IDI_MSA_PIC_MERCURY_WEIGH 82
+
+#define IDI_MSA_PIC_SATURN_0 84
+#define IDI_MSA_PIC_SATURN_1 86
+#define IDI_MSA_PIC_SATURN_2 90
+#define IDI_MSA_PIC_SATURN_3 91
+#define IDI_MSA_PIC_SATURN_ISLAND 89 // CRYSTAL
+#define IDI_MSA_PIC_SATURN_LAKE_0 85 // USE MATTRESS
+#define IDI_MSA_PIC_SATURN_LAKE_1 88 // USE MATTRESS
+#define IDI_MSA_PIC_SATURN_LAKE_2 92 // USE MATTRESS
+#define IDI_MSA_PIC_SATURN_SHIP 87
+#define IDI_MSA_PIC_SATURN_WEIGH 83 // WEIGH MICKEY
+
+#define IDI_MSA_PIC_PLUTO_0 93
+#define IDI_MSA_PIC_PLUTO_1 96
+#define IDI_MSA_PIC_PLUTO_2 97
+#define IDI_MSA_PIC_PLUTO_3 98
+#define IDI_MSA_PIC_PLUTO_4 101
+#define IDI_MSA_PIC_PLUTO_ALIENS 100 // CRYSTAL, GIVE BONE
+#define IDI_MSA_PIC_PLUTO_CAVE_0 99
+#define IDI_MSA_PIC_PLUTO_CAVE_1 103
+#define IDI_MSA_PIC_PLUTO_CRATER 102
+#define IDI_MSA_PIC_PLUTO_SHIP 95
+#define IDI_MSA_PIC_PLUTO_WEIGH 94 // WEIGH MICKEY
+
+#define IDI_MSA_PIC_JUPITER_0 106
+#define IDI_MSA_PIC_JUPITER_1 107
+#define IDI_MSA_PIC_JUPITER_2 108
+#define IDI_MSA_PIC_JUPITER_3 109
+#define IDI_MSA_PIC_JUPITER_4 113
+#define IDI_MSA_PIC_JUPITER_5 116
+#define IDI_MSA_PIC_JUPITER_6 117
+#define IDI_MSA_PIC_JUPITER_7 120
+#define IDI_MSA_PIC_JUPITER_CRACK 114
+#define IDI_MSA_PIC_JUPITER_LAVA 110 // CRYSTAL, THROW ROCK
+#define IDI_MSA_PIC_JUPITER_ROCK_0 112 // GET ROCK
+#define IDI_MSA_PIC_JUPITER_ROCK_1 119 // GET ROCK
+#define IDI_MSA_PIC_JUPITER_SHIP 115
+#define IDI_MSA_PIC_JUPITER_WEIGH 118 // WEIGH MICKEY
+
+#define IDI_MSA_PIC_MARS_0 121
+#define IDI_MSA_PIC_MARS_1 124
+#define IDI_MSA_PIC_MARS_2 125
+#define IDI_MSA_PIC_MARS_3 126
+#define IDI_MSA_PIC_MARS_4 127
+#define IDI_MSA_PIC_MARS_5 128
+#define IDI_MSA_PIC_MARS_6 130
+#define IDI_MSA_PIC_MARS_SHIP 123
+#define IDI_MSA_PIC_MARS_TUBE_0 129
+#define IDI_MSA_PIC_MARS_TUBE_1 131
+#define IDI_MSA_PIC_MARS_VOLCANO 132 // CRYSTAL, DIG PLUTO
+#define IDI_MSA_PIC_MARS_WEIGH 122 // WEIGH MICKEY
+
+#define IDI_MSA_PIC_URANUS_0 133
+#define IDI_MSA_PIC_URANUS_1 134
+#define IDI_MSA_PIC_URANUS_2 135
+#define IDI_MSA_PIC_URANUS_3 138
+#define IDI_MSA_PIC_URANUS_4 139
+#define IDI_MSA_PIC_URANUS_5 140
+#define IDI_MSA_PIC_URANUS_6 142
+#define IDI_MSA_PIC_URANUS_CHAMBER 145 // CRYSTAL, USE CROWBAR
+#define IDI_MSA_PIC_URANUS_SHIP 137
+#define IDI_MSA_PIC_URANUS_STEPS 144
+#define IDI_MSA_PIC_URANUS_ENTRANCE 141 // ENTER TEMPLE
+#define IDI_MSA_PIC_URANUS_TEMPLE 143 // USE CRYSTAL, ENTER DOOR
+#define IDI_MSA_PIC_URANUS_TEMPLE_1 206 // crystal used
+#define IDI_MSA_PIC_URANUS_TEMPLE_2 207 // door open
+#define IDI_MSA_PIC_URANUS_WEIGH 136 // WEIGH MICKEY
+
+#define IDI_MSA_PIC_STAR_MAP 165
+#define IDI_MSA_PIC_TITLE 240
+
+// objects
+
+enum ENUM_MSA_OBJECT {
+ IDI_MSA_OBJECT_NONE = -1,
+ IDI_MSA_OBJECT_ROCK_0,
+ IDI_MSA_OBJECT_WRENCH,
+ IDI_MSA_OBJECT_SCALE,
+ IDI_MSA_OBJECT_CROWBAR,
+ IDI_MSA_OBJECT_BONE,
+ IDI_MSA_OBJECT_SUNGLASSES,
+ IDI_MSA_OBJECT_DESK_STUFF,
+ IDI_MSA_OBJECT_MATTRESS,
+ IDI_MSA_OBJECT_SCARF,
+ IDI_MSA_OBJECT_FLASHLIGHT,
+ IDI_MSA_OBJECT_ROPE,
+ IDI_MSA_OBJECT_ROCK_1,
+ IDI_MSA_OBJECT_SCARF_C64,
+ IDI_MSA_OBJECT_ROCK_2,
+ IDI_MSA_OBJECT_ROCK_3,
+ IDI_MSA_OBJECT_W_EARTH,
+ IDI_MSA_OBJECT_W_VENUS,
+ IDI_MSA_OBJECT_W_TRITON,
+ IDI_MSA_OBJECT_W_MERCURY,
+ IDI_MSA_OBJECT_W_TITAN,
+ IDI_MSA_OBJECT_W_PLUTO,
+ IDI_MSA_OBJECT_W_IO,
+ IDI_MSA_OBJECT_W_MARS,
+ IDI_MSA_OBJECT_W_OBERON,
+ IDI_MSA_OBJECT_W_SPACE,
+ IDI_MSA_OBJECT_XL31,
+ IDI_MSA_OBJECT_XL31E,
+ IDI_MSA_OBJECT_XL32,
+ IDI_MSA_OBJECT_XL32E,
+ IDI_MSA_OBJECT_XL33,
+ IDI_MSA_OBJECT_XL33E,
+ IDI_MSA_OBJECT_CRYSTAL
+};
+
+const char IDS_MSA_NAME_OBJ[][9] = {
+ "rok1", "wrench", "scale", "cbar", "bone", "glasses", "deskstuf", "raft",
+ "scarf", "flashlit", "rope", "rok1", "scarfc64", "rok2", "rock35", "earthw",
+ "venw", "trw", "merw", "titw", "plw", "iow", "mrw", "obw", "spw", "xl31",
+ "xl31e", "xl32", "xl32e", "xl33", "xl33e", "crys1"
+};
+
+const int IDI_MSA_XTAL_ROOM_XY[IDI_MSA_MAX_PLANET][3] = {
+ // room x y
+ {IDI_MSA_PIC_EARTH_UP_IN_TREE, 14, 76},
+ {IDI_MSA_PIC_VENUS_PROBE, 74, 80},
+ {IDI_MSA_PIC_NEPTUNE_LEADER, 70, 27},
+ {IDI_MSA_PIC_MERCURY_ALIEN_0, 123, 64},
+ {IDI_MSA_PIC_SATURN_ISLAND, 110, 115},
+ {IDI_MSA_PIC_PLUTO_ALIENS, 60, 104},
+ {IDI_MSA_PIC_JUPITER_LAVA, 56, 54},
+ {IDI_MSA_PIC_MARS_VOLCANO, 107, 100},
+ {IDI_MSA_PIC_URANUS_CHAMBER, 90, 4}
+};
+
+// planets
+
+enum ENUM_MSA_PLANET {
+ IDI_MSA_PLANET_EARTH = 0,
+ IDI_MSA_PLANET_VENUS,
+ IDI_MSA_PLANET_NEPTUNE,
+ IDI_MSA_PLANET_MERCURY,
+ IDI_MSA_PLANET_SATURN,
+ IDI_MSA_PLANET_PLUTO,
+ IDI_MSA_PLANET_JUPITER,
+ IDI_MSA_PLANET_MARS,
+ IDI_MSA_PLANET_URANUS,
+ IDI_MSA_PLANET_SPACESHIP
+};
+
+const char IDS_MSA_NAME_DAT[][13] = {
+ "earth.dat", "venus.dat", "neptune.dat", "mercury.dat", "saturn.dat",
+ "pluto.dat", "jupiter.dat", "mars.dat", "uranus.dat", "spacship.dat"
+};
+
+const char IDS_MSA_NAME_PLANET[][10] = {
+ "EARTH", "VENUS", "TRITON", "MERCURY", "TITAN",
+ "PLUTO", "IO", "MARS", "OBERON"
+};
+
+const char IDS_MSA_NAME_PLANET_2[][10] = {
+ "EARTH", "VENUS", "NEPTUNE", "MERCURY", "SATURN",
+ "PLUTO", "JUPITER", "MARS", "URANUS"
+};
+
+const char IDS_MSA_ADDR_PLANET[][7] = {
+ "OB", "B", "OOBBB", "O", "OOBB",
+ "OOOBBB", "OBB", "OOB", "OOOBB"
+};
+
+const int IDI_MSA_HOME_PLANET[] = {
+ IDI_MSA_PIC_EARTH_SHIP, IDI_MSA_PIC_VENUS_SHIP, IDI_MSA_PIC_NEPTUNE_SHIP, IDI_MSA_PIC_MERCURY_SHIP,
+ IDI_MSA_PIC_SATURN_SHIP, IDI_MSA_PIC_PLUTO_SHIP, IDI_MSA_PIC_JUPITER_SHIP, IDI_MSA_PIC_MARS_SHIP,
+ IDI_MSA_PIC_URANUS_SHIP
+};
+
+const int IDI_MSA_SHIP_PLANET[] = {
+ 0, IDI_MSA_PIC_SHIP_VENUS, IDI_MSA_PIC_SHIP_NEPTUNE, IDI_MSA_PIC_SHIP_MERCURY, IDI_MSA_PIC_SHIP_SATURN,
+ IDI_MSA_PIC_SHIP_PLUTO, IDI_MSA_PIC_SHIP_JUPITER, IDI_MSA_PIC_SHIP_MARS, IDI_MSA_PIC_SHIP_URANUS
+};
+
+// items
+
+enum ENUM_MSA_ITEM {
+ IDI_MSA_ITEM_FLASHLIGHT = 0,
+ IDI_MSA_ITEM_ROPE,
+ IDI_MSA_ITEM_BONE,
+ IDI_MSA_ITEM_LETTER,
+ IDI_MSA_ITEM_CROWBAR,
+ IDI_MSA_ITEM_WRENCH,
+ IDI_MSA_ITEM_MATTRESS,
+ IDI_MSA_ITEM_SCARF,
+ IDI_MSA_ITEM_SUNGLASSES,
+ IDI_MSA_ITEM_SCALE,
+ IDI_MSA_ITEM_ROCK
+};
+
+const char IDS_MSA_NAME_ITEM[][15] = {
+ "A FLASHLIGHT", "A ROPE ", "A BONE ", "A LETTER", "A CROWBAR", "A WRENCH",
+ "A MATTRESS", "A SCARF", "SUNGLASSES", "A SCALE ", "A ROCK "
+};
+
+// buttons
+
+#define IDI_MSA_BUTTON_ORANGE 0x4F // 'O'
+#define IDI_MSA_BUTTON_BLUE 0x42 // 'B'
+
+// file structures
+
+struct MSA_TEXT_ENTRY {
+ uint8 x0;
+ uint8 szText[11];
+};
+
+struct MSA_TEXT_BLOCK {
+ uint8 count;
+ MSA_TEXT_ENTRY entry[5];
+};
+
+struct MSA_MSG_BLOCK {
+ uint8 data[5];
+};
+
+struct MSA_MENU {
+ MSA_TEXT_BLOCK row[2];
+ MSA_MSG_BLOCK cmd[5];
+ MSA_MSG_BLOCK arg[5];
+};
+
+struct MSA_DAT_HEADER {
+ uint16 filelen;
+ uint16 ofsRoom[IDI_MSA_MAX_ROOM];
+ uint16 ofsDesc[IDI_MSA_MAX_ROOM];
+ uint16 ofsStr[IDI_MSA_MAX_STR];
+};
+
+struct MSA_SND_NOTE {
+ uint16 counter; // freq = 1193180 / counter
+ uint8 length; // msec = length / 0.0182
+};
+
+// file offset modifiers
+
+#define IDI_MSA_OFS_INVALID 0xFE9A
+#define IDI_MSA_OFS_DAT 0x0002
+#define IDI_MSA_OFS_EXE 0x35C0
+#define IDI_MSA_OFS_OBJECT_DATA 0x58E8
+
+// actions
+
+#define IDI_MSA_ACTION_GOTO_ROOM 0x00
+#define IDI_MSA_ACTION_SHOW_INT_STR 0x01
+#define IDI_MSA_ACTION_UNUSED 0x02
+#define IDI_MSA_ACTION_SHOW_DAT_STR 0x03
+
+#define IDI_MSA_ACTION_GET_ROPE 0x7F
+#define IDI_MSA_ACTION_UNTIE_ROPE 0x80
+#define IDI_MSA_ACTION_GET_BONE 0x81
+#define IDI_MSA_ACTION_GET_XTAL_EARTH 0x82
+#define IDI_MSA_ACTION_LOOK_DESK 0x83
+#define IDI_MSA_ACTION_WRITE_LETTER 0x84
+#define IDI_MSA_ACTION_MAIL_LETTER 0x85
+#define IDI_MSA_ACTION_OPEN_CUPBOARD 0x86
+#define IDI_MSA_ACTION_GET_FLASHLIGHT 0x87
+#define IDI_MSA_ACTION_OPEN_CABINET 0x88
+#define IDI_MSA_ACTION_GET_CROWBAR 0x89
+#define IDI_MSA_ACTION_GET_WRENCH 0x8A
+#define IDI_MSA_ACTION_OPEN_CLOSET 0x8B
+#define IDI_MSA_ACTION_GET_MATTRESS 0x8C
+#define IDI_MSA_ACTION_GET_SCARF 0x8D
+#define IDI_MSA_ACTION_GET_SUNGLASSES 0x8E
+#define IDI_MSA_ACTION_GET_SCALE 0x8F
+#define IDI_MSA_ACTION_GOTO_SPACESHIP 0x90
+
+#define IDI_MSA_ACTION_DOWN_CHASM 0x91
+#define IDI_MSA_ACTION_DOWN_ROPE 0x92
+#define IDI_MSA_ACTION_USE_ROPE 0x93
+#define IDI_MSA_ACTION_OPEN_HATCH 0x94
+#define IDI_MSA_ACTION_USE_WRENCH 0x95
+#define IDI_MSA_ACTION_GET_XTAL_VENUS 0x96
+
+#define IDI_MSA_ACTION_LOOK_CASTLE 0x97
+#define IDI_MSA_ACTION_ENTER_OPENING 0x98
+#define IDI_MSA_ACTION_USE_CROWBAR 0x99
+#define IDI_MSA_ACTION_GET_XTAL_NEPTUNE 0x9A
+#define IDI_MSA_ACTION_TALK_LEADER 0x9B
+#define IDI_MSA_ACTION_GIVE_SCARF 0x9C
+
+#define IDI_MSA_ACTION_GET_XTAL_MERCURY 0x9D
+#define IDI_MSA_ACTION_GIVE_SUNGLASSES 0x9E
+#define IDI_MSA_ACTION_CROSS_LAKE 0x9F
+#define IDI_MSA_ACTION_USE_MATTRESS 0xA0
+#define IDI_MSA_ACTION_GET_XTAL_SATURN 0xA1
+#define IDI_MSA_ACTION_LEAVE_ISLAND 0xA2
+
+#define IDI_MSA_ACTION_GET_XTAL_PLUTO 0xA3
+#define IDI_MSA_ACTION_GIVE_BONE 0xA4
+
+#define IDI_MSA_ACTION_GET_ROCK_0 0xA5
+#define IDI_MSA_ACTION_GET_ROCK_1 0xA6
+#define IDI_MSA_ACTION_GET_XTAL_JUPITER 0xA7
+#define IDI_MSA_ACTION_THROW_ROCK 0xA8
+
+#define IDI_MSA_ACTION_GO_TUBE 0xA9
+#define IDI_MSA_ACTION_USE_FLASHLIGHT 0xAA
+#define IDI_MSA_ACTION_PLUTO_DIG 0xAB
+#define IDI_MSA_ACTION_GET_XTAL_MARS 0xAC
+
+#define IDI_MSA_ACTION_USE_CRYSTAL 0xAD
+#define IDI_MSA_ACTION_OPEN_DOOR 0xAE
+#define IDI_MSA_ACTION_ENTER_DOOR 0xAF
+#define IDI_MSA_ACTION_GET_XTAL_URANUS 0xB0
+#define IDI_MSA_ACTION_USE_CROWBAR_1 0xB1
+
+#define IDI_MSA_ACTION_GO_NORTH 0xB2
+#define IDI_MSA_ACTION_GO_PLANET 0xB3
+#define IDI_MSA_ACTION_PRESS_BUTTON 0xB4
+#define IDI_MSA_ACTION_WEAR_SPACESUIT 0xB5
+#define IDI_MSA_ACTION_READ_GAUGE 0xB6
+#define IDI_MSA_ACTION_PRESS_ORANGE 0xB7
+#define IDI_MSA_ACTION_PRESS_BLUE 0xB8
+#define IDI_MSA_ACTION_FLIP_SWITCH 0xB9
+#define IDI_MSA_ACTION_PUSH_THROTTLE 0xBA
+#define IDI_MSA_ACTION_PULL_THROTTLE 0xBB
+#define IDI_MSA_ACTION_LEAVE_ROOM 0xBC
+#define IDI_MSA_ACTION_OPEN_CABINET_1 0xBD
+#define IDI_MSA_ACTION_READ_MAP 0xBE
+#define IDI_MSA_ACTION_GO_WEST 0xBF
+
+#define IDI_MSA_ACTION_PLANET_INFO 0xC0
+#define IDI_MSA_ACTION_ENTER_TEMPLE 0xC1
+#define IDI_MSA_ACTION_OPEN_MAILBOX 0xC2
+#define IDI_MSA_ACTION_SAVE_GAME 0xC3
+#define IDI_MSA_ACTION_LOOK_MICKEY 0xC4
+
+// sounds
+
+enum ENUM_MSA_SOUND {
+ IDI_MSA_SND_THEME,
+ IDI_MSA_SND_CRYSTAL,
+ IDI_MSA_SND_TAKE,
+ IDI_MSA_SND_GAME_OVER,
+ IDI_MSA_SND_PRESS_BLUE,
+ IDI_MSA_SND_PRESS_ORANGE,
+ IDI_MSA_SND_SHIP_LAND,
+ IDI_MSA_SND_XL30
+};
+
+// message offsets within mickey.exe
+
+const int IDO_MSA_ERROR[] = {
+ 0x4C9C, 0x4CB9, 0x4CD4, 0x4CEA, 0x4D0D, 0x4D20, 0x4D3B, 0x4D5E
+};
+
+const int IDO_MSA_HIDDEN_MSG[] = {
+ 0x8C44, 0x8C83, 0x8D23, 0x8D97, 0x8E2A
+};
+
+const int IDO_MSA_GAME_OVER[] = {
+ 0x7914, 0x7978, 0x7A17, 0x7A94, 0x7B04, 0x7B8F, 0x7BEB, 0x7C79
+};
+
+const int IDO_MSA_SAVE_GAME[] = {
+ 0x73FA, 0x7436, 0x746C, 0x74E9, 0x75F6, 0x766A, 0x758B
+ // do you have a formatted disk, insert disk, insert disk 2, save by number
+ // everything will be lost, previous game will be lost, game saved
+};
+
+const int IDO_MSA_LOAD_GAME[] = {
+ 0x76CE, 0x770B, 0x7777
+ // do you want to load game, insert game save disk, game restored
+};
+
+const int IDO_MSA_AIR_SUPPLY[] = {
+ 0x7D10, 0x7D31, 0x7D51, 0x7D9B
+ // be aware, low, dangerously low, out of air
+ // 30, 20, 10, 0
+};
+
+const int IDI_MSA_AIR_SUPPLY[] = { 30, 20, 10, 0 };
+
+// planet information
+
+const int IDO_MSA_PLANET_INFO[IDI_MSA_MAX_PLANET][4] = {
+ {0x6313, 0x63B2, 0x6449, 0}, // EARTH
+ {0x61EB, 0x6288, 0, 0}, // VENUS
+ {0x6B64, 0x6C06, 0x6CA3, 0}, // NEPTUNE
+ {0x609B, 0x612C, 0x61CA, 0}, // MERCURY
+ {0x6879, 0x6916, 0x6984, 0}, // SATURN
+ {0x6CCF, 0x6D72, 0x6E10, 0}, // PLUTO
+ {0x667C, 0x6714, 0x67B1, 0x684E}, // JUPITER
+ {0x6471, 0x650F, 0x65AD, 0x6651}, // MARS
+ {0x69C3, 0x6A62, 0x6B00, 0} // URANUS
+};
+
+// next crystal piece hints
+
+const int IDO_MSA_NEXT_PIECE[IDI_MSA_MAX_PLANET][5] = {
+ {0, 0, 0, 0, 0}, // earth
+ {0x4DCC, 0x4E20, 0x4E64, 0x4E9E, 0x4F0B}, // venus
+ {0x5900, 0x599B, 0x5A07, 0x5A8E, 0x5B07}, // neptune
+ {0x4F57, 0x4FA3, 0x4FF1, 0x5056, 0x50BD}, // mercury
+ {0x5471, 0x54DF, 0x5548, 0x55C2, 0x562A}, // saturn
+ {0x5B78, 0x5BB6, 0x5C29, 0x5C76, 0x5CE1}, // pluto
+ {0x526B, 0x52DA, 0x5340, 0x53A1, 0x540C}, // jupiter
+ {0x50F6, 0x512C, 0x5170, 0x51D5, 0x5228}, // mars
+ {0x56AA, 0x571C, 0x579E, 0x5807, 0x5875} // uranus
+};
+
+// message offsets
+
+#define IDO_MSA_COPYRIGHT 0x7801
+#define IDO_MSA_INTRO 0x4679
+#define IDO_MSA_GAME_STORY 0x6E9C
+
+#define IDO_MSA_CHECK_DISK_DRIVE 0x7885
+#define IDO_MSA_YOU_CAN_SEE_MICKEY_ALREADY 0x46D1
+#define IDO_MSA_THE_CABINET_IS_ALREADY_OPEN 0x46EF
+
+#define IDO_MSA_PRESS_1_TO_9 0x7530
+#define IDO_MSA_PRESS_YES_OR_NO 0x480D
+#define IDO_MSA_TOO_MANY_BUTTONS_PRESSED 0x5DF7
+
+#define IDO_MSA_MICKEY_HAS_PRESSED 0x5D90
+
+#define IDO_MSA_XL30_SPEAKING 0x4725
+#define IDO_MSA_CRYSTAL_PIECE_FOUND 0x600C
+
+#define IDO_MSA_FONT 0x7EDC // 256 chars, 2048 bytes (00110010 * 8 = character)
+
+#define IDO_MSA_ROOM_TEXT 0x4B80
+#define IDO_MSA_ROOM_TEXT_OFFSETS 0x8B01
+#define IDO_MSA_ROOM_OBJECT 0x475C
+#define IDO_MSA_ROOM_PICTURE 0x4AE4
+#define IDO_MSA_ROOM_OBJECT_XY_OFFSETS 0x8EA8
+#define IDO_MSA_PIC_SHIP_LIGHT 0x8F38
+#define IDO_MSA_XTAL_ROOM_XY 0x97F8
+//#define IDO_MSA_PLANET_INFO 0x6048
+#define IDO_MSA_ROOM_MENU_FIX 0x4a27
+#define IDO_MSA_ROOM_MENU_FIX_OFFSETS 0x5E7A
+
+// offsets to offset arrays
+
+#define IDOFS_MSA_INTERPRETER_ERRORS 0x4c8e
+#define IDOFS_MSA_HIDDEN_FEATURE 0x8c3a
+#define IDOFS_MSA_MENU_PATCHES 0x5e7a
+#define IDOFS_MSA_SOUND_DATA 0x9deb
+#define IDOFS_MSA_NEXT_PLANET_CLUES 0x4d7c
+#define IDOFS_MSA_PLANET_INFORMATION 0x6048
+#define IDOFS_MSA_PLANET_ADDRESSES 0x5e40
+#define IDOFS_MSA_OBJECT_DATA 0x8ea8
+#define IDOFS_MSA_EXTENDED_ROOM_DESCRIPTIONS 0x8b01
+
+// game structure
+
+struct MSA_GAME {
+ int iRoom;
+ int iPlanet;
+ int iDisk;
+
+ int nAir;
+ int nButtons;
+ int nRocks;
+
+ bool fHasXtal;
+ int nXtals;
+ int iPlanetXtal[IDI_MSA_MAX_DAT];
+ int iClue[IDI_MSA_MAX_PLANET];
+ char szAddr[IDI_MSA_MAX_BUTTON + 1];
+
+ bool fIntro;
+ bool fSuit;
+ bool fShipDoorOpen;
+ bool fFlying;
+ bool fStoryShown;
+ bool fTempleDoorOpen;
+
+ bool fItem[IDI_MSA_MAX_ITEM];
+ bool fItemUsed[IDI_MSA_MAX_ITEM];
+ int iItem[IDI_MSA_MAX_ITEM];
+ int nItems;
+
+ int8 fRmTxt[IDI_MSA_MAX_ROOM];
+ int8 iRmObj[IDI_MSA_MAX_ROOM];
+ uint8 iRmPic[IDI_MSA_MAX_ROOM];
+ uint16 oRmTxt[IDI_MSA_MAX_ROOM];
+
+ uint8 iRmMenu[IDI_MSA_MAX_ROOM];
+ uint8 nRmMenu[IDI_MSA_MAX_ROOM];
+
+ int nFrame; // 0.1.4
+ bool fAnimXL30; // 0.1.4
+ int nTicks; // 0.1.4
+};
+
+class Mickey {
+ friend class PreAgiEngine;
+public:
+
+ Mickey(PreAgiEngine *vm);
+ ~Mickey();
+
+ void init();
+ void run();
+protected:
+ PreAgiEngine *_vm;
+ MSA_GAME game;
+ bool clickToMove;
+
+ int getDat(int);
+ void readExe(int, uint8*, long);
+ void getDatFileName(int, char*);
+ void readDatHdr(char*, MSA_DAT_HEADER*);
+ void readDesc(int, char*, long);
+ void readMenu(int, char*);
+ void readDatStr(int, int, char*, long);
+ void readOfsData(int, int, uint8*, long);
+ bool chooseY_N(int, bool);
+ int choose1to9(int);
+ void printStr(char*);
+ void printExeStr(int);
+ void printExeMsg(int);
+ void printDatStr(int, int);
+ void printDesc(int);
+ void drawMenu(MSA_MENU, int, int);
+ void getMouseMenuSelRow(MSA_MENU, int*, int*, int, int, int);
+ bool getMenuSelRow(MSA_MENU, int*, int*, int);
+ void getMenuSel(char*, int*, int*);
+ void centerMenu(MSA_MENU*);
+ void patchMenu(MSA_MENU*);
+ void printDatString(int);
+ void printDatMessage(int);
+ void playNote(MSA_SND_NOTE);
+ void playSound(ENUM_MSA_SOUND);
+ void debug();
+ void drawObj(ENUM_MSA_OBJECT, int, int);
+ void drawPic(int);
+ void drawRoomPicture();
+ void drawRoomObjects();
+ void drawRoomAnimation();
+ void drawRoom();
+ void drawLogo();
+ void animate();
+ void printRoomDesc();
+ bool loadGame();
+ void saveGame();
+ void showPlanetInfo();
+ void printStory();
+ void hidden();
+ int getPlanet();
+ void pressOB(int);
+ void checkAirSupply(bool, int*);
+ void insertDisk(int);
+ void gameOver();
+ void inventory();
+ void randomize();
+ void flashScreen();
+ void intro();
+ void getItem(ENUM_MSA_ITEM);
+ void getXtal(int);
+ bool parse(int, int);
+ void gameLoop();
+ void debug_DrawObjs();
+ void debug_DrawPics();
+ void initVars();
+ void initEngine();
+ void flipSwitch();
+ void waitAnyKeyAnim();
+ void waitAnyKey(bool anim = false);
+};
+
+} // End of namespace Agi
+
+#endif
diff --git a/engines/agi/preagi_troll.cpp b/engines/agi/preagi_troll.cpp
new file mode 100644
index 0000000000..5136286768
--- /dev/null
+++ b/engines/agi/preagi_troll.cpp
@@ -0,0 +1,502 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#include "agi/preagi.h"
+#include "agi/preagi_common.h"
+#include "agi/preagi_troll.h"
+#include "agi/graphics.h"
+
+#include "graphics/cursorman.h"
+
+#include "common/events.h"
+
+namespace Agi {
+
+Troll::Troll(PreAgiEngine* vm) : _vm(vm) {
+}
+
+// User Interface
+
+void Troll::pressAnyKey() {
+ _vm->drawStr(24, 4, kColorDefault, IDS_TRO_PRESSANYKEY);
+ _vm->_gfx->doUpdate();
+ _vm->waitAnyKeyChoice();
+}
+
+void Troll::drawMenu(const char *szMenu, int iSel) {
+ _vm->clearTextArea();
+ _vm->drawStr(21, 0, kColorDefault, szMenu);
+ _vm->drawStr(22 + iSel, 0, kColorDefault, " *");
+ _vm->_gfx->doUpdate();
+}
+
+void Troll::getMenuSel(const char *szMenu, int *iSel, int nSel) {
+ Common::Event event;
+ int y;
+
+ drawMenu(szMenu, *iSel);
+
+ for (;;) {
+ while (_vm->_system->getEventManager()->pollEvent(event)) {
+ switch(event.type) {
+ case Common::EVENT_QUIT:
+ _vm->_system->quit();
+ case Common::EVENT_MOUSEMOVE:
+ y = event.mouse.y / 8;
+
+ if (y >= 22)
+ if (nSel > y - 22)
+ *iSel = y - 22;
+
+ drawMenu(szMenu, *iSel);
+ break;
+ case Common::EVENT_LBUTTONUP:
+ return;
+ case Common::EVENT_KEYDOWN:
+ switch (event.kbd.keycode) {
+ case Common::KEYCODE_t:
+ case Common::KEYCODE_f:
+ inventory();
+ *iSel = 0;
+ drawMenu(szMenu, *iSel);
+ break;
+ case Common::KEYCODE_SPACE:
+ *iSel += 1;
+
+ if (*iSel == nSel)
+ *iSel = IDI_TRO_SEL_OPTION_1;
+
+ drawMenu(szMenu, *iSel);
+ break;
+ case Common::KEYCODE_RETURN:
+ case Common::KEYCODE_KP_ENTER:
+ return;
+ default:
+ break;
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ _vm->_system->updateScreen();
+ _vm->_system->delayMillis(10);
+ }
+}
+
+// Graphics
+
+void Troll::drawPic(int iPic, bool f3IsCont, bool clear) {
+ uint8 frame[] = {
+ 0xf1, 0x3, 0xf9, 0x0, 0x0, 0x9f, 0x0, 0x9f, 0xa7, 0x0, 0xa7, 0x0, 0x0, 0xff
+ };
+
+ if (clear)
+ _vm->clearScreen(0x0f);
+
+ _vm->_picture->setDimensions(IDI_TRO_PIC_WIDTH, IDI_TRO_PIC_HEIGHT);
+
+ _vm->_picture->setPictureData(frame, ARRAYSIZE(frame));
+ _vm->_picture->drawPicture();
+
+ _vm->_picture->setPictureData(_gameData + _pictureOffsets[iPic], 4096);
+
+ if (f3IsCont)
+ _vm->_picture->setPictureFlags(kPicFf3Cont);
+ else
+ _vm->_picture->setPictureFlags(kPicFf3Stop);
+
+ _vm->_picture->drawPicture();
+
+ _vm->_picture->showPic();
+ _vm->_gfx->doUpdate();
+}
+
+// Game Logic
+
+void Troll::inventory() {
+ char szMissing[40];
+
+ _vm->clearScreen(0x07);
+ _vm->drawStr(1, 12, kColorDefault, IDS_TRO_TREASURE_0);
+ _vm->drawStr(2, 12, kColorDefault, IDS_TRO_TREASURE_1);
+
+ switch (_treasuresLeft) {
+ case 1:
+ sprintf(szMissing, IDS_TRO_TREASURE_5, _treasuresLeft);
+ _vm->drawStr(20, 10,kColorDefault, szMissing);
+ break;
+ case 0:
+ _vm->drawStr(20, 1, kColorDefault, IDS_TRO_TREASURE_6);
+ break;
+ case IDI_TRO_MAX_TREASURE:
+ _vm->drawStr(3, 17, kColorDefault, IDS_TRO_TREASURE_2);
+ default:
+ sprintf(szMissing, IDS_TRO_TREASURE_4, _treasuresLeft);
+ _vm->drawStr(20, 10,kColorDefault, szMissing);
+ break;
+ }
+
+ _vm->drawStr(24, 6, kColorDefault, IDS_TRO_PRESSANYKEY);
+ _vm->_gfx->doUpdate();
+ _vm->waitAnyKeyChoice();
+}
+
+void Troll::waitAnyKeyIntro() {
+ Common::Event event;
+ int iMsg = 0;
+
+ for (;;) {
+ while (_vm->_system->getEventManager()->pollEvent(event)) {
+ switch(event.type) {
+ case Common::EVENT_QUIT:
+ _vm->_system->quit();
+ case Common::EVENT_LBUTTONUP:
+ case Common::EVENT_KEYDOWN:
+ return;
+ default:
+ break;
+ }
+ }
+
+ switch (iMsg) {
+ case 200:
+ iMsg = 0;
+ case 0:
+ _vm->drawStr(22, 3, kColorDefault, IDS_TRO_INTRO_2);
+ _vm->_gfx->doUpdate();
+ break;
+ case 100:
+ _vm->drawStr(22, 3, kColorDefault, IDS_TRO_INTRO_3);
+ _vm->_gfx->doUpdate();
+ break;
+ }
+
+ iMsg++;
+
+ _vm->_system->updateScreen();
+ _vm->_system->delayMillis(10);
+ }
+}
+
+void Troll::credits() {
+ _vm->clearScreen(0x07);
+
+ _vm->drawStr(1, 2, kColorDefault, IDS_TRO_CREDITS_0);
+
+ int color = 10;
+ char str[2];
+
+ str[1] = 0;
+
+ for (uint i = 0; i < strlen(IDS_TRO_CREDITS_1); i++) {
+ str[0] = IDS_TRO_CREDITS_1[i];
+ _vm->drawStr(7, 19 + i, color++, str);
+ if (color > 15)
+ color = 9;
+ }
+
+ _vm->drawStr(8, 19, kColorDefault, IDS_TRO_CREDITS_2);
+
+ _vm->drawStr(13, 11, 9, IDS_TRO_CREDITS_3);
+ _vm->drawStr(15, 8, 10, IDS_TRO_CREDITS_4);
+ _vm->drawStr(17, 7, 12, IDS_TRO_CREDITS_5);
+ _vm->drawStr(19, 2, 14, IDS_TRO_CREDITS_6);
+
+ _vm->_gfx->doUpdate();
+
+ pressAnyKey();
+}
+
+void Troll::tutorial() {
+ bool done = false;
+ int iSel = 0;
+ //char szTreasure[16] = {0};
+
+ for (;;) {
+ _vm->clearScreen(0xFF);
+
+ _vm->printStr(IDS_TRO_TUTORIAL_0);
+ _vm->getSelection(kSelSpace);
+
+ _vm->clearScreen(0x55);
+ _vm->setDefaultTextColor(0x0F);
+
+ done = false;
+ while (!done) {
+ getMenuSel(IDS_TRO_TUTORIAL_1, &iSel, IDI_TRO_MAX_OPTION);
+ switch(iSel) {
+ case IDI_TRO_SEL_OPTION_1:
+ _vm->clearScreen(0x22, false);
+ _vm->_gfx->doUpdate();
+ break;
+ case IDI_TRO_SEL_OPTION_2:
+ _vm->clearScreen(0x00, false);
+ _vm->_gfx->doUpdate();
+ break;
+ case IDI_TRO_SEL_OPTION_3:
+ done = true;
+ break;
+ }
+ }
+
+ // do you need more practice ?
+ _vm->clearScreen(0x4F);
+ _vm->drawStr(7, 4, kColorDefault, IDS_TRO_TUTORIAL_5);
+ _vm->drawStr(9, 4, kColorDefault, IDS_TRO_TUTORIAL_6);
+ _vm->_gfx->doUpdate();
+
+ if (!_vm->getSelection(kSelYesNo))
+ break;
+ }
+
+ // show info texts
+ _vm->clearScreen(0x5F);
+ _vm->drawStr(4, 1, kColorDefault, IDS_TRO_TUTORIAL_7);
+ _vm->drawStr(5, 1, kColorDefault, IDS_TRO_TUTORIAL_8);
+ _vm->_gfx->doUpdate();
+ pressAnyKey();
+
+ _vm->clearScreen(0x2F);
+ _vm->drawStr(6, 1, kColorDefault, IDS_TRO_TUTORIAL_9);
+ _vm->_gfx->doUpdate();
+ pressAnyKey();
+
+ _vm->clearScreen(0x19);
+ _vm->drawStr(7, 1, kColorDefault, IDS_TRO_TUTORIAL_10);
+ _vm->drawStr(8, 1, kColorDefault, IDS_TRO_TUTORIAL_11);
+ _vm->_gfx->doUpdate();
+ pressAnyKey();
+
+ _vm->clearScreen(0x6E);
+ _vm->drawStr(9, 1, kColorDefault, IDS_TRO_TUTORIAL_12);
+ _vm->drawStr(10, 1, kColorDefault, IDS_TRO_TUTORIAL_13);
+ _vm->_gfx->doUpdate();
+ pressAnyKey();
+
+ _vm->clearScreen(0x4C);
+ _vm->drawStr(11, 1, kColorDefault, IDS_TRO_TUTORIAL_14);
+ _vm->drawStr(12, 1, kColorDefault, IDS_TRO_TUTORIAL_15);
+ _vm->_gfx->doUpdate();
+ pressAnyKey();
+
+ _vm->clearScreen(0x5D);
+ _vm->drawStr(13, 1, kColorDefault, IDS_TRO_TUTORIAL_16);
+ _vm->drawStr(14, 1, kColorDefault, IDS_TRO_TUTORIAL_17);
+ _vm->drawStr(15, 1, kColorDefault, IDS_TRO_TUTORIAL_18);
+ _vm->_gfx->doUpdate();
+ pressAnyKey();
+
+ // show treasures
+ _vm->clearScreen(0x2A);
+ _vm->drawStr(2, 1, kColorDefault, IDS_TRO_TUTORIAL_19);
+ for (int i = 0; i < IDI_TRO_MAX_TREASURE; i++)
+ _vm->drawStr(19 - i, 11, kColorDefault, (const char *)IDS_TRO_NAME_TREASURE[i]);
+
+ _vm->_gfx->doUpdate();
+
+ pressAnyKey();
+}
+
+void Troll::intro() {
+ // sierra on-line presents
+ _vm->clearScreen(0x2F);
+ _vm->drawStr(9, 10, kColorDefault, IDS_TRO_INTRO_0);
+ _vm->drawStr(14, 15, kColorDefault, IDS_TRO_INTRO_1);
+ _vm->_gfx->doUpdate();
+ _vm->_system->updateScreen();
+ _vm->_system->delayMillis(3200);
+
+ // Draw logo
+ drawPic(45, false, true);
+ _vm->_gfx->doUpdate();
+
+ // wait for keypress and alternate message
+ waitAnyKeyIntro();
+
+ // have you played this game before?
+ _vm->drawStr(22, 3, kColorDefault, IDS_TRO_INTRO_4);
+ _vm->drawStr(23, 6, kColorDefault, IDS_TRO_INTRO_5);
+ _vm->_gfx->doUpdate();
+
+ if (!_vm->getSelection(kSelYesNo))
+ tutorial();
+
+ credits();
+}
+
+void Troll::gameOver() {
+ char szMoves[40];
+
+ _vm->clearScreen(0x0f); // hack
+
+ _vm->clearTextArea();
+ //DrawPic(0);
+
+ _vm->clearTextArea();
+ //DrawPic(0);
+
+ sprintf(szMoves, IDS_TRO_GAMEOVER_0, _moves);
+ _vm->drawStr(21, 1, kColorDefault, szMoves);
+ _vm->drawStr(22, 1, kColorDefault, IDS_TRO_GAMEOVER_1);
+ _vm->_gfx->doUpdate();
+ pressAnyKey();
+}
+
+int Troll::drawRoom(char *menu) {
+ int n;
+
+ drawPic(_currentRoom - 1, false, true);
+ _vm->_gfx->doUpdate();
+
+ // TODO: Troll
+
+ char tmp[10];
+ strncat(menu, (char*)_gameData + IDO_TRO_LOCMESSAGES + _locationDescIndex * 39, 39);
+
+ for (int i = 0; i < 3; i++) {
+ if (_roomDescs[_currentRoom - 1].options[i]) {
+ sprintf(tmp, "\n %d.", i);
+ strcat(menu, tmp);
+
+ strncat(menu, (char *)_gameData + _options[_roomDescs[_currentRoom - 1].options[i]], 35);
+
+ n = i + 1;
+ }
+ }
+
+ return n;
+}
+
+void Troll::gameLoop() {
+ bool done = false;
+ char menu[160+5];
+ int currentOption, numberOfOptions;
+
+ _moves = 0;
+ _currentRoom = 1;
+ _treasuresLeft = IDI_TRO_MAX_TREASURE;
+ _haveFlashlight = false;
+ _locationDescIndex = 0;
+
+ while (!done) {
+ *menu = 0;
+
+ currentOption = 0;
+
+ numberOfOptions = drawRoom(menu);
+
+ getMenuSel(menu, &currentOption, numberOfOptions);
+ _moves++;
+
+ switch(_roomDescs[_currentRoom - 1].optionTypes[currentOption]) {
+ case IDI_TRO_SEL_OPTION_1:
+ break;
+ case IDI_TRO_SEL_OPTION_2:
+ break;
+ case IDI_TRO_SEL_OPTION_3:
+ break;
+ case OT_UNKN:
+ break;
+ }
+ }
+
+}
+
+void Troll::fillOffsets() {
+ int i;
+
+ for (i = 0; i < IDI_TRO_PICNUM; i++)
+ _pictureOffsets[i] = READ_LE_UINT16(_gameData + IDO_TRO_PIC_START + i * 2);
+
+ for (i = 0; i < IDI_TRO_NUM_OPTIONS; i++)
+ _options[i] = READ_LE_UINT16(_gameData + IDO_TRO_OPTIONS + i * 2);
+}
+
+void Troll::fillRoomDescs() {
+ int start = READ_LE_UINT16(_gameData + IDO_TRO_ROOMDESCS);
+ int ptr;
+ int j;
+
+ for (int i = 0; i < IDI_TRO_NUM_ROOMDESCS; i++) {
+ ptr = READ_LE_UINT16(_gameData + start);
+
+ for (j = 0; j < 3; j++)
+ _roomDescs[i].options[j] = _gameData[ptr++];
+
+ for (j = 0; j < 3; j++) {
+ switch (_gameData[ptr++]) {
+ case 0:
+ _roomDescs[i].optionTypes[j] = OT_GO;
+ break;
+ case 1:
+ _roomDescs[i].optionTypes[j] = OT_GET;
+ break;
+ case 2:
+ _roomDescs[i].optionTypes[j] = OT_WIN;
+ break;
+ case 3:
+ _roomDescs[i].optionTypes[j] = OT_UNKN;
+ break;
+ default:
+ error("Bad data @ (%x) %d", ptr - 1, i);
+ }
+ }
+
+ for (j = 0; j < 3; j++)
+ _roomDescs[i].roomDescIndex[j] = _gameData[ptr++];
+
+ start += 2;
+ }
+}
+
+// Init
+
+void Troll::init() {
+ _vm->_picture->setPictureVersion(AGIPIC_V15);
+ //SetScreenPar(320, 200, (char*)ibm_fontdata);
+
+ Common::File infile;
+ if (!infile.open(IDA_TRO_BINNAME))
+ return;
+
+ _gameData = (byte *)malloc(infile.size());
+ infile.seek(IDO_TRO_DATA_START);
+ infile.read(_gameData, infile.size() - IDO_TRO_DATA_START);
+ infile.close();
+
+ fillOffsets();
+ fillRoomDescs();
+}
+
+void Troll::run() {
+ intro();
+
+ gameLoop();
+
+ gameOver();
+}
+
+} // end of namespace Agi
diff --git a/engines/agi/preagi_troll.h b/engines/agi/preagi_troll.h
new file mode 100644
index 0000000000..ef458afb41
--- /dev/null
+++ b/engines/agi/preagi_troll.h
@@ -0,0 +1,197 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#ifndef AGI_PREAGI_TROLL_H
+#define AGI_PREAGI_TROLL_H
+
+#include "agi/agi.h"
+
+namespace Agi {
+
+// strings
+
+#define IDS_TRO_DISK "ERROR ERROR !"
+#define IDS_TRO_PATH_PIC "%s"
+
+#define IDS_TRO_PRESSANYKEY "PRESS ANY KEY TO CONTINUE:"
+
+#define IDS_TRO_INTRO_0 "SIERRA ON-LINE INC."
+#define IDS_TRO_INTRO_1 "Presents :"
+#define IDS_TRO_INTRO_2 "Copyright 1984 Sierra On-Line Inc."
+#define IDS_TRO_INTRO_3 " Press any key to continue. "
+#define IDS_TRO_INTRO_4 "HAVE YOU PLAYED THIS GAME BEFORE ?"
+#define IDS_TRO_INTRO_5 "PRESS <Y> OR <N>"
+
+#define IDS_TRO_TUTORIAL_0 " First press the <space bar>.\n 1. Turn the screen GREEN.\n 2. Turn the screen BLACK.\n *3. SEE a SURPRISE, and then more."
+#define IDS_TRO_TUTORIAL_1 " Press <return> to make your choice.\n 1. Turn the screen GREEN.\n 2. Turn the screen BLACK.\n 3. SEE a SURPRISE, and then more."
+//#define IDS_TRO_TUTORIAL_0 "First press the <space bar>."
+//#define IDS_TRO_TUTORIAL_1 "1. Turn the screen GREEN."
+//#define IDS_TRO_TUTORIAL_2 "2. Turn the screen BLACK."
+//#define IDS_TRO_TUTORIAL_3 "3. SEE a SURPRISE, and then more."
+//#define IDS_TRO_TUTORIAL_4 "Press <return> to make your choice."
+#define IDS_TRO_TUTORIAL_5 "Would you like more practice ?"
+#define IDS_TRO_TUTORIAL_6 "Press <Y> for yes, <N> for no."
+#define IDS_TRO_TUTORIAL_7 "The evil TROLL has hidden all the"
+#define IDS_TRO_TUTORIAL_8 "Treasures of MARK, the Dwarf King."
+#define IDS_TRO_TUTORIAL_9 "Help KING MARK find his Treasures."
+#define IDS_TRO_TUTORIAL_10 "You can't take a Treasure if the TROLL"
+#define IDS_TRO_TUTORIAL_11 "is in the same picture as the Treasure."
+#define IDS_TRO_TUTORIAL_12 "To make the TROLL go away you have to"
+#define IDS_TRO_TUTORIAL_13 "make the picture change."
+#define IDS_TRO_TUTORIAL_14 "During the game see the Treasures you"
+#define IDS_TRO_TUTORIAL_15 "have already found by pressing <F>."
+#define IDS_TRO_TUTORIAL_16 "During the game you can turn the sound"
+#define IDS_TRO_TUTORIAL_17 "on or off by pressing the <S> key "
+#define IDS_TRO_TUTORIAL_18 "while holding down the <Ctrl> key."
+#define IDS_TRO_TUTORIAL_19 "The TROLL has hidden these Treasures:"
+
+#define IDS_TRO_CREDITS_0 "Prepare to enter the world of . . ."
+#define IDS_TRO_CREDITS_1 "TROLL'S TALE (tm)"
+#define IDS_TRO_CREDITS_2 "------------"
+#define IDS_TRO_CREDITS_3 "Written by MIKE MACCHESNEY"
+#define IDS_TRO_CREDITS_4 "Conversion by PETER OLIPHANT"
+#define IDS_TRO_CREDITS_5 "Graphic Art by DOUG MACNEILL"
+#define IDS_TRO_CREDITS_6 "Original Version by AL LOWE"
+
+#define IDS_TRO_TREASURE_0 "TREASURES FOUND"
+#define IDS_TRO_TREASURE_1 "---------------"
+#define IDS_TRO_TREASURE_2 "NONE"
+#define IDS_TRO_TREASURE_3 "THERE ARE STILL"
+#define IDS_TRO_TREASURE_4 "%d TREASURES TO FIND"
+#define IDS_TRO_TREASURE_5 "%d TREASURE TO FIND"
+#define IDS_TRO_TREASURE_6 "YOU HAVE FOUND ALL OF THE TREASURES!!"
+#define IDS_TRO_TREASURE_7 "THERE'S ONLY ONE MORE TREASURE TO FIND."
+#define IDS_TRO_TREASURE_8 "GREAT!! YOU HAVE FOUND EVERY TREASURE."
+#define IDS_TRO_TREASURE_9 "TAKE THE TREASURES TO THE GUARD."
+
+#define IDS_TRO_GAMEOVER_0 "You took %d moves to complete TROLL'S"
+#define IDS_TRO_GAMEOVER_1 "TALE. Do you think you can do better?"
+
+const char IDS_TRO_NAME_TREASURE[][16] = {
+ " FLASHLIGHT ", " BAG OF GOLD ", " BOX OF JEWELS ", " DIAMOND RING ",
+ " CANDY SUCKER ", "DOLLAR AND CENT", " FIDDLE ", "BAG OF PENNIES ",
+ " TREASURE CHEST", " PENNY ", " SILVER CUP ", " NECKLACE ",
+ " SHELL ", " GOLD BRICK ", " GIFT ", " POT OF MONEY "
+};
+
+// picture
+
+#define IDI_TRO_PICNUM 47
+
+#define IDI_TRO_PIC_WIDTH 160
+#define IDI_TRO_PIC_HEIGHT 168
+#define IDI_TRO_PIC_X0 0
+#define IDI_TRO_PIC_Y0 0
+#define IDI_TRO_PIC_FLAGS IDF_AGI_PIC_V15
+
+// max values
+
+#define IDI_TRO_MAX_TREASURE 16
+#define IDI_TRO_MAX_OPTION 3
+
+#define IDI_TRO_SEL_OPTION_1 0
+#define IDI_TRO_SEL_OPTION_2 1
+#define IDI_TRO_SEL_OPTION_3 2
+
+#define IDI_TRO_MAX_ROW_PIC 21
+
+#define IDI_TRO_NUM_ROOMDESCS 65
+#define IDI_TRO_NUM_OPTIONS 129
+
+// offsets
+
+#define IDA_TRO_BINNAME "troll.exe"
+
+#define IDO_TRO_DATA_START 0x1960
+#define IDO_TRO_PIC_START 0x3EF5
+#define IDO_TRO_LOCMESSAGES 0x1F7C
+#define IDO_TRO_ROOMDESCS 0x0082
+#define IDO_TRO_OPTIONS 0x0364
+
+enum OptionType {
+ OT_GO,
+ OT_GET,
+ OT_WIN,
+ OT_UNKN
+};
+
+struct RoomDesc {
+ int options[3];
+ OptionType optionTypes[3];
+ int roomDescIndex[3];
+};
+
+class Troll {
+ friend class PreAgiEngine;
+public:
+ Troll(PreAgiEngine *vm);
+
+ void init();
+ void run();
+
+private:
+ int _currentRoom;
+ int _moves;
+ int _treasuresLeft;
+ int _locationDescIndex;
+ int _numberOfOptions;
+
+ bool _haveFlashlight;
+
+ RoomDesc _roomDescs[IDI_TRO_NUM_ROOMDESCS];
+ int _options[IDI_TRO_NUM_OPTIONS];
+
+ byte *_gameData;
+
+ PreAgiEngine *_vm;
+
+ void intro();
+ void drawPic(int iPic, bool f3IsCont, bool clear);
+ void gameLoop();
+ void gameOver();
+ void tutorial();
+ void credits();
+
+ void inventory();
+
+ int drawRoom(char *menu);
+
+ void pressAnyKey();
+ void waitAnyKeyIntro();
+
+ void getMenuSel(const char*, int*, int);
+
+ void drawMenu(const char *szMenu, int iSel);
+
+ void fillOffsets();
+ void fillRoomDescs();
+
+private:
+ int _pictureOffsets[IDI_TRO_PICNUM];
+};
+
+} // End of namespace Agi
+
+#endif
diff --git a/engines/agi/preagi_winnie.cpp b/engines/agi/preagi_winnie.cpp
new file mode 100644
index 0000000000..8d60f0861e
--- /dev/null
+++ b/engines/agi/preagi_winnie.cpp
@@ -0,0 +1,1127 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#include "agi/preagi.h"
+#include "agi/preagi_winnie.h"
+#include "agi/graphics.h"
+
+#include "graphics/cursorman.h"
+
+#include "common/events.h"
+#include "common/savefile.h"
+
+namespace Agi {
+
+// default attributes
+#define IDA_DEFAULT 0x0F
+#define IDA_DEFAULT_REV 0xF0
+
+void Winnie::initEngine() {
+ //SetScreenPar(320, 200, (char*)ibm_fontdata);
+ //SetMenuPars(21, 21, IDS_WTP_SELECTION);
+}
+
+void Winnie::initVars() {
+ memset(&game, 0, sizeof(game));
+ game.fSound = 1;
+ game.nObjMiss = IDI_WTP_MAX_OBJ_MISSING;
+ game.nObjRet = 0;
+ game.fGame[0] = 1;
+ game.fGame[1] = 1;
+ room = IDI_WTP_ROOM_HOME;
+
+ mist = -1;
+ doWind = false;
+ winnie_event = false;
+}
+
+void Winnie::readRoom(int iRoom, uint8 *buffer, int buflen) {
+ char szFile[256] = {0};
+ sprintf(szFile, IDS_WTP_PATH_ROOM, iRoom);
+ Common::File file;
+ if (!file.open(szFile))
+ return;
+ uint32 filelen = file.size();
+ memset(buffer, 0, sizeof(buffer));
+ file.read(buffer, filelen);
+ file.close();
+}
+
+void Winnie::readObj(int iObj, uint8 *buffer, int buflen) {
+ char szFile[256] = {0};
+ sprintf(szFile, IDS_WTP_PATH_OBJ, iObj);
+ Common::File file;
+ if (!file.open(szFile))
+ return;
+ uint32 filelen = file.size();
+ memset(buffer, 0, sizeof(buffer));
+ file.read(buffer, filelen);
+ file.close();
+}
+
+void Winnie::randomize() {
+ int iObj = 0;
+ int iRoom = 0;
+ bool done;
+
+ for (int i = 0; i < IDI_WTP_MAX_OBJ_MISSING; i++) {
+ done = false;
+ while (!done) {
+ iObj = _vm->rnd(IDI_WTP_MAX_OBJ - 1) + 2;
+ done = true;
+ for (int j = 0; j < IDI_WTP_MAX_OBJ_MISSING; j++) {
+ if (game.iUsedObj[j] == iObj) {
+ done = false;
+ break;
+ }
+ }
+ }
+
+ game.iUsedObj[i] = iObj;
+
+ done = false;
+ while (!done) {
+ iRoom = _vm->rnd(IDI_WTP_MAX_ROOM_NORMAL) + 1;
+ done = true;
+ for (int j = 0; j < IDI_WTP_MAX_ROOM_OBJ; j++) {
+ if (game.iObjRoom[j] == iRoom) {
+ done = false;
+ break;
+ }
+ }
+ }
+
+ game.iObjRoom[iObj] = iRoom;
+ }
+}
+
+void Winnie::intro() {
+ drawPic(IDS_WTP_FILE_LOGO);
+ _vm->printStr(IDS_WTP_INTRO_0);
+ _vm->_system->delayMillis(0x640);
+ drawPic(IDS_WTP_FILE_TITLE);
+ _vm->printStr(IDS_WTP_INTRO_1);
+ _vm->_system->delayMillis(0x640);
+ //if (!Winnie_PlaySound(IDI_WTP_SND_POOH_0)) return;
+ //if (!Winnie_PlaySound(IDI_WTP_SND_POOH_1)) return;
+ //if (!Winnie_PlaySound(IDI_WTP_SND_POOH_2)) return;
+}
+
+int Winnie::getObjInRoom(int iRoom) {
+ for (int iObj = 1; iObj < IDI_WTP_MAX_ROOM_OBJ; iObj++)
+ if (game.iObjRoom[iObj] == iRoom)
+ return iObj;
+ return 0;
+}
+
+#define setTakeDrop() {\
+ if (getObjInRoom(room))\
+ fCanSel[IDI_WTP_SEL_TAKE] = true;\
+ else\
+ fCanSel[IDI_WTP_SEL_TAKE] = false;\
+ if (game.iObjHave)\
+ fCanSel[IDI_WTP_SEL_DROP] = true;\
+ else\
+ fCanSel[IDI_WTP_SEL_DROP] = false;\
+}
+
+void Winnie::setFlag(int iFlag) {
+ game.fGame[iFlag] = 1;
+}
+
+void Winnie::clearFlag(int iFlag) {
+ game.fGame[iFlag] = 0;
+}
+
+int Winnie::parser(int pc, int index, uint8 *buffer) {
+ WTP_ROOM_HDR hdr;
+ int startpc = pc;
+ int8 opcode;
+ int iNewRoom = 0;
+
+ int iSel, iDir, iBlock;
+ int fCanSel[IDI_WTP_SEL_LAST + 1];
+ char szMenu[121] = {0};
+ bool done;
+ int fBlock;
+
+ // extract header from buffer
+ memcpy(&hdr, buffer, sizeof(WTP_ROOM_HDR));
+
+ for (;;) {
+ pc = startpc;
+
+ // check if block is to be run
+
+ iBlock = *(buffer + pc++);
+ if (iBlock == 0)
+ return IDI_WTP_PAR_OK;
+
+ fBlock = *(buffer + pc++);
+ if (game.fGame[iBlock] != fBlock)
+ return IDI_WTP_PAR_OK;
+
+ // extract text from block
+
+ opcode = *(buffer + pc);
+ switch(opcode) {
+ case 0:
+ case IDO_WTP_OPTION_0:
+ case IDO_WTP_OPTION_1:
+ case IDO_WTP_OPTION_2:
+ // clear fCanSel block
+ memset(fCanSel, 0, sizeof(fCanSel));
+
+ // check if NSEW directions should be displayed
+ if (hdr.roomNew[0])
+ fCanSel[IDI_WTP_SEL_NORTH] = fCanSel[IDI_WTP_SEL_SOUTH] =
+ fCanSel[IDI_WTP_SEL_EAST] = fCanSel[IDI_WTP_SEL_WEST] = true;
+
+ // check if object in room or player carrying one
+ setTakeDrop();
+
+ // check which rows have a menu option
+ for (iSel = 0; iSel < IDI_WTP_MAX_OPTION; iSel++) {
+ opcode = *(buffer + pc++);
+ if (opcode) {
+ fCanSel[opcode - IDO_WTP_OPTION_0] = true;
+ fCanSel[iSel + IDI_WTP_SEL_REAL_OPT_1] = opcode - 0x14;
+ }
+ }
+
+ // extract menu string
+ strcpy(szMenu, (char *)(buffer + pc));
+ _vm->XOR80(szMenu);
+ break;
+ default:
+ // print description
+ _vm->printStrXOR((char *)(buffer + pc));
+ if (getSelOkBack())
+ return IDI_WTP_PAR_OK;
+ else
+ return IDI_WTP_PAR_BACK;
+ }
+
+ // input handler
+
+ done = false;
+ while (!done) {
+ // run wind if it's time
+ if (doWind)
+ wind();
+
+ // get menu selection
+ getMenuSel(szMenu, &iSel, fCanSel);
+
+ if (++game.nMoves == IDI_WTP_MAX_MOVES_UNTIL_WIND)
+ doWind = true;
+
+ if (winnie_event && (room <= IDI_WTP_MAX_ROOM_TELEPORT)) {
+ if (!tigger_mist) {
+ tigger_mist = 1;
+ //Winnie_Tigger();
+ } else {
+ tigger_mist = 0;
+ //Winnie_Mist();
+ }
+ winnie_event = false;
+ return IDI_WTP_PAR_GOTO;
+ }
+
+ // process selection
+ switch(iSel) {
+ case IDI_WTP_SEL_HOME:
+ switch(room) {
+ case IDI_WTP_ROOM_HOME:
+ case IDI_WTP_ROOM_MIST:
+ case IDI_WTP_ROOM_TIGGER:
+ break;
+ default:
+ room = IDI_WTP_ROOM_HOME;
+ return IDI_WTP_PAR_GOTO;
+ }
+ break;
+ case IDI_WTP_SEL_BACK:
+ return IDI_WTP_PAR_BACK;
+ case IDI_WTP_SEL_OPT_1:
+ case IDI_WTP_SEL_OPT_2:
+ case IDI_WTP_SEL_OPT_3:
+ done = true;
+ break;
+ case IDI_WTP_SEL_NORTH:
+ case IDI_WTP_SEL_SOUTH:
+ case IDI_WTP_SEL_EAST:
+ case IDI_WTP_SEL_WEST:
+ iDir = iSel - IDI_WTP_SEL_NORTH;
+ if (hdr.roomNew[iDir] == IDI_WTP_ROOM_NONE) {
+ _vm->printStr(IDS_WTP_CANT_GO);
+ _vm->waitAnyKeyChoice();
+ } else {
+ room = hdr.roomNew[iDir];
+ return IDI_WTP_PAR_GOTO;
+ }
+ break;
+ case IDI_WTP_SEL_TAKE:
+ takeObj(room);
+ setTakeDrop();
+ break;
+ case IDI_WTP_SEL_DROP:
+ dropObj(room);
+ setTakeDrop();
+ break;
+ }
+ }
+
+ // jump to the script block of the selected option
+ pc = hdr.opt[index].ofsOpt[iSel] - IDI_WTP_OFS_ROOM;
+ opcode = *(buffer + pc);
+ if (!opcode) pc++;
+
+ // process script
+ do {
+ opcode = *(buffer + pc++);
+ switch(opcode) {
+ case IDO_WTP_GOTO_ROOM:
+ opcode = *(buffer + pc++);
+ iNewRoom = opcode;
+ break;
+ case IDO_WTP_PRINT_MSG:
+ opcode = *(buffer + pc++);
+ printRoomStr(room, opcode);
+ _vm->waitAnyKeyChoice();
+ break;
+ case IDO_WTP_PRINT_STR:
+ opcode = *(buffer + pc++);
+ printRoomStr(room, opcode);
+ break;
+ case IDO_WTP_DROP_OBJ:
+ opcode = *(buffer + pc++);
+ opcode = -1;
+ dropObjRnd();
+ break;
+ case IDO_WTP_FLAG_CLEAR:
+ opcode = *(buffer + pc++);
+ clearFlag(opcode);
+ break;
+ case IDO_WTP_FLAG_SET:
+ opcode = *(buffer + pc++);
+ setFlag(opcode);
+ break;
+ case IDO_WTP_GAME_OVER:
+ gameOver();
+ break;
+ case IDO_WTP_WALK_MIST:
+ mist--;
+ if (!mist) {
+ room = _vm->rnd(IDI_WTP_MAX_ROOM_TELEPORT) + 1;
+ return IDI_WTP_PAR_GOTO;
+ }
+ break;
+ case IDO_WTP_PLAY_SOUND:
+ opcode = *(buffer + pc++);
+ //Winnie_PlaySound((ENUM_WTP_SOUND)opcode);
+ break;
+ case IDO_WTP_SAVE_GAME:
+ saveGame();
+ room = IDI_WTP_ROOM_HOME;
+ return IDI_WTP_PAR_GOTO;
+ case IDO_WTP_LOAD_GAME:
+ loadGame();
+ room = IDI_WTP_ROOM_HOME;
+ return IDI_WTP_PAR_GOTO;
+ case IDO_WTP_OWL_HELP:
+ opcode = *(buffer + pc++);
+ showOwlHelp();
+ break;
+ case IDO_WTP_GOTO_RND:
+ room = _vm->rnd(IDI_WTP_MAX_ROOM_TELEPORT) + 1;
+ return IDI_WTP_PAR_GOTO;
+ default:
+ opcode = 0;
+ break;
+ }
+ } while (opcode);
+
+ if (iNewRoom) {
+ room = iNewRoom;
+ return IDI_WTP_PAR_GOTO;
+ }
+
+ if (iBlock == 1)
+ return IDI_WTP_PAR_OK;
+ }
+}
+
+void Winnie::keyHelp() {
+ //Winnie_PlaySound(IDI_WTP_SND_KEYHELP);
+ _vm->printStr(IDS_WTP_HELP_0);
+ _vm->waitAnyKeyChoice();
+ _vm->printStr(IDS_WTP_HELP_1);
+ _vm->waitAnyKeyChoice();
+}
+
+void Winnie::inventory() {
+ char szMissing[41] = {0};
+
+ if (game.iObjHave)
+ printObjStr(game.iObjHave, IDI_WTP_OBJ_TAKE);
+ else {
+ _vm->clearTextArea();
+ _vm->drawStr(IDI_WTP_ROW_MENU, IDI_WTP_COL_MENU, IDA_DEFAULT, IDS_WTP_INVENTORY_0);
+ }
+
+ sprintf(szMissing, IDS_WTP_INVENTORY_1, game.nObjMiss);
+ _vm->drawStr(IDI_WTP_ROW_OPTION_4, IDI_WTP_COL_MENU, IDA_DEFAULT, szMissing);
+ _vm->_gfx->doUpdate();
+ _vm->_system->updateScreen();
+ _vm->waitAnyKeyChoice();
+}
+
+void Winnie::printObjStr(int iObj, int iStr) {
+ WTP_OBJ_HDR hdr;
+ uint8 *buffer = (uint8 *)malloc(2048);
+
+ readObj(iObj, buffer, 2048);
+ memcpy(&hdr, buffer, sizeof(hdr));
+ _vm->printStrXOR((char *)(buffer + hdr.ofsStr[iStr] - IDI_WTP_OFS_OBJ));
+
+ free(buffer);
+}
+
+bool Winnie::isRightObj(int iRoom, int iObj, int *iCode) {
+ WTP_ROOM_HDR roomhdr;
+ WTP_OBJ_HDR objhdr;
+ uint8 *roomdata = new uint8[4096];
+ uint8 *objdata = new uint8[2048];
+
+ readRoom(iRoom, roomdata, 4096);
+ memcpy(&roomhdr, roomdata, sizeof(WTP_ROOM_HDR));
+ readObj(iObj, objdata, 2048);
+ memcpy(&objhdr, objdata, sizeof(WTP_OBJ_HDR));
+
+ delete [] roomdata;
+ delete [] objdata;
+
+ *iCode = objhdr.objId;
+
+ if (objhdr.objId == 11) objhdr.objId = 34;
+
+ if (roomhdr.objId == objhdr.objId)
+ return true;
+ else
+ return false;
+}
+
+void Winnie::takeObj(int iRoom) {
+ if (game.iObjHave) {
+ // player is already carrying an object, can't take
+ _vm->printStr(IDS_WTP_CANT_TAKE);
+ _vm->waitAnyKeyChoice();
+ } else {
+ // take object
+ int iObj = getObjInRoom(iRoom);
+ game.iObjHave = iObj;
+ game.iObjRoom[iObj] = 0;
+
+ _vm->printStr(IDS_WTP_OK);
+ //Winnie_PlaySound(IDI_WTP_SND_TAKE);
+
+ drawRoomPic();
+
+ // print object "take" string
+ printObjStr(game.iObjHave, IDI_WTP_OBJ_TAKE);
+ _vm->waitAnyKeyChoice();
+
+ // HACK WARNING
+ if (iObj == 18) {
+ game.fGame[0x0d] = 1;
+ }
+ }
+}
+
+void Winnie::dropObj(int iRoom) {
+ int iCode;
+
+ if (getObjInRoom(iRoom)) {
+ // there already is an object in the room, can't drop
+ _vm->printStr(IDS_WTP_CANT_DROP);
+ _vm->waitAnyKeyChoice();
+ } else {
+ // HACK WARNING
+ if (game.iObjHave == 18) {
+ game.fGame[0x0d] = 0;
+ }
+
+ if (isRightObj(iRoom, game.iObjHave, &iCode)) {
+ // object has been dropped in the right place
+ _vm->printStr(IDS_WTP_OK);
+ _vm->waitAnyKeyChoice();
+ //Winnie_PlaySound(IDI_WTP_SND_DROP_OK);
+ printObjStr(game.iObjHave, IDI_WTP_OBJ_DROP);
+ _vm->waitAnyKeyChoice();
+
+ // increase amount of objects returned, decrease amount of objects missing
+ game.nObjMiss--;
+ game.nObjRet++;
+
+ // xor the dropped object with 0x80 to signify it has been dropped in the right place
+ for (int i = 0; i < IDI_WTP_MAX_OBJ_MISSING; i++) {
+ if (game.iUsedObj[i] == game.iObjHave) {
+ game.iUsedObj[i] ^= 0x80;
+ break;
+ }
+ }
+
+ // set flag according to dropped object's id
+ game.fGame[iCode] = 1;
+
+ // player is carrying nothing
+ game.iObjHave = 0;
+
+ if (!game.nObjMiss) {
+ // all objects returned, tell player to find party
+ //Winnie_PlaySound(IDI_WTP_SND_FANFARE);
+ _vm->printStr(IDS_WTP_GAME_OVER_0);
+ _vm->waitAnyKeyChoice();
+ _vm->printStr(IDS_WTP_GAME_OVER_1);
+ _vm->waitAnyKeyChoice();
+ }
+ } else {
+ // drop object in the given room
+ game.iObjRoom[game.iObjHave] = iRoom;
+
+ // object has been dropped in the wrong place
+ _vm->printStr(IDS_WTP_WRONG_PLACE);
+ _vm->waitAnyKeyChoice();
+ //Winnie_PlaySound(IDI_WTP_SND_DROP);
+ drawRoomPic();
+ _vm->printStr(IDS_WTP_WRONG_PLACE);
+ _vm->waitAnyKeyChoice();
+
+ // print object description
+ printObjStr(game.iObjHave, IDI_WTP_OBJ_DESC);
+ _vm->waitAnyKeyChoice();
+
+ game.iObjHave = 0;
+ }
+ }
+}
+
+void Winnie::dropObjRnd() {
+ if (!game.iObjHave)
+ return;
+
+ int iRoom = 0;
+ bool done = false;
+
+ while (!done) {
+ iRoom = _vm->rnd(IDI_WTP_MAX_ROOM_NORMAL);
+ done = true;
+ if (iRoom == room)
+ done = false;
+ for (int j = 0; j < IDI_WTP_MAX_ROOM_OBJ; j++) {
+ if (game.iObjRoom[j] == iRoom) {
+ done = false;
+ }
+ }
+ }
+
+ game.iObjRoom[game.iObjHave] = iRoom;
+ game.iObjHave = 0;
+}
+
+void Winnie::wind() {
+ int iRoom = 0;
+ bool done;
+
+ doWind = 0;
+ game.nMoves = 0;
+ if (!game.nObjMiss)
+ return;
+
+ _vm->printStr(IDS_WTP_WIND_0);
+ //Winnie_PlaySound(IDI_WTP_SND_WIND_0);
+ _vm->waitAnyKeyChoice();
+ _vm->printStr(IDS_WTP_WIND_1);
+ //Winnie_PlaySound(IDI_WTP_SND_WIND_0);
+ _vm->waitAnyKeyChoice();
+
+ dropObjRnd();
+
+ // randomize positions of objects at large
+ for (int i = 0; i < IDI_WTP_MAX_OBJ_MISSING; i++) {
+ if (!(game.iUsedObj[i] & IDI_XOR_KEY)) {
+ done = false;
+ while (!done) {
+ iRoom = _vm->rnd(IDI_WTP_MAX_ROOM_NORMAL);
+ done = true;
+ for (int j = 0; j < IDI_WTP_MAX_ROOM_OBJ; j++) {
+ if (game.iObjRoom[j] == iRoom) {
+ done = false;
+ }
+ }
+ }
+ game.iObjRoom[game.iUsedObj[i]] = iRoom;
+ }
+ }
+}
+
+void Winnie::showOwlHelp() {
+ if (game.iObjHave) {
+ _vm->printStr(IDS_WTP_OWL_0);
+ _vm->waitAnyKeyChoice();
+ printObjStr(game.iObjHave, IDI_WTP_OBJ_HELP);
+ _vm->waitAnyKeyChoice();
+ }
+ if (getObjInRoom(room)) {
+ _vm->printStr(IDS_WTP_OWL_0);
+ _vm->waitAnyKeyChoice();
+ printObjStr(getObjInRoom(room), IDI_WTP_OBJ_HELP);
+ _vm->waitAnyKeyChoice();
+ }
+}
+
+
+void Winnie::drawMenu(char *szMenu, int iSel, int fCanSel[]) {
+ int iRow = 0, iCol = 0;
+
+ _vm->clearTextArea();
+ _vm->drawStr(IDI_WTP_ROW_MENU, IDI_WTP_COL_MENU, IDA_DEFAULT, szMenu);
+
+ if (fCanSel[IDI_WTP_SEL_NORTH])
+ _vm->drawStr(IDI_WTP_ROW_OPTION_4, IDI_WTP_COL_NSEW, IDA_DEFAULT, IDS_WTP_NSEW);
+ if (fCanSel[IDI_WTP_SEL_TAKE])
+ _vm->drawStr(IDI_WTP_ROW_OPTION_4, IDI_WTP_COL_TAKE, IDA_DEFAULT, IDS_WTP_TAKE);
+ if (fCanSel[IDI_WTP_SEL_DROP])
+ _vm->drawStr(IDI_WTP_ROW_OPTION_4, IDI_WTP_COL_DROP, IDA_DEFAULT, IDS_WTP_DROP);
+
+ switch(iSel) {
+ case IDI_WTP_SEL_OPT_1:
+ iRow = IDI_WTP_ROW_OPTION_1;
+ iCol = IDI_WTP_COL_OPTION;
+ break;
+ case IDI_WTP_SEL_OPT_2:
+ iRow = IDI_WTP_ROW_OPTION_2;
+ iCol = IDI_WTP_COL_OPTION;
+ break;
+ case IDI_WTP_SEL_OPT_3:
+ iRow = IDI_WTP_ROW_OPTION_3;
+ iCol = IDI_WTP_COL_OPTION;
+ break;
+ case IDI_WTP_SEL_NORTH:
+ iRow = IDI_WTP_ROW_OPTION_4;
+ iCol = IDI_WTP_COL_NORTH;
+ break;
+ case IDI_WTP_SEL_SOUTH:
+ iRow = IDI_WTP_ROW_OPTION_4;
+ iCol = IDI_WTP_COL_SOUTH;
+ break;
+ case IDI_WTP_SEL_EAST:
+ iRow = IDI_WTP_ROW_OPTION_4;
+ iCol = IDI_WTP_COL_EAST;
+ break;
+ case IDI_WTP_SEL_WEST:
+ iRow = IDI_WTP_ROW_OPTION_4;
+ iCol = IDI_WTP_COL_WEST;
+ break;
+ case IDI_WTP_SEL_TAKE:
+ iRow = IDI_WTP_ROW_OPTION_4;
+ iCol = IDI_WTP_COL_TAKE;
+ break;
+ case IDI_WTP_SEL_DROP:
+ iRow = IDI_WTP_ROW_OPTION_4;
+ iCol = IDI_WTP_COL_DROP;
+ break;
+ }
+ _vm->drawStr(iRow, iCol - 1, IDA_DEFAULT, IDS_WTP_SELECTION);
+ _vm->_gfx->doUpdate();
+ _vm->_system->updateScreen(); // TODO: this should go in the game's main loop
+}
+
+void Winnie::incMenuSel(int *iSel, int fCanSel[]) {
+ do {
+ *iSel += 1;
+ if (*iSel > IDI_WTP_SEL_DROP) *iSel = IDI_WTP_SEL_OPT_1;
+ } while(!fCanSel[*iSel]);
+}
+
+void Winnie::decMenuSel(int *iSel, int fCanSel[]) {
+ do {
+ *iSel -= 1;
+ if (*iSel < IDI_WTP_SEL_OPT_1) *iSel = IDI_WTP_SEL_DROP;
+ } while(!fCanSel[*iSel]);
+}
+
+void Winnie::getMenuMouseSel(int *iSel, int fCanSel[], int x, int y) {
+ switch(y) {
+ case IDI_WTP_ROW_OPTION_1:
+ if (fCanSel[IDI_WTP_SEL_OPT_1]) *iSel = IDI_WTP_SEL_OPT_1;
+ break;
+ case IDI_WTP_ROW_OPTION_2:
+ if (fCanSel[IDI_WTP_SEL_OPT_2]) *iSel = IDI_WTP_SEL_OPT_2;
+ break;
+ case IDI_WTP_ROW_OPTION_3:
+ if (fCanSel[IDI_WTP_SEL_OPT_3]) *iSel = IDI_WTP_SEL_OPT_3;
+ break;
+ case IDI_WTP_ROW_OPTION_4:
+ if (fCanSel[IDI_WTP_SEL_NORTH] && (x > IDI_WTP_COL_NORTH - 1) && (x < 6)) *iSel = IDI_WTP_SEL_NORTH;
+ if (fCanSel[IDI_WTP_SEL_SOUTH] && (x > IDI_WTP_COL_SOUTH - 1) && (x < 13)) *iSel = IDI_WTP_SEL_SOUTH;
+ if (fCanSel[IDI_WTP_SEL_EAST] && (x > IDI_WTP_COL_EAST - 1) && (x < 19)) *iSel = IDI_WTP_SEL_EAST;
+ if (fCanSel[IDI_WTP_SEL_WEST] && (x > IDI_WTP_COL_WEST - 1) && (x < 25)) *iSel = IDI_WTP_SEL_WEST;
+ if (fCanSel[IDI_WTP_SEL_TAKE] && (x > IDI_WTP_COL_TAKE - 1) && (x < 33)) *iSel = IDI_WTP_SEL_TAKE;
+ if (fCanSel[IDI_WTP_SEL_DROP] && (x > IDI_WTP_COL_DROP - 1) && (x < 39)) *iSel = IDI_WTP_SEL_DROP;
+ break;
+ }
+}
+
+#define makeSel() {\
+ if (fCanSel[*iSel]) {\
+ return;\
+ } else {\
+ keyHelp();\
+ clrMenuSel(iSel, fCanSel);\
+ }\
+}
+
+void Winnie::getMenuSel(char *szMenu, int *iSel, int fCanSel[]) {
+ Common::Event event;
+ int x, y;
+
+ clrMenuSel(iSel, fCanSel);
+ drawMenu(szMenu, *iSel, fCanSel);
+
+ // Show the mouse cursor for the menu
+ CursorMan.showMouse(true);
+
+ for (;;) {
+ // check if tigger/mist is to be triggered
+// if (something)
+// event = true;
+
+ while (_vm->_system->getEventManager()->pollEvent(event)) {
+ switch(event.type) {
+ case Common::EVENT_QUIT:
+ _vm->_system->quit();
+ break;
+ case Common::EVENT_MOUSEMOVE:
+ x = event.mouse.x / 8;
+ y = event.mouse.y / 8;
+ getMenuMouseSel(iSel, fCanSel, x, y);
+
+ // Change cursor
+ if (fCanSel[IDI_WTP_SEL_NORTH] && (event.mouse.x >= 20 && event.mouse.x <= (IDI_WTP_PIC_WIDTH + 10) * 2) &&
+ (event.mouse.y >= 0 && event.mouse.y <= 10)) {
+ _vm->_gfx->setCursorPalette(true);
+ } else if (fCanSel[IDI_WTP_SEL_SOUTH] && (event.mouse.x >= 20 && event.mouse.x <= (IDI_WTP_PIC_WIDTH + 10) * 2) &&
+ (event.mouse.y >= IDI_WTP_PIC_HEIGHT - 10 && event.mouse.y <= IDI_WTP_PIC_HEIGHT)) {
+ _vm->_gfx->setCursorPalette(true);
+ } else if (fCanSel[IDI_WTP_SEL_WEST] && (event.mouse.y >= 0 && event.mouse.y <= IDI_WTP_PIC_HEIGHT) &&
+ (event.mouse.x >= 20 && event.mouse.x <= 30)) {
+ _vm->_gfx->setCursorPalette(true);
+ } else if (fCanSel[IDI_WTP_SEL_EAST] && (event.mouse.y >= 0 && event.mouse.y <= IDI_WTP_PIC_HEIGHT) &&
+ (event.mouse.x >= IDI_WTP_PIC_WIDTH * 2 && event.mouse.x <= (IDI_WTP_PIC_WIDTH + 10) * 2)) {
+ _vm->_gfx->setCursorPalette(true);
+ } else {
+ _vm->_gfx->setCursorPalette(false);
+ }
+
+ break;
+ case Common::EVENT_LBUTTONUP:
+ // Click to move
+ if (fCanSel[IDI_WTP_SEL_NORTH] && (event.mouse.x >= 20 && event.mouse.x <= (IDI_WTP_PIC_WIDTH + 10) * 2) &&
+ (event.mouse.y >= 0 && event.mouse.y <= 10)) {
+ *iSel = IDI_WTP_SEL_NORTH;
+ makeSel();
+ _vm->_gfx->setCursorPalette(false);
+ return;
+ } else if (fCanSel[IDI_WTP_SEL_SOUTH] && (event.mouse.x >= 20 && event.mouse.x <= (IDI_WTP_PIC_WIDTH + 10) * 2) &&
+ (event.mouse.y >= IDI_WTP_PIC_HEIGHT - 10 && event.mouse.y <= IDI_WTP_PIC_HEIGHT)) {
+ *iSel = IDI_WTP_SEL_SOUTH;
+ makeSel();
+ _vm->_gfx->setCursorPalette(false);
+ return;
+ } else if (fCanSel[IDI_WTP_SEL_WEST] && (event.mouse.y >= 0 && event.mouse.y <= IDI_WTP_PIC_HEIGHT) &&
+ (event.mouse.x >= 20 && event.mouse.x <= 30)) {
+ *iSel = IDI_WTP_SEL_WEST;
+ makeSel();
+ _vm->_gfx->setCursorPalette(false);
+ return;
+ } else if (fCanSel[IDI_WTP_SEL_EAST] && (event.mouse.y >= 0 && event.mouse.y <= IDI_WTP_PIC_HEIGHT) &&
+ (event.mouse.x >= IDI_WTP_PIC_WIDTH * 2 && event.mouse.x <= (IDI_WTP_PIC_WIDTH + 10) * 2)) {
+ *iSel = IDI_WTP_SEL_EAST;
+ makeSel();
+ _vm->_gfx->setCursorPalette(false);
+ return;
+ } else {
+ _vm->_gfx->setCursorPalette(false);
+ }
+
+ switch(*iSel) {
+ case IDI_WTP_SEL_OPT_1:
+ case IDI_WTP_SEL_OPT_2:
+ case IDI_WTP_SEL_OPT_3:
+ for (int iSel2 = 0; iSel2 < IDI_WTP_MAX_OPTION; iSel2++) {
+ if (*iSel == (fCanSel[iSel2 + IDI_WTP_SEL_REAL_OPT_1] - 1)) {
+ *iSel = iSel2;
+ // Menu selection made, hide the mouse cursor
+ CursorMan.showMouse(false);
+ return;
+ }
+ }
+ break;
+ default:
+ if (fCanSel[*iSel]) {
+ // Menu selection made, hide the mouse cursor
+ CursorMan.showMouse(false);
+ return;
+ }
+ break;
+ }
+ break;
+ case Common::EVENT_RBUTTONUP:
+ *iSel = IDI_WTP_SEL_BACK;
+ // Menu selection made, hide the mouse cursor
+ CursorMan.showMouse(false);
+ return;
+ case Common::EVENT_WHEELUP:
+ decMenuSel(iSel, fCanSel);
+ break;
+ case Common::EVENT_WHEELDOWN:
+ incMenuSel(iSel, fCanSel);
+ break;
+ case Common::EVENT_KEYDOWN:
+ switch (event.kbd.keycode) {
+ case Common::KEYCODE_ESCAPE:
+ *iSel = IDI_WTP_SEL_HOME;
+ // Menu selection made, hide the mouse cursor
+ CursorMan.showMouse(false);
+ return;
+ case Common::KEYCODE_BACKSPACE:
+ *iSel = IDI_WTP_SEL_BACK;
+ // Menu selection made, hide the mouse cursor
+ CursorMan.showMouse(false);
+ return;
+ case Common::KEYCODE_c:
+ inventory();
+ break;
+ case Common::KEYCODE_SPACE:
+ case Common::KEYCODE_RIGHT:
+ case Common::KEYCODE_DOWN:
+ incMenuSel(iSel, fCanSel);
+ break;
+ case Common::KEYCODE_LEFT:
+ case Common::KEYCODE_UP:
+ decMenuSel(iSel, fCanSel);
+ break;
+ case Common::KEYCODE_1:
+ case Common::KEYCODE_2:
+ case Common::KEYCODE_3:
+ *iSel = event.kbd.keycode - Common::KEYCODE_1;
+ if (fCanSel[*iSel + IDI_WTP_SEL_REAL_OPT_1]) {
+ // Menu selection made, hide the mouse cursor
+ CursorMan.showMouse(false);
+ return;
+ } else {
+ keyHelp();
+ clrMenuSel(iSel, fCanSel);
+ }
+ break;
+ case Common::KEYCODE_n:
+ *iSel = IDI_WTP_SEL_NORTH;
+ makeSel();
+ break;
+ case Common::KEYCODE_s:
+ if (event.kbd.flags & Common::KBD_CTRL) {
+ //FlipSound();
+ } else {
+ *iSel = IDI_WTP_SEL_SOUTH;
+ makeSel();
+ }
+ break;
+ case Common::KEYCODE_e:
+ *iSel = IDI_WTP_SEL_EAST;
+ makeSel();
+ break;
+ case Common::KEYCODE_w:
+ *iSel = IDI_WTP_SEL_WEST;
+ makeSel();
+ break;
+ case Common::KEYCODE_t:
+ *iSel = IDI_WTP_SEL_TAKE;
+ makeSel();
+ break;
+ case Common::KEYCODE_d:
+ *iSel = IDI_WTP_SEL_DROP;
+ makeSel();
+ break;
+ case Common::KEYCODE_RETURN:
+ switch(*iSel) {
+ case IDI_WTP_SEL_OPT_1:
+ case IDI_WTP_SEL_OPT_2:
+ case IDI_WTP_SEL_OPT_3:
+ for (int iSel2 = 0; iSel2 < IDI_WTP_MAX_OPTION; iSel2++) {
+ if (*iSel == (fCanSel[iSel2 + IDI_WTP_SEL_REAL_OPT_1] - 1)) {
+ *iSel = iSel2;
+ // Menu selection made, hide the mouse cursor
+ CursorMan.showMouse(false);
+ return;
+ }
+ }
+ break;
+ default:
+ if (fCanSel[*iSel]) {
+ // Menu selection made, hide the mouse cursor
+ CursorMan.showMouse(false);
+ return;
+ }
+ break;
+ }
+ default:
+ keyHelp();
+ clrMenuSel(iSel, fCanSel);
+ break;
+ }
+ break;
+ default:
+ break;
+ }
+
+ drawMenu(szMenu, *iSel, fCanSel);
+ }
+ }
+}
+
+void Winnie::gameLoop() {
+ WTP_ROOM_HDR hdr;
+ uint8 *roomdata = new uint8[4096];
+ int iBlock;
+
+phase0:
+ if (!game.nObjMiss && (room == IDI_WTP_ROOM_PICNIC))
+ room = IDI_WTP_ROOM_PARTY;
+ readRoom(room, roomdata, 4096);
+ memcpy(&hdr, roomdata, sizeof(WTP_ROOM_HDR));
+ drawRoomPic();
+phase1:
+ if (getObjInRoom(room)) {
+ printObjStr(getObjInRoom(room), IDI_WTP_OBJ_DESC);
+ _vm->waitAnyKeyChoice();
+ }
+phase2:
+ for (iBlock = 0; iBlock < IDI_WTP_MAX_BLOCK; iBlock++) {
+ if (parser(hdr.ofsDesc[iBlock] - IDI_WTP_OFS_ROOM, iBlock, roomdata) == IDI_WTP_PAR_BACK) {
+ goto phase1;
+ }
+ }
+ for (;;) {
+ for (iBlock = 0; iBlock < IDI_WTP_MAX_BLOCK; iBlock++) {
+ switch(parser(hdr.ofsBlock[iBlock] - IDI_WTP_OFS_ROOM, iBlock, roomdata)) {
+ case IDI_WTP_PAR_GOTO:
+ goto phase0;
+ break;
+ case IDI_WTP_PAR_BACK:
+ goto phase2;
+ break;
+ }
+ }
+ }
+
+ delete [] roomdata;
+}
+
+void Winnie::drawPic(const char *szName) {
+ char szFile[256] = {0};
+ uint8 *buffer = new uint8[4096];
+
+ // construct filename
+ sprintf(szFile, IDS_WTP_PATH, szName);
+ Common::File file;
+ if (!file.open(szName))
+ return;
+ uint32 size = file.size();
+ file.read(buffer, size);
+ file.close();
+
+ _vm->_picture->decodePicture(buffer, size, 1, IDI_WTP_PIC_WIDTH, IDI_WTP_PIC_HEIGHT);
+ _vm->_picture->showPic(IDI_WTP_PIC_X0, IDI_WTP_PIC_Y0, IDI_WTP_PIC_WIDTH, IDI_WTP_PIC_HEIGHT);
+ _vm->_gfx->doUpdate();
+ _vm->_system->updateScreen(); // TODO: this should go in the game's main loop
+
+ delete [] buffer;
+}
+
+void Winnie::drawObjPic(int iObj, int x0, int y0) {
+ WTP_OBJ_HDR objhdr;
+ uint8 *buffer = new uint8[2048];
+
+ if (!iObj)
+ return;
+
+ readObj(iObj, buffer, 2048);
+ memcpy(&objhdr, buffer, sizeof(WTP_OBJ_HDR));
+
+ _vm->_picture->setOffset(x0, y0);
+ _vm->_picture->decodePicture(buffer + objhdr.ofsPic - IDI_WTP_OFS_OBJ, 4096, 0, IDI_WTP_PIC_WIDTH, IDI_WTP_PIC_HEIGHT);
+ _vm->_picture->setOffset(0, 0);
+ _vm->_picture->showPic(10, 0, IDI_WTP_PIC_WIDTH, IDI_WTP_PIC_HEIGHT);
+ _vm->_gfx->doUpdate();
+ _vm->_system->updateScreen();
+
+ delete [] buffer;
+}
+
+void Winnie::drawRoomPic() {
+ WTP_ROOM_HDR roomhdr;
+ uint8 *buffer = new uint8[4096];
+ int iObj = getObjInRoom(room);
+
+ // clear gfx screen
+ _vm->_gfx->clearScreen(0);
+ _vm->_gfx->doUpdate();
+ _vm->_system->updateScreen(); // TODO: this should go in the game's main loop
+
+ // read room picture
+ readRoom(room, buffer, 4096);
+ memcpy(&roomhdr, buffer, sizeof(WTP_ROOM_HDR));
+
+ // draw room picture
+ _vm->_picture->decodePicture(buffer + roomhdr.ofsPic - IDI_WTP_OFS_ROOM, 4096, 1, IDI_WTP_PIC_WIDTH, IDI_WTP_PIC_HEIGHT);
+ _vm->_picture->showPic(IDI_WTP_PIC_X0, IDI_WTP_PIC_Y0, IDI_WTP_PIC_WIDTH, IDI_WTP_PIC_HEIGHT);
+ _vm->_gfx->doUpdate();
+ _vm->_system->updateScreen(); // TODO: this should go in the game's main loop
+
+ // draw object picture
+ drawObjPic(iObj, IDI_WTP_PIC_X0 + roomhdr.objX, IDI_WTP_PIC_Y0 + roomhdr.objY);
+
+ delete [] buffer;
+}
+
+bool Winnie::getSelOkBack() {
+ Common::Event event;
+
+ for (;;) {
+ while (_vm->_system->getEventManager()->pollEvent(event)) {
+ switch (event.type) {
+ case Common::EVENT_QUIT:
+ _vm->_system->quit();
+ break;
+ case Common::EVENT_LBUTTONUP:
+ return true;
+ case Common::EVENT_RBUTTONUP:
+ return false;
+ case Common::EVENT_KEYDOWN:
+ switch (event.kbd.keycode) {
+ case Common::KEYCODE_BACKSPACE:
+ return false;
+ default:
+ return true;
+ }
+ default:
+ break;
+ }
+ }
+ }
+}
+void Winnie::clrMenuSel(int *iSel, int fCanSel[]) {
+ *iSel = IDI_WTP_SEL_OPT_1;
+ while(!fCanSel[*iSel]) {
+ *iSel += 1;
+ }
+}
+
+void Winnie::printRoomStr(int iRoom, int iStr) {
+ WTP_ROOM_HDR hdr;
+ uint8 *buffer = (uint8 *)malloc(4096);
+
+ readRoom(iRoom, buffer, 4096);
+ memcpy(&hdr, buffer, sizeof(hdr));
+ _vm->printStrXOR((char *)(buffer + hdr.ofsStr[iStr - 1] - IDI_WTP_OFS_ROOM));
+
+ free(buffer);
+}
+
+void Winnie::gameOver() {
+ // sing the Pooh song forever
+ for (;;) {
+ _vm->printStr(IDS_WTP_SONG_0);
+ //Winnie_PlaySound(IDI_WTP_SND_POOH_0);
+ _vm->printStr(IDS_WTP_SONG_1);
+ //Winnie_PlaySound(IDI_WTP_SND_POOH_1);
+ _vm->printStr(IDS_WTP_SONG_2);
+ //Winnie_PlaySound(IDI_WTP_SND_POOH_2);
+ _vm->waitAnyKeyChoice();
+ }
+}
+
+void Winnie::saveGame() {
+ uint8 *buffer = new uint8[sizeof(WTP_SAVE_GAME)];
+ memcpy(buffer, &game, sizeof(WTP_SAVE_GAME));
+ writeSaveGame(buffer);
+ delete [] buffer;
+}
+
+void Winnie::loadGame() {
+ uint8 *buffer = new uint8[sizeof(WTP_SAVE_GAME)];
+ readSaveGame(buffer);
+ memcpy(&game, buffer, sizeof(WTP_SAVE_GAME));
+ delete [] buffer;
+}
+
+void Winnie::readSaveGame(uint8 *buffer) {
+ Common::InSaveFile* infile;
+ char szFile[256] = {0};
+ sprintf(szFile, IDS_WTP_FILE_SAVEGAME);
+ if (!(infile = _vm->getSaveFileMan()->openForLoading(szFile)))
+ return;
+ infile->read(buffer, sizeof(WTP_SAVE_GAME));
+ delete infile;
+}
+
+void Winnie::writeSaveGame(uint8 *buffer) {
+ Common::OutSaveFile* outfile;
+ char szFile[256] = {0};
+ sprintf(szFile, IDS_WTP_FILE_SAVEGAME);
+ if (!(outfile = _vm->getSaveFileMan()->openForSaving(szFile)))
+ return;
+ outfile->write(buffer, sizeof(WTP_SAVE_GAME));
+ delete outfile;
+}
+
+Winnie::Winnie(PreAgiEngine* vm) : _vm(vm) {
+
+}
+
+void Winnie::init() {
+ initEngine();
+ initVars();
+}
+
+void Winnie::run() {
+ randomize();
+ intro();
+ gameLoop();
+}
+
+}
diff --git a/engines/agi/preagi_winnie.h b/engines/agi/preagi_winnie.h
new file mode 100644
index 0000000000..625795d7e1
--- /dev/null
+++ b/engines/agi/preagi_winnie.h
@@ -0,0 +1,352 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#ifndef AGI_PREAGI_WINNIE_H
+#define AGI_PREAGI_WINNIE_H
+
+#include "agi/agi.h"
+
+namespace Agi {
+
+// strings
+
+#define IDS_WTP_SELECTION ">"
+
+#define IDS_WTP_PATH_ROOM "rooms\\rm.%02d"
+#define IDS_WTP_PATH_OBJ "obj.%02d"
+#define IDS_WTP_PATH_SND "snd.%02d"
+#define IDS_WTP_PATH "%s"
+
+#define IDS_WTP_FILE_LOGO "logo.pic"
+#define IDS_WTP_FILE_TITLE "title.pic"
+#define IDS_WTP_FILE_SAVEGAME "savegame"
+#define IDS_WTP_FILE_RND "rnd"
+
+#define IDS_WTP_DISK_ERROR "There is a problem with your disk drive.Please make sure your Winnie-the-Pooh disk is in the drive correctly."
+
+#define IDS_WTP_INTRO_0 " PRESENT"
+#define IDS_WTP_INTRO_1 " TM designates trademark of\n Sierra On-Line, Inc.\n (c) 1985 Walt Disney Productions"
+
+#define IDS_WTP_HELP_0 "The <SPACE BAR> moves the pointer. Press <RETURN> when it is by the choice you want. Press the <Backspace> key to see what you just finished reading."
+#define IDS_WTP_HELP_1 "Press <C> to see what you are carrying. <Ctrl-S> turns the sound off and on. <ESC> takes you to the playroom (in caseyou get lost or want to save the game)."
+
+#define IDS_WTP_GAME_OVER_0 "Congratulations!! You did it! You returned everything that was lost. Now,Christopher Robin invites you to a Hero party."
+#define IDS_WTP_GAME_OVER_1 "The good news is: YOU are the Hero!! The bad news is: you have to find the party by yourself. Good luck!"
+
+#define IDS_WTP_OWL_0 "\"For example, that object you are carrying now is interesting. I know I've seen it before. Hmmm. Let me think about this . . .\""
+#define IDS_WTP_OWL_1 "\"You know, this object here beside me isfamiliar. I'm sure I could give you some sort of clue about it. Let me see. . .\""
+
+#define IDS_WTP_WIND_0 "Oh, no! The Blustery Wind begins to howl. It has returned, and mixed up all the objects in the Wood."
+#define IDS_WTP_WIND_1 "But don't worry. Everyone still has theobjects you returned to them.\n\n (Today must be Winds-day!)"
+#define IDS_WTP_TIGGER "\"Hallooooo, there!!!! It's ME, Tigger! Let's BOUNCE!\""
+#define IDS_WTP_MIST "Oh, look out! The mysterious mist is coming in. It gets so thick that you can't see through it. Just keep walkingand it will soon clear up."
+
+#define IDS_WTP_SONG_0 "Winnie-the-Pooh, Winnie-the-Pooh, Tubby little cubby all stuffed with fluff, He's Winnie-the-Pooh, Winnie-the-Pooh, Willy, nilly, silly, old bear."
+#define IDS_WTP_SONG_1 "Deep in the Hundred Acre Wood, Where Christopher Robin plays, You will find the enchanted neighborhoodof Christopher's childhood days."
+#define IDS_WTP_SONG_2 "A donkey named Eeyore is his friend, and Kanga and little Roo. There's Rabbit and Piglet and there's Owl But most of all Winnie-the-Pooh!"
+
+#define IDS_WTP_NSEW "North South East West"
+#define IDS_WTP_TAKE "Take"
+#define IDS_WTP_DROP "Drop"
+#define IDS_WTP_CANT_GO "\nSorry, but you can't go that way."
+#define IDS_WTP_CANT_TAKE "You can't take it. You can only carry one object at a time."
+#define IDS_WTP_CANT_DROP "You can't drop it. Another object is already here."
+#define IDS_WTP_WRONG_PLACE "\nOk, but it doesn't belong here."
+#define IDS_WTP_OK "\nOk."
+
+#define IDS_WTP_INVENTORY_0 "You are carrying nothing."
+#define IDS_WTP_INVENTORY_1 "Number of objects still missing: %d"
+
+// COMMODORE 64 version strings
+
+#define IDS_WTP_PATH_ROOM_C64 "%sroom%02d"
+#define IDS_WTP_PATH_OBJ_C64 "%sobject%02d"
+#define IDS_WTP_PATH_SND_C64 "%ssound.obj"
+#define IDS_WTP_FILE_SAVEGAME_C64 "saved game"
+#define IDS_WTP_DISK_ERROR_C64 "There is a problem with your disk drive.Please make sure your disk is in the drive correctly."
+#define IDS_WTP_HELP_0_C64 "The <SPACE BAR> moves the pointer. Press <RETURN> when it is by the choice you want. <F1> brings back what you have already read."
+#define IDS_WTP_HELP_1_C64 "<F3> takes you back to the playroom (if you get lost, or want to save the game).<F5> turns the sound off and on. <F7> shows what you're carrying."
+#define IDS_WTP_WRONG_PLACE_C64 "\nOk, but this is not the right place."
+
+// maximum values
+
+#define IDI_WTP_MAX_OBJ_MISSING 10
+
+#define IDI_WTP_MAX_ROOM 62
+#define IDI_WTP_MAX_OBJ 40
+#define IDI_WTP_MAX_SND 14
+#define IDI_WTP_MAX_PIC 2
+
+#define IDI_WTP_MAX_ROOM_NORMAL 57
+#define IDI_WTP_MAX_ROOM_TELEPORT 30
+#define IDI_WTP_MAX_ROOM_OBJ 42
+#define IDI_WTP_MAX_BLOCK 4
+#define IDI_WTP_MAX_STR 6
+#define IDI_WTP_MAX_OBJ_STR 4
+#define IDI_WTP_MAX_OBJ_STR_END 2
+#define IDI_WTP_MAX_FLAG 40
+#define IDI_WTP_MAX_OPTION 3
+#define IDI_WTP_MAX_DIR 4
+#define IDI_WTP_MAX_MOVES_UNTIL_WIND 150
+
+// positions
+
+#define IDI_WTP_ROW_MENU 21
+#define IDI_WTP_ROW_OPTION_1 21
+#define IDI_WTP_ROW_OPTION_2 22
+#define IDI_WTP_ROW_OPTION_3 23
+#define IDI_WTP_ROW_OPTION_4 24
+
+#define IDI_WTP_COL_MENU 0
+#define IDI_WTP_COL_OPTION 1
+#define IDI_WTP_COL_NSEW 1
+#define IDI_WTP_COL_NORTH 1
+#define IDI_WTP_COL_SOUTH 8
+#define IDI_WTP_COL_EAST 15
+#define IDI_WTP_COL_WEST 21
+#define IDI_WTP_COL_TAKE 29
+#define IDI_WTP_COL_DROP 35
+#define IDI_WTP_COL_PRESENT 17
+
+// data file offset modifiers
+
+#define IDI_WTP_OFS_ROOM 0x5400
+#define IDI_WTP_OFS_OBJ 0x0800
+
+// picture
+
+#define IDI_WTP_PIC_WIDTH 140
+#define IDI_WTP_PIC_HEIGHT 159
+#define IDI_WTP_PIC_X0 10
+#define IDI_WTP_PIC_Y0 0
+#define IDI_WTP_PIC_FLAGS IDF_AGI_PIC_V2
+
+// selections
+
+enum {
+ IDI_WTP_SEL_HOME = -2,
+ IDI_WTP_SEL_BACK,
+ IDI_WTP_SEL_OPT_1,
+ IDI_WTP_SEL_OPT_2,
+ IDI_WTP_SEL_OPT_3,
+ IDI_WTP_SEL_NORTH,
+ IDI_WTP_SEL_SOUTH,
+ IDI_WTP_SEL_EAST,
+ IDI_WTP_SEL_WEST,
+ IDI_WTP_SEL_TAKE,
+ IDI_WTP_SEL_DROP,
+ IDI_WTP_SEL_REAL_OPT_1,
+ IDI_WTP_SEL_REAL_OPT_2,
+ IDI_WTP_SEL_REAL_OPT_3
+};
+
+#define IDI_WTP_SEL_LAST IDI_WTP_SEL_REAL_OPT_3
+
+// rooms
+
+enum {
+ IDI_WTP_ROOM_NONE = -1,
+ IDI_WTP_ROOM_NORTH,
+ IDI_WTP_ROOM_SOUTH,
+ IDI_WTP_ROOM_EAST,
+ IDI_WTP_ROOM_WEST
+};
+
+#define IDI_WTP_ROOM_HIDE 0
+
+#define IDI_WTP_ROOM_PICNIC 2
+#define IDI_WTP_ROOM_HOME 28
+#define IDI_WTP_ROOM_PARTY 58
+#define IDI_WTP_ROOM_MIST 59
+#define IDI_WTP_ROOM_TIGGER 61
+
+// sound
+
+enum ENUM_WTP_SOUND {
+ IDI_WTP_SND_POOH_0 = 1,
+ IDI_WTP_SND_TIGGER,
+ IDI_WTP_SND_TAKE,
+ IDI_WTP_SND_DROP,
+ IDI_WTP_SND_DROP_OK,
+ IDI_WTP_SND_FANFARE,
+ IDI_WTP_SND_POOH_1,
+ IDI_WTP_SND_KEYHELP,
+ IDI_WTP_SND_POOH_2,
+ IDI_WTP_SND_WIND_0,
+ IDI_WTP_SND_WIND_1
+};
+
+// script opcodes
+
+#define IDO_WTP_GOTO_ROOM 0x06
+#define IDO_WTP_PRINT_MSG 0x08
+#define IDO_WTP_PRINT_STR 0x0A
+#define IDO_WTP_DROP_OBJ 0x0C
+#define IDO_WTP_FLAG_CLEAR 0x0E
+#define IDO_WTP_FLAG_SET 0x10
+#define IDO_WTP_GAME_OVER 0x12
+#define IDO_WTP_WALK_MIST 0x14
+#define IDO_WTP_PLAY_SOUND 0x16
+#define IDO_WTP_SAVE_GAME 0x18
+#define IDO_WTP_LOAD_GAME 0x1A
+#define IDO_WTP_OWL_HELP 0x1C
+#define IDO_WTP_GOTO_RND 0x1E
+
+#define IDO_WTP_OPTION_0 0x15
+#define IDO_WTP_OPTION_1 0x16
+#define IDO_WTP_OPTION_2 0x17
+
+enum {
+ IDI_WTP_OBJ_DESC = 0,
+ IDI_WTP_OBJ_TAKE,
+ IDI_WTP_OBJ_DROP,
+ IDI_WTP_OBJ_HELP
+};
+
+enum {
+ IDI_WTP_PAR_OK = 0,
+ IDI_WTP_PAR_GOTO,
+ IDI_WTP_PAR_BACK
+};
+
+// room file option block
+
+struct WTP_ROOM_BLOCK {
+ uint16 ofsOpt[IDI_WTP_MAX_BLOCK];
+};
+
+// room file header
+
+struct WTP_ROOM_HDR {
+ uint8 roomNumber;
+ uint8 objId;
+ uint16 ofsPic;
+ uint16 fileLen;
+ uint16 reserved0;
+ int8 roomNew[IDI_WTP_MAX_DIR];
+ uint8 objX;
+ uint8 objY;
+ uint16 reserved1;
+ uint16 ofsDesc[IDI_WTP_MAX_BLOCK];
+ uint16 ofsBlock[IDI_WTP_MAX_BLOCK];
+ uint16 ofsStr[IDI_WTP_MAX_STR];
+ uint32 reserved2;
+ WTP_ROOM_BLOCK opt[IDI_WTP_MAX_BLOCK];
+};
+
+// object file header
+
+struct WTP_OBJ_HDR {
+ uint16 fileLen;
+ uint16 objId;
+ uint16 ofsEndStr[IDI_WTP_MAX_OBJ_STR_END];
+ uint16 ofsStr[IDI_WTP_MAX_OBJ_STR];
+ uint16 ofsPic;
+};
+
+// savegame
+
+struct WTP_SAVE_GAME {
+ uint16 reserved0; // 10c2 unused
+ uint16 fSound; // 10c4
+ uint16 nMoves; // 10c6
+ uint16 nObjMiss; // 10c8
+ uint16 nObjRet; // 10ca
+ uint16 reserved1; // 10ce unused
+ uint16 reserved2; // 10cf unused
+ uint16 reserved3; // 10d0 unused
+ uint16 iObjHave; // 10d2
+ uint16 o10d4; // 10d4 can be ignored
+ uint16 o10d6; // 10d6 can be ignored
+ uint16 o10d8; // 10d8 can be ignored
+ uint8 fGame[IDI_WTP_MAX_FLAG]; // 10da
+ uint8 iUsedObj[IDI_WTP_MAX_OBJ_MISSING]; // 1102
+ uint8 iObjRoom[IDI_WTP_MAX_ROOM_OBJ]; // 110c
+ uint16 o1136; // 1136 can be ignored
+ uint16 o1138; // 1138 can be ignored
+};
+
+#define IDI_XOR_KEY 0x80
+
+class Winnie {
+ friend class PreAgiEngine;
+public:
+ Winnie(PreAgiEngine *vm);
+ //~Winnie();
+
+ void init();
+ void run();
+
+private:
+ PreAgiEngine *_vm;
+ WTP_SAVE_GAME game;
+ int room;
+ int mist;
+ bool doWind;
+ bool winnie_event;
+ int tigger_mist;
+
+ void initEngine();
+ void initVars();
+ void randomize();
+ void intro();
+ void drawPic(const char*);
+ void gameLoop();
+ void readRoom(int, uint8*, int);
+ void drawRoomPic();
+ int parser(int, int, uint8*);
+ int getObjInRoom(int);
+ bool getSelOkBack();
+ void getMenuSel(char*, int*, int[]);
+ void keyHelp();
+ void clrMenuSel(int*, int[]);
+ void incMenuSel(int*, int[]);
+ void decMenuSel(int*, int[]);
+ void drawMenu(char*, int, int[]);
+ void printRoomStr(int, int);
+ void inventory();
+ void printObjStr(int, int);
+ void readObj(int, uint8*, int);
+ void takeObj(int);
+ void dropObj(int);
+ bool isRightObj(int, int, int*);
+ void drawObjPic(int, int, int);
+ void getMenuMouseSel(int*, int[], int, int);
+ void setFlag(int);
+ void clearFlag(int);
+ void gameOver();
+ void saveGame();
+ void loadGame();
+ void writeSaveGame(uint8*);
+ void readSaveGame(uint8*);
+ void dropObjRnd();
+ void wind();
+ void showOwlHelp();
+};
+
+} // End of namespace Agi
+
+#endif
+
diff --git a/engines/agi/predictive.cpp b/engines/agi/predictive.cpp
index eef4360cbf..5ffa3d159f 100644
--- a/engines/agi/predictive.cpp
+++ b/engines/agi/predictive.cpp
@@ -199,7 +199,8 @@ bool AgiEngine::predictiveDialog(void) {
color2 = 7;
}
- bool _addIsActive = false; // FIXME
+ // needs fixing, or remove it!
+ bool _addIsActive = false; // FIXME: word adding is not implemented
if (i == 10 && !_addIsActive) { // Add
color2 = 7;
}
diff --git a/engines/agi/saveload.cpp b/engines/agi/saveload.cpp
index 05ce80b1a3..c8cae3b479 100644
--- a/engines/agi/saveload.cpp
+++ b/engines/agi/saveload.cpp
@@ -525,7 +525,7 @@ int AgiEngine::selectSlot() {
int oldActive = active + 1;
for (;;) {
- int sbPos;
+ int sbPos = 0;
if (oldFirstSlot != _firstSlot || oldActive != active) {
char dstr[64];
diff --git a/engines/agi/sound.cpp b/engines/agi/sound.cpp
index b083b77440..b76ab309a5 100644
--- a/engines/agi/sound.cpp
+++ b/engines/agi/sound.cpp
@@ -25,6 +25,10 @@
#include "common/stdafx.h"
+#include "common/md5.h"
+#include "common/config-manager.h"
+#include "common/fs.h"
+#include "common/algorithm.h"
#include "sound/mixer.h"
#include "agi/agi.h"
@@ -33,204 +37,241 @@
namespace Agi {
#define USE_INTERPOLATION
-#define USE_CHORUS
+static bool g_useChorus = true;
/* TODO: add support for variable sampling rate in the output device
*/
-#ifdef USE_IIGS_SOUND
+AgiSound *AgiSound::createFromRawResource(uint8 *data, uint32 len, int resnum, SoundMgr &manager) {
+ if (data == NULL || len < 2) return NULL; // Check for too small resource or no resource at all
+ uint16 type = READ_LE_UINT16(data);
+
+ switch (type) { // Create a sound object based on the type
+ case AGI_SOUND_SAMPLE : return new IIgsSample(data, len, resnum, manager);
+ case AGI_SOUND_MIDI : return new IIgsMidi (data, len, resnum, manager);
+ case AGI_SOUND_4CHN : return new PCjrSound (data, len, resnum, manager);
+ }
+
+ warning("Sound resource (%d) has unknown type (0x%04x). Not using the sound", resnum, type);
+ return NULL;
+}
-struct IIgsEnvelopeSegment {
- uint8 bp;
- uint16 inc; ///< 8b.8b fixed point, big endian?
-};
+IIgsMidi::IIgsMidi(uint8 *data, uint32 len, int resnum, SoundMgr &manager) : AgiSound(manager) {
+ _data = data; // Save the resource pointer
+ _ptr = _data + 2; // Set current position to just after the header
+ _len = len; // Save the resource's length
+ _type = READ_LE_UINT16(data); // Read sound resource's type
+ _isValid = (_type == AGI_SOUND_MIDI) && (_data != NULL) && (_len >= 2);
-#define ENVELOPE_SEGMENT_COUNT 8
-struct IIgsEnvelope {
- IIgsEnvelopeSegment seg[ENVELOPE_SEGMENT_COUNT];
-};
+ if (!_isValid) // Check for errors
+ warning("Error creating Apple IIGS midi sound from resource %d (Type %d, length %d)", resnum, _type, len);
+}
-// 2**(1/12) i.e. the 12th root of 2
-#define SEMITONE 1.059463094359295
-
-struct IIgsWaveInfo {
- uint8 top;
- uint8 addr;
- uint8 size;
-// Oscillator channel (Bits 4-7 of mode-byte). Simplified to use only stereo here.
-#define MASK_OSC_CHANNEL (1 << 4)
-#define OSC_CHANNEL_LEFT (1 << 4)
-#define OSC_CHANNEL_RIGHT (0 << 4)
-// Oscillator halt bit (Bit 0 of mode-byte)
-#define MASK_OSC_HALT (1 << 0)
-#define OSC_HALT (1 << 0)
-// Oscillator mode (Bits 1 and 2 of mode-byte)
-#define MASK_OSC_MODE (3 << 1)
-#define OSC_MODE_LOOP (0 << 1)
-#define OSC_MODE_ONESHOT (1 << 1)
-#define OSC_MODE_SYNC_AM (2 << 1)
-#define OSC_MODE_SWAP (3 << 1)
- uint8 mode;
- uint16 relPitch; ///< 8b.8b fixed point, big endian?
-};
+PCjrSound::PCjrSound(uint8 *data, uint32 len, int resnum, SoundMgr &manager) : AgiSound(manager) {
+ _data = data; // Save the resource pointer
+ _len = len; // Save the resource's length
+ _type = READ_LE_UINT16(data); // Read sound resource's type
+ _isValid = (_type == AGI_SOUND_4CHN) && (_data != NULL) && (_len >= 2);
-#define MAX_WAVE_COUNT 8
-struct IIgsInstrumentHeader {
- IIgsEnvelope env;
- uint8 relseg;
- uint8 priority;
- uint8 bendrange;
- uint8 vibdepth;
- uint8 vibspeed;
- uint8 spare;
- uint8 wac;
- uint8 wbc;
- IIgsWaveInfo wal[MAX_WAVE_COUNT];
- IIgsWaveInfo wbl[MAX_WAVE_COUNT];
-};
+ if (!_isValid) // Check for errors
+ warning("Error creating PCjr 4-channel sound from resource %d (Type %d, length %d)", resnum, _type, len);
+}
-struct IIgsSampleHeader {
- uint16 type;
- uint8 pitch; ///< Logarithmic, base is 2**(1/12), unknown multiplier (Possibly in range 1040-1080)
- uint8 unknownByte_Ofs3; // 0x7F in Gold Rush's sound resource 60, 0 in all others.
- uint8 volume; ///< Current guess: Logarithmic in 6 dB steps
- uint8 unknownByte_Ofs5; ///< 0 in all tested samples.
- uint16 instrumentSize; ///< Little endian. 44 in all tested samples. A guess.
- uint16 sampleSize; ///< Little endian. Accurate in all tested samples excluding Manhunter I's sound resource 16.
- IIgsInstrumentHeader instrument;
-};
+const uint8 *PCjrSound::getVoicePointer(uint voiceNum) {
+ assert(voiceNum < 4);
+ uint16 voiceStartOffset = READ_LE_UINT16(_data + voiceNum * 2);
+ return _data + voiceStartOffset;
+}
-#if 0
-static SoundInstrument *instruments;
-static int numInstruments;
-static uint8 *wave;
-#endif
+IIgsSample::IIgsSample(uint8 *data, uint32 len, int resnum, SoundMgr &manager) : AgiSound(manager) {
+ Common::MemoryReadStream stream(data, len, true);
-bool readIIgsEnvelope(IIgsEnvelope &envelope, Common::SeekableReadStream &stream) {
+ // Check that the header was read ok and that it's of the correct type
+ if (_header.read(stream) && _header.type == AGI_SOUND_SAMPLE) { // An Apple IIGS AGI sample resource
+ uint32 sampleStartPos = stream.pos();
+ uint32 tailLen = stream.size() - sampleStartPos;
+
+ if (tailLen < _header.sampleSize) { // Check if there's no room for the sample data in the stream
+ // Apple IIGS Manhunter I: Sound resource 16 has only 16074 bytes
+ // of sample data although header says it should have 16384 bytes.
+ warning("Apple IIGS sample (%d) too short (%d bytes. Should be %d bytes). Using the part that's left",
+ resnum, tailLen, _header.sampleSize);
+ _header.sampleSize = (uint16) tailLen; // Use the part that's left
+ }
+
+ if (_header.pitch > 0x7F) { // Check if the pitch is invalid
+ warning("Apple IIGS sample (%d) has too high pitch (0x%02x)", resnum, _header.pitch);
+ _header.pitch &= 0x7F; // Apple IIGS AGI probably did it this way too
+ }
+
+ // Finalize the header info using the 8-bit unsigned sample data
+ _header.finalize(stream);
+
+ // Convert sample data from 8-bit unsigned to 16-bit signed format
+ stream.seek(sampleStartPos);
+ _sample = new int16[_header.sampleSize];
+ if (_sample != NULL)
+ _isValid = _manager.convertWave(stream, _sample, _header.sampleSize);
+ }
+
+ if (!_isValid) // Check for errors
+ warning("Error creating Apple IIGS sample from resource %d (Type %d, length %d)", resnum, _header.type, len);
+}
+
+/** Reads an Apple IIGS envelope from then given stream. */
+bool IIgsEnvelope::read(Common::SeekableReadStream &stream) {
for (int segNum = 0; segNum < ENVELOPE_SEGMENT_COUNT; segNum++) {
- envelope.seg[segNum].bp = stream.readByte();
- envelope.seg[segNum].inc = stream.readUint16BE();
+ seg[segNum].bp = stream.readByte();
+ seg[segNum].inc = stream.readUint16LE();
}
return !stream.ioFailed();
}
-bool readIIgsWaveInfo(IIgsWaveInfo &waveInfo, Common::SeekableReadStream &stream) {
- waveInfo.top = stream.readByte();
- waveInfo.addr = stream.readByte();
- waveInfo.size = stream.readByte();
- waveInfo.mode = stream.readByte();
- waveInfo.relPitch = stream.readUint16BE();
+/** Reads an Apple IIGS wave information structure from the given stream. */
+bool IIgsWaveInfo::read(Common::SeekableReadStream &stream, bool ignoreAddr) {
+ top = stream.readByte();
+ addr = stream.readByte() * 256;
+ size = (1 << (stream.readByte() & 7)) * 256;
+
+ // Read packed mode byte and parse it into parts
+ byte packedModeByte = stream.readByte();
+ channel = (packedModeByte >> 4) & 1; // Bit 4
+ mode = (packedModeByte >> 1) & 3; // Bits 1-2
+ halt = (packedModeByte & 1) != 0; // Bit 0 (Converted to boolean)
+
+ relPitch = stream.readSint16LE();
+
+ // Zero the wave address if we want to ignore the wave address info
+ if (ignoreAddr)
+ addr = 0;
+
return !stream.ioFailed();
}
-/**
- * Read an Apple IIGS instrument header from the given stream.
- * @param header The header to which to write the data.
- * @param stream The source stream from which to read the data.
- * @return True if successful, false otherwise.
- */
-bool readIIgsInstrumentHeader(IIgsInstrumentHeader &header, Common::SeekableReadStream &stream) {
- readIIgsEnvelope(header.env, stream);
- header.relseg = stream.readByte();
- header.priority = stream.readByte();
- header.bendrange = stream.readByte();
- header.vibdepth = stream.readByte();
- header.vibspeed = stream.readByte();
- header.spare = stream.readByte();
- header.wac = stream.readByte();
- header.wbc = stream.readByte();
- for (int waveA = 0; waveA < header.wac; waveA++) // Read A wave lists
- readIIgsWaveInfo(header.wal[waveA], stream);
- for (int waveB = 0; waveB < header.wbc; waveB++) // Read B wave lists
- readIIgsWaveInfo(header.wbl[waveB], stream);
- return !stream.ioFailed();
+bool IIgsWaveInfo::finalize(Common::SeekableReadStream &uint8Wave) {
+ uint32 startPos = uint8Wave.pos(); // Save stream's starting position
+ uint8Wave.seek(addr, SEEK_CUR); // Seek to wave's address
+
+ // Calculate the true sample size (A zero ends the sample prematurely)
+ uint trueSize = size; // Set a default value for the result
+ for (uint i = 0; i < size; i++) {
+ if (uint8Wave.readByte() == 0) {
+ trueSize = i;
+ // A zero in the sample stream turns off looping
+ // (At least that's what MESS 0.117 and KEGS32 0.91 seem to do)
+ if (mode == OSC_MODE_LOOP)
+ mode = OSC_MODE_ONESHOT;
+ break;
+ }
+ }
+ size = trueSize; // Set the true sample size
+
+ uint8Wave.seek(startPos); // Seek back to the stream's starting position
+ return true;
}
-/**
- * Read an Apple IIGS AGI sample header from the given stream.
- * @param header The header to which to write the data.
- * @param stream The source stream from which to read the data.
- * @return True if successful, false otherwise.
- */
-bool readIIgsSampleHeader(IIgsSampleHeader &header, Common::SeekableReadStream &stream) {
- header.type = stream.readUint16LE();
- header.pitch = stream.readByte();
- header.unknownByte_Ofs3 = stream.readByte();
- header.volume = stream.readByte();
- header.unknownByte_Ofs5 = stream.readByte();
- header.instrumentSize = stream.readUint16LE();
- header.sampleSize = stream.readUint16LE();
- return readIIgsInstrumentHeader(header.instrument, stream);
+bool IIgsOscillator::finalize(Common::SeekableReadStream &uint8Wave) {
+ for (uint i = 0; i < WAVES_PER_OSCILLATOR; i++)
+ if (!waves[i].finalize(uint8Wave))
+ return false;
+ return true;
}
-/**
- * Load an Apple IIGS AGI sample resource from the given stream and
- * create an AudioStream out of it.
- *
- * @param stream The source stream.
- * @param resnum Sound resource number. Optional. Used for error messages.
- * @return A non-null AudioStream pointer if successful, NULL otherwise.
- * @note In case of failure (i.e. NULL is returned), stream is reset back
- * to its original position and its I/O failed -status is cleared.
- * TODO: Add better handling of invalid resource number when printing error messages.
- * TODO: Add support for looping sounds.
- * FIXME: Fix sample rate calculation, it's probably not accurate at the moment.
- */
-Audio::AudioStream *makeIIgsSampleStream(Common::SeekableReadStream &stream, int resnum = -1) {
- const uint32 startPos = stream.pos();
- IIgsSampleHeader header;
- Audio::AudioStream *result = NULL;
- bool readHeaderOk = readIIgsSampleHeader(header, stream);
+bool IIgsOscillatorList::read(Common::SeekableReadStream &stream, uint oscillatorCount, bool ignoreAddr) {
+ // First read the A waves and then the B waves for the oscillators
+ for (uint waveNum = 0; waveNum < WAVES_PER_OSCILLATOR; waveNum++)
+ for (uint oscNum = 0; oscNum < oscillatorCount; oscNum++)
+ if (!osc[oscNum].waves[waveNum].read(stream, ignoreAddr))
+ return false;
- // Check that the header was read ok and that it's of the correct type
- // and that there's room for the sample data in the stream.
- if (readHeaderOk && header.type == AGI_SOUND_SAMPLE) { // An Apple IIGS AGI sample resource
- uint32 tailLen = stream.size() - stream.pos();
- if (tailLen < header.sampleSize) { // Check if there's no room for the sample data in the stream
- // Apple IIGS Manhunter I: Sound resource 16 has only 16074 bytes
- // of sample data although header says it should have 16384 bytes.
- warning("Apple IIGS sample (%d) too short (%d bytes. Should be %d bytes). Using the part that's left", resnum, tailLen, header.sampleSize);
- header.sampleSize = (uint16) tailLen; // Use the part that's left
- }
- if (header.pitch > 0x7F) { // Check if the pitch is invalid
- warning("Apple IIGS sample (%d) has too high pitch (0x%02x)", resnum, header.pitch);
- header.pitch &= 0x7F; // Apple IIGS AGI probably did it this way too
- }
- // Allocate memory for the sample data and read it in
- byte *sampleData = (byte *) malloc(header.sampleSize);
- uint32 readBytes = stream.read(sampleData, header.sampleSize);
- if (readBytes == header.sampleSize) { // Check that we got all the data we requested
- // Make an audio stream from the mono, 8 bit, unsigned input data
- byte flags = Audio::Mixer::FLAG_AUTOFREE | Audio::Mixer::FLAG_UNSIGNED;
- int rate = (int) (1076 * pow(SEMITONE, header.pitch));
- result = Audio::makeLinearInputStream(sampleData, header.sampleSize, rate, flags, 0, 0);
- }
- }
+ count = oscillatorCount; // Set the oscillator count
+ return true;
+}
- // If couldn't make a sample out of the input stream for any reason then
- // rewind back to stream's starting position and clear I/O failed -status.
- if (result == NULL) {
- stream.seek(startPos);
- stream.clearIOFailed();
- }
+bool IIgsOscillatorList::finalize(Common::SeekableReadStream &uint8Wave) {
+ for (uint i = 0; i < count; i++)
+ if (!osc[i].finalize(uint8Wave))
+ return false;
+ return true;
+}
- return result;
+bool IIgsInstrumentHeader::read(Common::SeekableReadStream &stream, bool ignoreAddr) {
+ env.read(stream);
+ relseg = stream.readByte();
+ /*byte priority =*/ stream.readByte(); // Not needed? 32 in all tested data.
+ bendrange = stream.readByte();
+ vibdepth = stream.readByte();
+ vibspeed = stream.readByte();
+ /*byte spare =*/ stream.readByte(); // Not needed? 0 in all tested data.
+ byte wac = stream.readByte(); // Read A wave count
+ byte wbc = stream.readByte(); // Read B wave count
+ oscList.read(stream, wac, ignoreAddr); // Read the oscillators
+ return (wac == wbc) && !stream.ioFailed(); // A and B wave counts must match
}
-#endif
+bool IIgsInstrumentHeader::finalize(Common::SeekableReadStream &uint8Wave) {
+ return oscList.finalize(uint8Wave);
+}
+
+bool IIgsSampleHeader::read(Common::SeekableReadStream &stream) {
+ type = stream.readUint16LE();
+ pitch = stream.readByte();
+ unknownByte_Ofs3 = stream.readByte();
+ volume = stream.readByte();
+ unknownByte_Ofs5 = stream.readByte();
+ instrumentSize = stream.readUint16LE();
+ sampleSize = stream.readUint16LE();
+ // Read the instrument header *ignoring* its wave address info
+ return instrument.read(stream, true);
+}
+
+bool IIgsSampleHeader::finalize(Common::SeekableReadStream &uint8Wave) {
+ return instrument.finalize(uint8Wave);
+}
+
+/** Older Apple IIGS AGI instrument set. Used only by Space Quest I (AGI v1.002). */
+static const instrumentSetInfo instSetV1 = {
+ 1192, 26, "7ee16bbc135171ffd6b9120cc7ff1af2", "edd3bf8905d9c238e02832b732fb2e18"
+};
-static int playing;
-static ChannelInfo chn[NUM_CHANNELS];
-static int endflag = -1;
-static int playingSound = -1;
-static uint8 *song;
-static uint8 env;
+/** Newer Apple IIGS AGI instrument set (AGI v1.003+). Used by all others than Space Quest I. */
+static const instrumentSetInfo instSetV2 = {
+ 1292, 28, "b7d428955bb90721996de1cbca25e768", "c05fb0b0e11deefab58bc68fbd2a3d07"
+};
+/** Information about different Apple IIGS AGI executables. */
+static const IIgsExeInfo IIgsExeInfos[] = {
+ {GID_SQ1, "SQ", 0x1002, 138496, 0x80AD, instSetV1},
+ {GID_LSL1, "LL", 0x1003, 141003, 0x844E, instSetV2},
+ {GID_AGIDEMO, "DEMO", 0x1005, 141884, 0x8469, instSetV2},
+ {GID_KQ1, "KQ", 0x1006, 141894, 0x8469, instSetV2},
+ {GID_PQ1, "PQ", 0x1007, 141882, 0x8469, instSetV2},
+ {GID_MIXEDUP, "MG", 0x1013, 142552, 0x84B7, instSetV2},
+ {GID_KQ2, "KQ2", 0x1013, 143775, 0x84B7, instSetV2},
+ {GID_KQ3, "KQ3", 0x1014, 144312, 0x84B7, instSetV2},
+ {GID_SQ2, "SQ2", 0x1014, 107882, 0x6563, instSetV2},
+ {GID_MH1, "MH", 0x2004, 147678, 0x8979, instSetV2},
+ {GID_KQ4, "KQ4", 0x2006, 147652, 0x8979, instSetV2},
+ {GID_BC, "BC", 0x3001, 148192, 0x8979, instSetV2},
+ {GID_GOLDRUSH, "GR", 0x3003, 148268, 0x8979, instSetV2}
+};
-static int16 *sndBuffer;
-static int16 *waveform;
+static IIgsInstrumentHeader g_instruments[MAX_INSTRUMENTS];
+static uint g_numInstruments = 0;
+static int16 g_wave[SIERRASTANDARD_SIZE]; // FIXME? Should this be allocated from the heap? (Size is 128KiB)
+// Time (In milliseconds) in Apple IIGS mixing buffer time granularity
+// (i.e. in IIGS_BUFFER_SIZE / getRate() seconds granularity)
+static uint32 g_IIgsBufGranMillis = 0;
+static uint32 g_midiMillis = 0; // Time position (In milliseconds) in currently playing MIDI sound
+
+bool SoundMgr::finalizeInstruments(Common::SeekableReadStream &uint8Wave) {
+ for (uint i = 0; i < g_numInstruments; i++)
+ if (!g_instruments[i].finalize(uint8Wave))
+ return false;
+ return true;
+}
-static int16 waveformRamp[WAVEFORM_SIZE] = {
+static const int16 waveformRamp[WAVEFORM_SIZE] = {
0, 8, 16, 24, 32, 40, 48, 56,
64, 72, 80, 88, 96, 104, 112, 120,
128, 136, 144, 152, 160, 168, 176, 184,
@@ -241,7 +282,7 @@ static int16 waveformRamp[WAVEFORM_SIZE] = {
-64, -56, -48, -40, -32, -24, -16, -8 /* Ramp up */
};
-static int16 waveformSquare[WAVEFORM_SIZE] = {
+static const int16 waveformSquare[WAVEFORM_SIZE] = {
255, 230, 220, 220, 220, 220, 220, 220,
220, 220, 220, 220, 220, 220, 220, 220,
220, 220, 220, 220, 220, 220, 220, 220,
@@ -252,7 +293,7 @@ static int16 waveformSquare[WAVEFORM_SIZE] = {
-220, -220, -220, -110, 0, 0, 0, 0 /* Square */
};
-static int16 waveformMac[WAVEFORM_SIZE] = {
+static const int16 waveformMac[WAVEFORM_SIZE] = {
45, 110, 135, 161, 167, 173, 175, 176,
156, 137, 123, 110, 91, 72, 35, -2,
-60, -118, -142, -165, -170, -176, -177, -179,
@@ -263,157 +304,137 @@ static int16 waveformMac[WAVEFORM_SIZE] = {
-175, -172, -165, -159, -137, -114, -67, -19
};
-#ifdef USE_IIGS_SOUND
-
-static uint16 period[] = {
+static const uint16 period[] = {
1024, 1085, 1149, 1218, 1290, 1367,
1448, 1534, 1625, 1722, 1825, 1933
};
-static struct AgiNote playSample[] = {
- {0xff, 0x7f, 0x18, 0x00, 0x7f},
- {0xff, 0xff, 0x00, 0x00, 0x00},
- {0xff, 0xff, 0x00, 0x00, 0x00},
- {0xff, 0xff, 0x00, 0x00, 0x00}
-};
-
+#if 0
static int noteToPeriod(int note) {
return 10 * (period[note % 12] >> (note / 12 - 3));
}
-
-#endif /* USE_IIGS_SOUND */
+#endif
void SoundMgr::unloadSound(int resnum) {
if (_vm->_game.dirSound[resnum].flags & RES_LOADED) {
- if (_vm->_game.sounds[resnum].flags & SOUND_PLAYING)
- /* FIXME: Stop playing */
- ;
+ if (_vm->_game.sounds[resnum]->isPlaying()) {
+ _vm->_game.sounds[resnum]->stop();
+ }
- /* Release RAW data for sound */
- free(_vm->_game.sounds[resnum].rdata);
- _vm->_game.sounds[resnum].rdata = NULL;
+ // Release the sound resource's data
+ delete _vm->_game.sounds[resnum];
+ _vm->_game.sounds[resnum] = NULL;
_vm->_game.dirSound[resnum].flags &= ~RES_LOADED;
}
}
-void SoundMgr::decodeSound(int resnum) {
-#if 0
- int type, size;
- int16 *buf;
- uint8 *src;
- struct SoundIIgsSample *smp;
-
- debugC(3, kDebugLevelSound, "(%d)", resnum);
- type = READ_LE_UINT16(_vm->_game.sounds[resnum].rdata);
-
- if (type == AGI_SOUND_SAMPLE) {
- /* Convert sample data to 16 bit signed format
- */
- smp = (struct SoundIIgsSample *)_vm->_game.sounds[resnum].rdata;
- size = ((int)smp->sizeHi << 8) + smp->sizeLo;
- src = (uint8 *)_vm->_game.sounds[resnum].rdata;
- buf = (int16 *)calloc(1, 54 + (size << 1) + 100); /* FIXME */
- memcpy(buf, src, 54);
- for (; size--; buf[size + 54] = ((int16)src[size + 54] - 0x80) << 4); /* FIXME */
- _vm->_game.sounds[resnum].rdata = (uint8 *) buf;
- free(src);
- }
-#endif
-}
-
void SoundMgr::startSound(int resnum, int flag) {
- int i, type;
-#if 0
- struct SoundIIgsSample *smp;
-#endif
+ int i;
+ AgiSoundType type;
- if (_vm->_game.sounds[resnum].flags & SOUND_PLAYING)
+ if (_vm->_game.sounds[resnum] != NULL && _vm->_game.sounds[resnum]->isPlaying())
return;
stopSound();
- if (_vm->_game.sounds[resnum].rdata == NULL)
+ if (_vm->_game.sounds[resnum] == NULL) // Is this needed at all?
return;
- type = READ_LE_UINT16(_vm->_game.sounds[resnum].rdata);
+ type = (AgiSoundType)_vm->_game.sounds[resnum]->type();
if (type != AGI_SOUND_SAMPLE && type != AGI_SOUND_MIDI && type != AGI_SOUND_4CHN)
return;
- _vm->_game.sounds[resnum].flags |= SOUND_PLAYING;
- _vm->_game.sounds[resnum].type = type;
- playingSound = resnum;
- song = (uint8 *)_vm->_game.sounds[resnum].rdata;
+ _vm->_game.sounds[resnum]->play();
+ _playingSound = resnum;
+
+ debugC(3, kDebugLevelSound, "startSound(resnum = %d, flag = %d)", resnum, flag);
switch (type) {
-#if 0
- case AGI_SOUND_SAMPLE:
- debugC(3, kDebugLevelSound, "IIGS sample");
- smp = (struct SoundIIgsSample *)_vm->_game.sounds[resnum].rdata;
- for (i = 0; i < NUM_CHANNELS; i++) {
- chn[i].type = type;
- chn[i].flags = 0;
- chn[i].ins = (int16 *)&_vm->_game.sounds[resnum].rdata[54];
- chn[i].size = ((int)smp->sizeHi << 8) + smp->sizeLo;
- chn[i].ptr = &playSample[i];
- chn[i].timer = 0;
- chn[i].vol = 0;
- chn[i].end = 0;
- }
+ case AGI_SOUND_SAMPLE: {
+ IIgsSample *sampleRes = (IIgsSample *) _vm->_game.sounds[_playingSound];
+ const IIgsWaveInfo &waveInfo = _IIgsChannel.ins.oscList(0).waves[0];
+ const IIgsSampleHeader &header = sampleRes->getHeader();
+
+ _IIgsChannel.ins = header.instrument;
+ _IIgsChannel.sample = sampleRes->getSample() + waveInfo.addr;
+ _IIgsChannel.pos = intToFrac(0);
+ _IIgsChannel.posAdd = intToFrac(0);
+ _IIgsChannel.note = intToFrac(header.pitch) + doubleToFrac(waveInfo.relPitch/256.0);
+ _IIgsChannel.startEnvVol = intToFrac(0);
+ _IIgsChannel.chanVol = intToFrac(header.volume);
+ _IIgsChannel.envVol = _IIgsChannel.startEnvVol;
+ _IIgsChannel.vol = doubleToFrac(fracToDouble(_IIgsChannel.envVol) * fracToDouble(_IIgsChannel.chanVol) / 127.0);
+ _IIgsChannel.envSeg = intToFrac(0);
+ _IIgsChannel.loop = (waveInfo.mode == OSC_MODE_LOOP);
+ _IIgsChannel.size = waveInfo.size - waveInfo.addr;
+ _IIgsChannel.end = false;
break;
+ }
case AGI_SOUND_MIDI:
+ g_IIgsBufGranMillis = g_midiMillis = 0;
+#if 0
debugC(3, kDebugLevelSound, "IIGS MIDI sequence");
for (i = 0; i < NUM_CHANNELS; i++) {
- chn[i].type = type;
- chn[i].flags = AGI_SOUND_LOOP | AGI_SOUND_ENVELOPE;
- chn[i].ins = waveform;
- chn[i].size = WAVEFORM_SIZE;
- chn[i].vol = 0;
- chn[i].end = 0;
+ _chn[i].type = type;
+ _chn[i].flags = AGI_SOUND_LOOP | AGI_SOUND_ENVELOPE;
+ _chn[i].ins = _waveform;
+ _chn[i].size = WAVEFORM_SIZE;
+ _chn[i].vol = 0;
+ _chn[i].end = 0;
}
- chn[0].timer = *(song + 2);
- chn[0].ptr = (struct AgiNote *)(song + 3);
- break;
+ _chn[0].timer = *(song + 2);
+ _chn[0].ptr = (struct AgiNote *)(song + 3);
#endif
+ break;
case AGI_SOUND_4CHN:
+ PCjrSound *pcjrSound = (PCjrSound *) _vm->_game.sounds[resnum];
/* Initialize channel info */
for (i = 0; i < NUM_CHANNELS; i++) {
- chn[i].type = type;
- chn[i].flags = AGI_SOUND_LOOP;
- if (env) {
- chn[i].flags |= AGI_SOUND_ENVELOPE;
- chn[i].adsr = AGI_SOUND_ENV_ATTACK;
+ _chn[i].type = type;
+ _chn[i].flags = AGI_SOUND_LOOP;
+ if (_env) {
+ _chn[i].flags |= AGI_SOUND_ENVELOPE;
+ _chn[i].adsr = AGI_SOUND_ENV_ATTACK;
}
- chn[i].ins = waveform;
- chn[i].size = WAVEFORM_SIZE;
- chn[i].ptr = (struct AgiNote *)(song + (song[i << 1] | (song[(i << 1) + 1] << 8)));
- chn[i].timer = 0;
- chn[i].vol = 0;
- chn[i].end = 0;
+ _chn[i].ins = _waveform;
+ _chn[i].size = WAVEFORM_SIZE;
+ _chn[i].ptr = pcjrSound->getVoicePointer(i % 4);
+ _chn[i].timer = 0;
+ _chn[i].vol = 0;
+ _chn[i].end = 0;
}
break;
}
- memset(sndBuffer, 0, BUFFER_SIZE << 1);
- endflag = flag;
+ memset(_sndBuffer, 0, BUFFER_SIZE << 1);
+ _endflag = flag;
/* Nat Budin reports that the flag should be reset when sound starts
*/
- _vm->setflag(endflag, false);
+ _vm->setflag(_endflag, false);
}
void SoundMgr::stopSound() {
int i;
- endflag = -1;
- for (i = 0; i < NUM_CHANNELS; i++)
- stopNote(i);
+ _endflag = -1;
+ if (_vm->_soundemu != SOUND_EMU_APPLE2GS) {
+ for (i = 0; i < NUM_CHANNELS; i++)
+ stopNote(i);
+ }
- if (playingSound != -1) {
- _vm->_game.sounds[playingSound].flags &= ~SOUND_PLAYING;
- playingSound = -1;
+ if (_playingSound != -1) {
+ _vm->_game.sounds[_playingSound]->stop();
+
+ if (_vm->_soundemu == SOUND_EMU_APPLE2GS) {
+ _IIgsChannel.end = true;
+ _IIgsChannel.chanVol = intToFrac(0);
+ }
+
+ _playingSound = -1;
}
}
@@ -422,37 +443,36 @@ static int16 *buffer;
int SoundMgr::initSound() {
int r = -1;
- buffer = sndBuffer = (int16 *)calloc(2, BUFFER_SIZE);
+ buffer = _sndBuffer = (int16 *)calloc(2, BUFFER_SIZE);
- env = false;
+ _env = false;
switch (_vm->_soundemu) {
case SOUND_EMU_NONE:
- waveform = waveformRamp;
- env = true;
+ _waveform = waveformRamp;
+ _env = true;
break;
case SOUND_EMU_AMIGA:
case SOUND_EMU_PC:
- waveform = waveformSquare;
+ _waveform = waveformSquare;
break;
case SOUND_EMU_MAC:
- waveform = waveformMac;
+ _waveform = waveformMac;
+ break;
+ case SOUND_EMU_APPLE2GS:
+ loadInstruments();
break;
}
report("Initializing sound:\n");
report("sound: envelopes ");
- if (env) {
+ if (_env) {
report("enabled (decay=%d, sustain=%d)\n", ENV_DECAY, ENV_SUSTAIN);
} else {
report("disabled\n");
}
-#ifdef USE_IIGS_SOUND
- /*loadInstruments("demo.sys"); */
-#endif
-
_mixer->playInputStream(Audio::Mixer::kPlainSoundType, &_soundHandle, this, -1, Audio::Mixer::kMaxChannelVolume, 0, false, true);
return r;
@@ -461,19 +481,19 @@ int SoundMgr::initSound() {
void SoundMgr::deinitSound() {
debugC(3, kDebugLevelSound, "()");
_mixer->stopHandle(_soundHandle);
- free(sndBuffer);
+ free(_sndBuffer);
}
void SoundMgr::stopNote(int i) {
- chn[i].adsr = AGI_SOUND_ENV_RELEASE;
+ _chn[i].adsr = AGI_SOUND_ENV_RELEASE;
-#ifdef USE_CHORUS
- /* Stop chorus ;) */
- if (chn[i].type == AGI_SOUND_4CHN &&
- _vm->_soundemu == SOUND_EMU_NONE && i < 3) {
- stopNote(i + 4);
+ if (g_useChorus) {
+ /* Stop chorus ;) */
+ if (_chn[i].type == AGI_SOUND_4CHN &&
+ _vm->_soundemu == SOUND_EMU_NONE && i < 3) {
+ stopNote(i + 4);
+ }
}
-#endif
}
void SoundMgr::playNote(int i, int freq, int vol) {
@@ -482,127 +502,186 @@ void SoundMgr::playNote(int i, int freq, int vol) {
else if (vol && _vm->_soundemu == SOUND_EMU_PC)
vol = 160;
- chn[i].phase = 0;
- chn[i].freq = freq;
- chn[i].vol = vol;
- chn[i].env = 0x10000;
- chn[i].adsr = AGI_SOUND_ENV_ATTACK;
-
-#ifdef USE_CHORUS
- /* Add chorus ;) */
- if (chn[i].type == AGI_SOUND_4CHN &&
- _vm->_soundemu == SOUND_EMU_NONE && i < 3) {
- int newfreq = freq * 1007 / 1000;
- if (freq == newfreq)
- newfreq++;
- playNote(i + 4, newfreq, vol * 2 / 3);
+ _chn[i].phase = 0;
+ _chn[i].freq = freq;
+ _chn[i].vol = vol;
+ _chn[i].env = 0x10000;
+ _chn[i].adsr = AGI_SOUND_ENV_ATTACK;
+
+ if (g_useChorus) {
+ /* Add chorus ;) */
+ if (_chn[i].type == AGI_SOUND_4CHN &&
+ _vm->_soundemu == SOUND_EMU_NONE && i < 3) {
+ int newfreq = freq * 1007 / 1000;
+ if (freq == newfreq)
+ newfreq++;
+ playNote(i + 4, newfreq, vol * 2 / 3);
+ }
}
-#endif
}
-#ifdef USE_IIGS_SOUND
-
void SoundMgr::playMidiSound() {
- uint8 *p;
+ const uint8 *p;
uint8 parm1, parm2;
static uint8 cmd, ch;
- playing = 1;
-
- if (chn[0].timer > 0) {
- chn[0].timer -= 2;
+ if (_playingSound == -1 || _vm->_game.sounds[_playingSound] == NULL) {
+ warning("Error playing Apple IIGS MIDI sound resource");
+ _playing = false;
return;
}
- p = (uint8 *)chn[0].ptr;
+ IIgsMidi *midiObj = (IIgsMidi *) _vm->_game.sounds[_playingSound];
- if (*p & 0x80) {
- cmd = *p++;
- ch = cmd & 0x0f;
- cmd >>= 4;
- }
+ _playing = true;
+ p = midiObj->getPtr();
- switch (cmd) {
- case 0x08:
- parm1 = *p++;
- parm2 = *p++;
- if (ch < NUM_CHANNELS)
- stopNote(ch);
- break;
- case 0x09:
- parm1 = *p++;
- parm2 = *p++;
- if (ch < NUM_CHANNELS)
- playNote(ch, noteToPeriod(parm1), 127);
- break;
- case 0x0b:
- parm1 = *p++;
- parm2 = *p++;
- debugC(3, kDebugLevelSound, "controller %02x, ch %02x, val %02x", parm1, ch, parm2);
- break;
- case 0x0c:
- parm1 = *p++;
-#if 0
- if (ch < NUM_CHANNELS) {
- chn[ch].ins = (uint16 *)&wave[waveaddr[parm1]];
- chn[ch].size = wavesize[parm1];
+ g_IIgsBufGranMillis += (IIGS_BUFFER_SIZE * 1000) / getRate();
+
+ while (g_midiMillis < g_IIgsBufGranMillis) {
+ uint8 readByte = *p++;
+
+ // Check for end of MIDI sequence marker (Can also be here before delta-time)
+ if (readByte == MIDI_BYTE_STOP_SEQUENCE) {
+ debugC(3, kDebugLevelSound, "End of MIDI sequence (Before reading delta-time)");
+ g_IIgsBufGranMillis = g_midiMillis = 0;
+ _playing = false;
+ midiObj->rewind();
+ return;
+ } else if (readByte == MIDI_BYTE_TIMER_SYNC) {
+ debugC(3, kDebugLevelSound, "Timer sync");
+ continue;
+ }
+
+ uint8 deltaTime = readByte;
+ uint32 bpm = 120; // Don't know if this is correct
+ g_midiMillis += (deltaTime * 1000) / bpm;
+
+ // Check for end of MIDI sequence marker (This time it after reading delta-time)
+ if (*p == MIDI_BYTE_STOP_SEQUENCE) {
+ debugC(3, kDebugLevelSound, "End of MIDI sequence (After reading delta-time)");
+ g_IIgsBufGranMillis = g_midiMillis = 0;
+ _playing = false;
+ midiObj->rewind();
+ return;
+ }
+
+ // Separate byte into command and channel if it's a command byte.
+ // Otherwise use running status (i.e. previously set command and channel).
+ if (*p & 0x80) {
+ cmd = *p++;
+ ch = cmd & 0x0f;
+ cmd >>= 4;
}
- debugC(3, kDebugLevelSound, "set patch %02x (%d,%d), ch %02x",
- parm1, waveaddr[parm1], wavesize[parm1], ch);
+
+ switch (cmd) {
+ case MIDI_CMD_NOTE_OFF:
+ parm1 = *p++;
+ parm2 = *p++;
+#if 0
+ if (ch < NUM_CHANNELS)
+ stopNote(ch);
#endif
- break;
+ debugC(3, kDebugLevelSound, "note off, channel %02x, note %02x, velocity %02x", ch, parm1, parm2);
+ break;
+ case MIDI_CMD_NOTE_ON:
+ parm1 = *p++;
+ parm2 = *p++;
+#if 0
+ if (ch < NUM_CHANNELS)
+ playNote(ch, noteToPeriod(parm1), 127);
+#endif
+ debugC(3, kDebugLevelSound, "note on, channel %02x, note %02x, velocity %02x", ch, parm1, parm2);
+ break;
+ case MIDI_CMD_CONTROLLER:
+ // The tested Apple IIGS AGI MIDI resources only used
+ // controllers 0 (Bank select?), 7 (Volume) and 64 (Sustain On/Off).
+ // Controller 0's parameter was in range 94-127,
+ // controller 7's parameter was in range 0-127 and
+ // controller 64's parameter was always 0 (i.e. sustain off).
+ // TODO: Find out what controller 0 does and implement volume changes.
+ parm1 = *p++;
+ parm2 = *p++;
+ debugC(3, kDebugLevelSound, "controller %02x, ch %02x, val %02x", parm1, ch, parm2);
+ break;
+ case MIDI_CMD_PROGRAM_CHANGE:
+ // In all the tested Apple IIGS AGI MIDI resources
+ // program change's parameter was in range 0-43.
+ // This doesn't map directly to instrument numbers as all of
+ // the tested Apple IIGS AGI games only use 26 or 28 instruments.
+ // TODO: Find out the mapping to instruments and implement it.
+ parm1 = *p++;
+ debugC(3, kDebugLevelSound, "program change %02x, channel %02x", parm1, ch);
+#if 0
+ if (ch < NUM_CHANNELS) {
+ chn[ch].ins = (uint16 *)&wave[waveaddr[parm1]];
+ chn[ch].size = wavesize[parm1];
+ }
+ debugC(3, kDebugLevelSound, "set patch %02x (%d,%d), ch %02x",
+ parm1, waveaddr[parm1], wavesize[parm1], ch);
+#endif
+ break;
+ case MIDI_CMD_PITCH_WHEEL:
+ parm1 = *p++;
+ parm2 = *p++;
+ // In all the tested Apple IIGS AGI MIDI resources
+ // pitch wheel commands always had 0x2000 (Center position)
+ // as the combined 14-bit value for the position.
+ uint16 wheelPos = ((parm2 & 0x7F) << 7) | (parm1 & 0x7F); // 14-bit value
+ debugC(3, kDebugLevelSound, "Pitch wheel position %04x (Not implemented yet)", wheelPos);
+ break;
+ }
}
- chn[0].timer = *p++;
- chn[0].ptr = (struct AgiNote *)p;
+ midiObj->setPtr(p);
+}
- if (*p >= 0xfc) {
- debugC(3, kDebugLevelSound, "end of sequence");
- playing = 0;
+void SoundMgr::playSampleSound() {
+ if (_vm->_soundemu != SOUND_EMU_APPLE2GS) {
+ warning("Trying to play a sample but not using Apple IIGS sound emulation mode");
return;
}
-}
-void SoundMgr::playSampleSound() {
- playNote(0, 11025 * 10, 200);
- playing = 1;
+ if (_playingSound != -1)
+ _playing = !_IIgsChannel.end;
}
-#endif /* USE_IIGS_SOUND */
-
void SoundMgr::playAgiSound() {
- int i, freq;
+ int i;
+ AgiNote note;
- for (playing = i = 0; i < (_vm->_soundemu == SOUND_EMU_PC ? 1 : 4); i++) {
- playing |= !chn[i].end;
+ _playing = false;
+ for (i = 0; i < (_vm->_soundemu == SOUND_EMU_PC ? 1 : 4); i++) {
+ _playing |= !_chn[i].end;
+ note.read(_chn[i].ptr); // Read a single note (Doesn't advance the pointer)
- if (chn[i].end)
+ if (_chn[i].end)
continue;
- if ((--chn[i].timer) <= 0) {
+ if ((--_chn[i].timer) <= 0) {
stopNote(i);
- freq = ((chn[i].ptr->frq0 & 0x3f) << 4) | (int)(chn[i].ptr->frq1 & 0x0f);
- if (freq) {
- uint8 v = chn[i].ptr->vol & 0x0f;
- playNote(i, freq * 10, v == 0xf ? 0 : 0xff - (v << 1));
+ if (note.freqDiv != 0) {
+ int volume = (note.attenuation == 0x0F) ? 0 : (0xFF - note.attenuation * 2);
+ playNote(i, note.freqDiv * 10, volume);
}
- chn[i].timer = ((int)chn[i].ptr->durHi << 8) | chn[i].ptr->durLo;
-
- if (chn[i].timer == 0xffff) {
- chn[i].end = 1;
- chn[i].vol = 0;
- chn[i].env = 0;
-#ifdef USE_CHORUS
- /* chorus */
- if (chn[i].type == AGI_SOUND_4CHN && _vm->_soundemu == SOUND_EMU_NONE && i < 3) {
- chn[i + 4].vol = 0;
- chn[i + 4].env = 0;
+ _chn[i].timer = note.duration;
+
+ if (_chn[i].timer == 0xffff) {
+ _chn[i].end = 1;
+ _chn[i].vol = 0;
+ _chn[i].env = 0;
+
+ if (g_useChorus) {
+ /* chorus */
+ if (_chn[i].type == AGI_SOUND_4CHN && _vm->_soundemu == SOUND_EMU_NONE && i < 3) {
+ _chn[i + 4].vol = 0;
+ _chn[i + 4].env = 0;
+ }
}
-#endif
}
- chn[i].ptr++;
+ _chn[i].ptr += 5; // Advance the pointer to the next note data (5 bytes per note)
}
}
}
@@ -610,100 +689,183 @@ void SoundMgr::playAgiSound() {
void SoundMgr::playSound() {
int i;
- if (endflag == -1)
+ if (_endflag == -1)
return;
-#ifdef USE_IIGS_SOUND
- if (chn[0].type == AGI_SOUND_MIDI) {
- /* play_midi_sound (); */
- playing = 0;
- } else if (chn[0].type == AGI_SOUND_SAMPLE) {
- playSampleSound();
- } else
-#endif
+ if (_vm->_soundemu == SOUND_EMU_APPLE2GS) {
+ if (_playingSound != -1) {
+ if (_vm->_game.sounds[_playingSound]->type() == AGI_SOUND_MIDI) {
+ playMidiSound();
+ //warning("playSound: Trying to play an Apple IIGS MIDI sound. Not yet implemented!");
+ } else if (_vm->_game.sounds[_playingSound]->type() == AGI_SOUND_SAMPLE) {
+ //debugC(3, kDebugLevelSound, "playSound: Trying to play an Apple IIGS sample");
+ playSampleSound();
+ }
+ }
+ } else {
+ //debugC(3, kDebugLevelSound, "playSound: Trying to play a PCjr 4-channel sound");
playAgiSound();
+ }
- if (!playing) {
- for (i = 0; i < NUM_CHANNELS; chn[i++].vol = 0);
+ if (!_playing) {
+ if (_vm->_soundemu != SOUND_EMU_APPLE2GS) {
+ for (i = 0; i < NUM_CHANNELS; _chn[i++].vol = 0);
+ }
- if (endflag != -1)
- _vm->setflag(endflag, true);
+ if (_endflag != -1)
+ _vm->setflag(_endflag, true);
- if (playingSound != -1)
- _vm->_game.sounds[playingSound].flags &= ~SOUND_PLAYING;
- playingSound = -1;
- endflag = -1;
+ if (_playingSound != -1)
+ _vm->_game.sounds[_playingSound]->stop();
+ _playingSound = -1;
+ _endflag = -1;
}
}
uint32 SoundMgr::mixSound(void) {
register int i, p;
- int16 *src;
+ const int16 *src;
int c, b, m;
- memset(sndBuffer, 0, BUFFER_SIZE << 1);
+ memset(_sndBuffer, 0, BUFFER_SIZE << 1);
+
+ if (!_playing || _playingSound == -1)
+ return BUFFER_SIZE;
+
+ // Handle Apple IIGS sound mixing here
+ if (_vm->_soundemu == SOUND_EMU_APPLE2GS) {
+ AgiSoundType type = (AgiSoundType) _vm->_game.sounds[_playingSound]->type();
+ // Currently we only support mixing a single sample in Apple IIGS mixing code.
+ if (type != AGI_SOUND_SAMPLE)
+ return IIGS_BUFFER_SIZE;
+ //IIgsWaveInfo &waveInfo = _IIgsChannel.ins.oscList(0).waves[0];
+
+ //uint period = noteToPeriod(fracToInt(_IIgsChannel.note + FRAC_HALF));
+ //_IIgsChannel.posAdd = ((frac_t) (118600 * 4 / period)) << (FRAC_BITS - 8);
+
+ // Hertz (number of vibrations a second) = 6.875 x 2 ^ ( ( 3 + MIDI_Pitch ) / 12 )
+ // From http://www.musicmasterworks.com/WhereMathMeetsMusic.html
+ //double hertz = 6.875 * pow(SEMITONE, 3 + fracToDouble(_IIgsChannel.note));
+ //double hertz = 8.175798915644 * pow(SEMITONE, fracToDouble(_IIgsChannel.note));
+ // double step = getRate() / hertz;
+ // _IIgsChannel.posAdd = doubleToFrac(step);
+
+ // Frequency multiplier was 1076.0 based on tests made with MESS 0.117.
+ // Tests made with KEGS32 averaged the multiplier to around 1045.
+ // So this is a guess but maybe it's 1046.5... i.e. C6's frequency?
+ double hertz = C6_FREQ * pow(SEMITONE, fracToDouble(_IIgsChannel.note));
+ _IIgsChannel.posAdd = doubleToFrac(hertz / getRate());
+ _IIgsChannel.vol = doubleToFrac(fracToDouble(_IIgsChannel.envVol) * fracToDouble(_IIgsChannel.chanVol) / 127.0);
+ double tempVol = fracToDouble(_IIgsChannel.vol)/127.0;
+
+ for (i = 0; i < IIGS_BUFFER_SIZE; i++) {
+ b = _IIgsChannel.sample[fracToInt(_IIgsChannel.pos)];
+ // DOESN'T DO MIXING YET! ONLY ONE SAMPLE PER PLAYING!
+ _sndBuffer[i] = (int16) (b * tempVol);
+ _IIgsChannel.pos += _IIgsChannel.posAdd;
+
+ if (_IIgsChannel.pos >= intToFrac(_IIgsChannel.size)) {
+ if (_IIgsChannel.loop) {
+ _IIgsChannel.pos %= intToFrac(_IIgsChannel.size);
+ // Probably we should loop the envelope too
+ _IIgsChannel.envSeg = 0;
+ _IIgsChannel.envVol = _IIgsChannel.startEnvVol;
+ } else {
+ _IIgsChannel.pos = _IIgsChannel.chanVol = 0;
+ _IIgsChannel.end = true;
+ break;
+ }
+ }
+ }
+
+ if (_IIgsChannel.envSeg <= _IIgsChannel.ins.relseg) {
+ IIgsEnvelopeSegment &seg = _IIgsChannel.ins.env.seg[_IIgsChannel.envSeg];
+ double bufSecLen = IIGS_BUFFER_SIZE / (double) getRate();
+ double ticksPerSec = 100; // 1000 is way too much
+ double bufTickLen = bufSecLen / (1.0/ticksPerSec);
+ frac_t envVolDelta = doubleToFrac((seg.inc/256.0)*bufTickLen);
+ if (intToFrac(seg.bp) >= _IIgsChannel.envVol) {
+ _IIgsChannel.envVol += envVolDelta;
+ if (_IIgsChannel.envVol >= intToFrac(seg.bp)) {
+ _IIgsChannel.envVol = intToFrac(seg.bp);
+ _IIgsChannel.envSeg += 1;
+ }
+ } else {
+ _IIgsChannel.envVol -= envVolDelta;
+ if (_IIgsChannel.envVol <= intToFrac(seg.bp)) {
+ _IIgsChannel.envVol = intToFrac(seg.bp);
+ _IIgsChannel.envSeg += 1;
+ }
+ }
+ }
+ //_IIgsChannel.envSeg += doubleToFrac(1/100.0);
+ return IIGS_BUFFER_SIZE;
+ } /* else ... */
+ // Handle PCjr 4-channel sound mixing here
for (c = 0; c < NUM_CHANNELS; c++) {
- if (!chn[c].vol)
+ if (!_chn[c].vol)
continue;
- m = chn[c].flags & AGI_SOUND_ENVELOPE ?
- chn[c].vol * chn[c].env >> 16 : chn[c].vol;
+ m = _chn[c].flags & AGI_SOUND_ENVELOPE ?
+ _chn[c].vol * _chn[c].env >> 16 : _chn[c].vol;
- if (chn[c].type != AGI_SOUND_4CHN || c != 3) {
- src = chn[c].ins;
+ if (_chn[c].type != AGI_SOUND_4CHN || c != 3) {
+ src = _chn[c].ins;
- p = chn[c].phase;
+ p = _chn[c].phase;
for (i = 0; i < BUFFER_SIZE; i++) {
b = src[p >> 8];
#ifdef USE_INTERPOLATION
- b += ((src[((p >> 8) + 1) % chn[c].size] - src[p >> 8]) * (p & 0xff)) >> 8;
+ b += ((src[((p >> 8) + 1) % _chn[c].size] - src[p >> 8]) * (p & 0xff)) >> 8;
#endif
- sndBuffer[i] += (b * m) >> 4;
+ _sndBuffer[i] += (b * m) >> 4;
- p += (uint32) 118600 *4 / chn[c].freq;
+ p += (uint32) 118600 *4 / _chn[c].freq;
+ // FIXME: Fingolfin asks: why is there a FIXME here? Please either clarify what
+ // needs fixing, or remove it!
/* FIXME */
- if (chn[c].flags & AGI_SOUND_LOOP) {
- p %= chn[c].size << 8;
+ if (_chn[c].flags & AGI_SOUND_LOOP) {
+ p %= _chn[c].size << 8;
} else {
- if (p >= chn[c].size << 8) {
- p = chn[c].vol = 0;
- chn[c].end = 1;
+ if (p >= _chn[c].size << 8) {
+ p = _chn[c].vol = 0;
+ _chn[c].end = 1;
break;
}
}
}
- chn[c].phase = p;
+ _chn[c].phase = p;
} else {
/* Add white noise */
for (i = 0; i < BUFFER_SIZE; i++) {
b = _vm->_rnd->getRandomNumber(255) - 128;
- sndBuffer[i] += (b * m) >> 4;
+ _sndBuffer[i] += (b * m) >> 4;
}
}
- switch (chn[c].adsr) {
+ switch (_chn[c].adsr) {
case AGI_SOUND_ENV_ATTACK:
/* not implemented */
- chn[c].adsr = AGI_SOUND_ENV_DECAY;
+ _chn[c].adsr = AGI_SOUND_ENV_DECAY;
break;
case AGI_SOUND_ENV_DECAY:
- if (chn[c].env > chn[c].vol * ENV_SUSTAIN + ENV_DECAY) {
- chn[c].env -= ENV_DECAY;
+ if (_chn[c].env > _chn[c].vol * ENV_SUSTAIN + ENV_DECAY) {
+ _chn[c].env -= ENV_DECAY;
} else {
- chn[c].env = chn[c].vol * ENV_SUSTAIN;
- chn[c].adsr = AGI_SOUND_ENV_SUSTAIN;
+ _chn[c].env = _chn[c].vol * ENV_SUSTAIN;
+ _chn[c].adsr = AGI_SOUND_ENV_SUSTAIN;
}
break;
case AGI_SOUND_ENV_SUSTAIN:
break;
case AGI_SOUND_ENV_RELEASE:
- if (chn[c].env >= ENV_RELEASE) {
- chn[c].env -= ENV_RELEASE;
+ if (_chn[c].env >= ENV_RELEASE) {
+ _chn[c].env -= ENV_RELEASE;
} else {
- chn[c].env = 0;
+ _chn[c].env = 0;
}
}
}
@@ -711,101 +873,194 @@ uint32 SoundMgr::mixSound(void) {
return BUFFER_SIZE;
}
-#ifdef USE_IIGS_SOUND
+/**
+ * Finds information about an Apple IIGS AGI executable based on the game ID.
+ * @return A non-null IIgsExeInfo pointer if successful, otherwise NULL.
+ */
+const IIgsExeInfo *SoundMgr::getIIgsExeInfo(enum AgiGameID gameid) const {
+ for (int i = 0; i < ARRAYSIZE(IIgsExeInfos); i++)
+ if (IIgsExeInfos[i].gameid == gameid)
+ return &IIgsExeInfos[i];
+ return NULL;
+}
-#if 0
-int SoundMgr::loadInstruments(char *fname) {
- Common::File fp;
- int i, j, k;
- struct SoundInstrument ai;
- int numWav;
- char *path;
-
- path = "sierrast";
-
- if (!fp.open(path))
- return errBadFileOpen;
- report("Loading samples: %s\n", path);
-
- if ((wave = malloc(0x10000 * 2)) == NULL)
- return errNotEnoughMemory;
-
- fp.read(wave, 0x10000);
- fp.close();
- for (i = 0x10000; i--;) {
- ((int16 *)wave)[i] = 2 * ((int16)wave[i] - 128);
- }
+bool SoundMgr::loadInstrumentHeaders(const Common::String &exePath, const IIgsExeInfo &exeInfo) {
+ bool loadedOk = false; // Was loading successful?
+ Common::File file;
- fp = fopen("bla", "w");
- fwrite(wave, 2, 0x10000, fp);
- fclose(fp);
+ // Open the executable file and check that it has correct size
+ file.open(exePath);
+ if (file.size() != exeInfo.exeSize) {
+ debugC(3, kDebugLevelSound, "Apple IIGS executable (%s) has wrong size (Is %d, should be %d)",
+ exePath.c_str(), file.size(), exeInfo.exeSize);
+ }
- report("Loading instruments: %s\n", path);
+ // Read the whole executable file into memory
+ Common::MemoryReadStream *data = file.readStream(file.size());
+ file.close();
+
+ // Check that we got enough data to be able to parse the instruments
+ if (data != NULL && data->size() >= (exeInfo.instSetStart + exeInfo.instSet.byteCount)) {
+ // Check instrument set's length (The info's saved in the executable)
+ data->seek(exeInfo.instSetStart - 4);
+ uint16 instSetByteCount = data->readUint16LE();
+ if (instSetByteCount != exeInfo.instSet.byteCount) {
+ debugC(3, kDebugLevelSound, "Wrong instrument set size (Is %d, should be %d) in Apple IIGS executable (%s)",
+ instSetByteCount, exeInfo.instSet.byteCount, exePath.c_str());
+ }
- if ((fp = fopen(path, "rb")) == NULL)
- return errBadFileOpen;
+ // Check instrument set's md5sum
+ data->seek(exeInfo.instSetStart);
+ char md5str[32+1];
+ Common::md5_file_string(*data, md5str, exeInfo.instSet.byteCount);
+ if (scumm_stricmp(md5str, exeInfo.instSet.md5)) {
+ warning("Unknown Apple IIGS instrument set (md5: %s) in %s, trying to use it nonetheless",
+ md5str, exePath.c_str());
+ }
- fseek(fp, 0x8469, SEEK_SET);
+ // Read in the instrument set one instrument at a time
+ data->seek(exeInfo.instSetStart);
+ g_numInstruments = 0; // Zero number of successfully loaded instruments
+ for (uint i = 0; i < exeInfo.instSet.instCount; i++) {
+ if (!g_instruments[i].read(*data)) {
+ warning("Error loading Apple IIGS instrument (%d. of %d) from %s, not loading more instruments",
+ i + 1, exeInfo.instSet.instCount, exePath.c_str());
+ break;
+ }
+ g_numInstruments++; // Increase number of successfully loaded instruments
+ }
- for (numWav = j = 0; j < 40; j++) {
- fread(&ai, 1, 32, fp);
+ // Loading was successful only if all instruments were loaded successfully
+ loadedOk = (g_numInstruments == exeInfo.instSet.instCount);
+ } else // Couldn't read enough data from the executable file
+ warning("Error loading instruments from Apple IIGS executable (%s)", exePath.c_str());
- if (ai.env[0].bp > 0x7f)
- break;
+ delete data; // Free the memory buffer allocated for reading the executable file
+ return loadedOk;
+}
-#if 0
- printf("Instrument %d loaded ----------------\n", j);
- printf("Envelope:\n");
- for (i = 0; i < 8; i++)
- printf("[seg %d]: BP %02x Inc %04x\n", i, ai.env[i].bp,
- ((int)ai.env[i].inc_hi << 8) | ai.env[i].inc_lo);
- printf("rel seg: %d, pri inc: %d, bend range: %d, vib dep: %d, "
- "vib spd: %d\n", ai.relseg, ai.priority,
- ai.bendrange, ai.vibdepth, ai.vibspeed);
- printf("A wave count: %d, B wave count: %d\n", ai.wac, ai.wbc);
-#endif
+/**
+ * Convert sample from 8-bit unsigned to 16-bit signed format.
+ * @param source Source stream containing the 8-bit unsigned sample data.
+ * @param dest Destination buffer for the 16-bit signed sample data.
+ * @param length Length of the sample data to be converted.
+ */
+bool SoundMgr::convertWave(Common::SeekableReadStream &source, int16 *dest, uint length) {
+ // Convert the wave from 8-bit unsigned to 16-bit signed format
+ for (uint i = 0; i < length; i++)
+ dest[i] = (int16) ((source.readByte() - 128) * 256);
+ return !source.ioFailed();
+}
- for (k = 0; k < ai.wac; k++, num_wav++) {
- fread(&ai.wal[k], 1, 6, fp);
-#if 0
- printf("[A %d of %d] top: %02x, wave address: %02x, "
- "size: %02x, mode: %02x, relPitch: %04x\n", k + 1,
- ai.wac, ai.wal[k].top, ai.wal[k].addr, ai.wal[k].size,
- ai.wal[k].mode, ((int)ai.wal[k].rel_hi << 8) | ai.wal[k].rel_lo);
-#endif
+Common::MemoryReadStream *SoundMgr::loadWaveFile(const Common::String &wavePath, const IIgsExeInfo &exeInfo) {
+ Common::File file;
+
+ // Open the wave file and read it into memory
+ file.open(wavePath);
+ Common::MemoryReadStream *uint8Wave = file.readStream(file.size());
+ file.close();
+
+ // Check that we got the whole wave file
+ if (uint8Wave != NULL && uint8Wave->size() == SIERRASTANDARD_SIZE) {
+ // Check wave file's md5sum
+ char md5str[32+1];
+ Common::md5_file_string(*uint8Wave, md5str, SIERRASTANDARD_SIZE);
+ if (scumm_stricmp(md5str, exeInfo.instSet.waveFileMd5)) {
+ warning("Unknown Apple IIGS wave file (md5: %s, game: %s).\n" \
+ "Please report the information on the previous line to the ScummVM team.\n" \
+ "Using the wave file as it is - music may sound weird", md5str, exeInfo.exePrefix);
}
+ uint8Wave->seek(0); // Seek wave to its start
+ return uint8Wave;
+ } else { // Couldn't read the wave file or it had incorrect size
+ warning("Error loading Apple IIGS wave file (%s), not loading instruments", wavePath.c_str());
+ delete uint8Wave; // Free the memory buffer allocated for reading the wave file
+ return NULL;
+ }
+}
- for (k = 0; k < ai.wbc; k++, num_wav++) {
- fread(&ai.wbl[k], 1, 6, fp);
-#if 0
- printf("[B %d of %d] top: %02x, wave address: %02x, "
- "size: %02x, mode: %02x, relPitch: %04x\n", k + 1, ai.wbc,
- ai.wbl[k].top, ai.wbl[k].addr, ai.wbl[k].size,
- ai.wbl[k].mode, ((int)ai.wbl[k].rel_hi << 8) | ai.wbl[k].rel_lo);
-#endif
- }
- waveaddr[j] = 256 * ai.wal[0].addr;
- wavesize[j] = 256 * (1 << ((ai.wal[0].size) & 0x07));
-#if 1
- printf("%d addr = %d\n", j, waveaddr[j]);
- printf(" size = %d\n", wavesize[j]);
-#endif
+/**
+ * A function object (i.e. a functor) for testing if a FilesystemNode
+ * object's name is equal (Ignoring case) to a string or to at least
+ * one of the strings in a list of strings. Can be used e.g. with find_if().
+ */
+struct fsnodeNameEqualsIgnoreCase : public Common::UnaryFunction<const FilesystemNode&, bool> {
+ fsnodeNameEqualsIgnoreCase(const Common::StringList &str) : _str(str) {}
+ fsnodeNameEqualsIgnoreCase(const Common::String str) { _str.push_back(str); }
+ bool operator()(const FilesystemNode &param) const {
+ for (Common::StringList::const_iterator iter = _str.begin(); iter != _str.end(); iter++)
+ if (param.getName().equalsIgnoreCase(*iter))
+ return true;
+ return false;
}
+private:
+ Common::StringList _str;
+};
- numInstruments = j;
- printf("%d Ensoniq 5503 instruments loaded. (%d waveforms)\n", num_instruments, num_wav);
+bool SoundMgr::loadInstruments() {
+ // Check that the platform is Apple IIGS, as only it uses custom instruments
+ if (_vm->getPlatform() != Common::kPlatformApple2GS) {
+ debugC(3, kDebugLevelSound, "Platform isn't Apple IIGS so not loading any instruments");
+ return true;
+ }
+
+ // Get info on the particular Apple IIGS AGI game's executable
+ const IIgsExeInfo *exeInfo = getIIgsExeInfo((enum AgiGameID) _vm->getGameID());
+ if (exeInfo == NULL) {
+ warning("Unsupported Apple IIGS game, not loading instruments");
+ return false;
+ }
+
+ // List files in the game path
+ FSList fslist;
+ FilesystemNode dir(ConfMan.get("path"));
+ if (!dir.getChildren(fslist, FilesystemNode::kListFilesOnly)) {
+ warning("Invalid game path (\"%s\"), not loading Apple IIGS instruments", dir.getPath().c_str());
+ return false;
+ }
- fclose(fp);
+ // Populate executable filenames list (Long filename and short filename) for searching
+ Common::StringList exeNames;
+ exeNames.push_back(Common::String(exeInfo->exePrefix) + ".SYS16");
+ exeNames.push_back(Common::String(exeInfo->exePrefix) + ".SYS");
+
+ // Populate wave filenames list (Long filename and short filename) for searching
+ Common::StringList waveNames;
+ waveNames.push_back("SIERRASTANDARD");
+ waveNames.push_back("SIERRAST");
+
+ // Search for the executable file and the wave file (i.e. check if any of the filenames match)
+ FSList::const_iterator exeFsnode, waveFsnode;
+ exeFsnode = Common::find_if(fslist.begin(), fslist.end(), fsnodeNameEqualsIgnoreCase(exeNames));
+ waveFsnode = Common::find_if(fslist.begin(), fslist.end(), fsnodeNameEqualsIgnoreCase(waveNames));
+
+ // Make sure that we found the executable file
+ if (exeFsnode == fslist.end()) {
+ warning("Couldn't find Apple IIGS game executable (%s), not loading instruments", exeNames.begin()->c_str());
+ return false;
+ }
- return errOK;
-}
+ // Make sure that we found the wave file
+ if (waveFsnode == fslist.end()) {
+ warning("Couldn't find Apple IIGS wave file (%s), not loading instruments", waveNames.begin()->c_str());
+ return false;
+ }
-void Sound::unloadInstruments() {
- free(instruments);
-}
-#endif
+ // First load the wave file and then load the instrument headers.
+ // Finally fix the instruments' lengths using the wave file data
+ // (A zero in the wave file data can end the sample prematurely)
+ // and convert the wave file from 8-bit unsigned to 16-bit signed format.
+ Common::MemoryReadStream *uint8Wave = loadWaveFile(waveFsnode->getPath(), *exeInfo);
+ // Seek the wave to its
+ if (uint8Wave != NULL)
+ uint8Wave->seek(0);
+
+ bool result = uint8Wave != NULL && loadInstrumentHeaders(exeFsnode->getPath(), *exeInfo) &&
+ finalizeInstruments(*uint8Wave) && convertWave(*uint8Wave, g_wave, uint8Wave->size());
-#endif /* USE_IIGS_SOUND */
+ delete uint8Wave; // Free the 8-bit unsigned wave file buffer
+ return result;
+}
static void fillAudio(void *udata, int16 *stream, uint len) {
SoundMgr *soundMgr = (SoundMgr *)udata;
@@ -834,10 +1089,14 @@ static void fillAudio(void *udata, int16 *stream, uint len) {
n -= s;
}
-SoundMgr::SoundMgr(AgiEngine *agi, Audio::Mixer *pMixer) {
+SoundMgr::SoundMgr(AgiBase *agi, Audio::Mixer *pMixer) {
_vm = agi;
_mixer = pMixer;
_sampleRate = pMixer->getOutputRate();
+ _endflag = -1;
+ _playingSound = -1;
+ _sndBuffer = 0;
+ _waveform = 0;
}
void SoundMgr::premixerCall(int16 *data, uint len) {
diff --git a/engines/agi/sound.h b/engines/agi/sound.h
index 5b3a16668b..5d9bfda445 100644
--- a/engines/agi/sound.h
+++ b/engines/agi/sound.h
@@ -26,20 +26,23 @@
#ifndef AGI_SOUND_H
#define AGI_SOUND_H
+#include "agi/agi.h"
#include "sound/audiostream.h"
#include "sound/mixer.h"
+#include "common/frac.h"
namespace Agi {
#define BUFFER_SIZE 410
+#define IIGS_BUFFER_SIZE 200
#define SOUND_EMU_NONE 0
#define SOUND_EMU_PC 1
#define SOUND_EMU_TANDY 2
#define SOUND_EMU_MAC 3
#define SOUND_EMU_AMIGA 4
+#define SOUND_EMU_APPLE2GS 5
-#define SOUND_PLAYING 0x01
#define WAVEFORM_SIZE 64
#define ENV_ATTACK 10000 /**< envelope attack rate */
#define ENV_DECAY 1000 /**< envelope decay rate */
@@ -47,51 +50,197 @@ namespace Agi {
#define ENV_RELEASE 7500 /**< envelope release rate */
#define NUM_CHANNELS 7 /**< number of sound channels */
-/**
- * AGI sound resource structure.
- */
-struct AgiSound {
- uint32 flen; /**< size of raw data */
- uint8 *rdata; /**< raw sound data */
- uint8 flags; /**< sound flags */
- uint16 type; /**< sound resource type */
+// MIDI command values (Shifted right by 4 so they're in the lower nibble)
+#define MIDI_CMD_NOTE_OFF 0x08
+#define MIDI_CMD_NOTE_ON 0x09
+#define MIDI_CMD_CONTROLLER 0x0B
+#define MIDI_CMD_PROGRAM_CHANGE 0x0C
+#define MIDI_CMD_PITCH_WHEEL 0x0E
+// Whole MIDI byte values (Command and channel info together)
+#define MIDI_BYTE_STOP_SEQUENCE 0xFC
+#define MIDI_BYTE_TIMER_SYNC 0xF8
+
+struct IIgsEnvelopeSegment {
+ uint8 bp;
+ uint16 inc; ///< 8b.8b fixed point, very probably little endian
+};
+
+#define ENVELOPE_SEGMENT_COUNT 8
+struct IIgsEnvelope {
+ IIgsEnvelopeSegment seg[ENVELOPE_SEGMENT_COUNT];
+
+ /** Reads an Apple IIGS envelope from then given stream. */
+ bool read(Common::SeekableReadStream &stream);
+};
+
+// 2**(1/12) i.e. the 12th root of 2
+#define SEMITONE 1.059463094359295
+
+// C6's frequency is A4's (440 Hz) frequency but one full octave and three semitones higher
+// i.e. C6_FREQ = 440 * pow(2.0, 15/12.0)
+#define C6_FREQ 1046.502261202395
+
+// Size of the SIERRASTANDARD file (i.e. the wave file i.e. the sample data used by the instruments).
+#define SIERRASTANDARD_SIZE 65536
+
+// Maximum number of instruments in an Apple IIGS instrument set.
+// Chosen empirically based on Apple IIGS AGI game data, increase if needed.
+#define MAX_INSTRUMENTS 28
+
+struct IIgsWaveInfo {
+ uint8 top;
+ uint addr;
+ uint size;
+// Oscillator channel
+#define OSC_CHANNEL_RIGHT 0
+#define OSC_CHANNEL_LEFT 1
+ uint channel;
+// Oscillator mode
+#define OSC_MODE_LOOP 0
+#define OSC_MODE_ONESHOT 1
+#define OSC_MODE_SYNC_AM 2
+#define OSC_MODE_SWAP 3
+ uint mode;
+ bool halt;
+ int16 relPitch; ///< Relative pitch in semitones (Signed 8b.8b fixed point)
+
+ /** Reads an Apple IIGS wave information structure from the given stream. */
+ bool read(Common::SeekableReadStream &stream, bool ignoreAddr = false);
+ bool finalize(Common::SeekableReadStream &uint8Wave);
};
-#include "common/pack-start.h"
+// Number of waves per Apple IIGS sound oscillator
+#define WAVES_PER_OSCILLATOR 2
+
+/** An Apple IIGS sound oscillator. Consists always of two waves. */
+struct IIgsOscillator {
+ IIgsWaveInfo waves[WAVES_PER_OSCILLATOR];
+
+ bool finalize(Common::SeekableReadStream &uint8Wave);
+};
+
+// Maximum number of oscillators in an Apple IIGS instrument.
+// Chosen empirically based on Apple IIGS AGI game data, increase if needed.
+#define MAX_OSCILLATORS 4
+
+/** An Apple IIGS sound oscillator list. */
+struct IIgsOscillatorList {
+ uint count; ///< Oscillator count
+ IIgsOscillator osc[MAX_OSCILLATORS]; ///< The oscillators
+
+ /** Indexing operators for easier access to the oscillators. */
+ const IIgsOscillator &operator()(uint index) const { return osc[index]; }
+ IIgsOscillator &operator()(uint index) { return osc[index]; }
+
+ /** Reads an Apple IIGS oscillator list from the given stream. */
+ bool read(Common::SeekableReadStream &stream, uint oscillatorCount, bool ignoreAddr = false);
+ bool finalize(Common::SeekableReadStream &uint8Wave);
+};
+
+struct IIgsInstrumentHeader {
+ IIgsEnvelope env;
+ uint8 relseg;
+ uint8 bendrange;
+ uint8 vibdepth;
+ uint8 vibspeed;
+ IIgsOscillatorList oscList;
+
+ /**
+ * Read an Apple IIGS instrument header from the given stream.
+ * @param stream The source stream from which to read the data.
+ * @param ignoreAddr Should we ignore wave infos' wave address variable's value?
+ * @return True if successful, false otherwise.
+ */
+ bool read(Common::SeekableReadStream &stream, bool ignoreAddr = false);
+ bool finalize(Common::SeekableReadStream &uint8Wave);
+};
+
+struct IIgsSampleHeader {
+ uint16 type;
+ uint8 pitch; ///< Logarithmic, base is 2**(1/12), unknown multiplier (Possibly in range 1040-1080)
+ uint8 unknownByte_Ofs3; // 0x7F in Gold Rush's sound resource 60, 0 in all others.
+ uint8 volume; ///< Current guess: Logarithmic in 6 dB steps
+ uint8 unknownByte_Ofs5; ///< 0 in all tested samples.
+ uint16 instrumentSize; ///< Little endian. 44 in all tested samples. A guess.
+ uint16 sampleSize; ///< Little endian. Accurate in all tested samples excluding Manhunter I's sound resource 16.
+ IIgsInstrumentHeader instrument;
+
+ /**
+ * Read an Apple IIGS AGI sample header from the given stream.
+ * @param stream The source stream from which to read the data.
+ * @return True if successful, false otherwise.
+ */
+ bool read(Common::SeekableReadStream &stream);
+ bool finalize(Common::SeekableReadStream &uint8Wave);
+};
/**
* AGI sound note structure.
*/
struct AgiNote {
- uint8 durLo; /**< LSB of note duration */
- uint8 durHi; /**< MSB of note duration */
- uint8 frq0; /**< LSB of note frequency */
- uint8 frq1; /**< MSB of note frequency */
- uint8 vol; /**< note volume */
+ uint16 duration; ///< Note duration
+ uint16 freqDiv; ///< Note frequency divisor (10-bit)
+ uint8 attenuation; ///< Note volume attenuation (4-bit)
+
+ /** Reads an AgiNote through the given pointer. */
+ void read(const uint8 *ptr) {
+ duration = READ_LE_UINT16(ptr);
+ uint16 freqByte0 = *(ptr + 2); // Bits 4-9 of the frequency divisor
+ uint16 freqByte1 = *(ptr + 3); // Bits 0-3 of the frequency divisor
+ // Merge the frequency divisor's bits together into a single variable
+ freqDiv = ((freqByte0 & 0x3F) << 4) | (freqByte1 & 0x0F);
+ attenuation = *(ptr + 4) & 0x0F;
+ }
};
-#include "common/pack-end.h"
+struct IIgsChannelInfo {
+ IIgsInstrumentHeader ins; ///< Instrument info
+ const int16 *sample; ///< Source sample data (16-bit signed format)
+ frac_t pos; ///< Current sample position
+ frac_t posAdd; ///< Current sample position adder (Calculated using note, vibrato etc)
+ frac_t note; ///< Note
+ frac_t vol; ///< Current volume (Takes both channel volume and enveloping into account)
+ frac_t chanVol; ///< Channel volume
+ frac_t startEnvVol; ///< Starting envelope volume
+ frac_t envVol; ///< Current envelope volume
+ uint envSeg; ///< Current envelope segment
+ uint size; ///< Sample size
+ bool loop; ///< Should we loop the sample?
+ bool end; ///< Has the playing ended?
+};
+ /**
+ * AGI sound resource types.
+ * It's probably coincidence that all the values here are powers of two
+ * as they're simply the different used values in AGI sound resources'
+ * starts (The first 16-bit little endian word, to be precise).
+ */
+ enum AgiSoundType {
+ AGI_SOUND_SAMPLE = 0x0001,
+ AGI_SOUND_MIDI = 0x0002,
+ AGI_SOUND_4CHN = 0x0008
+ };
+ enum AgiSoundFlags {
+ AGI_SOUND_LOOP = 0x0001,
+ AGI_SOUND_ENVELOPE = 0x0002
+ };
+ enum AgiSoundEnv {
+ AGI_SOUND_ENV_ATTACK = 3,
+ AGI_SOUND_ENV_DECAY = 2,
+ AGI_SOUND_ENV_SUSTAIN = 1,
+ AGI_SOUND_ENV_RELEASE = 0
+ };
/**
* AGI engine sound channel structure.
*/
struct ChannelInfo {
-#define AGI_SOUND_SAMPLE 0x0001
-#define AGI_SOUND_MIDI 0x0002
-#define AGI_SOUND_4CHN 0x0008
- uint32 type;
- struct AgiNote *ptr;
- int16 *ins;
+ AgiSoundType type;
+ const uint8 *ptr; // Pointer to the AgiNote data
+ const int16 *ins;
int32 size;
uint32 phase;
-#define AGI_SOUND_LOOP 0x0001
-#define AGI_SOUND_ENVELOPE 0x0002
- uint32 flags;
-#define AGI_SOUND_ENV_ATTACK 3
-#define AGI_SOUND_ENV_DECAY 2
-#define AGI_SOUND_ENV_SUSTAIN 1
-#define AGI_SOUND_ENV_RELEASE 0
- uint32 adsr;
+ uint32 flags; // ORs values from AgiSoundFlags
+ AgiSoundEnv adsr;
int32 timer;
uint32 end;
uint32 freq;
@@ -99,13 +248,101 @@ struct ChannelInfo {
uint32 env;
};
+class SoundMgr;
+
+/**
+ * AGI sound resource structure.
+ */
+class AgiSound {
+public:
+ AgiSound(SoundMgr &manager) : _manager(manager), _isPlaying(false), _isValid(false) {}
+ virtual ~AgiSound() {}
+ virtual void play() { _isPlaying = true; }
+ virtual void stop() { _isPlaying = false; }
+ virtual bool isPlaying() { return _isPlaying; }
+ virtual uint16 type() = 0;
+
+ /**
+ * A named constructor for creating different types of AgiSound objects
+ * from a raw sound resource.
+ *
+ * NOTE: This function should take responsibility for freeing the raw resource
+ * from memory using free() or delegate the responsibility onwards to some other
+ * function!
+ */
+ static AgiSound *createFromRawResource(uint8 *data, uint32 len, int resnum, SoundMgr &manager);
+
+protected:
+ SoundMgr &_manager; ///< AGI sound manager object
+ bool _isPlaying; ///< Is the sound playing?
+ bool _isValid; ///< Is this a valid sound object?
+};
+
+class PCjrSound : public AgiSound {
+public:
+ PCjrSound(uint8 *data, uint32 len, int resnum, SoundMgr &manager);
+ ~PCjrSound() { if (_data != NULL) free(_data); }
+ virtual uint16 type() { return _type; }
+ const uint8 *getVoicePointer(uint voiceNum);
+protected:
+ uint8 *_data; ///< Raw sound resource data
+ uint32 _len; ///< Length of the raw sound resource
+ uint16 _type; ///< Sound resource type
+};
+
+class IIgsMidi : public AgiSound {
+public:
+ IIgsMidi(uint8 *data, uint32 len, int resnum, SoundMgr &manager);
+ ~IIgsMidi() { if (_data != NULL) free(_data); }
+ virtual uint16 type() { return _type; }
+ virtual const uint8 *getPtr() { return _ptr; }
+ virtual void setPtr(const uint8 *ptr) { _ptr = ptr; }
+ virtual void rewind() { _ptr = _data + 2; }
+protected:
+ uint8 *_data; ///< Raw sound resource data
+ const uint8 *_ptr; ///< Pointer to the current position in the MIDI data
+ uint32 _len; ///< Length of the raw sound resource
+ uint16 _type; ///< Sound resource type
+};
+
+class IIgsSample : public AgiSound {
+public:
+ IIgsSample(uint8 *data, uint32 len, int resnum, SoundMgr &manager);
+ ~IIgsSample() { delete[] _sample; }
+ virtual uint16 type() { return _header.type; }
+ const IIgsSampleHeader &getHeader() const { return _header; }
+ const int16 *getSample() const { return _sample; }
+protected:
+ IIgsSampleHeader _header; ///< Apple IIGS AGI sample header
+ int16 *_sample; ///< Sample data (16-bit signed format)
+};
+
+/** Apple IIGS AGI instrument set information. */
+struct instrumentSetInfo {
+ uint byteCount; ///< Length of the whole instrument set in bytes
+ uint instCount; ///< Amount of instrument in the set
+ const char *md5; ///< MD5 hex digest of the whole instrument set
+ const char *waveFileMd5; ///< MD5 hex digest of the wave file (i.e. the sample data used by the instruments)
+};
+
+/** Apple IIGS AGI executable file information. */
+struct IIgsExeInfo {
+ enum AgiGameID gameid; ///< Game ID
+ const char *exePrefix; ///< Prefix of the Apple IIGS AGI executable (e.g. "SQ", "PQ", "KQ4" etc)
+ uint agiVer; ///< Apple IIGS AGI version number, not strictly needed
+ uint exeSize; ///< Size of the Apple IIGS AGI executable file in bytes
+ uint instSetStart; ///< Starting offset of the instrument set inside the executable file
+ const instrumentSetInfo &instSet; ///< Information about the used instrument set
+};
+
class AgiEngine;
+class AgiBase;
class SoundMgr : public Audio::AudioStream {
- AgiEngine *_vm;
+ AgiBase *_vm;
public:
- SoundMgr(AgiEngine *agi, Audio::Mixer *pMixer);
+ SoundMgr(AgiBase *agi, Audio::Mixer *pMixer);
~SoundMgr();
virtual void setVolume(uint8 volume);
@@ -133,11 +370,19 @@ private:
Audio::SoundHandle _soundHandle;
uint32 _sampleRate;
+ bool _playing;
+ ChannelInfo _chn[NUM_CHANNELS];
+ IIgsChannelInfo _IIgsChannel;
+ int _endflag;
+ int _playingSound;
+ uint8 _env;
+
+ int16 *_sndBuffer;
+ const int16 *_waveform;
+
void premixerCall(int16 *buf, uint len);
public:
-
- void decodeSound(int);
void unloadSound(int);
void playSound();
int initSound();
@@ -148,11 +393,15 @@ public:
void playNote(int i, int freq, int vol);
void playAgiSound();
uint32 mixSound();
- int loadInstruments(char *fname);
-#ifdef USE_IIGS_SOUND
+ bool loadInstruments();
void playMidiSound();
void playSampleSound();
-#endif
+ bool finalizeInstruments(Common::SeekableReadStream &uint8Wave);
+ Audio::AudioStream *makeIIgsSampleStream(Common::SeekableReadStream &stream, int resnum = -1);
+ const IIgsExeInfo *getIIgsExeInfo(enum AgiGameID gameid) const;
+ bool loadInstrumentHeaders(const Common::String &exePath, const IIgsExeInfo &exeInfo);
+ bool convertWave(Common::SeekableReadStream &source, int16 *dest, uint length);
+ Common::MemoryReadStream *loadWaveFile(const Common::String &wavePath, const IIgsExeInfo &exeInfo);
};
} // End of namespace Agi
diff --git a/engines/agi/text.cpp b/engines/agi/text.cpp
index 1d653a9415..bb334d0401 100644
--- a/engines/agi/text.cpp
+++ b/engines/agi/text.cpp
@@ -67,6 +67,8 @@ void AgiEngine::printText2(int l, const char *msg, int foff, int xoff, int yoff,
for (m = (const unsigned char *)msg, x1 = y1 = 0; *m; m++) {
if (*m >= 0x20 || *m == 1 || *m == 2 || *m == 3) {
+ // FIXME: Fingolfin asks: why is there a FIXME here? Please either clarify what
+ // needs fixing, or remove it!
/* FIXME */
int ypos;
diff --git a/engines/agos/agos.cpp b/engines/agos/agos.cpp
index 76e4378982..aa927b1dcd 100644
--- a/engines/agos/agos.cpp
+++ b/engines/agos/agos.cpp
@@ -37,21 +37,10 @@
#include "sound/mididrv.h"
#include "sound/mods/protracker.h"
-#ifdef PALMOS_68K
-#include "globals.h"
-#endif
-
using Common::File;
namespace AGOS {
-#ifdef PALMOS_68K
-#define PTR(a) a
-static const GameSpecificSettings *simon1_settings;
-static const GameSpecificSettings *simon2_settings;
-static const GameSpecificSettings *feeblefiles_settings;
-#else
-#define PTR(a) &a
static const GameSpecificSettings simon1_settings = {
"EFFECTS", // effects_filename
"SIMON", // speech_filename
@@ -71,8 +60,6 @@ static const GameSpecificSettings puzzlepack_settings = {
"", // effects_filename
"MUSIC", // speech_filename
};
-#endif
-
AGOSEngine_PuzzlePack::AGOSEngine_PuzzlePack(OSystem *system)
: AGOSEngine_Feeble(system) {
@@ -692,13 +679,9 @@ static const uint16 initialVideoWindows_Common[20] = {
};
void AGOSEngine_PuzzlePack::setupGame() {
- gss = PTR(puzzlepack_settings);
+ gss = &puzzlepack_settings;
_numVideoOpcodes = 85;
-#ifndef PALMOS_68K
_vgaMemSize = 7500000;
-#else
- _vgaMemSize = gVars->memory[kMemSimon2Games];
-#endif
_itemMemSize = 20000;
_tableMemSize = 200000;
_frameCount = 1;
@@ -713,13 +696,9 @@ void AGOSEngine_PuzzlePack::setupGame() {
}
void AGOSEngine_Feeble::setupGame() {
- gss = PTR(feeblefiles_settings);
+ gss = &feeblefiles_settings;
_numVideoOpcodes = 85;
-#ifndef PALMOS_68K
_vgaMemSize = 7500000;
-#else
- _vgaMemSize = gVars->memory[kMemSimon2Games];
-#endif
_itemMemSize = 20000;
_tableMemSize = 200000;
_frameCount = 1;
@@ -736,14 +715,12 @@ void AGOSEngine_Feeble::setupGame() {
}
void AGOSEngine_Simon2::setupGame() {
- gss = PTR(simon2_settings);
+ gss = &simon2_settings;
_tableIndexBase = 1580 / 4;
_textIndexBase = 1500 / 4;
_numVideoOpcodes = 75;
#if defined(__DS__)
_vgaMemSize = 1300000;
-#elif defined(PALMOS_68K)
- _vgaMemSize = gVars->memory[kMemSimon2Games];
#else
_vgaMemSize = 2000000;
#endif
@@ -772,15 +749,11 @@ void AGOSEngine_Simon2::setupGame() {
}
void AGOSEngine_Simon1::setupGame() {
- gss = PTR(simon1_settings);
+ gss = &simon1_settings;
_tableIndexBase = 1576 / 4;
_textIndexBase = 1460 / 4;
_numVideoOpcodes = 64;
-#ifndef PALMOS_68K
_vgaMemSize = 1000000;
-#else
- _vgaMemSize = gVars->memory[kMemSimon1Games];
-#endif
_itemMemSize = 20000;
_tableMemSize = 50000;
_musicIndexBase = 1316 / 4;
@@ -802,13 +775,9 @@ void AGOSEngine_Simon1::setupGame() {
}
void AGOSEngine_Waxworks::setupGame() {
- gss = PTR(simon1_settings);
+ gss = &simon1_settings;
_numVideoOpcodes = 64;
-#ifndef PALMOS_68K
_vgaMemSize = 1000000;
-#else
- _vgaMemSize = gVars->memory[kMemSimon1Games];
-#endif
_itemMemSize = 80000;
_tableMemSize = 50000;
_frameCount = 4;
@@ -826,13 +795,9 @@ void AGOSEngine_Waxworks::setupGame() {
}
void AGOSEngine_Elvira2::setupGame() {
- gss = PTR(simon1_settings);
+ gss = &simon1_settings;
_numVideoOpcodes = 60;
-#ifndef PALMOS_68K
_vgaMemSize = 1000000;
-#else
- _vgaMemSize = gVars->memory[kMemSimon1Games];
-#endif
_itemMemSize = 64000;
_tableMemSize = 100000;
_frameCount = 4;
@@ -849,13 +814,9 @@ void AGOSEngine_Elvira2::setupGame() {
}
void AGOSEngine_Elvira1::setupGame() {
- gss = PTR(simon1_settings);
+ gss = &simon1_settings;
_numVideoOpcodes = 57;
-#ifndef PALMOS_68K
_vgaMemSize = 1000000;
-#else
- _vgaMemSize = gVars->memory[kMemSimon1Games];
-#endif
_itemMemSize = 64000;
_tableMemSize = 256000;
_frameCount = 4;
@@ -1094,20 +1055,3 @@ void AGOSEngine::shutdown() {
}
} // End of namespace AGOS
-
-#ifdef PALMOS_68K
-#include "scumm_globals.h"
-
-_GINIT(AGOS_AGOS)
-_GSETPTR(AGOS::simon1_settings, GBVARS_SIMON1SETTINGS_INDEX, AGOS::GameSpecificSettings, GBVARS_AGOS)
-_GSETPTR(AGOS::simon2_settings, GBVARS_SIMON2SETTINGS_INDEX, AGOS::GameSpecificSettings, GBVARS_AGOS)
-_GSETPTR(AGOS::feeblefiles_settings, GBVARS_FEEBLEFILESSETTINGS_INDEX, AGOS::GameSpecificSettings, GBVARS_AGOS)
-_GEND
-
-_GRELEASE(AGOS_AGOS)
-_GRELEASEPTR(GBVARS_SIMON1SETTINGS_INDEX, GBVARS_AGOS)
-_GRELEASEPTR(GBVARS_SIMON2SETTINGS_INDEX, GBVARS_AGOS)
-_GRELEASEPTR(GBVARS_FEEBLEFILESSETTINGS_INDEX, GBVARS_AGOS)
-_GEND
-
-#endif
diff --git a/engines/agos/charset.cpp b/engines/agos/charset.cpp
index 9a37d90c33..68eb2d7ac8 100644
--- a/engines/agos/charset.cpp
+++ b/engines/agos/charset.cpp
@@ -543,7 +543,15 @@ void AGOSEngine::justifyOutPut(byte chr) {
doOutput(&chr, 1);
clsCheck(_textWindow);
} else if (chr == 0 || chr == ' ' || chr == 10) {
- if (_printCharMaxPos - _printCharCurPos >= _printCharPixelCount) {
+ bool fit;
+
+ if (getGameType() == GType_FF || getGameType() == GType_PP) {
+ fit = _printCharMaxPos - _printCharCurPos > _printCharPixelCount;
+ } else {
+ fit = _printCharMaxPos - _printCharCurPos >= _printCharPixelCount;
+ }
+
+ if (fit) {
_printCharCurPos += _printCharPixelCount;
doOutput(_lettersToPrintBuf, _numLettersToPrint);
@@ -741,22 +749,6 @@ void AGOSEngine::windowScroll(WindowBlock *window) {
_lockWord &= ~0x8000;
}
-#ifdef PALMOS_68K
-static const byte *feeble_windowFont;
-static const byte *czech_simonFont;
-static const byte *russian_simonFont;
-static const byte *polish_simonFont;
-static const byte *french_simonFont;
-static const byte *german_simonFont;
-static const byte *hebrew_simonFont;
-static const byte *italian_simonFont;
-static const byte *spanish_simonFont;
-static const byte *english_simonFont;
-static const byte *spanish_commonFont;
-static const byte *italian_commonFont;
-static const byte *french_commonFont;
-static const byte *english_commonFont;
-#else
static const byte feeble_windowFont[] = {
0,0,0,0,0,0,0,0,0,0,0,0,0,
128,128,128,128,128,128,128,0,0,128,0,0,0,
@@ -2267,7 +2259,6 @@ static const byte english_commonFont[] = {
0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC,
0x00, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0x00,
};
-#endif
void AGOSEngine::windowDrawChar(WindowBlock *window, uint x, uint y, byte chr) {
const byte *src;
@@ -2379,29 +2370,3 @@ void AGOSEngine::windowDrawChar(WindowBlock *window, uint x, uint y, byte chr) {
} // End of namespace AGOS
-#ifdef PALMOS_68K
-#include "scumm_globals.h"
-
-_GINIT(AGOS_Charset)
-_GSETPTR(AGOS::russian_windowFont, GBVARS_RUSSIANVIDEOFONT_INDEX, byte, GBVARS_AGOS)
-//_GSETPTR(AGOS::polish_windowFont, GBVARS_POLISHVIDEOFONT_INDEX, byte, GBVARS_AGOS)
-_GSETPTR(AGOS::french_windowFont, GBVARS_FRENCHVIDEOFONT_INDEX, byte, GBVARS_AGOS)
-_GSETPTR(AGOS::german_windowFont, GBVARS_GERMANVIDEOFONT_INDEX, byte, GBVARS_AGOS)
-_GSETPTR(AGOS::hebrew_windowFont, GBVARS_HEBREWVIDEOFONT_INDEX, byte, GBVARS_AGOS)
-_GSETPTR(AGOS::italian_windowFont, GBVARS_ITALIANVIDEOFONT_INDEX, byte, GBVARS_AGOS)
-_GSETPTR(AGOS::spanish_windowFont, GBVARS_SPANISHVIDEOFONT_INDEX, byte, GBVARS_AGOS)
-_GSETPTR(AGOS::english_windowFont, GBVARS_VIDEOFONT_INDEX, byte, GBVARS_AGOS)
-_GEND
-
-_GRELEASE(AGOS_Charset)
-_GRELEASEPTR(GBVARS_RUSSIANVIDEOFONT_INDEX, GBVARS_AGOS)
-//_GRELEASEPTR(GBVARS_POLISHVIDEOFONT_INDEX, GBVARS_AGOS)
-_GRELEASEPTR(GBVARS_FRENCHVIDEOFONT_INDEX, GBVARS_AGOS)
-_GRELEASEPTR(GBVARS_GERMANVIDEOFONT_INDEX, GBVARS_AGOS)
-_GRELEASEPTR(GBVARS_HEBREWVIDEOFONT_INDEX, GBVARS_AGOS)
-_GRELEASEPTR(GBVARS_ITALIANVIDEOFONT_INDEX, GBVARS_AGOS)
-_GRELEASEPTR(GBVARS_SPANISHVIDEOFONT_INDEX, GBVARS_AGOS)
-_GRELEASEPTR(GBVARS_VIDEOFONT_INDEX, GBVARS_AGOS)
-_GEND
-
-#endif
diff --git a/engines/agos/cursor.cpp b/engines/agos/cursor.cpp
index 35bb8ea216..9c2cb42988 100644
--- a/engines/agos/cursor.cpp
+++ b/engines/agos/cursor.cpp
@@ -790,16 +790,3 @@ void AGOSEngine::drawMousePointer() {
}
} // End of namespace AGOS
-
-#ifdef PALMOS_68K
-#include "scumm_globals.h"
-
-_GINIT(AGOS_Cursor)
-_GSETPTR(AGOS::_simon1_cursor, GBVARS_SIMON1CURSOR_INDEX, byte, GBVARS_AGOS)
-_GEND
-
-_GRELEASE(AGOS_Cursor)
-_GRELEASEPTR(GBVARS_SIMON1CURSOR_INDEX, GBVARS_AGOS)
-_GEND
-
-#endif
diff --git a/engines/agos/detection.cpp b/engines/agos/detection.cpp
index 0f5aa2768a..31ff220412 100644
--- a/engines/agos/detection.cpp
+++ b/engines/agos/detection.cpp
@@ -18,8 +18,8 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
- * $URL:https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/branches/gsoc2007-fsnode/engines/agos/detection.cpp $
- * $Id:detection.cpp 26949 2007-05-26 20:23:24Z david_corrales $
+ * $URL$
+ * $Id$
*
*/
@@ -101,55 +101,42 @@ static const Common::ADParams detectionParams = {
Common::kADFlagAugmentPreferredTarget
};
-GameList Engine_AGOS_gameIDList() {
- return GameList(simonGames);
-}
-
-GameDescriptor Engine_AGOS_findGameID(const char *gameid) {
- return Common::AdvancedDetector::findGameID(gameid, simonGames, obsoleteGameIDsTable);
-}
+bool engineCreateAgos(OSystem *syst, Engine **engine, Common::EncapsulatedADGameDesc encapsulatedDesc) {
+ const AGOS::AGOSGameDescription *gd = (const AGOS::AGOSGameDescription *)(encapsulatedDesc.realDesc);
+ bool res = true;
-GameList Engine_AGOS_detectGames(const FSList &fslist) {
- return Common::AdvancedDetector::detectAllGames(fslist, detectionParams);
-}
-
-PluginError Engine_AGOS_create(OSystem *syst, Engine **engine) {
- assert(engine);
- const char *gameid = ConfMan.get("gameid").c_str();
-
- //Common::EncapsulatedADGameDesc encapsulatedDesc = Common::AdvancedDetector::detectBestMatchingGame(detectionParams);
- //const AGOSGameDescription *gd = (const AGOSGameDescription *)(encapsulatedDesc.realDesc);
- //if (gd == 0) {
- // return kNoGameDataFoundError;
- //}
-
- if (!scumm_stricmp("elvira1", gameid)) {
+ switch (gd->gameType) {
+ case AGOS::GType_ELVIRA1:
*engine = new AGOS::AGOSEngine_Elvira1(syst);
- } else if (!scumm_stricmp("elvira2", gameid)) {
+ break;
+ case AGOS::GType_ELVIRA2:
*engine = new AGOS::AGOSEngine_Elvira2(syst);
- } else if (!scumm_stricmp("waxworks", gameid)) {
+ break;
+ case AGOS::GType_WW:
*engine = new AGOS::AGOSEngine_Waxworks(syst);
- } else if (!scumm_stricmp("simon1", gameid)) {
+ break;
+ case AGOS::GType_SIMON1:
*engine = new AGOS::AGOSEngine_Simon1(syst);
- } else if (!scumm_stricmp("simon2", gameid)) {
+ break;
+ case AGOS::GType_SIMON2:
*engine = new AGOS::AGOSEngine_Simon2(syst);
- } else if (!scumm_stricmp("feeble", gameid)) {
+ break;
+ case AGOS::GType_FF:
*engine = new AGOS::AGOSEngine_Feeble(syst);
- } else if (!scumm_stricmp("dimp", gameid)) {
- *engine = new AGOS::AGOSEngine_PuzzlePack(syst);
- } else if (!scumm_stricmp("jumble", gameid)) {
+ break;
+ case AGOS::GType_PP:
*engine = new AGOS::AGOSEngine_PuzzlePack(syst);
- } else if (!scumm_stricmp("puzzle", gameid)) {
- *engine = new AGOS::AGOSEngine_PuzzlePack(syst);
- } else if (!scumm_stricmp("swampy", gameid)) {
- *engine = new AGOS::AGOSEngine_PuzzlePack(syst);
- } else {
- error("AGOS engine created with invalid gameid");
+ break;
+ default:
+ res = false;
+ error("AGOS engine: unknown gameType");
}
- return kNoError;
+ return res;
}
-
+
+ADVANCED_DETECTOR_DEFINE_PLUGIN_WITH_COMPLEX_CREATION(AGOS, engineCreateAgos, detectionParams);
+
REGISTER_PLUGIN(AGOS, "AGOS", "AGOS (C) Adventure Soft");
namespace AGOS {
diff --git a/engines/agos/detection_tables.h b/engines/agos/detection_tables.h
index 988de6729b..f600b3febf 100644
--- a/engines/agos/detection_tables.h
+++ b/engines/agos/detection_tables.h
@@ -18,8 +18,8 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
- * $URL:https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/branches/gsoc2007-fsnode/engines/agos/detection_tables.h $
- * $Id:detection_tables.h 26949 2007-05-26 20:23:24Z david_corrales $
+ * $URL$
+ * $Id$
*
*/
@@ -290,6 +290,31 @@ static const AGOSGameDescription gameDescriptions[] = {
GF_OLD_BUNDLE | GF_CRUNCHED | GF_PLANAR
},
+ // Elvira 2 - German Amiga Floppy
+ {
+ {
+ "elvira2",
+ "Floppy",
+
+ {
+ { "menus.dat", GAME_MENUFILE, "a2fdc88a77c8bdffec6b36cbeda4d955", -1},
+ { "stripped.txt", GAME_STRFILE, "41c975a9c1106cb5298a0bc3df0a266e", -1},
+ { "gameamiga", GAME_BASEFILE, "7af80eb9759bcafcd8df21e61c5af200", -1},
+ { "icon.dat", GAME_ICONFILE, "a88b1c02e13ab04dd790ec30502c323d", -1},
+ { "tbllist", GAME_TBLFILE, "177f5f2640e80ef92d1421d32de06a5e", -1},
+ { "start", GAME_RESTFILE, "a9f876c6c66dfd011b971da3dc7b4ada", -1},
+ { NULL, 0, NULL, 0}
+ },
+ Common::DE_DEU,
+ Common::kPlatformAmiga,
+ Common::ADGF_NO_FLAGS
+ },
+
+ GType_ELVIRA2,
+ GID_ELVIRA2,
+ GF_OLD_BUNDLE | GF_CRUNCHED | GF_PLANAR
+ },
+
// Elvira 2 - Italian Amiga Floppy
{
{
diff --git a/engines/agos/draw.cpp b/engines/agos/draw.cpp
index bb28da73b5..68bb152844 100644
--- a/engines/agos/draw.cpp
+++ b/engines/agos/draw.cpp
@@ -503,8 +503,8 @@ void AGOSEngine::saveBackGround(VgaSprite *vsp) {
if (_window3Flag == 1) {
animTable->srcPtr = (const byte *)_window4BackScn;
} else {
- uint xoffs = (_videoWindows[vsp->windowNum * 4 + 0] * 2 + x) * 8;
- uint yoffs = (_videoWindows[vsp->windowNum * 4 + 1] + y);
+ int xoffs = (_videoWindows[vsp->windowNum * 4 + 0] * 2 + x) * 8;
+ int yoffs = (_videoWindows[vsp->windowNum * 4 + 1] + y);
animTable->srcPtr = getBackGround() + xoffs + yoffs * _screenWidth;
}
diff --git a/engines/agos/gfx.cpp b/engines/agos/gfx.cpp
index 15937db0da..20ab84d15d 100644
--- a/engines/agos/gfx.cpp
+++ b/engines/agos/gfx.cpp
@@ -668,7 +668,7 @@ void AGOSEngine_Simon1::drawImage(VC10_state *state) {
if (_windowNum == 4 || (_windowNum >= 10 && _windowNum <= 27)) {
state->surf2_addr = getBackGround();
state->surf2_pitch = _screenWidth;
-
+
state->surf_addr = _window4BackScn;
state->surf_pitch = _videoWindows[18] * 16;
diff --git a/engines/agos/intern.h b/engines/agos/intern.h
index 44d38fbeed..a6d843d183 100644
--- a/engines/agos/intern.h
+++ b/engines/agos/intern.h
@@ -187,13 +187,8 @@ struct TimeEvent {
};
struct GameSpecificSettings {
-#ifndef PALMOS_68K
const char *effects_filename;
const char *speech_filename;
- #else
- const char effects_filename[12];
- const char speech_filename[12];
- #endif
};
enum BoxFlags {
diff --git a/engines/cine/sound.cpp b/engines/cine/sound.cpp
index 4746e87a66..4ba083a653 100644
--- a/engines/cine/sound.cpp
+++ b/engines/cine/sound.cpp
@@ -18,8 +18,8 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
- * $URL:https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/branches/gsoc2007-fsnode/engines/cine/sound.cpp $
- * $Id:sound.cpp 26949 2007-05-26 20:23:24Z david_corrales $
+ * $URL$
+ * $Id$
*
*/
diff --git a/engines/cine/sound.h b/engines/cine/sound.h
index 4ebda2c236..719f37f151 100644
--- a/engines/cine/sound.h
+++ b/engines/cine/sound.h
@@ -18,8 +18,8 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
- * $URL:https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/branches/gsoc2007-fsnode/engines/cine/sound.h $
- * $Id:sound.h 26949 2007-05-26 20:23:24Z david_corrales $
+ * $URL$
+ * $Id$
*
*/
diff --git a/engines/cruise/actor.cpp b/engines/cruise/actor.cpp
index dd38e15838..c4af217117 100644
--- a/engines/cruise/actor.cpp
+++ b/engines/cruise/actor.cpp
@@ -18,8 +18,8 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
- * $URL:https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/branches/gsoc2007-fsnode/engines/cruise/actor.cpp $
- * $Id:actor.cpp 26949 2007-05-26 20:23:24Z david_corrales $
+ * $URL$
+ * $Id$
*
*/
@@ -471,8 +471,7 @@ void valide_noeud(int16 table[], int16 p, int *nclick, int16 solution0[20 + 3][2
(*nclick)++;
ctpVar19 = ctpVar11;
- if (*nclick == 2) // second point
- {
+ if (*nclick == 2) { // second point
x1 = table_ptselect[0][0];
y1 = table_ptselect[0][1];
x2 = table_ptselect[1][0];
@@ -858,26 +857,18 @@ void processAnimation(void) {
currentActor->phase = ANIM_PHASE_MOVE;
}
- if ((currentActor->counter >=
- 0)
- && ((currentActor->phase ==
- ANIM_PHASE_STATIC_END)
- || (currentActor->
- phase ==
- ANIM_PHASE_STATIC)))
+ if ((currentActor->counter >= 0)
+ && ((currentActor->phase == ANIM_PHASE_STATIC_END)
+ || (currentActor->phase == ANIM_PHASE_STATIC)))
{
int newA;
int inc = 1;
- int t_inc =
- currentActor->
- startDirection - 1;
+ int t_inc = currentActor->startDirection - 1;
if (t_inc < 0)
t_inc = 3;
- if (currentActor->
- nextDirection ==
- t_inc)
+ if (currentActor->nextDirection == t_inc)
inc = -1;
if (inc > 0)
diff --git a/engines/cruise/actor.h b/engines/cruise/actor.h
index 072eef9581..43b9b03e87 100644
--- a/engines/cruise/actor.h
+++ b/engines/cruise/actor.h
@@ -18,8 +18,8 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
- * $URL:https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/branches/gsoc2007-fsnode/engines/cruise/actor.h $
- * $Id:actor.h 26949 2007-05-26 20:23:24Z david_corrales $
+ * $URL$
+ * $Id$
*
*/
diff --git a/engines/cruise/background.cpp b/engines/cruise/background.cpp
index ebf0b78934..f23c331eb8 100644
--- a/engines/cruise/background.cpp
+++ b/engines/cruise/background.cpp
@@ -18,8 +18,8 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
- * $URL:https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/branches/gsoc2007-fsnode/engines/cruise/background.cpp $
- * $Id:background.cpp 26949 2007-05-26 20:23:24Z david_corrales $
+ * $URL$
+ * $Id$
*
*/
@@ -98,8 +98,7 @@ int loadBackground(char *name, int idx) {
backgroundPtrtable[idx] =
(uint8 *) mallocAndZero(320 * 200 /*64000 */ );
}
-/* else
- {
+/* else {
backgroundPtrtable[idx] = hwMemAddr[idx];
} */
}
diff --git a/engines/cruise/background.h b/engines/cruise/background.h
index b8b9e623c6..d506d1663e 100644
--- a/engines/cruise/background.h
+++ b/engines/cruise/background.h
@@ -18,8 +18,8 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
- * $URL:https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/branches/gsoc2007-fsnode/engines/cruise/background.h $
- * $Id:background.h 26949 2007-05-26 20:23:24Z david_corrales $
+ * $URL$
+ * $Id$
*
*/
diff --git a/engines/cruise/backgroundIncrust.cpp b/engines/cruise/backgroundIncrust.cpp
index edaa68b490..7e79c048b1 100644
--- a/engines/cruise/backgroundIncrust.cpp
+++ b/engines/cruise/backgroundIncrust.cpp
@@ -18,8 +18,8 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
- * $URL:https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/branches/gsoc2007-fsnode/engines/cruise/backgroundIncrust.cpp $
- * $Id:backgroundIncrust.cpp 26949 2007-05-26 20:23:24Z david_corrales $
+ * $URL$
+ * $Id$
*
*/
@@ -113,8 +113,7 @@ backgroundIncrustStruct *addBackgroundIncrust(int16 overlayIdx,
newElement->ptr = NULL;
strcpy(newElement->name, filesDatabase[params.fileIdx].subData.name);
- if (filesDatabase[params.fileIdx].subData.resourceType == 4) // sprite
- {
+ if (filesDatabase[params.fileIdx].subData.resourceType == 4) { // sprite
int width = filesDatabase[params.fileIdx].width;
int height = filesDatabase[params.fileIdx].height;
@@ -125,8 +124,7 @@ backgroundIncrustStruct *addBackgroundIncrust(int16 overlayIdx,
newElement->Y, newElement->X, (char *)backgroundPtr,
(char *)filesDatabase[params.fileIdx].subData.ptr);
// ASSERT(0);
- } else // poly
- {
+ } else { // poly
/* if(param4 == 1)
* {
* int var_A;
diff --git a/engines/cruise/backgroundIncrust.h b/engines/cruise/backgroundIncrust.h
index 3f61faadae..6de30978fd 100644
--- a/engines/cruise/backgroundIncrust.h
+++ b/engines/cruise/backgroundIncrust.h
@@ -18,8 +18,8 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
- * $URL:https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/branches/gsoc2007-fsnode/engines/cruise/backgroundIncrust.h $
- * $Id:backgroundIncrust.h 26949 2007-05-26 20:23:24Z david_corrales $
+ * $URL$
+ * $Id$
*
*/
diff --git a/engines/cruise/cell.cpp b/engines/cruise/cell.cpp
index 8a7b524a7b..d4b5aaed66 100644
--- a/engines/cruise/cell.cpp
+++ b/engines/cruise/cell.cpp
@@ -18,8 +18,8 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
- * $URL:https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/branches/gsoc2007-fsnode/engines/cruise/cell.cpp $
- * $Id:cell.cpp 26949 2007-05-26 20:23:24Z david_corrales $
+ * $URL$
+ * $Id$
*
*/
diff --git a/engines/cruise/cell.h b/engines/cruise/cell.h
index ea2fb7e777..c10ab93541 100644
--- a/engines/cruise/cell.h
+++ b/engines/cruise/cell.h
@@ -18,8 +18,8 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
- * $URL:https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/branches/gsoc2007-fsnode/engines/cruise/cell.h $
- * $Id:cell.h 26949 2007-05-26 20:23:24Z david_corrales $
+ * $URL$
+ * $Id$
*
*/
diff --git a/engines/cruise/cruise.cpp b/engines/cruise/cruise.cpp
index b427498c6f..9693fb7d03 100644
--- a/engines/cruise/cruise.cpp
+++ b/engines/cruise/cruise.cpp
@@ -18,8 +18,8 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
- * $URL:https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/branches/gsoc2007-fsnode/engines/cruise/cruise.cpp $
- * $Id:cruise.cpp 26949 2007-05-26 20:23:24Z david_corrales $
+ * $URL$
+ * $Id$
*
*/
diff --git a/engines/cruise/cruise.h b/engines/cruise/cruise.h
index cf768d8d57..73de46c599 100644
--- a/engines/cruise/cruise.h
+++ b/engines/cruise/cruise.h
@@ -18,8 +18,8 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
- * $URL:https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/branches/gsoc2007-fsnode/engines/cruise/cruise.h $
- * $Id:cruise.h 26949 2007-05-26 20:23:24Z david_corrales $
+ * $URL$
+ * $Id$
*
*/
diff --git a/engines/cruise/cruise_main.cpp b/engines/cruise/cruise_main.cpp
index 79a699433f..b3b0077ee7 100644
--- a/engines/cruise/cruise_main.cpp
+++ b/engines/cruise/cruise_main.cpp
@@ -18,8 +18,8 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
- * $URL:https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/branches/gsoc2007-fsnode/engines/cruise/cruise_main.cpp $
- * $Id:cruise_main.cpp 26949 2007-05-26 20:23:24Z david_corrales $
+ * $URL$
+ * $Id$
*
*/
@@ -627,192 +627,98 @@ int getCursorFromObject(int mouseX, int mouseY, int *outX, int *outY) {
cellStruct *currentObject = cellHead.prev;
while (currentObject) {
- if (currentObject->overlay >= 0) {
- if (overlayTable[currentObject->overlay].alreadyLoaded) {
- if (currentObject->type == 4
- || currentObject->type == 1
- || currentObject->type == 9
- || currentObject->type == 3) {
- strcpy(objectName,
- getObjectName(currentObject->idx,
- overlayTable[currentObject->
- overlay].ovlData->
- specialString2));
-
- if (strlen(objectName)) {
- if (currentObject->freeze == 0) {
- var_2 =
- currentObject->idx;
- var_4 =
- currentObject->
- overlay;
- var_14 =
- currentObject->
- followObjectIdx;
- var_16 =
- currentObject->
- followObjectOverlayIdx;
-
- getMultipleObjectParam
- (currentObject->
- overlay,
- currentObject->idx,
- &params);
-
- var_10 = 0;
- var_E = 0;
- var_C = 0;
-
- if ((var_4 != var_16)
- && (var_2 !=
- var_14)) {
- getMultipleObjectParam
- (var_16,
- var_14,
- &params);
-
- var_C =
- params.X;
- var_E =
- params.Y;
- var_10 =
- params.
- fileIdx;
+ if (currentObject->overlay >= 0 && overlayTable[currentObject->overlay].alreadyLoaded
+ && (currentObject->type == 4 || currentObject->type == 1
+ || currentObject->type == 9 || currentObject->type == 3)) {
+ strcpy(objectName,
+ getObjectName(currentObject->idx,
+ overlayTable[currentObject->overlay].ovlData->specialString2));
+
+ if (strlen(objectName)) {
+ if (currentObject->freeze == 0) {
+ var_2 = currentObject->idx;
+ var_4 = currentObject->overlay;
+ var_14 = currentObject->followObjectIdx;
+ var_16 = currentObject->followObjectOverlayIdx;
+
+ getMultipleObjectParam(currentObject->overlay, currentObject->idx, &params);
+
+ var_10 = 0;
+ var_E = 0;
+ var_C = 0;
+
+ if ((var_4 != var_16)
+ && (var_2 != var_14)) {
+ getMultipleObjectParam
+ (var_16, var_14, &params);
+
+ var_C = params.X;
+ var_E = params.Y;
+ var_10 = params.fileIdx;
+ }
+
+ if (params.var5 >= 0 && params.fileIdx >= 0) {
+ if (currentObject->type == 3) {
+ assert(0);
+
+ var_2 = params.scale;
+ var_A = params.X + var_C;
+
+ // TODO: this var3 is stupid, investigate...
+ if ((var_A <= mouseX) && (var_A + params.fileIdx >= mouseX) && (mouseY >= params.Y + var_E) && (params.Y + var_E + var2 >= mouseY)) {
+ *outX = var_16;
+ *outY = var_14;
+
+ return (currentObject->type);
}
+ } else if (currentObject->type == 4 ||
+ currentObject->type == 1 ||
+ currentObject->type == 9) {
+ int si;
+ int var_8;
+ int di;
- if (params.var5 >= 0
- && params.
- fileIdx >= 0) {
- if (currentObject->type == 3) {
- assert
- (0);
-
- var_2 =
- params.
- scale;
- var_A =
- params.
- X +
- var_C;
-
- // TODO: this var3 is stupid, investigate...
- if ((var_A <= mouseX) && (var_A + params.fileIdx >= mouseX) && (mouseY >= params.Y + var_E) && (params.Y + var_E + var2 >= mouseY)) {
- *outX
- =
- var_16;
- *outY
- =
- var_14;
-
- return
- (currentObject->
- type);
- }
- } else
- if
- (currentObject->
- type == 4
- ||
- currentObject->
- type == 1
- ||
- currentObject->
- type ==
- 9) {
- int si;
- int var_8;
- int di;
-
- var_A =
- params.
- X +
- var_C;
- var_6 =
- params.
- Y +
- var_E;
-
- di = params.fileIdx;
-
- if (di
- <
- 0)
- {
- di += var_10;
- }
+ var_A = params.X + var_C;
+ var_6 = params.Y + var_E;
-/* if((filesDatabase[di].subData.resourceType == 8) && (filesDatabase[di].subData.ptr))
- {
- assert(0);
- }
- else */
- {
- var_4
- =
- filesDatabase
- [di].
- resType;
+ di = params.fileIdx;
+ if (di < 0) {
+ di += var_10;
+ }
+
+/* if((filesDatabase[di].subData.resourceType == 8) && (filesDatabase[di].subData.ptr)) {
+ assert(0);
+ }
+*/
+ {
+ var_4 = filesDatabase[di].resType;
+
+ if (var_4 == 1) {
+ var_C = filesDatabase[di].widthInColumn / 2;
+ } else {
+ var_C = filesDatabase[di].width;
+ }
+
+ var_8 = filesDatabase[di].height;
+
+ var_2 = mouseX - var_A;
+ si = mouseY - var_6;
+
+ if (var_2 > 0 && var_C > var_2 && si > 0 && var_8 >= si) {
+ if (filesDatabase[di].subData.ptr) {
if (var_4 == 1) {
- var_C
- =
- filesDatabase
- [di].
- widthInColumn
- /
- 2;
} else {
- var_C
- =
- filesDatabase
- [di].
- width;
}
- var_8
- =
- filesDatabase
- [di].
- height;
-
- var_2
- =
- mouseX
- -
- var_A;
- si = mouseY - var_6;
-
- if (var_2 > 0) {
- if (var_C > var_2) {
- if (si > 0) {
- if (var_8 >= si) {
- if (filesDatabase[di].subData.ptr) {
- if (var_4 == 1) {
- } else {
- }
-
- printf
- ("should compare to mask in getCursorFromObject...\n");
+ printf("should compare to mask in getCursorFromObject...\n");
- *outX
- =
- var_16;
- *outY
- =
- var_14;
+ *outX = var_16;
+ *outY = var_14;
- printf
- ("Selected: %s\n",
- objectName);
+ printf("Selected: %s\n", objectName);
- return
- currentObject->
- type;
- }
- }
- }
- }
- }
+ return currentObject->type;
}
}
}
@@ -878,52 +784,22 @@ void buildInventory(int X, int Y) {
menuStruct *pMenu;
pMenu = createMenu(X, Y, "Inventaire");
-
menuTable[1] = pMenu;
- if (pMenu) {
- numObjectInInventory = 0;
+ if (pMenu && numOfLoadedOverlay > 1) {
+ for (int i = 1; i < numOfLoadedOverlay; i++) {
+ ovlDataStruct *pOvlData = overlayTable[i].ovlData;
- if (numOfLoadedOverlay > 1) {
- int i;
+ if (pOvlData && pOvlData->objDataTable && pOvlData->numObjData) {
+ for (int j = 0; j < pOvlData->numObjData; j++) {
+ if (buildInventorySub1(i, j) != 3) {
+ int16 returnVar;
- for (i = 1; i < numOfLoadedOverlay; i++) {
- ovlDataStruct *pOvlData =
- overlayTable[i].ovlData;
+ getSingleObjectParam(i, j, 5, &returnVar);
- if (pOvlData && pOvlData->objDataTable) {
- int var_2;
-
- var_2 = 0;
-
- if (pOvlData->numObjData) {
- int j;
-
- for (j = 0;
- j < pOvlData->numObjData;
- j++) {
- if (buildInventorySub1
- (i, j) != 3) {
- int16
- returnVar;
-
- getSingleObjectParam
- (i, j, 5,
- &returnVar);
-
- if (returnVar <
- -1) {
- addSelectableMenuEntry
- (i,
- j,
- pMenu,
- 1,
- -1,
- getObjectName
- (j, pOvlData->specialString2));
- numObjectInInventory++;
- }
- }
+ if (returnVar < -1) {
+ addSelectableMenuEntry(i, j, pMenu, 1, -1, getObjectName(j, pOvlData->specialString2));
+ numObjectInInventory++;
}
}
}
@@ -1014,12 +890,9 @@ int callInventoryObject(int param0, int param1, int x, int y) {
var_34->stringNameOffset);
if (var_2 == param0) {
- if (param1 ==
- var_34->stringNameOffset) {
+ if (param1 == var_34->stringNameOffset) {
if (pObject) {
- if (pObject->
- type !=
- 3) {
+ if (pObject->type != 3) {
char var_214[80];
char var_1C4[80];
char var_174[80];
@@ -1027,110 +900,52 @@ int callInventoryObject(int param0, int param1, int x, int y) {
char var_D4[80];
char var_84[80];
- ovlDataStruct
- *var_12;
- ovlDataStruct
- *var_22;
+ ovlDataStruct *var_12;
+ ovlDataStruct *var_22;
int var_E = var_34->varIdx;
- int cx
- =
- var_34->
- stringIdx;
+ int cx = var_34->stringIdx;
int var_C = var_34->procIdx;
- int di
- =
- var_E;
+ int di = var_E;
if (var_E == 0)
di = var_1E;
- var_2 =
- cx;
- if (cx
- ==
- 0)
- var_2
- =
- var_1E;
+ var_2 = cx;
+ if (cx == 0)
+ var_2 = var_1E;
if (var_C == 0)
- var_C
- =
- var_1E;
-
- var_12
- =
- NULL;
- var_22
- =
- NULL;
-
- var_214
- [0]
- =
- 0;
- var_1C4
- [0]
- =
- 0;
- var_174
- [0]
- =
- 0;
- var_124
- [0]
- =
- 0;
- var_D4
- [0]
- =
- 0;
- var_84
- [0]
- =
- 0;
-
- if (di
- >
- 0)
- {
- var_22
- =
- overlayTable
- [di].
- ovlData;
+ var_C = var_1E;
+
+ var_12 = NULL;
+ var_22 = NULL;
+
+ var_214[0] = 0;
+ var_1C4[0] = 0;
+ var_174[0] = 0;
+ var_124[0] = 0;
+ var_D4[0] = 0;
+ var_84[0] = 0;
+
+ if (di > 0) {
+ var_22 = overlayTable[di].ovlData;
}
if (var_2 > 0) {
- var_12
- =
- overlayTable
- [var_2].
- ovlData;
+ var_12 = overlayTable[var_2].ovlData;
}
if (var_12) {
if (var_34->stringNameOffset) {
- var_30
- =
- var_34->
- field_1A;
+ var_30 = var_34->field_1A;
if (var_28) {
if (var_12->specialString2) {
if (var_30 == -1 || var_30 == returnVar) {
char *ptrName = getObjectName(var_34->stringNameOffset, var_12->specialString2);
- menuTable
- [0]
- =
- createMenu
- (x,
- y,
- ptrName);
- var_28
- =
- 0;
+ menuTable[0] = createMenu(x, y, ptrName);
+ var_28 = 0;
}
}
}
@@ -1138,8 +953,7 @@ int callInventoryObject(int param0, int param1, int x, int y) {
}
if (var_22) {
- if (true /*var_34->varNameOffset>=0 */ ) // FIXME: This check is always true since varNameOffset is unsigned
- {
+ if (true /*var_34->varNameOffset>=0 */ ) { // FIXME: This check is always true since varNameOffset is unsigned
if (var_22->specialString1) {
char *ptr = getObjectName(var_34->varNameOffset, var_22->specialString1);
@@ -1289,8 +1103,7 @@ int processInput(void) {
ASSERT(0);
}
- if (var38 == 0) // are we in inventory mode ?
- {
+ if (var38 == 0) { // are we in inventory mode ?
if (menuTable[0] == 0) {
int X;
int Y;
diff --git a/engines/cruise/cruise_main.h b/engines/cruise/cruise_main.h
index 324d99f024..c42650a007 100644
--- a/engines/cruise/cruise_main.h
+++ b/engines/cruise/cruise_main.h
@@ -18,8 +18,8 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
- * $URL:https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/branches/gsoc2007-fsnode/engines/cruise/cruise_main.h $
- * $Id:cruise_main.h 26949 2007-05-26 20:23:24Z david_corrales $
+ * $URL$
+ * $Id$
*
*/
diff --git a/engines/cruise/ctp.cpp b/engines/cruise/ctp.cpp
index 07df6029b2..5af2cda46c 100644
--- a/engines/cruise/ctp.cpp
+++ b/engines/cruise/ctp.cpp
@@ -18,8 +18,8 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
- * $URL:https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/branches/gsoc2007-fsnode/engines/cruise/ctp.cpp $
- * $Id:ctp.cpp 26949 2007-05-26 20:23:24Z david_corrales $
+ * $URL$
+ * $Id$
*
*/
@@ -66,16 +66,14 @@ void loadCtpSub2(short int coordCount, short int *ptr) {
short int *cur_ctp_routeCoords = (short int *)ctp_routeCoords; // coordinates table
int8 *cur_ctp_routes = (int8 *) ctp_routes;
- for (i = 0; i < coordCount; i++) // for i < ctp_routeCoordCount
- {
+ for (i = 0; i < coordCount; i++) { // for i < ctp_routeCoordCount
int varX = cur_ctp_routeCoords[0]; // x
int varY = cur_ctp_routeCoords[1]; // y
int di = 0;
int var4Offset = 2;
- while (*(int16 *) cur_ctp_routes > di) // while (coordCount > counter++)
- {
+ while (*(int16 *) cur_ctp_routes > di) { // while (coordCount > counter++)
int idx = *(int16 *) (cur_ctp_routes + var4Offset);
ptr[offset + idx] =
ctpProc2(varX, varY, ctp_routeCoords[idx][0],
@@ -189,8 +187,7 @@ void loadCtpSub1(int boxIdx, int scale, uint16 *_walkboxTable,
ASSERT(boxIdx <= 15);
- if (_walkboxTable[boxIdx * 40] > 0) // is walkbox used ?
- {
+ if (_walkboxTable[boxIdx * 40] > 0) { // is walkbox used ?
getWalkBoxCenter(boxIdx, _walkboxTable);
currentWalkBoxCenterYBis = currentWalkBoxCenterY;
diff --git a/engines/cruise/ctp.h b/engines/cruise/ctp.h
index b35523a3a7..2ea47ce62e 100644
--- a/engines/cruise/ctp.h
+++ b/engines/cruise/ctp.h
@@ -18,8 +18,8 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
- * $URL:https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/branches/gsoc2007-fsnode/engines/cruise/ctp.h $
- * $Id:ctp.h 26949 2007-05-26 20:23:24Z david_corrales $
+ * $URL$
+ * $Id$
*
*/
diff --git a/engines/cruise/dataLoader.cpp b/engines/cruise/dataLoader.cpp
index 2212a3bde2..54a0e97732 100644
--- a/engines/cruise/dataLoader.cpp
+++ b/engines/cruise/dataLoader.cpp
@@ -18,8 +18,8 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
- * $URL:https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/branches/gsoc2007-fsnode/engines/cruise/dataLoader.cpp $
- * $Id:dataLoader.cpp 26949 2007-05-26 20:23:24Z david_corrales $
+ * $URL$
+ * $Id$
*
*/
diff --git a/engines/cruise/dataLoader.h b/engines/cruise/dataLoader.h
index 6b6bf52cf6..46e4ef447f 100644
--- a/engines/cruise/dataLoader.h
+++ b/engines/cruise/dataLoader.h
@@ -18,8 +18,8 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
- * $URL:https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/branches/gsoc2007-fsnode/engines/cruise/dataLoader.h $
- * $Id:dataLoader.h 26949 2007-05-26 20:23:24Z david_corrales $
+ * $URL$
+ * $Id$
*
*/
diff --git a/engines/cruise/decompiler.cpp b/engines/cruise/decompiler.cpp
index 68beab0846..b027f948aa 100644
--- a/engines/cruise/decompiler.cpp
+++ b/engines/cruise/decompiler.cpp
@@ -18,8 +18,8 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
- * $URL:https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/branches/gsoc2007-fsnode/engines/cruise/decompiler.cpp $
- * $Id:decompiler.cpp 26949 2007-05-26 20:23:24Z david_corrales $
+ * $URL$
+ * $Id$
*
*/
@@ -136,52 +136,47 @@ void pushDecomp(char *string, ...) {
void resolveDecompShort(char *buffer) {
ovlData3Struct *data3Ptr = currentScript;
+ int i;
- {
- int i;
+ importScriptStruct *importEntry =
+ (importScriptStruct *) (data3Ptr->dataPtr +
+ data3Ptr->offsetToImportData);
- importScriptStruct *importEntry =
- (importScriptStruct *) (data3Ptr->dataPtr +
- data3Ptr->offsetToImportData);
-
- for (i = 0; i < data3Ptr->numImport; i++) {
- switch (importEntry->type) {
- case 20: // script
- case 30:
- case 40:
- case 50:
- {
- if (importEntry->offset == currentDecompScriptPtr->var4 - 3) // param1
- {
- sprintf(buffer,
- data3Ptr->dataPtr +
- data3Ptr->
- offsetToImportName +
- importEntry->offsetToName);
- return;
- }
- if (importEntry->offset == currentDecompScriptPtr->var4 - 6) // param2
- {
- sprintf(buffer, "linkedIdx");
- return;
- }
- break;
+ for (i = 0; i < data3Ptr->numImport; i++) {
+ switch (importEntry->type) {
+ case 20: // script
+ case 30:
+ case 40:
+ case 50:
+ {
+ if (importEntry->offset == currentDecompScriptPtr->var4 - 3) { // param1
+ sprintf(buffer,
+ data3Ptr->dataPtr +
+ data3Ptr->
+ offsetToImportName +
+ importEntry->offsetToName);
+ return;
}
- default:
- {
- if (importEntry->offset ==
- currentDecompScriptPtr->var4 - 4) {
- sprintf(buffer,
- data3Ptr->dataPtr +
- data3Ptr->
- offsetToImportName +
- importEntry->offsetToName);
- return;
- }
+ if (importEntry->offset == currentDecompScriptPtr->var4 - 6) { // param2
+ sprintf(buffer, "linkedIdx");
+ return;
+ }
+ break;
+ }
+ default:
+ {
+ if (importEntry->offset ==
+ currentDecompScriptPtr->var4 - 4) {
+ sprintf(buffer,
+ data3Ptr->dataPtr +
+ data3Ptr->
+ offsetToImportName +
+ importEntry->offsetToName);
+ return;
}
}
- importEntry++;
}
+ importEntry++;
}
buffer[0] = 0;
@@ -190,31 +185,28 @@ void resolveDecompShort(char *buffer) {
void resolveDecompChar(char *buffer) {
ovlData3Struct *data3Ptr = currentScript;
+ int i;
- {
- int i;
+ importScriptStruct *importEntry =
+ (importScriptStruct *) (data3Ptr->dataPtr +
+ data3Ptr->offsetToImportData);
- importScriptStruct *importEntry =
- (importScriptStruct *) (data3Ptr->dataPtr +
- data3Ptr->offsetToImportData);
-
- for (i = 0; i < data3Ptr->numImport; i++) {
- switch (importEntry->type) {
- default:
- {
- if (importEntry->offset ==
- currentDecompScriptPtr->var4 - 2) {
- sprintf(buffer,
- data3Ptr->dataPtr +
- data3Ptr->
- offsetToImportName +
- importEntry->offsetToName);
- return;
- }
+ for (i = 0; i < data3Ptr->numImport; i++) {
+ switch (importEntry->type) {
+ default:
+ {
+ if (importEntry->offset ==
+ currentDecompScriptPtr->var4 - 2) {
+ sprintf(buffer,
+ data3Ptr->dataPtr +
+ data3Ptr->
+ offsetToImportName +
+ importEntry->offsetToName);
+ return;
}
}
- importEntry++;
}
+ importEntry++;
}
buffer[0] = 0;
@@ -342,16 +334,14 @@ void resolveVarName(char *ovlIdxString, int varType, char *varIdxString,
for (i = 0; i < currentDecompOvl->numExport; i++) {
if (varIdx == currentDecompOvl->exportDataPtr[i].idx) {
- if (((currentDecompOvl->exportDataPtr[i].var4 & 0xF0) == 0) && varType != 0x20) // var
- {
+ if (((currentDecompOvl->exportDataPtr[i].var4 & 0xF0) == 0) && varType != 0x20) { // var
strcpy(outputName,
currentDecompOvl->exportNamesPtr +
currentDecompOvl->exportDataPtr[i].
offsetToName);
return;
}
- if ((currentDecompOvl->exportDataPtr[i].var4) == 20 && varType == 0x20) // script
- {
+ if ((currentDecompOvl->exportDataPtr[i].var4) == 20 && varType == 0x20) { // script
strcpy(outputName,
currentDecompOvl->exportNamesPtr +
currentDecompOvl->exportDataPtr[i].
@@ -722,13 +712,11 @@ int decompCompare(void) {
if(!pop)
si = 1;
- if(pop<0)
- {
+ if(pop<0) {
si |= 4;
}
- if(pop>0)
- {
+ if(pop>0) {
si |= 2;
}
@@ -1435,7 +1423,7 @@ int decompBreak(void) {
}
void generateIndentation(void) {
- int i;
+ int i, j;
for (i = 0; i < positionInDecompileLineTable; i++) {
if (decompileLineTable[i].type != 0) {
@@ -1449,37 +1437,25 @@ void generateIndentation(void) {
gotoStatement = strchr(gotoStatement, ' ') + 1;
destLine = atoi(gotoStatement);
+ destLineIdx = -1;
- {
- int j;
-
- destLineIdx = -1;
-
- for (j = 0; j < positionInDecompileLineTable;
- j++) {
- if (decompileLineTable[j].lineOffset ==
- destLine) {
- destLineIdx = j;
- break;
- }
+ for (j = 0; j < positionInDecompileLineTable; j++) {
+ if (decompileLineTable[j].lineOffset == destLine) {
+ destLineIdx = j;
+ break;
}
+ }
- assert(destLineIdx != -1);
-
- if (destLineIdx > i) {
- int j;
+ assert(destLineIdx != -1);
- for (j = i + 1; j < destLineIdx; j++) {
- decompileLineTable[j].indent++;
- }
+ if (destLineIdx > i) {
+ for (j = i + 1; j < destLineIdx; j++) {
+ decompileLineTable[j].indent++;
+ }
- if (strstr(decompileLineTable
- [destLineIdx - 1].line,
- "goto") ==
- decompileLineTable[destLineIdx -
- 1].line) {
- //decompileLineTable[destLineIdx-1].pendingElse = 1;
- }
+ if (strstr(decompileLineTable[destLineIdx - 1].line, "goto") ==
+ decompileLineTable[destLineIdx - 1].line) {
+ //decompileLineTable[destLineIdx-1].pendingElse = 1;
}
}
}
diff --git a/engines/cruise/delphine-unpack.cpp b/engines/cruise/delphine-unpack.cpp
index db4188fbfe..b1cdc13148 100644
--- a/engines/cruise/delphine-unpack.cpp
+++ b/engines/cruise/delphine-unpack.cpp
@@ -18,8 +18,8 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
- * $URL:https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/branches/gsoc2007-fsnode/engines/cruise/delphine-unpack.cpp $
- * $Id:delphine-unpack.cpp 26949 2007-05-26 20:23:24Z david_corrales $
+ * $URL$
+ * $Id$
*
*/
diff --git a/engines/cruise/detection.cpp b/engines/cruise/detection.cpp
index fc1d864a56..2ca83f4046 100644
--- a/engines/cruise/detection.cpp
+++ b/engines/cruise/detection.cpp
@@ -18,8 +18,8 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
- * $URL:https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/branches/gsoc2007-fsnode/engines/cruise/detection.cpp $
- * $Id:detection.cpp 26949 2007-05-26 20:23:24Z david_corrales $
+ * $URL$
+ * $Id$
*
*/
diff --git a/engines/cruise/font.cpp b/engines/cruise/font.cpp
index 92064acc53..ee99567525 100644
--- a/engines/cruise/font.cpp
+++ b/engines/cruise/font.cpp
@@ -18,8 +18,8 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
- * $URL:https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/branches/gsoc2007-fsnode/engines/cruise/font.cpp $
- * $Id:font.cpp 26949 2007-05-26 20:23:24Z david_corrales $
+ * $URL$
+ * $Id$
*
*/
@@ -253,8 +253,7 @@ void renderWord(uint8 * fontPtr_Data, uint8 * outBufferPtr,
outBufferPtr += heightOff * width * 2; // param2 = height , param6 = width
outBufferPtr += drawPosPixel_X; // param1 = drawPosPixel_X
- for (i = 0; i < height; i++) // y++
- {
+ for (i = 0; i < height; i++) { // y++
uint16 currentColor1 =
(*(fontPtr_Data) << 8) | *(fontPtr_Data + 1);
uint16 currentColor2 =
diff --git a/engines/cruise/font.h b/engines/cruise/font.h
index 2a75cf28dd..b74482962d 100644
--- a/engines/cruise/font.h
+++ b/engines/cruise/font.h
@@ -18,8 +18,8 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
- * $URL:https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/branches/gsoc2007-fsnode/engines/cruise/font.h $
- * $Id:font.h 26949 2007-05-26 20:23:24Z david_corrales $
+ * $URL$
+ * $Id$
*
*/
diff --git a/engines/cruise/fontCharacterTable.cpp b/engines/cruise/fontCharacterTable.cpp
index ce0bec0f0f..2c2dddc479 100644
--- a/engines/cruise/fontCharacterTable.cpp
+++ b/engines/cruise/fontCharacterTable.cpp
@@ -18,8 +18,8 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
- * $URL:https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/branches/gsoc2007-fsnode/engines/cruise/fontCharacterTable.cpp $
- * $Id:fontCharacterTable.cpp 26949 2007-05-26 20:23:24Z david_corrales $
+ * $URL$
+ * $Id$
*
*/
diff --git a/engines/cruise/fontCharacterTable.h b/engines/cruise/fontCharacterTable.h
index f7956968ec..0bfe78641a 100644
--- a/engines/cruise/fontCharacterTable.h
+++ b/engines/cruise/fontCharacterTable.h
@@ -18,8 +18,8 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
- * $URL:https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/branches/gsoc2007-fsnode/engines/cruise/fontCharacterTable.h $
- * $Id:fontCharacterTable.h 26949 2007-05-26 20:23:24Z david_corrales $
+ * $URL$
+ * $Id$
*
*/
diff --git a/engines/cruise/function.cpp b/engines/cruise/function.cpp
index 092425bfc7..cfb579e331 100644
--- a/engines/cruise/function.cpp
+++ b/engines/cruise/function.cpp
@@ -18,8 +18,8 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
- * $URL:https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/branches/gsoc2007-fsnode/engines/cruise/function.cpp $
- * $Id:function.cpp 26949 2007-05-26 20:23:24Z david_corrales $
+ * $URL$
+ * $Id$
*
*/
@@ -1006,8 +1006,7 @@ actorStruct *addAnimation(actorStruct * pHead, int overlay, int objIdx, int para
return pNewElement;
}
-int removeAnimation(actorStruct * pHead, int overlay, int objIdx, int objType)
-{
+int removeAnimation(actorStruct * pHead, int overlay, int objIdx, int objType) {
actorStruct* pl;
actorStruct* pl2;
actorStruct* pl3;
@@ -1019,14 +1018,12 @@ int removeAnimation(actorStruct * pHead, int overlay, int objIdx, int objType)
pl2 = pl;
pl = pl2->next;
- while(pl)
- {
+ while (pl) {
pl2 = pl;
- if(((pl->overlayNumber == overlay) || (overlay == -1)) &&
+ if (((pl->overlayNumber == overlay) || (overlay == -1)) &&
((pl->idx == objIdx) || (objIdx == -1)) &&
- ((pl->type == objType) || (objType == -1)))
- {
+ ((pl->type == objType) || (objType == -1))) {
pl->type = -1;
}
@@ -1037,29 +1034,25 @@ int removeAnimation(actorStruct * pHead, int overlay, int objIdx, int objType)
pl2 = pl;
pl = pl2->next;
- while(pl)
- {
- if(pl->type == -1)
- {
+ while (pl) {
+ if (pl->type == -1) {
pl4 = pl->next;
pl2->next = pl4;
pl3 = pl4;
- if(pl3 == NULL)
+ if (pl3 == NULL)
pl3 = pHead;
pl3->prev = pl->prev;
dir = pl->startDirection;
- if(pl->idx >= 0)
+ if (pl->idx >= 0)
freePerso(pl->idx);
free(pl);
pl = pl4;
- }
- else
- {
+ } else {
pl2 = pl;
pl = pl2->next;
}
diff --git a/engines/cruise/function.h b/engines/cruise/function.h
index 76100e41ba..13eb21ea1f 100644
--- a/engines/cruise/function.h
+++ b/engines/cruise/function.h
@@ -18,8 +18,8 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
- * $URL:https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/branches/gsoc2007-fsnode/engines/cruise/function.h $
- * $Id:function.h 26949 2007-05-26 20:23:24Z david_corrales $
+ * $URL$
+ * $Id$
*
*/
diff --git a/engines/cruise/gfxModule.cpp b/engines/cruise/gfxModule.cpp
index 119f99739e..9228193560 100644
--- a/engines/cruise/gfxModule.cpp
+++ b/engines/cruise/gfxModule.cpp
@@ -18,8 +18,8 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
- * $URL:https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/branches/gsoc2007-fsnode/engines/cruise/gfxModule.cpp $
- * $Id:gfxModule.cpp 26949 2007-05-26 20:23:24Z david_corrales $
+ * $URL$
+ * $Id$
*
*/
@@ -526,10 +526,8 @@ void gfxModuleData_field_60(char *sourcePtr, int width, int height,
int i;
int j;
- for(i=x;i<height+x;i++)
- {
- for(j=y;j<width*16+y;j++)
- {
+ for(i=x;i<height+x;i++) {
+ for(j=y;j<width*16+y;j++) {
if(i>=0&&i<200&&j>=0&&j<320)
destPtr[i*320+j] = *(sourcePtr++);
}
diff --git a/engines/cruise/gfxModule.h b/engines/cruise/gfxModule.h
index 7339113f4c..e63b26e29f 100644
--- a/engines/cruise/gfxModule.h
+++ b/engines/cruise/gfxModule.h
@@ -18,8 +18,8 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
- * $URL:https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/branches/gsoc2007-fsnode/engines/cruise/gfxModule.h $
- * $Id:gfxModule.h 26949 2007-05-26 20:23:24Z david_corrales $
+ * $URL$
+ * $Id$
*
*/
diff --git a/engines/cruise/linker.cpp b/engines/cruise/linker.cpp
index 0057625e81..e72218037b 100644
--- a/engines/cruise/linker.cpp
+++ b/engines/cruise/linker.cpp
@@ -18,8 +18,8 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
- * $URL:https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/branches/gsoc2007-fsnode/engines/cruise/linker.cpp $
- * $Id:linker.cpp 26949 2007-05-26 20:23:24Z david_corrales $
+ * $URL$
+ * $Id$
*
*/
@@ -186,70 +186,36 @@ int updateScriptImport(int ovlIdx) {
int temp =
ptrImportData->
offset;
- if (out1) //is sub function... (ie 'invent.livre:s')
- {
+ if (out1) { //is sub function... (ie 'invent.livre:s')
uint8 *ptr = ptrData + temp;
- *(ptr +
- 1)
- =
- out2;
- *(int16
- *)
- (ptr
- +
- 2)
- =
- ptrDest2->
- idx;
-
- flipShort
- (
- (int16
- *)
- (ptr + 2));
+ *(ptr + 1) = out2;
+ *(int16 *)(ptr + 2) = ptrDest2->idx;
+
+ flipShort((int16 *)(ptr + 2));
} else {
- if (param2 == 20 || param2 == 30 || param2 == 40 || param2 == 50) // this patch a double push
- {
- uint8
- *
- ptr
- =
- ptrData
- +
- temp;
+ if (param2 == 20 || param2 == 30 || param2 == 40 || param2 == 50) { // this patch a double push
+ uint8 *ptr = ptrData + temp;
*(ptr + 1) = 0;
*(ptr + 2) = out2; // update the overlay number
- *(int16 *) (ptr + 4) = ptrDest2->idx;
+ *(int16 *)(ptr + 4) = ptrDest2->idx;
- flipShort
- (
- (int16
- *)
- (ptr + 4));
+ flipShort((int16 *)(ptr + 4));
} else {
int var_4 = ptrDest2->var4;
if (var_4 & 1) {
- param2
- =
- 8;
+ param2 = 8;
} else {
- param2
- =
- 16;
+ param2 = 16;
}
if (var_4 >= 0 && var_4 <= 3) {
- param2
- |=
- 5;
+ param2 |= 5;
} else {
- param2
- |=
- 6;
+ param2 |= 6;
}
*(ptrData + temp) = param2;
diff --git a/engines/cruise/linker.h b/engines/cruise/linker.h
index 975ed0f322..808ace75e0 100644
--- a/engines/cruise/linker.h
+++ b/engines/cruise/linker.h
@@ -18,8 +18,8 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
- * $URL:https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/branches/gsoc2007-fsnode/engines/cruise/linker.h $
- * $Id:linker.h 26949 2007-05-26 20:23:24Z david_corrales $
+ * $URL$
+ * $Id$
*
*/
diff --git a/engines/cruise/mainDraw.cpp b/engines/cruise/mainDraw.cpp
index 3d409d0ba5..b30dc29380 100644
--- a/engines/cruise/mainDraw.cpp
+++ b/engines/cruise/mainDraw.cpp
@@ -18,13 +18,14 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
- * $URL:https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/branches/gsoc2007-fsnode/engines/cruise/mainDraw.cpp $
- * $Id:mainDraw.cpp 26949 2007-05-26 20:23:24Z david_corrales $
+ * $URL$
+ * $Id$
*
*/
#include "cruise/cruise_main.h"
-#include "polys.h"
+#include "cruise/polys.h"
+#include "common/util.h"
namespace Cruise {
@@ -131,8 +132,7 @@ void getPolyData(int fileIndex, int X, int Y, int *outScale, int *outY,
newFileIndex += fileIndex;
- if (true /*newFileIndex >= 0 */ ) // FIXME: comparison is always true due to limited range of data type
- {
+ if (true /*newFileIndex >= 0 */ ) { // FIXME: comparison is always true due to limited range of data type
if (filesDatabase[newFileIndex].resType == 0
&& filesDatabase[newFileIndex].subData.ptr) {
dataPtr =
@@ -180,8 +180,7 @@ void getPolySize(int positionX, int positionY, int scale, int sizeTable[4],
int lowerBorder;
m_flipLeftRight = 0;
- if (scale < 0) // flip left right
- {
+ if (scale < 0) { // flip left right
m_flipLeftRight = 1;
scale = -scale;
}
@@ -208,11 +207,8 @@ void getPolySize(int positionX, int positionY, int scale, int sizeTable[4],
upperBorder = (upscaleValue(upperBorder, scale) + 0x8000) >> 16;
- if (upperBorder < lowerBorder) // exchange borders if lower > upper
- {
- int temp = upperBorder;
- upperBorder = lowerBorder;
- lowerBorder = temp;
+ if (upperBorder < lowerBorder) { // exchange borders if lower > upper
+ SWAP(upperBorder, lowerBorder);
}
sizeTable[0] = lowerBorder; // left
@@ -231,11 +227,8 @@ void getPolySize(int positionX, int positionY, int scale, int sizeTable[4],
upperBorder -= *(dataPtr + 4);
upperBorder = (upscaleValue(upperBorder, scale) + 0x8000) >> 16;
- if (upperBorder < lowerBorder) // exchange borders if lower > upper
- {
- int temp = upperBorder;
- upperBorder = lowerBorder;
- lowerBorder = temp;
+ if (upperBorder < lowerBorder) { // exchange borders if lower > upper
+ SWAP(upperBorder, lowerBorder);
}
sizeTable[2] = lowerBorder; // bottom
@@ -397,8 +390,7 @@ void buildPolyModel(int positionX, int positionY, int scale, char *ptr2,
m_flipLeftRight = 1;
}
- if (scale < 0x180) // If scale is smaller than 384
- {
+ if (scale < 0x180) { // If scale is smaller than 384
m_useSmallScale = 1;
m_scaleValue = scale << 1; // double scale
} else {
@@ -448,8 +440,7 @@ void buildPolyModel(int positionX, int positionY, int scale, char *ptr2,
x = *(dataPointer++) - m_first_X;
y = *(dataPointer++) - m_first_Y;
- if (m_useSmallScale) // shrink all coordinates by factor 2 if a scale smaller than 384 is used
- {
+ if (m_useSmallScale) { // shrink all coordinates by factor 2 if a scale smaller than 384 is used
x >>= 1;
y >>= 1;
}
@@ -502,8 +493,7 @@ void buildPolyModel(int positionX, int positionY, int scale, char *ptr2,
do {
int linesToDraw = *dataPointer++;
- if (linesToDraw > 1) // if value not zero
- {
+ if (linesToDraw > 1) { // if value not zero
uint16 minimumScale;
m_color = *dataPointer; // color
@@ -514,8 +504,7 @@ void buildPolyModel(int positionX, int positionY, int scale, char *ptr2,
flipShort(&minimumScale);
- if (minimumScale > scale) // if the scale is too small, for the model to be drawn ...
- {
+ if (minimumScale > scale) { // if the scale is too small, for the model to be drawn ...
dataPointer += linesToDraw; // ... skip ahead
} else {
if (m_flipLeftRight) {
@@ -913,13 +902,10 @@ void mainDraw(int16 param) {
}
if ((params.var5 >= 0) && (objZ2 >= 0) && filesDatabase[objZ2].subData.ptr) {
- if (filesDatabase[objZ2].subData.resourceType == 8) // Poly
- {
+ if (filesDatabase[objZ2].subData.resourceType == 8) { // Poly
mainDrawPolygons(objZ2, currentObjPtr, objX2, params.scale, objY2, (char *)gfxModuleData.pPage10, (char *)filesDatabase[objZ2].subData.ptr); // poly
- } else if (filesDatabase[objZ2].subData.resourceType == 6) // sound
- {
- } else if (filesDatabase[objZ2].resType == 1) //(num plan == 1)
- {
+ } else if (filesDatabase[objZ2].subData.resourceType == 6) { // sound
+ } else if (filesDatabase[objZ2].resType == 1) { //(num plan == 1)
} else if (filesDatabase[objZ2].subData.resourceType == 4) {
objX1 = filesDatabase[objZ2].width; // width
spriteHeight = filesDatabase[objZ2].height; // height
@@ -953,12 +939,10 @@ void mainDraw(int16 param) {
change = false;
currentObjPtr->animStep = 0;
- if (currentObjPtr->animType) // should we resume the script ?
- {
+ if (currentObjPtr->animType) { // should we resume the script ?
if (currentObjPtr->parentType == 20) {
changeScriptParamInList(currentObjPtr->parentOverlay, currentObjPtr->parent, &procHead, 0, -1);
- }
- else if(currentObjPtr->parentType == 30) {
+ } else if (currentObjPtr->parentType == 30) {
changeScriptParamInList(currentObjPtr->parentOverlay, currentObjPtr->parent, &relHead, 0, -1);
}
}
diff --git a/engines/cruise/mainDraw.h b/engines/cruise/mainDraw.h
index 7ff6ffdc8f..ad10bcddc6 100644
--- a/engines/cruise/mainDraw.h
+++ b/engines/cruise/mainDraw.h
@@ -18,8 +18,8 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
- * $URL:https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/branches/gsoc2007-fsnode/engines/cruise/mainDraw.h $
- * $Id:mainDraw.h 26949 2007-05-26 20:23:24Z david_corrales $
+ * $URL$
+ * $Id$
*
*/
diff --git a/engines/cruise/menu.cpp b/engines/cruise/menu.cpp
index e30542cc1b..4f828d1fd3 100644
--- a/engines/cruise/menu.cpp
+++ b/engines/cruise/menu.cpp
@@ -18,8 +18,8 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
- * $URL:https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/branches/gsoc2007-fsnode/engines/cruise/menu.cpp $
- * $Id:menu.cpp 26949 2007-05-26 20:23:24Z david_corrales $
+ * $URL$
+ * $Id$
*
*/
@@ -221,8 +221,7 @@ int playerMenu(int menuX, int menuY) {
freeStuff2();
}
/*
- if(currentMenu)
- {
+ if(currentMenu) {
freeMenu(currentMenu);
currentMenu = 0;
var37 = 0;
@@ -230,8 +229,7 @@ int playerMenu(int menuX, int menuY) {
main9 = -1;
}
- if(inventoryMenu)
- {
+ if(inventoryMenu) {
freeMenu(inventoryMenu);
inventoryMenu = 0;
var37 = 0;
@@ -239,8 +237,7 @@ int playerMenu(int menuX, int menuY) {
main9 = -1;
}*/
-/* if(mouseVar2)
- {
+/* if(mouseVar2) {
free3(mouseVar2);
} */
diff --git a/engines/cruise/menu.h b/engines/cruise/menu.h
index 9a33545224..4e15d15cf1 100644
--- a/engines/cruise/menu.h
+++ b/engines/cruise/menu.h
@@ -18,8 +18,8 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
- * $URL:https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/branches/gsoc2007-fsnode/engines/cruise/menu.h $
- * $Id:menu.h 26949 2007-05-26 20:23:24Z david_corrales $
+ * $URL$
+ * $Id$
*
*/
diff --git a/engines/cruise/mouse.cpp b/engines/cruise/mouse.cpp
index c9cec8f72a..a918e0536f 100644
--- a/engines/cruise/mouse.cpp
+++ b/engines/cruise/mouse.cpp
@@ -18,8 +18,8 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
- * $URL:https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/branches/gsoc2007-fsnode/engines/cruise/mouse.cpp $
- * $Id:mouse.cpp 26949 2007-05-26 20:23:24Z david_corrales $
+ * $URL$
+ * $Id$
*
*/
diff --git a/engines/cruise/mouse.h b/engines/cruise/mouse.h
index c7ef2a69c5..a6911ce27e 100644
--- a/engines/cruise/mouse.h
+++ b/engines/cruise/mouse.h
@@ -18,8 +18,8 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
- * $URL:https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/branches/gsoc2007-fsnode/engines/cruise/mouse.h $
- * $Id:mouse.h 26949 2007-05-26 20:23:24Z david_corrales $
+ * $URL$
+ * $Id$
*
*/
diff --git a/engines/cruise/object.cpp b/engines/cruise/object.cpp
index ce4de2a12b..22e81dea90 100644
--- a/engines/cruise/object.cpp
+++ b/engines/cruise/object.cpp
@@ -18,8 +18,8 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
- * $URL:https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/branches/gsoc2007-fsnode/engines/cruise/object.cpp $
- * $Id:object.cpp 26949 2007-05-26 20:23:24Z david_corrales $
+ * $URL$
+ * $Id$
*
*/
diff --git a/engines/cruise/object.h b/engines/cruise/object.h
index feec666687..546d2bc440 100644
--- a/engines/cruise/object.h
+++ b/engines/cruise/object.h
@@ -18,8 +18,8 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
- * $URL:https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/branches/gsoc2007-fsnode/engines/cruise/object.h $
- * $Id:object.h 26949 2007-05-26 20:23:24Z david_corrales $
+ * $URL$
+ * $Id$
*
*/
diff --git a/engines/cruise/overlay.cpp b/engines/cruise/overlay.cpp
index c1b35f61f6..179c53357d 100644
--- a/engines/cruise/overlay.cpp
+++ b/engines/cruise/overlay.cpp
@@ -18,8 +18,8 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
- * $URL:https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/branches/gsoc2007-fsnode/engines/cruise/overlay.cpp $
- * $Id:overlay.cpp 26949 2007-05-26 20:23:24Z david_corrales $
+ * $URL$
+ * $Id$
*
*/
@@ -375,8 +375,7 @@ int loadOverlay(const uint8 *scriptName) {
if (!ovlData->ptr8) {
/* releaseScript(scriptIdx,scriptName);
- if(freeIsNeeded)
- {
+ if(freeIsNeeded) {
freePtr(unpackedBuffer);
} */
@@ -396,8 +395,7 @@ int loadOverlay(const uint8 *scriptName) {
if (!ovlData->objDataTable) {
/* releaseScript(scriptIdx,scriptName);
- if(freeIsNeeded)
- {
+ if(freeIsNeeded) {
freePtr(unpackedBuffer);
} */
@@ -457,8 +455,7 @@ int loadOverlay(const uint8 *scriptName) {
if (!ovlData->objData2WorkTable) {
/* releaseScript(scriptIdx,scriptName);
- if(freeIsNeeded)
- {
+ if(freeIsNeeded) {
freePtr(unpackedBuffer);
} */
@@ -474,8 +471,7 @@ int loadOverlay(const uint8 *scriptName) {
if (!ovlData->objData2SourceTable) {
/* releaseScript(scriptIdx,scriptName);
- if(freeIsNeeded)
- {
+ if(freeIsNeeded) {
freePtr(unpackedBuffer);
} */
@@ -501,8 +497,7 @@ int loadOverlay(const uint8 *scriptName) {
}
}
-/* if(freeIsNeeded)
- {
+/* if(freeIsNeeded) {
freePtr(unpackedBuffer);
} */
@@ -701,14 +696,12 @@ int releaseOverlay(const char *name) {
if (!ovlDataPtr)
return -4;
/*
- if(overlayTable[overlayIdx].var1E)
- {
+ if(overlayTable[overlayIdx].var1E) {
free(overlayTable[overlayIdx].var1E);
overlayTable[overlayIdx].var1E = NULL;
}
- if(overlayTable[overlayIdx].var16)
- {
+ if(overlayTable[overlayIdx].var16) {
free(overlayTable[overlayIdx].var16);
overlayTable[overlayIdx].var16 = NULL;
} */
diff --git a/engines/cruise/overlay.h b/engines/cruise/overlay.h
index 03db06fada..5d2e4e890e 100644
--- a/engines/cruise/overlay.h
+++ b/engines/cruise/overlay.h
@@ -18,8 +18,8 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
- * $URL:https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/branches/gsoc2007-fsnode/engines/cruise/overlay.h $
- * $Id:overlay.h 26949 2007-05-26 20:23:24Z david_corrales $
+ * $URL$
+ * $Id$
*
*/
diff --git a/engines/cruise/perso.cpp b/engines/cruise/perso.cpp
index a95607a2f1..e0cd85f2fe 100644
--- a/engines/cruise/perso.cpp
+++ b/engines/cruise/perso.cpp
@@ -18,8 +18,8 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
- * $URL:https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/branches/gsoc2007-fsnode/engines/cruise/perso.cpp $
- * $Id:perso.cpp 26949 2007-05-26 20:23:24Z david_corrales $
+ * $URL$
+ * $Id$
*
*/
diff --git a/engines/cruise/perso.h b/engines/cruise/perso.h
index 0d5676a4c8..aa9f59a1a3 100644
--- a/engines/cruise/perso.h
+++ b/engines/cruise/perso.h
@@ -18,8 +18,8 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
- * $URL:https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/branches/gsoc2007-fsnode/engines/cruise/perso.h $
- * $Id:perso.h 26949 2007-05-26 20:23:24Z david_corrales $
+ * $URL$
+ * $Id$
*
*/
diff --git a/engines/cruise/polys.cpp b/engines/cruise/polys.cpp
index 83192b0dda..a2eea8a9a7 100644
--- a/engines/cruise/polys.cpp
+++ b/engines/cruise/polys.cpp
@@ -18,8 +18,8 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
- * $URL:https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/branches/gsoc2007-fsnode/engines/cruise/polys.cpp $
- * $Id:polys.cpp 26949 2007-05-26 20:23:24Z david_corrales $
+ * $URL$
+ * $Id$
*
*/
diff --git a/engines/cruise/polys.h b/engines/cruise/polys.h
index b5da8dd241..53ce4672cd 100644
--- a/engines/cruise/polys.h
+++ b/engines/cruise/polys.h
@@ -18,8 +18,8 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
- * $URL:https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/branches/gsoc2007-fsnode/engines/cruise/polys.h $
- * $Id:polys.h 26949 2007-05-26 20:23:24Z david_corrales $
+ * $URL$
+ * $Id$
*
*/
diff --git a/engines/cruise/saveload.cpp b/engines/cruise/saveload.cpp
index ffda142e66..189bde1ea1 100644
--- a/engines/cruise/saveload.cpp
+++ b/engines/cruise/saveload.cpp
@@ -18,8 +18,8 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
- * $URL:https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/branches/gsoc2007-fsnode/engines/cruise/saveload.cpp $
- * $Id:saveload.cpp 26949 2007-05-26 20:23:24Z david_corrales $
+ * $URL$
+ * $Id$
*
*/
diff --git a/engines/cruise/saveload.h b/engines/cruise/saveload.h
index de97f24b64..5a719066c5 100644
--- a/engines/cruise/saveload.h
+++ b/engines/cruise/saveload.h
@@ -18,8 +18,8 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
- * $URL:https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/branches/gsoc2007-fsnode/engines/cruise/saveload.h $
- * $Id:saveload.h 26949 2007-05-26 20:23:24Z david_corrales $
+ * $URL$
+ * $Id$
*
*/
diff --git a/engines/cruise/script.cpp b/engines/cruise/script.cpp
index dc1b12f736..c9ba819d75 100644
--- a/engines/cruise/script.cpp
+++ b/engines/cruise/script.cpp
@@ -18,8 +18,8 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
- * $URL:https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/branches/gsoc2007-fsnode/engines/cruise/script.cpp $
- * $Id:script.cpp 26949 2007-05-26 20:23:24Z david_corrales $
+ * $URL$
+ * $Id$
*
*/
@@ -73,8 +73,7 @@ int32 opcodeType0(void) {
if (!byte2) {
ptr = scriptDataPtrTable[var_E] + short1;
- } else // TODO:
- {
+ } else { // TODO:
if (!overlayTable[byte2].alreadyLoaded) {
return (-7);
}
@@ -145,8 +144,7 @@ int32 opcodeType0(void) {
if (!byte2) {
ptr = scriptDataPtrTable[var_E] + var_12;
- } else // TODO:
- {
+ } else { // TODO:
if (!overlayTable[byte2].alreadyLoaded) {
return (-7);
}
@@ -635,8 +633,7 @@ uint8 *attacheNewScriptToTail(int16 overlayNumber,
oldTail = scriptHandlePtr;
- while (oldTail->nextScriptPtr) // go to the end of the list
- {
+ while (oldTail->nextScriptPtr) { // go to the end of the list
oldTail = oldTail->nextScriptPtr;
}
@@ -660,8 +657,7 @@ uint8 *attacheNewScriptToTail(int16 overlayNumber,
tempPtr->scriptNumber = param;
tempPtr->overlayNumber = overlayNumber;
- if (scriptType == 20) // Obj or not ?
- {
+ if (scriptType == 20) { // Obj or not ?
tempPtr->sysKey = useArg3Neg;
} else {
tempPtr->sysKey = 1;
diff --git a/engines/cruise/script.h b/engines/cruise/script.h
index ca7d812836..e5d21b1ba0 100644
--- a/engines/cruise/script.h
+++ b/engines/cruise/script.h
@@ -18,8 +18,8 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
- * $URL:https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/branches/gsoc2007-fsnode/engines/cruise/script.h $
- * $Id:script.h 26949 2007-05-26 20:23:24Z david_corrales $
+ * $URL$
+ * $Id$
*
*/
diff --git a/engines/cruise/stack.cpp b/engines/cruise/stack.cpp
index 7622564503..1639ba3942 100644
--- a/engines/cruise/stack.cpp
+++ b/engines/cruise/stack.cpp
@@ -18,8 +18,8 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
- * $URL:https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/branches/gsoc2007-fsnode/engines/cruise/stack.cpp $
- * $Id:stack.cpp 26949 2007-05-26 20:23:24Z david_corrales $
+ * $URL$
+ * $Id$
*
*/
diff --git a/engines/cruise/stack.h b/engines/cruise/stack.h
index 1adb3540cb..831c07e217 100644
--- a/engines/cruise/stack.h
+++ b/engines/cruise/stack.h
@@ -18,8 +18,8 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
- * $URL:https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/branches/gsoc2007-fsnode/engines/cruise/stack.h $
- * $Id:stack.h 26949 2007-05-26 20:23:24Z david_corrales $
+ * $URL$
+ * $Id$
*
*/
diff --git a/engines/cruise/stringSupport.cpp b/engines/cruise/stringSupport.cpp
index 54747104ff..791f203d9b 100644
--- a/engines/cruise/stringSupport.cpp
+++ b/engines/cruise/stringSupport.cpp
@@ -18,8 +18,8 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
- * $URL:https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/branches/gsoc2007-fsnode/engines/cruise/stringSupport.cpp $
- * $Id:stringSupport.cpp 26949 2007-05-26 20:23:24Z david_corrales $
+ * $URL$
+ * $Id$
*
*/
diff --git a/engines/cruise/stringSupport.h b/engines/cruise/stringSupport.h
index 531fe56aca..841e2dd496 100644
--- a/engines/cruise/stringSupport.h
+++ b/engines/cruise/stringSupport.h
@@ -18,8 +18,8 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
- * $URL:https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/branches/gsoc2007-fsnode/engines/cruise/stringSupport.h $
- * $Id:stringSupport.h 26949 2007-05-26 20:23:24Z david_corrales $
+ * $URL$
+ * $Id$
*
*/
diff --git a/engines/cruise/various.cpp b/engines/cruise/various.cpp
index e4c908af5f..5c6134c374 100644
--- a/engines/cruise/various.cpp
+++ b/engines/cruise/various.cpp
@@ -18,8 +18,8 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
- * $URL:https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/branches/gsoc2007-fsnode/engines/cruise/various.cpp $
- * $Id:various.cpp 26949 2007-05-26 20:23:24Z david_corrales $
+ * $URL$
+ * $Id$
*
*/
diff --git a/engines/cruise/various.h b/engines/cruise/various.h
index f6e07e00e7..fe18e5abd6 100644
--- a/engines/cruise/various.h
+++ b/engines/cruise/various.h
@@ -18,8 +18,8 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
- * $URL:https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/branches/gsoc2007-fsnode/engines/cruise/various.h $
- * $Id:various.h 26949 2007-05-26 20:23:24Z david_corrales $
+ * $URL$
+ * $Id$
*
*/
diff --git a/engines/cruise/vars.cpp b/engines/cruise/vars.cpp
index 1a3d5f0a27..094680f0bb 100644
--- a/engines/cruise/vars.cpp
+++ b/engines/cruise/vars.cpp
@@ -18,8 +18,8 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
- * $URL:https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/branches/gsoc2007-fsnode/engines/cruise/vars.cpp $
- * $Id:vars.cpp 26949 2007-05-26 20:23:24Z david_corrales $
+ * $URL$
+ * $Id$
*
*/
diff --git a/engines/cruise/vars.h b/engines/cruise/vars.h
index 63a15f24e4..dbace8bdf3 100644
--- a/engines/cruise/vars.h
+++ b/engines/cruise/vars.h
@@ -18,8 +18,8 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
- * $URL:https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/branches/gsoc2007-fsnode/engines/cruise/vars.h $
- * $Id:vars.h 26949 2007-05-26 20:23:24Z david_corrales $
+ * $URL$
+ * $Id$
*
*/
diff --git a/engines/cruise/volume.cpp b/engines/cruise/volume.cpp
index 901ac4a7a5..b32ffb0ccd 100644
--- a/engines/cruise/volume.cpp
+++ b/engines/cruise/volume.cpp
@@ -18,8 +18,8 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
- * $URL:https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/branches/gsoc2007-fsnode/engines/cruise/volume.cpp $
- * $Id:volume.cpp 26949 2007-05-26 20:23:24Z david_corrales $
+ * $URL$
+ * $Id$
*
*/
diff --git a/engines/cruise/volume.h b/engines/cruise/volume.h
index 7881f6c872..0f9e489236 100644
--- a/engines/cruise/volume.h
+++ b/engines/cruise/volume.h
@@ -18,8 +18,8 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
- * $URL:https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/branches/gsoc2007-fsnode/engines/cruise/volume.h $
- * $Id:volume.h 26949 2007-05-26 20:23:24Z david_corrales $
+ * $URL$
+ * $Id$
*
*/
diff --git a/engines/drascula/drascula.cpp b/engines/drascula/drascula.cpp
index df433e12f0..eb676a7be4 100644
--- a/engines/drascula/drascula.cpp
+++ b/engines/drascula/drascula.cpp
@@ -118,7 +118,7 @@ static char mirar_t[3][88] = {TEXT100, TEXT101, TEXT54};
static char mirar_v[3][14] = {"100.als", "101.als", "54.als"};
static char poder_t[6][88] = {TEXT11, TEXT109, TEXT111, TEXT110, TEXT115, TEXT116};
static char poder_v[6][14] = {"11.als", "109.als", "111.als", "110.als", "115.als", "116.als"};
-
+
int DrasculaEngine::init() {
// Detect game
if (!initGame()) {
@@ -128,14 +128,13 @@ int DrasculaEngine::init() {
// Initialize backend
_system->beginGFXTransaction();
- initCommonGFX(false);
+ initCommonGFX(false);
_system->initSize(320, 200);
_system->endGFXTransaction();
return 0;
}
-
int DrasculaEngine::go() {
num_ejec = 1;
@@ -163,7 +162,8 @@ int DrasculaEngine::go() {
frame_velas = 0;
cont_sv = 0;
term_int = 0;
- cual_ejec = 0; hay_que_load = 0;
+ con_voces = 1;
+ hay_que_load = 0;
corta_musica = 0;
hay_seleccion = 0;
Leng = 0;
@@ -178,20 +178,73 @@ int DrasculaEngine::go() {
asigna_memoria();
carga_info();
- lee_dibujos("95.alg");
- descomprime_dibujo(dir_mesa, 1);
+ if (num_ejec != 6) {
+ lee_dibujos("95.alg");
+ descomprime_dibujo(dir_mesa, 1);
+ }
+
+ if (num_ejec == 6)
+ dir_pendulo = dir_dibujo3;
- lee_dibujos("96.alg");
- descomprime_dibujo(dir_hare_frente, COMPLETA);
if (num_ejec == 1) {
+ con_voces = 0;
+ lee_dibujos("96.alg");
+ descomprime_dibujo(dir_hare_frente, COMPLETA);
lee_dibujos("99.alg");
descomprime_dibujo(dir_hare_fondo, 1);
lee_dibujos("97.alg");
descomprime_dibujo(dir_hare_dch, 1);
} else if (num_ejec == 2) {
+ lee_dibujos("96.alg");
+ descomprime_dibujo(dir_hare_frente, COMPLETA);
lee_dibujos("pts.alg");
descomprime_dibujo(dir_dibujo2, 1);
- }
+ } else if (num_ejec == 3) {
+ lee_dibujos("aux13.alg");
+ descomprime_dibujo(dir_dibujo1, COMPLETA);
+ lee_dibujos("96.alg");
+ descomprime_dibujo(dir_hare_frente, 1);
+ lee_dibujos("97.alg");
+ descomprime_dibujo(dir_hare_dch, 1);
+ lee_dibujos("99.alg");
+ descomprime_dibujo(dir_hare_fondo, 1);
+ } else if (num_ejec == 4) {
+ lee_dibujos("96.alg");
+ descomprime_dibujo(dir_hare_frente, COMPLETA);
+ if (hay_que_load == 0)
+ animacion_rayo();
+ lee_dibujos("96.alg");
+ descomprime_dibujo(dir_hare_frente, 1);
+ borra_pantalla();
+ lee_dibujos("99.alg");
+ descomprime_dibujo(dir_hare_fondo, 1);
+ lee_dibujos("97.alg");
+ descomprime_dibujo(dir_hare_dch, 1);
+ } else if (num_ejec == 5) {
+ lee_dibujos("96.alg");
+ descomprime_dibujo(dir_hare_frente, COMPLETA);
+ lee_dibujos("97.alg");
+ descomprime_dibujo(dir_hare_dch, 1);
+ lee_dibujos("99.alg");
+ descomprime_dibujo(dir_hare_fondo, 1);
+ } else if (num_ejec == 6) {
+ x_igor = 105, y_igor = 85, sentido_igor = 1;
+ x_dr = 62, y_dr = 99, sentido_dr = 1;
+ frame_pen = 0;
+ flag_tv = 0;
+
+ dir_pendulo = dir_dibujo3;
+
+ lee_dibujos("96.alg");
+ descomprime_dibujo(dir_hare_frente, COMPLETA);
+ lee_dibujos("99.alg");
+ descomprime_dibujo(dir_hare_fondo, 1);
+ lee_dibujos("97.alg");
+ descomprime_dibujo(dir_hare_dch, 1);
+
+ lee_dibujos("95.alg");
+ descomprime_dibujo(dir_mesa, 1);
+ }
strcpy(nombre_icono[1], "look");
strcpy(nombre_icono[2], "take");
strcpy(nombre_icono[3], "open");
@@ -206,6 +259,7 @@ int DrasculaEngine::go() {
}
salir_al_dos(0);
}
+
return 0;
}
@@ -363,7 +417,7 @@ void DrasculaEngine::setvgapalette256(byte *PalBuf) {
}
void DrasculaEngine::DIBUJA_FONDO(int xorg, int yorg, int xdes, int ydes, int Ancho,
- int Alto, byte *Origen, byte *Destino) {
+ int Alto, byte *Origen, byte *Destino) {
int x;
Destino += xdes + ydes * 320;
Origen += xorg + yorg * 320;
@@ -375,7 +429,7 @@ void DrasculaEngine::DIBUJA_FONDO(int xorg, int yorg, int xdes, int ydes, int An
}
void DrasculaEngine::DIBUJA_BLOQUE(int xorg, int yorg, int xdes, int ydes, int Ancho,
- int Alto, byte *Origen, byte *Destino) {
+ int Alto, byte *Origen, byte *Destino) {
int y, x;
Destino += xdes + ydes * 320;
@@ -437,19 +491,21 @@ void DrasculaEngine::VUELCA_PANTALLA(int xorg, int yorg, int xdes, int ydes, int
}
bool DrasculaEngine::escoba() {
- int soc, l, n;
+ int n;
dir_texto = dir_mesa;
musica_antes = -1;
- soc = 0;
- for (l = 0; l < 6; l++) {
- soc = soc + ANCHO_PERSONAJE;
- frame_x[l] = soc;
+ if (num_ejec != 2) {
+ int soc = 0;
+ for (n = 0; n < 6; n++) {
+ soc = soc + ANCHO_PERSONAJE;
+ frame_x[n] = soc;
+ }
}
- for (n = 1; n < 43; n++)
+ for (n = 1; n < 50; n++)
objetos_que_tengo[n] = 0;
for (n = 0; n < NUM_BANDERAS; n++)
@@ -479,7 +535,7 @@ bool DrasculaEngine::escoba() {
if (hay_que_load != 0)
para_cargar(nom_partida);
else {
- carga_escoba_1("62.ald");
+ carga_escoba("62.ald");
hare_x = -20;
hare_y = 56;
lleva_al_hare(65, 145);
@@ -490,9 +546,73 @@ bool DrasculaEngine::escoba() {
sentido_hare = 3;
obj_saliendo = 162;
if (hay_que_load == 0)
- carga_escoba_2("14.ald");
+ carga_escoba("14.ald");
+ else
+ para_cargar(nom_partida);
+ } else if (num_ejec == 3) {
+ suma_objeto(28);
+ suma_objeto(11);
+ suma_objeto(14);
+ suma_objeto(22);
+ suma_objeto(9);
+ suma_objeto(20);
+ suma_objeto(19);
+ flags[1] = 1;
+ buffer_teclado();
+ sentido_hare = 1;
+ obj_saliendo = 99;
+ if (hay_que_load == 0)
+ carga_escoba("20.ald");
else
para_cargar(nom_partida);
+ } else if (num_ejec == 3) {
+ suma_objeto(28);
+ suma_objeto(9);
+ suma_objeto(20);
+ suma_objeto(22);
+ buffer_teclado();
+ obj_saliendo = 100;
+ if (hay_que_load == 0) {
+ carga_escoba("21.ald");
+ sentido_hare = 0;
+ hare_x = 235;
+ hare_y = 164;
+ } else
+ para_cargar(nom_partida);
+ } else if (num_ejec == 5) {
+ suma_objeto(28);
+ suma_objeto(7);
+ suma_objeto(9);
+ suma_objeto(11);
+ suma_objeto(13);
+ suma_objeto(14);
+ suma_objeto(15);
+ suma_objeto(17);
+ suma_objeto(20);
+ buffer_teclado();
+ sentido_hare = 1;
+ obj_saliendo = 100;
+ if (hay_que_load == 0) {
+ carga_escoba("45.ald");
+ } else
+ para_cargar(nom_partida);
+ } else if (num_ejec == 6) {
+ suma_objeto(28);
+ suma_objeto(9);
+
+ buffer_teclado();
+ sentido_hare = 1;
+ obj_saliendo = 104;
+ if (hay_que_load == 0)
+ carga_escoba("58.ald");
+ else
+ para_cargar(nom_partida);
+ if (hay_que_load == 0)
+ animacion_1_6();
+ else {
+ lee_dibujos("auxdr.alg");
+ descomprime_dibujo(dir_dibujo2, 1);
+ }
}
bucles:
@@ -525,38 +645,50 @@ bucles:
comprueba_objetos();
if (boton_dch == 1 && menu_scr == 1) {
- if (num_ejec == 1)
- lee_dibujos("99.alg");
- else if (num_ejec == 2)
+ if (num_ejec == 2)
lee_dibujos(fondo_y_menu);
+ else
+ lee_dibujos("99.alg");
descomprime_dibujo(dir_hare_fondo, 1);
setvgapalette256((byte *)&palJuego);
menu_scr = 0;
espera_soltar();
- cont_sv = 0;
+ if (num_ejec != 3)
+ cont_sv = 0;
}
if (boton_dch == 1 && menu_scr == 0) {
hare_se_mueve = 0;
if (sentido_hare == 2)
sentido_hare = 1;
- lee_dibujos("icons.alg");
+ if (num_ejec == 4)
+ lee_dibujos("icons2.alg");
+ else if (num_ejec == 5)
+ lee_dibujos("icons3.alg");
+ else if (num_ejec == 6)
+ lee_dibujos("iconsp.alg");
+ else
+ lee_dibujos("icons.alg");
descomprime_dibujo(dir_hare_fondo, 1);
menu_scr = 1;
espera_soltar();
sin_verbo();
- cont_sv = 0;
+ if (num_ejec != 3)
+ cont_sv = 0;
}
if (boton_izq == 1 && menu_bar == 1) {
elige_en_barra();
- cont_sv = 0;
+ if (num_ejec != 3)
+ cont_sv = 0;
} else if (boton_izq == 1 && lleva_objeto == 0) {
if (comprueba1())
return true;
- cont_sv = 0;
+ if (num_ejec != 3)
+ cont_sv = 0;
} else if (boton_izq == 1 && lleva_objeto == 1) {
comprueba2();
- cont_sv = 0;
+ if (num_ejec != 3)
+ cont_sv = 0;
}
if (y_raton < 24 && menu_scr == 0)
@@ -567,59 +699,85 @@ bucles:
Common::KeyCode key = getscan();
if (key == Common::KEYCODE_F1 && menu_scr == 0) {
elige_verbo(1);
- cont_sv = 0;
+ if (num_ejec != 3)
+ cont_sv = 0;
} else if (key == Common::KEYCODE_F2 && menu_scr == 0) {
elige_verbo(2);
- cont_sv = 0;
+ if (num_ejec != 3)
+ cont_sv = 0;
} else if (key == Common::KEYCODE_F3 && menu_scr == 0) {
elige_verbo(3);
- cont_sv = 0;
+ if (num_ejec != 3)
+ cont_sv = 0;
} else if (key == Common::KEYCODE_F4 && menu_scr == 0) {
elige_verbo(4);
cont_sv = 0;
} else if (key == Common::KEYCODE_F5 && menu_scr == 0) {
elige_verbo(5);
- cont_sv = 0;
+ if (num_ejec != 3)
+ cont_sv = 0;
} else if (key == Common::KEYCODE_F6 && menu_scr == 0) {
elige_verbo(6);
- cont_sv = 0;
+ if (num_ejec != 3)
+ cont_sv = 0;
} else if (key == Common::KEYCODE_F9) {
mesa();
- cont_sv = 0;
+ if (num_ejec != 3)
+ cont_sv = 0;
} else if (key == Common::KEYCODE_F10) {
saves();
- cont_sv = 0;
+ if (num_ejec != 3)
+ cont_sv = 0;
} else if (key == Common::KEYCODE_F8) {
sin_verbo();
- cont_sv = 0;
+ if (num_ejec != 3)
+ cont_sv = 0;
} else if (key == Common::KEYCODE_v) {
con_voces = 1;
print_abc(SYS2, 96, 86);
VUELCA_PANTALLA(0, 0, 0, 0, 320, 200, dir_zona_pantalla);
delay(1410);
- cont_sv = 0;
+ if (num_ejec != 3)
+ cont_sv = 0;
} else if (key == Common::KEYCODE_t) {
con_voces = 0;
print_abc(SYS3, 94, 86);
VUELCA_PANTALLA(0, 0, 0, 0, 320, 200, dir_zona_pantalla);
delay(1460);
- cont_sv = 0;
+ if (num_ejec != 3)
+ cont_sv = 0;
} else if (key == Common::KEYCODE_DELETE) {
- confirma_go();
- cont_sv = 0;
+ if (num_ejec == 4)
+ carga_partida("gsave00");
+ else
+ confirma_go();
+ if (num_ejec != 3)
+ cont_sv = 0;
} else if (key == Common::KEYCODE_ESCAPE) {
confirma_salir();
- cont_sv = 0;
+ if (num_ejec != 3)
+ cont_sv = 0;
+ } else if (num_ejec == 6 && key == Common::KEYCODE_0 && !strcmp(num_room, "61.alg")) {
+ lee_dibujos("alcbar.alg");
+ descomprime_dibujo(dir_dibujo1, 255);
} else if (cont_sv == 1500) {
salva_pantallas();
- cont_sv = 0;
- } else
- cont_sv++;
+ if (num_ejec != 3)
+ cont_sv = 0;
+ } else {
+ if (num_ejec != 3)
+ cont_sv++;
+ }
goto bucles;
}
void DrasculaEngine::agarra_objeto(int objeto) {
- lee_dibujos("icons.alg");
+ if (num_ejec == 6)
+ lee_dibujos("iconsp.alg");
+ else if (num_ejec == 4 || num_ejec == 5)
+ lee_dibujos("icons2.alg");
+ else
+ lee_dibujos("icons.alg");
descomprime_dibujo(dir_hare_fondo, 1);
elige_objeto(objeto);
lee_dibujos("99.alg");
@@ -627,8 +785,13 @@ void DrasculaEngine::agarra_objeto(int objeto) {
}
void DrasculaEngine::elige_objeto(int objeto) {
- if (lleva_objeto == 1 && menu_scr == 0)
- suma_objeto(objeto_que_lleva);
+ if (num_ejec == 5) {
+ if (lleva_objeto == 1 && menu_scr == 0 && objeto_que_lleva != 16)
+ suma_objeto(objeto_que_lleva);
+ } else {
+ if (lleva_objeto == 1 && menu_scr == 0)
+ suma_objeto(objeto_que_lleva);
+ }
DIBUJA_FONDO(x1d_menu[objeto], y1d_menu[objeto], 0, 0, ANCHOBJ,ALTOBJ, dir_hare_fondo, dir_dibujo3);
lleva_objeto = 1;
objeto_que_lleva = objeto;
@@ -1082,7 +1245,7 @@ bool DrasculaEngine::animacion_2_1() {
if ((term_int == 1) || (getscan() == Common::KEYCODE_ESCAPE))
break;
- strcpy(num_room,"16.alg");
+ strcpy(num_room, "16.alg");
if ((term_int == 1) || (getscan() == Common::KEYCODE_ESCAPE))
break;
@@ -1221,9 +1384,14 @@ void DrasculaEngine::sin_verbo() {
int c = 171;
if (menu_scr == 1)
c = 0;
- if (lleva_objeto == 1)
- suma_objeto(objeto_que_lleva);
- DIBUJA_FONDO(0, c, 0, 0, ANCHOBJ,ALTOBJ, dir_hare_fondo, dir_dibujo3);
+ if (num_ejec == 5) {
+ if (lleva_objeto == 1 && objeto_que_lleva != 16)
+ suma_objeto(objeto_que_lleva);
+ } else {
+ if (lleva_objeto == 1)
+ suma_objeto(objeto_que_lleva);
+ }
+ DIBUJA_FONDO(0, c, 0, 0, ANCHOBJ,ALTOBJ, dir_hare_fondo, dir_dibujo3);
lleva_objeto = 0;
hay_nombre = 0;
@@ -1232,14 +1400,14 @@ void DrasculaEngine::sin_verbo() {
void DrasculaEngine::para_cargar(char nom_game[]) {
musica_antes = musica_room;
menu_scr = 0;
- if (num_ejec == 2)
+ if (num_ejec == 2 || num_ejec == 3 || num_ejec == 4)
borra_pantalla();
carga_partida(nom_game);
- if (num_ejec == 1) {
- carga_escoba_1(datos_actuales);
- } else if (num_ejec == 2) {
- ald->close();
- carga_escoba_2(datos_actuales);
+ if (num_ejec == 1 || num_ejec == 4) {
+ carga_escoba(datos_actuales);
+ } else if (num_ejec == 2 || num_ejec == 3) {
+ delete ald;
+ carga_escoba(datos_actuales);
}
sin_verbo();
}
@@ -1269,10 +1437,11 @@ static char *getLine(Common::File *fp, char *buf, int len) {
return buf;
}
-void DrasculaEngine::carga_escoba_1(const char *nom_fich) {
- int l, obj_salir;
+void DrasculaEngine::carga_escoba(const char *nom_fich) {
+ int soc, l, martin, obj_salir;
float chiquez, pequegnez = 0;
- char para_codificar[13];
+ char pant1[20], pant2[20], pant3[20], pant4[20];
+ char para_codificar[20];
char buffer[256];
hay_nombre = 0;
@@ -1301,183 +1470,39 @@ void DrasculaEngine::carga_escoba_1(const char *nom_fich) {
getLine(ald, buffer, size);
sscanf(buffer, "%d", &nivel_osc);
- getLine(ald, buffer, size);
- sscanf(buffer, "%d", &objs_room);
-
- for (l = 0; l < objs_room; l++) {
+ if (num_ejec == 2) {
getLine(ald, buffer, size);
- sscanf(buffer, "%d", &num_obj[l]);
+ sscanf(buffer, "%d", &martin);
+ if (martin == 0)
+ goto martini;
+ ancho_hare = martin;
getLine(ald, buffer, size);
- sscanf(buffer, "%s", nombre_obj[l]);
+ sscanf(buffer, "%d",&alto_hare);
getLine(ald, buffer, size);
- sscanf(buffer, "%d", &x1[l]);
- getLine(ald, buffer, size);
- sscanf(buffer, "%d", &y1[l]);
+ sscanf(buffer, "%d",&alto_pies);
getLine(ald, buffer, size);
- sscanf(buffer, "%d", &x2[l]);
+ sscanf(buffer, "%d",&paso_x);
getLine(ald, buffer, size);
- sscanf(buffer, "%d", &y2[l]);
+ sscanf(buffer, "%d",&paso_y);
+
getLine(ald, buffer, size);
- sscanf(buffer, "%d", &sitiobj_x[l]);
+ sscanf(buffer, "%s",pant1);
getLine(ald, buffer, size);
- sscanf(buffer, "%d", &sitiobj_y[l]);
+ sscanf(buffer, "%s",pant2);
getLine(ald, buffer, size);
- sscanf(buffer, "%d", &sentidobj[l]);
+ sscanf(buffer, "%s",pant3);
getLine(ald, buffer, size);
- sscanf(buffer, "%d", &visible[l]);
- getLine(ald, buffer, size);
- sscanf(buffer, "%d", &espuerta[l]);
- if (espuerta[l] != 0) {
- getLine(ald, buffer, size);
- sscanf(buffer, "%s", alapantallakeva[l]);
- getLine(ald, buffer, size);
- sscanf(buffer, "%d", &x_alakeva[l]);
- getLine(ald, buffer, size);
- sscanf(buffer, "%d", &y_alakeva[l]);
- getLine(ald, buffer, size);
- sscanf(buffer, "%d", &sentido_alkeva[l]);
- getLine(ald, buffer, size);
- sscanf(buffer, "%d", &alapuertakeva[l]);
- puertas_cerradas(l);
- }
- }
-
- getLine(ald, buffer, size);
- sscanf(buffer, "%d", &suelo_x1);
- getLine(ald, buffer, size);
- sscanf(buffer, "%d", &suelo_y1);
- getLine(ald, buffer, size);
- sscanf(buffer, "%d", &suelo_x2);
- getLine(ald, buffer, size);
- sscanf(buffer, "%d", &suelo_y2);
-
- getLine(ald, buffer, size);
- sscanf(buffer, "%d", &lejos);
- getLine(ald, buffer, size);
- sscanf(buffer, "%d", &cerca);
- delete ald;
-
- canal_p(para_codificar);
-
- for (l = 0; l < objs_room; l++) {
- if (num_obj[l] == obj_saliendo)
- obj_salir = l;
- }
-
- lee_dibujos(pantalla_disco);
- descomprime_dibujo(dir_dibujo3, 1);
-
- lee_dibujos(num_room);
- descomprime_dibujo(dir_dibujo1, MEDIA);
-
- DIBUJA_FONDO(0, 171, 0, 0, ANCHOBJ, ALTOBJ, dir_hare_fondo, dir_dibujo3);
-
- color_hare();
- if (nivel_osc != 0)
- funde_hare(nivel_osc);
- paleta_hare_claro();
- color_hare();
- funde_hare(nivel_osc + 2);
- paleta_hare_oscuro();
-
- hare_claro();
- cambio_de_color = -1;
-
- for (l = 0; l <= suelo_y1; l++)
- factor_red[l] = lejos;
- for (l = suelo_y1; l <= 201; l++)
- factor_red[l] = cerca;
+ sscanf(buffer, "%s",pant4);
- chiquez = (float)(cerca-lejos) / (float)(suelo_y2 - suelo_y1);
- for (l = suelo_y1; l <= suelo_y2; l++) {
- factor_red[l] = (int)(lejos + pequegnez);
- pequegnez = pequegnez + chiquez;
- }
-
- if (hare_x == -1) {
- hare_x = x_alakeva[obj_salir];
- hare_y = y_alakeva[obj_salir];
- alto_hare = (ALTO_PERSONAJE * factor_red[hare_y]) / 100;
- ancho_hare = (ANCHO_PERSONAJE * factor_red[hare_y]) / 100;
- hare_y = hare_y - alto_hare;
- } else {
- alto_hare = (ALTO_PERSONAJE * factor_red[hare_y]) / 100;
- ancho_hare = (ANCHO_PERSONAJE * factor_red[hare_y]) / 100;
- }
- hare_se_mueve = 0;
-
- actualiza_datos();
-
- espuerta[7] = 0;
-
- if (musica_antes != musica_room)
- playmusic(musica_room);
- refresca_pantalla();
-}
-
-void DrasculaEngine::carga_escoba_2(const char *nom_fich) {
- int soc, l, martin, obj_salir;
- char pant1[20], pant2[20], pant3[20], pant4[20];
- char para_codificar[20];
- char buffer[256];
-
- hay_nombre = 0;
-
- strcpy(para_codificar, nom_fich);
- canal_p(para_codificar);
- strcpy(datos_actuales, nom_fich);
-
- buffer_teclado();
+ lee_dibujos(pant2);
+ descomprime_dibujo(dir_hare_dch, 1);
+ lee_dibujos(pant1);
+ descomprime_dibujo(dir_hare_frente, 1);
+ lee_dibujos(pant4);
+ descomprime_dibujo(dir_hare_fondo, 1);
- ald = new Common::File;
- ald->open(nom_fich);
- if (!ald->isOpen()) {
- error("missing data file");
+ strcpy(fondo_y_menu, pant4);
}
- int size = ald->size();
-
- getLine(ald, buffer, size);
- sscanf(buffer, "%s", num_room);
- strcat(num_room, ".alg");
-
- getLine(ald, buffer, size);
- sscanf(buffer, "%d", &musica_room);
- getLine(ald, buffer, size);
- sscanf(buffer, "%s", pantalla_disco);
- getLine(ald, buffer, size);
- sscanf(buffer, "%d", &nivel_osc);
-
- getLine(ald, buffer, size);
- sscanf(buffer, "%d", &martin);
- if (martin == 0)
- goto martini;
- ancho_hare = martin;
- getLine(ald, buffer, size);
- sscanf(buffer, "%d",&alto_hare);
- getLine(ald, buffer, size);
- sscanf(buffer, "%d",&alto_pies);
- getLine(ald, buffer, size);
- sscanf(buffer, "%d",&paso_x);
- getLine(ald, buffer, size);
- sscanf(buffer, "%d",&paso_y);
-
- getLine(ald, buffer, size);
- sscanf(buffer, "%s",pant1);
- getLine(ald, buffer, size);
- sscanf(buffer, "%s",pant2);
- getLine(ald, buffer, size);
- sscanf(buffer, "%s",pant3);
- getLine(ald, buffer, size);
- sscanf(buffer, "%s",pant4);
-
- lee_dibujos(pant2);
- descomprime_dibujo(dir_hare_dch, 1);
- lee_dibujos(pant1);
- descomprime_dibujo(dir_hare_frente, 1);
- lee_dibujos(pant4);
- descomprime_dibujo(dir_hare_fondo, 1);
-
- strcpy(fondo_y_menu, pant4);
martini:
@@ -1531,37 +1556,47 @@ martini:
getLine(ald, buffer, size);
sscanf(buffer, "%d", &suelo_y2);
+ if (num_ejec != 2) {
+ getLine(ald, buffer, size);
+ sscanf(buffer, "%d", &lejos);
+ getLine(ald, buffer, size);
+ sscanf(buffer, "%d", &cerca);
+ }
delete ald;
-
canal_p(para_codificar);
- if (martin == 0) {
- paso_x = PASO_HARE_X;
- paso_y = PASO_HARE_Y;
- alto_hare = ALTO_PERSONAJE;
- ancho_hare = ANCHO_PERSONAJE;
- alto_pies = PIES_HARE;
- lee_dibujos("97.alg");
- descomprime_dibujo(dir_hare_dch, 1);
- lee_dibujos("96.alg");
- descomprime_dibujo(dir_hare_frente, 1);
- lee_dibujos("99.alg");
- descomprime_dibujo(dir_hare_fondo, 1);
+ if (num_ejec == 2) {
+ if (martin == 0) {
+ paso_x = PASO_HARE_X;
+ paso_y = PASO_HARE_Y;
+ alto_hare = ALTO_PERSONAJE;
+ ancho_hare = ANCHO_PERSONAJE;
+ alto_pies = PIES_HARE;
+ lee_dibujos("97.alg");
+ descomprime_dibujo(dir_hare_dch, 1);
+ lee_dibujos("96.alg");
+ descomprime_dibujo(dir_hare_frente, 1);
+ lee_dibujos("99.alg");
+ descomprime_dibujo(dir_hare_fondo, 1);
- strcpy(fondo_y_menu,"99.alg");
+ strcpy(fondo_y_menu, "99.alg");
+ }
}
-
+
+ obj_salir = -1;
for (l = 0; l < objs_room; l++) {
if (num_obj[l] == obj_saliendo)
obj_salir = l;
}
- if (hare_x == -1) {
- hare_x = x_alakeva[obj_salir];
- hare_y = y_alakeva[obj_salir] - alto_hare;
+ if (num_ejec == 2) {
+ if (hare_x == -1) {
+ assert(obj_salir != -1);
+ hare_x = x_alakeva[obj_salir];
+ hare_y = y_alakeva[obj_salir] - alto_hare;
+ }
+ hare_se_mueve = 0;
}
- hare_se_mueve = 0;
-
lee_dibujos(pantalla_disco);
descomprime_dibujo(dir_dibujo3, 1);
@@ -1581,21 +1616,72 @@ martini:
hare_claro();
cambio_de_color = -1;
- color_abc(VERDE_CLARO);
+ if (num_ejec == 2)
+ color_abc(VERDE_CLARO);
+
+ if (num_ejec != 2) {
+ for (l = 0; l <= suelo_y1; l++)
+ factor_red[l] = lejos;
+ for (l = suelo_y1; l <= 201; l++)
+ factor_red[l] = cerca;
+
+ chiquez = (float)(cerca - lejos) / (float)(suelo_y2 - suelo_y1);
+ for (l = suelo_y1; l <= suelo_y2; l++) {
+ factor_red[l] = (int)(lejos + pequegnez);
+ pequegnez = pequegnez + chiquez;
+ }
+ }
+
+ if (!strcmp(num_room, "24.alg")) {
+ for (l = suelo_y1 - 1; l > 74; l--) {
+ factor_red[l] = (int)(lejos - pequegnez);
+ pequegnez = pequegnez + chiquez;
+ }
+ }
+
+ if (!strcmp(num_room, "54.alg")) {
+ for (l = suelo_y1 - 1; l > 84; l--) {
+ factor_red[l] = (int)(lejos - pequegnez);
+ pequegnez = pequegnez + chiquez;
+ }
+ }
- soc = 0;
- for (l = 0; l < 6; l++) {
- soc = soc + ancho_hare;
- frame_x[l] = soc;
+ if (num_ejec != 2) {
+ if (hare_x == -1) {
+ assert(obj_salir != -1);
+ hare_x = x_alakeva[obj_salir];
+ hare_y = y_alakeva[obj_salir];
+ alto_hare = (ALTO_PERSONAJE * factor_red[hare_y]) / 100;
+ ancho_hare = (ANCHO_PERSONAJE * factor_red[hare_y]) / 100;
+ hare_y = hare_y - alto_hare;
+ } else {
+ alto_hare = (ALTO_PERSONAJE * factor_red[hare_y]) / 100;
+ ancho_hare = (ANCHO_PERSONAJE * factor_red[hare_y]) / 100;
+ }
+ hare_se_mueve = 0;
+ }
+
+ if (num_ejec == 2) {
+ soc = 0;
+ for (l = 0; l < 6; l++) {
+ soc = soc + ancho_hare;
+ frame_x[l] = soc;
+ }
}
+ if (num_ejec == 5)
+ hare_se_ve = 1;
+
actualiza_datos();
+ if (num_ejec == 1)
+ espuerta[7] = 0;
+
if (!strcmp(num_room, "14.alg") && flags[39] == 1)
musica_room = 16;
else if (!strcmp(num_room, "15.alg") && flags[39] == 1)
musica_room = 16;
- if (!strcmp(num_room, "14.alg") && flags[5]==1)
+ if (!strcmp(num_room, "14.alg") && flags[5] == 1)
musica_room = 0;
else if (!strcmp(num_room, "15.alg") && flags[5] == 1)
musica_room = 0;
@@ -1606,9 +1692,17 @@ martini:
stopmusic();
if ((!strcmp(num_room, "9.alg")) || (strcmp(num_room, "2.alg"))
- || (!strcmp(num_room, "14.alg")) || (!strcmp(num_room, "18.alg")))
- conta_ciego_vez = vez();
+ || (!strcmp(num_room, "14.alg")) || (!strcmp(num_room, "18.alg"))
+ || (!strcmp(num_room, "26.alg")))
+ conta_ciego_vez = (int)vez();
+ if (!strcmp(num_room, "24.alg") && flags[29] == 1)
+ animacion_7_4();
+ if (!strcmp(num_room, "45.alg"))
+ hare_se_ve = 0;
+ if (!strcmp(num_room, "49.alg") && flags[7] == 0)
+ animacion_4_5();
+
refresca_pantalla();
}
@@ -1619,11 +1713,18 @@ void DrasculaEngine::borra_pantalla() {
}
void DrasculaEngine::lleva_al_hare(int punto_x, int punto_y) {
+ if (num_ejec == 5 || num_ejec == 6) {
+ if (hare_se_ve == 0) {
+ hare_x = sitio_x;
+ hare_y = sitio_y;
+ goto fin;
+ }
+ }
sitio_x = punto_x;
sitio_y = punto_y;
empieza_andar();
- for(;;) {
+ for (;;) {
refresca_pantalla();
VUELCA_PANTALLA(0, 0, 0, 0, 320, 200, dir_zona_pantalla);
if (hare_se_mueve == 0)
@@ -1634,6 +1735,7 @@ void DrasculaEngine::lleva_al_hare(int punto_x, int punto_y) {
anda_a_objeto = 0;
sentido_hare = sentido_final;
}
+fin:
refresca_pantalla();
VUELCA_PANTALLA(0, 0, 0, 0, 320, 200, dir_zona_pantalla);
}
@@ -1681,20 +1783,21 @@ void DrasculaEngine::comprueba_objetos() {
}
}
- if (num_ejec == 1)
+ if (num_ejec == 2) {
if (x_raton > hare_x + 2 && y_raton > hare_y + 2
- && x_raton < hare_x + ancho_hare - 2 && y_raton < hare_y + alto_hare - 2 && veo == 0) {
+ && x_raton < hare_x + ancho_hare - 2 && y_raton < hare_y + alto_hare - 2) {
strcpy(texto_nombre, "hacker");
hay_nombre = 1;
veo = 1;
}
- else if (num_ejec == 2)
+ } else {
if (x_raton > hare_x + 2 && y_raton > hare_y + 2
- && x_raton < hare_x + ancho_hare - 2 && y_raton < hare_y + alto_hare - 2) {
+ && x_raton < hare_x + ancho_hare - 2 && y_raton < hare_y + alto_hare - 2 && veo == 0) {
strcpy(texto_nombre, "hacker");
hay_nombre = 1;
veo = 1;
}
+ }
if (veo == 0)
hay_nombre = 0;
@@ -1790,6 +1893,8 @@ void DrasculaEngine::comprueba2() {
anda_a_objeto = 1;
lleva_al_hare(sitiobj_x[l], sitiobj_y[l]);
banderas(num_obj[l]);
+ if (num_ejec == 4)
+ break;
}
}
}
@@ -1847,8 +1952,13 @@ void DrasculaEngine::elige_verbo(int verbo) {
if (menu_scr == 1)
c = 0;
- if (lleva_objeto == 1)
- suma_objeto(objeto_que_lleva);
+ if (num_ejec == 5) {
+ if (lleva_objeto == 1 && objeto_que_lleva != 16)
+ suma_objeto(objeto_que_lleva);
+ } else {
+ if (lleva_objeto == 1)
+ suma_objeto(objeto_que_lleva);
+ }
DIBUJA_FONDO(ANCHOBJ * verbo, c, 0, 0, ANCHOBJ, ALTOBJ, dir_hare_fondo, dir_dibujo3);
@@ -1920,7 +2030,7 @@ void DrasculaEngine::mesa() {
void DrasculaEngine::saves() {
char nombres[10][23];
char fichero[13];
- int n, n2, num_sav, y = 27;
+ int n, n2, num_sav = 0, y = 27;
Common::InSaveFile *sav;
borra_pantalla();
@@ -1955,6 +2065,9 @@ void DrasculaEngine::saves() {
for (n = 0; n < NUM_SAVES; n++) {
if (x_raton > 115 && y_raton > y + (9 * n) && x_raton < 115 + 175 && y_raton < y + 10 + (9 * n)) {
strcpy(select, nombres[n]);
+
+ // FIXME: The indention is wrong and misleading here!!! Or maybe there's simply a
+ // closing brace missing here??? See below for a second FIXME of a similar kind...
if (strcmp(select, "*"))
hay_seleccion = 1;
@@ -1962,6 +2075,8 @@ void DrasculaEngine::saves() {
introduce_nombre();
strcpy(nombres[n], select);
if (hay_seleccion == 1) {
+ // FIXME: Just use:
+ //sprintf(fichero, "gsave%02d", n+1);
if (n == 0)
strcpy(fichero, "gsave01");
if (n == 1)
@@ -2001,6 +2116,8 @@ void DrasculaEngine::saves() {
y = y + 9;
}
if (hay_seleccion == 1) {
+ // FIXME: Just use:
+ //sprintf(fichero, "gsave%02d", n+1);
if (n == 0)
strcpy(fichero, "gsave01");
if (n == 1)
@@ -2020,7 +2137,12 @@ void DrasculaEngine::saves() {
if (n == 8)
strcpy(fichero, "gsave09");
if (n == 9)
- strcpy(fichero, "gsave10");}
+ strcpy(fichero, "gsave10");} // FIXME: EVIL wrong place for closing brace!
+ // In particular: is the assignment below maybe supposed to be inside the "if"
+ // statement that was just closed?
+ // Also note that the indention is wrong here, which is not immediately visible
+ // due to the other indention mistake above. But is the indention wrong, or is
+ // the brace placement wrong???
num_sav = n;
}
}
@@ -2052,7 +2174,7 @@ void DrasculaEngine::saves() {
} else if (x_raton > 168 && y_raton > 154 && x_raton < 242 && y_raton < 180)
break;
else if (hay_seleccion == 0) {
- print_abc("elige una partida",117,15);
+ print_abc("elige una partida", 117, 15);
}
VUELCA_PANTALLA(0, 0, 0, 0, 320, 200, dir_zona_pantalla);
delay(400);
@@ -2436,8 +2558,8 @@ char DrasculaEngine::LimitaVGA(char valor) {
}
void DrasculaEngine::centra_texto(const char *mensaje, int x_texto, int y_texto) {
- char bb[190], m2[190], m1[190], mb[10][40];
- char m3[190];
+ char bb[200], m2[200], m1[200], mb[10][50];
+ char m3[200];
int h, fil, x_texto3, x_texto2, x_texto1, conta_f = 0, ya = 0;
strcpy(m1, " ");
@@ -2669,10 +2791,14 @@ void DrasculaEngine::pon_igor() {
int pos_igor[6];
pos_igor[0] = 1;
- if (sentido_igor == 3)
+ if (num_ejec == 4) {
pos_igor[1] = 138;
- else if (sentido_igor == 1)
- pos_igor[1] = 76;
+ } else {
+ if (sentido_igor == 3)
+ pos_igor[1] = 138;
+ else if (sentido_igor == 1)
+ pos_igor[1] = 76;
+ }
pos_igor[2] = x_igor;
pos_igor[3] = y_igor;
pos_igor[4] = 54;
@@ -2719,13 +2845,13 @@ void DrasculaEngine::habla_igor_dch(const char *dicho, const char *filename) {
int tiempou;
long tiempol;
- int x_habla[8] = { 56, 82, 108, 134, 160, 186, 212, 238};
+ int x_habla[8] = { 56, 82, 108, 134, 160, 186, 212, 238 };
int cara;
int longitud;
longitud = strlen(dicho);
- tiempol = time (NULL);
+ tiempol = _system->getMillis();
tiempou = (unsigned int)tiempol / 2;
_rnd->setSeed(tiempou);
@@ -2754,11 +2880,9 @@ bucless:
pon_igor();
pon_dr();
- DIBUJA_FONDO(x_igor + 17, y_igor, x_igor + 17, y_igor, 37, 24,
- dir_dibujo1, dir_zona_pantalla);
+ DIBUJA_FONDO(x_igor + 17, y_igor, x_igor + 17, y_igor, 37, 24, dir_dibujo1, dir_zona_pantalla);
- DIBUJA_BLOQUE(x_habla[cara], 148, x_igor + 17, y_igor, 25, 24,
- dir_hare_frente, dir_zona_pantalla);
+ DIBUJA_BLOQUE(x_habla[cara], 148, x_igor + 17, y_igor, 25, 24, dir_hare_frente, dir_zona_pantalla);
actualiza_refresco();
@@ -2832,8 +2956,7 @@ bucless:
pon_dr();
DIBUJA_FONDO(x_dr, y_dr, x_dr, y_dr, 38, 31, dir_dibujo1, dir_zona_pantalla);
- DIBUJA_BLOQUE(x_habla[cara], 90, x_dr, y_dr, 38, 31,
- dir_hare_fondo, dir_zona_pantalla);
+ DIBUJA_BLOQUE(x_habla[cara], 90, x_dr, y_dr, 38, 31, dir_hare_fondo, dir_zona_pantalla);
actualiza_refresco();
@@ -2907,8 +3030,7 @@ bucless:
pon_dr();
DIBUJA_FONDO(x_dr, y_dr, x_dr, y_dr, 45, 31, dir_dibujo1, dir_zona_pantalla);
- DIBUJA_BLOQUE(x_habla[cara], 58, x_dr + 7, y_dr, 38, 31,
- dir_hare_fondo, dir_zona_pantalla);
+ DIBUJA_BLOQUE(x_habla[cara], 58, x_dr + 7, y_dr, 38, 31, dir_hare_fondo, dir_zona_pantalla);
actualiza_refresco();
@@ -2994,7 +3116,7 @@ void DrasculaEngine::habla_igor_frente(const char *dicho, const char *filename)
int tiempou;
long tiempol;
- int x_habla[8] = { 56, 86, 116, 146, 176, 206, 236, 266};
+ int x_habla[8] = { 56, 86, 116, 146, 176, 206, 236, 266 };
int cara;
int longitud;
@@ -3029,17 +3151,15 @@ bucless:
pon_igor();
pon_dr();
- DIBUJA_FONDO(x_igor, y_igor, x_igor, y_igor, 29, 25,
- dir_dibujo1, dir_zona_pantalla);
- DIBUJA_BLOQUE(x_habla[cara], 173, x_igor, y_igor, 29, 25,
- dir_hare_frente, dir_zona_pantalla);
+ DIBUJA_FONDO(x_igor, y_igor, x_igor, y_igor, 29, 25, dir_dibujo1, dir_zona_pantalla);
+ DIBUJA_BLOQUE(x_habla[cara], 173, x_igor, y_igor, 29, 25, dir_hare_frente, dir_zona_pantalla);
actualiza_refresco();
if (con_voces == 0)
centra_texto(dicho, x_igor + 26, y_igor);
- VUELCA_PANTALLA(0,0, 0,0, 320,200, dir_zona_pantalla);
+ VUELCA_PANTALLA(0, 0, 0, 0, 320, 200, dir_zona_pantalla);
pausa(3);
@@ -3070,7 +3190,7 @@ void DrasculaEngine::habla_tabernero(const char *dicho, const char *filename) {
int tiempou;
long tiempol;
- int x_habla[9] = { 1, 23, 45, 67, 89, 111, 133, 155, 177};
+ int x_habla[9] = { 1, 23, 45, 67, 89, 111, 133, 155, 177 };
int cara;
int longitud;
@@ -3138,23 +3258,33 @@ bucless:
void DrasculaEngine::hipo(int contador) {
int y = 0, sentido = 0;
-
- contador = contador;
+ if (num_ejec == 3)
+ y = -1;
comienza:
contador--;
refresca_pantalla();
- VUELCA_PANTALLA(0, 1, 0, y, 320, 198, dir_zona_pantalla);
+ if (num_ejec <= 2)
+ VUELCA_PANTALLA(0, 1, 0, y, 320, 198, dir_zona_pantalla);
+ else if (num_ejec == 3)
+ VUELCA_PANTALLA(0, 0, 0, y, 320, 200, dir_zona_pantalla);
if (sentido == 0)
y++;
else
y--;
- if (y == 2)
- sentido = 1;
- if (y == 0)
- sentido = 0;
+ if (num_ejec <= 2) {
+ if (y == 2)
+ sentido = 1;
+ if (y == 0)
+ sentido = 0;
+ } else if (num_ejec == 3) {
+ if (y == 1)
+ sentido = 1;
+ if (y == -1)
+ sentido = 0;
+ }
if (contador > 0)
goto comienza;
@@ -3175,7 +3305,7 @@ void DrasculaEngine::habla_bj(const char *dicho, const char *filename) {
int tiempou;
long tiempol;
- int x_habla[5] = { 64, 92, 120, 148, 176};
+ int x_habla[5] = { 64, 92, 120, 148, 176 };
int cara;
int longitud;
@@ -3258,6 +3388,17 @@ void DrasculaEngine::hablar(const char *dicho, const char *filename) {
int longitud;
longitud = strlen(dicho);
+ if (num_ejec == 6) {
+ if (flags[0] == 0 && (!strcmp(num_room, "102.alg"))) {
+ habla_pen(dicho, filename);
+ return;
+ }
+ if (flags[0] == 0 && (!strcmp(num_room, "58.alg"))) {
+ habla_pen2(dicho, filename);
+ return;
+ }
+ }
+
tiempol = _system->getMillis();
tiempou = (unsigned int)tiempol / 2;
_rnd->setSeed(tiempou);
@@ -3268,8 +3409,12 @@ void DrasculaEngine::hablar(const char *dicho, const char *filename) {
if (num_ejec == 2)
buffer_teclado();
- color_abc(AMARILLO);
-
+ if (num_ejec == 4) {
+ if (strcmp(num_room, "24.alg") || flags[29] == 0)
+ color_abc(AMARILLO);
+ } else {
+ color_abc(AMARILLO);
+ }
if (hay_sb == 1) {
sku = new Common::File;
sku->open(filename);
@@ -3289,20 +3434,15 @@ bucless:
actualiza_refresco_antes();
if (num_ejec == 1)
- DIBUJA_FONDO(hare_x, hare_y, ANCHOBJ + 1, 0,
- ancho_hare * factor_red[hare_y + alto_hare] / 100,
- (alto_habla - 1) * factor_red[hare_y + alto_hare] / 100,
- dir_zona_pantalla, dir_dibujo3);
+ DIBUJA_FONDO(hare_x, hare_y, ANCHOBJ + 1, 0, ancho_hare * factor_red[hare_y + alto_hare] / 100,
+ (alto_habla - 1) * factor_red[hare_y + alto_hare] / 100, dir_zona_pantalla, dir_dibujo3);
else if (num_ejec == 2)
- DIBUJA_FONDO(hare_x, hare_y, ANCHOBJ + 1, 0, ancho_hare, alto_habla - 1,
- dir_zona_pantalla, dir_dibujo3);
+ DIBUJA_FONDO(hare_x, hare_y, ANCHOBJ + 1, 0, ancho_hare, alto_habla - 1, dir_zona_pantalla, dir_dibujo3);
pon_hare();
if (num_ejec == 1)
- DIBUJA_FONDO(ANCHOBJ + 1, 0, hare_x, hare_y,
- ancho_hare * factor_red[hare_y + alto_hare] / 100,
- (alto_habla - 1) * factor_red[hare_y + alto_hare] / 100,
- dir_dibujo3, dir_zona_pantalla);
+ DIBUJA_FONDO(ANCHOBJ + 1, 0, hare_x, hare_y, ancho_hare * factor_red[hare_y + alto_hare] / 100,
+ (alto_habla - 1) * factor_red[hare_y + alto_hare] / 100, dir_dibujo3, dir_zona_pantalla);
else if (num_ejec == 2)
DIBUJA_FONDO(ANCHOBJ + 1, 0, hare_x, hare_y,
ancho_hare, alto_habla - 1,
@@ -3310,24 +3450,20 @@ bucless:
if (sentido_hare == 0) {
if (num_ejec == 1)
- reduce_hare_chico(x_habla_izq[cara], y_mask_habla,
- hare_x + 8 * factor_red[hare_y + alto_hare] / 100,
+ reduce_hare_chico(x_habla_izq[cara], y_mask_habla, hare_x + 8 * factor_red[hare_y + alto_hare] / 100,
hare_y, ancho_habla, alto_habla, factor_red[hare_y + alto_hare],
dir_hare_dch, dir_zona_pantalla);
else if (num_ejec == 2)
- DIBUJA_BLOQUE(x_habla_dch[cara], y_mask_habla,
- hare_x + 12, hare_y, ancho_habla, alto_habla,
+ DIBUJA_BLOQUE(x_habla_dch[cara], y_mask_habla, hare_x + 12, hare_y, ancho_habla, alto_habla,
dir_hare_dch, dir_zona_pantalla);
actualiza_refresco();
} else if (sentido_hare == 1) {
if (num_ejec == 1)
- reduce_hare_chico(x_habla_dch[cara], y_mask_habla,
- hare_x + 12 * factor_red[hare_y + alto_hare] / 100,
- hare_y, ancho_habla,alto_habla, factor_red[hare_y + alto_hare],
+ reduce_hare_chico(x_habla_dch[cara], y_mask_habla, hare_x + 12 * factor_red[hare_y + alto_hare] / 100,
+ hare_y, ancho_habla,alto_habla, factor_red[hare_y + alto_hare],
dir_hare_dch, dir_zona_pantalla);
else if (num_ejec == 2)
- DIBUJA_BLOQUE(x_habla_dch[cara], y_mask_habla,
- hare_x + 8, hare_y, ancho_habla, alto_habla,
+ DIBUJA_BLOQUE(x_habla_dch[cara], y_mask_habla, hare_x + 8, hare_y, ancho_habla, alto_habla,
dir_hare_dch, dir_zona_pantalla);
actualiza_refresco();
} else if (sentido_hare == 2) {
@@ -3393,7 +3529,13 @@ int DrasculaEngine::music_status() {
void DrasculaEngine::refresca_pantalla() {
DIBUJA_FONDO(0, 0, 0, 0, 320, 200, dir_dibujo1, dir_zona_pantalla);
actualiza_refresco_antes();
- pon_hare();
+ if (num_ejec == 3) {
+ if (flags[0] == 0)
+ pon_hare();
+ else
+ DIBUJA_BLOQUE(113, 54, hare_x - 20, hare_y - 1, 77, 89, dir_dibujo3, dir_zona_pantalla);
+ } else
+ pon_hare();
actualiza_refresco();
}
@@ -3465,38 +3607,92 @@ void DrasculaEngine::canal_p(const char *fich){
rename(fich2, fich);
}
-void DrasculaEngine::puertas_cerradas (int l) {
- if (num_ejec == 1)
+void DrasculaEngine::puertas_cerradas(int l) {
+ if (num_ejec == 1 || num_ejec == 3 || num_ejec == 5 || num_ejec == 6)
return;
-
- if (num_obj[l] == 138 && flags[0] == 0)
- espuerta[l] = 0;
- else if (num_obj[l] == 138 && flags[0] == 1)
- espuerta[l] = 1;
- else if (num_obj[l] == 136 && flags[8] == 0)
- espuerta[l] = 0;
- else if (num_obj[l] == 136 && flags[8] == 1)
- espuerta[l] = 1;
- else if (num_obj[l] == 156 && flags[16] == 0)
- espuerta[l] = 0;
- else if (num_obj[l] == 156 && flags[16] == 1)
- espuerta[l] = 1;
- else if (num_obj[l] == 163 && flags[17] == 0)
- espuerta[l] = 0;
- else if (num_obj[l] == 163 && flags[17] == 1)
- espuerta[l] = 1;
- else if (num_obj[l] == 177 && flags[15] == 0)
- espuerta[l] = 0;
- else if (num_obj[l] == 177 && flags[15] == 1)
- espuerta[l] = 1;
- else if (num_obj[l] == 175 && flags[40] == 0)
- espuerta[l] = 0;
- else if (num_obj[l] == 175 && flags[40] == 1)
- espuerta[l] = 1;
- else if (num_obj[l] == 173 && flags[36] == 0)
- espuerta[l] = 0;
- else if (num_obj[l] == 173 && flags[36] == 1)
- espuerta[l] = 1;
+ else if (num_ejec == 2) {
+ if (num_obj[l] == 138 && flags[0] == 0)
+ espuerta[l] = 0;
+ else if (num_obj[l] == 138 && flags[0] == 1)
+ espuerta[l] = 1;
+ else if (num_obj[l] == 136 && flags[8] == 0)
+ espuerta[l] = 0;
+ else if (num_obj[l] == 136 && flags[8] == 1)
+ espuerta[l] = 1;
+ else if (num_obj[l] == 156 && flags[16] == 0)
+ espuerta[l] = 0;
+ else if (num_obj[l] == 156 && flags[16] == 1)
+ espuerta[l] = 1;
+ else if (num_obj[l] == 163 && flags[17] == 0)
+ espuerta[l] = 0;
+ else if (num_obj[l] == 163 && flags[17] == 1)
+ espuerta[l] = 1;
+ else if (num_obj[l] == 177 && flags[15] == 0)
+ espuerta[l] = 0;
+ else if (num_obj[l] == 177 && flags[15] == 1)
+ espuerta[l] = 1;
+ else if (num_obj[l] == 175 && flags[40] == 0)
+ espuerta[l] = 0;
+ else if (num_obj[l] == 175 && flags[40] == 1)
+ espuerta[l] = 1;
+ else if (num_obj[l] == 173 && flags[36] == 0)
+ espuerta[l] = 0;
+ else if (num_obj[l] == 173 && flags[36] == 1)
+ espuerta[l] = 1;
+ } else if (num_ejec == 4) {
+ if (num_obj[l] == 101 && flags[0] == 0)
+ espuerta[l] = 0;
+ else if (num_obj[l] == 101 && flags[0] == 1 && flags[28] == 1)
+ espuerta[l] = 1;
+ else if (num_obj[l] == 103 && flags[0] == 0)
+ espuerta[l] = 0;
+ else if (num_obj[l] == 103 && flags[0] == 1)
+ espuerta[l] = 1;
+ else if (num_obj[l] == 104 && flags[1] == 0)
+ espuerta[l] = 0;
+ else if (num_obj[l] == 104 && flags[1] == 1)
+ espuerta[l] = 1;
+ else if (num_obj[l] == 105 && flags[1] == 0)
+ espuerta[l] = 0;
+ else if (num_obj[l] == 105 && flags[1] == 1)
+ espuerta[l] = 1;
+ else if (num_obj[l] == 106 && flags[2] == 0)
+ espuerta[l] = 0;
+ else if (num_obj[l] == 106 && flags[2] == 1)
+ espuerta[l] = 1;
+ else if (num_obj[l] == 107 && flags[2] == 0)
+ espuerta[l] = 0;
+ else if (num_obj[l] == 107 && flags[2] == 1)
+ espuerta[l] = 1;
+ else if (num_obj[l] == 110 && flags[6] == 0)
+ espuerta[l] = 0;
+ else if (num_obj[l] == 110 && flags[6] == 1)
+ espuerta[l] = 1;
+ else if (num_obj[l] == 114 && flags[4] == 0)
+ espuerta[l] = 0;
+ else if (num_obj[l] == 114 && flags[4] == 1)
+ espuerta[l] = 1;
+ else if (num_obj[l] == 115 && flags[4] == 0)
+ espuerta[l] = 0;
+ else if (num_obj[l] == 115 && flags[4] == 1)
+ espuerta[l] = 1;
+ else if (num_obj[l] == 116 && flags[5] == 0)
+ espuerta[l] = 0;
+ else if (num_obj[l] == 116 && flags[5] == 1 && flags[23] == 1)
+ espuerta[l] = 1;
+ else if (num_obj[l] == 117 && flags[5] == 0)
+ espuerta[l] = 0;
+ else if (num_obj[l] == 117 && flags[5] == 1)
+ espuerta[l] = 1;
+ else if (num_obj[l] == 120 && flags[8] == 0)
+ espuerta[l] = 0;
+ else if (num_obj[l] == 120 && flags[8] == 1)
+ espuerta[l] = 1;
+ else if (num_obj[l] == 122 && flags[7] == 0)
+ espuerta[l] = 0;
+ else if (num_obj[l] == 122 && flags[7] == 1)
+ espuerta[l] = 1;
+ }
}
void DrasculaEngine::color_hare() {
@@ -3559,18 +3755,7 @@ void DrasculaEngine::empieza_andar() {
paso_x = PASO_HARE_X;
paso_y = PASO_HARE_Y;
- if (num_ejec == 1) {
- if ((sitio_x < hare_x + ancho_hare / 2 ) && (sitio_y <= (hare_y + alto_hare)))
- cuadrante_1();
- else if ((sitio_x < hare_x + ancho_hare / 2) && (sitio_y > (hare_y + alto_hare)))
- cuadrante_3();
- else if ((sitio_x > hare_x + ancho_hare / 2) && (sitio_y <= (hare_y + alto_hare)))
- cuadrante_2();
- else if ((sitio_x > hare_x + ancho_hare / 2) && (sitio_y > (hare_y + alto_hare)))
- cuadrante_4();
- else
- hare_se_mueve = 0;
- } else if (num_ejec == 2) {
+ if (num_ejec == 2) {
if ((sitio_x < hare_x) && (sitio_y <= (hare_y + alto_hare)))
cuadrante_1();
else if ((sitio_x < hare_x) && (sitio_y > (hare_y + alto_hare)))
@@ -3583,6 +3768,17 @@ void DrasculaEngine::empieza_andar() {
anda_parriba();
else if (sitio_y > hare_y + alto_hare)
anda_pabajo();
+ } else {
+ if ((sitio_x < hare_x + ancho_hare / 2 ) && (sitio_y <= (hare_y + alto_hare)))
+ cuadrante_1();
+ else if ((sitio_x < hare_x + ancho_hare / 2) && (sitio_y > (hare_y + alto_hare)))
+ cuadrante_3();
+ else if ((sitio_x > hare_x + ancho_hare / 2) && (sitio_y <= (hare_y + alto_hare)))
+ cuadrante_2();
+ else if ((sitio_x > hare_x + ancho_hare / 2) && (sitio_y > (hare_y + alto_hare)))
+ cuadrante_4();
+ else
+ hare_se_mueve = 0;
}
conta_vez = vez();
}
@@ -3592,7 +3788,13 @@ void DrasculaEngine::actualiza_refresco() {
refresca_63();
else if (!strcmp(num_room, "62.alg"))
refresca_62();
- else if (!strcmp(num_room, "3.alg"))
+ else if (!strcmp(num_room, "60.alg"))
+ refresca_60();
+ else if (!strcmp(num_room, "61.alg"))
+ refresca_61();
+ else if (!strcmp(num_room, "58.alg"))
+ refresca_58();
+ else if (!strcmp(num_room, "3.alg"))
refresca_3();
else if (!strcmp(num_room, "2.alg"))
refresca_2();
@@ -3608,11 +3810,29 @@ void DrasculaEngine::actualiza_refresco() {
refresca_18();
else if (!strcmp(num_room, "10.alg"))
mapa();
-}
+ else if (!strcmp(num_room, "20.alg"))
+ refresca_20();
+ else if (!strcmp(num_room, "13.alg"))
+ refresca_13();
+ else if (!strcmp(num_room, "45.alg"))
+ mapa();
+ else if (!strcmp(num_room, "50.alg"))
+ refresca_50();
+ else if (!strcmp(num_room, "57.alg"))
+ refresca_57();
+ }
void DrasculaEngine::actualiza_refresco_antes() {
if (!strcmp(num_room, "62.alg"))
refresca_62_antes();
+ else if (!strcmp(num_room, "102.alg"))
+ refresca_pendulo();
+ else if (!strcmp(num_room, "58.alg"))
+ refresca_58_antes();
+ else if (!strcmp(num_room, "59.alg"))
+ refresca_59_antes();
+ else if (!strcmp(num_room, "60.alg"))
+ refresca_60_antes();
else if (!strcmp(num_room, "1.alg"))
refresca_1_antes();
else if (!strcmp(num_room, "3.alg"))
@@ -3639,6 +3859,14 @@ void DrasculaEngine::actualiza_refresco_antes() {
refresca_17_antes();
else if (!strcmp(num_room,"18.alg"))
refresca_18_antes();
+ else if (!strcmp(num_room,"49.alg"))
+ refresca_49_antes();
+ else if (!strcmp(num_room,"53.alg"))
+ refresca_53_antes();
+ else if (!strcmp(num_room,"54.alg"))
+ refresca_54_antes();
+ else if (!strcmp(num_room,"56.alg"))
+ refresca_56_antes();
}
void DrasculaEngine::pon_hare() {
@@ -3691,7 +3919,7 @@ void DrasculaEngine::pon_hare() {
}
}
- if (num_ejec == 1)
+ if (num_ejec == 1 || num_ejec == 4 || num_ejec == 5 || num_ejec == 6)
if (hare_se_ve == 0)
goto no_vuelco;
@@ -3700,100 +3928,76 @@ void DrasculaEngine::pon_hare() {
pos_hare[1] = DIF_MASK_HARE;
pos_hare[2] = hare_x;
pos_hare[3] = hare_y;
- if (num_ejec == 1) {
- pos_hare[4] = ANCHO_PERSONAJE;
- pos_hare[5] = ALTO_PERSONAJE;
- } else if (num_ejec == 2) {
+ if (num_ejec == 2) {
pos_hare[4] = ancho_hare;
pos_hare[5] = alto_hare;
+ } else {
+ pos_hare[4] = ANCHO_PERSONAJE;
+ pos_hare[5] = ALTO_PERSONAJE;
}
if (sentido_hare == 0) {
pos_hare[1] = 0;
- if (num_ejec == 1)
- reduce_hare_chico(pos_hare[0], pos_hare[1],
- pos_hare[2], pos_hare[3],
- pos_hare[4], pos_hare[5],
- factor_red[hare_y + alto_hare],
- dir_hare_dch, dir_zona_pantalla);
- else if (num_ejec == 2)
+ if (num_ejec == 2)
DIBUJA_BLOQUE_CUT(pos_hare, dir_hare_dch, dir_zona_pantalla);
+ else
+ reduce_hare_chico(pos_hare[0], pos_hare[1], pos_hare[2], pos_hare[3], pos_hare[4], pos_hare[5],
+ factor_red[hare_y + alto_hare], dir_hare_dch, dir_zona_pantalla);
} else if (sentido_hare == 1)
- if (num_ejec == 1)
- reduce_hare_chico(pos_hare[0], pos_hare[1],
- pos_hare[2], pos_hare[3],
- pos_hare[4], pos_hare[5],
- factor_red[hare_y + alto_hare],
- dir_hare_dch, dir_zona_pantalla);
- else if (num_ejec == 2)
+ if (num_ejec == 2)
DIBUJA_BLOQUE_CUT(pos_hare, dir_hare_dch, dir_zona_pantalla);
+ else
+ reduce_hare_chico(pos_hare[0], pos_hare[1], pos_hare[2], pos_hare[3], pos_hare[4], pos_hare[5],
+ factor_red[hare_y + alto_hare], dir_hare_dch, dir_zona_pantalla);
else if (sentido_hare == 2)
- if (num_ejec == 1)
- reduce_hare_chico( pos_hare[0], pos_hare[1],
- pos_hare[2], pos_hare[3],
- pos_hare[4], pos_hare[5],
- factor_red[hare_y + alto_hare],
- dir_hare_fondo, dir_zona_pantalla);
- else if (num_ejec == 2)
+ if (num_ejec == 2)
DIBUJA_BLOQUE_CUT(pos_hare, dir_hare_fondo, dir_zona_pantalla);
+ else
+ reduce_hare_chico(pos_hare[0], pos_hare[1], pos_hare[2], pos_hare[3], pos_hare[4], pos_hare[5],
+ factor_red[hare_y + alto_hare], dir_hare_fondo, dir_zona_pantalla);
else
- if (num_ejec == 1)
- reduce_hare_chico( pos_hare[0], pos_hare[1],
- pos_hare[2], pos_hare[3],
- pos_hare[4], pos_hare[5],
- factor_red[hare_y + alto_hare],
- dir_hare_frente, dir_zona_pantalla);
- else if (num_ejec == 2)
+ if (num_ejec == 2)
DIBUJA_BLOQUE_CUT(pos_hare, dir_hare_frente, dir_zona_pantalla);
+ else
+ reduce_hare_chico( pos_hare[0], pos_hare[1], pos_hare[2], pos_hare[3], pos_hare[4], pos_hare[5],
+ factor_red[hare_y + alto_hare], dir_hare_frente, dir_zona_pantalla);
} else if (hare_se_mueve == 1) {
pos_hare[0] = frame_x[num_frame];
pos_hare[1] = frame_y + DIF_MASK_HARE;
pos_hare[2] = hare_x;
pos_hare[3] = hare_y;
- if (num_ejec == 1) {
- pos_hare[4] = ANCHO_PERSONAJE;
- pos_hare[5] = ALTO_PERSONAJE;
- } else if (num_ejec == 2) {
+ if (num_ejec == 2) {
pos_hare[4] = ancho_hare;
pos_hare[5] = alto_hare;
+ } else {
+ pos_hare[4] = ANCHO_PERSONAJE;
+ pos_hare[5] = ALTO_PERSONAJE;
}
if (sentido_hare == 0) {
pos_hare[1] = 0;
- if (num_ejec == 1)
- reduce_hare_chico(pos_hare[0], pos_hare[1],
- pos_hare[2], pos_hare[3],
- pos_hare[4], pos_hare[5],
- factor_red[hare_y + alto_hare],
- dir_hare_dch, dir_zona_pantalla);
- else if (num_ejec == 2)
+ if (num_ejec == 2)
DIBUJA_BLOQUE_CUT(pos_hare, dir_hare_dch, dir_zona_pantalla);
+ else
+ reduce_hare_chico(pos_hare[0], pos_hare[1], pos_hare[2], pos_hare[3], pos_hare[4], pos_hare[5],
+ factor_red[hare_y + alto_hare], dir_hare_dch, dir_zona_pantalla);
} else if (sentido_hare == 1)
if (num_ejec == 1)
- reduce_hare_chico(pos_hare[0], pos_hare[1],
- pos_hare[2], pos_hare[3],
- pos_hare[4], pos_hare[5],
- factor_red[hare_y + alto_hare],
- dir_hare_dch, dir_zona_pantalla);
- else if (num_ejec == 2)
DIBUJA_BLOQUE_CUT(pos_hare, dir_hare_dch, dir_zona_pantalla);
+ else
+ reduce_hare_chico(pos_hare[0], pos_hare[1], pos_hare[2], pos_hare[3], pos_hare[4], pos_hare[5],
+ factor_red[hare_y + alto_hare], dir_hare_dch, dir_zona_pantalla);
else if (sentido_hare == 2)
- if (num_ejec == 1)
- reduce_hare_chico(pos_hare[0], pos_hare[1],
- pos_hare[2], pos_hare[3],
- pos_hare[4], pos_hare[5],
- factor_red[hare_y + alto_hare],
- dir_hare_fondo, dir_zona_pantalla);
- else if (num_ejec == 2)
+ if (num_ejec == 2)
DIBUJA_BLOQUE_CUT(pos_hare, dir_hare_fondo, dir_zona_pantalla);
+ else
+ reduce_hare_chico(pos_hare[0], pos_hare[1], pos_hare[2], pos_hare[3], pos_hare[4], pos_hare[5],
+ factor_red[hare_y + alto_hare], dir_hare_fondo, dir_zona_pantalla);
else
- if (num_ejec == 1)
- reduce_hare_chico(pos_hare[0], pos_hare[1],
- pos_hare[2], pos_hare[3],
- pos_hare[4], pos_hare[5],
- factor_red[hare_y + alto_hare],
- dir_hare_frente, dir_zona_pantalla);
- else if (num_ejec == 2)
+ if (num_ejec == 2)
DIBUJA_BLOQUE_CUT(pos_hare, dir_hare_frente, dir_zona_pantalla);
+ else
+ reduce_hare_chico(pos_hare[0], pos_hare[1], pos_hare[2], pos_hare[3], pos_hare[4], pos_hare[5],
+ factor_red[hare_y + alto_hare], dir_hare_frente, dir_zona_pantalla);
no_vuelco:
aumenta_num_frame();
@@ -3811,8 +4015,12 @@ void DrasculaEngine::menu_sin_volcar() {
h = objetos_que_tengo[n];
if (h != 0)
- DIBUJA_FONDO(x_pol[n], y_pol[n], x_obj[n], y_obj[n],
- ANCHOBJ, ALTOBJ, dir_hare_frente, dir_zona_pantalla);
+ if (num_ejec == 6)
+ DIBUJA_FONDO(x_pol[n], y_pol[n], x_obj[n], y_obj[n],
+ ANCHOBJ, ALTOBJ, dir_mesa, dir_zona_pantalla);
+ else
+ DIBUJA_FONDO(x_pol[n], y_pol[n], x_obj[n], y_obj[n],
+ ANCHOBJ, ALTOBJ, dir_hare_frente, dir_zona_pantalla);
DIBUJA_BLOQUE(x1d_menu[h], y1d_menu[h], x_obj[n], y_obj[n],
ANCHOBJ, ALTOBJ, dir_hare_fondo, dir_zona_pantalla);
@@ -3828,9 +4036,8 @@ void DrasculaEngine::barra_menu() {
for (n = 0; n < 7; n++) {
if (x_raton > x_barra[n] && x_raton < x_barra[n + 1])
sobre_verbo = 0;
- DIBUJA_BLOQUE(ANCHOBJ * n, ALTOBJ * sobre_verbo,
- x_barra[n], 2, ANCHOBJ, ALTOBJ,
- dir_hare_fondo, dir_zona_pantalla);
+ DIBUJA_BLOQUE(ANCHOBJ * n, ALTOBJ * sobre_verbo, x_barra[n], 2,
+ ANCHOBJ, ALTOBJ, dir_hare_fondo, dir_zona_pantalla);
sobre_verbo = 1;
}
}
@@ -3882,7 +4089,7 @@ bool DrasculaEngine::sal_de_la_habitacion(int l) {
strcpy(salgo, alapantallakeva[l]);
strcat(salgo, ".ald");
hare_x = -1;
- carga_escoba_1(salgo);
+ carga_escoba(salgo);
}
}
} else if (num_ejec == 2) {
@@ -3893,13 +4100,13 @@ bool DrasculaEngine::sal_de_la_habitacion(int l) {
sentido_hare = sentido_alkeva[l];
obj_saliendo = alapuertakeva[l];
rompo = 1;
- musica_antes = musica_room;
+ musica_antes = musica_room;
if (num_obj[l] == 136)
animacion_2_2();
if (num_obj[l] == 124)
animacion_3_2();
if (num_obj[l] == 173)
- animacion_35();
+ animacion_35_2();
if (num_obj[l] == 146 && flags[39] == 1) {
flags[5] = 1;
flags[11] = 1;
@@ -3910,11 +4117,91 @@ bool DrasculaEngine::sal_de_la_habitacion(int l) {
suma_objeto(11);
}
borra_pantalla();
- ald->close();
+ delete ald;
+ strcpy(salgo, alapantallakeva[l]);
+ strcat(salgo, ".ald");
+ hare_x =- 1;
+ carga_escoba(salgo);
+ }
+ } else if (num_ejec == 3) {
+ puertas_cerradas(l);
+ if (espuerta[l] != 0 && visible[l] == 1) {
+ lleva_al_hare(sitiobj_x[l], sitiobj_y[l]);
+ sentido_hare = sentidobj[l];
+ refresca_pantalla();
+ VUELCA_PANTALLA(0, 0, 0, 0, 320, 200, dir_zona_pantalla);
+ hare_se_mueve = 0;
+ sentido_hare = sentido_alkeva[l];
+ obj_saliendo = alapuertakeva[l];
+ rompo = 1;
+ musica_antes = musica_room;
+ borra_pantalla();
strcpy(salgo, alapantallakeva[l]);
strcat(salgo, ".ald");
hare_x =- 1;
- carga_escoba_2(salgo);
+ carga_escoba(salgo);
+ }
+ } else if (num_ejec == 4) {
+ puertas_cerradas(l);
+ if (espuerta[l] != 0) {
+ lleva_al_hare(sitiobj_x[l], sitiobj_y[l]);
+ sentido_hare = sentidobj[l];
+ refresca_pantalla();
+ VUELCA_PANTALLA(0, 0, 0, 0, 320, 200, dir_zona_pantalla);
+ hare_se_mueve = 0;
+ sentido_hare = sentido_alkeva[l];
+ obj_saliendo = alapuertakeva[l];
+ rompo = 1;
+ musica_antes = musica_room;
+
+ if (num_obj[l] == 108)
+ lleva_al_hare(171, 78);
+ borra_pantalla();
+ strcpy(salgo, alapantallakeva[l]);
+ strcat(salgo, ".ald");
+ hare_x = -1;
+ carga_escoba(salgo);
+ }
+ } else if (num_ejec == 5) {
+ puertas_cerradas(l);
+ if (espuerta[l] != 0 && visible[l] == 1) {
+ lleva_al_hare(sitiobj_x[l], sitiobj_y[l]);
+ sentido_hare = sentidobj[l];
+ refresca_pantalla();
+ VUELCA_PANTALLA(0, 0, 0, 0, 320, 200, dir_zona_pantalla);
+ hare_se_mueve = 0;
+ sentido_hare = sentido_alkeva[l];
+ obj_saliendo = alapuertakeva[l];
+ rompo = 1;
+ musica_antes = musica_room;
+ hare_se_ve = 1;
+ borra_pantalla();
+ strcpy(salgo, alapantallakeva[l]);
+ strcat(salgo, ".ald");
+ hare_x = -1;
+ carga_escoba(salgo);
+ }
+ } else if (num_ejec == 6) {
+ puertas_cerradas(l);
+
+ if (espuerta[l] != 0) {
+ lleva_al_hare(sitiobj_x[l], sitiobj_y[l]);
+ sentido_hare = sentidobj[l];
+ refresca_pantalla();
+ VUELCA_PANTALLA(0, 0, 0, 0, 320, 200, dir_zona_pantalla);
+ hare_se_mueve = 0;
+ sentido_hare = sentido_alkeva[l];
+ obj_saliendo = alapuertakeva[l];
+ rompo = 1;
+ musica_antes = musica_room;
+ borra_pantalla();
+ strcpy(salgo, alapantallakeva[l]);
+ strcat(salgo, ".ald");
+ hare_x = -1;
+ carga_escoba(salgo);
+
+ if (obj_saliendo == 105)
+ animacion_19_6();
}
}
@@ -3959,60 +4246,236 @@ void DrasculaEngine::banderas(int fl) {
hay_respuesta = 1;
if (menu_scr == 1) {
- if (objeto_que_lleva == MIRAR && fl == 28)
- hablar(TEXT328, "328.als");
- if ((objeto_que_lleva == MIRAR && fl == 22 && flags[23] == 0)
- || (objeto_que_lleva == ABRIR && fl == 22 && flags[23] == 0)) {
- hablar(TEXT164, "164.als");
- flags[23] = 1;
- sin_verbo();
- suma_objeto(7);
- suma_objeto(18);
- } else if (objeto_que_lleva == MIRAR && fl == 22 && flags[23] == 1)
- hablar(TEXT307, "307.als");
- else if (objeto_que_lleva == MIRAR && fl == 7)
- hablar(TEXT143, "143.als");
- else if (objeto_que_lleva == HABLAR && fl == 7)
- hablar(TEXT144, "144.als");
- else if (objeto_que_lleva == MIRAR && fl == 8)
- hablar(TEXT145, "145.als");
- else if (objeto_que_lleva == HABLAR && fl == 8)
- hablar(TEXT146, "146.als");
- else if (objeto_que_lleva == MIRAR && fl == 9)
- hablar(TEXT147, "147.als");
- else if (objeto_que_lleva == HABLAR && fl == 9)
- hablar(TEXT148, "148.als");
- else if (objeto_que_lleva == MIRAR && fl == 10)
- hablar(TEXT151, "151.als");
- else if (objeto_que_lleva == MIRAR && fl == 11)
- hablar(TEXT152, "152.als");
- else if (objeto_que_lleva == HABLAR && fl == 11)
- hablar(TEXT153, "153.als");
- else if (objeto_que_lleva == MIRAR && fl == 12)
- hablar(TEXT154, "154.als");
- else if (objeto_que_lleva == MIRAR && fl == 13)
- hablar(TEXT155, "155.als");
- else if (objeto_que_lleva == MIRAR && fl == 14)
- hablar(TEXT157, "157.als");
- else if (objeto_que_lleva == MIRAR && fl == 15)
- hablar(TEXT58, "58.als");
- else if (objeto_que_lleva == MIRAR && fl == 16)
- hablar(TEXT158, "158.als");
- else if (objeto_que_lleva == MIRAR && fl == 17)
- hablar(TEXT159, "159.als");
- else if (objeto_que_lleva == MIRAR && fl == 18)
- hablar(TEXT160, "160.als");
- else if (objeto_que_lleva == MIRAR && fl == 19)
- hablar(TEXT161, "161.als");
- else if (objeto_que_lleva == MIRAR && fl == 20)
- hablar(TEXT162, "162.als");
- else if (objeto_que_lleva == MIRAR && fl == 23)
- hablar(TEXT152, "152.als");
- else
- hay_respuesta = 0;
+ if (num_ejec == 4) {
+ if (objeto_que_lleva == MIRAR && fl == 28)
+ hablar(TEXT328, "328.als");
+ else if (objeto_que_lleva == MIRAR && fl == 7)
+ hablar(TEXT478, "478.als");
+ else if (objeto_que_lleva == MIRAR && fl == 8)
+ hablar(TEXT120, "120.als");
+ else if (objeto_que_lleva == MIRAR && fl == 9) {
+ hablar(TEXT482, "482.als");
+ hablar(TEXT483, "483.als");
+ } else if (objeto_que_lleva == MIRAR && fl == 11)
+ hablar(TEXT488, "488.als");
+ else if (objeto_que_lleva == MIRAR && fl == 13)
+ hablar(TEXT490, "490.als");
+ else if (objeto_que_lleva == MIRAR && fl == 14)
+ hablar(TEXT121, "121.als");
+ else if (objeto_que_lleva == MIRAR && fl == 15)
+ hablar(TEXT117, "117.als" );
+ else if (objeto_que_lleva == HABLAR && fl == 15)
+ hablar(TEXT118, "118.als" );
+ else if (objeto_que_lleva == ABRIR && fl == 15)
+ hablar(TEXT119, "119.als" );
+ else if (objeto_que_lleva == MIRAR && fl == 17)
+ hablar(TEXT478, "478.als");
+ else if (objeto_que_lleva == MIRAR && fl == 20)
+ hablar(TEXT162, "162.als");
+ else
+ hay_respuesta = 0;
+ return;
+ }
+ if (num_ejec == 3) {
+ if (objeto_que_lleva == MIRAR && fl == 22)
+ hablar(TEXT307, "307.als");
+ else if (objeto_que_lleva == MIRAR && fl == 28)
+ hablar(TEXT328, "328.als");
+ else if (objeto_que_lleva == MIRAR && fl == 7)
+ hablar(TEXT143, "143.als");
+ else if (objeto_que_lleva == HABLAR && fl == 7)
+ hablar(TEXT144, "144.als");
+ else if (objeto_que_lleva == MIRAR && fl == 8)
+ hablar(TEXT145, "145.als");
+ else if (objeto_que_lleva == HABLAR && fl == 8)
+ hablar(TEXT146, "146.als");
+ else if (objeto_que_lleva == MIRAR && fl == 9)
+ hablar(TEXT147, "147.als");
+ else if (objeto_que_lleva == HABLAR && fl == 9)
+ hablar(TEXT148, "148.als");
+ else if (objeto_que_lleva == MIRAR && fl == 10)
+ hablar(TEXT151, "151.als");
+ else if (objeto_que_lleva == MIRAR && fl == 11)
+ hablar(TEXT152, "152.als");
+ else if (objeto_que_lleva == HABLAR && fl == 11)
+ hablar(TEXT153, "153.als");
+ else if (objeto_que_lleva == MIRAR && fl == 12)
+ hablar(TEXT154, "154.als");
+ else if (objeto_que_lleva == MIRAR && fl == 13)
+ hablar(TEXT155, "155.als");
+ else if (objeto_que_lleva == MIRAR && fl == 14)
+ hablar(TEXT157, "157.als");
+ else if (objeto_que_lleva == MIRAR && fl == 15)
+ hablar(TEXT58, "58.als");
+ else if (objeto_que_lleva == MIRAR && fl == 16)
+ hablar(TEXT158, "158.als");
+ else if (objeto_que_lleva == MIRAR && fl == 17)
+ hablar(TEXT159, "159.als");
+ else if (objeto_que_lleva == MIRAR && fl == 18)
+ hablar(TEXT160, "160.als");
+ else if (objeto_que_lleva == MIRAR && fl == 19)
+ hablar(TEXT161, "161.als");
+ else if (objeto_que_lleva == MIRAR && fl == 20)
+ hablar(TEXT162, "162.als");
+ else if (objeto_que_lleva == MIRAR && fl == 23)
+ hablar(TEXT152, "152.als");
+ else
+ hay_respuesta = 0;
+ } else if (num_ejec == 1) {
+ if (objeto_que_lleva == MIRAR && fl == 28)
+ hablar(TEXT328, "328.als");
+ if ((objeto_que_lleva == MIRAR && fl == 22 && flags[23] == 0)
+ || (objeto_que_lleva == ABRIR && fl == 22 && flags[23] == 0)) {
+ hablar(TEXT164, "164.als");
+ flags[23] = 1;
+ sin_verbo();
+ suma_objeto(7);
+ suma_objeto(18);
+ } else if (objeto_que_lleva == MIRAR && fl == 22 && flags[23] == 1)
+ hablar(TEXT307, "307.als");
+ else if (objeto_que_lleva == MIRAR && fl == 7)
+ hablar(TEXT143, "143.als");
+ else if (objeto_que_lleva == HABLAR && fl == 7)
+ hablar(TEXT144, "144.als");
+ else if (objeto_que_lleva == MIRAR && fl == 8)
+ hablar(TEXT145, "145.als");
+ else if (objeto_que_lleva == HABLAR && fl == 8)
+ hablar(TEXT146, "146.als");
+ else if (objeto_que_lleva == MIRAR && fl == 9)
+ hablar(TEXT147, "147.als");
+ else if (objeto_que_lleva == HABLAR && fl == 9)
+ hablar(TEXT148, "148.als");
+ else if (objeto_que_lleva == MIRAR && fl == 10)
+ hablar(TEXT151, "151.als");
+ else if (objeto_que_lleva == MIRAR && fl == 11)
+ hablar(TEXT152, "152.als");
+ else if (objeto_que_lleva == HABLAR && fl == 11)
+ hablar(TEXT153, "153.als");
+ else if (objeto_que_lleva == MIRAR && fl == 12)
+ hablar(TEXT154, "154.als");
+ else if (objeto_que_lleva == MIRAR && fl == 13)
+ hablar(TEXT155, "155.als");
+ else if (objeto_que_lleva == MIRAR && fl == 14)
+ hablar(TEXT157, "157.als");
+ else if (objeto_que_lleva == MIRAR && fl == 15)
+ hablar(TEXT58, "58.als");
+ else if (objeto_que_lleva == MIRAR && fl == 16)
+ hablar(TEXT158, "158.als");
+ else if (objeto_que_lleva == MIRAR && fl == 17)
+ hablar(TEXT159, "159.als");
+ else if (objeto_que_lleva == MIRAR && fl == 18)
+ hablar(TEXT160, "160.als");
+ else if (objeto_que_lleva == MIRAR && fl == 19)
+ hablar(TEXT161, "161.als");
+ else if (objeto_que_lleva == MIRAR && fl == 20)
+ hablar(TEXT162, "162.als");
+ else if (objeto_que_lleva == MIRAR && fl == 23)
+ hablar(TEXT152, "152.als");
+ else
+ hay_respuesta = 0;
+ } else if (num_ejec == 4) {
+ if ((objeto_que_lleva == 18 && fl == 19) || (objeto_que_lleva == 19 && fl == 18)) {
+ sin_verbo();
+ elige_objeto(21);
+ resta_objeto(18);
+ resta_objeto(19);
+ } else if ((objeto_que_lleva == 14 && fl == 19) ||
+ (objeto_que_lleva == 19 && fl == 14))
+ hablar(TEXT484, "484.als");
+ else if (objeto_que_lleva == MIRAR && fl == 28)
+ hablar(TEXT328, "328.als");
+ else if (objeto_que_lleva == MIRAR && fl == 7)
+ hablar(TEXT478, "478.als");
+ else if (objeto_que_lleva == MIRAR && fl == 8)
+ hablar(TEXT480, "480.als");
+ else if (objeto_que_lleva == MIRAR && fl == 9) {
+ hablar(TEXT482, "482.als");
+ hablar(TEXT483, "483.als");
+ } else if (objeto_que_lleva == MIRAR && fl == 10)
+ hablar(TEXT485, "485.als");
+ else if (objeto_que_lleva == MIRAR && fl == 11)
+ hablar(TEXT488, "488.als");
+ else if (objeto_que_lleva == MIRAR && fl == 12)
+ hablar(TEXT486, "486.als");
+ else if (objeto_que_lleva == MIRAR && fl == 13)
+ hablar(TEXT490, "490.als");
+ else if (objeto_que_lleva == MIRAR && fl == 14)
+ hablar(TEXT122, "122.als");
+ else if (objeto_que_lleva == MIRAR && fl == 15)
+ hablar(TEXT117, "117.als");
+ else if (objeto_que_lleva == HABLAR && fl == 15)
+ hablar(TEXT118, "118.als");
+ else if (objeto_que_lleva == ABRIR && fl == 15)
+ hablar(TEXT119, "119.als");
+ else if (objeto_que_lleva == MIRAR && fl == 16)
+ hablar(TEXT491, "491.als");
+ else if (objeto_que_lleva == MIRAR && fl == 17)
+ hablar(TEXT478, "478.als");
+ else if (objeto_que_lleva == MIRAR && fl == 18)
+ hablar(TEXT493, "493.als");
+ else if (objeto_que_lleva == MIRAR && fl == 19) {
+ hablar(TEXT494, "494.als");
+ hablar(TEXT495, "495.als");
+ } else if (objeto_que_lleva == MIRAR && fl == 20)
+ hablar(TEXT162, "162.als");
+ else if (objeto_que_lleva == MIRAR && fl == 21)
+ hablar(TEXT496, "496.als");
+ else if (objeto_que_lleva == MIRAR && fl == 22)
+ hablar(TEXT161, "161.als");
+ else
+ hay_respuesta = 0;
+ } else if (num_ejec == 5) {
+ if (objeto_que_lleva == MIRAR && fl == 50)
+ hablar("Cuanto mas me miro, mas me gusto.", "54.als");
+ else if (objeto_que_lleva == ABRIR && fl == 50)
+ hablar(".y luego como me cierro?.", "19.als");
+ else if (objeto_que_lleva == CERRAR && fl == 50)
+ hablar("Tendre que abrirme primero .no?.", "19.als");
+ else if (objeto_que_lleva == MOVER && fl == 50)
+ hablar("Estoy bien donde estoy.", "19.als");
+ else if (objeto_que_lleva == COGER && fl == 50)
+ hablar("Ya me tengo.", "11.als");
+ else if (objeto_que_lleva == HABLAR && fl == 50)
+ hablar("hola yo.", "16.als" );
+ else if (objeto_que_lleva == 20 && fl == 50)
+ hablar(TEXT487, "487.als" );
+ else if (!strcmp(num_room, "49.alg"))
+ pantalla_49(fl);
+ else if (!strcmp(num_room, "53.alg"))
+ pantalla_53(fl);
+ else if (!strcmp(num_room, "54.alg"))
+ pantalla_54(fl);
+ else if (!strcmp(num_room, "55.alg"))
+ pantalla_55(fl);
+ else if (!strcmp(num_room, "56.alg"))
+ pantalla_56(fl);
+ else
+ hay_respuesta = 0;
+ return;
+ } else if (num_ejec == 6) {
+ if (objeto_que_lleva == MIRAR && fl == 28)
+ hablar(TEXT328, "328.als");
+ else if (objeto_que_lleva == MIRAR && fl == 9) {
+ hablar(TEXT482, "482.als");
+ hablar(TEXT483, "483.als");
+ } else if (objeto_que_lleva == MIRAR && fl == 20)
+ hablar(TEXT123, "123.als");
+ else if (objeto_que_lleva == MIRAR && fl == 21)
+ hablar(TEXT441, "441.als");
+ else
+ hay_respuesta = 0;
+ }
} else {
if (objeto_que_lleva == MIRAR && fl == 50)
- hablar(TEXT308, "308.als");
+ if (num_ejec == 3)
+ hablar(TEXT308, "308.als");
+ else if (num_ejec == 6)
+ if (flags[0] == 1)
+ hablar(TEXT308, "308.als");
+ else if (flags[0] == 0)
+ hablar(TEXT250, "250.als");
+ else
+ hablar(TEXT309, "309.als");
else if (objeto_que_lleva == ABRIR && fl == 50)
hablar(TEXT310, "310.als" );
else if (objeto_que_lleva == CERRAR && fl == 50)
@@ -4022,11 +4485,23 @@ void DrasculaEngine::banderas(int fl) {
else if (objeto_que_lleva == COGER && fl == 50)
hablar(TEXT313, "313.als" );
else if (objeto_que_lleva == HABLAR && fl == 50)
- hablar(TEXT314,"314.als" );
- else if (!strcmp(num_room, "62.alg"))
+ hablar(TEXT314, "314.als" );
+ else if (!strcmp(num_room, "102.alg"))
+ pantalla_pendulo(fl);
+ else if (!strcmp(num_room, "58.alg"))
+ pantalla_58(fl);
+ else if (!strcmp(num_room, "59.alg"))
+ pantalla_59(fl);
+ else if (!strcmp(num_room, "60.alg"))
+ pantalla_60(fl);
+ else if (!strcmp(num_room, "61.alg"))
+ pantalla_61(fl);
+ else if (!strcmp(num_room, "62.alg"))
pantalla_62(fl);
else if (!strcmp(num_room, "63.alg"))
pantalla_63(fl);
+ else if (!strcmp(num_room, "13.alg"))
+ pantalla_13(fl);
else
hay_respuesta = 0;
}
@@ -4196,29 +4671,52 @@ int DrasculaEngine::PlayFrameSSN() {
mSesion += 1;
}
switch (CHUNK) {
- case SET_PALET:
- if (!UsingMem)
- _Sesion->read(dacSSN, 768);
- else {
- memcpy(dacSSN, mSesion, 768);
- mSesion += 768;
- }
- set_dacSSN(dacSSN);
- break;
- case EMPTY_FRAME:
- WaitFrameSSN();
- break;
- case INIT_FRAME:
+ case SET_PALET:
+ if (!UsingMem)
+ _Sesion->read(dacSSN, 768);
+ else {
+ memcpy(dacSSN, mSesion, 768);
+ mSesion += 768;
+ }
+ set_dacSSN(dacSSN);
+ break;
+ case EMPTY_FRAME:
+ WaitFrameSSN();
+ break;
+ case INIT_FRAME:
+ if (!UsingMem) {
+ _Sesion->read(&CMP, 1);
+ _Sesion->read(&Lengt, 4);
+ } else {
+ memcpy(&CMP, mSesion, 1);
+ mSesion += 1;
+ memcpy(&Lengt, mSesion, 4);
+ mSesion += 4;
+ }
+ if (CMP == CMP_RLE) {
if (!UsingMem) {
- _Sesion->read(&CMP, 1);
- _Sesion->read(&Lengt, 4);
+ BufferSSN = (byte *)malloc(Lengt);
+ _Sesion->read(BufferSSN, Lengt);
} else {
- memcpy(&CMP, mSesion, 1);
- mSesion += 1;
- memcpy(&Lengt, mSesion, 4);
- mSesion += 4;
+ BufferSSN = (byte *)malloc(Lengt);
+ memcpy(BufferSSN, mSesion, Lengt);
+ mSesion += Lengt;
}
- if (CMP == CMP_RLE) {
+ Des_RLE(BufferSSN, MiVideoSSN);
+ free(BufferSSN);
+ if (FrameSSN) {
+ WaitFrameSSN();
+ MixVideo(VGA, MiVideoSSN);
+ _system->copyRectToScreen((const byte *)VGA, 320, 0, 0, 320, 200);
+ } else {
+ WaitFrameSSN();
+ memcpy(VGA, MiVideoSSN, 64000);
+ _system->copyRectToScreen((const byte *)VGA, 320, 0, 0, 320, 200);
+ }
+ _system->updateScreen();
+ FrameSSN++;
+ } else {
+ if (CMP == CMP_OFF) {
if (!UsingMem) {
BufferSSN = (byte *)malloc(Lengt);
_Sesion->read(BufferSSN, Lengt);
@@ -4227,7 +4725,7 @@ int DrasculaEngine::PlayFrameSSN() {
memcpy(BufferSSN, mSesion, Lengt);
mSesion += Lengt;
}
- Des_RLE(BufferSSN, MiVideoSSN);
+ Des_OFF(BufferSSN, MiVideoSSN, Lengt);
free(BufferSSN);
if (FrameSSN) {
WaitFrameSSN();
@@ -4240,39 +4738,17 @@ int DrasculaEngine::PlayFrameSSN() {
}
_system->updateScreen();
FrameSSN++;
- } else {
- if (CMP == CMP_OFF) {
- if (!UsingMem) {
- BufferSSN = (byte *)malloc(Lengt);
- _Sesion->read(BufferSSN, Lengt);
- } else {
- BufferSSN = (byte *)malloc(Lengt);
- memcpy(BufferSSN, mSesion, Lengt);
- mSesion += Lengt;
- }
- Des_OFF(BufferSSN, MiVideoSSN, Lengt);
- free(BufferSSN);
- if (FrameSSN) {
- WaitFrameSSN();
- MixVideo(VGA, MiVideoSSN);
- _system->copyRectToScreen((const byte *)VGA, 320, 0, 0, 320, 200);
- } else {
- WaitFrameSSN();
- memcpy(VGA, MiVideoSSN, 64000);
- _system->copyRectToScreen((const byte *)VGA, 320, 0, 0, 320, 200);
- }
- _system->updateScreen();
- FrameSSN++;
- }
}
- break;
- case END_ANIM:
- Exit = 1;
- break;
- default:
- Exit = 1;
- break;
}
+ break;
+ case END_ANIM:
+ Exit = 1;
+ break;
+ default:
+ Exit = 1;
+ break;
+ }
+
return (!Exit);
}
@@ -4348,7 +4824,8 @@ void DrasculaEngine::MixVideo(byte *OldScreen, byte *NewScreen) {
}
void DrasculaEngine::WaitFrameSSN() {
- while (clock() < LastFrame + GlobalSpeed) {};
+ while ((int)clock() < LastFrame + GlobalSpeed)
+ ;
LastFrame = LastFrame + GlobalSpeed;
}
@@ -4387,6 +4864,11 @@ void DrasculaEngine::WaitForNext(int FPS) {
}
float DrasculaEngine::vez() {
+ // FIXME: This function is really silly. It first divides an int by an int (resulting
+ // in an *int*, loosing precision), *then* converts the result to a float and returns
+ // that -- only so that many calling functions have to convert it back to an int :-).
+ // So: Either divide by 20.0 / cast to float *first*, if you absolutly need the precision.
+ // Or: Just change this to return int!
return _system->getMillis() / 20; // originaly was 1
}
@@ -4405,8 +4887,8 @@ void DrasculaEngine::reduce_hare_chico(int xx1, int yy1, int xx2, int yy2, int a
pixel_x = xx1;
pixel_y = yy1;
- for (n = 0;n < nuevo_alto; n++){
- for (m = 0; m < nuevo_ancho; m++){
+ for (n = 0; n < nuevo_alto; n++) {
+ for (m = 0; m < nuevo_ancho; m++) {
pos_pixel[0] = (int)pixel_x;
pos_pixel[1] = (int)pixel_y;
pos_pixel[2] = xx2 + m;
@@ -4430,10 +4912,10 @@ char DrasculaEngine::codifica(char car) {
void DrasculaEngine::cuadrante_1() {
float distancia_x = 0, distancia_y;
- if (num_ejec == 1)
- distancia_x = hare_x + ancho_hare / 2 - sitio_x;
- else if (num_ejec == 2)
+ if (num_ejec == 2)
distancia_x = hare_x + ancho_hare - sitio_x;
+ else
+ distancia_x = hare_x + ancho_hare / 2 - sitio_x;
distancia_y = (hare_y + alto_hare) - sitio_y;
@@ -4451,10 +4933,10 @@ void DrasculaEngine::cuadrante_1() {
void DrasculaEngine::cuadrante_2() {
float distancia_x = 0, distancia_y;
- if (num_ejec == 1)
- distancia_x = abs(hare_x + ancho_hare / 2 - sitio_x);
- else if (num_ejec == 2)
+ if (num_ejec == 2)
distancia_x = abs(hare_x + ancho_hare - sitio_x);
+ else
+ distancia_x = abs(hare_x + ancho_hare / 2 - sitio_x);
distancia_y = (hare_y + alto_hare) - sitio_y;
@@ -4472,10 +4954,10 @@ void DrasculaEngine::cuadrante_2() {
void DrasculaEngine::cuadrante_3() {
float distancia_x = 0, distancia_y;
- if (num_ejec == 1)
- distancia_x = hare_x + ancho_hare / 2 - sitio_x;
- else if (num_ejec == 2)
+ if (num_ejec == 2)
distancia_x = hare_x + ancho_hare - sitio_x;
+ else
+ distancia_x = hare_x + ancho_hare / 2 - sitio_x;
distancia_y = sitio_y - (hare_y + alto_hare);
@@ -4493,10 +4975,10 @@ void DrasculaEngine::cuadrante_3() {
void DrasculaEngine::cuadrante_4() {
float distancia_x = 0, distancia_y;
- if (num_ejec == 1)
- distancia_x = abs(hare_x + ancho_hare / 2 - sitio_x);
- else if (num_ejec == 2)
+ if (num_ejec == 2)
distancia_x = abs(hare_x + ancho_hare - sitio_x);
+ else
+ distancia_x = abs(hare_x + ancho_hare / 2 - sitio_x);
distancia_y = sitio_y - (hare_y + alto_hare);
@@ -4527,7 +5009,7 @@ void DrasculaEngine::refresca_63() {
}
void DrasculaEngine::refresca_62_antes() {
- int velas_y[] = { 158, 172, 186};
+ int velas_y[] = { 158, 172, 186 };
int cirio_x[] = { 14, 19, 24 };
int pianista_x[] = {1, 91, 61, 31, 91, 31, 1, 61, 31 };
int borracho_x[] = {1, 42, 83, 124, 165, 206, 247, 1 };
@@ -4642,7 +5124,7 @@ void DrasculaEngine::aumenta_num_frame() {
}
}
- if (num_ejec == 1) {
+ if (num_ejec != 2) {
diferencia_y = alto_hare - (int)nuevo_alto;
diferencia_x = ancho_hare - (int)nuevo_ancho;
hare_y = hare_y + diferencia_y;
@@ -4667,7 +5149,7 @@ int DrasculaEngine::sobre_que_objeto() {
void DrasculaEngine::comprueba_banderas_menu() {
int h, n;
- for (n = 0; n < 43; n++){
+ for (n = 0; n < 43; n++) {
if (sobre_que_objeto() == n) {
h = objetos_que_tengo[n];
if (h != 0)
@@ -4677,6 +5159,77 @@ void DrasculaEngine::comprueba_banderas_menu() {
}
void DrasculaEngine::pantalla_0() {
+ if (num_ejec == 6) {
+ if (objeto_que_lleva == MIRAR) {
+ hablar(mirar_t[c_mirar], mirar_v[c_mirar]);
+ c_mirar++;
+ if (c_mirar == 3)
+ c_mirar = 0;
+ } else if (objeto_que_lleva == MOVER)
+ hablar(TEXT19, "19.als");
+ else if (objeto_que_lleva == COGER) {
+ hablar(poder_t[c_poder], poder_v[c_poder]);
+ c_poder++;
+ if (c_poder == 6)
+ c_poder = 0;
+ } else if (objeto_que_lleva == ABRIR)
+ hablar(TEXT9, "9.als");
+ else if (objeto_que_lleva == CERRAR)
+ hablar(TEXT9, "9.als");
+ else if (objeto_que_lleva == HABLAR)
+ hablar(TEXT16, "16.als");
+ else {
+ hablar(poder_t[c_poder], poder_v[c_poder]);
+ c_poder++;
+ if (c_poder == 6)
+ c_poder = 0;
+ }
+ }
+ if (num_ejec == 5) {
+ if (objeto_que_lleva == MIRAR) {
+ hablar(mirar_t[c_mirar], mirar_v[c_mirar]);
+ c_mirar++;
+ if (c_mirar == 3)
+ c_mirar = 0;
+ } else if (objeto_que_lleva == MOVER)
+ hablar(TEXT19, "19.als");
+ else if (objeto_que_lleva == COGER) {
+ hablar(poder_t[c_poder], poder_v[c_poder]);
+ c_poder++;
+ if (c_poder == 6)
+ c_poder = 0;
+ } else if (objeto_que_lleva == ABRIR)
+ hablar(TEXT9, "9.als");
+ else if (objeto_que_lleva == CERRAR)
+ hablar(TEXT9, "9.als");
+ else if (objeto_que_lleva == HABLAR)
+ hablar(TEXT16, "16.als");
+ else {
+ hablar(poder_t[c_poder], poder_v[c_poder]);
+ c_poder++;
+ if (c_poder == 6)
+ c_poder = 0;
+ }
+ return;
+ }
+ if (num_ejec == 3) {
+ if (objeto_que_lleva == MIRAR)
+ hablar(TEXT316, "316.als");
+ else if (objeto_que_lleva == MOVER)
+ hablar(TEXT317, "317.als");
+ else if (objeto_que_lleva == COGER)
+ hablar(TEXT318, "318.als");
+ else if (objeto_que_lleva == ABRIR)
+ hablar(TEXT319, "319.als");
+ else if (objeto_que_lleva == CERRAR)
+ hablar(TEXT319, "319.als");
+ else if (objeto_que_lleva == HABLAR)
+ hablar(TEXT320, "320.als");
+ else
+ hablar(TEXT318, "318.als");
+ return;
+ }
+
if (objeto_que_lleva == MIRAR) {
if (num_ejec == 1)
hablar(TEXT54, "54.als");
@@ -4780,6 +5333,9 @@ void DrasculaEngine::conversa(const char *nom_fich) {
strcpy(para_codificar, nom_fich);
canal_p(para_codificar);
+ if (num_ejec == 5)
+ sin_verbo();
+
ald = new Common::File;
ald->open(nom_fich);
if (!ald->isOpen()) {
@@ -4818,6 +5374,18 @@ void DrasculaEngine::conversa(const char *nom_fich) {
respuesta3 = 31;
}
+ if (num_ejec == 6 && !strcmp(nom_fich, "op_5.cal") && flags[7] == 1) {
+ strcpy(frase3, TEXT273);
+ strcpy(suena3, "273.als");
+ respuesta3 = 14;
+ }
+
+ if (num_ejec == 6 && !strcmp(nom_fich, "op_5.cal") && flags[10] == 1) {
+ strcpy(frase3, ".cuanto.queda.para.que.acabe.el.partido?");
+ strcpy(suena3, "274.als");
+ respuesta3 = 15;
+ }
+
longitud = strlen(frase1);
for (h = 0; h < longitud; h++)
if (frase1[h] == (char)0xa7)
@@ -4840,7 +5408,7 @@ void DrasculaEngine::conversa(const char *nom_fich) {
lee_dibujos("car.alg");
descomprime_dibujo(dir_hare_fondo,1);
-/* TODO
+/* TODO this is limit for mouse, but we can't implement this
ent.w.ax = 8;
ent.w.cx = 1;
ent.w.dx = 31;
@@ -4858,10 +5426,19 @@ bucle_opc:
else if (num_ejec == 2)
if (music_status() == 0 && flags[11] == 0 && musica_room != 0)
playmusic(musica_room);
+ else if (num_ejec == 3)
+ if (music_status() == 0)
+ playmusic(musica_room);
+ else if (num_ejec == 4)
+ if (music_status() == 0)
+ playmusic(musica_room);
+ else if (num_ejec == 5)
+ if (music_status() == 0)
+ playmusic(musica_room);
MirarRaton();
- if ( y_raton > 0 && y_raton < 9) {
+ if (y_raton > 0 && y_raton < 9) {
if (usado1 == 1 && _color != BLANCO)
color_abc(BLANCO);
else if (usado1 == 0 && _color != VERDE_CLARO)
@@ -4898,15 +5475,24 @@ bucle_opc:
if ((boton_izq == 1) && (juego1 == 2)) {
usado1 = 1;
hablar(frase1, suena1);
- responde(respuesta1);
+ if (num_ejec == 3)
+ grr();
+ else
+ responde(respuesta1);
} else if ((boton_izq == 1) && (juego2 == 2)) {
usado2 = 1;
hablar(frase2, suena2);
- responde(respuesta2);
+ if (num_ejec == 3)
+ grr();
+ else
+ responde(respuesta2);
} else if ((boton_izq == 1) && (juego3 == 2)) {
usado3 = 1;
hablar(frase3, suena3);
- responde(respuesta3);
+ if (num_ejec == 3)
+ grr();
+ else
+ responde(respuesta3);
} else if ((boton_izq == 1) && (juego4 == 2)) {
hablar(frase4, suena4);
rompo_y_salgo = 1;
@@ -4938,7 +5524,8 @@ bucle_opc:
else if (num_ejec == 2)
lee_dibujos(fondo_y_menu);
descomprime_dibujo(dir_hare_fondo, 1);
- sin_verbo();
+ if (num_ejec < 5)
+ sin_verbo();
}
void DrasculaEngine::animacion_3_1() {
@@ -5196,7 +5783,51 @@ void DrasculaEngine::print_abc_opc(const char *dicho, int x_pantalla, int y_pant
}
void DrasculaEngine::responde(int funcion) {
- if (funcion == 10)
+ if (num_ejec == 5) {
+ if (funcion == 2)
+ animacion_2_5();
+ else if (funcion == 3)
+ animacion_3_5();
+ else if (funcion == 6)
+ animacion_6_5();
+ else if (funcion == 7)
+ animacion_7_5();
+ else if (funcion == 8)
+ animacion_8_5();
+ else if (funcion == 15)
+ animacion_15_5();
+ else if (funcion == 16)
+ animacion_16_5();
+ else if (funcion == 17)
+ animacion_17_5();
+ return;
+ }
+ if (num_ejec == 6) {
+ if (funcion == 2)
+ animacion_2_6();
+ else if (funcion == 3)
+ animacion_3_6();
+ else if (funcion == 4)
+ animacion_4_6();
+ else if (funcion == 11)
+ animacion_11_6();
+ else if (funcion == 12)
+ animacion_12_6();
+ else if (funcion == 13)
+ animacion_13_6();
+ else if (funcion == 14)
+ animacion_14_6();
+ else if (funcion == 15)
+ animacion_15_6();
+ return;
+ }
+ if (funcion == 2)
+ animacion_2_4();
+ else if (funcion == 3)
+ animacion_3_4();
+ else if (funcion == 4)
+ animacion_4_4();
+ else if (funcion == 10)
habla_borracho(TEXTB1, "B1.als");
else if (funcion == 11)
habla_borracho(TEXTB2, "B2.als");
@@ -5235,7 +5866,7 @@ void DrasculaEngine::responde(int funcion) {
void DrasculaEngine::habla_pianista(const char *dicho, const char *filename) {
int tiempou;
long tiempol;
- int x_habla[4] = { 97, 145, 193, 241};
+ int x_habla[4] = { 97, 145, 193, 241 };
int cara;
int longitud;
longitud = strlen(dicho);
@@ -5380,8 +6011,9 @@ bucless:
lee_dibujos("96.alg");
descomprime_dibujo(dir_hare_frente, 1);
- if (music_status() == 0 && flags[11] == 0)
- playmusic(musica_room);
+ if (num_ejec <= 3)
+ if (music_status() == 0 && flags[11] == 0)
+ playmusic(musica_room);
}
void DrasculaEngine::suma_objeto(int osj) {
@@ -5395,7 +6027,7 @@ void DrasculaEngine::suma_objeto(int osj) {
if (puesto == 0) {
for (h = 1; h < 43; h++) {
if (objetos_que_tengo[h] == 0) {
- objetos_que_tengo[h]=osj;
+ objetos_que_tengo[h] = osj;
puesto = 1;
break;
}
@@ -5473,6 +6105,29 @@ void DrasculaEngine::actualiza_datos() {
visible[4] = 0;
else if (!strcmp(num_room, "18.alg") && flags[28] == 1)
visible[2] = 0;
+ if (!strcmp(num_room,"49.alg") && flags[6] == 1)
+ visible[2] = 0;
+ if (!strcmp(num_room,"49.alg") && flags[6] == 0)
+ visible[1] = 0;
+ if (!strcmp(num_room,"49.alg") && flags[6] == 1)
+ visible[1] = 1;
+ if (!strcmp(num_room,"45.alg") && flags[6] == 1)
+ visible[3] = 1;
+ if (!strcmp(num_room,"53.alg") && flags[2] == 1)
+ visible[3] = 0;
+ if (!strcmp(num_room,"54.alg") && flags[13] == 1)
+ visible[3] = 0;
+ if (!strcmp(num_room,"55.alg") && flags[8] == 1)
+ visible[1] = 0;
+ if ((!strcmp(num_room, "58.alg")) && flags[8] == 0)
+ espuerta[1] = 0;
+ if ((!strcmp(num_room, "58.alg")) && flags[8] == 1)
+ espuerta[1] = 1;
+ if (!strcmp(num_room, "59.alg"))
+ espuerta[1] = 0;
+ if (!strcmp(num_room, "60.alg")) {
+ sentido_dr = 0; x_dr = 155; y_dr = 69;
+ }
}
void DrasculaEngine::animacion_1_2() {
@@ -5577,7 +6232,7 @@ void DrasculaEngine::animacion_4_2() {
flags[9] = 1;
pausa(12);
- hablar(TEXTD56, "d56.als" );
+ hablar(TEXTD56, "d56.als");
pausa(8);
borra_pantalla();
@@ -5680,12 +6335,12 @@ void DrasculaEngine::animacion_14() {
descomprime_dibujo(dir_hare_fondo, 1);
lee_dibujos("an14_1.alg");
- pos_cabina[0]=150;
- pos_cabina[1]=6;
- pos_cabina[2]=69;
- pos_cabina[3]=-160;
- pos_cabina[4]=158;
- pos_cabina[5]=161;
+ pos_cabina[0] = 150;
+ pos_cabina[1] = 6;
+ pos_cabina[2] = 69;
+ pos_cabina[3] = -160;
+ pos_cabina[4] = 158;
+ pos_cabina[5] = 161;
for (n = -160; n <= 0; n = n + 5 + l) {
DIBUJA_FONDO(0, 0, 0, 0, 320, 200, dir_dibujo1, dir_zona_pantalla);
@@ -5759,7 +6414,7 @@ void DrasculaEngine::animacion_16() {
descomprime_dibujo(dir_dibujo1, MEDIA);
DIBUJA_FONDO(0, 0, 0, 0, 320, 200, dir_dibujo1, dir_zona_pantalla);
centra_texto(HIS2, 180, 180);
- VUELCA_PANTALLA(0,0,0,0, 320,200, dir_zona_pantalla);
+ VUELCA_PANTALLA(0, 0, 0, 0, 320, 200, dir_zona_pantalla);
key = getscan();
if (key != 0)
goto asco;
@@ -5809,10 +6464,10 @@ void DrasculaEngine::animacion_16() {
if (key != 0)
goto asco;
- for (l = 1; l < 200; l++){
+ for (l = 1; l < 200; l++) {
DIBUJA_FONDO(0, 0, 0, l, 320, 200 - l, dir_dibujo3, dir_zona_pantalla);
DIBUJA_FONDO(0, 200 - l, 0, 0, 320, l, dir_dibujo1, dir_zona_pantalla);
- VUELCA_PANTALLA(0,0,0,0, 320,200, dir_zona_pantalla);
+ VUELCA_PANTALLA(0, 0, 0, 0, 320, 200, dir_zona_pantalla);
key = getscan();
if (key != 0)
goto asco;
@@ -5939,8 +6594,10 @@ void DrasculaEngine::animacion_23() {
void DrasculaEngine::animacion_23_anexo() {
int n, p_x = hare_x + 2, p_y = hare_y - 3;
- int x[] = {1,38,75,112,75,112,75,112,149,112,149,112,149,186,223,260,1,38,75,112,149,112,149,112,149,112,149,186,223,260,260,260,260,223};
- int y[] = {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,76,76,76,76,76,76,76,76,76,76,76,76,76,76,1,1,1,1};
+ int x[] = {1, 38, 75, 112, 75, 112, 75, 112, 149, 112, 149, 112, 149, 186, 223, 260,
+ 1, 38, 75, 112, 149, 112, 149, 112, 149, 112, 149, 186, 223, 260, 260, 260, 260, 223};
+ int y[] = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 76, 76, 76, 76, 76, 76, 76,
+ 76, 76, 76, 76, 76, 76, 76, 1, 1, 1, 1};
lee_dibujos("an23.alg");
descomprime_dibujo(dir_hare_fondo, 1);
@@ -5959,8 +6616,8 @@ void DrasculaEngine::animacion_23_anexo() {
void DrasculaEngine::animacion_23_anexo2() {
int n, p_x = hare_x + 4, p_y = hare_y;
- int x[] = {1,35,69,103,137,171,205,239,273,1,35,69,103,137};
- int y[] = {1,1,1,1,1,1,1,1,1,73,73,73,73,73};
+ int x[] = {1, 35, 69, 103, 137, 171, 205, 239, 273, 1, 35, 69, 103, 137};
+ int y[] = {1, 1, 1, 1, 1, 1, 1, 1, 1, 73, 73, 73, 73, 73};
pausa(50);
@@ -6010,7 +6667,7 @@ void DrasculaEngine::animacion_25() {
DIBUJA_BLOQUE_CUT(pos_cabina, dir_hare_fondo, dir_zona_pantalla);
actualiza_refresco();
- VUELCA_PANTALLA(0,0, 0,0, 320,200, dir_zona_pantalla);
+ VUELCA_PANTALLA(0, 0, 0, 0, 320, 200, dir_zona_pantalla);
}
fin_sound();
@@ -6129,7 +6786,7 @@ void DrasculaEngine::animacion_31(){
suma_objeto(20);
}
-void DrasculaEngine::animacion_35() {
+void DrasculaEngine::animacion_35_2() {
int n, x = 0;
lleva_al_hare(96, 165);
@@ -6150,8 +6807,8 @@ void DrasculaEngine::animacion_35() {
x = x + 46;
pausa(3);
}
- x = 0;
+ x = 0;
for (n = 0; n < 6; n++) {
x++;
DIBUJA_FONDO(x, 82, 70, 90, 46, 80, dir_hare_fondo, dir_zona_pantalla);
@@ -6161,7 +6818,6 @@ void DrasculaEngine::animacion_35() {
}
x = 0;
-
for (n = 0; n < 6; n++) {
x++;
DIBUJA_FONDO(x, 1, 70, 90, 46, 80, dir_hare_frente, dir_zona_pantalla);
@@ -6171,8 +6827,8 @@ void DrasculaEngine::animacion_35() {
pausa(3);
}
- x = 0;
+ x = 0;
for (n = 0; n < 2; n++) {
x++;
DIBUJA_FONDO(x, 82, 70, 90, 46, 80, dir_hare_frente, dir_zona_pantalla);
@@ -6196,14 +6852,14 @@ void DrasculaEngine::animacion_35() {
FundeAlNegro(2);
// TODO
- salir_al_dos(3);
+ error("hit part 3");
}
void DrasculaEngine::habla_vb(const char *dicho, const char *filename) {
int tiempou;
long tiempol;
- int x_habla[6] = {1,27,53,79,105,131};
+ int x_habla[6] = {1, 27, 53, 79, 105, 131};
int cara;
int longitud;
@@ -6328,7 +6984,7 @@ bucless:
void DrasculaEngine::habla_ciego(const char *dicho, const char *filename, const char *sincronia) {
byte *num_cara;
- int p;
+ int p = 0;
int pos_ciego[6];
int cara = 0;
@@ -6339,13 +6995,6 @@ void DrasculaEngine::habla_ciego(const char *dicho, const char *filename, const
color_abc(VON_BRAUN);
- // FIXME: We can't do this to a read-only string!
-#if 0
- for (p = 0; sincronia[p]; p++)
- sincronia[p] = toupper(sincronia[p]);
-#endif
-
- p = 0;
DIBUJA_FONDO(0, 0, 0, 0, 320, 200, dir_dibujo1, dir_zona_pantalla);
VUELCA_PANTALLA(0, 0, 0, 0, 320, 200, dir_zona_pantalla);
@@ -6369,21 +7018,22 @@ void DrasculaEngine::habla_ciego(const char *dicho, const char *filename, const
bucless:
DIBUJA_FONDO(0, 0, 0, 0, 320, 200, dir_dibujo1, dir_zona_pantalla);
pos_ciego[5] = 149;
- if (sincronia[p] == '0')
+ char c = toupper(sincronia[p]);
+ if (c == '0')
cara = 0;
- if (sincronia[p] == '1')
+ if (c == '1')
cara = 1;
- if (sincronia[p] == '2')
+ if (c == '2')
cara = 2;
- if (sincronia[p] == '3')
+ if (c == '3')
cara = 3;
- if (sincronia[p] == '4')
+ if (c == '4')
cara = 4;
- if (sincronia[p] == '5')
+ if (c == '5')
cara = 5;
- if (sincronia[p] == '6')
+ if (c == '6')
cara = 6;
- if (sincronia[p] == '7')
+ if (c == '7')
cara = 7;
if (cara == 0 || cara == 2 || cara == 4 || cara == 6)
@@ -6468,7 +7118,7 @@ bucless:
VUELCA_PANTALLA(0, 0, 0, 0, 320, 200, dir_zona_pantalla);
int key = getscan();
- if (key!=0)
+ if (key != 0)
ctvd_stop();
if (hay_sb == 1) {
if (LookForFree() != 0)
@@ -6560,22 +7210,33 @@ void DrasculaEngine::lleva_vb(int punto_x) {
void DrasculaEngine::hipo_sin_nadie(int contador){
int y = 0, sentido = 0;
- contador = contador;
+ if (num_ejec == 3)
+ y = -1;
comienza:
contador--;
DIBUJA_FONDO(0, 0, 0, 0, 320, 200, dir_dibujo1, dir_zona_pantalla);
- VUELCA_PANTALLA(0, 1, 0, y, 320, 198, dir_zona_pantalla);
+ if (num_ejec <= 2)
+ VUELCA_PANTALLA(0, 1, 0, y, 320, 198, dir_zona_pantalla);
+ else
+ VUELCA_PANTALLA(0, 0, 0, y, 320, 200, dir_zona_pantalla);
if (sentido == 0)
y++;
else
y--;
- if (y == 2)
- sentido = 1;
- if (y == 0)
- sentido = 0;
+ if (num_ejec <= 2) {
+ if (y == 2)
+ sentido = 1;
+ if (y == 0)
+ sentido = 0;
+ } else if (num_ejec == 3) {
+ if (y == 1)
+ sentido = 1;
+ if (y == -1)
+ sentido = 0;
+ }
if (contador > 0)
goto comienza;
@@ -6585,6 +7246,12 @@ comienza:
void DrasculaEngine::abre_puerta(int nflag, int n_puerta) {
if (flags[nflag] == 0) {
+ if (num_ejec == 5 || num_ejec == 6) {
+ comienza_sound("s3.als");
+ flags[nflag] = 1;
+ }
+ if (num_ejec == 1 && nflag == 7)
+ return;
comienza_sound("s3.als");
flags[nflag] = 1;
if (n_puerta != NO_PUERTA)
@@ -6592,7 +7259,8 @@ void DrasculaEngine::abre_puerta(int nflag, int n_puerta) {
refresca_pantalla();
VUELCA_PANTALLA(0, 0, 0, 0, 320, 200, dir_zona_pantalla);
fin_sound();
- sin_verbo();
+ if (num_ejec != 5)
+ sin_verbo();
}
}
@@ -6601,11 +7269,11 @@ void DrasculaEngine::mapa() {
for (l = 0; l < objs_room; l++) {
if (x_raton > x1[l] && y_raton > y1[l]
- && x_raton < x2[l] && y_raton < y2[l]
- && visible[l] == 1) {
- strcpy(texto_nombre, nombre_obj[l]);
- hay_nombre = 1;
- veo = 1;
+ && x_raton < x2[l] && y_raton < y2[l]
+ && visible[l] == 1) {
+ strcpy(texto_nombre, nombre_obj[l]);
+ hay_nombre = 1;
+ veo = 1;
}
}
@@ -6633,21 +7301,21 @@ void DrasculaEngine::refresca_1_antes() {
void DrasculaEngine::refresca_2(){
int pos_murci[6];
int diferencia;
- int murci_x[] = {0,38,76,114,152,190,228,266,
- 0,38,76,114,152,190,228,266,
- 0,38,76,114,152,190,
- 0,48,96,144,192,240,
- 30,88,146,204,262,
- 88,146,204,262,
- 88,146,204,262};
-
- int murci_y[] = {179,179,179,179,179,179,179,179,
- 158,158,158,158,158,158,158,158,
- 137,137,137,137,137,137,
- 115,115,115,115,115,115,
- 78,78,78,78,78,
- 41,41,41,41,
- 4,4,4,4};
+ int murci_x[] = {0, 38, 76, 114, 152, 190, 228, 266,
+ 0, 38, 76, 114, 152, 190, 228, 266,
+ 0, 38, 76, 114, 152, 190,
+ 0, 48, 96, 144, 192, 240,
+ 30, 88, 146, 204, 262,
+ 88, 146, 204, 262,
+ 88, 146, 204, 262};
+
+ int murci_y[] = {179, 179, 179, 179, 179, 179, 179, 179,
+ 158, 158, 158, 158, 158, 158, 158, 158,
+ 137, 137, 137, 137, 137, 137,
+ 115, 115, 115, 115, 115, 115,
+ 78, 78, 78, 78, 78,
+ 41, 41, 41, 41,
+ 4, 4, 4, 4};
if (frame_murcielago == 41)
frame_murcielago = 0;
@@ -6670,10 +7338,10 @@ void DrasculaEngine::refresca_2(){
pos_murci[3] = 19;
DIBUJA_BLOQUE_CUT(pos_murci, dir_dibujo3, dir_zona_pantalla);
- diferencia = vez() - conta_ciego_vez;
+ diferencia = (int)vez() - conta_ciego_vez;
if (diferencia >= 6) {
frame_murcielago++;
- conta_ciego_vez = vez();
+ conta_ciego_vez = (int)vez();
}
DIBUJA_BLOQUE(29, 37, 58, 114, 57, 39, dir_dibujo3, dir_zona_pantalla);
@@ -6696,7 +7364,7 @@ void DrasculaEngine::refresca_4() {
if (hare_x > 190)
cambio_de_color = 1;
else
- cambio_de_color=0;
+ cambio_de_color = 0;
if (cambio_col_antes != cambio_de_color && cambio_de_color == 1)
hare_oscuro();
@@ -6728,13 +7396,13 @@ void DrasculaEngine::refresca_5_antes(){
}
void DrasculaEngine::refresca_6_antes() {
- int cambio_col_antes=cambio_de_color;
+ int cambio_col_antes = cambio_de_color;
if ((hare_x > 149 && hare_y + alto_hare > 160 && hare_x < 220 && hare_y + alto_hare < 188) ||
(hare_x > 75 && hare_y + alto_hare > 183 && hare_x < 145))
cambio_de_color = 0;
else
- cambio_de_color=1;
+ cambio_de_color = 1;
if (cambio_col_antes != cambio_de_color && cambio_de_color == 1)
hare_oscuro();
@@ -6755,21 +7423,21 @@ void DrasculaEngine::refresca_7_antes() {
}
void DrasculaEngine::refresca_9_antes() {
- int ciego_x[] = {26,68,110,152,194,236,278,26,68};
- int ciego_y[] = {51,51,51,51,51,51,51,127,127};
+ int ciego_x[] = {26, 68, 110, 152, 194, 236, 278, 26, 68};
+ int ciego_y[] = {51, 51, 51, 51, 51, 51, 51, 127, 127};
int diferencia;
DIBUJA_BLOQUE(ciego_x[frame_ciego], ciego_y[frame_ciego], 122, 57, 41, 72, dir_dibujo3, dir_zona_pantalla);
if (flags[9] == 0) {
- diferencia = vez() - conta_ciego_vez;
+ diferencia = (int)vez() - conta_ciego_vez;
if (diferencia >= 11) {
frame_ciego++;
- conta_ciego_vez = vez();
+ conta_ciego_vez = (int)vez();
}
if (frame_ciego == 9)
frame_ciego = 0;
} else
- frame_ciego=3;
+ frame_ciego = 3;
}
void DrasculaEngine::refresca_12_antes() {
@@ -6778,10 +7446,10 @@ void DrasculaEngine::refresca_12_antes() {
}
void DrasculaEngine::refresca_14_antes() {
- int velas_y[] = {158,172,186};
- int cirio_x[] = {14,19,24};
- int pianista_x[] = {1,91,61,31,91,31,1,61,31};
- int borracho_x[] = {1,42,83,124,165,206,247,1};
+ int velas_y[] = {158, 172, 186};
+ int cirio_x[] = {14, 19, 24};
+ int pianista_x[] = {1, 91, 61, 31, 91, 31, 1, 61, 31};
+ int borracho_x[] = {1, 42, 83, 124, 165, 206, 247, 1};
int diferencia;
DIBUJA_FONDO(123, velas_y[frame_velas], 142, 14, 39, 13, dir_dibujo3, dir_zona_pantalla);
@@ -6800,7 +7468,7 @@ void DrasculaEngine::refresca_14_antes() {
if (flags[12] == 1)
DIBUJA_FONDO(borracho_x[frame_borracho], 82, 170, 50, 40, 53, dir_dibujo3, dir_zona_pantalla);
- diferencia = vez() - conta_ciego_vez;
+ diferencia = (int)vez() - conta_ciego_vez;
if (diferencia > 6) {
if (flags[12] == 1) {
frame_borracho++;
@@ -6818,7 +7486,7 @@ void DrasculaEngine::refresca_14_antes() {
if (frame_piano == 9)
frame_piano = 0;
parpadeo = _rnd->getRandomNumber(10);
- conta_ciego_vez=vez();
+ conta_ciego_vez = (int)vez();
}
}
@@ -6836,8 +7504,8 @@ void DrasculaEngine::refresca_17_antes() {
void DrasculaEngine::refresca_18_antes() {
int diferencia;
- int ronquido_x[] = {95,136,95,136,95,95,95,95,136,95,95,95,95,95,95,95};
- int ronquido_y[] = {18,18,56,56,94,94,94,94,94,18,18,18,18,18,18,18};
+ int ronquido_x[] = {95, 136, 95, 136, 95, 95, 95, 95, 136, 95, 95, 95, 95, 95, 95, 95};
+ int ronquido_y[] = {18, 18, 56, 56, 94, 94, 94, 94, 94, 18, 18, 18, 18, 18, 18, 18};
if (flags[21] == 0) {
DIBUJA_FONDO(1, 69, 120, 58, 56, 61, dir_dibujo3, dir_zona_pantalla);
@@ -6845,15 +7513,2134 @@ void DrasculaEngine::refresca_18_antes() {
} else
pon_vb();
- diferencia = vez() - conta_ciego_vez;
+ diferencia = (int)vez() - conta_ciego_vez;
if (diferencia > 9) {
frame_ronquido++;
if (frame_ronquido == 16)
frame_ronquido = 0;
- conta_ciego_vez = vez();
+ conta_ciego_vez = (int)vez();
+ }
+}
+
+void DrasculaEngine::grr() {
+ int longitud;
+ longitud = 30;
+
+ buffer_teclado();
+
+ color_abc(VERDE_OSCURO);
+
+ if (hay_sb == 1) {
+ sku = new Common::File;
+ sku->open("s10.als");
+ if (!sku->isOpen()) {
+ error("no puedo abrir archivo de voz");
+ }
+ ctvd_init(4);
+ ctvd_speaker(1);
+ ctvd_output(sku);
+ }
+
+ refresca_pantalla();
+ DIBUJA_FONDO(253, 110, 150, 65, 20, 30, dir_dibujo3, dir_zona_pantalla);
+
+ if (con_voces == 0)
+ centra_texto(".groaaarrrrgghhh!", 153, 65);
+
+ VUELCA_PANTALLA(0, 0, 0, 0, 320, 200, dir_zona_pantalla);
+
+bucless:
+ int key = getscan();
+ if (key != 0)
+ ctvd_stop();
+ buffer_teclado();
+ if (hay_sb == 1) {
+ if (LookForFree() != 0)
+ goto bucless;
+ delete sku;
+ ctvd_terminate();
+ } else {
+ longitud = longitud - 2;
+ if (longitud > 0)
+ goto bucless;
}
+
+ refresca_pantalla();
+ VUELCA_PANTALLA(0, 0, 0, 0, 320, 200, dir_zona_pantalla);
+}
+
+void DrasculaEngine::pantalla_13(int fl) {
+ if (objeto_que_lleva == MIRAR && fl == 51) {
+ hablar(TEXT411, "411.als");
+ sentido_hare = 3;
+ hablar(TEXT412, "412.als");
+ strcpy(nombre_obj[1], "yoda");
+ } else if (objeto_que_lleva == HABLAR && fl == 51)
+ conversa("op_7.cal");
+ else if (objeto_que_lleva == 19 && fl == 51)
+ animacion_1_3();
+ else if (objeto_que_lleva == 9 && fl == 51)
+ animacion_2_3();
+ else
+ hay_respuesta = 0;
+}
+
+void DrasculaEngine::refresca_13() {
+ if (hare_x > 55 && flags[3] == 0)
+ animacion_6();
+ if (flags[1] == 0)
+ DIBUJA_BLOQUE(185, 110, 121, 65, 67, 88, dir_dibujo3, dir_zona_pantalla);
+ if (flags[2] == 0)
+ DIBUJA_BLOQUE(185, 21, 121, 63, 67, 88, dir_dibujo3, dir_zona_pantalla);
+ DIBUJA_BLOQUE(3, 127, 99, 102, 181, 71, dir_dibujo3, dir_zona_pantalla);
+}
+
+void DrasculaEngine::refresca_20() {
+ DIBUJA_BLOQUE(1, 137, 106, 121, 213, 61, dir_dibujo3, dir_zona_pantalla);
+}
+
+void DrasculaEngine::animacion_1_3() {
+ hablar(TEXT413, "413.als");
+ grr();
+ pausa(50);
+ hablar(TEXT414, "414.als");
+}
+
+void DrasculaEngine::animacion_2_3() {
+ flags[0] = 1;
+ playmusic(13);
+ animacion_3_3();
+ playmusic(13);
+ animacion_4_3();
+ flags[1] = 1;
+ refresca_pantalla();
+ VUELCA_PANTALLA(120, 0, 120, 0, 200, 200, dir_zona_pantalla);
+ animacion_5();
+ flags[0] = 0;
+ flags[1] = 1;
+
+ lee_dibujos("96.alg");
+ descomprime_dibujo(dir_hare_frente, 1);
+ lee_dibujos("97.alg");
+ descomprime_dibujo(dir_hare_dch, 1);
+ lee_dibujos("99.alg");
+ descomprime_dibujo(dir_hare_fondo, 1);
+
+ lleva_al_hare(332, 127);
+ libera_memoria();
+ // TODO
+ error("4 segment hit");
}
+void DrasculaEngine::animacion_3_3() {
+ int n, x = 0;
+ int px = hare_x - 20, py = hare_y - 1;
+
+ lee_dibujos("an2y_1.alg");
+ descomprime_dibujo(dir_hare_frente, 1);
+ lee_dibujos("an2y_2.alg");
+ descomprime_dibujo(dir_hare_dch, 1);
+ lee_dibujos("an2y_3.alg");
+ descomprime_dibujo(dir_hare_fondo, 1);
+
+ for (n = 0; n < 4; n++) {
+ x++;
+ DIBUJA_FONDO(px, py, px, py, 71, 72, dir_dibujo1, dir_zona_pantalla);
+ DIBUJA_BLOQUE(x, 2, px, py, 71, 72, dir_hare_frente, dir_zona_pantalla);
+ VUELCA_PANTALLA(px, py, px, py, 71, 72, dir_zona_pantalla);
+ x = x + 71;
+ pausa(3);
+ }
+
+ x = 0;
+
+ for (n = 0; n < 4; n++) {
+ x++;
+ DIBUJA_FONDO(px, py, px, py, 71, 72, dir_dibujo1, dir_zona_pantalla);
+ DIBUJA_BLOQUE(x, 75, px, py, 71, 72, dir_hare_frente, dir_zona_pantalla);
+ VUELCA_PANTALLA(px, py, px, py, 71, 72, dir_zona_pantalla);
+ x = x + 71;
+ pausa(3);
+ }
+
+ x = 0;
+
+ for (n = 0; n < 4; n++) {
+ x++;
+ DIBUJA_FONDO(px, py, px, py, 71, 72, dir_dibujo1, dir_zona_pantalla);
+ DIBUJA_BLOQUE(x, 2, px, py, 71, 72, dir_hare_dch, dir_zona_pantalla);
+ VUELCA_PANTALLA(px, py, px, py, 71, 72, dir_zona_pantalla);
+ x = x + 71;
+ pausa(3);
+ }
+
+ x = 0;
+
+ for (n = 0; n < 4; n++) {
+ x++;
+ DIBUJA_FONDO(px, py, px, py, 71, 72, dir_dibujo1, dir_zona_pantalla);
+ DIBUJA_BLOQUE(x, 75, px, py, 71, 72, dir_hare_dch, dir_zona_pantalla);
+ VUELCA_PANTALLA(px, py, px, py, 71, 72, dir_zona_pantalla);
+ x = x + 71;
+ pausa(3);
+ }
+
+ x = 0;
+
+ for (n = 0; n < 4; n++) {
+ x++;
+ DIBUJA_FONDO(px, py, px, py, 71, 72, dir_dibujo1, dir_zona_pantalla);
+ DIBUJA_BLOQUE(x, 2, px, py, 71, 72, dir_hare_fondo, dir_zona_pantalla);
+ VUELCA_PANTALLA(px, py, px, py, 71, 72, dir_zona_pantalla);
+ x = x + 71;
+ pausa(3);
+ }
+
+ x = 0;
+
+ for (n = 0; n < 4; n++) {
+ x++;
+ DIBUJA_FONDO(px, py, px, py, 71, 72, dir_dibujo1, dir_zona_pantalla);
+ DIBUJA_BLOQUE(x, 75, px, py, 71, 72, dir_hare_fondo, dir_zona_pantalla);
+ VUELCA_PANTALLA(px, py, px, py, 71, 72, dir_zona_pantalla);
+ x = x + 71;
+ pausa(3);
+ }
+}
+
+void DrasculaEngine::animacion_4_3() {
+ int n, x = 0;
+ int px = 120, py = 63;
+
+ lee_dibujos("any_1.alg");
+ descomprime_dibujo(dir_hare_frente, 1);
+ lee_dibujos("any_2.alg");
+ descomprime_dibujo(dir_hare_dch, 1);
+ lee_dibujos("any_3.alg");
+ descomprime_dibujo(dir_hare_fondo, 1);
+
+ for (n = 0; n < 4; n++){
+ x++;
+ DIBUJA_FONDO(px, py, px, py, 77, 89, dir_dibujo1, dir_zona_pantalla);
+ DIBUJA_BLOQUE(x, 1, px, py, 77, 89, dir_hare_frente, dir_zona_pantalla);
+ VUELCA_PANTALLA(px, py, px, py, 77, 89, dir_zona_pantalla);
+ x = x + 77;
+ pausa(3);
+ }
+
+ x = 0;
+
+ for (n = 0; n < 4; n++) {
+ x++;
+ DIBUJA_FONDO(px, py, px, py, 77, 89, dir_dibujo1, dir_zona_pantalla);
+ DIBUJA_BLOQUE(x, 91, px, py, 77, 89, dir_hare_frente, dir_zona_pantalla);
+ VUELCA_PANTALLA(px, py, px, py, 77, 89, dir_zona_pantalla);
+ x = x + 77;
+ pausa(3);
+ }
+
+ x = 0;
+
+ for (n = 0; n < 4; n++) {
+ x++;
+ DIBUJA_FONDO(px, py, px, py, 77, 89, dir_dibujo1, dir_zona_pantalla);
+ DIBUJA_BLOQUE(x, 1, px, py, 77, 89, dir_hare_dch, dir_zona_pantalla);
+ VUELCA_PANTALLA(px, py, px, py, 77, 89, dir_zona_pantalla);
+ x = x + 77;
+ pausa(3);
+ }
+
+ x = 0;
+
+ for (n = 0; n < 4; n++) {
+ x++;
+ DIBUJA_FONDO(px, py, px, py, 77, 89, dir_dibujo1, dir_zona_pantalla);
+ DIBUJA_BLOQUE(x, 91, px, py, 77, 89, dir_hare_dch, dir_zona_pantalla);
+ VUELCA_PANTALLA(px, py, px, py, 77, 89, dir_zona_pantalla);
+ x = x + 77;
+ pausa(3);
+ }
+
+ x = 0;
+
+ for (n = 0; n < 4; n++) {
+ x++;
+ DIBUJA_FONDO(px, py, px, py, 77, 89, dir_dibujo1, dir_zona_pantalla);
+ DIBUJA_BLOQUE(x, 1, px, py, 77, 89, dir_hare_fondo, dir_zona_pantalla);
+ VUELCA_PANTALLA(px, py, px, py, 77, 89, dir_zona_pantalla);
+ x = x + 77;
+ pausa(3);
+ }
+
+ x = 0;
+
+ for (n = 0; n < 4; n++) {
+ x++;
+ DIBUJA_FONDO(px, py, px, py, 77, 89, dir_dibujo1, dir_zona_pantalla);
+ DIBUJA_BLOQUE(x, 91, px, py, 77, 89, dir_hare_fondo, dir_zona_pantalla);
+ VUELCA_PANTALLA(px, py, px, py, 77, 89, dir_zona_pantalla);
+ x = x + 77;
+ pausa(3);
+ }
+}
+
+void DrasculaEngine::animacion_5() {
+ int n, x = 0;
+ int px = hare_x - 20, py = hare_y - 1;
+
+ lee_dibujos("an3y_1.alg");
+ descomprime_dibujo(dir_hare_frente, 1);
+ lee_dibujos("an3y_2.alg");
+ descomprime_dibujo(dir_hare_dch, 1);
+ lee_dibujos("an3y_3.alg");
+ descomprime_dibujo(dir_hare_fondo, 1);
+
+ for (n = 0; n < 4; n++) {
+ x++;
+ DIBUJA_FONDO(px, py, px, py, 71, 72, dir_dibujo1, dir_zona_pantalla);
+ DIBUJA_BLOQUE(x, 2, px, py, 71, 72, dir_hare_frente, dir_zona_pantalla);
+ VUELCA_PANTALLA(px, py, px, py, 71, 72, dir_zona_pantalla);
+ x = x + 71;
+ pausa(3);
+ }
+
+ x = 0;
+
+ for (n = 0; n < 4; n++) {
+ x++;
+ DIBUJA_FONDO(px, py, px, py, 71, 72, dir_dibujo1, dir_zona_pantalla);
+ DIBUJA_BLOQUE(x, 75, px, py, 71, 72, dir_hare_frente, dir_zona_pantalla);
+ VUELCA_PANTALLA(px, py, px, py, 71, 72, dir_zona_pantalla);
+ x = x + 71;
+ pausa(3);
+ }
+
+ x = 0;
+
+ for (n = 0; n < 4; n++) {
+ x++;
+ DIBUJA_FONDO(px, py, px, py, 71, 72, dir_dibujo1, dir_zona_pantalla);
+ DIBUJA_BLOQUE(x, 2, px, py, 71, 72, dir_hare_dch, dir_zona_pantalla);
+ VUELCA_PANTALLA(px, py, px, py, 71, 72, dir_zona_pantalla);
+ x = x + 71;
+ pausa(3);
+ }
+
+ x = 0;
+
+ for (n = 0; n < 4; n++) {
+ x++;
+ DIBUJA_FONDO(px, py, px, py, 71, 72, dir_dibujo1, dir_zona_pantalla);
+ DIBUJA_BLOQUE(x, 75, px, py, 71, 72, dir_hare_dch, dir_zona_pantalla);
+ VUELCA_PANTALLA(px,py, px,py, 71,72, dir_zona_pantalla);
+ x = x + 71;
+ pausa(3);
+ }
+
+ x = 0;
+
+ for (n = 0; n < 4; n++) {
+ x++;
+ DIBUJA_FONDO(px, py, px, py, 71, 72, dir_dibujo1, dir_zona_pantalla);
+ DIBUJA_BLOQUE(x, 2, px, py, 71, 72, dir_hare_fondo, dir_zona_pantalla);
+ VUELCA_PANTALLA(px, py, px, py, 71, 72, dir_zona_pantalla);
+ x = x + 71;
+ pausa(3);
+ }
+
+ x = 0;
+
+ for (n = 0; n < 4; n++) {
+ x++;
+ DIBUJA_FONDO(px, py, px, py, 71, 72, dir_dibujo1, dir_zona_pantalla);
+ DIBUJA_BLOQUE(x, 75, px, py, 71, 72, dir_hare_fondo, dir_zona_pantalla);
+ VUELCA_PANTALLA(px, py, px, py, 71, 72, dir_zona_pantalla);
+ x = x + 71;
+ pausa(3);
+ }
+}
+
+void DrasculaEngine::animacion_6() {
+ int frame = 0, px = 112, py = 62;
+ int yoda_x[] = { 3 ,82, 161, 240, 3, 82 };
+ int yoda_y[] = { 3, 3, 3, 3, 94, 94 };
+
+ hare_se_mueve = 0;
+ flags[3] = 1;
+ refresca_pantalla();
+ VUELCA_PANTALLA(0, 0, 0, 0, 320, 200, dir_zona_pantalla);
+
+ flags[1] = 0;
+
+ lee_dibujos("an4y.alg");
+ descomprime_dibujo(dir_hare_frente, 1);
+
+ for (frame = 0; frame < 6; frame++) {
+ pausa(3);
+ DIBUJA_FONDO(0, 0, 0, 0, 320, 200, dir_dibujo1, dir_zona_pantalla);
+ DIBUJA_BLOQUE(yoda_x[frame], yoda_y[frame], px, py, 78, 90, dir_hare_frente, dir_zona_pantalla);
+ VUELCA_PANTALLA(px, py, px, py, 78, 90, dir_zona_pantalla);
+ }
+
+ flags[2] = 1;
+
+ lee_dibujos("96.alg");
+ descomprime_dibujo(dir_hare_frente, 1);
+
+ refresca_pantalla();
+ VUELCA_PANTALLA(0, 0, 0, 0, 320, 200, dir_zona_pantalla);
+}
+
+void DrasculaEngine::animacion_rayo() {
+ lee_dibujos("anr_1.alg");
+ descomprime_dibujo(dir_hare_frente, MEDIA);
+ lee_dibujos("anr_2.alg");
+ descomprime_dibujo(dir_hare_dch, 1);
+ lee_dibujos("anr_3.alg");
+ descomprime_dibujo(dir_hare_fondo, 1);
+ lee_dibujos("anr_4.alg");
+ descomprime_dibujo(dir_dibujo1, 1);
+ lee_dibujos("anr_5.alg");
+ descomprime_dibujo(dir_dibujo3, 1);
+
+ VUELCA_PANTALLA(0, 0, 0, 0, 320, 200, dir_hare_frente);
+
+ pausa(50);
+
+ comienza_sound("s5.als");
+
+ VUELCA_PANTALLA(0, 0, 0, 0, 320, 200, dir_hare_dch);
+ pausa(3);
+ VUELCA_PANTALLA(0, 0, 0, 0, 320, 200, dir_hare_fondo);
+ pausa(3);
+ VUELCA_PANTALLA(0, 0, 0, 0, 320, 200, dir_dibujo1);
+ pausa(3);
+ VUELCA_PANTALLA(0, 0, 0, 0, 320, 200, dir_hare_fondo);
+ pausa(3);
+ VUELCA_PANTALLA(0, 0, 0, 0, 320, 200, dir_dibujo3);
+ pausa(3);
+ VUELCA_PANTALLA(0, 0, 0, 0, 320, 200, dir_hare_frente);
+ fin_sound();
+}
+
+void DrasculaEngine::animacion_2_4() {
+ habla_igor_sentado(TEXTI16, "I16.als");
+ hablar(TEXT278, "278.als");
+ habla_igor_sentado(TEXTI17, "I17.als");
+ hablar(TEXT279, "279.als");
+ habla_igor_sentado(TEXTI18, "I18.als");
+}
+
+void DrasculaEngine::animacion_3_4() {
+ habla_igor_sentado(TEXTI19, "I19.als");
+ habla_igor_sentado(TEXTI20, "I20.als");
+ hablar(TEXT281, "281.als");
+}
+
+void DrasculaEngine::animacion_4_4() {
+ hablar(TEXT287, "287.als");
+ habla_igor_sentado(TEXTI21, "I21.als");
+ hablar(TEXT284, "284.als");
+ habla_igor_sentado(TEXTI22, "I22.als");
+ hablar(TEXT285, "285.als");
+ habla_igor_sentado(TEXTI23, "I23.als");
+}
+
+void DrasculaEngine::habla_igor_sentado(const char *dicho, const char *filename) {
+ int tiempou;
+ long tiempol;
+
+ int x_habla[4] = { 80, 102, 124, 146 };
+ int cara;
+
+ int longitud;
+ longitud = strlen(dicho);
+
+ tiempol = _system->getMillis();
+ tiempou = (unsigned int)tiempol / 2;
+ _rnd->setSeed(tiempou);
+
+ buffer_teclado();
+
+ color_abc(BLANCO);
+
+ if (hay_sb == 1) {
+ sku = new Common::File;
+ sku->open(filename);
+ if (!sku->isOpen()) {
+ error("no puedo abrir archivo de voz");
+ }
+ ctvd_init(2);
+ ctvd_speaker(1);
+ ctvd_output(sku);
+ }
+
+bucless:
+
+ cara = _rnd->getRandomNumber(3);
+
+ DIBUJA_FONDO(0, 0, 0, 0, 320, 200, dir_dibujo1, dir_zona_pantalla);
+
+ actualiza_refresco_antes();
+
+ DIBUJA_FONDO(x_habla[cara], 109, 207, 92, 21, 23, dir_dibujo3, dir_zona_pantalla);
+ pon_hare();
+ actualiza_refresco();
+
+ if (con_voces == 0)
+ centra_texto(dicho, 221, 102);
+
+ VUELCA_PANTALLA(0, 0, 0, 0, 320, 200, dir_zona_pantalla);
+
+ pausa(3);
+
+ int key = getscan();
+ if (key != 0)
+ ctvd_stop();
+ buffer_teclado();
+ if (hay_sb == 1) {
+ if (LookForFree() != 0)
+ goto bucless;
+ delete sku;
+ ctvd_terminate();
+ } else {
+ longitud = longitud - 2;
+ if (longitud > 0)
+ goto bucless;
+ }
+
+ refresca_pantalla();
+ VUELCA_PANTALLA(0, 0, 0, 0, 320, 200, dir_zona_pantalla);
+}
+
+void DrasculaEngine::animacion_7_4() {
+ Negro();
+ hablar(TEXT427, "427.als");
+ FundeDelNegro(1);
+ resta_objeto(8);
+ resta_objeto(10);
+ resta_objeto(12);
+ resta_objeto(16);
+ suma_objeto(17);
+ flags[30] = 0;
+ flags[29] = 0;
+}
+
+void DrasculaEngine::animacion_1_5() {
+ if (flags[0] == 0) {
+ hablar(TEXT430, "430.als");
+ habla_bj(TEXTBJ16, "BJ16.als");
+ habla_bj(TEXTBJ17, "BJ17.als");
+ habla_bj(TEXTBJ18, "BJ18.als");
+ hablar(TEXT217, "217.als");
+ habla_bj(TEXTBJ19, "BJ19.als");
+ hablar(TEXT229, "229.als");
+ pausa(5);
+ lleva_al_hare(114, 170);
+ sentido_hare = 3;
+ hablar(TEXT431, "431.als");
+ habla_bj(TEXTBJ20, "BJ20.als");
+ sentido_hare = 2;
+ pausa(4);
+ hablar(TEXT438, "438.als");
+ sitio_x = 120;
+ sitio_y = 157;
+ anda_a_objeto = 1;
+ sentido_final = 1;
+ empieza_andar();
+ habla_bj(TEXTBJ21, "BJ21.als");
+
+ for (;;) {
+ if (hare_se_mueve == 0)
+ break;
+ refresca_pantalla();
+ VUELCA_PANTALLA(0, 0, 0, 0, 320, 200, dir_zona_pantalla);
+ }
+
+ sentido_hare = 1;
+ hablar(TEXT229, "229.als");
+ flags[0] = 1;
+ }
+
+ sentido_hare = 1;
+ conversa("op_8.cal");
+}
+
+void DrasculaEngine::animacion_2_5() {
+ habla_bj(TEXTBJ22, "BJ22.als");
+}
+
+void DrasculaEngine::animacion_3_5() {
+ habla_bj(TEXTBJ23, "BJ23.als");
+ agarra_objeto(10);
+ rompo_y_salgo = 1;
+}
+
+void DrasculaEngine::animacion_4_5() {
+ flags[7] = 1;
+ refresca_pantalla();
+ VUELCA_PANTALLA(0, 0, 0, 0, 320, 200, dir_zona_pantalla);
+ hablar(TEXT228, "228.als");
+ habla_lobo(TEXTL1, "L1.als");
+ habla_lobo(TEXTL2, "L2.als");
+ pausa(23);
+ hablar(TEXT229, "229.als");
+ habla_lobo(TEXTL3, "L3.als");
+ habla_lobo(TEXTL4, "L4.als");
+ hablar(TEXT230, "230.als");
+ habla_lobo(TEXTL5, "L5.als");
+ hablar(TEXT231, "231.als");
+ habla_lobo(TEXTL6, "L6.als");
+ habla_lobo(TEXTL7, "L7.als");
+ pausa(33);
+ hablar(TEXT232, "232.als");
+ habla_lobo(TEXTL8, "L8.als");
+}
+
+void DrasculaEngine::animacion_5_5(){
+ int h;
+ int frame = 0;
+ int hueso_x[] = {1, 99, 197, 1, 99, 197, 1, 99, 197};
+ int hueso_y[] = {1, 1, 1, 66, 66, 66, 131, 131, 131};
+ int vuela_x[] = {1, 63, 125, 187, 249};
+ int pixel_x = hare_x - 53, pixel_y = hare_y - 9;
+
+ sin_verbo();
+ resta_objeto(8);
+
+ lleva_al_hare(hare_x - 19, hare_y + alto_hare);
+ sentido_hare = 1;
+ refresca_pantalla();
+ VUELCA_PANTALLA(0, 0, 0, 0, 320, 200, dir_zona_pantalla);
+
+ lee_dibujos("3an5_1.alg");
+ descomprime_dibujo(dir_hare_fondo, 1);
+ lee_dibujos("3an5_2.alg");
+ descomprime_dibujo(dir_hare_frente, 1);
+
+ for (frame = 0; frame < 9; frame++) {
+ pausa(3);
+ DIBUJA_FONDO(0, 0, 0, 0, 320, 200, dir_dibujo1, dir_zona_pantalla);
+ DIBUJA_BLOQUE(hueso_x[frame], hueso_y[frame], pixel_x, pixel_y, 97, 64, dir_hare_fondo, dir_zona_pantalla);
+ VUELCA_PANTALLA(pixel_x, pixel_y, pixel_x,pixel_y, 97,64, dir_zona_pantalla);
+ }
+
+ DIBUJA_FONDO(52, 161, 198, 81, 26, 24, dir_dibujo3, dir_zona_pantalla);
+ VUELCA_PANTALLA(198, 81, 198, 81, 26, 24, dir_zona_pantalla);
+
+ for (frame = 0; frame < 9; frame++) {
+ pausa(3);
+ DIBUJA_FONDO(0, 0, 0, 0, 320, 200, dir_dibujo1, dir_zona_pantalla);
+ DIBUJA_BLOQUE(hueso_x[frame], hueso_y[frame], pixel_x, pixel_y, 97, 64, dir_hare_frente, dir_zona_pantalla);
+ VUELCA_PANTALLA(pixel_x, pixel_y, pixel_x,pixel_y, 97, 64, dir_zona_pantalla);
+ }
+
+ flags[6] = 1;
+ actualiza_datos();
+ pausa(12);
+
+ lee_dibujos("96.alg");
+ descomprime_dibujo(dir_hare_frente, 1);
+ for (h = 0; h < (200 - 18); h++)
+ DIBUJA_FONDO(0, 53, 0, h, 320, 19, dir_hare_frente, dir_zona_pantalla);
+
+ VUELCA_PANTALLA(0, 0, 0, 0, 320, 200, dir_zona_pantalla);
+
+ lee_dibujos("101.alg");
+ descomprime_dibujo(dir_dibujo1, MEDIA);
+ lee_dibujos("3an5_3.alg");
+ descomprime_dibujo(dir_hare_fondo, 1);
+ lee_dibujos("3an5_4.alg");
+ descomprime_dibujo(dir_hare_dch, 1);
+
+ VUELCA_PANTALLA(0, 0, 0, 0, 320, 200, dir_dibujo1);
+ pausa(9);
+ for (frame = 0; frame < 5; frame++) {
+ pausa(3);
+ DIBUJA_FONDO(vuela_x[frame], 1, 174, 79, 61, 109, dir_hare_fondo, dir_zona_pantalla);
+ VUELCA_PANTALLA(174, 79, 174, 79, 61, 109, dir_zona_pantalla);
+ }
+ for (frame = 0; frame < 5; frame++) {
+ pausa(3);
+ DIBUJA_FONDO(vuela_x[frame], 1, 174, 79, 61, 109, dir_hare_dch, dir_zona_pantalla);
+ VUELCA_PANTALLA(174, 79, 174, 79, 61, 109, dir_zona_pantalla);
+ }
+ VUELCA_PANTALLA(0, 0, 0, 0, 320, 200, dir_dibujo1);
+
+ comienza_sound("s1.als");
+ fin_sound();
+
+ lee_dibujos("99.alg");
+ descomprime_dibujo(dir_hare_fondo, 1);
+ lee_dibujos("97.alg");
+ descomprime_dibujo(dir_hare_dch, 1);
+
+ borra_pantalla();
+
+ lee_dibujos("49.alg");
+ descomprime_dibujo(dir_dibujo1, MEDIA);
+}
+
+void DrasculaEngine::animacion_6_5() {
+ habla_lobo(TEXTL9, "L9.als");
+ hablar(TEXT234, "234.als");
+}
+
+void DrasculaEngine::animacion_7_5() {
+ habla_lobo(TEXTL10, "L10.als");
+ hablar(TEXT236, "236.als");
+ habla_lobo(TEXTL11, "L11.als");
+ habla_lobo(TEXTL12, "L12.als");
+ habla_lobo(TEXTL13, "L13.als");
+ pausa(34);
+ habla_lobo(TEXTL14, "L14.als");
+}
+
+void DrasculaEngine::animacion_8_5() {
+ habla_lobo(TEXTL15, "L15.als");
+ hablar(TEXT238, "238.als");
+ habla_lobo(TEXTL16, "L16.als");
+}
+
+void DrasculaEngine::animacion_9_5() {
+ flags[4] = 1;
+ hablar(TEXT401, "401.als");
+ sin_verbo();
+ resta_objeto(15);
+}
+
+void DrasculaEngine::animacion_10_5() {
+ flags[3] = 1;
+ hablar(TEXT401, "401.als");
+ sin_verbo();
+ resta_objeto(12);
+}
+
+void DrasculaEngine::animacion_11_5() {
+ flags[9] = 1;
+ if (flags[2] == 1 && flags[3] == 1 && flags[4] == 1)
+ animacion_12_5();
+ else {
+ flags[9] = 0;
+ hablar(TEXT33, "33.als");
+ }
+}
+
+void DrasculaEngine::animacion_12_5() {
+ DacPalette256 palFondo1;
+ DacPalette256 palFondo2;
+ DacPalette256 palFondo3;
+
+ int frame;
+ const int rayo_x[] = {1, 46, 91, 136, 181, 226, 271, 181};
+ const int frusky_x[] = {100, 139, 178, 217, 100, 178, 217, 139, 100, 139};
+ const int elfrusky_x[] = {1, 68, 135, 1, 68, 135, 1, 68, 135, 68, 1, 135, 68, 135, 68};
+ //const int humo_x[] = {1, 29, 57, 85, 113, 141, 169, 197, 225};
+ int color, componente;
+ char fundido;
+
+ playmusic(26);
+ refresca_pantalla();
+ VUELCA_PANTALLA(0, 0, 0, 0, 320, 200, dir_zona_pantalla);
+ pausa(27);
+ anima("rayo1.bin", 23);
+ comienza_sound("s5.als");
+ anima("rayo2.bin", 17);
+ sentido_hare = 1;
+ refresca_pantalla();
+ VUELCA_PANTALLA(0, 0, 0, 0, 320, 200, dir_zona_pantalla);
+
+ hare_oscuro();
+
+ for (color = 0; color < 255; color++)
+ for (componente = 0; componente < 3; componente++) {
+ palFondo1[color][componente] = palJuego[color][componente];
+ palFondo2[color][componente] = palJuego[color][componente];
+ palFondo3[color][componente] = palJuego[color][componente];
+ }
+
+ for (fundido = 1; fundido >= 0; fundido--) {
+ for (color = 0; color < 128; color++)
+ for (componente = 0; componente < 3; componente++)
+ palFondo1[color][componente] = LimitaVGA(palFondo1[color][componente] - 8 + fundido);
+ }
+
+ for (fundido = 2; fundido >= 0; fundido--) {
+ for (color = 0; color < 128; color++)
+ for (componente = 0; componente < 3; componente++)
+ palFondo2[color][componente] = LimitaVGA(palFondo2[color][componente] - 8 + fundido);
+ }
+
+ for (fundido = 3; fundido >= 0; fundido--) {
+ for (color = 0; color < 128; color++)
+ for (componente = 0; componente < 3; componente++)
+ palFondo3[color][componente] = LimitaVGA(palFondo3[color][componente] - 8 + fundido);
+ }
+
+ lee_dibujos("3an11_1.alg");
+ descomprime_dibujo(dir_hare_fondo, 1);
+
+ for (frame = 0; frame < 8; frame++) {
+ if (frame == 2 || frame == 4 || frame == 8 || frame==10)
+ setvgapalette256((byte *)&palFondo1);
+ else if (frame == 1 || frame == 5 || frame == 7 || frame == 9)
+ setvgapalette256((byte *)&palFondo2);
+ else
+ setvgapalette256((byte *)&palFondo3);
+
+ pausa(4);
+ refresca_pantalla();
+ DIBUJA_BLOQUE(rayo_x[frame], 1, 41, 0, 44, 44, dir_hare_fondo, dir_zona_pantalla);
+ DIBUJA_BLOQUE(frusky_x[frame], 113, 205, 50, 38, 86, dir_dibujo3, dir_zona_pantalla);
+ VUELCA_PANTALLA(0, 0, 0, 0, 320, 200, dir_zona_pantalla);
+ }
+
+ fin_sound_corte();
+
+ for (frame = 0; frame < 15; frame++) {
+ if (frame == 2 || frame == 4 || frame == 7 || frame == 9)
+ setvgapalette256((byte *)&palFondo1);
+ else if (frame == 1 || frame == 5)
+ setvgapalette256((byte *)&palJuego);
+ else
+ setvgapalette256((byte *)&palFondo2);
+
+ pausa(4);
+ refresca_pantalla();
+ DIBUJA_BLOQUE(elfrusky_x[frame], 47, 192, 39, 66, 106, dir_hare_fondo, dir_zona_pantalla);
+ VUELCA_PANTALLA(0, 0, 0, 0, 320, 200, dir_zona_pantalla);
+ }
+
+ anima("frel.bin", 16);
+ borra_pantalla();
+ hare_claro();
+ ActualizaPaleta();
+
+ flags[1] = 1;
+
+ animacion_13_5();
+ comienza_sound("s1.als");
+ hipo(12);
+ fin_sound();
+
+ lee_dibujos("99.alg");
+ descomprime_dibujo(dir_hare_fondo, 1);
+
+ lleva_al_hare(40, 169);
+ lleva_al_hare(-14, 175);
+
+ rompo = 1;
+ musica_antes = musica_room;
+ hare_se_ve = 1;
+ borra_pantalla();
+ sentido_hare = 1;
+ hare_se_mueve = 0;
+ hare_x = -1;
+ obj_saliendo = 104;
+ sin_verbo();
+ carga_escoba("57.ald");
+}
+
+void DrasculaEngine::animacion_13_5() {
+ int frank_x = 199;
+ int frame = 0;
+ int frus_x[] = {1, 46, 91, 136, 181, 226, 271};
+ int frus_y[] = {1, 1, 1, 1, 1, 1, 1, 89};
+ int pos_frusky[6];
+
+ lee_dibujos("auxfr.alg");
+ descomprime_dibujo(dir_hare_fondo, 1);
+
+ pos_frusky[3] = 81;
+ pos_frusky[4] = 44;
+ pos_frusky[5] = 87;
+ pos_frusky[0] = 1;
+ pos_frusky[1] = 1;
+ pos_frusky[2] = frank_x;
+ refresca_pantalla();
+ DIBUJA_BLOQUE_CUT(pos_frusky, dir_hare_fondo, dir_zona_pantalla);
+ VUELCA_PANTALLA(0, 0, 0, 0, 320, 200, dir_zona_pantalla);
+ pausa(15);
+
+ playmusic(18);
+
+ for (;;) {
+ refresca_pantalla();
+ pos_frusky[0] = frus_x[frame];
+ pos_frusky[1] = frus_y[frame];
+ pos_frusky[2] = frank_x;
+ DIBUJA_BLOQUE_CUT( pos_frusky, dir_hare_fondo, dir_zona_pantalla);
+ VUELCA_PANTALLA(0, 0, 0, 0, 320, 200, dir_zona_pantalla);
+ frank_x = frank_x - 5;
+ frame++;
+ if (frank_x <= -45)
+ break;
+ if (frame == 7) {
+ frame = 0;
+ sentido_hare = 3;
+ }
+ pausa(6);
+ }
+}
+
+void DrasculaEngine::animacion_14_5() {
+ flags[11] = 1;
+ comienza_sound("s3.als");
+ refresca_pantalla();
+ VUELCA_PANTALLA(0, 0, 0,0 , 320, 200, dir_zona_pantalla);
+ fin_sound();
+ pausa(17);
+ sentido_hare = 3;
+ hablar(TEXT246,"246.als");
+ lleva_al_hare(89, 160);
+ flags[10] = 1;
+ comienza_sound("s7.als");
+ refresca_pantalla();
+ VUELCA_PANTALLA(0, 0, 0, 0, 320, 200, dir_zona_pantalla);
+ fin_sound();
+ pausa(14);
+ sentido_hare = 3;
+ refresca_pantalla();
+ VUELCA_PANTALLA(0, 0, 0, 0, 320, 200, dir_zona_pantalla);
+ habla_solo(TEXTD18, "d18.als");
+ FundeAlNegro(1);
+ error("part 6 hit");
+}
+
+void DrasculaEngine::animacion_15_5() {
+ habla_mus(TEXTE4, "E4.als");
+ habla_mus(TEXTE5, "E5.als");
+ habla_mus(TEXTE6, "E6.als");
+ hablar(TEXT291, "291.als");
+ habla_mus(TEXTE7, "E7.als");
+}
+
+void DrasculaEngine::animacion_16_5() {
+ habla_mus(TEXTE8, "E8.als");
+}
+
+void DrasculaEngine::animacion_17_5() {
+ habla_mus(TEXTE9, "E9.als");
+}
+
+void DrasculaEngine::refresca_49_antes() {
+ if (flags[6] == 0)
+ DIBUJA_FONDO(2, 136, 176, 81, 49, 62, dir_dibujo3, dir_zona_pantalla);
+}
+
+void DrasculaEngine::refresca_53_antes() {
+ if (flags[1] == 0)
+ DIBUJA_BLOQUE(2, 113, 205, 50, 38, 86, dir_dibujo3, dir_zona_pantalla);
+ if (flags[2] == 0)
+ DIBUJA_FONDO(41, 159, 27, 117, 25, 40, dir_dibujo3, dir_zona_pantalla);
+ if (flags[9] == 1)
+ DIBUJA_FONDO(67, 184, 56, 93, 32, 15, dir_dibujo3, dir_zona_pantalla);
+}
+
+void DrasculaEngine::refresca_54_antes() {
+ if (flags[5] == 1)
+ DIBUJA_FONDO(168, 156, 187, 111, 7, 11, dir_dibujo3, dir_zona_pantalla);
+ if (flags[12] == 1)
+ DIBUJA_FONDO(16, 156, 190, 64, 18, 24, dir_dibujo3, dir_zona_pantalla);
+}
+
+void DrasculaEngine::refresca_56_antes() {
+ if (flags[10] == 0)
+ DIBUJA_FONDO(2, 126, 42, 67, 57, 67, dir_dibujo3, dir_zona_pantalla);
+ if (flags[11] == 1)
+ DIBUJA_FONDO(60, 160, 128, 97, 103, 38, dir_dibujo3, dir_zona_pantalla);
+}
+
+void DrasculaEngine::refresca_50() {
+ DIBUJA_BLOQUE(4, 153, 118, 95, 67, 44, dir_dibujo3, dir_zona_pantalla);
+}
+
+void DrasculaEngine::refresca_57() {
+ DIBUJA_BLOQUE(7, 113, 166, 61, 62, 82, dir_dibujo3, dir_zona_pantalla);
+}
+
+void DrasculaEngine::pantalla_49(int fl){
+ if (objeto_que_lleva == HABLAR && fl ==51)
+ conversa("op_9.cal");
+ else if (objeto_que_lleva == MIRAR && fl == 51)
+ hablar(TEXT132, "132.als");
+ else if ((objeto_que_lleva == 8 && fl == 51) || (objeto_que_lleva == 8 && fl == 203))
+ animacion_5_5();
+ else if (objeto_que_lleva == MIRAR && fl == 200)
+ hablar(TEXT133, "133.als");
+ else if (objeto_que_lleva == HABLAR && fl == 200)
+ hablar(TEXT134, "134.als");
+ else if (objeto_que_lleva == MIRAR && fl == 201)
+ hablar(TEXT135, "135.als");
+ else if (objeto_que_lleva == MIRAR && fl == 203)
+ hablar(TEXT137, "137.als");
+ else
+ hay_respuesta = 0;
+}
+
+void DrasculaEngine::pantalla_53(int fl) {
+ if (objeto_que_lleva == COGER && fl == 120) {
+ agarra_objeto(16);
+ visible[3] = 0;
+ } else if (objeto_que_lleva == MIRAR && fl == 121)
+ hablar(TEXT128, "128.als");
+ else if (objeto_que_lleva == MIRAR && fl == 209)
+ hablar(TEXT129, "129.als");
+ else if (objeto_que_lleva == MOVER && fl == 123)
+ animacion_11_5();
+ else if (objeto_que_lleva == MIRAR && fl == 52)
+ hablar(TEXT447, "447.als");
+ else if (objeto_que_lleva == HABLAR && fl == 52)
+ hablar(TEXT131, "131.als");
+ else if (objeto_que_lleva == 12 && fl == 52)
+ animacion_10_5();
+ else if (objeto_que_lleva == 15 && fl == 52)
+ animacion_9_5();
+ else if (objeto_que_lleva == 16 && fl == 121) {
+ flags[2] = 1;
+ sin_verbo();
+ actualiza_datos();
+ } else if (objeto_que_lleva == 16) {
+ hablar(TEXT439, "439.als");
+ sin_verbo();
+ visible[3] = 1;
+ } else
+ hay_respuesta = 0;
+}
+
+void DrasculaEngine::pantalla_54(int fl) {
+ if ((objeto_que_lleva == HABLAR && fl == 118) || (objeto_que_lleva == MIRAR && fl == 118 && flags[0] == 0))
+ animacion_1_5();
+ else if (objeto_que_lleva == MIRAR && fl == 118 && flags[0]==1)
+ hablar(TEXT124, "124.als");
+ else if (objeto_que_lleva == MIRAR && fl == 53)
+ hablar(TEXT127, "127.als");
+ else if (objeto_que_lleva == HABLAR && fl == 53 && flags[14] == 0) {
+ hablar(TEXT288, "288.als");
+ flags[12] = 1;
+ pausa(10);
+ habla_mus(TEXTE1, "E1.als");
+ hablar(TEXT289, "289.als");
+ habla_mus(TEXTE2, "E2.als");
+ habla_mus(TEXTE3, "E3.als");
+ conversa("op_10.cal");
+ flags[12] = 0;
+ flags[14] = 1;
+ } else if (objeto_que_lleva == HABLAR && fl == 53 && flags[14] == 1)
+ hablar(TEXT109, "109.als");
+ else if (objeto_que_lleva == COGER && fl == 9999 && flags[13] == 0) {
+ agarra_objeto(8);
+ flags[13] = 1;
+ habla_mus(TEXTE10, "e10.als");
+ actualiza_datos();
+ } else if (objeto_que_lleva == ABRIR && fl == 119)
+ hablar(TEXT125, "125.als");
+ else if (objeto_que_lleva == MIRAR && fl == 119)
+ hablar(TEXT126, "126.als");
+ else if (objeto_que_lleva == 10 && fl == 119) {
+ pausa(4);
+ hablar(TEXT436, "436.als");
+ sin_verbo();
+ resta_objeto(10);
+ } else
+ hay_respuesta = 0;
+}
+
+void DrasculaEngine::pantalla_55(int fl) {
+ if (objeto_que_lleva == COGER && fl == 122) {
+ agarra_objeto(12);
+ flags[8] = 1;
+ actualiza_datos();
+ } else if (objeto_que_lleva == MIRAR && fl == 122)
+ hablar(TEXT138, "138.als");
+ else if (objeto_que_lleva == MIRAR && fl == 204)
+ hablar(TEXT139, "139.als");
+ else if (objeto_que_lleva == MIRAR && fl == 205)
+ hablar(TEXT140, "140.als");
+ else if (fl == 206) {
+ comienza_sound("s11.als");
+ anima("det.bin", 17);
+ fin_sound();
+ lleva_al_hare(hare_x - 3, hare_y + alto_hare + 6);
+ } else
+ hay_respuesta = 0;
+}
+
+void DrasculaEngine::pantalla_56(int fl) {
+ if (objeto_que_lleva == ABRIR && fl == 124)
+ animacion_14_5();
+ else if (objeto_que_lleva == MIRAR && fl == 124)
+ hablar(TEXT450, "450.als");
+ else if (objeto_que_lleva == ABRIR && fl == 207)
+ hablar(TEXT141, "141.als");
+ else if (objeto_que_lleva == MIRAR && fl == 208)
+ hablar(TEXT142, "142.als");
+ else
+ hay_respuesta = 0;
+}
+
+void DrasculaEngine::habla_lobo(const char *dicho, const char *filename) {
+ int tiempou;
+ long tiempol;
+
+ int x_habla[9] = {52, 79, 106, 133, 160, 187, 214, 241, 268};
+ int cara;
+
+ int longitud;
+ longitud = strlen(dicho);
+
+ tiempol = _system->getMillis();
+ tiempou = (unsigned int)tiempol / 2;
+ _rnd->setSeed(tiempou);
+
+ color_abc(ROJO);
+
+ if (hay_sb == 1) {
+ sku = new Common::File;
+ sku->open(filename);
+ if (!sku->isOpen()) {
+ error("no puedo abrir archivo de voz");
+ }
+ ctvd_init(2);
+ ctvd_speaker(1);
+ ctvd_output(sku);
+ }
+
+bucless:
+
+ cara = _rnd->getRandomNumber(8);
+
+ DIBUJA_FONDO(0, 0, 0, 0, 320, 200, dir_dibujo1, dir_zona_pantalla);
+
+ actualiza_refresco_antes();
+
+ DIBUJA_FONDO(x_habla[cara], 136, 198, 81, 26, 24, dir_dibujo3, dir_zona_pantalla);
+ pon_hare();
+ actualiza_refresco();
+
+ if (con_voces == 0)
+ centra_texto(dicho, 203, 78);
+
+ VUELCA_PANTALLA(0, 0, 0, 0, 320, 200, dir_zona_pantalla);
+
+ pausa(3);
+
+ int key = getscan();
+ if (key != 0)
+ ctvd_stop();
+ buffer_teclado();
+ if (hay_sb == 1) {
+ if (LookForFree() != 0)
+ goto bucless;
+ delete sku;
+ ctvd_terminate();
+ } else {
+ longitud = longitud - 2;
+ if (longitud > 0)
+ goto bucless;
+ }
+
+ refresca_pantalla();
+ VUELCA_PANTALLA(0, 0, 0, 0, 320, 200, dir_zona_pantalla);
+}
+
+void DrasculaEngine::habla_mus(const char *dicho, const char *filename) {
+ int tiempou;
+ long tiempol;
+
+ int x_habla[8] = { 16, 35, 54, 73, 92, 111, 130, 149};
+ int cara;
+
+ int longitud;
+ longitud = strlen(dicho);
+
+ tiempol = _system->getMillis();
+ tiempou = (unsigned int)tiempol / 2;
+ _rnd->setSeed(tiempou);
+
+ buffer_teclado();
+
+ color_abc(BLANCO);
+
+ if (hay_sb == 1) {
+ sku = new Common::File;
+ sku->open(filename);
+ if (!sku->isOpen()) {
+ error("no puedo abrir archivo de voz");
+ }
+ ctvd_init(2);
+ ctvd_speaker(1);
+ ctvd_output(sku);
+ }
+
+bucless:
+
+ cara = _rnd->getRandomNumber(7);
+
+ DIBUJA_FONDO(0, 0, 0, 0, 320, 200, dir_dibujo1, dir_zona_pantalla);
+
+ actualiza_refresco_antes();
+
+ DIBUJA_FONDO(x_habla[cara], 156, 190, 64, 18, 24, dir_dibujo3, dir_zona_pantalla);
+ pon_hare();
+ actualiza_refresco();
+
+ if (con_voces == 0)
+ centra_texto(dicho, 197, 64);
+
+ VUELCA_PANTALLA(0, 0, 0, 0, 320, 200, dir_zona_pantalla);
+
+ pausa(3);
+
+ int key = getscan();
+ if (key != 0)
+ ctvd_stop();
+ buffer_teclado();
+ if (hay_sb == 1) {
+ if (LookForFree() != 0)
+ goto bucless;
+ delete sku;
+ ctvd_terminate();
+ } else {
+ longitud = longitud - 2;
+ if (longitud > 0)
+ goto bucless;
+ }
+
+ refresca_pantalla();
+ VUELCA_PANTALLA(0, 0, 0, 0, 320, 200, dir_zona_pantalla);
+}
+
+void DrasculaEngine::animacion_1_6() {
+ int l;
+
+ sentido_hare = 0;
+ hare_x = 103;
+ hare_y = 108;
+ flags[0] = 1;
+ for (l = 0; l < 200; l++)
+ factor_red[l] = 98;
+
+ lee_dibujos("auxig2.alg");
+ descomprime_dibujo(dir_hare_frente, 1);
+ lee_dibujos("auxdr.alg");
+ descomprime_dibujo(dir_dibujo2, 1);
+ lee_dibujos("car.alg");
+ descomprime_dibujo(dir_hare_fondo, 1);
+ habla_dr_dch(TEXTD19, "D19.als");
+ hablar(TEXT247, "247.als");
+ habla_dr_dch(TEXTD20, "d20.als");
+ habla_dr_dch(TEXTD21, "d21.als");
+ hablar(TEXT248, "248.als");
+ habla_dr_dch(TEXTD22, "d22.als");
+ hablar(TEXT249, "249.als");
+ habla_dr_dch(TEXTD23, "d23.als");
+ conversa("op_11.cal");
+ habla_dr_dch(TEXTD26, "d26.als");
+
+ anima("fum.bin", 15);
+
+ habla_dr_dch(TEXTD27, "d27.als");
+ hablar(TEXT254, "254.als");
+ habla_dr_dch(TEXTD28, "d28.als");
+ hablar(TEXT255, "255.als");
+ habla_dr_dch(TEXTD29, "d29.als");
+ FundeAlNegro(1);
+ borra_pantalla();
+ lee_dibujos("time1.alg");
+ descomprime_dibujo(dir_zona_pantalla, 1);
+ VUELCA_PANTALLA(0, 0, 0, 0, 320, 200, dir_zona_pantalla);
+ delay(930);
+ borra_pantalla();
+ Negro();
+ hare_se_ve = 0;
+ flags[0] = 0;
+ refresca_pantalla();
+ VUELCA_PANTALLA(0, 0, 0, 0, 320, 200, dir_zona_pantalla);
+ FundeDelNegro(1);
+ hablar(TEXT256, "256.als");
+ habla_dr_dch(TEXTD30, "d30.als");
+ hablar(TEXT257, "257.als");
+ FundeAlNegro(0);
+ borra_pantalla();
+ lee_dibujos("time1.alg");
+ descomprime_dibujo(dir_zona_pantalla,1);
+ VUELCA_PANTALLA(0, 0, 0, 0, 320, 200, dir_zona_pantalla);
+ delay(900);
+ borra_pantalla();
+ Negro();
+ refresca_pantalla();
+ VUELCA_PANTALLA(0, 0, 0, 0, 320, 200, dir_zona_pantalla);
+ FundeDelNegro(1);
+ hablar(TEXT258, "258.als");
+ habla_dr_dch(TEXTD31, "d31.als");
+ animacion_5_6();
+ habla_dr_dch(TEXTD32, "d32.als");
+ habla_igor_dch(TEXTI11, "I11.als");
+ sentido_igor = 3;
+ habla_dr_dch(TEXTD33, "d33.als");
+ habla_igor_frente(TEXTI12, "I12.als");
+ habla_dr_dch(TEXTD34, "d34.als");
+ sentido_dr = 0;
+ habla_dr_izq(TEXTD35,"d35.als");
+ borra_pantalla();
+ carga_escoba("102.ald");
+ activa_pendulo();
+}
+
+void DrasculaEngine::animacion_2_6() {
+ habla_dr_dch(TEXTD24, "d24.als");
+}
+
+void DrasculaEngine::animacion_3_6() {
+ habla_dr_dch(TEXTD24, "d24.als");
+}
+
+void DrasculaEngine::animacion_4_6() {
+ habla_dr_dch(TEXTD25, "d25.als");
+}
+
+void DrasculaEngine::animacion_5_6() {
+ int n, pos_pen[6];
+
+ pos_pen[0] = 1;
+ pos_pen[1] = 29;
+ pos_pen[2] = 204;
+ pos_pen[3] = -125;
+ pos_pen[4] = 18;
+ pos_pen[5] = 125;
+
+ anima("man.bin", 14);
+
+ for (n = -125; n <= 0; n = n + 2) {
+ DIBUJA_FONDO(0, 0, 0, 0, 320, 200, dir_dibujo1, dir_zona_pantalla);
+ actualiza_refresco_antes();
+ pos_pen[3] = n;
+ DIBUJA_BLOQUE_CUT(pos_pen, dir_dibujo3, dir_zona_pantalla);
+
+ actualiza_refresco();
+
+ VUELCA_PANTALLA(0, 0, 0, 0, 320, 200, dir_zona_pantalla);
+ pausa(2);
+ }
+
+ flags[3] = 1;
+}
+
+void DrasculaEngine::animacion_6_6() {
+ anima("rct.bin", 11);
+ borra_pantalla();
+ sin_verbo();
+ resta_objeto(20);
+ lee_dibujos("96.alg");
+ descomprime_dibujo(dir_hare_frente, 1);
+ lee_dibujos("97.alg");
+ descomprime_dibujo(dir_hare_frente, 1);
+ lee_dibujos("97.alg");
+ descomprime_dibujo(dir_hare_dch, 1);
+ lee_dibujos("99.alg");
+ descomprime_dibujo(dir_hare_fondo, 1);
+ rompo = 1;
+ obj_saliendo = 104;
+ hare_x = -1;
+ sin_verbo();
+ carga_escoba("58.ald");
+ hare_se_ve = 1;
+ sentido_hare = 1;
+ anima("hbp.bin", 14);
+
+ sentido_hare = 3;
+ flags[0] = 1;
+ flags[1] = 0;
+ flags[2] = 1;
+}
+
+void DrasculaEngine::animacion_7_6() {
+ flags[8] = 1;
+ actualiza_datos();
+}
+
+void DrasculaEngine::animacion_9_6() {
+ int v_cd;
+
+ anima("fin.bin", 14);
+ playmusic(13);
+ flags[5] = 1;
+ anima("drf.bin", 16);
+ FundeAlNegro(0);
+ borra_pantalla();
+ hare_x = -1;
+ obj_saliendo = 108;
+ carga_escoba("59.ald");
+ strcpy(num_room, "nada.alg");
+ lee_dibujos("nota2.alg");
+ descomprime_dibujo(dir_dibujo1, MEDIA);
+ Negro();
+ sentido_hare = 1;
+ hare_x -= 21;
+ refresca_pantalla();
+ VUELCA_PANTALLA(0, 0, 0, 0, 320, 200, dir_zona_pantalla);
+ FundeDelNegro(0);
+ pausa(96);
+ lleva_al_hare(116, 178);
+ sentido_hare = 2;
+ refresca_pantalla();
+ VUELCA_PANTALLA(0, 0, 0, 0, 320, 200, dir_zona_pantalla);
+ playmusic(9);
+ borra_pantalla();
+ lee_dibujos("nota.alg");
+ descomprime_dibujo(dir_dibujo1, COMPLETA);
+ color_abc(BLANCO);
+ habla_solo(TEXTBJ24, "bj24.als");
+ habla_solo(TEXTBJ25, "bj25.als");
+ habla_solo(TEXTBJ26, "bj26.als");
+ habla_solo(TEXTBJ27, "bj27.als");
+ habla_solo(TEXTBJ28, "bj28.als");
+ sentido_hare = 3;
+ borra_pantalla();
+ lee_dibujos("96.alg");
+ descomprime_dibujo(dir_hare_frente, COMPLETA);
+ lee_dibujos("nota2.alg");
+ descomprime_dibujo(dir_dibujo1, MEDIA);
+ hablar(TEXT296, "296.als");
+ hablar(TEXT297, "297.als");
+ hablar(TEXT298, "298.als");
+ sentido_hare = 1;
+ hablar(TEXT299, "299.als");
+ hablar(TEXT300, "300.als");
+ refresca_pantalla();
+ DIBUJA_FONDO(0, 0, 0, 0, 320, 200, dir_zona_pantalla, dir_dibujo1);
+ VUELCA_PANTALLA(0, 0, 0, 0, 320, 200, dir_zona_pantalla);
+ color_abc(VERDE_CLARO);
+ habla_solo("GOOOOOOOOOOOOOOOL", "s15.als");
+ lee_dibujos("nota2.alg");
+ descomprime_dibujo(dir_dibujo1, 1);
+ sentido_hare = 0;
+ refresca_pantalla();
+ VUELCA_PANTALLA(0, 0, 0, 0, 320, 200, dir_zona_pantalla);
+ hablar(TEXT301, "301.als");
+ v_cd = _mixer->getVolumeForSoundType(Audio::Mixer::kMusicSoundType) / 16;
+ v_cd = v_cd + 4;
+ playmusic(17);
+ FundeAlNegro(1);
+ borra_pantalla();
+ fliplay("qpc.bin", 1);
+ MusicFadeout();
+ stopmusic();
+ borra_pantalla();
+ _mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, v_cd * 16);
+ playmusic(3);
+ fliplay("crd.bin", 1);
+ stopmusic();
+ error("end of game ?");
+}
+
+void DrasculaEngine::animacion_10_6() {
+ comienza_sound ("s14.als");
+ DIBUJA_FONDO(0, 0, 0, 0, 320, 200, dir_dibujo1, dir_zona_pantalla);
+ actualiza_refresco_antes();
+ DIBUJA_FONDO(164, 85, 155, 48, 113, 114, dir_dibujo3, dir_zona_pantalla);
+
+ VUELCA_PANTALLA(0, 0, 0, 0, 320, 200, dir_zona_pantalla);
+ fin_sound();
+ habla_taber2(TEXTT23, "t23.als");
+ flags[7] = 1;
+ VUELCA_PANTALLA(0, 0, 0, 0, 320, 200, dir_zona_pantalla);
+ FundeDelNegro(0);
+ pausa(96);
+ lleva_al_hare(116, 178);
+ sentido_hare = 2;
+ refresca_pantalla();
+ VUELCA_PANTALLA(0, 0, 0, 0, 320, 200, dir_zona_pantalla);
+ playmusic(9);
+ borra_pantalla();
+ lee_dibujos("nota.alg");
+ descomprime_dibujo(dir_dibujo1, COMPLETA);
+ color_abc(BLANCO);
+ habla_solo(TEXTBJ24, "bj24.als");
+ habla_solo(TEXTBJ25, "bj25.als");
+ habla_solo(TEXTBJ26, "bj26.als");
+ habla_solo(TEXTBJ27, "bj27.als");
+ habla_solo(TEXTBJ28, "bj28.als");
+ sentido_hare = 3;
+ borra_pantalla();
+ lee_dibujos("96.alg");
+ descomprime_dibujo(dir_hare_frente, COMPLETA);
+ lee_dibujos("nota2.alg");
+ descomprime_dibujo(dir_dibujo1, MEDIA);
+ hablar(TEXT296, "296.als");
+ hablar(TEXT297, "297.als");
+ hablar(TEXT298, "298.als");
+ sentido_hare = 1;
+ hablar(TEXT299, "299.als");
+ hablar(TEXT300, "300.als");
+ refresca_pantalla();
+ DIBUJA_FONDO(0, 0, 0, 0, 320, 200, dir_zona_pantalla, dir_dibujo1);
+ VUELCA_PANTALLA(0, 0, 0, 0, 320, 200, dir_zona_pantalla);
+ color_abc(VERDE_CLARO);
+ habla_solo("GOOOOOOOOOOOOOOOL", "s15.als");
+ lee_dibujos("nota2.alg");
+ descomprime_dibujo(dir_dibujo1, 1);
+}
+
+void DrasculaEngine::animacion_11_6() {
+ habla_taber2(TEXTT10, "t10.als");
+ hablar(TEXT268, "268.als");
+ habla_taber2(TEXTT11, "t11.als");
+}
+
+void DrasculaEngine::animacion_12_6() {
+ habla_taber2(TEXTT12, "t12.als");
+ hablar(TEXT270, "270.als");
+ habla_taber2(TEXTT13, "t13.als");
+ habla_taber2(TEXTT14, "t14.als");
+}
+
+void DrasculaEngine::animacion_13_6() {
+ habla_taber2(TEXTT15, "t15.als");
+}
+
+void DrasculaEngine::animacion_14_6() {
+ habla_taber2(TEXTT24, "t24.als");
+ suma_objeto(21);
+ flags[10] = 1;
+ rompo_y_salgo = 1;
+}
+
+void DrasculaEngine::animacion_15_6() {
+ habla_taber2(TEXTT16, "t16.als");
+}
+
+void DrasculaEngine::animacion_18_6() {
+ sin_verbo();
+ resta_objeto(21);
+ anima("beb.bin", 10);
+}
+
+void DrasculaEngine::animacion_19_6() {
+ DIBUJA_FONDO(0, 0, 0, 0, 320, 200, dir_dibujo1, dir_zona_pantalla);
+ DIBUJA_FONDO(140, 23, 161, 69, 35, 80, dir_dibujo3, dir_zona_pantalla);
+
+ actualiza_refresco_antes();
+ pon_hare();
+ VUELCA_PANTALLA(0, 0, 0, 0, 320, 200, dir_zona_pantalla);
+ pausa(6);
+ refresca_pantalla();
+ VUELCA_PANTALLA(0, 0, 0, 0, 320, 200, dir_zona_pantalla);
+ comienza_sound("s4.als");
+ pausa(6);
+ fin_sound();
+}
+
+void DrasculaEngine::activa_pendulo() {
+ flags[1] = 2;
+ hare_se_ve = 0;
+ strcpy(num_room, "102.alg");
+ lee_dibujos("102.alg");
+ descomprime_dibujo(dir_dibujo1, MEDIA);
+ lee_dibujos("an_p1.alg");
+ descomprime_dibujo(dir_dibujo3, 1);
+ lee_dibujos("an_p2.alg");
+ descomprime_dibujo(dir_hare_dch, 1);
+ lee_dibujos("an_p3.alg");
+ descomprime_dibujo(dir_hare_frente, 1);
+
+ DIBUJA_FONDO(0, 171, 0, 0, ANCHOBJ, ALTOBJ, dir_hare_fondo, dir_dibujo3);
+
+ conta_ciego_vez = (int)vez();
+}
+
+void DrasculaEngine::habla_pen(const char *dicho, const char *filename) {
+ int tiempou;
+ long tiempol;
+
+ int x_habla[8] = {112, 138, 164, 190, 216, 242, 268, 294};
+ int cara;
+
+ int longitud;
+ longitud = strlen(dicho);
+
+ flags[1] = 1;
+
+ refresca_pantalla();
+ DIBUJA_BLOQUE(44, 145, 145, 105, 25, 29, dir_dibujo3, dir_zona_pantalla);
+ VUELCA_PANTALLA(0, 0, 0, 0, 320, 200, dir_zona_pantalla);
+
+ tiempol = _system->getMillis();
+ tiempou = (unsigned int)tiempol / 2;
+ _rnd->setSeed(tiempou);
+
+ buffer_teclado();
+
+ color_abc(AMARILLO);
+
+ if (hay_sb == 1) {
+ sku = new Common::File;
+ sku->open(filename);
+ if (!sku->isOpen()) {
+ error("no puedo abrir archivo de voz");
+ }
+ ctvd_init(2);
+ ctvd_speaker(1);
+ ctvd_output(sku);
+ }
+
+bucless:
+
+ cara = _rnd->getRandomNumber(7);
+
+ DIBUJA_FONDO(0, 0, 0, 0, 320, 200, dir_dibujo1, dir_zona_pantalla);
+
+ actualiza_refresco_antes();
+
+ DIBUJA_BLOQUE(x_habla[cara], 145, 145, 105, 25, 29, dir_dibujo3, dir_zona_pantalla);
+
+ actualiza_refresco();
+
+ if (con_voces == 0)
+ centra_texto(dicho, 160, 105);
+
+ VUELCA_PANTALLA(0, 0, 0, 0, 320, 200, dir_zona_pantalla);
+
+ pausa(3);
+
+ int key = getscan();
+ if (key != 0)
+ ctvd_stop();
+ buffer_teclado();
+ if (hay_sb == 1) {
+ if (LookForFree() != 0)
+ goto bucless;
+ delete sku;
+ ctvd_terminate();
+ } else {
+ longitud = longitud - 2;
+ if (longitud > 0)
+ goto bucless;
+ }
+
+ flags[1] = 0;
+ DIBUJA_FONDO(0, 0, 0, 0, 320, 200, dir_dibujo1, dir_zona_pantalla);
+ actualiza_refresco_antes();
+ VUELCA_PANTALLA(0, 0, 0, 0, 320, 200, dir_zona_pantalla);
+}
+
+void DrasculaEngine::habla_pen2(const char *dicho, const char *filename) {
+ int tiempou;
+ long tiempol;
+
+ int x_habla[5]={122, 148, 174, 200, 226};
+ int cara;
+
+ int longitud;
+ longitud = strlen(dicho);
+
+ flags[1] = 1;
+
+ tiempol = _system->getMillis();
+ tiempou = (unsigned int)tiempol / 2;
+ _rnd->setSeed(tiempou);
+
+ buffer_teclado();
+
+ color_abc(AMARILLO);
+
+ if (hay_sb == 1) {
+ sku = new Common::File;
+ sku->open(filename);
+ if (!sku->isOpen()) {
+ error("no puedo abrir archivo de voz");
+ }
+ ctvd_init(2);
+ ctvd_speaker(1);
+ ctvd_output(sku);
+ }
+
+bucless:
+
+ cara = _rnd->getRandomNumber(4);
+
+ DIBUJA_FONDO(0, 0, 0, 0, 320, 200, dir_dibujo1, dir_zona_pantalla);
+
+ actualiza_refresco_antes();
+
+ DIBUJA_FONDO(x_habla[cara], 171, 173, 116, 25, 28, dir_dibujo3, dir_zona_pantalla);
+
+ actualiza_refresco();
+
+ if (con_voces == 0)
+ centra_texto(dicho, 195, 107);
+
+ VUELCA_PANTALLA(0, 0, 0, 0, 320, 200, dir_zona_pantalla);
+
+ pausa(3);
+
+ int key = getscan();
+ if (key != 0)
+ ctvd_stop();
+ buffer_teclado();
+ if (hay_sb == 1) {
+ if (LookForFree() != 0)
+ goto bucless;
+ delete sku;
+ ctvd_terminate();
+ } else {
+ longitud = longitud - 2;
+ if (longitud > 0)
+ goto bucless;
+ }
+
+ flags[1] = 0;
+ DIBUJA_FONDO(0, 0, 0, 0, 320, 200, dir_dibujo1, dir_zona_pantalla);
+ actualiza_refresco_antes();
+ VUELCA_PANTALLA(0, 0, 0, 0, 320, 200, dir_zona_pantalla);
+}
+
+void DrasculaEngine::habla_taber2(const char *dicho, const char *filename) {
+ int tiempou;
+ long tiempol;
+
+ int x_habla[6] = {1, 23, 45, 67, 89, 111};
+ int cara;
+
+ int longitud;
+ longitud = strlen(dicho);
+
+ tiempol = _system->getMillis();
+ tiempou = (unsigned int)tiempol / 2;
+ _rnd->setSeed(tiempou);
+
+ buffer_teclado();
+
+ color_abc(MARRON);
+
+ if (hay_sb == 1) {
+ sku = new Common::File;
+ sku->open(filename);
+ if (!sku->isOpen()) {
+ error("no puedo abrir archivo de voz");
+ }
+ ctvd_init(2);
+ ctvd_speaker(1);
+ ctvd_output(sku);
+ }
+
+bucless:
+
+ cara = _rnd->getRandomNumber(5);
+
+ DIBUJA_FONDO(0, 0, 0, 0, 320, 200, dir_dibujo1, dir_zona_pantalla);
+
+ actualiza_refresco_antes();
+
+ DIBUJA_FONDO(x_habla[cara], 130, 151, 43, 21, 24, dir_dibujo3, dir_zona_pantalla);
+ pon_hare();
+ actualiza_refresco();
+
+ if (con_voces == 0)
+ centra_texto(dicho, 132, 45);
+
+ VUELCA_PANTALLA(0, 0, 0, 0, 320, 200, dir_zona_pantalla);
+
+ pausa(3);
+
+ int key = getscan();
+ if (key != 0)
+ ctvd_stop();
+ buffer_teclado();
+ if (hay_sb == 1) {
+ if (LookForFree() != 0)
+ goto bucless;
+ delete sku;
+ ctvd_terminate();
+ } else {
+ longitud = longitud - 2;
+ if (longitud > 0)
+ goto bucless;
+ }
+
+ refresca_pantalla();
+ VUELCA_PANTALLA(0, 0, 0, 0, 320, 200, dir_zona_pantalla);
+}
+
+void DrasculaEngine::refresca_58() {
+ if (hare_se_ve == 1)
+ DIBUJA_BLOQUE(67, 139, 140, 147, 12, 16, dir_dibujo3, dir_zona_pantalla);
+}
+
+void DrasculaEngine::refresca_60() {
+ if (hare_y - 10 < y_dr && flags[5] == 0)
+ pon_dr();
+}
+
+void DrasculaEngine::refresca_61() {
+ DIBUJA_BLOQUE(1, 154, 83, 122, 131, 44, dir_dibujo3, dir_zona_pantalla);
+}
+
+void DrasculaEngine::refresca_58_antes() {
+ if (flags[0] == 0)
+ DIBUJA_FONDO(1, 156, 143, 120, 120, 43, dir_dibujo3, dir_zona_pantalla);
+ if (flags[1] == 2)
+ DIBUJA_BLOQUE(252, 171, 173, 116, 25, 28, dir_dibujo3, dir_zona_pantalla);
+ if (flags[1] == 0 && flags[0] == 0)
+ DIBUJA_BLOQUE(278, 171, 173, 116, 25, 28, dir_dibujo3, dir_zona_pantalla);
+ if (flags[2] == 0) {
+ pon_igor();
+ pon_dr();
+ }
+ if (flags[3] == 1)
+ DIBUJA_BLOQUE(1, 29, 204, 0, 18, 125, dir_dibujo3, dir_zona_pantalla);
+ if (flags[8] == 1)
+ DIBUJA_FONDO(20, 60, 30, 64, 46, 95, dir_dibujo3, dir_zona_pantalla);
+}
+
+void DrasculaEngine::refresca_59_antes() {
+ if (flags[4] == 0)
+ DIBUJA_BLOQUE(1, 146, 65, 106, 83, 40, dir_dibujo3, dir_zona_pantalla);
+ if (flags[9] == 1) {
+ DIBUJA_FONDO(65, 103, 65, 103, 49, 38, dir_dibujo1, dir_zona_pantalla);
+ DIBUJA_BLOQUE(1, 105, 65, 103, 49, 38, dir_dibujo3, dir_zona_pantalla);
+ }
+}
+
+void DrasculaEngine::refresca_60_antes() {
+ int velas_y[] = {158, 172, 186};
+ int diferencia;
+
+ if (flags[5] == 0)
+ pon_dr();
+
+ DIBUJA_FONDO(123, velas_y[frame_velas], 142, 14, 39, 13, dir_dibujo3, dir_zona_pantalla);
+
+ if (flag_tv == 1)
+ DIBUJA_FONDO(114, 158, 8, 30, 8, 23, dir_dibujo3, dir_zona_pantalla);
+
+ diferencia = (int)vez() - conta_ciego_vez;
+ parpadeo = _rnd->getRandomNumber(7);
+ if (parpadeo == 5 && flag_tv == 0)
+ flag_tv = 1;
+ else if (parpadeo == 5 && flag_tv == 1)
+ flag_tv = 0;
+ if (diferencia > 6) {
+ frame_velas++;
+ if (frame_velas == 3)
+ frame_velas = 0;
+ conta_ciego_vez = (int)vez();
+ }
+}
+
+void DrasculaEngine::pantalla_58(int fl) {
+ if (objeto_que_lleva == MOVER && fl == 103)
+ animacion_7_6();
+ else if (objeto_que_lleva == MIRAR && fl == 104)
+ hablar(TEXT454, "454.als");
+ else
+ hay_respuesta = 0;
+}
+
+void DrasculaEngine::pantalla_59(int fl) {
+ if ((objeto_que_lleva == HABLAR && fl == 51) || (objeto_que_lleva == MIRAR && fl == 51)) {
+ flags[9] = 1;
+ hablar(TEXT259, "259.als");
+ habla_bj_cama(TEXTBJ13, "bj13.als");
+ hablar(TEXT263, "263.als");
+ habla_bj_cama(TEXTBJ14, "bj14.als");
+ pausa(40);
+ hablar(TEXT264, "264.als");
+ habla_bj_cama(TEXTBJ15, "BJ15.als");
+ hablar(TEXT265, "265.als");
+ flags[9] = 0;
+ if (flags[11] == 0) {
+ comienza_sound("s12.als");
+ delay(40);
+ fin_sound();
+ delay(10);
+ lleva_al_hare(174, 168);
+ sentido_hare = 2;
+ refresca_pantalla();
+ VUELCA_PANTALLA(0, 0, 0, 0, 320, 200, dir_zona_pantalla);
+ pausa(40);
+ comienza_sound("s12.als");
+ pausa(19);
+ fin_sound_corte();
+ hare_se_ve = 0;
+ refresca_pantalla();
+ DIBUJA_BLOQUE(101, 34, hare_x - 4, hare_y - 1, 37, 70, dir_dibujo3, dir_zona_pantalla);
+ DIBUJA_FONDO(0, 0, 0, 0, 320, 200, dir_zona_pantalla, dir_dibujo1);
+ VUELCA_PANTALLA(0, 0, 0, 0, 320, 200, dir_zona_pantalla);
+ hare_se_ve = 1;
+ borra_pantalla();
+ lee_dibujos("tlef0.alg");
+ descomprime_dibujo(dir_dibujo1, COMPLETA);
+ lee_dibujos("tlef1.alg");
+ descomprime_dibujo(dir_dibujo3, 1);
+ lee_dibujos("tlef2.alg");
+ descomprime_dibujo(dir_hare_frente, 1);
+ lee_dibujos("tlef3.alg");
+ descomprime_dibujo(dir_hare_fondo, 1);
+ habla_htel(TEXT240, "240.als");
+
+ color_abc(VON_BRAUN);
+ habla_solo(TEXTVB58, "VB58.als");
+ habla_htel(TEXT241, "241.als");
+ color_abc(VON_BRAUN);
+ habla_solo(TEXTVB59, "VB59.als");
+ habla_htel(TEXT242, "242.als");
+ color_abc(VON_BRAUN);
+ habla_solo(TEXTVB60, "VB60.als");
+ habla_htel(TEXT196, "196.als");
+ color_abc(VON_BRAUN);
+ habla_solo(TEXTVB61,"VB61.als");
+ habla_htel(TEXT244, "244.als");
+ color_abc(VON_BRAUN);
+ habla_solo(TEXTVB62, "VB62.als");
+ borra_pantalla();
+ lee_dibujos("aux59.alg");
+ descomprime_dibujo(dir_dibujo3, 1);
+ lee_dibujos("96.alg");
+ descomprime_dibujo(dir_hare_frente, COMPLETA);
+ lee_dibujos("99.alg");
+ descomprime_dibujo(dir_hare_fondo, 1);
+ lee_dibujos("59.alg");
+ descomprime_dibujo(dir_dibujo1, MEDIA);
+ sentido_hare = 3;
+ hablar(TEXT245, "245.als");
+ sin_verbo();
+ flags[11] = 1;
+ }
+ } else
+ hay_respuesta = 0;
+}
+
+void DrasculaEngine::pantalla_60(int fl) {
+ if (objeto_que_lleva == MOVER && fl == 112)
+ animacion_10();
+ else if (objeto_que_lleva == MIRAR && fl == 112)
+ hablar(TEXT440, "440.als");
+ else if (objeto_que_lleva == HABLAR && fl == 52) {
+ hablar(TEXT266, "266.als");
+ habla_taber2(TEXTT1, "t1.als");
+ conversa("op_12.cal");
+ sin_verbo();
+ objeto_que_lleva = 0;
+ } else if (objeto_que_lleva == HABLAR && fl == 115)
+ hablar(TEXT455, "455.als");
+ else if (objeto_que_lleva == HABLAR && fl == 56)
+ hablar(TEXT455, "455.als");
+ else if (objeto_que_lleva == MIRAR && fl == 114)
+ hablar(TEXT167, "167.als");
+ else if (objeto_que_lleva == MIRAR && fl == 113)
+ hablar(TEXT168, "168.als");
+ else if (objeto_que_lleva == COGER && fl == 113)
+ hablar(TEXT170, "170.als");
+ else if (objeto_que_lleva == MOVER && fl == 113)
+ hablar(TEXT170, "170.als");
+ else if (objeto_que_lleva == HABLAR && fl == 113)
+ hablar(TEXT169, "169.als");
+ else if (objeto_que_lleva == 21 && fl == 56)
+ animacion_18_6();
+ else if (objeto_que_lleva == 9 && fl == 56 && flags[6] == 1)
+ animacion_9();
+ else if (objeto_que_lleva == 9 && fl == 56 && flags[6] == 0) {
+ anima("cnf.bin", 14);
+ hablar(TEXT455, "455.als");
+ } else
+ hay_respuesta = 0;
+}
+
+void DrasculaEngine::pantalla_61(int fl) {
+ if (objeto_que_lleva == MIRAR && fl == 116)
+ hablar(TEXT172, "172.als");
+ else if (objeto_que_lleva == MIRAR && fl == 117)
+ hablar(TEXT173, "173.als");
+ else if (objeto_que_lleva == MOVER && fl == 117)
+ hablar(TEXT174, "174.als");
+ else if (objeto_que_lleva == ABRIR && fl == 117)
+ hablar(TEXT174, "174.als");
+ else
+ hay_respuesta = 0;
+}
+
+void DrasculaEngine::habla_bj_cama(const char *dicho, const char *filename) {
+ int tiempou;
+ long tiempol;
+
+ int x_habla[5] = {51, 101, 151, 201, 251};
+ int cara;
+
+ int longitud;
+ longitud = strlen(dicho);
+
+ tiempol = _system->getMillis();
+ tiempou = (unsigned int)tiempol / 2;
+ _rnd->setSeed(tiempou);
+
+ buffer_teclado();
+
+ color_abc(BLANCO);
+
+ if (hay_sb == 1) {
+ sku = new Common::File;
+ sku->open(filename);
+ if (!sku->isOpen()) {
+ error("no puedo abrir archivo de voz");
+ }
+ ctvd_init(2);
+ ctvd_speaker(1);
+ ctvd_output(sku);
+ }
+
+bucless:
+
+ cara = _rnd->getRandomNumber(4);
+
+ DIBUJA_FONDO(0, 0, 0, 0, 320, 200, dir_dibujo1, dir_zona_pantalla);
+
+ actualiza_refresco_antes();
+
+ DIBUJA_FONDO(65, 103, 65, 103, 49, 38, dir_dibujo1, dir_zona_pantalla);
+ DIBUJA_BLOQUE(x_habla[cara], 105, 65, 103, 49, 38, dir_dibujo3, dir_zona_pantalla);
+ pon_hare();
+ actualiza_refresco();
+
+ if (con_voces == 0)
+ centra_texto(dicho, 104, 102);
+
+ VUELCA_PANTALLA(0, 0, 0, 0, 320, 200, dir_zona_pantalla);
+
+ pausa(3);
+
+ int key = getscan();
+ if (key != 0)
+ ctvd_stop();
+ buffer_teclado();
+ if (hay_sb == 1) {
+ if (LookForFree() != 0)
+ goto bucless;
+ delete sku;
+ ctvd_terminate();
+ } else {
+ longitud = longitud - 2;
+ if (longitud > 0)
+ goto bucless;
+ }
+ refresca_pantalla();
+ VUELCA_PANTALLA(0, 0, 0, 0, 320, 200, dir_zona_pantalla);
+}
+
+void DrasculaEngine::habla_htel(const char *dicho, const char *filename) {
+ int tiempou;
+ long tiempol;
+ char *num_cara;
+
+ int x_habla[3] = {1, 94, 187};
+ int cara, pantalla;
+
+ int longitud;
+ longitud = strlen(dicho);
+
+ tiempol = _system->getMillis();
+ tiempou = (unsigned int)tiempol / 2;
+ _rnd->setSeed(tiempou);
+
+ buffer_teclado();
+
+ color_abc(AMARILLO);
+
+ if (hay_sb == 1) {
+ sku = new Common::File;
+ sku->open(filename);
+ if (!sku->isOpen()) {
+ error("no puedo abrir archivo de voz");
+ }
+ ctvd_init(2);
+ ctvd_speaker(1);
+ ctvd_output(sku);
+ }
+
+bucless:
+
+ cara = _rnd->getRandomNumber(2);
+ pantalla = _rnd->getRandomNumber(2);
+
+ if (cara == 0 && pantalla == 0)
+ num_cara = (char *)dir_dibujo3;
+ else if (pantalla == 1)
+ num_cara = (char *)dir_hare_frente;
+ else
+ num_cara = (char *)dir_hare_fondo;
+
+ DIBUJA_FONDO(0, 0, 0, 0, 320, 200, dir_dibujo1, dir_zona_pantalla);
+
+ DIBUJA_FONDO(x_habla[cara], 1, 45, 24, 92, 108, (byte *)num_cara, dir_zona_pantalla);
+
+ if (con_voces == 0)
+ centra_texto(dicho, 90, 50);
+
+ VUELCA_PANTALLA(0, 0, 0, 0, 320, 200, dir_zona_pantalla);
+ pausa(3);
+
+ int key = getscan();
+ if (key != 0)
+ ctvd_stop();
+ buffer_teclado();
+ if (hay_sb == 1) {
+ if (LookForFree() != 0)
+ goto bucless;
+ delete sku;
+ ctvd_terminate();
+ } else {
+ longitud = longitud - 2;
+ if (longitud > 0)
+ goto bucless;
+ }
+
+ DIBUJA_FONDO(0, 0, 0, 0, 320, 200, dir_dibujo1, dir_zona_pantalla);
+ VUELCA_PANTALLA(0, 0, 0, 0, 320, 200, dir_zona_pantalla);
+}
+
+void DrasculaEngine::refresca_pendulo() {
+ int pendulo_x[] = {40, 96, 152, 208, 264, 40, 96, 152, 208, 208, 152, 264, 40, 96, 152, 208, 264};
+ int diferencia;
+
+ if (frame_pen <= 4)
+ dir_pendulo = dir_dibujo3;
+ else if (frame_pen <= 11)
+ dir_pendulo = dir_hare_dch;
+ else
+ dir_pendulo = dir_hare_frente;
+
+ DIBUJA_FONDO(pendulo_x[frame_pen], 19, 152, 0, 55, 125, dir_pendulo, dir_zona_pantalla);
+
+ if (flags[1] == 2)
+ DIBUJA_BLOQUE(18, 145, 145, 105, 25, 29, dir_dibujo3, dir_zona_pantalla);
+
+ if (flags[1] == 0)
+ DIBUJA_BLOQUE(44, 145, 145, 105, 25, 29, dir_dibujo3, dir_zona_pantalla);
+
+ diferencia = (int)vez() - conta_ciego_vez;
+ if (diferencia > 8) {
+ frame_pen++;
+ if (frame_pen == 17)
+ frame_pen = 0;
+ conta_ciego_vez = (int)vez();
+ }
+}
+
+void DrasculaEngine::pantalla_pendulo(int fl) {
+ if (objeto_que_lleva == MIRAR && fl == 100)
+ hablar(TEXT452, "452.als");
+ else if (objeto_que_lleva == MIRAR && fl == 101)
+ hablar (TEXT123, "123.als");
+ else if (objeto_que_lleva == COGER && fl == 101)
+ agarra_objeto(20);
+ else if (objeto_que_lleva == 20 && fl == 100)
+ animacion_6_6();
+ else if (objeto_que_lleva == COGER || objeto_que_lleva == ABRIR)
+ hablar(TEXT453, "453.als");
+ else
+ hay_respuesta = 0;
+}
} // End of namespace Drascula
diff --git a/engines/drascula/drascula.h b/engines/drascula/drascula.h
index d8e49ba930..229e6d71b3 100644
--- a/engines/drascula/drascula.h
+++ b/engines/drascula/drascula.h
@@ -419,7 +419,7 @@ public:
char alapantallakeva[40][20];
int x_alakeva[40], y_alakeva[40], sentido_alkeva[40], alapuertakeva[40];
int x1[40], y1[40], x2[40], y2[40];
- int lleva_objeto , objeto_que_lleva;
+ int lleva_objeto, objeto_que_lleva;
int con_voces;
int menu_bar, menu_scr, hay_nombre;
char texto_nombre[20];
@@ -462,7 +462,7 @@ public:
int cont_sv;
int term_int;
int num_ejec;
- int cual_ejec, hay_que_load;
+ int hay_que_load;
char nom_partida[13];
int _color;
int corta_musica;
@@ -497,7 +497,6 @@ public:
void animacion_4_1();
void animacion_3_2();
void animacion_4_2();
- void animacion_7();
void animacion_8();
void animacion_9();
void animacion_10();
@@ -508,7 +507,6 @@ public:
void animacion_15();
void animacion_16();
void animacion_17();
- void animacion_18();
void animacion_19();
void animacion_20();
void animacion_21();
@@ -527,7 +525,7 @@ public:
void animacion_32();
void animacion_33();
void animacion_34();
- void animacion_35();
+ void animacion_35_2();
void animacion_36();
void refresca_1_antes();
@@ -553,8 +551,7 @@ public:
void sin_verbo();
void para_cargar(char[]);
- void carga_escoba_1(const char *);
- void carga_escoba_2(const char *);
+ void carga_escoba(const char *);
void borra_pantalla();
void lleva_al_hare(int, int);
void mueve_cursor();
@@ -654,6 +651,9 @@ public:
int GlobalSpeed;
int LastFrame;
+ int frame_pen;
+ int flag_tv;
+
byte *carga_pcx(byte *NamePcc);
void set_dac(byte *dac);
void WaitForNext(int FPS);
@@ -687,9 +687,86 @@ public:
void ctvd_speaker(int flag);
void ctvd_output(Common::File *file_handle);
void ctvd_init(int b);
-
-
-
+ void grr();
+ void pantalla_13(int fl);
+ void refresca_13();
+ void refresca_20();
+ void animacion_1_3();
+ void animacion_2_3();
+ void animacion_3_3();
+ void animacion_4_3();
+ void animacion_5();
+ void animacion_6();
+ void animacion_7_4();
+ void animacion_rayo();
+ void animacion_2_4();
+ void animacion_3_4();
+ void animacion_4_4();
+ void animacion_1_5();
+ void animacion_2_5();
+ void animacion_3_5();
+ void animacion_4_5();
+ void animacion_5_5();
+ void animacion_6_5();
+ void animacion_7_5();
+ void animacion_8_5();
+ void animacion_9_5();
+ void animacion_10_5();
+ void animacion_11_5();
+ void animacion_12_5();
+ void animacion_13_5();
+ void animacion_14_5();
+ void animacion_15_5();
+ void animacion_16_5();
+ void animacion_17_5();
+ void pantalla_49(int);
+ void pantalla_53(int);
+ void pantalla_54(int);
+ void pantalla_55(int);
+ void pantalla_56(int);
+ void refresca_53_antes();
+ void refresca_54_antes();
+ void refresca_49_antes();
+ void refresca_56_antes();
+ void refresca_50();
+ void refresca_57();
+ void habla_igor_sentado(const char *, const char *);
+ void habla_lobo(const char *dicho, const char *filename);
+ void habla_mus(const char *dicho, const char *filename);
+ void pantalla_58(int);
+ void pantalla_59(int);
+ void pantalla_60(int);
+ void pantalla_61(int);
+ void pantalla_pendulo(int);
+ void refresca_pendulo();
+ void refresca_58();
+ void refresca_58_antes();
+ void refresca_59_antes();
+ void refresca_60_antes();
+ void refresca_60();
+ void refresca_61();
+ void animacion_1_6();
+ void animacion_2_6();
+ void animacion_3_6();
+ void animacion_4_6();
+ void animacion_5_6();
+ void animacion_6_6();
+ void animacion_7_6();
+ void animacion_9_6();
+ void animacion_10_6();
+ void animacion_11_6();
+ void animacion_12_6();
+ void animacion_13_6();
+ void animacion_14_6();
+ void animacion_15_6();
+ void animacion_18_6();
+ void animacion_19_6();
+ void activa_pendulo();
+ void habla_pen(const char *, const char *);
+ void habla_pen2(const char *, const char *);
+ void habla_taber2(const char *, const char *);
+ void habla_bj_cama(const char *dicho, const char * filename);
+ void habla_htel(const char *dicho, const char *filename);
private:
diff --git a/engines/engine.cpp b/engines/engine.cpp
index f2b7198510..9750812f5e 100644
--- a/engines/engine.cpp
+++ b/engines/engine.cpp
@@ -43,7 +43,7 @@
extern bool isSmartphone(void);
#endif
-// FIXME - BIG HACK for MidiEmu & error()
+// FIXME: HACK for MidiEmu & error()
Engine *g_engine = 0;
diff --git a/engines/gob/cdrom.cpp b/engines/gob/cdrom.cpp
index 2ee8595ad3..1c26199bc1 100644
--- a/engines/gob/cdrom.cpp
+++ b/engines/gob/cdrom.cpp
@@ -151,40 +151,27 @@ void CDROM::playMultMusic() {
}
}
-void CDROM::startTrack(const char *trackname) {
- byte *curPtr, *matchPtr;
-
+void CDROM::startTrack(const char *trackName) {
if (!_LICbuffer)
return;
- debugC(1, kDebugMusic, "CDROM::startTrack(%s)", trackname);
-
- matchPtr = 0;
- curPtr = _LICbuffer;
-
- for (int i = 0; i < _numTracks; i++) {
- if (!scumm_stricmp((char *)curPtr, trackname)) {
- matchPtr = curPtr;
- break;
- }
- curPtr += 22;
- }
+ debugC(1, kDebugMusic, "CDROM::startTrack(%s)", trackName);
+ byte *matchPtr = getTrackBuffer(trackName);
if (!matchPtr) {
- warning("Track \"%s\" not found", trackname);
+ warning("Track \"%s\" not found", trackName);
return;
}
- strncpy0(_curTrack, trackname, 15);
+ strncpy0(_curTrack, trackName, 15);
stopPlaying();
+ _curTrackBuffer = matchPtr;
- while (getTrackPos() != -1);
-
- uint32 start, end;
+ while (getTrackPos() >= 0);
- start = READ_LE_UINT32(matchPtr + 12);
- end = READ_LE_UINT32(matchPtr + 16);
+ uint32 start = READ_LE_UINT32(matchPtr + 12);
+ uint32 end = READ_LE_UINT32(matchPtr + 16);
play(start, end);
@@ -205,12 +192,27 @@ void CDROM::play(uint32 from, uint32 to) {
_cdPlaying = true;
}
-int32 CDROM::getTrackPos() {
- uint32 curPos = _vm->_util->getTimeKey() - _startTime;
+int32 CDROM::getTrackPos(const char *keyTrack) {
+ byte *keyBuffer = getTrackBuffer(keyTrack);
+ uint32 curPos = (_vm->_util->getTimeKey() - _startTime) * 3 / 40;
+
+ if (_cdPlaying && (_vm->_util->getTimeKey() < _trackStop)) {
+ if (keyBuffer && _curTrackBuffer && (keyBuffer != _curTrackBuffer)) {
+ uint32 kStart = READ_LE_UINT32(keyBuffer + 12);
+ uint32 kEnd = READ_LE_UINT32(keyBuffer + 16);
+ uint32 cStart = READ_LE_UINT32(_curTrackBuffer + 12);
+ uint32 cEnd = READ_LE_UINT32(_curTrackBuffer + 16);
+
+ if ((kStart >= cStart) && (kEnd <= cEnd)) {
+ if ((kStart - cStart) > curPos)
+ return -2;
+ if ((kEnd - cStart) < curPos)
+ return -1;
+ }
+ }
- if (_cdPlaying && (_vm->_util->getTimeKey() < _trackStop))
- return curPos * 3 / 40;
- else
+ return curPos;
+ } else
return -1;
}
@@ -227,6 +229,7 @@ void CDROM::stopPlaying() {
void CDROM::stop() {
debugC(1, kDebugMusic, "CDROM::stop()");
+ _curTrackBuffer = 0;
AudioCD.stop();
_cdPlaying = false;
}
@@ -245,4 +248,22 @@ void CDROM::testCD(int trySubst, const char *label) {
// CD secor reading
}
+byte *CDROM::getTrackBuffer(const char *trackName) {
+ if (!_LICbuffer || !trackName)
+ return 0;
+
+ byte *matchPtr = 0;
+ byte *curPtr = _LICbuffer;
+
+ for (int i = 0; i < _numTracks; i++) {
+ if (!scumm_stricmp((char *) curPtr, trackName)) {
+ matchPtr = curPtr;
+ break;
+ }
+ curPtr += 22;
+ }
+
+ return matchPtr;
+}
+
} // End of namespace Gob
diff --git a/engines/gob/cdrom.h b/engines/gob/cdrom.h
index e977adcd6d..f847addaeb 100644
--- a/engines/gob/cdrom.h
+++ b/engines/gob/cdrom.h
@@ -35,11 +35,11 @@ public:
void readLIC(const char *fname);
void freeLICbuffer();
- void startTrack(const char *s);
+ void startTrack(const char *trackName);
void playBgMusic();
void playMultMusic();
void play(uint32 from, uint32 to);
- int32 getTrackPos();
+ int32 getTrackPos(const char *keyTrack = 0);
const char *getCurTrack();
void stopPlaying();
void stop();
@@ -49,11 +49,14 @@ public:
protected:
byte *_LICbuffer;
+ byte *_curTrackBuffer;
char _curTrack[16];
uint16 _numTracks;
uint32 _trackStop;
uint32 _startTime;
GobEngine *_vm;
+
+ byte *getTrackBuffer(const char *trackName);
};
} // End of namespace Gob
diff --git a/engines/gob/coktelvideo.cpp b/engines/gob/coktelvideo.cpp
index 16df54d85f..b3056a5ea3 100644
--- a/engines/gob/coktelvideo.cpp
+++ b/engines/gob/coktelvideo.cpp
@@ -885,9 +885,9 @@ bool Vmd::load(Common::SeekableReadStream &stream) {
_vidBufferSize = _stream->readUint32LE();
if (_hasVideo) {
- if (_frameDataSize == 0)
+ if ((_frameDataSize == 0) || (_frameDataSize > 1048576))
_frameDataSize = _width * _height + 500;
- if (_vidBufferSize == 0)
+ if ((_vidBufferSize == 0) || (_vidBufferSize > 1048576))
_vidBufferSize = _frameDataSize;
_frameData = new byte[_frameDataSize];
@@ -949,7 +949,7 @@ bool Vmd::load(Common::SeekableReadStream &stream) {
if (_frames[i].parts[j].type == kPartTypeAudio) {
_frames[i].parts[j].flags = _stream->readByte();
- _stream->skip(9); // Unknow
+ _stream->skip(9); // Unknown
} else if (_frames[i].parts[j].type == kPartTypeVideo) {
@@ -1068,9 +1068,13 @@ CoktelVideo::State Vmd::processFrame(uint16 frame) {
// Next sound slice data
if (part.flags == 1) {
- if (_soundEnabled)
+ if (_soundEnabled) {
filledSoundSlice(part.size);
- else
+
+ if (_soundStage == 1)
+ startSound = true;
+
+ } else
_stream->skip(part.size);
// Initial sound data (all slices)
@@ -1089,11 +1093,17 @@ CoktelVideo::State Vmd::processFrame(uint16 frame) {
// Empty sound slice
} else if (part.flags == 3) {
- if (_soundEnabled && (part.size > 0))
- emptySoundSlice(part.size);
- else
- _stream->skip(part.size);
+ if (_soundEnabled) {
+ emptySoundSlice(_soundSliceSize * _soundBytesPerSample);
+ if (_soundStage == 1)
+ startSound = true;
+ }
+
+ _stream->skip(part.size);
+ } else {
+ warning("Unknown sound part type %d", part.flags);
+ _stream->skip(part.size);
}
} else if (part.type == kPartTypeVideo) {
@@ -1252,23 +1262,18 @@ void Vmd::filledSoundSlice(uint32 size) {
}
void Vmd::filledSoundSlices(uint32 size, uint32 mask) {
- if (_soundBytesPerSample == 1) {
- soundSlice8bit(size);
- return;
- }
-
- for (int i = 0; i < (_soundSlicesCount - 1); i++) {
+ int n = MIN<int>(_soundSlicesCount - 1, 31);
+ for (int i = 0; i < n; i++) {
if (mask & 1)
- emptySoundSlice(_soundSliceSize * 2);
- else {
- int16 init = _stream->readSint16LE();
- soundSlice16bit(_soundSliceSize, init);
- }
+ emptySoundSlice(_soundSliceSize * _soundBytesPerSample);
+ else
+ filledSoundSlice(_soundSliceSize);
mask >>= 1;
}
-
+ if (_soundSlicesCount > 32)
+ filledSoundSlice((_soundSlicesCount - 32) * _soundSliceSize);
}
void Vmd::deDPCM(byte *soundBuf, byte *dataBuf, int16 &init, uint32 n) {
diff --git a/engines/gob/dataio.cpp b/engines/gob/dataio.cpp
index 361627caf4..7fd461b93c 100644
--- a/engines/gob/dataio.cpp
+++ b/engines/gob/dataio.cpp
@@ -273,28 +273,27 @@ int32 DataIO::readChunk(int16 handle, byte *buf, uint16 size) {
file = (handle - 50) / 10;
slot = (handle - 50) % 10;
- if (!_isCurrentSlot[file * MAX_SLOT_COUNT + slot]) {
+ int index = file * MAX_SLOT_COUNT + slot;
+
+ _chunkPos[index] = CLIP<int32>(_chunkPos[index], 0, _chunkSize[index]);
+
+ if (!_isCurrentSlot[index]) {
for (i = 0; i < MAX_SLOT_COUNT; i++)
_isCurrentSlot[file * MAX_SLOT_COUNT + i] = false;
- offset = _chunkOffset[file * MAX_SLOT_COUNT + slot] +
- _chunkPos[file * MAX_SLOT_COUNT + slot];
+ offset = _chunkOffset[index] + _chunkPos[index];
- debugC(7, kDebugFileIO, "seek: %d, %d",
- _chunkOffset[file * MAX_SLOT_COUNT + slot],
- _chunkPos[file * MAX_SLOT_COUNT + slot]);
+ debugC(7, kDebugFileIO, "seek: %d, %d", _chunkOffset[index], _chunkPos[index]);
file_getHandle(_dataFileHandles[file])->seek(offset, SEEK_SET);
}
- _isCurrentSlot[file * MAX_SLOT_COUNT + slot] = true;
- if ((_chunkPos[file * MAX_SLOT_COUNT + slot] + size) >
- (_chunkSize[file * MAX_SLOT_COUNT + slot]))
- size = _chunkSize[file * MAX_SLOT_COUNT + slot] -
- _chunkPos[file * MAX_SLOT_COUNT + slot];
+ _isCurrentSlot[index] = true;
+ if ((_chunkPos[index] + size) > (_chunkSize[index]))
+ size = _chunkSize[index] - _chunkPos[index];
file_getHandle(_dataFileHandles[file])->read(buf, size);
- _chunkPos[file * MAX_SLOT_COUNT + slot] += size;
+ _chunkPos[index] += size;
return size;
}
@@ -307,13 +306,15 @@ int16 DataIO::seekChunk(int16 handle, int32 pos, int16 from) {
file = (handle - 50) / 10;
slot = (handle - 50) % 10;
- _isCurrentSlot[file * MAX_SLOT_COUNT + slot] = false;
+ int index = file * MAX_SLOT_COUNT + slot;
+
+ _isCurrentSlot[index] = false;
if (from == SEEK_SET)
- _chunkPos[file * MAX_SLOT_COUNT + slot] = pos;
+ _chunkPos[index] = pos;
else
- _chunkPos[file * MAX_SLOT_COUNT + slot] += pos;
+ _chunkPos[index] += pos;
- return _chunkPos[file * MAX_SLOT_COUNT + slot];
+ return _chunkPos[index];
}
uint32 DataIO::getChunkPos(int16 handle) const {
diff --git a/engines/gob/detection.cpp b/engines/gob/detection.cpp
index 7faef57cc1..bfd2a0edfc 100644
--- a/engines/gob/detection.cpp
+++ b/engines/gob/detection.cpp
@@ -955,6 +955,19 @@ static const GOBGameDescription gameDescriptions[] = {
},
{
{
+ "lostintime",
+ "Demo",
+ AD_ENTRY1("demo.stk", "c06f8cc20eb239d4c71f225ce3093edf"),
+ UNK_LANG,
+ kPlatformPC,
+ Common::ADGF_DEMO
+ },
+ kGameTypeLostInTime,
+ kFeaturesAdlib,
+ "demo"
+ },
+ {
+ {
"gob3",
"",
AD_ENTRY1s("intro.stk", "32b0f57f5ae79a9ae97e8011df38af42", 157084),
diff --git a/engines/gob/driver_vga.cpp b/engines/gob/driver_vga.cpp
index 13e6aca4a8..ef1c9c328c 100644
--- a/engines/gob/driver_vga.cpp
+++ b/engines/gob/driver_vga.cpp
@@ -113,18 +113,23 @@ void VGAVideoDriver::drawSprite(SurfaceDesc *source, SurfaceDesc *dest,
byte *srcPos = source->getVidMem() + (top * source->getWidth()) + left;
byte *destPos = dest->getVidMem() + (y * dest->getWidth()) + x;
- while (height--) {
- if (transp) {
+ if (transp) {
+ while (height--) {
for (int16 i = 0; i < width; ++i) {
if (srcPos[i])
destPos[i] = srcPos[i];
- }
- } else
- for (int16 i = 0; i < width; ++i)
- destPos[i] = srcPos[i];
+ }
+
+ srcPos += source->getWidth();
+ destPos += dest->getWidth();
+ }
+ } else {
+ while (height--) {
+ memcpy(destPos, srcPos, width);
- srcPos += source->getWidth();
- destPos += dest->getWidth();
+ srcPos += source->getWidth();
+ destPos += dest->getWidth();
+ }
}
}
diff --git a/engines/gob/game_v1.cpp b/engines/gob/game_v1.cpp
index 9c18ec1151..3f681ddd1f 100644
--- a/engines/gob/game_v1.cpp
+++ b/engines/gob/game_v1.cpp
@@ -345,6 +345,7 @@ int16 Game_v1::checkCollisions(byte handleMouse, int16 deltaTime,
int16 oldIndex;
int16 oldId;
uint32 timeKey;
+ bool firstIteration = true;
if (deltaTime >= -1) {
_lastCollKey = 0;
@@ -357,6 +358,8 @@ int16 Game_v1::checkCollisions(byte handleMouse, int16 deltaTime,
resIndex = 0;
+ timeKey = _vm->_util->getTimeKey();
+
if ((_vm->_draw->_cursorIndex == -1) && (handleMouse != 0) &&
(_lastCollKey == 0)) {
_lastCollKey = checkMousePoint(1, &_lastCollId, &_lastCollAreaIndex);
@@ -374,7 +377,6 @@ int16 Game_v1::checkCollisions(byte handleMouse, int16 deltaTime,
if (handleMouse != 0)
_vm->_draw->animateCursor(-1);
- timeKey = _vm->_util->getTimeKey();
while (1) {
if (_vm->_inter->_terminate) {
if (handleMouse)
@@ -397,7 +399,7 @@ int16 Game_v1::checkCollisions(byte handleMouse, int16 deltaTime,
// and the return value is then discarded.
if (deltaTime < 0) {
uint32 curtime = _vm->_util->getTimeKey();
- if ((deltaTime == -1) || ((curtime + deltaTime) > timeKey)) {
+ if ((deltaTime == -1) || (((curtime + deltaTime) > timeKey) && !firstIteration)) {
if (pResId != 0)
*pResId = 0;
@@ -538,7 +540,10 @@ int16 Game_v1::checkCollisions(byte handleMouse, int16 deltaTime,
if (handleMouse != 0)
_vm->_draw->animateCursor(-1);
- _vm->_util->delay(10);
+ if (deltaTime < -10)
+ _vm->_util->delay(10);
+
+ firstIteration = false;
}
}
@@ -617,7 +622,7 @@ void Game_v1::collisionsBlock(void) {
int16 var_26;
int16 collStackPos;
Collision *collPtr;
- int16 timeKey;
+ uint32 timeKey;
byte *savedIP;
if (_shouldPushColls)
@@ -910,9 +915,9 @@ void Game_v1::collisionsBlock(void) {
_shouldPushColls = 0;
_vm->_global->_inter_execPtr = savedIP;
+
deltaTime = timeVal -
- ((_vm->_util->getTimeKey() - timeKey)
- - _vm->_video->_lastRetraceLength);
+ (_vm->_util->getTimeKey() - timeKey);
if (deltaTime < 2)
deltaTime = 2;
diff --git a/engines/gob/game_v2.cpp b/engines/gob/game_v2.cpp
index 7e87b9e8f8..8a528a96f5 100644
--- a/engines/gob/game_v2.cpp
+++ b/engines/gob/game_v2.cpp
@@ -1259,7 +1259,7 @@ int16 Game_v2::multiEdit(int16 time, int16 index, int16 *pCurPos,
if ((collArea->left > _vm->_global->_inter_mouseX) ||
(collArea->right < _vm->_global->_inter_mouseX) ||
(collArea->top > _vm->_global->_inter_mouseY) ||
- (collArea->bottom < _vm->_global->_inter_mouseY));
+ (collArea->bottom < _vm->_global->_inter_mouseY))
continue;
if ((collArea->id & 0xF000))
diff --git a/engines/gob/gob.cpp b/engines/gob/gob.cpp
index d9385b1b0f..8dee9c9e32 100644
--- a/engines/gob/gob.cpp
+++ b/engines/gob/gob.cpp
@@ -333,7 +333,7 @@ bool GobEngine::initGameParts() {
_mult = new Mult_v2(this);
_draw = new Draw_v2(this);
_game = new Game_v2(this);
- _map = new Map_v2(this);
+ _map = new Map_v4(this);
_goblin = new Goblin_v3(this);
_scenery = new Scenery_v2(this);
_saveLoad = new SaveLoad_v3(this, _targetName.c_str());
@@ -349,8 +349,6 @@ bool GobEngine::initGameParts() {
if (!_noMusic && hasAdlib())
_adlib = new Adlib(this);
- _map->init();
-
if (is640()) {
_video->_surfWidth = _width = 640;
_video->_surfHeight = _video->_splitHeight1 = _height = 480;
diff --git a/engines/gob/init.cpp b/engines/gob/init.cpp
index 4712a19a5d..1c6d7faa3b 100644
--- a/engines/gob/init.cpp
+++ b/engines/gob/init.cpp
@@ -60,14 +60,23 @@ void Init::initGame(const char *totName) {
int16 handle2;
int16 handle;
int16 imdHandle;
- char *infBuf;
+ byte *infBuf;
char *infPtr;
char *infEnd;
- char buffer[20];
+ char buffer[128];
int32 varsCount;
initVideo();
+ // The Lost In Time demo uses different file prefix
+ if (_vm->getGameType() == kGameTypeLostInTime) {
+ handle2 = _vm->_dataIO->openData("demo.stk");
+ if (handle2 >= 0) {
+ _vm->_dataIO->closeData(handle2);
+ _vm->_dataIO->openDataFile("demo.stk");
+ }
+ }
+
handle2 = _vm->_dataIO->openData("intro.stk");
if (handle2 >= 0) {
_vm->_dataIO->closeData(handle2);
@@ -111,10 +120,10 @@ void Init::initGame(const char *totName) {
} else {
_vm->_dataIO->closeData(handle);
- infPtr = (char *) _vm->_dataIO->getData("intro.inf");
- infBuf = infPtr;
+ infBuf = _vm->_dataIO->getData("intro.inf");
+ infPtr = (char *) infBuf;
- infEnd = infBuf + _vm->_dataIO->getDataSize("intro.inf");
+ infEnd = (char *) (infBuf + _vm->_dataIO->getDataSize("intro.inf"));
for (int i = 0; i < 4; i++, infPtr++) {
int j;
diff --git a/engines/gob/init_v3.cpp b/engines/gob/init_v3.cpp
index 6f1af258ca..61e7fb61d0 100644
--- a/engines/gob/init_v3.cpp
+++ b/engines/gob/init_v3.cpp
@@ -18,8 +18,8 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
- * $URL:https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/branches/gsoc2007-fsnode/engines/gob/init_v3.cpp $
- * $Id:init_v3.cpp 26949 2007-05-26 20:23:24Z david_corrales $
+ * $URL$
+ * $Id$
*
*/
diff --git a/engines/gob/inter_v2.cpp b/engines/gob/inter_v2.cpp
index 376aef75d9..b2ca8716be 100644
--- a/engines/gob/inter_v2.cpp
+++ b/engines/gob/inter_v2.cpp
@@ -1105,7 +1105,7 @@ void Inter_v2::o2_getCDTrackPos() {
varPos = _vm->_parse->parseVarIndex();
varName = _vm->_parse->parseVarIndex();
- WRITE_VAR_OFFSET(varPos, _vm->_cdrom->getTrackPos());
+ WRITE_VAR_OFFSET(varPos, _vm->_cdrom->getTrackPos(GET_VARO_STR(varName)));
WRITE_VARO_STR(varName, _vm->_cdrom->getCurTrack());
}
@@ -1561,7 +1561,8 @@ void Inter_v2::o2_openItk() {
evalExpr(0);
strncpy0(fileName, _vm->_global->_inter_resStr, 27);
- strcat(fileName, ".ITK");
+ if (!strchr(fileName, '.'))
+ strcat(fileName, ".ITK");
_vm->_dataIO->openDataFile(fileName, true);
}
diff --git a/engines/gob/map.cpp b/engines/gob/map.cpp
index 5485d66987..d467348039 100644
--- a/engines/gob/map.cpp
+++ b/engines/gob/map.cpp
@@ -34,9 +34,11 @@
namespace Gob {
Map::Map(GobEngine *vm) : _vm(vm) {
+ _widthByte = 0;
_mapWidth = -1;
_mapHeight = -1;
_screenWidth = 0;
+ _screenHeight = 0;
_tilesWidth = 0;
_tilesHeight = 0;
_passWidth = 0;
diff --git a/engines/gob/map.h b/engines/gob/map.h
index 0e0a80aad3..acfe8b675e 100644
--- a/engines/gob/map.h
+++ b/engines/gob/map.h
@@ -63,9 +63,11 @@ public:
#include "common/pack-end.h" // END STRUCT PACKING
+ byte _widthByte;
int16 _mapWidth;
int16 _mapHeight;
int16 _screenWidth;
+ int16 _screenHeight;
int16 _tilesWidth;
int16 _tilesHeight;
int16 _passWidth;
@@ -107,7 +109,6 @@ public:
virtual void findNearestToDest(Mult::Mult_Object *obj) = 0;
virtual void optimizePoints(Mult::Mult_Object *obj, int16 x, int16 y) = 0;
- virtual void init(void) = 0;
Map(GobEngine *vm);
virtual ~Map();
@@ -127,18 +128,24 @@ public:
virtual void optimizePoints(Mult::Mult_Object *obj, int16 x, int16 y);
virtual int8 getPass(int x, int y, int heightOff = -1) {
+ if (!_passMap)
+ return 0;
+
return _passMap[y * _mapWidth + x];
}
virtual void setPass(int x, int y, int8 pass, int heightOff = -1) {
+ if (!_passMap)
+ return;
+
_passMap[y * _mapWidth + x] = pass;
}
- virtual void init(void);
Map_v1(GobEngine *vm);
virtual ~Map_v1();
protected:
+ void init(void);
void loadSounds(Common::SeekableReadStream &data);
void loadGoblins(Common::SeekableReadStream &data, uint32 gobsPos);
void loadObjects(Common::SeekableReadStream &data, uint32 objsPos);
@@ -153,18 +160,23 @@ public:
virtual void optimizePoints(Mult::Mult_Object *obj, int16 x, int16 y);
virtual int8 getPass(int x, int y, int heightOff = -1) {
+ if (!_passMap)
+ return 0;
+
if (heightOff == -1)
heightOff = _passWidth;
return _passMap[y * heightOff + x];
}
virtual void setPass(int x, int y, int8 pass, int heightOff = -1) {
+ if (!_passMap)
+ return;
+
if (heightOff == -1)
heightOff = _passWidth;
_passMap[y * heightOff + x] = pass;
}
- virtual void init(void);
Map_v2(GobEngine *vm);
virtual ~Map_v2();
@@ -172,6 +184,14 @@ protected:
void loadGoblinStates(Common::SeekableReadStream &data, int index);
};
+class Map_v4 : public Map_v2 {
+public:
+ virtual void loadMapObjects(const char *avjFile);
+
+ Map_v4(GobEngine *vm);
+ virtual ~Map_v4();
+};
+
} // End of namespace Gob
#endif // GOB_MAP_H
diff --git a/engines/gob/map_v1.cpp b/engines/gob/map_v1.cpp
index c5a2622e44..7134527592 100644
--- a/engines/gob/map_v1.cpp
+++ b/engines/gob/map_v1.cpp
@@ -42,6 +42,9 @@ Map_v1::~Map_v1() {
}
void Map_v1::init(void) {
+ if (_passMap || _itemsMap)
+ return;
+
_mapWidth = 26;
_mapHeight = 28;
@@ -84,6 +87,8 @@ void Map_v1::loadMapObjects(const char *avjFile) {
}
Common::MemoryReadStream mapData(dataBuf, 4294967295U);
+ init();
+
if (_loadFromAvo) {
mapData.read(_passMap, _mapHeight * _mapWidth);
diff --git a/engines/gob/map_v2.cpp b/engines/gob/map_v2.cpp
index e1ed11c607..5133ac1286 100644
--- a/engines/gob/map_v2.cpp
+++ b/engines/gob/map_v2.cpp
@@ -38,15 +38,13 @@
namespace Gob {
Map_v2::Map_v2(GobEngine *vm) : Map_v1(vm) {
+ _screenHeight = 200;
}
Map_v2::~Map_v2() {
_passMap = 0;
}
-void Map_v2::init(void) {
-}
-
void Map_v2::loadMapObjects(const char *avjFile) {
uint8 wayPointsCount;
int16 var;
@@ -86,7 +84,7 @@ void Map_v2::loadMapObjects(const char *avjFile) {
_tilesHeight &= 0xFF;
_mapWidth = _screenWidth / _tilesWidth;
- _mapHeight = 200 / _tilesHeight;
+ _mapHeight = _screenHeight / _tilesHeight;
passPos = mapData.pos();
mapData.skip(_mapWidth * _mapHeight);
@@ -96,9 +94,7 @@ void Map_v2::loadMapObjects(const char *avjFile) {
else
wayPointsCount = _wayPointsCount == 0 ? 1 : _wayPointsCount;
- if (_wayPoints)
- delete[] _wayPoints;
-
+ delete[] _wayPoints;
_wayPoints = new Point[wayPointsCount];
for (int i = 0; i < _wayPointsCount; i++) {
_wayPoints[i].x = mapData.readSByte();
@@ -113,7 +109,7 @@ void Map_v2::loadMapObjects(const char *avjFile) {
byte *sizes;
_passMap = (int8 *) variables;
- mapHeight = 200 / _tilesHeight;
+ mapHeight = _screenHeight / _tilesHeight;
mapWidth = _screenWidth / _tilesWidth;
sizes = _vm->_global->_inter_variablesSizes +
(((byte *) _passMap) - _vm->_global->_inter_variables);
diff --git a/engines/gob/map_v4.cpp b/engines/gob/map_v4.cpp
new file mode 100644
index 0000000000..fb398ecbaf
--- /dev/null
+++ b/engines/gob/map_v4.cpp
@@ -0,0 +1,158 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#include "common/stdafx.h"
+#include "common/stream.h"
+
+#include "gob/gob.h"
+#include "gob/map.h"
+#include "gob/global.h"
+#include "gob/goblin.h"
+#include "gob/inter.h"
+#include "gob/game.h"
+#include "gob/parse.h"
+#include "gob/mult.h"
+
+namespace Gob {
+
+Map_v4::Map_v4(GobEngine *vm) : Map_v2(vm) {
+}
+
+Map_v4::~Map_v4() {
+}
+
+void Map_v4::loadMapObjects(const char *avjFile) {
+ uint8 wayPointsCount;
+ int16 var;
+ int16 id;
+ int16 mapWidth, mapHeight;
+ int16 tmp;
+ byte *variables;
+ byte *extData;
+ uint32 tmpPos;
+ uint32 passPos;
+
+ var = _vm->_parse->parseVarIndex();
+ variables = _vm->_global->_inter_variables + var;
+
+ id = _vm->_inter->load16();
+
+ if (((uint16) id) >= 65520) {
+ warning("Woodruff Stub: loadMapObjects ID >= 65520");
+ return;
+ } else if (id == -1) {
+ _passMap = (int8 *)(_vm->_global->_inter_variables + var);
+ return;
+ }
+
+ extData = _vm->_game->loadExtData(id, 0, 0);
+ Common::MemoryReadStream mapData(extData, 4294967295U);
+
+ _widthByte = mapData.readByte();
+ if (_widthByte == 4) {
+ _screenWidth = 640;
+ _screenHeight = 400;
+ } else if (_widthByte == 3) {
+ _screenWidth = 640;
+ _screenHeight = 200;
+ } else {
+ _screenWidth = 320;
+ _screenHeight = 200;
+ }
+
+ _wayPointsCount = mapData.readByte();
+ _tilesWidth = mapData.readSint16LE();
+ _tilesHeight = mapData.readSint16LE();
+
+ _bigTiles = !(_tilesHeight & 0xFF00);
+ _tilesHeight &= 0xFF;
+
+ if (_widthByte == 4) {
+ _screenWidth = mapData.readSint16LE();
+ _screenHeight = mapData.readSint16LE();
+ }
+
+ _mapWidth = _screenWidth / _tilesWidth;
+ _mapHeight = _screenHeight / _tilesHeight;
+
+ passPos = mapData.pos();
+ mapData.skip(_mapWidth * _mapHeight);
+
+ if (*extData == 1)
+ wayPointsCount = _wayPointsCount = 40;
+ else
+ wayPointsCount = _wayPointsCount == 0 ? 1 : _wayPointsCount;
+
+ delete[] _wayPoints;
+ _wayPoints = new Point[wayPointsCount];
+ for (int i = 0; i < _wayPointsCount; i++) {
+ _wayPoints[i].x = mapData.readSByte();
+ _wayPoints[i].y = mapData.readSByte();
+ _wayPoints[i].notWalkable = mapData.readSByte();
+ }
+
+ if (_widthByte == 4)
+ _mapWidth = (int16) READ_VARO_UINT16(68);
+
+ _passWidth = _mapWidth;
+
+ // In the original asm, this writes byte-wise into the variables-array
+ tmpPos = mapData.pos();
+ mapData.seek(passPos);
+ if (variables != _vm->_global->_inter_variables) {
+ byte *sizes;
+
+ _passMap = (int8 *) variables;
+ mapHeight = _screenHeight / _tilesHeight;
+ mapWidth = _screenWidth / _tilesWidth;
+ sizes = _vm->_global->_inter_variablesSizes +
+ (((byte *) _passMap) - _vm->_global->_inter_variables);
+ for (int i = 0; i < mapHeight; i++) {
+ for (int j = 0; j < mapWidth; j++)
+ setPass(j, i, mapData.readSByte());
+ memset(sizes + i * _passWidth, 0, mapWidth);
+ }
+ }
+ mapData.seek(tmpPos);
+
+ tmp = mapData.readSint16LE();
+ mapData.skip(tmp * 14);
+ tmp = mapData.readSint16LE();
+ mapData.skip(tmp * 14 + 28);
+ tmp = mapData.readSint16LE();
+ mapData.skip(tmp * 14);
+
+ _vm->_goblin->_gobsCount = tmp;
+ for (int i = 0; i < _vm->_goblin->_gobsCount; i++)
+ loadGoblinStates(mapData, i);
+
+ _vm->_goblin->_soundSlotsCount = _vm->_inter->load16();
+ for (int i = 0; i < _vm->_goblin->_soundSlotsCount; i++)
+ _vm->_goblin->_soundSlots[i] = _vm->_inter->loadSound(1);
+
+ delete[] extData;
+}
+
+} // End of namespace Gob
diff --git a/engines/gob/module.mk b/engines/gob/module.mk
index 7571853f27..b51de90656 100644
--- a/engines/gob/module.mk
+++ b/engines/gob/module.mk
@@ -33,6 +33,7 @@ MODULE_OBJS := \
map.o \
map_v1.o \
map_v2.o \
+ map_v4.o \
mult.o \
mult_v1.o \
mult_v2.o \
diff --git a/engines/gob/mult_v2.cpp b/engines/gob/mult_v2.cpp
index cced4aac63..ddce90df0c 100644
--- a/engines/gob/mult_v2.cpp
+++ b/engines/gob/mult_v2.cpp
@@ -259,8 +259,11 @@ void Mult_v2::loadImds(Common::SeekableReadStream &data) {
return;
size = data.readSint16LE();
- _multData->somepointer10 = new char[size * 20];
- data.read(_multData->somepointer10, size * 20);
+ if (size > 0) {
+ _multData->somepointer10 = new char[size * 20];
+ data.read(_multData->somepointer10, size * 20);
+ }
+
size = _vm->_inter->load16();
if (size <= 0)
return;
@@ -474,12 +477,11 @@ void Mult_v2::multSub(uint16 multIndex) {
}
if (_multData->animDirection == -1) {
- for (int i = 0; i < _multData->imdKeysCount[i]; i++) {
- if (_multData->imdKeys[index][i].frame > startFrame)
- break;
+ int i = 0;
+ while (_multData->imdKeys[index][i].frame <= startFrame)
+ i++;
- _multData->imdIndices[index] = i - 1;
- }
+ _multData->imdIndices[index] = i - 1;
}
firstFrame = (_multData->animDirection == 1) ? startFrame : stopFrame;
@@ -1091,15 +1093,11 @@ void Mult_v2::advanceObjects(int16 index) {
for (int i = 0; i < 4; i++) {
int obj = _multData->animObjs[index][i];
- if (_multData->animObjs[index][i] != -1) {
+ if ((obj != -1) && (obj != 1024)) {
int keyIndex = _multData->animKeysIndices[index][i];
int count = _multData->animKeysCount[i];
for (int j = keyIndex; j < count; j++) {
-
- if ((obj == -1) || (obj == 1024))
- continue;
-
Mult_AnimKey &key = _multData->animKeys[i][j];
Mult_Object &animObj = _objects[obj];
Mult_AnimData &animData = *(animObj.pAnimData);
@@ -1161,7 +1159,7 @@ void Mult_v2::advanceObjects(int16 index) {
_multData->imdIndices[1] = -1;
_multData->imdIndices[2] = -1;
_multData->imdIndices[3] = -1;
- if ((_multData->animDirection == 1) || (key2.imdFile == 1))
+ if ((_multData->animDirection == 1) || (key2.imdFile == -1))
_multData->imdIndices[i] = j;
else if (_multData->animKeysStopFrames[index] == frame)
_multData->imdIndices[i] = -1;
@@ -1187,7 +1185,8 @@ void Mult_v2::advanceObjects(int16 index) {
imdFile = _multData->imdFiles + fileN * 14;
dir = _multData->animDirection;
startFrame = frame - key.frame;
- if ((dir != 1) && (--startFrame > 0))
+
+ if ((dir != 1) && (--startFrame < 0))
startFrame = 0;
hasImds = true;
diff --git a/engines/gob/saveload.cpp b/engines/gob/saveload.cpp
index f4cb7bcf7a..ea22ede7b6 100644
--- a/engines/gob/saveload.cpp
+++ b/engines/gob/saveload.cpp
@@ -62,9 +62,11 @@ SaveLoad::SaveLoad(GobEngine *vm, const char *targetName) : _vm(vm) {
}
SaveLoad::~SaveLoad() {
- for (int i = 0; i < _stagesCount; i++)
- delete[] _buffer[i];
- delete[] _buffer;
+ if (_buffer) {
+ for (int i = 0; i < _stagesCount; i++)
+ delete[] _buffer[i];
+ delete[] _buffer;
+ }
delete _tempSprite;
diff --git a/engines/gob/saveload.h b/engines/gob/saveload.h
index d7e45246ad..84a6a643e9 100644
--- a/engines/gob/saveload.h
+++ b/engines/gob/saveload.h
@@ -130,6 +130,8 @@ protected:
virtual bool saveGame(int16 dataVar, int32 size, int32 offset);
virtual bool saveNotes(int16 dataVar, int32 size, int32 offset);
virtual bool saveScreenshot(int16 dataVar, int32 size, int32 offset);
+
+ void initBuffer();
};
class SaveLoad_v3 : public SaveLoad_v2 {
@@ -160,6 +162,7 @@ protected:
virtual bool saveScreenshot(int16 dataVar, int32 size, int32 offset);
bool saveGame(int32 screenshotSize);
+ void initBuffer();
};
} // End of namespace Gob
diff --git a/engines/gob/saveload_v2.cpp b/engines/gob/saveload_v2.cpp
index 13f23cccb6..b8d8d44557 100644
--- a/engines/gob/saveload_v2.cpp
+++ b/engines/gob/saveload_v2.cpp
@@ -38,12 +38,6 @@ SaveLoad_v2::SaveLoad_v2(GobEngine *vm, const char *targetName) :
SaveLoad(vm, targetName) {
_stagesCount = 1;
-
- _buffer = new byte*[_stagesCount];
-
- assert(_buffer);
-
- _buffer[0] = 0;
}
SaveType SaveLoad_v2::getSaveType(const char *fileName) {
@@ -190,6 +184,8 @@ bool SaveLoad_v2::loadScreenshot(int16 dataVar, int32 size, int32 offset) {
bool SaveLoad_v2::saveGame(int16 dataVar, int32 size, int32 offset) {
int32 varSize = READ_LE_UINT32(_vm->_game->_totFileData + 0x2C) * 4;
+ initBuffer();
+
if (size == 0) {
dataVar = 0;
size = varSize;
@@ -289,4 +285,13 @@ bool SaveLoad_v2::saveScreenshot(int16 dataVar, int32 size, int32 offset) {
return false;
}
+void SaveLoad_v2::initBuffer() {
+ if (_buffer)
+ return;
+
+ _buffer = new byte*[_stagesCount];
+ assert(_buffer);
+ _buffer[0] = 0;
+}
+
} // End of namespace Gob
diff --git a/engines/gob/saveload_v3.cpp b/engines/gob/saveload_v3.cpp
index d0f791d8df..f8f69342fe 100644
--- a/engines/gob/saveload_v3.cpp
+++ b/engines/gob/saveload_v3.cpp
@@ -45,19 +45,6 @@ SaveLoad_v3::SaveLoad_v3(GobEngine *vm, const char *targetName,
_saveSlot = -1;
_stagesCount = 3;
- _buffer = new byte*[_stagesCount];
-
- assert(_buffer);
-
- _buffer[0] = new byte[1000];
- _buffer[1] = new byte[1200];
- _buffer[2] = 0;
-
- assert(_buffer[0] && _buffer[1]);
-
- memset(_buffer[0], 0, 1000);
- memset(_buffer[1], 0, 1200);
-
_useScreenshots = false;
_firstSizeGame = true;
}
@@ -146,6 +133,8 @@ bool SaveLoad_v3::loadGame(int16 dataVar, int32 size, int32 offset) {
int slot = (offset - 1700) / varSize;
int slotR = (offset - 1700) % varSize;
+ initBuffer();
+
if ((size > 0) && (offset < 500) && ((size + offset) <= 500)) {
memcpy(_vm->_global->_inter_variables + dataVar,
@@ -279,6 +268,8 @@ bool SaveLoad_v3::saveGame(int16 dataVar, int32 size, int32 offset) {
int slot = (offset - 1700) / varSize;
int slotR = (offset - 1700) % varSize;
+ initBuffer();
+
if ((size > 0) && (offset < 500) && ((size + offset) <= 500)) {
memcpy(_buffer[0] + offset,
@@ -360,6 +351,8 @@ bool SaveLoad_v3::saveGame(int32 screenshotSize) {
_saveSlot = -1;
+ initBuffer();
+
if ((slot < 0) || (slot > 29)) {
warning("Can't save to slot %d: Out of range", slot);
delete[] _buffer[2];
@@ -433,4 +426,22 @@ bool SaveLoad_v3::saveGame(int32 screenshotSize) {
return true;
}
+void SaveLoad_v3::initBuffer() {
+ if (_buffer)
+ return;
+
+ _buffer = new byte*[_stagesCount];
+
+ assert(_buffer);
+
+ _buffer[0] = new byte[1000];
+ _buffer[1] = new byte[1200];
+ _buffer[2] = 0;
+
+ assert(_buffer[0] && _buffer[1]);
+
+ memset(_buffer[0], 0, 1000);
+ memset(_buffer[1], 0, 1200);
+}
+
} // End of namespace Gob
diff --git a/engines/gob/video.cpp b/engines/gob/video.cpp
index 0dc15a8657..ffedd6d1f6 100644
--- a/engines/gob/video.cpp
+++ b/engines/gob/video.cpp
@@ -94,7 +94,6 @@ Video::Video(GobEngine *vm) : _vm(vm) {
_splitHeight1 = 200;
_splitHeight2 = 0;
_splitStart = 0;
- _lastRetraceLength = 0;
_curSparse = 0;
_lastSparse = 0xFFFFFFFF;
@@ -162,8 +161,6 @@ SurfaceDesc *Video::initSurfDesc(int16 vidMode, int16 width, int16 height,
}
void Video::retrace(bool mouse) {
- uint32 time = _vm->_util->getTimeKey();
-
if (mouse)
CursorMan.showMouse((_vm->_draw->_showCursor & 2) != 0);
if (_vm->_global->_primarySurfDesc) {
@@ -176,13 +173,12 @@ void Video::retrace(bool mouse) {
_vm->_height - _splitHeight2, _vm->_width, _splitHeight2);
g_system->updateScreen();
}
-
- _lastRetraceLength = _vm->_util->getTimeKey() - time;
}
void Video::waitRetrace(bool mouse) {
+ uint32 time = _vm->_util->getTimeKey();
retrace(mouse);
- _vm->_util->delay(MAX(1, 10 - (int) _lastRetraceLength));
+ _vm->_util->delay(MAX(1, 10 - (int)(_vm->_util->getTimeKey() - time)));
}
void Video::sparseRetrace(int max) {
diff --git a/engines/gob/video.h b/engines/gob/video.h
index dc23bda81e..51d02bd219 100644
--- a/engines/gob/video.h
+++ b/engines/gob/video.h
@@ -104,7 +104,6 @@ public:
int16 _splitHeight1;
int16 _splitHeight2;
int16 _splitStart;
- uint32 _lastRetraceLength;
void freeDriver();
void initPrimary(int16 mode);
diff --git a/engines/gob/videoplayer.cpp b/engines/gob/videoplayer.cpp
index e72354a169..5d31c31b7b 100644
--- a/engines/gob/videoplayer.cpp
+++ b/engines/gob/videoplayer.cpp
@@ -53,7 +53,13 @@ bool VideoPlayer::openVideo(const char *video, int16 x, int16 y, int16 flags, Ty
strncpy0(fileName, video, 250);
- char *extStart = strchr(fileName, '.');
+ char *extStart = strrchr(fileName, '.');
+ // There's no empty extension
+ if (extStart == (fileName + strlen(fileName) - 1)) {
+ *extStart = 0;
+ extStart = 0;
+ }
+
if (extStart) {
// The requested file already has an extension. Verifying.
@@ -132,7 +138,7 @@ bool VideoPlayer::openVideo(const char *video, int16 x, int16 y, int16 flags, Ty
return false;
}
- _video->setXY(x, y);
+ strcpy(_curFile, fileName);
if (!(flags & kFlagNoVideo)) {
_backSurf = ((flags & kFlagFrontSurface) == 0);
@@ -147,6 +153,7 @@ bool VideoPlayer::openVideo(const char *video, int16 x, int16 y, int16 flags, Ty
if (!_video)
return false;
+ _video->setXY(x, y);
WRITE_VAR(7, _video->getFramesCount());
return true;
@@ -170,8 +177,12 @@ void VideoPlayer::play(int16 startFrame, int16 lastFrame, int16 breakKey,
endFrame = lastFrame;
palCmd &= 0x3F;
- if (_video->getCurrentFrame() != startFrame)
- _video->seekFrame(startFrame);
+ if (_video->getCurrentFrame() != startFrame) {
+ if (_video->getFeatures() & CoktelVideo::kFeaturesSound)
+ startFrame = _video->getCurrentFrame();
+ else
+ _video->seekFrame(startFrame);
+ }
_vm->_draw->_showCursor = 0;
_vm->_util->setFrameRate(12);
@@ -328,6 +339,7 @@ void VideoPlayer::closeVideo() {
_video = 0;
_stream = 0;
+ *_curFile = 0;
}
} // End of namespace Gob
diff --git a/engines/kyra/detection.cpp b/engines/kyra/detection.cpp
index 02b505b177..58622b3514 100644
--- a/engines/kyra/detection.cpp
+++ b/engines/kyra/detection.cpp
@@ -18,8 +18,8 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
- * $URL:https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/branches/gsoc2007-fsnode/engines/kyra/detection.cpp $
- * $Id:detection.cpp 26949 2007-05-26 20:23:24Z david_corrales $
+ * $URL$
+ * $Id$
*/
#include "kyra/kyra.h"
@@ -55,37 +55,315 @@ namespace {
#define KYRA3_CD_FLAGS FLAGS(false, false, true, false, Kyra::GI_KYRA3)
const KYRAGameDescription adGameDescs[] = {
- { { "kyra1", 0, AD_ENTRY1("GEMCUT.EMC", "3c244298395520bb62b5edfe41688879"), Common::EN_ANY, Common::kPlatformPC, Common::ADGF_NO_FLAGS }, KYRA1_FLOPPY_FLAGS },
- { { "kyra1", 0, AD_ENTRY1("GEMCUT.EMC", "796e44863dd22fa635b042df1bf16673"), Common::EN_ANY, Common::kPlatformPC, Common::ADGF_NO_FLAGS }, KYRA1_FLOPPY_FLAGS },
- { { "kyra1", 0, AD_ENTRY1("GEMCUT.EMC", "abf8eb360e79a6c2a837751fbd4d3d24"), Common::FR_FRA, Common::kPlatformPC, Common::ADGF_NO_FLAGS }, KYRA1_FLOPPY_FLAGS },
- { { "kyra1", 0, AD_ENTRY1("GEMCUT.EMC", "6018e1dfeaca7fe83f8d0b00eb0dd049"), Common::DE_DEU, Common::kPlatformPC, Common::ADGF_NO_FLAGS }, KYRA1_FLOPPY_FLAGS },
- { { "kyra1", 0, AD_ENTRY1("GEMCUT.EMC", "f0b276781f47c130f423ec9679fe9ed9"), Common::DE_DEU, Common::kPlatformPC, Common::ADGF_NO_FLAGS }, KYRA1_FLOPPY_FLAGS }, // from Arne.F
- { { "kyra1", 0, AD_ENTRY1("GEMCUT.EMC", "8909b41596913b3f5deaf3c9f1017b01"), Common::ES_ESP, Common::kPlatformPC, Common::ADGF_NO_FLAGS }, KYRA1_FLOPPY_FLAGS }, // from VooD
- { { "kyra1", 0, AD_ENTRY1("GEMCUT.EMC", "747861d2a9c643c59fdab570df5b9093"), Common::ES_ESP, Common::kPlatformPC, Common::ADGF_NO_FLAGS }, KYRA1_FLOPPY_FLAGS }, // floppy 1.8 from clemmy
- { { "kyra1", 0, AD_ENTRY1("GEMCUT.EMC", "ef08c8c237ee1473fd52578303fc36df"), Common::IT_ITA, Common::kPlatformPC, Common::ADGF_NO_FLAGS }, KYRA1_FLOPPY_FLAGS }, // from gourry
+ {
+ {
+ "kyra1",
+ 0,
+ AD_ENTRY1("GEMCUT.EMC", "3c244298395520bb62b5edfe41688879"),
+ Common::EN_ANY,
+ Common::kPlatformPC,
+ Common::ADGF_NO_FLAGS
+ },
+ KYRA1_FLOPPY_FLAGS
+ },
+ {
+ {
+ "kyra1",
+ 0,
+ AD_ENTRY1("GEMCUT.EMC", "796e44863dd22fa635b042df1bf16673"),
+ Common::EN_ANY,
+ Common::kPlatformPC,
+ Common::ADGF_NO_FLAGS
+ },
+ KYRA1_FLOPPY_FLAGS
+ },
+ {
+ {
+ "kyra1",
+ 0,
+ AD_ENTRY1("GEMCUT.EMC", "abf8eb360e79a6c2a837751fbd4d3d24"),
+ Common::FR_FRA,
+ Common::kPlatformPC,
+ Common::ADGF_NO_FLAGS
+ },
+ KYRA1_FLOPPY_FLAGS
+ },
+ {
+ {
+ "kyra1",
+ 0,
+ AD_ENTRY1("GEMCUT.EMC", "6018e1dfeaca7fe83f8d0b00eb0dd049"),
+ Common::DE_DEU,
+ Common::kPlatformPC,
+ Common::ADGF_NO_FLAGS
+ },
+ KYRA1_FLOPPY_FLAGS
+ },
+ { // from Arne.F
+ {
+ "kyra1",
+ 0,
+ AD_ENTRY1("GEMCUT.EMC", "f0b276781f47c130f423ec9679fe9ed9"),
+ Common::DE_DEU,
+ Common::kPlatformPC,
+ Common::ADGF_NO_FLAGS
+ },
+ KYRA1_FLOPPY_FLAGS
+ },
+ { // from VooD
+ {
+ "kyra1",
+ 0,
+ AD_ENTRY1("GEMCUT.EMC", "8909b41596913b3f5deaf3c9f1017b01"),
+ Common::ES_ESP,
+ Common::kPlatformPC,
+ Common::ADGF_NO_FLAGS
+ },
+ KYRA1_FLOPPY_FLAGS
+ },
+ { // floppy 1.8 from clemmy
+ {
+ "kyra1",
+ 0,
+ AD_ENTRY1("GEMCUT.EMC", "747861d2a9c643c59fdab570df5b9093"),
+ Common::ES_ESP,
+ Common::kPlatformPC,
+ Common::ADGF_NO_FLAGS
+ },
+ KYRA1_FLOPPY_FLAGS
+ },
+ { // from gourry
+ {
+ "kyra1",
+ 0,
+ AD_ENTRY1("GEMCUT.EMC", "ef08c8c237ee1473fd52578303fc36df"),
+ Common::IT_ITA,
+ Common::kPlatformPC,
+ Common::ADGF_NO_FLAGS
+ },
+ KYRA1_FLOPPY_FLAGS
+ },
+
+ {
+ {
+ "kyra1",
+ 0,
+ AD_ENTRY1("GEMCUT.PAK", "2bd1da653eaefd691e050e4a9eb68a64"),
+ Common::EN_ANY,
+ Common::kPlatformAmiga,
+ Common::ADGF_NO_FLAGS
+ },
+ KYRA1_AMIGA_FLAGS
+ },
+
+ {
+ {
+ "kyra1",
+ 0,
+ {
+ { "GEMCUT.EMC", 0, "796e44863dd22fa635b042df1bf16673", -1 },
+ { "BEAD.CPS", 0, "3038466f65b7751451844707187aa401", -1 },
+ { NULL, 0, NULL, 0 }
+ },
+ Common::EN_ANY,
+ Common::kPlatformMacintosh,
+ Common::ADGF_NO_FLAGS
+ },
+ KYRA1_FLOPPY_FLAGS
+ },
+
+ { // FM-Towns version
+ {
+ "kyra1",
+ 0,
+ AD_ENTRY1("TWMUSIC.PAK", "e53bca3a3e3fb49107d59463ec387a59"),
+ Common::EN_ANY,
+ Common::kPlatformFMTowns,
+ Common::ADGF_NO_FLAGS
+ },
+ KYRA1_TOWNS_FLAGS
+ },
+ {
+ {
+ "kyra1",
+ 0,
+ AD_ENTRY1("TWMUSIC.PAK", "e53bca3a3e3fb49107d59463ec387a59"),
+ Common::JA_JPN,
+ Common::kPlatformFMTowns,
+ Common::ADGF_NO_FLAGS
+ },
+ KYRA1_TOWNS_SJIS_FLAGS
+ },
+
+ { // PC-9821 version
+ {
+ "kyra1",
+ 0,
+ {
+ { "EMC.PAK", 0, "a046bb0b422061aab8e4c4689400343a", -1 },
+ { "MUSIC98.PAK", 0, "02fc212f799331b769b274e33d87b37f", -1 },
+ { NULL, 0, NULL, 0 }
+ },
+ Common::EN_ANY,
+ Common::kPlatformPC98,
+ Common::ADGF_NO_FLAGS
+ },
+ KYRA1_TOWNS_FLAGS
+ },
+ {
+ {
+ "kyra1",
+ 0,
+ {
+ { "JMC.PAK", 0, "9c5707a2a478e8167e44283246612d2c", -1 },
+ { "MUSIC98.PAK", 0, "02fc212f799331b769b274e33d87b37f", -1 },
+ { NULL, 0, NULL, 0 }
+ },
+ Common::JA_JPN,
+ Common::kPlatformPC98,
+ Common::ADGF_NO_FLAGS
+ },
+ KYRA1_TOWNS_SJIS_FLAGS
+ },
+
+ {
+ {
+ "kyra1",
+ "CD",
+ AD_ENTRY1("GEMCUT.PAK", "fac399fe62f98671e56a005c5e94e39f"),
+ Common::EN_ANY,
+ Common::kPlatformPC,
+ Common::ADGF_NO_FLAGS
+ },
+ KYRA1_CD_FLAGS
+ },
+ {
+ {
+ "kyra1",
+ "CD",
+ AD_ENTRY1("GEMCUT.PAK", "230f54e6afc007ab4117159181a1c722"),
+ Common::DE_DEU,
+ Common::kPlatformPC,
+ Common::ADGF_NO_FLAGS
+ },
+ KYRA1_CD_FLAGS
+ },
+ {
+ {
+ "kyra1",
+ "CD",
+ AD_ENTRY1("GEMCUT.PAK", "b037c41768b652a040360ffa3556fd2a"),
+ Common::FR_FRA,
+ Common::kPlatformPC,
+ Common::ADGF_NO_FLAGS
+ },
+ KYRA1_CD_FLAGS
+ },
+
+ { // italian fan translation see fr#1727941 "KYRA: add Italian CD Version to kyra.dat"
+ {
+ "kyra1",
+ "CD",
+ AD_ENTRY1("GEMCUT.PAK", "d8327fc4b7a72b23c900fa13aef4093a"),
+ Common::IT_ITA,
+ Common::kPlatformPC,
+ Common::ADGF_NO_FLAGS
+ },
+ KYRA1_CD_FLAGS
+ },
+
+ {
+ {
+ "kyra1",
+ "Demo",
+ AD_ENTRY1("DEMO1.WSA", "fb722947d94897512b13b50cc84fd648"),
+ Common::EN_ANY,
+ Common::kPlatformPC,
+ Common::ADGF_DEMO
+ },
+ KYRA1_DEMO_FLAGS
+ },
+
+ { // CD version
+ {
+ "kyra2",
+ 0,
+ AD_ENTRY1("FATE.PAK", "28cbad1c5bf06b2d3825ae57d760d032"),
+ Common::EN_ANY,
+ Common::kPlatformPC,
+ Common::ADGF_NO_FLAGS
+ },
+ KYRA2_CD_FLAGS
+ },
+ { // CD version
+ {
+ "kyra2",
+ 0,
+ AD_ENTRY1("FATE.PAK", "28cbad1c5bf06b2d3825ae57d760d032"),
+ Common::DE_DEU,
+ Common::kPlatformPC,
+ Common::ADGF_NO_FLAGS
+ },
+ KYRA2_CD_FLAGS
+ },
+ { // CD version
+ {
+ "kyra2",
+ 0,
+ AD_ENTRY1("FATE.PAK", "28cbad1c5bf06b2d3825ae57d760d032"),
+ Common::FR_FRA,
+ Common::kPlatformPC,
+ Common::ADGF_NO_FLAGS
+ },
+ KYRA2_CD_FLAGS
+ },
+
+ {
+ {
+ "kyra2",
+ "Demo",
+ AD_ENTRY1("GENERAL.PAK", "35825783e5b60755fd520360079f9c15"),
+ Common::EN_ANY,
+ Common::kPlatformPC,
+ Common::ADGF_DEMO
+ },
+ KYRA2_DEMO_FLAGS
+ },
+
+ {
+ {
+ "kyra3",
+ 0,
+ AD_ENTRY1("ONETIME.PAK", "3833ff312757b8e6147f464cca0a6587"),
+ Common::EN_ANY,
+ Common::kPlatformPC,
+ Common::ADGF_NO_FLAGS
+ },
+ KYRA3_CD_FLAGS
+ },
+ {
+ {
+ "kyra3",
+ 0,
+ AD_ENTRY1("ONETIME.PAK", "3833ff312757b8e6147f464cca0a6587"),
+ Common::DE_DEU,
+ Common::kPlatformPC,
+ Common::ADGF_NO_FLAGS
+ },
+ KYRA3_CD_FLAGS
+ },
+ {
+ {
+ "kyra3",
+ 0,
+ AD_ENTRY1("ONETIME.PAK", "3833ff312757b8e6147f464cca0a6587"),
+ Common::FR_FRA,
+ Common::kPlatformPC,
+ Common::ADGF_NO_FLAGS
+ },
+ KYRA3_CD_FLAGS
+ },
- { { "kyra1", 0, AD_ENTRY1("GEMCUT.PAK", "2bd1da653eaefd691e050e4a9eb68a64"), Common::EN_ANY, Common::kPlatformAmiga, Common::ADGF_NO_FLAGS }, KYRA1_AMIGA_FLAGS },
-
- { { "kyra1", 0, AD_ENTRY1("TWMUSIC.PAK", "e53bca3a3e3fb49107d59463ec387a59"), Common::EN_ANY, Common::kPlatformFMTowns, Common::ADGF_NO_FLAGS }, KYRA1_TOWNS_FLAGS },
- { { "kyra1", 0, AD_ENTRY1("TWMUSIC.PAK", "e53bca3a3e3fb49107d59463ec387a59"), Common::JA_JPN, Common::kPlatformFMTowns, Common::ADGF_NO_FLAGS }, KYRA1_TOWNS_SJIS_FLAGS },
-
- { { "kyra1", "CD", AD_ENTRY1("GEMCUT.PAK", "fac399fe62f98671e56a005c5e94e39f"), Common::EN_ANY, Common::kPlatformPC, Common::ADGF_NO_FLAGS }, KYRA1_CD_FLAGS },
- { { "kyra1", "CD", AD_ENTRY1("GEMCUT.PAK", "230f54e6afc007ab4117159181a1c722"), Common::DE_DEU, Common::kPlatformPC, Common::ADGF_NO_FLAGS }, KYRA1_CD_FLAGS },
- { { "kyra1", "CD", AD_ENTRY1("GEMCUT.PAK", "b037c41768b652a040360ffa3556fd2a"), Common::FR_FRA, Common::kPlatformPC, Common::ADGF_NO_FLAGS }, KYRA1_CD_FLAGS },
-
- { { "kyra1", "CD", AD_ENTRY1("GEMCUT.PAK", "d8327fc4b7a72b23c900fa13aef4093a"), Common::IT_ITA, Common::kPlatformPC, Common::ADGF_NO_FLAGS }, KYRA1_CD_FLAGS }, // italian fan translation see fr#1727941 "KYRA: add Italian CD Version to kyra.dat"
-
- { { "kyra1", "Demo", AD_ENTRY1("DEMO1.WSA", "fb722947d94897512b13b50cc84fd648"), Common::EN_ANY, Common::kPlatformPC, Common::ADGF_DEMO }, KYRA1_DEMO_FLAGS },
-
- { { "kyra2", 0, AD_ENTRY1("FATE.PAK", "28cbad1c5bf06b2d3825ae57d760d032"), Common::EN_ANY, Common::kPlatformPC, Common::ADGF_NO_FLAGS }, KYRA2_CD_FLAGS }, // CD version
- { { "kyra2", 0, AD_ENTRY1("FATE.PAK", "28cbad1c5bf06b2d3825ae57d760d032"), Common::DE_DEU, Common::kPlatformPC, Common::ADGF_NO_FLAGS }, KYRA2_CD_FLAGS }, // CD version
- { { "kyra2", 0, AD_ENTRY1("FATE.PAK", "28cbad1c5bf06b2d3825ae57d760d032"), Common::FR_FRA, Common::kPlatformPC, Common::ADGF_NO_FLAGS }, KYRA2_CD_FLAGS }, // CD version
-
- { { "kyra2", "Demo", AD_ENTRY1("GENERAL.PAK", "35825783e5b60755fd520360079f9c15"), Common::EN_ANY, Common::kPlatformPC, Common::ADGF_DEMO }, KYRA2_DEMO_FLAGS },
-
- { { "kyra3", 0, AD_ENTRY1("ONETIME.PAK", "3833ff312757b8e6147f464cca0a6587"), Common::EN_ANY, Common::kPlatformPC, Common::ADGF_NO_FLAGS }, KYRA3_CD_FLAGS },
- { { "kyra3", 0, AD_ENTRY1("ONETIME.PAK", "3833ff312757b8e6147f464cca0a6587"), Common::DE_DEU, Common::kPlatformPC, Common::ADGF_NO_FLAGS }, KYRA3_CD_FLAGS },
- { { "kyra3", 0, AD_ENTRY1("ONETIME.PAK", "3833ff312757b8e6147f464cca0a6587"), Common::FR_FRA, Common::kPlatformPC, Common::ADGF_NO_FLAGS }, KYRA3_CD_FLAGS },
{ AD_TABLE_END_MARKER, FLAGS(0, 0, 0, 0, 0) }
};
@@ -119,29 +397,9 @@ const Common::ADParams detectionParams = {
} // End of anonymous namespace
-GameList Engine_KYRA_gameIDList() {
- return GameList(gameList);
-}
-
-GameDescriptor Engine_KYRA_findGameID(const char *gameid) {
- return Common::AdvancedDetector::findGameID(gameid, gameList);
-}
-
-GameList Engine_KYRA_detectGames(const FSList &fslist) {
- return Common::AdvancedDetector::detectAllGames(fslist, detectionParams);
-}
-
-PluginError Engine_KYRA_create(OSystem *syst, Engine **engine) {
- assert(engine);
- const char *gameid = ConfMan.get("gameid").c_str();
-
- Common::EncapsulatedADGameDesc encapsulatedDesc = Common::AdvancedDetector::detectBestMatchingGame(detectionParams);
+bool engineCreateKyra(OSystem *syst, Engine **engine, Common::EncapsulatedADGameDesc encapsulatedDesc) {
const KYRAGameDescription *gd = (const KYRAGameDescription *)(encapsulatedDesc.realDesc);
-
- if (gd == 0) {
- // maybe add non md5 based detection again?
- return kNoGameDataFoundError;
- }
+ bool res = true;
Kyra::GameFlags flags = gd->flags;
@@ -160,17 +418,25 @@ PluginError Engine_KYRA_create(OSystem *syst, Engine **engine) {
flags.lang = Common::EN_ANY;
}
- if (!scumm_stricmp("kyra1", gameid)) {
+ switch (flags.gameID) {
+ case Kyra::GI_KYRA1:
*engine = new Kyra::KyraEngine_v1(syst, flags);
- } else if (!scumm_stricmp("kyra2", gameid)) {
+ break;
+ case Kyra::GI_KYRA2:
*engine = new Kyra::KyraEngine_v2(syst, flags);
- } else if (!scumm_stricmp("kyra3", gameid)) {
+ break;
+ case Kyra::GI_KYRA3:
*engine = new Kyra::KyraEngine_v3(syst, flags);
- } else
- error("Kyra engine created with invalid gameid ('%s')", gameid);
+ break;
+ default:
+ res = false;
+ error("Kyra engine: unknown gameID");
+ }
- return kNoError;
+ return res;
}
+ADVANCED_DETECTOR_DEFINE_PLUGIN_WITH_COMPLEX_CREATION(KYRA, engineCreateKyra, detectionParams);
+
REGISTER_PLUGIN(KYRA, "Legend of Kyrandia Engine", "The Legend of Kyrandia (C) Westwood Studios");
diff --git a/engines/kyra/gui_v1.cpp b/engines/kyra/gui_v1.cpp
index b7692cc97d..0d9d8224cd 100644
--- a/engines/kyra/gui_v1.cpp
+++ b/engines/kyra/gui_v1.cpp
@@ -41,7 +41,7 @@ void KyraEngine_v1::registerDefaultSettings() {
// Most settings already have sensible defaults. This one, however, is
// specific to the Kyra engine.
ConfMan.registerDefault("walkspeed", 2);
- ConfMan.registerDefault("cdaudio", _flags.platform == Common::kPlatformFMTowns);
+ ConfMan.registerDefault("cdaudio", (_flags.platform == Common::kPlatformFMTowns || _flags.platform == Common::kPlatformPC98));
}
void KyraEngine_v1::readSettings() {
@@ -59,7 +59,7 @@ void KyraEngine_v1::readSettings() {
_configTextspeed = 2; // Fast
_configWalkspeed = ConfMan.getInt("walkspeed");
- _configMusic = ConfMan.getBool("music_mute") ? 0 : ((ConfMan.getBool("cdaudio") && _flags.platform == Common::kPlatformFMTowns) ? 2 : 1);
+ _configMusic = ConfMan.getBool("music_mute") ? 0 : ((ConfMan.getBool("cdaudio") && (_flags.platform == Common::kPlatformFMTowns || _flags.platform == Common::kPlatformPC98)) ? 2 : 1);
_configSounds = ConfMan.getBool("sfx_mute") ? 0 : 1;
_sound->enableMusic(_configMusic);
@@ -494,7 +494,7 @@ void KyraEngine_v1::setGUILabels() {
menuLabelGarbageOffset = 72;
} else if (_flags.lang == Common::DE_DEU) {
offset = offsetMainMenu = offsetOn = offsetOptions = 24;
- } else if (_flags.platform == Common::kPlatformFMTowns) {
+ } else if (_flags.platform == Common::kPlatformFMTowns || _flags.platform == Common::kPlatformPC98) {
offset = 1;
offsetOptions = 10;
offsetOn = 0;
@@ -1303,7 +1303,7 @@ int KyraEngine_v1::gui_controlsChangeMusic(Button *button) {
debugC(9, kDebugLevelGUI, "KyraEngine_v1::gui_controlsChangeMusic()");
processMenuButton(button);
- _configMusic = ++_configMusic % (_flags.platform == Common::kPlatformFMTowns ? 3 : 2);
+ _configMusic = ++_configMusic % ((_flags.platform == Common::kPlatformFMTowns || _flags.platform == Common::kPlatformPC98) ? 3 : 2);
gui_setupControls(_menu[5]);
return 0;
}
diff --git a/engines/kyra/kyra.cpp b/engines/kyra/kyra.cpp
index 1d8d7440f0..0c2524327e 100644
--- a/engines/kyra/kyra.cpp
+++ b/engines/kyra/kyra.cpp
@@ -86,8 +86,13 @@ int KyraEngine::init() {
int midiDriver = MidiDriver::detectMusicDriver(MDT_MIDI | MDT_ADLIB/* | MDT_PREFER_MIDI*/);
if (_flags.platform == Common::kPlatformFMTowns) {
- // no sfx enabled for CD audio music atm
- // later on here should be a usage of MixedSoundDriver
+ // TODO: later on here should be a usage of MixedSoundDriver
+ _sound = new SoundTowns(this, _mixer);
+ } else if (_flags.platform == Common::kPlatformPC98) {
+ // TODO: currently we don't support the PC98 sound data,
+ // but since it has the FM-Towns data files, we just use the
+ // FM-Towns driver
+ // TODO: later on here should be a usage of MixedSoundDriver
_sound = new SoundTowns(this, _mixer);
} else if (midiDriver == MD_ADLIB) {
_sound = new SoundAdlibPC(this, _mixer);
diff --git a/engines/kyra/kyra_v1.cpp b/engines/kyra/kyra_v1.cpp
index 3c6e257376..c994325ca9 100644
--- a/engines/kyra/kyra_v1.cpp
+++ b/engines/kyra/kyra_v1.cpp
@@ -18,8 +18,8 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
- * $URL:https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/branches/gsoc2007-fsnode/engines/kyra/kyra_v1.cpp $
- * $Id:kyra_v1.cpp 26949 2007-05-26 20:23:24Z david_corrales $
+ * $URL$
+ * $Id$
*
*/
@@ -180,7 +180,7 @@ int KyraEngine_v1::init() {
initStaticResource();
- if (_flags.platform == Common::kPlatformFMTowns)
+ if (_flags.platform == Common::kPlatformFMTowns || _flags.platform == Common::kPlatformPC98)
_sound->setSoundFileList(_soundFilesTowns, _soundFilesTownsCount);
else
_sound->setSoundFileList(_soundFiles, _soundFilesCount);
diff --git a/engines/kyra/kyra_v1.h b/engines/kyra/kyra_v1.h
index 8c9437b6fe..6e5ba98d3c 100644
--- a/engines/kyra/kyra_v1.h
+++ b/engines/kyra/kyra_v1.h
@@ -18,8 +18,8 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
- * $URL:https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/branches/gsoc2007-fsnode/engines/kyra/kyra_v1.h $
- * $Id:kyra_v1.h 26949 2007-05-26 20:23:24Z david_corrales $
+ * $URL$
+ * $Id$
*
*/
diff --git a/engines/kyra/kyra_v2.cpp b/engines/kyra/kyra_v2.cpp
index 317fd218b2..e27f31b691 100644
--- a/engines/kyra/kyra_v2.cpp
+++ b/engines/kyra/kyra_v2.cpp
@@ -18,8 +18,8 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
- * $URL:https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/branches/gsoc2007-fsnode/engines/kyra/kyra_v2.cpp $
- * $Id:kyra_v2.cpp 26949 2007-05-26 20:23:24Z david_corrales $
+ * $URL$
+ * $Id$
*
*/
diff --git a/engines/kyra/kyra_v2.h b/engines/kyra/kyra_v2.h
index c87eeb66d4..fb8fd2c454 100644
--- a/engines/kyra/kyra_v2.h
+++ b/engines/kyra/kyra_v2.h
@@ -18,8 +18,8 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
- * $URL:https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/branches/gsoc2007-fsnode/engines/kyra/kyra_v2.h $
- * $Id:kyra_v2.h 26949 2007-05-26 20:23:24Z david_corrales $
+ * $URL$
+ * $Id$
*
*/
diff --git a/engines/kyra/kyra_v3.cpp b/engines/kyra/kyra_v3.cpp
index 32754ecf2f..9aa4b1f4da 100644
--- a/engines/kyra/kyra_v3.cpp
+++ b/engines/kyra/kyra_v3.cpp
@@ -18,8 +18,8 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
- * $URL:https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/branches/gsoc2007-fsnode/engines/kyra/kyra_v3.cpp $
- * $Id:kyra_v3.cpp 26949 2007-05-26 20:23:24Z david_corrales $
+ * $URL$
+ * $Id$
*
*/
diff --git a/engines/kyra/kyra_v3.h b/engines/kyra/kyra_v3.h
index f9b81b5126..79c48b0dcb 100644
--- a/engines/kyra/kyra_v3.h
+++ b/engines/kyra/kyra_v3.h
@@ -18,8 +18,8 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
- * $URL:https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/branches/gsoc2007-fsnode/engines/kyra/kyra_v3.h $
- * $Id:kyra_v3.h 26949 2007-05-26 20:23:24Z david_corrales $
+ * $URL$
+ * $Id$
*
*/
diff --git a/engines/kyra/resource.cpp b/engines/kyra/resource.cpp
index cb484b6183..32c090dc57 100644
--- a/engines/kyra/resource.cpp
+++ b/engines/kyra/resource.cpp
@@ -109,7 +109,7 @@ Resource::Resource(KyraEngine *vm) {
}
}
- if (_vm->gameFlags().platform == Common::kPlatformFMTowns) {
+ if (_vm->gameFlags().platform == Common::kPlatformFMTowns || _vm->gameFlags().platform == Common::kPlatformPC98) {
uint unloadHash = (_vm->gameFlags().lang == Common::EN_ANY) ? Common::hashit_lower("JMC.PAK") : Common::hashit_lower("EMC.PAK");
ResIterator file = Common::find_if(_pakfiles.begin(), _pakfiles.end(), ResFilenameEqual(unloadHash));
diff --git a/engines/kyra/saveload_v1.cpp b/engines/kyra/saveload_v1.cpp
index c2ceee1d3b..e9001968e9 100644
--- a/engines/kyra/saveload_v1.cpp
+++ b/engines/kyra/saveload_v1.cpp
@@ -84,8 +84,8 @@ void KyraEngine_v1::loadGame(const char *fileName) {
warning("Can not load cdrom savefile for this (non cdrom) gameversion");
delete in;
return;
- } else if ((flags & GF_FMTOWNS) && !(_flags.platform == Common::kPlatformFMTowns)) {
- warning("can not load FM-Towns savefile for this (non FM-Towns) gameversion");
+ } else if ((flags & GF_FMTOWNS) && !(_flags.platform == Common::kPlatformFMTowns || _flags.platform == Common::kPlatformPC98)) {
+ warning("can not load FM-Towns/PC98 savefile for this (non FM-Towns/PC98) gameversion");
delete in;
return;
}
@@ -206,7 +206,7 @@ void KyraEngine_v1::loadGame(const char *fileName) {
if (_curSfxFile >= _soundFilesTownsCount || _curSfxFile < 0)
_curSfxFile = 0;
- if (_flags.platform == Common::kPlatformFMTowns)
+ if (_flags.platform == Common::kPlatformFMTowns || _flags.platform == Common::kPlatformPC98)
_sound->loadSoundFile(_curSfxFile);
}
@@ -276,7 +276,7 @@ void KyraEngine_v1::saveGame(const char *fileName, const char *saveName) {
out->write(saveName, 31);
if (_flags.isTalkie)
out->writeUint32BE(GF_TALKIE);
- else if (_flags.platform == Common::kPlatformFMTowns)
+ else if (_flags.platform == Common::kPlatformFMTowns || _flags.platform == Common::kPlatformPC98)
out->writeUint32BE(GF_FMTOWNS);
else
out->writeUint32BE(GF_FLOPPY);
diff --git a/engines/kyra/scene.cpp b/engines/kyra/scene.cpp
index bf85ab1474..22cf2e0f2b 100644
--- a/engines/kyra/scene.cpp
+++ b/engines/kyra/scene.cpp
@@ -65,11 +65,11 @@ int KyraEngine::findWay(int x, int y, int toX, int toY, int *moveTable, int move
return 0x7D00;
}
// debug drawing
- //if (curX >= 0 && curY >= 0 && curX < 320 && curY < 200) {
- // _screen->setPagePixel(0, curX, curY, 11);
- // _screen->updateScreen();
- // waitTicks(5);
- //}
+ /*if (curX >= 0 && curY >= 0 && curX < 320 && curY < 200) {
+ screen()->setPagePixel(0, curX, curY, 11);
+ screen()->updateScreen();
+ //waitTicks(5);
+ }*/
moveTable[lastUsedEntry++] = newFacing;
x = curX;
y = curY;
@@ -81,11 +81,11 @@ int KyraEngine::findWay(int x, int y, int toX, int toY, int *moveTable, int move
newFacing = getFacingFromPointToPoint(curX, curY, toX, toY);
changePosTowardsFacing(curX, curY, newFacing);
// debug drawing
- //if (curX >= 0 && curY >= 0 && curX < 320 && curY < 200) {
- // _screen->setPagePixel(0, curX, curY, 8);
- // _screen->updateScreen();
- // waitTicks(5);
- //}
+ /*if (curX >= 0 && curY >= 0 && curX < 320 && curY < 200) {
+ screen()->setPagePixel(0, curX, curY, 8);
+ screen()->updateScreen();
+ //waitTicks(5);
+ }*/
if (!lineIsPassable(curX, curY)) {
if (curX != toX || curY != toY)
diff --git a/engines/kyra/scene_v1.cpp b/engines/kyra/scene_v1.cpp
index 3754d5e2ab..af7ee89fec 100644
--- a/engines/kyra/scene_v1.cpp
+++ b/engines/kyra/scene_v1.cpp
@@ -48,7 +48,7 @@ void KyraEngine_v1::enterNewScene(int sceneId, int facing, int unk1, int unk2, i
_abortWalkFlag = false;
_abortWalkFlag2 = false;
- if (_flags.platform == Common::kPlatformFMTowns) {
+ if (_flags.platform == Common::kPlatformFMTowns || _flags.platform == Common::kPlatformPC98) {
int newSfxFile = -1;
if (_currentCharacter->sceneId == 7 && sceneId == 24)
newSfxFile = 2;
@@ -1166,7 +1166,9 @@ void KyraEngine_v1::setCharactersPositions(int character) {
int KyraEngine_v1::findWay(int x, int y, int toX, int toY, int *moveTable, int moveTableSize) {
debugC(9, kDebugLevelMain, "KyraEngine_v1::findWay(%d, %d, %d, %d, %p, %d)", x, y, toX, toY, (const void *)moveTable, moveTableSize);
- KyraEngine::findWay(x, y, toX, toY, moveTable, moveTableSize);
+ int ret = KyraEngine::findWay(x, y, toX, toY, moveTable, moveTableSize);
+ if (ret == 0x7D00)
+ return 0;
return getMoveTableSize(moveTable);
}
diff --git a/engines/kyra/script.cpp b/engines/kyra/script.cpp
index 5966fa2c25..0778e1abd6 100644
--- a/engines/kyra/script.cpp
+++ b/engines/kyra/script.cpp
@@ -167,7 +167,7 @@ bool ScriptHelper::startScript(ScriptState *script, int function) {
return false;
if (_vm->game() == GI_KYRA1) {
- if (_vm->gameFlags().platform == Common::kPlatformFMTowns)
+ if (_vm->gameFlags().platform == Common::kPlatformFMTowns || _vm->gameFlags().platform == Common::kPlatformPC98)
script->ip = &script->dataPtr->data[functionOffset+1];
else
script->ip = &script->dataPtr->data[functionOffset];
diff --git a/engines/kyra/script_v1.cpp b/engines/kyra/script_v1.cpp
index bd776e2046..7a4f844400 100644
--- a/engines/kyra/script_v1.cpp
+++ b/engines/kyra/script_v1.cpp
@@ -52,7 +52,7 @@ int KyraEngine_v1::o1_characterSays(ScriptState *script) {
debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1characterSays(%p) ('%s', %d, %d)", (const void *)script, stackPosString(0), stackPos(1), stackPos(2));
const char *string = stackPosString(0);
- if (_flags.platform == Common::kPlatformFMTowns && _flags.lang == Common::JA_JPN) {
+ if ((_flags.platform == Common::kPlatformFMTowns || _flags.platform == Common::kPlatformPC98) && _flags.lang == Common::JA_JPN) {
static const uint8 townsString1[] = {
0x83, 0x75, 0x83, 0x89, 0x83, 0x93, 0x83, 0x83, 0x93, 0x81,
0x41, 0x82, 0xDC, 0x82, 0xBD, 0x97, 0x88, 0x82, 0xBD, 0x82,
diff --git a/engines/kyra/seqplayer.cpp b/engines/kyra/seqplayer.cpp
index 20a98c66c1..2136c2830d 100644
--- a/engines/kyra/seqplayer.cpp
+++ b/engines/kyra/seqplayer.cpp
@@ -435,7 +435,7 @@ void SeqPlayer::s1_playTrack() {
_sound->beginFadeOut();
} else {
_sound->haltTrack();
- if (_vm->gameFlags().platform == Common::kPlatformFMTowns)
+ if (_vm->gameFlags().platform == Common::kPlatformFMTowns || _vm->gameFlags().platform == Common::kPlatformPC98)
msg += 2;
_sound->playTrack(msg);
}
diff --git a/engines/kyra/sequences_v1.cpp b/engines/kyra/sequences_v1.cpp
index 3bba3406a8..00aac6cfb4 100644
--- a/engines/kyra/sequences_v1.cpp
+++ b/engines/kyra/sequences_v1.cpp
@@ -113,7 +113,7 @@ void KyraEngine_v1::seq_intro() {
_seq->setCopyViewOffs(true);
_screen->setFont(Screen::FID_8_FNT);
- if (_flags.platform != Common::kPlatformFMTowns)
+ if (_flags.platform != Common::kPlatformFMTowns && _flags.platform != Common::kPlatformPC98)
snd_playTheme(0, 2);
_text->setTalkCoords(144);
@@ -133,7 +133,7 @@ void KyraEngine_v1::seq_intro() {
void KyraEngine_v1::seq_introLogos() {
debugC(9, kDebugLevelMain, "KyraEngine_v1::seq_introLogos()");
- if (_flags.platform == Common::kPlatformFMTowns) {
+ if (_flags.platform == Common::kPlatformFMTowns || _flags.platform == Common::kPlatformPC98) {
_screen->loadBitmap("LOGO.CPS", 3, 3, _screen->_currentPalette);
_screen->copyRegion(0, 0, 0, 0, 320, 200, 2, 0);
_screen->updateScreen();
@@ -1083,13 +1083,13 @@ void KyraEngine_v1::seq_playCredits() {
_screen->_charWidth = -1;
// we only need this for the fm-towns version
- if (_flags.platform == Common::kPlatformFMTowns)
+ if (_flags.platform == Common::kPlatformFMTowns || _flags.platform == Common::kPlatformPC98)
snd_playWanderScoreViaMap(53, 1);
uint8 *buffer = 0;
uint32 size = 0;
- if (_flags.platform == Common::kPlatformFMTowns) {
+ if (_flags.platform == Common::kPlatformFMTowns || _flags.platform == Common::kPlatformPC98) {
int sizeTmp = 0;
const uint8 *bufferTmp = _staticres->loadRawData(kCreditsStrings, sizeTmp);
buffer = new uint8[sizeTmp];
@@ -1676,6 +1676,7 @@ int KyraEngine_v1::processBead(int x, int y, int &x2, int &y2, BeadState *ptr) {
void KyraEngine_v1::setupPanPages() {
debugC(9, kDebugLevelMain, "KyraEngine_v1::setupPanPages()");
+ _screen->savePageToDisk("BKGD.PG", 2);
_screen->loadBitmap("BEAD.CPS", 3, 3, 0);
if (_flags.platform == Common::kPlatformMacintosh || _flags.platform == Common::kPlatformAmiga) {
int pageBackUp = _screen->_curPage;
@@ -1701,6 +1702,7 @@ void KyraEngine_v1::setupPanPages() {
assert(_panPagesTable[i]);
}
}
+ _screen->loadPageFromDisk("BKGD.PG", 2);
}
void KyraEngine_v1::freePanPages() {
diff --git a/engines/kyra/sound_v1.cpp b/engines/kyra/sound_v1.cpp
index 3ea86189b2..032e3eda44 100644
--- a/engines/kyra/sound_v1.cpp
+++ b/engines/kyra/sound_v1.cpp
@@ -45,7 +45,7 @@ void KyraEngine_v1::snd_playTheme(int file, int track) {
void KyraEngine_v1::snd_playSoundEffect(int track) {
debugC(9, kDebugLevelMain | kDebugLevelSound, "KyraEngine_v1::snd_playSoundEffect(%d)", track);
- if (_flags.platform == Common::kPlatformFMTowns && track == 49) {
+ if ((_flags.platform == Common::kPlatformFMTowns || _flags.platform == Common::kPlatformPC98) && track == 49) {
snd_playWanderScoreViaMap(56, 1);
return;
}
@@ -57,7 +57,7 @@ void KyraEngine_v1::snd_playWanderScoreViaMap(int command, int restart) {
if (restart)
_lastMusicCommand = -1;
- if (_flags.platform == Common::kPlatformFMTowns) {
+ if (_flags.platform == Common::kPlatformFMTowns || _flags.platform == Common::kPlatformPC98) {
if (command == 1) {
_sound->beginFadeOut();
} else if (command >= 35 && command <= 38) {
diff --git a/engines/kyra/staticres.cpp b/engines/kyra/staticres.cpp
index 3cf8648aa8..2ffa7aee09 100644
--- a/engines/kyra/staticres.cpp
+++ b/engines/kyra/staticres.cpp
@@ -86,7 +86,7 @@ uint32 createFeatures(const GameFlags &flags) {
return GF_TALKIE;
if (flags.isDemo)
return GF_DEMO;
- if (flags.platform == Common::kPlatformFMTowns)
+ if (flags.platform == Common::kPlatformFMTowns || flags.platform == Common::kPlatformPC98)
return GF_FMTOWNS;
if (flags.platform == Common::kPlatformAmiga)
return GF_AMIGA;
@@ -605,7 +605,7 @@ uint8 *StaticResource::getFile(const char *name, int &size) {
ext = ".CD";
else if (_vm->gameFlags().isDemo)
ext = ".DEM";
- else if (_vm->gameFlags().platform == Common::kPlatformFMTowns)
+ else if (_vm->gameFlags().platform == Common::kPlatformFMTowns || _vm->gameFlags().platform == Common::kPlatformPC98)
ext = ".TNS";
else if (_vm->gameFlags().platform == Common::kPlatformAmiga)
ext = ".AMG";
diff --git a/engines/kyra/text_v1.cpp b/engines/kyra/text_v1.cpp
index c04aa2105f..ae18d793ef 100644
--- a/engines/kyra/text_v1.cpp
+++ b/engines/kyra/text_v1.cpp
@@ -302,7 +302,7 @@ void KyraEngine_v1::characterSays(int vocFile, const char *chatStr, int8 charNum
if (textEnabled()) {
_animator->restoreAllObjectBackgrounds();
- _screen->copyRegion(12, _text->_talkMessageY, 12, 136, 308, _text->_talkMessageH, 2, 2);
+ _screen->copyRegion(12, _text->_talkMessageY, 12, 136, 296, _text->_talkMessageH, 2, 2);
_screen->hideMouse();
_text->printCharacterText(processedString, charNum, _characterList[charNum].x1);
@@ -321,12 +321,12 @@ void KyraEngine_v1::characterSays(int vocFile, const char *chatStr, int8 charNum
if (textEnabled()) {
_animator->restoreAllObjectBackgrounds();
- _screen->copyRegion(12, 136, 12, _text->_talkMessageY, 308, _text->_talkMessageH, 2, 2);
+ _screen->copyRegion(12, 136, 12, _text->_talkMessageY, 296, _text->_talkMessageH, 2, 2);
_animator->preserveAllBackgrounds();
_animator->prepDrawAllObjects();
_screen->hideMouse();
- _screen->copyRegion(12, _text->_talkMessageY, 12, _text->_talkMessageY, 308, _text->_talkMessageH, 2, 0);
+ _screen->copyRegion(12, _text->_talkMessageY, 12, _text->_talkMessageY, 296, _text->_talkMessageH, 2, 0);
_screen->showMouse();
_animator->flagAllObjectsForRefresh();
_animator->copyChangedObjectsForward(0);
diff --git a/engines/lure/animseq.cpp b/engines/lure/animseq.cpp
index 39d74e5ec8..1dc2abe341 100644
--- a/engines/lure/animseq.cpp
+++ b/engines/lure/animseq.cpp
@@ -104,14 +104,14 @@ AnimationSequence::AnimationSequence(Screen &screen, OSystem &system, uint16 scr
_lineRefs = d.getEntry(_screenId + 1);
- // Show the screen that preceeds the start of the animation data
- _screen.setPaletteEmpty();
+ // Reset the palette and set the initial starting screen
+ _screen.setPaletteEmpty(RES_PALETTE_ENTRIES);
_screen.screen().data().copyFrom(_decodedData, 0, 0, FULL_SCREEN_HEIGHT * FULL_SCREEN_WIDTH);
_screen.update();
// Set the palette
if (fadeIn) _screen.paletteFadeIn(&_palette);
- else _screen.setPalette(&_palette);
+ else _screen.setPalette(&_palette, 0, _palette.numEntries());
// Set up frame poitners
_pPixels = _decodedData->data() + SCREEN_SIZE;
@@ -135,7 +135,7 @@ AnimAbortType AnimationSequence::show() {
while ((_pPixels < _pPixelsEnd) && (_pLines < _pLinesEnd)) {
decodeFrame(_pPixels, _pLines);
- result = delay(130);
+ result = delay(7 * 1000 / 50);
if (result != ABORT_NONE) return result;
}
diff --git a/engines/lure/detection.cpp b/engines/lure/detection.cpp
index d072a009d5..4291b9aedb 100644
--- a/engines/lure/detection.cpp
+++ b/engines/lure/detection.cpp
@@ -18,8 +18,8 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
- * $URL:https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/branches/gsoc2007-fsnode/engines/lure/detection.cpp $
- * $Id:detection.cpp 26949 2007-05-26 20:23:24Z david_corrales $
+ * $URL$
+ * $Id$
*
*/
@@ -97,7 +97,7 @@ GameList Engine_LURE_detectGames(const FSList &fslist) {
continue;
for (g = lure_games; g->gameid; g++) {
- if (scumm_stricmp(file->name().c_str(), g->checkFile) == 0)
+ if (scumm_stricmp(file->getName().c_str(), g->checkFile) == 0)
isFound = true;
}
if (isFound)
@@ -152,8 +152,7 @@ void LureEngine::detectGame() {
"Lure of the Temptress executable. See the documentation for creating it.",
SUPPORT_FILENAME);
- for (uint8 fileNum = 1; fileNum <= 4; ++fileNum)
- {
+ for (uint8 fileNum = 1; fileNum <= 4; ++fileNum) {
char sFilename[10];
sprintf(sFilename, "disk%d.vga", fileNum);
diff --git a/engines/lure/disk.cpp b/engines/lure/disk.cpp
index 8f0714c42e..b5465df8d9 100644
--- a/engines/lure/disk.cpp
+++ b/engines/lure/disk.cpp
@@ -31,6 +31,7 @@
#include "lure/disk.h"
#include "lure/luredefs.h"
+#include "lure/res.h"
namespace Lure {
@@ -125,6 +126,14 @@ void Disk::openFile(uint8 fileNum) {
}
uint32 Disk::getEntrySize(uint16 id) {
+ // Special room area check
+ uint16 tempId = id & 0x3fff;
+ if ((tempId == 0x120) || (tempId == 0x311) || (tempId == 8) || (tempId == 0x410)) {
+ ValueTableData &fieldList = Resources::getReference().fieldList();
+ if (fieldList.getField(AREA_FLAG) != 0)
+ id ^= 0x8000;
+ }
+
// Get the index of the resource, if necessary opening the correct file
uint8 index = indexOf(id);
@@ -135,8 +144,15 @@ uint32 Disk::getEntrySize(uint16 id) {
return size;
}
-MemoryBlock *Disk::getEntry(uint16 id)
-{
+MemoryBlock *Disk::getEntry(uint16 id) {
+ // Special room area check
+ uint16 tempId = id & 0x3fff;
+ if ((tempId == 0x120) || (tempId == 0x311) || (tempId == 8) || (tempId == 0x410)) {
+ ValueTableData &fieldList = Resources::getReference().fieldList();
+ if (fieldList.getField(AREA_FLAG) != 0)
+ id ^= 0x8000;
+ }
+
// Get the index of the resource, if necessary opening the correct file
uint8 index = indexOf(id);
diff --git a/engines/lure/fights.cpp b/engines/lure/fights.cpp
index 4c478bbc17..836c109ca7 100644
--- a/engines/lure/fights.cpp
+++ b/engines/lure/fights.cpp
@@ -335,8 +335,7 @@ void FightsManager::fightHandler(Hotspot &h, uint16 moveOffset) {
return;
}
- switch (moveValue)
- {
+ switch (moveValue) {
case 0xFFFA:
// Walk left
if ((fighter.fwmove_number == 5) || (fighter.fwmove_number == 10)) {
@@ -466,7 +465,7 @@ void FightsManager::fightHandler(Hotspot &h, uint16 moveOffset) {
moveOffset += 2 * sizeof(uint16);
if (v1 == opponent.fwblocking) {
- Sound.playSound(42);
+ Sound.addSound(42);
moveOffset = v2;
}
break;
@@ -478,7 +477,7 @@ void FightsManager::fightHandler(Hotspot &h, uint16 moveOffset) {
if (fighter.fwdist <= FIGHT_DISTANCE) {
if (h.hotspotId() == PLAYER_ID) {
// Player hits opponent
- Sound.playSound(52);
+ Sound.addSound(52);
if (opponent.fwhits != 5) {
opponent.fwseq_ad = v1;
@@ -490,13 +489,13 @@ void FightsManager::fightHandler(Hotspot &h, uint16 moveOffset) {
}
} else {
// Opponent hit player
- Sound.playSound(37);
+ Sound.addSound(37);
opponent.fwseq_ad = v1;
if (++opponent.fwhits == 10) {
// Player has been killed
fighter.fwhits = 10;
opponent.fwseq_ad = FIGHT_PLAYER_DIES;
- Sound.playSound(36);
+ Sound.addSound(36);
}
}
}
@@ -526,7 +525,7 @@ void FightsManager::fightHandler(Hotspot &h, uint16 moveOffset) {
case 0xFFEA:
// Fight sound
- Sound.playSound(getWord(moveOffset));
+ Sound.addSound(getWord(moveOffset) & 0xff);
moveOffset += sizeof(uint16);
break;
diff --git a/engines/lure/game.cpp b/engines/lure/game.cpp
index 5bffc6ade8..e4aeef2253 100644
--- a/engines/lure/game.cpp
+++ b/engines/lure/game.cpp
@@ -24,14 +24,16 @@
*/
#include "lure/game.h"
-#include "lure/strings.h"
-#include "lure/room.h"
-#include "lure/scripts.h"
-#include "lure/res_struct.h"
#include "lure/animseq.h"
#include "lure/fights.h"
+#include "lure/res_struct.h"
+#include "lure/room.h"
+#include "lure/scripts.h"
+#include "lure/sound.h"
+#include "lure/strings.h"
#include "common/config-manager.h"
+#include "common/system.h"
namespace Lure {
@@ -45,6 +47,7 @@ Game::Game() {
int_game = this;
_debugger = new Debugger();
_slowSpeedFlag = true;
+ _preloadFlag = false;
_soundFlag = true;
}
@@ -52,7 +55,7 @@ Game::~Game() {
delete _debugger;
}
-void Game::tick(bool fastSpeed) {
+void Game::tick() {
// Call the tick method for each hotspot - this is somewaht complicated
// by the fact that a tick proc can unload both itself and/or others,
// so we first get a list of the Ids, and call the tick proc for each
@@ -66,7 +69,7 @@ void Game::tick(bool fastSpeed) {
for (i = res.activeHotspots().begin(); i != res.activeHotspots().end(); ++i) {
Hotspot *hotspot = *i;
- if (!fastSpeed || ((hotspot->layer() != 0xff) &&
+ if (!_preloadFlag || ((hotspot->layer() != 0xff) &&
(hotspot->hotspotId() < FIRST_NONCHARACTER_ID)))
// Add hotspot to list to execute
idList[idSize++] = hotspot->hotspotId();
@@ -85,6 +88,21 @@ void Game::tick(bool fastSpeed) {
delete[] idList;
}
+void Game::tickCheck() {
+ Resources &res = Resources::getReference();
+ Room &room = Room::getReference();
+ bool remoteFlag = res.fieldList().getField(OLD_ROOM_NUMBER) != 0;
+
+ _state |= GS_TICK;
+ if ((room.roomNumber() == ROOMNUM_VILLAGE_SHOP) && !remoteFlag && ((_state & GS_TICK) != 0)) {
+ // In the village shop,
+ bool tockFlag = (_state & GS_TOCK) != 0;
+ Sound.addSound(tockFlag ? 16 : 50);
+
+ _state = _state ^ (GS_TICK | GS_TOCK);
+ }
+}
+
void Game::nextFrame() {
Resources &res = Resources::getReference();
Room &room = Room::getReference();
@@ -110,31 +128,48 @@ void Game::execute() {
ValueTableData &fields = res.fieldList();
uint32 timerVal = system.getMillis();
+ uint32 timerVal2 = system.getMillis();
screen.empty();
- //_screen.resetPalette();
screen.setPaletteEmpty();
- setState(0);
+ // Flag for starting game
+ setState(GS_RESTART);
- Script::execute(STARTUP_SCRIPT);
+ while (!events.quitFlag) {
+
+ if ((_state & GS_RESTART) != 0) {
+ res.reset();
- int bootParam = ConfMan.getInt("boot_param");
- handleBootParam(bootParam);
+ setState(0);
+ Script::execute(STARTUP_SCRIPT);
- // Set the player direction
- res.getActiveHotspot(PLAYER_ID)->setDirection(UP);
+ int bootParam = ConfMan.getInt("boot_param");
+ handleBootParam(bootParam);
+if (bootParam == 1) _state = GS_RESTORE_RESTART; //******DEBUG******
+ }
- room.update();
- mouse.setCursorNum(CURSOR_ARROW);
- mouse.cursorOn();
-
- while (!events.quitFlag) {
- while (!events.quitFlag && (_state == 0)) {
+ // Set the player direction
+// res.getActiveHotspot(PLAYER_ID)->setDirection(UP);
+
+ room.update();
+ mouse.setCursorNum(CURSOR_ARROW);
+ mouse.cursorOn();
+
+ // Main game loop
+ while (!events.quitFlag && ((_state & GS_RESTART) == 0)) {
// If time for next frame, allow everything to update
if (system.getMillis() > timerVal + GAME_FRAME_DELAY) {
timerVal = system.getMillis();
nextFrame();
+
+ Sound.musicInterface_ContinuePlaying();
+ }
+
+ // Also check if time to do another village shop tick check
+ if (system.getMillis() > timerVal2 + GAME_TICK_DELAY) {
+ timerVal2 = system.getMillis();
+ tickCheck();
}
res.delayList().tick();
@@ -161,48 +196,46 @@ void Game::execute() {
SaveRestoreDialog::show(false);
break;
- default:
- handled = false;
- }
- if (handled)
- continue;
+ case Common::KEYCODE_F9:
+ doRestart();
+ break;
- // Handle any remaining standard keys
- switch (events.event().kbd.keycode) {
- case Common::KEYCODE_ESCAPE:
- events.quitFlag = true;
- break;
+ case Common::KEYCODE_KP_PLUS:
+ while (++roomNum <= 51)
+ if (res.getRoom(roomNum) != NULL) break;
+ if (roomNum == 52) roomNum = 1;
- case '+':
- while (++roomNum <= 51)
- if (res.getRoom(roomNum) != NULL) break;
- if (roomNum == 52) roomNum = 1;
+ room.leaveRoom();
+ room.setRoomNumber(roomNum);
+ break;
- room.leaveRoom();
- room.setRoomNumber(roomNum);
- break;
+ case Common::KEYCODE_KP_MINUS:
+ if (roomNum == 1) roomNum = 55;
+ while (res.getRoom(--roomNum) == NULL) ;
- case '-':
- if (roomNum == 1) roomNum = 55;
- while (res.getRoom(--roomNum) == NULL) ;
+ room.leaveRoom();
+ room.setRoomNumber(roomNum);
+ break;
- room.leaveRoom();
- room.setRoomNumber(roomNum);
- break;
+ case Common::KEYCODE_KP_MULTIPLY:
+ res.getActiveHotspot(PLAYER_ID)->setRoomNumber(
+ room.roomNumber());
+ break;
- case '*':
- res.getActiveHotspot(PLAYER_ID)->setRoomNumber(
- room.roomNumber());
- break;
+ case Common::KEYCODE_KP_DIVIDE:
+ case Common::KEYCODE_SLASH:
+ room.setShowInfo(!room.showInfo());
+ break;
- case Common::KEYCODE_KP_DIVIDE:
- case Common::KEYCODE_SLASH:
- room.setShowInfo(!room.showInfo());
- break;
+ case Common::KEYCODE_ESCAPE:
+ doQuit();
+ break;
- default:
- break;
+ default:
+ handled = false;
}
+ if (handled)
+ continue;
}
if ((events.type() == Common::EVENT_LBUTTONDOWN) ||
@@ -232,24 +265,31 @@ void Game::execute() {
_debugger->onFrame();
}
+ room.leaveRoom();
+
// If Skorl catches player, show the catching animation
if ((_state & GS_CAUGHT) != 0) {
Palette palette(SKORL_CATCH_PALETTE_ID);
AnimationSequence *anim = new AnimationSequence(screen, system,
SKORL_CATCH_ANIM_ID, palette, false);
mouse.cursorOff();
+ Sound.addSound(0x33);
anim->show();
- mouse.cursorOn();
+ delete anim;
}
// If the Restart/Restore dialog is needed, show it
- if ((_state & GS_RESTORE_RESTART) != 0) {
- // TODO: Restore/Restart dialog - for now, simply flag for exit
+ if ((_state & GS_RESTORE) != 0) {
+ // Show the Restore/Restart dialog
+ bool restartFlag = RestartRestoreDialog::show();
+
+ if (restartFlag)
+ setState(GS_RESTART);
+
+ } else if ((_state & GS_RESTART) == 0)
+ // Exiting game
events.quitFlag = true;
- }
}
-
- room.leaveRoom();
}
void Game::handleMenuResponse(uint8 selection) {
@@ -261,6 +301,7 @@ void Game::handleMenuResponse(uint8 selection) {
break;
case MENUITEM_RESTART_GAME:
+ doRestart();
break;
case MENUITEM_SAVE_GAME:
@@ -296,6 +337,8 @@ void Game::playerChangeRoom() {
delayList.clear();
+ Sound.removeSounds();
+
RoomData *roomData = res.getRoom(roomNum);
assert(roomData);
roomData->flags |= HOTSPOTFLAG_FOUND;
@@ -332,8 +375,7 @@ void Game::playerChangeRoom() {
}
}
-void Game::displayChuteAnimation()
-{
+void Game::displayChuteAnimation() {
OSystem &system = *g_system;
Resources &res = Resources::getReference();
Screen &screen = Screen::getReference();
@@ -361,11 +403,10 @@ void Game::displayChuteAnimation()
delete anim;
mouse.cursorOn();
- fields.setField(82, 1);
+ fields.setField(AREA_FLAG, 1);
}
-void Game::displayBarrelAnimation()
-{
+void Game::displayBarrelAnimation() {
OSystem &system = *g_system;
Screen &screen = Screen::getReference();
Mouse &mouse = Mouse::getReference();
@@ -631,8 +672,7 @@ bool Game::GetTellActions() {
--_numTellCommands;
if (_numTellCommands < 0)
paramIndex = -1;
- else
- {
+ else {
paramIndex = 3;
statusLine = statusLinePos[_numTellCommands][paramIndex];
*statusLine = '\0';
@@ -791,14 +831,12 @@ void Game::doAction(Action action, uint16 hotspotId, uint16 usedId) {
room.setCursorState(CS_ACTION);
// Set the action
- if (action == TELL)
- {
+ if (action == TELL) {
// Tell action needs special handling because of the variable length parameter list - add in a
// placeholder entry, and then replace it's details with the TELL command data
player->currentActions().addFront(NONE, player->roomNumber(), 0, 0);
player->currentActions().top().supportData().setDetails2(TELL, _numTellCommands * 3 + 1, &_tellCommands[0]);
- }
- else
+ } else
// All other action types
player->currentActions().addFront(action, player->roomNumber(), hotspotId, usedId);
}
@@ -823,31 +861,13 @@ void Game::doShowCredits() {
}
void Game::doQuit() {
- Mouse &mouse = Mouse::getReference();
- Events &events = Events::getReference();
- Screen &screen = Screen::getReference();
-
- mouse.cursorOff();
- Surface *s = Surface::newDialog(190, "Are you sure (y/n)?");
- s->centerOnScreen();
- delete s;
-
- Common::KeyCode key = Common::KEYCODE_INVALID;
- do {
- if (events.pollEvent()) {
- if (events.event().type == Common::EVENT_KEYDOWN) {
- key = events.event().kbd.keycode;
- }
- }
- } while ((key != Common::KEYCODE_ESCAPE) &&
- (key != Common::KEYCODE_y) &&
- (key != Common::KEYCODE_n));
+ if (getYN())
+ Events::getReference().quitFlag = true;
+}
- events.quitFlag = (key == Common::KEYCODE_n);
- if (!events.quitFlag) {
- screen.update();
- mouse.cursorOn();
- }
+void Game::doRestart() {
+ if (getYN())
+ setState(GS_RESTART);
}
void Game::doTextSpeed() {
@@ -864,6 +884,7 @@ void Game::doSound() {
_soundFlag = !_soundFlag;
menu.getMenu(2).entries()[2] = sl.getString(_soundFlag ? S_SOUND_ON : S_SOUND_OFF);
+ Sound.setVolume(_soundFlag ? DEFAULT_VOLUME : 0);
}
void Game::handleBootParam(int value) {
@@ -908,7 +929,53 @@ void Game::handleBootParam(int value) {
room.setRoomNumber(2);
break;
+
+ default:
+ room.setRoomNumber(value);
+ break;
}
}
+bool Game::getYN() {
+ Mouse &mouse = Mouse::getReference();
+ Events &events = Events::getReference();
+ Screen &screen = Screen::getReference();
+
+ mouse.cursorOff();
+ Surface *s = Surface::newDialog(190, "Are you sure (y/n)?");
+ s->centerOnScreen();
+ delete s;
+
+ bool breakFlag = false;
+ bool result = false;
+
+ do {
+ if (events.pollEvent()) {
+ if (events.event().type == Common::EVENT_KEYDOWN) {
+ Common::KeyCode key = events.event().kbd.keycode;
+ if ((key == Common::KEYCODE_y) || (key == Common::KEYCODE_n) ||
+ (key == Common::KEYCODE_ESCAPE)) {
+ breakFlag = true;
+ result = key == Common::KEYCODE_y;
+ }
+ }
+ if (events.event().type == Common::EVENT_LBUTTONUP) {
+ breakFlag = true;
+ result = true;
+ }
+ if (events.event().type == Common::EVENT_RBUTTONUP) {
+ breakFlag = true;
+ result = false;
+ }
+ }
+
+ g_system->delayMillis(10);
+ } while (!events.quitFlag && !breakFlag);
+
+ screen.update();
+ mouse.cursorOn();
+
+ return result;
+}
+
} // end of namespace Lure
diff --git a/engines/lure/game.h b/engines/lure/game.h
index 20e56df776..50b730e354 100644
--- a/engines/lure/game.h
+++ b/engines/lure/game.h
@@ -39,7 +39,9 @@
namespace Lure {
-enum GameState {GS_RESTORE_RESTART = 1, GS_CAUGHT = 2, GS_EXIT = 3};
+enum GameState {GS_ERROR = 1, GS_TICK = 2, GS_TOCK = 4, GS_PROT = 8, GS_RESTART = 0x10,
+ GS_CAUGHT = 0x20, GS_RESTORE = 0x40, GS_FLOPPY = 0x80,
+ GS_RESTORE_RESTART = 0x50};
class Game {
private:
@@ -48,6 +50,7 @@ private:
uint8 _state;
uint16 _tellCommands[MAX_TELL_COMMANDS * 3 + 1];
int _numTellCommands;
+ bool _preloadFlag;
void handleMenuResponse(uint8 selection);
void handleClick();
@@ -60,21 +63,25 @@ private:
void displayChuteAnimation();
void displayBarrelAnimation();
void handleBootParam(int value);
+ bool getYN();
public:
Game();
virtual ~Game();
static Game &getReference();
- void tick(bool fastSpeed = false);
+ void tick();
+ void tickCheck();
void nextFrame();
void execute();
void setState(uint8 flags) { _state = flags; }
+ bool &preloadFlag() { return _preloadFlag; }
// Menu item support methods
void doDebugMenu();
void doShowCredits();
void doQuit();
+ void doRestart();
void doTextSpeed();
void doSound();
};
diff --git a/engines/lure/hotspots.cpp b/engines/lure/hotspots.cpp
index 7def0be9ab..93860bbd3e 100644
--- a/engines/lure/hotspots.cpp
+++ b/engines/lure/hotspots.cpp
@@ -35,6 +35,7 @@
#include "lure/events.h"
#include "lure/game.h"
#include "lure/fights.h"
+#include "lure/sound.h"
#include "common/endian.h"
namespace Lure {
@@ -69,12 +70,19 @@ Hotspot::Hotspot(HotspotData *res): _pathFinder(this) {
_hotspotScriptOffset = res->hotspotScriptOffset;
_tickCtr = res->tickTimeout;
_colourOffset = res->colourOffset;
+ _tempDest.counter = 0;
_override = resources.getHotspotOverride(res->hotspotId);
setAnimation(_data->animRecordId);
_tickHandler = HotspotTickHandlers::getHandler(_data->tickProcOffset);
_nameBuffer[0] = '\0';
+ if (_hotspotId < FIRST_NONCHARACTER_ID) {
+ // Default characters to facing upwards until they start moving
+ _direction = UP;
+ setFrameNumber(_anim->upFrame);
+ }
+
_frameCtr = 0;
_skipFlag = false;
_charRectY = 0;
@@ -165,6 +173,40 @@ Hotspot::Hotspot(Hotspot *character, uint16 objType): _pathFinder(this) {
_nameBuffer[0] = '\0';
}
+Hotspot::Hotspot(): _pathFinder(NULL) {
+ _data = NULL;
+ _anim = NULL;
+ _frames = NULL;
+ _numFrames = 0;
+ _persistant = false;
+ _hotspotId = 0xffff;
+ _override = NULL;
+ _colourOffset = 0;
+ _destHotspotId = 0;
+ _blockedOffset = 0;
+ _exitCtr = 0;
+ _voiceCtr = 0;
+ _walkFlag = false;
+ _skipFlag = false;
+ _roomNumber = 0;
+ _destHotspotId = 0;
+ _startX = 0;
+ _startY = 0;
+ _destX = 0;
+ _destY = 0;
+ _layer = 0;
+ _height = 0;
+ _width = 0;
+ _heightCopy = 0;
+ _widthCopy = 0;
+ _yCorrection = 0;
+ _tickCtr = 0;
+ _tickHandler = NULL;
+ _frameWidth = _width;
+ _frameStartsUsed = false;
+ _tempDest.counter = 0;
+}
+
Hotspot::~Hotspot() {
if (_frames) delete _frames;
}
@@ -386,8 +428,7 @@ uint16 Hotspot::nameId() {
return _data->nameId;
}
-const char *Hotspot::getName()
-{
+const char *Hotspot::getName() {
// If name hasn't been loaded yet, then do so
if (!_nameBuffer[0] && (nameId() != 0))
StringData::getReference().getString(nameId(), _nameBuffer);
@@ -658,6 +699,8 @@ void Hotspot::updateMovement() {
setOccupied(true);
}
}
+
+ resetDirection();
}
void Hotspot::updateMovement2(CharacterMode value) {
@@ -810,12 +853,12 @@ void Hotspot::startTalkDialog() {
/* */
/*-------------------------------------------------------------------------*/
-uint16 validRoomExitHotspots[] = {0x2711, 0x2712, 0x2714, 0x2715, 0x2716, 0x2717,
+static const uint16 validRoomExitHotspots[] = {0x2711, 0x2712, 0x2714, 0x2715, 0x2716, 0x2717,
0x2718, 0x2719, 0x271A, 0x271E, 0x271F, 0x2720, 0x2721, 0x2722, 0x2725, 0x2726,
0x2729, 0x272A, 0x272B, 0x272C, 0x272D, 0x272E, 0x272F, 0};
bool Hotspot::isRoomExit(uint16 id) {
- for (uint16 *p = &validRoomExitHotspots[0]; *p != 0; ++p)
+ for (const uint16 *p = &validRoomExitHotspots[0]; *p != 0; ++p)
if (*p == id) return true;
return false;
}
@@ -869,7 +912,7 @@ HotspotPrecheckResult Hotspot::actionPrecheck(HotspotData *hotspot) {
return PC_WAIT;
} else if (hotspot->actionHotspotId != _hotspotId) {
- if (fields.getField(82) != 2) {
+ if (fields.getField(AREA_FLAG) != 2) {
showMessage(5, hotspot->hotspotId);
setDelayCtr(4);
}
@@ -1056,6 +1099,29 @@ bool Hotspot::doorCloseCheck(uint16 doorId) {
return true;
}
+void Hotspot::resetDirection() {
+ uint16 newFrameNumber;
+ switch (_direction) {
+ case UP:
+ newFrameNumber = _anim->upFrame;
+ break;
+ case DOWN:
+ newFrameNumber = _anim->downFrame;
+ break;
+ case LEFT:
+ newFrameNumber = _anim->leftFrame;
+ break;
+ case RIGHT:
+ newFrameNumber = _anim->rightFrame;
+ break;
+ default:
+ // No need to change
+ return;
+ }
+
+ setFrameNumber(newFrameNumber);
+}
+
/*-------------------------------------------------------------------------*/
typedef void (Hotspot::*ActionProcPtr)(HotspotData *hotspot);
@@ -1121,12 +1187,10 @@ void Hotspot::doAction(Action action, HotspotData *hotspot) {
void Hotspot::doNothing(HotspotData *hotspot) {
_currentActions.pop();
- if (!_currentActions.isEmpty())
- {
+ if (!_currentActions.isEmpty()) {
setBlockedFlag(false);
currentActions().top().setAction(DISPATCH_ACTION);
- }
- else if (hotspotId() == PLAYER_ID) {
+ } else if (hotspotId() == PLAYER_ID) {
Room::getReference().setCursorState(CS_NONE);
}
}
@@ -1294,8 +1358,8 @@ void Hotspot::doClose(HotspotData *hotspot) {
joinRec = res.getExitJoin(hotspot->hotspotId);
if (!joinRec->blocked) {
// Close the door
- if (!doorCloseCheck(joinRec->hotspot1Id) ||
- !doorCloseCheck(joinRec->hotspot2Id)) {
+ if (!doorCloseCheck(joinRec->hotspots[0].hotspotId) ||
+ !doorCloseCheck(joinRec->hotspots[1].hotspotId)) {
// A character is preventing the door from closing
showMessage(2);
} else {
@@ -1486,59 +1550,32 @@ void Hotspot::doLook(HotspotData *hotspot) {
Dialog::show(Room::getReference().descId());
}
-uint16 hotspotLookAtList[] = {0x411, 0x412, 0x41F, 0x420, 0x421, 0x422, 0x426,
+static const uint16 hotspotLookAtList[] = {0x411, 0x412, 0x41F, 0x420, 0x421, 0x422, 0x426,
0x427, 0x428, 0x429, 0x436, 0x437, 0};
void Hotspot::doLookAt(HotspotData *hotspot) {
- Resources &res = Resources::getReference();
- uint16 sequenceOffset = res.getHotspotAction(hotspot->actionsOffset, LOOK_AT);
-
- if (hotspot->hotspotId >= FIRST_NONCHARACTER_ID) {
- // Check if the hotspot appears in the list of hotspots that don't
- // need to be walked to before being looked at
- uint16 *tempId = &hotspotLookAtList[0];
- while ((*tempId != 0) && (*tempId != hotspot->hotspotId)) ++tempId;
- if (!*tempId) {
- // Hotspot wasn't in the list
- HotspotPrecheckResult result = actionPrecheck(hotspot);
- if (result == PC_WAIT) return;
- else if (result != PC_EXECUTE) {
- endAction();
- return;
- }
- }
- }
-
- faceHotspot(hotspot);
- setActionCtr(0);
- endAction();
-
- if (sequenceOffset >= 0x8000) {
- showMessage(sequenceOffset);
- } else {
- if (sequenceOffset != 0)
- sequenceOffset = Script::execute(sequenceOffset);
-
- if (sequenceOffset == 0) {
- uint16 descId = (hotspot->descId2 != 0) ? hotspot->descId2 : hotspot->descId;
- Dialog::show(descId);
- }
- }
+ doLookAction(hotspot, LOOK_AT);
}
void Hotspot::doLookThrough(HotspotData *hotspot) {
+ doLookAction(hotspot, LOOK_THROUGH);
+}
+
+void Hotspot::doLookAction(HotspotData *hotspot, Action action) {
Resources &res = Resources::getReference();
- uint16 sequenceOffset = res.getHotspotAction(hotspot->actionsOffset, LOOK_THROUGH);
+ uint16 sequenceOffset = res.getHotspotAction(hotspot->actionsOffset, action);
if (hotspot->hotspotId >= FIRST_NONCHARACTER_ID) {
// Check if the hotspot appears in the list of hotspots that don't
// need to be walked to before being looked at
- uint16 *tempId = &hotspotLookAtList[0];
- while ((*tempId != 0) && (*tempId != hotspot->hotspotId)) ++tempId;
+ const uint16 *tempId = &hotspotLookAtList[0];
+ while ((*tempId != 0) && (*tempId != hotspot->hotspotId))
+ ++tempId;
if (!*tempId) {
// Hotspot wasn't in the list
HotspotPrecheckResult result = actionPrecheck(hotspot);
- if (result == PC_WAIT) return;
+ if (result == PC_WAIT)
+ return;
else if (result != PC_EXECUTE) {
endAction();
return;
@@ -1701,7 +1738,7 @@ void Hotspot::doReturn(HotspotData *hotspot) {
endAction();
}
-uint16 bribe_hotspot_list[] = {0x421, 0x879, 0x3E9, 0x8C7, 0x429, 0x8D1,
+static const uint16 bribe_hotspot_list[] = {0x421, 0x879, 0x3E9, 0x8C7, 0x429, 0x8D1,
0x422, 0x8D4, 0x420, 0x8D6, 0x42B, 0x956, 0x3F2, 0xBE6, 0};
void Hotspot::doBribe(HotspotData *hotspot) {
@@ -1717,7 +1754,7 @@ void Hotspot::doBribe(HotspotData *hotspot) {
return;
}
- uint16 *tempId = &bribe_hotspot_list[0];
+ const uint16 *tempId = &bribe_hotspot_list[0];
uint16 sequenceOffset = 0x14B; // Default sequence offset
while (*tempId != 0) {
if (*tempId++ == hotspotId()) {
@@ -2010,8 +2047,7 @@ uint16 Hotspot::getTalkId(HotspotData *charHotspot) {
TalkHeaderData *headerEntry;
// If the hotspot has a talk data override, return it
- if (charHotspot->talkOverride != 0)
- {
+ if (charHotspot->talkOverride != 0) {
// Has an override, so return it and reset back to zero
uint16 result = charHotspot->talkOverride;
charHotspot->talkOverride = 0;
@@ -2384,7 +2420,7 @@ void HotspotTickHandlers::standardCharacterAnimHandler(Hotspot &h) {
switch (action) {
case NO_ACTION:
- h.setCharacterMode(CHARMODE_IDLE);
+ h.updateMovement2(CHARMODE_IDLE);
break;
case DISPATCH_ACTION:
@@ -2479,8 +2515,7 @@ void HotspotTickHandlers::standardCharacterAnimHandler(Hotspot &h) {
// Increment the blocked state
h.setBlockedState((BlockedState) ((int) h.blockedState() + 1));
- if (!h.blockedFlag())
- {
+ if (!h.blockedFlag()) {
// Not already handling blocked, so add a new dummy action so that the new
// action set below will not replace the existing one
h.currentActions().addFront(DISPATCH_ACTION, 0);
@@ -2587,38 +2622,37 @@ void HotspotTickHandlers::puzzledAnimHandler(Hotspot &h) {
void HotspotTickHandlers::roomExitAnimHandler(Hotspot &h) {
Resources &res = Resources::getReference();
-// ValueTableData &fields = res.fieldList();
+ ValueTableData &fields = res.fieldList();
+ Room &room = Room::getReference();
+
RoomExitJoinData *rec = res.getExitJoin(h.hotspotId());
if (!rec) return;
- byte *currentFrame, *destFrame;
+ RoomExitJoinStruct &rs = (rec->hotspots[0].hotspotId == h.hotspotId()) ?
+ rec->hotspots[0] : rec->hotspots[1];
- if (rec->hotspot1Id == h.hotspotId()) {
- currentFrame = &rec->h1CurrentFrame;
- destFrame = &rec->h1DestFrame;
- } else {
- currentFrame = &rec->h2CurrentFrame;
- destFrame = &rec->h2DestFrame;
- }
-
- if ((rec->blocked != 0) && (*currentFrame != *destFrame)) {
+ if ((rec->blocked != 0) && (rs.currentFrame != rs.destFrame)) {
// Closing the door
h.setOccupied(true);
- ++*currentFrame;
- if (*currentFrame == *destFrame) {
- // TODO: play closed door sound
- }
- } else if ((rec->blocked == 0) && (*currentFrame != 0)) {
+ ++rs.currentFrame;
+ if ((rs.currentFrame == rs.destFrame) && (h.hotspotId() == room.roomNumber()))
+ Sound.addSound(rs.closeSound);
+
+ } else if ((rec->blocked == 0) && (rs.currentFrame != 0)) {
// Opening the door
h.setOccupied(false);
- --*currentFrame;
- if (*currentFrame == *destFrame) {
- //TODO: Check against script val 88 and play sound
+ --rs.currentFrame;
+ if ((rs.currentFrame == rs.destFrame) && (h.hotspotId() == room.roomNumber())) {
+ Sound.addSound(rs.openSound);
+
+ // If in the outside village, trash reverb
+ if (fields.getField(AREA_FLAG) == 1)
+ Sound.musicInterface_TrashReverb();
}
}
- h.setFrameNumber(*currentFrame);
+ h.setFrameNumber(rs.currentFrame);
}
void HotspotTickHandlers::playerAnimHandler(Hotspot &h) {
@@ -2859,7 +2893,7 @@ void HotspotTickHandlers::followerAnimHandler(Hotspot &h) {
h.currentActions().addFront(DISPATCH_ACTION, player->roomNumber());
else {
// Scan through the translation list for an alternate destination room
- RoomTranslationRecord *p = &roomTranslations[0];
+ const RoomTranslationRecord *p = &roomTranslations[0];
while ((p->srcRoom != 0) && (p->srcRoom != player->roomNumber()))
++p;
h.currentActions().addFront(DISPATCH_ACTION,
@@ -2931,10 +2965,11 @@ void HotspotTickHandlers::followerAnimHandler(Hotspot &h) {
void HotspotTickHandlers::jailorAnimHandler(Hotspot &h) {
Resources &res = Resources::getReference();
ValueTableData &fields = res.fieldList();
+ Game &game = Game::getReference();
HotspotData *player = res.getHotspot(PLAYER_ID);
if ((fields.getField(11) != 0) || (h.hotspotId() == CASTLE_SKORL_ID)) {
- if (!h.skipFlag() && (h.roomNumber() == player->roomNumber)) {
+ if (!h.skipFlag() && !game.preloadFlag() && (h.roomNumber() == player->roomNumber)) {
if (Support::charactersIntersecting(h.resource(), player)) {
// Skorl has caught the player
Game::getReference().setState(GS_RESTORE_RESTART | GS_CAUGHT);
@@ -2966,6 +3001,9 @@ void HotspotTickHandlers::droppingTorchAnimHandler(Hotspot &h) {
res.deactivateHotspot(h.hotspotId());
res.activateHotspot(0x41C);
+ // Add sound
+ Sound.addSound(8);
+
// Enable the fire and activate its animation
HotspotData *fire = res.getHotspot(0x418);
fire->flags |= 0x80;
@@ -2976,12 +3014,9 @@ void HotspotTickHandlers::droppingTorchAnimHandler(Hotspot &h) {
}
void HotspotTickHandlers::playerSewerExitAnimHandler(Hotspot &h) {
- if (h.frameCtr() > 0)
- {
+ if (h.frameCtr() > 0) {
h.decrFrameCtr();
- }
- else if (h.executeScript())
- {
+ } else if (h.executeScript()) {
Resources &res = Resources::getReference();
// Deactive the dropping animation
@@ -3484,7 +3519,7 @@ void HotspotTickHandlers::barmanAnimHandler(Hotspot &h) {
// All other actions
uint16 xp, id;
- uint16 *frameList;
+ const uint16 *frameList;
uint16 frameNumber;
BarmanAction action = (BarmanAction) (h.frameCtr() & 0x3F);
@@ -3518,12 +3553,10 @@ void HotspotTickHandlers::barmanAnimHandler(Hotspot &h) {
HotspotData *gwyn = res.getHotspot(GOEWIN_ID);
HotspotData *wayne = res.getHotspot(WAYNE_ID);
- if ((player->roomNumber != 35) && (gwyn->roomNumber != 35) && (wayne->roomNumber != 35))
- {
+ if ((player->roomNumber != 35) && (gwyn->roomNumber != 35) && (wayne->roomNumber != 35)) {
if (rnd.getRandomNumber(1) == 1)
id = BG_EXTRA1 << 8;
- else
- {
+ else {
// Set up alternate animation
h.setWidth(32);
h.setAnimation(EWAN_ALT_ANIM_ID);
@@ -3544,15 +3577,13 @@ void HotspotTickHandlers::barmanAnimHandler(Hotspot &h) {
frameList = barEntry.graphics[h.supportValue() >> 8];
frameNumber = frameList[h.supportValue() & 0xff];
- if (frameNumber != 0)
- {
+ if (frameNumber != 0) {
h.setActionCtr(frameNumber);
h.setFrameNumber(frameNumber);
return;
}
- if (h.hotspotId() == EWAN_ID)
- {
+ if (h.hotspotId() == EWAN_ID) {
// Make sure Ewan is back to his standard animation
h.setWidth(16);
h.setAnimation(EWAN_ANIM_ID);
@@ -4261,16 +4292,13 @@ void CurrentActionEntry::saveToStream(WriteStream *stream) {
if (hasSupportData()) {
// Handle the support data
stream->writeByte(_dynamicSupportData);
- if (_dynamicSupportData)
- {
+ if (_dynamicSupportData) {
// Write out the dynamic data
stream->writeByte(supportData().action());
stream->writeSint16LE(supportData().numParams());
for (int index = 0; index < supportData().numParams(); ++index)
stream->writeUint16LE(supportData().param(index));
- }
- else
- {
+ } else {
// Write out the Id for the static entry
stream->writeSint16LE(supportData().id());
}
@@ -4294,8 +4322,7 @@ CurrentActionEntry *CurrentActionEntry::loadFromStream(ReadStream *stream) {
} else {
// Handle support data for the entry
bool dynamicData = stream->readByte() != 0;
- if (dynamicData)
- {
+ if (dynamicData) {
// Load action entry that has dynamic data
result = new CurrentActionEntry(
(CurrentAction) actionNum, roomNumber);
@@ -4308,9 +4335,7 @@ CurrentActionEntry *CurrentActionEntry::loadFromStream(ReadStream *stream) {
result->_supportData->setDetails2(action, numParams, paramList);
delete paramList;
- }
- else
- {
+ } else {
// Load action entry with an NPC schedule entry
uint16 entryId = stream->readUint16LE();
CharacterScheduleEntry *entry = res.charSchedules().getEntry(entryId);
@@ -4394,8 +4419,7 @@ void CurrentActionStack::saveToStream(WriteStream *stream) {
list(buffer);
debugC(ERROR_DETAILED, kLureDebugAnimations, "%s", buffer);
- for (i = _actions.begin(); i != _actions.end(); ++i)
- {
+ for (i = _actions.begin(); i != _actions.end(); ++i) {
CurrentActionEntry *rec = *i;
rec->saveToStream(stream);
}
@@ -4553,8 +4577,7 @@ bool Support::isCharacterInList(uint16 *lst, int numEntries, uint16 charId) {
void HotspotList::saveToStream(WriteStream *stream) {
HotspotList::iterator i;
- for (i = begin(); i != end(); ++i)
- {
+ for (i = begin(); i != end(); ++i) {
Hotspot *hotspot = *i;
debugC(ERROR_INTERMEDIATE, kLureDebugAnimations, "Saving hotspot %xh", hotspot->hotspotId());
bool dynamicObject = hotspot->hotspotId() != hotspot->originalId();
@@ -4574,8 +4597,7 @@ void HotspotList::loadFromStream(ReadStream *stream) {
clear();
uint16 hotspotId = stream->readUint16LE();
- while (hotspotId != 0)
- {
+ while (hotspotId != 0) {
debugC(ERROR_INTERMEDIATE, kLureDebugAnimations, "Loading hotspot %xh", hotspotId);
bool dynamicObject = stream->readByte() != 0;
uint16 destHotspotId = stream->readUint16LE();
@@ -4585,9 +4607,7 @@ void HotspotList::loadFromStream(ReadStream *stream) {
Hotspot *destHotspot = res.getActiveHotspot(destHotspotId);
assert(destHotspot);
hotspot = new Hotspot(destHotspot, hotspotId);
- }
- else
- {
+ } else {
HotspotData *hotspotData = res.getHotspot(hotspotId);
assert(hotspotData);
hotspot = new Hotspot(hotspotData);
diff --git a/engines/lure/hotspots.h b/engines/lure/hotspots.h
index fb3bb1478b..c30faa58c5 100644
--- a/engines/lure/hotspots.h
+++ b/engines/lure/hotspots.h
@@ -342,9 +342,13 @@ private:
void npcPause(HotspotData *hotspot);
void npcStartTalking(HotspotData *hotspot);
void npcJumpAddress(HotspotData *hotspot);
+
+ // Auxillaries
+ void doLookAction(HotspotData *hotspot, Action action);
public:
Hotspot(HotspotData *res);
Hotspot(Hotspot *character, uint16 objType);
+ Hotspot();
~Hotspot();
void setAnimation(uint16 newAnimId);
diff --git a/engines/lure/intro.cpp b/engines/lure/intro.cpp
index 3f939c6389..ae4199051e 100644
--- a/engines/lure/intro.cpp
+++ b/engines/lure/intro.cpp
@@ -26,20 +26,26 @@
#include "lure/intro.h"
#include "lure/animseq.h"
#include "lure/events.h"
+#include "lure/sound.h"
namespace Lure {
struct AnimRecord {
uint16 resourceId;
uint8 paletteIndex;
- bool initialPause;
- bool endingPause;
+ uint16 initialPause;
+ uint16 endingPause;
+ uint8 soundNumber;
};
static const uint16 start_screens[] = {0x18, 0x1A, 0x1E, 0x1C, 0};
-static const AnimRecord anim_screens[] = {{0x40, 0, true, true}, {0x42, 1, false, true},
- {0x44, 2, false, false}, {0x24, 3, false, true}, {0x46, 3, false, false},
- {0, 0, false, false}};
+static const AnimRecord anim_screens[] = {
+ {0x40, 0, 0x35A, 0xC8, 0}, // The kingdom was at peace
+ {0x42, 1, 0, 0x5FA, 1}, // Cliff overhang
+ {0x44, 2, 0, 0, 2}, // Siluette in moonlight
+ {0x24, 3, 0, 0x328 + 0x24, 0xff}, // Exposition of reaching town
+ {0x46, 3, 0, 0, 3}, // Skorl approaches
+ {0, 0, 0, 0, 0xff}};
// showScreen
// Shows a screen by loading it from the given resource, and then fading it in
@@ -73,26 +79,38 @@ bool Introduction::show() {
if (showScreen(start_screens[ctr], start_screens[ctr] + 1, 5000))
return true;
- AnimationSequence *anim;
- bool result;
-
// Animated screens
+ AnimationSequence *anim;
+ bool result;
+ uint8 currentSound = 0xff;
PaletteCollection coll(0x32);
const AnimRecord *curr_anim = anim_screens;
- for (; curr_anim->resourceId; ++curr_anim)
- {
+ for (; curr_anim->resourceId; ++curr_anim) {
+ // Handle sound selection
+ if (curr_anim->soundNumber != 0xff) {
+ if (currentSound != 0xff)
+ // Fade out the previous sound
+ Sound.fadeOut();
+
+ currentSound = curr_anim->soundNumber;
+ Sound.musicInterface_Play(currentSound, 0);
+ // DEBUG TEST
+// g_system->delayMillis(1000);
+// Sound.musicInterface_Play(1, 1);
+ }
+
bool fadeIn = curr_anim == anim_screens;
anim = new AnimationSequence(_screen, _system, curr_anim->resourceId,
coll.getPalette(curr_anim->paletteIndex), fadeIn);
- if (curr_anim->initialPause)
- if (events.interruptableDelay(12000)) return true;
+ if (curr_anim->initialPause != 0)
+ if (events.interruptableDelay(curr_anim->initialPause * 1000 / 50)) return true;
result = false;
switch (anim->show()) {
case ABORT_NONE:
- if (curr_anim->endingPause) {
- result = events.interruptableDelay(12000);
+ if (curr_anim->endingPause != 0) {
+ result = events.interruptableDelay(curr_anim->endingPause * 1000 / 50);
}
break;
@@ -105,7 +123,10 @@ bool Introduction::show() {
}
delete anim;
- if (result) return true;
+ if (result) {
+ Sound.musicInterface_KillAll();
+ return true;
+ }
}
// Show battle pictures one frame at a time
@@ -119,12 +140,12 @@ bool Introduction::show() {
if (result) break;
} while (anim->step());
delete anim;
- if (result) return true;
-
- // Show final introduction screen
-
- showScreen(0x22, 0x21, 10000);
+
+ if (!result)
+ // Show final introduction screen
+ showScreen(0x22, 0x21, 10000);
+ Sound.musicInterface_KillAll();
return false;
}
diff --git a/engines/lure/lure.cpp b/engines/lure/lure.cpp
index f7c4272f0e..ada8f5081b 100644
--- a/engines/lure/lure.cpp
+++ b/engines/lure/lure.cpp
@@ -34,6 +34,7 @@
#include "lure/lure.h"
#include "lure/intro.h"
#include "lure/game.h"
+#include "lure/sound.h"
namespace Lure {
@@ -45,17 +46,16 @@ LureEngine::LureEngine(OSystem *system): Engine(system) {
Common::addSpecialDebugLevel(kLureDebugAnimations, "animations", "Animations debugging");
Common::addSpecialDebugLevel(kLureDebugHotspots, "hotspots", "Hotspots debugging");
Common::addSpecialDebugLevel(kLureDebugFights, "fights", "Fights debugging");
+ Common::addSpecialDebugLevel(kLureDebugSounds, "sounds", "Sounds debugging");
// Setup mixer
-/*
+
if (!_mixer->isReady()) {
warning("Sound initialization failed.");
}
_mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, ConfMan.getInt("sfx_volume"));
_mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, ConfMan.getInt("music_volume"));
- _mixer->setVolumeForSoundType(Audio::Mixer::kSpeechSoundType, ConfMan.getInt("speech_volume"));
-*/
_features = 0;
_game = 0;
@@ -106,7 +106,9 @@ LureEngine &LureEngine::getReference() {
int LureEngine::go() {
if (ConfMan.getInt("boot_param") == 0) {
// Show the introduction
+ Sound.loadSection(INTRO_SOUND_RESOURCE_ID);
Introduction *intro = new Introduction(*_screen, *_system);
+
intro->show();
delete intro;
}
@@ -114,6 +116,7 @@ int LureEngine::go() {
// Play the game
if (!_events->quitFlag) {
// Play the game
+ Sound.loadSection(MAIN_SOUND_RESOURCE_ID);
Game *gameInstance = new Game();
gameInstance->execute();
delete gameInstance;
@@ -169,8 +172,7 @@ bool LureEngine::loadGame(uint8 slotNumber) {
// Check for header
char buffer[5];
f->read(buffer, 5);
- if (memcmp(buffer, "lure", 5) != 0)
- {
+ if (memcmp(buffer, "lure", 5) != 0) {
warning(FAILED_MSG, slotNumber);
delete f;
return false;
@@ -179,8 +181,7 @@ bool LureEngine::loadGame(uint8 slotNumber) {
// Check language version
uint8 language = f->readByte();
uint8 version = f->readByte();
- if ((language != _language) || (version != LURE_DAT_MINOR))
- {
+ if ((language != _language) || (version != LURE_DAT_MINOR)) {
warning("loadGame: Failed to load slot %d - incorrect version", slotNumber);
delete f;
return false;
diff --git a/engines/lure/lure.h b/engines/lure/lure.h
index aa7f0ae93a..7ac0977900 100644
--- a/engines/lure/lure.h
+++ b/engines/lure/lure.h
@@ -71,6 +71,7 @@ public:
uint32 features() { return _features; }
uint8 game() { return _game; }
Disk &disk() { return *_disk; }
+ Common::Language getLanguage() { return _language; }
bool loadGame(uint8 slotNumber);
bool saveGame(uint8 slotNumber, Common::String &caption);
diff --git a/engines/lure/luredefs.h b/engines/lure/luredefs.h
index d5991a5807..ef48f6f452 100644
--- a/engines/lure/luredefs.h
+++ b/engines/lure/luredefs.h
@@ -34,7 +34,7 @@ namespace Lure {
#define SUPPORT_FILENAME "lure.dat"
#define LURE_DAT_MAJOR 1
-#define LURE_DAT_MINOR 20
+#define LURE_DAT_MINOR 21
#define LURE_DEBUG 1
@@ -45,7 +45,8 @@ enum {
kLureDebugScripts = 1 << 0,
kLureDebugAnimations = 1 << 1,
kLureDebugHotspots = 1 << 2,
- kLureDebugFights = 1 << 3
+ kLureDebugFights = 1 << 3,
+ kLureDebugSounds = 1 << 4
};
#define ERROR_BASIC 1
@@ -222,13 +223,15 @@ enum CursorType {CURSOR_ARROW = 0, CURSOR_DISK = 1, CURSOR_TIME_START = 2,
#define EXIT_HOTSPOT_ID_LIST 0x3f15
#define FIGHT_DATA_RESOURCE_ID 0x3f16
#define STRING_LIST_RESOURCE_ID 0x3f17
+#define SOUND_DESC_RESOURCE_ID 0x3f18
// Script constants
#define STARTUP_SCRIPT 0x23FC
// Miscellaneous resources
-#define CREDITS_RESOURCE_ID 0x7800
#define NAMES_RESOURCE_ID 9
+#define MAIN_SOUND_RESOURCE_ID 0xC
+#define INTRO_SOUND_RESOURCE_ID 0x31
#define NOONE_ID 0x3E7
#define PLAYER_ID 0x3E8
#define RATPOUCH_ID 0x3E9
@@ -249,12 +252,16 @@ enum CursorType {CURSOR_ARROW = 0, CURSOR_DISK = 1, CURSOR_TIME_START = 2,
#define SKORL_FIGHTER_ID 0x444
#define START_EXIT_ID 0x2710
#define BOTTLE_HOTSPOT_ID 0x2710
+#define CELL_DOOR_HOTSPOT_ID 0x2712
#define BRICKS_ID 0x2714
#define BOOK_ID 0x2723
#define START_NONVISUAL_HOTSPOT_ID 0x7530
+#define CREDITS_RESOURCE_ID 0x7800
+#define RESTART_RESOURCE_ID 0x7900
// Milliseconds delay between game frames
#define GAME_FRAME_DELAY 80
+#define GAME_TICK_DELAY 20
// Tick proc constants
#define STANDARD_CHARACTER_TICK_PROC 0x4f82
@@ -287,12 +294,14 @@ enum CursorType {CURSOR_ARROW = 0, CURSOR_DISK = 1, CURSOR_TIME_START = 2,
#define EWAN_ALT_ANIM_ID 0x59ED
#define PLAYER_ANIM_ID 0x5C80
#define SELENA_ANIM_ID 0x5CAA
+#define DEFAULT_VOLUME 192
#define CONVERSE_COUNTDOWN_SIZE 40
#define IDLE_COUNTDOWN_SIZE 15
#define MAX_TELL_COMMANDS 8
#define MAX_SAVEGAME_SLOTS 10
+#define ROOMNUM_VILLAGE_SHOP 35
#define ROOMNUM_CAVE 38
#define ROOMNUM_CELLAR 42
#define ROOMNUM_DINING_HALL 45
diff --git a/engines/lure/menu.cpp b/engines/lure/menu.cpp
index 3bb6769ff7..7dfb6e2a57 100644
--- a/engines/lure/menu.cpp
+++ b/engines/lure/menu.cpp
@@ -106,8 +106,7 @@ uint8 Menu::execute() {
while (events.pollEvent()) {
if (events.quitFlag) return MENUITEM_NONE;
- if (mouse.y() < MENUBAR_Y_SIZE)
- {
+ if (mouse.y() < MENUBAR_Y_SIZE) {
MenuRecord *p = getMenuAt(mouse.x());
if (_selectedMenu != p) {
diff --git a/engines/lure/res.cpp b/engines/lure/res.cpp
index 4da38eddc7..b0e99b5be5 100644
--- a/engines/lure/res.cpp
+++ b/engines/lure/res.cpp
@@ -42,11 +42,19 @@ Resources &Resources::getReference() {
Resources::Resources() {
int_resources = this;
reloadData();
+
+ // Load the string list
+ MemoryBlock *mb = Disk::getReference().getEntry(STRING_LIST_RESOURCE_ID);
+ _stringList.load(mb);
+ delete mb;
}
Resources::~Resources() {
// Free up any loaded data
freeData();
+
+ // Free up constant data
+ _stringList.clear();
}
void Resources::freeData() {
@@ -61,12 +69,16 @@ void Resources::freeData() {
_randomActions.clear();
_indexedRoomExitHospots.clear();
_pausedList.clear();
- _stringList.clear();
+ _actionsList.clear();
+ _coordinateList.clear();
+ _talkHeaders.clear();
+ _talkData.clear();
+ free(_hotspotScriptData);
delete _paletteSubset;
delete _scriptData;
delete _script2Data;
- free(_hotspotScriptData);
+ delete _talkDialogData;
delete _messagesData;
delete _cursors;
delete [] _charOffsets;
@@ -77,6 +89,13 @@ struct AnimRecordTemp {
MovementDataList *list;
};
+void Resources::reset() {
+ freeData();
+
+ _fieldList.reset();
+ reloadData();
+}
+
void Resources::reloadData() {
Disk &d = Disk::getReference();
MemoryBlock *mb, *paths;
@@ -312,11 +331,6 @@ void Resources::reloadData() {
indexedRec++;
}
- // Load the string list
- mb = d.getEntry(STRING_LIST_RESOURCE_ID);
- _stringList.load(mb);
- delete mb;
-
// Initialise delay list
_delayList.clear(true);
@@ -341,7 +355,7 @@ RoomExitJoinData *Resources::getExitJoin(uint16 hotspotId) {
for (i = _exitJoins.begin(); i != _exitJoins.end(); ++i) {
RoomExitJoinData *rec = *i;
- if ((rec->hotspot1Id == hotspotId) || (rec->hotspot2Id == hotspotId))
+ if ((rec->hotspots[0].hotspotId == hotspotId) || (rec->hotspots[1].hotspotId == hotspotId))
return rec;
}
@@ -645,8 +659,7 @@ void Resources::setTalkData(uint16 offset) {
error("Unknown talk entry offset %d requested", offset);
}
-void Resources::saveToStream(Common::WriteStream *stream)
-{
+void Resources::saveToStream(Common::WriteStream *stream) {
_hotspotData.saveToStream(stream);
_activeHotspots.saveToStream(stream);
_fieldList.saveToStream(stream);
diff --git a/engines/lure/res.h b/engines/lure/res.h
index 7c9970f27f..86d5ad5d95 100644
--- a/engines/lure/res.h
+++ b/engines/lure/res.h
@@ -88,12 +88,13 @@ private:
int _talkStartEntry;
uint16 _talkingCharacter;
+ void reloadData();
void freeData();
public:
Resources();
~Resources();
static Resources &getReference();
- void reloadData();
+ void reset();
byte *getResource(uint16 resId);
RoomDataList &roomData() { return _roomData; }
diff --git a/engines/lure/res_struct.cpp b/engines/lure/res_struct.cpp
index 12cf61a58a..f4506406ef 100644
--- a/engines/lure/res_struct.cpp
+++ b/engines/lure/res_struct.cpp
@@ -30,47 +30,47 @@
namespace Lure {
-const Action sortedActions[] = {ASK, BRIBE, BUY, CLOSE, DRINK, EXAMINE, GET, GIVE,
+extern const Action sortedActions[] = {ASK, BRIBE, BUY, CLOSE, DRINK, EXAMINE, GET, GIVE,
GO_TO, LOCK, LOOK, LOOK_AT, LOOK_THROUGH, OPEN, OPERATE, PULL, PUSH, RETURN,
STATUS, TALK_TO, TELL, UNLOCK, USE, NONE};
-int actionNumParams[NPC_JUMP_ADDRESS+1] = {0,
+extern const int actionNumParams[NPC_JUMP_ADDRESS+1] = {0,
1, 0, 1, 1, 1, 1, 1, 1, 1, 2, 2, 1, 1, 1, 1, 1, 1, 2, 0, 1,
0, 1, 1, 1, 1, 0, 0, 2, 1, 1, 0, 0, 1, 1, 2, 2, 5, 2, 2, 1};
// Barman related frame lists
-uint16 basicPolish[] = {8+13,8+14,8+15,8+16,8+17,8+18,8+17,8+16,8+15,8+14,
+static const uint16 basicPolish[] = {8+13,8+14,8+15,8+16,8+17,8+18,8+17,8+16,8+15,8+14,
8+15,8+16,8+17,8+18,8+17,8+16,8+15,8+14,8+13,0};
-uint16 sidsFetch[] = {12+1,12+2,12+3,12+4,12+5,12+6,12+5,12+6,12+5,12+4,12+3,12+7,12+8,0};
+static const uint16 sidsFetch[] = {12+1,12+2,12+3,12+4,12+5,12+6,12+5,12+6,12+5,12+4,12+3,12+7,12+8,0};
-uint16 nelliesScratch[] = {11+1,11+2,11+3,11+4,11+5,11+4,11+5,11+4,11+5,11+4,11+3,11+2,11+1,0};
+static const uint16 nelliesScratch[] = {11+1,11+2,11+3,11+4,11+5,11+4,11+5,11+4,11+5,11+4,11+3,11+2,11+1,0};
-uint16 nelliesFetch[] = {1,2,3,4,5,4,5,4,3,2,6,7,0};
+static const uint16 nelliesFetch[] = {1,2,3,4,5,4,5,4,3,2,6,7,0};
-uint16 ewansFetch[] = {13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,0};
+static const uint16 ewansFetch[] = {13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,0};
-uint16 ewanExtraGraphic1[]= {
+static const uint16 ewanExtraGraphic1[]= {
28,29,30,31,32,33,34,35,36,37,
38,39,40,41,42,43,44,45,46,47,
48,
40,39,38,37,36,35,34,33,32,31,30,29,28,
0};
-uint16 ewanExtraGraphic2[] = {
+static const uint16 ewanExtraGraphic2[] = {
1,2,3,4,5,6,7,8,9,
10,11,12,13,14,15,16,17,18,19,
20,21,22,23,24,0};
-BarEntry barList[3] = {
+static const BarEntry default_barList[3] = {
{29, SID_ID, {{0, 0}, {0, 0}, {0, 0}, {0, 0}}, {&basicPolish[0], &sidsFetch[0], NULL, NULL}, 13, NULL},
{32, NELLIE_ID, {{0, 0}, {0, 0}, {0, 0}, {0, 0}}, {&nelliesScratch[0], &nelliesFetch[0], NULL, NULL}, 14, NULL},
{35, EWAN_ID, {{0, 0}, {0, 0}, {0, 0}, {0, 0}}, {&ewansFetch[0], &ewansFetch[0],
&ewanExtraGraphic1[0], &ewanExtraGraphic2[0]}, 16, NULL}
};
-RoomTranslationRecord roomTranslations[] = {
+extern const RoomTranslationRecord roomTranslations[] = {
{0x1E, 0x13}, {0x07, 0x08}, {0x1C, 0x12}, {0x26, 0x0F},
{0x27, 0x0F}, {0x28, 0x0F}, {0x29, 0x0F}, {0x22, 0x0A},
{0x23, 0x13}, {0x24, 0x14}, {0x31, 0x2C}, {0x2F, 0x2C},
@@ -308,28 +308,29 @@ void RoomDataList::loadFromStream(ReadStream *stream) {
// Room exit joins class
RoomExitJoinData::RoomExitJoinData(RoomExitJoinResource *rec) {
- hotspot1Id = FROM_LE_16(rec->hotspot1Id);
- h1CurrentFrame = rec->h1CurrentFrame;
- h1DestFrame = rec->h1DestFrame;
- h1OpenSound = rec->h1OpenSound;
- h1CloseSound = rec->h1CloseSound;
- hotspot2Id = FROM_LE_16(rec->hotspot2Id);
- h2CurrentFrame = rec->h2CurrentFrame;
- h2DestFrame = rec->h2DestFrame;
- h2OpenSound = rec->h2OpenSound;
- h2CloseSound = rec->h2CloseSound;
+ hotspots[0].hotspotId = FROM_LE_16(rec->hotspot1Id);
+ hotspots[0].currentFrame = rec->h1CurrentFrame;
+ hotspots[0].destFrame = rec->h1DestFrame;
+ hotspots[0].openSound = rec->h1OpenSound;
+ hotspots[0].closeSound = rec->h1CloseSound;
+ hotspots[1].hotspotId = FROM_LE_16(rec->hotspot2Id);
+ hotspots[1].currentFrame = rec->h2CurrentFrame;
+ hotspots[1].destFrame = rec->h2DestFrame;
+ hotspots[1].openSound = rec->h2OpenSound;
+ hotspots[1].closeSound = rec->h2CloseSound;
blocked = rec->blocked;
}
void RoomExitJoinList::saveToStream(WriteStream *stream) {
for (RoomExitJoinList::iterator i = begin(); i != end(); ++i) {
RoomExitJoinData *rec = *i;
- stream->writeUint16LE(rec->hotspot1Id);
- stream->writeUint16LE(rec->hotspot2Id);
- stream->writeByte(rec->h1CurrentFrame);
- stream->writeByte(rec->h1DestFrame);
- stream->writeByte(rec->h2CurrentFrame);
- stream->writeByte(rec->h2DestFrame);
+
+ stream->writeUint16LE(rec->hotspots[0].hotspotId);
+ stream->writeUint16LE(rec->hotspots[1].hotspotId);
+ stream->writeByte(rec->hotspots[0].currentFrame);
+ stream->writeByte(rec->hotspots[0].destFrame);
+ stream->writeByte(rec->hotspots[1].currentFrame);
+ stream->writeByte(rec->hotspots[1].destFrame);
stream->writeByte(rec->blocked);
}
@@ -345,13 +346,14 @@ void RoomExitJoinList::loadFromStream(ReadStream *stream) {
if (hotspot1Id == 0xffff) error("Invalid room exit join list");
uint16 hotspot2Id = stream->readUint16LE();
- if ((rec->hotspot1Id != hotspot1Id) || (rec->hotspot2Id != hotspot2Id))
+ if ((rec->hotspots[0].hotspotId != hotspot1Id) ||
+ (rec->hotspots[1].hotspotId != hotspot2Id))
break;
- rec->h1CurrentFrame = stream->readByte();
- rec->h1DestFrame = stream->readByte();
- rec->h2CurrentFrame = stream->readByte();
- rec->h2DestFrame = stream->readByte();
+ rec->hotspots[0].currentFrame = stream->readByte();
+ rec->hotspots[0].destFrame = stream->readByte();
+ rec->hotspots[1].currentFrame = stream->readByte();
+ rec->hotspots[1].destFrame = stream->readByte();
rec->blocked = stream->readByte();
}
@@ -429,6 +431,8 @@ HotspotData::HotspotData(HotspotResource *rec) {
pauseCtr = 0;
actionHotspotId = 0;
talkOverride = 0;
+ talkGate = 0;
+ scriptHotspotId = 0;
}
void HotspotData::saveToStream(WriteStream *stream) {
@@ -517,8 +521,7 @@ void HotspotData::loadFromStream(ReadStream *stream) {
void HotspotDataList::saveToStream(WriteStream *stream) {
iterator i;
- for (i = begin(); i != end(); ++i)
- {
+ for (i = begin(); i != end(); ++i) {
HotspotData *hotspot = *i;
stream->writeUint16LE(hotspot->hotspotId);
hotspot->saveToStream(stream);
@@ -530,8 +533,7 @@ void HotspotDataList::loadFromStream(ReadStream *stream) {
Resources &res = Resources::getReference();
iterator i;
uint16 hotspotId = stream->readUint16LE();
- while (hotspotId != 0)
- {
+ while (hotspotId != 0) {
HotspotData *hotspot = res.getHotspot(hotspotId);
assert(hotspot);
hotspot->loadFromStream(stream);
@@ -963,8 +965,7 @@ RandomActionSet::~RandomActionSet() {
RandomActionSet *RandomActionList::getRoom(uint16 roomNumber) {
iterator i;
- for (i = begin(); i != end(); ++i)
- {
+ for (i = begin(); i != end(); ++i) {
RandomActionSet *v = *i;
if (v->roomNumber() == roomNumber)
return v;
@@ -1104,8 +1105,7 @@ int PausedCharacterList::check(uint16 charId, int numImpinging, uint16 *impingin
// There was, so move to next impinging character entry
continue;
- if ((hotspot->hotspotId() == PLAYER_ID) && !hotspot->coveredFlag())
- {
+ if ((hotspot->hotspotId() == PLAYER_ID) && !hotspot->coveredFlag()) {
hotspot->updateMovement();
return 1;
}
@@ -1137,39 +1137,37 @@ int PausedCharacterList::check(uint16 charId, int numImpinging, uint16 *impingin
// Wrapper class for the barman lists
-BarEntry &BarmanLists::getDetails(uint16 roomNumber)
-{
+BarmanLists::BarmanLists() {
+ for (int index = 0; index < 3; ++index)
+ _barList[index] = default_barList[index];
+}
+
+BarEntry &BarmanLists::getDetails(uint16 roomNumber) {
for (int index = 0; index < 3; ++index)
- if (barList[index].roomNumber == roomNumber)
- return barList[index];
+ if (_barList[index].roomNumber == roomNumber)
+ return _barList[index];
error("Invalid room %d specified for barman details retrieval", roomNumber);
}
-void BarmanLists::saveToStream(Common::WriteStream *stream)
-{
- for (int index = 0; index < 2; ++index)
- {
- uint16 value = (barList[index].currentCustomer - &barList[index].customers[0]) / sizeof(BarEntry);
+void BarmanLists::saveToStream(Common::WriteStream *stream) {
+ for (int index = 0; index < 2; ++index) {
+ uint16 value = (_barList[index].currentCustomer - &_barList[index].customers[0]) / sizeof(BarEntry);
stream->writeUint16LE(value);
- for (int ctr = 0; ctr < NUM_SERVE_CUSTOMERS; ++ctr)
- {
- stream->writeUint16LE(barList[index].customers[ctr].hotspotId);
- stream->writeByte(barList[index].customers[ctr].serveFlags);
+ for (int ctr = 0; ctr < NUM_SERVE_CUSTOMERS; ++ctr) {
+ stream->writeUint16LE(_barList[index].customers[ctr].hotspotId);
+ stream->writeByte(_barList[index].customers[ctr].serveFlags);
}
}
}
-void BarmanLists::loadFromStream(Common::ReadStream *stream)
-{
- for (int index = 0; index < 2; ++index)
- {
+void BarmanLists::loadFromStream(Common::ReadStream *stream) {
+ for (int index = 0; index < 2; ++index) {
int16 value = stream->readUint16LE();
- barList[index].currentCustomer = (value == 0) ? NULL : &barList[index].customers[value];
+ _barList[index].currentCustomer = (value == 0) ? NULL : &_barList[index].customers[value];
- for (int ctr = 0; ctr < NUM_SERVE_CUSTOMERS; ++ctr)
- {
- barList[index].customers[ctr].hotspotId = stream->readUint16LE();
- barList[index].customers[ctr].serveFlags = stream->readByte();
+ for (int ctr = 0; ctr < NUM_SERVE_CUSTOMERS; ++ctr) {
+ _barList[index].customers[ctr].hotspotId = stream->readUint16LE();
+ _barList[index].customers[ctr].serveFlags = stream->readByte();
}
}
}
@@ -1202,12 +1200,16 @@ void StringList::clear() {
// Field list and miscellaneous variables
ValueTableData::ValueTableData() {
+ reset();
+}
+
+void ValueTableData::reset() {
_numGroats = 0;
_playerNewPos.roomNumber = 0;
_playerNewPos.position.x = 0;
_playerNewPos.position.y = 0;
_flags = GAMEFLAG_4 | GAMEFLAG_1;
- _hdrFlagMask = 1;
+ _hdrFlagMask = 1;
for (uint16 index = 0; index < NUM_VALUE_FIELDS; ++index)
_fieldList[index] = 0;
@@ -1242,8 +1244,7 @@ void ValueTableData::setField(FieldName fieldName, uint16 value) {
setField((uint16) fieldName, value);
}
-void ValueTableData::saveToStream(Common::WriteStream *stream)
-{
+void ValueTableData::saveToStream(Common::WriteStream *stream) {
// Write out the special fields
stream->writeUint16LE(_numGroats);
stream->writeSint16LE(_playerNewPos.position.x);
@@ -1257,8 +1258,7 @@ void ValueTableData::saveToStream(Common::WriteStream *stream)
stream->writeUint16LE(_fieldList[index]);
}
-void ValueTableData::loadFromStream(Common::ReadStream *stream)
-{
+void ValueTableData::loadFromStream(Common::ReadStream *stream) {
// Load special fields
_numGroats = stream->readUint16LE();
_playerNewPos.position.x = stream->readSint16LE();
diff --git a/engines/lure/res_struct.h b/engines/lure/res_struct.h
index 4d2c55e6b1..81ecd87563 100644
--- a/engines/lure/res_struct.h
+++ b/engines/lure/res_struct.h
@@ -225,6 +225,18 @@ struct RoomExitIndexedHotspotResource {
uint16 hotspotId;
} PACKED_STRUCT;
+enum SoundDescFlags {SF_IN_USE = 1, SF_RESTORE = 2};
+
+// In desc entry, numChannels: bits 0-1 # roland, bits 2-3 #adlib, bits 4-5 #internal
+
+struct SoundDescResource {
+ uint8 soundNumber;
+ uint8 channel;
+ uint8 numChannels;
+ uint8 flags;
+ uint8 volume;
+} PACKED_STRUCT;
+
#include "common/pack-end.h" // END STRUCT PACKING
/**
@@ -242,23 +254,28 @@ public:
}
void clear() {
- typename Common::List<T>::iterator i;
- for (i = Common_List::begin(); i != Common_List::end(); ++i)
- delete *i;
- Common_List::clear();
+ typename Common_List::iterator i = Common_List::begin();
+ while (i != Common_List::end()) {
+ T v = *i;
+ i = Common_List::erase(i);
+ delete v;
+ }
}
- typename Common::List<T>::iterator erase(typename Common::List<T>::iterator pos) {
- delete *pos;
- return Common_List::erase(pos);
+ typename Common_List::iterator erase(typename Common_List::iterator pos) {
+ T obj = *pos;
+ typename Common_List::iterator result = Common_List::erase(pos);
+ delete obj;
+ return result;
}
- typename Common::List<T>::iterator erase(typename Common::List<T>::iterator first,
- typename Common::List<T>::iterator last) {
- typename Common::List<T>::iterator i;
- for (i = first; i != last; ++i)
- delete *i;
- return Common_List::erase(first, last);
+ typename Common_List::iterator erase(typename Common_List::iterator first,
+ typename Common_List::iterator last) {
+
+ while (first != last)
+ erase(first++);
+
+ return last;
}
};
@@ -353,22 +370,21 @@ public:
void loadFromStream(ReadStream *stream);
};
+struct RoomExitJoinStruct {
+ uint16 hotspotId;
+ byte currentFrame;
+ byte destFrame;
+ uint8 openSound;
+ uint8 closeSound;
+};
+
class RoomExitJoinData {
public:
RoomExitJoinData(RoomExitJoinResource *rec);
- uint16 hotspot1Id;
- byte h1CurrentFrame;
- byte h1DestFrame;
- uint8 h1OpenSound;
- uint8 h1CloseSound;
- uint16 hotspot2Id;
- byte h2CurrentFrame;
- byte h2DestFrame;
- uint8 h2OpenSound;
- uint8 h2CloseSound;
+ RoomExitJoinStruct hotspots[2];
+
byte blocked;
- uint32 unknown;
};
class RoomExitJoinList: public ManagedList<RoomExitJoinData *> {
@@ -618,7 +634,7 @@ public:
// The following classes holds the data for NPC schedules
-extern int actionNumParams[NPC_JUMP_ADDRESS+1];
+extern const int actionNumParams[NPC_JUMP_ADDRESS+1];
class CharacterScheduleSet;
@@ -730,13 +746,16 @@ struct BarEntry {
uint16 roomNumber;
uint16 barmanId;
ServeEntry customers[NUM_SERVE_CUSTOMERS];
- uint16 *graphics[4];
+ const uint16 *graphics[4];
uint16 gridLine;
ServeEntry *currentCustomer;
};
class BarmanLists {
+ BarEntry _barList[3];
public:
+ BarmanLists();
+
BarEntry &getDetails(uint16 roomNumber);
void saveToStream(Common::WriteStream *stream);
void loadFromStream(Common::ReadStream *stream);
@@ -749,7 +768,7 @@ struct RoomTranslationRecord {
uint8 destRoom;
};
-extern RoomTranslationRecord roomTranslations[];
+extern const RoomTranslationRecord roomTranslations[];
enum StringEnum {S_CREDITS = 25, S_RESTART_GAME = 26, S_SAVE_GAME = 27, S_RESTORE_GAME = 28,
S_QUIT = 29, S_FAST_TEXT = 30, S_SLOW_TEXT = 31, S_SOUND_ON = 32, S_SOUND_OFF = 33,
@@ -797,7 +816,8 @@ enum FieldName {
BOTTLE_FILLED = 18,
TALK_INDEX = 19,
SACK_CUT = 20,
- ROOM_EXIT_ANIMATION = 76
+ ROOM_EXIT_ANIMATION = 76,
+ AREA_FLAG = 82
};
enum GameFlags {
@@ -827,6 +847,7 @@ private:
bool isKnownField(uint16 fieldIndex);
public:
ValueTableData();
+ void reset();
uint16 getField(uint16 fieldIndex);
uint16 getField(FieldName fieldName);
diff --git a/engines/lure/room.cpp b/engines/lure/room.cpp
index b48b50197b..acab44deea 100644
--- a/engines/lure/room.cpp
+++ b/engines/lure/room.cpp
@@ -492,13 +492,13 @@ void Room::update() {
}
void Room::setRoomNumber(uint16 newRoomNumber, bool showOverlay) {
- Resources &r = Resources::getReference();
+ Resources &res = Resources::getReference();
Game &game = Game::getReference();
Mouse &mouse = Mouse::getReference();
mouse.pushCursorNum(CURSOR_DISK);
- _roomData = r.getRoom(newRoomNumber);
+ _roomData = res.getRoom(newRoomNumber);
if (!_roomData)
error("Tried to change to non-existant room: %d", newRoomNumber);
bool leaveFlag = (_layers[0] && (newRoomNumber != _roomNumber) && (_roomNumber != 0));
@@ -512,6 +512,7 @@ void Room::setRoomNumber(uint16 newRoomNumber, bool showOverlay) {
}
_screen.empty();
+ _screen.setPaletteEmpty(GAME_COLOURS);
_numLayers = _roomData->numLayers;
if (showOverlay) ++_numLayers;
@@ -521,36 +522,38 @@ void Room::setRoomNumber(uint16 newRoomNumber, bool showOverlay) {
_layers[layerNum] = new RoomLayer(_roomData->layers[layerNum],
layerNum == 0);
- // Load in the game palette and set the non-room specific colours at the top end of the palette
+ // Load in the game palette, which contains at it's top end general GUI element colours
Palette mainPalette(GAME_PALETTE_RESOURCE_ID);
- _screen.setPalette(&mainPalette, MAIN_PALETTE_SIZE, GAME_COLOURS - MAIN_PALETTE_SIZE);
+ _screen.setPalette(&mainPalette, 0, GAME_COLOURS);
+
+ // Generate the palette for the room that will be faded in
+ Palette p(MAIN_PALETTE_SIZE, NULL, RGB64);
+ Palette tempPalette(paletteId);
+ p.copyFrom(&tempPalette);
+ res.insertPaletteSubset(p);
// Set the new room number
- r.fieldList().setField(ROOM_NUMBER, newRoomNumber);
+ res.fieldList().setField(ROOM_NUMBER, newRoomNumber);
if (_roomData->sequenceOffset != 0xffff)
Script::execute(_roomData->sequenceOffset);
loadRoomHotspots();
- if (_roomData->exitTime != 0xffff)
- {
+ if ((_roomData->exitTime != 0xffff) && (_roomData->exitTime != 0)) {
// If time has passed, animation ticks needed before room is displayed
int numSeconds = (g_system->getMillis() - _roomData->exitTime) / 1000;
if (numSeconds > 300) numSeconds = 300;
+ game.preloadFlag() = true;
while (numSeconds-- > 0)
- game.tick(true);
+ game.tick();
+ game.preloadFlag() = false;
}
+ game.tick();
update();
_screen.update();
-
- // Generate the palette for the room and fade it in
- Palette p(MAIN_PALETTE_SIZE, NULL, RGB64);
- Palette tempPalette(paletteId);
- p.copyFrom(&tempPalette);
- r.insertPaletteSubset(p);
_screen.paletteFadeIn(&p);
mouse.popCursor();
diff --git a/engines/lure/screen.cpp b/engines/lure/screen.cpp
index 0cd2dd9357..552e609b84 100644
--- a/engines/lure/screen.cpp
+++ b/engines/lure/screen.cpp
@@ -55,11 +55,11 @@ Screen::~Screen() {
// setPaletteEmpty
// Defaults the palette to an empty set
-void Screen::setPaletteEmpty() {
+void Screen::setPaletteEmpty(int numEntries) {
delete _palette;
_palette = new Palette();
- _system.setPalette(_palette->data(), 0, GAME_COLOURS);
+ _system.setPalette(_palette->data(), 0, numEntries);
_system.updateScreen();
}
@@ -76,9 +76,8 @@ void Screen::setPalette(Palette *p) {
// Variation that allows the specification of a subset of a palette passed in to be copied
void Screen::setPalette(Palette *p, uint16 start, uint16 num) {
- _palette->palette()->copyFrom(p->palette(), start * PALETTE_FADE_INC_SIZE,
- start * PALETTE_FADE_INC_SIZE, num * PALETTE_FADE_INC_SIZE);
- _system.setPalette(_palette->data(), 0, GAME_COLOURS);
+ _palette->palette()->copyFrom(p->palette(), start * 4, start * 4, num * 4);
+ _system.setPalette(_palette->data(), start, num);
_system.updateScreen();
}
@@ -96,8 +95,7 @@ void Screen::paletteFadeIn(Palette *p) {
byte *pFinal = p->data();
byte *pCurrent = _palette->data();
- for (int palCtr = 0; palCtr < p->numEntries() * PALETTE_FADE_INC_SIZE; ++palCtr, ++pCurrent, ++pFinal)
- {
+ for (int palCtr = 0; palCtr < p->numEntries() * PALETTE_FADE_INC_SIZE; ++palCtr, ++pCurrent, ++pFinal) {
if (palCtr % PALETTE_FADE_INC_SIZE == (PALETTE_FADE_INC_SIZE - 1)) continue;
bool isDifferent = *pCurrent < *pFinal;
@@ -111,7 +109,7 @@ void Screen::paletteFadeIn(Palette *p) {
}
if (changed) {
- _system.setPalette(_palette->data(), 0, GAME_COLOURS);
+ _system.setPalette(_palette->data(), 0, p->numEntries());
_system.updateScreen();
_system.delayMillis(20);
events.pollEvent();
@@ -143,7 +141,7 @@ void Screen::paletteFadeOut(int numEntries) {
}
if (changed) {
- _system.setPalette(_palette->data(), 0, GAME_COLOURS);
+ _system.setPalette(_palette->data(), 0, numEntries);
_system.updateScreen();
_system.delayMillis(20);
events.pollEvent();
diff --git a/engines/lure/screen.h b/engines/lure/screen.h
index 7182c4236b..90db7ee314 100644
--- a/engines/lure/screen.h
+++ b/engines/lure/screen.h
@@ -47,12 +47,12 @@ public:
~Screen();
static Screen &getReference();
- void setPaletteEmpty();
+ void setPaletteEmpty(int numEntries = RES_PALETTE_ENTRIES);
void setPalette(Palette *p);
void setPalette(Palette *p, uint16 start, uint16 num);
Palette &getPalette() { return *_palette; }
void paletteFadeIn(Palette *p);
- void paletteFadeOut(int numEntries = MAIN_PALETTE_SIZE);
+ void paletteFadeOut(int numEntries = RES_PALETTE_ENTRIES);
void resetPalette();
void empty();
void update();
diff --git a/engines/lure/scripts.cpp b/engines/lure/scripts.cpp
index 3ce1b916b3..bba364bcf2 100644
--- a/engines/lure/scripts.cpp
+++ b/engines/lure/scripts.cpp
@@ -38,12 +38,12 @@ namespace Lure {
// This list of hotspot Ids are used by sequence method #5 to deallocate a set
// of hotspot Ids at once
-uint16 dealloc_list_1[] = {0x13F2, 0x418, 0x2711, 0x2712, 0x40D, 0x3EA, 0x411, 0};
-uint16 dealloc_list_2[] = {0x2729, 0x272A, 0x272B, 0x272C, 0x272E, 0x272E, 0x272F, 0};
-uint16 dealloc_list_3[] = {0x3EF, 0x3E9, 0x3EB, 0x3EC, 0x3ED, 0x3EE, 0x3F0, 0x3F1,
+static const uint16 dealloc_list_1[] = {0x13F2, 0x418, 0x2711, 0x2712, 0x40D, 0x3EA, 0x411, 0};
+static const uint16 dealloc_list_2[] = {0x2729, 0x272A, 0x272B, 0x272C, 0x272E, 0x272E, 0x272F, 0};
+static const uint16 dealloc_list_3[] = {0x3EF, 0x3E9, 0x3EB, 0x3EC, 0x3ED, 0x3EE, 0x3F0, 0x3F1,
0x420, 0x429, 0x436, 0x2715, 0x2716, 0x2717, 0x2718, 0x2719, 0x271A, 0x271E,
0x271F, 0x2720, 0x2721, 0x2722, 0x2725, 0x2726, 0};
-uint16 *hotspot_dealloc_set[4] = {&dealloc_list_1[0], &dealloc_list_2[0],
+static const uint16 *hotspot_dealloc_set[4] = {&dealloc_list_1[0], &dealloc_list_2[0],
&dealloc_list_3[1], &dealloc_list_3[0]};
/*------------------------------------------------------------------------*/
@@ -75,8 +75,8 @@ void Script::setHotspotScript(uint16 hotspotId, uint16 scriptIndex, uint16 v3) {
}
}
-void Script::addSound2(uint16 soundId, uint16 v2, uint16 v3) {
- // TODO: Not yet implemented
+void Script::addSound2(uint16 soundIndex, uint16 v2, uint16 v3) {
+ Sound.addSound2(soundIndex);
}
// Sets the bitmask indicating what group of rooms/hotspots to display when the
@@ -99,7 +99,7 @@ void Script::deactivateHotspotSet(uint16 listIndex, uint16 v2, uint16 v3) {
if (listIndex > 3)
error("Script::deactiveHotspotSet - Invalid list index");
Resources &res = Resources::getReference();
- uint16 *hotspotId = hotspot_dealloc_set[listIndex];
+ const uint16 *hotspotId = hotspot_dealloc_set[listIndex];
while (*hotspotId != 0) {
res.deactivateHotspot(*hotspotId);
@@ -132,8 +132,7 @@ void Script::deactivateHotspot(uint16 hotspotId, uint16 v2, uint16 v3) {
hs->layer = 0xff;
}
-// Sets the offset for the table of action sequence offsets for the given
-// hotspot
+// Sets the offset for the table of action sequence offsets for the given hotspot
void Script::setDesc(uint16 hotspotId, uint16 descId, uint16 v3) {
Resources &res = Resources::getReference();
@@ -151,8 +150,8 @@ void Script::addDelayedSequence(uint16 seqOffset, uint16 delay, uint16 canClear)
// Stops the specified sound
-void Script::killSound(uint16 soundId, uint16 v2, uint16 v3) {
- // TODO
+void Script::killSound(uint16 soundNumber, uint16 v2, uint16 v3) {
+ Sound.musicInterface_Stop(soundNumber);
}
// Checks whether the given character is in the specified room, and stores
@@ -179,8 +178,8 @@ void Script::setHotspotName(uint16 hotspotId, uint16 nameId, uint16 v3) {
// Unsure about this method, but at the moment I think it plays a sound
-void Script::addSound(uint16 v1, uint16 v2, uint16 v3) {
- // TODO: No implementation currently
+void Script::addSound(uint16 soundIndex, uint16 v2, uint16 v3) {
+ Sound.addSound(soundIndex);
}
void Script::endgameSequence(uint16 v1, uint16 v2, uint16 v3) {
@@ -251,10 +250,10 @@ void Script::startSpeakingToNoone(uint16 characterId, uint16 stringId, uint16 v3
charHotspot->converse(NOONE_ID, stringId, false);
}
+// Stops playing the specified sound index
-void Script::playMusic(uint16 musicNum, uint16 v2, uint16 v3) {
- // TODO: Play a given music
- warning("TODO: Play music #%d", musicNum);
+void Script::stopSound(uint16 soundIndex, uint16 v2, uint16 v3) {
+ Sound.stopSound(soundIndex);
}
// Gets the current blocked state for the given door and stores it in the
@@ -277,8 +276,7 @@ void Script::isSkorlInCell(uint16 v1, uint16 v2, uint16 v3) {
// Called by the script when Ratpouch is pushing the bricks in the Outer Cell
-void Script::ratpouchPushBricks(uint16 v1, uint16 v2, uint16 v3)
-{
+void Script::ratpouchPushBricks(uint16 v1, uint16 v2, uint16 v3) {
Resources &res = Resources::getReference();
// Mark the bricks exit as now open
@@ -309,8 +307,7 @@ void Script::characterChangeRoom(uint16 y, uint16 x, uint16 roomNumber) {
// Pauses Ratpouch for a long period (as good as idefinite)
-void Script::pauseRatpouch(uint16 v1, uint16 v2, uint16 v3)
-{
+void Script::pauseRatpouch(uint16 v1, uint16 v2, uint16 v3) {
Resources &res = Resources::getReference();
Hotspot *ratpouch = res.getActiveHotspot(RATPOUCH_ID);
assert(ratpouch);
@@ -599,7 +596,7 @@ void Script::moveCharacterToPlayer(uint16 characterId, uint16 v2, uint16 v3) {
return;
uint16 destRoom = playerHotspot->roomNumber();
- RoomTranslationRecord *rec;
+ const RoomTranslationRecord *rec;
for (rec = &roomTranslations[0]; rec->srcRoom != 0; ++rec) {
if (rec->srcRoom == destRoom) {
destRoom = rec->destRoom;
@@ -714,17 +711,20 @@ void Script::randomToGeneral(uint16 maxVal, uint16 minVal, uint16 v3) {
// Checks the status of the cell door, and starts music depending on it's state
void Script::checkCellDoor(uint16 v1, uint16 v2, uint16 v3) {
- // In the original game, this method checks to see if the cell door
- // is currently open, if it is, starts a music sequence.
- // TODO: Implement starting music if cell door is open
+ Resources &res = Resources::getReference();
+ RoomExitJoinData *joinRec = res.getExitJoin(CELL_DOOR_HOTSPOT_ID);
+
+ if ((joinRec->blocked == 0) && (res.fieldList().getField(TORCH_HIDE) != 0))
+ Sound.addSound(0x15);
}
// Checks if a sound is running
-void Script::checkSound(uint16 hotspotId, uint16 actions, uint16 v3) {
- // For now, simply set the general value field so that the Skorl schedule
- // will work properly
- Resources::getReference().fieldList().setField(GENERAL, 0);
+void Script::checkSound(uint16 soundNumber, uint16 v2, uint16 v3) {
+ Sound.tidySounds();
+
+ SoundDescResource *rec = Sound.findSound(soundNumber);
+ Resources::getReference().fieldList().setField(GENERAL, (rec != NULL) ? 1 : 0);
}
typedef void(*SequenceMethodPtr)(uint16, uint16, uint16);
@@ -734,7 +734,7 @@ struct SequenceMethodRecord {
SequenceMethodPtr proc;
};
-SequenceMethodRecord scriptMethods[] = {
+static const SequenceMethodRecord scriptMethods[] = {
{0, Script::activateHotspot},
{1, Script::setHotspotScript},
{2, Script::addSound2},
@@ -756,7 +756,7 @@ SequenceMethodRecord scriptMethods[] = {
{18, Script::remoteRoomViewSetup},
{19, Script::startSpeakingToNoone},
{20, Script::checkCellDoor},
- {21, Script::playMusic},
+ {21, Script::stopSound},
{22, Script::getDoorBlocked},
{23, Script::isSkorlInCell},
{24, Script::ratpouchPushBricks},
@@ -804,14 +804,14 @@ SequenceMethodRecord scriptMethods[] = {
{66, Script::checkSound},
{0xff, NULL}};
-const char *scriptOpcodes[] = {
+static const char *scriptOpcodes[] = {
"ABORT", "ADD", "SUBTRACT", "MULTIPLY", "DIVIDE", "EQUALS", "NOT_EQUALS",
"LT", "GT", "LTE", "GTE", "AND", "OR", "LOGICAL_AND", "LOGICAL_OR",
"GET_FIELD", "SET_FIELD", "PUSH", "SUBROUTINE", "EXEC", "END",
"COND_JUMP", "JUMP", "ABORT2", "ABORT3", "RANDOM"
};
-const char *scriptMethodNames[67] = {
+static const char *scriptMethodNames[67] = {
"ACTIVATE HOTSPOT", "SET HOTSPOT SCRIPT", "ADD SOUND 2", "SET HOTSPOT FLAG MASK",
"CLEAR SEQUENCE DELAY LIST", "DEACTIVATE HOTSPOT SET", "DEACTIVATE HOTSPOT",
"RESET PATHFINDER", "ADD DELAYED SCRIPT", "KILL SOUND",
@@ -860,7 +860,7 @@ uint16 Script::execute(uint16 startOffset) {
uint16 fieldNum;
uint32 tempVal;
SequenceMethodPtr ptr;
- SequenceMethodRecord *rec;
+ const SequenceMethodRecord *rec;
char debugInfo[MAX_DESC_SIZE];
uint16 offset = startOffset;
@@ -1152,9 +1152,9 @@ int16 HotspotScript::nextVal(MemoryBlock *data, uint16 &offset) {
return value;
}
-bool HotspotScript::execute(Hotspot *h)
-{
+bool HotspotScript::execute(Hotspot *h) {
Resources &r = Resources::getReference();
+ Room &room = Room::getReference();
MemoryBlock *scriptData = r.hotspotScriptData();
uint16 offset = h->hotspotScript();
int16 opcode = 0;
@@ -1225,14 +1225,17 @@ bool HotspotScript::execute(Hotspot *h)
case S2_OPCODE_PLAY_SOUND:
param1 = nextVal(scriptData, offset);
param2 = nextVal(scriptData, offset);
- debugC(ERROR_DETAILED, kLureDebugScripts, "PLAY_SOUND(%d,%d)", param1, param2);
-// warning("UNKNOWN_247 stub called");
+
+ if ((param2 == 0) || (room.roomNumber() == param2)) {
+ debugC(ERROR_DETAILED, kLureDebugScripts, "PLAY_SOUND(%d,%d)", param2, param1);
+ Sound.addSound2((uint8)param1);
+ }
break;
case S2_OPCODE_STOP_SOUND:
param1 = nextVal(scriptData, offset);
debugC(ERROR_DETAILED, kLureDebugScripts, "STOP_SOUND()");
-// warning("UNKNOWN_258 stub called");
+ Sound.stopSound((uint8)param1);
break;
case S2_OPCODE_ACTIONS:
diff --git a/engines/lure/scripts.h b/engines/lure/scripts.h
index 1191017d11..4ad5226e70 100644
--- a/engines/lure/scripts.h
+++ b/engines/lure/scripts.h
@@ -79,25 +79,25 @@ public:
static void activateHotspot(uint16 hotspotId, uint16 v2, uint16 v3);
static void setHotspotScript(uint16 hotspotId, uint16 scriptIndex, uint16 v3);
- static void addSound2(uint16 v1, uint16 v2, uint16 v3);
+ static void addSound2(uint16 soundIndex, uint16 v2, uint16 v3);
static void setHotspotFlagMask(uint16 maskVal, uint16 v2, uint16 v3);
static void clearSequenceDelayList(uint16 v1, uint16 scriptIndex, uint16 v3);
static void deactivateHotspotSet(uint16 listIndex, uint16 v2, uint16 v3);
static void deactivateHotspot(uint16 hotspotId, uint16 v2, uint16 v3);
static void resetPathfinder(uint16 v1, uint16 v2, uint16 v3);
static void addDelayedSequence(uint16 seqOffset, uint16 delay, uint16 canClear);
- static void killSound(uint16 soundId, uint16 v2, uint16 v3);
+ static void killSound(uint16 soundNumber, uint16 v2, uint16 v3);
static void characterInRoom(uint16 characterId, uint16 roomNumber, uint16 v3);
static void setDesc(uint16 hotspotId, uint16 descId, uint16 v3);
static void setHotspotName(uint16 hotspotId, uint16 nameId, uint16 v3);
- static void addSound(uint16 soundId, uint16 v2, uint16 v3);
+ static void addSound(uint16 soundIndex, uint16 v2, uint16 v3);
static void endgameSequence(uint16 v1, uint16 v2, uint16 v3);
static void setupPigFight(uint16 v1, uint16 v2, uint16 v3);
static void displayDialog(uint16 stringId, uint16 v2, uint16 v3);
static void setupSkorlFight(uint16 v1, uint16 v2, uint16 v3);
static void remoteRoomViewSetup(uint16 v1, uint16 v2, uint16 v3);
static void startSpeakingToNoone(uint16 characterId, uint16 stringId, uint16 v3);
- static void playMusic(uint16 musicNum, uint16 v2, uint16 v3);
+ static void stopSound(uint16 soundIndex, uint16 v2, uint16 v3);
static void getDoorBlocked(uint16 hotspotId, uint16 v2, uint16 v3);
static void isSkorlInCell(uint16 v1, uint16 v2, uint16 v3);
static void ratpouchPushBricks(uint16 v1, uint16 v2, uint16 v3);
@@ -142,7 +142,7 @@ public:
static void addActions(uint16 hotspotId, uint16 actions, uint16 v3);
static void randomToGeneral(uint16 maxVal, uint16 minVal, uint16 v3);
static void checkCellDoor(uint16 v1, uint16 v2, uint16 v3);
- static void checkSound(uint16 v1, uint16 v2, uint16 v3);
+ static void checkSound(uint16 soundNumber, uint16 v2, uint16 v3);
};
class HotspotScript {
diff --git a/engines/lure/sound.cpp b/engines/lure/sound.cpp
index 6961e4c7cc..bf9a2032ab 100644
--- a/engines/lure/sound.cpp
+++ b/engines/lure/sound.cpp
@@ -21,17 +21,607 @@
*/
#include "lure/sound.h"
+#include "lure/game.h"
+#include "lure/memory.h"
+#include "lure/res.h"
+#include "lure/room.h"
+
+#include "common/config-manager.h"
+#include "common/endian.h"
+#include "sound/midiparser.h"
DECLARE_SINGLETON(Lure::SoundManager);
namespace Lure {
+SoundManager::SoundManager() {
+ _descs = Disk::getReference().getEntry(SOUND_DESC_RESOURCE_ID);
+ _numDescs = _descs->size() / sizeof(SoundDescResource);
+ _soundData = NULL;
+
+ int midiDriver = MidiDriver::detectMusicDriver(MDT_MIDI | MDT_ADLIB | MDT_PREFER_MIDI);
+ _nativeMT32 = ((midiDriver == MD_MT32) || ConfMan.getBool("native_mt32"));
+
+ memset(_channelsInUse, false, NUM_CHANNELS_OUTER);
+
+ _driver = MidiDriver::createMidi(midiDriver);
+ int statusCode = _driver->open();
+ if (statusCode) {
+ warning("Sound driver returned error code %d", statusCode);
+ _driver = NULL;
+
+ } else {
+ if (_nativeMT32)
+ _driver->property(MidiDriver::PROP_CHANNEL_MASK, 0x03FE);
+
+ for (int index = 0; index < NUM_CHANNELS_INNER; ++index) {
+ _channelsInner[index].midiChannel = _driver->allocateChannel();
+ _channelsInner[index].volume = DEFAULT_VOLUME;
+ }
+ }
+}
+
+SoundManager::~SoundManager() {
+ if (_driver)
+ _driver->setTimerCallback(this, NULL);
+
+ removeSounds();
+ _activeSounds.clear();
+ _playingSounds.clear();
+
+
+ delete _descs;
+ if (_soundData)
+ delete _soundData;
+
+ if (_driver)
+ _driver->close();
+ _driver = NULL;
+}
+
+void SoundManager::loadSection(uint16 sectionId) {
+ debugC(ERROR_BASIC, kLureDebugSounds, "SoundManager::loadSection = %xh", sectionId);
+ killSounds();
+
+ if (_soundData) {
+ delete _soundData;
+ _driver->setTimerCallback(this, NULL);
+ }
+
+ _soundData = Disk::getReference().getEntry(sectionId);
+ _soundsTotal = *_soundData->data();
+
+ _driver->setTimerCallback(this, &onTimer);
+}
+
+void SoundManager::bellsBodge() {
+ debugC(ERROR_BASIC, kLureDebugSounds, "SoundManager::bellsBodge");
+ Resources &res = Resources::getReference();
+ Room &room = Room::getReference();
+
+ RoomData *roomData = res.getRoom(room.roomNumber());
+ if (roomData->areaFlag != res.fieldList().getField(AREA_FLAG)) {
+ res.fieldList().setField(AREA_FLAG, roomData->areaFlag);
+
+ switch (roomData->areaFlag) {
+ case 0:
+ killSound(1);
+ break;
+ case 1:
+ addSound(2);
+ killSound(33);
+ break;
+ case 2:
+ setVolume(0, 15);
+ // Deliberate fall through
+ default:
+ killSound(1);
+ break;
+ }
+ }
+}
+
void SoundManager::killSounds() {
+ debugC(ERROR_BASIC, kLureDebugSounds, "SoundManager::killSounds");
+
+ // Stop the player playing all sounds
+ musicInterface_KillAll();
+
+ // Clear the active sounds
+ _activeSounds.clear();
+ for (int channelNum = 0; channelNum < NUM_CHANNELS_INNER; ++channelNum)
+ _channelsInUse[channelNum] = false;
+}
+
+void SoundManager::addSound(uint8 soundIndex, bool tidyFlag) {
+ debugC(ERROR_BASIC, kLureDebugSounds, "SoundManager::addSound index=%d", soundIndex);
+ Game &game = Game::getReference();
+
+ if (tidyFlag)
+ tidySounds();
+
+ if (game.preloadFlag())
+ // Don't add a sound if in room preloading
+ return;
+
+ SoundDescResource &rec = soundDescs()[soundIndex];
+ int numChannels = (rec.numChannels >> 2) & 3;
+
+ int channelCtr = 0;
+ while (channelCtr <= (NUM_CHANNELS_OUTER - numChannels)) {
+ if (!_channelsInUse[channelCtr]) {
+ bool foundSpace = true;
+
+ int channelCtr2 = 1;
+ while (channelCtr2 < numChannels) {
+ foundSpace = !_channelsInUse[channelCtr + channelCtr2];
+ if (!foundSpace) break;
+ ++channelCtr2;
+ }
+
+ if (foundSpace)
+ break;
+ }
+
+ ++channelCtr;
+ }
+
+ if (channelCtr > NUM_CHANNELS_OUTER - numChannels) {
+ // No channels free
+ debugC(ERROR_BASIC, kLureDebugSounds, "SoundManager::addSound - no channels free");
+ return;
+ }
+
+ // Mark the found channels as in use
+ for (int channelCtr2 = 0; channelCtr2 < numChannels; ++channelCtr2)
+ _channelsInUse[channelCtr + channelCtr2] = true;
+
+ SoundDescResource *newEntry = new SoundDescResource();
+ newEntry->soundNumber = rec.soundNumber;
+ newEntry->channel = channelCtr;
+ newEntry->numChannels = numChannels;
+ newEntry->flags = rec.flags;
+ newEntry->volume = rec.volume;
+ _activeSounds.push_back(newEntry);
+
+ // TODO: Figure a better way of sharing channels between multiple parsers - currently
+ // each parser seems to use 8 channels of a maximum 16 available, but here I'm
+ // overlapping channels 4 - 7 (3rd & 4th parser) across the other two
+ byte innerChannel = (channelCtr < 4) ? ((channelCtr / 2) * 8) :
+ (4 + (channelCtr / 2) * 8);
+
+ musicInterface_Play(rec.soundNumber, innerChannel);
+ setVolume(rec.soundNumber, rec.volume);
+}
+
+void SoundManager::addSound2(uint8 soundIndex) {
+ debugC(ERROR_BASIC, kLureDebugSounds, "SoundManager::addSound2 index=%d", soundIndex);
+ tidySounds();
+
+ if (soundIndex == 6)
+ // Chinese torture
+ addSound(6);
+ else {
+ SoundDescResource &descEntry = soundDescs()[soundIndex];
+ SoundDescResource *rec = findSound(descEntry.soundNumber);
+ if (rec == NULL)
+ // Sound isn't active, so go and add it
+ addSound(soundIndex, false);
+ }
+}
+
+
+void SoundManager::stopSound(uint8 soundIndex) {
+ debugC(ERROR_BASIC, kLureDebugSounds, "SoundManager::stopSound index=%d", soundIndex);
+ SoundDescResource &rec = soundDescs()[soundIndex];
+ musicInterface_Stop(rec.soundNumber & 0x7f);
+}
+
+void SoundManager::killSound(uint8 soundNumber) {
+ debugC(ERROR_BASIC, kLureDebugSounds, "SoundManager::stopSound soundNumber=%d", soundNumber);
+ musicInterface_Stop(soundNumber & 0x7f);
+}
+
+void SoundManager::setVolume(uint8 soundNumber, uint8 volume) {
+ debugC(ERROR_BASIC, kLureDebugSounds, "SoundManager::setVolume soundNumber=%d, volume=%d",
+ soundNumber, volume);
+ musicInterface_TidySounds();
+
+ SoundDescResource *entry = findSound(soundNumber);
+ if (entry)
+ musicInterface_SetVolume(entry->channel, volume);
+}
+
+void SoundManager::setVolume(uint8 volume) {
+ debugC(ERROR_BASIC, kLureDebugSounds, "SoundManager::setVolume volume=%d", volume);
+
+ for (int index = 0; index < NUM_CHANNELS_INNER; ++index) {
+ _channelsInner[index].midiChannel->volume(volume);
+ _channelsInner[index].volume = volume;
+ }
+}
+
+SoundDescResource *SoundManager::findSound(uint8 soundNumber) {
+ debugC(ERROR_BASIC, kLureDebugSounds, "SoundManager::findSound soundNumber=%d", soundNumber);
+ ManagedList<SoundDescResource *>::iterator i;
+
+ for (i = _activeSounds.begin(); i != _activeSounds.end(); ++i) {
+ SoundDescResource *rec = *i;
+
+ if (rec->soundNumber == soundNumber) {
+ debugC(ERROR_INTERMEDIATE, kLureDebugSounds, "SoundManager::findSound - sound found");
+ return rec;
+ }
+ }
+
+ // Signal that sound wasn't found
+ debugC(ERROR_INTERMEDIATE, kLureDebugSounds, "SoundManager::findSound - sound not found");
+ return NULL;
+}
+
+void SoundManager::tidySounds() {
+ debugC(ERROR_INTERMEDIATE, kLureDebugSounds, "SoundManager::tidySounds");
+ ManagedList<SoundDescResource *>::iterator i = _activeSounds.begin();
+
+ while (i != _activeSounds.end()) {
+ SoundDescResource *rec = *i;
+
+ if (musicInterface_CheckPlaying(rec->soundNumber & 0x7f))
+ // Still playing, so move to next entry
+ ++i;
+ else {
+ // Mark the channels that it used as now being free
+ for (int channelCtr = 0; channelCtr < rec->numChannels; ++channelCtr)
+ _channelsInUse[rec->channel + channelCtr] = false;
+
+ i = _activeSounds.erase(i);
+ }
+ }
+}
+
+void SoundManager::removeSounds() {
+ debugC(ERROR_BASIC, kLureDebugSounds, "SoundManager::removeSounds");
+ bellsBodge();
+
+ ManagedList<SoundDescResource *>::iterator i = _activeSounds.begin();
+
+ while (i != _activeSounds.end()) {
+ SoundDescResource *rec = *i;
+
+ if ((rec->flags & SF_IN_USE) != 0)
+ musicInterface_Stop(rec->soundNumber);
+
+ ++i;
+ }
+}
+
+void SoundManager::restoreSounds() {
+ debugC(ERROR_BASIC, kLureDebugSounds, "SoundManager::restoreSounds");
+ ManagedList<SoundDescResource *>::iterator i = _activeSounds.begin();
+
+ while (i != _activeSounds.end()) {
+ SoundDescResource *rec = *i;
+
+ if ((rec->numChannels != 0) && ((rec->flags & SF_RESTORE) != 0)) {
+ for (int channelCtr = 0; channelCtr < rec->numChannels; ++channelCtr)
+ _channelsInUse[rec->channel + channelCtr] = true;
+
+ musicInterface_Play(rec->soundNumber, rec->channel);
+ musicInterface_SetVolume(rec->soundNumber, rec->volume);
+ }
+
+ ++i;
+ }
+}
+
+void SoundManager::fadeOut() {
+ debugC(ERROR_BASIC, kLureDebugSounds, "SoundManager::fadeOut");
+
+ // Fade out all the active sounds
+ musicInterface_TidySounds();
+
+ bool inProgress = true;
+ while (inProgress)
+ {
+ inProgress = false;
+
+ ManagedList<MidiMusic *>::iterator i;
+ for (i = _playingSounds.begin(); i != _playingSounds.end(); ++i) {
+ MidiMusic *music = *i;
+ if (music->getVolume() > 0) {
+ inProgress = true;
+ music->setVolume(music->getVolume() > 4 ? (music->getVolume() - 10) : 0);
+ }
+ }
+
+ g_system->delayMillis(10);
+ }
+
+ // Kill all the sounds
+ musicInterface_KillAll();
+}
+
+/*------------------------------------------------------------------------*/
+
+// musicInterface_Play
+// Play the specified sound
+
+void SoundManager::musicInterface_Play(uint8 soundNumber, uint8 channelNumber) {
+ debugC(ERROR_INTERMEDIATE, kLureDebugSounds, "musicInterface_Play soundNumber=%d, channel=%d",
+ soundNumber, channelNumber);
+
+ if (!_soundData)
+ error("Sound section has not been specified");
+
+ uint8 soundNum = soundNumber & 0x7f;
+ if (soundNum > _soundsTotal)
+ error("Invalid sound index %d requested", soundNum);
+
+ if (_driver == NULL)
+ // Only play sounds if a sound driver is active
+ return;
+
+ uint32 dataOfs = READ_LE_UINT32(_soundData->data() + soundNum * 4 + 2);
+ uint8 *soundStart = _soundData->data() + dataOfs;
+ uint32 dataSize;
+
+ if (soundNumber == _soundsTotal - 1)
+ dataSize = _soundData->size() - dataOfs;
+ else {
+ uint32 nextDataOfs = READ_LE_UINT32(_soundData->data() + (soundNum + 1) * 4 + 2);
+ dataSize = nextDataOfs - dataOfs;
+ }
+
+ MidiMusic *sound = new MidiMusic(_driver, _channelsInner, channelNumber, soundNumber,
+ soundStart, dataSize);
+ _playingSounds.push_back(sound);
+}
+
+// musicInterface_Stop
+// Stops the specified sound from playing
+
+void SoundManager::musicInterface_Stop(uint8 soundNumber) {
+ debugC(ERROR_INTERMEDIATE, kLureDebugSounds, "musicInterface_Stop soundNumber=%d", soundNumber);
+ musicInterface_TidySounds();
+ uint8 soundNum = soundNumber & 0x7f;
+
+ ManagedList<MidiMusic *>::iterator i;
+ for (i = _playingSounds.begin(); i != _playingSounds.end(); ++i) {
+ MidiMusic *music = *i;
+ if (music->soundNumber() == soundNum) {
+ _playingSounds.erase(i);
+ return;
+ }
+ }
+}
+
+// musicInterface_CheckPlaying
+// Returns true if a sound is still playing
+
+bool SoundManager::musicInterface_CheckPlaying(uint8 soundNumber) {
+ debugC(ERROR_DETAILED, kLureDebugSounds, "musicInterface_CheckPlaying soundNumber=%d", soundNumber);
+ musicInterface_TidySounds();
+ uint8 soundNum = soundNumber & 0x7f;
+
+ ManagedList<MidiMusic *>::iterator i;
+ for (i = _playingSounds.begin(); i != _playingSounds.end(); ++i) {
+ MidiMusic *music = *i;
+ if (music->soundNumber() == soundNum)
+ return true;
+ }
+
+ return false;
+}
+
+// musicInterface_SetVolume
+// Sets the volume of the specified channel
+
+void SoundManager::musicInterface_SetVolume(uint8 channelNum, uint8 volume) {
+ debugC(ERROR_INTERMEDIATE, kLureDebugSounds, "musicInterface_SetVolume channel=%d, volume=%d",
+ channelNum, volume);
+ musicInterface_TidySounds();
+
+ ManagedList<MidiMusic *>::iterator i;
+ for (i = _playingSounds.begin(); i != _playingSounds.end(); ++i) {
+ MidiMusic *music = *i;
+ if (music->channelNumber() == channelNum)
+ music->setVolume(volume);
+ }
+}
+
+// musicInterface_KillAll
+// Stops all currently active sounds playing
+
+void SoundManager::musicInterface_KillAll() {
+ debugC(ERROR_INTERMEDIATE, kLureDebugSounds, "musicInterface_KillAll");
+ musicInterface_TidySounds();
+
+ ManagedList<MidiMusic *>::iterator i;
+ for (i = _playingSounds.begin(); i != _playingSounds.end(); ++i) {
+ MidiMusic *music = *i;
+ music->stopMusic();
+ }
+
+ _playingSounds.clear();
+ _activeSounds.clear();
+}
+
+// musicInterface_ContinuePlaying
+// The original player used this method for any sound managers needing continual calls
+
+void SoundManager::musicInterface_ContinuePlaying() {
+ // No implementation needed
+}
+
+// musicInterface_TrashReverb
+// Trashes reverb on actively playing sounds
+
+void SoundManager::musicInterface_TrashReverb() {
+ // TODO: Handle support for trashing reverb
+ debugC(ERROR_INTERMEDIATE, kLureDebugSounds, "musicInterface_TrashReverb");
+}
+
+// musicInterface_KillAll
+// Scans all the active sounds and deallocates any objects that have finished playing
+
+void SoundManager::musicInterface_TidySounds() {
+ debugC(ERROR_DETAILED, kLureDebugSounds, "musicInterface_TidySounds");
+ ManagedList<MidiMusic *>::iterator i = _playingSounds.begin();
+ while (i != _playingSounds.end()) {
+ MidiMusic *music = *i;
+ if (!music->isPlaying())
+ i = _playingSounds.erase(i);
+ else
+ ++i;
+ }
+}
+
+void SoundManager::onTimer(void *data) {
+ SoundManager *snd = (SoundManager *) data;
+
+ ManagedList<MidiMusic *>::iterator i;
+ for (i = snd->_playingSounds.begin(); i != snd->_playingSounds.end(); ++i) {
+ MidiMusic *music = *i;
+ if (music->isPlaying())
+ music->onTimer();
+ }
+}
+
+/*------------------------------------------------------------------------*/
+
+MidiMusic::MidiMusic(MidiDriver *driver, ChannelEntry channels[NUM_CHANNELS_INNER],
+ uint8 channelNum, uint8 soundNum, void *soundData, uint32 size) {
+
+ _driver = driver;
+ _channels = channels;
+ _soundNumber = soundNum;
+ _channelNumber = channelNum;
+ _numChannels = 8;
+ _volume = _channels[channelNum].volume;
+
+ _passThrough = false;
+
+ _parser = MidiParser::createParser_SMF();
+ _parser->setMidiDriver(this);
+ _parser->setTimerRate(_driver->getBaseTempo());
+
+ this->open();
+
+ _soundData = (uint8 *) soundData;
+ _soundSize = size;
+
+ // Check whether the music data is compressed - if so, decompress it for the duration
+ // of playing the sound
+ _decompressedSound = NULL;
+ if ((*_soundData == 'C') || (*_soundData == 'c')) {
+ uint32 packedSize = size - 0x201;
+ _decompressedSound = Memory::allocate(packedSize * 2);
+
+ uint16 *data = (uint16 *)(_soundData + 1);
+ uint16 *dataDest = (uint16 *) _decompressedSound->data();
+ byte *idx = ((byte *)data) + 0x200;
+
+ for (uint i = 0; i < packedSize; i++)
+#if defined(SCUMM_NEED_ALIGNMENT)
+ memcpy(dataDest++, (byte*)((byte*)data + *(idx + i) * sizeof(uint16)), sizeof(uint16));
+#else
+ *dataDest++ = data[*(idx + i)];
+#endif
+
+ _soundData = _decompressedSound->data() + ((*_soundData == 'c') ? 1 : 0);
+ _soundSize = _decompressedSound->size();
+ }
+
+ playMusic();
+}
+
+MidiMusic::~MidiMusic() {
+ _parser->unloadMusic();
+ delete _parser;
+ this->close();
+ if (_decompressedSound != NULL)
+ delete _decompressedSound;
}
-void SoundManager::playSound(uint16 soundId) {
+void MidiMusic::setVolume(int volume) {
+ if (volume < 0)
+ volume = 0;
+ else if (volume > 255)
+ volume = 255;
+
+ if (_volume == volume)
+ return;
+
+ _volume = volume;
+
+ for (int i = 0; i < _numChannels; ++i)
+ _channels[_channelNumber + i].midiChannel->volume(
+ _channels[_channelNumber + i].volume * _volume / 255);
+}
+
+void MidiMusic::playMusic() {
+ debugC(ERROR_DETAILED, kLureDebugSounds, "MidiMusic::PlayMusic playing sound %d", _soundNumber);
+ _parser->loadMusic(_soundData, _soundSize);
+ _parser->setTrack(0);
+ _isPlaying = true;
+}
+
+int MidiMusic::open() {
+ // Don't ever call open without first setting the output driver!
+ if (!_driver)
+ return 255;
+
+ return 0;
+}
+
+void MidiMusic::close() {
+}
+
+void MidiMusic::send(uint32 b) {
+ if (_passThrough) {
+ _driver->send(b);
+ return;
+ }
+
+ byte channel = _channelNumber + (byte)(b & 0x0F);
+ if ((channel >= NUM_CHANNELS_INNER) || (_channels[channel].midiChannel == NULL))
+ return;
+
+ if ((b & 0xFFF0) == 0x07B0) {
+ // Adjust volume changes by master volume
+ byte volume = (byte)((b >> 16) & 0x7F);
+ _channels[channel].volume = volume;
+ volume = volume * _volume / 255;
+ b = (b & 0xFF00FFFF) | (volume << 16);
+ } else if ((b & 0xF0) == 0xC0 && !_nativeMT32) {
+ b = (b & 0xFFFF00FF) | MidiDriver::_mt32ToGm[(b >> 8) & 0xFF] << 8;
+ }
+ else if ((b & 0xFFF0) == 0x007BB0) {
+ // No implementation
+ }
+
+ _channels[channel].midiChannel->send(b);
+}
+
+void MidiMusic::metaEvent(byte type, byte *data, uint16 length) {
+ //Only thing we care about is End of Track.
+ if (type != 0x2F)
+ return;
+
+ stopMusic();
+}
+
+void MidiMusic::onTimer() {
+ if (_isPlaying)
+ _parser->onTimer();
+}
+void MidiMusic::stopMusic() {
+ debugC(ERROR_DETAILED, kLureDebugSounds, "MidiMusic::stopMusic sound %d", _soundNumber);
+ _isPlaying = false;
+ _parser->unloadMusic();
+ close();
}
} // end of namespace Lure
diff --git a/engines/lure/sound.h b/engines/lure/sound.h
index 4a7422d77f..cfe0739298 100644
--- a/engines/lure/sound.h
+++ b/engines/lure/sound.h
@@ -24,14 +24,131 @@
#define LURE_SOUND_H
#include "lure/luredefs.h"
+#include "lure/disk.h"
+#include "lure/memory.h"
+
#include "common/singleton.h"
+#include "sound/mididrv.h"
+#include "sound/mixer.h"
+
+class MidiParser;
namespace Lure {
+#define NUM_CHANNELS_OUTER 8
+#define NUM_CHANNELS_INNER 16
+
+struct ChannelEntry {
+ MidiChannel *midiChannel;
+ byte volume;
+};
+
+class MidiMusic: public MidiDriver {
+private:
+ uint8 _soundNumber;
+ uint8 _channelNumber;
+ uint8 _numChannels;
+ byte _volume;
+ MemoryBlock *_decompressedSound;
+ uint8 *_soundData;
+ uint8 _soundSize;
+ MidiDriver *_driver;
+ MidiParser *_parser;
+ ChannelEntry *_channels;
+ bool _isPlaying;
+ bool _nativeMT32;
+
+ void queueUpdatePos();
+ uint8 randomQueuePos();
+ uint32 songOffset(uint16 songNum) const;
+ uint32 songLength(uint16 songNum) const;
+
+ bool _passThrough;
+
+public:
+ MidiMusic(MidiDriver *driver, ChannelEntry channels[NUM_CHANNELS_INNER],
+ uint8 channelNum, uint8 soundNum, void *soundData, uint32 size);
+ ~MidiMusic();
+ void setVolume(int volume);
+ int getVolume() { return _volume; }
+
+ void hasNativeMT32(bool b) { _nativeMT32 = b; }
+ void playSong(uint16 songNum);
+ void stopSong() { stopMusic(); }
+ void playMusic();
+ void stopMusic();
+ void queueTuneList(int16 tuneList);
+ bool queueSong(uint16 songNum);
+ void setPassThrough(bool b) { _passThrough = b; }
+ void toggleVChange();
+
+ //MidiDriver interface implementation
+ int open();
+ void close();
+ void send(uint32 b);
+ void onTimer();
+
+ void metaEvent(byte type, byte *data, uint16 length);
+
+ void setTimerCallback(void *timerParam, void (*timerProc)(void *)) { }
+ uint32 getBaseTempo(void) { return _driver ? _driver->getBaseTempo() : 0; }
+
+ //Channel allocation functions
+ MidiChannel *allocateChannel() { return 0; }
+ MidiChannel *getPercussionChannel() { return 0; }
+
+ uint8 channelNumber() { return _channelNumber; }
+ uint8 soundNumber() { return _soundNumber; }
+ bool isPlaying() { return _isPlaying; }
+};
+
class SoundManager: public Common::Singleton<SoundManager> {
+private:
+ // Outer sound interface properties
+ MemoryBlock *_descs;
+ MemoryBlock *_soundData;
+ uint8 _soundsTotal;
+ int _numDescs;
+ SoundDescResource *soundDescs() { return (SoundDescResource *) _descs->data(); }
+ MidiDriver *_driver;
+ ManagedList<SoundDescResource *> _activeSounds;
+ ManagedList<MidiMusic *> _playingSounds;
+ ChannelEntry _channelsInner[NUM_CHANNELS_INNER];
+ bool _channelsInUse[NUM_CHANNELS_OUTER];
+ bool _isPlaying;
+ bool _nativeMT32;
+
+ // Internal support methods
+ void bellsBodge();
+ void musicInterface_TidySounds();
+ static void onTimer(void *data);
public:
- static void killSounds();
- static void playSound(uint16 soundId);
+ SoundManager();
+ ~SoundManager();
+
+ void loadSection(uint16 sectionId);
+ void killSounds();
+ void addSound(uint8 soundIndex, bool tidyFlag = true);
+ void addSound2(uint8 soundIndex);
+ void stopSound(uint8 soundIndex);
+ void killSound(uint8 soundNumber);
+ void setVolume(uint8 soundNumber, uint8 volume);
+ void setVolume(uint8 volume);
+ void tidySounds();
+ SoundDescResource *findSound(uint8 soundNumber);
+ void removeSounds();
+ void restoreSounds();
+ void fadeOut();
+
+ // The following methods implement the external sound player module
+ void musicInterface_Initialise();
+ void musicInterface_Play(uint8 soundNumber, uint8 channelNumber);
+ void musicInterface_Stop(uint8 soundNumber);
+ bool musicInterface_CheckPlaying(uint8 soundNumber);
+ void musicInterface_SetVolume(uint8 channelNum, uint8 volume);
+ void musicInterface_KillAll();
+ void musicInterface_ContinuePlaying();
+ void musicInterface_TrashReverb();
};
} // End of namespace Lure
diff --git a/engines/lure/surface.cpp b/engines/lure/surface.cpp
index 3486a5abb9..d5b9db4955 100644
--- a/engines/lure/surface.cpp
+++ b/engines/lure/surface.cpp
@@ -29,6 +29,7 @@
#include "lure/screen.h"
#include "lure/lure.h"
#include "lure/room.h"
+#include "lure/sound.h"
#include "lure/strings.h"
#include "common/endian.h"
@@ -50,8 +51,7 @@ void Surface::initialise() {
byte *pChar = int_font->data() + (ctr * 8);
fontSize[ctr] = 0;
- for (int yp = 0; yp < FONT_HEIGHT; ++yp)
- {
+ for (int yp = 0; yp < FONT_HEIGHT; ++yp) {
byte v = *pChar++;
for (int xp = 0; xp < FONT_WIDTH; ++xp) {
@@ -155,13 +155,11 @@ void Surface::transparentCopyTo(Surface *dest) {
}
}
-void Surface::copyTo(Surface *dest)
-{
+void Surface::copyTo(Surface *dest) {
copyTo(dest, 0, 0);
}
-void Surface::copyTo(Surface *dest, uint16 x, uint16 y)
-{
+void Surface::copyTo(Surface *dest, uint16 x, uint16 y) {
if ((x == 0) && (dest->width() == _width)) {
// Use fast data transfer
uint32 dataSize = dest->data().size() - (y * _width);
@@ -631,7 +629,6 @@ bool SaveRestoreDialog::show(bool saveDialog) {
Screen &screen = Screen::getReference();
Mouse &mouse = Mouse::getReference();
Events &events = Events::getReference();
- Room &room = Room::getReference();
Resources &res = Resources::getReference();
LureEngine &engine = LureEngine::getReference();
int selectedLine = -1;
@@ -655,7 +652,6 @@ bool SaveRestoreDialog::show(bool saveDialog) {
return false;
}
- room.update();
Surface *s = new Surface(INFO_DIALOG_WIDTH, SR_SAVEGAME_NAMES_Y +
numSaves * FONT_HEIGHT + FONT_HEIGHT + 2);
@@ -778,4 +774,139 @@ bool SaveRestoreDialog::show(bool saveDialog) {
return doneFlag;
}
+/*--------------------------------------------------------------------------*/
+
+struct RestartRecordPos {
+ int16 x, y;
+};
+
+struct RestartRecord {
+ Common::Language Language;
+ int16 width, height;
+ RestartRecordPos BtnRestart;
+ RestartRecordPos BtnRestore;
+};
+
+static const RestartRecord buttonBounds[] = {
+ { EN_ANY, 48, 14, { 118, 152 }, { 168, 152 } },
+ { DE_DEU, 48, 14, { 106, 152 }, { 168, 152 } },
+ { UNK_LANG, 48, 14, { 112, 152 }, { 168, 152 } }
+};
+
+
+bool RestartRestoreDialog::show() {
+ Resources &res = Resources::getReference();
+ Events &events = Events::getReference();
+ Mouse &mouse = Mouse::getReference();
+ Screen &screen = Screen::getReference();
+ LureEngine &engine = LureEngine::getReference();
+
+ Sound.killSounds();
+ Sound.musicInterface_Play(60, 0);
+ mouse.setCursorNum(CURSOR_ARROW);
+
+ // See if there are any savegames that can be restored
+ String *firstSave = engine.detectSave(1);
+ bool restartFlag = (firstSave == NULL);
+ int highlightedButton = -1;
+
+ if (!restartFlag) {
+ Memory::dealloc(firstSave);
+
+ // Get the correct button bounds record to use
+ const RestartRecord *btnRecord = &buttonBounds[0];
+ while ((btnRecord->Language != engine.getLanguage()) &&
+ (btnRecord->Language != UNK_LANG))
+ ++btnRecord;
+
+ // Fade out the screen
+ screen.paletteFadeOut(RES_PALETTE_ENTRIES);
+
+ // Get the palette that will be used, and first fade out the prior screen
+ Palette p(RESTART_RESOURCE_ID - 1);
+
+ // Turn on the mouse
+ mouse.cursorOn();
+
+ // Load the restore/restart screen image
+ Surface *s = Surface::getScreen(RESTART_RESOURCE_ID);
+ s->copyTo(&screen.screen(), 0, MENUBAR_Y_SIZE);
+ delete s;
+
+ res.activeHotspots().clear();
+ Hotspot *btnHotspot = new Hotspot();
+
+ // Restart button
+ btnHotspot->setSize(btnRecord->width, btnRecord->height);
+ btnHotspot->setPosition(btnRecord->BtnRestart.x, btnRecord->BtnRestart.y);
+ btnHotspot->setAnimation(0x184B);
+ btnHotspot->copyTo(&screen.screen());
+
+ // Restore button
+ btnHotspot->setFrameNumber(1);
+ btnHotspot->setPosition(btnRecord->BtnRestore.x, btnRecord->BtnRestore.y);
+ btnHotspot->copyTo(&screen.screen());
+
+ screen.update();
+ screen.paletteFadeIn(&p);
+
+ // Event loop for making selection
+ while (!events.quitFlag) {
+ // Handle events
+ if (events.pollEvent()) {
+ if ((events.type() == Common::EVENT_LBUTTONDOWN) && (highlightedButton != -1)) {
+ mouse.waitForRelease();
+ break;
+ }
+ }
+
+ // Check if the pointer is over either button
+ int currentButton = -1;
+ if ((mouse.y() >= btnRecord->BtnRestart.y) &&
+ (mouse.y() < btnRecord->BtnRestart.y + btnRecord->height)) {
+ // Check whether the Restart or Restore button is highlighted
+ if ((mouse.x() >= btnRecord->BtnRestart.x) &&
+ (mouse.x() < btnRecord->BtnRestart.x + btnRecord->width))
+ currentButton = 0;
+ else if ((mouse.x() >= btnRecord->BtnRestore.x) &&
+ (mouse.x() < btnRecord->BtnRestore.x + btnRecord->width))
+ currentButton = 1;
+ }
+
+ // Take care of highlighting as the selected button changes
+ if (currentButton != highlightedButton) {
+ highlightedButton = currentButton;
+
+ // Restart button
+ btnHotspot->setFrameNumber((highlightedButton == 0) ? 2 : 0);
+ btnHotspot->setPosition(btnRecord->BtnRestart.x, btnRecord->BtnRestart.y);
+ btnHotspot->copyTo(&screen.screen());
+
+ // Restore button
+ btnHotspot->setFrameNumber((highlightedButton == 1) ? 3 : 1);
+ btnHotspot->setPosition(btnRecord->BtnRestore.x, btnRecord->BtnRestore.y);
+ btnHotspot->copyTo(&screen.screen());
+ }
+
+
+ screen.update();
+ g_system->delayMillis(10);
+ }
+
+ restartFlag = highlightedButton == 0;
+ delete btnHotspot;
+ }
+
+ Sound.killSounds();
+
+ if (!restartFlag && !events.quitFlag) {
+ // Need to show Restore game dialog
+ if (!SaveRestoreDialog::show(false))
+ // User cancelled, so fall back on Restart
+ restartFlag = true;
+ }
+
+ return restartFlag;
+}
+
} // end of namespace Lure
diff --git a/engines/lure/surface.h b/engines/lure/surface.h
index f97666d1e7..564f65dd99 100644
--- a/engines/lure/surface.h
+++ b/engines/lure/surface.h
@@ -104,6 +104,11 @@ public:
static bool show(bool saveDialog);
};
+class RestartRestoreDialog {
+public:
+ static bool show();
+};
+
} // End of namespace Lure
#endif
diff --git a/engines/parallaction/animation.cpp b/engines/parallaction/animation.cpp
deleted file mode 100644
index 118f35e705..0000000000
--- a/engines/parallaction/animation.cpp
+++ /dev/null
@@ -1,683 +0,0 @@
-/* ScummVM - Graphic Adventure Engine
- *
- * ScummVM is the legal property of its developers, whose names
- * are too numerous to list here. Please refer to the COPYRIGHT
- * file distributed with this source distribution.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
-
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
-
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * $URL$
- * $Id$
- *
- */
-
-#include "common/stdafx.h"
-
-#include "parallaction/parallaction.h"
-
-
-namespace Parallaction {
-
-
-#define INST_ON 1
-#define INST_OFF 2
-#define INST_X 3
-#define INST_Y 4
-#define INST_Z 5
-#define INST_F 6
-#define INST_LOOP 7
-#define INST_ENDLOOP 8
-#define INST_SHOW 9
-#define INST_INC 10
-#define INST_DEC 11
-#define INST_SET 12
-#define INST_PUT 13
-#define INST_CALL 14
-#define INST_WAIT 15
-#define INST_START 16
-#define INST_SOUND 17
-#define INST_MOVE 18
-#define INST_END 1000
-
-
-void wrapLocalVar(LocalVariable *local);
-
-
-
-
-uint16 _numLocals = 0;
-char _localNames[10][10];
-
-Animation *Parallaction::findAnimation(const char *name) {
-
- for (AnimationList::iterator it = _animations.begin(); it != _animations.end(); it++)
- if (!scumm_stricmp((*it)->_label._text, name)) return *it;
-
- return NULL;
-}
-
-
-Animation *Parallaction::parseAnimation(Script& script, AnimationList &list, char *name) {
-// printf("parseAnimation(%s)\n", name);
-
- Animation *vD0 = new Animation;
-
- vD0->_label._text = (char*)malloc(strlen(name)+1);
- strcpy(vD0->_label._text, name);
-
- list.push_front(vD0);
-
- fillBuffers(script, true);
- while (scumm_stricmp(_tokens[0], "endanimation")) {
-// printf("token[0] = %s\n", _tokens[0]);
-
- if (!scumm_stricmp(_tokens[0], "script")) {
- loadProgram(vD0, _tokens[1]);
- }
- if (!scumm_stricmp(_tokens[0], "commands")) {
- parseCommands(script, vD0->_commands);
- }
- if (!scumm_stricmp(_tokens[0], "type")) {
- if (_tokens[2][0] != '\0') {
- vD0->_type = ((4 + _objectsNames->lookup(_tokens[2])) << 16) & 0xFFFF0000;
- }
- int16 _si = _zoneTypeNames->lookup(_tokens[1]);
- if (_si != -1) {
- vD0->_type |= 1 << (_si-1);
- if (((vD0->_type & 0xFFFF) != kZoneNone) && ((vD0->_type & 0xFFFF) != kZoneCommand)) {
- parseZoneTypeBlock(script, vD0);
- }
- }
- }
- if (!scumm_stricmp(_tokens[0], "label")) {
- _gfx->makeCnvFromString(&vD0->_label._cnv, _tokens[1]);
- }
- if (!scumm_stricmp(_tokens[0], "flags")) {
- uint16 _si = 1;
-
- do {
- byte _al = _zoneFlagNames->lookup(_tokens[_si]);
- _si++;
- vD0->_flags |= 1 << (_al - 1);
- } while (!scumm_stricmp(_tokens[_si++], "|"));
- }
- if (!scumm_stricmp(_tokens[0], "file")) {
- char vC8[200];
- strcpy(vC8, _tokens[1]);
- if (_engineFlags & kEngineTransformedDonna) {
- if (!scumm_stricmp(_tokens[1], "donnap") || !scumm_stricmp(_tokens[1], "donnapa")) {
- strcat(vC8, "tras");
- }
- }
- vD0->_cnv = _disk->loadFrames(vC8);
- }
- if (!scumm_stricmp(_tokens[0], "position")) {
- vD0->_left = atoi(_tokens[1]);
- vD0->_top = atoi(_tokens[2]);
- vD0->_z = atoi(_tokens[3]);
- }
- if (!scumm_stricmp(_tokens[0], "moveto")) {
- vD0->_moveTo.x = atoi(_tokens[1]);
- vD0->_moveTo.y = atoi(_tokens[2]);
- }
-
- fillBuffers(script, true);
- }
-
- vD0->_oldPos.x = -1000;
- vD0->_oldPos.y = -1000;
-
- vD0->_flags |= 0x1000000;
-
- return vD0;
-}
-
-
-void Parallaction::freeAnimations() {
- _animations.clear();
- return;
-}
-
-
-
-void jobDisplayAnimations(void *parm, Job *j) {
-// printf("jobDisplayAnimations()...\n");
-
- StaticCnv v14;
-
- uint16 _si = 0;
-
- for (AnimationList::iterator it = _vm->_animations.begin(); it != _vm->_animations.end(); it++) {
-
- Animation *v18 = *it;
-
- if ((v18->_flags & kFlagsActive) && ((v18->_flags & kFlagsRemove) == 0)) {
- v14._width = v18->width();
- v14._height = v18->height();
-
- int16 frame = CLIP((int)v18->_frame, 0, v18->getFrameNum()-1);
-
- v14._data0 = v18->getFrameData(frame);
-// v14._data1 = v18->_cnv->field_8[frame];
-
- if (v18->_flags & kFlagsNoMasked)
- _si = 3;
- else
- _si = _vm->_gfx->queryMask(v18->_top + v18->height());
-
- debugC(9, kDebugLocation, "jobDisplayAnimations(%s, x:%i, y:%i, z:%i, w:%i, h:%i, f:%i/%i, %p)", v18->_label._text, v18->_left, v18->_top, _si, v14._width, v14._height,
- frame, v18->getFrameNum(), v14._data0);
- _vm->_gfx->blitCnv(&v14, v18->_left, v18->_top, _si, Gfx::kBitBack);
-
- }
-
- if (((v18->_flags & kFlagsActive) == 0) && (v18->_flags & kFlagsRemove)) {
- v18->_flags &= ~kFlagsRemove;
- v18->_oldPos.x = -1000;
- }
-
- if ((v18->_flags & kFlagsActive) && (v18->_flags & kFlagsRemove)) {
- v18->_flags &= ~kFlagsActive;
- v18->_flags |= kFlagsRemove;
- }
-
- }
-
-// printf("done\n");
-
- return;
-}
-
-
-void jobEraseAnimations(void *arg_0, Job *j) {
- debugC(3, kDebugJobs, "jobEraseAnimations");
-
- for (AnimationList::iterator it = _vm->_animations.begin(); it != _vm->_animations.end(); it++) {
-
- Animation *a = *it;
-
- if (((a->_flags & kFlagsActive) == 0) && ((a->_flags & kFlagsRemove) == 0)) continue;
-
- Common::Rect r(a->width(), a->height());
- r.moveTo(a->_oldPos);
- _vm->_gfx->restoreBackground(r);
-
- if (arg_0) {
- a->_oldPos.x = a->_left;
- a->_oldPos.y = a->_top;
- }
-
- }
-
-// printf("done\n");
-
- return;
-}
-
-
-void Parallaction::loadProgram(Animation *a, char *filename) {
-// printf("loadProgram(%s)\n", filename);
-
- Script *script = _disk->loadScript(filename);
-
- _numLocals = 0;
-
- fillBuffers(*script);
-
- a->_program = new Program;
-
- Instruction *vCC = new Instruction;
-
- while (scumm_stricmp(_tokens[0], "endscript")) {
- parseScriptLine(vCC, a, a->_program->_locals);
- a->_program->_instructions.push_back(vCC);
- vCC = new Instruction;
- fillBuffers(*script);
- }
-
- // TODO: use List<>::end() to detect the end of the program
- vCC->_index = INST_END;
- a->_program->_instructions.push_back(vCC);
- a->_program->_ip = a->_program->_instructions.begin();
-
- delete script;
-
- return;
-}
-
-
-
-
-
-
-void Parallaction::parseScriptLine(Instruction *inst, Animation *a, LocalVariable *locals) {
-// printf("parseScriptLine()\n");
-
- if (_tokens[0][1] == '.') {
- _tokens[0][1] = '\0';
- a = findAnimation(&_tokens[0][2]);
- }
-
- if (_tokens[1][1] == '.') {
- _tokens[1][1] = '\0';
- a = findAnimation(&_tokens[1][2]);
- }
-
- int16 _si = _instructionNames->lookup(_tokens[0]);
- inst->_index = _si;
-
-// printf("token[0] = %s (%i)\n", _tokens[0], inst->_index);
-
- switch (inst->_index) {
- case INST_ON: // on
- case INST_OFF: // off
- case INST_START: // start
- if (!scumm_stricmp(_tokens[1], a->_label._text)) {
- inst->_opBase._a = a;
- } else {
- inst->_opBase._a = findAnimation(_tokens[1]);
- }
- break;
-
- case INST_LOOP: // loop
- inst->_opBase._loopCounter = getLValue(inst, _tokens[1], locals, a);
- break;
-
- case INST_X: // x
- inst->_opA._pvalue = &a->_left;
- inst->_opB = getLValue(inst, _tokens[1], locals, a);
- break;
-
- case INST_Y: // y
- inst->_opA._pvalue = &a->_top;
- inst->_opB = getLValue(inst, _tokens[1], locals, a);
- break;
-
- case INST_Z: // z
- inst->_opA._pvalue = &a->_z;
- inst->_opB = getLValue(inst, _tokens[1], locals, a);
- break;
-
- case INST_F: // f
- inst->_opA._pvalue = &a->_frame;
- inst->_opB = getLValue(inst, _tokens[1], locals, a);
- break;
-
- case INST_INC: // inc
- case INST_DEC: // dec
- if (!scumm_stricmp(_tokens[1], "X")) {
- inst->_opA._pvalue = &a->_left;
- } else
- if (!scumm_stricmp(_tokens[1], "Y")) {
- inst->_opA._pvalue = &a->_top;
- } else
- if (!scumm_stricmp(_tokens[1], "Z")) {
- inst->_opA._pvalue = &a->_z;
- } else
- if (!scumm_stricmp(_tokens[1], "F")) {
- inst->_opA._pvalue = &a->_frame;
- } else {
- inst->_flags |= kInstUsesLocal;
- inst->_opA = getLValue(inst, _tokens[1], locals, a);
- }
-
- inst->_opB = getLValue(inst, _tokens[2], locals, a);
-
- if (!scumm_stricmp(_tokens[3], "mod")) {
- inst->_flags |= kInstMod;
- }
- break;
-
- case INST_SET: // set
- inst->_opA = getLValue(inst, _tokens[1], locals, a);
- inst->_flags |= kInstUsesLocal;
- inst->_opB = getLValue(inst, _tokens[2], locals, a);
- break;
-
- case INST_MOVE: // move
- inst->_opA = getLValue(inst, _tokens[1], locals, a);
- inst->_opB = getLValue(inst, _tokens[2], locals, a);
- break;
-
- case INST_PUT: // put
- if (!scumm_stricmp(_tokens[1], a->_label._text)) {
- inst->_opBase._a = a;
- } else {
- inst->_opBase._a = findAnimation(_tokens[1]);
- }
-
- inst->_opA = getLValue(inst, _tokens[2], locals, a);
- inst->_opB = getLValue(inst, _tokens[3], locals, a);
- if (!scumm_stricmp(_tokens[4], "masked")) {
- inst->_flags |= kInstMaskedPut;
- }
- break;
-
- case INST_CALL: { // call
- int16 _ax = _callableNames->lookup(_tokens[1]);
- inst->_opBase._index = _ax - 1;
- if (_ax - 1 < 0) exit(0);
- }
- break;
-
- case INST_SOUND: // sound
- inst->_opBase._z = findZone(_tokens[1]);
- break;
-
- case INST_ENDLOOP: // endloop
- case INST_SHOW: // show
- case INST_WAIT: // wait
- break;
-
- default: // local definition
- strcpy(_localNames[_numLocals], _tokens[0]);
- locals[_numLocals]._value = atoi(_tokens[2]);
-
- if (_tokens[3][0] != '\0') {
- locals[_numLocals]._min = atoi(_tokens[3]);
- locals[_numLocals]._max = atoi(_tokens[4]);
- } else {
- locals[_numLocals]._min = -10000;
- locals[_numLocals]._max = 10000;
- }
-
- inst->_opA._local = &locals[_numLocals];
- inst->_opB._value = locals[_numLocals]._value;
-
- inst->_flags = kInstUsesLiteral | kInstUsesLocal;
- inst->_index = INST_SET;
- _numLocals++;
- break;
-
- }
-
-
- return;
-}
-
-LValue Parallaction::getLValue(Instruction *inst, char *str, LocalVariable *locals, Animation *a) {
-
- LValue v;
-
- v._pvalue = 0; // should stop compiler from complaining
-
- if (isdigit(str[0]) || str[0] == '-') {
- inst->_flags |= kInstUsesLiteral;
- v._value = atoi(str);
- return v;
- }
-
- for (uint16 _si = 0; _si < 10; _si++) {
- if (!scumm_stricmp(str, _localNames[_si])) {
- v._local = &locals[_si];
- return v;
- }
- }
-
- if (str[1] == '.') {
- a = findAnimation(&str[2]);
- }
-
- if (str[0] == 'X') {
- v._pvalue = &a->_left;
- } else
- if (str[0] == 'Y') {
- v._pvalue = &a->_top;
- } else
- if (str[0] == 'Z') {
- v._pvalue = &a->_z;
- } else
- if (str[0] == 'F') {
- v._pvalue = &a->_frame;
- }
-
- return v;
-}
-
-
-
-void jobRunScripts(void *parm, Job *j) {
- debugC(3, kDebugJobs, "jobRunScripts");
-
- static uint16 modCounter = 0;
-
- StaticCnv v18;
-
- for (AnimationList::iterator it = _vm->_animations.begin(); it != _vm->_animations.end(); it++) {
-
- Animation *a = *it;
-
- if (a->_flags & kFlagsCharacter) a->_z = a->_top + a->height();
-
- if ((a->_flags & kFlagsActing) == 0) continue;
- InstructionList::iterator inst = a->_program->_ip;
-
-// printf("Animation: %s, flags: %x\n", a->_name, a->_flags);
-
- while (((*inst)->_index != INST_SHOW) && (a->_flags & kFlagsActing)) {
-
- debugC(9, kDebugJobs, "Animation: %s, instruction: %s", a->_label._text, (*inst)->_index == INST_END ? "end" : _vm->_instructionNamesRes[(*inst)->_index - 1]);
-
- switch ((*inst)->_index) {
- case INST_ENDLOOP: // endloop
- if (--a->_program->_loopCounter > 0) {
- inst = a->_program->_loopStart;
- }
- break;
-
- case INST_OFF: {// off
- (*inst)->_opBase._a->_flags |= kFlagsRemove;
-// v1C = (*inst)->_opBase;
- }
- break;
-
- case INST_ON: // on
- (*inst)->_opBase._a->_flags |= kFlagsActive;
- (*inst)->_opBase._a->_flags &= ~kFlagsRemove;
- break;
-
- case INST_START: // start
-// v1C = (*inst)->_opBase;
- (*inst)->_opBase._a->_flags |= (kFlagsActing | kFlagsActive);
- break;
-
- case INST_LOOP: // loop
- if ((*inst)->_flags & kInstUsesLiteral) {
- a->_program->_loopCounter = (*inst)->_opBase._loopCounter._value;
- } else {
- a->_program->_loopCounter = *(*inst)->_opBase._loopCounter._pvalue;
- }
- a->_program->_loopStart = inst;
- break;
-
- case INST_INC: // inc
- case INST_DEC: { // dec
- int16 _si = 0;
- int16 _ax = 0, _bx = 0;
- if ((*inst)->_flags & kInstUsesLiteral) {
- _si = (*inst)->_opB._value;
- } else {
- _si = *(*inst)->_opB._pvalue;
- }
- if ((*inst)->_flags & kInstMod) { // mod
- _bx = (_si > 0 ? _si : -_si);
- if (modCounter % _bx != 0) break;
-
- _si = (_si > 0 ? 1 : -1);
- }
- if ((*inst)->_flags & kInstUsesLocal) { // local
- if ((*inst)->_index == INST_INC) _ax = _si;
- else _ax = -_si;
-
- (*inst)->_opA._local->_value += _ax;
- wrapLocalVar((*inst)->_opA._local);
- break;
- }
-
- // built-in variable (x, y, z, f)
- if ((*inst)->_index == INST_INC) _ax = _si;
- else _ax = -_si;
- *(*inst)->_opA._pvalue += _ax;
- }
- break;
-
- case INST_MOVE: { // move
- WalkNodeList *v4 = _vm->_char._builder.buildPath(*(*inst)->_opA._pvalue, *(*inst)->_opB._pvalue);
- _vm->addJob(&jobWalk, v4, kPriority19 );
- _engineFlags |= kEngineWalking;
- }
- break;
-
- case INST_PUT: // put
- v18._width = (*inst)->_opBase._a->width();
- v18._height = (*inst)->_opBase._a->height();
- v18._data0 = (*inst)->_opBase._a->getFrameData((*inst)->_opBase._a->_frame);
- v18._data1 = NULL; // (*inst)->_opBase._a->_cnv.field_8[(*inst)->_opBase._a->_frame];
-
- if ((*inst)->_flags & kInstMaskedPut) {
- uint16 _si = _vm->_gfx->queryMask((*inst)->_opB._value);
- _vm->_gfx->blitCnv(&v18, (*inst)->_opA._value, (*inst)->_opB._value, _si, Gfx::kBitBack);
- _vm->_gfx->blitCnv(&v18, (*inst)->_opA._value, (*inst)->_opB._value, _si, Gfx::kBit2);
- } else {
- _vm->_gfx->flatBlitCnv(&v18, (*inst)->_opA._value, (*inst)->_opB._value, Gfx::kBitBack);
- _vm->_gfx->flatBlitCnv(&v18, (*inst)->_opA._value, (*inst)->_opB._value, Gfx::kBit2);
- }
- break;
-
- case INST_END: // exit
- if ((a->_flags & kFlagsLooping) == 0) {
- a->_flags &= ~kFlagsActing;
- _vm->runCommands(a->_commands, a);
- }
- a->_program->_ip = a->_program->_instructions.begin();
- goto label1;
-
-
- case INST_CALL: // call
- _vm->callFunction((*inst)->_opBase._index, 0);
- break;
-
- case INST_WAIT: // wait
- if (_engineFlags & kEngineWalking) goto label1;
- break;
-
- case INST_SOUND: // sound
- _activeZone = (*inst)->_opBase._z;
- break;
-
- default: { // INST_SET, INST_X, INST_Y, INST_Z, INST_F
- int16 _si;
- if ((*inst)->_flags & kInstUsesLiteral) {
- _si = (*inst)->_opB._value;
- } else {
- _si = *(*inst)->_opB._pvalue;
- }
-
- if ((*inst)->_flags & kInstUsesLocal) {
- (*inst)->_opA._local->_value = _si;
- } else {
- *(*inst)->_opA._pvalue = _si;
- }
- }
- break;
-
- }
-
- inst++;
- }
-
- a->_program->_ip = ++inst;
-
-label1:
- if (a->_flags & kFlagsCharacter)
- a->_z = a->_top + a->height();
- }
-
- _vm->sortAnimations();
- modCounter++;
-
- return;
-}
-
-void wrapLocalVar(LocalVariable *local) {
-// printf("wrapLocalVar(v: %i, min: %i, max: %i)\n", local->_value, local->_min, local->_max);
-
- if (local->_value >= local->_max)
- local->_value = local->_min;
- if (local->_value < local->_min)
- local->_value = local->_max - 1;
-
- return;
-}
-
-int compareAnimationZ(const AnimationPointer &a1, const AnimationPointer &a2) {
- if (a1->_z == a2->_z) return 0;
- return (a1->_z < a2->_z ? -1 : 1);
-}
-
-
-void Parallaction::sortAnimations() {
- _char._ani._z = _char._ani.height() + _char._ani._top;
- _animations.sort(compareAnimationZ);
- return;
-}
-
-Animation::Animation() {
- _cnv = NULL;
- _program = NULL;
- _frame = 0;
- _z = 0;
-}
-
-Animation::~Animation() {
- if (_program)
- delete _program;
-
- if (_cnv)
- delete _cnv;
-}
-
-uint16 Animation::width() const {
- if (!_cnv) return 0;
- return _cnv->_width;
-}
-
-uint16 Animation::height() const {
- if (!_cnv) return 0;
- return _cnv->_height;
-}
-
-uint16 Animation::getFrameNum() const {
- if (!_cnv) return 0;
- return _cnv->_count;
-}
-
-byte* Animation::getFrameData(uint32 index) const {
- if (!_cnv) return NULL;
- return _cnv->getFramePtr(index);
-}
-
-
-Program::Program() {
- _loopCounter = 0;
- _locals = new LocalVariable[10];
-}
-
-Program::~Program() {
- delete[] _locals;
-}
-
-
-} // namespace Parallaction
diff --git a/engines/parallaction/callables_ns.cpp b/engines/parallaction/callables_ns.cpp
index 94a0747ab1..8f5c80fc0c 100644
--- a/engines/parallaction/callables_ns.cpp
+++ b/engines/parallaction/callables_ns.cpp
@@ -199,13 +199,11 @@ void Parallaction_ns::_c_score(void *parm) {
void Parallaction_ns::_c_fade(void *parm) {
- _gfx->setBlackPalette();
-
- Gfx::Palette pal;
- memset(pal, 0, sizeof(Gfx::Palette));
+ Palette pal;
+ _gfx->setPalette(pal);
for (uint16 _di = 0; _di < 64; _di++) {
- _gfx->fadePalette(pal, _gfx->_palette, 1);
+ pal.fadeTo(_gfx->_palette, 1);
_gfx->setPalette(pal);
_gfx->updateScreen();
@@ -331,35 +329,21 @@ void Parallaction_ns::_c_onMouse(void *parm) {
void Parallaction_ns::_c_setMask(void *parm) {
- _gfx->intGrottaHackMask();
+ memset(_backgroundInfo->mask.data + 3600, 0, 3600);
+ _gfx->_bgLayers[1] = 500;
return;
}
void Parallaction_ns::_c_endComment(void *param) {
- int16 w = 0, h = 0;
- _gfx->getStringExtent(_location._endComment, 130, &w, &h);
-
- Common::Rect r(w+5, h+5);
- r.moveTo(5, 5);
- _gfx->floodFill(Gfx::kBitFront, r, 0);
-
- r.setWidth(w+3);
- r.setHeight(h+3);
- r.moveTo(7, 7);
- _gfx->floodFill(Gfx::kBitFront, r, 1);
-
- _gfx->setFont(kFontDialogue);
- _gfx->displayWrappedString(_location._endComment, 3, 5, 0, 130);
- _gfx->updateScreen();
-
+ showLocationComment(_location._endComment, true);
- Gfx::Palette pal;
- _gfx->makeGrayscalePalette(pal);
+ Palette pal(_gfx->_palette);
+ pal.makeGrayscale();
for (uint di = 0; di < 64; di++) {
- _gfx->fadePalette(_gfx->_palette, pal, 1);
+ _gfx->_palette.fadeTo(pal, 1);
_gfx->setPalette(_gfx->_palette);
_gfx->updateScreen();
@@ -373,24 +357,19 @@ void Parallaction_ns::_c_endComment(void *param) {
void Parallaction_ns::_c_frankenstein(void *parm) {
- Gfx::Palette pal0;
- Gfx::Palette pal1;
+ Palette pal0(_gfx->_palette);
+ Palette pal1;
- for (uint16 i = 0; i <= BASE_PALETTE_COLORS; i++) {
- pal0[(i+FIRST_BASE_COLOR)] = _gfx->_palette[i];
- pal0[(i+FIRST_BASE_COLOR)*3+1] = 0;
- pal0[(i+FIRST_BASE_COLOR)*3+2] = 0;
-
- pal1[(i+FIRST_BASE_COLOR)*3+1] = 0;
- pal1[(i+FIRST_BASE_COLOR)*3+2] = 0;
+ for (uint16 i = 0; i <= 32; i++) {
+ pal0.setEntry(i, -1, 0, 0); // leaves reds unchanged while zeroing other components
}
for (uint16 _di = 0; _di < 30; _di++) {
g_system->delayMillis(20);
- _gfx->setPalette(pal0, FIRST_BASE_COLOR, BASE_PALETTE_COLORS);
+ _gfx->setPalette(pal0);
_gfx->updateScreen();
g_system->delayMillis(20);
- _gfx->setPalette(pal1, FIRST_BASE_COLOR, BASE_PALETTE_COLORS);
+ _gfx->setPalette(pal1);
_gfx->updateScreen();
}
@@ -435,7 +414,7 @@ void Parallaction_ns::_c_finito(void *parm) {
_gfx->setPalette(_gfx->_palette);
if (gameCompleted) {
- _gfx->setFont(kFontMenu);
+ _gfx->setFont(_menuFont);
_gfx->displayCenteredString(70, v4C[_language]);
_gfx->displayCenteredString(100, v3C[_language]);
_gfx->displayCenteredString(130, v2C[_language]);
@@ -448,7 +427,7 @@ void Parallaction_ns::_c_finito(void *parm) {
_engineFlags |= kEngineChangeLocation;
} else {
- _gfx->setFont(kFontMenu);
+ _gfx->setFont(_menuFont);
_gfx->displayCenteredString(70, v8C[_language]);
_gfx->displayCenteredString(100, v7C[_language]);
_gfx->displayCenteredString(130, v6C[_language]);
@@ -493,7 +472,7 @@ void Parallaction_ns::_c_testResult(void *parm) {
_disk->selectArchive("disk1");
parseLocation("common");
- _gfx->setFont(kFontMenu);
+ _gfx->setFont(_menuFont);
_gfx->displayCenteredString(38, _slideText[0]);
_gfx->displayCenteredString(58, _slideText[1]);
@@ -538,9 +517,9 @@ void Parallaction_ns::_c_startIntro(void *parm) {
void Parallaction_ns::_c_endIntro(void *parm) {
- _gfx->setFont(kFontMenu);
+ _gfx->setFont(_menuFont);
- debugC(1, kDebugLocation, "endIntro()");
+ debugC(1, kDebugExec, "endIntro()");
for (uint16 _si = 0; _si < 6; _si++) {
_gfx->displayCenteredString(80, _credits[_si]._role);
@@ -559,7 +538,7 @@ void Parallaction_ns::_c_endIntro(void *parm) {
_gfx->copyScreen(Gfx::kBitBack, Gfx::kBitFront);
}
- debugC(1, kDebugLocation, "endIntro(): done showing credits");
+ debugC(1, kDebugExec, "endIntro(): done showing credits");
if ((getFeatures() & GF_DEMO) == 0) {
_gfx->displayCenteredString(80, "CLICK MOUSE BUTTON TO START");
@@ -604,21 +583,40 @@ void Parallaction_ns::_c_moveSheet(void *parm) {
return;
}
-void plotPixel(int x, int y, int color, void *data) {
- _vm->_gfx->plotMaskPixel(x, y, color);
+void zeroMask(int x, int y, int color, void *data) {
+ //_vm->_gfx->zeroMaskValue(x, y, color);
+
+ BackgroundInfo* info = (BackgroundInfo*)data;
+
+ uint16 _ax = x + y * info->width;
+ info->mask.data[_ax >> 2] &= ~(3 << ((_ax & 3) << 1));
+
}
void Parallaction_ns::_c_sketch(void *parm) {
static uint16 index = 1;
- uint16 newy = _rightHandPositions[2*index+1];
- uint16 newx = _rightHandPositions[2*index];
+ uint16 newx;
+ uint16 newy;
uint16 oldy = _rightHandPositions[2*(index-1)+1];
uint16 oldx = _rightHandPositions[2*(index-1)];
- Graphics::drawLine(oldx, oldy, newx, newy, 0, plotPixel, NULL);
+ // WORKAROUND: original code overflowed _rightHandPositions by trying
+ // to access elements at positions 684 and 685. That used to happen
+ // when index == 342. Code now checks for this possibility and assigns
+ // the last valid value to the new coordinates for drawing without
+ // accessing the array.
+ if (index == 342) {
+ newy = oldy;
+ newx = oldx;
+ } else {
+ newy = _rightHandPositions[2*index+1];
+ newx = _rightHandPositions[2*index];
+ }
+
+ Graphics::drawLine(oldx, oldy, newx, newy, 0, zeroMask, _backgroundInfo);
_rightHandAnim->_left = newx;
_rightHandAnim->_top = newy - 20;
@@ -640,7 +638,12 @@ void Parallaction_ns::_c_shade(void *parm) {
_rightHandAnim->_top
);
- _gfx->fillMaskRect(r, 0);
+ uint16 _di = r.left/4 + r.top * _backgroundInfo->mask.internalWidth;
+
+ for (uint16 _si = r.top; _si < r.bottom; _si++) {
+ memset(_backgroundInfo->mask.data + _di, 0, r.width()/4+1);
+ _di += _backgroundInfo->mask.internalWidth;
+ }
return;
diff --git a/engines/parallaction/commands.cpp b/engines/parallaction/commands.cpp
deleted file mode 100644
index dc392fde2c..0000000000
--- a/engines/parallaction/commands.cpp
+++ /dev/null
@@ -1,351 +0,0 @@
-/* ScummVM - Graphic Adventure Engine
- *
- * ScummVM is the legal property of its developers, whose names
- * are too numerous to list here. Please refer to the COPYRIGHT
- * file distributed with this source distribution.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
-
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
-
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * $URL$
- * $Id$
- *
- */
-
-#include "common/stdafx.h"
-
-#include "parallaction/parallaction.h"
-
-
-namespace Parallaction {
-
-#define CMD_SET 1
-#define CMD_CLEAR 2
-#define CMD_START 3
-#define CMD_SPEAK 4
-#define CMD_GET 5
-#define CMD_LOCATION 6
-#define CMD_OPEN 7
-#define CMD_CLOSE 8
-#define CMD_ON 9
-#define CMD_OFF 10
-#define CMD_CALL 11
-#define CMD_TOGGLE 12
-#define CMD_DROP 13
-#define CMD_QUIT 14
-#define CMD_MOVE 15
-#define CMD_STOP 16
-
-
-void Parallaction::parseCommands(Script &script, CommandList& list) {
-// printf("parseCommands()");
-
- fillBuffers(script, true);
-
- while (scumm_stricmp(_tokens[0], "ENDCOMMANDS") && scumm_stricmp(_tokens[0], "ENDZONE")) {
-// printf("token[0] = %s", _tokens[0]);
-
- Command *cmd = new Command;
-
- cmd->_id = _commandsNames->lookup(_tokens[0]);
- uint16 _si = 1;
-
-// printf("cmd id = %i", cmd->_id);
-
- switch (cmd->_id) {
- case CMD_SET: // set
- case CMD_CLEAR: // clear
- case CMD_TOGGLE: // toggle
- if (_globalTable->lookup(_tokens[1]) == -1) {
- do {
- char _al = _localFlagNames->lookup(_tokens[_si]);
- _si++;
- cmd->u._flags |= 1 << (_al - 1);
- } while (!scumm_stricmp(_tokens[_si++], "|"));
- _si--;
- } else {
- cmd->u._flags |= kFlagsGlobal;
- do {
- char _al = _globalTable->lookup(_tokens[1]);
- _si++;
- cmd->u._flags |= 1 << (_al - 1);
- } while (!scumm_stricmp(_tokens[_si++], "|"));
- _si--;
- }
- break;
-
- case CMD_START: // start
- case CMD_STOP: // stop
- cmd->u._animation = findAnimation(_tokens[_si]);
- _si++;
- if (cmd->u._animation == NULL) {
- strcpy(_forwardedAnimationNames[_numForwards], _tokens[_si-1]);
- _forwardedCommands[_numForwards] = cmd;
- _numForwards++;
- }
- break;
-
- case CMD_SPEAK: // speak
- case CMD_GET: // get
- case CMD_OPEN: // open
- case CMD_CLOSE: // close
- case CMD_ON: // on
- case CMD_OFF: // off
- cmd->u._zone = findZone(_tokens[_si]);
- _si++;
- break;
-
- case CMD_LOCATION: // location
- cmd->u._string = (char*)malloc(strlen(_tokens[_si])+1);
- strcpy(cmd->u._string, _tokens[_si]);
- _si++;
- break;
-
- case CMD_CALL: // call
- cmd->u._callable = _callableNames->lookup(_tokens[_si]) - 1;
- _si++;
- break;
-
- case CMD_DROP: // drop
- cmd->u._object = _objectsNames->lookup(_tokens[_si]);
- _si++;
- break;
-
- case CMD_QUIT: // quit
- break;
-
- case CMD_MOVE: // move
- cmd->u._move._x = atoi(_tokens[_si]);
- _si++;
- cmd->u._move._y = atoi(_tokens[_si]);
- _si++;
- break;
-
- }
-
- if (!scumm_stricmp(_tokens[_si], "flags")) {
- _si++;
-
- do {
- if (!scumm_stricmp(_tokens[_si], "exit") || !scumm_stricmp(_tokens[_si], "exittrap")) {
- cmd->_flagsOn |= kFlagsExit;
- } else
- if (!scumm_stricmp(_tokens[_si], "enter") || !scumm_stricmp(_tokens[_si], "entertrap")) {
- cmd->_flagsOn |= kFlagsEnter;
- } else
- if (!scumm_strnicmp(_tokens[_si], "no", 2)) {
- byte _al = _localFlagNames->lookup(&_tokens[_si][2]);
- cmd->_flagsOff |= 1 << (_al - 1);
- } else {
- byte _al = _localFlagNames->lookup(_tokens[_si]);
- cmd->_flagsOn |= 1 << (_al - 1);
- }
-
- _si++;
-
- } while (!scumm_stricmp(_tokens[_si++], "|"));
-
- }
-
- if (!scumm_stricmp(_tokens[_si], "gflags")) {
- _si++;
- cmd->_flagsOn |= kFlagsGlobal;
-
- do {
- if (!scumm_stricmp(_tokens[_si], "exit")) {
- cmd->_flagsOn |= kFlagsExit;
- } else
- if (!scumm_stricmp(_tokens[_si], "enter")) {
- cmd->_flagsOn |= kFlagsEnter;
- } else
- if (!scumm_strnicmp(_tokens[_si], "no", 2)) {
- byte _al = _globalTable->lookup(&_tokens[_si][2]);
- cmd->_flagsOff |= 1 << (_al - 1);
- } else {
- byte _al = _globalTable->lookup(_tokens[_si]);
- cmd->_flagsOn |= 1 << (_al - 1);
- }
-
- _si++;
-
- } while (!scumm_stricmp(_tokens[_si++], "|"));
-
- }
-
- list.push_front(cmd); // NOTE: command lists are written backwards in scripts
- fillBuffers(script, true);
-
- }
-
-}
-
-
-void Parallaction::runCommands(CommandList& list, Zone *z) {
- debugC(1, kDebugLocation, "runCommands");
-
- CommandList::iterator it = list.begin();
- for ( ; it != list.end(); it++) {
-
- Command *cmd = *it;
- CommandData *u = &cmd->u;
- uint32 v8 = _localFlags[_currentLocationIndex];
-
- if (_engineFlags & kEngineQuit)
- break;
-
- if (cmd->_flagsOn & kFlagsGlobal) {
- v8 = _commandFlags | kFlagsGlobal;
- }
-
- if ((cmd->_flagsOn & v8) != cmd->_flagsOn) continue;
- if ((cmd->_flagsOff & ~v8) != cmd->_flagsOff) continue;
-
- debugC(1, kDebugLocation, "runCommands: %s (on: %x, off: %x)", _commandsNamesRes[cmd->_id-1], cmd->_flagsOn, cmd->_flagsOff);
-
- switch (cmd->_id) {
-
- case CMD_SET: // set
- if (cmd->u._flags & kFlagsGlobal) {
- cmd->u._flags &= ~kFlagsGlobal;
- _commandFlags |= cmd->u._flags;
- } else {
- _localFlags[_currentLocationIndex] |= cmd->u._flags;
- }
- break;
-
- case CMD_CLEAR: // clear
- if (cmd->u._flags & kFlagsGlobal) {
- cmd->u._flags &= ~kFlagsGlobal;
- _commandFlags &= ~cmd->u._flags;
- } else {
- _localFlags[_currentLocationIndex] &= ~cmd->u._flags;
- }
- break;
-
- case CMD_TOGGLE: // toggle
- if (cmd->u._flags & kFlagsGlobal) {
- cmd->u._flags &= ~kFlagsGlobal;
- _commandFlags ^= cmd->u._flags;
- } else {
- _localFlags[_currentLocationIndex] ^= cmd->u._flags;
- }
- break;
-
- case CMD_START: // start
- cmd->u._zone->_flags |= kFlagsActing;
- break;
-
- case CMD_STOP: // stop
- cmd->u._zone->_flags &= ~kFlagsActing;
- break;
-
- case CMD_SPEAK: // speak
- _activeZone = u->_zone;
- break;
-
- case CMD_GET: // get
- u->_zone->_flags &= ~kFlagsFixed;
- if (!runZone(u->_zone)) {
- runCommands(u->_zone->_commands);
- }
- break;
-
- case CMD_DROP: // drop
- dropItem( u->_object );
- break;
-
- case CMD_OPEN: // open
- u->_zone->_flags &= ~kFlagsClosed;
- if (u->_zone->u.door->_cnv) {
- addJob(&jobToggleDoor, (void*)u->_zone, kPriority18 );
- }
- break;
-
- case CMD_CLOSE: // close
- u->_zone->_flags |= kFlagsClosed;
- if (u->_zone->u.door->_cnv) {
- addJob(&jobToggleDoor, (void*)u->_zone, kPriority18 );
- }
- break;
-
- case CMD_ON: // on
- // WORKAROUND: the original DOS-based engine didn't check u->_zone before dereferencing
- // the pointer to get structure members, thus leading to crashes in systems with memory
- // protection.
- // As a side note, the overwritten address is the 5th entry in the DOS interrupt table
- // (print screen handler): this suggests that a system would hang when the print screen
- // key is pressed after playing Nippon Safes, provided that this code path is taken.
- if (u->_zone != NULL) {
- u->_zone->_flags &= ~kFlagsRemove;
- u->_zone->_flags |= kFlagsActive;
- if ((u->_zone->_type & 0xFFFF) == kZoneGet) {
- addJob(&jobDisplayDroppedItem, u->_zone, kPriority17 );
- }
- }
- break;
-
- case CMD_OFF: // off
- u->_zone->_flags |= kFlagsRemove;
- break;
-
- case CMD_LOCATION: // location
- strcpy(_location._name, u->_string);
- _engineFlags |= kEngineChangeLocation;
- break;
-
- case CMD_CALL: // call
- callFunction(u->_callable, z);
- break;
-
- case CMD_QUIT: // quit
- _engineFlags |= kEngineQuit;
- break;
-
- case CMD_MOVE: { // move
- if ((_char._ani._flags & kFlagsRemove) || (_char._ani._flags & kFlagsActive) == 0) {
- continue;
- }
-
- WalkNodeList *vC = _char._builder.buildPath(u->_move._x, u->_move._y);
-
- addJob(&jobWalk, vC, kPriority19 );
- _engineFlags |= kEngineWalking;
- }
- break;
-
- }
- }
-
- debugC(1, kDebugLocation, "runCommands completed");
-
- return;
-
-}
-
-Command::Command() {
- _id = 0;
- _flagsOn = 0;
- _flagsOff = 0;
-}
-
-Command::~Command() {
-
- if (_id == CMD_LOCATION) free(u._string);
-
-}
-
-} // namespace Parallaction
-
-
-
diff --git a/engines/parallaction/debug.cpp b/engines/parallaction/debug.cpp
index 95091789a9..5e419def52 100644
--- a/engines/parallaction/debug.cpp
+++ b/engines/parallaction/debug.cpp
@@ -116,7 +116,7 @@ bool Debugger::Cmd_Give(int argc, const char **argv) {
DebugPrintf("give <item name>\n");
} else {
int index = _vm->_objectsNames->lookup(argv[1]);
- if (index != -1)
+ if (index != Table::notFound)
_vm->addInventoryItem(index + 4);
else
DebugPrintf("invalid item name '%s'\n", argv[1]);
@@ -135,7 +135,7 @@ bool Debugger::Cmd_Jobs(int argc, const char **argv) {
"|tag| description |\n"
"+---+-------------------------------------------------------------+\n");
for ( ; b != e; b++) {
- DebugPrintf("|%3i| %-60s|\n", (*b)->_tag, _jobDescriptions[(*b)->_tag] );
+ DebugPrintf("|%3i| %-60s|\n", (*b)->_job->_tag, _jobDescriptions[(*b)->_job->_tag] );
}
DebugPrintf("+---+-------------------------------------------------------------+\n");
diff --git a/engines/parallaction/detection.cpp b/engines/parallaction/detection.cpp
index 84c45584a4..8ad79f34eb 100644
--- a/engines/parallaction/detection.cpp
+++ b/engines/parallaction/detection.cpp
@@ -48,6 +48,7 @@ Common::Platform Parallaction::getPlatform() const { return _gameDescription->de
}
static const PlainGameDescriptor parallactionGames[] = {
+ {"parallaction", "Parallaction engine game"},
{"nippon", "Nippon Safes Inc."},
{"bra", "The Big Red Adventure"},
{0, 0}
@@ -176,7 +177,7 @@ static const Common::ADParams detectionParams = {
// Structure for autoupgrading obsolete targets
0,
// Name of single gameid (optional)
- 0,
+ "parallaction",
// List of files for file-based fallback detection (optional)
0,
// Fallback callback
@@ -185,33 +186,27 @@ static const Common::ADParams detectionParams = {
Common::kADFlagAugmentPreferredTarget
};
-GameList Engine_PARALLACTION_gameIDList() {
- return GameList(parallactionGames);
-}
-
-GameDescriptor Engine_PARALLACTION_findGameID(const char *gameid) {
- return Common::AdvancedDetector::findGameID(gameid, parallactionGames);
-}
-
-GameList Engine_PARALLACTION_detectGames(const FSList &fslist) {
- return Common::AdvancedDetector::detectAllGames(fslist, detectionParams);
-}
-
-PluginError Engine_PARALLACTION_create(OSystem *syst, Engine **engine) {
- assert(engine);
- const char *gameid = ConfMan.get("gameid").c_str();
+bool engineCreateParallaction(OSystem *syst, Engine **engine, Common::EncapsulatedADGameDesc encapsulatedDesc) {
+ const Parallaction::PARALLACTIONGameDescription *gd = (const Parallaction::PARALLACTIONGameDescription *)(encapsulatedDesc.realDesc);
+ bool res = true;
- if (!scumm_stricmp("nippon", gameid)) {
+ switch (gd->gameType) {
+ case Parallaction::GType_Nippon:
*engine = new Parallaction::Parallaction_ns(syst);
- } else
- if (!scumm_stricmp("bra", gameid)) {
+ break;
+ case Parallaction::GType_BRA:
*engine = new Parallaction::Parallaction_br(syst);
- } else
- error("Parallaction engine created with invalid gameid ('%s')", gameid);
+ break;
+ default:
+ res = false;
+ error("Parallaction engine: unknown gameType");
+ }
- return kNoError;
+ return res;
}
+ADVANCED_DETECTOR_DEFINE_PLUGIN_WITH_COMPLEX_CREATION(PARALLACTION, engineCreateParallaction, detectionParams);
+
REGISTER_PLUGIN(PARALLACTION, "Parallaction engine", "Nippon Safes Inc. (C) Dynabyte");
diff --git a/engines/parallaction/dialogue.cpp b/engines/parallaction/dialogue.cpp
index 84ecde6e64..15a280d3be 100644
--- a/engines/parallaction/dialogue.cpp
+++ b/engines/parallaction/dialogue.cpp
@@ -46,7 +46,7 @@ namespace Parallaction {
#define ANSWER_CHARACTER_X 10
#define ANSWER_CHARACTER_Y 80
-int16 selectAnswer(Question *q, StaticCnv*);
+int16 selectAnswer(Question *q, Graphics::Surface*);
int16 getHoverAnswer(int16 x, int16 y, Question *q);
int16 _answerBalloonX[10] = { 80, 120, 150, 150, 150, 0, 0, 0, 0, 0 };
@@ -56,136 +56,6 @@ int16 _answerBalloonH[10] = { 0 };
-Dialogue *Parallaction::parseDialogue(Script &script) {
-// printf("parseDialogue()\n");
- uint16 numQuestions = 0;
-
- Dialogue *dialogue = new Dialogue;
-
- Table forwards(20);
-
- fillBuffers(script, true);
-
- while (scumm_stricmp(_tokens[0], "enddialogue")) {
- if (scumm_stricmp(_tokens[0], "Question")) continue;
-
- Question *question = new Question;
- dialogue->_questions[numQuestions] = question;
-
- forwards.addData(_tokens[1]);
-
- question->_text = parseDialogueString(script);
-
- fillBuffers(script, true);
- question->_mood = atoi(_tokens[0]);
-
- uint16 numAnswers = 0;
-
- fillBuffers(script, true);
- while (scumm_stricmp(_tokens[0], "endquestion")) { // parse answers
-
- Answer *answer = new Answer;
- question->_answers[numAnswers] = answer;
-
- if (_tokens[1][0]) {
-
- Table* flagNames;
- uint16 token;
-
- if (!scumm_stricmp(_tokens[1], "global")) {
- token = 2;
- flagNames = _globalTable;
- answer->_yesFlags |= kFlagsGlobal;
- } else {
- token = 1;
- flagNames = _localFlagNames;
- }
-
- do {
-
- if (!scumm_strnicmp(_tokens[token], "no", 2)) {
- byte _al = flagNames->lookup(_tokens[token]+2);
- answer->_noFlags |= 1 << (_al - 1);
- } else {
- byte _al = flagNames->lookup(_tokens[token]);
- answer->_yesFlags |= 1 << (_al - 1);
- }
-
- token++;
-
- } while (!scumm_stricmp(_tokens[token++], "|"));
-
- }
-
- answer->_text = parseDialogueString(script);
-
- fillBuffers(script, true);
- answer->_mood = atoi(_tokens[0]);
- answer->_following._name = parseDialogueString(script);
-
- fillBuffers(script, true);
- if (!scumm_stricmp(_tokens[0], "commands")) {
- parseCommands(script, answer->_commands);
- fillBuffers(script, true);
- }
-
- numAnswers++;
- }
-
- fillBuffers(script, true);
- numQuestions++;
-
- }
-
- // link questions
- byte v50[20];
- memset(v50, 0, 20);
-
- for (uint16 i = 0; i < numQuestions; i++) {
- Question *question = dialogue->_questions[i];
-
- for (uint16 j = 0; j < NUM_ANSWERS; j++) {
- Answer *answer = question->_answers[j];
- if (answer == 0) continue;
-
- int16 index = forwards.lookup(answer->_following._name);
- free(answer->_following._name);
-
- if (index == -1)
- answer->_following._question = 0;
- else
- answer->_following._question = dialogue->_questions[index - 1];
-
-
- }
- }
-
- return dialogue;
-}
-
-
-char *Parallaction::parseDialogueString(Script &script) {
-
- char vC8[200];
- char *vD0 = NULL;
- do {
-
- vD0 = script.readLine(vC8, 200);
- if (vD0 == 0) return NULL;
-
- vD0 = Common::ltrim(vD0);
-
- } while (strlen(vD0) == 0);
-
- vD0[strlen(vD0)-1] = '\0'; // deletes the trailing '0xA'
- // this is critical for Gfx::displayWrappedString to work properly
-
- char *vCC = (char*)malloc(strlen(vD0)+1);
- strcpy(vCC, vD0);
-
- return vCC;
-}
-
class DialogueManager {
Parallaction *_vm;
@@ -195,8 +65,8 @@ class DialogueManager {
bool _askPassword;
bool isNpc;
- Cnv *_questioner;
- Cnv *_answerer;
+ Frames *_questioner;
+ Frames *_answerer;
Question *_q;
@@ -233,7 +103,7 @@ protected:
};
uint16 DialogueManager::askPassword() {
- debugC(1, kDebugDialogue, "checkDialoguePassword()");
+ debugC(3, kDebugExec, "checkDialoguePassword()");
char password[100];
uint16 passwordLen;
@@ -258,9 +128,10 @@ uint16 DialogueManager::askPassword() {
// FIXME: see comment for updateInput()
if (!g_system->getEventManager()->pollEvent(e)) continue;
- if (e.type != Common::EVENT_KEYDOWN) continue;
if (e.type == Common::EVENT_QUIT)
g_system->quit();
+
+ if (e.type != Common::EVENT_KEYDOWN) continue;
if (!isdigit(e.kbd.ascii)) continue;
password[passwordLen] = e.kbd.ascii;
@@ -291,7 +162,7 @@ uint16 DialogueManager::askPassword() {
bool DialogueManager::displayAnswer(uint16 i) {
- uint32 v28 = _localFlags[_vm->_currentLocationIndex];
+ uint32 v28 = _vm->_localFlags[_vm->_currentLocationIndex];
if (_q->_answers[i]->_yesFlags & kFlagsGlobal)
v28 = _commandFlags | kFlagsGlobal;
@@ -370,7 +241,7 @@ uint16 DialogueManager::getAnswer() {
clear();
- debugC(1, kDebugDialogue, "runDialogue: user selected answer #%i", answer);
+ debugC(3, kDebugExec, "runDialogue: user selected answer #%i", answer);
return answer;
}
@@ -383,6 +254,8 @@ void DialogueManager::run() {
_q = _dialogue->_questions[0];
int16 answer;
+ _vm->_gfx->copyScreen(Gfx::kBitFront, Gfx::kBitBack);
+
while (_q) {
answer = 0;
@@ -488,9 +361,9 @@ int16 DialogueManager::getHoverAnswer(int16 x, int16 y) {
void Parallaction::runDialogue(SpeakData *data) {
- debugC(1, kDebugDialogue, "runDialogue: starting dialogue '%s'", data->_name);
+ debugC(1, kDebugExec, "runDialogue: starting dialogue '%s'", data->_name);
- _gfx->setFont(kFontDialogue);
+ _gfx->setFont(_dialogueFont);
if (getPlatform() == Common::kPlatformPC)
showCursor(false);
@@ -503,34 +376,5 @@ void Parallaction::runDialogue(SpeakData *data) {
return;
}
-Answer::Answer() {
- _text = NULL;
- _mood = 0;
- _following._question = NULL;
- _noFlags = 0;
- _yesFlags = 0;
-}
-
-Answer::~Answer() {
- if (_text)
- free(_text);
-}
-
-Question::Question() {
- _text = NULL;
- _mood = 0;
-
- for (uint32 i = 0; i < NUM_ANSWERS; i++)
- _answers[i] = NULL;
-
-}
-
-Question::~Question() {
-
- for (uint32 i = 0; i < NUM_ANSWERS; i++)
- if (_answers[i]) delete _answers[i];
-
- free(_text);
-}
} // namespace Parallaction
diff --git a/engines/parallaction/disk.h b/engines/parallaction/disk.h
index ae572b1122..6adab69f51 100644
--- a/engines/parallaction/disk.h
+++ b/engines/parallaction/disk.h
@@ -28,6 +28,7 @@
#include "parallaction/defs.h"
#include "common/file.h"
+#include "graphics/surface.h"
namespace Parallaction {
@@ -37,9 +38,10 @@ class Gfx;
class Script;
class Font;
+struct Frames;
struct Cnv;
-struct StaticCnv;
-
+struct Sprites;
+struct BackgroundInfo;
class Disk {
@@ -52,15 +54,15 @@ public:
virtual Script* loadLocation(const char *name) = 0;
virtual Script* loadScript(const char* name) = 0;
- virtual Cnv* loadTalk(const char *name) = 0;
- virtual Cnv* loadObjects(const char *name) = 0;
- virtual StaticCnv* loadPointer() = 0;
- virtual StaticCnv* loadHead(const char* name) = 0;
+ virtual Frames* loadTalk(const char *name) = 0;
+ virtual Frames* loadObjects(const char *name) = 0;
+ virtual Graphics::Surface* loadPointer(const char *name) = 0;
+ virtual Graphics::Surface* loadHead(const char* name) = 0;
virtual Font* loadFont(const char* name) = 0;
- virtual StaticCnv* loadStatic(const char* name) = 0;
- virtual Cnv* loadFrames(const char* name) = 0;
- virtual void loadSlide(const char *filename) = 0;
- virtual void loadScenery(const char* background, const char* mask) = 0;
+ virtual Graphics::Surface* loadStatic(const char* name) = 0;
+ virtual Frames* loadFrames(const char* name) = 0;
+ virtual void loadSlide(BackgroundInfo& info, const char *filename) = 0;
+ virtual void loadScenery(BackgroundInfo& info, const char* background, const char* mask, const char* path) = 0;
virtual Table* loadTable(const char* name) = 0;
virtual Common::SeekableReadStream* loadMusic(const char* name) = 0;
virtual Common::ReadStream* loadSound(const char* name) = 0;
@@ -128,11 +130,11 @@ private:
void unpackBackground(Common::ReadStream *stream, byte *screen, byte *mask, byte *path);
Cnv* loadExternalCnv(const char *filename);
Cnv* loadCnv(const char *filename);
- StaticCnv *loadExternalStaticCnv(const char *filename);
- void loadBackground(const char *filename);
- void loadMaskAndPath(const char *name);
+ Graphics::Surface *loadExternalStaticCnv(const char *filename);
+ void loadBackground(BackgroundInfo& info, const char *filename);
+ void loadMaskAndPath(BackgroundInfo& info, const char *name);
void parseDepths(Common::SeekableReadStream &stream);
- void parseBackground(Common::SeekableReadStream &stream);
+ void parseBackground(BackgroundInfo& info, Common::SeekableReadStream &stream);
Font *createFont(const char *name, Cnv* cnv);
protected:
@@ -144,15 +146,15 @@ public:
Script* loadLocation(const char *name);
Script* loadScript(const char* name);
- Cnv* loadTalk(const char *name);
- Cnv* loadObjects(const char *name);
- StaticCnv* loadPointer();
- StaticCnv* loadHead(const char* name);
+ Frames* loadTalk(const char *name);
+ Frames* loadObjects(const char *name);
+ Graphics::Surface* loadPointer(const char *name);
+ Graphics::Surface* loadHead(const char* name);
Font* loadFont(const char* name);
- StaticCnv* loadStatic(const char* name);
- Cnv* loadFrames(const char* name);
- void loadSlide(const char *filename);
- void loadScenery(const char* background, const char* mask);
+ Graphics::Surface* loadStatic(const char* name);
+ Frames* loadFrames(const char* name);
+ void loadSlide(BackgroundInfo& info, const char *filename);
+ void loadScenery(BackgroundInfo& info, const char* background, const char* mask, const char* path);
Table* loadTable(const char* name);
Common::SeekableReadStream* loadMusic(const char* name);
Common::ReadStream* loadSound(const char* name);
@@ -162,15 +164,15 @@ class AmigaDisk_ns : public Disk_ns {
protected:
Cnv* makeCnv(Common::SeekableReadStream &stream);
- StaticCnv* makeStaticCnv(Common::SeekableReadStream &stream);
+ Graphics::Surface* makeStaticCnv(Common::SeekableReadStream &stream);
void patchFrame(byte *dst, byte *dlta, uint16 bytesPerPlane, uint16 height);
void unpackFrame(byte *dst, byte *src, uint16 planeSize);
void unpackBitmap(byte *dst, byte *src, uint16 numFrames, uint16 bytesPerPlane, uint16 height);
Common::SeekableReadStream *openArchivedFile(const char* name, bool errorOnFileNotFound = false);
Font *createFont(const char *name, Common::SeekableReadStream &stream);
- void loadMask(const char *name);
- void loadPath(const char *name);
- void loadBackground(const char *name);
+ void loadMask(BackgroundInfo& info, const char *name);
+ void loadPath(BackgroundInfo& info, const char *name);
+ void loadBackground(BackgroundInfo& info, const char *name);
public:
AmigaDisk_ns(Parallaction *vm);
@@ -178,15 +180,15 @@ public:
Script* loadLocation(const char *name);
Script* loadScript(const char* name);
- Cnv* loadTalk(const char *name);
- Cnv* loadObjects(const char *name);
- StaticCnv* loadPointer();
- StaticCnv* loadHead(const char* name);
+ Frames* loadTalk(const char *name);
+ Frames* loadObjects(const char *name);
+ Graphics::Surface* loadPointer(const char *name);
+ Graphics::Surface* loadHead(const char* name);
Font* loadFont(const char* name);
- StaticCnv* loadStatic(const char* name);
- Cnv* loadFrames(const char* name);
- void loadSlide(const char *filename);
- void loadScenery(const char* background, const char* mask);
+ Graphics::Surface* loadStatic(const char* name);
+ Frames* loadFrames(const char* name);
+ void loadSlide(BackgroundInfo& info, const char *filename);
+ void loadScenery(BackgroundInfo& info, const char* background, const char* mask, const char* path);
Table* loadTable(const char* name);
Common::SeekableReadStream* loadMusic(const char* name);
Common::ReadStream* loadSound(const char* name);
@@ -200,9 +202,13 @@ class DosDisk_br : public Disk {
protected:
Parallaction *_vm;
+ char _partPath[PATH_LEN];
+ char _languageDir[2];
protected:
void errorFileNotFound(const char *s);
+ Font *createFont(const char *name, Common::ReadStream &stream);
+ Sprites* createSprites(const char *name);
public:
DosDisk_br(Parallaction *vm);
@@ -212,15 +218,15 @@ public:
void setLanguage(uint16 language);
Script* loadLocation(const char *name);
Script* loadScript(const char* name);
- Cnv* loadTalk(const char *name);
- Cnv* loadObjects(const char *name);
- StaticCnv* loadPointer();
- StaticCnv* loadHead(const char* name);
+ Frames* loadTalk(const char *name);
+ Frames* loadObjects(const char *name);
+ Graphics::Surface* loadPointer(const char *name);
+ Graphics::Surface* loadHead(const char* name);
Font* loadFont(const char* name);
- StaticCnv* loadStatic(const char* name);
- Cnv* loadFrames(const char* name);
- void loadSlide(const char *filename);
- void loadScenery(const char* background, const char* mask);
+ Graphics::Surface* loadStatic(const char* name);
+ Frames* loadFrames(const char* name);
+ void loadSlide(BackgroundInfo& info, const char *filename);
+ void loadScenery(BackgroundInfo& info, const char* background, const char* mask, const char* path);
Table* loadTable(const char* name);
Common::SeekableReadStream* loadMusic(const char* name);
Common::ReadStream* loadSound(const char* name);
diff --git a/engines/parallaction/disk_br.cpp b/engines/parallaction/disk_br.cpp
index 452b74be51..5b79ad7df6 100644
--- a/engines/parallaction/disk_br.cpp
+++ b/engines/parallaction/disk_br.cpp
@@ -30,18 +30,95 @@
namespace Parallaction {
+struct Sprite {
+ uint16 size;
+ uint16 x;
+ uint16 y;
+ uint16 w;
+ uint16 h;
+
+ byte *packedData;
+
+ Sprite() : size(0), x(0), y(0), w(0), h(0), packedData(0) {
+ }
+
+ ~Sprite() {
+ if (packedData)
+ free(packedData);
+ }
+};
+
+struct Sprites : public Frames {
+ uint16 _num;
+ Sprite* _sprites;
+
+ Sprites(uint num) {
+ _num = num;
+ _sprites = new Sprite[_num];
+ }
+
+ ~Sprites() {
+ delete _sprites;
+ }
+
+ uint16 getNum() {
+ return _num;
+ }
+
+ byte* getData(uint16 index) {
+ assert(index < _num);
+ return _sprites[index].packedData;
+ }
+
+ void getRect(uint16 index, Common::Rect &r) {
+ assert(index < _num);
+ r.setWidth(_sprites[index].w);
+ r.setHeight(_sprites[index].h);
+ r.moveTo(_sprites[index].x, _sprites[index].y);
+}
+
+};
+
+
+
void DosDisk_br::errorFileNotFound(const char *s) {
error("File '%s' not found", s);
}
Common::String DosDisk_br::selectArchive(const Common::String& name) {
debugC(5, kDebugDisk, "DosDisk_br::selectArchive");
- return "";
+
+ Common::String oldPath(_partPath);
+ strcpy(_partPath, name.c_str());
+
+ return oldPath;
}
void DosDisk_br::setLanguage(uint16 language) {
debugC(5, kDebugDisk, "DosDisk_br::setLanguage");
+ switch (language) {
+ case 0:
+ strcpy(_languageDir, "it");
+ break;
+
+ case 1:
+ strcpy(_languageDir, "fr");
+ break;
+
+ case 2:
+ strcpy(_languageDir, "en");
+ break;
+
+ case 3:
+ strcpy(_languageDir, "ge");
+ break;
+
+ default:
+ error("unknown language");
+
+ }
+
return;
}
@@ -52,71 +129,239 @@ DosDisk_br::DosDisk_br(Parallaction* vm) : _vm(vm) {
DosDisk_br::~DosDisk_br() {
}
-Cnv* DosDisk_br::loadTalk(const char *name) {
+Frames* DosDisk_br::loadTalk(const char *name) {
debugC(5, kDebugDisk, "DosDisk_br::loadTalk");
- return 0;
+ char path[PATH_LEN];
+ sprintf(path, "%s/tal/%s.tal", _partPath, name);
+
+ return createSprites(path);
}
Script* DosDisk_br::loadLocation(const char *name) {
debugC(5, kDebugDisk, "DosDisk_br::loadLocation");
- return 0;
+
+ Common::File *stream = new Common::File;
+
+ char path[PATH_LEN];
+ sprintf(path, "%s/%s/%s.slf", _partPath, _languageDir, name);
+ if (!stream->open(path)) {
+ sprintf(path, "%s/%s/%s.loc", _partPath, _languageDir, name);
+ if (!stream->open(path))
+ errorFileNotFound(path);
+ }
+
+ return new Script(stream, true);
}
Script* DosDisk_br::loadScript(const char* name) {
debugC(5, kDebugDisk, "DosDisk_br::loadScript");
- return 0;
+
+ Common::File *stream = new Common::File;
+
+ char path[PATH_LEN];
+ sprintf(path, "%s/scripts/%s.scr", _partPath, name);
+ if (!stream->open(path))
+ errorFileNotFound(path);
+
+ return new Script(stream, true);
}
// there are no Head resources in Big Red Adventure
-StaticCnv* DosDisk_br::loadHead(const char* name) {
+Graphics::Surface* DosDisk_br::loadHead(const char* name) {
debugC(5, kDebugDisk, "DosDisk_br::loadHead");
return 0;
}
-StaticCnv* DosDisk_br::loadPointer() {
+Graphics::Surface* DosDisk_br::loadPointer(const char *name) {
debugC(5, kDebugDisk, "DosDisk_br::loadPointer");
- return 0;
+
+ char path[PATH_LEN];
+ sprintf(path, "%s.ras", name);
+
+ Common::File stream;
+ if (!stream.open(path))
+ errorFileNotFound(path);
+
+ stream.skip(4);
+ uint width = stream.readUint32BE();
+ uint height = stream.readUint32BE();
+ stream.skip(20);
+ stream.skip(768);
+
+ Graphics::Surface *surf = new Graphics::Surface;
+
+ surf->create(width, height, 1);
+ stream.read(surf->pixels, width * height);
+
+ return surf;
}
Font* DosDisk_br::loadFont(const char* name) {
debugC(5, kDebugDisk, "DosDisk_br::loadFont");
- return 0;
+
+ char path[PATH_LEN];
+ sprintf(path, "%s.fnt", name);
+
+ Common::File stream;
+ if (!stream.open(path))
+ errorFileNotFound(path);
+
+ return createFont(name, stream);
}
-Cnv* DosDisk_br::loadObjects(const char *name) {
+Frames* DosDisk_br::loadObjects(const char *name) {
debugC(5, kDebugDisk, "DosDisk_br::loadObjects");
return 0;
}
+void genSlidePath(char *path, const char* name) {
+ sprintf(path, "%s.bmp", name);
+}
-StaticCnv* DosDisk_br::loadStatic(const char* name) {
+Graphics::Surface* DosDisk_br::loadStatic(const char* name) {
debugC(5, kDebugDisk, "DosDisk_br::loadStatic");
return 0;
}
-Cnv* DosDisk_br::loadFrames(const char* name) {
+Sprites* DosDisk_br::createSprites(const char *path) {
+
+ Common::File stream;
+ if (!stream.open(path)) {
+ errorFileNotFound(path);
+ }
+
+ uint16 num = stream.readUint16LE();
+
+ Sprites *sprites = new Sprites(num);
+
+ for (uint i = 0; i < num; i++) {
+ Sprite *spr = &sprites->_sprites[i];
+ spr->size = stream.readUint16LE();
+ spr->x = stream.readUint16LE();
+ spr->y = stream.readUint16LE();
+ spr->w = stream.readUint16LE();
+ spr->h = stream.readUint16LE();
+
+ spr->packedData = (byte*)malloc(spr->size);
+ stream.read(spr->packedData, spr->size);
+ }
+
+ return sprites;
+}
+
+Frames* DosDisk_br::loadFrames(const char* name) {
debugC(5, kDebugDisk, "DosDisk_br::loadFrames");
- return 0;
+
+ char path[PATH_LEN];
+ sprintf(path, "%s/ani/%s.ani", _partPath, name);
+
+ return createSprites(path);
}
-// there are no Slide resources in Big Red Adventure
-void DosDisk_br::loadSlide(const char *filename) {
+// Slides in Nippon Safes are basically screen-sized pictures with valid
+// palette data used for menu and for location switches. Big Red Adventure
+// doesn't need slides in that sense, but it still has some special
+// graphics resources with palette data, so those will be named slides.
+//
+void DosDisk_br::loadSlide(BackgroundInfo& info, const char *name) {
debugC(5, kDebugDisk, "DosDisk_br::loadSlide");
+
+ char path[PATH_LEN];
+ genSlidePath(path, name);
+
+ Common::File stream;
+ if (!stream.open(path))
+ errorFileNotFound(path);
+
+ stream.skip(4);
+ info.width = stream.readUint32BE();
+ info.height = stream.readUint32BE();
+ stream.skip(20);
+
+ byte rgb[768];
+ stream.read(rgb, 768);
+
+ for (uint i = 0; i < 256; i++) {
+ info.palette.setEntry(i, rgb[i] >> 2, rgb[i+256] >> 2, rgb[i+512] >> 2);
+ }
+
+ info.bg.create(info.width, info.height, 1);
+ stream.read(info.bg.pixels, info.width * info.height);
+
return;
}
-void DosDisk_br::loadScenery(const char *name, const char *mask) {
+void DosDisk_br::loadScenery(BackgroundInfo& info, const char *name, const char *mask, const char* path) {
debugC(5, kDebugDisk, "DosDisk_br::loadScenery");
+
+ char filename[PATH_LEN];
+ Common::File stream;
+
+ if (name) {
+ sprintf(filename, "%s/bkg/%s.bkg", _partPath, name);
+ if (!stream.open(filename))
+ errorFileNotFound(filename);
+
+ stream.skip(4);
+ info.width = stream.readUint32BE();
+ info.height = stream.readUint32BE();
+ stream.skip(20);
+
+ byte rgb[768];
+ stream.read(rgb, 768);
+
+ for (uint i = 0; i < 256; i++) {
+ info.palette.setEntry(i, rgb[i] >> 2, rgb[i+256] >> 2, rgb[i+512] >> 2);
+ }
+
+ info.bg.create(info.width, info.height, 1);
+ stream.read(info.bg.pixels, info.width * info.height);
+ }
+
+ if (mask) {
+ sprintf(filename, "%s/msk/%s.msk", _partPath, mask);
+ if (!stream.open(filename))
+ errorFileNotFound(filename);
+
+ // NOTE: info.width and info.height are only valid if the background graphics
+ // have already been loaded
+ info.mask.create(info.width, info.height);
+ stream.read(info.mask.data, info.width * info.height);
+ }
+
+ if (path) {
+ sprintf(filename, "%s/pth/%s.pth", _partPath, path);
+ if (!stream.open(filename))
+ errorFileNotFound(filename);
+
+ // NOTE: info.width and info.height are only valid if the background graphics
+ // have already been loaded
+ info.path.create(info.width, info.height);
+ stream.read(info.path.data, info.width * info.height);
+ }
+
return;
}
Table* DosDisk_br::loadTable(const char* name) {
debugC(5, kDebugDisk, "DosDisk_br::loadTable");
- return 0;
+
+ char path[PATH_LEN];
+ sprintf(path, "%s/%s.tab", _partPath, name);
+
+ Common::File stream;
+ if (!stream.open(path))
+ errorFileNotFound(path);
+
+ Table *t = createTableFromStream(100, stream);
+
+ stream.close();
+
+ return t;
}
Common::SeekableReadStream* DosDisk_br::loadMusic(const char* name) {
diff --git a/engines/parallaction/disk_ns.cpp b/engines/parallaction/disk_ns.cpp
index c0bb2691ef..8b5ce850ff 100644
--- a/engines/parallaction/disk_ns.cpp
+++ b/engines/parallaction/disk_ns.cpp
@@ -345,7 +345,7 @@ Cnv* DosDisk_ns::loadExternalCnv(const char *filename) {
return new Cnv(numFrames, width, height, data);
}
-StaticCnv *DosDisk_ns::loadExternalStaticCnv(const char *filename) {
+Graphics::Surface *DosDisk_ns::loadExternalStaticCnv(const char *filename) {
char path[PATH_LEN];
@@ -356,16 +356,14 @@ StaticCnv *DosDisk_ns::loadExternalStaticCnv(const char *filename) {
if (!stream.open(path))
errorFileNotFound(path);
- StaticCnv *cnv = new StaticCnv;
+ Graphics::Surface *cnv = new Graphics::Surface;
stream.skip(1);
- cnv->_width = stream.readByte();
- cnv->_height = stream.readByte();
+ byte w = stream.readByte();
+ byte h = stream.readByte();
- uint16 size = cnv->_width*cnv->_height;
-
- cnv->_data0 = (byte*)malloc(size);
- stream.read(cnv->_data0, size);
+ cnv->create(w, h, 1);
+ stream.read(cnv->pixels, w*h);
return cnv;
}
@@ -395,7 +393,7 @@ Cnv* DosDisk_ns::loadCnv(const char *filename) {
return new Cnv(numFrames, width, height, data);
}
-Cnv* DosDisk_ns::loadTalk(const char *name) {
+Frames* DosDisk_ns::loadTalk(const char *name) {
const char *ext = strstr(name, ".talk");
if (ext != NULL) {
@@ -462,7 +460,7 @@ Script* DosDisk_ns::loadScript(const char* name) {
return new Script(new DummyArchiveStream(_resArchive), true);
}
-StaticCnv* DosDisk_ns::loadHead(const char* name) {
+Graphics::Surface* DosDisk_ns::loadHead(const char* name) {
char path[PATH_LEN];
@@ -477,8 +475,8 @@ StaticCnv* DosDisk_ns::loadHead(const char* name) {
}
-StaticCnv* DosDisk_ns::loadPointer() {
- return loadExternalStaticCnv("pointer");
+Graphics::Surface* DosDisk_ns::loadPointer(const char *name) {
+ return loadExternalStaticCnv(name);
}
@@ -489,7 +487,7 @@ Font* DosDisk_ns::loadFont(const char* name) {
}
-Cnv* DosDisk_ns::loadObjects(const char *name) {
+Frames* DosDisk_ns::loadObjects(const char *name) {
if (IS_MINI_CHARACTER(name)) {
name += 4;
@@ -501,7 +499,7 @@ Cnv* DosDisk_ns::loadObjects(const char *name) {
}
-StaticCnv* DosDisk_ns::loadStatic(const char* name) {
+Graphics::Surface* DosDisk_ns::loadStatic(const char* name) {
char path[PATH_LEN];
@@ -512,22 +510,21 @@ StaticCnv* DosDisk_ns::loadStatic(const char* name) {
errorFileNotFound(path);
}
- StaticCnv* cnv = new StaticCnv;
+ Graphics::Surface* cnv = new Graphics::Surface;
_resArchive.skip(1);
- cnv->_width = _resArchive.readByte();
- cnv->_height = _resArchive.readByte();
+ byte w = _resArchive.readByte();
+ byte h = _resArchive.readByte();
- uint16 size = cnv->_width*cnv->_height;
- cnv->_data0 = (byte*)malloc(size);
+ cnv->create(w, h, 1);
Graphics::PackBitsReadStream decoder(_resArchive);
- decoder.read(cnv->_data0, size);
+ decoder.read(cnv->pixels, w*h);
return cnv;
}
-Cnv* DosDisk_ns::loadFrames(const char* name) {
+Frames* DosDisk_ns::loadFrames(const char* name) {
return loadCnv(name);
}
@@ -565,10 +562,16 @@ void DosDisk_ns::parseDepths(Common::SeekableReadStream &stream) {
}
-void DosDisk_ns::parseBackground(Common::SeekableReadStream &stream) {
+void DosDisk_ns::parseBackground(BackgroundInfo& info, Common::SeekableReadStream &stream) {
+
+ byte tmp[3];
- stream.read(_vm->_gfx->_palette, BASE_PALETTE_SIZE);
- _vm->_gfx->setPalette(_vm->_gfx->_palette);
+ for (uint i = 0; i < 32; i++) {
+ tmp[0] = stream.readByte();
+ tmp[1] = stream.readByte();
+ tmp[2] = stream.readByte();
+ info.palette.setEntry(i, tmp[0], tmp[1], tmp[2]);
+ }
parseDepths(stream);
@@ -582,28 +585,22 @@ void DosDisk_ns::parseBackground(Common::SeekableReadStream &stream) {
}
-void DosDisk_ns::loadBackground(const char *filename) {
+void DosDisk_ns::loadBackground(BackgroundInfo& info, const char *filename) {
if (!_resArchive.openArchivedFile(filename))
errorFileNotFound(filename);
- parseBackground(_resArchive);
+ info.width = _vm->_screenWidth; // 320
+ info.height = _vm->_screenHeight; // 200
- byte *bg = (byte*)calloc(1, _vm->_screenSize);
- byte *mask = (byte*)calloc(1, _vm->_screenMaskSize);
- byte *path = (byte*)calloc(1, _vm->_screenPathSize);
+ parseBackground(info, _resArchive);
+ info.bg.create(info.width, info.height, 1);
+ info.mask.create(info.width, info.height);
+ info.path.create(info.width, info.height);
Graphics::PackBitsReadStream stream(_resArchive);
- unpackBackground(&stream, bg, mask, path);
-
- _vm->_gfx->setBackground(bg);
- _vm->_gfx->setMask(mask);
- _vm->setPath(path);
-
- free(bg);
- free(mask);
- free(path);
+ unpackBackground(&stream, (byte*)info.bg.pixels, info.mask.data, info.path.data);
return;
}
@@ -614,43 +611,44 @@ void DosDisk_ns::loadBackground(const char *filename) {
// mask and path are normally combined (via OR) into the background picture itself
// read the comment on the top of this file for more
//
-void DosDisk_ns::loadMaskAndPath(const char *name) {
+void DosDisk_ns::loadMaskAndPath(BackgroundInfo& info, const char *name) {
char path[PATH_LEN];
sprintf(path, "%s.msk", name);
if (!_resArchive.openArchivedFile(path))
errorFileNotFound(name);
- byte *maskBuf = (byte*)calloc(1, _vm->_screenMaskSize);
- byte *pathBuf = (byte*)calloc(1, _vm->_screenPathSize);
-
parseDepths(_resArchive);
- _resArchive.read(pathBuf, _vm->_screenPathSize);
- _resArchive.read(maskBuf, _vm->_screenMaskSize);
+ info.path.create(info.width, info.height);
+ _resArchive.read(info.path.data, info.path.size);
- _vm->_gfx->setMask(maskBuf);
- _vm->setPath(pathBuf);
+ info.mask.create(info.width, info.height);
+ _resArchive.read(info.mask.data, info.mask.size);
return;
}
-void DosDisk_ns::loadSlide(const char *filename) {
+void DosDisk_ns::loadSlide(BackgroundInfo& info, const char *filename) {
char path[PATH_LEN];
sprintf(path, "%s.slide", filename);
- loadBackground(path);
+ loadBackground(info, path);
+
+ return;
}
-void DosDisk_ns::loadScenery(const char *name, const char *mask) {
- char path[PATH_LEN];
- sprintf(path, "%s.dyn", name);
- loadBackground(path);
+void DosDisk_ns::loadScenery(BackgroundInfo& info, const char *name, const char *mask, const char* path) {
+ char filename[PATH_LEN];
+ sprintf(filename, "%s.dyn", name);
+
+ loadBackground(info, filename);
if (mask != NULL) {
// load external masks and paths only for certain locations
- loadMaskAndPath(mask);
+ loadMaskAndPath(info, mask);
}
+ return;
}
Table* DosDisk_ns::loadTable(const char* name) {
@@ -661,13 +659,7 @@ Table* DosDisk_ns::loadTable(const char* name) {
if (!stream.open(path))
errorFileNotFound(path);
- Table *t = new Table(100);
-
- fillBuffers(stream);
- while (scumm_stricmp(_tokens[0], "ENDTABLE")) {
- t->addData(_tokens[0]);
- fillBuffers(stream);
- }
+ Table *t = createTableFromStream(100, stream);
stream.close();
@@ -974,7 +966,7 @@ void AmigaDisk_ns::unpackBitmap(byte *dst, byte *src, uint16 numFrames, uint16 b
}
-StaticCnv* AmigaDisk_ns::makeStaticCnv(Common::SeekableReadStream &stream) {
+Graphics::Surface* AmigaDisk_ns::makeStaticCnv(Common::SeekableReadStream &stream) {
stream.skip(1);
uint16 width = stream.readByte();
@@ -988,19 +980,13 @@ StaticCnv* AmigaDisk_ns::makeStaticCnv(Common::SeekableReadStream &stream) {
byte *buf = (byte*)malloc(rawsize);
stream.read(buf, rawsize);
- uint32 decsize = width * height;
- byte *data = (byte*)calloc(decsize, 1);
+ Graphics::Surface *cnv = new Graphics::Surface;
+ cnv->create(width, height, 1);
- unpackBitmap(data, buf, 1, bytesPerPlane, height);
+ unpackBitmap((byte*)cnv->pixels, buf, 1, bytesPerPlane, height);
free(buf);
- StaticCnv *cnv = new StaticCnv();
- cnv->_width = width;
- cnv->_height = height;
- cnv->_data0 = data;
- cnv->_data1 = NULL;
-
return cnv;
}
@@ -1063,21 +1049,21 @@ Script* AmigaDisk_ns::loadScript(const char* name) {
return new Script(new DummyArchiveStream(_resArchive), true);
}
-StaticCnv* AmigaDisk_ns::loadPointer() {
+Graphics::Surface* AmigaDisk_ns::loadPointer(const char* name) {
debugC(1, kDebugDisk, "AmigaDisk_ns::loadPointer");
Common::File stream;
- if (!stream.open("pointer"))
- errorFileNotFound("pointer");
+ if (!stream.open(name))
+ errorFileNotFound(name);
return makeStaticCnv(stream);
}
-StaticCnv* AmigaDisk_ns::loadStatic(const char* name) {
+Graphics::Surface* AmigaDisk_ns::loadStatic(const char* name) {
debugC(1, kDebugDisk, "AmigaDisk_ns::loadStatic '%s'", name);
Common::SeekableReadStream *s = openArchivedFile(name, true);
- StaticCnv *cnv = makeStaticCnv(*s);
+ Graphics::Surface *cnv = makeStaticCnv(*s);
delete s;
@@ -1186,28 +1172,38 @@ public:
};
-void AmigaDisk_ns::loadBackground(const char *name) {
+void AmigaDisk_ns::loadBackground(BackgroundInfo& info, const char *name) {
Common::SeekableReadStream *s = openArchivedFile(name, true);
- Graphics::Surface surf;
byte *pal;
- BackgroundDecoder decoder(*s, surf, pal, _vm->_gfx->_palettefx);
+
+ BackgroundDecoder decoder(*s, info.bg, pal, _vm->_gfx->_palettefx);
decoder.decode();
- for (uint32 i = 0; i < BASE_PALETTE_COLORS * 3; i++)
- _vm->_gfx->_palette[i] = pal[i] >> 2;
+ info.width = info.bg.w;
+ info.height = info.bg.h;
+
+ byte *p = pal;
+ for (uint i = 0; i < 32; i++) {
+ byte r = *p >> 2;
+ p++;
+ byte g = *p >> 2;
+ p++;
+ byte b = *p >> 2;
+ p++;
+ info.palette.setEntry(i, r, g, b);
+ }
+
free(pal);
- _vm->_gfx->setPalette(_vm->_gfx->_palette);
- _vm->_gfx->setBackground(static_cast<byte*>(surf.pixels));
- surf.free();
+
delete s;
return;
}
-void AmigaDisk_ns::loadMask(const char *name) {
+void AmigaDisk_ns::loadMask(BackgroundInfo& info, const char *name) {
debugC(5, kDebugDisk, "AmigaDisk_ns::loadMask(%s)", name);
char path[PATH_LEN];
@@ -1236,18 +1232,16 @@ void AmigaDisk_ns::loadMask(const char *name) {
s->seek(0x126, SEEK_SET); // HACK: skipping IFF/ILBM header should be done by analysis, not magic
Graphics::PackBitsReadStream stream(*s);
- byte *buf = (byte*)malloc(_vm->_screenMaskSize);
- stream.read(buf, _vm->_screenMaskSize);
- buildMask(buf);
+ info.mask.create(info.width, info.height);
+ stream.read(info.mask.data, info.mask.size);
+ buildMask(info.mask.data);
- _vm->_gfx->setMask(buf);
- free(buf);
delete s;
return;
}
-void AmigaDisk_ns::loadPath(const char *name) {
+void AmigaDisk_ns::loadPath(BackgroundInfo& info, const char *name) {
char path[PATH_LEN];
sprintf(path, "%s.path", name);
@@ -1260,49 +1254,52 @@ void AmigaDisk_ns::loadPath(const char *name) {
s->seek(0x120, SEEK_SET); // HACK: skipping IFF/ILBM header should be done by analysis, not magic
Graphics::PackBitsReadStream stream(*s);
- byte *buf = (byte*)malloc(_vm->_screenPathSize);
- stream.read(buf, _vm->_screenPathSize);
- _vm->setPath(buf);
- free(buf);
+
+ info.path.create(info.width, info.height);
+ stream.read(info.path.data, info.path.size);
+
delete s;
return;
}
-void AmigaDisk_ns::loadScenery(const char* background, const char* mask) {
+void AmigaDisk_ns::loadScenery(BackgroundInfo& info, const char* background, const char* mask, const char* path) {
debugC(1, kDebugDisk, "AmigaDisk_ns::loadScenery '%s', '%s'", background, mask);
- char path[PATH_LEN];
- sprintf(path, "%s.bkgnd", background);
+ char filename[PATH_LEN];
+ sprintf(filename, "%s.bkgnd", background);
- loadBackground(path);
+ loadBackground(info, filename);
if (mask == NULL) {
- loadMask(background);
- loadPath(background);
+ loadMask(info, background);
+ loadPath(info, background);
} else {
- loadMask(mask);
- loadPath(mask);
+ loadMask(info, mask);
+ loadPath(info, mask);
}
return;
}
-void AmigaDisk_ns::loadSlide(const char *name) {
+void AmigaDisk_ns::loadSlide(BackgroundInfo& info, const char *name) {
debugC(1, kDebugDisk, "AmigaDisk_ns::loadSlide '%s'", name);
char path[PATH_LEN];
sprintf(path, "slides/%s", name);
Common::SeekableReadStream *s = openArchivedFile(path, false);
+
if (s)
- loadBackground(path);
+ loadBackground(info, path);
else
- loadBackground(name);
+ loadBackground(info, name);
+
+ delete s;
return;
}
-Cnv* AmigaDisk_ns::loadFrames(const char* name) {
+Frames* AmigaDisk_ns::loadFrames(const char* name) {
debugC(1, kDebugDisk, "AmigaDisk_ns::loadFrames '%s'", name);
Common::SeekableReadStream *s;
@@ -1320,14 +1317,14 @@ Cnv* AmigaDisk_ns::loadFrames(const char* name) {
return cnv;
}
-StaticCnv* AmigaDisk_ns::loadHead(const char* name) {
+Graphics::Surface* AmigaDisk_ns::loadHead(const char* name) {
debugC(1, kDebugDisk, "AmigaDisk_ns::loadHead '%s'", name);
char path[PATH_LEN];
sprintf(path, "%s.head", name);
Common::SeekableReadStream *s = openArchivedFile(path, true);
- StaticCnv *cnv = makeStaticCnv(*s);
+ Graphics::Surface *cnv = makeStaticCnv(*s);
delete s;
@@ -1335,7 +1332,7 @@ StaticCnv* AmigaDisk_ns::loadHead(const char* name) {
}
-Cnv* AmigaDisk_ns::loadObjects(const char *name) {
+Frames* AmigaDisk_ns::loadObjects(const char *name) {
debugC(1, kDebugDisk, "AmigaDisk_ns::loadObjects");
char path[PATH_LEN];
@@ -1353,7 +1350,7 @@ Cnv* AmigaDisk_ns::loadObjects(const char *name) {
}
-Cnv* AmigaDisk_ns::loadTalk(const char *name) {
+Frames* AmigaDisk_ns::loadTalk(const char *name) {
debugC(1, kDebugDisk, "AmigaDisk_ns::loadTalk '%s'", name);
Common::SeekableReadStream *s;
@@ -1401,13 +1398,7 @@ Table* AmigaDisk_ns::loadTable(const char* name) {
stream = &_resArchive;
}
- Table *t = new Table(100);
-
- fillBuffers(*stream);
- while (scumm_stricmp(_tokens[0], "ENDTABLE")) {
- t->addData(_tokens[0]);
- fillBuffers(*stream);
- }
+ Table *t = createTableFromStream(100, *stream);
if (dispose)
delete stream;
diff --git a/engines/parallaction/exec_br.cpp b/engines/parallaction/exec_br.cpp
new file mode 100644
index 0000000000..7862a4a0c6
--- /dev/null
+++ b/engines/parallaction/exec_br.cpp
@@ -0,0 +1,588 @@
+
+#include "common/stdafx.h"
+#include "parallaction/parallaction.h"
+
+namespace Parallaction {
+
+#define INST_ON 1
+#define INST_OFF 2
+#define INST_X 3
+#define INST_Y 4
+#define INST_Z 5
+#define INST_F 6
+#define INST_LOOP 7
+#define INST_ENDLOOP 8
+#define INST_SHOW 9
+#define INST_INC 10
+#define INST_DEC 11
+#define INST_SET 12
+#define INST_PUT 13
+#define INST_CALL 14
+#define INST_WAIT 15
+#define INST_START 16
+#define INST_PROCESS 17
+#define INST_MOVE 18
+#define INST_COLOR 19
+#define INST_SOUND 20
+#define INST_MASK 21
+#define INST_PRINT 22
+#define INST_TEXT 23
+#define INST_MUL 24
+#define INST_DIV 25
+#define INST_IFEQ 26
+#define INST_IFLT 27
+#define INST_IFGT 28
+#define INST_ENDIF 29
+#define INST_STOP 30
+#define INST_ENDSCRIPT 31
+
+
+
+typedef OpcodeImpl<Parallaction_br> OpcodeV2;
+#define COMMAND_OPCODE(op) OpcodeV2(this, &Parallaction_br::cmdOp_##op)
+#define DECLARE_COMMAND_OPCODE(op) void Parallaction_br::cmdOp_##op()
+
+#define INSTRUCTION_OPCODE(op) OpcodeV2(this, &Parallaction_br::instOp_##op)
+#define DECLARE_INSTRUCTION_OPCODE(op) void Parallaction_br::instOp_##op()
+
+void Parallaction_br::setupSubtitles(char *s, char *s2, int y) {
+ debugC(5, kDebugExec, "setupSubtitles(%s, %s, %i)", s, s2, y);
+
+ if (!scumm_stricmp("clear", s)) {
+
+ removeJob(_jDisplaySubtitle);
+ addJob(kJobWaitRemoveSubtitleJob, _jEraseSubtitle, 15);
+ _jDisplaySubtitle = 0;
+
+ _subtitle0.free();
+ _subtitle1.free();
+ return;
+ }
+
+ _subtitle0.free();
+ _subtitle1.free();
+
+ renderLabel(&_subtitle0._cnv, s);
+ _subtitle0._text = strdup(s);
+
+ if (s2) {
+ renderLabel(&_subtitle1._cnv, s2);
+ _subtitle1._text = strdup(s2);
+ }
+
+ _subtitleLipSync = 0;
+
+ if (y != -1) {
+ _subtitle0._pos.y = y;
+ _subtitle1._pos.y = y + 5 + _labelFont->height();
+ }
+
+ _subtitle0._pos.x = (_gfx->_screenX << 2) + ((640 - _subtitle0._cnv.w) >> 1);
+ if (_subtitle1._text)
+ _subtitle1._pos.x = (_gfx->_screenX << 2) + ((640 - _subtitle1._cnv.w) >> 1);
+
+ if (_jDisplaySubtitle == 0) {
+ _subtitle0._old.x = -1000;
+ _subtitle0._old.y = -1000;
+ _jDisplaySubtitle = addJob(kJobDisplaySubtitle, 0, 1);
+ _jEraseSubtitle = addJob(kJobEraseSubtitle, 0, 20);
+ }
+}
+
+
+
+DECLARE_COMMAND_OPCODE(location) {
+ warning("Parallaction_br::cmdOp_location command not yet implemented");
+}
+
+
+DECLARE_COMMAND_OPCODE(open) {
+ warning("Parallaction_br::cmdOp_open command not yet implemented");
+}
+
+
+DECLARE_COMMAND_OPCODE(close) {
+ warning("Parallaction_br::cmdOp_close not yet implemented");
+}
+
+
+DECLARE_COMMAND_OPCODE(on) {
+ warning("Parallaction_br::cmdOp_on not yet implemented");
+}
+
+
+DECLARE_COMMAND_OPCODE(off) {
+ warning("Parallaction_br::cmdOp_off not yet implemented");
+}
+
+
+DECLARE_COMMAND_OPCODE(call) {
+ callFunction(_cmdRunCtxt.cmd->u._callable, _cmdRunCtxt.z);
+}
+
+
+DECLARE_COMMAND_OPCODE(drop) {
+ warning("Parallaction_br::cmdOp_drop not yet implemented");
+}
+
+
+DECLARE_COMMAND_OPCODE(move) {
+ warning("Parallaction_br::cmdOp_move not yet implemented");
+}
+
+DECLARE_COMMAND_OPCODE(start) {
+ warning("Parallaction_br::cmdOp_start not yet implemented");
+}
+
+DECLARE_COMMAND_OPCODE(stop) {
+ warning("Parallaction_br::cmdOp_stop not yet implemented");
+}
+
+
+DECLARE_COMMAND_OPCODE(character) {
+ warning("Parallaction_br::cmdOp_character not yet implemented");
+}
+
+
+DECLARE_COMMAND_OPCODE(followme) {
+ warning("Parallaction_br::cmdOp_followme not yet implemented");
+}
+
+
+DECLARE_COMMAND_OPCODE(onmouse) {
+ showCursor(true);
+}
+
+
+DECLARE_COMMAND_OPCODE(offmouse) {
+ showCursor(false);
+}
+
+
+DECLARE_COMMAND_OPCODE(add) {
+ warning("Parallaction_br::cmdOp_add not yet implemented");
+}
+
+
+DECLARE_COMMAND_OPCODE(leave) {
+ warning("Parallaction_br::cmdOp_leave not yet implemented");
+}
+
+
+DECLARE_COMMAND_OPCODE(inc) {
+ _counters[_cmdRunCtxt.cmd->u._lvalue] += _cmdRunCtxt.cmd->u._rvalue;
+}
+
+
+DECLARE_COMMAND_OPCODE(dec) {
+ _counters[_cmdRunCtxt.cmd->u._lvalue] -= _cmdRunCtxt.cmd->u._rvalue;
+}
+
+
+DECLARE_COMMAND_OPCODE(ifeq) {
+ if (_counters[_cmdRunCtxt.cmd->u._lvalue] == _cmdRunCtxt.cmd->u._rvalue) {
+ _localFlags[_currentLocationIndex] |= kFlagsTestTrue;
+ } else {
+ _localFlags[_currentLocationIndex] &= ~kFlagsTestTrue;
+ }
+}
+
+DECLARE_COMMAND_OPCODE(iflt) {
+ if (_counters[_cmdRunCtxt.cmd->u._lvalue] < _cmdRunCtxt.cmd->u._rvalue) {
+ _localFlags[_currentLocationIndex] |= kFlagsTestTrue;
+ } else {
+ _localFlags[_currentLocationIndex] &= ~kFlagsTestTrue;
+ }
+}
+
+DECLARE_COMMAND_OPCODE(ifgt) {
+ if (_counters[_cmdRunCtxt.cmd->u._lvalue] > _cmdRunCtxt.cmd->u._rvalue) {
+ _localFlags[_currentLocationIndex] |= kFlagsTestTrue;
+ } else {
+ _localFlags[_currentLocationIndex] &= ~kFlagsTestTrue;
+ }
+}
+
+
+DECLARE_COMMAND_OPCODE(let) {
+ _counters[_cmdRunCtxt.cmd->u._lvalue] = _cmdRunCtxt.cmd->u._rvalue;
+}
+
+
+DECLARE_COMMAND_OPCODE(music) {
+ warning("Parallaction_br::cmdOp_music not yet implemented");
+}
+
+
+DECLARE_COMMAND_OPCODE(fix) {
+ _cmdRunCtxt.cmd->u._zone->_flags |= kFlagsFixed;
+}
+
+
+DECLARE_COMMAND_OPCODE(unfix) {
+ _cmdRunCtxt.cmd->u._zone->_flags &= ~kFlagsFixed;
+}
+
+
+DECLARE_COMMAND_OPCODE(zeta) {
+ _zeta0 = _cmdRunCtxt.cmd->u._zeta0;
+ _zeta1 = _cmdRunCtxt.cmd->u._zeta1;
+ _zeta2 = _cmdRunCtxt.cmd->u._zeta2;
+}
+
+
+DECLARE_COMMAND_OPCODE(scroll) {
+ warning("Parallaction_br::cmdOp_scroll not yet implemented");
+}
+
+
+DECLARE_COMMAND_OPCODE(swap) {
+ warning("Parallaction_br::cmdOp_swap not yet implemented");
+}
+
+
+DECLARE_COMMAND_OPCODE(give) {
+ warning("Parallaction_br::cmdOp_give not yet implemented");
+}
+
+
+DECLARE_COMMAND_OPCODE(text) {
+ CommandData *data = &_cmdRunCtxt.cmd->u;
+ setupSubtitles(data->_string, data->_string2, data->_zeta0);
+}
+
+
+DECLARE_COMMAND_OPCODE(part) {
+ warning("Parallaction_br::cmdOp_part not yet implemented");
+}
+
+
+DECLARE_COMMAND_OPCODE(testsfx) {
+ warning("Parallaction_br::cmdOp_testsfx not completely implemented");
+ _localFlags[_currentLocationIndex] &= ~kFlagsTestTrue; // should test if sfx are enabled
+}
+
+
+DECLARE_COMMAND_OPCODE(ret) {
+ warning("Parallaction_br::cmdOp_ret not yet implemented");
+}
+
+
+DECLARE_COMMAND_OPCODE(onsave) {
+ warning("Parallaction_br::cmdOp_onsave not yet implemented");
+}
+
+
+DECLARE_COMMAND_OPCODE(offsave) {
+ warning("Parallaction_br::cmdOp_offsave not yet implemented");
+}
+
+
+
+
+DECLARE_INSTRUCTION_OPCODE(on) {
+ warning("Parallaction_br::instOp_on not yet implemented");
+}
+
+
+DECLARE_INSTRUCTION_OPCODE(off) {
+ warning("Parallaction_br::instOp_off not yet implemented");
+}
+
+
+DECLARE_INSTRUCTION_OPCODE(set) {
+ Instruction *inst = *_instRunCtxt.inst;
+
+ int16 rvalue = inst->_opB.getRValue();
+ int16* lvalue = inst->_opA.getLValue();
+
+ *lvalue = rvalue;
+
+}
+
+
+DECLARE_INSTRUCTION_OPCODE(loop) {
+ Instruction *inst = *_instRunCtxt.inst;
+
+ _instRunCtxt.a->_program->_loopCounter = inst->_opB.getRValue();
+ _instRunCtxt.a->_program->_loopStart = _instRunCtxt.inst;
+}
+
+
+DECLARE_INSTRUCTION_OPCODE(inc) {
+ Instruction *inst = *_instRunCtxt.inst;
+
+ int16 rvalue = inst->_opB.getRValue();
+
+ if (inst->_flags & kInstMod) { // mod
+ int16 _bx = (rvalue > 0 ? rvalue : -rvalue);
+ if (_instRunCtxt.modCounter % _bx != 0) return;
+
+ rvalue = (rvalue > 0 ? 1 : -1);
+ }
+
+ int16 *lvalue = inst->_opA.getLValue();
+
+ switch (inst->_index) {
+ case INST_INC:
+ *lvalue += rvalue;
+ break;
+
+ case INST_DEC:
+ *lvalue -= rvalue;
+ break;
+
+ case INST_MUL:
+ *lvalue *= rvalue;
+ break;
+
+ case INST_DIV:
+ *lvalue /= rvalue;
+ break;
+
+ default:
+ error("This should never happen. Report immediately");;
+ }
+
+ if (inst->_opA._flags & kParaLocal) {
+ wrapLocalVar(inst->_opA._local);
+ }
+
+}
+
+
+DECLARE_INSTRUCTION_OPCODE(put) {
+ warning("Parallaction_br::instOp_put not yet implemented");
+}
+
+
+
+DECLARE_INSTRUCTION_OPCODE(wait) {
+ warning("Parallaction_br::instOp_wait not yet implemented");
+}
+
+
+DECLARE_INSTRUCTION_OPCODE(start) {
+ (*_instRunCtxt.inst)->_z->_flags |= kFlagsActing;
+}
+
+
+DECLARE_INSTRUCTION_OPCODE(process) {
+ _activeZone2 = (*_instRunCtxt.inst)->_z;
+}
+
+
+DECLARE_INSTRUCTION_OPCODE(move) {
+ warning("Parallaction_br::instOp_move not yet implemented");
+}
+
+
+DECLARE_INSTRUCTION_OPCODE(color) {
+ Instruction *inst = *_instRunCtxt.inst;
+
+ int16 entry = inst->_opB.getRValue();
+
+ _gfx->_palette.setEntry(entry, inst->_colors[0], inst->_colors[1], inst->_colors[2]);
+
+}
+
+
+DECLARE_INSTRUCTION_OPCODE(mask) {
+ Instruction *inst = *_instRunCtxt.inst;
+
+ _gfx->_bgLayers[0] = inst->_opA.getRValue();
+ _gfx->_bgLayers[1] = inst->_opB.getRValue();
+ _gfx->_bgLayers[2] = inst->_opC.getRValue();
+}
+
+
+DECLARE_INSTRUCTION_OPCODE(print) {
+ warning("Parallaction_br::instOp_print not yet implemented");
+}
+
+
+
+void Parallaction_br::jobDisplaySubtitle(void *parm, Job *job) {
+ _gfx->drawLabel(_subtitle0);
+ _gfx->drawLabel(_subtitle1);
+}
+
+void Parallaction_br::jobEraseSubtitle(void *parm, Job *job) {
+ Common::Rect r;
+
+ if (_subtitle0._old.x != -1000) {
+ _subtitle0.getRect(r);
+
+// printf("sub0: (%i, %i, %i, %i)\n", r.left, r.top, r.right, r.bottom);
+
+ _gfx->restoreBackground(r);
+ }
+ _subtitle0._old = _subtitle0._pos;
+
+ if (_subtitle1._old.x != -1000) {
+ _subtitle0.getRect(r);
+
+// printf("sub1: (%i, %i, %i, %i)\n", r.left, r.top, r.right, r.bottom);
+
+ _gfx->restoreBackground(r);
+ }
+ _subtitle1._old = _subtitle1._pos;
+}
+
+DECLARE_INSTRUCTION_OPCODE(text) {
+ Instruction *inst = (*_instRunCtxt.inst);
+ setupSubtitles(inst->_text, inst->_text2, inst->_y);
+}
+
+
+DECLARE_INSTRUCTION_OPCODE(ifeq) {
+ warning("Parallaction_br::instOp_ifeq not yet implemented");
+}
+
+
+DECLARE_INSTRUCTION_OPCODE(iflt) {
+ warning("Parallaction_br::instOp_iflt not yet implemented");
+}
+
+
+DECLARE_INSTRUCTION_OPCODE(ifgt) {
+ warning("Parallaction_br::instOp_ifgt not yet implemented");
+}
+
+
+DECLARE_INSTRUCTION_OPCODE(endif) {
+ warning("Parallaction_br::instOp_endif not yet implemented");
+}
+
+
+DECLARE_INSTRUCTION_OPCODE(stop) {
+ warning("Parallaction_br::instOp_stop not yet implemented");
+}
+
+DECLARE_INSTRUCTION_OPCODE(endscript) {
+ warning("Parallaction_br::instOp_endscript not yet implemented");
+}
+
+void Parallaction_br::initOpcodes() {
+
+ static const OpcodeV2 op1[] = {
+ COMMAND_OPCODE(invalid),
+ COMMAND_OPCODE(set),
+ COMMAND_OPCODE(clear),
+ COMMAND_OPCODE(start),
+ COMMAND_OPCODE(speak),
+ COMMAND_OPCODE(get),
+ COMMAND_OPCODE(location),
+ COMMAND_OPCODE(open),
+ COMMAND_OPCODE(close),
+ COMMAND_OPCODE(on),
+ COMMAND_OPCODE(off),
+ COMMAND_OPCODE(call),
+ COMMAND_OPCODE(toggle),
+ COMMAND_OPCODE(drop),
+ COMMAND_OPCODE(quit),
+ COMMAND_OPCODE(move),
+ COMMAND_OPCODE(stop),
+ COMMAND_OPCODE(character),
+ COMMAND_OPCODE(followme),
+ COMMAND_OPCODE(onmouse),
+ COMMAND_OPCODE(offmouse),
+ COMMAND_OPCODE(add),
+ COMMAND_OPCODE(leave),
+ COMMAND_OPCODE(inc),
+ COMMAND_OPCODE(dec),
+ COMMAND_OPCODE(ifeq),
+ COMMAND_OPCODE(iflt),
+ COMMAND_OPCODE(ifgt),
+ COMMAND_OPCODE(let),
+ COMMAND_OPCODE(music),
+ COMMAND_OPCODE(fix),
+ COMMAND_OPCODE(unfix),
+ COMMAND_OPCODE(zeta),
+ COMMAND_OPCODE(scroll),
+ COMMAND_OPCODE(swap),
+ COMMAND_OPCODE(give),
+ COMMAND_OPCODE(text),
+ COMMAND_OPCODE(part),
+ COMMAND_OPCODE(testsfx),
+ COMMAND_OPCODE(ret),
+ COMMAND_OPCODE(onsave),
+ COMMAND_OPCODE(offsave)
+ };
+
+ uint i;
+ for (i = 0; i < ARRAYSIZE(op1); i++)
+ _commandOpcodes.push_back(&op1[i]);
+
+
+ static const OpcodeV2 op2[] = {
+ INSTRUCTION_OPCODE(invalid),
+ INSTRUCTION_OPCODE(on),
+ INSTRUCTION_OPCODE(off),
+ INSTRUCTION_OPCODE(set), // x
+ INSTRUCTION_OPCODE(set), // y
+ INSTRUCTION_OPCODE(set), // z
+ INSTRUCTION_OPCODE(set), // f
+ INSTRUCTION_OPCODE(loop),
+ INSTRUCTION_OPCODE(endloop),
+ INSTRUCTION_OPCODE(null), // show
+ INSTRUCTION_OPCODE(inc),
+ INSTRUCTION_OPCODE(inc), // dec
+ INSTRUCTION_OPCODE(set),
+ INSTRUCTION_OPCODE(put),
+ INSTRUCTION_OPCODE(call),
+ INSTRUCTION_OPCODE(wait),
+ INSTRUCTION_OPCODE(start),
+ INSTRUCTION_OPCODE(process),
+ INSTRUCTION_OPCODE(move),
+ INSTRUCTION_OPCODE(color),
+ INSTRUCTION_OPCODE(process), // sound
+ INSTRUCTION_OPCODE(mask),
+ INSTRUCTION_OPCODE(print),
+ INSTRUCTION_OPCODE(text),
+ INSTRUCTION_OPCODE(inc), // mul
+ INSTRUCTION_OPCODE(inc), // div
+ INSTRUCTION_OPCODE(ifeq),
+ INSTRUCTION_OPCODE(iflt),
+ INSTRUCTION_OPCODE(ifgt),
+ INSTRUCTION_OPCODE(endif),
+ INSTRUCTION_OPCODE(stop),
+ INSTRUCTION_OPCODE(endscript)
+ };
+
+ for (i = 0; i < ARRAYSIZE(op2); i++)
+ _instructionOpcodes.push_back(&op2[i]);
+
+
+}
+
+
+void Parallaction_br::jobWaitRemoveLabelJob(void *parm, Job *job) {
+
+}
+
+
+void Parallaction_br::jobWaitRemoveSubtitleJob(void *parm, Job *job) {
+
+}
+
+
+void Parallaction_br::jobPauseSfx(void *parm, Job *job) {
+
+}
+
+
+void Parallaction_br::jobStopFollower(void *parm, Job *job) {
+
+}
+
+
+void Parallaction_br::jobScroll(void *parm, Job *job) {
+
+}
+
+
+
+
+
+} // namespace Parallaction
diff --git a/engines/parallaction/exec_ns.cpp b/engines/parallaction/exec_ns.cpp
new file mode 100644
index 0000000000..2b88469702
--- /dev/null
+++ b/engines/parallaction/exec_ns.cpp
@@ -0,0 +1,925 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#include "common/stdafx.h"
+#include "parallaction/parallaction.h"
+#include "parallaction/sound.h"
+
+
+namespace Parallaction {
+
+#define INST_ON 1
+#define INST_OFF 2
+#define INST_X 3
+#define INST_Y 4
+#define INST_Z 5
+#define INST_F 6
+#define INST_LOOP 7
+#define INST_ENDLOOP 8
+#define INST_SHOW 9
+#define INST_INC 10
+#define INST_DEC 11
+#define INST_SET 12
+#define INST_PUT 13
+#define INST_CALL 14
+#define INST_WAIT 15
+#define INST_START 16
+#define INST_SOUND 17
+#define INST_MOVE 18
+#define INST_ENDSCRIPT 19
+
+
+typedef OpcodeImpl<Parallaction_ns> OpcodeV1;
+#define COMMAND_OPCODE(op) OpcodeV1(this, &Parallaction_ns::cmdOp_##op)
+#define DECLARE_COMMAND_OPCODE(op) void Parallaction_ns::cmdOp_##op()
+
+#define INSTRUCTION_OPCODE(op) OpcodeV1(this, &Parallaction_ns::instOp_##op)
+#define DECLARE_INSTRUCTION_OPCODE(op) void Parallaction_ns::instOp_##op()
+
+
+
+
+DECLARE_INSTRUCTION_OPCODE(on) {
+ Instruction *inst = *_instRunCtxt.inst;
+
+ inst->_a->_flags |= kFlagsActive;
+ inst->_a->_flags &= ~kFlagsRemove;
+}
+
+
+DECLARE_INSTRUCTION_OPCODE(off) {
+ (*_instRunCtxt.inst)->_a->_flags |= kFlagsRemove;
+}
+
+
+DECLARE_INSTRUCTION_OPCODE(loop) {
+ Instruction *inst = *_instRunCtxt.inst;
+
+ _instRunCtxt.a->_program->_loopCounter = inst->_opB.getRValue();
+ _instRunCtxt.a->_program->_loopStart = _instRunCtxt.inst;
+}
+
+
+DECLARE_INSTRUCTION_OPCODE(endloop) {
+ if (--_instRunCtxt.a->_program->_loopCounter > 0) {
+ _instRunCtxt.inst = _instRunCtxt.a->_program->_loopStart;
+ }
+}
+
+DECLARE_INSTRUCTION_OPCODE(inc) {
+ Instruction *inst = *_instRunCtxt.inst;
+ int16 _si = inst->_opB.getRValue();
+
+ if (inst->_flags & kInstMod) { // mod
+ int16 _bx = (_si > 0 ? _si : -_si);
+ if (_instRunCtxt.modCounter % _bx != 0) return;
+
+ _si = (_si > 0 ? 1 : -1);
+ }
+
+ int16* lvalue = inst->_opA.getLValue();
+
+ if (inst->_index == INST_INC) {
+ *lvalue += _si;
+ } else {
+ *lvalue -= _si;
+ }
+
+ if (inst->_opA._flags & kParaLocal) {
+ wrapLocalVar(inst->_opA._local);
+ }
+
+}
+
+
+DECLARE_INSTRUCTION_OPCODE(set) {
+ Instruction *inst = *_instRunCtxt.inst;
+
+ int16 _si = inst->_opB.getRValue();
+ int16 *lvalue = inst->_opA.getLValue();
+
+ *lvalue = _si;
+
+}
+
+
+DECLARE_INSTRUCTION_OPCODE(put) {
+ Instruction *inst = *_instRunCtxt.inst;
+ Graphics::Surface v18;
+ v18.w = inst->_a->width();
+ v18.h = inst->_a->height();
+ v18.pixels = inst->_a->getFrameData(inst->_a->_frame);
+
+ int16 x = inst->_opA.getRValue();
+ int16 y = inst->_opB.getRValue();
+
+ if (inst->_flags & kInstMaskedPut) {
+ uint16 z = _gfx->queryMask(y);
+ _gfx->blitCnv(&v18, x, y, z, Gfx::kBitBack);
+ _gfx->blitCnv(&v18, x, y, z, Gfx::kBit2);
+ } else {
+ _gfx->flatBlitCnv(&v18, x, y, Gfx::kBitBack);
+ _gfx->flatBlitCnv(&v18, x, y, Gfx::kBit2);
+ }
+}
+
+DECLARE_INSTRUCTION_OPCODE(null) {
+
+}
+
+DECLARE_INSTRUCTION_OPCODE(invalid) {
+ error("Can't execute invalid opcode %i", (*_instRunCtxt.inst)->_index);
+}
+
+DECLARE_INSTRUCTION_OPCODE(call) {
+ callFunction((*_instRunCtxt.inst)->_immediate, 0);
+}
+
+
+DECLARE_INSTRUCTION_OPCODE(wait) {
+ if (_engineFlags & kEngineWalking)
+ _instRunCtxt.suspend = true;
+}
+
+
+DECLARE_INSTRUCTION_OPCODE(start) {
+ (*_instRunCtxt.inst)->_a->_flags |= (kFlagsActing | kFlagsActive);
+}
+
+
+DECLARE_INSTRUCTION_OPCODE(sound) {
+ _activeZone = (*_instRunCtxt.inst)->_z;
+}
+
+
+DECLARE_INSTRUCTION_OPCODE(move) {
+ Instruction *inst = (*_instRunCtxt.inst);
+
+ int16 x = inst->_opA.getRValue();
+ int16 y = inst->_opB.getRValue();
+
+ WalkNodeList *v4 = _char._builder.buildPath(x, y);
+ addJob(kJobWalk, v4, kPriority19 );
+ _engineFlags |= kEngineWalking;
+}
+
+DECLARE_INSTRUCTION_OPCODE(endscript) {
+ if ((_instRunCtxt.a->_flags & kFlagsLooping) == 0) {
+ _instRunCtxt.a->_flags &= ~kFlagsActing;
+ runCommands(_instRunCtxt.a->_commands, _instRunCtxt.a);
+ }
+ _instRunCtxt.a->_program->_ip = _instRunCtxt.a->_program->_instructions.begin();
+
+ _instRunCtxt.suspend = true;
+}
+
+
+
+void Parallaction_ns::wrapLocalVar(LocalVariable *local) {
+
+ if (local->_value >= local->_max)
+ local->_value = local->_min;
+ if (local->_value < local->_min)
+ local->_value = local->_max - 1;
+
+ return;
+}
+
+
+DECLARE_COMMAND_OPCODE(invalid) {
+ error("Can't execute invalid command '%i'", _cmdRunCtxt.cmd->_id);
+}
+
+DECLARE_COMMAND_OPCODE(set) {
+ if (_cmdRunCtxt.cmd->u._flags & kFlagsGlobal) {
+ _cmdRunCtxt.cmd->u._flags &= ~kFlagsGlobal;
+ _commandFlags |= _cmdRunCtxt.cmd->u._flags;
+ } else {
+ _localFlags[_currentLocationIndex] |= _cmdRunCtxt.cmd->u._flags;
+ }
+}
+
+
+DECLARE_COMMAND_OPCODE(clear) {
+ if (_cmdRunCtxt.cmd->u._flags & kFlagsGlobal) {
+ _cmdRunCtxt.cmd->u._flags &= ~kFlagsGlobal;
+ _commandFlags &= ~_cmdRunCtxt.cmd->u._flags;
+ } else {
+ _localFlags[_currentLocationIndex] &= ~_cmdRunCtxt.cmd->u._flags;
+ }
+}
+
+
+DECLARE_COMMAND_OPCODE(start) {
+ _cmdRunCtxt.cmd->u._animation->_flags |= kFlagsActing;
+}
+
+
+DECLARE_COMMAND_OPCODE(speak) {
+ _activeZone = _cmdRunCtxt.cmd->u._zone;
+}
+
+
+DECLARE_COMMAND_OPCODE(get) {
+ _cmdRunCtxt.cmd->u._zone->_flags &= ~kFlagsFixed;
+ if (!runZone(_cmdRunCtxt.cmd->u._zone)) {
+ runCommands(_cmdRunCtxt.cmd->u._zone->_commands);
+ }
+}
+
+
+DECLARE_COMMAND_OPCODE(location) {
+ strcpy(_location._name, _cmdRunCtxt.cmd->u._string);
+ _engineFlags |= kEngineChangeLocation;
+}
+
+
+DECLARE_COMMAND_OPCODE(open) {
+ _cmdRunCtxt.cmd->u._zone->_flags &= ~kFlagsClosed;
+ if (_cmdRunCtxt.cmd->u._zone->u.door->_cnv) {
+ addJob(kJobToggleDoor, (void*)_cmdRunCtxt.cmd->u._zone, kPriority18 );
+ }
+}
+
+
+DECLARE_COMMAND_OPCODE(close) {
+ _cmdRunCtxt.cmd->u._zone->_flags |= kFlagsClosed;
+ if (_cmdRunCtxt.cmd->u._zone->u.door->_cnv) {
+ addJob(kJobToggleDoor, (void*)_cmdRunCtxt.cmd->u._zone, kPriority18 );
+ }
+}
+
+
+DECLARE_COMMAND_OPCODE(on) {
+ // WORKAROUND: the original DOS-based engine didn't check u->_zone before dereferencing
+ // the pointer to get structure members, thus leading to crashes in systems with memory
+ // protection.
+ // As a side note, the overwritten address is the 5th entry in the DOS interrupt table
+ // (print screen handler): this suggests that a system would hang when the print screen
+ // key is pressed after playing Nippon Safes, provided that this code path is taken.
+ if (_cmdRunCtxt.cmd->u._zone != NULL) {
+ _cmdRunCtxt.cmd->u._zone->_flags &= ~kFlagsRemove;
+ _cmdRunCtxt.cmd->u._zone->_flags |= kFlagsActive;
+ if ((_cmdRunCtxt.cmd->u._zone->_type & 0xFFFF) == kZoneGet) {
+ addJob(kJobDisplayDroppedItem, _cmdRunCtxt.cmd->u._zone, kPriority17 );
+ }
+ }
+}
+
+
+DECLARE_COMMAND_OPCODE(off) {
+ _cmdRunCtxt.cmd->u._zone->_flags |= kFlagsRemove;
+}
+
+
+DECLARE_COMMAND_OPCODE(call) {
+ callFunction(_cmdRunCtxt.cmd->u._callable, _cmdRunCtxt.z);
+}
+
+
+DECLARE_COMMAND_OPCODE(toggle) {
+ if (_cmdRunCtxt.cmd->u._flags & kFlagsGlobal) {
+ _cmdRunCtxt.cmd->u._flags &= ~kFlagsGlobal;
+ _commandFlags ^= _cmdRunCtxt.cmd->u._flags;
+ } else {
+ _localFlags[_currentLocationIndex] ^= _cmdRunCtxt.cmd->u._flags;
+ }
+}
+
+
+DECLARE_COMMAND_OPCODE(drop){
+ dropItem( _cmdRunCtxt.cmd->u._object );
+}
+
+
+DECLARE_COMMAND_OPCODE(quit) {
+ _engineFlags |= kEngineQuit;
+}
+
+
+DECLARE_COMMAND_OPCODE(move) {
+ if ((_char._ani._flags & kFlagsRemove) || (_char._ani._flags & kFlagsActive) == 0) {
+ return;
+ }
+
+ WalkNodeList *vC = _char._builder.buildPath(_cmdRunCtxt.cmd->u._move.x, _cmdRunCtxt.cmd->u._move.y);
+
+ addJob(kJobWalk, vC, kPriority19 );
+ _engineFlags |= kEngineWalking;
+}
+
+
+DECLARE_COMMAND_OPCODE(stop) {
+ _cmdRunCtxt.cmd->u._animation->_flags &= ~kFlagsActing;
+}
+
+
+void Parallaction_ns::jobDisplayAnimations(void *parm, Job *j) {
+
+ Graphics::Surface v14;
+
+ uint16 _si = 0;
+
+ for (AnimationList::iterator it = _animations.begin(); it != _animations.end(); it++) {
+
+ Animation *v18 = *it;
+
+ if ((v18->_flags & kFlagsActive) && ((v18->_flags & kFlagsRemove) == 0)) {
+ v14.w = v18->width();
+ v14.h = v18->height();
+
+ int16 frame = CLIP((int)v18->_frame, 0, v18->getFrameNum()-1);
+
+ v14.pixels = v18->getFrameData(frame);
+
+ if (v18->_flags & kFlagsNoMasked)
+ _si = 3;
+ else
+ _si = _gfx->queryMask(v18->_top + v18->height());
+
+ debugC(9, kDebugExec, "jobDisplayAnimations(%s, x:%i, y:%i, z:%i, w:%i, h:%i, f:%i/%i, %p)", v18->_label._text, v18->_left, v18->_top, _si, v14.w, v14.h,
+ frame, v18->getFrameNum(), v14.pixels);
+ _gfx->blitCnv(&v14, v18->_left, v18->_top, _si, Gfx::kBitBack);
+
+ }
+
+ if (((v18->_flags & kFlagsActive) == 0) && (v18->_flags & kFlagsRemove)) {
+ v18->_flags &= ~kFlagsRemove;
+ v18->_oldPos.x = -1000;
+ }
+
+ if ((v18->_flags & kFlagsActive) && (v18->_flags & kFlagsRemove)) {
+ v18->_flags &= ~kFlagsActive;
+ v18->_flags |= kFlagsRemove;
+ }
+ }
+
+ return;
+}
+
+
+void Parallaction_ns::jobEraseAnimations(void *arg_0, Job *j) {
+ debugC(9, kDebugExec, "jobEraseAnimations");
+
+ for (AnimationList::iterator it = _animations.begin(); it != _animations.end(); it++) {
+
+ Animation *a = *it;
+
+ if (((a->_flags & kFlagsActive) == 0) && ((a->_flags & kFlagsRemove) == 0)) continue;
+
+ Common::Rect r(a->width(), a->height());
+ r.moveTo(a->_oldPos);
+ _gfx->restoreBackground(r);
+
+ if (arg_0) {
+ a->_oldPos.x = a->_left;
+ a->_oldPos.y = a->_top;
+ }
+
+ }
+
+ return;
+}
+
+
+void Parallaction_ns::jobRunScripts(void *parm, Job *j) {
+ debugC(9, kDebugExec, "jobRunScripts");
+
+ static uint16 modCounter = 0;
+
+ for (AnimationList::iterator it = _animations.begin(); it != _animations.end(); it++) {
+
+ Animation *a = *it;
+
+ if (a->_flags & kFlagsCharacter)
+ a->_z = a->_top + a->height();
+
+ if ((a->_flags & kFlagsActing) == 0)
+ continue;
+
+ InstructionList::iterator inst = a->_program->_ip;
+ while (((*inst)->_index != INST_SHOW) && (a->_flags & kFlagsActing)) {
+
+ debugC(9, kDebugExec, "Animation: %s, instruction: %s", a->_label._text, _instructionNamesRes[(*inst)->_index - 1]);
+
+ _instRunCtxt.inst = inst;
+ _instRunCtxt.a = a;
+ _instRunCtxt.modCounter = modCounter;
+ _instRunCtxt.suspend = false;
+
+ (*_instructionOpcodes[(*inst)->_index])();
+
+ inst = _instRunCtxt.inst; // handles endloop correctly
+
+ if (_instRunCtxt.suspend)
+ goto label1;
+
+ inst++;
+ }
+
+ a->_program->_ip = ++inst;
+
+label1:
+ if (a->_flags & kFlagsCharacter)
+ a->_z = a->_top + a->height();
+ }
+
+ sortAnimations();
+ modCounter++;
+
+ return;
+}
+
+
+void Parallaction::runCommands(CommandList& list, Zone *z) {
+ debugC(3, kDebugExec, "runCommands");
+
+ CommandList::iterator it = list.begin();
+ for ( ; it != list.end(); it++) {
+
+ Command *cmd = *it;
+ uint32 v8 = _localFlags[_currentLocationIndex];
+
+ if (_engineFlags & kEngineQuit)
+ break;
+
+ if (cmd->_flagsOn & kFlagsGlobal) {
+ v8 = _commandFlags | kFlagsGlobal;
+ }
+
+ if ((cmd->_flagsOn & v8) != cmd->_flagsOn) continue;
+ if ((cmd->_flagsOff & ~v8) != cmd->_flagsOff) continue;
+
+ debugC(3, kDebugExec, "runCommands[%i]: %s (on: %x, off: %x)", cmd->_id, _commandsNamesRes[cmd->_id-1], cmd->_flagsOn, cmd->_flagsOff);
+
+ _cmdRunCtxt.z = z;
+ _cmdRunCtxt.cmd = cmd;
+
+ (*_commandOpcodes[cmd->_id])();
+ }
+
+ debugC(3, kDebugExec, "runCommands completed");
+
+ return;
+
+}
+
+
+
+
+// displays character head commenting an examined object
+//
+// works on the frontbuffer
+//
+void Parallaction::displayCharacterComment(ExamineData *data) {
+ if (data->_description == NULL) return;
+
+ // NOTE: saving visible screen before displaying comment allows
+ // to restore the exact situation after the comment is deleted.
+ // This means animations are restored in the exact position as
+ // they were, thus avoiding clipping effect as signalled in
+ // BUG item #1762614.
+ _gfx->copyScreen(Gfx::kBitFront, Gfx::kBitBack);
+
+ _gfx->setFont(_dialogueFont);
+ _gfx->flatBlitCnv(_char._talk, 0, 190, 80, Gfx::kBitFront);
+
+ int16 v26, v28;
+ _gfx->getStringExtent(data->_description, 130, &v28, &v26);
+ Common::Rect r(v28, v26);
+ r.moveTo(140, 10);
+ _gfx->drawBalloon(r, 0);
+ _gfx->displayWrappedString(data->_description, 140, 10, 0, 130);
+
+ waitUntilLeftClick();
+
+ _gfx->copyScreen(Gfx::kBitBack, Gfx::kBitFront);
+ _gfx->updateScreen();
+
+ return;
+}
+
+//
+// ZONE TYPE: EXAMINE
+//
+
+// display detail view of an item (and eventually comments)
+//
+// works on the frontbuffer
+//
+
+void Parallaction::displayItemComment(ExamineData *data) {
+
+ if (data->_description == NULL) return;
+
+ _gfx->setHalfbriteMode(true);
+
+ char v68[PATH_LEN];
+ strcpy(v68, data->_filename);
+ data->_cnv = _disk->loadStatic(v68);
+ _gfx->flatBlitCnv(data->_cnv, 140, (_screenHeight - data->_cnv->h)/2, Gfx::kBitFront);
+ delete data->_cnv;
+
+ int16 v6A = 0, v6C = 0;
+
+ _gfx->setFont(_dialogueFont);
+ _gfx->getStringExtent(data->_description, 130, &v6C, &v6A);
+ Common::Rect r(v6C, v6A);
+ r.moveTo(0, 90);
+ _gfx->drawBalloon(r, 0);
+ _gfx->flatBlitCnv(_char._head, 100, 152, Gfx::kBitFront);
+ _gfx->displayWrappedString(data->_description, 0, 90, 0, 130);
+
+ jobEraseAnimations((void*)1, NULL);
+ _gfx->updateScreen();
+
+ waitUntilLeftClick();
+
+ _gfx->setHalfbriteMode(false);
+ _gfx->copyScreen(Gfx::kBitBack, Gfx::kBitFront);
+ _gfx->updateScreen();
+
+ return;
+}
+
+
+
+uint16 Parallaction::runZone(Zone *z) {
+ debugC(3, kDebugExec, "runZone (%s)", z->_label._text);
+
+ uint16 subtype = z->_type & 0xFFFF;
+
+ debugC(3, kDebugExec, "type = %x, object = %x", subtype, (z->_type & 0xFFFF0000) >> 16);
+ switch(subtype) {
+
+ case kZoneExamine:
+ if (z->u.examine->_filename) {
+ displayItemComment(z->u.examine);
+ } else {
+ displayCharacterComment(z->u.examine);
+ }
+ break;
+
+ case kZoneGet:
+ if (z->_flags & kFlagsFixed) break;
+ if (pickupItem(z) != 0) {
+ return 1;
+ }
+ z->_flags |= kFlagsRemove;
+ break;
+
+ case kZoneDoor:
+ if (z->_flags & kFlagsLocked) break;
+ z->_flags ^= kFlagsClosed;
+ if (z->u.door->_cnv == NULL) break;
+ addJob(kJobToggleDoor, z, kPriority18 );
+ break;
+
+ case kZoneHear:
+ _soundMan->playSfx(z->u.hear->_name, z->u.hear->_channel, (z->_flags & kFlagsLooping) == kFlagsLooping, 60);
+ break;
+
+ case kZoneSpeak:
+ runDialogue(z->u.speak);
+ break;
+
+ }
+
+ debugC(3, kDebugExec, "runZone completed");
+
+ return 0;
+}
+
+//
+// ZONE TYPE: DOOR
+//
+void Parallaction_ns::jobToggleDoor(void *parm, Job *j) {
+
+ static byte count = 0;
+
+ Zone *z = (Zone*)parm;
+
+ if (z->u.door->_cnv) {
+ Common::Rect r;
+ z->u.door->_cnv->getRect(0, r);
+ r.moveTo(z->_left, z->_top);
+
+ uint16 _ax = (z->_flags & kFlagsClosed ? 1 : 0);
+ _gfx->restoreDoorBackground(r, z->u.door->_cnv->getData(_ax), z->u.door->_background);
+
+ _ax = (z->_flags & kFlagsClosed ? 0 : 1);
+ _gfx->flatBlitCnv(z->u.door->_cnv, _ax, z->_left, z->_top, Gfx::kBitBack);
+ _gfx->flatBlitCnv(z->u.door->_cnv, _ax, z->_left, z->_top, Gfx::kBit2);
+ }
+
+ count++;
+ if (count == 2) {
+ j->_finished = 1;
+ count = 0;
+ }
+
+ return;
+}
+
+
+
+//
+// ZONE TYPE: GET
+//
+
+int16 Parallaction::pickupItem(Zone *z) {
+ int r = addInventoryItem(z->u.get->_icon);
+ if (r == 0)
+ addJob(kJobRemovePickedItem, z, kPriority17 );
+
+ return r;
+}
+
+void Parallaction_ns::jobRemovePickedItem(void *parm, Job *j) {
+
+ Zone *z = (Zone*)parm;
+
+ static uint16 count = 0;
+
+ if (z->u.get->_cnv) {
+ Common::Rect r(z->_left, z->_top, z->_left + z->u.get->_cnv->w, z->_top + z->u.get->_cnv->h);
+
+ _gfx->restoreGetBackground(r, z->u.get->_backup);
+ }
+
+ count++;
+ if (count == 2) {
+ count = 0;
+ j->_finished = 1;
+ }
+
+ return;
+}
+
+void Parallaction_ns::jobDisplayDroppedItem(void *parm, Job *j) {
+// printf("jobDisplayDroppedItem...");
+
+ Zone *z = (Zone*)parm;
+
+ if (z->u.get->_cnv) {
+ if (j->_count == 0) {
+ _gfx->backupGetBackground(z->u.get, z->_left, z->_top);
+ }
+
+ _gfx->flatBlitCnv(z->u.get->_cnv, z->_left, z->_top, Gfx::kBitBack);
+ _gfx->flatBlitCnv(z->u.get->_cnv, z->_left, z->_top, Gfx::kBit2);
+ }
+
+ j->_count++;
+ if (j->_count == 2) {
+ j->_count = 0;
+ j->_finished = 1;
+ }
+
+// printf("done");
+
+ return;
+}
+
+
+
+
+Zone *Parallaction::hitZone(uint32 type, uint16 x, uint16 y) {
+// printf("hitZone(%i, %i, %i)", type, x, y);
+
+ uint16 _di = y;
+ uint16 _si = x;
+
+ for (ZoneList::iterator it = _zones.begin(); it != _zones.end(); it++) {
+// printf("Zone name: %s", z->_name);
+
+ Zone *z = *it;
+
+ if (z->_flags & kFlagsRemove) continue;
+
+ Common::Rect r;
+ z->getRect(r);
+ r.right++; // adjust border because Common::Rect doesn't include bottom-right edge
+ r.bottom++;
+
+ r.grow(-1); // allows some tolerance for mouse click
+
+ if (!r.contains(_si, _di)) {
+
+ // out of Zone, so look for special values
+ if ((z->_left == -2) || (z->_left == -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,
+ // but we need to check it separately here. The same workaround is applied in freeZones.
+ if ((((z->_type & 0xFFFF) == kZoneMerge) && (((_si == z->u.merge->_obj1) && (_di == z->u.merge->_obj2)) || ((_si == z->u.merge->_obj2) && (_di == z->u.merge->_obj1)))) ||
+ (((z->_type & 0xFFFF) == kZoneGet) && ((_si == z->u.get->_icon) || (_di == z->u.get->_icon)))) {
+
+ // special Zone
+ if ((type == 0) && ((z->_type & 0xFFFF0000) == 0))
+ return z;
+ if (z->_type == type)
+ return z;
+ if ((z->_type & 0xFFFF0000) == type)
+ return z;
+
+ }
+ }
+
+ if (z->_left != -1)
+ continue;
+ if (_si < _char._ani._left)
+ continue;
+ if (_si > (_char._ani._left + _char._ani.width()))
+ continue;
+ if (_di < _char._ani._top)
+ continue;
+ if (_di > (_char._ani._top + _char._ani.height()))
+ continue;
+
+ }
+
+ // normal Zone
+ if ((type == 0) && ((z->_type & 0xFFFF0000) == 0))
+ return z;
+ if (z->_type == type)
+ return z;
+ if ((z->_type & 0xFFFF0000) == type)
+ return z;
+
+ }
+
+
+ int16 _a, _b, _c, _d, _e, _f;
+ for (AnimationList::iterator it = _animations.begin(); it != _animations.end(); it++) {
+
+ Animation *a = *it;
+
+ _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
+
+ _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
+ _d = ((a->_type & 0xFFFF0000) != type) ? 0 : 1; // _d: Animation is an object of the same type
+
+ if ((_a != 0 && _e != 0 && _f != 0) && ((_b != 0 && _c != 0) || (a->_type == type) || (_d != 0))) {
+
+ return a;
+
+ }
+
+ }
+
+ return NULL;
+}
+
+
+void Parallaction_ns::initOpcodes() {
+
+ static const OpcodeV1 op1[] = {
+ INSTRUCTION_OPCODE(invalid),
+ INSTRUCTION_OPCODE(on),
+ INSTRUCTION_OPCODE(off),
+ INSTRUCTION_OPCODE(set), // x
+ INSTRUCTION_OPCODE(set), // y
+ INSTRUCTION_OPCODE(set), // z
+ INSTRUCTION_OPCODE(set), // f
+ INSTRUCTION_OPCODE(loop),
+ INSTRUCTION_OPCODE(endloop),
+ INSTRUCTION_OPCODE(null),
+ INSTRUCTION_OPCODE(inc),
+ INSTRUCTION_OPCODE(inc), // dec
+ INSTRUCTION_OPCODE(set),
+ INSTRUCTION_OPCODE(put),
+ INSTRUCTION_OPCODE(call),
+ INSTRUCTION_OPCODE(wait),
+ INSTRUCTION_OPCODE(start),
+ INSTRUCTION_OPCODE(sound),
+ INSTRUCTION_OPCODE(move),
+ INSTRUCTION_OPCODE(endscript)
+ };
+
+ uint i;
+ for (i = 0; i < ARRAYSIZE(op1); i++)
+ _instructionOpcodes.push_back(&op1[i]);
+
+ static const OpcodeV1 op3[] = {
+ COMMAND_OPCODE(invalid),
+ COMMAND_OPCODE(set),
+ COMMAND_OPCODE(clear),
+ COMMAND_OPCODE(start),
+ COMMAND_OPCODE(speak),
+ COMMAND_OPCODE(get),
+ COMMAND_OPCODE(location),
+ COMMAND_OPCODE(open),
+ COMMAND_OPCODE(close),
+ COMMAND_OPCODE(on),
+ COMMAND_OPCODE(off),
+ COMMAND_OPCODE(call),
+ COMMAND_OPCODE(toggle),
+ COMMAND_OPCODE(drop),
+ COMMAND_OPCODE(quit),
+ COMMAND_OPCODE(move),
+ COMMAND_OPCODE(stop)
+ };
+
+ for (i = 0; i < ARRAYSIZE(op3); i++)
+ _commandOpcodes.push_back(&op3[i]);
+
+}
+
+
+
+void Parallaction_ns::jobDisplayLabel(void *parm, Job *j) {
+
+ Label *label = (Label*)parm;
+ debugC(9, kDebugExec, "jobDisplayLabel (%p)", (const void*) label);
+
+ _gfx->drawLabel(*label);
+
+ return;
+}
+
+void Parallaction_ns::jobEraseLabel(void *parm, Job *j) {
+ Label *label = (Label*)parm;
+
+ debugC(9, kDebugExec, "jobEraseLabel (%p)", (const void*) label);
+
+ int16 _si, _di;
+
+ if (_activeItem._id != 0) {
+ _si = _mousePos.x + 16 - label->_cnv.w/2;
+ _di = _mousePos.y + 34;
+ } else {
+ _si = _mousePos.x + 8 - label->_cnv.w/2;
+ _di = _mousePos.y + 21;
+ }
+
+ if (_si < 0) _si = 0;
+ if (_di > 190) _di = 190;
+
+ if (label->_cnv.w + _si > _screenWidth)
+ _si = _screenWidth - label->_cnv.w;
+
+ Common::Rect r;
+ label->getRect(r, true);
+ _gfx->restoreBackground(r);
+
+ label->_old = label->_pos;
+ label->_pos.x = _si;
+ label->_pos.y = _di;
+
+ return;
+}
+
+
+
+// this Job uses a static counter to delay removal
+// and is in fact only used to remove jEraseLabel jobs
+//
+void Parallaction_ns::jobWaitRemoveJob(void *parm, Job *j) {
+ Job *arg = (Job*)parm;
+
+ static uint16 count = 0;
+
+ debugC(9, kDebugExec, "jobWaitRemoveJob: count = %i", count);
+
+ _engineFlags |= kEngineBlockInput;
+
+ count++;
+ if (count == 2) {
+ count = 0;
+ removeJob(arg);
+ _engineFlags &= ~kEngineBlockInput;
+ j->_finished = 1;
+ }
+
+ return;
+}
+
+
+
+} // namespace Parallaction
diff --git a/engines/parallaction/font.cpp b/engines/parallaction/font.cpp
index 13e94a4cda..afa00f81af 100644
--- a/engines/parallaction/font.cpp
+++ b/engines/parallaction/font.cpp
@@ -18,8 +18,8 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
- * $URL:https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/branches/gsoc2007-fsnode/engines/parallaction/font.cpp $
- * $Id:font.cpp 26949 2007-05-26 20:23:24Z david_corrales $
+ * $URL$
+ * $Id$
*
*/
@@ -34,6 +34,146 @@ namespace Parallaction {
extern byte _amigaTopazFont[];
+class BraFont : public Font {
+
+ byte *_cp;
+ uint _bufPitch;
+
+ uint32 _height;
+ byte _numGlyphs;
+
+ byte *_widths;
+ uint *_offsets;
+
+ byte *_data;
+
+ static byte _charMap[];
+
+ byte mapChar(byte c) {
+ return _charMap[c];
+ }
+
+public:
+ BraFont(Common::ReadStream &stream) {
+
+ _numGlyphs = stream.readByte();
+ _height = stream.readUint32BE();
+
+ _widths = (byte*)malloc(_numGlyphs);
+ stream.read(_widths, _numGlyphs);
+
+ _offsets = (uint*)malloc(_numGlyphs * sizeof(uint));
+ _offsets[0] = 0;
+ for (uint i = 1; i < _numGlyphs; i++)
+ _offsets[i] = _offsets[i-1] + _widths[i-1] * _height;
+
+ uint size = _offsets[_numGlyphs-1] + _widths[_numGlyphs-1] * _height;
+
+ _data = (byte*)malloc(size);
+ stream.read(_data, size);
+
+ }
+
+ ~BraFont() {
+ free(_widths);
+ free(_offsets);
+ free(_data);
+ }
+
+
+ uint32 getStringWidth(const char *s) {
+ uint32 len = 0;
+
+ while (*s) {
+ byte c = mapChar(*s);
+ len += (_widths[c] + 2);
+ s++;
+ }
+
+ return len;
+ }
+
+ uint16 height() {
+ return (uint16)_height;
+ }
+
+ uint16 drawChar(char c) {
+ assert(c < _numGlyphs);
+
+ byte *src = _data + _offsets[c];
+ byte *dst = _cp;
+ uint16 w = _widths[c];
+
+ for (uint16 j = 0; j < height(); j++) {
+ for (uint16 k = 0; k < w; k++) {
+
+ if (*src) {
+ *dst = (_color) ? _color : *src;
+ }
+
+ dst++;
+ src++;
+ }
+
+ dst += (_bufPitch - w);
+ }
+
+ return w + 2;
+
+ }
+
+ void drawString(byte* buffer, uint32 pitch, const char *s) {
+ if (s == NULL)
+ return;
+
+ _bufPitch = pitch;
+
+ _cp = buffer;
+ while (*s) {
+ byte c = mapChar(*s);
+ _cp += drawChar(c);
+ s++;
+ }
+ }
+
+};
+
+byte BraFont::_charMap[] = {
+// 0
+ 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34,
+// 1
+ 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34,
+// 2
+ 0x34, 0x49, 0x48, 0x34, 0x34, 0x34, 0x34, 0x47, 0x34, 0x34, 0x34, 0x34, 0x40, 0x34, 0x3F, 0x34,
+// 3
+ 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x46, 0x45, 0x34, 0x34, 0x34, 0x42,
+// 4
+ 0x34, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E,
+// 5
+ 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x34, 0x34, 0x34, 0x34, 0x34,
+// 6
+ 0x34, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28,
+// 7
+ 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, 0x31, 0x32, 0x33, 0x34, 0x34, 0x34, 0x34, 0x34,
+// 8
+ 0x5E, 0x5D, 0x4E, 0x4B, 0x4D, 0x4C, 0x34, 0x5E, 0x4F, 0x51, 0x50, 0x34, 0x34, 0x34, 0x34, 0x34,
+// 9
+ 0x34, 0x34, 0x34, 0x57, 0x59, 0x58, 0x5B, 0x5C, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34,
+// A
+ 0x4A, 0x52, 0x34, 0x5A, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34,
+// B
+ 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34,
+// C
+ 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34,
+// D
+ 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34,
+// E
+ 0x34, 0x5F, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34,
+// F
+ 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34
+};
+
+
class DosFont : public Font {
protected:
@@ -430,19 +570,22 @@ Font *AmigaDisk_ns::createFont(const char *name, Common::SeekableReadStream &str
return new AmigaFont(stream);
}
-void Gfx::initFonts() {
+Font *DosDisk_br::createFont(const char *name, Common::ReadStream &stream) {
+// printf("DosDisk_br::createFont(%s)\n", name);
+ return new BraFont(stream);
+}
- if (_vm->getPlatform() == Common::kPlatformPC) {
- _fonts[kFontDialogue] = _vm->_disk->loadFont("comic");
- _fonts[kFontLabel] = _vm->_disk->loadFont("topaz");
- _fonts[kFontMenu] = _vm->_disk->loadFont("slide");
- } else {
- _fonts[kFontDialogue] = _vm->_disk->loadFont("comic");
+void Parallaction_ns::initFonts() {
+ if (getPlatform() == Common::kPlatformPC) {
+ _dialogueFont = _disk->loadFont("comic");
+ _labelFont = _disk->loadFont("topaz");
+ _menuFont = _disk->loadFont("slide");
+ } else {
+ _dialogueFont = _disk->loadFont("comic");
Common::MemoryReadStream stream(_amigaTopazFont, 2600, false);
- _fonts[kFontLabel] = new AmigaFont(stream);
-
- _fonts[kFontMenu] = _vm->_disk->loadFont("slide");
+ _labelFont = new AmigaFont(stream);
+ _menuFont = _disk->loadFont("slide");
}
}
diff --git a/engines/parallaction/graphics.cpp b/engines/parallaction/graphics.cpp
index 8d45c4aaa9..6a8ef0718b 100644
--- a/engines/parallaction/graphics.cpp
+++ b/engines/parallaction/graphics.cpp
@@ -32,12 +32,147 @@
namespace Parallaction {
-byte * Gfx::_buffers[];
-#define BALLOON_WIDTH 12
-#define BALLOON_HEIGHT 10
-byte _resBalloon[2][BALLOON_WIDTH*BALLOON_HEIGHT] = {
+Palette::Palette() {
+
+ int gameType = _vm->getGameType();
+
+ if (gameType == GType_Nippon) {
+ _colors = 32;
+ _hb = (_vm->getPlatform() == Common::kPlatformAmiga);
+ } else
+ if (gameType == GType_BRA) {
+ _colors = 256;
+ _hb = false;
+ } else
+ error("can't create palette for id = '%i'", gameType);
+
+ _size = _colors * 3;
+
+ makeBlack();
+}
+
+Palette::Palette(const Palette &pal) {
+ clone(pal);
+}
+
+void Palette::clone(const Palette &pal) {
+ _colors = pal._colors;
+ _hb = pal._hb;
+ _size = pal._size;
+ memcpy(_data, pal._data, _size);
+}
+
+
+void Palette::makeBlack() {
+ memset(_data, 0, _size);
+}
+
+void Palette::setEntry(uint index, int red, int green, int blue) {
+ assert(index < _colors);
+
+ if (red >= 0)
+ _data[index*3] = red & 0xFF;
+
+ if (green >= 0)
+ _data[index*3+1] = green & 0xFF;
+
+ if (blue >= 0)
+ _data[index*3+2] = blue & 0xFF;
+}
+
+void Palette::makeGrayscale() {
+ byte v;
+ for (uint16 i = 0; i < _colors; i++) {
+ v = MAX(_data[i*3+1], _data[i*3+2]);
+ v = MAX(v, _data[i*3]);
+ setEntry(i, v, v, v);
+ }
+}
+
+void Palette::fadeTo(const Palette& target, uint step) {
+
+ if (step == 0)
+ return;
+
+ for (uint16 i = 0; i < _size; i++) {
+ if (_data[i] == target._data[i]) continue;
+
+ if (_data[i] < target._data[i])
+ _data[i] = CLIP(_data[i] + step, (uint)0, (uint)target._data[i]);
+ else
+ _data[i] = CLIP(_data[i] - step, (uint)target._data[i], (uint)255);
+ }
+
+ return;
+}
+
+uint Palette::fillRGBA(byte *rgba) {
+
+ byte r, g, b;
+ byte *hbPal = rgba + _size;
+
+ for (uint32 i = 0; i < _colors; i++) {
+ r = (_data[i*3] << 2) | (_data[i*3] >> 4);
+ g = (_data[i*3+1] << 2) | (_data[i*3+1] >> 4);
+ b = (_data[i*3+2] << 2) | (_data[i*3+2] >> 4);
+
+ rgba[i*4] = r;
+ rgba[i*4+1] = g;
+ rgba[i*4+2] = b;
+ rgba[i*4+3] = 0;
+
+ if (_hb) {
+ hbPal[i*4] = r >> 1;
+ hbPal[i*4+1] = g >> 1;
+ hbPal[i*4+2] = b >> 1;
+ hbPal[i*4+3] = 0;
+ }
+
+ }
+
+ return ((_hb) ? 2 : 1) * _colors;
+}
+
+void Palette::rotate(uint first, uint last, bool forward) {
+
+ byte tmp[3];
+
+ if (forward) { // forward
+
+ tmp[0] = _data[first * 3];
+ tmp[1] = _data[first * 3 + 1];
+ tmp[2] = _data[first * 3 + 2];
+
+ memmove(_data+first*3, _data+(first+1)*3, (last - first)*3);
+
+ _data[last * 3] = tmp[0];
+ _data[last * 3 + 1] = tmp[1];
+ _data[last * 3 + 2] = tmp[2];
+
+ } else { // backward
+
+ tmp[0] = _data[last * 3];
+ tmp[1] = _data[last * 3 + 1];
+ tmp[2] = _data[last * 3 + 2];
+
+ memmove(_data+(first+1)*3, _data+first*3, (last - first)*3);
+
+ _data[first * 3] = tmp[0];
+ _data[first * 3 + 1] = tmp[1];
+ _data[first * 3 + 2] = tmp[2];
+
+ }
+
+}
+
+
+#define BALLOON_TAIL_WIDTH 12
+#define BALLOON_TAIL_HEIGHT 10
+
+
+byte _resBalloonTail[2][BALLOON_TAIL_WIDTH*BALLOON_TAIL_HEIGHT] = {
{
0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x02, 0x02,
0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x02, 0x02,
@@ -69,96 +204,41 @@ void Gfx::drawBalloon(const Common::Rect& r, uint16 winding) {
Common::Rect q = r;
+ // draws balloon
q.right += 5;
floodFill(kBitFront, q, 0);
-
- q.left++;
- q.top+=2;
- q.right--;
- q.bottom--;
+ q.grow(-1);
floodFill(kBitFront, q, 1);
+ // draws tail
+ // TODO: this bitmap tail should only be used for Dos games. Amiga should use a polygon fill.
winding = (winding == 0 ? 1 : 0);
- byte *s = _resBalloon[winding];
- byte *d = _buffers[kBitFront] + (r.left + (r.width()+5)/2 - 5) + (r.bottom - 1) * _vm->_screenWidth;
-
- for (uint16 i = 0; i < BALLOON_HEIGHT; i++) {
- for (uint16 j = 0; j < BALLOON_WIDTH; j++) {
- if (*s != 2) *d = *s;
- d++;
- s++;
- }
-
- d += (_vm->_screenWidth - BALLOON_WIDTH);
- }
-
-// printf("done\n");
+ Common::Rect s(BALLOON_TAIL_WIDTH, BALLOON_TAIL_HEIGHT);
+ s.moveTo(r.left + (r.width()+5)/2 - 5, r.bottom - 1);
+ flatBlit(s, _resBalloonTail[winding], kBitFront, 2);
return;
}
-void Gfx::setPalette(Palette pal, uint32 first, uint32 num) {
-// printf("setPalette(%i, %i)\n", first, num);
-
- if (first + num > BASE_PALETTE_COLORS)
- error("wrong parameters for setPalette()");
-
- byte sysBasePal[EHB_PALETTE_COLORS*4];
- byte sysExtraPal[BASE_PALETTE_COLORS*4];
-
- byte r, g, b;
- uint32 j = 0;
- for (uint32 i = first; i < first+num; i++) {
- r = (pal[i*3] << 2) | (pal[i*3] >> 4);
- g = (pal[i*3+1] << 2) | (pal[i*3+1] >> 4);
- b = (pal[i*3+2] << 2) | (pal[i*3+2] >> 4);
-
- sysBasePal[j*4] = r;
- sysBasePal[j*4+1] = g;
- sysBasePal[j*4+2] = b;
- sysBasePal[j*4+3] = 0;
-
- if (_vm->getPlatform() == Common::kPlatformAmiga) {
- sysExtraPal[j*4] = r >> 1;
- sysExtraPal[j*4+1] = g >> 1;
- sysExtraPal[j*4+2] = b >> 1;
- sysExtraPal[j*4+3] = 0;
- } else {
- sysExtraPal[j*4] = 0;
- sysExtraPal[j*4+1] = 0;
- sysExtraPal[j*4+2] = 0;
- sysExtraPal[j*4+3] = 0;
- }
-
- j++;
- }
-
- g_system->setPalette(sysBasePal, first, num);
- if (_vm->getPlatform() == Common::kPlatformAmiga)
- g_system->setPalette(sysExtraPal, first+FIRST_EHB_COLOR, num);
-// g_system->updateScreen();
+void Gfx::setPalette(Palette pal) {
+ byte sysPal[256*4];
- return;
+ uint n = pal.fillRGBA(sysPal);
+ g_system->setPalette(sysPal, 0, n);
}
void Gfx::setBlackPalette() {
Palette pal;
- memset(pal, 0, PALETTE_SIZE);
setPalette(pal);
}
-//
-// palette Animation
-//
-// FIXME: the effect is different from the original
-//
-void Gfx::animatePalette() {
-// printf("Gfx::animatePalette()\n");
- byte tmp[3];
+
+
+void Gfx::animatePalette() {
for (uint16 i = 0; i < 4; i++) {
@@ -170,32 +250,7 @@ void Gfx::animatePalette() {
_palettefx[i]._timer = 0; // reset timer
- if (_palettefx[i]._flags & 2) { // forward
-
- tmp[0] = _palette[_palettefx[i]._first * 3];
- tmp[1] = _palette[_palettefx[i]._first * 3 + 1];
- tmp[2] = _palette[_palettefx[i]._first * 3 + 2];
-
- memmove(_palette+_palettefx[i]._first*3, _palette+(_palettefx[i]._first+1)*3, (_palettefx[i]._last - _palettefx[i]._first)*3);
-
- _palette[_palettefx[i]._last * 3] = tmp[0];
- _palette[_palettefx[i]._last * 3 + 1] = tmp[1];
- _palette[_palettefx[i]._last * 3 + 2] = tmp[2];
-
- } else { // backward
-
- tmp[0] = _palette[_palettefx[i]._last * 3];
- tmp[1] = _palette[_palettefx[i]._last * 3 + 1];
- tmp[2] = _palette[_palettefx[i]._last * 3 + 2];
-
- memmove(_palette+(_palettefx[i]._first+1)*3, _palette+_palettefx[i]._first*3, (_palettefx[i]._last - _palettefx[i]._first)*3);
-
- _palette[_palettefx[i]._first * 3] = tmp[0];
- _palette[_palettefx[i]._first * 3 + 1] = tmp[1];
- _palette[_palettefx[i]._first * 3 + 2] = tmp[2];
-
- }
-
+ _palette.rotate(_palettefx[i]._first, _palettefx[i]._last, (_palettefx[i]._flags & 2) != 0);
}
setPalette(_palette);
@@ -203,39 +258,9 @@ void Gfx::animatePalette() {
return;
}
-void Gfx::makeGrayscalePalette(Palette pal) {
-
- for (uint16 i = 0; i < BASE_PALETTE_COLORS; i++) {
- byte max;
-
- max = MAX(_palette[i*3+1], _palette[i*3+2]);
- max = MAX(max, _palette[i*3]);
-
- pal[i*3] = max;
- pal[i*3+1] = max;
- pal[i*3+2] = max;
- }
-
- return;
-}
-
-void Gfx::fadePalette(Palette pal, Palette target, uint step) {
-
- if (step == 0)
- return;
-
- for (uint16 i = 0; i < BASE_PALETTE_COLORS * 3; i++) {
- if (pal[i] == target[i]) continue;
- if (pal[i] < target[i])
- pal[i] = CLIP(pal[i] + step, (uint)0, (uint)target[i]);
- else
- pal[i] = CLIP(pal[i] - step, (uint)target[i], (uint)255);
- }
- return;
-}
void Gfx::setHalfbriteMode(bool enable) {
#ifdef HALFBRITE
@@ -255,15 +280,14 @@ void Gfx::setHalfbriteMode(bool enable) {
}
void Gfx::updateScreen() {
-// printf("Gfx::updateScreen()\n");
- g_system->copyRectToScreen(_buffers[kBitFront], _vm->_screenWidth, 0, 0, _vm->_screenWidth, _vm->_screenHeight);
+ g_system->copyRectToScreen((const byte*)_buffers[kBitFront]->pixels, _buffers[kBitFront]->pitch, _screenX, _screenY, _vm->_screenWidth, _vm->_screenHeight);
g_system->updateScreen();
return;
}
void Gfx::swapBuffers() {
- byte *temp = _buffers[kBitFront];
+ Graphics::Surface *temp = _buffers[kBitFront];
_buffers[kBitFront] = _buffers[kBitBack];
_buffers[kBitBack] = temp;
updateScreen();
@@ -275,7 +299,7 @@ void Gfx::swapBuffers() {
// graphic primitives
//
void Gfx::clearScreen(Gfx::Buffers buffer) {
- memset(_buffers[buffer], 0, _vm->_screenSize);
+ memset(_buffers[buffer]->pixels, 0, _vm->_screenSize);
if (buffer == kBitFront) updateScreen();
@@ -284,24 +308,21 @@ void Gfx::clearScreen(Gfx::Buffers buffer) {
void Gfx::copyScreen(Gfx::Buffers srcbuffer, Gfx::Buffers dstbuffer) {
- memcpy(_buffers[dstbuffer], _buffers[srcbuffer], _vm->_screenSize);
-
-// if (dstbuffer == kBitFront) updateScreen();
+ memcpy(_buffers[dstbuffer]->pixels, _buffers[srcbuffer]->pixels, _vm->_screenSize);
return;
}
void Gfx::floodFill(Gfx::Buffers buffer, const Common::Rect& r, byte color) {
-// printf("Gfx::floodFill(%i, %i, %i, %i, %i)\n", color, left, top, right, bottom);
- byte *d = _buffers[buffer] + (r.left + r.top * _vm->_screenWidth);
+ byte *d = (byte*)_buffers[buffer]->getBasePtr(r.left, r.top);
uint16 w = r.width() + 1;
uint16 h = r.height() + 1;
for (uint16 i = 0; i < h; i++) {
memset(d, color, w);
- d += _vm->_screenWidth;
+ d += _backgroundWidth;
}
return;
@@ -325,7 +346,7 @@ void Gfx::screenClip(Common::Rect& r, Common::Point& p) {
}
-void Gfx::flatBlit(const Common::Rect& r, byte *data, Gfx::Buffers buffer) {
+void Gfx::flatBlit(const Common::Rect& r, byte *data, Gfx::Buffers buffer, byte transparentColor) {
Common::Point dp;
Common::Rect q(r);
@@ -333,17 +354,22 @@ void Gfx::flatBlit(const Common::Rect& r, byte *data, Gfx::Buffers buffer) {
screenClip(q, dp);
byte *s = data + q.left + q.top * r.width();
- byte *d = _buffers[buffer] + dp.x + dp.y * _vm->_screenWidth;
+ byte *d = (byte*)_buffers[buffer]->getBasePtr(dp.x, dp.y);
+
+ uint sPitch = r.width() - q.width();
+ uint dPitch = _backgroundWidth - q.width();
for (uint16 i = q.top; i < q.bottom; i++) {
for (uint16 j = q.left; j < q.right; j++) {
- if (*s != 0) *d = *s;
+ if (*s != transparentColor)
+ *d = *s;
+
s++;
d++;
}
- s += (r.width() - q.width());
- d += (_vm->_screenWidth - q.width());
+ s += sPitch;
+ d += dPitch;
}
return;
@@ -358,182 +384,91 @@ void Gfx::blit(const Common::Rect& r, uint16 z, byte *data, Gfx::Buffers buffer)
screenClip(q, dp);
byte *s = data + q.left + q.top * r.width();
- byte *d = _buffers[buffer] + dp.x + dp.y * _vm->_screenWidth;
+ byte *d = (byte*)_buffers[buffer]->getBasePtr(dp.x, dp.y);
- for (uint16 i = q.top; i < q.bottom; i++) {
+ uint sPitch = r.width() - q.width();
+ uint dPitch = _backgroundWidth - q.width();
- uint16 n = dp.x % 4;
- byte *m = _buffers[kMask0] + dp.x/4 + (dp.y + i - q.top)*_vm->_screenMaskWidth;
+ for (uint16 i = 0; i < q.height(); i++) {
- for (uint16 j = q.left; j < q.right; j++) {
+ for (uint16 j = 0; j < q.width(); j++) {
if (*s != 0) {
- uint16 v = ((3 << (n << 1)) & *m) >> (n << 1);
+ byte v = _depthMask->getValue(dp.x + j, dp.y + i);
if (z >= v) *d = *s;
}
- n++;
- if (n==4) m++;
- n &= 0x3;
-
s++;
d++;
}
- s += (r.width() - q.right + q.left);
- d += (_vm->_screenWidth - q.right + q.left);
+ s += sPitch;
+ d += dPitch;
}
return;
}
-
-void jobDisplayLabel(void *parm, Job *j) {
-
- Label *label = (Label*)parm;
- debugC(9, kDebugJobs, "jobDisplayLabel (%p)", (const void*) label);
-
- if (label->_cnv._width == 0)
+void Gfx::drawLabel(Label &label) {
+ if (label._text == 0)
return;
- _vm->_gfx->flatBlitCnv(&label->_cnv, _vm->_gfx->_labelPosition[0].x, _vm->_gfx->_labelPosition[0].y, Gfx::kBitBack);
-
- return;
-}
-
-void jobEraseLabel(void *parm, Job *j) {
- Label *label = (Label*)parm;
-
- debugC(9, kDebugJobs, "jobEraseLabel (%p)", (const void*) label);
-
- int16 _si, _di;
-
- if (_vm->_activeItem._id != 0) {
- _si = _vm->_mousePos.x + 16 - label->_cnv._width/2;
- _di = _vm->_mousePos.y + 34;
- } else {
- _si = _vm->_mousePos.x + 8 - label->_cnv._width/2;
- _di = _vm->_mousePos.y + 21;
- }
-
- if (_si < 0) _si = 0;
- if (_di > 190) _di = 190;
-
- if (label->_cnv._width + _si > _vm->_screenWidth)
- _si = _vm->_screenWidth - label->_cnv._width;
-
- Common::Rect r(label->_cnv._width, label->_cnv._height);
- r.moveTo(_vm->_gfx->_labelPosition[1]);
- _vm->_gfx->restoreBackground(r);
-
- _vm->_gfx->_labelPosition[1] = _vm->_gfx->_labelPosition[0];
- _vm->_gfx->_labelPosition[0].x = _si;
- _vm->_gfx->_labelPosition[0].y = _di;
-
- return;
-}
-
-void Gfx::initMouse(uint16 arg_0) {
-
- _mouseComposedArrow = _vm->_disk->loadPointer();
-
- byte temp[MOUSEARROW_WIDTH*MOUSEARROW_HEIGHT];
- memcpy(temp, _mouseArrow, MOUSEARROW_WIDTH*MOUSEARROW_HEIGHT);
-
- uint16 k = 0;
- for (uint16 i = 0; i < 4; i++) {
- for (uint16 j = 0; j < 64; j++) _mouseArrow[k++] = temp[i + j * 4];
- }
-
- return;
-}
-
-
-void Gfx::setMousePointer(int16 index) {
-
- if (index == kCursorArrow) { // standard mouse pointer
-
- g_system->setMouseCursor(_mouseArrow, MOUSEARROW_WIDTH, MOUSEARROW_HEIGHT, 0, 0, 0);
- g_system->showMouse(true);
-
- } else {
- // inventory item pointer
- byte *v8 = _mouseComposedArrow->_data0;
- // FIXME: destination offseting is not clear
- byte* s = _vm->_char._objs->getFramePtr(getInventoryItemIndex(index));
- byte* d = v8 + 7 + MOUSECOMBO_WIDTH * 7;
-
- for (uint32 i = 0; i < INVENTORYITEM_HEIGHT; i++) {
- memcpy(d, s, INVENTORYITEM_WIDTH);
-
- s += INVENTORYITEM_PITCH;
- d += MOUSECOMBO_WIDTH;
- }
-
- g_system->setMouseCursor(v8, MOUSECOMBO_WIDTH, MOUSECOMBO_HEIGHT, 0, 0, 0);
- }
-
- return;
+ flatBlitCnv(&label._cnv, label._pos.x, label._pos.y, Gfx::kBitBack);
}
-
-
//
// Cnv management
//
-void Gfx::flatBlitCnv(Cnv *cnv, uint16 frame, int16 x, int16 y, Gfx::Buffers buffer) {
+void Gfx::flatBlitCnv(Frames *cnv, uint16 frame, int16 x, int16 y, Gfx::Buffers buffer) {
- StaticCnv scnv;
+ Graphics::Surface scnv;
+ Common::Rect r;
- scnv._width = cnv->_width;
- scnv._height = cnv->_height;
- scnv._data0 = cnv->getFramePtr(frame);
- scnv._data1 = NULL; // _questioner->field_8[v60->_mood & 0xF];
+ cnv->getRect(frame, r);
+
+ scnv.w = r.width();
+ scnv.h = r.height();
+ scnv.pixels = cnv->getData(frame);
flatBlitCnv(&scnv, x, y, buffer);
}
-void Gfx::flatBlitCnv(StaticCnv *cnv, int16 x, int16 y, Gfx::Buffers buffer) {
- Common::Rect r(cnv->_width, cnv->_height);
+void Gfx::flatBlitCnv(Graphics::Surface *cnv, int16 x, int16 y, Gfx::Buffers buffer) {
+ Common::Rect r(cnv->w, cnv->h);
r.moveTo(x, y);
- flatBlit(r, cnv->_data0, buffer);
+ flatBlit(r, (byte*)cnv->pixels, buffer, 0);
return;
}
-void Gfx::blitCnv(StaticCnv *cnv, int16 x, int16 y, uint16 z, Gfx::Buffers buffer) {
- Common::Rect r(cnv->_width, cnv->_height);
+void Gfx::blitCnv(Graphics::Surface *cnv, int16 x, int16 y, uint16 z, Gfx::Buffers buffer) {
+ Common::Rect r(cnv->w, cnv->h);
r.moveTo(x, y);
- blit(r, z, cnv->_data0, buffer);
+ blit(r, z, (byte*)cnv->pixels, buffer);
return;
}
void Gfx::backupDoorBackground(DoorData *data, int16 x, int16 y) {
-
- byte *s = _buffers[kBit2] + x + y * _vm->_screenWidth;
- byte *d = data->_background;
-
- for (uint16 i = 0; i < data->_cnv->_height ; i++) {
- memcpy(d, s, data->_cnv->_width);
-
- s += _vm->_screenWidth;
- d += data->_cnv->_width;
- }
-
+ byte *s = (byte*)_buffers[kBit2]->getBasePtr(x, y);
+ Common::Rect r;
+ data->_cnv->getRect(0, r);
+ copyRect(r.width(), r.height(), data->_background, r.width(), s,_backgroundWidth);
return;
}
void Gfx::backupGetBackground(GetData *data, int16 x, int16 y) {
- byte *t = data->_cnv->_data0;
- byte *s = _buffers[kBitBack] + x + y * _vm->_screenWidth;
+ byte *t = (byte*)data->_cnv->pixels;
+ byte *s = (byte*)_buffers[kBitBack]->getBasePtr(x, y);
byte *d = data->_backup;
- for (uint16 i = 0; i < data->_cnv->_height ; i++) {
- for (uint16 j = 0; j < data->_cnv->_width ; j++) {
+ uint pitch = _backgroundWidth - data->_cnv->w;
+
+ for (uint16 i = 0; i < data->_cnv->h ; i++) {
+ for (uint16 j = 0; j < data->_cnv->w ; j++) {
*d = (*t) ? *s : 0;
d++;
@@ -541,7 +476,7 @@ void Gfx::backupGetBackground(GetData *data, int16 x, int16 y) {
s++;
}
- s += (_vm->_screenWidth - data->_cnv->_width);
+ s += pitch;
}
return;
@@ -550,12 +485,14 @@ void Gfx::backupGetBackground(GetData *data, int16 x, int16 y) {
//
// restores background according to specified frame
//
-void Gfx::restoreDoorBackground(StaticCnv *cnv, const Common::Rect& r, byte* background) {
+void Gfx::restoreDoorBackground(const Common::Rect& r, byte *data, byte* background) {
- byte *t = cnv->_data0;
+ byte *t = data;
byte *s = background;
- byte *d0 = _buffers[kBitBack] + r.left + r.top * _vm->_screenWidth;
- byte *d1 = _buffers[kBit2] + r.left + r.top * _vm->_screenWidth;
+ byte *d0 = (byte*)_buffers[kBitBack]->getBasePtr(r.left, r.top);
+ byte *d1 = (byte*)_buffers[kBit2]->getBasePtr(r.left, r.top);
+
+ uint pitch = _backgroundWidth - r.width();
for (uint16 i = 0; i < r.height() ; i++) {
for (uint16 j = 0; j < r.width() ; j++) {
@@ -570,8 +507,8 @@ void Gfx::restoreDoorBackground(StaticCnv *cnv, const Common::Rect& r, byte* bac
s++;
}
- d0 += (_vm->_screenWidth - r.width());
- d1 += (_vm->_screenWidth - r.width());
+ d0 += pitch;
+ d1 += pitch;
}
@@ -584,47 +521,16 @@ void Gfx::restoreDoorBackground(StaticCnv *cnv, const Common::Rect& r, byte* bac
//
void Gfx::restoreGetBackground(const Common::Rect& r, byte *data) {
- StaticCnv cnv;
-
- cnv._data0 = data;
- cnv._data1 = NULL;
- cnv._width = r.width();
- cnv._height = r.height();
-
- flatBlitCnv(&cnv, r.left, r.top, kBitBack);
- flatBlitCnv(&cnv, r.left, r.top, kBit2);
+ flatBlit(r, data, kBitBack, 0);
+ flatBlit(r, data, kBit2, 0);
return;
}
-void Gfx::makeCnvFromString(StaticCnv *cnv, char *text) {
- assert(_font == _fonts[kFontLabel]);
-
- if (_vm->getPlatform() == Common::kPlatformAmiga) {
- cnv->_width = _font->getStringWidth(text) + 16;
- cnv->_height = 10;
- cnv->_data0 = (byte*)malloc(cnv->_width * cnv->_height);
- memset(cnv->_data0, 0, cnv->_width * cnv->_height);
-
- _font->setColor(7);
- _font->drawString(cnv->_data0 + 1, cnv->_width, text);
- _font->drawString(cnv->_data0 + 1 + cnv->_width * 2, cnv->_width, text);
- _font->drawString(cnv->_data0 + cnv->_width, cnv->_width, text);
- _font->drawString(cnv->_data0 + 2 + cnv->_width, cnv->_width, text);
- _font->setColor(1);
- _font->drawString(cnv->_data0 + 1 + cnv->_width, cnv->_width, text);
- } else {
- cnv->_width = _font->getStringWidth(text);
- cnv->_height = _font->height();
- cnv->_data0 = (byte*)malloc(cnv->_width * cnv->_height);
- memset(cnv->_data0, 0, cnv->_width * cnv->_height);
- _font->drawString(cnv->_data0, cnv->_width, text);
- }
-}
void Gfx::displayString(uint16 x, uint16 y, const char *text, byte color) {
- byte *dst = _buffers[kBitFront] + x + y*_vm->_screenWidth;
+ byte *dst = (byte*)_buffers[kBitFront]->getBasePtr(x, y);
_font->setColor(color);
_font->drawString(dst, _vm->_screenWidth, text);
}
@@ -635,7 +541,6 @@ void Gfx::displayCenteredString(uint16 y, const char *text) {
}
bool Gfx::displayWrappedString(char *text, uint16 x, uint16 y, byte color, int16 wrapwidth) {
-// printf("Gfx::displayWrappedString(%s, %i, %i, %i, %i)...", text, x, y, color, wrapwidth);
uint16 lines = 0;
bool rv = false;
@@ -676,8 +581,6 @@ bool Gfx::displayWrappedString(char *text, uint16 x, uint16 y, byte color, int16
text = Common::ltrim(text);
}
-// printf("done\n");
-
return rv;
}
@@ -721,9 +624,9 @@ void Gfx::getStringExtent(char *text, uint16 maxwidth, int16* width, int16* heig
}
-void Gfx::setFont(Fonts name) {
- assert(name < 3);
- _font = _fonts[name];
+void Gfx::setFont(Font *font) {
+ assert(font);
+ _font = font;
}
@@ -737,107 +640,55 @@ void Gfx::restoreBackground(const Common::Rect& r) {
if (left < 0) left = 0;
if (top < 0) top = 0;
- if (left >= _vm->_screenWidth) return;
- if (top >= _vm->_screenHeight) return;
+ if (left >= _backgroundWidth) return;
+ if (top >= _backgroundHeight) return;
- if (left+width >= _vm->_screenWidth) width = _vm->_screenWidth - left;
- if (top+height >= _vm->_screenHeight) height = _vm->_screenHeight - top;
+ if (left+width >= _backgroundWidth) width = _backgroundWidth - left;
+ if (top+height >= _backgroundHeight) height = _backgroundHeight - top;
Common::Rect q(width, height);
q.moveTo(left, top);
- copyRect(
- kBitBack,
- q,
- _buffers[kBit2] + q.left + q.top * _vm->_screenWidth,
- _vm->_screenWidth
- );
-
- return;
-}
-
-void Gfx::freeStaticCnv(StaticCnv *cnv) {
-// printf("free_static_cnv()\n");
-
- if (!cnv) return;
-
- if (!cnv || !cnv->_data0) return;
- free(cnv->_data0);
- cnv->_data0 = NULL;
+ copyRect(kBitBack, q, (byte*)_buffers[kBit2]->getBasePtr(q.left, q.top), _backgroundWidth);
return;
}
-void Gfx::setBackground(byte *background) {
- memcpy(_buffers[kBitBack], background, _vm->_screenSize);
- copyScreen(kBitBack, kBit2);
-}
+void Gfx::setBackground(Graphics::Surface *surface) {
+ _buffers[kBit2] = surface;
-void Gfx::setMask(byte *mask) {
- memcpy(_buffers[kMask0], mask, _vm->_screenMaskSize);
+ initBuffers(surface->w, surface->h);
+ copyScreen(kBit2, kBitBack);
}
-
-
-void Gfx::copyRect(Gfx::Buffers dstbuffer, const Common::Rect& r, byte *src, uint16 pitch) {
-
- byte *d = _buffers[dstbuffer] + r.left + _vm->_screenWidth * r.top;
- byte *s = src;
-
- for (uint16 _si = 0; _si < r.height(); _si++) {
- memcpy(d, s, r.width());
-
- s += pitch;
- d += _vm->_screenWidth;
- }
-
-
+void Gfx::setMask(MaskBuffer *buffer) {
+ _depthMask = buffer;
}
+void Gfx::copyRect(uint width, uint height, byte *dst, uint dstPitch, byte *src, uint srcPitch) {
-void Gfx::grabRect(byte *dst, const Common::Rect& r, Gfx::Buffers srcbuffer, uint16 pitch) {
-
- byte *s = _buffers[srcbuffer] + r.left + _vm->_screenWidth * r.top;
-
- for (uint16 i = 0; i < r.height(); i++) {
- memcpy(dst, s, r.width());
+ for (uint16 _si = 0; _si < height; _si++) {
+ memcpy(dst, src, width);
- s += _vm->_screenWidth;
- dst += pitch;
+ src += srcPitch;
+ dst += dstPitch;
}
return;
}
-/*
- the following 3 routines are hacks for Nippon Safes coming from the original code,
- so they shouldn't be modified when adding support for other games
-*/
-
-void Gfx::plotMaskPixel(uint16 x, uint16 y, byte color) {
-
- uint16 _ax = x + y * _vm->_screenWidth;
- _buffers[kMask0][_ax >> 2] &= ~(3 << ((_ax & 3) << 1));
-
+void Gfx::copyRect(Gfx::Buffers dstbuffer, const Common::Rect& r, byte *src, uint16 pitch) {
+ byte *d = (byte*)_buffers[dstbuffer]->getBasePtr(r.left, r.top);
+ copyRect(r.width(), r.height(), d, _backgroundWidth, src, pitch);
return;
}
-void Gfx::fillMaskRect(const Common::Rect& r, byte color) {
-
- uint16 _di = r.left/4 + r.top * _vm->_screenMaskWidth;
-
- for (uint16 _si = r.top; _si < r.bottom; _si++) {
- memset(&_buffers[kMask0][_di], color, r.width()/4+1);
- _di += _vm->_screenMaskWidth;
- }
- return;
-}
-void Gfx::intGrottaHackMask() {
- memset(_buffers[kMask0] + 3600, 0, 3600);
- _bgLayers[1] = 500;
+void Gfx::grabRect(byte *dst, const Common::Rect& r, Gfx::Buffers srcbuffer, uint16 pitch) {
+ byte *s = (byte*)_buffers[srcbuffer]->getBasePtr(r.left, r.top);
+ copyRect(r.width(), r.height(), dst, pitch, s, _backgroundWidth);
return;
}
@@ -856,23 +707,26 @@ Gfx::Gfx(Parallaction* vm) :
g_system->beginGFXTransaction();
g_system->initSize(_vm->_screenWidth, _vm->_screenHeight);
+ _vm->initCommonGFX(_vm->getGameType() == GType_BRA);
g_system->endGFXTransaction();
- _buffers[kBitFront] = (byte*)malloc(_vm->_screenSize);
- _buffers[kBitBack] = (byte*)malloc(_vm->_screenSize);
- _buffers[kBit2] = (byte*)malloc(_vm->_screenSize);
- _buffers[kMask0] = (byte*)malloc(_vm->_screenMaskWidth * _vm->_screenHeight);
+ _buffers[kBit2] = 0;
+ _depthMask = 0;
+
+ _buffers[kBitFront] = 0;
+ _buffers[kBitBack] = 0;
+
+ initBuffers(_vm->_screenWidth, _vm->_screenHeight);
+
+ setPalette(_palette);
- setBlackPalette();
+ _screenX = 0;
+ _screenY = 0;
_bgLayers[0] = _bgLayers[1] = _bgLayers[2] = _bgLayers[3] = 0;
- memset(_palette, 0, sizeof(_palette));
memset(_palettefx, 0, sizeof(_palettefx));
- initMouse( 0 );
- initFonts();
-
_halfbrite = false;
_font = NULL;
@@ -882,19 +736,48 @@ Gfx::Gfx(Parallaction* vm) :
Gfx::~Gfx() {
- free(_buffers[kMask0]);
- free(_buffers[kBitFront]);
- free(_buffers[kBitBack]);
- free(_buffers[kBit2]);
+ freeBuffers();
- delete _fonts[kFontDialogue];
- delete _fonts[kFontLabel];
- delete _fonts[kFontMenu];
+ return;
+}
- freeStaticCnv(_mouseComposedArrow);
- delete _mouseComposedArrow;
+void Gfx::initBuffers(int w, int h) {
- return;
+ _backgroundWidth = w;
+ _backgroundHeight = h;
+
+ if (!_buffers[kBitFront]) {
+ _buffers[kBitFront] = new Graphics::Surface;
+ }
+
+ if (!_buffers[kBitBack]) {
+ _buffers[kBitBack] = new Graphics::Surface;
+ }
+
+ if (_buffers[kBitFront]->w != w || _buffers[kBitFront]->h != h) {
+ _buffers[kBitFront]->create(w, h, 1);
+ }
+
+ if (_buffers[kBitBack]->w != w || _buffers[kBitBack]->h != h) {
+ _buffers[kBitBack]->create(w, h, 1);
+ }
+
+}
+
+void Gfx::freeBuffers() {
+
+ if (_buffers[kBitFront]) {
+ _buffers[kBitFront]->free();
+ delete _buffers[kBitFront];
+ }
+
+ if (_buffers[kBitBack]) {
+ _buffers[kBitBack]->free();
+ delete _buffers[kBitBack];
+ }
+
+ _buffers[kBitFront] = 0;
+ _buffers[kBitBack] = 0;
}
diff --git a/engines/parallaction/graphics.h b/engines/parallaction/graphics.h
index f518bd6625..9f1101efa2 100644
--- a/engines/parallaction/graphics.h
+++ b/engines/parallaction/graphics.h
@@ -29,6 +29,7 @@
#include "common/rect.h"
#include "common/stream.h"
+#include "graphics/surface.h"
#include "parallaction/defs.h"
@@ -36,25 +37,6 @@
namespace Parallaction {
-#define BASE_PALETTE_COLORS 32
-#define FIRST_BASE_COLOR 0
-#define LAST_BASE_COLOR (FIRST_BASE_COLOR+BASE_PALETTE_COLORS-1)
-
-#define EHB_PALETTE_COLORS 32 // extra half-brite colors for amiga
-#define FIRST_EHB_COLOR (LAST_BASE_COLOR+1)
-#define LAST_EHB_COLOR (FIRST_EHB_COLOR+EHB_PALETTE_COLORS-1)
-
-#define PALETTE_COLORS (BASE_PALETTE_COLORS+EHB_PALETTE_COLORS)
-
-#define BASE_PALETTE_SIZE BASE_PALETTE_COLORS*3
-#define PALETTE_SIZE PALETTE_COLORS*3
-
-#define MOUSEARROW_WIDTH 16
-#define MOUSEARROW_HEIGHT 16
-
-#define MOUSECOMBO_WIDTH 32 // sizes for cursor + selected inventory item
-#define MOUSECOMBO_HEIGHT 32
-
#include "common/pack-start.h" // START STRUCT PACKING
struct PaletteFxRange {
@@ -90,19 +72,19 @@ public:
};
-struct StaticCnv {
- uint16 _width; //
- uint16 _height; //
- byte* _data0; // bitmap
- byte* _data1; // unused
- StaticCnv() {
- _width = _height = 0;
- _data0 = _data1 = NULL;
- }
+struct Frames {
+
+ virtual uint16 getNum() = 0;
+ virtual byte* getData(uint16 index) = 0;
+ virtual void getRect(uint16 index, Common::Rect &r) = 0;
+
+ virtual ~Frames() { }
+
};
-struct Cnv {
+
+struct Cnv : public Frames {
uint16 _count; // # of frames
uint16 _width; //
uint16 _height; //
@@ -129,6 +111,21 @@ public:
return NULL;
return &_data[index * _width * _height];
}
+
+ uint16 getNum() {
+ return _count;
+ }
+
+ byte *getData(uint16 index) {
+ return getFramePtr(index);
+ }
+
+ void getRect(uint16 index, Common::Rect &r) {
+ r.left = 0;
+ r.top = 0;
+ r.setWidth(_width);
+ r.setHeight(_height);
+ }
};
@@ -138,31 +135,83 @@ class Parallaction;
struct DoorData;
struct GetData;
+struct Label;
+
+struct MaskBuffer {
+ // handles a 2-bit depth buffer used for z-buffering
+
+ uint16 w;
+ uint16 internalWidth;
+ uint16 h;
+ uint size;
+ byte *data;
+
+public:
+ MaskBuffer() : w(0), internalWidth(0), h(0), size(0), data(0) {
+ }
+
+ void create(uint16 width, uint16 height) {
+ w = width;
+ internalWidth = w >> 2;
+ h = height;
+ size = (internalWidth * h);
+ data = (byte*)calloc(size, 1);
+ }
+
+ void free() {
+ if (data)
+ ::free(data);
+ data = 0;
+ w = 0;
+ h = 0;
+ internalWidth = 0;
+ size = 0;
+ }
+
+ inline byte getValue(uint16 x, uint16 y) {
+ byte m = data[(x >> 2) + y * internalWidth];
+ uint n = (x & 3) << 1;
+ return ((3 << n) & m) >> n;
+ }
-enum Fonts {
- kFontDialogue = 0,
- kFontLabel = 1,
- kFontMenu = 2
};
-class Gfx {
+class Palette {
+
+ byte _data[768];
+ uint _colors;
+ uint _size;
+ bool _hb;
public:
- typedef byte Palette[PALETTE_SIZE];
+ Palette();
+ Palette(const Palette &pal);
+
+ void clone(const Palette &pal);
+
+ void makeBlack();
+ void setEntries(byte* data, uint first, uint num);
+ void setEntry(uint index, int red, int green, int blue);
+ void makeGrayscale();
+ void fadeTo(const Palette& target, uint step);
+ uint fillRGBA(byte *rgba);
+
+ void rotate(uint first, uint last, bool forward);
+};
+
+class Gfx {
+public:
enum Buffers {
// bit buffers
kBitFront,
kBitBack,
- kBit2,
- // mask buffers
- kMask0
+ kBit2
};
public:
- void screenClip(Common::Rect& r, Common::Point& p);
- // dialogue and text
+ // balloons and text
void drawBalloon(const Common::Rect& r, uint16 arg_8);
void displayString(uint16 x, uint16 y, const char *text, byte color);
void displayCenteredString(uint16 y, const char *text);
@@ -170,82 +219,73 @@ public:
uint16 getStringWidth(const char *text);
void getStringExtent(char *text, uint16 maxwidth, int16* width, int16* height);
- // cnv management
- void makeCnvFromString(StaticCnv *cnv, char *text);
- void freeStaticCnv(StaticCnv *cnv);
+ void drawLabel(Label &label);
+
+ // cut/paste
+ void flatBlitCnv(Graphics::Surface *cnv, int16 x, int16 y, Gfx::Buffers buffer);
+ void flatBlitCnv(Frames *cnv, uint16 frame, int16 x, int16 y, Gfx::Buffers buffer);
+ void blitCnv(Graphics::Surface *cnv, int16 x, int16 y, uint16 z, Gfx::Buffers buffer);
+ void restoreBackground(const Common::Rect& r);
void backupDoorBackground(DoorData *data, int16 x, int16 y);
+ void restoreDoorBackground(const Common::Rect& r, byte *data, byte* background);
void backupGetBackground(GetData *data, int16 x, int16 y);
void restoreGetBackground(const Common::Rect& r, byte *data);
- void restoreDoorBackground(StaticCnv *cnv, const Common::Rect& r, byte* background);
-
- // location
- void setBackground(byte *background);
- void setMask(byte *mask);
- int16 queryMask(int16 v);
- void intGrottaHackMask();
- void restoreBackground(const Common::Rect& r);
- // intro
- void fillMaskRect(const Common::Rect& r, byte color);
- void plotMaskPixel(uint16 x, uint16 y, byte color);
- // low level
- void swapBuffers();
- void updateScreen();
+ // low level surfaces
void clearScreen(Gfx::Buffers buffer);
void copyScreen(Gfx::Buffers srcbuffer, Gfx::Buffers dstbuffer);
void copyRect(Gfx::Buffers dstbuffer, const Common::Rect& r, byte *src, uint16 pitch);
void grabRect(byte *dst, const Common::Rect& r, Gfx::Buffers srcbuffer, uint16 pitch);
void floodFill(Gfx::Buffers buffer, const Common::Rect& r, byte color);
- // NOTE: flatBlitCnv used to have an additional unused parameter,
- // that was always the _data1 member of the StaticCnv parameter.
- // DOS version didn't make use of it, but it is probably needed for Amiga stuff.
- void flatBlitCnv(StaticCnv *cnv, int16 x, int16 y, Gfx::Buffers buffer);
- void blitCnv(StaticCnv *cnv, int16 x, int16 y, uint16 z, Gfx::Buffers buffer);
- void flatBlitCnv(Cnv *cnv, uint16 frame, int16 x, int16 y, Gfx::Buffers buffer);
-
-
// palette
- void setPalette(Palette palette, uint32 first = FIRST_BASE_COLOR, uint32 num = BASE_PALETTE_COLORS);
+ void setPalette(Palette palette);
void setBlackPalette();
void animatePalette();
- void fadePalette(Palette palette, Palette target, uint step); // fades palette to target palette, with specified step
- void makeGrayscalePalette(Palette palette); // transform palette into black and white
// amiga specific
void setHalfbriteMode(bool enable);
+ // misc
+ int16 queryMask(int16 v);
+ void setFont(Font* font);
+ void swapBuffers();
+ void updateScreen();
+ void setBackground(Graphics::Surface *surf);
+ void setMask(MaskBuffer *buffer);
+
// init
Gfx(Parallaction* vm);
virtual ~Gfx();
- void setMousePointer(int16 index);
-
- void initFonts();
- void setFont(Fonts name);
public:
- Common::Point _labelPosition[2];
uint16 _bgLayers[4];
PaletteFxRange _palettefx[6];
Palette _palette;
+ int _backgroundWidth;
+ int _backgroundHeight;
+
+ uint _screenX; // scrolling position
+ uint _screenY;
+
protected:
Parallaction* _vm;
- static byte * _buffers[NUM_BUFFERS];
- static byte _mouseArrow[256];
- StaticCnv *_mouseComposedArrow;
+ Graphics::Surface *_buffers[NUM_BUFFERS];
+ MaskBuffer *_depthMask;
Font *_font;
- Font *_fonts[3];
bool _halfbrite;
protected:
- byte mapChar(byte c);
- void flatBlit(const Common::Rect& r, byte *data, Gfx::Buffers buffer);
+ void initBuffers(int w, int h);
+ void freeBuffers();
+
+ void copyRect(uint width, uint height, byte *dst, uint dstPitch, byte *src, uint srcPitch);
+ void flatBlit(const Common::Rect& r, byte *data, Gfx::Buffers buffer, byte transparentColor);
void blit(const Common::Rect& r, uint16 z, byte *data, Gfx::Buffers buffer);
- void initBuffers();
- void initMouse(uint16 arg_0);
+ void screenClip(Common::Rect& r, Common::Point& p);
};
@@ -254,3 +294,7 @@ protected:
#endif
+
+
+
+
diff --git a/engines/parallaction/inventory.cpp b/engines/parallaction/inventory.cpp
index c9e74b2074..06d48744be 100644
--- a/engines/parallaction/inventory.cpp
+++ b/engines/parallaction/inventory.cpp
@@ -117,9 +117,12 @@ void drawInventoryItem(uint16 pos, InventoryItem *item) {
uint16 line = pos / INVENTORY_ITEMS_PER_LINE;
uint16 col = pos % INVENTORY_ITEMS_PER_LINE;
+ Common::Rect r;
+ _vm->_char._objs->getRect(0, r);
+
// FIXME: this will end up in a general blit function
- byte* s = _vm->_char._objs->getFramePtr(item->_index);
- byte* d = _buffer + col * INVENTORYITEM_WIDTH + line * _vm->_char._objs->_height * INVENTORY_WIDTH;
+ byte* s = _vm->_char._objs->getData(item->_index);
+ byte* d = _buffer + col * INVENTORYITEM_WIDTH + line * r.height() * INVENTORY_WIDTH;
for (uint32 i = 0; i < INVENTORYITEM_HEIGHT; i++) {
memcpy(d, s, INVENTORYITEM_WIDTH);
@@ -157,7 +160,7 @@ void Parallaction::dropItem(uint16 v) {
bool found = false;
for (uint16 slot = 0; slot < INVENTORY_MAX_ITEMS - 1; slot++) {
- if (v + INVENTORY_FIRST_ITEM == _inventory[slot]._index) {
+ if (v == _inventory[slot]._index) {
found = true;
}
@@ -210,8 +213,10 @@ void highlightInventoryItem(int16 pos, byte color) {
uint16 line = pos / INVENTORY_ITEMS_PER_LINE;
uint16 col = pos % INVENTORY_ITEMS_PER_LINE;
- Common::Rect r(INVENTORYITEM_WIDTH, _vm->_char._objs->_height);
- r.moveTo(col * INVENTORYITEM_WIDTH, line * _vm->_char._objs->_height);
+ Common::Rect r;
+ _vm->_char._objs->getRect(0, r);
+ r.setWidth(INVENTORYITEM_WIDTH);
+ r.moveTo(col * INVENTORYITEM_WIDTH, line * r.height());
drawBorder(r, _buffer, color);
@@ -228,7 +233,7 @@ int16 getInventoryItemIndex(int16 pos) {
-void jobShowInventory(void *parm, Job *j) {
+void Parallaction_ns::jobShowInventory(void *parm, Job *j) {
// printf("job_showInventory()...");
int16 slot = getNumUsedSlots();
@@ -238,19 +243,14 @@ void jobShowInventory(void *parm, Job *j) {
r.moveTo(_invPosition);
- _vm->_gfx->copyRect(
- Gfx::kBitBack,
- r,
- _buffer,
- INVENTORY_WIDTH
- );
+ _gfx->copyRect(Gfx::kBitBack, r, _buffer, INVENTORY_WIDTH);
return;
}
-void jobHideInventory(void *parm, Job *j) {
+void Parallaction_ns::jobHideInventory(void *parm, Job *j) {
// printf("job_hideInventory()\n");
static uint16 count = 0;
@@ -267,7 +267,7 @@ void jobHideInventory(void *parm, Job *j) {
Common::Rect r(INVENTORY_WIDTH, _numInvLines * INVENTORYITEM_HEIGHT);
r.moveTo(_invPosition);
- _vm->_gfx->restoreBackground(r);
+ _gfx->restoreBackground(r);
return;
}
diff --git a/engines/parallaction/inventory.h b/engines/parallaction/inventory.h
index 4a3e07cc97..2ca3559b8f 100644
--- a/engines/parallaction/inventory.h
+++ b/engines/parallaction/inventory.h
@@ -31,8 +31,6 @@
namespace Parallaction {
-struct Cnv;
-
struct InventoryItem {
uint32 _id; // object name (lowest 16 bits are always zero)
uint16 _index; // index to frame in objs file
diff --git a/engines/parallaction/location.cpp b/engines/parallaction/location.cpp
deleted file mode 100644
index 024938074b..0000000000
--- a/engines/parallaction/location.cpp
+++ /dev/null
@@ -1,466 +0,0 @@
-/* ScummVM - Graphic Adventure Engine
- *
- * ScummVM is the legal property of its developers, whose names
- * are too numerous to list here. Please refer to the COPYRIGHT
- * file distributed with this source distribution.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
-
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
-
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * $URL$
- * $Id$
- *
- */
-
-#include "common/stdafx.h"
-
-#include "common/system.h"
-
-#include "parallaction/parallaction.h"
-#include "parallaction/sound.h"
-
-namespace Parallaction {
-
-
-void Parallaction::parseLocation(const char *filename) {
- debugC(1, kDebugLocation, "parseLocation('%s')", filename);
-
- uint16 _si = 1;
- _gfx->setFont(kFontLabel);
-
- Script *_locationScript = _disk->loadLocation(filename);
- _hasLocationSound = false;
-
- fillBuffers(*_locationScript, true);
- while (scumm_stricmp(_tokens[0], "ENDLOCATION")) {
-
- if (!scumm_stricmp(_tokens[0], "LOCATION")) {
- // The parameter for location is 'location.mask'.
- // If mask is not present, then it is assumed
- // that path & mask are encoded in the background
- // bitmap, otherwise a separate .msk file exists.
-
- char *mask = strchr(_tokens[1], '.');
- if (mask) {
- mask[0] = '\0';
- mask++;
- }
-
- // WORKAROUND: the original code erroneously incremented
- // _currentLocationIndex, thus producing inconsistent
- // savegames. This workaround modified the following loop
- // and if-statement, so the code exactly matches the one
- // in Big Red Adventure.
- _currentLocationIndex = -1;
- uint16 _di = 0;
- while (_locationNames[_di][0] != '\0') {
- if (!scumm_stricmp(_locationNames[_di], filename)) {
- _currentLocationIndex = _di;
- }
- _di++;
- }
-
- if (_currentLocationIndex == -1) {
- strcpy(_locationNames[_numLocations], filename);
- _currentLocationIndex = _numLocations;
-
- _numLocations++;
- _locationNames[_numLocations][0] = '\0';
- _localFlags[_numLocations] = 0;
- } else {
- _localFlags[_currentLocationIndex] |= kFlagsVisited; // 'visited'
- }
-
- strcpy(_location._name, _tokens[1]);
- switchBackground(_location._name, mask);
-
- if (_tokens[2][0] != '\0') {
- _char._ani._left = atoi(_tokens[2]);
- _char._ani._top = atoi(_tokens[3]);
- }
-
- if (_tokens[4][0] != '\0') {
- _char._ani._frame = atoi(_tokens[4]);
- }
- }
- if (!scumm_stricmp(_tokens[0], "DISK")) {
- _disk->selectArchive(_tokens[1]);
- }
- if (!scumm_stricmp(_tokens[0], "LOCALFLAGS")) {
- _si = 1; // _localFlagNames[0] = 'visited'
- while (_tokens[_si][0] != '\0') {
- _localFlagNames->addData(_tokens[_si]);
- _si++;
- }
- }
- if (!scumm_stricmp(_tokens[0], "COMMANDS")) {
- parseCommands(*_locationScript, _location._commands);
- }
- if (!scumm_stricmp(_tokens[0], "ACOMMANDS")) {
- parseCommands(*_locationScript, _location._aCommands);
- }
- if (!scumm_stricmp(_tokens[0], "FLAGS")) {
- if ((_localFlags[_currentLocationIndex] & kFlagsVisited) == 0) {
- // only for 1st visit
- _localFlags[_currentLocationIndex] = 0;
- _si = 1;
-
- do {
- byte _al = _localFlagNames->lookup(_tokens[_si]);
- _localFlags[_currentLocationIndex] |= 1 << (_al - 1);
-
- _si++;
- if (scumm_stricmp(_tokens[_si], "|")) break;
- _si++;
- } while (true);
- }
- }
- if (!scumm_stricmp(_tokens[0], "COMMENT")) {
- _location._comment = parseComment(*_locationScript);
- debugC(3, kDebugLocation, "Location comment: '%s'", _location._comment);
- }
- if (!scumm_stricmp(_tokens[0], "ENDCOMMENT")) {
- _location._endComment = parseComment(*_locationScript);
- }
- if (!scumm_stricmp(_tokens[0], "ZONE")) {
- parseZone(*_locationScript, _zones, _tokens[1]);
- }
- if (!scumm_stricmp(_tokens[0], "NODES")) {
- parseWalkNodes(*_locationScript, _location._walkNodes);
- }
- if (!scumm_stricmp(_tokens[0], "ANIMATION")) {
- parseAnimation(*_locationScript, _animations, _tokens[1]);
- }
- if (!scumm_stricmp(_tokens[0], "SOUND")) {
- if (getPlatform() == Common::kPlatformAmiga) {
- strcpy(_locationSound, _tokens[1]);
- _hasLocationSound = true;
- }
- }
- if (!scumm_stricmp(_tokens[0], "MUSIC")) {
- if (getPlatform() == Common::kPlatformAmiga)
- _soundMan->setMusicFile(_tokens[1]);
- }
- fillBuffers(*_locationScript, true);
- }
-
- resolveLocationForwards();
-
- delete _locationScript;
-
- return;
-}
-
-void Parallaction::resolveLocationForwards() {
-
- for (uint16 _si = 0; _forwardedCommands[_si]; _si++) {
- _forwardedCommands[_si]->u._animation = findAnimation(_forwardedAnimationNames[_si]);
- _forwardedCommands[_si] = NULL;
- }
-
- _numForwards = 0;
- return;
-}
-
-
-void Parallaction::freeLocation() {
- debugC(7, kDebugLocation, "freeLocation");
-
- _soundMan->stopSfx(0);
- _soundMan->stopSfx(1);
- _soundMan->stopSfx(2);
- _soundMan->stopSfx(3);
-
- if (_localFlagNames)
- delete _localFlagNames;
-
- // HACK: prevents leakage. A routine like this
- // should allocate memory at all, though.
- if ((_engineFlags & kEngineQuit) == 0) {
- _localFlagNames = new Table(120);
- _localFlagNames->addData("visited");
- }
-
- _location._walkNodes.clear();
-
- // TODO (LIST): helperNode should be rendered useless by the use of a Common::List<>
- // to store Zones and Animations. Right now, it holds a list of Zones to be preserved
- // but that'll pretty meaningless with a single list approach.
- freeZones();
- freeAnimations();
-
- if (_location._comment) {
- free(_location._comment);
- }
- _location._comment = NULL;
-
- _location._commands.clear();
- _location._aCommands.clear();
-
- return;
-}
-
-
-
-void Parallaction::parseWalkNodes(Script& script, WalkNodeList &list) {
-
- fillBuffers(script, true);
- while (scumm_stricmp(_tokens[0], "ENDNODES")) {
-
- if (!scumm_stricmp(_tokens[0], "COORD")) {
-
- WalkNode *v4 = new WalkNode(
- atoi(_tokens[1]) - _char._ani.width()/2,
- atoi(_tokens[2]) - _char._ani.height()
- );
-
- list.push_front(v4);
- }
-
- fillBuffers(script, true);
- }
-
- return;
-
-}
-
-void Parallaction::switchBackground(const char* background, const char* mask) {
-// printf("switchBackground(%s)", name);
-
- Gfx::Palette pal;
-
- uint16 v2 = 0;
- if (!scumm_stricmp(background, "final")) {
- _gfx->clearScreen(Gfx::kBitBack);
- for (uint16 _si = 0; _si <= 93; ) {
- pal[_si] = v2;
- pal[_si+1] = v2;
- pal[_si+2] = v2;
- v2 += 4;
- _si += 3;
- }
-
- g_system->delayMillis(20);
- _gfx->setPalette(pal);
- _gfx->updateScreen();
- }
-
- _disk->loadScenery(background, mask);
-
- return;
-}
-
-extern Zone *_hoverZone;
-extern Job *_jDrawLabel;
-extern Job *_jEraseLabel;
-
-void Parallaction::showSlide(const char *name) {
-
- _disk->loadSlide(name);
- _gfx->setPalette(_gfx->_palette);
- _gfx->copyScreen(Gfx::kBitBack, Gfx::kBitFront);
-
- debugC(1, kDebugLocation, "changeLocation: new background set");
-
- _gfx->setFont(kFontMenu);
-
- _gfx->displayCenteredString(14, _slideText[0]); // displays text on screen
- _gfx->updateScreen();
-
- waitUntilLeftClick();
-
- debugC(2, kDebugLocation, "changeLocation: intro text shown");
-
- return;
-}
-
-/*
- changeLocation handles transitions between locations, and is able to display slides
- between one and the other. The input parameter 'location' exists in some flavours:
-
- 1 - [S].slide.[L]{.[C]}
- 2 - [L]{.[C]}
-
- where:
-
- [S] is the slide to be shown
- [L] is the location to switch to (immediately in case 2, or right after slide [S] in case 1)
- [C] is the character to be selected, and is optional
-
- The routine tells one form from the other by searching for the '.slide.'
-
- NOTE: there exists one script in which [L] is not used in the case 1, but its use
- is commented out, and would definitely crash the current implementation.
-*/
-void Parallaction::changeLocation(char *location) {
- debugC(1, kDebugLocation, "changeLocation(%s)", location);
-
- _soundMan->playLocationMusic(location);
-
- // WORKAROUND: this if-statement has been added to avoid crashes caused by
- // execution of label jobs after a location switch. The other workaround in
- // Parallaction::runGame should have been rendered useless by this one.
- if (_jDrawLabel != NULL) {
- removeJob(_jDrawLabel);
- removeJob(_jEraseLabel);
- _jDrawLabel = NULL;
- _jEraseLabel = NULL;
- }
-
-
- _hoverZone = NULL;
- if (_engineFlags & kEngineBlockInput) {
- changeCursor( kCursorArrow );
- }
-
- _animations.remove(&_char._ani);
-
- freeLocation();
- char buf[100];
- strcpy(buf, location);
-
- Common::StringList list;
- char *tok = strtok(location, ".");
- while (tok) {
- list.push_back(tok);
- tok = strtok(NULL, ".");
- }
-
- if (list.size() < 1 || list.size() > 4)
- error("changeLocation: ill-formed location string '%s'", location);
-
- if (list.size() > 1) {
- if (list[1] == "slide") {
- showSlide(list[0].c_str());
- list.remove_at(0); // removes slide name
- list.remove_at(0); // removes 'slide'
- }
-
- // list is now only [L].{[C]} (see above comment)
- if (list.size() == 2) {
- changeCharacter(list[1].c_str());
- strcpy(_characterName, list[1].c_str());
- }
- }
-
- _animations.push_front(&_char._ani);
-
- strcpy(_saveData1, list[0].c_str());
- parseLocation(list[0].c_str());
-
- _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;
- _location._startPosition.y = -1000;
- _location._startPosition.x = -1000;
- }
-
-
- _gfx->copyScreen(Gfx::kBitBack, Gfx::kBitFront);
- _gfx->copyScreen(Gfx::kBitBack, Gfx::kBit2);
- _gfx->setBlackPalette();
- _gfx->updateScreen();
-
- if (_location._commands.size() > 0) {
- runCommands(_location._commands);
- runJobs();
- _gfx->swapBuffers();
- runJobs();
- _gfx->swapBuffers();
- }
-
- if (_location._comment) {
- doLocationEnterTransition();
- }
-
- runJobs();
- _gfx->swapBuffers();
-
- _gfx->setPalette(_gfx->_palette);
- if (_location._aCommands.size() > 0) {
- runCommands(_location._aCommands);
- }
-
- if (_hasLocationSound)
- _soundMan->playSfx(_locationSound, 0, true);
-
- debugC(1, kDebugLocation, "changeLocation() done");
-
- return;
-
-}
-
-// displays transition before a new location
-//
-// clears screen (in white??)
-// shows location comment (if any)
-// waits for mouse click
-// fades towards game palette
-//
-// THE FINAL PALETTE IS NOT THE SAME AS THE MAIN PALETTE!!!!!!
-//
-void Parallaction::doLocationEnterTransition() {
- debugC(1, kDebugLocation, "doLocationEnterTransition");
-
- if (_localFlags[_currentLocationIndex] & kFlagsVisited) {
- debugC(3, kDebugLocation, "skipping location transition");
- return; // visited
- }
-
- byte pal[PALETTE_SIZE];
- _gfx->makeGrayscalePalette(pal);
- _gfx->setPalette(pal);
-
- jobRunScripts(NULL, NULL);
- jobEraseAnimations(NULL, NULL);
- jobDisplayAnimations(NULL, NULL);
-
- _gfx->setFont(kFontDialogue);
- _gfx->swapBuffers();
- _gfx->copyScreen(Gfx::kBitFront, Gfx::kBitBack);
-
- int16 w, h;
- _gfx->getStringExtent(_location._comment, 130, &w, &h);
-
- Common::Rect r(10 + w, 5 + h);
- r.moveTo(5, 5);
- _gfx->floodFill(Gfx::kBitFront, r, 0);
- r.grow(-1);
- _gfx->floodFill(Gfx::kBitFront, r, 1);
- _gfx->displayWrappedString(_location._comment, 3, 5, 0, 130);
-
- _gfx->updateScreen();
- waitUntilLeftClick();
-
- _gfx->copyScreen(Gfx::kBitBack, Gfx::kBitFront );
-
- // fades maximum intensity palette towards approximation of main palette
- for (uint16 _si = 0; _si<6; _si++) {
- _gfx->fadePalette(pal, _gfx->_palette, 4);
- _gfx->setPalette(pal);
- waitTime( 1 );
- _gfx->updateScreen();
- }
-
- debugC(1, kDebugLocation, "doLocationEnterTransition completed");
-
- return;
-}
-
-} // namespace Parallaction
diff --git a/engines/parallaction/menu.cpp b/engines/parallaction/menu.cpp
index 12b03ab4b0..14d50c6373 100644
--- a/engines/parallaction/menu.cpp
+++ b/engines/parallaction/menu.cpp
@@ -114,7 +114,7 @@ void Menu::start() {
splash();
- _vm->_gfx->setFont(kFontMenu);
+ _vm->_gfx->setFont(_vm->_menuFont);
_language = chooseLanguage();
_vm->_disk->setLanguage(_language);
@@ -128,15 +128,11 @@ void Menu::start() {
void Menu::splash() {
- _vm->_disk->loadSlide("intro");
- _vm->_gfx->setPalette(_vm->_gfx->_palette);
- _vm->_gfx->copyScreen(Gfx::kBitBack, Gfx::kBitFront);
+ _vm->showSlide("intro");
_vm->_gfx->updateScreen();
g_system->delayMillis(2000);
- _vm->_disk->loadSlide("minintro");
- _vm->_gfx->setPalette(_vm->_gfx->_palette);
- _vm->_gfx->copyScreen(Gfx::kBitBack, Gfx::kBitFront);
+ _vm->showSlide("minintro");
_vm->_gfx->updateScreen();
g_system->delayMillis(2000);
@@ -155,8 +151,8 @@ void Menu::newGame() {
_vm->_disk->selectArchive("disk1");
- _vm->_disk->loadScenery("test", NULL);
- _vm->_gfx->setPalette(_vm->_gfx->_palette);
+ _vm->setBackground("test", NULL, NULL);
+
_vm->_gfx->swapBuffers();
_vm->_gfx->displayCenteredString(50, v14[0]);
@@ -200,11 +196,7 @@ uint16 Menu::chooseLanguage() {
}
// user can choose language in dos version
-
- _vm->_disk->loadSlide("lingua");
- _vm->_gfx->setPalette(_vm->_gfx->_palette);
- _vm->_gfx->copyScreen(Gfx::kBitBack, Gfx::kBitFront);
-
+ _vm->showSlide("lingua");
_vm->_gfx->displayString(60, 30, "SELECT LANGUAGE", 1);
_vm->changeCursor(kCursorArrow);
@@ -260,8 +252,7 @@ uint16 Menu::selectGame() {
return 0; // can't load a savegame in demo versions
}
- _vm->_disk->loadSlide("restore");
- _vm->_gfx->setPalette(_vm->_gfx->_palette);
+ _vm->showSlide("restore");
uint16 _si = 0;
uint16 _di = 3;
@@ -343,23 +334,17 @@ void Menu::selectCharacter() {
uint16 _donna_points, _dino_points, _dough_points;
- StaticCnv v14;
-
- v14._data0 = (byte*)malloc(BLOCK_WIDTH*BLOCK_HEIGHT);
- v14._width = BLOCK_WIDTH;
- v14._height = BLOCK_HEIGHT;
+ Graphics::Surface v14;
+ v14.create(BLOCK_WIDTH, BLOCK_HEIGHT, 1);
_vm->changeCursor(kCursorArrow);
_vm->_soundMan->stopMusic();
- _vm->_gfx->setFont(kFontMenu);
+ _vm->_gfx->setFont(_vm->_menuFont);
_vm->_disk->selectArchive((_vm->getFeatures() & GF_LANG_MULT) ? "disk1" : "disk0");
- _vm->_disk->loadSlide("password"); // loads background into kBitBack buffer
- _vm->_gfx->copyScreen(Gfx::kBitBack, Gfx::kBitFront); //
-
- _vm->_gfx->setPalette(_vm->_gfx->_palette);
+ _vm->showSlide("password"); // loads background into kBitBack buffer
while (true) {
@@ -383,7 +368,7 @@ void Menu::selectCharacter() {
Common::Rect r;
int _si = getSelectedBlock(_vm->_mousePos, r);
if (_si != -1) {
- _vm->_gfx->grabRect(v14._data0, r, Gfx::kBitFront, BLOCK_WIDTH);
+ _vm->_gfx->grabRect((byte*)v14.pixels, r, Gfx::kBitFront, BLOCK_WIDTH);
_vm->_gfx->flatBlitCnv(&v14, _di * SLOT_WIDTH + SLOT_X, SLOT_Y, Gfx::kBitFront);
// beep();
@@ -435,7 +420,7 @@ void Menu::selectCharacter() {
_engineFlags |= kEngineChangeLocation;
- free(v14._data0);
+ v14.free();
return;
diff --git a/engines/parallaction/module.mk b/engines/parallaction/module.mk
index b7f60eeb32..56eaddac95 100644
--- a/engines/parallaction/module.mk
+++ b/engines/parallaction/module.mk
@@ -1,29 +1,30 @@
MODULE := engines/parallaction
MODULE_OBJS := \
- animation.o \
callables_br.o \
callables_ns.o \
- commands.o \
debug.o \
detection.o \
dialogue.o \
disk_br.o \
disk_ns.o \
+ exec_br.o \
+ exec_ns.o \
font.o \
graphics.o \
inventory.o \
- location.o \
menu.o \
- parser.o \
+ objects.o \
parallaction.o \
parallaction_br.o \
parallaction_ns.o \
+ parser.o \
+ parser_br.o \
+ parser_ns.o \
saveload.o \
sound.o \
staticres.o \
- walk.o \
- zone.o
+ walk.o
# This module can be built as a plugin
ifdef BUILD_PLUGINS
diff --git a/engines/parallaction/objects.cpp b/engines/parallaction/objects.cpp
new file mode 100644
index 0000000000..0e0d7c4c38
--- /dev/null
+++ b/engines/parallaction/objects.cpp
@@ -0,0 +1,408 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#include "common/stdafx.h"
+#include "parallaction/objects.h"
+#include "parallaction/parser.h"
+
+namespace Parallaction {
+
+
+
+Command::Command() {
+ _id = 0;
+ _flagsOn = 0;
+ _flagsOff = 0;
+}
+
+Command::~Command() {
+
+}
+
+
+Animation::Animation() {
+ _cnv = NULL;
+ _program = NULL;
+ _scriptName = 0;
+ _frame = 0;
+ _z = 0;
+}
+
+Animation::~Animation() {
+ if (_program)
+ delete _program;
+
+ if (_scriptName)
+ free(_scriptName);
+
+ if (_cnv)
+ delete _cnv;
+}
+
+uint16 Animation::width() const {
+ if (!_cnv) return 0;
+ Common::Rect r;
+ _cnv->getRect(0, r);
+ return r.width();
+}
+
+uint16 Animation::height() const {
+ if (!_cnv) return 0;
+ Common::Rect r;
+ _cnv->getRect(0, r);
+ return r.height();
+}
+
+uint16 Animation::getFrameNum() const {
+ if (!_cnv) return 0;
+ return _cnv->getNum();
+}
+
+byte* Animation::getFrameData(uint32 index) const {
+ if (!_cnv) return NULL;
+ return _cnv->getData(index);
+}
+
+
+#define NUM_LOCALS 10
+char _localNames[NUM_LOCALS][10];
+
+Program::Program() {
+ _loopCounter = 0;
+ _locals = new LocalVariable[NUM_LOCALS];
+ _numLocals = 0;
+}
+
+Program::~Program() {
+ delete[] _locals;
+}
+
+int16 Program::findLocal(const char* name) {
+ for (uint16 _si = 0; _si < NUM_LOCALS; _si++) {
+ if (!scumm_stricmp(name, _localNames[_si]))
+ return _si;
+ }
+
+ return -1;
+}
+
+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;
+
+ return _numLocals++;
+}
+
+
+
+Zone::Zone() {
+ _left = _top = _right = _bottom = 0;
+
+ _type = 0;
+ _flags = 0;
+}
+
+Zone::~Zone() {
+// printf("~Zone(%s)\n", _label._text);
+
+ switch (_type & 0xFFFF) {
+ case kZoneExamine:
+ free(u.examine->_filename);
+ free(u.examine->_description);
+ delete u.examine;
+ break;
+
+ case kZoneDoor:
+ free(u.door->_location);
+ free(u.door->_background);
+ if (u.door->_cnv)
+ delete u.door->_cnv;
+ delete u.door;
+ break;
+
+ case kZoneSpeak:
+ delete u.speak->_dialogue;
+ delete u.speak;
+ break;
+
+ case kZoneGet:
+ free(u.get->_backup);
+ if (u.get->_cnv) {
+ u.get->_cnv->free();
+ delete u.get->_cnv;
+ }
+ delete u.get;
+ break;
+
+ case kZoneHear:
+ delete u.hear;
+ break;
+
+ case kZoneMerge:
+ delete u.merge;
+ break;
+
+ default:
+ break;
+ }
+}
+
+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;
+ _top += y;
+ _bottom += y;
+}
+
+uint16 Zone::width() const {
+ return _right - _left;
+}
+
+uint16 Zone::height() const {
+ return _bottom - _top;
+}
+
+Label::Label() {
+ resetPosition();
+ _text = 0;
+}
+
+Label::~Label() {
+ free();
+}
+
+void Label::free() {
+ _cnv.free();
+ if (_text)
+ ::free(_text);
+ _text = 0;
+
+ resetPosition();
+}
+
+void Label::resetPosition() {
+ _pos.x = -1000;
+ _pos.y = -1000;
+ _old.x = -1000;
+ _old.y = -1000;
+}
+
+void Label::getRect(Common::Rect &r, bool old) {
+ r.setWidth(_cnv.w);
+ r.setHeight(_cnv.h);
+
+ if (old) {
+ r.moveTo(_old);
+ } else {
+ r.moveTo(_pos);
+ }
+}
+
+Answer::Answer() {
+ _text = NULL;
+ _mood = 0;
+ _following._question = NULL;
+ _noFlags = 0;
+ _yesFlags = 0;
+}
+
+Answer::~Answer() {
+ if (_text)
+ free(_text);
+}
+
+Question::Question() {
+ _text = NULL;
+ _mood = 0;
+
+ for (uint32 i = 0; i < NUM_ANSWERS; i++)
+ _answers[i] = NULL;
+
+}
+
+Question::~Question() {
+
+ for (uint32 i = 0; i < NUM_ANSWERS; i++)
+ if (_answers[i]) delete _answers[i];
+
+ free(_text);
+}
+
+Instruction::Instruction() {
+ memset(this, 0, sizeof(Instruction));
+}
+
+Instruction::~Instruction() {
+ if (_text)
+ free(_text);
+ if (_text2)
+ free(_text2);
+}
+
+int16 ScriptVar::getRValue() {
+
+ if (_flags & kParaImmediate) {
+ return _value;
+ }
+
+ if (_flags & kParaLocal) {
+ return _local->_value;
+ }
+
+ if (_flags & kParaField) {
+ return *_pvalue;
+ }
+
+ if (_flags & kParaRandom) {
+ return (rand() * _value) / 32767;
+ }
+
+ error("Parameter is not an r-value");
+
+ return 0;
+}
+
+int16* ScriptVar::getLValue() {
+
+ if (_flags & kParaLocal) {
+ return &_local->_value;
+ }
+
+ if (_flags & kParaField) {
+ return _pvalue;
+ }
+
+ error("Parameter is not an l-value");
+
+}
+
+void ScriptVar::setLocal(LocalVariable *local) {
+ _local = local;
+ _flags |= kParaLocal;
+}
+
+void ScriptVar::setField(int16 *field) {
+ _pvalue = field;
+ _flags |= kParaField;
+}
+
+void ScriptVar::setImmediate(int16 value) {
+ _value = value;
+ _flags |= kParaImmediate;
+}
+
+void ScriptVar::setRandom(int16 seed) {
+ _value = seed;
+ _flags |= kParaRandom;
+}
+
+
+ScriptVar::ScriptVar() {
+ _flags = 0;
+ _local = 0;
+ _value = 0;
+ _pvalue = 0;
+}
+
+Table::Table(uint32 size) : _size(size), _used(0), _disposeMemory(true) {
+ _data = (char**)calloc(size, sizeof(char*));
+}
+
+Table::Table(uint32 size, const char **data) : _size(size), _used(size), _disposeMemory(false) {
+ _data = const_cast<char**>(data);
+}
+
+Table::~Table() {
+
+ if (!_disposeMemory) return;
+
+ clear();
+
+ free(_data);
+
+}
+
+void Table::addData(const char* s) {
+
+ if (!(_used < _size))
+ error("Table overflow");
+
+ _data[_used++] = strdup(s);
+
+}
+
+uint16 Table::lookup(const char* s) {
+
+ for (uint16 i = 0; i < _used; i++) {
+ if (!scumm_stricmp(_data[i], s)) return i + 1;
+ }
+
+ return notFound;
+}
+
+void Table::clear() {
+ for (uint32 i = 0; i < _used; i++)
+ free(_data[i]);
+
+ _used = 0;
+}
+
+FixedTable::FixedTable(uint32 size, uint32 fixed) : Table(size), _numFixed(fixed) {
+}
+
+void FixedTable::clear() {
+ for (uint32 i = _numFixed; i < _used; i++) {
+ free(_data[i]);
+ _used--;
+ }
+}
+
+Table* createTableFromStream(uint32 size, Common::SeekableReadStream &stream) {
+
+ Table *t = new Table(size);
+
+ fillBuffers(stream);
+ while (scumm_stricmp(_tokens[0], "ENDTABLE")) {
+ t->addData(_tokens[0]);
+ fillBuffers(stream);
+ }
+
+ return t;
+}
+
+
+} // namespace Parallaction
diff --git a/engines/parallaction/zone.h b/engines/parallaction/objects.h
index 634a1364aa..41e8bbcf5d 100644
--- a/engines/parallaction/zone.h
+++ b/engines/parallaction/objects.h
@@ -30,12 +30,19 @@
#include "parallaction/defs.h"
-#include "parallaction/commands.h"
#include "parallaction/graphics.h"
namespace Parallaction {
+struct Zone;
+struct Animation;
+struct Command;
+struct Question;
+struct Answer;
+struct Instruction;
+struct Program;
+
enum ZoneTypes {
kZoneExamine = 1, // zone displays comment if activated
kZoneDoor = 2, // zone activated on click (after some walk if needed)
@@ -64,16 +71,77 @@ enum ZoneFlags {
kFlagsLooping = 0x100, // Animation: script is to be executed repeatedly
kFlagsAdded = 0x200, // NEVER USED in Nippon Safes
kFlagsCharacter = 0x400, //
- kFlagsNoWalk = 0x800 // Zone: character doesn't need to walk towards object to interact
+ kFlagsNoWalk = 0x800, // Zone: character doesn't need to walk towards object to interact
+
+ // BRA specific
+ kFlagsYourself = 0x1000,
+ kFlagsScaled = 0x2000,
+ kFlagsSelfuse = 0x4000,
+ kFlagsAnimLinked = 0x2000000
+};
+
+
+enum CommandFlags {
+ kFlagsVisited = 1,
+ kFlagsExit = 0x10000000,
+ kFlagsEnter = 0x20000000,
+ kFlagsGlobal = 0x40000000,
+
+ // BRA specific
+ kFlagsTestTrue = 2
+};
+
+struct CommandData {
+ uint32 _flags;
+ Animation * _animation;
+ Zone* _zone;
+ char* _string;
+ uint16 _callable;
+ uint16 _object;
+ Common::Point _move;
+
+ // BRA specific
+ Common::Point _startPos;
+ Common::Point _startPos2;
+ uint _lvalue;
+ int _rvalue;
+ int _zeta0;
+ int _zeta1;
+ int _zeta2;
+ int _characterId;
+ char* _string2;
+ int _musicCommand;
+ int _musicParm;
+
+
+ CommandData() {
+ memset(this, 0, sizeof(CommandData));
+ }
+
+ ~CommandData() {
+ if (_string)
+ free(_string);
+ if (_string2)
+ free(_string2);
+ }
};
+struct Command {
+ uint16 _id;
+ CommandData u;
+ uint32 _flagsOn;
+ uint32 _flagsOff;
+
+ Command();
+ ~Command();
+};
+
+typedef ManagedList<Command*> CommandList;
+
#define NUM_QUESTIONS 20
#define NUM_ANSWERS 5
-struct Command;
-struct Question;
-
struct Answer {
char* _text;
uint16 _mood;
@@ -104,7 +172,7 @@ struct Dialogue {
struct GetData { // size = 24
uint32 _icon;
- StaticCnv *_cnv;
+ Graphics::Surface *_cnv;
byte *_backup;
uint16 field_14; // unused
uint16 field_16; // unused
@@ -125,7 +193,7 @@ struct SpeakData { // size = 36
}
};
struct ExamineData { // size = 28
- StaticCnv *_cnv;
+ Graphics::Surface *_cnv;
uint16 _opBase; // unused
uint16 field_12; // unused
char* _description;
@@ -140,7 +208,7 @@ struct ExamineData { // size = 28
};
struct DoorData { // size = 28
char* _location;
- Cnv *_cnv;
+ Frames *_cnv;
byte* _background;
Common::Point _startPos;
uint16 _startFrame;
@@ -192,11 +260,18 @@ struct TypeData {
};
struct Label {
- char* _text;
- StaticCnv _cnv;
+ char* _text;
+ Graphics::Surface _cnv;
+
+ Common::Point _pos;
+ Common::Point _old;
Label();
~Label();
+
+ void free();
+ void resetPosition();
+ void getRect(Common::Rect &r, bool old = false);
};
struct Zone {
@@ -213,6 +288,11 @@ struct Zone {
CommandList _commands;
Common::Point _moveTo;
+ // BRA specific
+ uint _index;
+ char *_linkedName;
+ Animation *_linkedAnim;
+
Zone();
virtual ~Zone();
@@ -237,57 +317,81 @@ struct LocalVariable {
}
};
-union LValue {
+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
+};
+
+
+struct ScriptVar {
+ uint32 _flags;
+
int16 _value;
int16* _pvalue;
LocalVariable* _local;
- LValue() {
- _local = NULL;
- }
+ ScriptVar();
+
+ int16 getRValue();
+ int16* getLValue();
+
+ void setLocal(LocalVariable *local);
+ void setField(int16 *field);
+ void setImmediate(int16 value);
+ void setRandom(int16 seed);
};
enum InstructionFlags {
- kInstUsesLiteral = 1,
- kInstUsesLocal = 2,
kInstMod = 4,
- kInstMaskedPut = 8
+ kInstMaskedPut = 8,
+ kInstUnk20 = 0x20
};
-struct Animation;
+typedef ManagedList<Instruction*> InstructionList;
struct Instruction {
uint32 _index;
uint32 _flags;
- struct {
- Animation *_a;
- Zone *_z;
- uint32 _index;
- LValue _loopCounter;
- } _opBase;
- LValue _opA;
- LValue _opB;
-
- Instruction() {
- _index = 0;
- _flags = 0;
- _opBase._a = NULL;
- }
+
+ // common
+ Animation *_a;
+ Zone *_z;
+ int16 _immediate;
+ ScriptVar _opA;
+ ScriptVar _opB;
+
+ // BRA specific
+ byte _colors[3];
+ ScriptVar _opC;
+ char *_text;
+ char *_text2;
+ int _y;
+ InstructionList::iterator _endif;
+
+ Instruction();
+ ~Instruction();
+
};
-//typedef Common::List<Instruction*> InstructionList;
-typedef ManagedList<Instruction*> InstructionList;
struct Program {
LocalVariable *_locals;
+
uint16 _loopCounter;
+ uint16 _numLocals;
+
InstructionList::iterator _ip;
InstructionList::iterator _loopStart;
InstructionList _instructions;
Program();
~Program();
+
+ int16 findLocal(const char* name);
+ int16 addLocal(const char *name, int16 value = 0, int16 min = -10000, int16 max = 10000);
};
@@ -296,7 +400,8 @@ struct Animation : public Zone {
Common::Point _oldPos;
Program *_program;
- Cnv *_cnv;
+ Frames *_cnv;
+ char *_scriptName;
int16 _frame;
uint16 field_50; // unused
int16 _z;
@@ -319,6 +424,40 @@ typedef Animation* AnimationPointer;
typedef ManagedList<AnimationPointer> AnimationList;
+class Table {
+
+protected:
+ char **_data;
+ uint16 _size;
+ uint16 _used;
+ bool _disposeMemory;
+
+public:
+ Table(uint32 size);
+ Table(uint32 size, const char** data);
+
+ virtual ~Table();
+
+ enum {
+ notFound = 0
+ };
+
+ virtual void addData(const char* s);
+ virtual void clear();
+ virtual uint16 lookup(const char* s);
+};
+
+class FixedTable : public Table {
+
+ uint16 _numFixed;
+
+public:
+ FixedTable(uint32 size, uint32 fixed);
+ void clear();
+};
+
+Table* createTableFromStream(uint32 size, Common::SeekableReadStream &stream);
+
} // namespace Parallaction
#endif
diff --git a/engines/parallaction/parallaction.cpp b/engines/parallaction/parallaction.cpp
index 986bc6ebd7..7b641bf838 100644
--- a/engines/parallaction/parallaction.cpp
+++ b/engines/parallaction/parallaction.cpp
@@ -35,7 +35,6 @@
#include "parallaction/parallaction.h"
#include "parallaction/debug.h"
-#include "parallaction/menu.h"
#include "parallaction/sound.h"
@@ -54,11 +53,9 @@ char _saveData1[30] = { '\0' };
uint16 _language = 0;
char _slideText[2][40];
uint32 _engineFlags = 0;
-Zone *_activeZone = NULL;
uint16 _score = 1;
-uint32 _localFlags[120] = { 0 };
Command * _forwardedCommands[20] = {
NULL,
NULL,
@@ -92,15 +89,14 @@ uint16 _introSarcData2 = 1;
// private stuff
static Job *_jDrawInventory = NULL;
-Job *_jDrawLabel = NULL;
-Job *_jEraseLabel = NULL;
-Zone *_hoverZone = NULL;
static Job *_jRunScripts = NULL;
Parallaction::Parallaction(OSystem *syst) :
Engine(syst) {
+ // FIXME: Fingolfin asks: why is there a FIXME here? Please either clarify what
+ // needs fixing, or remove it!
// FIXME
_vm = this;
@@ -109,11 +105,11 @@ Parallaction::Parallaction(OSystem *syst) :
Common::File::addDefaultDirectory( _gameDataPath );
Common::addSpecialDebugLevel(kDebugDialogue, "dialogue", "Dialogues debug level");
- Common::addSpecialDebugLevel(kDebugLocation, "location", "Location debug level");
+ Common::addSpecialDebugLevel(kDebugParser, "parser", "Parser debug level");
Common::addSpecialDebugLevel(kDebugDisk, "disk", "Disk debug level");
Common::addSpecialDebugLevel(kDebugWalk, "walk", "Walk debug level");
Common::addSpecialDebugLevel(kDebugGraphics, "gfx", "Gfx debug level");
- Common::addSpecialDebugLevel(kDebugJobs, "jobs", "Jobs debug level");
+ Common::addSpecialDebugLevel(kDebugExec, "exec", "Execution debug level");
Common::addSpecialDebugLevel(kDebugInput, "input", "Input debug level");
Common::addSpecialDebugLevel(kDebugAudio, "audio", "Audio debug level");
Common::addSpecialDebugLevel(kDebugMenu, "menu", "Menu debug level");
@@ -123,11 +119,13 @@ Parallaction::Parallaction(OSystem *syst) :
Parallaction::~Parallaction() {
delete _debugger;
+ freeBackground();
+ delete _backgroundInfo;
+
delete _globalTable;
delete _callableNames;
- delete _commandsNames;
- delete _instructionNames;
+ delete _localFlagNames;
delete _zoneTypeNames;
delete _zoneFlagNames;
@@ -150,7 +148,6 @@ int Parallaction::init() {
_objectsNames = NULL;
_globalTable = NULL;
_hasLocationSound = false;
- _skipMenu = false;
_transCurrentHoverItem = 0;
_actionAfterWalk = false; // actived when the character needs to move before taking an action
_activeItem._index = 0;
@@ -164,20 +161,25 @@ int Parallaction::init() {
_location._comment = NULL;
_location._endComment = NULL;
- _screenMaskWidth = _screenWidth / 4;
- _screenPathWidth = _screenWidth / 8;
+ _backgroundInfo = 0;
+ _pathBuffer = 0;
+ _activeZone = 0;
+
_screenSize = _screenWidth * _screenHeight;
- _screenMaskSize = _screenMaskWidth * _screenHeight;
- _screenPathSize = _screenPathWidth * _screenHeight;
+
+ _backgroundInfo = new BackgroundInfo;
strcpy(_characterName1, "null");
strcpy(_characterName, "dough");
- memset(_locationNames, 0, 120*32);
+ memset(_locationNames, 0, NUM_LOCATIONS * 32);
- initWalk(); // needs to be pushed into subclass
initInventory(); // needs to be pushed into subclass
+ _jDrawLabel = NULL;
+ _jEraseLabel = NULL;
+ _hoverZone = NULL;
+
_animations.push_front(&_char._ani);
_gfx = new Gfx(this);
@@ -190,48 +192,7 @@ int Parallaction::init() {
-int Parallaction::go() {
-
- initGame();
- runGame();
-
- return 0;
-}
-
-void Parallaction::initGame() {
-
- _menu = new Menu(this);
-
- initGlobals();
- if (_skipMenu == false) {
- _menu->start();
- }
-
- char *v4 = strchr(_location._name, '.');
- if (v4) {
- *v4 = '\0';
- }
-
- _engineFlags &= ~kEngineChangeLocation;
- changeCharacter(_characterName);
-
- strcpy(_saveData1, _location._name);
- parseLocation(_location._name);
- if (_location._startPosition.x != -1000) {
- _char._ani._left = _location._startPosition.x;
- _char._ani._top = _location._startPosition.y;
- _char._ani._frame = _location._startFrame;
- _location._startPosition.y = -1000;
- _location._startPosition.x = -1000;
- }
-
- return;
-}
-
-void Parallaction::initGlobals() {
- _globalTable = _disk->loadTable("global");
-}
// FIXME: the engine has 3 event loops. The following routine hosts the main one,
// and it's called from 8 different places in the code. There exist 2 more specialised
@@ -324,9 +285,9 @@ void waitUntilLeftClick() {
void Parallaction::runGame() {
- addJob(&jobEraseAnimations, (void*)1, kPriority20);
- _jRunScripts = addJob(&jobRunScripts, 0, kPriority15);
- addJob(&jobDisplayAnimations, 0, kPriority3);
+ addJob(kJobEraseAnimations, (void*)1, kPriority20);
+ _jRunScripts = addJob(kJobRunScripts, 0, kPriority15);
+ addJob(kJobDisplayAnimations, 0, kPriority3);
_gfx->copyScreen(Gfx::kBitBack, Gfx::kBit2);
@@ -391,11 +352,34 @@ void Parallaction::runGame() {
}
- delete _menu;
-
return;
}
+void Parallaction::showLabel(Label &label) {
+ label.resetPosition();
+ _jDrawLabel = addJob(kJobDisplayLabel, (void*)&label, kPriority0);
+ _jEraseLabel = addJob(kJobEraseLabel, (void*)&label, kPriority20);
+}
+
+void Parallaction::hideLabel(uint priority) {
+
+ if (!_jDrawLabel)
+ return;
+
+ removeJob(_jDrawLabel);
+ _jDrawLabel = 0;
+
+ if (priority == kPriority99) {
+ // remove job immediately
+ removeJob(_jEraseLabel);
+ _jEraseLabel = 0;
+ } else {
+ // schedule job for deletion
+ addJob(kJobWaitRemoveJob, _jEraseLabel, priority);
+ }
+
+}
+
void Parallaction::processInput(InputData *data) {
Zone *z;
@@ -403,19 +387,12 @@ void Parallaction::processInput(InputData *data) {
switch (data->_event) {
case kEvEnterZone:
debugC(2, kDebugInput, "processInput: kEvEnterZone");
- _gfx->_labelPosition[1].x = -1000;
- _gfx->_labelPosition[1].y = -1000;
- _gfx->_labelPosition[0].x = -1000;
- _gfx->_labelPosition[0].y = -1000;
- _jDrawLabel = addJob(&jobDisplayLabel, (void*)data->_label, kPriority0);
- _jEraseLabel = addJob(&jobEraseLabel, (void*)data->_label, kPriority20);
+ showLabel(*data->_label);
break;
case kEvExitZone:
debugC(2, kDebugInput, "processInput: kEvExitZone");
- removeJob(_jDrawLabel);
- addJob(&jobWaitRemoveJob, _jEraseLabel, kPriority15);
- _jDrawLabel = NULL;
+ hideLabel(kPriority15);
break;
case kEvAction:
@@ -433,15 +410,12 @@ void Parallaction::processInput(InputData *data) {
case kEvOpenInventory:
_procCurrentHoverItem = -1;
_hoverZone = NULL;
- if (_jDrawLabel != 0) {
- removeJob(_jDrawLabel);
- _jDrawLabel = NULL;
- addJob(&jobWaitRemoveJob, _jEraseLabel, kPriority2);
+ hideLabel(kPriority2);
+ if (hitZone(kZoneYou, _mousePos.x, _mousePos.y) == 0) {
+ changeCursor(kCursorArrow);
}
- if (hitZone(kZoneYou, _mousePos.x, _mousePos.y) == 0)
- changeCursor(kCursorArrow);
removeJob(_jRunScripts);
- _jDrawInventory = addJob(&jobShowInventory, 0, kPriority2);
+ _jDrawInventory = addJob(kJobShowInventory, 0, kPriority2);
openInventory();
break;
@@ -451,8 +425,8 @@ void Parallaction::processInput(InputData *data) {
// activates item
changeCursor(data->_inventoryIndex);
}
- _jRunScripts = addJob(&jobRunScripts, 0, kPriority15);
- addJob(&jobHideInventory, 0, kPriority20);
+ _jRunScripts = addJob(kJobRunScripts, 0, kPriority15);
+ addJob(kJobHideInventory, 0, kPriority20);
removeJob(_jDrawInventory);
break;
@@ -469,7 +443,7 @@ void Parallaction::processInput(InputData *data) {
if (_char._ani._flags & kFlagsRemove) break;
if ((_char._ani._flags & kFlagsActive) == 0) break;
WalkNodeList *v4 = _char._builder.buildPath(data->_mousePos.x, data->_mousePos.y);
- addJob(&jobWalk, v4, kPriority19);
+ addJob(kJobWalk, v4, kPriority19);
_engineFlags |= kEngineWalking; // inhibits processing of input until walking is over
}
break;
@@ -662,11 +636,7 @@ void Parallaction::changeCursor(int32 index) {
debugC(1, kDebugInput, "changeCursor(%i), label: %p", index, (const void*)_jDrawLabel);
- if (_jDrawLabel != NULL) {
- removeJob(_jDrawLabel);
- addJob(&jobWaitRemoveJob, _jEraseLabel, kPriority15 );
- _jDrawLabel = NULL;
- }
+ hideLabel(kPriority15);
_activeItem._id = 0;
@@ -674,7 +644,7 @@ void Parallaction::changeCursor(int32 index) {
_activeItem._id = _inventory[index]._id;
}
- _gfx->setMousePointer(index);
+ setMousePointer(index);
return;
}
@@ -682,7 +652,7 @@ void Parallaction::changeCursor(int32 index) {
void Parallaction::freeCharacter() {
- debugC(3, kDebugLocation, "freeCharacter()");
+ debugC(1, kDebugExec, "freeCharacter()");
if (!IS_DUMMY_CHARACTER(_characterName)) {
if (_objectsNames)
@@ -697,9 +667,7 @@ void Parallaction::freeCharacter() {
delete _char._talk;
_char._talk = NULL;
- _gfx->freeStaticCnv(_char._head);
- if (_char._head)
- delete _char._head;
+ delete _char._head;
_char._head = NULL;
if (_char._objs)
@@ -710,96 +678,49 @@ void Parallaction::freeCharacter() {
return;
}
-void Parallaction::changeCharacter(const char *name) {
- debugC(1, kDebugLocation, "changeCharacter(%s)", name);
-
- char baseName[20];
- if (IS_MINI_CHARACTER(name)) {
- strcpy(baseName, name+4);
- } else {
- strcpy(baseName, name);
- }
-
- char fullName[20];
- strcpy(fullName, name);
- if (_engineFlags & kEngineTransformedDonna)
- strcat(fullName, "tras");
-
- if (scumm_stricmp(fullName, _characterName1)) {
-
- // freeCharacter takes responsibility for checking
- // character for sanity before memory is freed
- freeCharacter();
-
- Common::String oldArchive = _disk->selectArchive((getFeatures() & GF_LANG_MULT) ? "disk1" : "disk0");
- _char._ani._cnv = _disk->loadFrames(fullName);
-
- if (!IS_DUMMY_CHARACTER(name)) {
- if (getPlatform() == Common::kPlatformAmiga && (getFeatures() & GF_LANG_MULT))
- _disk->selectArchive("disk0");
- _char._head = _disk->loadHead(baseName);
- _char._talk = _disk->loadTalk(baseName);
- _char._objs = _disk->loadObjects(baseName);
- _objectsNames = _disk->loadTable(baseName);
-
- _soundMan->playCharacterMusic(name);
-
- if (!(getFeatures() & GF_DEMO))
- parseLocation("common");
- }
-
- if (!oldArchive.empty())
- _disk->selectArchive(oldArchive);
- }
-
- strcpy(_characterName1, fullName);
-
- debugC(1, kDebugLocation, "changeCharacter() done");
-
- return;
-}
/*
helper function to provide *descending* ordering of the job list
(higher priorities values comes first in the list)
*/
int compareJobPriority(const JobPointer &j1, const JobPointer &j2) {
- return (j1->_tag >= j2->_tag ? -1 : 1);
+ return (j1->_job->_tag >= j2->_job->_tag ? -1 : 1);
}
-Job *Parallaction::addJob(JobFn fn, void *parm, uint16 tag) {
- debugC(3, kDebugJobs, "addJob(%i)", tag);
+Job *Parallaction::addJob(uint functionId, void *parm, uint16 tag) {
+ debugC(9, kDebugExec, "addJob(%i)", tag);
Job *v8 = new Job;
v8->_parm = parm;
- v8->_fn = fn;
v8->_tag = tag;
v8->_finished = 0;
v8->_count = 0;
- _jobs.insertSorted(v8, compareJobPriority);
+ JobOpcode *op = createJobOpcode(functionId, v8);
+
+ _jobs.insertSorted(op, compareJobPriority);
return v8;
}
void Parallaction::removeJob(Job *j) {
- debugC(3, kDebugJobs, "addJob(%i)", j->_tag);
+ debugC(9, kDebugExec, "addJob(%i)", j->_tag);
j->_finished = 1;
return;
}
void Parallaction::pauseJobs() {
- debugC(3, kDebugJobs, "pausing jobs execution");
+ debugC(9, kDebugExec, "pausing jobs execution");
_engineFlags |= kEnginePauseJobs;
return;
}
void Parallaction::resumeJobs() {
- debugC(3, kDebugJobs, "resuming jobs execution");
+ debugC(9, kDebugExec, "resuming jobs execution");
_engineFlags &= ~kEnginePauseJobs;
return;
@@ -811,7 +732,8 @@ void Parallaction::runJobs() {
JobList::iterator it = _jobs.begin();
while (it != _jobs.end()) {
- if ((*it)->_finished == 1)
+ Job *job = (*it)->_job;
+ if (job->_finished == 1)
it = _jobs.erase(it);
else
it++;
@@ -819,8 +741,9 @@ void Parallaction::runJobs() {
it = _jobs.begin();
while (it != _jobs.end()) {
- debugC(9, kDebugJobs, "runJobs: %i", (*it)->_tag);
- (*(*it)->_fn)((*it)->_parm, (*it));
+ Job *job = (*it)->_job;
+ debugC(9, kDebugExec, "runJobs: %i", job->_tag);
+ (*(*it))();
it++;
}
@@ -828,66 +751,317 @@ void Parallaction::runJobs() {
return;
}
-// this Job uses a static counter to delay removal
-// and is in fact only used to remove jEraseLabel jobs
-//
-void jobWaitRemoveJob(void *parm, Job *j) {
- Job *arg = (Job*)parm;
- static uint16 count = 0;
- debugC(3, kDebugJobs, "jobWaitRemoveJob: count = %i", count);
- _engineFlags |= kEngineBlockInput;
+void Parallaction::pushParserTables(OpcodeSet *opcodes, Table *statements) {
+ _opcodes.push(_currentOpcodes);
+ _statements.push(_currentStatements);
+
+ _currentOpcodes = opcodes;
+ _currentStatements = statements;
+}
+
+void Parallaction::popParserTables() {
+ assert(_opcodes.size() > 0);
+
+ _currentOpcodes = _opcodes.pop();
+ _currentStatements = _statements.pop();
+}
+
+void Parallaction::parseStatement() {
+ assert(_currentOpcodes != 0);
+
+ _lookup = _currentStatements->lookup(_tokens[0]);
+
+ debugC(9, kDebugParser, "parseStatement: %s (lookup = %i)", _tokens[0], _lookup);
+
+ (*(*_currentOpcodes)[_lookup])();
+}
+
+
+
+
+Animation *Parallaction::findAnimation(const char *name) {
+
+ for (AnimationList::iterator it = _animations.begin(); it != _animations.end(); it++)
+ if (!scumm_stricmp((*it)->_label._text, name)) return *it;
+
+ return NULL;
+}
+
+void Parallaction::freeAnimations() {
+ _animations.clear();
+ return;
+}
+
+int compareAnimationZ(const AnimationPointer &a1, const AnimationPointer &a2) {
+ if (a1->_z == a2->_z) return 0;
+ return (a1->_z < a2->_z ? -1 : 1);
+}
+
+void Parallaction::sortAnimations() {
+ _char._ani._z = _char._ani.height() + _char._ani._top;
+ _animations.sort(compareAnimationZ);
+ return;
+}
+
- count++;
- if (count == 2) {
- count = 0;
- _vm->removeJob(arg);
- _engineFlags &= ~kEngineBlockInput;
- j->_finished = 1;
+void Parallaction::allocateLocationSlot(const char *name) {
+ // WORKAROUND: the original code erroneously incremented
+ // _currentLocationIndex, thus producing inconsistent
+ // savegames. This workaround modified the following loop
+ // and if-statement, so the code exactly matches the one
+ // in Big Red Adventure.
+ _currentLocationIndex = -1;
+ uint16 _di = 0;
+ while (_locationNames[_di][0] != '\0') {
+ if (!scumm_stricmp(_locationNames[_di], name)) {
+ _currentLocationIndex = _di;
+ }
+ _di++;
}
+ if (_di == 120)
+ error("No more location slots available. Please report this immediately to ScummVM team.");
+
+ if (_currentLocationIndex == -1) {
+ strcpy(_locationNames[_numLocations], name);
+ _currentLocationIndex = _numLocations;
+
+ _numLocations++;
+ _locationNames[_numLocations][0] = '\0';
+ _localFlags[_numLocations] = 0;
+ } else {
+ _localFlags[_currentLocationIndex] |= kFlagsVisited; // 'visited'
+ }
+}
+
+
+
+void Parallaction::freeLocation() {
+ debugC(2, kDebugExec, "freeLocation");
+
+ _soundMan->stopSfx(0);
+ _soundMan->stopSfx(1);
+ _soundMan->stopSfx(2);
+ _soundMan->stopSfx(3);
+
+ _localFlagNames->clear();
+
+ _location._walkNodes.clear();
+
+ freeZones();
+ freeAnimations();
+
+ if (_location._comment) {
+ free(_location._comment);
+ }
+ _location._comment = NULL;
+
+ _location._commands.clear();
+ _location._aCommands.clear();
+
return;
}
-Table::Table(uint32 size) : _size(size), _used(0), _disposeMemory(true) {
- _data = (char**)malloc(sizeof(char*)*size);
+
+void Parallaction::freeBackground() {
+
+ if (!_backgroundInfo)
+ return;
+
+ _backgroundInfo->bg.free();
+ _backgroundInfo->mask.free();
+ _backgroundInfo->path.free();
+
+ _pathBuffer = 0;
+
+}
+
+void Parallaction::setBackground(const char* name, const char* mask, const char* path) {
+
+ _disk->loadScenery(*_backgroundInfo, name, mask, path);
+
+ _gfx->setPalette(_backgroundInfo->palette);
+ _gfx->_palette.clone(_backgroundInfo->palette);
+ _gfx->setBackground(&_backgroundInfo->bg);
+
+ if (_backgroundInfo->mask.data)
+ _gfx->setMask(&_backgroundInfo->mask);
+
+ if (_backgroundInfo->path.data)
+ _pathBuffer = &_backgroundInfo->path;
+
+ return;
}
-Table::Table(uint32 size, const char **data) : _size(size), _used(size), _disposeMemory(false) {
- _data = const_cast<char**>(data);
+void Parallaction::showLocationComment(const char *text, bool end) {
+
+ _gfx->setFont(_dialogueFont);
+
+ int16 w, h;
+ _gfx->getStringExtent(const_cast<char*>(text), 130, &w, &h);
+
+ Common::Rect r(w + (end ? 5 : 10), h + 5);
+ r.moveTo(5, 5);
+
+ _gfx->floodFill(Gfx::kBitFront, r, 0);
+ r.grow(-2);
+ _gfx->floodFill(Gfx::kBitFront, r, 1);
+ _gfx->displayWrappedString(const_cast<char*>(text), 3, 5, 0, 130);
+
+ _gfx->updateScreen();
+
+ return;
}
-Table::~Table() {
+void Parallaction::switchBackground(const char* background, const char* mask) {
+// printf("switchBackground(%s)", name);
+
+ Palette pal;
- if (!_disposeMemory) return;
+ uint16 v2 = 0;
+ if (!scumm_stricmp(background, "final")) {
+ _gfx->clearScreen(Gfx::kBitBack);
+ for (uint16 _si = 0; _si <= 32; _si++) {
+ pal.setEntry(_si, v2, v2, v2);
+ v2 += 4;
+ }
- for (uint32 i = 0; i < _used; i++)
- free(_data[i]);
+ g_system->delayMillis(20);
+ _gfx->setPalette(pal);
+ _gfx->updateScreen();
+ }
- free(_data);
+ setBackground(background, mask, mask);
+ return;
}
-void Table::addData(const char* s) {
- if (!(_used < _size))
- error("Table overflow");
+void Parallaction::showSlide(const char *name) {
- _data[_used++] = strdup(s);
+ BackgroundInfo info;
+
+ _disk->loadSlide(info, name);
+
+ // TODO: avoid using screen buffers for displaying slides. Using a generic buffer
+ // allows for positioning of graphics as needed by Big Red Adventure.
+ // The main problem lies with menu, which relies on multiple buffers, mainly because
+ // it is crappy code.
+ _gfx->setBackground(&info.bg);
+ _gfx->setPalette(info.palette);
+ _gfx->copyScreen(Gfx::kBitBack, Gfx::kBitFront);
+ info.bg.free();
+ info.mask.free();
+ info.path.free();
+
+ return;
}
-int16 Table::lookup(const char* s) {
- for (uint16 i = 0; i < _used; i++) {
- if (!scumm_stricmp(_data[i], s)) return i + 1;
+
+// displays transition before a new location
+//
+// clears screen (in white??)
+// shows location comment (if any)
+// waits for mouse click
+// fades towards game palette
+//
+void Parallaction::doLocationEnterTransition() {
+ debugC(2, kDebugExec, "doLocationEnterTransition");
+
+ if (_localFlags[_currentLocationIndex] & kFlagsVisited) {
+ debugC(2, kDebugExec, "skipping location transition");
+ return; // visited
+ }
+
+ Palette pal(_gfx->_palette);
+ pal.makeGrayscale();
+ _gfx->setPalette(pal);
+
+ jobRunScripts(NULL, NULL);
+ jobEraseAnimations(NULL, NULL);
+ jobDisplayAnimations(NULL, NULL);
+
+ _gfx->swapBuffers();
+ _gfx->copyScreen(Gfx::kBitFront, Gfx::kBitBack);
+
+ showLocationComment(_location._comment, false);
+ waitUntilLeftClick();
+
+ _gfx->copyScreen(Gfx::kBitBack, Gfx::kBitFront );
+
+ // fades maximum intensity palette towards approximation of main palette
+ for (uint16 _si = 0; _si<6; _si++) {
+ pal.fadeTo(_gfx->_palette, 4);
+ _gfx->setPalette(pal);
+ waitTime( 1 );
+ _gfx->updateScreen();
+ }
+
+ debugC(2, kDebugExec, "doLocationEnterTransition completed");
+
+ return;
+}
+
+
+
+Zone *Parallaction::findZone(const char *name) {
+
+ for (ZoneList::iterator it = _zones.begin(); it != _zones.end(); it++) {
+ if (!scumm_stricmp((*it)->_label._text, name)) return *it;
}
- return -1;
+ return findAnimation(name);
}
+
+void Parallaction::freeZones() {
+ debugC(2, kDebugExec, "freeZones: kEngineQuit = %i", _engineFlags & kEngineQuit);
+
+ ZoneList::iterator it = _zones.begin();
+
+ while ( it != _zones.end() ) {
+
+ Zone* z = *it;
+
+ // 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,
+ // but we need to check it separately here. The same workaround is applied in hitZone.
+ if (((z->_top == -1) ||
+ ((z->_left == -2) && (
+ (((z->_type & 0xFFFF) == kZoneMerge) && ((isItemInInventory(MAKE_INVENTORY_ID(z->u.merge->_obj1)) != 0) || (isItemInInventory(MAKE_INVENTORY_ID(z->u.merge->_obj2)) != 0))) ||
+ (((z->_type & 0xFFFF) == kZoneGet) && ((isItemInInventory(MAKE_INVENTORY_ID(z->u.get->_icon)) != 0)))
+ ))) &&
+ ((_engineFlags & kEngineQuit) == 0)) {
+
+ debugC(2, kDebugExec, "freeZones preserving zone '%s'", z->_label._text);
+
+ it++;
+
+ } else
+
+ it = _zones.erase(it);
+
+ }
+
+ return;
+}
+
+
+
+
+
+
+
+
+
+
+
+
} // namespace Parallaction
diff --git a/engines/parallaction/parallaction.h b/engines/parallaction/parallaction.h
index 31b125c92a..c0975d4c85 100644
--- a/engines/parallaction/parallaction.h
+++ b/engines/parallaction/parallaction.h
@@ -27,21 +27,18 @@
#define PARALLACTION_H
#include "common/str.h"
-
+#include "common/stack.h"
+#include "common/array.h"
#include "engines/engine.h"
#include "parallaction/defs.h"
#include "parallaction/inventory.h"
#include "parallaction/parser.h"
+#include "parallaction/objects.h"
#include "parallaction/disk.h"
#include "parallaction/walk.h"
-#include "parallaction/zone.h"
-namespace GUI {
- class ListWidget;
- class CommandSender;
-}
extern OSystem *g_system;
@@ -50,10 +47,10 @@ namespace Parallaction {
enum {
kDebugDisk = 1 << 0,
kDebugWalk = 1 << 1,
- kDebugLocation = 1 << 2,
+ kDebugParser = 1 << 2,
kDebugDialogue = 1 << 3,
kDebugGraphics = 1 << 4,
- kDebugJobs = 1 << 5,
+ kDebugExec = 1 << 5,
kDebugInput = 1 << 6,
kDebugAudio = 1 << 7,
kDebugMenu = 1 << 8
@@ -93,7 +90,8 @@ enum {
kPriority18 = 18,
kPriority19 = 19,
kPriority20 = 20,
- kPriority21 = 21
+ kPriority21 = 21,
+ kPriority99 = 99 // fictitious priority value used as a flag to handle quick label deletion
};
enum {
@@ -143,32 +141,23 @@ struct PARALLACTIONGameDescription;
struct Job;
-typedef void (*JobFn)(void*, Job*);
struct Job {
uint16 _count; // # of executions left
uint16 _tag; // used for ordering
uint16 _finished;
void * _parm;
- JobFn _fn;
public:
- Job() : _count(0), _tag(0), _finished(0), _parm(NULL), _fn(NULL) {
+ Job() : _count(0), _tag(0), _finished(0), _parm(NULL) {
}
};
-typedef Job* JobPointer;
-typedef ManagedList<JobPointer> JobList;
-
-typedef void (*callable)(void*);
extern uint16 _mouseButtons;
extern uint16 _score;
extern uint16 _language;
-extern Zone *_activeZone;
extern uint32 _engineFlags;
-extern callable _callables[];
-extern uint32 _localFlags[];
extern Command *_forwardedCommands[];
extern char _forwardedAnimationNames[][20];
extern uint16 _numForwards;
@@ -200,19 +189,6 @@ extern const char *_minidrkiName;
void waitUntilLeftClick();
-void jobRemovePickedItem(void*, Job *j);
-void jobDisplayDroppedItem(void*, Job *j);
-void jobToggleDoor(void*, Job *j);
-void jobEraseAnimations(void *arg_0, Job *j);
-void jobWalk(void*, Job *j);
-void jobRunScripts(void*, Job *j);
-void jobDisplayAnimations(void*, Job *j);
-void jobDisplayLabel(void *parm, Job *j);
-void jobWaitRemoveJob(void *parm, Job *j);
-void jobShowInventory(void *parm, Job *j);
-void jobHideInventory(void *parm, Job *j);
-void jobEraseLabel(void *parm, Job *j);
-
class Debugger;
@@ -221,12 +197,10 @@ class Menu;
class SoundMan;
-
struct Location {
Common::Point _startPosition;
uint16 _startFrame;
- WalkNodeList _walkNodes;
char _name[100];
CommandList _aCommands;
@@ -234,13 +208,18 @@ struct Location {
char *_comment;
char *_endComment;
+ // NS specific
+ WalkNodeList _walkNodes;
+
+ // BRA specific
+ CommandList _escapeCommands;
};
struct Character {
Animation _ani;
- StaticCnv *_head;
- Cnv *_talk;
- Cnv *_objs;
+ Graphics::Surface *_head;
+ Frames *_talk;
+ Frames *_objs;
PathBuilder _builder;
Character() : _builder(&_ani) {
@@ -256,31 +235,133 @@ struct Character {
_ani._frame = 0;
_ani._flags = kFlagsActive | kFlagsNoName;
_ani._type = kZoneYou;
- _ani._label._cnv._data0 = NULL;
+ _ani._label._cnv.pixels = NULL;
_ani._label._text = strdup("yourself");
}
+ void getFoot(Common::Point &foot) {
+ foot.x = _ani._left + _ani.width() / 2;
+ foot.y = _ani._top + _ani.height();
+ }
+
+ void setFoot(const Common::Point &foot) {
+ _ani._left = foot.x - _ani.width() / 2;
+ _ani._top = foot.y - _ani.height();
+ }
+
+
+};
+
+
+
+
+struct BackgroundInfo {
+ uint width;
+ uint height;
+
+ Graphics::Surface bg;
+ MaskBuffer mask;
+ PathBuffer path;
+
+ Palette palette;
};
+class Opcode {
+
+public:
+ virtual void operator()() const = 0;
+ virtual ~Opcode() { }
+};
-class Table {
+template <class T>
+class OpcodeImpl : public Opcode {
- char **_data;
- uint16 _size;
- uint16 _used;
- bool _disposeMemory;
+ typedef void (T::*Fn)();
+
+ T* _instance;
+ Fn _fn;
public:
- Table(uint32 size);
- Table(uint32 size, const char** data);
+ OpcodeImpl(T* instance, const Fn &fn) : _instance(instance), _fn(fn) { }
+
+ void operator()() const {
+ (_instance->*_fn)();
+ }
+
+};
+
+typedef Common::Array<const Opcode*> OpcodeSet;
- ~Table();
+class JobOpcode {
- void addData(const char* s);
+public:
+ Job *_job;
- int16 lookup(const char* s);
+ JobOpcode(Job *job) : _job(job) { }
+
+ virtual void operator()() const = 0;
+ virtual ~JobOpcode() {
+ delete _job;
+ }
};
+template <class T>
+class OpcodeImpl2 : public JobOpcode {
+
+ typedef void (T::*Fn)(void *, Job*);
+
+ T* _instance;
+ Fn _fn;
+
+public:
+ OpcodeImpl2(T* instance, const Fn &fn, Job* job) : JobOpcode(job), _instance(instance), _fn(fn) { }
+
+ void operator()() const {
+ (_instance->*_fn)(_job->_parm, _job);
+ }
+
+};
+
+typedef JobOpcode* JobPointer;
+typedef ManagedList<JobPointer> JobList;
+
+enum Jobs {
+ kJobDisplayAnimations = 0,
+ kJobEraseAnimations = 1,
+ kJobDisplayDroppedItem = 2,
+ kJobRemovePickedItem = 3,
+ kJobRunScripts = 4,
+ kJobWalk = 5,
+ kJobDisplayLabel = 6,
+ kJobEraseLabel = 7,
+ kJobWaitRemoveJob = 8,
+ kJobToggleDoor = 9,
+
+ // NS specific
+ kJobShowInventory = 10,
+ kJobHideInventory,
+
+ // BRA specific
+ kJobEraseSubtitle = 10,
+ kJobDisplaySubtitle,
+ kJobWaitRemoveSubtitleJob,
+ kJobPauseSfx,
+ kJobStopFollower,
+ kJobScroll
+};
+
+
+#define DECLARE_UNQUALIFIED_ZONE_PARSER(sig) void locZoneParse_##sig()
+#define DECLARE_UNQUALIFIED_ANIM_PARSER(sig) void locAnimParse_##sig()
+#define DECLARE_UNQUALIFIED_COMMAND_PARSER(sig) void cmdParse_##sig()
+#define DECLARE_UNQUALIFIED_LOCATION_PARSER(sig) void locParse_##sig()
+#define DECLARE_UNQUALIFIED_INSTRUCTION_PARSER(sig) void instParse_##sig()
+
+#define DECLARE_UNQUALIFIED_COMMAND_OPCODE(op) void cmdOp_##op()
+#define DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(op) void instOp_##op()
+
+
+#define NUM_LOCATIONS 120
class Parallaction : public Engine {
friend class Debugger;
@@ -291,31 +372,50 @@ public:
~Parallaction();
int init();
- int go();
- void loadGame();
- void saveGame();
+ virtual void loadGame() = 0;
+ virtual void saveGame() = 0;
uint16 updateInput();
void waitTime(uint32 t);
- void parseLocation(const char *filename);
+ uint _lookup;
+ Common::Stack<OpcodeSet*> _opcodes;
+ Common::Stack<Table*> _statements;
+ OpcodeSet *_currentOpcodes;
+ Table *_currentStatements;
+ void pushParserTables(OpcodeSet *opcodes, Table* statements);
+ void popParserTables();
+ void parseStatement();
+
+ OpcodeSet _commandOpcodes;
+
+ struct {
+ Command *cmd;
+ Zone *z;
+ } _cmdRunCtxt;
+
+ OpcodeSet _instructionOpcodes;
+
+ struct {
+ Animation *a;
+ InstructionList::iterator inst;
+ uint16 modCounter;
+ bool suspend;
+ } _instRunCtxt;
+
+
void changeCursor(int32 index);
void showCursor(bool visible);
- void changeCharacter(const char *name);
-
- char *parseComment(Script &script);
- char *parseDialogueString(Script &script);
- Dialogue *parseDialogue(Script &script);
- Job *addJob(JobFn fn, void *parm, uint16 tag);
+ Job *addJob(uint functionId, void *parm, uint16 tag);
void removeJob(Job *j);
void pauseJobs();
void resumeJobs();
void runJobs();
+ virtual JobOpcode* createJobOpcode(uint functionId, Job *job) = 0;
- void setPath(byte *path);
void finalizeWalk(WalkNodeList *list);
int16 selectWalkFrame(const Common::Point& pos, const WalkNode* from);
void clipMove(Common::Point& pos, const WalkNode* from);
@@ -333,16 +433,20 @@ public:
void sortAnimations();
void freeAnimations();
+ void showSlide(const char *name);
+ void setBackground(const char *background, const char *mask, const char *path);
+ void freeBackground();
+
Table *_globalTable;
Table *_objectsNames;
Table *_zoneTypeNames;
Table *_zoneFlagNames;
- Table *_commandsNames;
Table *_callableNames;
- Table *_instructionNames;
Table *_localFlagNames;
+ void showLabel(Label &label);
+ void hideLabel(uint priority);
public:
int getGameType() const;
@@ -359,21 +463,18 @@ public:
int32 _screenHeight;
int32 _screenSize;
- int32 _screenMaskWidth;
- int32 _screenMaskSize;
- int32 _screenPathWidth;
- int32 _screenPathSize;
+ PathBuffer *_pathBuffer;
SoundMan *_soundMan;
Gfx* _gfx;
- Menu* _menu;
Disk* _disk;
Character _char;
char _characterName[30];
- char _locationNames[120][32];
+ uint32 _localFlags[NUM_LOCATIONS];
+ char _locationNames[NUM_LOCATIONS][32];
int16 _currentLocationIndex;
uint16 _numLocations;
Location _location;
@@ -382,9 +483,16 @@ public:
Common::Point _mousePos;
+ Zone *_activeZone;
+
ZoneList _zones;
AnimationList _animations;
+ Font *_labelFont;
+ Font *_menuFont;
+ Font *_dialogueFont;
+
+
protected: // data
Debugger *_debugger;
@@ -397,8 +505,6 @@ protected: // data
Label* _label;
};
- bool _skipMenu;
-
bool _mouseHidden;
// input-only
@@ -422,11 +528,15 @@ protected: // data
bool _hasLocationSound;
char _locationSound[50];
+ BackgroundInfo *_backgroundInfo;
+
+ Job *_jDrawLabel;
+ Job *_jEraseLabel;
+ Zone *_hoverZone;
protected: // members
bool detectGame(void);
- void initGame();
void initGlobals();
void runGame();
uint32 getElapsedTime();
@@ -435,34 +545,20 @@ protected: // members
InputData *translateInput();
void processInput(InputData*);
- int buildSaveFileList(Common::StringList& l);
- int selectSaveFile(uint16 arg_0, const char* caption, const char* button);
- void doLoadGame(uint16 slot);
- void doSaveGame(uint16 slot, const char* name);
-
void doLocationEnterTransition();
- void changeLocation(char *location);
- void showSlide(const char *name);
- void resolveLocationForwards();
+ virtual void changeLocation(char *location) = 0;
+ virtual void changeCharacter(const char *name) = 0;
+ void allocateLocationSlot(const char *name);
+ void finalizeLocationParsing();
void switchBackground(const char* background, const char* mask);
void freeLocation();
+ void showLocationComment(const char *text, bool end);
- void parseZone(Script &script, ZoneList &list, char *name);
- void parseZoneTypeBlock(Script &script, Zone *z);
void displayCharacterComment(ExamineData *data);
void displayItemComment(ExamineData *data);
- void parseWalkNodes(Script& script, WalkNodeList &list);
- void initWalk();
uint16 checkDoor();
- Animation * parseAnimation(Script &script, AnimationList &list, char *name);
- void parseScriptLine(Instruction *inst, Animation *a, LocalVariable *locals);
- void loadProgram(Animation *a, char *filename);
- LValue getLValue(Instruction *inst, char *str, LocalVariable *locals, Animation *a);
-
- void parseCommands(Script &script, CommandList&);
-
void freeCharacter();
int addInventoryItem(uint16 item);
@@ -473,6 +569,23 @@ protected: // members
public:
virtual void callFunction(uint index, void* parm) { }
+ virtual void renderLabel(Graphics::Surface *cnv, char *text) { }
+ virtual void setMousePointer(int16 index) = 0;
+
+
+ virtual void parseLocation(const char* name) = 0;
+
+ virtual void jobDisplayAnimations(void*, Job *j) = 0;
+ virtual void jobEraseAnimations(void *arg_0, Job *j) = 0;
+ virtual void jobRunScripts(void*, Job *j) = 0;
+ virtual void jobDisplayDroppedItem(void*, Job *j) = 0;
+ virtual void jobRemovePickedItem(void*, Job *j) = 0;
+ virtual void jobToggleDoor(void*, Job *j) = 0;
+ virtual void jobWalk(void*, Job *j) = 0;
+ virtual void jobDisplayLabel(void *parm, Job *j) = 0;
+ virtual void jobEraseLabel(void *parm, Job *j) = 0;
+ virtual void jobWaitRemoveJob(void *parm, Job *j) = 0;
+
public:
const char **_zoneFlagNamesRes;
@@ -483,21 +596,54 @@ public:
};
+
class Parallaction_ns : public Parallaction {
public:
Parallaction_ns(OSystem* syst) : Parallaction(syst) { }
- ~Parallaction_ns() { }
+ ~Parallaction_ns();
int init();
+ int go();
public:
typedef void (Parallaction_ns::*Callable)(void*);
virtual void callFunction(uint index, void* parm);
+ void renderLabel(Graphics::Surface *cnv, char *text);
+ void setMousePointer(int16 index);
+
+ void initJobs();
+
+ typedef void (Parallaction_ns::*JobFn)(void*, Job*);
+
+ const JobFn *_jobsFn;
+ JobOpcode* createJobOpcode(uint functionId, Job *job);
+
+ void loadGame();
+ void saveGame();
+
private:
- void initResources();
+ Menu* _menu;
+
+ void initFonts();
+ void freeFonts();
+
+private:
+ void changeLocation(char *location);
+ void changeCharacter(const char *name);
+
+ void doLoadGame(uint16 slot);
+ void doSaveGame(uint16 slot, const char* name);
+ int buildSaveFileList(Common::StringList& l);
+ int selectSaveFile(uint16 arg_0, const char* caption, const char* button);
+
+ void initResources();
+ void initCursors();
+
+ static byte _mouseArrow[256];
+ Graphics::Surface *_mouseComposedArrow;
static const Callable _dosCallables[25];
static const Callable _amigaCallables[25];
@@ -536,26 +682,266 @@ private:
void _c_HBOn(void*);
const Callable *_callables;
+
+protected:
+ void jobDisplayAnimations(void*, Job *j);
+ void jobEraseAnimations(void *arg_0, Job *j);
+ void jobRunScripts(void*, Job *j);
+ void jobDisplayDroppedItem(void*, Job *j);
+ void jobRemovePickedItem(void*, Job *j);
+ void jobToggleDoor(void*, Job *j);
+ void jobWalk(void*, Job *j);
+ void jobDisplayLabel(void *parm, Job *j);
+ void jobEraseLabel(void *parm, Job *j);
+ void jobWaitRemoveJob(void *parm, Job *j);
+ void jobShowInventory(void *parm, Job *j);
+ void jobHideInventory(void *parm, Job *j);
+
+ // location parser
+ OpcodeSet _locationParsers;
+ OpcodeSet _locationZoneParsers;
+ OpcodeSet _locationAnimParsers;
+ OpcodeSet _commandParsers;
+ Table *_commandsNames;
+ Table *_locationStmt;
+ Table *_locationZoneStmt;
+ Table *_locationAnimStmt;
+
+ struct LocationParserContext {
+ bool end;
+
+ const char *filename;
+ Script *script;
+ Zone *z;
+ Animation *a;
+ int nextToken;
+ CommandList *list;
+ bool endcommands;
+ Command *cmd;
+
+ // BRA specific
+ int numZones;
+ } _locParseCtxt;
+
+ DECLARE_UNQUALIFIED_LOCATION_PARSER(invalid);
+ DECLARE_UNQUALIFIED_LOCATION_PARSER(endlocation);
+ DECLARE_UNQUALIFIED_LOCATION_PARSER(location);
+ DECLARE_UNQUALIFIED_LOCATION_PARSER(disk);
+ DECLARE_UNQUALIFIED_LOCATION_PARSER(nodes);
+ DECLARE_UNQUALIFIED_LOCATION_PARSER(zone);
+ DECLARE_UNQUALIFIED_LOCATION_PARSER(animation);
+ DECLARE_UNQUALIFIED_LOCATION_PARSER(localflags);
+ DECLARE_UNQUALIFIED_LOCATION_PARSER(commands);
+ DECLARE_UNQUALIFIED_LOCATION_PARSER(acommands);
+ DECLARE_UNQUALIFIED_LOCATION_PARSER(flags);
+ DECLARE_UNQUALIFIED_LOCATION_PARSER(comment);
+ DECLARE_UNQUALIFIED_LOCATION_PARSER(endcomment);
+ DECLARE_UNQUALIFIED_LOCATION_PARSER(sound);
+ DECLARE_UNQUALIFIED_LOCATION_PARSER(music);
+ DECLARE_UNQUALIFIED_LOCATION_PARSER(redundant);
+ DECLARE_UNQUALIFIED_ZONE_PARSER(invalid);
+ DECLARE_UNQUALIFIED_ZONE_PARSER(limits);
+ DECLARE_UNQUALIFIED_ZONE_PARSER(moveto);
+ DECLARE_UNQUALIFIED_ZONE_PARSER(type);
+ DECLARE_UNQUALIFIED_ZONE_PARSER(commands);
+ DECLARE_UNQUALIFIED_ZONE_PARSER(label);
+ DECLARE_UNQUALIFIED_ZONE_PARSER(flags);
+ DECLARE_UNQUALIFIED_ZONE_PARSER(endzone);
+ DECLARE_UNQUALIFIED_ANIM_PARSER(invalid);
+ DECLARE_UNQUALIFIED_ANIM_PARSER(script);
+ DECLARE_UNQUALIFIED_ANIM_PARSER(commands);
+ DECLARE_UNQUALIFIED_ANIM_PARSER(type);
+ DECLARE_UNQUALIFIED_ANIM_PARSER(label);
+ DECLARE_UNQUALIFIED_ANIM_PARSER(flags);
+ DECLARE_UNQUALIFIED_ANIM_PARSER(file);
+ DECLARE_UNQUALIFIED_ANIM_PARSER(position);
+ DECLARE_UNQUALIFIED_ANIM_PARSER(moveto);
+ DECLARE_UNQUALIFIED_ANIM_PARSER(endanimation);
+ DECLARE_UNQUALIFIED_COMMAND_PARSER(invalid);
+ DECLARE_UNQUALIFIED_COMMAND_PARSER(flags);
+ DECLARE_UNQUALIFIED_COMMAND_PARSER(animation);
+ DECLARE_UNQUALIFIED_COMMAND_PARSER(zone);
+ DECLARE_UNQUALIFIED_COMMAND_PARSER(location);
+ DECLARE_UNQUALIFIED_COMMAND_PARSER(drop);
+ DECLARE_UNQUALIFIED_COMMAND_PARSER(call);
+ DECLARE_UNQUALIFIED_COMMAND_PARSER(simple);
+ DECLARE_UNQUALIFIED_COMMAND_PARSER(move);
+ DECLARE_UNQUALIFIED_COMMAND_PARSER(endcommands);
+
+ virtual void parseGetData(Script &script, Zone *z);
+ virtual void parseExamineData(Script &script, Zone *z);
+ virtual void parseDoorData(Script &script, Zone *z);
+ virtual void parseMergeData(Script &script, Zone *z);
+ virtual void parseHearData(Script &script, Zone *z);
+ virtual void parseSpeakData(Script &script, Zone *z);
+
+ void parseLocation(const char *filename);
+ char *parseComment(Script &script);
+ char *parseDialogueString(Script &script);
+ Dialogue *parseDialogue(Script &script);
+ void parseZone(Script &script, ZoneList &list, char *name);
+ void parseZoneTypeBlock(Script &script, Zone *z);
+ void parseWalkNodes(Script& script, WalkNodeList &list);
+ Animation *parseAnimation(Script &script, AnimationList &list, char *name);
+ void parseCommands(Script &script, CommandList&);
+ void parseCommandFlags();
+ void createCommand(uint id);
+ void addCommand();
+ void initOpcodes();
+ void initParsers();
+
+
+ // program parser
+ OpcodeSet _instructionParsers;
+ Table *_instructionNames;
+
+ struct {
+ bool end;
+ Animation *a;
+ Instruction *inst;
+ LocalVariable *locals;
+ Program *program;
+
+ // BRA specific
+ Instruction *openIf;
+ } _instParseCtxt;
+
+ DECLARE_UNQUALIFIED_INSTRUCTION_PARSER(defLocal);
+ DECLARE_UNQUALIFIED_INSTRUCTION_PARSER(animation);
+ DECLARE_UNQUALIFIED_INSTRUCTION_PARSER(loop);
+ DECLARE_UNQUALIFIED_INSTRUCTION_PARSER(x);
+ DECLARE_UNQUALIFIED_INSTRUCTION_PARSER(y);
+ DECLARE_UNQUALIFIED_INSTRUCTION_PARSER(z);
+ DECLARE_UNQUALIFIED_INSTRUCTION_PARSER(f);
+ DECLARE_UNQUALIFIED_INSTRUCTION_PARSER(inc);
+ DECLARE_UNQUALIFIED_INSTRUCTION_PARSER(set);
+ DECLARE_UNQUALIFIED_INSTRUCTION_PARSER(move);
+ DECLARE_UNQUALIFIED_INSTRUCTION_PARSER(put);
+ DECLARE_UNQUALIFIED_INSTRUCTION_PARSER(call);
+ DECLARE_UNQUALIFIED_INSTRUCTION_PARSER(sound);
+ DECLARE_UNQUALIFIED_INSTRUCTION_PARSER(null);
+ DECLARE_UNQUALIFIED_INSTRUCTION_PARSER(endscript);
+
+ void parseInstruction(Animation *a, LocalVariable *locals);
+ void loadProgram(Animation *a, const char *filename);
+ void parseLValue(ScriptVar &var, const char *str);
+ virtual void parseRValue(ScriptVar &var, const char *str);
+ void wrapLocalVar(LocalVariable *local);
+
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(invalid);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(set);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(clear);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(start);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(speak);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(get);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(location);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(open);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(close);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(on);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(off);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(call);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(toggle);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(drop);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(quit);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(move);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(stop);
+
+ DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(invalid);
+ DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(on);
+ DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(off);
+ DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(loop);
+ DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(endloop);
+ DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(null);
+ DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(call);
+ DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(inc);
+ DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(set);
+ DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(put);
+ DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(wait);
+ DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(start);
+ DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(sound);
+ DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(move);
+ DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(endscript);
+
};
-class Parallaction_br : public Parallaction {
+
+
+#define NUM_ZONES 100
+
+class Parallaction_br : public Parallaction_ns {
+
+ typedef Parallaction_ns Super;
public:
- Parallaction_br(OSystem* syst) : Parallaction(syst) { }
- ~Parallaction_br() { }
+ Parallaction_br(OSystem* syst) : Parallaction_ns(syst) { }
+ ~Parallaction_br();
int init();
+ int go();
public:
typedef void (Parallaction_br::*Callable)(void*);
virtual void callFunction(uint index, void* parm);
public:
+ Table *_countersNames;
+
Table *_audioCommandsNames;
const char **_audioCommandsNamesRes;
+ int _part;
+ int _progress;
+
+ int _zeta0;
+ int _zeta1;
+ int _zeta2;
+
+ int16 _lipSyncVal;
+ uint _subtitleLipSync;
+
+ Label _subtitle0;
+ Label _subtitle1;
+
+ Zone *_activeZone2;
+
+ int32 _counters[32];
+
+ uint32 _zoneFlags[NUM_LOCATIONS][NUM_ZONES];
+
private:
void initResources();
+ void initFonts();
+ void freeFonts();
+ void initOpcodes();
+ void initParsers();
+ void initJobs();
+
+ typedef void (Parallaction_br::*JobFn)(void*, Job*);
+ const JobFn *_jobsFn;
+ JobOpcode* createJobOpcode(uint functionId, Job *job);
+
+
+ void changeLocation(char *location);
+ void changeCharacter(const char *name);
+
+ void initPart();
+ void freePart();
+ void startPart();
+
+ void setMousePointer(int16 index);
+ void initCursors();
+
+ Graphics::Surface *_dinoCursor;
+ Graphics::Surface *_dougCursor;
+ Graphics::Surface *_donnaCursor;
+ Graphics::Surface *_mouseArrow;
+
+
+ int showMenu();
+ void renderMenuItem(Graphics::Surface &surf, const char *text);
+ void invertMenuItem(Graphics::Surface &surf);
+
+ void splash(const char *name);
static const Callable _dosCallables[6];
@@ -567,6 +953,130 @@ private:
void _c_password(void*);
const Callable *_callables;
+
+ DECLARE_UNQUALIFIED_LOCATION_PARSER(location);
+ DECLARE_UNQUALIFIED_LOCATION_PARSER(zone);
+ DECLARE_UNQUALIFIED_LOCATION_PARSER(animation);
+ DECLARE_UNQUALIFIED_LOCATION_PARSER(localflags);
+ DECLARE_UNQUALIFIED_LOCATION_PARSER(flags);
+ DECLARE_UNQUALIFIED_LOCATION_PARSER(comment);
+ DECLARE_UNQUALIFIED_LOCATION_PARSER(endcomment);
+ DECLARE_UNQUALIFIED_LOCATION_PARSER(sound);
+ DECLARE_UNQUALIFIED_LOCATION_PARSER(music);
+ DECLARE_UNQUALIFIED_LOCATION_PARSER(redundant);
+ DECLARE_UNQUALIFIED_LOCATION_PARSER(ifchar);
+ DECLARE_UNQUALIFIED_LOCATION_PARSER(character);
+ DECLARE_UNQUALIFIED_LOCATION_PARSER(mask);
+ DECLARE_UNQUALIFIED_LOCATION_PARSER(path);
+ DECLARE_UNQUALIFIED_LOCATION_PARSER(escape);
+ DECLARE_UNQUALIFIED_LOCATION_PARSER(zeta);
+ DECLARE_UNQUALIFIED_LOCATION_PARSER(null);
+ DECLARE_UNQUALIFIED_COMMAND_PARSER(ifchar);
+ DECLARE_UNQUALIFIED_COMMAND_PARSER(endif);
+ DECLARE_UNQUALIFIED_COMMAND_PARSER(zone);
+ DECLARE_UNQUALIFIED_COMMAND_PARSER(location);
+ DECLARE_UNQUALIFIED_COMMAND_PARSER(toggle);
+ DECLARE_UNQUALIFIED_COMMAND_PARSER(string);
+ DECLARE_UNQUALIFIED_COMMAND_PARSER(math);
+ DECLARE_UNQUALIFIED_COMMAND_PARSER(test);
+ DECLARE_UNQUALIFIED_COMMAND_PARSER(music);
+ DECLARE_UNQUALIFIED_COMMAND_PARSER(zeta);
+ DECLARE_UNQUALIFIED_COMMAND_PARSER(swap);
+ DECLARE_UNQUALIFIED_COMMAND_PARSER(give);
+ DECLARE_UNQUALIFIED_COMMAND_PARSER(text);
+ DECLARE_UNQUALIFIED_COMMAND_PARSER(unary);
+
+ void parseLocation(const char* name);
+
+ DECLARE_UNQUALIFIED_INSTRUCTION_PARSER(zone);
+ DECLARE_UNQUALIFIED_INSTRUCTION_PARSER(color);
+ DECLARE_UNQUALIFIED_INSTRUCTION_PARSER(mask);
+ DECLARE_UNQUALIFIED_INSTRUCTION_PARSER(print);
+ DECLARE_UNQUALIFIED_INSTRUCTION_PARSER(text);
+ DECLARE_UNQUALIFIED_INSTRUCTION_PARSER(if_op);
+ DECLARE_UNQUALIFIED_INSTRUCTION_PARSER(endif);
+
+ virtual void parseRValue(ScriptVar &var, const char *str);
+
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(location);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(open);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(close);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(on);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(off);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(call);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(drop);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(move);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(start);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(stop);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(character);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(followme);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(onmouse);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(offmouse);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(add);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(leave);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(inc);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(dec);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(ifeq);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(iflt);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(ifgt);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(let);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(music);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(fix);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(unfix);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(zeta);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(scroll);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(swap);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(give);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(text);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(part);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(testsfx);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(ret);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(onsave);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(offsave);
+ DECLARE_UNQUALIFIED_ZONE_PARSER(limits);
+ DECLARE_UNQUALIFIED_ZONE_PARSER(moveto);
+ DECLARE_UNQUALIFIED_ZONE_PARSER(type);
+ DECLARE_UNQUALIFIED_ANIM_PARSER(file);
+ DECLARE_UNQUALIFIED_ANIM_PARSER(position);
+ DECLARE_UNQUALIFIED_ANIM_PARSER(moveto);
+ DECLARE_UNQUALIFIED_ANIM_PARSER(endanimation);
+
+ DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(on);
+ DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(off);
+ DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(loop);
+ DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(inc);
+ DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(dec);
+ DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(set);
+ DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(put);
+ DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(wait);
+ DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(start);
+ DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(process);
+ DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(move);
+ DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(color);
+ DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(mask);
+ DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(print);
+ DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(text);
+ DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(mul);
+ DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(div);
+ DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(ifeq);
+ DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(iflt);
+ DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(ifgt);
+ DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(endif);
+ DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(stop);
+ DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(endscript);
+
+ Job *_jDisplaySubtitle;
+ Job *_jEraseSubtitle;
+ void setupSubtitles(char *s, char *s2, int y);
+
+ void jobWaitRemoveLabelJob(void *parm, Job *job);
+ void jobDisplaySubtitle(void *parm, Job *job);
+ void jobEraseSubtitle(void *parm, Job *job);
+ void jobWaitRemoveSubtitleJob(void *parm, Job *job);
+ void jobPauseSfx(void *parm, Job *job);
+ void jobStopFollower(void *parm, Job *job);
+ void jobScroll(void *parm, Job *job);
+
};
// FIXME: remove global
diff --git a/engines/parallaction/parallaction_br.cpp b/engines/parallaction/parallaction_br.cpp
index 7dcc94d7c6..f2b9626ead 100644
--- a/engines/parallaction/parallaction_br.cpp
+++ b/engines/parallaction/parallaction_br.cpp
@@ -24,11 +24,39 @@
*/
#include "common/stdafx.h"
+#include "common/system.h"
+
#include "parallaction/parallaction.h"
#include "parallaction/sound.h"
namespace Parallaction {
+enum MenuOptions {
+ kMenuPart0 = 0,
+ kMenuPart1 = 1,
+ kMenuPart2 = 2,
+ kMenuPart3 = 3,
+ kMenuPart4 = 4,
+ kMenuLoadGame = 5,
+ kMenuQuit = 6
+};
+
+const char *partNames[] = {
+ "PART0",
+ "PART1",
+ "PART2",
+ "PART3",
+ "PART4"
+};
+
+const char *partFirstLocation[] = {
+ "intro",
+ "museo",
+ "start",
+ "bolscoi",
+ "treno"
+};
+
int Parallaction_br::init() {
// Detect game
@@ -43,6 +71,7 @@ int Parallaction_br::init() {
if (getGameType() == GType_BRA) {
if (getPlatform() == Common::kPlatformPC) {
_disk = new DosDisk_br(this);
+ _disk->setLanguage(2); // NOTE: language is now hardcoded to English. Original used command-line parameters.
} else
error("unsupported platform for Big Red Adventure");
} else
@@ -50,17 +79,311 @@ int Parallaction_br::init() {
_soundMan = new DummySoundMan(this);
+ _activeZone2 = 0;
+
+ initJobs();
initResources();
+ initFonts();
+ initCursors();
+ initOpcodes();
+ initParsers();
+
+ _part = -1;
Parallaction::init();
return 0;
}
+Parallaction_br::~Parallaction_br() {
+ freeFonts();
+
+ _dinoCursor->free();
+ _dougCursor->free();
+ _donnaCursor->free();
+
+ delete _dinoCursor;
+ delete _dougCursor;
+ delete _donnaCursor;
+
+}
+
void Parallaction_br::callFunction(uint index, void* parm) {
assert(index < 6); // magic value 6 is maximum # of callables for Big Red Adventure
(this->*_callables[index])(parm);
}
+int Parallaction_br::go() {
+ splash("dyna");
+ splash("core");
+
+ // TODO: load progress value from special save game
+ _progress = 3;
+
+ while ((_engineFlags & kEngineQuit) == 0) {
+
+// initCharacter();
+
+ int option = showMenu();
+ switch (option) {
+ case kMenuQuit:
+ _engineFlags |= kEngineQuit;
+ break;
+
+ case kMenuLoadGame:
+ warning("loadgame not yet implemented");
+ break;
+
+ default:
+ _part = option;
+ _disk->selectArchive(partNames[_part]);
+ startPart();
+ break;
+ }
+
+
+ runGame();
+
+ freePart();
+// freeLocation();
+// freeCharacter();
+
+ }
+
+ return 0;
+}
+
+void Parallaction_br::splash(const char *name) {
+
+ BackgroundInfo info;
+
+ _gfx->clearScreen(Gfx::kBitFront);
+
+ _disk->loadSlide(info, name);
+ _gfx->setPalette(info.palette);
+ _gfx->flatBlitCnv(&info.bg, (640 - info.width) >> 1, (400 - info.height) >> 1, Gfx::kBitFront);
+ _gfx->updateScreen();
+ _system->delayMillis(600);
+
+ Palette pal;
+ for (uint i = 0; i < 64; i++) {
+ info.palette.fadeTo(pal, 1);
+ _gfx->setPalette(info.palette);
+ _gfx->updateScreen();
+ _system->delayMillis(20);
+ }
+ info.bg.free();
+
+ return;
+}
+
+#define MENUITEMS_X 250
+#define MENUITEMS_Y 200
+
+#define MENUITEM_WIDTH 190
+#define MENUITEM_HEIGHT 18
+
+void Parallaction_br::renderMenuItem(Graphics::Surface &surf, const char *text) {
+ surf.create(MENUITEM_WIDTH, MENUITEM_HEIGHT, 1);
+ _menuFont->setColor(0);
+ _menuFont->drawString((byte*)surf.getBasePtr(5, 2), MENUITEM_WIDTH, text);
+}
+
+void Parallaction_br::invertMenuItem(Graphics::Surface &surf) {
+ for (int i = 0; i < surf.w * surf.h; i++)
+ ((byte*)surf.pixels)[i] ^= 0xD;
+}
+
+int Parallaction_br::showMenu() {
+ // TODO: filter menu entries according to progress in game
+
+ _gfx->clearScreen(Gfx::kBitFront);
+
+ BackgroundInfo info;
+
+ Graphics::Surface _menuItems[7];
+
+ const char *menuStrings[7] = {
+ "SEE INTRO",
+ "NEW GAME",
+ "SAVED GAME",
+ "EXIT TO DOS",
+ "PART 2",
+ "PART 3",
+ "PART 4"
+ };
+
+ MenuOptions options[7] = {
+ kMenuPart0,
+ kMenuPart1,
+ kMenuLoadGame,
+ kMenuQuit,
+ kMenuPart2,
+ kMenuPart3,
+ kMenuPart4
+ };
+
+ _disk->loadSlide(info, "tbra");
+ _gfx->setPalette(info.palette);
+ _gfx->flatBlitCnv(&info.bg, 20, 50, Gfx::kBitFront);
+
+ int availItems = 4 + _progress;
+
+ for (int i = 0; i < availItems; i++)
+ renderMenuItem(_menuItems[i], menuStrings[i]);
+
+ int selectedItem = -1, oldSelectedItem = -2;
+
+ setMousePointer(0);
+
+ while (true) {
+
+ if ((_mouseButtons == kMouseLeftUp) && selectedItem >= 0)
+ break;
+
+ updateInput();
+
+ if ((_mousePos.x > MENUITEMS_X) && (_mousePos.x < (MENUITEMS_X+MENUITEM_WIDTH)) && (_mousePos.y > MENUITEMS_Y)) {
+ selectedItem = (_mousePos.y - MENUITEMS_Y) / MENUITEM_HEIGHT;
+
+ if (!(selectedItem < availItems))
+ selectedItem = -1;
+ } else
+ selectedItem = -1;
+
+
+ if (selectedItem != oldSelectedItem) {
+
+ if (selectedItem >= 0 && selectedItem < availItems)
+ invertMenuItem(_menuItems[selectedItem]);
+
+ if (oldSelectedItem >= 0 && oldSelectedItem < availItems)
+ invertMenuItem(_menuItems[oldSelectedItem]);
+
+ Common::Rect r(MENUITEM_WIDTH, MENUITEM_HEIGHT);
+
+ for (int i = 0; i < availItems; i++) {
+ r.moveTo(MENUITEMS_X, MENUITEMS_Y + i * 20);
+ _gfx->copyRect(Gfx::kBitFront, r, (byte*)_menuItems[i].pixels, _menuItems[i].pitch);
+ }
+
+ oldSelectedItem = selectedItem;
+ }
+
+ _gfx->updateScreen();
+ _system->delayMillis(20);
+ }
+
+ _system->showMouse(false);
+
+ info.bg.free();
+
+ for (int i = 0; i < availItems; i++)
+ _menuItems[i].free();
+
+ return options[selectedItem];
+}
+
+
+void Parallaction_br::initFonts() {
+
+ _menuFont = _disk->loadFont("russia");
+ _dialogueFont = _disk->loadFont("comic");
+ _labelFont = _menuFont;
+
+}
+
+void Parallaction_br::freeFonts() {
+
+ delete _menuFont;
+ delete _dialogueFont;
+
+ return;
+}
+
+void Parallaction_br::initCursors() {
+
+ _dinoCursor = _disk->loadPointer("pointer1");
+ _dougCursor = _disk->loadPointer("pointer2");
+ _donnaCursor = _disk->loadPointer("pointer3");
+
+ _mouseArrow = _donnaCursor;
+
+}
+
+void Parallaction_br::setMousePointer(int16 index) {
+
+ _system->setMouseCursor((byte*)_mouseArrow->pixels, _mouseArrow->w, _mouseArrow->h, 0, 0, 0);
+ _system->showMouse(true);
+
+}
+
+void Parallaction_br::initPart() {
+
+ memset(_counters, 0, ARRAYSIZE(_counters));
+
+ _globalTable = _disk->loadTable("global");
+ _objectsNames = _disk->loadTable("objects");
+ _countersNames = _disk->loadTable("counters");
+
+// _disk->loadObjects("icone.ico");
+
+}
+
+void Parallaction_br::freePart() {
+
+ delete _globalTable;
+ delete _objectsNames;
+ delete _countersNames;
+
+}
+
+void Parallaction_br::startPart() {
+
+ initPart();
+
+ strcpy(_location._name, partFirstLocation[_part]);
+
+ parseLocation("common");
+ parseLocation(_location._name);
+
+}
+
+void Parallaction_br::changeLocation(char *location) {
+
+}
+
+void Parallaction_br::changeCharacter(const char *name) {
+
+}
+
+void Parallaction_br::initJobs() {
+
+ static const JobFn jobs[] = {
+ &Parallaction_br::jobDisplayAnimations,
+ &Parallaction_br::jobEraseAnimations,
+ &Parallaction_br::jobDisplayDroppedItem,
+ &Parallaction_br::jobRemovePickedItem,
+ &Parallaction_br::jobRunScripts,
+ &Parallaction_br::jobWalk,
+ &Parallaction_br::jobDisplayLabel,
+ &Parallaction_br::jobEraseLabel,
+ &Parallaction_br::jobWaitRemoveLabelJob,
+ &Parallaction_br::jobToggleDoor,
+ &Parallaction_br::jobEraseSubtitle,
+ &Parallaction_br::jobDisplaySubtitle,
+ &Parallaction_br::jobWaitRemoveSubtitleJob,
+ &Parallaction_br::jobPauseSfx,
+ &Parallaction_br::jobStopFollower,
+ &Parallaction_br::jobScroll
+ };
+
+ _jobsFn = jobs;
+}
+
+JobOpcode* Parallaction_br::createJobOpcode(uint functionId, Job *job) {
+ return new OpcodeImpl2<Parallaction_br>(this, _jobsFn[functionId], job);
+}
+
} // namespace Parallaction
diff --git a/engines/parallaction/parallaction_ns.cpp b/engines/parallaction/parallaction_ns.cpp
index 947cb22a7f..46161c5021 100644
--- a/engines/parallaction/parallaction_ns.cpp
+++ b/engines/parallaction/parallaction_ns.cpp
@@ -24,13 +24,23 @@
*/
#include "common/stdafx.h"
+#include "common/system.h"
+
#include "common/config-manager.h"
#include "parallaction/parallaction.h"
#include "parallaction/sound.h"
+#include "parallaction/menu.h"
+
namespace Parallaction {
+#define MOUSEARROW_WIDTH 16
+#define MOUSEARROW_HEIGHT 16
+
+#define MOUSECOMBO_WIDTH 32 // sizes for cursor + selected inventory item
+#define MOUSECOMBO_HEIGHT 32
+
int Parallaction_ns::init() {
// Detect game
@@ -61,13 +71,103 @@ int Parallaction_ns::init() {
_soundMan = new AmigaSoundMan(this);
}
+ initJobs();
initResources();
+ initFonts();
+ initCursors();
+ initOpcodes();
+ initParsers();
Parallaction::init();
return 0;
}
+Parallaction_ns::~Parallaction_ns() {
+ freeFonts();
+
+ _mouseComposedArrow->free();
+ delete _mouseComposedArrow;
+
+
+ delete _commandsNames;
+ delete _instructionNames;
+ delete _locationStmt;
+
+}
+
+
+void Parallaction_ns::freeFonts() {
+
+ delete _dialogueFont;
+ delete _labelFont;
+ delete _menuFont;
+
+ return;
+}
+
+void Parallaction_ns::renderLabel(Graphics::Surface *cnv, char *text) {
+
+ if (getPlatform() == Common::kPlatformAmiga) {
+ cnv->create(_labelFont->getStringWidth(text) + 16, 10, 1);
+
+ _labelFont->setColor(7);
+ _labelFont->drawString((byte*)cnv->pixels + 1, cnv->w, text);
+ _labelFont->drawString((byte*)cnv->pixels + 1 + cnv->w * 2, cnv->w, text);
+ _labelFont->drawString((byte*)cnv->pixels + cnv->w, cnv->w, text);
+ _labelFont->drawString((byte*)cnv->pixels + 2 + cnv->w, cnv->w, text);
+ _labelFont->setColor(1);
+ _labelFont->drawString((byte*)cnv->pixels + 1 + cnv->w, cnv->w, text);
+ } else {
+ cnv->create(_labelFont->getStringWidth(text), _labelFont->height(), 1);
+ _labelFont->drawString((byte*)cnv->pixels, cnv->w, text);
+ }
+
+}
+
+void Parallaction_ns::initCursors() {
+
+ _mouseComposedArrow = _disk->loadPointer("pointer");
+
+ byte temp[MOUSEARROW_WIDTH*MOUSEARROW_HEIGHT];
+ memcpy(temp, _mouseArrow, MOUSEARROW_WIDTH*MOUSEARROW_HEIGHT);
+
+ uint16 k = 0;
+ for (uint16 i = 0; i < 4; i++) {
+ for (uint16 j = 0; j < 64; j++) _mouseArrow[k++] = temp[i + j * 4];
+ }
+
+ return;
+}
+
+void Parallaction_ns::setMousePointer(int16 index) {
+
+ if (index == kCursorArrow) { // standard mouse pointer
+
+ _system->setMouseCursor(_mouseArrow, MOUSEARROW_WIDTH, MOUSEARROW_HEIGHT, 0, 0, 0);
+ _system->showMouse(true);
+
+ } else {
+ // inventory item pointer
+ byte *v8 = (byte*)_mouseComposedArrow->pixels;
+
+ // FIXME: destination offseting is not clear
+ byte* s = _char._objs->getData(getInventoryItemIndex(index));
+ byte* d = v8 + 7 + MOUSECOMBO_WIDTH * 7;
+
+ for (uint i = 0; i < INVENTORYITEM_HEIGHT; i++) {
+ memcpy(d, s, INVENTORYITEM_WIDTH);
+
+ s += INVENTORYITEM_PITCH;
+ d += MOUSECOMBO_WIDTH;
+ }
+
+ _system->setMouseCursor(v8, MOUSECOMBO_WIDTH, MOUSECOMBO_HEIGHT, 0, 0, 0);
+ }
+
+ return;
+}
+
void Parallaction_ns::callFunction(uint index, void* parm) {
assert(index < 25); // magic value 25 is maximum # of callables for Nippon Safes
@@ -75,4 +175,232 @@ void Parallaction_ns::callFunction(uint index, void* parm) {
}
+int Parallaction_ns::go() {
+
+ _menu = new Menu(this);
+ _menu->start();
+
+ char *v4 = strchr(_location._name, '.');
+ if (v4) {
+ *v4 = '\0';
+ }
+
+ _globalTable = _disk->loadTable("global");
+
+ _engineFlags &= ~kEngineChangeLocation;
+ changeCharacter(_characterName);
+
+ strcpy(_saveData1, _location._name);
+ parseLocation(_location._name);
+
+ if (_location._startPosition.x != -1000) {
+ _char._ani._left = _location._startPosition.x;
+ _char._ani._top = _location._startPosition.y;
+ _char._ani._frame = _location._startFrame;
+ _location._startPosition.y = -1000;
+ _location._startPosition.x = -1000;
+ };
+
+ runGame();
+
+ delete _menu;
+
+ return 0;
+}
+
+
+/*
+ changeLocation handles transitions between locations, and is able to display slides
+ between one and the other. The input parameter 'location' exists in some flavours:
+
+ 1 - [S].slide.[L]{.[C]}
+ 2 - [L]{.[C]}
+
+ where:
+
+ [S] is the slide to be shown
+ [L] is the location to switch to (immediately in case 2, or right after slide [S] in case 1)
+ [C] is the character to be selected, and is optional
+
+ The routine tells one form from the other by searching for the '.slide.'
+
+ NOTE: there exists one script in which [L] is not used in the case 1, but its use
+ is commented out, and would definitely crash the current implementation.
+*/
+void Parallaction_ns::changeLocation(char *location) {
+ debugC(1, kDebugExec, "changeLocation(%s)", location);
+
+ _soundMan->playLocationMusic(location);
+
+ // WORKAROUND: this hideLabel has been added to avoid crashes caused by
+ // execution of label jobs after a location switch. The other workaround in
+ // Parallaction::runGame should have been rendered useless by this one.
+ hideLabel(kPriority99);
+
+ _hoverZone = NULL;
+ if (_engineFlags & kEngineBlockInput) {
+ changeCursor( kCursorArrow );
+ }
+
+ _animations.remove(&_char._ani);
+
+ freeLocation();
+ char buf[100];
+ strcpy(buf, location);
+
+ Common::StringList list;
+ char *tok = strtok(location, ".");
+ while (tok) {
+ list.push_back(tok);
+ tok = strtok(NULL, ".");
+ }
+
+ if (list.size() < 1 || list.size() > 4)
+ error("changeLocation: ill-formed location string '%s'", location);
+
+ if (list.size() > 1) {
+ if (list[1] == "slide") {
+ showSlide(list[0].c_str());
+ _gfx->setFont(_menuFont);
+ _gfx->displayCenteredString(14, _slideText[0]); // displays text on screen
+ _gfx->updateScreen();
+ waitUntilLeftClick();
+
+ list.remove_at(0); // removes slide name
+ list.remove_at(0); // removes 'slide'
+ }
+
+ // list is now only [L].{[C]} (see above comment)
+ if (list.size() == 2) {
+ changeCharacter(list[1].c_str());
+ strcpy(_characterName, list[1].c_str());
+ }
+ }
+
+ _animations.push_front(&_char._ani);
+
+ strcpy(_saveData1, list[0].c_str());
+ parseLocation(list[0].c_str());
+
+ _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;
+ _location._startPosition.y = -1000;
+ _location._startPosition.x = -1000;
+ }
+
+
+ _gfx->copyScreen(Gfx::kBitBack, Gfx::kBitFront);
+ _gfx->copyScreen(Gfx::kBitBack, Gfx::kBit2);
+ _gfx->setBlackPalette();
+ _gfx->updateScreen();
+
+ if (_location._commands.size() > 0) {
+ runCommands(_location._commands);
+ runJobs();
+ _gfx->swapBuffers();
+ runJobs();
+ _gfx->swapBuffers();
+ }
+
+ if (_location._comment) {
+ doLocationEnterTransition();
+ }
+
+ runJobs();
+ _gfx->swapBuffers();
+
+ _gfx->setPalette(_gfx->_palette);
+ if (_location._aCommands.size() > 0) {
+ runCommands(_location._aCommands);
+ }
+
+ if (_hasLocationSound)
+ _soundMan->playSfx(_locationSound, 0, true);
+
+ debugC(1, kDebugExec, "changeLocation() done");
+
+ return;
+
+}
+
+void Parallaction_ns::changeCharacter(const char *name) {
+ debugC(1, kDebugExec, "changeCharacter(%s)", name);
+
+ char baseName[20];
+ if (IS_MINI_CHARACTER(name)) {
+ strcpy(baseName, name+4);
+ } else {
+ strcpy(baseName, name);
+ }
+
+ char fullName[20];
+ strcpy(fullName, name);
+ if (_engineFlags & kEngineTransformedDonna)
+ strcat(fullName, "tras");
+
+ if (scumm_stricmp(fullName, _characterName1)) {
+
+ // freeCharacter takes responsibility for checking
+ // character for sanity before memory is freed
+ freeCharacter();
+
+ Common::String oldArchive = _disk->selectArchive((getFeatures() & GF_LANG_MULT) ? "disk1" : "disk0");
+ _char._ani._cnv = _disk->loadFrames(fullName);
+
+ if (!IS_DUMMY_CHARACTER(name)) {
+ if (getPlatform() == Common::kPlatformAmiga && (getFeatures() & GF_LANG_MULT))
+ _disk->selectArchive("disk0");
+
+ _char._head = _disk->loadHead(baseName);
+ _char._talk = _disk->loadTalk(baseName);
+ _char._objs = _disk->loadObjects(baseName);
+ _objectsNames = _disk->loadTable(baseName);
+
+ _soundMan->playCharacterMusic(name);
+
+ if (!(getFeatures() & GF_DEMO))
+ parseLocation("common");
+ }
+
+ if (!oldArchive.empty())
+ _disk->selectArchive(oldArchive);
+ }
+
+ strcpy(_characterName1, fullName);
+
+ debugC(1, kDebugExec, "changeCharacter() done");
+
+ return;
+}
+
+void Parallaction_ns::initJobs() {
+
+ static const JobFn jobs[] = {
+ &Parallaction_ns::jobDisplayAnimations,
+ &Parallaction_ns::jobEraseAnimations,
+ &Parallaction_ns::jobDisplayDroppedItem,
+ &Parallaction_ns::jobRemovePickedItem,
+ &Parallaction_ns::jobRunScripts,
+ &Parallaction_ns::jobWalk,
+ &Parallaction_ns::jobDisplayLabel,
+ &Parallaction_ns::jobEraseLabel,
+ &Parallaction_ns::jobWaitRemoveJob,
+ &Parallaction_ns::jobToggleDoor,
+ &Parallaction_ns::jobShowInventory,
+ &Parallaction_ns::jobHideInventory
+ };
+
+ _jobsFn = jobs;
+}
+
+JobOpcode* Parallaction_ns::createJobOpcode(uint functionId, Job *job) {
+ return new OpcodeImpl2<Parallaction_ns>(this, _jobsFn[functionId], job);
+}
+
} // namespace Parallaction
diff --git a/engines/parallaction/parser.cpp b/engines/parallaction/parser.cpp
index 44aae6c1cc..dfda083392 100644
--- a/engines/parallaction/parser.cpp
+++ b/engines/parallaction/parser.cpp
@@ -48,7 +48,7 @@ char *Script::readLine(char *buf, size_t bufSize) {
v2 = _input->readSByte();
- if (v2 == 0xA || _input->eos()) break;
+ if (v2 == 0xA || v2 == 0xD || _input->eos()) break;
if (!_input->eos() && _si < bufSize) buf[_si] = v2;
}
@@ -82,34 +82,6 @@ void Script::seek(int32 offset, int whence) {
error("seek not supported on Script streams");
}
-//
-// a comment can appear both at location and Zone levels
-// comments are displayed into rectangles on the screen
-//
-char *Parallaction::parseComment(Script &script) {
-
- char _tmp_comment[1000] = "\0";
- char *v194;
-
- do {
- char v190[400];
- v194 = script.readLine(v190, 400);
-
- v194[strlen(v194)-1] = '\0';
- if (!scumm_stricmp(v194, "endtext"))
- break;
-
- strcat(_tmp_comment, v194);
- strcat(_tmp_comment, " ");
- } while (true);
-
- v194 = (char*)malloc(strlen(_tmp_comment)+1);
- strcpy(v194, _tmp_comment);
- _tmp_comment[0] = '\0';
-
- return v194;
-}
-
void clearTokens() {
for (uint16 i = 0; i < 20; i++)
@@ -119,6 +91,14 @@ void clearTokens() {
}
+void skip(Script* script, const char* endToken) {
+
+ while (scumm_stricmp(_tokens[0], endToken)) {
+ fillBuffers(*script, true);
+ }
+
+}
+
//
// Scans 's' until one of the stop-chars in 'brk' is found, building a token.
// If the routine encounters quotes, it will extract the contained text and
diff --git a/engines/parallaction/parser.h b/engines/parallaction/parser.h
index aa3929a52c..3d1b32ec3a 100644
--- a/engines/parallaction/parser.h
+++ b/engines/parallaction/parser.h
@@ -57,6 +57,9 @@ public:
void seek(int32 offset, int whence = SEEK_SET);
};
+void skip(Script* script, const char* endToken);
+
+
} // namespace Parallaction
#endif
diff --git a/engines/parallaction/parser_br.cpp b/engines/parallaction/parser_br.cpp
new file mode 100644
index 0000000000..94f5b0d790
--- /dev/null
+++ b/engines/parallaction/parser_br.cpp
@@ -0,0 +1,935 @@
+#include "common/stdafx.h"
+
+#include "parallaction/parallaction.h"
+#include "parallaction/sound.h"
+
+namespace Parallaction {
+
+#define CMD_SET 1
+#define CMD_CLEAR 2
+#define CMD_START 3
+#define CMD_SPEAK 4
+#define CMD_GET 5
+#define CMD_LOCATION 6
+#define CMD_OPEN 7
+#define CMD_CLOSE 8
+#define CMD_ON 9
+#define CMD_OFF 10
+#define CMD_CALL 11
+#define CMD_TOGGLE 12
+#define CMD_DROP 13
+#define CMD_QUIT 14
+#define CMD_MOVE 15
+#define CMD_STOP 16
+#define CMD_CHARACTER 17
+#define CMD_FOLLOWME 18
+#define CMD_ONMOUSE 19
+#define CMD_OFFMOUSE 20
+#define CMD_ADD 21
+#define CMD_LEAVE 22
+#define CMD_INC 23
+#define CMD_DEC 24
+#define CMD_TEST 25
+#define CMD_TEST_GT 26
+#define CMD_TEST_LT 27
+#define CMD_LET 28
+#define CMD_MUSIC 29
+#define CMD_FIX 30
+#define CMD_UNFIX 31
+#define CMD_ZETA 32
+#define CMD_SCROLL 33
+#define CMD_SWAP 34
+#define CMD_GIVE 35
+#define CMD_TEXT 36
+#define CMD_PART 37
+#define CMD_TEST_SFX 38
+#define CMD_RETURN 39
+#define CMD_ONSAVE 40
+#define CMD_OFFSAVE 41
+
+
+#define INST_ON 1
+#define INST_OFF 2
+#define INST_X 3
+#define INST_Y 4
+#define INST_Z 5
+#define INST_F 6
+#define INST_LOOP 7
+#define INST_ENDLOOP 8
+#define INST_SHOW 9
+#define INST_INC 10
+#define INST_DEC 11
+#define INST_SET 12
+#define INST_PUT 13
+#define INST_CALL 14
+#define INST_WAIT 15
+#define INST_START 16
+#define INST_PROCESS 17
+#define INST_MOVE 18
+#define INST_COLOR 19
+#define INST_SOUND 20
+#define INST_MASK 21
+#define INST_PRINT 22
+#define INST_TEXT 23
+#define INST_MUL 24
+#define INST_DIV 25
+#define INST_IF 26
+#define INST_IFEQ 27
+#define INST_IFLT 28
+#define INST_IFGT 29
+#define INST_ENDIF 30
+#define INST_STOP 31
+
+#define DECLARE_ZONE_PARSER(sig) void Parallaction_br::locZoneParse_##sig()
+#define DECLARE_ANIM_PARSER(sig) void Parallaction_br::locAnimParse_##sig()
+#define DECLARE_COMMAND_PARSER(sig) void Parallaction_br::cmdParse_##sig()
+#define DECLARE_INSTRUCTION_PARSER(sig) void Parallaction_br::instParse_##sig()
+#define DECLARE_LOCATION_PARSER(sig) void Parallaction_br::locParse_##sig()
+
+
+DECLARE_LOCATION_PARSER(location) {
+ debugC(7, kDebugParser, "LOCATION_PARSER(location) ");
+
+ strcpy(_location._name, _tokens[1]);
+
+ bool flip = false;
+ int nextToken;
+
+ if (!scumm_stricmp("flip", _tokens[2])) {
+ flip = true;
+ nextToken = 3;
+ } else {
+ nextToken = 2;
+ }
+
+ _disk->loadScenery(*_backgroundInfo, _location._name, NULL, NULL);
+
+// if (flip) {
+// flip();
+// }
+
+ _gfx->setBackground(&_backgroundInfo->bg);
+ _gfx->_palette.clone(_backgroundInfo->palette);
+ _gfx->setPalette(_backgroundInfo->palette);
+
+
+ if (_tokens[nextToken][0] != '\0') {
+ _char._ani._left = atoi(_tokens[nextToken]);
+ nextToken++;
+ _char._ani._top = atoi(_tokens[nextToken]);
+ nextToken++;
+ }
+
+ if (_tokens[nextToken][0] != '\0') {
+ _char._ani._frame = atoi(_tokens[nextToken]);
+ }
+}
+
+
+
+DECLARE_LOCATION_PARSER(zone) {
+ debugC(7, kDebugParser, "LOCATION_PARSER(zone) ");
+
+ parseZone(*_locParseCtxt.script, _zones, _tokens[1]);
+
+ _locParseCtxt.z->_index = _locParseCtxt.numZones++;
+
+ if (_localFlags[_currentLocationIndex] & kFlagsVisited) {
+ _locParseCtxt.z->_flags = _zoneFlags[_currentLocationIndex][_locParseCtxt.z->_index];
+ } else {
+ _zoneFlags[_currentLocationIndex][_locParseCtxt.z->_index] = _locParseCtxt.z->_flags;
+ }
+
+}
+
+
+DECLARE_LOCATION_PARSER(animation) {
+ debugC(7, kDebugParser, "LOCATION_PARSER(animation) ");
+
+ parseAnimation(*_locParseCtxt.script, _animations, _tokens[1]);
+
+ _locParseCtxt.a->_index = _locParseCtxt.numZones++;
+
+ if (_localFlags[_currentLocationIndex] & kFlagsVisited) {
+ _locParseCtxt.a->_flags = _zoneFlags[_currentLocationIndex][_locParseCtxt.a->_index];
+ } else {
+ _zoneFlags[_currentLocationIndex][_locParseCtxt.a->_index] = _locParseCtxt.a->_flags;
+ }
+
+}
+
+
+DECLARE_LOCATION_PARSER(localflags) {
+ debugC(7, kDebugParser, "LOCATION_PARSER(localflags) ");
+
+ int _si = 1;
+ while (_tokens[_si][0] != '\0') {
+ _localFlagNames->addData(_tokens[_si]);
+ _si++;
+ }
+}
+
+
+DECLARE_LOCATION_PARSER(flags) {
+ debugC(7, kDebugParser, "LOCATION_PARSER(flags) ");
+
+ if ((_localFlags[_currentLocationIndex] & kFlagsVisited) == 0) {
+ // only for 1st visit
+ _localFlags[_currentLocationIndex] = 0;
+ int _si = 1;
+
+ do {
+ byte _al = _localFlagNames->lookup(_tokens[_si]);
+ _localFlags[_currentLocationIndex] |= 1 << (_al - 1);
+
+ _si++;
+ if (scumm_stricmp(_tokens[_si], "|")) break;
+ _si++;
+ } while (true);
+ }
+}
+
+
+DECLARE_LOCATION_PARSER(comment) {
+ debugC(7, kDebugParser, "LOCATION_PARSER(comment) ");
+
+ _location._comment = parseComment(*_locParseCtxt.script);
+}
+
+
+DECLARE_LOCATION_PARSER(endcomment) {
+ debugC(7, kDebugParser, "LOCATION_PARSER(endcomment) ");
+
+ _location._endComment = parseComment(*_locParseCtxt.script);
+}
+
+
+DECLARE_LOCATION_PARSER(sound) {
+ debugC(7, kDebugParser, "LOCATION_PARSER(sound) ");
+
+// _soundMan->loadSound(_tokens[1]);
+}
+
+
+DECLARE_LOCATION_PARSER(music) {
+ debugC(7, kDebugParser, "LOCATION_PARSER(music) ");
+
+// _soundMan->loadMusic(_tokens[1]);
+}
+
+DECLARE_LOCATION_PARSER(redundant) {
+ debugC(7, kDebugParser, "LOCATION_PARSER(redundant) ");
+
+ warning("redundant '%s' line found in script '%s'", _tokens[0], _locParseCtxt.filename);
+}
+
+
+DECLARE_LOCATION_PARSER(character) {
+ debugC(7, kDebugParser, "LOCATION_PARSER(character) ");
+
+// changeCharacter(character);
+}
+
+
+DECLARE_LOCATION_PARSER(ifchar) {
+ debugC(7, kDebugParser, "LOCATION_PARSER(ifchar) ");
+
+ skip(_locParseCtxt.script, "ENDIF");
+}
+
+
+DECLARE_LOCATION_PARSER(null) {
+ debugC(7, kDebugParser, "LOCATION_PARSER(null) ");
+
+
+}
+
+
+DECLARE_LOCATION_PARSER(mask) {
+ debugC(7, kDebugParser, "LOCATION_PARSER(mask) ");
+
+ _disk->loadScenery(*_backgroundInfo, NULL, _tokens[1], NULL);
+ _gfx->setMask(&_backgroundInfo->mask);
+
+ _gfx->_bgLayers[0] = atoi(_tokens[2]);
+ _gfx->_bgLayers[1] = atoi(_tokens[3]);
+ _gfx->_bgLayers[2] = atoi(_tokens[4]);
+}
+
+
+DECLARE_LOCATION_PARSER(path) {
+ debugC(7, kDebugParser, "LOCATION_PARSER(path) ");
+
+ _disk->loadScenery(*_backgroundInfo, NULL, NULL, _tokens[1]);
+ _pathBuffer = &_backgroundInfo->path;
+}
+
+
+DECLARE_LOCATION_PARSER(escape) {
+ debugC(7, kDebugParser, "LOCATION_PARSER(escape) ");
+
+ parseCommands(*_locParseCtxt.script, _location._escapeCommands);
+}
+
+
+DECLARE_LOCATION_PARSER(zeta) {
+ debugC(7, kDebugParser, "LOCATION_PARSER(zeta) ");
+
+ _zeta0 = atoi(_tokens[1]);
+ _zeta1 = atoi(_tokens[2]);
+
+ if (_tokens[3][0] != '\0') {
+ _zeta2 = atoi(_tokens[1]);
+ } else {
+ _zeta2 = 50;
+ }
+}
+
+DECLARE_COMMAND_PARSER(ifchar) {
+ debugC(7, kDebugParser, "COMMAND_PARSER(ifchar) ");
+
+ if (!scumm_stricmp(_characterName, _tokens[1]))
+ skip(_locParseCtxt.script, "endif");
+}
+
+
+DECLARE_COMMAND_PARSER(endif) {
+ debugC(7, kDebugParser, "COMMAND_PARSER(endif) ");
+
+
+}
+
+
+DECLARE_COMMAND_PARSER(location) {
+ debugC(7, kDebugParser, "COMMAND_PARSER(location) ");
+
+ createCommand(_lookup);
+
+ _locParseCtxt.cmd->u._string = strdup(_tokens[1]);
+ _locParseCtxt.nextToken++;
+
+ if (_tokens[_locParseCtxt.nextToken][0] != '\0') {
+ _locParseCtxt.cmd->u._startPos.x = atoi(_tokens[_locParseCtxt.nextToken]);
+ _locParseCtxt.nextToken++;
+ _locParseCtxt.cmd->u._startPos.y = atoi(_tokens[_locParseCtxt.nextToken]);
+ _locParseCtxt.nextToken++;
+ }
+
+ if (_tokens[_locParseCtxt.nextToken][0] != '\0') {
+ _locParseCtxt.cmd->u._startPos2.x = atoi(_tokens[_locParseCtxt.nextToken]);
+ _locParseCtxt.nextToken++;
+ _locParseCtxt.cmd->u._startPos2.y = atoi(_tokens[_locParseCtxt.nextToken]);
+ _locParseCtxt.nextToken++;
+ }
+
+ parseCommandFlags();
+ addCommand();
+}
+
+
+DECLARE_COMMAND_PARSER(string) {
+ debugC(7, kDebugParser, "COMMAND_PARSER(string) ");
+
+ createCommand(_lookup);
+
+ _locParseCtxt.cmd->u._string = strdup(_tokens[1]);
+ _locParseCtxt.nextToken++;
+
+ parseCommandFlags();
+ addCommand();
+}
+
+DECLARE_COMMAND_PARSER(math) {
+ debugC(7, kDebugParser, "COMMAND_PARSER(math) ");
+
+ createCommand(_lookup);
+
+ _locParseCtxt.cmd->u._lvalue = _countersNames->lookup(_tokens[1]);
+ _locParseCtxt.nextToken++;
+ _locParseCtxt.cmd->u._rvalue = atoi(_tokens[2]);
+ _locParseCtxt.nextToken++;
+
+ parseCommandFlags();
+ addCommand();
+}
+
+
+DECLARE_COMMAND_PARSER(test) {
+ debugC(7, kDebugParser, "COMMAND_PARSER(test) ");
+
+ createCommand(_lookup);
+
+ uint counter = _countersNames->lookup(_tokens[1]);
+ _locParseCtxt.nextToken++;
+
+ if (counter == Table::notFound) {
+ if (!scumm_stricmp("SFX", _tokens[1])) {
+ _locParseCtxt.cmd->_id = CMD_TEST_SFX;
+ } else {
+ error("unknown counter '%s' in test opcode", _tokens[1]);
+ }
+ } else {
+ _locParseCtxt.cmd->u._lvalue = counter;
+ _locParseCtxt.cmd->u._rvalue = atoi(_tokens[3]);
+ _locParseCtxt.nextToken++;
+
+ if (_tokens[2][0] == '>') {
+ _locParseCtxt.cmd->_id = CMD_TEST_GT;
+ } else
+ if (_tokens[2][0] == '<') {
+ _locParseCtxt.cmd->_id = CMD_TEST_LT;
+ }
+ _locParseCtxt.nextToken++;
+ }
+
+ parseCommandFlags();
+ addCommand();
+}
+
+
+DECLARE_COMMAND_PARSER(music) {
+ debugC(7, kDebugParser, "COMMAND_PARSER(music) ");
+
+ createCommand(_lookup);
+
+ _locParseCtxt.cmd->u._musicCommand = _audioCommandsNames->lookup(_tokens[1]);
+ _locParseCtxt.nextToken++;
+
+ if (_tokens[2][0] != '\0' && scumm_stricmp("flags", _tokens[2]) && scumm_stricmp("gflags", _tokens[2])) {
+ _locParseCtxt.cmd->u._musicParm = atoi(_tokens[2]);
+ _locParseCtxt.nextToken++;
+ }
+
+ parseCommandFlags();
+ addCommand();
+}
+
+
+DECLARE_COMMAND_PARSER(zone) {
+ debugC(7, kDebugParser, "COMMAND_PARSER(zone) ");
+
+ createCommand(_lookup);
+
+ _locParseCtxt.cmd->u._zone = findZone(_tokens[_locParseCtxt.nextToken]);
+ _locParseCtxt.nextToken++;
+
+ if (_locParseCtxt.cmd->u._zone == NULL) {
+ strcpy(_forwardedAnimationNames[_numForwards], _tokens[_locParseCtxt.nextToken-1]);
+ _forwardedCommands[_numForwards] = _locParseCtxt.cmd;
+ _numForwards++;
+ }
+
+ parseCommandFlags();
+ addCommand();
+}
+
+
+DECLARE_COMMAND_PARSER(zeta) {
+ debugC(7, kDebugParser, "COMMAND_PARSER(zeta) ");
+
+ createCommand(_lookup);
+
+ _locParseCtxt.cmd->u._zeta0 = atoi(_tokens[1]);
+ _locParseCtxt.nextToken++;
+ _locParseCtxt.cmd->u._zeta1 = atoi(_tokens[2]);
+ _locParseCtxt.nextToken++;
+
+ if (_tokens[3][0] != '\0') {
+ _locParseCtxt.cmd->u._zeta2 = atoi(_tokens[3]);
+ _locParseCtxt.nextToken++;
+ } else {
+ _locParseCtxt.cmd->u._zeta2 = 50;
+ }
+
+ parseCommandFlags();
+ addCommand();
+}
+
+
+DECLARE_COMMAND_PARSER(give) {
+ debugC(7, kDebugParser, "COMMAND_PARSER(give) ");
+
+ createCommand(_lookup);
+
+ _locParseCtxt.cmd->u._object = 4 + atoi(_tokens[1]);
+ _locParseCtxt.nextToken++;
+
+ if (!scumm_stricmp("dino", _tokens[2])) {
+ _locParseCtxt.cmd->u._characterId = 1;
+ } else
+ if (!scumm_stricmp("doug", _tokens[2])) {
+ _locParseCtxt.cmd->u._characterId = 2;
+ } else
+ if (!scumm_stricmp("donna", _tokens[2])) {
+ _locParseCtxt.cmd->u._characterId = 3;
+ } else
+ error("unknown recipient '%s' in give command", _tokens[2]);
+
+ _locParseCtxt.nextToken++;
+
+ parseCommandFlags();
+ addCommand();
+}
+
+
+DECLARE_COMMAND_PARSER(text) {
+ debugC(7, kDebugParser, "COMMAND_PARSER(text) ");
+
+ createCommand(_lookup);
+
+ if (isdigit(_tokens[1][1])) {
+ _locParseCtxt.cmd->u._zeta0 = atoi(_tokens[1]);
+ _locParseCtxt.nextToken++;
+ } else {
+ _locParseCtxt.cmd->u._zeta0 = 0;
+ }
+
+ _locParseCtxt.cmd->u._string = strdup(_tokens[_locParseCtxt.nextToken]);
+ _locParseCtxt.nextToken++;
+
+ if (_tokens[_locParseCtxt.nextToken][0] != '\0' && scumm_stricmp("flags", _tokens[_locParseCtxt.nextToken])) {
+ _locParseCtxt.cmd->u._string2 = strdup(_tokens[_locParseCtxt.nextToken]);
+ _locParseCtxt.nextToken++;
+ }
+
+
+ parseCommandFlags();
+ addCommand();
+}
+
+
+DECLARE_COMMAND_PARSER(unary) {
+ debugC(7, kDebugParser, "COMMAND_PARSER(unary) ");
+
+ createCommand(_lookup);
+
+ _locParseCtxt.cmd->u._rvalue = atoi(_tokens[1]);
+ _locParseCtxt.nextToken++;
+
+ parseCommandFlags();
+ addCommand();
+}
+
+
+DECLARE_ZONE_PARSER(limits) {
+ debugC(7, kDebugParser, "ZONE_PARSER(limits) ");
+
+ if (isalpha(_tokens[1][1])) {
+ _locParseCtxt.z->_flags |= kFlagsAnimLinked;
+ _locParseCtxt.z->_linkedAnim = findAnimation(_tokens[1]);
+ _locParseCtxt.z->_linkedName = strdup(_tokens[1]);
+ } else {
+ _locParseCtxt.z->_left = atoi(_tokens[1]);
+ _locParseCtxt.z->_top = atoi(_tokens[2]);
+ _locParseCtxt.z->_right = atoi(_tokens[3]);
+ _locParseCtxt.z->_bottom = atoi(_tokens[4]);
+ }
+}
+
+
+DECLARE_ZONE_PARSER(moveto) {
+ debugC(7, kDebugParser, "ZONE_PARSER(moveto) ");
+
+ _locParseCtxt.z->_moveTo.x = atoi(_tokens[1]);
+ _locParseCtxt.z->_moveTo.y = atoi(_tokens[2]);
+// _locParseCtxt.z->_moveTo.z = atoi(_tokens[3]);
+}
+
+
+DECLARE_ZONE_PARSER(type) {
+ debugC(7, kDebugParser, "ZONE_PARSER(type) ");
+
+ if (_tokens[2][0] != '\0') {
+ _locParseCtxt.z->_type = (4 + _objectsNames->lookup(_tokens[2])) << 16;
+ }
+ int16 _si = _zoneTypeNames->lookup(_tokens[1]);
+ if (_si != Table::notFound) {
+ _locParseCtxt.z->_type |= 1 << (_si - 1);
+ parseZoneTypeBlock(*_locParseCtxt.script, _locParseCtxt.z);
+
+// if (_locParseCtxt.z->_type & kZoneHear) {
+// _soundMan->sfxCommand(START...);
+// }
+ }
+
+ popParserTables();
+}
+
+
+DECLARE_ANIM_PARSER(file) {
+ debugC(7, kDebugParser, "ANIM_PARSER(file) ");
+
+ _locParseCtxt.a->_cnv = _disk->loadFrames(_tokens[1]);
+}
+
+
+DECLARE_ANIM_PARSER(position) {
+ debugC(7, kDebugParser, "ANIM_PARSER(position) ");
+
+ _locParseCtxt.a->_left = atoi(_tokens[1]);
+ _locParseCtxt.a->_top = atoi(_tokens[2]);
+ _locParseCtxt.a->_z = atoi(_tokens[3]);
+ _locParseCtxt.a->_frame = atoi(_tokens[4]);
+}
+
+
+DECLARE_ANIM_PARSER(moveto) {
+ debugC(7, kDebugParser, "ANIM_PARSER(moveto) ");
+
+ _locParseCtxt.a->_moveTo.x = atoi(_tokens[1]);
+ _locParseCtxt.a->_moveTo.y = atoi(_tokens[2]);
+// _locParseCtxt.a->_moveTo.z = atoi(_tokens[3]);
+}
+
+
+DECLARE_ANIM_PARSER(endanimation) {
+ debugC(7, kDebugParser, "ANIM_PARSER(endanimation) ");
+
+
+ if (_locParseCtxt.a->_cnv) {
+ _locParseCtxt.a->_right = _locParseCtxt.a->width();
+ _locParseCtxt.a->_bottom = _locParseCtxt.a->height();
+ }
+
+ _locParseCtxt.a->_oldPos.x = -1000;
+ _locParseCtxt.a->_oldPos.y = -1000;
+
+ _locParseCtxt.a->_flags |= 0x1000000;
+
+ popParserTables();
+}
+
+
+
+
+
+
+
+
+
+
+DECLARE_INSTRUCTION_PARSER(zone) {
+ debugC(7, kDebugParser, "INSTRUCTION_PARSER(zone) ");
+
+ _instParseCtxt.inst->_z = findZone(_tokens[1]);
+}
+
+
+
+DECLARE_INSTRUCTION_PARSER(color) {
+ debugC(7, kDebugParser, "INSTRUCTION_PARSER(color) ");
+
+
+ parseRValue(_instParseCtxt.inst->_opB, _tokens[1]);
+
+ _instParseCtxt.inst->_colors[0] = atoi(_tokens[2]);
+ _instParseCtxt.inst->_colors[1] = atoi(_tokens[3]);
+ _instParseCtxt.inst->_colors[2] = atoi(_tokens[4]);
+
+}
+
+
+DECLARE_INSTRUCTION_PARSER(mask) {
+ debugC(7, kDebugParser, "INSTRUCTION_PARSER(mask) ");
+
+
+ parseRValue(_instParseCtxt.inst->_opA, _tokens[1]);
+ parseRValue(_instParseCtxt.inst->_opB, _tokens[2]);
+ parseRValue(_instParseCtxt.inst->_opC, _tokens[3]);
+
+}
+
+
+DECLARE_INSTRUCTION_PARSER(print) {
+ debugC(7, kDebugParser, "INSTRUCTION_PARSER(print) ");
+
+ parseRValue(_instParseCtxt.inst->_opB, _tokens[1]);
+}
+
+
+DECLARE_INSTRUCTION_PARSER(text) {
+ debugC(7, kDebugParser, "INSTRUCTION_PARSER(text) ");
+
+
+ int _si = 1;
+
+ if (isdigit(_tokens[1][1])) {
+ _instParseCtxt.inst->_y = atoi(_tokens[1]);
+ _si = 2;
+ } else {
+ _instParseCtxt.inst->_y = -1;
+ }
+
+ _instParseCtxt.inst->_text = strdup(_tokens[_si]);
+ _si++;
+
+ if (_tokens[_si][0] != '\0' && scumm_stricmp("flags", _tokens[_si])) {
+ _instParseCtxt.inst->_text2 = strdup(_tokens[_si]);
+ }
+
+}
+
+
+DECLARE_INSTRUCTION_PARSER(if_op) {
+ debugC(7, kDebugParser, "INSTRUCTION_PARSER(if_op) ");
+
+
+ if (_instParseCtxt.openIf)
+ error("cannot nest 'if' blocks");
+
+ parseLValue(_instParseCtxt.inst->_opA, _tokens[1]);
+ parseRValue(_instParseCtxt.inst->_opB, _tokens[3]);
+
+ if (_tokens[2][0] == '=') {
+ _instParseCtxt.inst->_index = INST_IFEQ;
+ } else
+ if (_tokens[2][0] == '>') {
+ _instParseCtxt.inst->_index = INST_IFGT;
+ } else
+ if (_tokens[2][0] == '<') {
+ _instParseCtxt.inst->_index = INST_IFLT;
+ } else
+ error("unknown test operator '%s' in if-clause", _tokens[2]);
+
+ _instParseCtxt.openIf = _instParseCtxt.inst;
+
+}
+
+
+DECLARE_INSTRUCTION_PARSER(endif) {
+ debugC(7, kDebugParser, "INSTRUCTION_PARSER(endif) ");
+
+ if (_instParseCtxt.openIf == 0)
+ error("unexpected 'endif'");
+
+// _instParseCtxt.openIf->_endif = _instParseCtxt.inst;
+ _instParseCtxt.openIf = NULL;
+}
+
+
+void Parallaction_br::parseRValue(ScriptVar &v, const char *str) {
+
+ if (isdigit(str[0]) || str[0] == '-') {
+ v.setImmediate(atoi(str));
+ return;
+ }
+
+ int index = _instParseCtxt.program->findLocal(str);
+ if (index != -1) {
+ v.setLocal(&_instParseCtxt.locals[index]);
+ return;
+ }
+
+ Animation *a;
+ if (str[1] == '.') {
+ a = findAnimation(&str[2]);
+ if (!a) {
+ error("unknown animation '%s' in script", &str[2]);
+ }
+ } else
+ a = _instParseCtxt.a;
+
+ if (str[0] == 'X') {
+ v.setField(&a->_left);
+ } else
+ if (str[0] == 'Y') {
+ v.setField(&a->_top);
+ } else
+ if (str[0] == 'Z') {
+ v.setField(&a->_z);
+ } else
+ if (str[0] == 'F') {
+ v.setField(&a->_frame);
+ } else
+ if (str[0] == 'N') {
+ v.setImmediate(a->getFrameNum());
+ } else
+ if (str[0] == 'R') {
+ v.setRandom(atoi(&str[1]));
+ } else
+ if (str[0] == 'L') {
+ v.setField(&_lipSyncVal);
+ }
+
+}
+
+typedef OpcodeImpl<Parallaction_br> OpcodeV2;
+#define INSTRUCTION_PARSER(sig) OpcodeV2(this, &Parallaction_br::instParse_##sig)
+#define ZONE_PARSER(sig) OpcodeV2(this, &Parallaction_br::locZoneParse_##sig)
+#define ANIM_PARSER(sig) OpcodeV2(this, &Parallaction_br::locAnimParse_##sig)
+#define LOCATION_PARSER(sig) OpcodeV2(this, &Parallaction_br::locParse_##sig)
+#define COMMAND_PARSER(sig) OpcodeV2(this, &Parallaction_br::cmdParse_##sig)
+
+void Parallaction_br::initParsers() {
+
+ static const OpcodeV2 op0[] = {
+ INSTRUCTION_PARSER(defLocal), // invalid opcode -> local definition
+ INSTRUCTION_PARSER(zone), // on
+ INSTRUCTION_PARSER(zone), // off
+ INSTRUCTION_PARSER(x),
+ INSTRUCTION_PARSER(y),
+ INSTRUCTION_PARSER(z),
+ INSTRUCTION_PARSER(f),
+ INSTRUCTION_PARSER(loop),
+ INSTRUCTION_PARSER(null), // endloop
+ INSTRUCTION_PARSER(null), // show
+ INSTRUCTION_PARSER(inc),
+ INSTRUCTION_PARSER(inc), // dec
+ INSTRUCTION_PARSER(set),
+ INSTRUCTION_PARSER(put),
+ INSTRUCTION_PARSER(call),
+ INSTRUCTION_PARSER(null), // wait
+ INSTRUCTION_PARSER(zone), // start
+ INSTRUCTION_PARSER(zone), // process
+ INSTRUCTION_PARSER(move),
+ INSTRUCTION_PARSER(color),
+ INSTRUCTION_PARSER(zone), // sound
+ INSTRUCTION_PARSER(mask),
+ INSTRUCTION_PARSER(print),
+ INSTRUCTION_PARSER(text),
+ INSTRUCTION_PARSER(inc), // mul
+ INSTRUCTION_PARSER(inc), // div
+ INSTRUCTION_PARSER(if_op),
+ INSTRUCTION_PARSER(null),
+ INSTRUCTION_PARSER(null),
+ INSTRUCTION_PARSER(endif),
+ INSTRUCTION_PARSER(zone), // stop
+ INSTRUCTION_PARSER(endscript)
+ };
+
+ uint i;
+ for (i = 0; i < ARRAYSIZE(op0); i++)
+ _instructionParsers.push_back(&op0[i]);
+
+
+ static const OpcodeV2 op2[] = {
+ COMMAND_PARSER(invalid),
+ COMMAND_PARSER(flags), // set
+ COMMAND_PARSER(flags), // clear
+ COMMAND_PARSER(animation), // start
+ COMMAND_PARSER(zone), // speak
+ COMMAND_PARSER(zone), // get
+ COMMAND_PARSER(location),
+ COMMAND_PARSER(zone), // open
+ COMMAND_PARSER(zone), // close
+ COMMAND_PARSER(zone), // on
+ COMMAND_PARSER(zone), // off
+ COMMAND_PARSER(call),
+ COMMAND_PARSER(flags), // toggle
+ COMMAND_PARSER(drop),
+ COMMAND_PARSER(simple), // quit
+ COMMAND_PARSER(move),
+ COMMAND_PARSER(animation), // stop
+ COMMAND_PARSER(string), // character
+ COMMAND_PARSER(string), // followme
+ COMMAND_PARSER(simple), // onmouse
+ COMMAND_PARSER(simple), // offmouse
+ COMMAND_PARSER(drop), // add
+ COMMAND_PARSER(zone), // leave
+ COMMAND_PARSER(math), // inc
+ COMMAND_PARSER(math), // dec
+ COMMAND_PARSER(test), // test
+ COMMAND_PARSER(invalid),
+ COMMAND_PARSER(invalid),
+ COMMAND_PARSER(math), // let
+ COMMAND_PARSER(music),
+ COMMAND_PARSER(zone), // fix
+ COMMAND_PARSER(zone), // unfix
+ COMMAND_PARSER(zeta),
+ COMMAND_PARSER(unary), // scroll
+ COMMAND_PARSER(string), // swap
+ COMMAND_PARSER(give),
+ COMMAND_PARSER(text),
+ COMMAND_PARSER(unary), // part
+ COMMAND_PARSER(invalid),
+ COMMAND_PARSER(simple), // return
+ COMMAND_PARSER(simple), // onsave
+ COMMAND_PARSER(simple), // offsave
+ COMMAND_PARSER(endcommands), // endcommands
+ COMMAND_PARSER(ifchar),
+ COMMAND_PARSER(endif)
+ };
+
+ for (i = 0; i < ARRAYSIZE(op2); i++)
+ _commandParsers.push_back(&op2[i]);
+
+ static const OpcodeV2 op4[] = {
+ LOCATION_PARSER(invalid),
+ LOCATION_PARSER(character),
+ LOCATION_PARSER(endlocation),
+ LOCATION_PARSER(ifchar),
+ LOCATION_PARSER(null), // endif
+ LOCATION_PARSER(location),
+ LOCATION_PARSER(mask),
+ LOCATION_PARSER(path),
+ LOCATION_PARSER(null), // disk
+ LOCATION_PARSER(localflags),
+ LOCATION_PARSER(commands),
+ LOCATION_PARSER(escape),
+ LOCATION_PARSER(acommands),
+ LOCATION_PARSER(flags),
+ LOCATION_PARSER(comment),
+ LOCATION_PARSER(endcomment),
+ LOCATION_PARSER(zone),
+ LOCATION_PARSER(animation),
+ LOCATION_PARSER(zeta),
+ LOCATION_PARSER(music),
+ LOCATION_PARSER(sound)
+// LOCATION_PARSER(redundant) // for redundant endanimation
+ };
+
+ for (i = 0; i < ARRAYSIZE(op4); i++)
+ _locationParsers.push_back(&op4[i]);
+
+ static const OpcodeV2 op5[] = {
+ ZONE_PARSER(invalid),
+ ZONE_PARSER(endzone),
+ ZONE_PARSER(limits),
+ ZONE_PARSER(moveto),
+ ZONE_PARSER(type),
+ ZONE_PARSER(commands),
+ ZONE_PARSER(label),
+ ZONE_PARSER(flags)
+ };
+
+ for (i = 0; i < ARRAYSIZE(op5); i++)
+ _locationZoneParsers.push_back(&op5[i]);
+
+ static const OpcodeV2 op6[] = {
+ ANIM_PARSER(invalid),
+ ANIM_PARSER(endanimation),
+ ANIM_PARSER(endanimation), // endzone
+ ANIM_PARSER(script),
+ ANIM_PARSER(commands),
+ ANIM_PARSER(type),
+ ANIM_PARSER(label),
+ ANIM_PARSER(flags),
+ ANIM_PARSER(file),
+ ANIM_PARSER(position),
+ ANIM_PARSER(moveto)
+ };
+
+ for (i = 0; i < ARRAYSIZE(op6); i++)
+ _locationAnimParsers.push_back(&op6[i]);
+
+ _currentOpcodes = 0;
+ _currentStatements = 0;
+
+}
+
+void Parallaction_br::parseLocation(const char* filename) {
+
+ _locParseCtxt.numZones = 0;
+
+ Super::parseLocation(filename);
+
+// drawZones();
+
+ return;
+}
+
+
+
+
+
+} // namespace Parallaction
diff --git a/engines/parallaction/parser_ns.cpp b/engines/parallaction/parser_ns.cpp
new file mode 100644
index 0000000000..1b47f2fe3d
--- /dev/null
+++ b/engines/parallaction/parser_ns.cpp
@@ -0,0 +1,1494 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#include "common/stdafx.h"
+
+#include "parallaction/parallaction.h"
+#include "parallaction/sound.h"
+
+namespace Parallaction {
+
+#define CMD_SET 1
+#define CMD_CLEAR 2
+#define CMD_START 3
+#define CMD_SPEAK 4
+#define CMD_GET 5
+#define CMD_LOCATION 6
+#define CMD_OPEN 7
+#define CMD_CLOSE 8
+#define CMD_ON 9
+#define CMD_OFF 10
+#define CMD_CALL 11
+#define CMD_TOGGLE 12
+#define CMD_DROP 13
+#define CMD_QUIT 14
+#define CMD_MOVE 15
+#define CMD_STOP 16
+
+#define INST_ON 1
+#define INST_OFF 2
+#define INST_X 3
+#define INST_Y 4
+#define INST_Z 5
+#define INST_F 6
+#define INST_LOOP 7
+#define INST_ENDLOOP 8
+#define INST_SHOW 9
+#define INST_INC 10
+#define INST_DEC 11
+#define INST_SET 12
+#define INST_PUT 13
+#define INST_CALL 14
+#define INST_WAIT 15
+#define INST_START 16
+#define INST_SOUND 17
+#define INST_MOVE 18
+#define INST_END 19
+
+
+#define DECLARE_ZONE_PARSER(sig) void Parallaction_ns::locZoneParse_##sig()
+#define DECLARE_ANIM_PARSER(sig) void Parallaction_ns::locAnimParse_##sig()
+#define DECLARE_COMMAND_PARSER(sig) void Parallaction_ns::cmdParse_##sig()
+#define DECLARE_INSTRUCTION_PARSER(sig) void Parallaction_ns::instParse_##sig()
+#define DECLARE_LOCATION_PARSER(sig) void Parallaction_ns::locParse_##sig()
+
+
+
+
+DECLARE_ANIM_PARSER(invalid) {
+ debugC(7, kDebugParser, "ANIM_PARSER(invalid) ");
+
+ error("unknown statement '%s' in animation %s", _tokens[0], _locParseCtxt.a->_label._text);
+}
+
+
+DECLARE_ANIM_PARSER(script) {
+ debugC(7, kDebugParser, "ANIM_PARSER(script) ");
+
+ _locParseCtxt.a->_scriptName = strdup(_tokens[1]);
+}
+
+
+DECLARE_ANIM_PARSER(commands) {
+ debugC(7, kDebugParser, "ANIM_PARSER(commands) ");
+
+ parseCommands(*_locParseCtxt.script, _locParseCtxt.a->_commands);
+}
+
+
+DECLARE_ANIM_PARSER(type) {
+ debugC(7, kDebugParser, "ANIM_PARSER(type) ");
+
+ if (_tokens[2][0] != '\0') {
+ _locParseCtxt.a->_type = ((4 + _objectsNames->lookup(_tokens[2])) << 16) & 0xFFFF0000;
+ }
+ int16 _si = _zoneTypeNames->lookup(_tokens[1]);
+ if (_si != Table::notFound) {
+ _locParseCtxt.a->_type |= 1 << (_si-1);
+ if (((_locParseCtxt.a->_type & 0xFFFF) != kZoneNone) && ((_locParseCtxt.a->_type & 0xFFFF) != kZoneCommand)) {
+ parseZoneTypeBlock(*_locParseCtxt.script, _locParseCtxt.a);
+ }
+ }
+
+ _locParseCtxt.a->_oldPos.x = -1000;
+ _locParseCtxt.a->_oldPos.y = -1000;
+
+ _locParseCtxt.a->_flags |= 0x1000000;
+
+ popParserTables();
+}
+
+
+DECLARE_ANIM_PARSER(label) {
+ debugC(7, kDebugParser, "ANIM_PARSER(label) ");
+
+ renderLabel(&_locParseCtxt.a->_label._cnv, _tokens[1]);
+}
+
+
+DECLARE_ANIM_PARSER(flags) {
+ debugC(7, kDebugParser, "ANIM_PARSER(flags) ");
+
+ uint16 _si = 1;
+
+ do {
+ byte _al = _zoneFlagNames->lookup(_tokens[_si]);
+ _si++;
+ _locParseCtxt.a->_flags |= 1 << (_al - 1);
+ } while (!scumm_stricmp(_tokens[_si++], "|"));
+}
+
+
+DECLARE_ANIM_PARSER(file) {
+ debugC(7, kDebugParser, "ANIM_PARSER(file) ");
+
+ char vC8[200];
+ strcpy(vC8, _tokens[1]);
+ if (_engineFlags & kEngineTransformedDonna) {
+ if (!scumm_stricmp(_tokens[1], "donnap") || !scumm_stricmp(_tokens[1], "donnapa")) {
+ strcat(vC8, "tras");
+ }
+ }
+ _locParseCtxt.a->_cnv = _disk->loadFrames(vC8);
+}
+
+
+DECLARE_ANIM_PARSER(position) {
+ debugC(7, kDebugParser, "ANIM_PARSER(position) ");
+
+ _locParseCtxt.a->_left = atoi(_tokens[1]);
+ _locParseCtxt.a->_top = atoi(_tokens[2]);
+ _locParseCtxt.a->_z = atoi(_tokens[3]);
+}
+
+
+DECLARE_ANIM_PARSER(moveto) {
+ debugC(7, kDebugParser, "ANIM_PARSER(moveto) ");
+
+ _locParseCtxt.a->_moveTo.x = atoi(_tokens[1]);
+ _locParseCtxt.a->_moveTo.y = atoi(_tokens[2]);
+}
+
+
+DECLARE_ANIM_PARSER(endanimation) {
+ debugC(7, kDebugParser, "ANIM_PARSER(endanimation) ");
+
+
+ _locParseCtxt.a->_oldPos.x = -1000;
+ _locParseCtxt.a->_oldPos.y = -1000;
+
+ _locParseCtxt.a->_flags |= 0x1000000;
+
+ popParserTables();
+}
+
+Animation *Parallaction_ns::parseAnimation(Script& script, AnimationList &list, char *name) {
+ debugC(5, kDebugParser, "parseAnimation(name: %s)", name);
+
+ Animation *a = new Animation;
+
+ a->_label._text = strdup(name);
+
+ list.push_front(a);
+
+ _locParseCtxt.a = a;
+ _locParseCtxt.script = &script;
+
+ pushParserTables(&_locationAnimParsers, _locationAnimStmt);
+
+ return a;
+}
+
+void Parallaction_ns::parseInstruction(Animation *a, LocalVariable *locals) {
+
+ Instruction *inst = new Instruction;
+
+ if (_tokens[0][1] == '.') {
+ _tokens[0][1] = '\0';
+ _instParseCtxt.a = findAnimation(&_tokens[0][2]);
+ } else
+ if (_tokens[1][1] == '.') {
+ _tokens[1][1] = '\0';
+ _instParseCtxt.a = findAnimation(&_tokens[1][2]);
+ } else
+ _instParseCtxt.a = a;
+
+ inst->_index = _instructionNames->lookup(_tokens[0]);
+ _instParseCtxt.inst = inst;
+ _instParseCtxt.locals = locals;
+
+ (*(_instructionParsers[inst->_index]))();
+
+ a->_program->_instructions.push_back(inst);
+
+ return;
+}
+
+void Parallaction_ns::loadProgram(Animation *a, const char *filename) {
+ debugC(1, kDebugParser, "loadProgram(Animation: %s, script: %s)", a->_label._text, filename);
+
+ Script *script = _disk->loadScript(filename);
+
+ a->_program = new Program;
+
+ _instParseCtxt.openIf = NULL;
+ _instParseCtxt.end = false;
+ _instParseCtxt.program = a->_program;
+
+ do {
+ fillBuffers(*script);
+ parseInstruction(a, a->_program->_locals);
+ } while (!_instParseCtxt.end);
+
+ a->_program->_ip = a->_program->_instructions.begin();
+
+ delete script;
+
+ debugC(1, kDebugParser, "loadProgram() done");
+
+ return;
+}
+
+DECLARE_INSTRUCTION_PARSER(animation) {
+ debugC(7, kDebugParser, "INSTRUCTION_PARSER(animation) ");
+
+ if (!scumm_stricmp(_tokens[1], _instParseCtxt.a->_label._text)) {
+ _instParseCtxt.inst->_a = _instParseCtxt.a;
+ } else {
+ _instParseCtxt.inst->_a = findAnimation(_tokens[1]);
+ }
+}
+
+
+DECLARE_INSTRUCTION_PARSER(loop) {
+ debugC(7, kDebugParser, "INSTRUCTION_PARSER(loop) ");
+
+ parseRValue(_instParseCtxt.inst->_opB, _tokens[1]);
+}
+
+
+DECLARE_INSTRUCTION_PARSER(x) {
+ debugC(7, kDebugParser, "INSTRUCTION_PARSER(x) ");
+
+ parseLValue(_instParseCtxt.inst->_opA, "X");
+ parseRValue(_instParseCtxt.inst->_opB, _tokens[1]);
+}
+
+
+DECLARE_INSTRUCTION_PARSER(y) {
+ debugC(7, kDebugParser, "INSTRUCTION_PARSER(y) ");
+
+ parseLValue(_instParseCtxt.inst->_opA, "Y");
+ parseRValue(_instParseCtxt.inst->_opB, _tokens[1]);
+}
+
+
+DECLARE_INSTRUCTION_PARSER(z) {
+ debugC(7, kDebugParser, "INSTRUCTION_PARSER(z) ");
+
+ parseLValue(_instParseCtxt.inst->_opA, "Z");
+ parseRValue(_instParseCtxt.inst->_opB, _tokens[1]);
+}
+
+
+DECLARE_INSTRUCTION_PARSER(f) {
+ debugC(7, kDebugParser, "INSTRUCTION_PARSER(f) ");
+
+ parseLValue(_instParseCtxt.inst->_opA, "F");
+ parseRValue(_instParseCtxt.inst->_opB, _tokens[1]);
+}
+
+
+DECLARE_INSTRUCTION_PARSER(inc) {
+ debugC(7, kDebugParser, "INSTRUCTION_PARSER(inc) ");
+
+ parseLValue(_instParseCtxt.inst->_opA, _tokens[1]);
+ parseRValue(_instParseCtxt.inst->_opB, _tokens[2]);
+
+ if (!scumm_stricmp(_tokens[3], "mod")) {
+ _instParseCtxt.inst->_flags |= kInstMod;
+ }
+}
+
+
+DECLARE_INSTRUCTION_PARSER(set) {
+ debugC(7, kDebugParser, "INSTRUCTION_PARSER(set) ");
+
+ // WORKAROUND: At least one script (balzo.script) in Amiga versions didn't declare
+ // local variables before using them, thus leading to crashes. The line launching the
+ // script was commented out on Dos version. This workaround enables the engine
+ // to dynamically add a local variable when it is encountered the first time in
+ // the script, so should fix any other occurrence as well.
+ if (_instParseCtxt.program->findLocal(_tokens[1]) == -1) {
+ _instParseCtxt.program->addLocal(_tokens[1]);
+ }
+
+ parseLValue(_instParseCtxt.inst->_opA, _tokens[1]);
+ parseRValue(_instParseCtxt.inst->_opB, _tokens[2]);
+}
+
+
+DECLARE_INSTRUCTION_PARSER(move) {
+ debugC(7, kDebugParser, "INSTRUCTION_PARSER(move) ");
+
+ parseRValue(_instParseCtxt.inst->_opA, _tokens[1]);
+ parseRValue(_instParseCtxt.inst->_opB, _tokens[2]);
+}
+
+
+DECLARE_INSTRUCTION_PARSER(put) {
+ debugC(7, kDebugParser, "INSTRUCTION_PARSER(put) ");
+
+ if (!scumm_stricmp(_tokens[1], _instParseCtxt.a->_label._text)) {
+ _instParseCtxt.inst->_a = _instParseCtxt.a;
+ } else {
+ _instParseCtxt.inst->_a = findAnimation(_tokens[1]);
+ }
+
+ parseRValue(_instParseCtxt.inst->_opA, _tokens[2]);
+ parseRValue(_instParseCtxt.inst->_opB, _tokens[3]);
+ if (!scumm_stricmp(_tokens[4], "masked")) {
+ _instParseCtxt.inst->_flags |= kInstMaskedPut;
+ }
+}
+
+
+DECLARE_INSTRUCTION_PARSER(call) {
+ debugC(7, kDebugParser, "INSTRUCTION_PARSER(call) ");
+
+ int index = _callableNames->lookup(_tokens[1]);
+ if (index == Table::notFound)
+ error("unknown callable '%s'", _tokens[1]);
+ _instParseCtxt.inst->_immediate = index - 1;
+}
+
+
+DECLARE_INSTRUCTION_PARSER(sound) {
+ debugC(7, kDebugParser, "INSTRUCTION_PARSER(sound) ");
+
+ _instParseCtxt.inst->_z = findZone(_tokens[1]);
+}
+
+
+DECLARE_INSTRUCTION_PARSER(null) {
+ debugC(7, kDebugParser, "INSTRUCTION_PARSER(null) ");
+
+
+}
+
+
+DECLARE_INSTRUCTION_PARSER(defLocal) {
+ debugC(7, kDebugParser, "INSTRUCTION_PARSER(defLocal) ");
+
+ int16 val = atoi(_tokens[2]);
+ int16 index;
+
+ if (_tokens[3][0] != '\0') {
+ index = _instParseCtxt.program->addLocal(_tokens[0], val, atoi(_tokens[3]), atoi(_tokens[4]));
+ } else {
+ index = _instParseCtxt.program->addLocal(_tokens[0], val);
+ }
+
+ _instParseCtxt.inst->_opA.setLocal(&_instParseCtxt.locals[index]);
+ _instParseCtxt.inst->_opB.setImmediate(_instParseCtxt.locals[index]._value);
+
+ _instParseCtxt.inst->_index = INST_SET;
+}
+
+DECLARE_INSTRUCTION_PARSER(endscript) {
+ debugC(7, kDebugParser, "INSTRUCTION_PARSER(endscript) ");
+
+ _instParseCtxt.end = true;
+}
+
+
+
+void Parallaction_ns::parseRValue(ScriptVar &v, const char *str) {
+
+ if (isdigit(str[0]) || str[0] == '-') {
+ v.setImmediate(atoi(str));
+ return;
+ }
+
+ int index = _instParseCtxt.program->findLocal(str);
+ if (index != -1) {
+ v.setLocal(&_instParseCtxt.locals[index]);
+ return;
+ }
+
+ Animation *a;
+ if (str[1] == '.') {
+ a = findAnimation(&str[2]);
+ } else {
+ a = _instParseCtxt.a;
+ }
+
+ if (str[0] == 'X') {
+ v.setField(&a->_left);
+ } else
+ if (str[0] == 'Y') {
+ v.setField(&a->_top);
+ } else
+ if (str[0] == 'Z') {
+ v.setField(&a->_z);
+ } else
+ if (str[0] == 'F') {
+ v.setField(&a->_frame);
+ }
+
+}
+
+void Parallaction_ns::parseLValue(ScriptVar &v, const char *str) {
+
+ int index = _instParseCtxt.program->findLocal(str);
+ if (index != -1) {
+ v.setLocal(&_instParseCtxt.locals[index]);
+ return;
+ }
+
+ Animation *a;
+ if (str[1] == '.') {
+ a = findAnimation(&str[2]);
+ } else {
+ a = _instParseCtxt.a;
+ }
+
+ if (str[0] == 'X') {
+ v.setField(&a->_left);
+ } else
+ if (str[0] == 'Y') {
+ v.setField(&a->_top);
+ } else
+ if (str[0] == 'Z') {
+ v.setField(&a->_z);
+ } else
+ if (str[0] == 'F') {
+ v.setField(&a->_frame);
+ }
+
+}
+
+
+DECLARE_COMMAND_PARSER(flags) {
+ debugC(7, kDebugParser, "COMMAND_PARSER(flags) ");
+
+ createCommand(_lookup);
+
+ if (_globalTable->lookup(_tokens[1]) == Table::notFound) {
+ do {
+ char _al = _localFlagNames->lookup(_tokens[_locParseCtxt.nextToken]);
+ _locParseCtxt.nextToken++;
+ _locParseCtxt.cmd->u._flags |= 1 << (_al - 1);
+ } while (!scumm_stricmp(_tokens[_locParseCtxt.nextToken++], "|"));
+ _locParseCtxt.nextToken--;
+ } else {
+ _locParseCtxt.cmd->u._flags |= kFlagsGlobal;
+ do {
+ char _al = _globalTable->lookup(_tokens[1]);
+ _locParseCtxt.nextToken++;
+ _locParseCtxt.cmd->u._flags |= 1 << (_al - 1);
+ } while (!scumm_stricmp(_tokens[_locParseCtxt.nextToken++], "|"));
+ _locParseCtxt.nextToken--;
+ }
+
+ parseCommandFlags();
+ addCommand();
+}
+
+
+DECLARE_COMMAND_PARSER(animation) {
+ debugC(7, kDebugParser, "COMMAND_PARSER(animation) ");
+
+ createCommand(_lookup);
+
+ _locParseCtxt.cmd->u._animation = findAnimation(_tokens[_locParseCtxt.nextToken]);
+ _locParseCtxt.nextToken++;
+ if (_locParseCtxt.cmd->u._animation == NULL) {
+ strcpy(_forwardedAnimationNames[_numForwards], _tokens[_locParseCtxt.nextToken-1]);
+ _forwardedCommands[_numForwards] = _locParseCtxt.cmd;
+ _numForwards++;
+ }
+
+ parseCommandFlags();
+ addCommand();
+}
+
+
+DECLARE_COMMAND_PARSER(zone) {
+ debugC(7, kDebugParser, "COMMAND_PARSER(zone) ");
+
+ createCommand(_lookup);
+
+ _locParseCtxt.cmd->u._zone = findZone(_tokens[_locParseCtxt.nextToken]);
+ _locParseCtxt.nextToken++;
+
+ parseCommandFlags();
+ addCommand();
+}
+
+
+DECLARE_COMMAND_PARSER(location) {
+ debugC(7, kDebugParser, "COMMAND_PARSER(location) ");
+
+ createCommand(_lookup);
+
+ _locParseCtxt.cmd->u._string = (char*)malloc(strlen(_tokens[_locParseCtxt.nextToken])+1);
+ strcpy(_locParseCtxt.cmd->u._string, _tokens[_locParseCtxt.nextToken]);
+ _locParseCtxt.nextToken++;
+
+ parseCommandFlags();
+ addCommand();
+}
+
+
+DECLARE_COMMAND_PARSER(drop) {
+ debugC(7, kDebugParser, "COMMAND_PARSER(drop) ");
+
+ createCommand(_lookup);
+
+ _locParseCtxt.cmd->u._object = 4 + _objectsNames->lookup(_tokens[_locParseCtxt.nextToken]);
+ _locParseCtxt.nextToken++;
+
+ parseCommandFlags();
+ addCommand();
+}
+
+
+DECLARE_COMMAND_PARSER(call) {
+ debugC(7, kDebugParser, "COMMAND_PARSER(call) ");
+
+ createCommand(_lookup);
+
+ _locParseCtxt.cmd->u._callable = _callableNames->lookup(_tokens[_locParseCtxt.nextToken]) - 1;
+ _locParseCtxt.nextToken++;
+
+ parseCommandFlags();
+ addCommand();
+}
+
+
+DECLARE_COMMAND_PARSER(simple) {
+ debugC(7, kDebugParser, "COMMAND_PARSER(simple) ");
+
+ createCommand(_lookup);
+ addCommand();
+}
+
+
+DECLARE_COMMAND_PARSER(move) {
+ debugC(7, kDebugParser, "COMMAND_PARSER(move) ");
+
+ createCommand(_lookup);
+
+ _locParseCtxt.cmd->u._move.x = atoi(_tokens[_locParseCtxt.nextToken]);
+ _locParseCtxt.nextToken++;
+ _locParseCtxt.cmd->u._move.y = atoi(_tokens[_locParseCtxt.nextToken]);
+ _locParseCtxt.nextToken++;
+
+ parseCommandFlags();
+ addCommand();
+}
+
+DECLARE_COMMAND_PARSER(invalid) {
+ debugC(7, kDebugParser, "COMMAND_PARSER(invalid) ");
+
+ error("Can't parse unknown command '%s'", _tokens[0]);
+}
+
+DECLARE_COMMAND_PARSER(endcommands) {
+ debugC(7, kDebugParser, "COMMAND_PARSER(endcommands) ");
+
+ popParserTables();
+
+ // temporary trick to handle dialogue commands
+ _locParseCtxt.endcommands = true;
+}
+
+void Parallaction_ns::parseCommandFlags() {
+
+ int _si = _locParseCtxt.nextToken;
+ Command *cmd = _locParseCtxt.cmd;
+
+ if (!scumm_stricmp(_tokens[_si], "flags")) {
+ _si++;
+
+ do {
+ if (!scumm_stricmp(_tokens[_si], "exit") || !scumm_stricmp(_tokens[_si], "exittrap")) {
+ cmd->_flagsOn |= kFlagsExit;
+ } else
+ if (!scumm_stricmp(_tokens[_si], "enter") || !scumm_stricmp(_tokens[_si], "entertrap")) {
+ cmd->_flagsOn |= kFlagsEnter;
+ } else
+ if (!scumm_strnicmp(_tokens[_si], "no", 2)) {
+ byte _al = _localFlagNames->lookup(&_tokens[_si][2]);
+ cmd->_flagsOff |= 1 << (_al - 1);
+ } else {
+ byte _al = _localFlagNames->lookup(_tokens[_si]);
+ cmd->_flagsOn |= 1 << (_al - 1);
+ }
+
+ _si++;
+
+ } while (!scumm_stricmp(_tokens[_si++], "|"));
+
+ }
+
+ if (!scumm_stricmp(_tokens[_si], "gflags")) {
+ _si++;
+ cmd->_flagsOn |= kFlagsGlobal;
+
+ do {
+ if (!scumm_stricmp(_tokens[_si], "exit")) {
+ cmd->_flagsOn |= kFlagsExit;
+ } else
+ if (!scumm_stricmp(_tokens[_si], "enter")) {
+ cmd->_flagsOn |= kFlagsEnter;
+ } else
+ if (!scumm_strnicmp(_tokens[_si], "no", 2)) {
+ byte _al = _globalTable->lookup(&_tokens[_si][2]);
+ cmd->_flagsOff |= 1 << (_al - 1);
+ } else {
+ byte _al = _globalTable->lookup(_tokens[_si]);
+ cmd->_flagsOn |= 1 << (_al - 1);
+ }
+
+ _si++;
+
+ } while (!scumm_stricmp(_tokens[_si++], "|"));
+
+ }
+
+ _si = _locParseCtxt.nextToken;
+
+}
+
+void Parallaction_ns::addCommand() {
+ _locParseCtxt.list->push_front(_locParseCtxt.cmd); // NOTE: command lists are written backwards in scripts
+}
+
+void Parallaction_ns::createCommand(uint id) {
+
+ _locParseCtxt.nextToken = 1;
+ _locParseCtxt.cmd = new Command;
+ _locParseCtxt.cmd->_id = id;
+
+}
+
+void Parallaction_ns::parseCommands(Script &script, CommandList& list) {
+ debugC(5, kDebugParser, "parseCommands()");
+
+ _locParseCtxt.list = &list;
+ _locParseCtxt.endcommands = false;
+ _locParseCtxt.script = &script;
+
+ pushParserTables(&_commandParsers, _commandsNames);
+}
+
+Dialogue *Parallaction_ns::parseDialogue(Script &script) {
+ debugC(7, kDebugParser, "parseDialogue()");
+
+ uint16 numQuestions = 0;
+
+ Dialogue *dialogue = new Dialogue;
+
+ Table forwards(20);
+
+ fillBuffers(script, true);
+
+ while (scumm_stricmp(_tokens[0], "enddialogue")) {
+ if (scumm_stricmp(_tokens[0], "Question")) continue;
+
+ Question *question = new Question;
+ dialogue->_questions[numQuestions] = question;
+
+ forwards.addData(_tokens[1]);
+
+ question->_text = parseDialogueString(script);
+
+ fillBuffers(script, true);
+ question->_mood = atoi(_tokens[0]);
+
+ uint16 numAnswers = 0;
+
+ fillBuffers(script, true);
+ while (scumm_stricmp(_tokens[0], "endquestion")) { // parse answers
+
+ Answer *answer = new Answer;
+ question->_answers[numAnswers] = answer;
+
+ if (_tokens[1][0]) {
+
+ Table* flagNames;
+ uint16 token;
+
+ if (!scumm_stricmp(_tokens[1], "global")) {
+ token = 2;
+ flagNames = _globalTable;
+ answer->_yesFlags |= kFlagsGlobal;
+ } else {
+ token = 1;
+ flagNames = _localFlagNames;
+ }
+
+ do {
+
+ if (!scumm_strnicmp(_tokens[token], "no", 2)) {
+ byte _al = flagNames->lookup(_tokens[token]+2);
+ answer->_noFlags |= 1 << (_al - 1);
+ } else {
+ byte _al = flagNames->lookup(_tokens[token]);
+ answer->_yesFlags |= 1 << (_al - 1);
+ }
+
+ token++;
+
+ } while (!scumm_stricmp(_tokens[token++], "|"));
+
+ }
+
+ answer->_text = parseDialogueString(script);
+
+ fillBuffers(script, true);
+ answer->_mood = atoi(_tokens[0]);
+ answer->_following._name = parseDialogueString(script);
+
+ fillBuffers(script, true);
+ if (!scumm_stricmp(_tokens[0], "commands")) {
+
+ parseCommands(script, answer->_commands);
+ _locParseCtxt.endcommands = false;
+ do {
+ fillBuffers(script, true);
+ parseStatement();
+ } while (!_locParseCtxt.endcommands);
+
+ fillBuffers(script, true);
+ }
+
+ numAnswers++;
+ }
+
+ fillBuffers(script, true);
+ numQuestions++;
+
+ }
+
+ // link questions
+ byte v50[20];
+ memset(v50, 0, 20);
+
+ for (uint16 i = 0; i < numQuestions; i++) {
+ Question *question = dialogue->_questions[i];
+
+ for (uint16 j = 0; j < NUM_ANSWERS; j++) {
+ Answer *answer = question->_answers[j];
+ if (answer == 0) continue;
+
+ int16 index = forwards.lookup(answer->_following._name);
+ free(answer->_following._name);
+
+ if (index == Table::notFound)
+ answer->_following._question = 0;
+ else
+ answer->_following._question = dialogue->_questions[index - 1];
+
+
+ }
+ }
+
+ debugC(7, kDebugParser, "parseDialogue() done");
+
+ return dialogue;
+}
+
+
+char *Parallaction_ns::parseDialogueString(Script &script) {
+
+ char vC8[200];
+ char *vD0 = NULL;
+ do {
+
+ vD0 = script.readLine(vC8, 200);
+ if (vD0 == 0) return NULL;
+
+ vD0 = Common::ltrim(vD0);
+
+ } while (strlen(vD0) == 0);
+
+ vD0[strlen(vD0)-1] = '\0'; // deletes the trailing '0xA'
+ // this is critical for Gfx::displayWrappedString to work properly
+ return strdup(vD0);
+}
+
+
+DECLARE_LOCATION_PARSER(invalid) {
+ debugC(7, kDebugParser, "LOCATION_PARSER(invalid) ");
+
+ error("unknown keyword '%s' in location '%s'", _tokens[0], _locParseCtxt.filename);
+}
+
+DECLARE_LOCATION_PARSER(endlocation) {
+ debugC(7, kDebugParser, "LOCATION_PARSER(endlocation) ");
+
+ _locParseCtxt.end = true;
+}
+
+
+DECLARE_LOCATION_PARSER(location) {
+ debugC(7, kDebugParser, "LOCATION_PARSER(location) ");
+
+ // The parameter for location is 'location.mask'.
+ // If mask is not present, then it is assumed
+ // that path & mask are encoded in the background
+ // bitmap, otherwise a separate .msk file exists.
+
+ char *mask = strchr(_tokens[1], '.');
+ if (mask) {
+ mask[0] = '\0';
+ mask++;
+ }
+
+ strcpy(_location._name, _tokens[1]);
+ switchBackground(_location._name, mask);
+
+ if (_tokens[2][0] != '\0') {
+ _char._ani._left = atoi(_tokens[2]);
+ _char._ani._top = atoi(_tokens[3]);
+ }
+
+ if (_tokens[4][0] != '\0') {
+ _char._ani._frame = atoi(_tokens[4]);
+ }
+}
+
+
+DECLARE_LOCATION_PARSER(disk) {
+ debugC(7, kDebugParser, "LOCATION_PARSER(disk) ");
+
+ _disk->selectArchive(_tokens[1]);
+}
+
+
+DECLARE_LOCATION_PARSER(nodes) {
+ debugC(7, kDebugParser, "LOCATION_PARSER(nodes) ");
+
+ parseWalkNodes(*_locParseCtxt.script, _location._walkNodes);
+}
+
+
+DECLARE_LOCATION_PARSER(zone) {
+ debugC(7, kDebugParser, "LOCATION_PARSER(zone) ");
+
+ parseZone(*_locParseCtxt.script, _zones, _tokens[1]);
+}
+
+
+DECLARE_LOCATION_PARSER(animation) {
+ debugC(7, kDebugParser, "LOCATION_PARSER(animation) ");
+
+ parseAnimation(*_locParseCtxt.script, _animations, _tokens[1]);
+}
+
+
+DECLARE_LOCATION_PARSER(localflags) {
+ debugC(7, kDebugParser, "LOCATION_PARSER(localflags) ");
+
+ int _si = 1;
+ while (_tokens[_si][0] != '\0') {
+ _localFlagNames->addData(_tokens[_si]);
+ _si++;
+ }
+}
+
+
+DECLARE_LOCATION_PARSER(commands) {
+ debugC(7, kDebugParser, "LOCATION_PARSER(commands) ");
+
+ parseCommands(*_locParseCtxt.script, _location._commands);
+}
+
+
+DECLARE_LOCATION_PARSER(acommands) {
+ debugC(7, kDebugParser, "LOCATION_PARSER(acommands) ");
+
+ parseCommands(*_locParseCtxt.script, _location._aCommands);
+}
+
+
+DECLARE_LOCATION_PARSER(flags) {
+ debugC(7, kDebugParser, "LOCATION_PARSER(flags) ");
+
+ if ((_localFlags[_currentLocationIndex] & kFlagsVisited) == 0) {
+ // only for 1st visit
+ _localFlags[_currentLocationIndex] = 0;
+ int _si = 1;
+
+ do {
+ byte _al = _localFlagNames->lookup(_tokens[_si]);
+ _localFlags[_currentLocationIndex] |= 1 << (_al - 1);
+
+ _si++;
+ if (scumm_stricmp(_tokens[_si], "|")) break;
+ _si++;
+ } while (true);
+ }
+}
+
+
+DECLARE_LOCATION_PARSER(comment) {
+ debugC(7, kDebugParser, "LOCATION_PARSER(comment) ");
+
+ _location._comment = parseComment(*_locParseCtxt.script);
+}
+
+
+DECLARE_LOCATION_PARSER(endcomment) {
+ debugC(7, kDebugParser, "LOCATION_PARSER(endcomment) ");
+
+ _location._endComment = parseComment(*_locParseCtxt.script);
+}
+
+
+DECLARE_LOCATION_PARSER(sound) {
+ debugC(7, kDebugParser, "LOCATION_PARSER(sound) ");
+
+ if (getPlatform() == Common::kPlatformAmiga) {
+ strcpy(_locationSound, _tokens[1]);
+ _hasLocationSound = true;
+ }
+}
+
+
+DECLARE_LOCATION_PARSER(music) {
+ debugC(7, kDebugParser, "LOCATION_PARSER(music) ");
+
+ if (getPlatform() == Common::kPlatformAmiga)
+ _soundMan->setMusicFile(_tokens[1]);
+}
+
+DECLARE_LOCATION_PARSER(redundant) {
+ debugC(7, kDebugParser, "LOCATION_PARSER(redundant) ");
+
+ warning("redundant '%s' line found in script '%s'", _tokens[0], _locParseCtxt.filename);
+}
+
+
+void Parallaction_ns::parseLocation(const char *filename) {
+ debugC(1, kDebugParser, "parseLocation('%s')", filename);
+
+ allocateLocationSlot(filename);
+// printf("got location slot #%i for %s\n", _currentLocationIndex, filename);
+
+ Script *script = _disk->loadLocation(filename);
+
+ // TODO: the following two lines are specific to Nippon Safes
+ // and should be moved into something like 'initializeParsing()'
+ _gfx->setFont(_labelFont);
+ _hasLocationSound = false;
+
+ _locParseCtxt.end = false;
+ _locParseCtxt.script = script;
+ _locParseCtxt.filename = filename;
+
+ pushParserTables(&_locationParsers, _locationStmt);
+ do {
+ fillBuffers(*script, true);
+ parseStatement();
+ } while (!_locParseCtxt.end);
+ popParserTables();
+
+ delete script;
+
+ // this resolves any forward references in the script
+ for (uint16 _si = 0; _forwardedCommands[_si]; _si++) {
+ _forwardedCommands[_si]->u._animation = findAnimation(_forwardedAnimationNames[_si]);
+ _forwardedCommands[_si] = NULL;
+ }
+ _numForwards = 0;
+
+ // this loads animation scripts
+ AnimationList::iterator it = _animations.begin();
+ for ( ; it != _animations.end(); it++) {
+ if ((*it)->_scriptName)
+ loadProgram(*it, (*it)->_scriptName);
+ }
+
+ debugC(1, kDebugParser, "parseLocation('%s') done", filename);
+ return;
+}
+
+
+void Parallaction_ns::parseWalkNodes(Script& script, WalkNodeList &list) {
+ debugC(5, kDebugParser, "parseWalkNodes()");
+
+ fillBuffers(script, true);
+ while (scumm_stricmp(_tokens[0], "ENDNODES")) {
+
+ if (!scumm_stricmp(_tokens[0], "COORD")) {
+
+ WalkNode *v4 = new WalkNode(
+ atoi(_tokens[1]),
+ atoi(_tokens[2])
+ );
+
+ list.push_front(v4);
+ }
+
+ fillBuffers(script, true);
+ }
+
+ debugC(5, kDebugParser, "parseWalkNodes() done");
+
+ return;
+}
+
+typedef OpcodeImpl<Parallaction_ns> OpcodeV1;
+#define INSTRUCTION_PARSER(sig) OpcodeV1(this, &Parallaction_ns::instParse_##sig)
+#define ZONE_PARSER(sig) OpcodeV1(this, &Parallaction_ns::locZoneParse_##sig)
+#define ANIM_PARSER(sig) OpcodeV1(this, &Parallaction_ns::locAnimParse_##sig)
+#define LOCATION_PARSER(sig) OpcodeV1(this, &Parallaction_ns::locParse_##sig)
+#define COMMAND_PARSER(sig) OpcodeV1(this, &Parallaction_ns::cmdParse_##sig)
+
+void Parallaction_ns::initParsers() {
+
+ static const OpcodeV1 op0[] = {
+ INSTRUCTION_PARSER(defLocal), // invalid opcode -> local definition
+ INSTRUCTION_PARSER(animation), // on
+ INSTRUCTION_PARSER(animation), // off
+ INSTRUCTION_PARSER(x),
+ INSTRUCTION_PARSER(y),
+ INSTRUCTION_PARSER(z),
+ INSTRUCTION_PARSER(f),
+ INSTRUCTION_PARSER(loop),
+ INSTRUCTION_PARSER(null), // endloop
+ INSTRUCTION_PARSER(null), // show
+ INSTRUCTION_PARSER(inc),
+ INSTRUCTION_PARSER(inc), // dec
+ INSTRUCTION_PARSER(set),
+ INSTRUCTION_PARSER(put),
+ INSTRUCTION_PARSER(call),
+ INSTRUCTION_PARSER(null), // wait
+ INSTRUCTION_PARSER(animation), // start
+ INSTRUCTION_PARSER(sound),
+ INSTRUCTION_PARSER(move),
+ INSTRUCTION_PARSER(endscript)
+ };
+
+ uint i;
+ for (i = 0; i < ARRAYSIZE(op0); i++)
+ _instructionParsers.push_back(&op0[i]);
+
+
+ static const OpcodeV1 op2[] = {
+ COMMAND_PARSER(invalid),
+ COMMAND_PARSER(flags), // set
+ COMMAND_PARSER(flags), // clear
+ COMMAND_PARSER(animation), // start
+ COMMAND_PARSER(zone), // speak
+ COMMAND_PARSER(zone), // get
+ COMMAND_PARSER(location), // location
+ COMMAND_PARSER(zone), // open
+ COMMAND_PARSER(zone), // close
+ COMMAND_PARSER(zone), // on
+ COMMAND_PARSER(zone), // off
+ COMMAND_PARSER(call), // call
+ COMMAND_PARSER(flags), // toggle
+ COMMAND_PARSER(drop), // drop
+ COMMAND_PARSER(simple), // quit
+ COMMAND_PARSER(move), // move
+ COMMAND_PARSER(animation), // stop
+ COMMAND_PARSER(endcommands), // endcommands
+ COMMAND_PARSER(endcommands) // endzone
+ };
+
+ for (i = 0; i < ARRAYSIZE(op2); i++)
+ _commandParsers.push_back(&op2[i]);
+
+
+ static const OpcodeV1 op4[] = {
+ LOCATION_PARSER(invalid),
+ LOCATION_PARSER(endlocation),
+ LOCATION_PARSER(location),
+ LOCATION_PARSER(disk),
+ LOCATION_PARSER(nodes),
+ LOCATION_PARSER(zone),
+ LOCATION_PARSER(animation),
+ LOCATION_PARSER(localflags),
+ LOCATION_PARSER(commands),
+ LOCATION_PARSER(acommands),
+ LOCATION_PARSER(flags),
+ LOCATION_PARSER(comment),
+ LOCATION_PARSER(endcomment),
+ LOCATION_PARSER(sound),
+ LOCATION_PARSER(music),
+ LOCATION_PARSER(redundant) // for redundant endanimation
+ };
+
+ for (i = 0; i < ARRAYSIZE(op4); i++)
+ _locationParsers.push_back(&op4[i]);
+
+ static const OpcodeV1 op5[] = {
+ ZONE_PARSER(invalid),
+ ZONE_PARSER(limits),
+ ZONE_PARSER(moveto),
+ ZONE_PARSER(type),
+ ZONE_PARSER(commands),
+ ZONE_PARSER(label),
+ ZONE_PARSER(flags),
+ ZONE_PARSER(endzone)
+ };
+
+ for (i = 0; i < ARRAYSIZE(op5); i++)
+ _locationZoneParsers.push_back(&op5[i]);
+
+ static const OpcodeV1 op6[] = {
+ ANIM_PARSER(invalid),
+ ANIM_PARSER(script),
+ ANIM_PARSER(commands),
+ ANIM_PARSER(type),
+ ANIM_PARSER(label),
+ ANIM_PARSER(flags),
+ ANIM_PARSER(file),
+ ANIM_PARSER(position),
+ ANIM_PARSER(moveto),
+ ANIM_PARSER(endanimation)
+ };
+
+ for (i = 0; i < ARRAYSIZE(op6); i++)
+ _locationAnimParsers.push_back(&op6[i]);
+
+ _currentOpcodes = 0;
+ _currentStatements = 0;
+
+}
+
+//
+// a comment can appear both at location and Zone levels
+// comments are displayed into rectangles on the screen
+//
+char *Parallaction_ns::parseComment(Script &script) {
+
+ char _tmp_comment[1000] = "\0";
+ char *v194;
+
+ do {
+ char v190[400];
+ v194 = script.readLine(v190, 400);
+
+ v194[strlen(v194)-1] = '\0';
+ if (!scumm_stricmp(v194, "endtext"))
+ break;
+
+ strcat(_tmp_comment, v194);
+ strcat(_tmp_comment, " ");
+ } while (true);
+
+ v194 = strdup(_tmp_comment);
+ _tmp_comment[0] = '\0';
+
+ return v194;
+}
+
+
+DECLARE_ZONE_PARSER(invalid) {
+ debugC(7, kDebugParser, "ZONE_PARSER(invalid) ");
+
+ error("unknown statement '%s' in zone %s", _tokens[0], _locParseCtxt.z->_label._text);
+}
+
+DECLARE_ZONE_PARSER(endzone) {
+ debugC(7, kDebugParser, "ZONE_PARSER(endzone) ");
+
+ popParserTables();
+}
+
+DECLARE_ZONE_PARSER(limits) {
+ debugC(7, kDebugParser, "ZONE_PARSER(limits) ");
+
+ _locParseCtxt.z->_left = atoi(_tokens[1]);
+ _locParseCtxt.z->_top = atoi(_tokens[2]);
+ _locParseCtxt.z->_right = atoi(_tokens[3]);
+ _locParseCtxt.z->_bottom = atoi(_tokens[4]);
+}
+
+
+DECLARE_ZONE_PARSER(moveto) {
+ debugC(7, kDebugParser, "ZONE_PARSER(moveto) ");
+
+ _locParseCtxt.z->_moveTo.x = atoi(_tokens[1]);
+ _locParseCtxt.z->_moveTo.y = atoi(_tokens[2]);
+}
+
+
+DECLARE_ZONE_PARSER(type) {
+ debugC(7, kDebugParser, "ZONE_PARSER(type) ");
+
+ if (_tokens[2][0] != '\0') {
+ _locParseCtxt.z->_type = (4 + _objectsNames->lookup(_tokens[2])) << 16;
+ }
+ int16 _si = _zoneTypeNames->lookup(_tokens[1]);
+ if (_si != Table::notFound) {
+ _locParseCtxt.z->_type |= 1 << (_si - 1);
+ parseZoneTypeBlock(*_locParseCtxt.script, _locParseCtxt.z);
+ }
+
+ popParserTables();
+}
+
+
+DECLARE_ZONE_PARSER(commands) {
+ debugC(7, kDebugParser, "ZONE_PARSER(commands) ");
+
+ parseCommands(*_locParseCtxt.script, _locParseCtxt.z->_commands);
+}
+
+
+DECLARE_ZONE_PARSER(label) {
+ debugC(7, kDebugParser, "ZONE_PARSER(label) ");
+
+// printf("label: %s", _tokens[1]);
+ renderLabel(&_locParseCtxt.z->_label._cnv, _tokens[1]);
+}
+
+
+DECLARE_ZONE_PARSER(flags) {
+ debugC(7, kDebugParser, "ZONE_PARSER(flags) ");
+
+ uint16 _si = 1;
+
+ do {
+ char _al = _zoneFlagNames->lookup(_tokens[_si]);
+ _si++;
+ _locParseCtxt.z->_flags |= 1 << (_al - 1);
+ } while (!scumm_stricmp(_tokens[_si++], "|"));
+}
+
+void Parallaction_ns::parseZone(Script &script, ZoneList &list, char *name) {
+ debugC(5, kDebugParser, "parseZone(name: %s)", name);
+
+ if (findZone(name)) {
+ while (scumm_stricmp(_tokens[0], "endzone")) {
+ fillBuffers(script, true);
+ }
+ return;
+ }
+
+ Zone *z = new Zone;
+
+ z->_label._text = strdup(name);
+
+ _locParseCtxt.z = z;
+ _locParseCtxt.script = &script;
+
+ list.push_front(z);
+
+ pushParserTables(&_locationZoneParsers, _locationZoneStmt);
+
+ return;
+}
+
+
+
+
+void Parallaction_ns::parseGetData(Script &script, Zone *z) {
+
+ GetData *data = new GetData;
+
+ do {
+
+ if (!scumm_stricmp(_tokens[0], "file")) {
+ data->_cnv = _disk->loadStatic(_tokens[1]);
+ data->_backup = (byte*)malloc(data->_cnv->w*data->_cnv->h);
+
+ if ((z->_flags & kFlagsRemove) == 0) {
+ _gfx->backupGetBackground(data, z->_left, z->_top);
+ _gfx->flatBlitCnv(data->_cnv, z->_left, z->_top, Gfx::kBitBack);
+ }
+ }
+
+ if (!scumm_stricmp(_tokens[0], "icon")) {
+ data->_icon = 4 + _objectsNames->lookup(_tokens[1]);
+ }
+
+ fillBuffers(script, true);
+ } while (scumm_stricmp(_tokens[0], "endzone"));
+
+ z->u.get = data;
+
+}
+
+
+void Parallaction_ns::parseExamineData(Script &script, Zone *z) {
+
+ ExamineData *data = new ExamineData;
+
+ do {
+
+ if (!scumm_stricmp(_tokens[0], "file")) {
+ data->_filename = strdup(_tokens[1]);
+ }
+ if (!scumm_stricmp(_tokens[0], "desc")) {
+ data->_description = parseComment(script);
+ }
+
+ fillBuffers(script, true);
+ } while (scumm_stricmp(_tokens[0], "endzone"));
+
+ z->u.examine = data;
+
+}
+
+
+void Parallaction_ns::parseDoorData(Script &script, Zone *z) {
+
+ DoorData *data = new DoorData;
+
+ do {
+
+ if (!scumm_stricmp(_tokens[0], "slidetext")) {
+ strcpy(_slideText[0], _tokens[1]);
+// printf("%s\t", _slideText[0]);
+ strcpy(_slideText[1], _tokens[2]);
+ }
+
+ if (!scumm_stricmp(_tokens[0], "location")) {
+ data->_location = strdup(_tokens[1]);
+ }
+
+ if (!scumm_stricmp(_tokens[0], "file")) {
+// printf("file: '%s'", _tokens[0]);
+
+ data->_cnv = _disk->loadFrames(_tokens[1]);
+ uint16 _ax = (z->_flags & kFlagsClosed ? 0 : 1);
+
+ Common::Rect r;
+ data->_cnv->getRect(0, r);
+
+ data->_background = (byte*)malloc(r.width() * r.height());
+ _gfx->backupDoorBackground(data, z->_left, z->_top);
+
+ _gfx->flatBlitCnv(data->_cnv, _ax, z->_left, z->_top, Gfx::kBitBack);
+ }
+
+ if (!scumm_stricmp(_tokens[0], "startpos")) {
+ data->_startPos.x = atoi(_tokens[1]);
+ data->_startPos.y = atoi(_tokens[2]);
+ data->_startFrame = atoi(_tokens[3]);
+ }
+
+ fillBuffers(script, true);
+ } while (scumm_stricmp(_tokens[0], "endzone"));
+
+ z->u.door = data;
+
+}
+
+
+void Parallaction_ns::parseMergeData(Script &script, Zone *z) {
+
+ MergeData *data = new MergeData;
+
+ do {
+
+ if (!scumm_stricmp(_tokens[0], "obj1")) {
+ data->_obj1 = 4 + _objectsNames->lookup(_tokens[1]);
+ }
+ if (!scumm_stricmp(_tokens[0], "obj2")) {
+ data->_obj2 = 4 + _objectsNames->lookup(_tokens[1]);
+ }
+ if (!scumm_stricmp(_tokens[0], "newobj")) {
+ data->_obj3 = 4 + _objectsNames->lookup(_tokens[1]);
+ }
+
+ fillBuffers(script, true);
+ } while (scumm_stricmp(_tokens[0], "endzone"));
+
+ z->u.merge = data;
+
+}
+
+void Parallaction_ns::parseHearData(Script &script, Zone *z) {
+
+ HearData *data = new HearData;
+
+ do {
+
+ if (!scumm_stricmp(_tokens[0], "sound")) {
+ strcpy(data->_name, _tokens[1]);
+ data->_channel = atoi(_tokens[2]);
+ }
+ if (!scumm_stricmp(_tokens[0], "freq")) {
+ data->_freq = atoi(_tokens[1]);
+ }
+
+ fillBuffers(script, true);
+ } while (scumm_stricmp(_tokens[0], "endzone"));
+
+ z->u.hear = data;
+
+}
+
+void Parallaction_ns::parseSpeakData(Script &script, Zone *z) {
+
+ SpeakData *data = new SpeakData;
+
+ do {
+
+ if (!scumm_stricmp(_tokens[0], "file")) {
+ strcpy(data->_name, _tokens[1]);
+ }
+ if (!scumm_stricmp(_tokens[0], "Dialogue")) {
+ data->_dialogue = parseDialogue(script);
+ }
+
+ fillBuffers(script, true);
+ } while (scumm_stricmp(_tokens[0], "endzone"));
+
+ z->u.speak = data;
+
+}
+
+
+void Parallaction_ns::parseZoneTypeBlock(Script &script, Zone *z) {
+ debugC(7, kDebugParser, "parseZoneTypeBlock(name: %s, type: %x)", z->_label._text, z->_type);
+
+ switch (z->_type & 0xFFFF) {
+ case kZoneExamine: // examine Zone alloc
+ parseExamineData(script, z);
+ break;
+
+ case kZoneDoor: // door Zone alloc
+ parseDoorData(script, z);
+ break;
+
+ case kZoneGet: // get Zone alloc
+ parseGetData(script, z);
+ break;
+
+ case kZoneMerge: // merge Zone alloc
+ parseMergeData(script, z);
+ break;
+
+ case kZoneHear: // hear Zone alloc
+ parseHearData(script, z);
+ break;
+
+ case kZoneSpeak: // speak Zone alloc
+ parseSpeakData(script, z);
+ break;
+
+ default:
+ // eats up 'ENDZONE' line for unprocessed zone types
+ fillBuffers(script, true);
+ break;
+ }
+
+ debugC(7, kDebugParser, "parseZoneTypeBlock() done");
+
+ return;
+}
+
+
+} // namespace Parallaction
diff --git a/engines/parallaction/saveload.cpp b/engines/parallaction/saveload.cpp
index 279dbda1b9..299eba18a3 100644
--- a/engines/parallaction/saveload.cpp
+++ b/engines/parallaction/saveload.cpp
@@ -47,8 +47,6 @@
namespace Parallaction {
-extern char _gameNames[][20];
-
class SaveLoadChooser : public GUI::Dialog {
typedef Common::String String;
@@ -61,12 +59,12 @@ protected:
GUI::StaticTextWidget *_time;
GUI::StaticTextWidget *_playtime;
GUI::ContainerWidget *_container;
- Parallaction *_vm;
+ Parallaction_ns *_vm;
uint8 _fillR, _fillG, _fillB;
public:
- SaveLoadChooser(const String &title, const String &buttonLabel, Parallaction *engine);
+ SaveLoadChooser(const String &title, const String &buttonLabel, Parallaction_ns *engine);
~SaveLoadChooser();
virtual void handleCommand(GUI::CommandSender *sender, uint32 cmd, uint32 data);
@@ -80,7 +78,7 @@ public:
-void Parallaction::doLoadGame(uint16 slot) {
+void Parallaction_ns::doLoadGame(uint16 slot) {
_introSarcData3 = 200;
_introSarcData2 = 1;
@@ -179,7 +177,7 @@ void Parallaction::doLoadGame(uint16 slot) {
}
-void Parallaction::doSaveGame(uint16 slot, const char* name) {
+void Parallaction_ns::doSaveGame(uint16 slot, const char* name) {
char path[PATH_LEN];
sprintf(path, "game.%i", slot);
@@ -251,8 +249,7 @@ enum {
};
-
-SaveLoadChooser::SaveLoadChooser(const String &title, const String &buttonLabel, Parallaction *engine)
+SaveLoadChooser::SaveLoadChooser(const String &title, const String &buttonLabel, Parallaction_ns *engine)
: Dialog("scummsaveload"), _list(0), _chooseButton(0), _gfxWidget(0), _vm(engine) {
// _drawingHints |= GUI::THEME_HINT_SPECIAL_COLOR;
@@ -340,7 +337,7 @@ void SaveLoadChooser::reflowLayout() {
Dialog::reflowLayout();
}
-int Parallaction::buildSaveFileList(Common::StringList& l) {
+int Parallaction_ns::buildSaveFileList(Common::StringList& l) {
char name[16];
char buf[30];
@@ -367,7 +364,7 @@ int Parallaction::buildSaveFileList(Common::StringList& l) {
}
-int Parallaction::selectSaveFile(uint16 arg_0, const char* caption, const char* button) {
+int Parallaction_ns::selectSaveFile(uint16 arg_0, const char* caption, const char* button) {
SaveLoadChooser* slc = new SaveLoadChooser(caption, button, this);
@@ -388,7 +385,7 @@ int Parallaction::selectSaveFile(uint16 arg_0, const char* caption, const char*
-void Parallaction::loadGame() {
+void Parallaction_ns::loadGame() {
int _di = selectSaveFile( 0, "Load file", "Load" );
if (_di == -1) {
@@ -406,7 +403,7 @@ void Parallaction::loadGame() {
}
-void Parallaction::saveGame() {
+void Parallaction_ns::saveGame() {
if (!scumm_stricmp(_location._name, "caveau"))
return;
diff --git a/engines/parallaction/sound.cpp b/engines/parallaction/sound.cpp
index 21dcc3c788..9b8e179ccb 100644
--- a/engines/parallaction/sound.cpp
+++ b/engines/parallaction/sound.cpp
@@ -18,8 +18,8 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
- * $URL:https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/branches/gsoc2007-fsnode/engines/parallaction/sound.cpp $
- * $Id:sound.cpp 26949 2007-05-26 20:23:24Z david_corrales $
+ * $URL$
+ * $Id$
*
*/
@@ -265,7 +265,7 @@ void DosSoundMan::playCharacterMusic(const char *character) {
setMusicFile("dino");
} else
if (!scumm_stricmp(name, _donnaName)) {
- setMusicFile("dough");
+ setMusicFile("donna");
} else
if (!scumm_stricmp(name, _doughName)) {
setMusicFile("nuts");
@@ -281,14 +281,14 @@ void DosSoundMan::playLocationMusic(const char *location) {
if (_musicData1 != 0) {
playCharacterMusic(_vm->_characterName);
_musicData1 = 0;
- debugC(2, kDebugLocation, "changeLocation: started character specific music");
+ debugC(2, kDebugExec, "changeLocation: started character specific music");
}
if (!scumm_stricmp(location, "night") || !scumm_stricmp(location, "intsushi")) {
setMusicFile("nuts");
playMusic();
- debugC(2, kDebugLocation, "changeLocation: started music 'soft'");
+ debugC(2, kDebugExec, "changeLocation: started music 'soft'");
}
if (!scumm_stricmp(location, "museo") ||
@@ -302,7 +302,7 @@ void DosSoundMan::playLocationMusic(const char *location) {
stopMusic();
_musicData1 = 1;
- debugC(2, kDebugLocation, "changeLocation: music stopped");
+ debugC(2, kDebugExec, "changeLocation: music stopped");
}
}
diff --git a/engines/parallaction/sound.h b/engines/parallaction/sound.h
index 7a903ec790..f8f1a9e6b0 100644
--- a/engines/parallaction/sound.h
+++ b/engines/parallaction/sound.h
@@ -18,8 +18,8 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
- * $URL:https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/branches/gsoc2007-fsnode/engines/parallaction/sound.h $
- * $Id:sound.h 26949 2007-05-26 20:23:24Z david_corrales $
+ * $URL$
+ * $Id$
*
*/
diff --git a/engines/parallaction/staticres.cpp b/engines/parallaction/staticres.cpp
index 046176a933..94d2692ff1 100644
--- a/engines/parallaction/staticres.cpp
+++ b/engines/parallaction/staticres.cpp
@@ -30,7 +30,7 @@
namespace Parallaction {
-byte Gfx::_mouseArrow[256] = {
+byte Parallaction_ns::_mouseArrow[256] = {
0x12, 0x11, 0x11, 0x11, 0x13, 0x12, 0x12, 0x12, 0x13, 0x12, 0x12, 0x11, 0x13, 0x12, 0x12, 0x00,
0x13, 0x12, 0x12, 0x11, 0x13, 0x12, 0x12, 0x12, 0x13, 0x12, 0x12, 0x12, 0x13, 0x12, 0x12, 0x12,
0x13, 0x12, 0x12, 0x12, 0x13, 0x12, 0x12, 0x12, 0x13, 0x12, 0x12, 0x13, 0x13, 0x13, 0x12, 0x00,
@@ -50,8 +50,7 @@ byte Gfx::_mouseArrow[256] = {
};
-byte _amigaTopazFont[2600] =
-{
+byte _amigaTopazFont[2600] = {
0x00, 0x00, 0x03, 0xf3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x79, 0x00, 0x00, 0x03, 0xe9, 0x00, 0x00, 0x02, 0x79,
0x70, 0xff, 0x4e, 0x75, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
@@ -249,19 +248,6 @@ const char *_zoneTypeNamesRes_ns[] = {
"Command"
};
-const char _gameNames[10][20] = {
- "GAME1",
- "GAME2",
- "GAME3",
- "GAME4",
- "GAME5",
- "GAME6",
- "GAME7",
- "GAME8",
- "GAME9",
- "GAME10"
-};
-
const char *_commandsNamesRes_ns[] = {
"set",
"clear",
@@ -278,7 +264,9 @@ const char *_commandsNamesRes_ns[] = {
"drop",
"quit",
"move",
- "stop"
+ "stop",
+ "endcommands",
+ "endzone"
};
const char *_instructionNamesRes_ns[] = {
@@ -299,7 +287,8 @@ const char *_instructionNamesRes_ns[] = {
"wait",
"start",
"sound",
- "move"
+ "move",
+ "endscript"
};
const char *_callableNamesRes_ns[] = {
@@ -330,6 +319,46 @@ const char *_callableNamesRes_ns[] = {
"TestResult"
};
+const char *_locationStmtRes_ns[] = {
+ "endlocation",
+ "location",
+ "disk",
+ "nodes",
+ "zone",
+ "animation",
+ "localflags",
+ "commands",
+ "acommands",
+ "flags",
+ "comment",
+ "endcomment",
+ "sound",
+ "music",
+ "endanimation"
+};
+
+const char *_locationZoneStmtRes_ns[] = {
+ "limits",
+ "moveto",
+ "type",
+ "commands",
+ "label",
+ "flags",
+ "endzone"
+};
+
+const char *_locationAnimStmtRes_ns[] = {
+ "script",
+ "commands",
+ "type",
+ "label",
+ "flags",
+ "file",
+ "position",
+ "moveto",
+ "endanimation"
+};
+
const char *_zoneTypeNamesRes_br[] = {
"examine",
"door",
@@ -392,11 +421,11 @@ const char *_instructionNamesRes_br[] = {
"mul",
"div",
"if",
- "ifeq",
- "iflt",
- "ifgt",
+ "dummy",
+ "dummy",
"endif",
- "stop"
+ "stop",
+ "endscript"
};
const char *_commandsNamesRes_br[] = {
@@ -404,7 +433,7 @@ const char *_commandsNamesRes_br[] = {
"clear",
"start",
"speak",
- "get"
+ "get",
"location",
"open",
"close",
@@ -424,7 +453,7 @@ const char *_commandsNamesRes_br[] = {
"leave",
"inc",
"dec",
- "text",
+ "test",
"dummy",
"dummy",
"let",
@@ -440,7 +469,10 @@ const char *_commandsNamesRes_br[] = {
"dummy",
"return",
"onsave",
- "offsave"
+ "offsave",
+ "endcommands",
+ "ifchar",
+ "endif"
};
const char *_callableNamesRes_br[] = {
@@ -472,6 +504,52 @@ const char *_audioCommandsNamesRes_br[] = {
"loop"
};
+const char *_locationStmtRes_br[] = {
+ "character",
+ "endlocation",
+ "ifchar",
+ "endif",
+ "location",
+ "mask",
+ "path",
+ "disk",
+ "localflags",
+ "commands",
+ "escape",
+ "acommands",
+ "flags",
+ "comment",
+ "endcomment",
+ "zone",
+ "animation",
+ "zeta",
+ "music",
+ "sound"
+};
+
+const char *_locationZoneStmtRes_br[] = {
+ "endzone",
+ "limits",
+ "moveto",
+ "type",
+ "commands",
+ "label",
+ "flags"
+};
+
+const char *_locationAnimStmtRes_br[] = {
+ "endanimation",
+ "endzone",
+ "script",
+ "commands",
+ "type",
+ "label",
+ "flags",
+ "file",
+ "position",
+ "moveto"
+};
+
const char *_dinoName = "dino";
const char *_donnaName = "donna";
const char *_doughName = "dough";
@@ -525,7 +603,7 @@ const Parallaction_ns::Callable Parallaction_ns::_amigaCallables[] = {
CALLABLE_NS(_c_startMusic),
CALLABLE_NS(_c_closeMusic),
CALLABLE_NS(_c_fade),
- CALLABLE_NS(_c_play_boogie),
+ CALLABLE_NS(_c_HBOn),
CALLABLE_NS(_c_moveSarc),
CALLABLE_NS(_c_contaFoglie),
CALLABLE_NS(_c_zeroFoglie),
@@ -564,8 +642,11 @@ void Parallaction_ns::initResources() {
_zoneFlagNames = new Table(ARRAYSIZE(_zoneFlagNamesRes_ns), _zoneFlagNamesRes_ns);
_zoneTypeNames = new Table(ARRAYSIZE(_zoneTypeNamesRes_ns), _zoneTypeNamesRes_ns);
_commandsNames = new Table(ARRAYSIZE(_commandsNamesRes_ns), _commandsNamesRes_ns);
+ _locationStmt = new Table(ARRAYSIZE(_locationStmtRes_ns), _locationStmtRes_ns);
+ _locationZoneStmt = new Table(ARRAYSIZE(_locationZoneStmtRes_ns), _locationZoneStmtRes_ns);
+ _locationAnimStmt = new Table(ARRAYSIZE(_locationAnimStmtRes_ns), _locationAnimStmtRes_ns);
- _localFlagNames = new Table(120);
+ _localFlagNames = new FixedTable(NUM_LOCATIONS, 1);
_localFlagNames->addData("visited");
if (getPlatform() == Common::kPlatformPC) {
@@ -591,10 +672,13 @@ void Parallaction_br::initResources() {
_zoneTypeNames = new Table(ARRAYSIZE(_zoneTypeNamesRes_br), _zoneTypeNamesRes_br);
_commandsNames = new Table(ARRAYSIZE(_commandsNamesRes_br), _commandsNamesRes_br);
_audioCommandsNames = new Table(ARRAYSIZE(_audioCommandsNamesRes_br), _audioCommandsNamesRes_br);
+ _locationStmt = new Table(ARRAYSIZE(_locationStmtRes_br), _locationStmtRes_br);
+ _locationZoneStmt = new Table(ARRAYSIZE(_locationZoneStmtRes_br), _locationZoneStmtRes_br);
+ _locationAnimStmt = new Table(ARRAYSIZE(_locationAnimStmtRes_br), _locationAnimStmtRes_br);
- // TODO: make sure there are 120 max locations in Big Red Adventure
- _localFlagNames = new Table(120);
+ _localFlagNames = new FixedTable(NUM_LOCATIONS, 2);
_localFlagNames->addData("visited");
+ _localFlagNames->addData("testtrue");
if (getPlatform() == Common::kPlatformPC) {
_callables = _dosCallables;
diff --git a/engines/parallaction/walk.cpp b/engines/parallaction/walk.cpp
index d57e9d2532..73b7407308 100644
--- a/engines/parallaction/walk.cpp
+++ b/engines/parallaction/walk.cpp
@@ -29,8 +29,6 @@
namespace Parallaction {
-static byte *_buffer;
-
static uint16 _doorData1 = 1000;
static Zone *_zoneTrap = NULL;
@@ -38,32 +36,27 @@ static uint16 walkData1 = 0;
static uint16 walkData2 = 0; // next walk frame
-uint16 queryPath(uint16 x, uint16 y) {
-
- // NOTE: a better solution would have us mirror each byte in the mask in the loading routine
- // AmigaDisk_ns::loadPath() instead of doing it here.
-
- byte _al = _buffer[y*40 + x/8];
- byte _dl = (_vm->getPlatform() == Common::kPlatformPC) ? (x & 7) : (7 - (x & 7));
-
- return _al & (1 << _dl);
+inline byte PathBuffer::getValue(uint16 x, uint16 y) {
+ byte m = data[(x >> 3) + y * internalWidth];
+ uint n = (_vm->getPlatform() == Common::kPlatformPC) ? (x & 7) : (7 - (x & 7));
+ return ((1 << n) & m) >> n;
}
// adjusts position towards nearest walkable point
//
void PathBuilder::correctPathPoint(Common::Point &to) {
- if (queryPath(to.x, to.y)) return;
+ if (_vm->_pathBuffer->getValue(to.x, to.y)) return;
int16 right = to.x;
int16 left = to.x;
do {
right++;
- } while ((queryPath(right, to.y) == 0) && (right < _vm->_screenWidth));
+ } while ((_vm->_pathBuffer->getValue(right, to.y) == 0) && (right < _vm->_pathBuffer->w));
do {
left--;
- } while ((queryPath(left, to.y) == 0) && (left > 0));
- right = (right == _vm->_screenWidth) ? 1000 : right - to.x;
+ } while ((_vm->_pathBuffer->getValue(left, to.y) == 0) && (left > 0));
+ right = (right == _vm->_pathBuffer->w) ? 1000 : right - to.x;
left = (left == 0) ? 1000 : to.x - left;
@@ -71,12 +64,12 @@ void PathBuilder::correctPathPoint(Common::Point &to) {
int16 bottom = to.y;
do {
top--;
- } while ((queryPath(to.x, top) == 0) && (top > 0));
+ } while ((_vm->_pathBuffer->getValue(to.x, top) == 0) && (top > 0));
do {
bottom++;
- } while ((queryPath(to.x, bottom) == 0) && (bottom < _vm->_screenHeight));
+ } while ((_vm->_pathBuffer->getValue(to.x, bottom) == 0) && (bottom < _vm->_pathBuffer->h));
top = (top == 0) ? 1000 : to.y - top;
- bottom = (bottom == _vm->_screenHeight) ? 1000 : bottom - to.y;
+ bottom = (bottom == _vm->_pathBuffer->h) ? 1000 : bottom - to.y;
int16 closeX = (right >= left) ? left : right;
@@ -163,7 +156,7 @@ WalkNodeList *PathBuilder::buildPath(uint16 x, uint16 y) {
correctPathPoint(to);
debugC(1, kDebugWalk, "found closest path point at (%i, %i)", to.x, to.y);
- WalkNode *v48 = new WalkNode(to.x - _vm->_char._ani.width() / 2, to.y - _vm->_char._ani.height());
+ WalkNode *v48 = new WalkNode(to.x, to.y);
WalkNode *v44 = new WalkNode(*v48);
uint16 v38 = walkFunc1(to.x, to.y, v44);
@@ -185,7 +178,9 @@ WalkNodeList *PathBuilder::buildPath(uint16 x, uint16 y) {
#endif
Common::Point stop(v48->_x, v48->_y);
- Common::Point pos(_vm->_char._ani._left, _vm->_char._ani._top);
+ Common::Point pos;
+ _vm->_char.getFoot(pos);
+
uint32 v34 = buildSubPath(pos, stop);
if (v38 != 0 && v34 > v38) {
// no alternative path (gap?)
@@ -223,19 +218,17 @@ uint16 PathBuilder::walkFunc1(int16 x, int16 y, WalkNode *Node) {
Common::Point v4(0, 0);
- Common::Point foot(
- _vm->_char._ani._left + _vm->_char._ani.width()/2,
- _vm->_char._ani._top + _vm->_char._ani.height()
- );
+ Common::Point foot;
+ _vm->_char.getFoot(foot);
Common::Point v8(foot);
while (foot != arg) {
- if (foot.x < x && queryPath(foot.x + 1, foot.y) != 0) foot.x++;
- if (foot.x > x && queryPath(foot.x - 1, foot.y) != 0) foot.x--;
- if (foot.y < y && queryPath(foot.x, foot.y + 1) != 0) foot.y++;
- if (foot.y > y && queryPath(foot.x, foot.y - 1) != 0) foot.y--;
+ if (foot.x < x && _vm->_pathBuffer->getValue(foot.x + 1, foot.y) != 0) foot.x++;
+ if (foot.x > x && _vm->_pathBuffer->getValue(foot.x - 1, foot.y) != 0) foot.x--;
+ if (foot.y < y && _vm->_pathBuffer->getValue(foot.x, foot.y + 1) != 0) foot.y++;
+ if (foot.y > y && _vm->_pathBuffer->getValue(foot.x, foot.y - 1) != 0) foot.y--;
if (foot == v8 && foot != arg) {
@@ -245,10 +238,10 @@ uint16 PathBuilder::walkFunc1(int16 x, int16 y, WalkNode *Node) {
while (foot != arg) {
- if (foot.x < x && queryPath(foot.x + 1, foot.y) == 0) foot.x++;
- if (foot.x > x && queryPath(foot.x - 1, foot.y) == 0) foot.x--;
- if (foot.y < y && queryPath(foot.x, foot.y + 1) == 0) foot.y++;
- if (foot.y > y && queryPath(foot.x, foot.y - 1) == 0) foot.y--;
+ if (foot.x < x && _vm->_pathBuffer->getValue(foot.x + 1, foot.y) == 0) foot.x++;
+ if (foot.x > x && _vm->_pathBuffer->getValue(foot.x - 1, foot.y) == 0) foot.x--;
+ if (foot.y < y && _vm->_pathBuffer->getValue(foot.x, foot.y + 1) == 0) foot.y++;
+ if (foot.y > y && _vm->_pathBuffer->getValue(foot.x, foot.y - 1) == 0) foot.y--;
if (foot == v8 && foot != arg)
return 0;
@@ -256,8 +249,8 @@ uint16 PathBuilder::walkFunc1(int16 x, int16 y, WalkNode *Node) {
v8 = foot;
}
- Node->_x = v4.x - _vm->_char._ani.width() / 2;
- Node->_y = v4.y - _vm->_char._ani.height();
+ Node->_x = v4.x;
+ Node->_y = v4.y;
return (x - v4.x) * (x - v4.x) + (y - v4.y) * (y - v4.y);
}
@@ -272,19 +265,19 @@ uint16 PathBuilder::walkFunc1(int16 x, int16 y, WalkNode *Node) {
void Parallaction::clipMove(Common::Point& pos, const WalkNode* from) {
- if ((pos.x < from->_x) && (pos.x < _screenWidth) && (queryPath(_char._ani.width()/2 + pos.x + 2, _char._ani.height() + pos.y) != 0)) {
+ if ((pos.x < from->_x) && (pos.x < _pathBuffer->w) && (_pathBuffer->getValue(pos.x + 2, pos.y) != 0)) {
pos.x = (pos.x + 2 < from->_x) ? pos.x + 2 : from->_x;
}
- if ((pos.x > from->_x) && (pos.x > -20) && (queryPath(_char._ani.width()/2 + pos.x - 2, _char._ani.height() + pos.y) != 0)) {
+ if ((pos.x > from->_x) && (pos.x > 0) && (_pathBuffer->getValue(pos.x - 2, pos.y) != 0)) {
pos.x = (pos.x - 2 > from->_x) ? pos.x - 2 : from->_x;
}
- if ((pos.y < from->_y) && (pos.y < (_screenHeight - _char._ani.height())) && (queryPath(_char._ani.width()/2 + pos.x, _char._ani.height() + pos.y + 2) != 0)) {
+ if ((pos.y < from->_y) && (pos.y < _pathBuffer->h) && (_pathBuffer->getValue(pos.x, pos.y + 2) != 0)) {
pos.y = (pos.y + 2 <= from->_y) ? pos.y + 2 : from->_y;
}
- if ((pos.y > from->_y) && (pos.y > -20) && (queryPath(_char._ani.width()/2 + pos.x, _char._ani.height() + pos.y- 2) != 0)) {
+ if ((pos.y > from->_y) && (pos.y > 0) && (_pathBuffer->getValue(pos.x, pos.y - 2) != 0)) {
pos.y = (pos.y - 2 >= from->_y) ? pos.y - 2 :from->_y;
}
@@ -342,13 +335,16 @@ uint16 Parallaction::checkDoor() {
}
_engineFlags &= ~kEngineWalking;
- Zone *z = hitZone(kZoneDoor, _char._ani._left + _char._ani.width() / 2, _char._ani._top + _char._ani.height());
+
+ Common::Point foot;
+
+ _char.getFoot(foot);
+ Zone *z = hitZone(kZoneDoor, foot.x, foot.y);
if (z != NULL) {
if ((z->_flags & kFlagsClosed) == 0) {
- _location._startPosition.x = z->u.door->_startPos.x;
- _location._startPosition.y = z->u.door->_startPos.y;
+ _location._startPosition = z->u.door->_startPos;
_location._startFrame = z->u.door->_startFrame;
strcpy(_location._name, z->u.door->_location);
@@ -360,7 +356,8 @@ uint16 Parallaction::checkDoor() {
}
}
- z = hitZone(kZoneTrap, _char._ani._left + _char._ani.width() / 2, _char._ani._top + _char._ani.height());
+ _char.getFoot(foot);
+ z = hitZone(kZoneTrap, foot.x, foot.y);
if (z != NULL) {
_localFlags[_currentLocationIndex] |= kFlagsEnter;
@@ -387,11 +384,14 @@ void Parallaction::finalizeWalk(WalkNodeList *list) {
delete list;
}
-void jobWalk(void *parm, Job *j) {
+void Parallaction_ns::jobWalk(void *parm, Job *j) {
WalkNodeList *list = (WalkNodeList*)parm;
- Common::Point pos(_vm->_char._ani._left, _vm->_char._ani._top);
- _vm->_char._ani._oldPos = pos;
+ _char._ani._oldPos.x = _char._ani._left;
+ _char._ani._oldPos.y = _char._ani._top;
+
+ Common::Point pos;
+ _char.getFoot(pos);
WalkNodeList::iterator it = list->begin();
@@ -404,39 +404,31 @@ void jobWalk(void *parm, Job *j) {
if (it == list->end()) {
debugC(1, kDebugWalk, "jobWalk reached last node");
j->_finished = 1;
- _vm->finalizeWalk(list);
+ finalizeWalk(list);
return;
}
j->_parm = list;
// selectWalkFrame must be performed before position is changed by clipMove
- int16 v16 = _vm->selectWalkFrame(pos, *it);
- _vm->clipMove(pos, *it);
+ int16 v16 = selectWalkFrame(pos, *it);
+ clipMove(pos, *it);
- _vm->_char._ani._left = pos.x;
- _vm->_char._ani._top = pos.y;
+ _char.setFoot(pos);
- if (pos == _vm->_char._ani._oldPos) {
+ Common::Point newpos(_char._ani._left, _char._ani._top);
+
+ if (newpos == _char._ani._oldPos) {
debugC(1, kDebugWalk, "jobWalk was blocked by an unforeseen obstacle");
j->_finished = 1;
- _vm->finalizeWalk(list);
+ finalizeWalk(list);
} else {
- _vm->_char._ani._frame = v16 + walkData2 + 1;
+ _char._ani._frame = v16 + walkData2 + 1;
}
return;
}
-void Parallaction::setPath(byte *path) {
- memcpy(_buffer, path, _screenPathSize);
-}
-
-void Parallaction::initWalk() {
- _buffer = (byte*)malloc(_screenPathSize);
-}
-
-
WalkNode::WalkNode() : _x(0), _y(0) {
}
@@ -459,3 +451,4 @@ PathBuilder::PathBuilder(Animation *anim) : _anim(anim), _list(0) {
+
diff --git a/engines/parallaction/walk.h b/engines/parallaction/walk.h
index 476f5cc47a..dcbc3d5aa9 100644
--- a/engines/parallaction/walk.h
+++ b/engines/parallaction/walk.h
@@ -50,6 +50,40 @@ typedef ManagedList<WalkNode*> WalkNodeList;
void jobWalk(void*, Job *j);
+struct PathBuffer {
+ // handles a 1-bit depth buffer used for masking non-walkable areas
+
+ uint16 w;
+ uint16 internalWidth;
+ uint16 h;
+ uint size;
+ byte *data;
+
+public:
+ PathBuffer() : w(0), internalWidth(0), h(0), size(0), data(0) {
+ }
+
+ void create(uint16 width, uint16 height) {
+ w = width;
+ internalWidth = w >> 3;
+ h = height;
+ size = (internalWidth * h);
+ data = (byte*)calloc(size, 1);
+ }
+
+ void free() {
+ if (data)
+ ::free(data);
+ data = 0;
+ w = 0;
+ h = 0;
+ internalWidth = 0;
+ size = 0;
+ }
+
+ inline byte getValue(uint16 x, uint16 y);
+};
+
class PathBuilder {
diff --git a/engines/parallaction/zone.cpp b/engines/parallaction/zone.cpp
deleted file mode 100644
index 50f63b3b75..0000000000
--- a/engines/parallaction/zone.cpp
+++ /dev/null
@@ -1,690 +0,0 @@
-/* ScummVM - Graphic Adventure Engine
- *
- * ScummVM is the legal property of its developers, whose names
- * are too numerous to list here. Please refer to the COPYRIGHT
- * file distributed with this source distribution.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
-
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
-
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * $URL$
- * $Id$
- *
- */
-
-
-#include "common/stdafx.h"
-
-#include "parallaction/parallaction.h"
-#include "parallaction/sound.h"
-
-namespace Parallaction {
-
-
-
-
-Zone *Parallaction::findZone(const char *name) {
-
- for (ZoneList::iterator it = _zones.begin(); it != _zones.end(); it++)
- if (!scumm_stricmp((*it)->_label._text, name)) return *it;
-
- return findAnimation(name);
-}
-
-
-
-
-void Parallaction::parseZone(Script &script, ZoneList &list, char *name) {
-// printf("parseZone(%s)", name);
-
- if (findZone(name)) {
- while (scumm_stricmp(_tokens[0], "endzone")) {
- fillBuffers(script, true);
- }
- return;
- }
-
- Zone *z = new Zone;
-
- z->_label._text = (char*)malloc(strlen(name)+1);
- strcpy(z->_label._text, name);
-
- list.push_front(z);
-
- fillBuffers(script, true);
- while (scumm_stricmp(_tokens[0], "endzone")) {
-// printf("token[0] = %s", _tokens[0]);
-
- if (!scumm_stricmp(_tokens[0], "limits")) {
- z->_left = atoi(_tokens[1]);
- z->_top = atoi(_tokens[2]);
- z->_right = atoi(_tokens[3]);
- z->_bottom = atoi(_tokens[4]);
- }
- if (!scumm_stricmp(_tokens[0], "moveto")) {
- z->_moveTo.x = atoi(_tokens[1]);
- z->_moveTo.y = atoi(_tokens[2]);
- }
- if (!scumm_stricmp(_tokens[0], "type")) {
- if (_tokens[2][0] != '\0') {
- z->_type = (4 + _objectsNames->lookup(_tokens[2])) << 16;
- }
- int16 _si = _zoneTypeNames->lookup(_tokens[1]);
- if (_si != -1) {
- z->_type |= 1 << (_si - 1);
- parseZoneTypeBlock(script, z);
- continue;
- }
- }
- if (!scumm_stricmp(_tokens[0], "commands")) {
- parseCommands(script, z->_commands);
- }
- if (!scumm_stricmp(_tokens[0], "label")) {
-// printf("label: %s", _tokens[1]);
- _gfx->makeCnvFromString(&z->_label._cnv, _tokens[1]);
- }
- if (!scumm_stricmp(_tokens[0], "flags")) {
- uint16 _si = 1;
-
- do {
- char _al = _zoneFlagNames->lookup(_tokens[_si]);
- _si++;
- z->_flags |= 1 << (_al - 1);
- } while (!scumm_stricmp(_tokens[_si++], "|"));
- }
-
- fillBuffers(script, true);
- }
-
- return;
-}
-
-void Parallaction::freeZones() {
- debugC(1, kDebugLocation, "freeZones: kEngineQuit = %i", _engineFlags & kEngineQuit);
-
- ZoneList::iterator it = _zones.begin();
-
- while ( it != _zones.end() ) {
-
- Zone* z = *it;
-
- // 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,
- // but we need to check it separately here. The same workaround is applied in hitZone.
- if (((z->_top == -1) ||
- ((z->_left == -2) && (
- (((z->_type & 0xFFFF) == kZoneMerge) && ((isItemInInventory(MAKE_INVENTORY_ID(z->u.merge->_obj1)) != 0) || (isItemInInventory(MAKE_INVENTORY_ID(z->u.merge->_obj2)) != 0))) ||
- (((z->_type & 0xFFFF) == kZoneGet) && ((isItemInInventory(MAKE_INVENTORY_ID(z->u.get->_icon)) != 0)))
- ))) &&
- ((_engineFlags & kEngineQuit) == 0)) {
-
- debugC(1, kDebugLocation, "freeZones preserving zone '%s'", z->_label._text);
-
- it++;
-
- } else
-
- it = _zones.erase(it);
-
- }
-
- return;
-}
-
-
-
-
-
-
-
-
-
-void Parallaction::parseZoneTypeBlock(Script &script, Zone *z) {
-// printf("parseZoneTypeBlock()");
-
- TypeData *u = &z->u;
-
- switch (z->_type & 0xFFFF) {
- case kZoneExamine: // examine Zone alloc
- u->examine = new ExamineData;
- break;
-
- case kZoneDoor: // door Zone alloc
- u->door = new DoorData;
- break;
-
- case kZoneGet: // get Zone alloc
- u->get = new GetData;
- break;
-
- case kZoneMerge: // merge Zone alloc
- u->merge = new MergeData;
- break;
-
- case kZoneHear: // hear Zone alloc
- u->hear = new HearData;
- break;
-
- case kZoneSpeak: // speak Zone alloc
- u->speak = new SpeakData;
- break;
-
- }
-
- char vC8[PATH_LEN];
-
-// printf("type = %x", z->_type);
-
- do {
-
- switch (z->_type & 0xFFFF) {
- case kZoneExamine: // examine Zone init
- if (!scumm_stricmp(_tokens[0], "file")) {
- u->examine->_filename = (char*)malloc(strlen(_tokens[1])+1);
- strcpy(u->examine->_filename, _tokens[1]);
- }
- if (!scumm_stricmp(_tokens[0], "desc")) {
- u->examine->_description = parseComment(script);
- }
- break;
-
- case kZoneDoor: // door Zone init
- if (!scumm_stricmp(_tokens[0], "slidetext")) {
- strcpy(_slideText[0], _tokens[1]);
-// printf("%s\t", _slideText[0]);
- strcpy(_slideText[1], _tokens[2]);
- }
-
- if (!scumm_stricmp(_tokens[0], "location")) {
- u->door->_location = (char*)malloc(strlen(_tokens[1])+1);
- strcpy(u->door->_location, _tokens[1]);
- }
-
- if (!scumm_stricmp(_tokens[0], "file")) {
-// printf("file: '%s'", _tokens[0]);
-
- strcpy(vC8, _tokens[1]);
-
- u->door->_cnv = _disk->loadFrames(vC8);
- uint16 _ax = (z->_flags & kFlagsClosed ? 0 : 1);
-
- u->door->_background = (byte*)malloc(u->door->_cnv->_width * u->door->_cnv->_height);
- _gfx->backupDoorBackground(u->door, z->_left, z->_top);
-
- _gfx->flatBlitCnv(u->door->_cnv, _ax, z->_left, z->_top, Gfx::kBitBack);
- }
-
- if (!scumm_stricmp(_tokens[0], "startpos")) {
- u->door->_startPos.x = atoi(_tokens[1]);
- u->door->_startPos.y = atoi(_tokens[2]);
- u->door->_startFrame = atoi(_tokens[3]);
- }
- break;
-
- case kZoneGet: // get Zone init
- if (!scumm_stricmp(_tokens[0], "file")) {
- strcpy(vC8, _tokens[1]);
- u->get->_cnv = _disk->loadStatic(vC8);
- u->get->_backup = (byte*)malloc(u->get->_cnv->_width*u->get->_cnv->_height);
-
- if ((z->_flags & kFlagsRemove) == 0) {
- _gfx->backupGetBackground(u->get, z->_left, z->_top);
- _gfx->flatBlitCnv(u->get->_cnv, z->_left, z->_top, Gfx::kBitBack);
- }
- }
-
- if (!scumm_stricmp(_tokens[0], "icon")) {
- u->get->_icon = 4 + _objectsNames->lookup(_tokens[1]);
- }
- break;
-
- case kZoneMerge: // merge Zone init
- if (!scumm_stricmp(_tokens[0], "obj1")) {
- u->merge->_obj1 = 4 + _objectsNames->lookup(_tokens[1]);
- }
- if (!scumm_stricmp(_tokens[0], "obj2")) {
- u->merge->_obj2 = 4 + _objectsNames->lookup(_tokens[1]);
- }
- if (!scumm_stricmp(_tokens[0], "newobj")) {
- u->merge->_obj3 = 4 + _objectsNames->lookup(_tokens[1]);
- }
- break;
-
- case kZoneHear: // hear Zone init
- if (!scumm_stricmp(_tokens[0], "sound")) {
- strcpy(u->hear->_name, _tokens[1]);
- z->u.hear->_channel = atoi(_tokens[2]);
- }
- if (!scumm_stricmp(_tokens[0], "freq")) {
- z->u.hear->_freq = atoi(_tokens[1]);
- }
- break;
-
- case kZoneSpeak: // speak Zone init
- if (!scumm_stricmp(_tokens[0], "file")) {
- strcpy(u->speak->_name, _tokens[1]);
-// printf("speak file name: %s", u.speak._name);
- }
- if (!scumm_stricmp(_tokens[0], "Dialogue")) {
- u->speak->_dialogue = parseDialogue(script);
- }
- break;
- }
-
- fillBuffers(script, true);
- } while (scumm_stricmp(_tokens[0], "endzone"));
-
- return;
-}
-
-// displays character head commenting an examined object
-//
-// works on the frontbuffer
-//
-void Parallaction::displayCharacterComment(ExamineData *data) {
- if (data->_description == NULL) return;
-
- // NOTE: saving visible screen before displaying comment allows
- // to restore the exact situation after the comment is deleted.
- // This means animations are restored in the exact position as
- // they were, thus avoiding clipping effect as signalled in
- // BUG item #1762614.
- _gfx->copyScreen(Gfx::kBitFront, Gfx::kBitBack);
-
- _gfx->setFont(kFontDialogue);
- _gfx->flatBlitCnv(_char._talk, 0, 190, 80, Gfx::kBitFront);
-
- int16 v26, v28;
- _gfx->getStringExtent(data->_description, 130, &v28, &v26);
- Common::Rect r(v28, v26);
- r.moveTo(140, 10);
- _gfx->drawBalloon(r, 0);
- _gfx->displayWrappedString(data->_description, 140, 10, 0, 130);
-
- waitUntilLeftClick();
-
- _gfx->copyScreen(Gfx::kBitBack, Gfx::kBitFront);
- _gfx->updateScreen();
-
- return;
-}
-
-//
-// ZONE TYPE: EXAMINE
-//
-
-// display detail view of an item (and eventually comments)
-//
-// works on the frontbuffer
-//
-
-void Parallaction::displayItemComment(ExamineData *data) {
-
- if (data->_description == NULL) return;
-
- _gfx->setHalfbriteMode(true);
-
- char v68[PATH_LEN];
- strcpy(v68, data->_filename);
- data->_cnv = _disk->loadStatic(v68);
- _gfx->flatBlitCnv(data->_cnv, 140, (_screenHeight - data->_cnv->_height)/2, Gfx::kBitFront);
- _gfx->freeStaticCnv(data->_cnv);
- delete data->_cnv;
-
- int16 v6A = 0, v6C = 0;
-
- _gfx->setFont(kFontDialogue);
- _gfx->getStringExtent(data->_description, 130, &v6C, &v6A);
- Common::Rect r(v6C, v6A);
- r.moveTo(0, 90);
- _gfx->drawBalloon(r, 0);
- _gfx->flatBlitCnv(_char._head, 100, 152, Gfx::kBitFront);
- _gfx->displayWrappedString(data->_description, 0, 90, 0, 130);
-
- jobEraseAnimations((void*)1, NULL);
- _gfx->updateScreen();
-
- waitUntilLeftClick();
-
- _gfx->setHalfbriteMode(false);
- _gfx->copyScreen(Gfx::kBitBack, Gfx::kBitFront);
- _gfx->updateScreen();
-
- return;
-}
-
-
-
-uint16 Parallaction::runZone(Zone *z) {
- debugC(3, kDebugLocation, "runZone (%s)", z->_label._text);
-
- uint16 subtype = z->_type & 0xFFFF;
-
- debugC(3, kDebugLocation, "type = %x, object = %x", subtype, (z->_type & 0xFFFF0000) >> 16);
- switch(subtype) {
-
- case kZoneExamine:
- if (z->u.examine->_filename) {
- displayItemComment(z->u.examine);
- } else {
- displayCharacterComment(z->u.examine);
- }
- break;
-
- case kZoneGet:
- if (z->_flags & kFlagsFixed) break;
- if (pickupItem(z) != 0) {
- return 1;
- }
- z->_flags |= kFlagsRemove;
- break;
-
- case kZoneDoor:
- if (z->_flags & kFlagsLocked) break;
- z->_flags ^= kFlagsClosed;
- if (z->u.door->_cnv == NULL) break;
- addJob(&jobToggleDoor, z, kPriority18 );
- break;
-
- case kZoneHear:
- _soundMan->playSfx(z->u.hear->_name, z->u.hear->_channel, (z->_flags & kFlagsLooping) == kFlagsLooping, 60);
- break;
-
- case kZoneSpeak:
- runDialogue(z->u.speak);
- break;
-
- }
-
- debugC(3, kDebugLocation, "runZone completed");
-
- return 0;
-}
-
-//
-// ZONE TYPE: DOOR
-//
-void jobToggleDoor(void *parm, Job *j) {
-
- static byte count = 0;
-
- Zone *z = (Zone*)parm;
-
- StaticCnv v14;
-
- if (z->u.door->_cnv) {
- Common::Rect r(z->_left, z->_top, z->_left+z->u.door->_cnv->_width, z->_top+z->u.door->_cnv->_height);
-
- uint16 _ax = (z->_flags & kFlagsClosed ? 1 : 0);
-
- v14._width = z->u.door->_cnv->_width;
- v14._height = z->u.door->_cnv->_height;
- v14._data0 = z->u.door->_cnv->getFramePtr(_ax);
-
- _vm->_gfx->restoreDoorBackground(&v14, r, z->u.door->_background);
-
- _ax = (z->_flags & kFlagsClosed ? 0 : 1);
-
- _vm->_gfx->flatBlitCnv(z->u.door->_cnv, _ax, z->_left, z->_top, Gfx::kBitBack);
- _vm->_gfx->flatBlitCnv(z->u.door->_cnv, _ax, z->_left, z->_top, Gfx::kBit2);
- }
-
- count++;
- if (count == 2) {
- j->_finished = 1;
- count = 0;
- }
-
- return;
-}
-
-
-
-//
-// ZONE TYPE: GET
-//
-
-int16 Parallaction::pickupItem(Zone *z) {
- int r = addInventoryItem(z->u.get->_icon);
- if (r == 0)
- addJob(&jobRemovePickedItem, z, kPriority17 );
-
- return r;
-}
-
-void jobRemovePickedItem(void *parm, Job *j) {
-
- Zone *z = (Zone*)parm;
-
- static uint16 count = 0;
-
- if (z->u.get->_cnv) {
- Common::Rect r(z->_left, z->_top, z->_left + z->u.get->_cnv->_width, z->_top + z->u.get->_cnv->_height);
-
- _vm->_gfx->restoreGetBackground(r, z->u.get->_backup);
- }
-
- count++;
- if (count == 2) {
- count = 0;
- j->_finished = 1;
- }
-
- return;
-}
-
-void jobDisplayDroppedItem(void *parm, Job *j) {
-// printf("jobDisplayDroppedItem...");
-
- Zone *z = (Zone*)parm;
-
- if (z->u.get->_cnv) {
- if (j->_count == 0) {
- _vm->_gfx->backupGetBackground(z->u.get, z->_left, z->_top);
- }
-
- _vm->_gfx->flatBlitCnv(z->u.get->_cnv, z->_left, z->_top, Gfx::kBitBack);
- _vm->_gfx->flatBlitCnv(z->u.get->_cnv, z->_left, z->_top, Gfx::kBit2);
- }
-
- j->_count++;
- if (j->_count == 2) {
- j->_count = 0;
- j->_finished = 1;
- }
-
-// printf("done");
-
- return;
-}
-
-
-
-
-Zone *Parallaction::hitZone(uint32 type, uint16 x, uint16 y) {
-// printf("hitZone(%i, %i, %i)", type, x, y);
-
- uint16 _di = y;
- uint16 _si = x;
-
- for (ZoneList::iterator it = _zones.begin(); it != _zones.end(); it++) {
-// printf("Zone name: %s", z->_name);
-
- Zone *z = *it;
-
- if (z->_flags & kFlagsRemove) continue;
-
- Common::Rect r;
- z->getRect(r);
- r.right++; // adjust border because Common::Rect doesn't include bottom-right edge
- r.bottom++;
-
- r.grow(-1); // allows some tolerance for mouse click
-
- if (!r.contains(_si, _di)) {
-
- // out of Zone, so look for special values
- if ((z->_left == -2) || (z->_left == -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,
- // but we need to check it separately here. The same workaround is applied in freeZones.
- if ((((z->_type & 0xFFFF) == kZoneMerge) && (((_si == z->u.merge->_obj1) && (_di == z->u.merge->_obj2)) || ((_si == z->u.merge->_obj2) && (_di == z->u.merge->_obj1)))) ||
- (((z->_type & 0xFFFF) == kZoneGet) && ((_si == z->u.get->_icon) || (_di == z->u.get->_icon)))) {
-
- // special Zone
- if ((type == 0) && ((z->_type & 0xFFFF0000) == 0))
- return z;
- if (z->_type == type)
- return z;
- if ((z->_type & 0xFFFF0000) == type)
- return z;
-
- }
- }
-
- if (z->_left != -1)
- continue;
- if (_si < _char._ani._left)
- continue;
- if (_si > (_char._ani._left + _char._ani.width()))
- continue;
- if (_di < _char._ani._top)
- continue;
- if (_di > (_char._ani._top + _char._ani.height()))
- continue;
-
- }
-
- // normal Zone
- if ((type == 0) && ((z->_type & 0xFFFF0000) == 0))
- return z;
- if (z->_type == type)
- return z;
- if ((z->_type & 0xFFFF0000) == type)
- return z;
-
- }
-
-
- int16 _a, _b, _c, _d, _e, _f;
- for (AnimationList::iterator it = _animations.begin(); it != _animations.end(); it++) {
-
- Animation *a = *it;
-
- _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
-
- _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
- _d = ((a->_type & 0xFFFF0000) != type) ? 0 : 1; // _d: Animation is an object of the same type
-
- if ((_a != 0 && _e != 0 && _f != 0) && ((_b != 0 && _c != 0) || (a->_type == type) || (_d != 0))) {
-
- return a;
-
- }
-
- }
-
- return NULL;
-}
-
-
-Zone::Zone() {
- _left = _top = _right = _bottom = 0;
-
- _type = 0;
- _flags = 0;
-}
-
-Zone::~Zone() {
-// printf("~Zone(%s)\n", _label._text);
-
- switch (_type & 0xFFFF) {
- case kZoneExamine:
- free(u.examine->_filename);
- free(u.examine->_description);
- delete u.examine;
- break;
-
- case kZoneDoor:
- free(u.door->_location);
- free(u.door->_background);
- if (u.door->_cnv)
- delete u.door->_cnv;
- delete u.door;
- break;
-
- case kZoneSpeak:
- delete u.speak->_dialogue;
- delete u.speak;
- break;
-
- case kZoneGet:
- free(u.get->_backup);
- _vm->_gfx->freeStaticCnv(u.get->_cnv);
- if (u.get->_cnv)
- delete u.get->_cnv;
- delete u.get;
- break;
-
- case kZoneHear:
- delete u.hear;
- break;
-
- case kZoneMerge:
- delete u.merge;
- break;
-
- default:
- break;
- }
-}
-
-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;
- _top += y;
- _bottom += y;
-}
-
-uint16 Zone::width() const {
- return _right - _left;
-}
-
-uint16 Zone::height() const {
- return _bottom - _top;
-}
-
-Label::Label() {
- _text = NULL;
-}
-
-Label::~Label() {
- _vm->_gfx->freeStaticCnv(&_cnv);
- if (_text)
- free(_text);
-}
-
-
-} // namespace Parallaction
diff --git a/engines/queen/cutaway.cpp b/engines/queen/cutaway.cpp
index 1f34128820..721d7bb318 100644
--- a/engines/queen/cutaway.cpp
+++ b/engines/queen/cutaway.cpp
@@ -181,8 +181,7 @@ void Cutaway::loadStrings(uint16 offset) {
debug(6, "_talkTo = %i", _talkTo);
}
-const byte *Cutaway::getCutawayObject(const byte *ptr, CutawayObject &object)
-{
+const byte *Cutaway::getCutawayObject(const byte *ptr, CutawayObject &object) {
const byte *oldPtr = ptr;
object.objectNumber = (int16)READ_BE_INT16(ptr); ptr += 2;
@@ -216,8 +215,7 @@ const byte *Cutaway::getCutawayObject(const byte *ptr, CutawayObject &object)
return ptr;
}
-void Cutaway::dumpCutawayObject(int index, CutawayObject &object)
-{
+void Cutaway::dumpCutawayObject(int index, CutawayObject &object) {
debug(6, "----- CutawayObject[%i] -----", index);
const char *objectNumberStr;
@@ -367,7 +365,7 @@ void Cutaway::changeRooms(CutawayObject &object) {
_vm->logic()->oldRoom(_initialRoom);
- // FIXME - Cutaway c41f is played at the end of the command 0x178. This command
+ // FIXME: Cutaway c41f is played at the end of the command 0x178. This command
// setups some persons and associates bob slots to them. They should be hidden as
// their y coordinate is > 150, but they aren't ! As a workaround, we display the room
// with the panel area enabled. We do the same problem for cutaway c62c.
diff --git a/engines/queen/display.cpp b/engines/queen/display.cpp
index a8c2747753..9c4101f1d3 100644
--- a/engines/queen/display.cpp
+++ b/engines/queen/display.cpp
@@ -36,14 +36,6 @@
namespace Queen {
-#ifdef PALMOS_68K
-static const uint8 *_fontRegular;
-static const uint8 *_fontHebrew;
-static const uint8 *_fontRussian;
-static const uint8 *_palJoeClothes;
-static const uint8 *_palJoeDress;
-#endif
-
Display::Display(QueenEngine *vm, OSystem *system)
: _fullscreen(true), _horizontalScroll(0), _bdWidth(0), _bdHeight(0),
_system(system), _vm(vm) {
@@ -1230,7 +1222,6 @@ void Display::blankScreenEffect3() {
}
}
-#ifndef PALMOS_68K
const uint8 Display::_fontRegular[] = {
0xF8, 0xB0, 0xB0, 0x80, 0xB0, 0xB0, 0xC0, 0x00, 0xF8, 0xB0, 0xB0, 0x80, 0xB0, 0xB0, 0xC0, 0x00,
0xF8, 0xB0, 0xB0, 0x80, 0xB0, 0xB0, 0xC0, 0x00, 0xF8, 0xB0, 0xB0, 0x80, 0xB0, 0xB0, 0xC0, 0x00,
@@ -1636,25 +1627,4 @@ const uint8 Display::_palJoeDress[] = {
0x22, 0xED, 0x42, 0x42, 0x80, 0x45, 0x45, 0xA3, 0x5F, 0x5F, 0xC8, 0x7C, 0x7C, 0xEC, 0x9C, 0x9C
};
-#endif
-
} // End of namespace Queen
-
-#ifdef PALMOS_68K
-#include "scumm_globals.h"
-
-_GINIT(Queen_Display)
-_GSETPTR(Queen::_fontRegular, GBVARS_DISPLAYFONTREGULAR_INDEX, uint8, GBVARS_QUEEN)
-_GSETPTR(Queen::_fontHebrew, GBVARS_DISPLAYFONTHEBREW_INDEX, uint8, GBVARS_QUEEN)
-_GSETPTR(Queen::_palJoeClothes, GBVARS_DISPLAYPALJOECLOTHES_INDEX, uint8, GBVARS_QUEEN)
-_GSETPTR(Queen::_palJoeDress, GBVARS_DISPLAYPALJOEDRESS_INDEX, uint8, GBVARS_QUEEN)
-_GEND
-
-_GRELEASE(Queen_Display)
-_GRELEASEPTR(GBVARS_DISPLAYFONTREGULAR_INDEX, GBVARS_QUEEN)
-_GRELEASEPTR(GBVARS_DISPLAYFONTHEBREW_INDEX, GBVARS_QUEEN)
-_GRELEASEPTR(GBVARS_DISPLAYPALJOECLOTHES_INDEX, GBVARS_QUEEN)
-_GRELEASEPTR(GBVARS_DISPLAYPALJOEDRESS_INDEX, GBVARS_QUEEN)
-_GEND
-
-#endif
diff --git a/engines/queen/display.h b/engines/queen/display.h
index 23316f880a..b26ae1fac0 100644
--- a/engines/queen/display.h
+++ b/engines/queen/display.h
@@ -254,13 +254,12 @@ private:
QueenEngine *_vm;
const uint8 *_font;
-#ifndef PALMOS_68K
+
static const uint8 _fontRegular[];
static const uint8 _fontHebrew[];
static const uint8 _fontRussian[];
static const uint8 _palJoeClothes[];
static const uint8 _palJoeDress[];
-#endif
};
diff --git a/engines/queen/graphics.cpp b/engines/queen/graphics.cpp
index 4beca6556d..6199a75e7c 100644
--- a/engines/queen/graphics.cpp
+++ b/engines/queen/graphics.cpp
@@ -36,13 +36,6 @@
namespace Queen {
-#ifdef PALMOS_68K
-static const BamScene::BamDataBlock *_carData;
-static const BamScene::BamDataBlock *_fight1Data;
-static const BamScene::BamDataBlock *_fight2Data;
-static const BamScene::BamDataBlock *_fight3Data;
-#endif
-
const Box BobSlot::_defaultBox(-1, -1, -1, -1);
void BobSlot::curPos(int16 xx, int16 yy) {
@@ -1311,7 +1304,6 @@ void BamScene::loadState(uint32 ver, byte *&ptr) {
_flag = READ_BE_UINT16(ptr); ptr += 2;
}
-#ifndef PALMOS_68K
const BamScene::BamDataBlock BamScene::_carData[] = {
{ { 310, 105, 1 }, { 314, 106, 17 }, { 366, 101, 1 }, 0 },
{ { 303, 105, 1 }, { 307, 106, 17 }, { 214, 0, 10 }, 0 },
@@ -1630,25 +1622,5 @@ const BamScene::BamDataBlock BamScene::_fight4Data[] = {
{ { 75, 96, 1 }, { 187, 96, -23 }, { 0, 0, 0 }, 0 },
{ { 75, 96, 1 }, { 187, 96, -23 }, { 0, 0, 0 }, 99 }
};
-#endif
} // End of namespace Queen
-
-#ifdef PALMOS_68K
-#include "scumm_globals.h"
-
-_GINIT(Queen_Graphics)
-_GSETPTR(Queen::_carData, GBVARS_GRAPHICSCARDATA_INDEX, Queen::BamScene::BamDataBlock, GBVARS_QUEEN)
-_GSETPTR(Queen::_fight1Data, GBVARS_GRAPHICSFIGHT1DATA_INDEX, Queen::BamScene::BamDataBlock, GBVARS_QUEEN)
-_GSETPTR(Queen::_fight2Data, GBVARS_GRAPHICSFIGHT2DATA_INDEX, Queen::BamScene::BamDataBlock, GBVARS_QUEEN)
-_GSETPTR(Queen::_fight3Data, GBVARS_GRAPHICSFIGHT3DATA_INDEX, Queen::BamScene::BamDataBlock, GBVARS_QUEEN)
-_GEND
-
-_GRELEASE(Queen_Graphics)
-_GRELEASEPTR(GBVARS_GRAPHICSCARDATA_INDEX, GBVARS_QUEEN)
-_GRELEASEPTR(GBVARS_GRAPHICSFIGHT1DATA_INDEX, GBVARS_QUEEN)
-_GRELEASEPTR(GBVARS_GRAPHICSFIGHT2DATA_INDEX, GBVARS_QUEEN)
-_GRELEASEPTR(GBVARS_GRAPHICSFIGHT3DATA_INDEX, GBVARS_QUEEN)
-_GEND
-
-#endif
diff --git a/engines/queen/graphics.h b/engines/queen/graphics.h
index 3963224069..9684217ef0 100644
--- a/engines/queen/graphics.h
+++ b/engines/queen/graphics.h
@@ -261,18 +261,12 @@ private:
int16 frame;
};
-#ifdef PALMOS_68K
-public:
-#endif
struct BamDataBlock {
BamDataObj obj1; // truck / Frank
BamDataObj obj2; // Rico / robot
BamDataObj fx;
int16 sfx;
};
-#ifdef PALMOS_68K
-private:
-#endif
BobSlot *_obj1;
BobSlot *_obj2;
@@ -283,13 +277,11 @@ private:
QueenEngine *_vm;
-#ifndef PALMOS_68K
static const BamDataBlock _carData[];
static const BamDataBlock _fight1Data[];
static const BamDataBlock _fight2Data[];
static const BamDataBlock _fight3Data[];
static const BamDataBlock _fight4Data[];
-#endif
};
} // End of namespace Queen
diff --git a/engines/queen/musicdata.cpp b/engines/queen/musicdata.cpp
index bfb843766c..a0b2a73697 100644
--- a/engines/queen/musicdata.cpp
+++ b/engines/queen/musicdata.cpp
@@ -28,16 +28,6 @@
namespace Queen {
-#ifdef PALMOS_68K
-
-const songData *Sound::_songDemo;
-const songData *Sound::_song;
-const tuneData *Sound::_tuneDemo;
-const tuneData *Sound::_tune;
-const char *Sound::_sfxName;
-const int16 *Sound::_jungleList;
-
-#else
const songData Sound::_songDemo[] = {
/* 1 - Hotel Gangsters */
{ { 1, 0 }, 128, 128, 128, 1, 0 },
@@ -1919,29 +1909,6 @@ const char *Sound::_sfxName[] = {
};
const int16 Sound::_jungleList[] = { 15, 16, 17, 18, 7, 8, 9, 10, 11, 12, 13, 14, 0 };
-#endif
-} // End of namespace Queen
-#ifdef PALMOS_68K
-#include "scumm_globals.h"
-
-_GINIT(Queen_Musicdata)
-_GSETPTR(Queen::Sound::_songDemo, GBVARS_MUSICDATASONGDEMO_INDEX, Queen::songData, GBVARS_QUEEN)
-_GSETPTR(Queen::Sound::_song, GBVARS_MUSICDATASONG_INDEX, Queen::songData, GBVARS_QUEEN)
-_GSETPTR(Queen::Sound::_tuneDemo, GBVARS_MUSICDATATUNEDEMO_INDEX, Queen::tuneData, GBVARS_QUEEN)
-_GSETPTR(Queen::Sound::_tune, GBVARS_MUSICDATATUNE_INDEX, Queen::tuneData, GBVARS_QUEEN)
-_GSETPTR(Queen::Sound::_sfxName, GBVARS_MUSICDATASFXNAME_INDEX, char, GBVARS_QUEEN)
-_GSETPTR(Queen::Sound::_jungleList, GBVARS_MUSICDATAJUNGLELIST_INDEX, int16, GBVARS_QUEEN)
-_GEND
-
-_GRELEASE(Queen_Musicdata)
-_GRELEASEPTR(GBVARS_MUSICDATASONGDEMO_INDEX, GBVARS_QUEEN)
-_GRELEASEPTR(GBVARS_MUSICDATASONG_INDEX, GBVARS_QUEEN)
-_GRELEASEPTR(GBVARS_MUSICDATATUNEDEMO_INDEX, GBVARS_QUEEN)
-_GRELEASEPTR(GBVARS_MUSICDATATUNE_INDEX, GBVARS_QUEEN)
-_GRELEASEPTR(GBVARS_MUSICDATASFXNAME_INDEX, GBVARS_QUEEN)
-_GRELEASEPTR(GBVARS_MUSICDATAJUNGLELIST_INDEX, GBVARS_QUEEN)
-_GEND
-
-#endif
+} // End of namespace Queen
diff --git a/engines/queen/resource.cpp b/engines/queen/resource.cpp
index 999a86d432..20b047cb71 100644
--- a/engines/queen/resource.cpp
+++ b/engines/queen/resource.cpp
@@ -30,9 +30,6 @@
namespace Queen {
-#ifdef PALMOS_68K
-static ResourceEntry *_resourceTablePEM10;
-#endif
const char *Resource::_tableFilename = "queen.tbl";
@@ -325,16 +322,3 @@ Common::File *Resource::findSound(const char *filename, uint32 *size) {
}
} // End of namespace Queen
-
-#ifdef PALMOS_68K
-#include "scumm_globals.h"
-
-_GINIT(Queen_Restables)
-_GSETPTR(Queen::_resourceTablePEM10, GBVARS_RESOURCETABLEPM10_INDEX, Queen::ResourceEntry, GBVARS_QUEEN)
-_GEND
-
-_GRELEASE(Queen_Restables)
-_GRELEASEPTR(GBVARS_RESOURCETABLEPM10_INDEX, GBVARS_QUEEN)
-_GEND
-
-#endif
diff --git a/engines/queen/resource.h b/engines/queen/resource.h
index 16094193d9..43c8e68939 100644
--- a/engines/queen/resource.h
+++ b/engines/queen/resource.h
@@ -165,10 +165,8 @@ protected:
//! known FOTAQ versions
static const RetailGameVersion _gameVersions[];
-#ifndef PALMOS_68K
//! resource table for english floppy version
static ResourceEntry _resourceTablePEM10[];
-#endif
};
} // End of namespace Queen
diff --git a/engines/queen/restables.cpp b/engines/queen/restables.cpp
index 721bde626f..d4c30c7bea 100644
--- a/engines/queen/restables.cpp
+++ b/engines/queen/restables.cpp
@@ -27,7 +27,6 @@
namespace Queen {
-#ifndef PALMOS_68K
//English Floppy Version
ResourceEntry Resource::_resourceTablePEM10[] = {
{ "1000SSSS.SB", 1, 0x00000000, 0x000027fe },
@@ -1107,5 +1106,5 @@ ResourceEntry Resource::_resourceTablePEM10[] = {
{ "ZOMBIE1.DOG", 1, 0x0159ecef, 0x00000f6a },
{ "ZOMBIE2.DOG", 1, 0x0159fc59, 0x00000c40 }
};
-#endif
+
} // End of namespace Queen
diff --git a/engines/queen/sound.cpp b/engines/queen/sound.cpp
index a4cac2417e..1da07cf97c 100644
--- a/engines/queen/sound.cpp
+++ b/engines/queen/sound.cpp
@@ -173,13 +173,8 @@ PCSound::~PCSound() {
}
void PCSound::playSfx(uint16 sfx) {
- if (sfxOn() && sfx != 0) {
-#ifndef PALMOS_68K
+ if (sfxOn() && sfx != 0)
playSound(_sfxName[sfx - 1], false);
-#else
- playSound(_sfxName + 10 * (sfx - 1), false); // saved as 8char + /0/0
-#endif
- }
}
void PCSound::playSong(int16 songNum) {
diff --git a/engines/queen/sound.h b/engines/queen/sound.h
index 145a2d1384..d87ab63a18 100644
--- a/engines/queen/sound.h
+++ b/engines/queen/sound.h
@@ -103,21 +103,12 @@ public:
void saveState(byte *&ptr);
void loadState(uint32 ver, byte *&ptr);
-#ifndef PALMOS_68K
static const songData _songDemo[];
static const songData _song[];
static const tuneData _tuneDemo[];
static const tuneData _tune[];
static const char *_sfxName[];
static const int16 _jungleList[];
-#else
- static const songData *_songDemo;
- static const songData *_song;
- static const tuneData *_tuneDemo;
- static const tuneData *_tune;
- static const char *_sfxName;
- static const int16 *_jungleList;
-#endif
protected:
diff --git a/engines/queen/talk.cpp b/engines/queen/talk.cpp
index a47584a003..8396356685 100644
--- a/engines/queen/talk.cpp
+++ b/engines/queen/talk.cpp
@@ -46,10 +46,6 @@
namespace Queen {
-#ifdef PALMOS_68K
-static const Talk::SpeechParameters *_speechParameters;
-#endif
-
void Talk::talk(
const char *filename,
int personInRoom,
@@ -1357,7 +1353,6 @@ int16 Talk::selectSentence() {
return selectedSentence;
}
-#ifndef PALMOS_68K
const Talk::SpeechParameters Talk::_speechParameters[] = {
{ "JOE", 0, 1, 1, 10, 2, 3, "", 0 },
{ "JOE", 0, 3, 3, 28, 2, 3, "", 0 },
@@ -1818,19 +1813,5 @@ const Talk::SpeechParameters Talk::_speechParameters[] = {
{ "*", 0, 0, 0, 0, 0, 0, "", 0 }
};
-#endif
} // End of namespace Queen
-
-#ifdef PALMOS_68K
-#include "scumm_globals.h"
-
-_GINIT(Queen_Talk)
-_GSETPTR(Queen::_speechParameters, GBVARS_SPEECHPARAMETERS_INDEX, Queen::Talk::SpeechParameters, GBVARS_QUEEN)
-_GEND
-
-_GRELEASE(Queen_Talk)
-_GRELEASEPTR(GBVARS_SPEECHPARAMETERS_INDEX, GBVARS_QUEEN)
-_GEND
-
-#endif
diff --git a/engines/queen/talk.h b/engines/queen/talk.h
index 1548d0ba27..036dfadbcd 100644
--- a/engines/queen/talk.h
+++ b/engines/queen/talk.h
@@ -81,7 +81,6 @@ private:
int16 gameStateValue;
};
-#ifndef PALMOS_68K
struct SpeechParameters {
const char *name;
signed char state,faceDirection;
@@ -89,17 +88,6 @@ private:
const char *animation;
signed char ff;
};
-#else
-public:
- struct SpeechParameters {
- const char name[11];
- signed char state,faceDirection;
- signed char body,bf,rf,af;
- const char animation[80];
- signed char ff;
- };
-private:
-#endif
QueenEngine *_vm;
@@ -154,9 +142,7 @@ private:
char _talkString[5][MAX_STRING_SIZE];
char _joeVoiceFilePrefix[5][MAX_STRING_SIZE];
-#ifndef PALMOS_68K
static const SpeechParameters _speechParameters[];
-#endif
Talk(QueenEngine *vm);
~Talk();
diff --git a/engines/saga/actor.cpp b/engines/saga/actor.cpp
index c2ecff4a1a..6d996d2d40 100644
--- a/engines/saga/actor.cpp
+++ b/engines/saga/actor.cpp
@@ -29,18 +29,12 @@
#include "saga/animation.h"
#include "saga/console.h"
#include "saga/events.h"
-#include "saga/gfx.h"
-#include "saga/interface.h"
#include "saga/isomap.h"
-#include "saga/itedata.h"
#include "saga/objectmap.h"
#include "saga/sagaresnames.h"
#include "saga/rscfile.h"
#include "saga/script.h"
#include "saga/sndres.h"
-#include "saga/sprite.h"
-#include "saga/stream.h"
-#include "saga/font.h"
#include "saga/sound.h"
#include "saga/scene.h"
@@ -48,24 +42,6 @@
namespace Saga {
-enum ActorFrameIds {
-//ITE
- kFrameITEStand = 0,
- kFrameITEWalk = 1,
- kFrameITESpeak = 2,
- kFrameITEGive = 3,
- kFrameITEGesture = 4,
- kFrameITEWait = 5,
- kFrameITEPickUp = 6,
- kFrameITELook = 7,
-//IHNM
- kFrameIHNMStand = 0,
- kFrameIHNMSpeak = 1,
- kFrameIHNMWait = 2,
- kFrameIHNMGesture = 3,
- kFrameIHNMWalk = 4
-};
-
static int commonObjectCompare(const CommonObjectDataPointer& obj1, const CommonObjectDataPointer& obj2) {
int p1 = obj1->_location.y - obj1->_location.z;
int p2 = obj2->_location.y - obj2->_location.z;
@@ -76,6 +52,16 @@ static int commonObjectCompare(const CommonObjectDataPointer& obj1, const Common
return 1;
}
+static int commonObjectCompareIHNM(const CommonObjectDataPointer& obj1, const CommonObjectDataPointer& obj2) {
+ int p1 = obj1->_location.y;
+ int p2 = obj2->_location.y;
+ if (p1 == p2)
+ return 0;
+ if (p1 < p2)
+ return -1;
+ return 1;
+}
+
static int tileCommonObjectCompare(const CommonObjectDataPointer& obj1, const CommonObjectDataPointer& obj2) {
int p1 = -obj1->_location.u() - obj1->_location.v() - obj1->_location.z;
int p2 = -obj2->_location.u() - obj2->_location.v() - obj2->_location.z;
@@ -89,140 +75,6 @@ static int tileCommonObjectCompare(const CommonObjectDataPointer& obj1, const Co
return 1;
}
-inline int16 int16Compare(int16 i1, int16 i2) {
- return ((i1) > (i2) ? 1 : ((i1) < (i2) ? -1 : 0));
-}
-
-inline int16 quickDistance(const Point &point1, const Point &point2, int16 compressX) {
- Point delta;
- delta.x = ABS(point1.x - point2.x) / compressX;
- delta.y = ABS(point1.y - point2.y);
- return ((delta.x < delta.y) ? (delta.y + delta.x / 2) : (delta.x + delta.y / 2));
-}
-
-inline void calcDeltaS(const Point &point1, const Point &point2, Point &delta, Point &s) {
-
- delta.x = point2.x - point1.x;
- if (delta.x == 0) {
- s.x = 0;
- } else {
- if (delta.x > 0) {
- s.x = 1;
- } else {
- s.x = -1;
- delta.x = -delta.x;
- }
- }
-
-
- delta.y = point2.y - point1.y;
- if (delta.y == 0) {
- s.y = 0;
- } else {
- if (delta.y > 0) {
- s.y = 1;
- } else {
- s.y = -1;
- delta.y = -delta.y;
- }
- }
-}
-
-// Lookup table to convert 8 cardinal directions to 4
-static const int actorDirectectionsLUT[8] = {
- ACTOR_DIRECTION_BACK, // kDirUp
- ACTOR_DIRECTION_RIGHT, // kDirUpRight
- ACTOR_DIRECTION_RIGHT, // kDirRight
- ACTOR_DIRECTION_RIGHT, // kDirDownRight
- ACTOR_DIRECTION_FORWARD,// kDirDown
- ACTOR_DIRECTION_LEFT, // kDirDownLeft
- ACTOR_DIRECTION_LEFT, // kDirLeft
- ACTOR_DIRECTION_LEFT, // kDirUpLeft
-};
-
-static const PathDirectionData pathDirectionLUT[8][3] = {
- { { 0, Point( 0, -1) }, { 7, Point(-1, -1) }, { 4, Point( 1, -1) } },
- { { 1, Point( 1, 0) }, { 4, Point( 1, -1) }, { 5, Point( 1, 1) } },
- { { 2, Point( 0, 1) }, { 5, Point( 1, 1) }, { 6, Point(-1, 1) } },
- { { 3, Point(-1, 0) }, { 6, Point(-1, 1) }, { 7, Point(-1, -1) } },
- { { 0, Point( 0, -1) }, { 1, Point( 1, 0) }, { 4, Point( 1, -1) } },
- { { 1, Point( 1, 0) }, { 2, Point( 0, 1) }, { 5, Point( 1, 1) } },
- { { 2, Point( 0, 1) }, { 3, Point(-1, 0) }, { 6, Point(-1, 1) } },
- { { 3, Point(-1, 0) }, { 0, Point( 0, -1) }, { 7, Point(-1, -1) } }
-};
-
-static const int pathDirectionLUT2[8][2] = {
- { 0, -1 },
- { 1, 0 },
- { 0, 1 },
- { -1, 0 },
- { 1, -1 },
- { 1, 1 },
- { -1, 1 },
- { -1, -1 }
-};
-
-static const int angleLUT[16][2] = {
- { 0, -256 },
- { 98, -237 },
- { 181, -181 },
- { 237, -98 },
- { 256, 0 },
- { 237, 98 },
- { 181, 181 },
- { 98, 237 },
- { 0, 256 },
- { -98, 237 },
- { -181, 181 },
- { -237, 98 },
- { -256, 0 },
- { -237, -98 },
- { -181, -181 },
- { -98, -237 }
-};
-
-static const int directionLUT[8][2] = {
- { 0 * 2, -2 * 2 },
- { 2 * 2, -1 * 2 },
- { 3 * 2, 0 * 2 },
- { 2 * 2, 1 * 2 },
- { 0 * 2, 2 * 2 },
- { -2 * 2, 1 * 2 },
- { -4 * 2, 0 * 2 },
- { -2 * 2, -1 * 2 }
-};
-
-static const int tileDirectionLUT[8][2] = {
- { 1, 1 },
- { 2, 0 },
- { 1, -1 },
- { 0, -2 },
- { -1, -1 },
- { -2, 0 },
- { -1, 1 },
- { 0, 2 }
-};
-
-struct DragonMove {
- uint16 baseFrame;
- int16 offset[4][2];
-};
-
-static const DragonMove dragonMoveTable[12] = {
- { 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 } } },
- { 28, { { -0, 0 }, { -1, 6 }, { -5, 11 }, { -10, 15 } } },
- { 56, { { 0, 0 }, { 1, 6 }, { 5, 11 }, { 10, 15 } } },
- { 40, { { 0, 0 }, { 6, 1 }, { 11, 5 }, { 15, 10 } } },
- { 44, { { 0, 0 }, { 6, -1 }, { 11, -5 }, { 15, -10 } } },
- { 32, { { -0, -0 }, { -6, -1 }, { -11, -5 }, { -15, -10 } } },
- { 52, { { -0, 0 }, { -6, 1 }, { -11, 5 }, { -15, 10 } } },
- { 36, { { 0, -0 }, { 1, -6 }, { 5, -11 }, { 10, -15 } } },
- { 48, { { -0, -0 }, { -1, -6 }, { -5, -11 }, { -10, -15 } } }
-};
-
Actor::Actor(SagaEngine *vm) : _vm(vm) {
int i;
byte *stringsPointer;
@@ -268,8 +120,6 @@ Actor::Actor(SagaEngine *vm) : _vm(vm) {
_pathRect.top = _vm->getDisplayInfo().pathStartY;
_pathRect.bottom = _vm->_scene->getHeight();
- _showActors = true;
-
// Get actor resource file context
_actorContext = _vm->_resource->getContext(GAME_RESOURCEFILE);
if (_actorContext == NULL) {
@@ -723,76 +573,6 @@ void Actor::stepZoneAction(ActorData *actor, const HitZone *hitZone, bool exit,
}
}
-void Actor::realLocation(Location &location, uint16 objectId, uint16 walkFlags) {
- int angle;
- int distance;
- ActorData *actor;
- ObjectData *obj;
- debug (8, "Actor::realLocation objectId=%i", objectId);
- if (walkFlags & kWalkUseAngle) {
- if (_vm->_scene->getFlags() & kSceneFlagISO) {
- angle = (location.x + 2) & 15;
- distance = location.y;
-
- location.u() = (angleLUT[angle][0] * distance) >> 8;
- location.v() = -(angleLUT[angle][1] * distance) >> 8;
- } else {
- angle = location.x & 15;
- distance = location.y;
-
- location.x = (angleLUT[angle][0] * distance) >> 6;
- location.y = (angleLUT[angle][1] * distance) >> 6;
- }
- }
-
- if (objectId != ID_NOTHING) {
- if (validActorId(objectId)) {
- actor = getActor(objectId);
- location.addXY(actor->_location);
- } else if (validObjId(objectId)) {
- obj = getObj(objectId);
- location.addXY(obj->_location);
- }
- }
-}
-
-void Actor::actorFaceTowardsPoint(uint16 actorId, const Location &toLocation) {
- ActorData *actor;
- Location delta;
- //debug (8, "Actor::actorFaceTowardsPoint actorId=%i", actorId);
- actor = getActor(actorId);
-
- toLocation.delta(actor->_location, delta);
-
- if (_vm->_scene->getFlags() & kSceneFlagISO) {
- if (delta.u() > 0) {
- actor->_facingDirection = (delta.v() > 0) ? kDirUp : kDirRight;
- } else {
- actor->_facingDirection = (delta.v() > 0) ? kDirLeft : kDirDown;
- }
- } else {
- if (ABS(delta.y) > ABS(delta.x * 2)) {
- actor->_facingDirection = (delta.y > 0) ? kDirDown : kDirUp;
- } else {
- actor->_facingDirection = (delta.x > 0) ? kDirRight : kDirLeft;
- }
- }
-}
-
-void Actor::actorFaceTowardsObject(uint16 actorId, uint16 objectId) {
- ActorData *actor;
- ObjectData *obj;
-
- if (validActorId(objectId)) {
- actor = getActor(objectId);
- actorFaceTowardsPoint(actorId, actor->_location);
- } else if (validObjId(objectId)) {
- obj = getObj(objectId);
- actorFaceTowardsPoint(actorId, obj->_location);
- }
-}
-
-
ObjectData *Actor::getObj(uint16 objId) {
ObjectData *obj;
@@ -830,18 +610,6 @@ ActorData *Actor::getActor(uint16 actorId) {
return actor;
}
-bool Actor::validFollowerLocation(const Location &location) {
- Point point;
- location.toScreenPointXY(point);
-
- if ((point.x < 5) || (point.x >= _vm->getDisplayWidth() - 5) ||
- (point.y < 0) || (point.y > _vm->_scene->getHeight())) {
- return false;
- }
-
- return (_vm->_scene->canWalk(point));
-}
-
void Actor::setProtagState(int state) {
_protagState = state;
@@ -855,149 +623,6 @@ void Actor::setProtagState(int state) {
}
}
-void Actor::updateActorsScene(int actorsEntrance) {
- int i, j;
- int followerDirection;
- ActorData *actor;
- Location tempLocation;
- Location possibleLocation;
- Point delta;
- const SceneEntry *sceneEntry;
-
- if (_vm->_scene->currentSceneNumber() == 0) {
- error("Actor::updateActorsScene _vm->_scene->currentSceneNumber() == 0");
- }
-
- _vm->_sound->stopVoice();
- _activeSpeech.stringsCount = 0;
- _activeSpeech.playing = false;
- _protagonist = NULL;
-
- for (i = 0; i < _actorsCount; i++) {
- actor = _actors[i];
- actor->_inScene = false;
- actor->_spriteList.freeMem();
- if (actor->_disabled) {
- continue;
- }
- if ((actor->_flags & (kProtagonist | kFollower)) || (i == 0)) {
- if (actor->_flags & kProtagonist) {
- actor->_finalTarget = actor->_location;
- _centerActor = _protagonist = actor;
- } else if (_vm->getGameType() == GType_ITE &&
- _vm->_scene->currentSceneResourceId() == RID_ITE_OVERMAP_SCENE) {
- continue;
- }
-
- actor->_sceneNumber = _vm->_scene->currentSceneNumber();
- }
- if (actor->_sceneNumber == _vm->_scene->currentSceneNumber()) {
- actor->_inScene = true;
- actor->_actionCycle = (_vm->_rnd.getRandomNumber(7) & 0x7) * 4; // 1/8th chance
- }
- }
-
- // _protagonist can be null while loading a game from the command line
- if (_protagonist == NULL)
- return;
-
- if ((actorsEntrance >= 0) && (_vm->_scene->_entryList.entryListCount > 0)) {
- if (_vm->_scene->_entryList.entryListCount <= actorsEntrance) {
- actorsEntrance = 0; //OCEAN bug
- }
-
- sceneEntry = _vm->_scene->_entryList.getEntry(actorsEntrance);
- if (_vm->_scene->getFlags() & kSceneFlagISO) {
- _protagonist->_location = sceneEntry->location;
- } else {
- _protagonist->_location.x = sceneEntry->location.x * ACTOR_LMULT;
- _protagonist->_location.y = sceneEntry->location.y * ACTOR_LMULT;
- _protagonist->_location.z = sceneEntry->location.z * ACTOR_LMULT;
- }
- // Workaround for bug #1328045:
- // "When entering any of the houses at the start of the
- // game if you click on anything inside the building you
- // start walking through the door, turn around and leave."
- //
- // After steping of action zone - Rif trying to exit.
- // This piece of code shift Rif's entry position to non action zone area.
- if (_vm->getGameType() == GType_ITE) {
- if ((_vm->_scene->currentSceneNumber() >= 53) && (_vm->_scene->currentSceneNumber() <= 66))
- _protagonist->_location.y += 10;
- }
-
- _protagonist->_facingDirection = _protagonist->_actionDirection = sceneEntry->facing;
- }
-
- _protagonist->_currentAction = kActionWait;
-
- if (_vm->_scene->getFlags() & kSceneFlagISO) {
- //nothing?
- } else {
- _vm->_scene->initDoorsState(); //TODO: move to _scene
- }
-
- followerDirection = _protagonist->_facingDirection + 3;
- calcScreenPosition(_protagonist);
-
- for (i = 0; i < _actorsCount; i++) {
- actor = _actors[i];
- if (actor->_flags & (kFollower)) {
- actor->_facingDirection = actor->_actionDirection = _protagonist->_facingDirection;
- actor->_currentAction = kActionWait;
- actor->_walkStepsCount = actor->_walkStepIndex = 0;
- actor->_location.z = _protagonist->_location.z;
-
-
- if (_vm->_scene->getFlags() & kSceneFlagISO) {
- _vm->_isoMap->placeOnTileMap(_protagonist->_location, actor->_location, 3, followerDirection & 0x07);
- } else {
- followerDirection &= 0x07;
-
- possibleLocation = _protagonist->_location;
-
-
- delta.x = directionLUT[followerDirection][0];
- delta.y = directionLUT[followerDirection][1];
-
-
- for (j = 0; j < 30; j++) {
- tempLocation = possibleLocation;
- tempLocation.x += delta.x;
- tempLocation.y += delta.y;
-
- if (validFollowerLocation(tempLocation)) {
- possibleLocation = tempLocation;
- } else {
- tempLocation = possibleLocation;
- tempLocation.x += delta.x;
- if (validFollowerLocation(tempLocation)) {
- possibleLocation = tempLocation;
- } else {
- tempLocation = possibleLocation;
- tempLocation.y += delta.y;
- if (validFollowerLocation(tempLocation)) {
- possibleLocation = tempLocation;
- } else {
- break;
- }
- }
- }
- }
-
- actor->_location = possibleLocation;
- }
- followerDirection += 2;
- }
-
- }
-
- handleActions(0, true);
- if (_vm->_scene->getFlags() & kSceneFlagISO) {
- _vm->_isoMap->adjustScroll(true);
- }
-}
-
int Actor::getFrameType(ActorFrameTypes frameType) {
if (_vm->getGameType() == GType_ITE) {
@@ -1235,413 +860,6 @@ void Actor::handleSpeech(int msec) {
_activeSpeech.playing = true;
}
-void Actor::handleActions(int msec, bool setup) {
- int i;
- ActorData *actor;
- ActorFrameRange *frameRange;
- int state;
- int speed;
- int32 framesLeft;
- Location delta;
- Location addDelta;
- int hitZoneIndex;
- const HitZone *hitZone;
- Point hitPoint;
- Location pickLocation;
-
- for (i = 0; i < _actorsCount; i++) {
- actor = _actors[i];
- if (!actor->_inScene)
- continue;
-
- if ((_vm->getGameType() == GType_ITE) && (i == ACTOR_DRAGON_INDEX)) {
- moveDragon(actor);
- continue;
- }
-
- switch (actor->_currentAction) {
- case kActionWait:
- if (!setup && (actor->_flags & kFollower)) {
- followProtagonist(actor);
- if (actor->_currentAction != kActionWait)
- break;
- }
-
- if (actor->_targetObject != ID_NOTHING) {
- actorFaceTowardsObject(actor->_id, actor->_targetObject);
- }
-
- if (actor->_flags & kCycle) {
- frameRange = getActorFrameRange(actor->_id, getFrameType(kFrameStand));
- if (frameRange->frameCount > 0) {
- actor->_actionCycle++;
- actor->_actionCycle = (actor->_actionCycle) % frameRange->frameCount;
- } else {
- actor->_actionCycle = 0;
- }
- actor->_frameNumber = frameRange->frameIndex + actor->_actionCycle;
- break;
- }
-
- if ((actor->_actionCycle & 3) == 0) {
- actor->cycleWrap(100);
-
- frameRange = getActorFrameRange(actor->_id, getFrameType(kFrameWait));
- if ((frameRange->frameCount < 1 || actor->_actionCycle > 33))
- frameRange = getActorFrameRange(actor->_id, getFrameType(kFrameStand));
-
- if (frameRange->frameCount) {
- actor->_frameNumber = frameRange->frameIndex + (uint16)_vm->_rnd.getRandomNumber(frameRange->frameCount - 1);
- } else {
- actor->_frameNumber = frameRange->frameIndex;
- }
- }
- actor->_actionCycle++;
- break;
-
- case kActionWalkToPoint:
- case kActionWalkToLink:
- if (_vm->_scene->getFlags() & kSceneFlagISO) {
- actor->_partialTarget.delta(actor->_location, delta);
-
- while ((delta.u() == 0) && (delta.v() == 0)) {
-
- if ((actor == _protagonist) && (_vm->mouseButtonPressed())) {
- _vm->_isoMap->screenPointToTileCoords(_vm->mousePos(), pickLocation);
-
- if (!actorWalkTo(_protagonist->_id, pickLocation)) {
- break;
- }
- } else if (!_vm->_isoMap->nextTileTarget(actor) && !actorEndWalk(actor->_id, true)) {
- break;
- }
-
- actor->_partialTarget.delta(actor->_location, delta);
- actor->_partialTarget.z = 0;
- }
-
- if (actor->_flags & kFastest) {
- speed = 8;
- } else if (actor->_flags & kFaster) {
- speed = 6;
- } else {
- speed = 4;
- }
-
- if (_vm->_scene->currentSceneResourceId() == RID_ITE_OVERMAP_SCENE) {
- speed = 2;
- }
-
- if ((actor->_actionDirection == 2) || (actor->_actionDirection == 6)) {
- speed = speed / 2;
- }
-
- if (ABS(delta.v()) > ABS(delta.u())) {
- addDelta.v() = clamp(-speed, delta.v(), speed);
- if (addDelta.v() == delta.v()) {
- addDelta.u() = delta.u();
- } else {
- addDelta.u() = delta.u() * addDelta.v();
- addDelta.u() += (addDelta.u() > 0) ? (delta.v() / 2) : (-delta.v() / 2);
- addDelta.u() /= delta.v();
- }
- } else {
- addDelta.u() = clamp(-speed, delta.u(), speed);
- if (addDelta.u() == delta.u()) {
- addDelta.v() = delta.v();
- } else {
- addDelta.v() = delta.v() * addDelta.u();
- addDelta.v() += (addDelta.v() > 0) ? (delta.u() / 2) : (-delta.u() / 2);
- addDelta.v() /= delta.u();
- }
- }
-
- actor->_location.add(addDelta);
- } else {
- actor->_partialTarget.delta(actor->_location, delta);
-
- while ((delta.x == 0) && (delta.y == 0)) {
-
- if (actor->_walkStepIndex >= actor->_walkStepsCount) {
- actorEndWalk(actor->_id, true);
- break;
- }
-
- actor->_partialTarget.fromScreenPoint(actor->_walkStepsPoints[actor->_walkStepIndex++]);
- if (_vm->getGameType() == GType_ITE) {
- if (actor->_partialTarget.x > 224 * 2 * ACTOR_LMULT) {
- actor->_partialTarget.x -= 256 * 2 * ACTOR_LMULT;
- }
- } else {
- if (actor->_partialTarget.x > 224 * 4 * ACTOR_LMULT) {
- actor->_partialTarget.x -= 256 * 4 * ACTOR_LMULT;
- }
- }
-
- actor->_partialTarget.delta(actor->_location, delta);
-
- if (ABS(delta.y) > ABS(delta.x)) {
- actor->_actionDirection = delta.y > 0 ? kDirDown : kDirUp;
- } else {
- actor->_actionDirection = delta.x > 0 ? kDirRight : kDirLeft;
- }
- }
-
- if(_vm->getGameType() == GType_ITE)
- speed = (ACTOR_LMULT * 2 * actor->_screenScale + 63) / 256;
- else
- speed = (ACTOR_SPEED * actor->_screenScale + 128) >> 8;
-
- if (speed < 1)
- speed = 1;
-
- if(_vm->getGameType() == GType_IHNM)
- speed = speed / 2;
-
- if ((actor->_actionDirection == kDirUp) || (actor->_actionDirection == kDirDown)) {
- addDelta.y = clamp(-speed, delta.y, speed);
- if (addDelta.y == delta.y) {
- addDelta.x = delta.x;
- } else {
- addDelta.x = delta.x * addDelta.y;
- addDelta.x += (addDelta.x > 0) ? (delta.y / 2) : (-delta.y / 2);
- addDelta.x /= delta.y;
- actor->_facingDirection = actor->_actionDirection;
- }
- } else {
- addDelta.x = clamp(-2 * speed, delta.x, 2 * speed);
- if (addDelta.x == delta.x) {
- addDelta.y = delta.y;
- } else {
- addDelta.y = delta.y * addDelta.x;
- addDelta.y += (addDelta.y > 0) ? (delta.x / 2) : (-delta.x / 2);
- addDelta.y /= delta.x;
- actor->_facingDirection = actor->_actionDirection;
- }
- }
-
- actor->_location.add(addDelta);
- }
-
- if (actor->_actorFlags & kActorBackwards) {
- actor->_facingDirection = (actor->_actionDirection + 4) & 7;
- actor->_actionCycle--;
- } else {
- actor->_actionCycle++;
- }
-
- frameRange = getActorFrameRange(actor->_id, actor->_walkFrameSequence);
-
- if (actor->_actionCycle < 0) {
- actor->_actionCycle = frameRange->frameCount - 1;
- } else if (actor->_actionCycle >= frameRange->frameCount) {
- actor->_actionCycle = 0;
- }
-
- actor->_frameNumber = frameRange->frameIndex + actor->_actionCycle;
- break;
-
- case kActionWalkDir:
- if (_vm->_scene->getFlags() & kSceneFlagISO) {
- actor->_location.u() += tileDirectionLUT[actor->_actionDirection][0];
- actor->_location.v() += tileDirectionLUT[actor->_actionDirection][1];
-
- frameRange = getActorFrameRange(actor->_id, actor->_walkFrameSequence);
-
- actor->_actionCycle++;
- actor->cycleWrap(frameRange->frameCount);
- actor->_frameNumber = frameRange->frameIndex + actor->_actionCycle;
- } else {
- if (_vm->getGameType() == GType_ITE) {
- actor->_location.x += directionLUT[actor->_actionDirection][0] * 2;
- actor->_location.y += directionLUT[actor->_actionDirection][1] * 2;
- } else {
- // FIXME: The original does not multiply by 8 here, but we do
- actor->_location.x += (directionLUT[actor->_actionDirection][0] * 8 * actor->_screenScale + 128) >> 8;
- actor->_location.y += (directionLUT[actor->_actionDirection][1] * 8 * actor->_screenScale + 128) >> 8;
- }
-
- frameRange = getActorFrameRange(actor->_id, actor->_walkFrameSequence);
- actor->_actionCycle++;
- actor->cycleWrap(frameRange->frameCount);
- actor->_frameNumber = frameRange->frameIndex + actor->_actionCycle;
- }
- break;
-
- case kActionSpeak:
- actor->_actionCycle++;
- actor->cycleWrap(64);
-
- frameRange = getActorFrameRange(actor->_id, getFrameType(kFrameGesture));
- if (actor->_actionCycle >= frameRange->frameCount) {
- if (actor->_actionCycle & 1)
- break;
- frameRange = getActorFrameRange(actor->_id, getFrameType(kFrameSpeak));
-
- state = (uint16)_vm->_rnd.getRandomNumber(frameRange->frameCount);
-
- if (state == 0) {
- frameRange = getActorFrameRange(actor->_id, getFrameType(kFrameStand));
- } else {
- state--;
- }
- } else {
- state = actor->_actionCycle;
- }
-
- actor->_frameNumber = frameRange->frameIndex + state;
- break;
-
- case kActionAccept:
- case kActionStoop:
- break;
-
- case kActionCycleFrames:
- case kActionPongFrames:
- if (actor->_cycleTimeCount > 0) {
- actor->_cycleTimeCount--;
- break;
- }
-
- actor->_cycleTimeCount = actor->_cycleDelay;
- actor->_actionCycle++;
-
- frameRange = getActorFrameRange(actor->_id, actor->_cycleFrameSequence);
-
- if (actor->_currentAction == kActionPongFrames) {
- if (actor->_actionCycle >= frameRange->frameCount * 2 - 2) {
- if (actor->_actorFlags & kActorContinuous) {
- actor->_actionCycle = 0;
- } else {
- actor->_currentAction = kActionFreeze;
- break;
- }
- }
-
- state = actor->_actionCycle;
- if (state >= frameRange->frameCount) {
- state = frameRange->frameCount * 2 - 2 - state;
- }
- } else {
- if (actor->_actionCycle >= frameRange->frameCount) {
- if (actor->_actorFlags & kActorContinuous) {
- actor->_actionCycle = 0;
- } else {
- actor->_currentAction = kActionFreeze;
- break;
- }
- }
- state = actor->_actionCycle;
- }
-
- if (frameRange->frameCount && (actor->_actorFlags & kActorRandom)) {
- state = _vm->_rnd.getRandomNumber(frameRange->frameCount - 1);
- }
-
- if (actor->_actorFlags & kActorBackwards) {
- actor->_frameNumber = frameRange->frameIndex + frameRange->frameCount - 1 - state;
- } else {
- actor->_frameNumber = frameRange->frameIndex + state;
- }
- break;
-
- case kActionFall:
- if (actor->_actionCycle > 0) {
- framesLeft = actor->_actionCycle--;
- actor->_finalTarget.delta(actor->_location, delta);
- delta.x /= framesLeft;
- delta.y /= framesLeft;
- actor->_location.addXY(delta);
- actor->_fallVelocity += actor->_fallAcceleration;
- actor->_fallPosition += actor->_fallVelocity;
- actor->_location.z = actor->_fallPosition >> 4;
- } else {
- actor->_location = actor->_finalTarget;
- actor->_currentAction = kActionFreeze;
- _vm->_script->wakeUpActorThread(kWaitTypeWalk, actor);
- }
- break;
-
- case kActionClimb:
- actor->_cycleDelay++;
- if (actor->_cycleDelay & 3) {
- break;
- }
-
- if (actor->_location.z >= actor->_finalTarget.z + ACTOR_CLIMB_SPEED) {
- actor->_location.z -= ACTOR_CLIMB_SPEED;
- actor->_actionCycle--;
- } else if (actor->_location.z <= actor->_finalTarget.z - ACTOR_CLIMB_SPEED) {
- actor->_location.z += ACTOR_CLIMB_SPEED;
- actor->_actionCycle++;
- } else {
- actor->_location.z = actor->_finalTarget.z;
- actor->_currentAction = kActionFreeze;
- _vm->_script->wakeUpActorThread(kWaitTypeWalk, actor);
- }
-
- frameRange = getActorFrameRange(actor->_id, actor->_cycleFrameSequence);
-
- if (actor->_actionCycle < 0) {
- actor->_actionCycle = frameRange->frameCount - 1;
- }
- actor->cycleWrap(frameRange->frameCount);
- actor->_frameNumber = frameRange->frameIndex + actor->_actionCycle;
- break;
- }
-
- if ((actor->_currentAction >= kActionWalkToPoint) && (actor->_currentAction <= kActionWalkDir)) {
- hitZone = NULL;
-
- if (_vm->_scene->getFlags() & kSceneFlagISO) {
- actor->_location.toScreenPointUV(hitPoint);
- } else {
- actor->_location.toScreenPointXY(hitPoint);
- }
- hitZoneIndex = _vm->_scene->_actionMap->hitTest(hitPoint);
- if (hitZoneIndex != -1) {
- hitZone = _vm->_scene->_actionMap->getHitZone(hitZoneIndex);
- }
-
- if (hitZone != actor->_lastZone) {
- if (actor->_lastZone)
- stepZoneAction(actor, actor->_lastZone, true, false);
- actor->_lastZone = hitZone;
- // WORKAROUND for graphics glitch in the rat caves. Don't do this step zone action in the rat caves
- // (room 51) to avoid the glitch
- if (hitZone && !(_vm->getGameType() == GType_ITE && _vm->_scene->currentSceneNumber() == 51))
- stepZoneAction(actor, hitZone, false, false);
- }
- }
- }
- // Update frameCount for sfWaitFrames in IHNM
- _vm->_frameCount++;
-}
-
-void Actor::direct(int msec) {
-
- if (_vm->_scene->_entryList.entryListCount == 0) {
- return;
- }
-
- if (_vm->_interface->_statusTextInput) {
- return;
- }
-
- // FIXME: HACK. This should be turned into cycle event.
- _lastTickMsec += msec;
-
- if (_lastTickMsec > 1000 / _handleActionDiv) {
- _lastTickMsec = 0;
- //process actions
- handleActions(msec, false);
- }
-
-//process speech
- handleSpeech(msec);
-}
-
-
bool Actor::calcScreenPosition(CommonObjectData *commonObjectData) {
int beginSlope, endSlope, middle;
bool result;
@@ -1738,7 +956,10 @@ void Actor::createDrawOrderList() {
if (_vm->_scene->getFlags() & kSceneFlagISO) {
compareFunction = &tileCommonObjectCompare;
} else {
- compareFunction = &commonObjectCompare;
+ if (_vm->getGameType() == GType_ITE)
+ compareFunction = &commonObjectCompare;
+ else
+ compareFunction = &commonObjectCompareIHNM;
}
_drawOrderList.clear();
@@ -1814,10 +1035,6 @@ void Actor::drawActors() {
return;
}
- if (!_showActors) {
- return;
- }
-
CommonObjectOrderList::iterator drawOrderIterator;
CommonObjectDataPointer drawObject;
int frameNumber;
@@ -1891,382 +1108,6 @@ void Actor::drawSpeech(void) {
free(outputString);
}
-bool Actor::followProtagonist(ActorData *actor) {
- Location protagonistLocation;
- Location newLocation;
- Location delta;
- int protagonistBGMaskType;
- Point prefer1;
- Point prefer2;
- Point prefer3;
- int16 prefU;
- int16 prefV;
- int16 newU;
- int16 newV;
-
- assert(_protagonist);
-
- actor->_flags &= ~(kFaster | kFastest);
- protagonistLocation = _protagonist->_location;
- calcScreenPosition(_protagonist);
-
- if (_vm->_scene->getFlags() & kSceneFlagISO) {
- prefU = 60;
- prefV = 60;
-
-
- actor->_location.delta(protagonistLocation, delta);
-
- if (actor->_id == actorIndexToId(2)) {
- prefU = prefV = 48;
- }
-
- if ((delta.u() > prefU) || (delta.u() < -prefU) || (delta.v() > prefV) || (delta.v() < -prefV)) {
-
- if ((delta.u() > prefU * 2) || (delta.u() < -prefU * 2) || (delta.v() > prefV * 2) || (delta.v() < -prefV * 2)) {
- actor->_flags |= kFaster;
-
- if ((delta.u() > prefU * 3) || (delta.u() < -prefU*3) || (delta.v() > prefV * 3) || (delta.v() < -prefV * 3)) {
- actor->_flags |= kFastest;
- }
- }
-
- prefU /= 2;
- prefV /= 2;
-
- newU = clamp(-prefU, delta.u(), prefU) + protagonistLocation.u();
- newV = clamp(-prefV, delta.v(), prefV) + protagonistLocation.v();
-
- newLocation.u() = newU + _vm->_rnd.getRandomNumber(prefU - 1) - prefU / 2;
- newLocation.v() = newV + _vm->_rnd.getRandomNumber(prefV - 1) - prefV / 2;
- newLocation.z = 0;
-
- return actorWalkTo(actor->_id, newLocation);
- }
-
- } else {
- prefer1.x = (100 * _protagonist->_screenScale) >> 8;
- prefer1.y = (50 * _protagonist->_screenScale) >> 8;
-
- if (_protagonist->_currentAction == kActionWalkDir) {
- prefer1.x /= 2;
- }
-
- if (prefer1.x < 8) {
- prefer1.x = 8;
- }
-
- if (prefer1.y < 8) {
- prefer1.y = 8;
- }
-
- prefer2.x = prefer1.x * 2;
- prefer2.y = prefer1.y * 2;
- prefer3.x = prefer1.x + prefer1.x / 2;
- prefer3.y = prefer1.y + prefer1.y / 2;
-
- actor->_location.delta(protagonistLocation, delta);
-
- protagonistBGMaskType = 0;
- if (_vm->_scene->isBGMaskPresent() && _vm->_scene->validBGMaskPoint(_protagonist->_screenPosition)) {
- protagonistBGMaskType = _vm->_scene->getBGMaskType(_protagonist->_screenPosition);
- }
-
- if ((_vm->_rnd.getRandomNumber(7) & 0x7) == 0) // 1/8th chance
- actor->_actorFlags &= ~kActorNoFollow;
-
- if (actor->_actorFlags & kActorNoFollow) {
- return false;
- }
-
- if ((delta.x > prefer2.x) || (delta.x < -prefer2.x) ||
- (delta.y > prefer2.y) || (delta.y < -prefer2.y) ||
- ((_protagonist->_currentAction == kActionWait) &&
- (delta.x * 2 < prefer1.x) && (delta.x * 2 > -prefer1.x) &&
- (delta.y < prefer1.y) && (delta.y > -prefer1.y))) {
-
- if (ABS(delta.x) > ABS(delta.y)) {
-
- delta.x = (delta.x > 0) ? prefer3.x : -prefer3.x;
-
- newLocation.x = delta.x + protagonistLocation.x;
- newLocation.y = clamp(-prefer2.y, delta.y, prefer2.y) + protagonistLocation.y;
- } else {
- delta.y = (delta.y > 0) ? prefer3.y : -prefer3.y;
-
- newLocation.x = clamp(-prefer2.x, delta.x, prefer2.x) + protagonistLocation.x;
- newLocation.y = delta.y + protagonistLocation.y;
- }
- newLocation.z = 0;
-
- if (protagonistBGMaskType != 3) {
- newLocation.x += _vm->_rnd.getRandomNumber(prefer1.x - 1) - prefer1.x / 2;
- newLocation.y += _vm->_rnd.getRandomNumber(prefer1.y - 1) - prefer1.y / 2;
- }
-
- newLocation.x = clamp(-31*4, newLocation.x, (_vm->getDisplayWidth() + 31) * 4); //fixme
-
- return actorWalkTo(actor->_id, newLocation);
- }
- }
- return false;
-}
-
-bool Actor::actorEndWalk(uint16 actorId, bool recurse) {
- bool walkMore = false;
- ActorData *actor;
- const HitZone *hitZone;
- int hitZoneIndex;
- Point testPoint;
-
- actor = getActor(actorId);
- actor->_actorFlags &= ~kActorBackwards;
-
- if (_vm->getGameType() == GType_ITE) {
-
- if (actor->_location.distance(actor->_finalTarget) > 8 && (actor->_flags & kProtagonist) && recurse && !(actor->_actorFlags & kActorNoCollide)) {
- actor->_actorFlags |= kActorNoCollide;
- return actorWalkTo(actorId, actor->_finalTarget);
- }
- }
-
- actor->_currentAction = kActionWait;
- if (actor->_actorFlags & kActorFinalFace) {
- actor->_facingDirection = actor->_actionDirection = (actor->_actorFlags >> 6) & 0x07; //?
- }
-
- actor->_actorFlags &= ~(kActorNoCollide | kActorCollided | kActorFinalFace | kActorFacingMask);
- actor->_flags &= ~(kFaster | kFastest);
-
- if (actor == _protagonist) {
- _vm->_script->wakeUpActorThread(kWaitTypeWalk, actor);
- if (_vm->_script->_pendingVerb == _vm->_script->getVerbType(kVerbWalkTo)) {
- if (_vm->getGameType() == GType_ITE)
- actor->_location.toScreenPointUV(testPoint); // it's wrong calculation, but it is used in ITE
- else
- actor->_location.toScreenPointXY(testPoint);
-
- hitZoneIndex = _vm->_scene->_actionMap->hitTest(testPoint);
- if (hitZoneIndex != -1) {
- hitZone = _vm->_scene->_actionMap->getHitZone(hitZoneIndex);
- stepZoneAction(actor, hitZone, false, true);
- } else {
- _vm->_script->setNoPendingVerb();
- }
- } else if (_vm->_script->_pendingVerb != _vm->_script->getVerbType(kVerbNone)) {
- _vm->_script->doVerb();
- }
- } else {
- if (recurse && (actor->_flags & kFollower))
- walkMore = followProtagonist(actor);
-
- _vm->_script->wakeUpActorThread(kWaitTypeWalk, actor);
- }
- return walkMore;
-}
-
-bool Actor::actorWalkTo(uint16 actorId, const Location &toLocation) {
- ActorData *actor;
- ActorData *anotherActor;
- int i;
-
- Rect testBox;
- Rect testBox2;
- Point anotherActorScreenPosition;
- Point collision;
- Point pointFrom, pointTo, pointBest, pointAdd;
- Point delta, bestDelta;
- Point tempPoint;
- bool extraStartNode;
- bool extraEndNode;
-
- actor = getActor(actorId);
-
- if (actor == _protagonist) {
- _vm->_scene->setDoorState(2, 0xff);
- _vm->_scene->setDoorState(3, 0);
- } else {
- _vm->_scene->setDoorState(2, 0);
- _vm->_scene->setDoorState(3, 0xff);
- }
-
- if (_vm->_scene->getFlags() & kSceneFlagISO) {
-
- if ((_vm->getGameType() == GType_ITE) && (actor->_index == ACTOR_DRAGON_INDEX)) {
- return false;
- }
-
- actor->_finalTarget = toLocation;
- actor->_walkStepsCount = 0;
- _vm->_isoMap->findTilePath(actor, actor->_location, toLocation);
-
-
- if ((actor->_walkStepsCount == 0) && (actor->_flags & kProtagonist)) {
- actor->_actorFlags |= kActorNoCollide;
- _vm->_isoMap->findTilePath(actor, actor->_location, toLocation);
- }
-
- actor->_walkStepIndex = 0;
- if (_vm->_isoMap->nextTileTarget(actor)) {
- actor->_currentAction = kActionWalkToPoint;
- actor->_walkFrameSequence = getFrameType(kFrameWalk);
- } else {
- actorEndWalk(actorId, false);
- return false;
- }
- } else {
-
- actor->_location.toScreenPointXY(pointFrom);
- pointFrom.x &= ~1;
-
- extraStartNode = _vm->_scene->offscreenPath(pointFrom);
-
- toLocation.toScreenPointXY(pointTo);
- pointTo.x &= ~1;
-
- extraEndNode = _vm->_scene->offscreenPath(pointTo);
-
- if (_vm->_scene->isBGMaskPresent()) {
-
- if ((((actor->_currentAction >= kActionWalkToPoint) &&
- (actor->_currentAction <= kActionWalkDir)) || (actor == _protagonist)) &&
- !_vm->_scene->canWalk(pointFrom)) {
-
- int max = _vm->getGameType() == GType_ITE ? 8 : 4;
-
- for (i = 1; i < max; i++) {
- pointAdd = pointFrom;
- pointAdd.y += i;
- if (_vm->_scene->canWalk(pointAdd)) {
- pointFrom = pointAdd;
- break;
- }
- pointAdd = pointFrom;
- pointAdd.y -= i;
- if (_vm->_scene->canWalk(pointAdd)) {
- pointFrom = pointAdd;
- break;
- }
- if (_vm->getGameType() == GType_ITE) {
- pointAdd = pointFrom;
- pointAdd.x += i;
- if (_vm->_scene->canWalk(pointAdd)) {
- pointFrom = pointAdd;
- break;
- }
- pointAdd = pointFrom;
- pointAdd.x -= i;
- if (_vm->_scene->canWalk(pointAdd)) {
- pointFrom = pointAdd;
- break;
- }
- }
- }
- }
-
- _barrierCount = 0;
- if (!(actor->_actorFlags & kActorNoCollide)) {
- collision.x = ACTOR_COLLISION_WIDTH * actor->_screenScale / (256 * 2);
- collision.y = ACTOR_COLLISION_HEIGHT * actor->_screenScale / (256 * 2);
-
-
- for (i = 0; (i < _actorsCount) && (_barrierCount < ACTOR_BARRIERS_MAX); i++) {
- anotherActor = _actors[i];
- if (!anotherActor->_inScene)
- continue;
- if (anotherActor == actor)
- continue;
-
- anotherActorScreenPosition = anotherActor->_screenPosition;
- testBox.left = (anotherActorScreenPosition.x - collision.x) & ~1;
- testBox.right = (anotherActorScreenPosition.x + collision.x) & ~1 + 1;
- testBox.top = anotherActorScreenPosition.y - collision.y;
- testBox.bottom = anotherActorScreenPosition.y + collision.y + 1;
- testBox2 = testBox;
- testBox2.right += 2;
- testBox2.left -= 2;
- testBox2.top -= 1;
- testBox2.bottom += 1;
-
- if (testBox2.contains(pointFrom)) {
- if (pointFrom.x > anotherActorScreenPosition.x + 4) {
- testBox.right = pointFrom.x - 1;
- } else if (pointFrom.x < anotherActorScreenPosition.x - 4) {
- testBox.left = pointFrom.x + 2;
- } else if (pointFrom.y > anotherActorScreenPosition.y) {
- testBox.bottom = pointFrom.y;
- } else {
- testBox.top = pointFrom.y + 1 ;
- }
- }
-
- if ((testBox.width() > 0) && (testBox.height() > 0)) {
- _barrierList[_barrierCount++] = testBox;
- }
- }
- }
-
-
- pointBest = pointTo;
- actor->_walkStepsCount = 0;
- findActorPath(actor, pointFrom, pointTo);
-
- if (actor->_walkStepsCount == 0) {
- error("actor->_walkStepsCount == 0");
- }
-
- if (extraStartNode) {
- actor->_walkStepIndex = 0;
- } else {
- actor->_walkStepIndex = 1;
- }
-
- if (extraEndNode) {
- toLocation.toScreenPointXY(tempPoint);
- actor->_walkStepsCount--;
- actor->addWalkStepPoint(tempPoint);
- }
-
-
- pointBest = actor->_walkStepsPoints[actor->_walkStepsCount - 1];
-
- pointBest.x &= ~1;
- delta.x = ABS(pointFrom.x - pointTo.x);
- delta.y = ABS(pointFrom.y - pointTo.y);
-
- bestDelta.x = ABS(pointBest.x - pointTo.x);
- bestDelta.y = ABS(pointBest.y - pointTo.y);
-
- if ((delta.x + delta.y <= bestDelta.x + bestDelta.y) && (actor->_flags & kFollower)) {
- actor->_actorFlags |= kActorNoFollow;
- }
-
- if (pointBest == pointFrom) {
- actor->_walkStepsCount = 0;
- }
- } else {
- actor->_walkStepsCount = 0;
- actor->addWalkStepPoint(pointTo);
- actor->_walkStepIndex = 0;
- }
-
- actor->_partialTarget = actor->_location;
- actor->_finalTarget = toLocation;
- if (actor->_walkStepsCount == 0) {
- actorEndWalk(actorId, false);
- return false;
- } else {
- if (actor->_flags & kProtagonist) {
- _actors[1]->_actorFlags &= ~kActorNoFollow; // TODO: mark all actors with kFollower flag, not only 1 and 2
- _actors[2]->_actorFlags &= ~kActorNoFollow;
- }
- actor->_currentAction = (actor->_walkStepsCount >= ACTOR_MAX_STEPS_COUNT) ? kActionWalkToLink : kActionWalkToPoint;
- actor->_walkFrameSequence = getFrameType(kFrameWalk);
- }
- }
- return true;
-}
-
void Actor::actorSpeech(uint16 actorId, const char **strings, int stringsCount, int sampleResourceId, int speechFlags) {
ActorData *actor;
int i;
@@ -2303,11 +1144,11 @@ void Actor::actorSpeech(uint16 actorId, const char **strings, int stringsCount,
_activeSpeech.speechBox.right = _vm->getDisplayWidth() - 10;
}
- // WORKAROUND for the compact disk in Ellen's chapter
+ // HACK for the compact disk in Ellen's chapter
// Once Ellen starts saying that "Something is different", bring the compact disk in the
// scene. After speaking with AM, the compact disk is visible. She always says this line
// when entering room 59, after speaking with AM, if the compact disk is not picked up yet
- // Check Script::sfDropObject for the other part of this workaround
+ // Check Script::sfDropObject for the other part of this hack
if (_vm->getGameType() == GType_IHNM && _vm->_scene->currentChapterNumber() == 3 &&
_vm->_scene->currentSceneNumber() == 59 && _activeSpeech.sampleResourceId == 286) {
for (i = 0; i < _objsCount; i++) {
@@ -2383,759 +1224,6 @@ void Actor::abortSpeech() {
_activeSpeech.playingTime = 0;
}
-void Actor::moveDragon(ActorData *actor) {
- int16 dir0, dir1, dir2, dir3;
- int16 moveType;
- Event event;
- const DragonMove *dragonMove;
-
- if ((actor->_actionCycle < 0) ||
- ((actor->_actionCycle == 0) && (actor->_dragonMoveType >= ACTOR_DRAGON_TURN_MOVES))) {
-
- moveType = kDragonMoveInvalid;
- if (actor->_location.distance(_protagonist->_location) < 24) {
- if (_dragonHunt && (_protagonist->_currentAction != kActionFall)) {
- event.type = kEvTOneshot;
- event.code = kScriptEvent;
- event.op = kEventExecNonBlocking;
- event.time = 0;
- event.param = _vm->_scene->getScriptModuleNumber(); // module number
- event.param2 = ACTOR_EXP_KNOCK_RIF; // script entry point number
- event.param3 = -1; // Action
- event.param4 = -1; // Object
- event.param5 = -1; // With Object
- event.param6 = -1; // Actor
-
- _vm->_events->queue(&event);
- _dragonHunt = false;
- }
- } else {
- _dragonHunt = true;
- }
-
- if (actor->_walkStepIndex + 2 > actor->_walkStepsCount) {
-
- _vm->_isoMap->findDragonTilePath(actor, actor->_location, _protagonist->_location, actor->_actionDirection);
-
- if (actor->_walkStepsCount == 0) {
- _vm->_isoMap->findDragonTilePath(actor, actor->_location, _protagonist->_location, 0);
- }
-
- if (actor->_walkStepsCount < 2) {
- return;
- }
-
- actor->_partialTarget = actor->_location;
- actor->_finalTarget = _protagonist->_location;
- actor->_walkStepIndex = 0;
- }
-
- dir0 = actor->_actionDirection;
- dir1 = actor->_tileDirections[actor->_walkStepIndex++];
- dir2 = actor->_tileDirections[actor->_walkStepIndex];
- dir3 = actor->_tileDirections[actor->_walkStepIndex + 1];
-
- if (dir0 != dir1){
- actor->_actionDirection = dir0 = dir1;
- }
-
- actor->_location = actor->_partialTarget;
-
- if ((dir1 != dir2) && (dir1 == dir3)) {
- switch (dir1) {
- case kDirUpLeft:
- actor->_partialTarget.v() += 16;
- moveType = kDragonMoveUpLeft;
- break;
- case kDirDownLeft:
- actor->_partialTarget.u() -= 16;
- moveType = kDragonMoveDownLeft;
- break;
- case kDirDownRight:
- actor->_partialTarget.v() -= 16;
- moveType = kDragonMoveDownRight;
- break;
- case kDirUpRight:
- actor->_partialTarget.u() += 16;
- moveType = kDragonMoveUpRight;
- break;
- }
-
- switch (dir2) {
- case kDirUpLeft:
- actor->_partialTarget.v() += 16;
- break;
- case kDirDownLeft:
- actor->_partialTarget.u() -= 16;
- break;
- case kDirDownRight:
- actor->_partialTarget.v() -= 16;
- break;
- case kDirUpRight:
- actor->_partialTarget.u() += 16;
- break;
- }
-
- actor->_walkStepIndex++;
- } else {
- switch (dir1) {
- case kDirUpLeft:
- actor->_partialTarget.v() += 16;
- switch (dir2) {
- case kDirDownLeft:
- moveType = kDragonMoveUpLeft_Left;
- actor->_partialTarget.u() -= 16;
- break;
- case kDirUpLeft:
- moveType = kDragonMoveUpLeft;
- break;
- case kDirUpRight:
- actor->_partialTarget.u() += 16;
- moveType = kDragonMoveUpLeft_Right;
- break;
- default:
- actor->_actionDirection = dir1;
- actor->_walkStepsCount = 0;
- break;
- }
- break;
- case kDirDownLeft:
- actor->_partialTarget.u() -= 16;
- switch (dir2) {
- case kDirDownRight:
- moveType = kDragonMoveDownLeft_Left;
- actor->_partialTarget.v() -= 16;
- break;
- case kDirDownLeft:
- moveType = kDragonMoveDownLeft;
- break;
- case kDirUpLeft:
- moveType = kDragonMoveDownLeft_Right;
- actor->_partialTarget.v() += 16;
- break;
- default:
- actor->_actionDirection = dir1;
- actor->_walkStepsCount = 0;
- break;
- }
- break;
- case kDirDownRight:
- actor->_partialTarget.v() -= 16;
- switch (dir2) {
- case kDirUpRight:
- moveType = kDragonMoveDownRight_Left;
- actor->_partialTarget.u() += 16;
- break;
- case kDirDownRight:
- moveType = kDragonMoveDownRight;
- break;
- case kDirDownLeft:
- moveType = kDragonMoveDownRight_Right;
- actor->_partialTarget.u() -= 16;
- break;
- default:
- actor->_actionDirection = dir1;
- actor->_walkStepsCount = 0;
- break;
- }
- break;
- case kDirUpRight:
- actor->_partialTarget.u() += 16;
- switch (dir2) {
- case kDirUpLeft:
- moveType = kDragonMoveUpRight_Left;
- actor->_partialTarget.v() += 16;
- break;
- case kDirUpRight:
- moveType = kDragonMoveUpRight;
- break;
- case kDirDownRight:
- moveType = kDragonMoveUpRight_Right;
- actor->_partialTarget.v() -= 16;
- break;
- default:
- actor->_actionDirection = dir1;
- actor->_walkStepsCount = 0;
- break;
- }
- break;
-
- default:
- actor->_actionDirection = dir1;
- actor->_walkStepsCount = 0;
- break;
- }
- }
-
- actor->_dragonMoveType = moveType;
-
- if (moveType >= ACTOR_DRAGON_TURN_MOVES) {
- actor->_dragonStepCycle = 0;
- actor->_actionCycle = 4;
- actor->_walkStepIndex++;
- } else {
- actor->_actionCycle = 4;
- }
- }
-
- actor->_actionCycle--;
-
- if ((actor->_walkStepsCount < 1) || (actor->_actionCycle < 0)) {
- return;
- }
-
- if (actor->_dragonMoveType < ACTOR_DRAGON_TURN_MOVES) {
-
- actor->_dragonStepCycle++;
- if (actor->_dragonStepCycle >= 7) {
- actor->_dragonStepCycle = 0;
- }
-
- actor->_dragonBaseFrame = actor->_dragonMoveType * 7;
-
- if (actor->_location.u() > actor->_partialTarget.u() + 3) {
- actor->_location.u() -= 4;
- } else if (actor->_location.u() < actor->_partialTarget.u() - 3) {
- actor->_location.u() += 4;
- } else {
- actor->_location.u() = actor->_partialTarget.u();
- }
-
- if (actor->_location.v() > actor->_partialTarget.v() + 3) {
- actor->_location.v() -= 4;
- } else if (actor->_location.v() < actor->_partialTarget.v() - 3) {
- actor->_location.v() += 4;
- } else {
- actor->_location.v() = actor->_partialTarget.v();
- }
- } else {
- dragonMove = &dragonMoveTable[actor->_dragonMoveType];
- actor->_dragonBaseFrame = dragonMove->baseFrame;
-
-
- actor->_location.u() = actor->_partialTarget.u() - dragonMove->offset[actor->_actionCycle][0];
- actor->_location.v() = actor->_partialTarget.v() - dragonMove->offset[actor->_actionCycle][1];
-
- actor->_dragonStepCycle++;
- if (actor->_dragonStepCycle >= 3) {
- actor->_dragonStepCycle = 3;
- }
- }
-
- actor->_frameNumber = actor->_dragonBaseFrame + actor->_dragonStepCycle;
-}
-
-void Actor::findActorPath(ActorData *actor, const Point &fromPoint, const Point &toPoint) {
- Point iteratorPoint;
- Point bestPoint;
- int maskType;
- int i;
- Rect intersect;
-
-#ifdef ACTOR_DEBUG
- _debugPointsCount = 0;
-#endif
-
- actor->_walkStepsCount = 0;
- if (fromPoint == toPoint) {
- actor->addWalkStepPoint(toPoint);
- return;
- }
-
- for (iteratorPoint.y = 0; iteratorPoint.y < _yCellCount; iteratorPoint.y++) {
- for (iteratorPoint.x = 0; iteratorPoint.x < _xCellCount; iteratorPoint.x++) {
- if (_vm->_scene->validBGMaskPoint(iteratorPoint)) {
- maskType = _vm->_scene->getBGMaskType(iteratorPoint);
- setPathCell(iteratorPoint, _vm->_scene->getDoorState(maskType) ? kPathCellBarrier : kPathCellEmpty);
- } else {
- setPathCell(iteratorPoint, kPathCellBarrier);
- }
- }
- }
-
- for (i = 0; i < _barrierCount; i++) {
- intersect.left = MAX(_pathRect.left, _barrierList[i].left);
- intersect.top = MAX(_pathRect.top, _barrierList[i].top);
- intersect.right = MIN(_pathRect.right, _barrierList[i].right);
- intersect.bottom = MIN(_pathRect.bottom, _barrierList[i].bottom);
-
- for (iteratorPoint.y = intersect.top; iteratorPoint.y < intersect.bottom; iteratorPoint.y++) {
- for (iteratorPoint.x = intersect.left; iteratorPoint.x < intersect.right; iteratorPoint.x++) {
- setPathCell(iteratorPoint, kPathCellBarrier);
- }
- }
- }
-
-#ifdef ACTOR_DEBUG
- for (iteratorPoint.y = 0; iteratorPoint.y < _yCellCount; iteratorPoint.y++) {
- for (iteratorPoint.x = 0; iteratorPoint.x < _xCellCount; iteratorPoint.x++) {
- if (getPathCell(iteratorPoint) == kPathCellBarrier) {
- addDebugPoint(iteratorPoint, 24);
- }
- }
- }
-#endif
-
- if (scanPathLine(fromPoint, toPoint)) {
- actor->addWalkStepPoint(fromPoint);
- actor->addWalkStepPoint(toPoint);
- return;
- }
-
- i = fillPathArray(fromPoint, toPoint, bestPoint);
-
- if (fromPoint == bestPoint) {
- actor->addWalkStepPoint(bestPoint);
- return;
- }
-
- if (i == 0) {
- error("fillPathArray returns zero");
- }
-
- setActorPath(actor, fromPoint, bestPoint);
-}
-
-bool Actor::scanPathLine(const Point &point1, const Point &point2) {
- Point point;
- Point delta;
- Point s;
- Point fDelta;
- int16 errterm;
-
- calcDeltaS(point1, point2, delta, s);
- point = point1;
-
- fDelta.x = delta.x * 2;
- fDelta.y = delta.y * 2;
-
- if (delta.y > delta.x) {
-
- errterm = fDelta.x - delta.y;
-
- while (delta.y > 0) {
- while (errterm >= 0) {
- point.x += s.x;
- errterm -= fDelta.y;
- }
-
- point.y += s.y;
- errterm += fDelta.x;
-
- if (!validPathCellPoint(point)) {
- return false;
- }
- if (getPathCell(point) == kPathCellBarrier) {
- return false;
- }
- delta.y--;
- }
- } else {
-
- errterm = fDelta.y - delta.x;
-
- while (delta.x > 0) {
- while (errterm >= 0) {
- point.y += s.y;
- errterm -= fDelta.x;
- }
-
- point.x += s.x;
- errterm += fDelta.y;
-
- if (!validPathCellPoint(point)) {
- return false;
- }
- if (getPathCell(point) == kPathCellBarrier) {
- return false;
- }
- delta.x--;
- }
- }
- return true;
-}
-
-int Actor::fillPathArray(const Point &fromPoint, const Point &toPoint, Point &bestPoint) {
- int bestRating;
- int currentRating;
- int i;
- Point bestPath;
- int pointCounter;
- int startDirection;
- PathDirectionData *pathDirection;
- PathDirectionData *newPathDirection;
- const PathDirectionData *samplePathDirection;
- Point nextPoint;
- int directionCount;
- int16 compressX = (_vm->getGameType() == GType_ITE) ? 2 : 1;
-
- _pathDirectionListCount = 0;
- pointCounter = 0;
- bestRating = quickDistance(fromPoint, toPoint, compressX);
- bestPath = fromPoint;
-
- for (startDirection = 0; startDirection < 4; startDirection++) {
- newPathDirection = addPathDirectionListData();
- newPathDirection->coord = fromPoint;
- newPathDirection->direction = startDirection;
- }
-
- if (validPathCellPoint(fromPoint)) {
- setPathCell(fromPoint, kDirUp);
-
-#ifdef ACTOR_DEBUG
- addDebugPoint(fromPoint, 24+36);
-#endif
- }
-
- i = 0;
-
- do {
- pathDirection = &_pathDirectionList[i];
- for (directionCount = 0; directionCount < 3; directionCount++) {
- samplePathDirection = &pathDirectionLUT[pathDirection->direction][directionCount];
- nextPoint = pathDirection->coord;
- nextPoint.x += samplePathDirection->coord.x;
- nextPoint.y += samplePathDirection->coord.y;
-
- if (!validPathCellPoint(nextPoint)) {
- continue;
- }
-
- if (getPathCell(nextPoint) != kPathCellEmpty) {
- continue;
- }
-
- setPathCell(nextPoint, samplePathDirection->direction);
-
-#ifdef ACTOR_DEBUG
- addDebugPoint(nextPoint, samplePathDirection->direction + 96);
-#endif
- newPathDirection = addPathDirectionListData();
- newPathDirection->coord = nextPoint;
- newPathDirection->direction = samplePathDirection->direction;
- ++pointCounter;
- if (nextPoint == toPoint) {
- bestPoint = toPoint;
- return pointCounter;
- }
- currentRating = quickDistance(nextPoint, toPoint, compressX);
- if (currentRating < bestRating) {
- bestRating = currentRating;
- bestPath = nextPoint;
- }
- pathDirection = &_pathDirectionList[i];
- }
- ++i;
- } while (i < _pathDirectionListCount);
-
- bestPoint = bestPath;
- return pointCounter;
-}
-
-void Actor::setActorPath(ActorData *actor, const Point &fromPoint, const Point &toPoint) {
- Point nextPoint;
- int8 direction;
- int i;
-
- _pathListIndex = -1;
- addPathListPoint(toPoint);
- nextPoint = toPoint;
-
- while (!(nextPoint == fromPoint)) {
- direction = getPathCell(nextPoint);
- if ((direction < 0) || (direction >= 8)) {
- error("Actor::setActorPath error direction 0x%X", direction);
- }
- nextPoint.x -= pathDirectionLUT2[direction][0];
- nextPoint.y -= pathDirectionLUT2[direction][1];
- addPathListPoint(nextPoint);
-
-#ifdef ACTOR_DEBUG
- addDebugPoint(nextPoint, 0x8a);
-#endif
- }
-
- pathToNode();
- removeNodes();
- nodeToPath();
- removePathPoints();
-
- for (i = 0; i <= _pathNodeListIndex; i++) {
- actor->addWalkStepPoint(_pathNodeList[i].point);
- }
-}
-
-void Actor::pathToNode() {
- Point point1, point2, delta;
- int direction;
- int i;
- Point *point;
-
- point= &_pathList[_pathListIndex];
- direction = 0;
-
- _pathNodeListIndex = -1;
- addPathNodeListPoint(*point);
-
- for (i = _pathListIndex; i > 0; i--) {
- point1 = *point;
- --point;
- point2 = *point;
- if (direction == 0) {
- delta.x = int16Compare(point2.x, point1.x);
- delta.y = int16Compare(point2.y, point1.y);
- direction++;
- }
- if ((point1.x + delta.x != point2.x) || (point1.y + delta.y != point2.y)) {
- addPathNodeListPoint(point1);
- direction--;
- i++;
- point++;
- }
- }
- addPathNodeListPoint(*_pathList);
-}
-
-int pathLine(Point *pointList, const Point &point1, const Point &point2) {
- Point point;
- Point delta;
- Point tempPoint;
- Point s;
- int16 errterm;
- int16 res;
-
- calcDeltaS(point1, point2, delta, s);
-
- point = point1;
-
- tempPoint.x = delta.x * 2;
- tempPoint.y = delta.y * 2;
-
- if (delta.y > delta.x) {
-
- errterm = tempPoint.x - delta.y;
- res = delta.y;
-
- while (delta.y > 0) {
- while (errterm >= 0) {
- point.x += s.x;
- errterm -= tempPoint.y;
- }
-
- point.y += s.y;
- errterm += tempPoint.x;
-
- *pointList = point;
- pointList++;
- delta.y--;
- }
- } else {
-
- errterm = tempPoint.y - delta.x;
- res = delta.x;
-
- while (delta.x > 0) {
- while (errterm >= 0) {
- point.y += s.y;
- errterm -= tempPoint.x;
- }
-
- point.x += s.x;
- errterm += tempPoint.y;
-
- *pointList = point;
- pointList++;
- delta.x--;
- }
- }
- return res;
-}
-
-void Actor::nodeToPath() {
- int i;
- Point point1, point2;
- PathNode *node;
- Point *point;
-
- for (i = 0, point = _pathList; i < _pathListAlloced; i++, point++) {
- point->x = point->y = PATH_NODE_EMPTY;
- }
-
- _pathListIndex = 1;
- _pathList[0] = _pathNodeList[0].point;
- _pathNodeList[0].link = 0;
- for (i = 0, node = _pathNodeList; i < _pathNodeListIndex; i++) {
- point1 = node->point;
- node++;
- point2 = node->point;
- _pathListIndex += pathLine(&_pathList[_pathListIndex], point1, point2);
- node->link = _pathListIndex - 1;
- }
- _pathListIndex--;
- _pathNodeList[_pathNodeListIndex].link = _pathListIndex;
-
-}
-
-void Actor::removeNodes() {
- int i, j, k;
- PathNode *iNode, *jNode, *kNode, *fNode;
- fNode = &_pathNodeList[_pathNodeListIndex];
-
- if (scanPathLine(_pathNodeList[0].point, fNode->point)) {
- _pathNodeList[1] = *fNode;
- _pathNodeListIndex = 1;
- }
-
- if (_pathNodeListIndex < 4) {
- return;
- }
-
- for (i = _pathNodeListIndex - 1, iNode = fNode-1; i > 1 ; i--, iNode--) {
- if (iNode->point.x == PATH_NODE_EMPTY) {
- continue;
- }
-
- if (scanPathLine(_pathNodeList[0].point, iNode->point)) {
- for (j = 1, jNode = _pathNodeList + 1; j < i; j++, jNode++) {
- jNode->point.x = PATH_NODE_EMPTY;
- }
- }
- }
-
- for (i = 1, iNode = _pathNodeList + 1; i < _pathNodeListIndex - 1; i++, iNode++) {
- if (iNode->point.x == PATH_NODE_EMPTY) {
- continue;
- }
-
- if (scanPathLine(fNode->point, iNode->point)) {
- for (j = i + 1, jNode = iNode + 1; j < _pathNodeListIndex; j++, jNode++) {
- jNode->point.x = PATH_NODE_EMPTY;
- }
- }
- }
- condenseNodeList();
-
- for (i = 1, iNode = _pathNodeList + 1; i < _pathNodeListIndex - 1; i++, iNode++) {
- if (iNode->point.x == PATH_NODE_EMPTY) {
- continue;
- }
- for (j = i + 2, jNode = iNode + 2; j < _pathNodeListIndex; j++, jNode++) {
- if (jNode->point.x == PATH_NODE_EMPTY) {
- continue;
- }
-
- if (scanPathLine(iNode->point, jNode->point)) {
- for (k = i + 1,kNode = iNode + 1; k < j; k++, kNode++) {
- kNode->point.x = PATH_NODE_EMPTY;
- }
- }
- }
- }
- condenseNodeList();
-}
-
-void Actor::condenseNodeList() {
- int i, j, count;
- PathNode *iNode, *jNode;
-
- count = _pathNodeListIndex;
-
- for (i = 1, iNode = _pathNodeList + 1; i < _pathNodeListIndex; i++, iNode++) {
- if (iNode->point.x == PATH_NODE_EMPTY) {
- j = i + 1;
- jNode = iNode + 1;
- while (jNode->point.x == PATH_NODE_EMPTY) {
- j++;
- jNode++;
- }
- *iNode = *jNode;
- count = i;
- jNode->point.x = PATH_NODE_EMPTY;
- if (j == _pathNodeListIndex) {
- break;
- }
- }
- }
- _pathNodeListIndex = count;
-}
-
-void Actor::removePathPoints() {
- int i, j, k, l;
- PathNode *node;
- int start;
- int end;
- Point point1, point2;
-
- if (_pathNodeListIndex < 2)
- return;
-
- _newPathNodeListIndex = -1;
- addNewPathNodeListPoint(_pathNodeList[0]);
-
- for (i = 1, node = _pathNodeList + 1; i < _pathNodeListIndex; i++, node++) {
- addNewPathNodeListPoint(*node);
-
- for (j = 5; j > 0; j--) {
- start = node->link - j;
- end = node->link + j;
-
- if (start < 0 || end > _pathListIndex) {
- continue;
- }
-
- point1 = _pathList[start];
- point2 = _pathList[end];
- if ((point1.x == PATH_NODE_EMPTY) || (point2.x == PATH_NODE_EMPTY)) {
- continue;
- }
-
- if (scanPathLine(point1, point2)) {
- for (l = 1; l <= _newPathNodeListIndex; l++) {
- if (start <= _newPathNodeList[l].link) {
- _newPathNodeListIndex = l;
- _newPathNodeList[_newPathNodeListIndex].point = point1;
- _newPathNodeList[_newPathNodeListIndex].link = start;
- incrementNewPathNodeListIndex();
- break;
- }
- }
- _newPathNodeList[_newPathNodeListIndex].point = point2;
- _newPathNodeList[_newPathNodeListIndex].link = end;
-
- for (k = start + 1; k < end; k++) {
- _pathList[k].x = PATH_NODE_EMPTY;
- }
- break;
- }
- }
- }
-
- addNewPathNodeListPoint(_pathNodeList[_pathNodeListIndex]);
-
- for (i = 0, j = 0; i <= _newPathNodeListIndex; i++) {
- if (_newPathNodeListIndex == i || (_newPathNodeList[i].point != _newPathNodeList[i+1].point)) {
- _pathNodeList[j++] = _newPathNodeList[i];
- }
- }
- _pathNodeListIndex = j - 1;
-}
-
-void Actor::drawPathTest() {
-#ifdef ACTOR_DEBUG
- int i;
- Surface *surface;
- surface = _vm->_gfx->getBackBuffer();
- if (_debugPoints == NULL) {
- return;
- }
-
- for (i = 0; i < _debugPointsCount; i++) {
- *((byte *)surface->pixels + (_debugPoints[i].point.y * surface->pitch) + _debugPoints[i].point.x) = _debugPoints[i].color;
- }
-#endif
-}
-
void Actor::saveState(Common::OutSaveFile *out) {
uint16 i;
@@ -3156,7 +1244,7 @@ void Actor::loadState(Common::InSaveFile *in) {
int32 i;
int16 protagState = in->readSint16LE();
- if (protagState != 0)
+ if (protagState != 0 || _protagonist->_shareFrames)
setProtagState(protagState);
for (i = 0; i < _actorsCount; i++) {
@@ -3178,24 +1266,4 @@ void Actor::loadState(Common::InSaveFile *in) {
}
}
-// Console wrappers - must be safe to run
-
-void Actor::cmdActorWalkTo(int argc, const char **argv) {
- uint16 actorId = (uint16) atoi(argv[1]);
- Location location;
- Point movePoint;
-
- movePoint.x = atoi(argv[2]);
- movePoint.y = atoi(argv[3]);
-
- location.fromScreenPoint(movePoint);
-
- if (!validActorId(actorId)) {
- _vm->_console->DebugPrintf("Actor::cmActorWalkTo Invalid actorId 0x%X.\n", actorId);
- return;
- }
-
- actorWalkTo(actorId, location);
-}
-
} // End of namespace Saga
diff --git a/engines/saga/actor.h b/engines/saga/actor.h
index ef62661c6c..7022ef1289 100644
--- a/engines/saga/actor.h
+++ b/engines/saga/actor.h
@@ -94,6 +94,24 @@ enum ActorActions {
kActionClimb = 12
};
+enum ActorFrameIds {
+//ITE
+ kFrameITEStand = 0,
+ kFrameITEWalk = 1,
+ kFrameITESpeak = 2,
+ kFrameITEGive = 3,
+ kFrameITEGesture = 4,
+ kFrameITEWait = 5,
+ kFrameITEPickUp = 6,
+ kFrameITELook = 7,
+//IHNM
+ kFrameIHNMStand = 0,
+ kFrameIHNMSpeak = 1,
+ kFrameIHNMWait = 2,
+ kFrameIHNMGesture = 3,
+ kFrameIHNMWalk = 4
+};
+
enum SpeechFlags {
kSpeakNoAnimate = 1,
kSpeakAsync = 2,
@@ -112,6 +130,18 @@ enum ActorFrameTypes {
kFrameLook
};
+// Lookup table to convert 8 cardinal directions to 4
+static const int actorDirectectionsLUT[8] = {
+ ACTOR_DIRECTION_BACK, // kDirUp
+ ACTOR_DIRECTION_RIGHT, // kDirUpRight
+ ACTOR_DIRECTION_RIGHT, // kDirRight
+ ACTOR_DIRECTION_RIGHT, // kDirDownRight
+ ACTOR_DIRECTION_FORWARD,// kDirDown
+ ACTOR_DIRECTION_LEFT, // kDirDownLeft
+ ACTOR_DIRECTION_LEFT, // kDirLeft
+ ACTOR_DIRECTION_LEFT, // kDirUpLeft
+};
+
enum ActorFlagsEx {
kActorNoCollide = (1 << 0),
kActorNoFollow = (1 << 1),
@@ -612,8 +642,6 @@ public:
void freeObjList();
void loadObjList(int objectCount, int objectsResourceID);
- void showActors(bool flag) { _showActors = flag; }
-
protected:
friend class Script;
bool loadActorResources(ActorData *actor);
@@ -709,7 +737,6 @@ private:
int _xCellCount;
int _yCellCount;
Rect _pathRect;
- bool _showActors;
PathDirectionData *_pathDirectionList;
int _pathDirectionListCount;
diff --git a/engines/saga/actor_walk.cpp b/engines/saga/actor_walk.cpp
new file mode 100644
index 0000000000..47bf804edb
--- /dev/null
+++ b/engines/saga/actor_walk.cpp
@@ -0,0 +1,1942 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#include "saga/saga.h"
+
+#include "saga/actor.h"
+#include "saga/console.h"
+#include "saga/events.h"
+#include "saga/isomap.h"
+#include "saga/objectmap.h"
+#include "saga/sagaresnames.h"
+#include "saga/script.h"
+#include "saga/sound.h"
+#include "saga/scene.h"
+
+namespace Saga {
+
+static const PathDirectionData pathDirectionLUT[8][3] = {
+ { { 0, Point( 0, -1) }, { 7, Point(-1, -1) }, { 4, Point( 1, -1) } },
+ { { 1, Point( 1, 0) }, { 4, Point( 1, -1) }, { 5, Point( 1, 1) } },
+ { { 2, Point( 0, 1) }, { 5, Point( 1, 1) }, { 6, Point(-1, 1) } },
+ { { 3, Point(-1, 0) }, { 6, Point(-1, 1) }, { 7, Point(-1, -1) } },
+ { { 0, Point( 0, -1) }, { 1, Point( 1, 0) }, { 4, Point( 1, -1) } },
+ { { 1, Point( 1, 0) }, { 2, Point( 0, 1) }, { 5, Point( 1, 1) } },
+ { { 2, Point( 0, 1) }, { 3, Point(-1, 0) }, { 6, Point(-1, 1) } },
+ { { 3, Point(-1, 0) }, { 0, Point( 0, -1) }, { 7, Point(-1, -1) } }
+};
+
+static const int pathDirectionLUT2[8][2] = {
+ { 0, -1 },
+ { 1, 0 },
+ { 0, 1 },
+ { -1, 0 },
+ { 1, -1 },
+ { 1, 1 },
+ { -1, 1 },
+ { -1, -1 }
+};
+
+static const int angleLUT[16][2] = {
+ { 0, -256 },
+ { 98, -237 },
+ { 181, -181 },
+ { 237, -98 },
+ { 256, 0 },
+ { 237, 98 },
+ { 181, 181 },
+ { 98, 237 },
+ { 0, 256 },
+ { -98, 237 },
+ { -181, 181 },
+ { -237, 98 },
+ { -256, 0 },
+ { -237, -98 },
+ { -181, -181 },
+ { -98, -237 }
+};
+
+static const int directionLUT[8][2] = {
+ { 0 * 2, -2 * 2 },
+ { 2 * 2, -1 * 2 },
+ { 3 * 2, 0 * 2 },
+ { 2 * 2, 1 * 2 },
+ { 0 * 2, 2 * 2 },
+ { -2 * 2, 1 * 2 },
+ { -4 * 2, 0 * 2 },
+ { -2 * 2, -1 * 2 }
+};
+
+static const int tileDirectionLUT[8][2] = {
+ { 1, 1 },
+ { 2, 0 },
+ { 1, -1 },
+ { 0, -2 },
+ { -1, -1 },
+ { -2, 0 },
+ { -1, 1 },
+ { 0, 2 }
+};
+
+struct DragonMove {
+ uint16 baseFrame;
+ int16 offset[4][2];
+};
+
+static const DragonMove dragonMoveTable[12] = {
+ { 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 } } },
+ { 28, { { -0, 0 }, { -1, 6 }, { -5, 11 }, { -10, 15 } } },
+ { 56, { { 0, 0 }, { 1, 6 }, { 5, 11 }, { 10, 15 } } },
+ { 40, { { 0, 0 }, { 6, 1 }, { 11, 5 }, { 15, 10 } } },
+ { 44, { { 0, 0 }, { 6, -1 }, { 11, -5 }, { 15, -10 } } },
+ { 32, { { -0, -0 }, { -6, -1 }, { -11, -5 }, { -15, -10 } } },
+ { 52, { { -0, 0 }, { -6, 1 }, { -11, 5 }, { -15, 10 } } },
+ { 36, { { 0, -0 }, { 1, -6 }, { 5, -11 }, { 10, -15 } } },
+ { 48, { { -0, -0 }, { -1, -6 }, { -5, -11 }, { -10, -15 } } }
+};
+
+inline int16 quickDistance(const Point &point1, const Point &point2, int16 compressX) {
+ Point delta;
+ delta.x = ABS(point1.x - point2.x) / compressX;
+ delta.y = ABS(point1.y - point2.y);
+ return ((delta.x < delta.y) ? (delta.y + delta.x / 2) : (delta.x + delta.y / 2));
+}
+
+inline void calcDeltaS(const Point &point1, const Point &point2, Point &delta, Point &s) {
+
+ delta.x = point2.x - point1.x;
+ if (delta.x == 0) {
+ s.x = 0;
+ } else {
+ if (delta.x > 0) {
+ s.x = 1;
+ } else {
+ s.x = -1;
+ delta.x = -delta.x;
+ }
+ }
+
+
+ delta.y = point2.y - point1.y;
+ if (delta.y == 0) {
+ s.y = 0;
+ } else {
+ if (delta.y > 0) {
+ s.y = 1;
+ } else {
+ s.y = -1;
+ delta.y = -delta.y;
+ }
+ }
+}
+
+inline int16 int16Compare(int16 i1, int16 i2) {
+ return ((i1) > (i2) ? 1 : ((i1) < (i2) ? -1 : 0));
+}
+
+bool Actor::validFollowerLocation(const Location &location) {
+ Point point;
+ location.toScreenPointXY(point);
+
+ if ((point.x < 5) || (point.x >= _vm->getDisplayWidth() - 5) ||
+ (point.y < 0) || (point.y > _vm->_scene->getHeight())) {
+ return false;
+ }
+
+ return (_vm->_scene->canWalk(point));
+}
+
+void Actor::realLocation(Location &location, uint16 objectId, uint16 walkFlags) {
+ int angle;
+ int distance;
+ ActorData *actor;
+ ObjectData *obj;
+ debug (8, "Actor::realLocation objectId=%i", objectId);
+ if (walkFlags & kWalkUseAngle) {
+ if (_vm->_scene->getFlags() & kSceneFlagISO) {
+ angle = (location.x + 2) & 15;
+ distance = location.y;
+
+ location.u() = (angleLUT[angle][0] * distance) >> 8;
+ location.v() = -(angleLUT[angle][1] * distance) >> 8;
+ } else {
+ angle = location.x & 15;
+ distance = location.y;
+
+ location.x = (angleLUT[angle][0] * distance) >> 6;
+ location.y = (angleLUT[angle][1] * distance) >> 6;
+ }
+ }
+
+ if (objectId != ID_NOTHING) {
+ if (validActorId(objectId)) {
+ actor = getActor(objectId);
+ location.addXY(actor->_location);
+ } else if (validObjId(objectId)) {
+ obj = getObj(objectId);
+ location.addXY(obj->_location);
+ }
+ }
+}
+
+void Actor::actorFaceTowardsObject(uint16 actorId, uint16 objectId) {
+ ActorData *actor;
+ ObjectData *obj;
+
+ if (validActorId(objectId)) {
+ actor = getActor(objectId);
+ actorFaceTowardsPoint(actorId, actor->_location);
+ } else if (validObjId(objectId)) {
+ obj = getObj(objectId);
+ actorFaceTowardsPoint(actorId, obj->_location);
+ }
+}
+
+void Actor::actorFaceTowardsPoint(uint16 actorId, const Location &toLocation) {
+ ActorData *actor;
+ Location delta;
+ //debug (8, "Actor::actorFaceTowardsPoint actorId=%i", actorId);
+ actor = getActor(actorId);
+
+ toLocation.delta(actor->_location, delta);
+
+ if (_vm->_scene->getFlags() & kSceneFlagISO) {
+ if (delta.u() > 0) {
+ actor->_facingDirection = (delta.v() > 0) ? kDirUp : kDirRight;
+ } else {
+ actor->_facingDirection = (delta.v() > 0) ? kDirLeft : kDirDown;
+ }
+ } else {
+ if (ABS(delta.y) > ABS(delta.x * 2)) {
+ actor->_facingDirection = (delta.y > 0) ? kDirDown : kDirUp;
+ } else {
+ actor->_facingDirection = (delta.x > 0) ? kDirRight : kDirLeft;
+ }
+ }
+}
+
+void Actor::updateActorsScene(int actorsEntrance) {
+ int i, j;
+ int followerDirection;
+ ActorData *actor;
+ Location tempLocation;
+ Location possibleLocation;
+ Point delta;
+ const SceneEntry *sceneEntry;
+
+ if (_vm->_scene->currentSceneNumber() == 0) {
+ error("Actor::updateActorsScene _vm->_scene->currentSceneNumber() == 0");
+ }
+
+ _vm->_sound->stopVoice();
+ _activeSpeech.stringsCount = 0;
+ _activeSpeech.playing = false;
+ _protagonist = NULL;
+
+ for (i = 0; i < _actorsCount; i++) {
+ actor = _actors[i];
+ actor->_inScene = false;
+ actor->_spriteList.freeMem();
+ if (actor->_disabled) {
+ continue;
+ }
+ if ((actor->_flags & (kProtagonist | kFollower)) || (i == 0)) {
+ if (actor->_flags & kProtagonist) {
+ actor->_finalTarget = actor->_location;
+ _centerActor = _protagonist = actor;
+ } else if (_vm->getGameType() == GType_ITE &&
+ _vm->_scene->currentSceneResourceId() == RID_ITE_OVERMAP_SCENE) {
+ continue;
+ }
+
+ actor->_sceneNumber = _vm->_scene->currentSceneNumber();
+ }
+ if (actor->_sceneNumber == _vm->_scene->currentSceneNumber()) {
+ actor->_inScene = true;
+ actor->_actionCycle = (_vm->_rnd.getRandomNumber(7) & 0x7) * 4; // 1/8th chance
+ }
+ }
+
+ // _protagonist can be null while loading a game from the command line
+ if (_protagonist == NULL)
+ return;
+
+ if ((actorsEntrance >= 0) && (_vm->_scene->_entryList.entryListCount > 0)) {
+ if (_vm->_scene->_entryList.entryListCount <= actorsEntrance) {
+ actorsEntrance = 0; //OCEAN bug
+ }
+
+ sceneEntry = _vm->_scene->_entryList.getEntry(actorsEntrance);
+ if (_vm->_scene->getFlags() & kSceneFlagISO) {
+ _protagonist->_location = sceneEntry->location;
+ } else {
+ _protagonist->_location.x = sceneEntry->location.x * ACTOR_LMULT;
+ _protagonist->_location.y = sceneEntry->location.y * ACTOR_LMULT;
+ _protagonist->_location.z = sceneEntry->location.z * ACTOR_LMULT;
+ }
+ // Workaround for bug #1328045:
+ // "When entering any of the houses at the start of the
+ // game if you click on anything inside the building you
+ // start walking through the door, turn around and leave."
+ //
+ // After stepping on an action zone, Rif is trying to exit.
+ // Shift Rif's entry position to a non action zone area.
+ if (_vm->getGameType() == GType_ITE) {
+ if ((_vm->_scene->currentSceneNumber() >= 53) && (_vm->_scene->currentSceneNumber() <= 66))
+ _protagonist->_location.y += 10;
+ }
+
+ _protagonist->_facingDirection = _protagonist->_actionDirection = sceneEntry->facing;
+ }
+
+ _protagonist->_currentAction = kActionWait;
+
+ if (_vm->_scene->getFlags() & kSceneFlagISO) {
+ //nothing?
+ } else {
+ _vm->_scene->initDoorsState(); //TODO: move to _scene
+ }
+
+ followerDirection = _protagonist->_facingDirection + 3;
+ calcScreenPosition(_protagonist);
+
+ for (i = 0; i < _actorsCount; i++) {
+ actor = _actors[i];
+ if (actor->_flags & (kFollower)) {
+ actor->_facingDirection = actor->_actionDirection = _protagonist->_facingDirection;
+ actor->_currentAction = kActionWait;
+ actor->_walkStepsCount = actor->_walkStepIndex = 0;
+ actor->_location.z = _protagonist->_location.z;
+
+
+ if (_vm->_scene->getFlags() & kSceneFlagISO) {
+ _vm->_isoMap->placeOnTileMap(_protagonist->_location, actor->_location, 3, followerDirection & 0x07);
+ } else {
+ followerDirection &= 0x07;
+
+ possibleLocation = _protagonist->_location;
+
+ delta.x = directionLUT[followerDirection][0];
+ delta.y = directionLUT[followerDirection][1];
+
+ for (j = 0; j < 30; j++) {
+ tempLocation = possibleLocation;
+ tempLocation.x += delta.x;
+ tempLocation.y += delta.y;
+
+ if (validFollowerLocation(tempLocation)) {
+ possibleLocation = tempLocation;
+ } else {
+ tempLocation = possibleLocation;
+ tempLocation.x += delta.x;
+ if (validFollowerLocation(tempLocation)) {
+ possibleLocation = tempLocation;
+ } else {
+ tempLocation = possibleLocation;
+ tempLocation.y += delta.y;
+ if (validFollowerLocation(tempLocation)) {
+ possibleLocation = tempLocation;
+ } else {
+ break;
+ }
+ }
+ }
+ }
+
+ actor->_location = possibleLocation;
+ }
+ followerDirection += 2;
+ }
+
+ }
+
+ handleActions(0, true);
+ if (_vm->_scene->getFlags() & kSceneFlagISO) {
+ _vm->_isoMap->adjustScroll(true);
+ }
+}
+
+void Actor::handleActions(int msec, bool setup) {
+ int i;
+ ActorData *actor;
+ ActorFrameRange *frameRange;
+ int state;
+ int speed;
+ int32 framesLeft;
+ Location delta;
+ Location addDelta;
+ int hitZoneIndex;
+ const HitZone *hitZone;
+ Point hitPoint;
+ Location pickLocation;
+
+ for (i = 0; i < _actorsCount; i++) {
+ actor = _actors[i];
+ if (!actor->_inScene)
+ continue;
+
+ if ((_vm->getGameType() == GType_ITE) && (i == ACTOR_DRAGON_INDEX)) {
+ moveDragon(actor);
+ continue;
+ }
+
+ switch (actor->_currentAction) {
+ case kActionWait:
+ if (!setup && (actor->_flags & kFollower)) {
+ followProtagonist(actor);
+ if (actor->_currentAction != kActionWait)
+ break;
+ }
+
+ if (actor->_targetObject != ID_NOTHING) {
+ actorFaceTowardsObject(actor->_id, actor->_targetObject);
+ }
+
+ if (actor->_flags & kCycle) {
+ frameRange = getActorFrameRange(actor->_id, getFrameType(kFrameStand));
+ if (frameRange->frameCount > 0) {
+ actor->_actionCycle++;
+ actor->_actionCycle = (actor->_actionCycle) % frameRange->frameCount;
+ } else {
+ actor->_actionCycle = 0;
+ }
+ actor->_frameNumber = frameRange->frameIndex + actor->_actionCycle;
+ break;
+ }
+
+ if ((actor->_actionCycle & 3) == 0) {
+ actor->cycleWrap(100);
+
+ frameRange = getActorFrameRange(actor->_id, getFrameType(kFrameWait));
+ if ((frameRange->frameCount < 1 || actor->_actionCycle > 33))
+ frameRange = getActorFrameRange(actor->_id, getFrameType(kFrameStand));
+
+ if (frameRange->frameCount) {
+ actor->_frameNumber = frameRange->frameIndex + (uint16)_vm->_rnd.getRandomNumber(frameRange->frameCount - 1);
+ } else {
+ actor->_frameNumber = frameRange->frameIndex;
+ }
+ }
+ actor->_actionCycle++;
+ break;
+
+ case kActionWalkToPoint:
+ case kActionWalkToLink:
+ if (_vm->_scene->getFlags() & kSceneFlagISO) {
+ actor->_partialTarget.delta(actor->_location, delta);
+
+ while ((delta.u() == 0) && (delta.v() == 0)) {
+
+ if ((actor == _protagonist) && (_vm->mouseButtonPressed())) {
+ _vm->_isoMap->screenPointToTileCoords(_vm->mousePos(), pickLocation);
+
+ if (!actorWalkTo(_protagonist->_id, pickLocation)) {
+ break;
+ }
+ } else if (!_vm->_isoMap->nextTileTarget(actor) && !actorEndWalk(actor->_id, true)) {
+ break;
+ }
+
+ actor->_partialTarget.delta(actor->_location, delta);
+ actor->_partialTarget.z = 0;
+ }
+
+ if (actor->_flags & kFastest) {
+ speed = 8;
+ } else if (actor->_flags & kFaster) {
+ speed = 6;
+ } else {
+ speed = 4;
+ }
+
+ if (_vm->_scene->currentSceneResourceId() == RID_ITE_OVERMAP_SCENE) {
+ speed = 2;
+ }
+
+ if ((actor->_actionDirection == 2) || (actor->_actionDirection == 6)) {
+ speed = speed / 2;
+ }
+
+ if (ABS(delta.v()) > ABS(delta.u())) {
+ addDelta.v() = clamp(-speed, delta.v(), speed);
+ if (addDelta.v() == delta.v()) {
+ addDelta.u() = delta.u();
+ } else {
+ addDelta.u() = delta.u() * addDelta.v();
+ addDelta.u() += (addDelta.u() > 0) ? (delta.v() / 2) : (-delta.v() / 2);
+ addDelta.u() /= delta.v();
+ }
+ } else {
+ addDelta.u() = clamp(-speed, delta.u(), speed);
+ if (addDelta.u() == delta.u()) {
+ addDelta.v() = delta.v();
+ } else {
+ addDelta.v() = delta.v() * addDelta.u();
+ addDelta.v() += (addDelta.v() > 0) ? (delta.u() / 2) : (-delta.u() / 2);
+ addDelta.v() /= delta.u();
+ }
+ }
+
+ actor->_location.add(addDelta);
+ } else {
+ actor->_partialTarget.delta(actor->_location, delta);
+
+ while ((delta.x == 0) && (delta.y == 0)) {
+
+ if (actor->_walkStepIndex >= actor->_walkStepsCount) {
+ actorEndWalk(actor->_id, true);
+ break;
+ }
+
+ actor->_partialTarget.fromScreenPoint(actor->_walkStepsPoints[actor->_walkStepIndex++]);
+ if (_vm->getGameType() == GType_ITE) {
+ if (actor->_partialTarget.x > 224 * 2 * ACTOR_LMULT) {
+ actor->_partialTarget.x -= 256 * 2 * ACTOR_LMULT;
+ }
+ } else {
+ if (actor->_partialTarget.x > 224 * 4 * ACTOR_LMULT) {
+ actor->_partialTarget.x -= 256 * 4 * ACTOR_LMULT;
+ }
+ }
+
+ actor->_partialTarget.delta(actor->_location, delta);
+
+ if (ABS(delta.y) > ABS(delta.x)) {
+ actor->_actionDirection = delta.y > 0 ? kDirDown : kDirUp;
+ } else {
+ actor->_actionDirection = delta.x > 0 ? kDirRight : kDirLeft;
+ }
+ }
+
+ if(_vm->getGameType() == GType_ITE)
+ speed = (ACTOR_LMULT * 2 * actor->_screenScale + 63) / 256;
+ else
+ speed = (ACTOR_SPEED * actor->_screenScale + 128) >> 8;
+
+ if (speed < 1)
+ speed = 1;
+
+ if(_vm->getGameType() == GType_IHNM)
+ speed = speed / 2;
+
+ if ((actor->_actionDirection == kDirUp) || (actor->_actionDirection == kDirDown)) {
+ addDelta.y = clamp(-speed, delta.y, speed);
+ if (addDelta.y == delta.y) {
+ addDelta.x = delta.x;
+ } else {
+ addDelta.x = delta.x * addDelta.y;
+ addDelta.x += (addDelta.x > 0) ? (delta.y / 2) : (-delta.y / 2);
+ addDelta.x /= delta.y;
+ actor->_facingDirection = actor->_actionDirection;
+ }
+ } else {
+ addDelta.x = clamp(-2 * speed, delta.x, 2 * speed);
+ if (addDelta.x == delta.x) {
+ addDelta.y = delta.y;
+ } else {
+ addDelta.y = delta.y * addDelta.x;
+ addDelta.y += (addDelta.y > 0) ? (delta.x / 2) : (-delta.x / 2);
+ addDelta.y /= delta.x;
+ actor->_facingDirection = actor->_actionDirection;
+ }
+ }
+
+ actor->_location.add(addDelta);
+ }
+
+ if (actor->_actorFlags & kActorBackwards) {
+ actor->_facingDirection = (actor->_actionDirection + 4) & 7;
+ actor->_actionCycle--;
+ } else {
+ actor->_actionCycle++;
+ }
+
+ frameRange = getActorFrameRange(actor->_id, actor->_walkFrameSequence);
+
+ if (actor->_actionCycle < 0) {
+ actor->_actionCycle = frameRange->frameCount - 1;
+ } else if (actor->_actionCycle >= frameRange->frameCount) {
+ actor->_actionCycle = 0;
+ }
+
+ actor->_frameNumber = frameRange->frameIndex + actor->_actionCycle;
+ break;
+
+ case kActionWalkDir:
+ if (_vm->_scene->getFlags() & kSceneFlagISO) {
+ actor->_location.u() += tileDirectionLUT[actor->_actionDirection][0];
+ actor->_location.v() += tileDirectionLUT[actor->_actionDirection][1];
+
+ frameRange = getActorFrameRange(actor->_id, actor->_walkFrameSequence);
+
+ actor->_actionCycle++;
+ actor->cycleWrap(frameRange->frameCount);
+ actor->_frameNumber = frameRange->frameIndex + actor->_actionCycle;
+ } else {
+ if (_vm->getGameType() == GType_ITE) {
+ actor->_location.x += directionLUT[actor->_actionDirection][0] * 2;
+ actor->_location.y += directionLUT[actor->_actionDirection][1] * 2;
+ } else {
+ // FIXME: The original does not multiply by 8 here, but we do
+ actor->_location.x += (directionLUT[actor->_actionDirection][0] * 8 * actor->_screenScale + 128) >> 8;
+ actor->_location.y += (directionLUT[actor->_actionDirection][1] * 8 * actor->_screenScale + 128) >> 8;
+ }
+
+ frameRange = getActorFrameRange(actor->_id, actor->_walkFrameSequence);
+ actor->_actionCycle++;
+ actor->cycleWrap(frameRange->frameCount);
+ actor->_frameNumber = frameRange->frameIndex + actor->_actionCycle;
+ }
+ break;
+
+ case kActionSpeak:
+ actor->_actionCycle++;
+ actor->cycleWrap(64);
+
+ frameRange = getActorFrameRange(actor->_id, getFrameType(kFrameGesture));
+ if (actor->_actionCycle >= frameRange->frameCount) {
+ if (actor->_actionCycle & 1)
+ break;
+ frameRange = getActorFrameRange(actor->_id, getFrameType(kFrameSpeak));
+
+ state = (uint16)_vm->_rnd.getRandomNumber(frameRange->frameCount);
+
+ if (state == 0) {
+ frameRange = getActorFrameRange(actor->_id, getFrameType(kFrameStand));
+ } else {
+ state--;
+ }
+ } else {
+ state = actor->_actionCycle;
+ }
+
+ actor->_frameNumber = frameRange->frameIndex + state;
+ break;
+
+ case kActionAccept:
+ case kActionStoop:
+ break;
+
+ case kActionCycleFrames:
+ case kActionPongFrames:
+ if (actor->_cycleTimeCount > 0) {
+ actor->_cycleTimeCount--;
+ break;
+ }
+
+ actor->_cycleTimeCount = actor->_cycleDelay;
+ actor->_actionCycle++;
+
+ frameRange = getActorFrameRange(actor->_id, actor->_cycleFrameSequence);
+
+ if (actor->_currentAction == kActionPongFrames) {
+ if (actor->_actionCycle >= frameRange->frameCount * 2 - 2) {
+ if (actor->_actorFlags & kActorContinuous) {
+ actor->_actionCycle = 0;
+ } else {
+ actor->_currentAction = kActionFreeze;
+ break;
+ }
+ }
+
+ state = actor->_actionCycle;
+ if (state >= frameRange->frameCount) {
+ state = frameRange->frameCount * 2 - 2 - state;
+ }
+ } else {
+ if (actor->_actionCycle >= frameRange->frameCount) {
+ if (actor->_actorFlags & kActorContinuous) {
+ actor->_actionCycle = 0;
+ } else {
+ actor->_currentAction = kActionFreeze;
+ break;
+ }
+ }
+ state = actor->_actionCycle;
+ }
+
+ if (frameRange->frameCount && (actor->_actorFlags & kActorRandom)) {
+ state = _vm->_rnd.getRandomNumber(frameRange->frameCount - 1);
+ }
+
+ if (actor->_actorFlags & kActorBackwards) {
+ actor->_frameNumber = frameRange->frameIndex + frameRange->frameCount - 1 - state;
+ } else {
+ actor->_frameNumber = frameRange->frameIndex + state;
+ }
+ break;
+
+ case kActionFall:
+ if (actor->_actionCycle > 0) {
+ framesLeft = actor->_actionCycle--;
+ actor->_finalTarget.delta(actor->_location, delta);
+ delta.x /= framesLeft;
+ delta.y /= framesLeft;
+ actor->_location.addXY(delta);
+ actor->_fallVelocity += actor->_fallAcceleration;
+ actor->_fallPosition += actor->_fallVelocity;
+ actor->_location.z = actor->_fallPosition >> 4;
+ } else {
+ actor->_location = actor->_finalTarget;
+ actor->_currentAction = kActionFreeze;
+ _vm->_script->wakeUpActorThread(kWaitTypeWalk, actor);
+ }
+ break;
+
+ case kActionClimb:
+ actor->_cycleDelay++;
+ if (actor->_cycleDelay & 3) {
+ break;
+ }
+
+ if (actor->_location.z >= actor->_finalTarget.z + ACTOR_CLIMB_SPEED) {
+ actor->_location.z -= ACTOR_CLIMB_SPEED;
+ actor->_actionCycle--;
+ } else if (actor->_location.z <= actor->_finalTarget.z - ACTOR_CLIMB_SPEED) {
+ actor->_location.z += ACTOR_CLIMB_SPEED;
+ actor->_actionCycle++;
+ } else {
+ actor->_location.z = actor->_finalTarget.z;
+ actor->_currentAction = kActionFreeze;
+ _vm->_script->wakeUpActorThread(kWaitTypeWalk, actor);
+ }
+
+ frameRange = getActorFrameRange(actor->_id, actor->_cycleFrameSequence);
+
+ if (actor->_actionCycle < 0) {
+ actor->_actionCycle = frameRange->frameCount - 1;
+ }
+ actor->cycleWrap(frameRange->frameCount);
+ actor->_frameNumber = frameRange->frameIndex + actor->_actionCycle;
+ break;
+ }
+
+ if ((actor->_currentAction >= kActionWalkToPoint) && (actor->_currentAction <= kActionWalkDir)) {
+ hitZone = NULL;
+
+ if (_vm->_scene->getFlags() & kSceneFlagISO) {
+ actor->_location.toScreenPointUV(hitPoint);
+ } else {
+ actor->_location.toScreenPointXY(hitPoint);
+ }
+ hitZoneIndex = _vm->_scene->_actionMap->hitTest(hitPoint);
+ if (hitZoneIndex != -1) {
+ hitZone = _vm->_scene->_actionMap->getHitZone(hitZoneIndex);
+ }
+
+ if (hitZone != actor->_lastZone) {
+ if (actor->_lastZone)
+ stepZoneAction(actor, actor->_lastZone, true, false);
+ actor->_lastZone = hitZone;
+ // WORKAROUND for graphics glitch in the rat caves. Don't do this step zone action in the rat caves
+ // (room 51) for hitzone 24577 (the door with the copy protection) to avoid the glitch. This glitch
+ // happens because the copy protection is supposed to kick in at this point, but it's bypassed
+ // (with permission from Wyrmkeep Entertainment)
+ if (hitZone &&
+ !(_vm->getGameType() == GType_ITE && _vm->_scene->currentSceneNumber() == 51 && hitZone->getHitZoneId() == 24577))
+ stepZoneAction(actor, hitZone, false, false);
+ }
+ }
+ }
+ // Update frameCount for sfWaitFrames in IHNM
+ _vm->_frameCount++;
+}
+
+void Actor::direct(int msec) {
+
+ if (_vm->_scene->_entryList.entryListCount == 0) {
+ return;
+ }
+
+ if (_vm->_interface->_statusTextInput) {
+ return;
+ }
+
+ // FIXME: HACK. This should be turned into cycle event.
+ _lastTickMsec += msec;
+
+ if (_lastTickMsec > 1000 / _handleActionDiv) {
+ _lastTickMsec = 0;
+ //process actions
+ handleActions(msec, false);
+ }
+
+//process speech
+ handleSpeech(msec);
+}
+
+bool Actor::followProtagonist(ActorData *actor) {
+ Location protagonistLocation;
+ Location newLocation;
+ Location delta;
+ int protagonistBGMaskType;
+ Point prefer1;
+ Point prefer2;
+ Point prefer3;
+ int16 prefU;
+ int16 prefV;
+ int16 newU;
+ int16 newV;
+
+ assert(_protagonist);
+
+ actor->_flags &= ~(kFaster | kFastest);
+ protagonistLocation = _protagonist->_location;
+ calcScreenPosition(_protagonist);
+
+ if (_vm->_scene->getFlags() & kSceneFlagISO) {
+ prefU = 60;
+ prefV = 60;
+
+
+ actor->_location.delta(protagonistLocation, delta);
+
+ if (actor->_id == actorIndexToId(2)) {
+ prefU = prefV = 48;
+ }
+
+ if ((delta.u() > prefU) || (delta.u() < -prefU) || (delta.v() > prefV) || (delta.v() < -prefV)) {
+
+ if ((delta.u() > prefU * 2) || (delta.u() < -prefU * 2) || (delta.v() > prefV * 2) || (delta.v() < -prefV * 2)) {
+ actor->_flags |= kFaster;
+
+ if ((delta.u() > prefU * 3) || (delta.u() < -prefU*3) || (delta.v() > prefV * 3) || (delta.v() < -prefV * 3)) {
+ actor->_flags |= kFastest;
+ }
+ }
+
+ prefU /= 2;
+ prefV /= 2;
+
+ newU = clamp(-prefU, delta.u(), prefU) + protagonistLocation.u();
+ newV = clamp(-prefV, delta.v(), prefV) + protagonistLocation.v();
+
+ newLocation.u() = newU + _vm->_rnd.getRandomNumber(prefU - 1) - prefU / 2;
+ newLocation.v() = newV + _vm->_rnd.getRandomNumber(prefV - 1) - prefV / 2;
+ newLocation.z = 0;
+
+ return actorWalkTo(actor->_id, newLocation);
+ }
+
+ } else {
+ prefer1.x = (100 * _protagonist->_screenScale) >> 8;
+ prefer1.y = (50 * _protagonist->_screenScale) >> 8;
+
+ if (_protagonist->_currentAction == kActionWalkDir) {
+ prefer1.x /= 2;
+ }
+
+ if (prefer1.x < 8) {
+ prefer1.x = 8;
+ }
+
+ if (prefer1.y < 8) {
+ prefer1.y = 8;
+ }
+
+ prefer2.x = prefer1.x * 2;
+ prefer2.y = prefer1.y * 2;
+ prefer3.x = prefer1.x + prefer1.x / 2;
+ prefer3.y = prefer1.y + prefer1.y / 2;
+
+ actor->_location.delta(protagonistLocation, delta);
+
+ protagonistBGMaskType = 0;
+ if (_vm->_scene->isBGMaskPresent() && _vm->_scene->validBGMaskPoint(_protagonist->_screenPosition)) {
+ protagonistBGMaskType = _vm->_scene->getBGMaskType(_protagonist->_screenPosition);
+ }
+
+ if ((_vm->_rnd.getRandomNumber(7) & 0x7) == 0) // 1/8th chance
+ actor->_actorFlags &= ~kActorNoFollow;
+
+ if (actor->_actorFlags & kActorNoFollow) {
+ return false;
+ }
+
+ if ((delta.x > prefer2.x) || (delta.x < -prefer2.x) ||
+ (delta.y > prefer2.y) || (delta.y < -prefer2.y) ||
+ ((_protagonist->_currentAction == kActionWait) &&
+ (delta.x * 2 < prefer1.x) && (delta.x * 2 > -prefer1.x) &&
+ (delta.y < prefer1.y) && (delta.y > -prefer1.y))) {
+
+ if (ABS(delta.x) > ABS(delta.y)) {
+
+ delta.x = (delta.x > 0) ? prefer3.x : -prefer3.x;
+
+ newLocation.x = delta.x + protagonistLocation.x;
+ newLocation.y = clamp(-prefer2.y, delta.y, prefer2.y) + protagonistLocation.y;
+ } else {
+ delta.y = (delta.y > 0) ? prefer3.y : -prefer3.y;
+
+ newLocation.x = clamp(-prefer2.x, delta.x, prefer2.x) + protagonistLocation.x;
+ newLocation.y = delta.y + protagonistLocation.y;
+ }
+ newLocation.z = 0;
+
+ if (protagonistBGMaskType != 3) {
+ newLocation.x += _vm->_rnd.getRandomNumber(prefer1.x - 1) - prefer1.x / 2;
+ newLocation.y += _vm->_rnd.getRandomNumber(prefer1.y - 1) - prefer1.y / 2;
+ }
+
+ newLocation.x = clamp(-31 * 4, newLocation.x, (_vm->getDisplayWidth() + 31) * 4);
+
+ return actorWalkTo(actor->_id, newLocation);
+ }
+ }
+ return false;
+}
+
+bool Actor::actorWalkTo(uint16 actorId, const Location &toLocation) {
+ ActorData *actor;
+ ActorData *anotherActor;
+ int i;
+
+ Rect testBox;
+ Rect testBox2;
+ Point anotherActorScreenPosition;
+ Point collision;
+ Point pointFrom, pointTo, pointBest, pointAdd;
+ Point delta, bestDelta;
+ Point tempPoint;
+ bool extraStartNode;
+ bool extraEndNode;
+
+ actor = getActor(actorId);
+
+ if (actor == _protagonist) {
+ _vm->_scene->setDoorState(2, 0xff);
+ _vm->_scene->setDoorState(3, 0);
+ } else {
+ _vm->_scene->setDoorState(2, 0);
+ _vm->_scene->setDoorState(3, 0xff);
+ }
+
+ if (_vm->_scene->getFlags() & kSceneFlagISO) {
+
+ if ((_vm->getGameType() == GType_ITE) && (actor->_index == ACTOR_DRAGON_INDEX)) {
+ return false;
+ }
+
+ actor->_finalTarget = toLocation;
+ actor->_walkStepsCount = 0;
+ _vm->_isoMap->findTilePath(actor, actor->_location, toLocation);
+
+
+ if ((actor->_walkStepsCount == 0) && (actor->_flags & kProtagonist)) {
+ actor->_actorFlags |= kActorNoCollide;
+ _vm->_isoMap->findTilePath(actor, actor->_location, toLocation);
+ }
+
+ actor->_walkStepIndex = 0;
+ if (_vm->_isoMap->nextTileTarget(actor)) {
+ actor->_currentAction = kActionWalkToPoint;
+ actor->_walkFrameSequence = getFrameType(kFrameWalk);
+ } else {
+ actorEndWalk(actorId, false);
+ return false;
+ }
+ } else {
+
+ actor->_location.toScreenPointXY(pointFrom);
+ pointFrom.x &= ~1;
+
+ extraStartNode = _vm->_scene->offscreenPath(pointFrom);
+
+ toLocation.toScreenPointXY(pointTo);
+ pointTo.x &= ~1;
+
+ extraEndNode = _vm->_scene->offscreenPath(pointTo);
+
+ if (_vm->_scene->isBGMaskPresent()) {
+
+ if ((((actor->_currentAction >= kActionWalkToPoint) &&
+ (actor->_currentAction <= kActionWalkDir)) || (actor == _protagonist)) &&
+ !_vm->_scene->canWalk(pointFrom)) {
+
+ int max = _vm->getGameType() == GType_ITE ? 8 : 4;
+
+ for (i = 1; i < max; i++) {
+ pointAdd = pointFrom;
+ pointAdd.y += i;
+ if (_vm->_scene->canWalk(pointAdd)) {
+ pointFrom = pointAdd;
+ break;
+ }
+ pointAdd = pointFrom;
+ pointAdd.y -= i;
+ if (_vm->_scene->canWalk(pointAdd)) {
+ pointFrom = pointAdd;
+ break;
+ }
+ if (_vm->getGameType() == GType_ITE) {
+ pointAdd = pointFrom;
+ pointAdd.x += i;
+ if (_vm->_scene->canWalk(pointAdd)) {
+ pointFrom = pointAdd;
+ break;
+ }
+ pointAdd = pointFrom;
+ pointAdd.x -= i;
+ if (_vm->_scene->canWalk(pointAdd)) {
+ pointFrom = pointAdd;
+ break;
+ }
+ }
+ }
+ }
+
+ _barrierCount = 0;
+ if (!(actor->_actorFlags & kActorNoCollide)) {
+ collision.x = ACTOR_COLLISION_WIDTH * actor->_screenScale / (256 * 2);
+ collision.y = ACTOR_COLLISION_HEIGHT * actor->_screenScale / (256 * 2);
+
+
+ for (i = 0; (i < _actorsCount) && (_barrierCount < ACTOR_BARRIERS_MAX); i++) {
+ anotherActor = _actors[i];
+ if (!anotherActor->_inScene)
+ continue;
+ if (anotherActor == actor)
+ continue;
+
+ anotherActorScreenPosition = anotherActor->_screenPosition;
+ testBox.left = (anotherActorScreenPosition.x - collision.x) & ~1;
+ testBox.right = (anotherActorScreenPosition.x + collision.x) & ~1 + 1;
+ testBox.top = anotherActorScreenPosition.y - collision.y;
+ testBox.bottom = anotherActorScreenPosition.y + collision.y + 1;
+ testBox2 = testBox;
+ testBox2.right += 2;
+ testBox2.left -= 2;
+ testBox2.top -= 1;
+ testBox2.bottom += 1;
+
+ if (testBox2.contains(pointFrom)) {
+ if (pointFrom.x > anotherActorScreenPosition.x + 4) {
+ testBox.right = pointFrom.x - 1;
+ } else if (pointFrom.x < anotherActorScreenPosition.x - 4) {
+ testBox.left = pointFrom.x + 2;
+ } else if (pointFrom.y > anotherActorScreenPosition.y) {
+ testBox.bottom = pointFrom.y;
+ } else {
+ testBox.top = pointFrom.y + 1 ;
+ }
+ }
+
+ if ((testBox.width() > 0) && (testBox.height() > 0)) {
+ _barrierList[_barrierCount++] = testBox;
+ }
+ }
+ }
+
+
+ pointBest = pointTo;
+ actor->_walkStepsCount = 0;
+ findActorPath(actor, pointFrom, pointTo);
+
+ if (actor->_walkStepsCount == 0) {
+ error("actor->_walkStepsCount == 0");
+ }
+
+ if (extraStartNode) {
+ actor->_walkStepIndex = 0;
+ } else {
+ actor->_walkStepIndex = 1;
+ }
+
+ if (extraEndNode) {
+ toLocation.toScreenPointXY(tempPoint);
+ actor->_walkStepsCount--;
+ actor->addWalkStepPoint(tempPoint);
+ }
+
+
+ pointBest = actor->_walkStepsPoints[actor->_walkStepsCount - 1];
+
+ pointBest.x &= ~1;
+ delta.x = ABS(pointFrom.x - pointTo.x);
+ delta.y = ABS(pointFrom.y - pointTo.y);
+
+ bestDelta.x = ABS(pointBest.x - pointTo.x);
+ bestDelta.y = ABS(pointBest.y - pointTo.y);
+
+ if ((delta.x + delta.y <= bestDelta.x + bestDelta.y) && (actor->_flags & kFollower)) {
+ actor->_actorFlags |= kActorNoFollow;
+ }
+
+ if (pointBest == pointFrom) {
+ actor->_walkStepsCount = 0;
+ }
+ } else {
+ actor->_walkStepsCount = 0;
+ actor->addWalkStepPoint(pointTo);
+ actor->_walkStepIndex = 0;
+ }
+
+ actor->_partialTarget = actor->_location;
+ actor->_finalTarget = toLocation;
+ if (actor->_walkStepsCount == 0) {
+ actorEndWalk(actorId, false);
+ return false;
+ } else {
+ if (actor->_flags & kProtagonist) {
+ _actors[1]->_actorFlags &= ~kActorNoFollow; // TODO: mark all actors with kFollower flag, not only 1 and 2
+ _actors[2]->_actorFlags &= ~kActorNoFollow;
+ }
+ actor->_currentAction = (actor->_walkStepsCount >= ACTOR_MAX_STEPS_COUNT) ? kActionWalkToLink : kActionWalkToPoint;
+ actor->_walkFrameSequence = getFrameType(kFrameWalk);
+ }
+ }
+ return true;
+}
+
+bool Actor::actorEndWalk(uint16 actorId, bool recurse) {
+ bool walkMore = false;
+ ActorData *actor;
+ const HitZone *hitZone;
+ int hitZoneIndex;
+ Point testPoint;
+
+ actor = getActor(actorId);
+ actor->_actorFlags &= ~kActorBackwards;
+
+ if (_vm->getGameType() == GType_ITE) {
+
+ if (actor->_location.distance(actor->_finalTarget) > 8 && (actor->_flags & kProtagonist) && recurse && !(actor->_actorFlags & kActorNoCollide)) {
+ actor->_actorFlags |= kActorNoCollide;
+ return actorWalkTo(actorId, actor->_finalTarget);
+ }
+ }
+
+ actor->_currentAction = kActionWait;
+ if (actor->_actorFlags & kActorFinalFace) {
+ actor->_facingDirection = actor->_actionDirection = (actor->_actorFlags >> 6) & 0x07; //?
+ }
+
+ actor->_actorFlags &= ~(kActorNoCollide | kActorCollided | kActorFinalFace | kActorFacingMask);
+ actor->_flags &= ~(kFaster | kFastest);
+
+ if (actor == _protagonist) {
+ _vm->_script->wakeUpActorThread(kWaitTypeWalk, actor);
+ if (_vm->_script->_pendingVerb == _vm->_script->getVerbType(kVerbWalkTo)) {
+ if (_vm->getGameType() == GType_ITE)
+ actor->_location.toScreenPointUV(testPoint); // it's wrong calculation, but it is used in ITE
+ else
+ actor->_location.toScreenPointXY(testPoint);
+
+ hitZoneIndex = _vm->_scene->_actionMap->hitTest(testPoint);
+ if (hitZoneIndex != -1) {
+ hitZone = _vm->_scene->_actionMap->getHitZone(hitZoneIndex);
+ stepZoneAction(actor, hitZone, false, true);
+ } else {
+ _vm->_script->setNoPendingVerb();
+ }
+ } else if (_vm->_script->_pendingVerb != _vm->_script->getVerbType(kVerbNone)) {
+ _vm->_script->doVerb();
+ }
+ } else {
+ if (recurse && (actor->_flags & kFollower))
+ walkMore = followProtagonist(actor);
+
+ _vm->_script->wakeUpActorThread(kWaitTypeWalk, actor);
+ }
+ return walkMore;
+}
+
+void Actor::moveDragon(ActorData *actor) {
+ int16 dir0, dir1, dir2, dir3;
+ int16 moveType;
+ Event event;
+ const DragonMove *dragonMove;
+
+ if ((actor->_actionCycle < 0) ||
+ ((actor->_actionCycle == 0) && (actor->_dragonMoveType >= ACTOR_DRAGON_TURN_MOVES))) {
+
+ moveType = kDragonMoveInvalid;
+ if (actor->_location.distance(_protagonist->_location) < 24) {
+ if (_dragonHunt && (_protagonist->_currentAction != kActionFall)) {
+ event.type = kEvTOneshot;
+ event.code = kScriptEvent;
+ event.op = kEventExecNonBlocking;
+ event.time = 0;
+ event.param = _vm->_scene->getScriptModuleNumber(); // module number
+ event.param2 = ACTOR_EXP_KNOCK_RIF; // script entry point number
+ event.param3 = -1; // Action
+ event.param4 = -1; // Object
+ event.param5 = -1; // With Object
+ event.param6 = -1; // Actor
+ _vm->_events->queue(&event);
+
+ _dragonHunt = false;
+ }
+ } else {
+ _dragonHunt = true;
+ }
+
+ if (actor->_walkStepIndex + 2 > actor->_walkStepsCount) {
+
+ _vm->_isoMap->findDragonTilePath(actor, actor->_location, _protagonist->_location, actor->_actionDirection);
+
+ if (actor->_walkStepsCount == 0) {
+ _vm->_isoMap->findDragonTilePath(actor, actor->_location, _protagonist->_location, 0);
+ }
+
+ if (actor->_walkStepsCount < 2) {
+ return;
+ }
+
+ actor->_partialTarget = actor->_location;
+ actor->_finalTarget = _protagonist->_location;
+ actor->_walkStepIndex = 0;
+ }
+
+ dir0 = actor->_actionDirection;
+ dir1 = actor->_tileDirections[actor->_walkStepIndex++];
+ dir2 = actor->_tileDirections[actor->_walkStepIndex];
+ dir3 = actor->_tileDirections[actor->_walkStepIndex + 1];
+
+ if (dir0 != dir1){
+ actor->_actionDirection = dir0 = dir1;
+ }
+
+ actor->_location = actor->_partialTarget;
+
+ if ((dir1 != dir2) && (dir1 == dir3)) {
+ switch (dir1) {
+ case kDirUpLeft:
+ actor->_partialTarget.v() += 16;
+ moveType = kDragonMoveUpLeft;
+ break;
+ case kDirDownLeft:
+ actor->_partialTarget.u() -= 16;
+ moveType = kDragonMoveDownLeft;
+ break;
+ case kDirDownRight:
+ actor->_partialTarget.v() -= 16;
+ moveType = kDragonMoveDownRight;
+ break;
+ case kDirUpRight:
+ actor->_partialTarget.u() += 16;
+ moveType = kDragonMoveUpRight;
+ break;
+ }
+
+ switch (dir2) {
+ case kDirUpLeft:
+ actor->_partialTarget.v() += 16;
+ break;
+ case kDirDownLeft:
+ actor->_partialTarget.u() -= 16;
+ break;
+ case kDirDownRight:
+ actor->_partialTarget.v() -= 16;
+ break;
+ case kDirUpRight:
+ actor->_partialTarget.u() += 16;
+ break;
+ }
+
+ actor->_walkStepIndex++;
+ } else {
+ switch (dir1) {
+ case kDirUpLeft:
+ actor->_partialTarget.v() += 16;
+ switch (dir2) {
+ case kDirDownLeft:
+ moveType = kDragonMoveUpLeft_Left;
+ actor->_partialTarget.u() -= 16;
+ break;
+ case kDirUpLeft:
+ moveType = kDragonMoveUpLeft;
+ break;
+ case kDirUpRight:
+ actor->_partialTarget.u() += 16;
+ moveType = kDragonMoveUpLeft_Right;
+ break;
+ default:
+ actor->_actionDirection = dir1;
+ actor->_walkStepsCount = 0;
+ break;
+ }
+ break;
+ case kDirDownLeft:
+ actor->_partialTarget.u() -= 16;
+ switch (dir2) {
+ case kDirDownRight:
+ moveType = kDragonMoveDownLeft_Left;
+ actor->_partialTarget.v() -= 16;
+ break;
+ case kDirDownLeft:
+ moveType = kDragonMoveDownLeft;
+ break;
+ case kDirUpLeft:
+ moveType = kDragonMoveDownLeft_Right;
+ actor->_partialTarget.v() += 16;
+ break;
+ default:
+ actor->_actionDirection = dir1;
+ actor->_walkStepsCount = 0;
+ break;
+ }
+ break;
+ case kDirDownRight:
+ actor->_partialTarget.v() -= 16;
+ switch (dir2) {
+ case kDirUpRight:
+ moveType = kDragonMoveDownRight_Left;
+ actor->_partialTarget.u() += 16;
+ break;
+ case kDirDownRight:
+ moveType = kDragonMoveDownRight;
+ break;
+ case kDirDownLeft:
+ moveType = kDragonMoveDownRight_Right;
+ actor->_partialTarget.u() -= 16;
+ break;
+ default:
+ actor->_actionDirection = dir1;
+ actor->_walkStepsCount = 0;
+ break;
+ }
+ break;
+ case kDirUpRight:
+ actor->_partialTarget.u() += 16;
+ switch (dir2) {
+ case kDirUpLeft:
+ moveType = kDragonMoveUpRight_Left;
+ actor->_partialTarget.v() += 16;
+ break;
+ case kDirUpRight:
+ moveType = kDragonMoveUpRight;
+ break;
+ case kDirDownRight:
+ moveType = kDragonMoveUpRight_Right;
+ actor->_partialTarget.v() -= 16;
+ break;
+ default:
+ actor->_actionDirection = dir1;
+ actor->_walkStepsCount = 0;
+ break;
+ }
+ break;
+
+ default:
+ actor->_actionDirection = dir1;
+ actor->_walkStepsCount = 0;
+ break;
+ }
+ }
+
+ actor->_dragonMoveType = moveType;
+
+ if (moveType >= ACTOR_DRAGON_TURN_MOVES) {
+ actor->_dragonStepCycle = 0;
+ actor->_actionCycle = 4;
+ actor->_walkStepIndex++;
+ } else {
+ actor->_actionCycle = 4;
+ }
+ }
+
+ actor->_actionCycle--;
+
+ if ((actor->_walkStepsCount < 1) || (actor->_actionCycle < 0)) {
+ return;
+ }
+
+ if (actor->_dragonMoveType < ACTOR_DRAGON_TURN_MOVES) {
+
+ actor->_dragonStepCycle++;
+ if (actor->_dragonStepCycle >= 7) {
+ actor->_dragonStepCycle = 0;
+ }
+
+ actor->_dragonBaseFrame = actor->_dragonMoveType * 7;
+
+ if (actor->_location.u() > actor->_partialTarget.u() + 3) {
+ actor->_location.u() -= 4;
+ } else if (actor->_location.u() < actor->_partialTarget.u() - 3) {
+ actor->_location.u() += 4;
+ } else {
+ actor->_location.u() = actor->_partialTarget.u();
+ }
+
+ if (actor->_location.v() > actor->_partialTarget.v() + 3) {
+ actor->_location.v() -= 4;
+ } else if (actor->_location.v() < actor->_partialTarget.v() - 3) {
+ actor->_location.v() += 4;
+ } else {
+ actor->_location.v() = actor->_partialTarget.v();
+ }
+ } else {
+ dragonMove = &dragonMoveTable[actor->_dragonMoveType];
+ actor->_dragonBaseFrame = dragonMove->baseFrame;
+
+
+ actor->_location.u() = actor->_partialTarget.u() - dragonMove->offset[actor->_actionCycle][0];
+ actor->_location.v() = actor->_partialTarget.v() - dragonMove->offset[actor->_actionCycle][1];
+
+ actor->_dragonStepCycle++;
+ if (actor->_dragonStepCycle >= 3) {
+ actor->_dragonStepCycle = 3;
+ }
+ }
+
+ actor->_frameNumber = actor->_dragonBaseFrame + actor->_dragonStepCycle;
+}
+
+void Actor::findActorPath(ActorData *actor, const Point &fromPoint, const Point &toPoint) {
+ Point iteratorPoint;
+ Point bestPoint;
+ int maskType;
+ int i;
+ Rect intersect;
+
+#ifdef ACTOR_DEBUG
+ _debugPointsCount = 0;
+#endif
+
+ actor->_walkStepsCount = 0;
+ if (fromPoint == toPoint) {
+ actor->addWalkStepPoint(toPoint);
+ return;
+ }
+
+ for (iteratorPoint.y = 0; iteratorPoint.y < _yCellCount; iteratorPoint.y++) {
+ for (iteratorPoint.x = 0; iteratorPoint.x < _xCellCount; iteratorPoint.x++) {
+ if (_vm->_scene->validBGMaskPoint(iteratorPoint)) {
+ maskType = _vm->_scene->getBGMaskType(iteratorPoint);
+ setPathCell(iteratorPoint, _vm->_scene->getDoorState(maskType) ? kPathCellBarrier : kPathCellEmpty);
+ } else {
+ setPathCell(iteratorPoint, kPathCellBarrier);
+ }
+ }
+ }
+
+ for (i = 0; i < _barrierCount; i++) {
+ intersect.left = MAX(_pathRect.left, _barrierList[i].left);
+ intersect.top = MAX(_pathRect.top, _barrierList[i].top);
+ intersect.right = MIN(_pathRect.right, _barrierList[i].right);
+ intersect.bottom = MIN(_pathRect.bottom, _barrierList[i].bottom);
+
+ for (iteratorPoint.y = intersect.top; iteratorPoint.y < intersect.bottom; iteratorPoint.y++) {
+ for (iteratorPoint.x = intersect.left; iteratorPoint.x < intersect.right; iteratorPoint.x++) {
+ setPathCell(iteratorPoint, kPathCellBarrier);
+ }
+ }
+ }
+
+#ifdef ACTOR_DEBUG
+ for (iteratorPoint.y = 0; iteratorPoint.y < _yCellCount; iteratorPoint.y++) {
+ for (iteratorPoint.x = 0; iteratorPoint.x < _xCellCount; iteratorPoint.x++) {
+ if (getPathCell(iteratorPoint) == kPathCellBarrier) {
+ addDebugPoint(iteratorPoint, 24);
+ }
+ }
+ }
+#endif
+
+ if (scanPathLine(fromPoint, toPoint)) {
+ actor->addWalkStepPoint(fromPoint);
+ actor->addWalkStepPoint(toPoint);
+ return;
+ }
+
+ i = fillPathArray(fromPoint, toPoint, bestPoint);
+
+ if (fromPoint == bestPoint) {
+ actor->addWalkStepPoint(bestPoint);
+ return;
+ }
+
+ if (i == 0) {
+ error("fillPathArray returns zero");
+ }
+
+ setActorPath(actor, fromPoint, bestPoint);
+}
+
+bool Actor::scanPathLine(const Point &point1, const Point &point2) {
+ Point point;
+ Point delta;
+ Point s;
+ Point fDelta;
+ int16 errterm;
+
+ calcDeltaS(point1, point2, delta, s);
+ point = point1;
+
+ fDelta.x = delta.x * 2;
+ fDelta.y = delta.y * 2;
+
+ if (delta.y > delta.x) {
+
+ errterm = fDelta.x - delta.y;
+
+ while (delta.y > 0) {
+ while (errterm >= 0) {
+ point.x += s.x;
+ errterm -= fDelta.y;
+ }
+
+ point.y += s.y;
+ errterm += fDelta.x;
+
+ if (!validPathCellPoint(point)) {
+ return false;
+ }
+ if (getPathCell(point) == kPathCellBarrier) {
+ return false;
+ }
+ delta.y--;
+ }
+ } else {
+
+ errterm = fDelta.y - delta.x;
+
+ while (delta.x > 0) {
+ while (errterm >= 0) {
+ point.y += s.y;
+ errterm -= fDelta.x;
+ }
+
+ point.x += s.x;
+ errterm += fDelta.y;
+
+ if (!validPathCellPoint(point)) {
+ return false;
+ }
+ if (getPathCell(point) == kPathCellBarrier) {
+ return false;
+ }
+ delta.x--;
+ }
+ }
+ return true;
+}
+
+int Actor::fillPathArray(const Point &fromPoint, const Point &toPoint, Point &bestPoint) {
+ int bestRating;
+ int currentRating;
+ int i;
+ Point bestPath;
+ int pointCounter;
+ int startDirection;
+ PathDirectionData *pathDirection;
+ PathDirectionData *newPathDirection;
+ const PathDirectionData *samplePathDirection;
+ Point nextPoint;
+ int directionCount;
+ int16 compressX = (_vm->getGameType() == GType_ITE) ? 2 : 1;
+
+ _pathDirectionListCount = 0;
+ pointCounter = 0;
+ bestRating = quickDistance(fromPoint, toPoint, compressX);
+ bestPath = fromPoint;
+
+ for (startDirection = 0; startDirection < 4; startDirection++) {
+ newPathDirection = addPathDirectionListData();
+ newPathDirection->coord = fromPoint;
+ newPathDirection->direction = startDirection;
+ }
+
+ if (validPathCellPoint(fromPoint)) {
+ setPathCell(fromPoint, kDirUp);
+
+#ifdef ACTOR_DEBUG
+ addDebugPoint(fromPoint, 24+36);
+#endif
+ }
+
+ i = 0;
+
+ do {
+ pathDirection = &_pathDirectionList[i];
+ for (directionCount = 0; directionCount < 3; directionCount++) {
+ samplePathDirection = &pathDirectionLUT[pathDirection->direction][directionCount];
+ nextPoint = pathDirection->coord;
+ nextPoint.x += samplePathDirection->coord.x;
+ nextPoint.y += samplePathDirection->coord.y;
+
+ if (!validPathCellPoint(nextPoint)) {
+ continue;
+ }
+
+ if (getPathCell(nextPoint) != kPathCellEmpty) {
+ continue;
+ }
+
+ setPathCell(nextPoint, samplePathDirection->direction);
+
+#ifdef ACTOR_DEBUG
+ addDebugPoint(nextPoint, samplePathDirection->direction + 96);
+#endif
+ newPathDirection = addPathDirectionListData();
+ newPathDirection->coord = nextPoint;
+ newPathDirection->direction = samplePathDirection->direction;
+ ++pointCounter;
+ if (nextPoint == toPoint) {
+ bestPoint = toPoint;
+ return pointCounter;
+ }
+ currentRating = quickDistance(nextPoint, toPoint, compressX);
+ if (currentRating < bestRating) {
+ bestRating = currentRating;
+ bestPath = nextPoint;
+ }
+ pathDirection = &_pathDirectionList[i];
+ }
+ ++i;
+ } while (i < _pathDirectionListCount);
+
+ bestPoint = bestPath;
+ return pointCounter;
+}
+
+void Actor::setActorPath(ActorData *actor, const Point &fromPoint, const Point &toPoint) {
+ Point nextPoint;
+ int8 direction;
+ int i;
+
+ _pathListIndex = -1;
+ addPathListPoint(toPoint);
+ nextPoint = toPoint;
+
+ while (!(nextPoint == fromPoint)) {
+ direction = getPathCell(nextPoint);
+ if ((direction < 0) || (direction >= 8)) {
+ error("Actor::setActorPath error direction 0x%X", direction);
+ }
+ nextPoint.x -= pathDirectionLUT2[direction][0];
+ nextPoint.y -= pathDirectionLUT2[direction][1];
+ addPathListPoint(nextPoint);
+
+#ifdef ACTOR_DEBUG
+ addDebugPoint(nextPoint, 0x8a);
+#endif
+ }
+
+ pathToNode();
+ removeNodes();
+ nodeToPath();
+ removePathPoints();
+
+ for (i = 0; i <= _pathNodeListIndex; i++) {
+ actor->addWalkStepPoint(_pathNodeList[i].point);
+ }
+}
+
+void Actor::pathToNode() {
+ Point point1, point2, delta;
+ int direction;
+ int i;
+ Point *point;
+
+ point= &_pathList[_pathListIndex];
+ direction = 0;
+
+ _pathNodeListIndex = -1;
+ addPathNodeListPoint(*point);
+
+ for (i = _pathListIndex; i > 0; i--) {
+ point1 = *point;
+ --point;
+ point2 = *point;
+ if (direction == 0) {
+ delta.x = int16Compare(point2.x, point1.x);
+ delta.y = int16Compare(point2.y, point1.y);
+ direction++;
+ }
+ if ((point1.x + delta.x != point2.x) || (point1.y + delta.y != point2.y)) {
+ addPathNodeListPoint(point1);
+ direction--;
+ i++;
+ point++;
+ }
+ }
+ addPathNodeListPoint(*_pathList);
+}
+
+int pathLine(Point *pointList, const Point &point1, const Point &point2) {
+ Point point;
+ Point delta;
+ Point tempPoint;
+ Point s;
+ int16 errterm;
+ int16 res;
+
+ calcDeltaS(point1, point2, delta, s);
+
+ point = point1;
+
+ tempPoint.x = delta.x * 2;
+ tempPoint.y = delta.y * 2;
+
+ if (delta.y > delta.x) {
+
+ errterm = tempPoint.x - delta.y;
+ res = delta.y;
+
+ while (delta.y > 0) {
+ while (errterm >= 0) {
+ point.x += s.x;
+ errterm -= tempPoint.y;
+ }
+
+ point.y += s.y;
+ errterm += tempPoint.x;
+
+ *pointList = point;
+ pointList++;
+ delta.y--;
+ }
+ } else {
+
+ errterm = tempPoint.y - delta.x;
+ res = delta.x;
+
+ while (delta.x > 0) {
+ while (errterm >= 0) {
+ point.y += s.y;
+ errterm -= tempPoint.x;
+ }
+
+ point.x += s.x;
+ errterm += tempPoint.y;
+
+ *pointList = point;
+ pointList++;
+ delta.x--;
+ }
+ }
+ return res;
+}
+
+void Actor::nodeToPath() {
+ int i;
+ Point point1, point2;
+ PathNode *node;
+ Point *point;
+
+ for (i = 0, point = _pathList; i < _pathListAlloced; i++, point++) {
+ point->x = point->y = PATH_NODE_EMPTY;
+ }
+
+ _pathListIndex = 1;
+ _pathList[0] = _pathNodeList[0].point;
+ _pathNodeList[0].link = 0;
+ for (i = 0, node = _pathNodeList; i < _pathNodeListIndex; i++) {
+ point1 = node->point;
+ node++;
+ point2 = node->point;
+ _pathListIndex += pathLine(&_pathList[_pathListIndex], point1, point2);
+ node->link = _pathListIndex - 1;
+ }
+ _pathListIndex--;
+ _pathNodeList[_pathNodeListIndex].link = _pathListIndex;
+
+}
+
+void Actor::removeNodes() {
+ int i, j, k;
+ PathNode *iNode, *jNode, *kNode, *fNode;
+ fNode = &_pathNodeList[_pathNodeListIndex];
+
+ if (scanPathLine(_pathNodeList[0].point, fNode->point)) {
+ _pathNodeList[1] = *fNode;
+ _pathNodeListIndex = 1;
+ }
+
+ if (_pathNodeListIndex < 4) {
+ return;
+ }
+
+ for (i = _pathNodeListIndex - 1, iNode = fNode-1; i > 1 ; i--, iNode--) {
+ if (iNode->point.x == PATH_NODE_EMPTY) {
+ continue;
+ }
+
+ if (scanPathLine(_pathNodeList[0].point, iNode->point)) {
+ for (j = 1, jNode = _pathNodeList + 1; j < i; j++, jNode++) {
+ jNode->point.x = PATH_NODE_EMPTY;
+ }
+ }
+ }
+
+ for (i = 1, iNode = _pathNodeList + 1; i < _pathNodeListIndex - 1; i++, iNode++) {
+ if (iNode->point.x == PATH_NODE_EMPTY) {
+ continue;
+ }
+
+ if (scanPathLine(fNode->point, iNode->point)) {
+ for (j = i + 1, jNode = iNode + 1; j < _pathNodeListIndex; j++, jNode++) {
+ jNode->point.x = PATH_NODE_EMPTY;
+ }
+ }
+ }
+ condenseNodeList();
+
+ for (i = 1, iNode = _pathNodeList + 1; i < _pathNodeListIndex - 1; i++, iNode++) {
+ if (iNode->point.x == PATH_NODE_EMPTY) {
+ continue;
+ }
+ for (j = i + 2, jNode = iNode + 2; j < _pathNodeListIndex; j++, jNode++) {
+ if (jNode->point.x == PATH_NODE_EMPTY) {
+ continue;
+ }
+
+ if (scanPathLine(iNode->point, jNode->point)) {
+ for (k = i + 1,kNode = iNode + 1; k < j; k++, kNode++) {
+ kNode->point.x = PATH_NODE_EMPTY;
+ }
+ }
+ }
+ }
+ condenseNodeList();
+}
+
+void Actor::condenseNodeList() {
+ int i, j, count;
+ PathNode *iNode, *jNode;
+
+ count = _pathNodeListIndex;
+
+ for (i = 1, iNode = _pathNodeList + 1; i < _pathNodeListIndex; i++, iNode++) {
+ if (iNode->point.x == PATH_NODE_EMPTY) {
+ j = i + 1;
+ jNode = iNode + 1;
+ while (jNode->point.x == PATH_NODE_EMPTY) {
+ j++;
+ jNode++;
+ }
+ *iNode = *jNode;
+ count = i;
+ jNode->point.x = PATH_NODE_EMPTY;
+ if (j == _pathNodeListIndex) {
+ break;
+ }
+ }
+ }
+ _pathNodeListIndex = count;
+}
+
+void Actor::removePathPoints() {
+ int i, j, k, l;
+ PathNode *node;
+ int start;
+ int end;
+ Point point1, point2;
+
+ if (_pathNodeListIndex < 2)
+ return;
+
+ _newPathNodeListIndex = -1;
+ addNewPathNodeListPoint(_pathNodeList[0]);
+
+ for (i = 1, node = _pathNodeList + 1; i < _pathNodeListIndex; i++, node++) {
+ addNewPathNodeListPoint(*node);
+
+ for (j = 5; j > 0; j--) {
+ start = node->link - j;
+ end = node->link + j;
+
+ if (start < 0 || end > _pathListIndex) {
+ continue;
+ }
+
+ point1 = _pathList[start];
+ point2 = _pathList[end];
+ if ((point1.x == PATH_NODE_EMPTY) || (point2.x == PATH_NODE_EMPTY)) {
+ continue;
+ }
+
+ if (scanPathLine(point1, point2)) {
+ for (l = 1; l <= _newPathNodeListIndex; l++) {
+ if (start <= _newPathNodeList[l].link) {
+ _newPathNodeListIndex = l;
+ _newPathNodeList[_newPathNodeListIndex].point = point1;
+ _newPathNodeList[_newPathNodeListIndex].link = start;
+ incrementNewPathNodeListIndex();
+ break;
+ }
+ }
+ _newPathNodeList[_newPathNodeListIndex].point = point2;
+ _newPathNodeList[_newPathNodeListIndex].link = end;
+
+ for (k = start + 1; k < end; k++) {
+ _pathList[k].x = PATH_NODE_EMPTY;
+ }
+ break;
+ }
+ }
+ }
+
+ addNewPathNodeListPoint(_pathNodeList[_pathNodeListIndex]);
+
+ for (i = 0, j = 0; i <= _newPathNodeListIndex; i++) {
+ if (_newPathNodeListIndex == i || (_newPathNodeList[i].point != _newPathNodeList[i+1].point)) {
+ _pathNodeList[j++] = _newPathNodeList[i];
+ }
+ }
+ _pathNodeListIndex = j - 1;
+}
+
+void Actor::drawPathTest() {
+#ifdef ACTOR_DEBUG
+ int i;
+ Surface *surface;
+ surface = _vm->_gfx->getBackBuffer();
+ if (_debugPoints == NULL) {
+ return;
+ }
+
+ for (i = 0; i < _debugPointsCount; i++) {
+ *((byte *)surface->pixels + (_debugPoints[i].point.y * surface->pitch) + _debugPoints[i].point.x) = _debugPoints[i].color;
+ }
+#endif
+}
+
+// Console wrappers - must be safe to run
+
+void Actor::cmdActorWalkTo(int argc, const char **argv) {
+ uint16 actorId = (uint16) atoi(argv[1]);
+ Location location;
+ Point movePoint;
+
+ movePoint.x = atoi(argv[2]);
+ movePoint.y = atoi(argv[3]);
+
+ location.fromScreenPoint(movePoint);
+
+ if (!validActorId(actorId)) {
+ _vm->_console->DebugPrintf("Actor::cmActorWalkTo Invalid actorId 0x%X.\n", actorId);
+ return;
+ }
+
+ actorWalkTo(actorId, location);
+}
+
+} // End of namespace Saga
diff --git a/engines/saga/animation.cpp b/engines/saga/animation.cpp
index 7b3bdcd665..09b2ba412d 100644
--- a/engines/saga/animation.cpp
+++ b/engines/saga/animation.cpp
@@ -78,92 +78,75 @@ void Anim::freeCutawayList(void) {
_cutawayListLength = 0;
}
-void Anim::playCutaway(int cut, bool fade) {
+int Anim::playCutaway(int cut, bool fade) {
debug(0, "playCutaway(%d, %d)", cut, fade);
+ Event event;
+ Event *q_event = NULL;
bool startImmediately = false;
+ byte *resourceData;
+ size_t resourceDataLength;
+ ResourceContext *context = _vm->_resource->getContext(GAME_RESOURCEFILE);
_cutAwayFade = fade;
- // Chained cutaway, clean up the previous cutaway
- if (_cutawayActive) {
- clearCutaway();
-
- // This is used because when AM is zapping the child's mother in Benny's chapter,
- // there is a cutaway followed by a video. The video needs to start immediately after
- // the cutaway so that it looks like the original
- startImmediately = true;
- }
-
- // WORKAROUND: The IHNM demo deals with chained cutaways in a different manner. Don't save
- // the palette of cutaway 11 (the woman looking at the marble)
- if (!(_vm->getGameId() == GID_IHNM_DEMO && cut == 11))
- _vm->_gfx->savePalette();
+ _vm->_gfx->savePalette();
+ _vm->_gfx->getCurrentPal(saved_pal);
if (fade) {
- _vm->_gfx->getCurrentPal(saved_pal);
- // TODO
- /*
- Event event;
static PalEntry cur_pal[PAL_ENTRIES];
- _vm->_gfx->getCurrentPal(cur_pal);
+ _vm->_interface->setFadeMode(kFadeOut);
+ // Fade to black out
+ _vm->_gfx->getCurrentPal(cur_pal);
event.type = kEvTImmediate;
event.code = kPalEvent;
event.op = kEventPalToBlack;
event.time = 0;
event.duration = kNormalFadeDuration;
event.data = cur_pal;
+ q_event = _vm->_events->queue(&event);
- _vm->_events->queue(&event);
- */
+ // set fade mode
+ event.type = kEvTImmediate;
+ event.code = kInterfaceEvent;
+ event.op = kEventSetFadeMode;
+ event.param = kNoFade;
+ event.time = 0;
+ event.duration = 0;
+ q_event = _vm->_events->chain(q_event, &event);
}
// Prepare cutaway
- _vm->_gfx->showCursor(false);
- _vm->_interface->setStatusText("");
- _vm->_interface->setSaveReminderState(0);
- _vm->_interface->rememberMode();
+ if (!_cutawayActive) {
+ _vm->_gfx->showCursor(false);
+ _vm->_interface->setStatusText("");
+ _vm->_interface->setSaveReminderState(0);
+ _vm->_interface->rememberMode();
+ _cutawayActive = true;
+ } else {
+ // If another cutaway is up, start the next cutaway immediately
+ startImmediately = true;
+ }
+
if (_cutAwayMode == kPanelVideo)
_vm->_interface->setMode(kPanelVideo);
else
_vm->_interface->setMode(kPanelCutaway);
- _cutawayActive = true;
-
- // Set the initial background and palette for the cutaway
- ResourceContext *context = _vm->_resource->getContext(GAME_RESOURCEFILE);
-
- byte *resourceData;
- size_t resourceDataLength;
-
- _vm->_resource->loadResource(context, _cutawayList[cut].backgroundResourceId, resourceData, resourceDataLength);
-
- byte *buf;
- size_t buflen;
- int width;
- int height;
-
- _vm->decodeBGImage(resourceData, resourceDataLength, &buf, &buflen, &width, &height);
-
- const PalEntry *palette = (const PalEntry *)_vm->getImagePal(resourceData, resourceDataLength);
-
- Surface *bgSurface = _vm->_render->getBackGroundSurface();
- const Rect rect(width, height);
-
- bgSurface->blit(rect, buf);
- _vm->_frameCount++;
-
- _vm->_gfx->setPalette(palette);
- // WORKAROUND for a bug found in the original IHNM demo. The palette of cutaway 12 is incorrect (the incorrect
- // palette can be seen in the original demo too, for a split second). Therefore, use the saved palette for this
- // cutaway
- if (_vm->getGameId() == GID_IHNM_DEMO && cut == 12)
- _vm->_gfx->restorePalette();
-
- free(buf);
- free(resourceData);
+ if (fade) {
+ // Set the initial background and palette for the cutaway
+ event.type = kEvTImmediate;
+ event.code = kCutawayEvent;
+ event.op = kEventShowCutawayBg;
+ event.time = 0;
+ event.duration = 0;
+ event.param = _cutawayList[cut].backgroundResourceId;
+ q_event = _vm->_events->chain(q_event, &event);
+ } else {
+ showCutawayBg(_cutawayList[cut].backgroundResourceId);
+ }
// Play the animation
@@ -183,7 +166,7 @@ void Anim::playCutaway(int cut, bool fade) {
if (cutawaySlot == -1) {
warning("Could not allocate cutaway animation slot");
- return;
+ return 0;
}
// Some cutaways in IHNM have animResourceId equal to 0, which means that they only have
@@ -191,48 +174,47 @@ void Anim::playCutaway(int cut, bool fade) {
// An example is the "nightfall" animation in Ben's chapter (fadein-fadeout), the animation
// for the second from the left monitor in Ellen's chapter etc
// Therefore, skip the animation bit if animResourceId is 0 and only show the background
- if (_cutawayList[cut].animResourceId == 0)
- return;
-
- _vm->_resource->loadResource(context, _cutawayList[cut].animResourceId, resourceData, resourceDataLength);
-
- load(MAX_ANIMATIONS + cutawaySlot, resourceData, resourceDataLength);
-
- free(resourceData);
+ if (_cutawayList[cut].animResourceId != 0) {
+ _vm->_resource->loadResource(context, _cutawayList[cut].animResourceId, resourceData, resourceDataLength);
+ load(MAX_ANIMATIONS + cutawaySlot, resourceData, resourceDataLength);
+ free(resourceData);
- setCycles(MAX_ANIMATIONS + cutawaySlot, _cutawayList[cut].cycles);
- setFrameTime(MAX_ANIMATIONS + cutawaySlot, 1000 / _cutawayList[cut].frameRate);
+ setCycles(MAX_ANIMATIONS + cutawaySlot, _cutawayList[cut].cycles);
+ setFrameTime(MAX_ANIMATIONS + cutawaySlot, 1000 / _cutawayList[cut].frameRate);
+ }
if (_cutAwayMode != kPanelVideo || startImmediately)
play(MAX_ANIMATIONS + cutawaySlot, 0);
else {
- Event event;
event.type = kEvTOneshot;
event.code = kAnimEvent;
event.op = kEventPlay;
event.param = MAX_ANIMATIONS + cutawaySlot;
event.time = (40 / 3) * 1000 / _cutawayList[cut].frameRate;
- _vm->_events->queue(&event);
+ if (fade)
+ q_event = _vm->_events->chain(q_event, &event);
+ else
+ _vm->_events->queue(&event);
}
+
+ return MAX_ANIMATIONS + cutawaySlot;
}
void Anim::endCutaway(void) {
- // I believe this is called by scripts after running one cutaway. At
- // this time, nothing needs to be done here.
+ // This is called by scripts after a cutaway is finished. At this time,
+ // nothing needs to be done here.
debug(0, "endCutaway()");
}
void Anim::returnFromCutaway(void) {
- // I believe this is called by scripts after running a cutaway to
- // ensure that we return to the scene as if nothing had happened. It's
- // not called by the IHNM intro, presumably because there is no old
- // scene to return to.
+ // This is called by scripts after a cutaway is finished, to return back
+ // to the scene that the cutaway was called from. It's not called by the
+ // IHNM intro, as there is no old scene to return to.
debug(0, "returnFromCutaway()");
-
if (_cutawayActive) {
Event event;
Event *q_event = NULL;
@@ -240,16 +222,26 @@ void Anim::returnFromCutaway(void) {
if (_cutAwayFade) {
static PalEntry cur_pal[PAL_ENTRIES];
- _vm->_gfx->getCurrentPal(cur_pal);
+ _vm->_interface->setFadeMode(kFadeOut);
+ // Fade to black out
+ _vm->_gfx->getCurrentPal(cur_pal);
event.type = kEvTImmediate;
event.code = kPalEvent;
event.op = kEventPalToBlack;
event.time = 0;
event.duration = kNormalFadeDuration;
event.data = cur_pal;
-
q_event = _vm->_events->queue(&event);
+
+ // set fade mode
+ event.type = kEvTImmediate;
+ event.code = kInterfaceEvent;
+ event.op = kEventSetFadeMode;
+ event.param = kNoFade;
+ event.time = 0;
+ event.duration = 0;
+ q_event = _vm->_events->chain(q_event, &event);
}
// Clear the cutaway. Note that this sets _cutawayActive to false
@@ -272,7 +264,6 @@ void Anim::returnFromCutaway(void) {
event.op = kEventResumeAll;
event.time = 0;
event.duration = 0;
-
q_event = _vm->_events->chain(q_event, &event); // chain with the other events
// Draw the scene
@@ -281,7 +272,6 @@ void Anim::returnFromCutaway(void) {
event.op = kEventDraw;
event.time = 0;
event.duration = 0;
-
q_event = _vm->_events->chain(q_event, &event); // chain with the other events
// Handle fade up, if we previously faded down
@@ -292,22 +282,22 @@ void Anim::returnFromCutaway(void) {
event.time = 0;
event.duration = kNormalFadeDuration;
event.data = saved_pal;
-
q_event = _vm->_events->chain(q_event, &event);
-
}
event.type = kEvTOneshot;
event.code = kScriptEvent;
event.op = kEventThreadWake;
event.param = kWaitTypeWakeUp;
-
q_event = _vm->_events->chain(q_event, &event);
}
}
void Anim::clearCutaway(void) {
+ PalEntry *pal;
+
debug(1, "clearCutaway()");
+
if (_cutawayActive) {
_cutawayActive = false;
@@ -317,18 +307,56 @@ void Anim::clearCutaway(void) {
}
_vm->_interface->restoreMode();
-
- if (_vm->getGameId() != GID_IHNM_DEMO) {
- if (_vm->_scene->currentSceneNumber() >= 144 && _vm->_scene->currentSceneNumber() <= 149) {
- // Don't show the mouse cursor in the non-interactive part of the IHNM demo
- } else {
- _vm->_gfx->showCursor(true);
- }
- } else {
+ _vm->_gfx->showCursor(true);
+
+ if (_vm->getGameId() == GID_IHNM_DEMO) {
// Enable the save reminder state after each cutaway for the IHNM demo
_vm->_interface->setSaveReminderState(true);
}
+
+ // Set the scene's palette
+ _vm->_scene->getBGPal(pal);
+ _vm->_gfx->setPalette(pal);
+ }
+}
+
+void Anim::showCutawayBg(int bg) {
+ ResourceContext *context = _vm->_resource->getContext(GAME_RESOURCEFILE);
+
+ byte *resourceData;
+ size_t resourceDataLength;
+ byte *buf;
+ size_t buflen;
+ int width;
+ int height;
+ Event event;
+ static PalEntry pal[PAL_ENTRIES];
+
+ _vm->_resource->loadResource(context, bg, resourceData, resourceDataLength);
+ _vm->decodeBGImage(resourceData, resourceDataLength, &buf, &buflen, &width, &height);
+
+ const byte *palPointer = _vm->getImagePal(resourceData, resourceDataLength);
+ memcpy(pal, palPointer, sizeof(pal));
+ Surface *bgSurface = _vm->_render->getBackGroundSurface();
+ const Rect rect(width, height);
+ bgSurface->blit(rect, buf);
+ _vm->_frameCount++;
+
+ if (_cutAwayFade) {
+ // Handle fade up, if we previously faded down
+ event.type = kEvTImmediate;
+ event.code = kPalEvent;
+ event.op = kEventBlackToPal;
+ event.time = 0;
+ event.duration = kNormalFadeDuration;
+ event.data = pal;
+ _vm->_events->queue(&event);
+ } else {
+ _vm->_gfx->setPalette(pal);
}
+
+ free(buf);
+ free(resourceData);
}
void Anim::startVideo(int vid, bool fade) {
@@ -380,6 +408,12 @@ void Anim::load(uint16 animId, const byte *animResourceData, size_t animResource
anim->start += temp;
// Cache frame offsets
+
+ // WORKAROUND: Cutaway with background resource ID 37 (loaded as cutaway #4) is ending credits.
+ // For some reason it has wrong number of frames specified in its header. So we calculate it here:
+ if (animId > MAX_ANIMATIONS && _cutawayListLength > 4 && _cutawayList[4].backgroundResourceId == 37 && anim->maxFrame == 143)
+ anim->maxFrame = fillFrameOffsets(anim, false);
+
anim->frameOffsets = (size_t *)malloc((anim->maxFrame + 1) * sizeof(*anim->frameOffsets));
if (anim->frameOffsets == NULL) {
memoryError("Anim::load");
@@ -388,7 +422,9 @@ void Anim::load(uint16 animId, const byte *animResourceData, size_t animResource
fillFrameOffsets(anim);
// Set animation data
- anim->currentFrame = 0;
+ // HACK: We set currentFrame to -1, as the first frame of the animation is never drawn otherwise
+ // (check Anim::play)
+ anim->currentFrame = -1;
anim->completed = 0;
anim->cycles = anim->maxFrame;
@@ -422,6 +458,13 @@ void Anim::setCycles(uint16 animId, int cycles) {
anim->cycles = cycles;
}
+int Anim::getCycles(uint16 animId) {
+ if (animId >= MAX_ANIMATIONS && _cutawayAnimations[animId - MAX_ANIMATIONS] == NULL)
+ return 0;
+
+ return getAnimation(animId)->cycles;
+}
+
void Anim::play(uint16 animId, int vectorTime, bool playing) {
Event event;
Surface *backGroundSurface;
@@ -440,6 +483,23 @@ void Anim::play(uint16 animId, int vectorTime, bool playing) {
if (animId < MAX_ANIMATIONS && _cutawayActive)
return;
+ if (animId >= MAX_ANIMATIONS && _cutawayAnimations[animId - MAX_ANIMATIONS] == NULL) {
+ // In IHNM, cutaways without an animation bit are not rendered, but the framecount
+ // needs to be updated
+ _vm->_frameCount++;
+
+ event.type = kEvTOneshot;
+ event.code = kAnimEvent;
+ event.op = kEventFrame;
+ event.param = animId;
+ event.time = 10;
+ _vm->_events->queue(&event);
+
+ // Nothing to render here (apart from the background, which is already rendered),
+ // so return
+ return;
+ }
+
anim = getAnimation(animId);
backGroundSurface = _vm->_render->getBackGroundSurface();
@@ -453,19 +513,28 @@ void Anim::play(uint16 animId, int vectorTime, bool playing) {
return;
}
+ // HACK: The first frame of the animation is never shown when entering a scene
+ // For now, we initialize currentFrame to be -1 instead of 0 and we draw the
+ // first frame of the animation on the next iteration of Anim::play
+ // FIXME: find out why this occurs and remove this hack. Note that when this
+ // hack is removed, currentFrame should be initialized to 0 again in Anim::load
+ if (anim->currentFrame < 0) {
+ anim->currentFrame = 0;
+ event.type = kEvTOneshot;
+ event.code = kAnimEvent;
+ event.op = kEventFrame;
+ event.param = animId;
+ event.time = 0;
+ _vm->_events->queue(&event);
+
+ return;
+ }
+
if (anim->completed < anim->cycles) {
- frame = anim->currentFrame;
+ if (anim->currentFrame < 0)
+ anim->currentFrame = 0;
- // WORKAROUND for a buggy animation in IHNM. Animation 0 in scene 67 (the mob of angry prisoners) should
- // start from frame 0, not frame 1. Frame 0 is the background of the animation (the mob of prisoners), whereas
- // the rest of the frames are their animated arms. Therefore, in order for the prisoners to appear correctly,
- // frame 0 should be displayed as the first frame, but anim->currentframe is set to 1, which means that the
- // prisoners will never be shown. In the original, the prisoners (first frame in the animation) are shown a
- // bit after the animation is started (which is wrong again, but not that apparent), whereas in ScummVM the
- // first frame is never shown. Therefore, make sure that for this animation, frame 0 is shown first
- if (_vm->getGameType() == GType_IHNM && _vm->_scene->currentChapterNumber() == 4 &&
- _vm->_scene->currentSceneNumber() == 67 && animId == 0 && anim->completed == 1)
- frame = 0;
+ frame = anim->currentFrame;
// FIXME: if start > 0, then this works incorrectly
decodeFrame(anim, anim->frameOffsets[frame], displayBuffer, _vm->getDisplayWidth() * _vm->getDisplayHeight());
@@ -488,6 +557,9 @@ void Anim::play(uint16 animId, int vectorTime, bool playing) {
_vm->_frameCount += 100; // make sure the waiting thread stops waiting
// Animation done playing
anim->state = ANIM_PAUSE;
+ anim->currentFrame = 0;
+ anim->completed = 0;
+
if (anim->linkId == -1) {
if (anim->flags & ANIM_FLAG_ENDSCENE) {
// This animation ends the scene
@@ -498,9 +570,6 @@ void Anim::play(uint16 animId, int vectorTime, bool playing) {
_vm->_events->queue(&event);
}
return;
- } else {
- anim->currentFrame = 0;
- anim->completed = 0;
}
}
@@ -521,7 +590,6 @@ void Anim::play(uint16 animId, int vectorTime, bool playing) {
event.op = kEventFrame;
event.param = animId;
event.time = frameTime;
-
_vm->_events->queue(&event);
}
@@ -592,6 +660,22 @@ void Anim::setFrameTime(uint16 animId, int time) {
anim->frameTime = time;
}
+int Anim::getFrameTime(uint16 animId) {
+ AnimationData *anim;
+
+ anim = getAnimation(animId);
+
+ return anim->frameTime;
+}
+
+bool Anim::isPlaying(uint16 animId) {
+ AnimationData *anim;
+
+ anim = getAnimation(animId);
+
+ return (anim->state == ANIM_PLAYING);
+}
+
int16 Anim::getCurrentFrame(uint16 animId) {
AnimationData *anim;
@@ -631,11 +715,12 @@ void Anim::decodeFrame(AnimationData *anim, size_t frameOffset, byte *buf, size_
MemoryReadStream readS(anim->resourceData + frameOffset, anim->resourceLength - frameOffset);
-
+// FIXME: This is thrown when the first video of the IHNM end sequence is shown (the "turn off screen"
+// video), however the video is played correctly and the rest of the end sequence continues normally
#if 1
#define VALIDATE_WRITE_POINTER \
if ((writePointer < buf) || (writePointer >= (buf + screenWidth * screenHeight))) { \
- error("VALIDATE_WRITE_POINTER: writePointer=%p buf=%p", (void *)writePointer, (void *)buf); \
+ warning("VALIDATE_WRITE_POINTER: writePointer=%p buf=%p", (void *)writePointer, (void *)buf); \
}
#else
#define VALIDATE_WRITE_POINTER
@@ -758,8 +843,8 @@ void Anim::decodeFrame(AnimationData *anim, size_t frameOffset, byte *buf, size_
} while (1);
}
-void Anim::fillFrameOffsets(AnimationData *anim) {
- uint16 currentFrame;
+int Anim::fillFrameOffsets(AnimationData *anim, bool reallyFill) {
+ uint16 currentFrame = 0;
byte markByte;
uint16 control;
uint16 runcount;
@@ -772,12 +857,18 @@ void Anim::fillFrameOffsets(AnimationData *anim) {
readS._bigEndian = !_vm->isBigEndian(); // RLE has inversion BE<>LE
- for (currentFrame = 0; currentFrame <= anim->maxFrame; currentFrame++) {
- anim->frameOffsets[currentFrame] = readS.pos();
+ while (!readS.eos()) {
+ if (reallyFill) {
+ anim->frameOffsets[currentFrame] = readS.pos();
+
+ if (currentFrame == anim->maxFrame)
+ break;
+ }
+ currentFrame++;
// For some strange reason, the animation header is in little
// endian format, but the actual RLE encoded frame data,
- // including the frame header, is in big endian format. */
+ // including the frame header, is in big endian format
do {
markByte = readS.readByte();
// debug(7, "_pos=%x currentFrame=%i markByte=%x", readS.pos(), currentFrame, markByte);
@@ -816,8 +907,7 @@ void Anim::fillFrameOffsets(AnimationData *anim) {
case SAGA_FRAME_LONG_UNCOMPRESSED_RUN: // (16) 0001 0000
// Long Uncompressed Run
runcount = readS.readSint16BE();
- for (i = 0; i < runcount; i++)
- readS.readByte();
+ readS.seek(runcount, SEEK_CUR);
continue;
break;
case SAGA_FRAME_NOOP: // Does nothing
@@ -855,6 +945,8 @@ void Anim::fillFrameOffsets(AnimationData *anim) {
}
} while (markByte != SAGA_FRAME_END);
}
+
+ return currentFrame;
}
void Anim::animInfo() {
diff --git a/engines/saga/animation.h b/engines/saga/animation.h
index f8cf90425f..4306d8e00d 100644
--- a/engines/saga/animation.h
+++ b/engines/saga/animation.h
@@ -115,10 +115,11 @@ public:
void loadCutawayList(const byte *resourcePointer, size_t resourceLength);
void freeCutawayList(void);
- void playCutaway(int cut, bool fade);
+ int playCutaway(int cut, bool fade);
void endCutaway(void);
void returnFromCutaway(void);
void clearCutaway(void);
+ void showCutawayBg(int bg);
void startVideo(int vid, bool fade);
void endVideo(void);
@@ -140,12 +141,10 @@ public:
void resume(uint16 animId, int cycles);
void resumeAll();
int16 getCurrentFrame(uint16 animId);
- bool hasCutaway(void) {
- return _cutawayActive;
- }
- void setCutAwayMode(int mode) {
- _cutAwayMode = mode;
- }
+ int getFrameTime(uint16 animId);
+ int getCycles(uint16 animId);
+ bool isPlaying(uint16 animId);
+
bool hasAnimation(uint16 animId) {
if (animId >= MAX_ANIMATIONS) {
if (animId < MAX_ANIMATIONS + ARRAYSIZE(_cutawayAnimations))
@@ -154,10 +153,16 @@ public:
}
return (_animations[animId] != NULL);
}
- int cutawayResourceID(int cutaway) { return _cutawayList[cutaway].animResourceId; }
+
+ bool hasCutaway(void) { return _cutawayActive; }
+ void setCutAwayMode(int mode) { _cutAwayMode = mode; }
+ int cutawayListLength() { return _cutawayListLength; }
+ int cutawayBgResourceID(int cutaway) { return _cutawayList[cutaway].backgroundResourceId; }
+ int cutawayAnimResourceID(int cutaway) { return _cutawayList[cutaway].animResourceId; }
+
private:
void decodeFrame(AnimationData *anim, size_t frameOffset, byte *buf, size_t bufLength);
- void fillFrameOffsets(AnimationData *anim);
+ int fillFrameOffsets(AnimationData *anim, bool reallyFill = true);
void validateAnimationId(uint16 animId) {
if (animId >= MAX_ANIMATIONS) {
@@ -168,7 +173,7 @@ private:
}
}
if (_animations[animId] == NULL) {
- error("validateAnimationId: animId=%i unassigned", animId);
+ error("validateAnimationId: animId=%i unassigned.", animId);
}
}
diff --git a/engines/saga/console.cpp b/engines/saga/console.cpp
index 421245ab30..0a6b733e00 100644
--- a/engines/saga/console.cpp
+++ b/engines/saga/console.cpp
@@ -75,6 +75,14 @@ Console::Console(SagaEngine *vm) : GUI::Debugger() {
// Panel commands
DCmd_Register("current_panel_mode", WRAP_METHOD(Console, cmdCurrentPanelMode));
DCmd_Register("set_panel_mode", WRAP_METHOD(Console, cmdSetPanelMode));
+
+ // Font commands
+ DCmd_Register("set_font_mapping", WRAP_METHOD(Console, cmdSetFontMapping));
+
+ // Global flags commands
+ DCmd_Register("global_flags_info", WRAP_METHOD(Console, cmdGlobalFlagsInfo));
+ DCmd_Register("set_global_flag", WRAP_METHOD(Console, cmdSetGlobalFlag));
+ DCmd_Register("clear_global_flag", WRAP_METHOD(Console, cmdClearGlobalFlag));
}
Console::~Console() {
@@ -158,4 +166,92 @@ bool Console::cmdSetPanelMode(int argc, const char **argv) {
return true;
}
+bool Console::cmdSetFontMapping(int argc, const char **argv) {
+ if (argc != 2) {
+ DebugPrintf("Sets font mapping\nUsage: %s <Font mapping flag>\n", argv[0]);
+ DebugPrintf("Mapping flags:\n0 - default game behavior\n1 - force font mapping\n2 - ignore font mapping\n");
+ } else {
+ _vm->_font->setFontMapping(atoi(argv[1]));
+ }
+ return true;
+}
+
+bool Console::cmdGlobalFlagsInfo(int argc, const char **argv) {
+ DebugPrintf("Global flags status for IHNM:\n");
+
+ // Global flags in IHNM:
+ // 00: Unknown
+ // 01: Unknown
+ // 02: Unknown
+ // 03: Unknown
+ // 04: Unknown
+ // 05: Unknown
+ // 06: Unknown
+ // 07: Unknown
+ // 08: Unknown
+ // 09: Unknown
+ // 10: Unknown
+ // 11: Unknown
+ // 12: Unknown
+ // 13: Unknown
+ // 14: Unknown
+ // 15: Unknown
+ // 16: Used in the final chapter. If it's 0 when a character dies, the "bad" ending for that character is shown
+ // 17: Unknown
+ // 18: Unknown
+ // 19: Unknown, used in the final chapter
+ // 20: Unknown
+ // 21: Unknown
+ // 22: Unknown
+ // 23: Unknown
+ // 24: Unknown
+ // 25: Unknown
+ // 26: Unknown
+ // 27: Unknown
+ // 28: Unknown
+ // 29: Unknown
+ // 30: Unknown
+ // 31: Unknown
+
+ int i = 0, k = 0, flagStatus = 0;
+
+ for (i = 0; i < 32; i += 8) {
+ for (k = i; k < i + 8; k ++) {
+ flagStatus = _vm->_globalFlags & (1 << k) ? 1 : 0;
+ _vm->_console->DebugPrintf("%02d: %u |", k, flagStatus);
+ }
+ _vm->_console->DebugPrintf("\n");
+ }
+
+ return true;
+}
+
+bool Console::cmdSetGlobalFlag(int argc, const char **argv) {
+ if (argc != 2) {
+ DebugPrintf("Usage: %s <Global flag number>\nValid flag numbers are 0 - 31\n", argv[0]);
+ } else {
+ int flagNumber = atoi(argv[1]);
+ if (flagNumber >= 0 && flagNumber <= 31) {
+ _vm->_globalFlags |= (1 << flagNumber);
+ } else {
+ DebugPrintf("Valid flag numbers are 0 - 31\n");
+ }
+ }
+ return true;
+}
+
+bool Console::cmdClearGlobalFlag(int argc, const char **argv) {
+ if (argc != 2) {
+ DebugPrintf("Usage: %s <Global flag number>\nValid flag numbers are 0 - 31\n", argv[0]);
+ } else {
+ int flagNumber = atoi(argv[1]);
+ if (flagNumber >= 0 && flagNumber <= 31) {
+ _vm->_globalFlags &= ~(1 << flagNumber);
+ } else {
+ DebugPrintf("Valid flag numbers are 0 - 31\n");
+ }
+ }
+ return true;
+}
+
} // End of namespace Saga
diff --git a/engines/saga/console.h b/engines/saga/console.h
index 3db9833f22..7936d3a959 100644
--- a/engines/saga/console.h
+++ b/engines/saga/console.h
@@ -55,6 +55,12 @@ private:
bool cmdCurrentPanelMode(int argc, const char **argv);
bool cmdSetPanelMode(int argc, const char **argv);
+ bool cmdSetFontMapping(int argc, const char **argv);
+
+ bool cmdGlobalFlagsInfo(int argc, const char **argv);
+ bool cmdSetGlobalFlag(int argc, const char **argv);
+ bool cmdClearGlobalFlag(int argc, const char **argv);
+
private:
SagaEngine *_vm;
};
diff --git a/engines/saga/detection.cpp b/engines/saga/detection.cpp
index c8918998f1..29ca0e8bbe 100644
--- a/engines/saga/detection.cpp
+++ b/engines/saga/detection.cpp
@@ -18,8 +18,8 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
- * $URL:https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/branches/gsoc2007-fsnode/engines/saga/detection.cpp $
- * $Id:detection.cpp 26949 2007-05-26 20:23:24Z david_corrales $
+ * $URL$
+ * $Id$
*
*/
@@ -49,7 +49,6 @@ struct SAGAGameDescription {
const GameFontDescription *fontDescriptions;
const GameSoundInfo *voiceInfo;
const GameSoundInfo *sfxInfo;
- const GameSoundInfo *musicInfo;
int patchesCount;
const GamePatchDescription *patchDescriptions;
};
@@ -59,7 +58,18 @@ const bool SagaEngine::isMacResources() const { return (getPlatform() == Common:
const GameResourceDescription *SagaEngine::getResourceDescription() { return _gameDescription->resourceDescription; }
const GameSoundInfo *SagaEngine::getVoiceInfo() const { return _gameDescription->voiceInfo; }
const GameSoundInfo *SagaEngine::getSfxInfo() const { return _gameDescription->sfxInfo; }
-const GameSoundInfo *SagaEngine::getMusicInfo() const { return _gameDescription->musicInfo; }
+const GameSoundInfo *SagaEngine::getMusicInfo() const {
+ static GameSoundInfo musicInfo;
+ musicInfo.resourceType = kSoundPCM;
+ musicInfo.frequency = 11025;
+ musicInfo.sampleBits = 16;
+ // The digital music in the ITE Mac demo version is not stereo
+ musicInfo.stereo = _gameDescription->gameType == GID_ITE_MACDEMO2 ? false : true;
+ musicInfo.isBigEndian = false;
+ musicInfo.isSigned = true;
+
+ return &musicInfo;
+}
const GameFontDescription *SagaEngine::getFontDescription(int index) {
assert(index < _gameDescription->fontsCount);
diff --git a/engines/saga/detection_tables.h b/engines/saga/detection_tables.h
index 0d57adb87d..5bb408e947 100644
--- a/engines/saga/detection_tables.h
+++ b/engines/saga/detection_tables.h
@@ -18,8 +18,8 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
- * $URL:https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/branches/gsoc2007-fsnode/engines/saga/detection_tables.h $
- * $Id:detection_tables.h 26949 2007-05-26 20:23:24Z david_corrales $
+ * $URL$
+ * $Id$
*
*/
@@ -34,6 +34,7 @@ static const GameResourceDescription ITE_Resources = {
RID_ITE_CONVERSE_PANEL,
RID_ITE_OPTION_PANEL,
0, // Warning panel (IHNM only)
+ 0, // Warning panel sprites (IHNM only)
RID_ITE_MAIN_SPRITES,
RID_ITE_MAIN_PANEL_SPRITES,
0, // Option panel sprites (IHNM only)
@@ -50,6 +51,7 @@ static const GameResourceDescription ITEDemo_Resources = {
RID_ITEDEMO_CONVERSE_PANEL,
RID_ITEDEMO_OPTION_PANEL,
0, // Warning panel (IHNM only)
+ 0, // Warning panel sprites (IHNM only)
RID_ITEDEMO_MAIN_SPRITES,
RID_ITEDEMO_MAIN_PANEL_SPRITES,
0, // Option panel sprites (IHNM only)
@@ -59,188 +61,6 @@ static const GameResourceDescription ITEDemo_Resources = {
RID_ITEDEMO_ACTOR_NAMES
};
-// Inherit the Earth - DOS Demo version
-static const GameFontDescription ITEDEMO_GameFonts[] = {
- {0},
- {1}
-};
-
-// Inherit the Earth - Wyrmkeep Win32 Demo version
-
-static const GameFontDescription ITEWINDEMO_GameFonts[] = {
- {2},
- {0}
-};
-
-static const GameSoundInfo ITEWINDEMO1_GameSound = {
- kSoundPCM,
- 22050,
- 8,
- false,
- false,
- false
-};
-
-static const GameSoundInfo ITEWINDEMO2_GameVoice = {
- kSoundVOX,
- 22050,
- 16,
- false,
- false,
- true
-};
-
-static const GameSoundInfo ITEWINDEMO2_GameSound = {
- kSoundPCM,
- 22050,
- 16,
- false,
- false,
- true
-};
-
-// Inherit the Earth - Wyrmkeep Mac Demo version
-static const GameSoundInfo ITEMACDEMO_GameVoice = {
- kSoundVOX,
- 22050,
- 16,
- false,
- false,
- true
-};
-
-static const GameSoundInfo ITEMACDEMO_GameSound = {
- kSoundPCM,
- 22050,
- 16,
- false,
- true,
- true
-};
-
-static const GameSoundInfo ITEMACDEMO_GameMusic = {
- kSoundPCM,
- 11025,
- 16,
- false,
- false,
- true
-};
-
-static const GameSoundInfo ITEMACCD_G_GameSound = {
- kSoundMacPCM,
- 22050,
- 8,
- false,
- false,
- false
-};
-
-// Inherit the Earth - Mac Wyrmkeep version
-static const GameSoundInfo ITEMACCD_GameSound = {
- kSoundPCM,
- 22050,
- 16,
- false,
- true,
- true
-};
-
-static const GameSoundInfo ITEMACCD_GameMusic = {
- kSoundPCM,
- 11025,
- 16,
- true,
- false,
- true
-};
-
-// Inherit the Earth - Diskette version
-static const GameFontDescription ITEDISK_GameFonts[] = {
- {2},
- {0},
- {1}
-};
-
-static const GameSoundInfo ITEDISK_GameSound = {
- kSoundVOC,
- -1,
- -1,
- false,
- false,
- true
-};
-
-static const GameFontDescription ITECD_GameFonts[] = {
- {2},
- {0},
- {1}
-};
-
-static const GameSoundInfo ITECD_GameSound = {
- kSoundPCM,
- 22050,
- 16,
- false,
- false,
- true
-};
-
-// Patch files. Files not found will be ignored
-static const GamePatchDescription ITEPatch_Files[] = {
- { "cave.mid", GAME_RESOURCEFILE, 9, NULL},
- { "intro.mid", GAME_RESOURCEFILE, 10, NULL},
- { "fvillage.mid", GAME_RESOURCEFILE, 11, NULL},
- { "elkhall.mid", GAME_RESOURCEFILE, 12, NULL},
- { "mouse.mid", GAME_RESOURCEFILE, 13, NULL},
- { "darkclaw.mid", GAME_RESOURCEFILE, 14, NULL},
- { "birdchrp.mid", GAME_RESOURCEFILE, 15, NULL},
- { "orbtempl.mid", GAME_RESOURCEFILE, 16, NULL},
- { "spooky.mid", GAME_RESOURCEFILE, 17, NULL},
- { "catfest.mid", GAME_RESOURCEFILE, 18, NULL},
- { "elkfanfare.mid", GAME_RESOURCEFILE, 19, NULL},
- { "bcexpl.mid", GAME_RESOURCEFILE, 20, NULL},
- { "boargtnt.mid", GAME_RESOURCEFILE, 21, NULL},
- { "boarking.mid", GAME_RESOURCEFILE, 22, NULL},
- { "explorea.mid", GAME_RESOURCEFILE, 23, NULL},
- { "exploreb.mid", GAME_RESOURCEFILE, 24, NULL},
- { "explorec.mid", GAME_RESOURCEFILE, 25, NULL},
- { "sunstatm.mid", GAME_RESOURCEFILE, 26, NULL},
- { "nitstrlm.mid", GAME_RESOURCEFILE, 27, NULL},
- { "humruinm.mid", GAME_RESOURCEFILE, 28, NULL},
- { "damexplm.mid", GAME_RESOURCEFILE, 29, NULL},
- { "tychom.mid", GAME_RESOURCEFILE, 30, NULL},
- { "kitten.mid", GAME_RESOURCEFILE, 31, NULL},
- { "sweet.mid", GAME_RESOURCEFILE, 32, NULL},
- { "brutalmt.mid", GAME_RESOURCEFILE, 33, NULL},
- { "shiala.mid", GAME_RESOURCEFILE, 34, NULL},
-
- { "wyrm.pak", GAME_RESOURCEFILE, 1529, NULL},
- { "wyrm1.dlt", GAME_RESOURCEFILE, 1530, NULL},
- { "wyrm2.dlt", GAME_RESOURCEFILE, 1531, NULL},
- { "wyrm3.dlt", GAME_RESOURCEFILE, 1532, NULL},
- { "wyrm4.dlt", GAME_RESOURCEFILE, 1533, NULL},
- { "credit3n.dlt", GAME_RESOURCEFILE, 1796, NULL},
- { "credit3m.dlt", GAME_RESOURCEFILE, 1796, NULL}, // Macintosh
- { "credit4n.dlt", GAME_RESOURCEFILE, 1797, NULL},
- { "credit4m.dlt", GAME_RESOURCEFILE, 1797, NULL}, // Macintosh
- { "p2_a.voc", GAME_VOICEFILE, 4, NULL},
- { "p2_a.iaf", GAME_VOICEFILE, 4, &ITECD_GameSound}
-};
-
-static const GamePatchDescription ITEMacPatch_Files[] = {
- { "wyrm.pak", GAME_RESOURCEFILE, 1529, NULL},
- { "wyrm1.dlt", GAME_RESOURCEFILE, 1530, NULL},
- { "wyrm2.dlt", GAME_RESOURCEFILE, 1531, NULL},
- { "wyrm3.dlt", GAME_RESOURCEFILE, 1532, NULL},
- { "wyrm4.dlt", GAME_RESOURCEFILE, 1533, NULL},
- { "credit3m.dlt", GAME_RESOURCEFILE, 1796, NULL},
- { "credit4m.dlt", GAME_RESOURCEFILE, 1797, NULL},
- { "p2_a.iaf", GAME_VOICEFILE, 4, &ITEMACCD_GameSound}
-};
-
-// IHNM section
-
static const GameResourceDescription IHNM_Resources = {
RID_IHNM_SCENE_LUT, // Scene lookup table RN
RID_IHNM_SCRIPT_LUT, // Script lookup table RN
@@ -248,6 +68,7 @@ static const GameResourceDescription IHNM_Resources = {
RID_IHNM_CONVERSE_PANEL,
RID_IHNM_OPTION_PANEL,
RID_IHNM_WARNING_PANEL,
+ RID_IHNM_WARNING_PANEL_SPRITES,
RID_IHNM_MAIN_SPRITES,
RID_IHNM_MAIN_PANEL_SPRITES,
RID_IHNM_OPTION_PANEL_SPRITES,
@@ -264,6 +85,7 @@ static const GameResourceDescription IHNMDEMO_Resources = {
RID_IHNMDEMO_CONVERSE_PANEL,
RID_IHNMDEMO_OPTION_PANEL,
RID_IHNMDEMO_WARNING_PANEL,
+ RID_IHNMDEMO_WARNING_PANEL_SPRITES,
RID_IHNMDEMO_MAIN_SPRITES,
RID_IHNMDEMO_MAIN_PANEL_SPRITES,
RID_IHNMDEMO_OPTION_PANEL_SPRITES,
@@ -273,29 +95,73 @@ static const GameResourceDescription IHNMDEMO_Resources = {
0 // Actors strings (ITE only)
};
-static const GameFontDescription IHNMDEMO_GameFonts[] = {
- {2},
- {3},
- {4}
-};
+static const GameFontDescription ITEDEMO_GameFonts[] = { {0}, {1} };
+static const GameFontDescription ITEWINDEMO_GameFonts[] = { {2}, {0} };
+static const GameFontDescription ITE_GameFonts[] = { {2}, {0}, {1} };
+static const GameFontDescription IHNMDEMO_GameFonts[] = { {2}, {3}, {4} };
+// Font 6 is kIHNMFont8, font 8 is kIHNMMainFont
+static const GameFontDescription IHNMCD_GameFonts[] = { {2}, {3}, {4}, {5}, {6}, {7}, {8} };
+
+// frequency, sampleBits, stereo, isBigEndian, isSigned
+static const GameSoundInfo ITEPC_GameSound = { kSoundPCM, 22050, 16, false, false, true };
+static const GameSoundInfo ITEMAC_GameSound = { kSoundPCM, 22050, 16, false, true, true };
+static const GameSoundInfo ITEWINDEMO1_GameSound = { kSoundPCM, 22050, 8, false, false, false };
+static const GameSoundInfo ITEMACCD_G_GameSound = { kSoundMacPCM, 22050, 8, false, false, false };
+static const GameSoundInfo ITEDISK_GameSound = { kSoundVOC, -1, -1, false, false, true };
+static const GameSoundInfo ITEDEMO_GameVoice = { kSoundVOX, 22050, 16, false, false, true };
+static const GameSoundInfo IHNM_GameSound = { kSoundWAV, -1, -1, false, false, true };
-static const GameFontDescription IHNMCD_GameFonts[] = {
- {2},
- {3},
- {4},
- {5},
- {6}, // kIHNMFont8
- {7},
- {8} // kIHNMMainFont
+// Patch files. Files not found will be ignored
+static const GamePatchDescription ITEPatch_Files[] = {
+ { "cave.mid", GAME_RESOURCEFILE, 9, NULL},
+ { "intro.mid", GAME_RESOURCEFILE, 10, NULL},
+ { "fvillage.mid", GAME_RESOURCEFILE, 11, NULL},
+ { "elkhall.mid", GAME_RESOURCEFILE, 12, NULL},
+ { "mouse.mid", GAME_RESOURCEFILE, 13, NULL},
+ { "darkclaw.mid", GAME_RESOURCEFILE, 14, NULL},
+ { "birdchrp.mid", GAME_RESOURCEFILE, 15, NULL},
+ { "orbtempl.mid", GAME_RESOURCEFILE, 16, NULL},
+ { "spooky.mid", GAME_RESOURCEFILE, 17, NULL},
+ { "catfest.mid", GAME_RESOURCEFILE, 18, NULL},
+ { "elkfanfare.mid", GAME_RESOURCEFILE, 19, NULL},
+ { "bcexpl.mid", GAME_RESOURCEFILE, 20, NULL},
+ { "boargtnt.mid", GAME_RESOURCEFILE, 21, NULL},
+ { "boarking.mid", GAME_RESOURCEFILE, 22, NULL},
+ { "explorea.mid", GAME_RESOURCEFILE, 23, NULL},
+ { "exploreb.mid", GAME_RESOURCEFILE, 24, NULL},
+ { "explorec.mid", GAME_RESOURCEFILE, 25, NULL},
+ { "sunstatm.mid", GAME_RESOURCEFILE, 26, NULL},
+ { "nitstrlm.mid", GAME_RESOURCEFILE, 27, NULL},
+ { "humruinm.mid", GAME_RESOURCEFILE, 28, NULL},
+ { "damexplm.mid", GAME_RESOURCEFILE, 29, NULL},
+ { "tychom.mid", GAME_RESOURCEFILE, 30, NULL},
+ { "kitten.mid", GAME_RESOURCEFILE, 31, NULL},
+ { "sweet.mid", GAME_RESOURCEFILE, 32, NULL},
+ { "brutalmt.mid", GAME_RESOURCEFILE, 33, NULL},
+ { "shiala.mid", GAME_RESOURCEFILE, 34, NULL},
+
+ { "wyrm.pak", GAME_RESOURCEFILE, 1529, NULL},
+ { "wyrm1.dlt", GAME_RESOURCEFILE, 1530, NULL},
+ { "wyrm2.dlt", GAME_RESOURCEFILE, 1531, NULL},
+ { "wyrm3.dlt", GAME_RESOURCEFILE, 1532, NULL},
+ { "wyrm4.dlt", GAME_RESOURCEFILE, 1533, NULL},
+ { "credit3n.dlt", GAME_RESOURCEFILE, 1796, NULL}, // PC
+ { "credit3m.dlt", GAME_RESOURCEFILE, 1796, NULL}, // Macintosh
+ { "credit4n.dlt", GAME_RESOURCEFILE, 1797, NULL}, // PC
+ { "credit4m.dlt", GAME_RESOURCEFILE, 1797, NULL}, // Macintosh
+ { "p2_a.voc", GAME_VOICEFILE, 4, NULL},
+ { "p2_a.iaf", GAME_VOICEFILE, 4, &ITEPC_GameSound}
};
-static const GameSoundInfo IHNM_GameSound = {
- kSoundWAV,
- -1,
- -1,
- false,
- false,
- true
+static const GamePatchDescription ITEMacPatch_Files[] = {
+ { "wyrm.pak", GAME_RESOURCEFILE, 1529, NULL},
+ { "wyrm1.dlt", GAME_RESOURCEFILE, 1530, NULL},
+ { "wyrm2.dlt", GAME_RESOURCEFILE, 1531, NULL},
+ { "wyrm3.dlt", GAME_RESOURCEFILE, 1532, NULL},
+ { "wyrm4.dlt", GAME_RESOURCEFILE, 1533, NULL},
+ { "credit3m.dlt", GAME_RESOURCEFILE, 1796, NULL},
+ { "credit4m.dlt", GAME_RESOURCEFILE, 1797, NULL},
+ { "p2_a.iaf", GAME_VOICEFILE, 4, &ITEMAC_GameSound}
};
static const SAGAGameDescription gameDescriptions[] = {
@@ -333,7 +199,6 @@ static const SAGAGameDescription gameDescriptions[] = {
ITEDEMO_GameFonts,
&ITEDISK_GameSound,
&ITEDISK_GameSound,
- &ITEMACCD_GameMusic, // note: this version did not originally have digital music
0,
NULL,
},
@@ -363,18 +228,15 @@ static const SAGAGameDescription gameDescriptions[] = {
&ITE_Resources,
ARRAYSIZE(ITEWINDEMO_GameFonts),
ITEWINDEMO_GameFonts,
- &ITEMACDEMO_GameVoice,
- &ITEMACDEMO_GameSound,
- &ITEMACDEMO_GameMusic,
+ &ITEDEMO_GameVoice,
+ &ITEMAC_GameSound,
ARRAYSIZE(ITEMacPatch_Files),
ITEMacPatch_Files,
},
- // Note: This version is NOT supported yet
- // Exiting the faire leads to a crash
-
// Inherit the earth - MAC Demo version 1
+ // Non-interactive demo
{
{
"ite",
@@ -393,14 +255,13 @@ static const SAGAGameDescription gameDescriptions[] = {
},
GType_ITE,
GID_ITE_MACDEMO1,
- GF_BIG_ENDIAN_DATA | GF_WYRMKEEP | GF_CD_FX,
+ GF_BIG_ENDIAN_DATA | GF_WYRMKEEP | GF_CD_FX | GF_NON_INTERACTIVE,
ITE_DEFAULT_SCENE,
&ITE_Resources,
ARRAYSIZE(ITEWINDEMO_GameFonts),
ITEWINDEMO_GameFonts,
- &ITEMACDEMO_GameVoice,
- &ITEMACDEMO_GameSound,
- &ITEMACCD_GameMusic,
+ &ITEDEMO_GameVoice,
+ &ITEMAC_GameSound,
ARRAYSIZE(ITEMacPatch_Files),
ITEMacPatch_Files,
},
@@ -431,18 +292,15 @@ static const SAGAGameDescription gameDescriptions[] = {
&ITE_Resources,
ARRAYSIZE(ITEWINDEMO_GameFonts),
ITEWINDEMO_GameFonts,
- &ITEWINDEMO2_GameVoice,
- &ITEWINDEMO2_GameSound,
- &ITEMACCD_GameMusic,
+ &ITEDEMO_GameVoice,
+ &ITEPC_GameSound,
ARRAYSIZE(ITEPatch_Files),
ITEPatch_Files,
},
- // Note: This version is NOT supported yet
- // Exiting the faire leads to a crash
-
// Inherit the earth - Win32 Demo version 1
+ // Non-interactive demo
{
{
"ite",
@@ -460,14 +318,13 @@ static const SAGAGameDescription gameDescriptions[] = {
},
GType_ITE,
GID_ITE_WINDEMO1,
- GF_WYRMKEEP | GF_CD_FX,
+ GF_WYRMKEEP | GF_CD_FX | GF_NON_INTERACTIVE,
ITE_DEFAULT_SCENE,
&ITE_Resources,
ARRAYSIZE(ITEWINDEMO_GameFonts),
ITEWINDEMO_GameFonts,
&ITEWINDEMO1_GameSound,
&ITEWINDEMO1_GameSound,
- &ITEMACCD_GameMusic, // note: this version did not originally have digital music
ARRAYSIZE(ITEPatch_Files),
ITEPatch_Files,
},
@@ -504,7 +361,6 @@ static const SAGAGameDescription gameDescriptions[] = {
ITEWINDEMO_GameFonts,
&ITEMACCD_G_GameSound,
&ITEMACCD_G_GameSound,
- &ITEMACCD_GameMusic, // note: this version did not originally have digital music
0,
NULL,
},
@@ -533,9 +389,8 @@ static const SAGAGameDescription gameDescriptions[] = {
&ITE_Resources,
ARRAYSIZE(ITEWINDEMO_GameFonts),
ITEWINDEMO_GameFonts,
- &ITEMACCD_GameSound,
- &ITEMACCD_GameSound,
- &ITEMACCD_GameMusic,
+ &ITEMAC_GameSound,
+ &ITEMAC_GameSound,
ARRAYSIZE(ITEMacPatch_Files),
ITEMacPatch_Files,
},
@@ -570,11 +425,10 @@ static const SAGAGameDescription gameDescriptions[] = {
GF_WYRMKEEP | GF_CD_FX,
ITE_DEFAULT_SCENE,
&ITE_Resources,
- ARRAYSIZE(ITECD_GameFonts),
- ITECD_GameFonts,
- &ITEMACCD_GameSound,
- &ITECD_GameSound,
- &ITEMACCD_GameMusic,
+ ARRAYSIZE(ITE_GameFonts),
+ ITE_GameFonts,
+ &ITEMAC_GameSound,
+ &ITEPC_GameSound,
0,
NULL,
},
@@ -601,11 +455,10 @@ static const SAGAGameDescription gameDescriptions[] = {
GF_CD_FX,
ITE_DEFAULT_SCENE,
&ITE_Resources,
- ARRAYSIZE(ITECD_GameFonts),
- ITECD_GameFonts,
- &ITECD_GameSound,
- &ITECD_GameSound,
- &ITEMACCD_GameMusic,
+ ARRAYSIZE(ITE_GameFonts),
+ ITE_GameFonts,
+ &ITEPC_GameSound,
+ &ITEPC_GameSound,
ARRAYSIZE(ITEPatch_Files),
ITEPatch_Files,
},
@@ -631,11 +484,10 @@ static const SAGAGameDescription gameDescriptions[] = {
GF_CD_FX,
ITE_DEFAULT_SCENE,
&ITE_Resources,
- ARRAYSIZE(ITECD_GameFonts),
- ITECD_GameFonts,
- &ITECD_GameSound,
- &ITECD_GameSound,
- &ITEMACCD_GameMusic, // note: this version did not originally have digital music
+ ARRAYSIZE(ITE_GameFonts),
+ ITE_GameFonts,
+ &ITEPC_GameSound,
+ &ITEPC_GameSound,
ARRAYSIZE(ITEPatch_Files),
ITEPatch_Files,
},
@@ -662,11 +514,10 @@ static const SAGAGameDescription gameDescriptions[] = {
GF_CD_FX,
ITE_DEFAULT_SCENE,
&ITE_Resources,
- ARRAYSIZE(ITECD_GameFonts),
- ITECD_GameFonts,
- &ITECD_GameSound,
- &ITECD_GameSound,
- &ITEMACCD_GameMusic, // note: this version did not originally have digital music
+ ARRAYSIZE(ITE_GameFonts),
+ ITE_GameFonts,
+ &ITEPC_GameSound,
+ &ITEPC_GameSound,
0,
NULL,
},
@@ -694,11 +545,10 @@ static const SAGAGameDescription gameDescriptions[] = {
0,
ITE_DEFAULT_SCENE,
&ITE_Resources,
- ARRAYSIZE(ITEDISK_GameFonts),
- ITEDISK_GameFonts,
+ ARRAYSIZE(ITE_GameFonts),
+ ITE_GameFonts,
&ITEDISK_GameSound,
&ITEDISK_GameSound,
- &ITEMACCD_GameMusic, // note: this version did not originally have digital music
0,
NULL,
},
@@ -723,11 +573,10 @@ static const SAGAGameDescription gameDescriptions[] = {
0,
ITE_DEFAULT_SCENE,
&ITE_Resources,
- ARRAYSIZE(ITEDISK_GameFonts),
- ITEDISK_GameFonts,
+ ARRAYSIZE(ITE_GameFonts),
+ ITE_GameFonts,
&ITEDISK_GameSound,
&ITEDISK_GameSound,
- &ITEMACCD_GameMusic, // note: this version did not originally have digital music
ARRAYSIZE(ITEPatch_Files),
ITEPatch_Files,
},
@@ -766,7 +615,6 @@ static const SAGAGameDescription gameDescriptions[] = {
IHNMDEMO_GameFonts,
&IHNM_GameSound,
&IHNM_GameSound,
- NULL,
0,
NULL,
},
@@ -805,7 +653,6 @@ static const SAGAGameDescription gameDescriptions[] = {
IHNMCD_GameFonts,
&IHNM_GameSound,
&IHNM_GameSound,
- NULL,
0,
NULL,
},
@@ -845,7 +692,6 @@ static const SAGAGameDescription gameDescriptions[] = {
IHNMCD_GameFonts,
&IHNM_GameSound,
&IHNM_GameSound,
- NULL,
0,
NULL,
},
@@ -884,7 +730,6 @@ static const SAGAGameDescription gameDescriptions[] = {
IHNMCD_GameFonts,
&IHNM_GameSound,
&IHNM_GameSound,
- NULL,
0,
NULL,
},
@@ -923,12 +768,12 @@ static const SAGAGameDescription gameDescriptions[] = {
IHNMCD_GameFonts,
&IHNM_GameSound,
&IHNM_GameSound,
- NULL,
0,
NULL,
},
// I Have No Mouth And I Must Scream - Fr CD version
+ // Censored CD version (without Nimdok)
{
{
"ihnm",
@@ -961,11 +806,10 @@ static const SAGAGameDescription gameDescriptions[] = {
IHNMCD_GameFonts,
&IHNM_GameSound,
&IHNM_GameSound,
- NULL,
0,
NULL,
},
- { AD_TABLE_END_MARKER, 0, 0, 0, 0, NULL, 0, NULL, NULL, NULL, NULL, 0, NULL }
+ { AD_TABLE_END_MARKER, 0, 0, 0, 0, NULL, 0, NULL, NULL, NULL, 0, NULL }
};
} // End of namespace Saga
diff --git a/engines/saga/displayinfo.h b/engines/saga/displayinfo.h
index 74bbcc4343..d7d51a1e9f 100644
--- a/engines/saga/displayinfo.h
+++ b/engines/saga/displayinfo.h
@@ -18,8 +18,8 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
- * $URL:https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/branches/gsoc2007-fsnode/engines/saga/displayinfo.h $
- * $Id:displayinfo.h 26949 2007-05-26 20:23:24Z david_corrales $
+ * $URL$
+ * $Id$
*
*/
@@ -280,7 +280,7 @@ static const GameDisplayInfo ITE_DisplayInfo = {
};
-//TODO: ihnm
+// IHNM
#define IHNM_CONVERSE_MAX_TEXT_WIDTH (485 - 8)
#define IHNM_CONVERSE_TEXT_HEIGHT 10
#define IHNM_CONVERSE_TEXT_LINES 11
@@ -330,20 +330,20 @@ static PanelButton IHNM_OptionPanelButtons[] = {
{kPanelButtonOptionText,60,61, 0,0, kTextMusic,'-',0, 0,0,0}, // text: music
{kPanelButtonOptionText,60,86, 0,0, kTextSound,'-',0, 0,0,0}, // text: noise
{kPanelButtonOptionText,56,111, 0,0, kTextVoices,'-',0, 0,0,0}, // text: voices
- {kPanelButtonOption, 153,29, 79,23, kTextReadingSpeed,'r',0, 0,0,0}, //read speed
- {kPanelButtonOption, 153,54, 79,23, kTextMusic,'m',0, 0,0,0}, //music
- {kPanelButtonOption, 153,79, 79,23, kTextSound,'n',0, 0,0,0}, //sound-noise
- {kPanelButtonOption, 153,104,79,23, kTextVoices,'v',0, 0,0,0}, //voices
- {kPanelButtonOption, 19,149, 200,25, kTextQuitGame,'q',0, 0,0,0}, //quit
- {kPanelButtonOption, 19,177, 200,25, kTextContinuePlaying,'c',0, 0,0,0}, //continue
+ {kPanelButtonOption, 154,30, 79,23, kTextReadingSpeed,'r',0, 0,0,0}, //read speed
+ {kPanelButtonOption, 154,55, 79,23, kTextMusic,'m',0, 0,0,0}, //music
+ {kPanelButtonOption, 154,80, 79,23, kTextSound,'n',0, 0,0,0}, //sound-noise
+ {kPanelButtonOption, 154,105,79,23, kTextVoices,'v',0, 0,0,0}, //voices
+ {kPanelButtonOption, 20,150, 200,25, kTextQuitGame,'q',0, 0,0,0}, //quit
+ {kPanelButtonOption, 20,178, 200,25, kTextContinuePlaying,'c',0, 0,0,0}, //continue
{kPanelButtonOptionSaveFiles, 244,18, 170,138, 0,'-',0, 0,0,0}, //savefiles
- {kPanelButtonOption, 242,162, 79,23, kTextLoad,'l',0, 0,0,0}, //load
- {kPanelButtonOption, 333,162, 79,23, kTextSave,'s',0, 0,0,0}, //save
+ {kPanelButtonOption, 243,163, 79,23, kTextLoad,'l',0, 0,0,0}, //load
+ {kPanelButtonOption, 334,163, 79,23, kTextSave,'s',0, 0,0,0}, //save
};
static PanelButton IHNM_QuitPanelButtons[] = {
- {kPanelButtonQuit, 25,79, 80,25, kTextQuit,'q',0, 0,0,0},
- {kPanelButtonQuit, 155,79, 80,25, kTextCancel,'c',0, 0,0,0},
+ {kPanelButtonQuit, 26,80, 80,25, kTextQuit,'q',0, 0,0,0},
+ {kPanelButtonQuit, 156,80, 80,25, kTextCancel,'c',0, 0,0,0},
{kPanelButtonQuitText, 75,30, 0,0, kTextQuitTheGameQuestion,'-',0, 0,0,0},
};
@@ -354,11 +354,10 @@ static PanelButton IHNM_LoadPanelButtons[] = {
};
static PanelButton IHNM_SavePanelButtons[] = {
- // TODO
{kPanelButtonSave, 25,79, 80,25, kTextSave,'s',0, 0,0,0},
{kPanelButtonSave, 155,79, 80,25, kTextCancel,'c',0, 0,0,0},
- {kPanelButtonSaveEdit, 26,57, 209,17, 0,'-',0, 0,0,0},
- {kPanelButtonSaveText, 75,30, 0,0, kTextEnterSaveGameName,'-',0, 0,0,0},
+ {kPanelButtonSaveEdit, 22,56, 216,17, 0,'-',0, 0,0,0},
+ {kPanelButtonSaveText, 74,30, 0,0, kTextEnterSaveGameName,'-',0, 0,0,0},
};
diff --git a/engines/saga/events.cpp b/engines/saga/events.cpp
index 80e6b58595..50297b7ef0 100644
--- a/engines/saga/events.cpp
+++ b/engines/saga/events.cpp
@@ -154,10 +154,12 @@ int Events::handleContinuous(Event *event) {
case kEventBlackToPal:
_vm->_gfx->blackToPal((PalEntry *)event->data, event_pc);
break;
-
case kEventPalToBlack:
_vm->_gfx->palToBlack((PalEntry *)event->data, event_pc);
break;
+ case kEventPalFade:
+ _vm->_gfx->palFade((PalEntry *)event->data, event->param, event->param2, event->param3, event->param4, event_pc);
+ break;
default:
break;
}
@@ -237,10 +239,12 @@ int Events::handleImmediate(Event *event) {
case kEventBlackToPal:
_vm->_gfx->blackToPal((PalEntry *)event->data, event_pc);
break;
-
case kEventPalToBlack:
_vm->_gfx->palToBlack((PalEntry *)event->data, event_pc);
break;
+ case kEventPalFade:
+ _vm->_gfx->palFade((PalEntry *)event->data, event->param, event->param2, event->param3, event->param4, event_pc);
+ break;
default:
break;
}
@@ -251,6 +255,7 @@ int Events::handleImmediate(Event *event) {
case kSceneEvent:
case kAnimEvent:
case kCutawayEvent:
+ case kActorEvent:
handleOneShot(event);
event_done = true;
break;
@@ -338,11 +343,22 @@ int Events::handleOneShot(Event *event) {
if (event->param == kEvPSetPalette) {
PalEntry *palPointer;
+
+ if (_vm->getGameType() == GType_IHNM) {
+ if (_vm->_spiritualBarometer > 255)
+ _vm->_gfx->setPaletteColor(kIHNMColorPortrait, 0xff, 0xff, 0xff);
+ else
+ _vm->_gfx->setPaletteColor(kIHNMColorPortrait,
+ _vm->_spiritualBarometer * _vm->_interface->_portraitBgColor.red / 256,
+ _vm->_spiritualBarometer * _vm->_interface->_portraitBgColor.green / 256,
+ _vm->_spiritualBarometer * _vm->_interface->_portraitBgColor.blue / 256);
+ }
+
_vm->_scene->getBGPal(palPointer);
_vm->_gfx->setPalette(palPointer);
}
}
- _vm->_actor->showActors(true);
+ _vm->_render->clearFlag(RF_DISABLE_ACTORS);
}
break;
case kPsychicProfileBgEvent:
@@ -374,7 +390,7 @@ int Events::handleOneShot(Event *event) {
free(buf);
free(resourceData);
- // Draw the scene. It won't be drawn by Render::drawScene(), as the RF_PLACARD is set
+ // Draw the scene. It won't be drawn by Render::drawScene(), as a placard is up
_vm->_scene->draw();
}
break;
@@ -455,6 +471,9 @@ int Events::handleOneShot(Event *event) {
case kEventSetFadeMode:
_vm->_interface->setFadeMode(event->param);
break;
+ case kEventRestoreMode:
+ _vm->_interface->restoreMode();
+ break;
default:
break;
}
@@ -530,6 +549,17 @@ int Events::handleOneShot(Event *event) {
case kEventClear:
_vm->_anim->clearCutaway();
break;
+ case kEventShowCutawayBg:
+ _vm->_anim->showCutawayBg(event->param);
+ break;
+ default:
+ break;
+ }
+ case kActorEvent:
+ switch (event->op) {
+ case kEventMove:
+ // TODO (check Actor::direct)
+ break;
default:
break;
}
diff --git a/engines/saga/events.h b/engines/saga/events.h
index 2486525751..de4d296eab 100644
--- a/engines/saga/events.h
+++ b/engines/saga/events.h
@@ -69,21 +69,20 @@ enum EventOps {
// BG events
kEventDisplay = 1,
// ANIM events
- // kEventPlay = 1, // reused
- // kEventStop = 2, // reused
+ kEventPlay = 1, // used in music and sound events too
+ kEventStop = 2, // used in music and sound events too
kEventFrame = 3,
- kEventSetFlag = 4,
- kEventClearFlag = 5,
+ kEventSetFlag = 4, // used in graphics events too
+ kEventClearFlag = 5, // used in graphics events too
kEventResumeAll = 6,
- // MUISC & SOUND events
- kEventPlay = 1,
- kEventStop = 2,
+ // MUSIC and SOUND events
+ // Reused: kEventPlay, kEventStop
// SCENE events
kEventDraw = 1,
kEventEnd = 2,
// TEXT events
- kEventHide = 2,
kEventRemove = 3,
+ // Reused: kEventHide
// PALANIM events
kEventCycleStart = 1,
kEventCycleStep = 2,
@@ -93,6 +92,7 @@ enum EventOps {
kEventSetStatus = 3,
kEventClearStatus = 4,
kEventSetFadeMode = 5,
+ kEventRestoreMode = 6,
// ACTOR events
kEventMove = 1,
// SCRIPT events
@@ -101,23 +101,24 @@ enum EventOps {
kEventThreadWake = 3,
// CURSOR events
kEventShow = 1,
- // kEventHide = 2, // reused
+ kEventHide = 2, // used in text events too
kEventSetNormalCursor = 3,
kEventSetBusyCursor = 4,
// GRAPHICS events
kEventFillRect = 1,
- // kEventSetFlag = 4, // reused
- // kEventClearFlag = 5, // reused
-
+ // Reused: kEventSetFlag, kEventClearFlag
// CONTINUOUS events
+ //
// PALETTE events
kEventPalToBlack = 1,
kEventBlackToPal = 2,
+ kEventPalFade = 3,
// TRANSITION events
kEventDissolve = 1,
kEventDissolveBGMask = 2,
// CUTAWAY events
- kEventClear = 1
+ kEventClear = 1,
+ kEventShowCutawayBg = 2
};
enum EventParams {
diff --git a/engines/saga/font.cpp b/engines/saga/font.cpp
index 71cd6b0eef..06e51a78e4 100644
--- a/engines/saga/font.cpp
+++ b/engines/saga/font.cpp
@@ -49,6 +49,7 @@ Font::Font(SagaEngine *vm) : _vm(vm), _initialized(false) {
}
_initialized = true;
+ _fontMapping = 0;
}
Font::~Font(void) {
@@ -325,14 +326,29 @@ void Font::outFont(const FontStyle &drawFont, Surface *ds, const char *text, siz
c_code = *textPointer & 0xFFU;
// Translate character
- if (!(flags & kFontDontmap))
+ if (_fontMapping == 0) { // Check font mapping debug flag
+ // Default game behavior
+
+ // It seems that this font mapping causes problems with non-english
+ // versions of IHNM, so it has been changed to apply for ITE only.
+ // It doesn't make any difference for the English version of IHNM.
+ // Fixes bug #1796045: "IHNM: Spanish font wrong".
+ if (!(flags & kFontDontmap) && _vm->getGameType() == GType_ITE)
+ c_code = _charMap[c_code];
+ } else if (_fontMapping == 1) {
+ // Force font mapping
c_code = _charMap[c_code];
+ } else {
+ // In all other cases, ignore font mapping
+ }
assert(c_code < FONT_CHARCOUNT);
// Check if character is defined
if ((drawFont.fontCharEntry[c_code].index == 0) && (c_code != FONT_FIRSTCHAR)) {
#if FONT_SHOWUNDEFINED
- if (c_code == FONT_CH_SPACE || c_code == 9) {
+ // A tab character appears in the IHNM demo instructions screen, so filter
+ // it out here
+ if (c_code == FONT_CH_SPACE || c_code == FONT_CH_TAB) {
textPoint.x += drawFont.fontCharEntry[c_code].tracking;
continue;
}
@@ -632,8 +648,7 @@ Font::FontId Font::knownFont2FontIdx(KnownFont font) {
// The demo version of IHNM has 3 font types (like ITE), not 6 (like the full version of IHNM)
if (_vm->getGameType() == GType_ITE || _vm->getGameId() == GID_IHNM_DEMO) {
- switch (font)
- {
+ switch (font) {
case (kKnownFontSmall):
fontId = kSmallFont;
break;
@@ -655,8 +670,7 @@ Font::FontId Font::knownFont2FontIdx(KnownFont font) {
break;
}
} else if (_vm->getGameType() == GType_IHNM && _vm->getGameId() != GID_IHNM_DEMO) {
- switch (font)
- {
+ switch (font) {
case (kKnownFontSmall):
fontId = kSmallFont;
break;
diff --git a/engines/saga/font.h b/engines/saga/font.h
index 5823513e0f..16fdfc22b9 100644
--- a/engines/saga/font.h
+++ b/engines/saga/font.h
@@ -39,6 +39,7 @@ namespace Saga {
// have a valid offset of '0'
#define FONT_FIRSTCHAR 33
+#define FONT_CH_TAB 9
#define FONT_CH_SPACE 32
#define FONT_CH_QMARK 63
@@ -140,8 +141,11 @@ class Font {
}
void textDrawRect(KnownFont font, Surface *ds, const char *text, const Common::Rect &rect, int color, int effectColor, FontEffectFlags flags) {
textDrawRect(knownFont2FontIdx(font), ds, text, rect, color, effectColor, flags);
+ }
+ void setFontMapping(int mapping) {
+ _fontMapping = mapping;
}
-
+
private:
enum FontId {
kSmallFont,
@@ -196,6 +200,7 @@ class Font {
SagaEngine *_vm;
bool _initialized;
+ int _fontMapping;
int _loadedFonts;
FontData **_fonts;
diff --git a/engines/saga/gfx.cpp b/engines/saga/gfx.cpp
index 56ffe04c96..8509da62ed 100644
--- a/engines/saga/gfx.cpp
+++ b/engines/saga/gfx.cpp
@@ -356,8 +356,6 @@ void Gfx::blackToPal(PalEntry *srcPal, double percent) {
// Exponential fade
fpercent = percent * percent;
- fpercent = 1.0 - fpercent;
-
// Use the correct percentage change per frame for each palette entry
for (i = 0, ppal = _currentPal; i < PAL_ENTRIES; i++, ppal += 4) {
if (i < from || i >= from + numcolors)
@@ -365,7 +363,7 @@ void Gfx::blackToPal(PalEntry *srcPal, double percent) {
else
palE = &srcPal[i];
- new_entry = (int)(palE->red - palE->red * fpercent);
+ new_entry = (int)(palE->red * fpercent);
if (new_entry < 0) {
ppal[0] = 0;
@@ -373,7 +371,7 @@ void Gfx::blackToPal(PalEntry *srcPal, double percent) {
ppal[0] = (byte)new_entry;
}
- new_entry = (int)(palE->green - palE->green * fpercent);
+ new_entry = (int)(palE->green * fpercent);
if (new_entry < 0) {
ppal[1] = 0;
@@ -381,7 +379,7 @@ void Gfx::blackToPal(PalEntry *srcPal, double percent) {
ppal[1] = (byte) new_entry;
}
- new_entry = (int)(palE->blue - palE->blue * fpercent);
+ new_entry = (int)(palE->blue * fpercent);
if (new_entry < 0) {
ppal[2] = 0;
@@ -402,7 +400,79 @@ void Gfx::blackToPal(PalEntry *srcPal, double percent) {
_system->setPalette(_currentPal, 0, PAL_ENTRIES);
}
+// Used in IHNM only
+void Gfx::palFade(PalEntry *srcPal, int16 from, int16 to, int16 start, int16 numColors, double percent) {
+ int i;
+ int new_entry;
+ byte *ppal;
+ PalEntry *palE;
+ double fpercent;
+
+ from = from > 256 ? 256 : from;
+ from = from < 0 ? 0 : from;
+ to = to > 256 ? 256 : to;
+ to = to < 0 ? 0 : to;
+
+ if (from == 0 || to == 0) {
+ // This case works like palToBlack or blackToPal, so no changes are needed
+ } else {
+ double x = from > to ? from / to : to / from;
+ percent /= x;
+ if (from < to)
+ percent += 1 / x;
+ }
+
+ // Exponential fade
+ percent = percent > 1.0 ? 1.0 : percent;
+ fpercent = percent * percent;
+
+ if (from > to)
+ fpercent = 1.0 - fpercent;
+
+ // Use the correct percentage change per frame for each palette entry
+ for (i = 0, ppal = _currentPal; i < PAL_ENTRIES; i++, ppal += 4) {
+ if (i < start || i >= start + numColors)
+ palE = &_globalPalette[i];
+ else
+ palE = &srcPal[i];
+
+ new_entry = (int)(palE->red * fpercent);
+
+ if (new_entry < 0) {
+ ppal[0] = 0;
+ } else {
+ ppal[0] = (byte) new_entry;
+ }
+
+ new_entry = (int)(palE->green * fpercent);
+
+ if (new_entry < 0) {
+ ppal[1] = 0;
+ } else {
+ ppal[1] = (byte) new_entry;
+ }
+
+ new_entry = (int)(palE->blue * fpercent);
+
+ if (new_entry < 0) {
+ ppal[2] = 0;
+ } else {
+ ppal[2] = (byte) new_entry;
+ }
+ ppal[3] = 0;
+ }
+
+ // Color 0 should always be black in IHNM
+ memset(&_currentPal[0 * 4], 0, 4);
+
+ _system->setPalette(_currentPal, 0, PAL_ENTRIES);
+}
+
void Gfx::showCursor(bool state) {
+ // Don't show the mouse cursor in the non-interactive part of the IHNM demo
+ if (_vm->_scene->isNonInteractiveIHNMDemoPart())
+ state = false;
+
CursorMan.showMouse(state);
}
diff --git a/engines/saga/gfx.h b/engines/saga/gfx.h
index 0fa7aab742..ea1370c79d 100644
--- a/engines/saga/gfx.h
+++ b/engines/saga/gfx.h
@@ -150,6 +150,7 @@ public:
void restorePalette() { setPalette(_savedPalette, true); }
void palToBlack(PalEntry *src_pal, double percent);
void blackToPal(PalEntry *src_pal, double percent);
+ void palFade(PalEntry *srcPal, int16 from, int16 to, int16 start, int16 numColors, double percent);
void showCursor(bool state);
void setCursor(CursorType cursorType = kCursorNormal);
diff --git a/engines/saga/ihnm_introproc.cpp b/engines/saga/ihnm_introproc.cpp
index 631da37e82..fcf69d1bd1 100644
--- a/engines/saga/ihnm_introproc.cpp
+++ b/engines/saga/ihnm_introproc.cpp
@@ -31,154 +31,52 @@
#include "saga/animation.h"
#include "saga/events.h"
#include "saga/interface.h"
+#include "saga/render.h"
#include "saga/rscfile.h"
#include "saga/sndres.h"
#include "saga/music.h"
#include "saga/scene.h"
-namespace Saga {
+#include "common/events.h"
-SceneResourceData IHNM_IntroMovie1RL[] = {
- {30, 2, 0, 0, false},
- {31, 14, 0, 0, false}
-};
-
-SceneDescription IHNM_IntroMovie1Desc = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- IHNM_IntroMovie1RL,
- ARRAYSIZE(IHNM_IntroMovie1RL)
-};
-
-SceneResourceData IHNM_IntroMovie2RL[] = {
- {32, 2, 0, 0, false},
- {33, 14, 0, 0, false}
-};
-
-SceneDescription IHNM_IntroMovie2Desc = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- IHNM_IntroMovie2RL,
- ARRAYSIZE(IHNM_IntroMovie2RL)
-};
-
-SceneResourceData IHNM_IntroMovie3RL[] = {
- {34, 2, 0, 0, false},
- {35, 14, 0, 0, false}
-};
-
-SceneDescription IHNM_IntroMovie3Desc = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- IHNM_IntroMovie3RL,
- ARRAYSIZE(IHNM_IntroMovie3RL)
-};
-
-SceneResourceData IHNM_IntroMovie4RL[] = {
- {1227, 2, 0, 0, false},
- {1226, 14, 0, 0, false}
-};
-
-SceneDescription IHNM_IntroMovie4Desc = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- IHNM_IntroMovie4RL,
- ARRAYSIZE(IHNM_IntroMovie4RL)
-};
-
-// Demo
-SceneResourceData IHNMDEMO_IntroMovie1RL[] = {
- {19, 2, 0, 0, false} // this scene doesn't have an animation
-};
-
-SceneDescription IHNMDEMO_IntroMovie1Desc = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- IHNMDEMO_IntroMovie1RL,
- ARRAYSIZE(IHNMDEMO_IntroMovie1RL)
-};
-
-SceneResourceData IHNMDEMO_IntroMovie2RL[] = {
- {22, 2, 0, 0, false},
- {23, 14, 0, 0, false}
-};
-
-SceneDescription IHNMDEMO_IntroMovie2Desc = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- IHNMDEMO_IntroMovie2RL,
- ARRAYSIZE(IHNMDEMO_IntroMovie2RL)
-};
-
-LoadSceneParams IHNM_IntroList[] = {
- {0, kLoadByDescription, &IHNM_IntroMovie1Desc, Scene::SC_IHNMIntroMovieProc1, false, kTransitionNoFade, 0, NO_CHAPTER_CHANGE},
- {0, kLoadByDescription, &IHNM_IntroMovie2Desc, Scene::SC_IHNMIntroMovieProc2, false, kTransitionNoFade, 0, NO_CHAPTER_CHANGE},
- {0, kLoadByDescription, &IHNM_IntroMovie3Desc, Scene::SC_IHNMIntroMovieProc3, false, kTransitionNoFade, 0, NO_CHAPTER_CHANGE},
-};
-
-LoadSceneParams IHNMDEMO_IntroList[] = {
- {0, kLoadByDescription, &IHNMDEMO_IntroMovie1Desc, Scene::SC_IHNMIntroMovieProc1, false, kTransitionNoFade, 0, NO_CHAPTER_CHANGE},
- {0, kLoadByDescription, &IHNMDEMO_IntroMovie2Desc, Scene::SC_IHNMIntroMovieProc3, false, kTransitionNoFade, 0, NO_CHAPTER_CHANGE},
-};
+namespace Saga {
// IHNM cutaway intro resource IDs
#define RID_IHNM_INTRO_CUTAWAYS 39
#define RID_IHNMDEMO_INTRO_CUTAWAYS 25
int Scene::IHNMStartProc() {
- size_t n_introscenes;
- size_t i;
-
LoadSceneParams firstScene;
- /*
- // Test code - uses loadCutawayList to load the intro cutaways, like the original
+ IHNMLoadCutaways();
- ResourceContext *resourceContext;
- //ResourceContext *soundContext;
- byte *resourcePointer;
- size_t resourceLength;
-
- resourceContext = _vm->_resource->getContext(GAME_RESOURCEFILE);
- if (resourceContext == NULL) {
- error("Scene::IHNMStartProc() resource context not found");
- }
-
- if (_vm->getGameId() != GID_IHNM_DEMO)
- _vm->_resource->loadResource(resourceContext, RID_IHNM_INTRO_CUTAWAYS, resourcePointer, resourceLength);
- else
- _vm->_resource->loadResource(resourceContext, RID_IHNMDEMO_INTRO_CUTAWAYS, resourcePointer, resourceLength);
-
- if (resourceLength == 0) {
- error("Scene::IHNMStartProc() Can't load cutaway list");
- }
-
- // Load the cutaways for the title screens
- _vm->_anim->loadCutawayList(resourcePointer, resourceLength);
-
- // Note that the resource ID needed is the returned ID minus one
- printf("%i\n", _vm->_anim->cutawayResourceID(0));
- printf("%i\n", _vm->_anim->cutawayResourceID(1));
- printf("%i\n", _vm->_anim->cutawayResourceID(2));
- */
-
- // The original used the "play video" mechanism for the first part of
- // the intro. We just use that panel mode.
-
- _vm->_anim->setCutAwayMode(kPanelVideo);
- _vm->_interface->setMode(kPanelVideo);
-
- if (_vm->getGameId() != GID_IHNM_DEMO)
- n_introscenes = ARRAYSIZE(IHNM_IntroList);
- else
- n_introscenes = ARRAYSIZE(IHNMDEMO_IntroList);
-
- // Queue the company and title videos
if (_vm->getGameId() != GID_IHNM_DEMO) {
- for (i = 0; i < n_introscenes; i++) {
- _vm->_scene->queueScene(&IHNM_IntroList[i]);
+ int logoLength = -168;
+
+ if (_vm->getLanguage() == Common::DE_DEU || _vm->getLanguage() == Common::ES_ESP)
+ logoLength = -128;
+
+ // Play Cyberdreams logo for 168 frames
+ if (!playTitle(0, logoLength, true)) {
+ // Play Dreamers Guild logo for 10 seconds
+ if (!playLoopingTitle(1, 10)) {
+ // Play the title music
+ _vm->_music->play(1, MUSIC_NORMAL);
+ // Play title screen
+ playTitle(2, 17);
+ }
}
} else {
- for (i = 0; i < n_introscenes; i++) {
- _vm->_scene->queueScene(&IHNMDEMO_IntroList[i]);
- }
+ _vm->_music->play(1, MUSIC_NORMAL);
+ playTitle(0, 10);
+ playTitle(2, 12);
}
+ _vm->_music->setVolume(0, 1000);
+ _vm->_anim->freeCutawayList();
+
+ // Queue first scene
firstScene.loadFlag = kLoadBySceneNumber;
firstScene.sceneDescriptor = -1;
firstScene.sceneDescription = NULL;
@@ -193,241 +91,189 @@ int Scene::IHNMStartProc() {
return SUCCESS;
}
-int Scene::SC_IHNMIntroMovieProc1(int param, void *refCon) {
- return ((Scene *)refCon)->IHNMIntroMovieProc1(param);
-}
+int Scene::IHNMCreditsProc() {
+ IHNMLoadCutaways();
-int Scene::IHNMIntroMovieProc1(int param) {
- Event event;
- Event *q_event;
-
- switch (param) {
- case SCENE_BEGIN:
- // Background for intro scene is the first frame of the
- // intro animation; display it and set the palette
- event.type = kEvTOneshot;
- event.code = kBgEvent;
- event.op = kEventDisplay;
- event.param = kEvPSetPalette;
- event.time = 0;
-
- q_event = _vm->_events->queue(&event);
-
- if (_vm->getGameId() != GID_IHNM_DEMO) {
- _vm->_anim->setFrameTime(0, IHNM_INTRO_FRAMETIME);
- _vm->_anim->setFlag(0, ANIM_FLAG_ENDSCENE);
-
- event.type = kEvTOneshot;
- event.code = kAnimEvent;
- event.op = kEventPlay;
- event.param = 0;
- event.time = 0;
-
- q_event = _vm->_events->chain(q_event, &event);
- } else {
- // Start playing the intro music for the demo version
- event.type = kEvTOneshot;
- event.code = kMusicEvent;
- event.param = 1;
- event.param2 = MUSIC_NORMAL;
- event.op = kEventPlay;
- event.time = 0;
-
- q_event = _vm->_events->chain(q_event, &event);
-
- // The IHNM demo doesn't have an animation at the
- // Cyberdreans logo screen
-
- // Queue end of scene after a while
- event.type = kEvTOneshot;
- event.code = kSceneEvent;
- event.op = kEventEnd;
- event.time = 8000;
-
- q_event = _vm->_events->chain(q_event, &event);
- }
+ _vm->_music->play(0, MUSIC_NORMAL);
- break;
- default:
- break;
+ if (_vm->getGameId() != GID_IHNM_DEMO) {
+ // Display the credits for 400 frames
+ playTitle(4, -400, true);
+ } else {
+ // Display sales info for 60 seconds
+ playTitle(3, 60, true);
}
- return 0;
-}
+ _vm->_music->setVolume(0, 1000);
+ _vm->_anim->freeCutawayList();
-int Scene::SC_IHNMIntroMovieProc2(int param, void *refCon) {
- return ((Scene *)refCon)->IHNMIntroMovieProc2(param);
+ return SUCCESS;
}
-int Scene::IHNMIntroMovieProc2(int param) {
- Event event;
- Event *q_event;
- PalEntry *pal;
-
- static PalEntry current_pal[PAL_ENTRIES];
-
- switch (param) {
- case SCENE_BEGIN:
- // Fade to black out of the intro CyberDreams logo anim
- _vm->_gfx->getCurrentPal(current_pal);
-
- event.type = kEvTContinuous;
- event.code = kPalEvent;
- event.op = kEventPalToBlack;
- event.time = 0;
- event.duration = IHNM_PALFADE_TIME;
- event.data = current_pal;
-
- q_event = _vm->_events->queue(&event);
-
- // Background for intro scene is the first frame of the
- // intro animation; display it but don't set palette
- event.type = kEvTOneshot;
- event.code = kBgEvent;
- event.op = kEventDisplay;
- event.param = kEvPNoSetPalette;
- event.time = 0;
-
- q_event = _vm->_events->chain(q_event, &event);
-
- _vm->_anim->setCycles(0, -1);
-
- // Unlike the original, we keep the logo spinning during the
- // palette fades. We don't have to, but I think it looks better
- // that way.
-
- event.type = kEvTOneshot;
- event.code = kAnimEvent;
- event.op = kEventPlay;
- event.param = 0;
- event.time = 0;
-
- q_event = _vm->_events->chain(q_event, &event);
-
- // Fade in from black to the scene background palette
- _vm->_scene->getBGPal(pal);
-
- event.type = kEvTContinuous;
- event.code = kPalEvent;
- event.op = kEventBlackToPal;
- event.time = 0;
- event.duration = IHNM_PALFADE_TIME;
- event.data = pal;
-
- q_event = _vm->_events->chain(q_event, &event);
-
- // Fade to black after looping animation for a while
- event.type = kEvTContinuous;
- event.code = kPalEvent;
- event.op = kEventPalToBlack;
- event.time = IHNM_DGLOGO_TIME;
- event.duration = IHNM_PALFADE_TIME;
- event.data = pal;
-
- q_event = _vm->_events->chain(q_event, &event);
-
- // Queue end of scene
- event.type = kEvTOneshot;
- event.code = kSceneEvent;
- event.op = kEventEnd;
- event.time = 0;
-
- q_event = _vm->_events->chain(q_event, &event);
- break;
- default:
- break;
+void Scene::IHNMLoadCutaways() {
+ ResourceContext *resourceContext;
+ //ResourceContext *soundContext;
+ byte *resourcePointer;
+ size_t resourceLength;
+
+ resourceContext = _vm->_resource->getContext(GAME_RESOURCEFILE);
+ if (resourceContext == NULL) {
+ error("Scene::IHNMStartProc() resource context not found");
}
- return 0;
-}
+ if (_vm->getGameId() != GID_IHNM_DEMO)
+ _vm->_resource->loadResource(resourceContext, RID_IHNM_INTRO_CUTAWAYS, resourcePointer, resourceLength);
+ else
+ _vm->_resource->loadResource(resourceContext, RID_IHNMDEMO_INTRO_CUTAWAYS, resourcePointer, resourceLength);
-int Scene::SC_IHNMIntroMovieProc3(int param, void *refCon) {
- return ((Scene *)refCon)->IHNMIntroMovieProc3(param);
-}
+ if (resourceLength == 0) {
+ error("Scene::IHNMStartProc() Can't load cutaway list");
+ }
-int Scene::IHNMIntroMovieProc3(int param) {
- Event event;
- Event *q_event;
- PalEntry *pal;
- static PalEntry current_pal[PAL_ENTRIES];
+ // Load the cutaways for the title screens
+ _vm->_anim->loadCutawayList(resourcePointer, resourceLength);
+}
- switch (param) {
- case SCENE_BEGIN:
- // Fade to black out of the intro DG logo anim
- _vm->_gfx->getCurrentPal(current_pal);
+bool Scene::checkKey() {
+ Common::Event event;
+ bool res = false;
+
+ while (_vm->_eventMan->pollEvent(event)) {
+ switch (event.type) {
+ case Common::EVENT_QUIT:
+ _vm->shutDown();
+ // fallthrough
+ case Common::EVENT_KEYDOWN:
+ res = true;
+ break;
+ default:
+ break;
+ }
+ }
- event.type = kEvTContinuous;
- event.code = kPalEvent;
- event.op = kEventPalToBlack;
- event.time = 0;
- event.duration = IHNM_PALFADE_TIME;
- event.data = current_pal;
+ return res;
+}
- q_event = _vm->_events->queue(&event);
+bool Scene::playTitle(int title, int time, int mode) {
+ bool interrupted = false;
+ Surface *backBufferSurface;
+ int startTime = _vm->_system->getMillis();
+ int frameTime = 0;
+ int curTime;
+ int assignedId;
+ int phase = 0;
+ bool done = false;
+ bool playParameter = true;
+ static PalEntry cur_pal[PAL_ENTRIES];
+ static PalEntry pal_cut[PAL_ENTRIES];
+
+ backBufferSurface = _vm->_render->getBackGroundSurface();
+
+ // Load the cutaway
+
+ _vm->_anim->setCutAwayMode(mode);
+ _vm->_frameCount = 0;
+
+ _vm->_gfx->getCurrentPal(cur_pal);
+
+ assignedId = _vm->_anim->playCutaway(title, false);
+
+ _vm->_gfx->getCurrentPal(pal_cut);
+
+ while (!done) {
+ curTime = _vm->_system->getMillis();
+
+ switch (phase) {
+ case 0: // fadeout
+ case 1: // fadeout 100%
+ case 7: // fadeout
+ case 8: // fadeout 100%
+ _vm->_gfx->palToBlack(cur_pal, (double)(curTime - startTime) / kNormalFadeDuration);
+ // fall through
+
+ case 3: // fadein
+ case 4: // fadein 100%
+ if (phase == 3 || phase == 4)
+ _vm->_gfx->blackToPal(pal_cut, (double)(curTime - startTime) / kNormalFadeDuration);
+
+ if (curTime - startTime > kNormalFadeDuration) {
+ phase++;
+ if (phase == 2 || phase == 5 || phase == 9)
+ startTime = curTime;
+ break;
+ }
+ break;
+
+ case 2: // display background
+ _vm->_system->copyRectToScreen((byte *)backBufferSurface->pixels, backBufferSurface->w, 0, 0,
+ backBufferSurface->w, backBufferSurface->h);
+ phase++;
+ startTime = curTime;
+ break;
+
+ case 5: // playback
+ if (time < 0) {
+ if (_vm->_frameCount >= -time) {
+ phase++;
+ break;
+ }
+ } else {
+ if (curTime - startTime >= time * 1000) {
+ phase++;
+ break;
+ }
+ }
+
+ if (checkKey()) {
+ interrupted = true;
+ done = true;
+ break;
+ }
+
+ if (_vm->_anim->getCycles(assignedId)) { // IHNM demo has 0 frames logo
+ if (curTime - frameTime > _vm->_anim->getFrameTime(assignedId)) {
+ _vm->_anim->play(assignedId, 0, playParameter);
+
+ if (playParameter == true) // Do not loop animations
+ playParameter = false;
+
+ frameTime = curTime;
+
+ _vm->_system->copyRectToScreen((byte *)backBufferSurface->pixels, backBufferSurface->w, 0, 0,
+ backBufferSurface->w, backBufferSurface->h);
+ }
+
+ }
+ break;
+
+ case 6: // playback end
+ startTime = curTime;
+ _vm->_gfx->getCurrentPal(cur_pal);
+ phase++;
+ break;
+
+ case 9: // end
+ done = true;
+ break;
+ }
- // Music, maestro
+ _vm->_system->updateScreen();
+ _vm->_system->delayMillis(10);
+ }
- // In the GM file, this music also appears as tracks 7, 13, 19,
- // 25 and 31, but only track 1 sounds right with the FM music.
+ // Clean up
- if (_vm->getGameId() != GID_IHNM_DEMO) {
- event.type = kEvTOneshot;
- event.code = kMusicEvent;
- event.param = 1;
- event.param2 = MUSIC_NORMAL;
- event.op = kEventPlay;
- event.time = 0;
+ _vm->_anim->endVideo();
- q_event = _vm->_events->chain(q_event, &event);
- }
+ memset((byte *)backBufferSurface->pixels, 0, backBufferSurface->w * backBufferSurface->h);
+ _vm->_system->copyRectToScreen((byte *)backBufferSurface->pixels, backBufferSurface->w, 0, 0,
+ backBufferSurface->w, backBufferSurface->h);
- // Background for intro scene is the first frame of the intro
- // animation; display it but don't set palette
- event.type = kEvTOneshot;
- event.code = kBgEvent;
- event.op = kEventDisplay;
- event.param = kEvPNoSetPalette;
- event.time = 0;
-
- q_event = _vm->_events->chain(q_event, &event);
-
- // Fade in from black to the scene background palette
- _vm->_scene->getBGPal(pal);
-
- event.type = kEvTContinuous;
- event.code = kPalEvent;
- event.op = kEventBlackToPal;
- event.time = 0;
- event.duration = IHNM_PALFADE_TIME;
- event.data = pal;
-
- q_event = _vm->_events->chain(q_event, &event);
-
- event.type = kEvTOneshot;
- event.code = kAnimEvent;
- event.op = kEventPlay;
- event.param = 0;
- event.time = 0;
-
- q_event = _vm->_events->chain(q_event, &event);
-
- // Queue end of scene after a while
- // The delay has been increased so the speech won't start until the music has ended
- event.type = kEvTOneshot;
- event.code = kSceneEvent;
- event.op = kEventEnd;
- if (_vm->getGameId() != GID_IHNM_DEMO)
- event.time = _vm->_music->hasAdlib() ? IHNM_TITLE_TIME_FM : IHNM_TITLE_TIME_GM;
- else
- event.time = 12000;
-
- q_event = _vm->_events->chain(q_event, &event);
- break;
- default:
- break;
- }
+ return interrupted;
+}
- return 0;
+bool Scene::playLoopingTitle(int title, int seconds) {
+ return playTitle(title, seconds, kPanelCutaway);
}
} // End of namespace Saga
diff --git a/engines/saga/input.cpp b/engines/saga/input.cpp
index 358a225efa..5082ec7aca 100644
--- a/engines/saga/input.cpp
+++ b/engines/saga/input.cpp
@@ -49,7 +49,7 @@ int SagaEngine::processInput() {
_console->attach();
}
if (_interface->_textInput || _interface->_statusTextInput) {
- _interface->processAscii(event.kbd.ascii);
+ _interface->processAscii(event.kbd);
return SUCCESS;
}
@@ -115,7 +115,7 @@ int SagaEngine::processInput() {
_render->toggleFlag(RF_RENDERPAUSE);
break;
default:
- _interface->processAscii(event.kbd.ascii);
+ _interface->processAscii(event.kbd);
break;
}
break;
diff --git a/engines/saga/interface.cpp b/engines/saga/interface.cpp
index 8cfd993391..e6854b1c05 100644
--- a/engines/saga/interface.cpp
+++ b/engines/saga/interface.cpp
@@ -229,6 +229,12 @@ Interface::Interface(SagaEngine *vm) : _vm(vm) {
_vm->_sprite->loadList(_vm->getResourceDescription()->mainPanelSpritesResourceId, _mainPanel.sprites);
// Option panel sprites
_vm->_sprite->loadList(_vm->getResourceDescription()->optionPanelSpritesResourceId, _optionPanel.sprites);
+ // Save panel sprites
+ _vm->_sprite->loadList(_vm->getResourceDescription()->warningPanelSpritesResourceId, _savePanel.sprites);
+ // Load panel sprites
+ _vm->_sprite->loadList(_vm->getResourceDescription()->warningPanelSpritesResourceId, _loadPanel.sprites);
+ // Quit panel sprites
+ _vm->_sprite->loadList(_vm->getResourceDescription()->warningPanelSpritesResourceId, _quitPanel.sprites);
if (_vm->getGameType() == GType_ITE) {
_vm->_sprite->loadList(_vm->getResourceDescription()->defaultPortraitsResourceId, _defPortraits);
@@ -342,18 +348,10 @@ int Interface::activate() {
} else if (_panelMode == kPanelNull && _vm->getGameId() == GID_IHNM_DEMO) {
_saveReminderState = 1;
}
+ _vm->_gfx->showCursor(true);
draw();
}
- if (_vm->getGameId() != GID_IHNM_DEMO) {
- _vm->_gfx->showCursor(true);
- } else {
- if (_vm->_scene->currentSceneNumber() >= 144 && _vm->_scene->currentSceneNumber() <= 149) {
- // Don't show the mouse cursor in the non-interactive part of the IHNM demo
- } else {
- _vm->_gfx->showCursor(true);
- }
- }
return SUCCESS;
}
@@ -369,7 +367,7 @@ int Interface::deactivate() {
}
void Interface::rememberMode() {
- debug(1, "rememberMode(%d)", _savedMode);
+ debug(1, "rememberMode(%d)", _panelMode);
_savedMode = _panelMode;
}
@@ -400,9 +398,6 @@ void Interface::setMode(int mode) {
if (_vm->getGameId() == GID_IHNM_DEMO) {
_inMainMode = true;
_saveReminderState = 1;
- if ((_vm->_scene->currentSceneNumber() >= 144 && _vm->_scene->currentSceneNumber() <= 149) ||
- _vm->_scene->currentSceneNumber() == 0 || _vm->_scene->currentSceneNumber() == -1)
- _vm->_gfx->showCursor(false);
}
} else if (mode == kPanelOption) {
// Show the cursor in the IHNM demo
@@ -420,8 +415,8 @@ void Interface::setMode(int mode) {
switch (_panelMode) {
case kPanelMain:
- if (_vm->getGameType() == GType_IHNM)
- warning("FIXME: Implement IHNM differences from ExecuteInventoryPanel");
+ // FIXME: Implement IHNM differences from ExecuteInventoryPanel for IHNM (though I believe they're already
+ // implemented)
_mainPanel.currentButton = NULL;
break;
@@ -481,22 +476,22 @@ void Interface::setMode(int mode) {
draw();
}
-bool Interface::processAscii(uint16 ascii) {
+bool Interface::processAscii(Common::KeyState keystate) {
// TODO: Checking for Esc and Enter below is a bit hackish, and
// and probably only works with the English version. Maybe we should
// add a flag to the button so it can indicate if it's the default or
// cancel button?
-
+ uint16 ascii = keystate.ascii;
int i;
PanelButton *panelButton;
if (_statusTextInput) {
- processStatusTextInput(ascii);
+ processStatusTextInput(keystate);
return true;
}
switch (_panelMode) {
case kPanelNull:
- if (ascii == 27) { // Esc
+ if (keystate.keycode == Common::KEYCODE_ESCAPE) {
if (_vm->_scene->isInIntro()) {
_vm->_scene->skipScene();
} else {
@@ -506,26 +501,22 @@ bool Interface::processAscii(uint16 ascii) {
return true;
}
- if (_vm->getGameId() == GID_IHNM_DEMO) {
- if (_vm->_scene->currentSceneNumber() >= 144 && _vm->_scene->currentSceneNumber() <= 149)
- _vm->_scene->showIHNMDemoSpecialScreen();
- }
+ if (_vm->_scene->isNonInteractiveIHNMDemoPart())
+ _vm->_scene->showIHNMDemoSpecialScreen();
break;
case kPanelCutaway:
- if (ascii == 27) { // Esc
+ if (keystate.keycode == Common::KEYCODE_ESCAPE) {
if (!_disableAbortSpeeches)
_vm->_actor->abortAllSpeeches();
_vm->_scene->cutawaySkip();
return true;
}
- if (_vm->getGameId() == GID_IHNM_DEMO) {
- if (_vm->_scene->currentSceneNumber() >= 144 && _vm->_scene->currentSceneNumber() <= 149)
- _vm->_scene->showIHNMDemoSpecialScreen();
- }
+ if (_vm->_scene->isNonInteractiveIHNMDemoPart())
+ _vm->_scene->showIHNMDemoSpecialScreen();
break;
case kPanelVideo:
- if (ascii == 27) { // Esc
+ if (keystate.keycode == Common::KEYCODE_ESCAPE) {
if (_vm->_scene->isInIntro()) {
_vm->_scene->skipScene();
} else {
@@ -536,14 +527,12 @@ bool Interface::processAscii(uint16 ascii) {
return true;
}
- if (_vm->getGameId() == GID_IHNM_DEMO) {
- if (_vm->_scene->currentSceneNumber() >= 144 && _vm->_scene->currentSceneNumber() <= 149)
- _vm->_scene->showIHNMDemoSpecialScreen();
- }
+ if (_vm->_scene->isNonInteractiveIHNMDemoPart())
+ _vm->_scene->showIHNMDemoSpecialScreen();
break;
case kPanelOption:
// TODO: check input dialog keys
- if (ascii == 27 || ascii == 13) { // Esc or Enter
+ if (keystate.keycode == Common::KEYCODE_ESCAPE || keystate.keycode == Common::KEYCODE_RETURN) { // Esc or Enter
ascii = 'c'; //continue
}
@@ -558,13 +547,13 @@ bool Interface::processAscii(uint16 ascii) {
}
break;
case kPanelSave:
- if (_textInput && processTextInput(ascii)) {
+ if (_textInput && processTextInput(keystate)) {
return true;
}
- if (ascii == 27) { // Esc
+ if (keystate.keycode == Common::KEYCODE_ESCAPE) {
ascii = 'c'; // cancel
- } else if (ascii == 13) { // Enter
+ } else if (keystate.keycode == Common::KEYCODE_RETURN) { // Enter
ascii = 's'; // save
}
@@ -579,9 +568,9 @@ bool Interface::processAscii(uint16 ascii) {
}
break;
case kPanelQuit:
- if (ascii == 27) { // Esc
+ if (keystate.keycode == Common::KEYCODE_ESCAPE) {
ascii = 'c'; // cancel
- } else if (ascii == 13) { // Enter
+ } else if (keystate.keycode == Common::KEYCODE_RETURN) { // Enter
ascii = 'q'; // quit
}
@@ -619,8 +608,7 @@ bool Interface::processAscii(uint16 ascii) {
return true;
}
}
- if (ascii == 15) // ctrl-o
- {
+ if (keystate.keycode == Common::KEYCODE_o && keystate.flags == Common::KBD_CTRL) { // ctrl-o
if (_saveReminderState > 0) {
setMode(kPanelOption);
return true;
@@ -663,7 +651,7 @@ bool Interface::processAscii(uint16 ascii) {
mapPanelClean();
break;
case kPanelSceneSubstitute:
- if (ascii == 13) {
+ if (keystate.keycode == Common::KEYCODE_RETURN) {
_vm->_render->clearFlag(RF_DEMO_SUBST);
_vm->_gfx->setPalette(_mapSavedPal);
setMode(kPanelMain);
@@ -678,11 +666,11 @@ bool Interface::processAscii(uint16 ascii) {
break;
case kPanelProtect:
if (_vm->getGameType() == GType_ITE) {
- if (_textInput && processTextInput(ascii)) {
+ if (_textInput && processTextInput(keystate)) {
return true;
}
- if (ascii == 27 || ascii == 13) { // Esc or Enter
+ if (keystate.keycode == Common::KEYCODE_ESCAPE || keystate.keycode == Common::KEYCODE_RETURN) {
_vm->_script->wakeUpThreads(kWaitTypeRequest);
_vm->_interface->setMode(kPanelMain);
@@ -725,7 +713,7 @@ void Interface::setStatusText(const char *text, int statusColor) {
assert(text != NULL);
assert(strlen(text) < STATUS_TEXT_LEN);
- if (_vm->_render->getFlags() & (RF_PLACARD | RF_MAP))
+ if (_vm->_render->getFlags() & RF_MAP || _vm->_interface->getMode() == kPanelPlacard)
return;
strncpy(_statusText, text, STATUS_TEXT_LEN);
@@ -801,16 +789,6 @@ void Interface::draw() {
converseDisplayTextLines(backBuffer);
}
- if (_vm->getGameType() == GType_IHNM) {
- if (_vm->_spiritualBarometer > 255)
- _vm->_gfx->setPaletteColor(kIHNMColorPortrait, 0xff, 0xff, 0xff);
- else
- _vm->_gfx->setPaletteColor(kIHNMColorPortrait,
- _vm->_spiritualBarometer * _portraitBgColor.red / 256,
- _vm->_spiritualBarometer * _portraitBgColor.green / 256,
- _vm->_spiritualBarometer * _portraitBgColor.blue / 256);
- }
-
if (_panelMode == kPanelMain || _panelMode == kPanelConverse ||
_lockedMode == kPanelMain || _lockedMode == kPanelConverse ||
(_panelMode == kPanelNull && _vm->getGameId() == GID_IHNM_DEMO)) {
@@ -841,14 +819,19 @@ void Interface::calcOptionSaveSlider() {
int totalFiles = _vm->getSaveFilesCount();
int visibleFiles = _vm->getDisplayInfo().optionSaveFileVisible;
int height = _optionSaveFileSlider->height;
- int sliderHeight;
+ int sliderHeight = 13; // IHNM's save file list slider has a fixed height
int pos;
if (totalFiles < visibleFiles) {
totalFiles = visibleFiles;
}
- sliderHeight = visibleFiles * height / totalFiles;
+ if (_vm->getGameType() == GType_ITE) {
+ // ITE's save file list slider has a dynamically computed height, depending on
+ // the number of save games
+ sliderHeight = visibleFiles * height / totalFiles;
+ }
+
if (sliderHeight < 7) {
sliderHeight = 7;
}
@@ -931,6 +914,7 @@ void Interface::drawOption() {
PanelButton *panelButton;
Point textPoint;
Point point;
+ Point sliderPoint;
int spritenum = 0;
backBuffer = _vm->_gfx->getBackBuffer();
@@ -959,7 +943,15 @@ void Interface::drawOption() {
backBuffer->drawRect(_optionSaveRectTop, kITEColorDarkGrey);
}
- drawButtonBox(backBuffer, _optionSaveRectSlider, kSlider, _optionSaveFileSlider->state > 0);
+ if (_vm->getGameType() == GType_ITE) {
+ drawButtonBox(backBuffer, _optionSaveRectSlider, kSlider, _optionSaveFileSlider->state > 0);
+ } else {
+ panelButton = &_optionPanel.buttons[0];
+ sliderPoint.x = _optionPanel.x + panelButton->xOffset;
+ sliderPoint.y = _optionSaveRectSlider.top;
+ _vm->_sprite->draw(backBuffer, _vm->getDisplayClip(), _optionPanel.sprites, 0 + _optionSaveFileSlider->state, sliderPoint, 256);
+
+ }
if (_optionSaveRectBottom.height() > 0) {
backBuffer->drawRect(_optionSaveRectBottom, kITEColorDarkGrey);
@@ -970,7 +962,10 @@ void Interface::drawOption() {
rect2 = rect;
fontHeight = _vm->_font->getHeight(kKnownFontSmall);
for (j = 0; j < _vm->getDisplayInfo().optionSaveFileVisible; j++) {
- bgColor = kITEColorDarkGrey0C;
+ if (_vm->getGameType() == GType_ITE)
+ bgColor = kITEColorDarkGrey0C;
+ else
+ bgColor = kIHNMColorBlack;
fgColor = kITEColorBrightWhite;
idx = j + _optionSaveFileTop;
@@ -1052,7 +1047,10 @@ void Interface::setQuit(PanelButton *panelButton) {
setMode(kPanelOption);
break;
case kTextQuit:
- _vm->shutDown();
+ if (_vm->getGameId() == GID_IHNM_DEMO)
+ _vm->_scene->creditsScene(); // display sales info for IHNM demo
+ else
+ _vm->shutDown();
break;
}
}
@@ -1118,20 +1116,20 @@ void Interface::setLoad(PanelButton *panelButton) {
}
}
-void Interface::processStatusTextInput(uint16 ascii) {
+void Interface::processStatusTextInput(Common::KeyState keystate) {
- switch (ascii) {
- case 27: // esc
+ switch (keystate.keycode) {
+ case Common::KEYCODE_ESCAPE:
_statusTextInputState = kStatusTextInputAborted;
_statusTextInput = false;
_vm->_script->wakeUpThreads(kWaitTypeStatusTextInput);
break;
- case 13: // return
+ case Common::KEYCODE_RETURN:
_statusTextInputState = kStatusTextInputEntered;
_statusTextInput = false;
_vm->_script->wakeUpThreads(kWaitTypeStatusTextInput);
break;
- case 8: // backspace
+ case Common::KEYCODE_BACKSPACE:
if (_statusTextInputPos == 0) {
break;
}
@@ -1141,36 +1139,36 @@ void Interface::processStatusTextInput(uint16 ascii) {
if (_statusTextInputPos >= STATUS_TEXT_INPUT_MAX) {
break;
}
- if (((ascii >= 'a') && (ascii <='z')) ||
- ((ascii >= '0') && (ascii <='9')) ||
- ((ascii >= 'A') && (ascii <='Z')) ||
- (ascii == ' ')) {
- _statusTextInputString[_statusTextInputPos++] = ascii;
+ if (isalnum(keystate.ascii) || (keystate.ascii == ' ')) {
+ _statusTextInputString[_statusTextInputPos++] = keystate.ascii;
_statusTextInputString[_statusTextInputPos] = 0;
}
}
setStatusText(_statusTextInputString);
}
-bool Interface::processTextInput(uint16 ascii) {
+bool Interface::processTextInput(Common::KeyState keystate) {
char ch[2];
char tempString[SAVE_TITLE_SIZE];
uint tempWidth;
memset(tempString, 0, SAVE_TITLE_SIZE);
ch[1] = 0;
+ // IHNM has a smaller save title size than ITE. We only limit the save title size during text input
+ // in IHNM, to preserve backwards compatibility with older save games
+ uint save_title_size = _vm->getGameType() == GType_ITE ? SAVE_TITLE_SIZE : IHNM_SAVE_TITLE_SIZE;
- switch (ascii) {
- case 13:
+ switch (keystate.keycode) {
+ case Common::KEYCODE_RETURN:
return false;
- case 27: // esc
+ case Common::KEYCODE_ESCAPE:
_textInput = false;
break;
- case 8: // backspace
+ case Common::KEYCODE_BACKSPACE:
if (_textInputPos <= 1) {
break;
}
_textInputPos--;
- case 127: // del
+ case Common::KEYCODE_DELETE:
if (_textInputPos <= _textInputStringLength) {
if (_textInputPos != 1) {
strncpy(tempString, _textInputString, _textInputPos - 1);
@@ -1182,27 +1180,25 @@ bool Interface::processTextInput(uint16 ascii) {
_textInputStringLength = strlen(_textInputString);
}
break;
- case 276: // left
+ case Common::KEYCODE_LEFT:
if (_textInputPos > 1) {
_textInputPos--;
}
break;
- case 275: // right
+ case Common::KEYCODE_RIGHT:
if (_textInputPos <= _textInputStringLength) {
_textInputPos++;
}
break;
default:
- if (((ascii >= 'a') && (ascii <='z')) ||
- ((ascii >= '0') && (ascii <='9')) ||
- ((ascii >= 'A') && (ascii <='Z')) ||
- (ascii == ' ')) {
- if (_textInputStringLength < SAVE_TITLE_SIZE - 1) {
- ch[0] = ascii;
+ if (isalnum(keystate.ascii) || (keystate.ascii == ' ') ||
+ (keystate.ascii == '-') || (keystate.ascii == '_')) {
+ if (_textInputStringLength < save_title_size - 1) {
+ ch[0] = keystate.ascii;
tempWidth = _vm->_font->getStringWidth(kKnownFontSmall, ch, 0, kFontNormal);
tempWidth += _vm->_font->getStringWidth(kKnownFontSmall, _textInputString, 0, kFontNormal);
if (tempWidth > _textInputMaxWidth) {
- break;
+ break;
}
if (_textInputPos != 1) {
strncpy(tempString, _textInputString, _textInputPos - 1);
@@ -1243,10 +1239,10 @@ void Interface::drawTextInput(Surface *ds, InterfacePanel *panel, PanelButton *p
while ((ch[0] = _textInputString[i++]) != 0) {
rect.setWidth(_vm->_font->getStringWidth(kKnownFontSmall, ch, 0, kFontNormal));
if ((i == _textInputPos) && _textInput) {
- fgColor = kITEColorBlack;
- ds->fillRect(rect, kITEColorWhite);
+ fgColor = _vm->KnownColor2ColorId(kKnownColorBlack);
+ ds->fillRect(rect, _vm->KnownColor2ColorId(kKnownColorWhite));
} else {
- fgColor = kITEColorWhite;
+ fgColor = _vm->KnownColor2ColorId(kKnownColorWhite);
}
textPoint.x = rect.left;
textPoint.y = rect.top + 1;
@@ -1257,7 +1253,7 @@ void Interface::drawTextInput(Surface *ds, InterfacePanel *panel, PanelButton *p
if (_textInput && (_textInputPos >= i)) {
ch[0] = ' ';
rect.setWidth(_vm->_font->getStringWidth(kKnownFontSmall, ch, 0, kFontNormal));
- ds->fillRect(rect, kITEColorWhite);
+ ds->fillRect(rect, _vm->KnownColor2ColorId(kKnownColorWhite));
}
}
@@ -1468,11 +1464,22 @@ void Interface::handleOptionClick(const Point& mousePoint) {
void Interface::handleChapterSelectionUpdate(const Point& mousePoint) {
uint16 objectId;
+ int hitZoneIndex;
+ const HitZone * hitZone;
// FIXME: Original handled more object types here.
objectId = _vm->_actor->hitTest(mousePoint, true);
+ if (objectId == ID_NOTHING) {
+ hitZoneIndex = _vm->_scene->_objectMap->hitTest(mousePoint);
+
+ if ((hitZoneIndex != -1)) {
+ hitZone = _vm->_scene->_objectMap->getHitZone(hitZoneIndex);
+ objectId = hitZone->getHitZoneId();
+ }
+ }
+
if (objectId != _vm->_script->_pointerObject) {
_vm->_script->_pointerObject = objectId;
}
@@ -1492,12 +1499,12 @@ void Interface::handleChapterSelectionClick(const Point& mousePoint) {
switch (objectTypeId(obj)) {
case kGameObjectHitZone:
- hitZone = _vm->_scene->_actionMap->getHitZone(objectIdToIndex(obj));
+ hitZone = _vm->_scene->_objectMap->getHitZone(objectIdToIndex(obj));
if (hitZone == NULL)
return;
- if (hitZone->getFlags() & kHitZoneExit)
+ if (hitZone->getFlags() & kHitZoneEnabled)
script = hitZone->getScriptNumber();
break;
@@ -1523,7 +1530,6 @@ void Interface::handleChapterSelectionClick(const Point& mousePoint) {
event.param4 = obj; // Object
event.param5 = 0; // With Object
event.param6 = obj; // Actor
-
_vm->_events->queue(&event);
}
}
@@ -1540,11 +1546,8 @@ void Interface::setOption(PanelButton *panelButton) {
} else {
if (_vm->_scene->currentChapterNumber() == 8) {
setMode(kPanelChapterSelection);
- } else if (_vm->getGameId() == GID_IHNM_DEMO) {
- if (_vm->_scene->currentSceneNumber() >= 144 && _vm->_scene->currentSceneNumber() <= 149)
- setMode(kPanelNull);
- else
- setMode(kPanelMain);
+ } else if (_vm->_scene->isNonInteractiveIHNMDemoPart()) {
+ setMode(kPanelNull);
} else {
setMode(kPanelMain);
}
@@ -1564,11 +1567,9 @@ void Interface::setOption(PanelButton *panelButton) {
}
break;
case kTextSave:
- // Disallow saving in the non-interactive part of the IHNM demo
- if (_vm->getGameId() == GID_IHNM_DEMO) {
- if (_vm->_scene->currentSceneNumber() >= 144 && _vm->_scene->currentSceneNumber() <= 149)
- return;
- }
+ // Disallow saving in the non-interactive part of the IHNM demo (original demo didn't support saving at all)
+ if (_vm->_scene->isNonInteractiveIHNMDemoPart())
+ return;
if (!_vm->isSaveListFull() && (_optionSaveFileTitleNumber == 0)) {
_textInputString[0] = 0;
@@ -1787,10 +1788,8 @@ void Interface::update(const Point& mousePoint, int updateFlag) {
break;
case kPanelNull:
- if (_vm->getGameId() == GID_IHNM_DEMO && (updateFlag & UPDATE_MOUSECLICK)) {
- if (_vm->_scene->currentSceneNumber() >= 144 && _vm->_scene->currentSceneNumber() <= 149)
- _vm->_scene->showIHNMDemoSpecialScreen();
- }
+ if (_vm->_scene->isNonInteractiveIHNMDemoPart() && (updateFlag & UPDATE_MOUSECLICK))
+ _vm->_scene->showIHNMDemoSpecialScreen();
break;
}
@@ -1808,6 +1807,10 @@ void Interface::drawStatusBar() {
if (_vm->getGameType() == GType_IHNM && _vm->_scene->currentChapterNumber() == 8)
return;
+ // Don't draw the status bar while fading out
+ if (_fadeMode == kFadeOut)
+ return;
+
backBuffer = _vm->_gfx->getBackBuffer();
// Erase background of status bar
@@ -1921,7 +1924,6 @@ void Interface::handleMainUpdate(const Point& mousePoint) {
if ((panelButton != NULL) && (panelButton->type == kPanelButtonArrow)) {
if (panelButton->state == 1) {
- //TODO: insert timeout catchup
inventoryChangePos(panelButton->id);
}
changed = true;
@@ -1938,11 +1940,14 @@ void Interface::handleMainUpdate(const Point& mousePoint) {
//inventory stuff
void Interface::inventoryChangePos(int chg) {
- if ((chg < 0 && _inventoryStart + chg >= 0) ||
- (chg > 0 && _inventoryStart < _inventoryEnd)) {
- _inventoryStart += chg;
- draw();
+ // Arrows will scroll the inventory up or down up to 4 items
+ for (int i = 1; i <= 4; i++) {
+ if ((chg < 0 && _inventoryStart + chg >= 0) ||
+ (chg > 0 && _inventoryStart < _inventoryEnd)) {
+ _inventoryStart += chg;
}
+ }
+ draw();
}
void Interface::inventorySetPos(int key) {
@@ -2087,18 +2092,19 @@ void Interface::drawButtonBox(Surface *ds, const Rect& rect, ButtonKind kind, bo
solidColor = down ? kITEColorLightBlue94 : kITEColorLightBlue96;
break;
case kEdit:
- cornerColor = kITEColorLightBlue96;
- frameColor = kITEColorLightBlue96;
- fillColor = kITEColorLightBlue96;
- our = kITEColorDarkBlue8a;
- odl = kITEColorLightBlue94;
- iur = 0x97;
- idl = 0x95;
- if (down) {
- solidColor = kITEColorBlue;
+ if (_vm->getGameType() == GType_ITE) {
+ cornerColor = frameColor = fillColor = kITEColorLightBlue96;
+ our = kITEColorDarkBlue8a;
+ odl = kITEColorLightBlue94;
+ solidColor = down ? kITEColorBlue : kITEColorDarkGrey0C;
} else {
- solidColor = kITEColorDarkGrey0C;
+ cornerColor = frameColor = fillColor = kIHNMColorBlack;
+ our = kIHNMColorBlack;
+ odl = kIHNMColorBlack;
+ solidColor = kIHNMColorBlack;
}
+ iur = 0x97;
+ idl = 0x95;
break;
default:
cornerColor = 0x8b;
@@ -2248,21 +2254,25 @@ void Interface::drawPanelButtonText(Surface *ds, InterfacePanel *panel, PanelBut
litButton = panelButton->state > 0;
if (panel == &_optionPanel) {
- texturePoint.x = _optionPanel.x + panelButton->xOffset;
- texturePoint.y = _optionPanel.y + panelButton->yOffset;
+ texturePoint.x = _optionPanel.x + panelButton->xOffset - 1;
+ texturePoint.y = _optionPanel.y + panelButton->yOffset - 1;
_vm->_sprite->draw(ds, _vm->getDisplayClip(), _optionPanel.sprites, spritenum + 2 + litButton, texturePoint, 256);
} else if (panel == &_quitPanel) {
- texturePoint.x = _quitPanel.x + panelButton->xOffset;
- texturePoint.y = _quitPanel.y + panelButton->yOffset;
- _vm->_sprite->draw(ds, _vm->getDisplayClip(), _optionPanel.sprites, 14 + litButton, texturePoint, 256);
+ texturePoint.x = _quitPanel.x + panelButton->xOffset - 3;
+ texturePoint.y = _quitPanel.y + panelButton->yOffset - 3;
+ _vm->_sprite->draw(ds, _vm->getDisplayClip(), _quitPanel.sprites, litButton, texturePoint, 256);
} else if (panel == &_savePanel) {
- texturePoint.x = _savePanel.x + panelButton->xOffset;
- texturePoint.y = _savePanel.y + panelButton->yOffset;
- _vm->_sprite->draw(ds, _vm->getDisplayClip(), _optionPanel.sprites, 14 + litButton, texturePoint, 256);
+ texturePoint.x = _savePanel.x + panelButton->xOffset - 3;
+ texturePoint.y = _savePanel.y + panelButton->yOffset - 3;
+ _vm->_sprite->draw(ds, _vm->getDisplayClip(), _savePanel.sprites, litButton, texturePoint, 256);
+ // Input text box sprite
+ texturePoint.x = _savePanel.x + _saveEdit->xOffset - 2;
+ texturePoint.y = _savePanel.y + _saveEdit->yOffset - 2;
+ _vm->_sprite->draw(ds, _vm->getDisplayClip(), _savePanel.sprites, 2, texturePoint, 256);
} else if (panel == &_loadPanel) {
- texturePoint.x = _loadPanel.x + panelButton->xOffset;
- texturePoint.y = _loadPanel.y + panelButton->yOffset;
- _vm->_sprite->draw(ds, _vm->getDisplayClip(), _optionPanel.sprites, 14 + litButton, texturePoint, 256);
+ texturePoint.x = _loadPanel.x + panelButton->xOffset - 3;
+ texturePoint.y = _loadPanel.y + panelButton->yOffset - 3;
+ _vm->_sprite->draw(ds, _vm->getDisplayClip(), _loadPanel.sprites, litButton, texturePoint, 256);
} else {
// revert to default behavior
drawButtonBox(ds, rect, kButton, panelButton->state > 0);
@@ -2523,11 +2533,14 @@ void Interface::converseDisplayTextLines(Surface *ds) {
}
void Interface::converseChangePos(int chg) {
- if ((chg < 0 && _converseStartPos + chg >= 0) ||
- (chg > 0 && _converseStartPos < _converseEndPos)) {
- _converseStartPos += chg;
- draw();
+ // Arrows will scroll the converse panel or down up to 4 conversation options
+ for (int i = 1; i <= 4; i++) {
+ if ((chg < 0 && _converseStartPos + chg >= 0) ||
+ (chg > 0 && _converseStartPos < _converseEndPos)) {
+ _converseStartPos += chg;
+ }
}
+ draw();
}
void Interface::converseSetPos(int key) {
@@ -2580,7 +2593,6 @@ void Interface::handleConverseUpdate(const Point& mousePoint) {
if (_conversePanel.currentButton->type == kPanelButtonArrow) {
if (_conversePanel.currentButton->state == 1) {
- //TODO: insert timeout catchup
converseChangePos(_conversePanel.currentButton->id);
}
draw();
diff --git a/engines/saga/interface.h b/engines/saga/interface.h
index 7ae225219a..a8e2d5a647 100644
--- a/engines/saga/interface.h
+++ b/engines/saga/interface.h
@@ -28,6 +28,7 @@
#ifndef SAGA_INTERFACE_H
#define SAGA_INTERFACE_H
+#include "common/keyboard.h"
#include "common/savefile.h"
#include "saga/displayinfo.h"
@@ -225,7 +226,7 @@ public:
void drawStatusBar();
void setVerbState(int verb, int state);
- bool processAscii(uint16 ascii);
+ bool processAscii(Common::KeyState keystate);
void keyBoss();
void keyBossExit();
@@ -341,8 +342,8 @@ private:
void drawVerbPanelText(Surface *ds, PanelButton *panelButton, KnownColor textKnownColor, KnownColor textShadowKnownColor);
void drawVerbPanel(Surface *backBuffer, PanelButton* panelButton);
void calcOptionSaveSlider();
- bool processTextInput(uint16 ascii);
- void processStatusTextInput(uint16 ascii);
+ bool processTextInput(Common::KeyState keystate);
+ void processStatusTextInput(Common::KeyState keystate);
public:
void converseInit(void);
@@ -379,6 +380,7 @@ private:
public:
SpriteList _defPortraits;
+ PalEntry _portraitBgColor;
private:
SagaEngine *_vm;
@@ -416,7 +418,6 @@ private:
int _statusOnceColor;
int _leftPortrait;
int _rightPortrait;
- PalEntry _portraitBgColor;
Point _lastMousePoint;
diff --git a/engines/saga/ite_introproc.cpp b/engines/saga/ite_introproc.cpp
index 1664969644..1b74d41cb7 100644
--- a/engines/saga/ite_introproc.cpp
+++ b/engines/saga/ite_introproc.cpp
@@ -115,7 +115,6 @@ Event *Scene::ITEQueueDialogue(Event *q_event, int n_dialogues, const IntroDialo
event.op = kEventDisplay;
event.data = entry;
event.time = (i == 0) ? 0 : VOICE_PAD;
-
q_event = _vm->_events->chain(q_event, &event);
// Play voice
@@ -124,7 +123,6 @@ Event *Scene::ITEQueueDialogue(Event *q_event, int n_dialogues, const IntroDialo
event.op = kEventPlay;
event.param = dialogue[i].i_voice_rn;
event.time = 0;
-
q_event = _vm->_events->chain(q_event, &event);
voice_len = _vm->_sndRes->getVoiceLength(dialogue[i].i_voice_rn);
@@ -138,7 +136,6 @@ Event *Scene::ITEQueueDialogue(Event *q_event, int n_dialogues, const IntroDialo
event.op = kEventRemove;
event.data = entry;
event.time = voice_len;
-
q_event = _vm->_events->chain(q_event, &event);
}
@@ -265,7 +262,6 @@ Event *Scene::ITEQueueCredits(int delta_time, int duration, int n_credits, const
event.op = kEventDisplay;
event.data = entry;
event.time = delta_time;
-
q_event = _vm->_events->queue(&event);
// Remove text
@@ -274,7 +270,6 @@ Event *Scene::ITEQueueCredits(int delta_time, int duration, int n_credits, const
event.op = kEventRemove;
event.data = entry;
event.time = duration;
-
q_event = _vm->_events->chain(q_event, &event);
y += (_vm->_font->getHeight(font) + line_spacing);
@@ -301,7 +296,6 @@ int Scene::ITEIntroAnimProc(int param) {
event.op = kEventDisplay;
event.param = kEvPSetPalette;
event.time = 0;
-
q_event = _vm->_events->queue(&event);
debug(3, "Intro animation procedure started.");
@@ -340,7 +334,6 @@ int Scene::ITEIntroAnimProc(int param) {
event.op = kEventPlay;
event.param = 0;
event.time = 0;
-
q_event = _vm->_events->chain(q_event, &event);
// Queue intro music playback
@@ -350,7 +343,6 @@ int Scene::ITEIntroAnimProc(int param) {
event.param2 = MUSIC_LOOP;
event.op = kEventPlay;
event.time = 0;
-
q_event = _vm->_events->chain(q_event, &event);
}
break;
@@ -427,7 +419,6 @@ int Scene::ITEIntroCave1Proc(int param) {
event.code = kPalAnimEvent;
event.op = kEventCycleStart;
event.time = 0;
-
q_event = _vm->_events->queue(&event);
// Queue narrator dialogue list
@@ -438,8 +429,8 @@ int Scene::ITEIntroCave1Proc(int param) {
event.code = kSceneEvent;
event.op = kEventEnd;
event.time = VOICE_PAD;
-
q_event = _vm->_events->chain(q_event, &event);
+
break;
case SCENE_END:
break;
@@ -504,7 +495,6 @@ int Scene::ITEIntroCave2Proc(int param) {
event.op = kEventDissolve;
event.time = 0;
event.duration = DISSOLVE_DURATION;
-
q_event = _vm->_events->queue(&event);
// Begin palette cycling animation for candles
@@ -512,7 +502,6 @@ int Scene::ITEIntroCave2Proc(int param) {
event.code = kPalAnimEvent;
event.op = kEventCycleStart;
event.time = 0;
-
q_event = _vm->_events->chain(q_event, &event);
// Queue narrator dialogue list
@@ -523,8 +512,8 @@ int Scene::ITEIntroCave2Proc(int param) {
event.code = kSceneEvent;
event.op = kEventEnd;
event.time = VOICE_PAD;
-
q_event = _vm->_events->chain(q_event, &event);
+
break;
case SCENE_END:
break;
@@ -588,7 +577,6 @@ int Scene::ITEIntroCave3Proc(int param) {
event.op = kEventDissolve;
event.time = 0;
event.duration = DISSOLVE_DURATION;
-
q_event = _vm->_events->queue(&event);
// Begin palette cycling animation for candles
@@ -596,7 +584,6 @@ int Scene::ITEIntroCave3Proc(int param) {
event.code = kPalAnimEvent;
event.op = kEventCycleStart;
event.time = 0;
-
q_event = _vm->_events->chain(q_event, &event);
// Queue narrator dialogue list
@@ -607,8 +594,8 @@ int Scene::ITEIntroCave3Proc(int param) {
event.code = kSceneEvent;
event.op = kEventEnd;
event.time = VOICE_PAD;
-
q_event = _vm->_events->chain(q_event, &event);
+
break;
case SCENE_END:
break;
@@ -681,7 +668,6 @@ int Scene::ITEIntroCave4Proc(int param) {
event.op = kEventDissolve;
event.time = 0;
event.duration = DISSOLVE_DURATION;
-
q_event = _vm->_events->queue(&event);
// Begin palette cycling animation for candles
@@ -689,7 +675,6 @@ int Scene::ITEIntroCave4Proc(int param) {
event.code = kPalAnimEvent;
event.op = kEventCycleStart;
event.time = 0;
-
q_event = _vm->_events->chain(q_event, &event);
// Queue narrator dialogue list
@@ -700,8 +685,8 @@ int Scene::ITEIntroCave4Proc(int param) {
event.code = kSceneEvent;
event.op = kEventEnd;
event.time = VOICE_PAD;
-
q_event = _vm->_events->chain(q_event, &event);
+
break;
case SCENE_END:
break;
@@ -747,7 +732,6 @@ int Scene::ITEIntroValleyProc(int param) {
event.op = kEventPlay;
event.param = 0;
event.time = 0;
-
q_event = _vm->_events->queue(&event);
// Begin ITE title theme music
@@ -759,7 +743,6 @@ int Scene::ITEIntroValleyProc(int param) {
event.param2 = MUSIC_NORMAL;
event.op = kEventPlay;
event.time = 0;
-
q_event = _vm->_events->chain(q_event, &event);
// Pause animation before logo
@@ -768,7 +751,6 @@ int Scene::ITEIntroValleyProc(int param) {
event.op = kEventStop;
event.param = 0;
event.time = 3000;
-
q_event = _vm->_events->chain(q_event, &event);
// Display logo
@@ -777,7 +759,6 @@ int Scene::ITEIntroValleyProc(int param) {
event.op = kEventDissolveBGMask;
event.time = 0;
event.duration = LOGO_DISSOLVE_DURATION;
-
q_event = _vm->_events->chain(q_event, &event);
// Remove logo
@@ -786,7 +767,6 @@ int Scene::ITEIntroValleyProc(int param) {
event.op = kEventDissolve;
event.time = 3000;
event.duration = LOGO_DISSOLVE_DURATION;
-
q_event = _vm->_events->chain(q_event, &event);
// Unpause animation before logo
@@ -795,7 +775,6 @@ int Scene::ITEIntroValleyProc(int param) {
event.op = kEventPlay;
event.time = 0;
event.param = 0;
-
q_event = _vm->_events->chain(q_event, &event);
// Queue game credits list
@@ -806,8 +785,8 @@ int Scene::ITEIntroValleyProc(int param) {
event.code = kSceneEvent;
event.op = kEventEnd;
event.time = 1000;
-
q_event = _vm->_events->chain(q_event, &event);
+
break;
case SCENE_END:
break;
@@ -870,7 +849,6 @@ int Scene::ITEIntroTreeHouseProc(int param) {
event.op = kEventDissolve;
event.time = 0;
event.duration = DISSOLVE_DURATION;
-
q_event = _vm->_events->queue(&event);
if (_vm->_anim->hasAnimation(0)) {
@@ -882,7 +860,6 @@ int Scene::ITEIntroTreeHouseProc(int param) {
event.op = kEventPlay;
event.param = 0;
event.time = 0;
-
q_event = _vm->_events->chain(q_event, &event);
}
@@ -895,8 +872,8 @@ int Scene::ITEIntroTreeHouseProc(int param) {
event.code = kSceneEvent;
event.op = kEventEnd;
event.time = 1000;
-
q_event = _vm->_events->chain(q_event, &event);
+
break;
case SCENE_END:
break;
@@ -950,7 +927,6 @@ int Scene::ITEIntroFairePathProc(int param) {
event.op = kEventDissolve;
event.time = 0;
event.duration = DISSOLVE_DURATION;
-
q_event = _vm->_events->queue(&event);
// Begin title screen background animation
@@ -961,7 +937,6 @@ int Scene::ITEIntroFairePathProc(int param) {
event.op = kEventPlay;
event.param = 0;
event.time = 0;
-
q_event = _vm->_events->chain(q_event, &event);
// Queue game credits list
@@ -973,8 +948,8 @@ int Scene::ITEIntroFairePathProc(int param) {
event.code = kSceneEvent;
event.op = kEventEnd;
event.time = 1000;
-
q_event = _vm->_events->chain(q_event, &event);
+
break;
case SCENE_END:
break;
@@ -1005,7 +980,6 @@ int Scene::ITEIntroFaireTentProc(int param) {
event.op = kEventDissolve;
event.time = 0;
event.duration = DISSOLVE_DURATION;
-
q_event_start = _vm->_events->queue(&event);
// End scene after momentary pause
@@ -1014,6 +988,7 @@ int Scene::ITEIntroFaireTentProc(int param) {
event.op = kEventEnd;
event.time = 5000;
q_event = _vm->_events->chain(q_event_start, &event);
+
break;
case SCENE_END:
break;
diff --git a/engines/saga/itedata.h b/engines/saga/itedata.h
index d9bd59adc4..3c594b5fec 100644
--- a/engines/saga/itedata.h
+++ b/engines/saga/itedata.h
@@ -41,9 +41,6 @@ enum ActorFlags {
kNoScale = 0x80 // (1<<7) Actor is not scaled
};
-// TODO: This doesn't quite correspond to the original Actor struct, so I'm not
-// sure if I got it right.
-
struct ActorTableData {
byte flags;
byte nameIndex;
diff --git a/engines/saga/module.mk b/engines/saga/module.mk
index 6c1812ad23..68cf91be32 100644
--- a/engines/saga/module.mk
+++ b/engines/saga/module.mk
@@ -2,6 +2,7 @@ MODULE := engines/saga
MODULE_OBJS := \
actor.o \
+ actor_walk.o \
animation.o \
console.o \
detection.o \
diff --git a/engines/saga/music.cpp b/engines/saga/music.cpp
index 04e79c174d..6b233e0256 100644
--- a/engines/saga/music.cpp
+++ b/engines/saga/music.cpp
@@ -92,7 +92,7 @@ DigitalMusicInputStream::DigitalMusicInputStream(SagaEngine *vm, ResourceContext
_compressedStream = NULL;
- if (Common::File::exists("music.cmp")) {
+ if (Common::File::exists("music.cmp") || Common::File::exists("musicd.cmp")) {
// Read compressed header to determine compression type
_file->seek((long)resourceData->offset, SEEK_SET);
_file->read(compressedHeader, 9);
@@ -320,6 +320,8 @@ void MusicPlayer::metaEvent(byte type, byte *data, uint16 length) {
void MusicPlayer::onTimer(void *refCon) {
MusicPlayer *music = (MusicPlayer *)refCon;
+ Common::StackLock lock(music->_mutex);
+
if (music->_isPlaying)
music->_parser->onTimer();
}
@@ -329,6 +331,8 @@ void MusicPlayer::playMusic() {
}
void MusicPlayer::stopMusic() {
+ Common::StackLock lock(_mutex);
+
_isPlaying = false;
if (_parser) {
_parser->unloadMusic();
@@ -352,6 +356,7 @@ Music::Music(SagaEngine *vm, Audio::Mixer *mixer, MidiDriver *driver, int enable
}
Music::~Music() {
+ _vm->_timer->removeTimerProc(&musicVolumeGaugeCallback);
_mixer->stopHandle(_musicHandle);
delete _player;
xmidiParser->setMidiDriver(NULL);
@@ -561,7 +566,7 @@ void Music::play(uint32 resourceId, MusicFlags flags) {
parser->property(MidiParser::mpCenterPitchWheelOnUnload, 1);
_player->_parser = parser;
- _player->setVolume(_vm->_musicVolume == 10 ? 255 : _vm->_musicVolume * 25);
+ setVolume(_vm->_musicVolume == 10 ? 255 : _vm->_musicVolume * 25);
if (flags & MUSIC_LOOP)
_player->setLoop(true);
@@ -574,15 +579,17 @@ void Music::play(uint32 resourceId, MusicFlags flags) {
}
void Music::pause(void) {
- //TODO: do it
+ _player->setVolume(-1);
+ _player->setPlaying(false);
}
void Music::resume(void) {
- //TODO: do it}
+ _player->setVolume(_vm->_musicVolume == 10 ? 255 : _vm->_musicVolume * 25);
+ _player->setPlaying(true);
}
void Music::stop(void) {
- //TODO: do it
+ _player->stopMusic();
}
} // End of namespace Saga
diff --git a/engines/saga/music.h b/engines/saga/music.h
index b038a25a11..1fbdda53f2 100644
--- a/engines/saga/music.h
+++ b/engines/saga/music.h
@@ -34,6 +34,7 @@
#include "sound/mp3.h"
#include "sound/vorbis.h"
#include "sound/flac.h"
+#include "common/mutex.h"
namespace Saga {
@@ -49,6 +50,7 @@ public:
~MusicPlayer();
bool isPlaying() { return _isPlaying; }
+ void setPlaying(bool playing) { _isPlaying = playing; }
void setVolume(int volume);
int getVolume() { return _masterVolume; }
@@ -77,6 +79,7 @@ public:
MidiChannel *getPercussionChannel() { return 0; }
MidiParser *_parser;
+ Common::Mutex _mutex;
protected:
diff --git a/engines/saga/palanim.cpp b/engines/saga/palanim.cpp
index 19c2fc4d40..f318b815cc 100644
--- a/engines/saga/palanim.cpp
+++ b/engines/saga/palanim.cpp
@@ -131,7 +131,6 @@ int PalAnim::cycleStart() {
event.code = kPalAnimEvent;
event.op = kEventCycleStep;
event.time = PALANIM_CYCLETIME;
-
_vm->_events->queue(&event);
return SUCCESS;
@@ -178,7 +177,6 @@ int PalAnim::cycleStep(int vectortime) {
event.code = kPalAnimEvent;
event.op = kEventCycleStep;
event.time = vectortime + PALANIM_CYCLETIME;
-
_vm->_events->queue(&event);
return SUCCESS;
diff --git a/engines/saga/render.cpp b/engines/saga/render.cpp
index 930476b4e2..e006b4a627 100644
--- a/engines/saga/render.cpp
+++ b/engines/saga/render.cpp
@@ -85,11 +85,12 @@ void Render::drawScene() {
// Get mouse coordinates
mousePoint = _vm->mousePos();
- if (!(_flags & (RF_DEMO_SUBST | RF_PLACARD | RF_MAP))) {
- // Display scene background
- _vm->_scene->draw();
-
+ if (!(_flags & (RF_DEMO_SUBST | RF_MAP) || _vm->_interface->getMode() == kPanelPlacard)) {
if (_vm->_interface->getFadeMode() != kFadeOut) {
+ // Display scene background
+ if (!(_flags & RF_DISABLE_ACTORS))
+ _vm->_scene->draw();
+
if (_vm->_puzzle->isActive()) {
_vm->_puzzle->movePiece(mousePoint);
_vm->_actor->drawSpeech();
diff --git a/engines/saga/render.h b/engines/saga/render.h
index 4c6e3ee5b1..95abc2e4df 100644
--- a/engines/saga/render.h
+++ b/engines/saga/render.h
@@ -39,11 +39,10 @@ enum RENDER_FLAGS {
RF_OBJECTMAP_TEST = (1 << 3),
RF_RENDERPAUSE = (1 << 4),
RF_GAMEPAUSE = (1 << 5),
- RF_PLACARD = (1 << 6),
- RF_ACTOR_PATH_TEST = (1 << 7),
- RF_MAP = (1 << 8),
- RF_DISABLE_ACTORS = (1 << 9),
- RF_DEMO_SUBST = (1 << 10)
+ RF_ACTOR_PATH_TEST = (1 << 6),
+ RF_MAP = (1 << 7),
+ RF_DISABLE_ACTORS = (1 << 8),
+ RF_DEMO_SUBST = (1 << 9)
};
class Render {
diff --git a/engines/saga/rscfile.cpp b/engines/saga/rscfile.cpp
index 4d3ff1e47c..ba56e838b7 100644
--- a/engines/saga/rscfile.cpp
+++ b/engines/saga/rscfile.cpp
@@ -330,7 +330,11 @@ bool Resource::loadContext(ResourceContext *context) {
if (resourceData->patchData->_patchFile->open(patchDescription->fileName)) {
resourceData->offset = 0;
resourceData->size = resourceData->patchData->_patchFile->size();
- resourceData->patchData->_patchFile->close();
+ // ITE uses several patch files which are loaded and then not needed
+ // anymore (as they're in memory), so close them here. IHNM uses only
+ // 1 patch file, which is reused, so don't close it
+ if (_vm->getGameType() == GType_ITE)
+ resourceData->patchData->_patchFile->close();
} else {
delete resourceData->patchData;
resourceData->patchData = NULL;
@@ -606,7 +610,11 @@ void Resource::loadResource(ResourceContext *context, uint32 resourceId, byte*&r
if (file->read(resourceBuffer, resourceSize) != resourceSize) {
error("Resource::loadResource() failed to read");
}
- if (resourceData->patchData != NULL)
+
+ // ITE uses several patch files which are loaded and then not needed
+ // anymore (as they're in memory), so close them here. IHNM uses only
+ // 1 patch file, which is reused, so don't close it
+ if (resourceData->patchData != NULL && _vm->getGameType() == GType_ITE)
file->close();
}
@@ -742,6 +750,12 @@ void Resource::loadGlobalResources(int chapter, int actorsEntrance) {
if (_metaResource.songTableID > 0) {
_vm->_resource->loadResource(resourceContext, _metaResource.songTableID, resourcePointer, resourceLength);
+ if (chapter == 6) {
+ int32 id = READ_LE_UINT32(&resourcePointer[actorsEntrance * 4]);
+ free(resourcePointer);
+ _vm->_resource->loadResource(resourceContext, id, resourcePointer, resourceLength);
+ }
+
if (resourceLength == 0) {
error("Resource::loadGlobalResources Can't load songs list for current track");
}
@@ -758,6 +772,7 @@ void Resource::loadGlobalResources(int chapter, int actorsEntrance) {
free(resourcePointer);
} else {
// The IHNM demo has a fixed music track and doesn't load a song table
+ _vm->_music->setVolume(_vm->_musicVolume == 10 ? -1 : _vm->_musicVolume * 25, 1);
_vm->_music->play(3, MUSIC_LOOP);
}
diff --git a/engines/saga/saga.cpp b/engines/saga/saga.cpp
index 76731c201a..01a75f4af1 100644
--- a/engines/saga/saga.cpp
+++ b/engines/saga/saga.cpp
@@ -259,10 +259,10 @@ int SagaEngine::go() {
_scene->changeScene(getStartSceneNumber(), 0, kTransitionNoFade);
_events->handleEvents(0); // Process immediate events
+ _interface->setMode(kPanelMain);
char *fileName;
fileName = calcSaveFileName(ConfMan.getInt("save_slot"));
load(fileName);
- _interface->setMode(kPanelMain);
} else {
_framesEsc = 0;
_scene->startScene();
@@ -428,6 +428,9 @@ ColorId SagaEngine::KnownColor2ColorId(KnownColor knownColor) {
case (kKnownColorBrightWhite):
colorId = kITEColorBrightWhite;
break;
+ case (kKnownColorWhite):
+ colorId = kITEColorWhite;
+ break;
case (kKnownColorBlack):
colorId = kITEColorBlack;
break;
@@ -449,8 +452,7 @@ ColorId SagaEngine::KnownColor2ColorId(KnownColor knownColor) {
error("SagaEngine::KnownColor2ColorId unknown color %i", knownColor);
}
} else if (getGameType() == GType_IHNM) {
- switch (knownColor)
- {
+ switch (knownColor) {
case(kKnownColorTransparent):
colorId = kITEColorTransBlack;
break;
@@ -458,6 +460,9 @@ ColorId SagaEngine::KnownColor2ColorId(KnownColor knownColor) {
case (kKnownColorBrightWhite):
colorId = kITEColorBrightWhite;
break;
+ case (kKnownColorWhite):
+ colorId = kITEColorBrightWhite;
+ break;
case (kKnownColorBlack):
colorId = kIHNMColorBlack;
break;
diff --git a/engines/saga/saga.h b/engines/saga/saga.h
index 43952fe564..8016fb9e65 100644
--- a/engines/saga/saga.h
+++ b/engines/saga/saga.h
@@ -69,7 +69,12 @@ struct StringList;
#define MAXPATH 512 //TODO: remove
+// Note that IHNM has a smaller save title size than ITE
+// We allocate the ITE save title size in savegames, to
+// preserve savegame backwards compatibility. We only check
+// for IHNM's save title during text input
#define SAVE_TITLE_SIZE 28
+#define IHNM_SAVE_TITLE_SIZE 22
#define MAX_SAVES 96
#define MAX_FILE_NAME 256
@@ -153,7 +158,8 @@ enum GameFeatures {
GF_WYRMKEEP = 1 << 1,
GF_CD_FX = 1 << 2,
GF_SCENE_SUBSTITUTES = 1 << 3,
- GF_COMPRESSED_SOUNDS = 1 << 4
+ GF_COMPRESSED_SOUNDS = 1 << 4,
+ GF_NON_INTERACTIVE = 1 << 5
};
enum VerbTypeIds {
@@ -297,6 +303,7 @@ struct GameResourceDescription {
uint32 conversePanelResourceId;
uint32 optionPanelResourceId;
uint32 warningPanelResourceId;
+ uint32 warningPanelSpritesResourceId;
uint32 mainSpritesResourceId;
uint32 mainPanelSpritesResourceId;
uint32 optionPanelSpritesResourceId;
@@ -441,6 +448,7 @@ enum ColorId {
enum KnownColor {
kKnownColorTransparent,
kKnownColorBrightWhite,
+ kKnownColorWhite,
kKnownColorBlack,
kKnownColorSubtitleTextColor,
diff --git a/engines/saga/sagaresnames.h b/engines/saga/sagaresnames.h
index 761ac1ab68..b416d85fd8 100644
--- a/engines/saga/sagaresnames.h
+++ b/engines/saga/sagaresnames.h
@@ -108,6 +108,7 @@ namespace Saga {
#define RID_IHNM_OPTION_PANEL 15
#define RID_IHNM_OPTION_PANEL_SPRITES 16
#define RID_IHNM_WARNING_PANEL 17
+#define RID_IHNM_WARNING_PANEL_SPRITES 18
#define RID_IHNM_BOSS_SCREEN 19
#define RID_IHNM_PROFILE_BG 20
#define RID_IHNM_MAIN_STRINGS 21
@@ -122,7 +123,8 @@ namespace Saga {
#define RID_IHNMDEMO_OPTION_PANEL 10
#define RID_IHNMDEMO_OPTION_PANEL_SPRITES 11
#define RID_IHNMDEMO_WARNING_PANEL 12
-#define RID_IHNMDEMO_BOSS_SCREEN 13 // Does not exist in the demo
+#define RID_IHNMDEMO_WARNING_PANEL_SPRITES 13
+#define RID_IHNMDEMO_BOSS_SCREEN 14 // Does not exist in the demo
#define RID_IHNMDEMO_PROFILE_BG 15
#define RID_IHNMDEMO_MAIN_STRINGS 16
diff --git a/engines/saga/saveload.cpp b/engines/saga/saveload.cpp
index 77d7816963..6e731de44e 100644
--- a/engines/saga/saveload.cpp
+++ b/engines/saga/saveload.cpp
@@ -187,6 +187,9 @@ void SagaEngine::save(const char *fileName, const char *saveName) {
_saveHeader.type = MKID_BE('SAGA');
_saveHeader.size = 0;
_saveHeader.version = CURRENT_SAGA_VER;
+ // Note that IHNM has a smaller save title size than ITE
+ // We allocate the ITE save title size here, to preserve
+ // savegame backwards compatibility
strncpy(_saveHeader.name, saveName, SAVE_TITLE_SIZE);
out->writeUint32BE(_saveHeader.type);
@@ -255,8 +258,8 @@ void SagaEngine::load(const char *fileName) {
// Some older saves were not written in an endian safe fashion.
// We try to detect this here by checking for extremly high version values.
// If found, we retry with the data swapped.
- // FIXME: Maybe display a warning/error message instead?
if (_saveHeader.version > 0xFFFFFF) {
+ warning("This savegame is not endian safe, retrying with the data swapped");
_saveHeader.version = SWAP_BYTES_32(_saveHeader.version);
}
@@ -276,7 +279,6 @@ void SagaEngine::load(const char *fileName) {
// Surrounding scene
sceneNumber = in->readSint32LE();
- // Protagonist
if (getGameType() != GType_ITE) {
int currentChapter = _scene->currentChapterNumber();
_scene->setChapterNumber(in->readSint32LE());
@@ -286,10 +288,13 @@ void SagaEngine::load(const char *fileName) {
_scene->setCurrentMusicTrack(in->readSint32LE());
_scene->setCurrentMusicRepeat(in->readSint32LE());
_music->stop();
- if (getGameId() != GID_IHNM_DEMO)
+ if (_scene->currentChapterNumber() == 8)
+ _interface->setMode(kPanelChapterSelection);
+ if (getGameId() != GID_IHNM_DEMO) {
_music->play(_music->_songTable[_scene->getCurrentMusicTrack()], _scene->getCurrentMusicRepeat() ? MUSIC_LOOP : MUSIC_NORMAL);
- else
+ } else {
_music->play(3, MUSIC_LOOP);
+ }
}
// Inset scene
@@ -323,11 +328,14 @@ void SagaEngine::load(const char *fileName) {
if (getGameType() != GType_ITE) {
if (_scene->currentProtag() != 0 && _scene->currentChapterNumber() != 6) {
ActorData *actor1 = _actor->getFirstActor();
- // Original stores the current protagonist ID from sfSwapActors:
- //ActorData *actor2 = _actor->getActor(_scene->currentProtag());
- // However, we already store the protagonist, so merely getting the saved
- // protagonist is easier and safer, and works without glitches
- ActorData *actor2 = _actor->_protagonist;
+ ActorData *actor2;
+ // The original gets actor2 from the current protagonist ID, but this is sometimes wrong
+ // If the current protagonist ID is not correct, use the stored protagonist
+ if (!_actor->validActorId(_scene->currentProtag())) {
+ actor2 = _actor->_protagonist;
+ } else {
+ actor2 = _actor->getActor(_scene->currentProtag());
+ }
SWAP(actor1->_location, actor2->_location);
@@ -345,6 +353,7 @@ void SagaEngine::load(const char *fileName) {
if (insetSceneNumber != sceneNumber) {
_render->setFlag(RF_DISABLE_ACTORS);
+ _scene->draw();
_render->drawScene();
_render->clearFlag(RF_DISABLE_ACTORS);
_scene->changeScene(insetSceneNumber, ACTOR_NO_ENTRANCE, kTransitionNoFade);
diff --git a/engines/saga/scene.cpp b/engines/saga/scene.cpp
index c49fe546ee..a80b482e47 100644
--- a/engines/saga/scene.cpp
+++ b/engines/saga/scene.cpp
@@ -205,6 +205,7 @@ Scene::Scene(SagaEngine *vm) : _vm(vm) {
_sceneLoaded = false;
_sceneNumber = 0;
+ _chapterNumber = 0;
_sceneResourceId = 0;
_inGame = false;
_loadDescription = false;
@@ -281,6 +282,9 @@ void Scene::startScene() {
break;
}
+ // Stop the intro music
+ _vm->_music->stop();
+
// Load the head in scene queue
queueIterator = _sceneQueue.begin();
if (queueIterator == _sceneQueue.end()) {
@@ -292,6 +296,31 @@ void Scene::startScene() {
loadScene(sceneQueue);
}
+void Scene::creditsScene() {
+ // End the last game ending scene
+ _vm->_scene->endScene();
+ // We're not in the game anymore
+ _inGame = false;
+
+ // Hide cursor during credits
+ _vm->_gfx->showCursor(false);
+
+ switch (_vm->getGameType()) {
+ case GType_ITE:
+ // Not called by ITE
+ break;
+ case GType_IHNM:
+ IHNMCreditsProc();
+ break;
+ default:
+ error("Scene::creditsScene(): Error: Can't start credits scene... gametype not supported");
+ break;
+ }
+
+ _vm->shutDown();
+ return;
+}
+
void Scene::nextScene() {
SceneQueueList::iterator queueIterator;
LoadSceneParams *sceneQueue;
@@ -561,6 +590,9 @@ void Scene::loadScene(LoadSceneParams *loadSceneParams) {
Event *q_event;
static PalEntry current_pal[PAL_ENTRIES];
+ if (loadSceneParams->transitionType == kTransitionFade)
+ _vm->_interface->setFadeMode(kFadeOut);
+
// Change the cursor to an hourglass in IHNM
event.type = kEvTOneshot;
event.code = kCursorEvent;
@@ -575,19 +607,11 @@ void Scene::loadScene(LoadSceneParams *loadSceneParams) {
error("loadScene wrong usage");
}
- if (loadSceneParams->chapter == 6)
+ if (loadSceneParams->chapter == 6 || loadSceneParams->chapter == 8)
_vm->_interface->setLeftPortrait(0);
_vm->_anim->freeCutawayList();
- // FIXME: Freed script modules are not reloaded correctly when changing chapters.
- // This is apparent when returning back to the character selection screen,
- // where the scene script module is loaded incorrectly
- // Don't free them for now, but free them on game exit, like ITE.
- // This has no impact on the game itself (other than increased memory usage),
- // as each chapter uses a different module slot
- // TODO: Find out why the script modules are not loaded correctly when
- // changing chapters and uncomment this again
- //_vm->_script->freeModules();
+ _vm->_script->freeModules();
// deleteAllScenes();
@@ -612,6 +636,7 @@ void Scene::loadScene(LoadSceneParams *loadSceneParams) {
_vm->_script->setVerb(_vm->_script->getVerbType(kVerbWalkTo));
if (loadSceneParams->sceneDescriptor == -2) {
+ _vm->_interface->setFadeMode(kNoFade);
return;
}
}
@@ -651,11 +676,11 @@ void Scene::loadScene(LoadSceneParams *loadSceneParams) {
debug(3, "Loading scene number %d:", _sceneNumber);
- if (_vm->getGameId() == GID_IHNM_DEMO && _sceneNumber == 144) {
+ if (isNonInteractiveIHNMDemoPart()) {
// WORKAROUND for the non-interactive part of the IHNM demo: When restarting the
- // non-interactive demo, opcode sfMainMode is incorrectly called. Therefore, if the
- // starting scene of the non-interactive demo is loaded (scene 144), set panel to null
- // and lock the user interface
+ // non-interactive demo, opcode sfMainMode is incorrectly called. Therefore, if any
+ // of the scenes of the non-interactive demo are loaded (scenes 144-149), set panel
+ // to null and lock the user interface
_vm->_interface->deactivate();
_vm->_interface->setMode(kPanelNull);
}
@@ -709,15 +734,6 @@ void Scene::loadScene(LoadSceneParams *loadSceneParams) {
q_event = NULL;
- //fix placard bug
- //i guess we should remove RF_PLACARD flag - and use _interface->getMode()
- event.type = kEvTOneshot;
- event.code = kGraphicsEvent;
- event.op = kEventClearFlag;
- event.param = RF_PLACARD;
-
- q_event = _vm->_events->chain(q_event, &event);
-
if (loadSceneParams->transitionType == kTransitionFade) {
_vm->_interface->setFadeMode(kFadeOut);
@@ -764,7 +780,6 @@ void Scene::loadScene(LoadSceneParams *loadSceneParams) {
event.param4 = _sceneNumber; // Object
event.param5 = loadSceneParams->actorsEntrance; // With Object
event.param6 = 0; // Actor
-
q_event = _vm->_events->chain(q_event, &event);
}
@@ -786,7 +801,6 @@ void Scene::loadScene(LoadSceneParams *loadSceneParams) {
event.time = 0;
event.duration = kNormalFadeDuration;
event.data = _bg.pal;
-
q_event = _vm->_events->chain(q_event, &event);
// set fade mode
@@ -807,11 +821,6 @@ void Scene::loadScene(LoadSceneParams *loadSceneParams) {
_vm->_sound->stopAll();
- // FIXME: Does IHNM use scene background music, or is all the
- // music scripted? At the very least, it shouldn't try
- // to start song 0 at the beginning of the game, since
- // it's the end credits music.
-
if (_vm->getGameType() == GType_ITE) {
if (_sceneDescription.musicResourceId >= 0) {
event.type = kEvTOneshot;
@@ -820,14 +829,12 @@ void Scene::loadScene(LoadSceneParams *loadSceneParams) {
event.param2 = MUSIC_DEFAULT;
event.op = kEventPlay;
event.time = 0;
-
_vm->_events->queue(&event);
} else {
event.type = kEvTOneshot;
event.code = kMusicEvent;
event.op = kEventStop;
event.time = 0;
-
_vm->_events->queue(&event);
}
}
@@ -838,7 +845,6 @@ void Scene::loadScene(LoadSceneParams *loadSceneParams) {
event.op = kEventDisplay;
event.param = kEvPSetPalette;
event.time = 0;
-
_vm->_events->queue(&event);
// Begin palette cycle animation if present
@@ -846,7 +852,6 @@ void Scene::loadScene(LoadSceneParams *loadSceneParams) {
event.code = kPalAnimEvent;
event.op = kEventCycleStart;
event.time = 0;
-
q_event = _vm->_events->queue(&event);
// Start the scene main script
@@ -861,7 +866,6 @@ void Scene::loadScene(LoadSceneParams *loadSceneParams) {
event.param4 = _sceneNumber; // Object
event.param5 = loadSceneParams->actorsEntrance; // With Object
event.param6 = 0; // Actor
-
_vm->_events->queue(&event);
}
@@ -1178,7 +1182,9 @@ void Scene::endScene() {
_sceneProc(SCENE_END, this);
}
- //
+ // Stop showing actors till the next scene's background is drawn from loadScene
+ _vm->_render->setFlag(RF_DISABLE_ACTORS);
+
_vm->_script->abortAllThreads();
_vm->_script->_skipSpeeches = false;
@@ -1308,31 +1314,38 @@ void Scene::clearPlacard() {
Event event;
Event *q_event;
- _vm->_interface->restoreMode();
+ _vm->_interface->setFadeMode(kFadeOut);
+ // Fade to black out
_vm->_gfx->getCurrentPal(cur_pal);
-
event.type = kEvTImmediate;
event.code = kPalEvent;
event.op = kEventPalToBlack;
event.time = 0;
event.duration = kNormalFadeDuration;
event.data = cur_pal;
-
q_event = _vm->_events->queue(&event);
- event.type = kEvTOneshot;
- event.code = kGraphicsEvent;
- event.op = kEventClearFlag;
- event.param = RF_PLACARD;
-
+ // set fade mode
+ event.type = kEvTImmediate;
+ event.code = kInterfaceEvent;
+ event.op = kEventSetFadeMode;
+ event.param = kNoFade;
+ event.time = 0;
+ event.duration = 0;
q_event = _vm->_events->chain(q_event, &event);
event.type = kEvTOneshot;
event.code = kTextEvent;
event.op = kEventRemove;
event.data = _vm->_script->getPlacardTextEntry();
+ q_event = _vm->_events->chain(q_event, &event);
+ event.type = kEvTImmediate;
+ event.code = kInterfaceEvent;
+ event.op = kEventRestoreMode;
+ event.time = 0;
+ event.duration = 0;
q_event = _vm->_events->chain(q_event, &event);
_vm->_scene->getBGPal(pal);
@@ -1343,20 +1356,17 @@ void Scene::clearPlacard() {
event.time = 0;
event.duration = kNormalFadeDuration;
event.data = pal;
-
q_event = _vm->_events->chain(q_event, &event);
event.type = kEvTOneshot;
event.code = kCursorEvent;
event.op = kEventShow;
-
q_event = _vm->_events->chain(q_event, &event);
event.type = kEvTOneshot;
event.code = kScriptEvent;
event.op = kEventThreadWake;
event.param = kWaitTypePlacard;
-
q_event = _vm->_events->chain(q_event, &event);
}
@@ -1378,37 +1388,37 @@ void Scene::showPsychicProfile(const char *text) {
event.type = kEvTOneshot;
event.code = kCursorEvent;
event.op = kEventHide;
-
q_event = _vm->_events->queue(&event);
- _vm->_gfx->getCurrentPal(cur_pal);
+ _vm->_interface->setFadeMode(kFadeOut);
+ // Fade to black out
+ _vm->_gfx->getCurrentPal(cur_pal);
event.type = kEvTImmediate;
event.code = kPalEvent;
event.op = kEventPalToBlack;
event.time = 0;
event.duration = kNormalFadeDuration;
event.data = cur_pal;
-
q_event = _vm->_events->chain(q_event, &event);
- event.type = kEvTOneshot;
+ // set fade mode
+ event.type = kEvTImmediate;
event.code = kInterfaceEvent;
- event.op = kEventClearStatus;
-
+ event.op = kEventSetFadeMode;
+ event.param = kNoFade;
+ event.time = 0;
+ event.duration = 0;
q_event = _vm->_events->chain(q_event, &event);
event.type = kEvTOneshot;
- event.code = kGraphicsEvent;
- event.op = kEventSetFlag;
- event.param = RF_PLACARD;
-
+ event.code = kInterfaceEvent;
+ event.op = kEventClearStatus;
q_event = _vm->_events->chain(q_event, &event);
// Set the background and palette for the psychic profile
event.type = kEvTOneshot;
event.code = kPsychicProfileBgEvent;
-
q_event = _vm->_events->chain(q_event, &event);
_vm->_scene->_textList.clear();
@@ -1432,7 +1442,6 @@ void Scene::showPsychicProfile(const char *text) {
event.code = kTextEvent;
event.op = kEventDisplay;
event.data = _psychicProfileTextEntry;
-
q_event = _vm->_events->chain(q_event, &event);
}
@@ -1444,22 +1453,21 @@ void Scene::showPsychicProfile(const char *text) {
event.time = 0;
event.duration = kNormalFadeDuration;
event.data = pal;
-
q_event = _vm->_events->chain(q_event, &event);
event.type = kEvTOneshot;
event.code = kScriptEvent;
event.op = kEventThreadWake;
event.param = kWaitTypePlacard;
-
q_event = _vm->_events->chain(q_event, &event);
}
void Scene::clearPsychicProfile() {
if (_vm->_interface->getMode() == kPanelPlacard || _vm->getGameId() == GID_IHNM_DEMO) {
+ _vm->_interface->restoreMode();
_vm->_scene->clearPlacard();
_vm->_scene->_textList.clear();
- _vm->_actor->showActors(false);
+ _vm->_render->setFlag(RF_DISABLE_ACTORS);
_vm->_gfx->restorePalette();
_vm->_scene->restoreScene();
_vm->_interface->activate();
diff --git a/engines/saga/scene.h b/engines/saga/scene.h
index da97bddff5..aca3f910e0 100644
--- a/engines/saga/scene.h
+++ b/engines/saga/scene.h
@@ -221,6 +221,7 @@ class Scene {
void cmdSceneChange(int argc, const char **argv);
void startScene();
+ void creditsScene();
void nextScene();
void skipScene();
void endScene();
@@ -345,6 +346,10 @@ class Scene {
void clearPsychicProfile();
void showIHNMDemoSpecialScreen();
+ bool isNonInteractiveIHNMDemoPart() {
+ return _vm->getGameId() == GID_IHNM_DEMO && (_sceneNumber >= 144 && _sceneNumber <= 149);
+ }
+
private:
void loadScene(LoadSceneParams *loadSceneParams);
void loadSceneDescriptor(uint32 resourceId);
@@ -391,17 +396,26 @@ class Scene {
private:
int IHNMStartProc();
+ int IHNMCreditsProc();
int ITEStartProc();
+ void IHNMLoadCutaways();
+ bool checkKey();
+
+ bool playTitle(int title, int time, int mode = kPanelVideo);
+ bool playLoopingTitle(int title, int seconds);
+
public:
static int SC_IHNMIntroMovieProc1(int param, void *refCon);
static int SC_IHNMIntroMovieProc2(int param, void *refCon);
static int SC_IHNMIntroMovieProc3(int param, void *refCon);
+ static int SC_IHNMCreditsMovieProc(int param, void *refCon);
private:
int IHNMIntroMovieProc1(int param);
int IHNMIntroMovieProc2(int param);
int IHNMIntroMovieProc3(int param);
+ int IHNMCreditsMovieProc(int param);
public:
static int SC_ITEIntroAnimProc(int param, void *refCon);
diff --git a/engines/saga/script.cpp b/engines/saga/script.cpp
index 82fcb352c0..611975f471 100644
--- a/engines/saga/script.cpp
+++ b/engines/saga/script.cpp
@@ -204,6 +204,7 @@ void Script::freeModules() {
for (i = 0; i < _modulesCount; i++) {
if (_modules[i].loaded) {
_modules[i].freeMem();
+ _modules[i].loaded = false;
}
}
_staticSize = 0;
@@ -359,8 +360,6 @@ int Script::getVerbType(VerbTypes verbType) {
}
}
else {
- // TODO: This is ugly and needs rewriting, but
- // it works for now
switch (verbType) {
case kVerbNone:
return kVerbIHNMNone;
@@ -507,7 +506,6 @@ void Script::doVerb() {
event.param4 = _pendingObject[0]; // Object
event.param5 = _pendingObject[1]; // With Object
event.param6 = (objectType == kGameObjectActor) ? _pendingObject[0] : ID_PROTAG; // Actor
-
_vm->_events->queue(&event);
} else {
@@ -773,7 +771,13 @@ void Script::whichObject(const Point& mousePoint) {
objectId = newObjectId;
if (_vm->getGameType() == GType_ITE)
objectFlags = kObjUseWith;
+ // Note: for IHNM, the default right button action is "Look at" for actors,
+ // but "Talk to" makes much more sense
newRightButtonVerb = getVerbType(kVerbTalkTo);
+ // Slight hack because of the above change: the jukebox in Gorrister's chapter
+ // is an actor, so change the right button action to "Look at"
+ if (_vm->getGameType() == GType_IHNM && objectId == 8199)
+ newRightButtonVerb = getVerbType(kVerbLookAt);
if ((_currentVerb == getVerbType(kVerbPickUp)) ||
(_currentVerb == getVerbType(kVerbOpen)) ||
@@ -827,6 +831,10 @@ void Script::whichObject(const Point& mousePoint) {
if (newRightButtonVerb >= getVerbType(kVerbOptions)) {
newRightButtonVerb = getVerbType(kVerbNone);
}
+ } else {
+ if (newRightButtonVerb >= getVerbType(kVerbOptions)) {
+ newRightButtonVerb = getVerbType(kVerbWalkTo);
+ }
}
if ((_currentVerb == getVerbType(kVerbTalkTo)) || ((_currentVerb == getVerbType(kVerbGive)) && _firstObjectSet)) {
diff --git a/engines/saga/script.h b/engines/saga/script.h
index 5e5e702132..37e35cf241 100644
--- a/engines/saga/script.h
+++ b/engines/saga/script.h
@@ -237,7 +237,6 @@ struct ModuleData {
voiceLUT.freeMem();
free(moduleBase);
free(entryPoints);
- memset(this, 0x0, sizeof(*this));
}
};
@@ -597,7 +596,7 @@ private:
void sfShowIHNMDemoHelpPage(SCRIPTFUNC_PARAMS);
void sfGetPoints(SCRIPTFUNC_PARAMS);
void sfSetGlobalFlag(SCRIPTFUNC_PARAMS);
- void sf92(SCRIPTFUNC_PARAMS);
+ void sfDemoSetInteractive(SCRIPTFUNC_PARAMS);
void sfClearGlobalFlag(SCRIPTFUNC_PARAMS);
void sfTestGlobalFlag(SCRIPTFUNC_PARAMS);
void sfSetPoints(SCRIPTFUNC_PARAMS);
diff --git a/engines/saga/sfuncs.cpp b/engines/saga/sfuncs.cpp
index c0e44584df..74f192c7f7 100644
--- a/engines/saga/sfuncs.cpp
+++ b/engines/saga/sfuncs.cpp
@@ -230,7 +230,7 @@ static const ScriptFunctionDescription IHNMscriptFunctionsList[IHNM_SCRIPT_FUNCT
OPCODE(sfShowIHNMDemoHelpPage),
OPCODE(sfVstopFX),
OPCODE(sfVstopLoopedFX),
- OPCODE(sf92), // only used in the demo version of IHNM
+ OPCODE(sfDemoSetInteractive), // only used in the demo version of IHNM
OPCODE(sfDemoIsInteractive),
OPCODE(sfVsetTrack),
OPCODE(sfGetPoints),
@@ -253,8 +253,7 @@ static const ScriptFunctionDescription IHNMscriptFunctionsList[IHNM_SCRIPT_FUNCT
// Script function #0 (0x00)
// Print a debugging message
void Script::sfPutString(SCRIPTFUNC_PARAMS) {
- const char *str;
- str = thread->_strings->getString(thread->pop());
+ const char *str = thread->_strings->getString(thread->pop());
_vm->_console->DebugPrintf("sfPutString: %s\n",str);
debug(0, "sfPutString: %s", str);
@@ -263,8 +262,7 @@ void Script::sfPutString(SCRIPTFUNC_PARAMS) {
// Script function #1 (0x01) blocking
// Param1: time in ticks
void Script::sfWait(SCRIPTFUNC_PARAMS) {
- int16 time;
- time = thread->pop();
+ int16 time = thread->pop();
if (!_skipSpeeches) {
thread->waitDelay(_vm->ticksToMSec(time)); // put thread to sleep
@@ -274,17 +272,17 @@ void Script::sfWait(SCRIPTFUNC_PARAMS) {
// Script function #2 (0x02)
void Script::sfTakeObject(SCRIPTFUNC_PARAMS) {
uint16 objectId = thread->pop();
- ObjectData *obj;
- obj = _vm->_actor->getObj(objectId);
+ ObjectData *obj = _vm->_actor->getObj(objectId);
+
if (obj->_sceneNumber != ITE_SCENE_INV) {
obj->_sceneNumber = ITE_SCENE_INV;
// WORKAROUND for two incorrect object sprites in the IHNM demo
// (the mirror and the icon in Ted's part). Set them correctly here
if (_vm->getGameId() == GID_IHNM_DEMO) {
- if (obj->_spriteListResourceId == 4 && objectId == 16408)
+ if (objectId == 16408)
obj->_spriteListResourceId = 24;
- if (obj->_spriteListResourceId == 3 && objectId == 16409)
+ if (objectId == 16409)
obj->_spriteListResourceId = 25;
}
@@ -297,23 +295,20 @@ void Script::sfTakeObject(SCRIPTFUNC_PARAMS) {
void Script::sfIsCarried(SCRIPTFUNC_PARAMS) {
uint16 objectId = thread->pop();
CommonObjectData *object;
+
if (_vm->_actor->validObjId(objectId)) {
object = _vm->_actor->getObj(objectId);
thread->_returnValue = (object->_sceneNumber == ITE_SCENE_INV) ? 1 : 0;
} else {
thread->_returnValue = 0;
}
-
-
}
// Script function #4 (0x04) nonblocking
// Set the command display to the specified text string
// Param1: dialogue index of string
void Script::sfStatusBar(SCRIPTFUNC_PARAMS) {
- int16 stringIndex = thread->pop();
-
- _vm->_interface->setStatusText(thread->_strings->getString(stringIndex));
+ _vm->_interface->setStatusText(thread->_strings->getString(thread->pop()));
}
// Script function #5 (0x05)
@@ -323,9 +318,29 @@ void Script::sfMainMode(SCRIPTFUNC_PARAMS) {
showVerb();
_vm->_interface->activate();
_vm->_interface->setMode(kPanelMain);
+ // Sometimes, the active cutaway is cleared after this opcode is called,
+ // resulting in an incorrect mode being set. An example is Ellen's chapter
+ // in IHNM, when using the computer with the chaos trebler CD. Make sure
+ // that the saved mode is kPanelMain, so that it won't get overwritten
+ // by an incorrect stored mode
+ _vm->_interface->rememberMode();
if (_vm->getGameType() == GType_ITE)
setPointerVerb();
+
+ // The early Windows and Mac demos of ITE were non-interactive. In those demos,
+ // the intro is shown and then when the first scene is shown, there's a dialog
+ // thanking the user for playing the demo and asking him to buy the full game,
+ // without allowing him to continue any further. The game data itself for these
+ // demos does not contain any scripts for the first scene (i.e. there's no text
+ // in the game data to look at Rif's silver medallion). Also, there are no more
+ // scenes apart from the Grand Tournament scene. This opcode is called in those
+ // demos, and I assume that its use there is to just show the popup window and
+ // exit the game. Therefore, once this opcode is called in the older ITE demos,
+ // exit the game. Known non-interactive demos are GID_ITE_MACDEMO1 and
+ // GID_ITE_WINDEMO1
+ if (_vm->getFeatures() & GF_NON_INTERACTIVE)
+ _vm->shutDown();
}
// Script function #6 (0x06) blocking
@@ -333,15 +348,11 @@ void Script::sfMainMode(SCRIPTFUNC_PARAMS) {
// Param2: actor x
// Param3: actor y
void Script::sfScriptWalkTo(SCRIPTFUNC_PARAMS) {
- uint16 actorId;
+ uint16 actorId = thread->pop();
+ ActorData *actor = _vm->_actor->getActor(actorId);
Location actorLocation;
- ActorData *actor;
-
- actorId = thread->pop();
actorLocation.x = thread->pop();
actorLocation.y = thread->pop();
-
- actor = _vm->_actor->getActor(actorId);
actorLocation.z = actor->_location.z;
actor->_flags &= ~kFollower;
@@ -357,10 +368,10 @@ void Script::sfScriptWalkTo(SCRIPTFUNC_PARAMS) {
// Param3: theObject
// Param4: withObject
void Script::sfScriptDoAction(SCRIPTFUNC_PARAMS) {
- uint16 objectId;
- uint16 action;
- uint16 theObject;
- uint16 withObject;
+ uint16 objectId = thread->pop();
+ uint16 action = thread->pop();
+ uint16 theObject = thread->pop();
+ uint16 withObject = thread->pop();
int16 scriptEntryPointNumber;
int16 moduleNumber;
ActorData *actor;
@@ -368,11 +379,6 @@ void Script::sfScriptDoAction(SCRIPTFUNC_PARAMS) {
const HitZone *hitZone;
Event event;
- objectId = thread->pop();
- action = thread->pop();
- theObject = thread->pop();
- withObject = thread->pop();
-
switch (objectTypeId(objectId)) {
case kGameObjectObject:
obj = _vm->_actor->getObj(objectId);
@@ -381,6 +387,8 @@ void Script::sfScriptDoAction(SCRIPTFUNC_PARAMS) {
return;
}
moduleNumber = 0;
+ if (_vm->getGameType() == GType_IHNM)
+ moduleNumber = _vm->_scene->getScriptModuleNumber();
break;
case kGameObjectActor:
actor = _vm->_actor->getActor(objectId);
@@ -393,6 +401,8 @@ void Script::sfScriptDoAction(SCRIPTFUNC_PARAMS) {
} else {
moduleNumber = _vm->_scene->getScriptModuleNumber();
}
+ if (_vm->getGameType() == GType_IHNM)
+ moduleNumber = _vm->_scene->getScriptModuleNumber();
break;
case kGameObjectHitZone:
case kGameObjectStepZone:
@@ -421,7 +431,6 @@ void Script::sfScriptDoAction(SCRIPTFUNC_PARAMS) {
event.param4 = theObject; // Object
event.param5 = withObject; // With Object
event.param6 = objectId;
-
_vm->_events->queue(&event);
}
@@ -429,14 +438,9 @@ void Script::sfScriptDoAction(SCRIPTFUNC_PARAMS) {
// Param1: actor id
// Param2: actor orientation
void Script::sfSetActorFacing(SCRIPTFUNC_PARAMS) {
- int16 actorId;
- int actorDirection;
- ActorData *actor;
+ ActorData *actor = _vm->_actor->getActor(thread->pop());
+ int actorDirection = thread->pop();
- actorId = thread->pop();
- actorDirection = thread->pop();
-
- actor = _vm->_actor->getActor(actorId);
actor->_facingDirection = actor->_actionDirection = actorDirection;
actor->_targetObject = ID_NOTHING;
}
@@ -448,7 +452,9 @@ void Script::sfStartBgdAnim(SCRIPTFUNC_PARAMS) {
_vm->_anim->setCycles(animId, cycles);
_vm->_anim->setFrameTime(animId, _vm->ticksToMSec(kRepeatSpeedTicks));
- _vm->_anim->play(animId, 0);
+
+ if (!_vm->_anim->isPlaying(animId))
+ _vm->_anim->play(animId, 0);
debug(1, "sfStartBgdAnim(%d, %d)", animId, cycles);
}
@@ -468,11 +474,7 @@ void Script::sfStopBgdAnim(SCRIPTFUNC_PARAMS) {
// reenabled.
// Param1: boolean
void Script::sfLockUser(SCRIPTFUNC_PARAMS) {
- int16 lock;
-
- lock = thread->pop();
-
- if (lock) {
+ if (thread->pop()) {
_vm->_interface->deactivate();
} else {
_vm->_interface->activate();
@@ -485,6 +487,7 @@ void Script::sfLockUser(SCRIPTFUNC_PARAMS) {
void Script::sfPreDialog(SCRIPTFUNC_PARAMS) {
_vm->_interface->deactivate();
_vm->_interface->converseClear();
+
if (_vm->_interface->isInMainMode())
_vm->_interface->setMode(kPanelConverse);
else
@@ -497,10 +500,7 @@ void Script::sfPreDialog(SCRIPTFUNC_PARAMS) {
void Script::sfKillActorThreads(SCRIPTFUNC_PARAMS) {
ScriptThread *anotherThread;
ScriptThreadList::iterator threadIterator;
- int16 actorId;
-
- actorId = thread->pop();
-
+ int16 actorId = thread->pop();
for (threadIterator = _threadList.begin(); threadIterator != _threadList.end(); ++threadIterator) {
anotherThread = threadIterator.operator->();
@@ -515,34 +515,21 @@ void Script::sfKillActorThreads(SCRIPTFUNC_PARAMS) {
// Param1: actor id
// Param2: object id
void Script::sfFaceTowards(SCRIPTFUNC_PARAMS) {
- int16 actorId;
- int16 targetObject;
- ActorData *actor;
-
- actorId = thread->pop();
- targetObject = thread->pop();
-
- actor = _vm->_actor->getActor(actorId);
- actor->_targetObject = targetObject;
+ ActorData *actor = _vm->_actor->getActor(thread->pop());
+ actor->_targetObject = thread->pop();
}
// Script function #15 (0x0F)
// Param1: actor id
// Param2: target object
void Script::sfSetFollower(SCRIPTFUNC_PARAMS) {
- int16 actorId;
- int16 targetObject;
-
- ActorData *actor;
+ int16 actorId = thread->pop();
+ ActorData *actor = _vm->_actor->getActor(actorId);
+ actor->_targetObject = thread->pop();
- actorId = thread->pop();
- targetObject = thread->pop();
+ debug(1, "sfSetFollower(%d, %d) [%d]", actorId, actor->_targetObject, _vm->_actor->actorIdToIndex(actorId));
- debug(1, "sfSetFollower(%d, %d) [%d]", actorId, targetObject, _vm->_actor->actorIdToIndex(actorId));
-
- actor = _vm->_actor->getActor(actorId);
- actor->_targetObject = targetObject;
- if (targetObject != ID_NOTHING) {
+ if (actor->_targetObject != ID_NOTHING) {
actor->_flags |= kFollower;
actor->_actorFlags &= ~kActorNoFollow;
} else {
@@ -552,53 +539,33 @@ void Script::sfSetFollower(SCRIPTFUNC_PARAMS) {
// Script function #16 (0x10)
void Script::sfScriptGotoScene(SCRIPTFUNC_PARAMS) {
- int16 sceneNumber;
- int16 entrance;
- int16 transition = 0; // IHNM
+ int16 sceneNumber = thread->pop();
+ int16 entrance = thread->pop();
- sceneNumber = thread->pop();
- entrance = thread->pop();
if (_vm->getGameType() == GType_IHNM) {
- transition = thread->pop();
-
_vm->_gfx->setCursor(kCursorBusy);
}
- if ((_vm->getGameType() == GType_ITE && sceneNumber < 0) ||
- (_vm->getGameType() == GType_IHNM && sceneNumber == 0)) {
- // TODO: set creditsFlag to true for IHNM
+ if (_vm->getGameType() == GType_ITE && sceneNumber < 0) {
_vm->shutDown();
return;
}
- if (_vm->getGameType() == GType_IHNM) {
- // WORKAROUND for the briefly appearing actors at the beginning of each chapter
- // This will stop the actors being drawn in those specific scenes until the scene background has been drawn
- if ((_vm->_scene->currentChapterNumber() == 1 && _vm->_scene->currentSceneNumber() == 6) ||
- (_vm->_scene->currentChapterNumber() == 2 && _vm->_scene->currentSceneNumber() == 31) ||
- (_vm->_scene->currentChapterNumber() == 3 && _vm->_scene->currentSceneNumber() == 58) ||
- (_vm->_scene->currentChapterNumber() == 4 && _vm->_scene->currentSceneNumber() == 68) ||
- (_vm->_scene->currentChapterNumber() == 5 && _vm->_scene->currentSceneNumber() == 91) ||
- (_vm->_scene->currentChapterNumber() == 7 && _vm->_scene->currentSceneNumber() == 145))
- _vm->_actor->showActors(false); // Stop showing actors before the background is drawn
-
- // Since it doesn't look like the IHNM scripts remove the
- // cutaway after the intro, this is probably the best place to do it
- _vm->_anim->clearCutaway();
+ if (_vm->getGameType() == GType_IHNM && sceneNumber == 0) {
+ _vm->_scene->creditsScene();
+ return;
}
// It is possible to leave scene when converse panel is on,
// particulalrly it may happen at Moneychanger tent. This
- // prevent this from happening.
+ // prevents this from happening.
if (_vm->_interface->getMode() == kPanelConverse) {
_vm->_interface->setMode(kPanelMain);
}
// changeScene calls loadScene which calls setVerb. setVerb resets all pending objects and object flags
if (sceneNumber == -1 && _vm->getGameType() == GType_IHNM) {
- // TODO: This is used to return back to the character selection screen in IHNM.
- // However, it seems more than this is needed, AM's speech is wrong and no actors
- // are shown
+ // Return back to the character selection screen in IHNM
_vm->_scene->changeScene(154, entrance, kTransitionFade, 8);
} else {
_vm->_scene->changeScene(sceneNumber, entrance, (sceneNumber == ITE_SCENE_ENDCREDIT1) ? kTransitionFade : kTransitionNoFade);
@@ -615,23 +582,27 @@ void Script::sfScriptGotoScene(SCRIPTFUNC_PARAMS) {
_currentObject[0] = _currentObject[1] = ID_NOTHING;
showVerb(); // calls setStatusText("")
- if (_vm->getGameType() == GType_IHNM)
+ if (_vm->getGameType() == GType_IHNM) {
+ // There are some cutaways which are not removed by game scripts, like the cutaway
+ // after the intro of IHNM or the cutaway at the end of Ellen's part in the IHNM demo.
+ // Clear any remaining cutaways here
+ _vm->_anim->clearCutaway();
_vm->_gfx->setCursor(kCursorNormal);
+ }
}
// Script function #17 (0x11)
// Param1: object id
// Param2: sprite index
void Script::sfSetObjImage(SCRIPTFUNC_PARAMS) {
- uint16 objectId;
- uint16 spriteId;
- ObjectData *obj;
-
- objectId = thread->pop();
- spriteId = thread->pop();
+ uint16 objectId = thread->pop();
+ uint16 spriteId = thread->pop();
+ ObjectData *obj = _vm->_actor->getObj(objectId);
- obj = _vm->_actor->getObj(objectId);
- obj->_spriteListResourceId = OBJ_SPRITE_BASE + spriteId;
+ if (_vm->getGameType() == GType_IHNM)
+ obj->_spriteListResourceId = spriteId;
+ else
+ obj->_spriteListResourceId = OBJ_SPRITE_BASE + spriteId;
_vm->_interface->refreshInventory();
}
@@ -639,26 +610,18 @@ void Script::sfSetObjImage(SCRIPTFUNC_PARAMS) {
// Param1: object id
// Param2: name index
void Script::sfSetObjName(SCRIPTFUNC_PARAMS) {
- uint16 objectId;
- uint16 nameIdx;
- ObjectData *obj;
-
- objectId = thread->pop();
- nameIdx = thread->pop();
+ uint16 objectId = thread->pop();
+ uint16 nameIdx = thread->pop();
+ ObjectData *obj = _vm->_actor->getObj(objectId);
- obj = _vm->_actor->getObj(objectId);
obj->_nameIndex = nameIdx;
}
// Script function #19 (0x13)
// Param1: object id
void Script::sfGetObjImage(SCRIPTFUNC_PARAMS) {
- uint16 objectId;
- ObjectData *obj;
-
- objectId = thread->pop();
-
- obj = _vm->_actor->getObj(objectId);
+ uint16 objectId = thread->pop();
+ ObjectData *obj = _vm->_actor->getObj(objectId);
if (_vm->getGameType() == GType_IHNM)
thread->_returnValue = obj->_spriteListResourceId;
@@ -686,8 +649,7 @@ void Script::sfGetNumber(SCRIPTFUNC_PARAMS) {
// Script function #21 (0x15)
// Param1: door #
void Script::sfScriptOpenDoor(SCRIPTFUNC_PARAMS) {
- int16 doorNumber;
- doorNumber = thread->pop();
+ int16 doorNumber = thread->pop();
if (_vm->_scene->getFlags() & kSceneFlagISO) {
_vm->_isoMap->setTileDoorState(doorNumber, 1);
@@ -699,8 +661,7 @@ void Script::sfScriptOpenDoor(SCRIPTFUNC_PARAMS) {
// Script function #22 (0x16)
// Param1: door #
void Script::sfScriptCloseDoor(SCRIPTFUNC_PARAMS) {
- int16 doorNumber;
- doorNumber = thread->pop();
+ int16 doorNumber = thread->pop();
if (_vm->_scene->getFlags() & kSceneFlagISO) {
_vm->_isoMap->setTileDoorState(doorNumber, 0);
@@ -728,10 +689,7 @@ void Script::SF_cycleColors(SCRIPTFUNC_PARAMS) {
// Script function #25 (0x19)
// Param1: actor id
void Script::sfDoCenterActor(SCRIPTFUNC_PARAMS) {
- int16 actorId;
- actorId = thread->pop();
-
- _vm->_actor->_centerActor = _vm->_actor->getActor(actorId);
+ _vm->_actor->_centerActor = _vm->_actor->getActor(thread->pop());
}
// Script function #26 (0x1A) nonblocking
@@ -743,7 +701,9 @@ void Script::sfStartBgdAnimSpeed(SCRIPTFUNC_PARAMS) {
_vm->_anim->setCycles(animId, cycles);
_vm->_anim->setFrameTime(animId, _vm->ticksToMSec(speed));
- _vm->_anim->play(animId, 0);
+
+ if (!_vm->_anim->isPlaying(animId))
+ _vm->_anim->play(animId, 0);
debug(1, "sfStartBgdAnimSpeed(%d, %d, %d)", animId, cycles, speed);
}
@@ -753,19 +713,14 @@ void Script::sfStartBgdAnimSpeed(SCRIPTFUNC_PARAMS) {
// Param2: actor x
// Param3: actor y
void Script::sfScriptWalkToAsync(SCRIPTFUNC_PARAMS) {
- int16 actorId;
+ int16 actorId = thread->pop();
+ ActorData *actor = _vm->_actor->getActor(actorId);
Location actorLocation;
- ActorData *actor;
-
- actorId = thread->pop();
actorLocation.x = thread->pop();
actorLocation.y = thread->pop();
-
- actor = _vm->_actor->getActor(actorId);
actorLocation.z = actor->_location.z;
actor->_flags &= ~kFollower;
-
_vm->_actor->actorWalkTo(actorId, actorLocation);
}
@@ -797,14 +752,8 @@ void Script::sfEnableZone(SCRIPTFUNC_PARAMS) {
// Param1: actor id
// Param2: current action
void Script::sfSetActorState(SCRIPTFUNC_PARAMS) {
- int16 actorId;
- int currentAction;
- ActorData *actor;
-
- actorId = thread->pop();
- currentAction = thread->pop();
-
- actor = _vm->_actor->getActor(actorId);
+ ActorData *actor = _vm->_actor->getActor(thread->pop());
+ int currentAction = thread->pop();
if ((currentAction >= kActionWalkToPoint) && (currentAction <= kActionWalkToPoint)) {
wakeUpActorThread(kWaitTypeWalk, actor);
@@ -818,14 +767,12 @@ void Script::sfSetActorState(SCRIPTFUNC_PARAMS) {
// Param2: actor pos x
// Param3: actor pos y
void Script::sfScriptMoveTo(SCRIPTFUNC_PARAMS) {
- int16 objectId;
+ int16 objectId = thread->pop();
Location location;
- ActorData *actor;
- ObjectData *obj;
-
- objectId = thread->pop();
location.x = thread->pop();
location.y = thread->pop();
+ ActorData *actor;
+ ObjectData *obj;
if (_vm->_actor->validActorId(objectId)) {
actor = _vm->_actor->getActor(objectId);
@@ -854,18 +801,11 @@ void Script::sfSceneEq(SCRIPTFUNC_PARAMS) {
// Script function #32 (0x20)
void Script::sfDropObject(SCRIPTFUNC_PARAMS) {
- uint16 objectId;
- uint16 spriteId;
- int16 x;
- int16 y;
- ObjectData *obj;
-
- objectId = thread->pop();
- spriteId = thread->pop();
- x = thread->pop();
- y = thread->pop();
-
- obj = _vm->_actor->getObj(objectId);
+ uint16 objectId = thread->pop();
+ ObjectData *obj = _vm->_actor->getObj(objectId);
+ uint16 spriteId = thread->pop();
+ obj->_location.x = thread->pop();
+ obj->_location.y = thread->pop();
if (obj->_sceneNumber == ITE_SCENE_INV) {
_vm->_interface->removeFromInventory(objectId);
@@ -873,10 +813,10 @@ void Script::sfDropObject(SCRIPTFUNC_PARAMS) {
obj->_sceneNumber = _vm->_scene->currentSceneNumber();
- // WORKAROUND for the compact disk in Ellen's chapter
+ // HACK for the compact disk in Ellen's chapter
// Change the scene number of the compact disk so that it's not shown. It will be shown
// once Ellen says that there's something different (i.e. after speaking with AM)
- // See Actor::actorSpeech for the other part of this workaround
+ // See Actor::actorSpeech for the other part of this hack
if (_vm->getGameType() == GType_IHNM && _vm->_scene->currentChapterNumber() == 3 &&
_vm->_scene->currentSceneNumber() == 59 && obj->_id == 16385)
obj->_sceneNumber = -1;
@@ -891,9 +831,6 @@ void Script::sfDropObject(SCRIPTFUNC_PARAMS) {
} else {
obj->_spriteListResourceId = OBJ_SPRITE_BASE + spriteId;
}
-
- obj->_location.x = x;
- obj->_location.y = y;
}
// Script function #33 (0x21)
@@ -909,16 +846,10 @@ void Script::sfFinishBgdAnim(SCRIPTFUNC_PARAMS) {
// Param1: actor id 1
// Param2: actor id 2
void Script::sfSwapActors(SCRIPTFUNC_PARAMS) {
- int16 actorId1;
- int16 actorId2;
- ActorData *actor1;
- ActorData *actor2;
-
- actorId1 = thread->pop();
- actorId2 = thread->pop();
-
- actor1 = _vm->_actor->getActor(actorId1);
- actor2 = _vm->_actor->getActor(actorId2);
+ int16 actorId1 = thread->pop();
+ int16 actorId2 = thread->pop();
+ ActorData *actor1 = _vm->_actor->getActor(actorId1);
+ ActorData *actor2 = _vm->_actor->getActor(actorId2);
SWAP(actor1->_location, actor2->_location);
@@ -944,24 +875,19 @@ void Script::sfSwapActors(SCRIPTFUNC_PARAMS) {
///....
// Param3: actor idN
void Script::sfSimulSpeech(SCRIPTFUNC_PARAMS) {
- int16 stringId;
- int16 actorsCount;
+ int16 stringId = thread->pop();
+ int16 actorsCount = thread->pop();
int i;
uint16 actorsIds[ACTOR_SPEECH_ACTORS_MAX];
- const char *string;
+ const char *string = thread->_strings->getString(stringId);
int16 sampleResourceId = -1;
- stringId = thread->pop();
- actorsCount = thread->pop();
-
if (actorsCount > ACTOR_SPEECH_ACTORS_MAX)
error("sfSimulSpeech actorsCount=0x%X exceed ACTOR_SPEECH_ACTORS_MAX", actorsCount);
for (i = 0; i < actorsCount; i++)
actorsIds[i] = thread->pop();
- string = thread->_strings->getString(stringId);
-
if (thread->_voiceLUT->voices) {
if (_vm->getGameType() == GType_IHNM && stringId >= 338) {
sampleResourceId = -1;
@@ -982,22 +908,16 @@ void Script::sfSimulSpeech(SCRIPTFUNC_PARAMS) {
// Param3: actor y
// Param4: actor walk flag
void Script::sfScriptWalk(SCRIPTFUNC_PARAMS) {
- int16 actorId;
+ int16 actorId = thread->pop();
+ ActorData *actor = _vm->_actor->getActor(actorId);
Location actorLocation;
- ActorData *actor;
- uint16 walkFlags;
-
- actorId = thread->pop();
actorLocation.x = thread->pop();
actorLocation.y = thread->pop();
- walkFlags = thread->pop();
-
- actor = _vm->_actor->getActor(actorId);
actorLocation.z = actor->_location.z;
-
- _vm->_actor->realLocation(actorLocation, ID_NOTHING, walkFlags);
+ uint16 walkFlags = thread->pop();
actor->_flags &= ~kFollower;
+ _vm->_actor->realLocation(actorLocation, ID_NOTHING, walkFlags);
if (_vm->_actor->actorWalkTo(actorId, actorLocation) && !(walkFlags & kWalkAsync)) {
thread->waitWalk(actor);
@@ -1016,18 +936,10 @@ void Script::sfScriptWalk(SCRIPTFUNC_PARAMS) {
// Param3: cycle frame number
// Param4: cycle delay
void Script::sfCycleFrames(SCRIPTFUNC_PARAMS) {
- int16 actorId;
- int16 flags;
- int cycleFrameSequence;
- int cycleDelay;
- ActorData *actor;
-
- actorId = thread->pop();
- flags = thread->pop();
- cycleFrameSequence = thread->pop();
- cycleDelay = thread->pop();
-
- actor = _vm->_actor->getActor(actorId);
+ ActorData *actor = _vm->_actor->getActor(thread->pop());
+ int16 flags = thread->pop();
+ int cycleFrameSequence = thread->pop();
+ int cycleDelay = thread->pop();
if (flags & kCyclePong) {
actor->_currentAction = kActionPongFrames;
@@ -1046,8 +958,8 @@ void Script::sfCycleFrames(SCRIPTFUNC_PARAMS) {
if (flags & kCycleReverse) {
if (_vm->getGameType() == GType_IHNM &&
_vm->_scene->currentChapterNumber() == 2 && _vm->_scene->currentSceneNumber() == 41) {
- // Prevent Benny from walking backwards after talking to the child via the monitor. This occurs in the
- // original as well, and is fixed by not setting the kActorBackwards flag at this point
+ // WORKAROUND: Prevent Benny from walking backwards after talking to the child via the monitor. This
+ // occurs in the original as well, and is fixed by not setting the kActorBackwards flag at this point
} else {
actor->_actorFlags |= kActorBackwards;
}
@@ -1064,19 +976,11 @@ void Script::sfCycleFrames(SCRIPTFUNC_PARAMS) {
// Param2: frame type
// Param3: frame offset
void Script::sfSetFrame(SCRIPTFUNC_PARAMS) {
- int16 actorId;
- int frameType;
- int frameOffset;
- ActorData *actor;
- ActorFrameRange *frameRange;
-
- actorId = thread->pop();
- frameType = thread->pop();
- frameOffset = thread->pop();
-
- actor = _vm->_actor->getActor(actorId);
-
- frameRange = _vm->_actor->getActorFrameRange(actorId, frameType);
+ int16 actorId = thread->pop();
+ ActorData *actor = _vm->_actor->getActor(actorId);
+ int frameType = thread->pop();
+ int frameOffset = thread->pop();
+ ActorFrameRange *frameRange = _vm->_actor->getActorFrameRange(actorId, frameType);
actor->_frameNumber = frameRange->frameIndex + frameOffset;
@@ -1088,17 +992,13 @@ void Script::sfSetFrame(SCRIPTFUNC_PARAMS) {
// Script function #39 (0x27)
// Sets the right-hand portrait
void Script::sfSetPortrait(SCRIPTFUNC_PARAMS) {
- int16 param = thread->pop();
-
- _vm->_interface->setRightPortrait(param);
+ _vm->_interface->setRightPortrait(thread->pop());
}
// Script function #40 (0x28)
// Sets the left-hand portrait
void Script::sfSetProtagPortrait(SCRIPTFUNC_PARAMS) {
- int16 param = thread->pop();
-
- _vm->_interface->setLeftPortrait(param);
+ _vm->_interface->setLeftPortrait(thread->pop());
}
// Script function #41 (0x29) nonblocking
@@ -1130,21 +1030,15 @@ void Script::sfChainBgdAnim(SCRIPTFUNC_PARAMS) {
// Param3: actor y
// Param4: frame seq
void Script::sfScriptSpecialWalk(SCRIPTFUNC_PARAMS) {
- int16 actorId;
- int16 walkFrameSequence;
+ int16 actorId = thread->pop();
+ ActorData *actor = _vm->_actor->getActor(actorId);
Location actorLocation;
- ActorData *actor;
-
- actorId = thread->pop();
actorLocation.x = thread->pop();
actorLocation.y = thread->pop();
- walkFrameSequence = thread->pop();
-
- actor = _vm->_actor->getActor(actorId);
actorLocation.z = actor->_location.z;
+ int16 walkFrameSequence = thread->pop();
_vm->_actor->actorWalkTo(actorId, actorLocation);
-
actor->_walkFrameSequence = walkFrameSequence;
}
@@ -1156,39 +1050,20 @@ void Script::sfScriptSpecialWalk(SCRIPTFUNC_PARAMS) {
// Param5: actor action
// Param6: actor frame number
void Script::sfPlaceActor(SCRIPTFUNC_PARAMS) {
- int16 actorId;
- Location actorLocation;
- int actorDirection;
- int frameType;
- int frameOffset;
- ActorData *actor;
+ int16 actorId = thread->pop();
+ ActorData *actor = _vm->_actor->getActor(actorId);
+ actor->_location.x = thread->pop();
+ actor->_location.y = thread->pop();
+ actor->_facingDirection = actor->_actionDirection = thread->pop();
+ int frameType = thread->pop();
+ int frameOffset = thread->pop();
ActorFrameRange *frameRange;
- actorId = thread->pop();
- actorLocation.x = thread->pop();
- actorLocation.y = thread->pop();
- actorDirection = thread->pop();
- frameType = thread->pop();
- frameOffset = thread->pop();
-
- debug(1, "sfPlaceActor(id = 0x%x, x=%d, y=%d, dir=%d, frameType=%d, frameOffset=%d)", actorId, actorLocation.x,
- actorLocation.y, actorDirection, frameType, frameOffset);
-
- actor = _vm->_actor->getActor(actorId);
- actor->_location.x = actorLocation.x;
- actor->_location.y = actorLocation.y;
- actor->_facingDirection = actor->_actionDirection = actorDirection;
-
- if (!actor->_frames)
- _vm->_actor->loadActorResources(actor); //? is not it already loaded ?
+ debug(1, "sfPlaceActor(id = 0x%x, x=%d, y=%d, dir=%d, frameType=%d, frameOffset=%d)", actorId, actor->_location.x,
+ actor->_location.y, actor->_facingDirection, frameType, frameOffset);
if (frameType >= 0) {
frameRange = _vm->_actor->getActorFrameRange(actorId, frameType);
-
- if (frameRange->frameCount <= frameOffset) {
- warning("Wrong frameOffset 0x%X", frameOffset);
- }
-
actor->_frameNumber = frameRange->frameIndex + frameOffset;
actor->_currentAction = kActionFreeze;
} else {
@@ -1213,24 +1088,17 @@ void Script::sfCheckUserInterrupt(SCRIPTFUNC_PARAMS) {
// Param4: actor y
// Param5: actor walk flag
void Script::sfScriptWalkRelative(SCRIPTFUNC_PARAMS) {
- int16 actorId;
- int16 objectId;
- uint16 walkFlags;
+ int16 actorId = thread->pop();
+ ActorData *actor = _vm->_actor->getActor(actorId);
+ int16 objectId = thread->pop();
Location actorLocation;
- ActorData *actor;
-
- actorId = thread->pop();
- objectId = thread->pop();
actorLocation.x = thread->pop();
actorLocation.y = thread->pop();
- walkFlags = thread->pop();
-
- actor = _vm->_actor->getActor(actorId);
actorLocation.z = actor->_location.z;
-
- _vm->_actor->realLocation(actorLocation, objectId, walkFlags);
+ uint16 walkFlags = thread->pop();
actor->_flags &= ~kFollower;
+ _vm->_actor->realLocation(actorLocation, objectId, walkFlags);
if (_vm->_actor->actorWalkTo(actorId, actorLocation) && !(walkFlags & kWalkAsync)) {
thread->waitWalk(actor);
@@ -1250,50 +1118,36 @@ void Script::sfScriptWalkRelative(SCRIPTFUNC_PARAMS) {
// Param4: actor y
// Param5: actor walk flag
void Script::sfScriptMoveRelative(SCRIPTFUNC_PARAMS) {
- int16 actorId;
- int16 objectId;
- uint16 walkFlags;
+ ActorData *actor = _vm->_actor->getActor(thread->pop());
+ int16 objectId = thread->pop();
Location actorLocation;
- ActorData *actor;
-
- actorId = thread->pop();
- objectId = thread->pop();
actorLocation.x = thread->pop();
actorLocation.y = thread->pop();
- walkFlags = thread->pop();
-
- actor = _vm->_actor->getActor(actorId);
actorLocation.z = actor->_location.z;
+ uint16 walkFlags = thread->pop();
_vm->_actor->realLocation(actorLocation, objectId, walkFlags);
-
actor->_location = actorLocation;
actor->_actorFlags = (actor->_actorFlags & ~kActorFacingMask) | (walkFlags & kActorFacingMask);
}
// Script function #47 (0x2F)
void Script::sfSimulSpeech2(SCRIPTFUNC_PARAMS) {
- int16 stringId;
- int16 actorsCount;
- int16 speechFlags;
+ int16 stringId = thread->pop();
+ const char *string = thread->_strings->getString(stringId);
+ int16 actorsCount = thread->pop();
+ int16 speechFlags = thread->pop();
int i;
uint16 actorsIds[ACTOR_SPEECH_ACTORS_MAX];
- const char *string;
int16 sampleResourceId = -1;
- stringId = thread->pop();
- actorsCount = thread->pop();
- speechFlags = thread->pop();
-
if (actorsCount > ACTOR_SPEECH_ACTORS_MAX)
error("sfSimulSpeech2 actorsCount=0x%X exceed ACTOR_SPEECH_ACTORS_MAX", actorsCount);
for (i = 0; i < actorsCount; i++)
actorsIds[i] = thread->pop();
- string = thread->_strings->getString(stringId);
-
if (thread->_voiceLUT->voices) {
sampleResourceId = thread->_voiceLUT->voices[stringId];
if (sampleResourceId <= 0 || sampleResourceId > 4000)
@@ -1308,7 +1162,7 @@ void Script::sfSimulSpeech2(SCRIPTFUNC_PARAMS) {
// Script function #48 (0x30)
// Param1: string rid
void Script::sfPlacard(SCRIPTFUNC_PARAMS) {
- int stringId;
+ int stringId = thread->pop();
Surface *backBuffer = _vm->_gfx->getBackBuffer();
static PalEntry cur_pal[PAL_ENTRIES];
PalEntry *pal;
@@ -1320,36 +1174,35 @@ void Script::sfPlacard(SCRIPTFUNC_PARAMS) {
_vm->_interface->rememberMode();
_vm->_interface->setMode(kPanelPlacard);
- stringId = thread->pop();
-
event.type = kEvTOneshot;
event.code = kCursorEvent;
event.op = kEventHide;
-
q_event = _vm->_events->queue(&event);
- _vm->_gfx->getCurrentPal(cur_pal);
+ _vm->_interface->setFadeMode(kFadeOut);
+ // Fade to black out
+ _vm->_gfx->getCurrentPal(cur_pal);
event.type = kEvTImmediate;
event.code = kPalEvent;
event.op = kEventPalToBlack;
event.time = 0;
event.duration = kNormalFadeDuration;
event.data = cur_pal;
-
q_event = _vm->_events->chain(q_event, &event);
- event.type = kEvTOneshot;
+ // set fade mode
+ event.type = kEvTImmediate;
event.code = kInterfaceEvent;
- event.op = kEventClearStatus;
-
+ event.op = kEventSetFadeMode;
+ event.param = kNoFade;
+ event.time = 0;
+ event.duration = 0;
q_event = _vm->_events->chain(q_event, &event);
event.type = kEvTOneshot;
- event.code = kGraphicsEvent;
- event.op = kEventSetFlag;
- event.param = RF_PLACARD;
-
+ event.code = kInterfaceEvent;
+ event.op = kEventClearStatus;
q_event = _vm->_events->chain(q_event, &event);
event.type = kEvTOneshot;
@@ -1361,7 +1214,6 @@ void Script::sfPlacard(SCRIPTFUNC_PARAMS) {
event.param3 = _vm->_scene->getHeight();
event.param4 = 0;
event.param5 = _vm->getDisplayWidth();
-
q_event = _vm->_events->chain(q_event, &event);
// Put the text in the center of the viewport, assuming it will fit on
@@ -1386,25 +1238,21 @@ void Script::sfPlacard(SCRIPTFUNC_PARAMS) {
event.code = kTextEvent;
event.op = kEventDisplay;
event.data = _placardTextEntry;
-
q_event = _vm->_events->chain(q_event, &event);
_vm->_scene->getBGPal(pal);
-
event.type = kEvTImmediate;
event.code = kPalEvent;
event.op = kEventBlackToPal;
event.time = 0;
event.duration = kNormalFadeDuration;
event.data = pal;
-
q_event = _vm->_events->chain(q_event, &event);
event.type = kEvTOneshot;
event.code = kScriptEvent;
event.op = kEventThreadWake;
event.param = kWaitTypePlacard;
-
q_event = _vm->_events->chain(q_event, &event);
}
@@ -1419,8 +1267,7 @@ void Script::sfPlacardOff(SCRIPTFUNC_PARAMS) {
void Script::sfPsychicProfile(SCRIPTFUNC_PARAMS) {
thread->wait(kWaitTypePlacard);
- int stringId = thread->pop();
- _vm->_scene->showPsychicProfile(thread->_strings->getString(stringId));
+ _vm->_scene->showPsychicProfile(thread->_strings->getString(thread->pop()));
}
void Script::sfPsychicProfileOff(SCRIPTFUNC_PARAMS) {
@@ -1433,9 +1280,7 @@ void Script::sfPsychicProfileOff(SCRIPTFUNC_PARAMS) {
// Script function #50 (0x32)
void Script::sfSetProtagState(SCRIPTFUNC_PARAMS) {
- int protagState = thread->pop();
-
- _vm->_actor->setProtagState(protagState);
+ _vm->_actor->setProtagState(thread->pop());
}
// Script function #51 (0x33)
@@ -1456,28 +1301,20 @@ void Script::sfResumeBgdAnim(SCRIPTFUNC_PARAMS) {
// Param5: actionCycle
// Param6: flags
void Script::sfThrowActor(SCRIPTFUNC_PARAMS) {
- int16 actorId;
- ActorData *actor;
- int16 flags;
- int32 actionCycle;
- Location location;
+ ActorData *actor = _vm->_actor->getActor(thread->pop());
+ actor->_finalTarget.x = thread->pop();
+ actor->_finalTarget.y = thread->pop();
+ actor->_finalTarget.z = actor->_location.z;
+ thread->pop(); // not used
+ int32 actionCycle = thread->pop();
+ int16 flags = thread->pop();
- actorId = thread->pop();
- location.x = thread->pop();
- location.y = thread->pop();
- thread->pop();
- actionCycle = thread->pop();
- flags = thread->pop();
-
- actor = _vm->_actor->getActor(actorId);
- location.z = actor->_location.z;
actor->_currentAction = kActionFall;
actor->_actionCycle = actionCycle;
actor->_fallAcceleration = -20;
actor->_fallVelocity = - (actor->_fallAcceleration * actor->_actionCycle) / 2;
- actor->_fallPosition = actor->_location.z << 4;
+ actor->_fallPosition = actor->_location.z << 4;
- actor->_finalTarget = location;
actor->_actionCycle--;
if (!(flags & kWalkAsync)) {
thread->waitWalk(actor);
@@ -1488,11 +1325,7 @@ void Script::sfThrowActor(SCRIPTFUNC_PARAMS) {
// Param1: actor id
// Param2: target object
void Script::sfWaitWalk(SCRIPTFUNC_PARAMS) {
- int16 actorId;
- ActorData *actor;
-
- actorId = thread->pop();
- actor = _vm->_actor->getActor(actorId);
+ ActorData *actor = _vm->_actor->getActor(thread->pop());
if ((actor->_currentAction == kActionWalkToPoint) ||
(actor->_currentAction == kActionWalkToLink) ||
@@ -1510,14 +1343,8 @@ void Script::sfScriptSceneID(SCRIPTFUNC_PARAMS) {
// Param1: actor id
// Param2: scene number
void Script::sfChangeActorScene(SCRIPTFUNC_PARAMS) {
- int16 actorId;
- int32 sceneNumber;
- ActorData *actor;
-
- actorId = thread->pop();
- sceneNumber = thread->pop();
- actor = _vm->_actor->getActor(actorId);
- actor->_sceneNumber = sceneNumber;
+ ActorData *actor = _vm->_actor->getActor(thread->pop());
+ actor->_sceneNumber = thread->pop();
}
// Script function #56 (0x38)
@@ -1526,19 +1353,11 @@ void Script::sfChangeActorScene(SCRIPTFUNC_PARAMS) {
// Param3: frame seq
// Param4: flags
void Script::sfScriptClimb(SCRIPTFUNC_PARAMS) {
- int16 actorId;
- int16 z;
- ActorData *actor;
- uint16 flags;
- int cycleFrameSequence;
-
- actorId = thread->pop();
- z = thread->pop();
- cycleFrameSequence = thread->pop();
- flags = thread->pop();
+ ActorData *actor = _vm->_actor->getActor(thread->pop());
+ actor->_finalTarget.z = thread->pop();
+ int cycleFrameSequence = thread->pop();
+ uint16 flags = thread->pop();
- actor = _vm->_actor->getActor(actorId);
- actor->_finalTarget.z = z;
actor->_flags &= ~kFollower;
actor->_actionCycle = 1;
actor->_cycleFrameSequence = cycleFrameSequence;
@@ -1552,10 +1371,8 @@ void Script::sfScriptClimb(SCRIPTFUNC_PARAMS) {
// Param1: door #
// Param2: door state
void Script::sfSetDoorState(SCRIPTFUNC_PARAMS) {
- int16 doorNumber;
- int16 doorState;
- doorNumber = thread->pop();
- doorState = thread->pop();
+ int16 doorNumber = thread->pop();
+ int16 doorState = thread->pop();
if (_vm->_scene->getFlags() & kSceneFlagISO) {
_vm->_isoMap->setTileDoorState(doorNumber, doorState);
@@ -1568,14 +1385,10 @@ void Script::sfSetDoorState(SCRIPTFUNC_PARAMS) {
// Param1: actor id
// Param2: z
void Script::sfSetActorZ(SCRIPTFUNC_PARAMS) {
- int16 objectId;
+ int16 objectId = thread->pop();
+ int16 z = thread->pop();
ActorData *actor;
ObjectData *obj;
- int16 z;
-
- objectId = thread->pop();
- z = thread->pop();
-
if (_vm->_actor->validActorId(objectId)) {
actor = _vm->_actor->getActor(objectId);
@@ -1595,22 +1408,15 @@ void Script::sfSetActorZ(SCRIPTFUNC_PARAMS) {
// Param4: x
// Param5: y
void Script::sfScriptText(SCRIPTFUNC_PARAMS) {
- int16 stringId;
- int16 flags;
- Rect rect;
- int color;
+ const char *text = thread->_strings->getString(thread->pop());
+ int16 flags = thread->pop();
+ int color = thread->pop();
Point point;
- int width;
- const char*text;
- stringId = thread->pop();
- flags = thread->pop();
- color = thread->pop();
point.x = thread->pop();
point.y = thread->pop();
+ Rect rect;
+ int width = _vm->_font->getStringWidth(kKnownFontScript, text, 0, kFontOutline);
- text = thread->_strings->getString(stringId);
-
- width = _vm->_font->getStringWidth(kKnownFontScript, text, 0, kFontOutline);
rect.top = point.y - 6;
rect.setHeight(12);
rect.left = point.x - width / 2;
@@ -1623,11 +1429,7 @@ void Script::sfScriptText(SCRIPTFUNC_PARAMS) {
// Script function #60 (0x3C)
// Param1: actor id
void Script::sfGetActorX(SCRIPTFUNC_PARAMS) {
- int16 actorId;
- ActorData *actor;
-
- actorId = thread->pop();
- actor = _vm->_actor->getActor(actorId);
+ ActorData *actor = _vm->_actor->getActor(thread->pop());
thread->_returnValue = actor->_location.x >> 2;
}
@@ -1635,23 +1437,17 @@ void Script::sfGetActorX(SCRIPTFUNC_PARAMS) {
// Script function #61 (0x3D)
// Param1: actor id
void Script::sfGetActorY(SCRIPTFUNC_PARAMS) {
- int16 actorId;
- ActorData *actor;
-
- actorId = thread->pop();
- actor = _vm->_actor->getActor(actorId);
+ ActorData *actor = _vm->_actor->getActor(thread->pop());
thread->_returnValue = actor->_location.y >> 2;
}
// Script function #62 (0x3E)
void Script::sfEraseDelta(SCRIPTFUNC_PARAMS) {
- Surface *backGroundSurface;
+ Surface *backGroundSurface = _vm->_render->getBackGroundSurface();
BGInfo backGroundInfo;
- backGroundSurface = _vm->_render->getBackGroundSurface();
_vm->_scene->getBGInfo(backGroundInfo);
-
backGroundSurface->blit(backGroundInfo.bounds, backGroundInfo.buffer);
}
@@ -1712,12 +1508,11 @@ void Script::sfPickClimbOutPos(SCRIPTFUNC_PARAMS) {
// Script function #65 (0x41)
void Script::sfTossRif(SCRIPTFUNC_PARAMS) {
- int16 uc , vc;
uint16 direction;
ActorData *protagonist = _vm->_actor->_protagonist;
+ int16 uc = protagonist->_location.u() >> 4;
+ int16 vc = protagonist->_location.v() >> 4;
- uc = protagonist->_location.u() >> 4;
- vc = protagonist->_location.v() >> 4;
if (_vm->_isoMap->findNearestChasm(uc, vc, direction)) {
uc <<= 4;
vc <<= 4;
@@ -1793,10 +1588,9 @@ void Script::sfPlayLoopedSound(SCRIPTFUNC_PARAMS) {
}
// Script function #72 (0x48)
+// Param1: animation id
void Script::sfGetDeltaFrame(SCRIPTFUNC_PARAMS) {
- uint16 animId = (uint16)thread->pop();
-
- thread->_returnValue = _vm->_anim->getCurrentFrame(animId);
+ thread->_returnValue = _vm->_anim->getCurrentFrame((uint16)thread->pop());
}
// Script function #73 (0x49)
@@ -1813,10 +1607,8 @@ void Script::sfProtectResult(SCRIPTFUNC_PARAMS) {
if (_vm->_copyProtection) {
thread->_returnValue = _vm->_interface->getProtectHash();
} else {
- int protectHash;
-
//cheating
- protectHash = thread->pop();
+ int protectHash = thread->pop();
thread->push(protectHash);
thread->_returnValue = protectHash;
}
@@ -1824,10 +1616,7 @@ void Script::sfProtectResult(SCRIPTFUNC_PARAMS) {
// Script function #75 (0x4b)
void Script::sfRand(SCRIPTFUNC_PARAMS) {
- int16 param;
-
- param = thread->pop();
- thread->_returnValue = _vm->_rnd.getRandomNumber(param - 1);
+ thread->_returnValue = _vm->_rnd.getRandomNumber(thread->pop() - 1);
}
// Script function #76 (0x4c)
@@ -1839,7 +1628,6 @@ void Script::sfFadeMusic(SCRIPTFUNC_PARAMS) {
void Script::sfPlayVoice(SCRIPTFUNC_PARAMS) {
int16 param = thread->pop();
- warning("sfPlayVoice(%d)", param);
if (param > 0) {
_vm->_sndRes->playVoice(param + 3712);
} else {
@@ -1881,13 +1669,24 @@ void Script::finishDialog(int strID, int replyID, int flags, int bitOffset) {
}
void Script::sfSetChapterPoints(SCRIPTFUNC_PARAMS) {
- int16 ethics = thread->pop();
- int16 barometer = thread->pop();
int chapter = _vm->_scene->currentChapterNumber();
+ _vm->_ethicsPoints[chapter] = thread->pop();
+ int16 barometer = thread->pop();
+ static PalEntry cur_pal[PAL_ENTRIES];
- _vm->_ethicsPoints[chapter] = ethics;
- _vm->_spiritualBarometer = ethics * 256 / barometer;
+ _vm->_spiritualBarometer = _vm->_ethicsPoints[chapter] * 256 / barometer;
_vm->_scene->setChapterPointsChanged(true); // don't save this music when saving in IHNM
+
+ if (_vm->_spiritualBarometer > 255)
+ _vm->_gfx->setPaletteColor(kIHNMColorPortrait, 0xff, 0xff, 0xff);
+ else
+ _vm->_gfx->setPaletteColor(kIHNMColorPortrait,
+ _vm->_spiritualBarometer * _vm->_interface->_portraitBgColor.red / 256,
+ _vm->_spiritualBarometer * _vm->_interface->_portraitBgColor.green / 256,
+ _vm->_spiritualBarometer * _vm->_interface->_portraitBgColor.blue / 256);
+
+ _vm->_gfx->getCurrentPal(cur_pal);
+ _vm->_gfx->setPalette(cur_pal);
}
void Script::sfSetPortraitBgColor(SCRIPTFUNC_PARAMS) {
@@ -1899,12 +1698,9 @@ void Script::sfSetPortraitBgColor(SCRIPTFUNC_PARAMS) {
}
void Script::sfScriptStartCutAway(SCRIPTFUNC_PARAMS) {
- int16 cut;
- int16 fade;
-
- cut = thread->pop();
+ int16 cut = thread->pop();
thread->pop(); // Not used
- fade = thread->pop();
+ int16 fade = thread->pop();
_vm->_anim->setCutAwayMode(kPanelCutaway);
_vm->_anim->playCutaway(cut, fade != 0);
@@ -1930,61 +1726,37 @@ void Script::sfResetMouseClicks(SCRIPTFUNC_PARAMS) {
// Used in IHNM only
// Param1: frames
void Script::sfWaitFrames(SCRIPTFUNC_PARAMS) {
- int16 frames;
- frames = thread->pop();
-
- // HACK for the nightfall scene in Benny's chapter
- // sfWaitFrames is supposed to wait for fadein and fadeout during that cutaway, but we
- // don't support it yet (function sfScriptFade). This is a temporary hack to avoid
- // having ScummVM wait for ever in that cutaway
- // FIXME: Remove this hack once the palette fading is properly handled
- if (_vm->_scene->currentChapterNumber() == 2 && _vm->_scene->currentSceneNumber() == 41 && _vm->_anim->hasCutaway())
- return;
+ int16 frames = thread->pop();
if (!_skipSpeeches)
thread->waitFrames(_vm->_frameCount + frames);
}
void Script::sfScriptFade(SCRIPTFUNC_PARAMS) {
- thread->pop(); // first pal entry, ignored (already handled by Gfx::palToBlack)
- thread->pop(); // last pal entry, ignored (already handled by Gfx::palToBlack)
+ int16 firstPalEntry = thread->pop();
+ int16 lastPalEntry = thread->pop();
int16 startingBrightness = thread->pop();
int16 endingBrightness = thread->pop();
- // delay between pal changes is always 10 (not used)
- static PalEntry cur_pal[PAL_ENTRIES];
Event event;
- short delta = (startingBrightness < endingBrightness) ? +1 : -1;
+ static PalEntry cur_pal[PAL_ENTRIES];
_vm->_gfx->getCurrentPal(cur_pal);
-
- // TODO: This is still wrong, probably a new event type needs to be added (kEventPalFade)
- warning("TODO: sfScriptFade");
- return;
-
- if (startingBrightness > 255)
- startingBrightness = 255;
- if (startingBrightness < 0 )
- startingBrightness = 0;
- if (endingBrightness > 255)
- endingBrightness = 255;
- if (endingBrightness < 0)
- endingBrightness = 0;
-
event.type = kEvTImmediate;
event.code = kPalEvent;
- event.op = kEventPalToBlack;
+ event.op = kEventPalFade;
event.time = 0;
- event.duration = kNormalFadeDuration - ((endingBrightness - startingBrightness) * delta);
+ event.duration = kNormalFadeDuration;
event.data = cur_pal;
-
- _vm->_events->queue(&event);
+ event.param = startingBrightness;
+ event.param2 = endingBrightness;
+ event.param3 = firstPalEntry;
+ event.param4 = lastPalEntry - firstPalEntry + 1;
+ _vm->_events->queue(&event);
}
void Script::sfScriptStartVideo(SCRIPTFUNC_PARAMS) {
- int16 vid;
- int16 fade;
- vid = thread->pop();
- fade = thread->pop();
+ int16 vid = thread->pop();
+ int16 fade = thread->pop();
_vm->_anim->setCutAwayMode(kPanelVideo);
_vm->_anim->startVideo(vid, fade != 0);
@@ -2006,14 +1778,10 @@ void Script::sfShowIHNMDemoHelpBg(SCRIPTFUNC_PARAMS) {
}
void Script::sfAddIHNMDemoHelpTextLine(SCRIPTFUNC_PARAMS) {
- int stringId, textHeight;
+ int stringId = thread->pop();
TextListEntry textEntry;
Event event;
- stringId = thread->pop();
-
- textHeight = _vm->_font->getHeight(kKnownFontVerb, thread->_strings->getString(stringId), 226, kFontCentered);
-
textEntry.knownColor = kKnownColorBlack;
textEntry.useRect = true;
textEntry.rect.left = 245;
@@ -2030,10 +1798,9 @@ void Script::sfAddIHNMDemoHelpTextLine(SCRIPTFUNC_PARAMS) {
event.code = kTextEvent;
event.op = kEventDisplay;
event.data = _psychicProfileTextEntry;
-
_vm->_events->queue(&event);
- _ihnmDemoCurrentY += 10;
+ _ihnmDemoCurrentY += _vm->_font->getHeight(kKnownFontVerb, thread->_strings->getString(stringId), 226, kFontCentered);
}
void Script::sfShowIHNMDemoHelpPage(SCRIPTFUNC_PARAMS) {
@@ -2051,9 +1818,14 @@ void Script::sfVstopLoopedFX(SCRIPTFUNC_PARAMS) {
_vm->_sound->stopSound();
}
-void Script::sf92(SCRIPTFUNC_PARAMS) {
- SF_stub("sf92", thread, nArgs);
- // This opcode is empty in the full version of IHNM, but it's not empty in the demo
+void Script::sfDemoSetInteractive(SCRIPTFUNC_PARAMS) {
+ if (thread->pop() == 0) {
+ _vm->_interface->deactivate();
+ _vm->_interface->setMode(kPanelNull);
+ }
+
+ // Note: the original also sets an appropriate flag here, but we don't,
+ // as we don't use it
}
void Script::sfDemoIsInteractive(SCRIPTFUNC_PARAMS) {
@@ -2159,7 +1931,6 @@ void Script::sfQueueMusic(SCRIPTFUNC_PARAMS) {
// change
// FIXME: If this is too short for other cases apart from chapter
// point change, set it back to 1000
-
_vm->_events->queue(&event);
if (!_vm->_scene->haveChapterPointsChanged()) {
@@ -2173,9 +1944,7 @@ void Script::sfQueueMusic(SCRIPTFUNC_PARAMS) {
}
void Script::sfDisableAbortSpeeches(SCRIPTFUNC_PARAMS) {
- int value = thread->pop();
-
- _vm->_interface->disableAbortSpeeches(value != 0);
+ _vm->_interface->disableAbortSpeeches(thread->pop() != 0);
}
void Script::sfNull(SCRIPTFUNC_PARAMS) {
diff --git a/engines/saga/sndres.cpp b/engines/saga/sndres.cpp
index edbdebabab..ac21656dfa 100644
--- a/engines/saga/sndres.cpp
+++ b/engines/saga/sndres.cpp
@@ -101,8 +101,7 @@ SndRes::~SndRes() {
}
}
-void SndRes::setVoiceBank(int serial)
-{
+void SndRes::setVoiceBank(int serial) {
if (_voiceSerial == serial) return;
_voiceSerial = serial;
@@ -183,9 +182,9 @@ bool SndRes::load(ResourceContext *context, uint32 resourceId, SoundBuffer &buff
}
bool uncompressedSound = false;
- // If a patch file exists for sound resource 4 (used in ITE intro), don't treat this sound as compressed
- if (_vm->getGameType() == GType_ITE && resourceId == 4 &&
- (Common::File::exists("sound/p2_a.iaf") || Common::File::exists("sound/p2_a.voc")))
+ // If patch data exists for sound resource 4 (used in ITE intro), don't treat this sound as compressed
+ // Patch data for this resource is in file p2_a.iaf or p2_a.voc
+ if (_vm->getGameType() == GType_ITE && resourceId == 4 && context->table[resourceId].patchData != NULL)
uncompressedSound = true;
// FIXME: Currently, the SFX.RES file in IHNM cannot be compressed
diff --git a/engines/scumm/actor.cpp b/engines/scumm/actor.cpp
index 187a45b836..38517c1d69 100644
--- a/engines/scumm/actor.cpp
+++ b/engines/scumm/actor.cpp
@@ -523,7 +523,7 @@ void Actor_v2::walkActor() {
if (_moving & MF_TURN) {
new_dir = updateActorDirection(false);
- // FIXME -- is this correct?
+ // FIXME: is this correct?
if (_facing != new_dir)
setDirection(new_dir);
else
@@ -670,7 +670,7 @@ int Actor::remapDirection(int dir, bool is_walking) {
bool flipX;
bool flipY;
- // FIXME - It seems that at least in The Dig the original code does
+ // FIXME: It seems that at least in The Dig the original code does
// check _ignoreBoxes here. However, it breaks some animations in Loom,
// causing Bobbin to face towards the camera instead of away from it
// in some places: After the tree has been destroyed by lightning, and
@@ -1446,7 +1446,7 @@ void Actor::drawActorCostume(bool hitTestMode) {
bcr->_actorX *= V12_X_MULTIPLIER;
bcr->_actorY *= V12_Y_MULTIPLIER;
}
- bcr->_actorX -= _vm->virtscr[0].xstart;
+ bcr->_actorX -= _vm->_virtscr[kMainVirtScreen].xstart;
if (_vm->_game.platform == Common::kPlatformNES) {
// In the NES version, when the actor is facing right,
@@ -1532,7 +1532,7 @@ void Actor::drawActorCostume(bool hitTestMode) {
_heNoTalkAnimation = 0;
// If the actor is partially hidden, redraw it next frame.
- if (bcr->drawCostume(_vm->virtscr[0], _vm->_gdi->_numStrips, this, _drawToBackBuf) & 1) {
+ if (bcr->drawCostume(_vm->_virtscr[kMainVirtScreen], _vm->_gdi->_numStrips, this, _drawToBackBuf) & 1) {
_needRedraw = (_vm->_game.version <= 6);
}
@@ -1902,7 +1902,7 @@ void ScummEngine::actorTalk(const byte *msg) {
convertMessageToString(msg, _charsetBuffer, sizeof(_charsetBuffer));
- // FIXME: Workaround for bugs #770039 and #770049
+ // WORKAROUND for bugs #770039 and #770049
if (_game.id == GID_LOOM) {
if (!*_charsetBuffer)
return;
@@ -2325,7 +2325,7 @@ void ScummEngine_v71he::postProcessAuxQueue() {
int y = (int16)READ_LE_UINT16(axfd + 4) + dy;
int w = (int16)READ_LE_UINT16(axfd + 6);
int h = (int16)READ_LE_UINT16(axfd + 8);
- VirtScreen *pvs = &virtscr[kMainVirtScreen];
+ VirtScreen *pvs = &_virtscr[kMainVirtScreen];
uint8 *dst1 = pvs->getPixels(0, pvs->topline);
uint8 *dst2 = pvs->getBackPixels(0, pvs->topline);
switch (comp) {
diff --git a/engines/scumm/akos.cpp b/engines/scumm/akos.cpp
index c8667d7ab2..86a19540d6 100644
--- a/engines/scumm/akos.cpp
+++ b/engines/scumm/akos.cpp
@@ -546,7 +546,7 @@ void AkosRenderer::codec1_genericDecode(Codec1 &v1) {
scaleytab = &v1.scaletable[v1.scaleYindex];
maskbit = revBitMask(v1.x & 7);
- mask = _vm->getMaskBuffer(v1.x - (_vm->virtscr[0].xstart & 7), v1.y, _zbuf);
+ mask = _vm->getMaskBuffer(v1.x - (_vm->_virtscr[kMainVirtScreen].xstart & 7), v1.y, _zbuf);
if (len)
goto StartPos;
@@ -610,17 +610,13 @@ void AkosRenderer::codec1_genericDecode(Codec1 &v1) {
skip_column = true;
v1.scaleXindex += v1.scaleXstep;
dst = v1.destptr;
- mask = _vm->getMaskBuffer(v1.x - (_vm->virtscr[0].xstart & 7), v1.y, _zbuf);
+ mask = _vm->getMaskBuffer(v1.x - (_vm->_virtscr[kMainVirtScreen].xstart & 7), v1.y, _zbuf);
}
StartPos:;
} while (--len);
} while (1);
}
-#ifdef PALMOS_68K
-const byte *bigCostumeScaleTable;
-const byte *smallCostumeScaleTableAKOS;
-#else
// This is exact duplicate of smallCostumeScaleTable[] in costume.cpp
// See FIXME below for explanation
const byte smallCostumeScaleTableAKOS[256] = {
@@ -757,7 +753,6 @@ const byte bigCostumeScaleTable[768] = {
0x0F, 0x8F, 0x4F, 0xCF, 0x2F, 0xAF, 0x6F, 0xEF,
0x1F, 0x9F, 0x5F, 0xDF, 0x3F, 0xBF, 0x7F, 0xFF,
};
-#endif
byte AkosRenderer::codec1(int xmoveCur, int ymoveCur) {
int num_colors;
@@ -987,8 +982,8 @@ byte AkosRenderer::codec1(int xmoveCur, int ymoveCur) {
}
void AkosRenderer::markRectAsDirty(Common::Rect rect) {
- rect.left -= _vm->virtscr[0].xstart & 7;
- rect.right -= _vm->virtscr[0].xstart & 7;
+ rect.left -= _vm->_virtscr[kMainVirtScreen].xstart & 7;
+ rect.right -= _vm->_virtscr[kMainVirtScreen].xstart & 7;
_vm->markRectAsDirty(kMainVirtScreen, rect, _actorID);
}
@@ -1862,18 +1857,3 @@ void ScummEngine_v7::akos_processQueue() {
#endif
} // End of namespace Scumm
-
-#ifdef PALMOS_68K
-#include "scumm_globals.h"
-
-_GINIT(Akos)
-_GSETPTR(Scumm::bigCostumeScaleTable, GBVARS_BIGSCALETABLE_INDEX, byte, GBVARS_SCUMM)
-//_GSETPTR(Scumm::smallCostumeScaleTableAKOS, GBVARS_SMALLSCALETABLEAKOS_INDEX, byte, GBVARS_SCUMM)
-_GEND
-
-_GRELEASE(Akos)
-_GRELEASEPTR(GBVARS_BIGSCALETABLE_INDEX, GBVARS_SCUMM)
-//_GRELEASEPTR(GBVARS_SMALLSCALETABLEAKOS_INDEX, GBVARS_SCUMM)
-_GEND
-
-#endif
diff --git a/engines/scumm/base-costume.cpp b/engines/scumm/base-costume.cpp
index 8886dbfcd4..fe87dc65ec 100644
--- a/engines/scumm/base-costume.cpp
+++ b/engines/scumm/base-costume.cpp
@@ -39,9 +39,9 @@ byte BaseCostumeRenderer::drawCostume(const VirtScreen &vs, int numStrips, const
else
_out.pixels = vs.getPixels(0, 0);
- _actorX += _vm->virtscr[0].xstart & 7;
+ _actorX += _vm->_virtscr[kMainVirtScreen].xstart & 7;
_out.w = _out.pitch;
- _out.pixels = (byte *)_out.pixels - (_vm->virtscr[0].xstart & 7);
+ _out.pixels = (byte *)_out.pixels - (_vm->_virtscr[kMainVirtScreen].xstart & 7);
_numStrips = numStrips;
diff --git a/engines/scumm/base-costume.h b/engines/scumm/base-costume.h
index 155bbff97f..7acaff2679 100644
--- a/engines/scumm/base-costume.h
+++ b/engines/scumm/base-costume.h
@@ -42,15 +42,8 @@ struct CostumeInfo {
#include "common/pack-end.h" // END STRUCT PACKING
-
-#ifdef PALMOS_68K
-extern const byte *smallCostumeScaleTable;
-extern const byte *bigCostumeScaleTable;
-#else
extern const byte smallCostumeScaleTable[256];
extern const byte bigCostumeScaleTable[768];
-#endif
-
class Actor;
diff --git a/engines/scumm/camera.cpp b/engines/scumm/camera.cpp
index d6ecc715ea..ea6ac9b528 100644
--- a/engines/scumm/camera.cpp
+++ b/engines/scumm/camera.cpp
@@ -199,7 +199,7 @@ void ScummEngine::cameraMoved() {
screenLeft = _screenStartStrip * 8;
}
- virtscr[0].xstart = screenLeft;
+ _virtscr[kMainVirtScreen].xstart = screenLeft;
}
void ScummEngine::panCameraTo(int x, int y) {
diff --git a/engines/scumm/charset.cpp b/engines/scumm/charset.cpp
index 2271bf53a1..6eb6cfd7c6 100644
--- a/engines/scumm/charset.cpp
+++ b/engines/scumm/charset.cpp
@@ -50,10 +50,7 @@ void ScummEngine::loadCJKFont() {
_useCJKMode = false;
_textSurfaceMultiplier = 1;
- if (_game.platform == Common::kPlatformSegaCD)
- return;
-
- if (_language == Common::JA_JPN && _game.version <= 5) { // FM-TOWNS v3 / v5 Kanji
+ if (_game.version <= 5 && _game.platform == Common::kPlatformFMTowns && _language == Common::JA_JPN) { // FM-TOWNS v3 / v5 Kanji
int numChar = 256 * 32;
_2byteWidth = 16;
_2byteHeight = 16;
@@ -66,7 +63,7 @@ void ScummEngine::loadCJKFont() {
fp.close();
}
_textSurfaceMultiplier = 2;
- } else if (_language == Common::KO_KOR || _language == Common::JA_JPN || _language == Common::ZH_TWN) {
+ } else if (_game.version >= 7 && (_language == Common::KO_KOR || _language == Common::JA_JPN || _language == Common::ZH_TWN)) {
int numChar = 0;
const char *fontFile = NULL;
@@ -77,7 +74,7 @@ void ScummEngine::loadCJKFont() {
break;
case Common::JA_JPN:
fontFile = (_game.id == GID_DIG) ? "kanji16.fnt" : "japanese.fnt";
- numChar = 1024; //FIXME
+ numChar = 1024; //FIXME: sev needs japanese font files to clarify font size
break;
case Common::ZH_TWN:
if (_game.id == GID_CMI) {
@@ -501,13 +498,6 @@ void CharsetRenderer::addLinebreaks(int a, byte *str, int pos, int maxwidth) {
setCurID(oldID);
}
-#ifdef PALMOS_68K
-static const byte *englishCharsetDataV2;
-static const byte *germanCharsetDataV2;
-static const byte *frenchCharsetDataV2;
-static const byte *italianCharsetDataV2;
-static const byte *spanishCharsetDataV2;
-#else
// English Zak font
static const byte englishCharsetDataV2[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@@ -1168,7 +1158,6 @@ static const byte spanishCharsetDataV2[] = {
0x1c, 0x36, 0x36, 0x7c, 0x66, 0x66, 0x7c, 0x40,
0x08, 0x0c, 0x0e, 0xff, 0xff, 0x0e, 0x0c, 0x08,
};
-#endif
CharsetRendererV2::CharsetRendererV2(ScummEngine *vm, Common::Language language)
: CharsetRendererV3(vm) {
@@ -1237,8 +1226,7 @@ int CharsetRendererV3::getCharWidth(byte chr) {
return spacing;
}
-void CharsetRendererV3::setColor(byte color)
-{
+void CharsetRendererV3::setColor(byte color) {
bool useShadow = false;
_color = color;
@@ -1769,7 +1757,7 @@ void CharsetRendererNut::printChar(int chr, bool ignoreCharsetMask) {
int drawTop = _top;
if (ignoreCharsetMask) {
- VirtScreen *vs = &_vm->virtscr[kMainVirtScreen];
+ VirtScreen *vs = &_vm->_virtscr[kMainVirtScreen];
s = *vs;
s.pixels = vs->getPixels(0, 0);
} else {
@@ -1893,24 +1881,3 @@ void CharsetRendererNES::drawBits1(const Graphics::Surface &s, byte *dst, const
}
} // End of namespace Scumm
-
-#ifdef PALMOS_68K
-#include "scumm_globals.h"
-
-_GINIT(Charset)
-_GSETPTR(Scumm::germanCharsetDataV2, GBVARS_GERMANCHARSETDATAV2_INDEX, byte, GBVARS_SCUMM)
-_GSETPTR(Scumm::frenchCharsetDataV2, GBVARS_FRENCHCHARSETDATAV2_INDEX, byte, GBVARS_SCUMM)
-_GSETPTR(Scumm::englishCharsetDataV2, GBVARS_ENGLISHCHARSETDATAV2_INDEX, byte, GBVARS_SCUMM)
-_GSETPTR(Scumm::italianCharsetDataV2, GBVARS_ITALIANCHARSETDATAV2_INDEX, byte, GBVARS_SCUMM)
-_GSETPTR(Scumm::spanishCharsetDataV2, GBVARS_SPANISHCHARSETDATAV2_INDEX, byte, GBVARS_SCUMM)
-_GEND
-
-_GRELEASE(Charset)
-_GRELEASEPTR(GBVARS_GERMANCHARSETDATAV2_INDEX, GBVARS_SCUMM)
-_GRELEASEPTR(GBVARS_FRENCHCHARSETDATAV2_INDEX, GBVARS_SCUMM)
-_GRELEASEPTR(GBVARS_ENGLISHCHARSETDATAV2_INDEX, GBVARS_SCUMM)
-_GRELEASEPTR(GBVARS_ITALIANCHARSETDATAV2_INDEX, GBVARS_SCUMM)
-_GRELEASEPTR(GBVARS_SPANISHCHARSETDATAV2_INDEX, GBVARS_SCUMM)
-_GEND
-
-#endif
diff --git a/engines/scumm/costume.cpp b/engines/scumm/costume.cpp
index 2c5be5bf21..ac61d39d25 100644
--- a/engines/scumm/costume.cpp
+++ b/engines/scumm/costume.cpp
@@ -32,9 +32,6 @@
namespace Scumm {
-#ifdef PALMOS_68K
-const byte *smallCostumeScaleTable;
-#else
const byte smallCostumeScaleTable[256] = {
0xFF, 0xFD, 0x7D, 0xBD, 0x3D, 0xDD, 0x5D, 0x9D,
0x1D, 0xED, 0x6D, 0xAD, 0x2D, 0xCD, 0x4D, 0x8D,
@@ -69,7 +66,6 @@ const byte smallCostumeScaleTable[256] = {
0x0E, 0x8E, 0x4E, 0xCE, 0x2E, 0xAE, 0x6E, 0xEE,
0x1E, 0x9E, 0x5E, 0xDE, 0x3E, 0xBE, 0x7E, 0xFE
};
-#endif
static const int v1MMNESLookup[25] = {
0x00, 0x03, 0x01, 0x06, 0x08,
@@ -1165,16 +1161,3 @@ byte C64CostumeLoader::increaseAnim(Actor *a, int slot) {
} // End of namespace Scumm
-
-#ifdef PALMOS_68K
-#include "scumm_globals.h"
-
-_GINIT(Costume)
-_GSETPTR(Scumm::smallCostumeScaleTable, GBVARS_SMALLSCALETABLE_INDEX, byte, GBVARS_SCUMM)
-_GEND
-
-_GRELEASE(Costume)
-_GRELEASEPTR(GBVARS_SMALLSCALETABLE_INDEX, GBVARS_SCUMM)
-_GEND
-
-#endif
diff --git a/engines/scumm/cursor.cpp b/engines/scumm/cursor.cpp
index 23657946c6..b8b2cbcb6d 100644
--- a/engines/scumm/cursor.cpp
+++ b/engines/scumm/cursor.cpp
@@ -236,7 +236,7 @@ void ScummEngine_v6::setCursorFromImg(uint img, uint room, uint imgindex) {
}
void ScummEngine_v6::useIm01Cursor(const byte *im, int w, int h) {
- VirtScreen *vs = &virtscr[0];
+ VirtScreen *vs = &_virtscr[kMainVirtScreen];
byte *buf, *dst;
const byte *src;
int i;
diff --git a/engines/scumm/debugger.cpp b/engines/scumm/debugger.cpp
index 83ba9e24c1..68a001c983 100644
--- a/engines/scumm/debugger.cpp
+++ b/engines/scumm/debugger.cpp
@@ -652,7 +652,7 @@ static int gfxPrimitivesCompareInt(const void *a, const void *b);
static void hlineColor(ScummEngine *scumm, int x1, int x2, int y, byte color) {
- VirtScreen *vs = &scumm->virtscr[0];
+ VirtScreen *vs = &scumm->_virtscr[kMainVirtScreen];
byte *ptr;
// Clip y
diff --git a/engines/scumm/detection.cpp b/engines/scumm/detection.cpp
index be830cab64..90c6e40aa7 100644
--- a/engines/scumm/detection.cpp
+++ b/engines/scumm/detection.cpp
@@ -18,8 +18,8 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
- * $URL:https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/branches/gsoc2007-fsnode/engines/scumm/detection.cpp $
- * $Id:detection.cpp 26949 2007-05-26 20:23:24Z david_corrales $
+ * $URL$
+ * $Id$
*
*/
@@ -56,11 +56,7 @@ static int compareMD5Table(const void *a, const void *b) {
}
static const MD5Table *findInMD5Table(const char *md5) {
-#ifdef PALMOS_68K
- uint32 arraySize = MemPtrSize((void *)md5table) / sizeof(MD5Table) - 1;
-#else
uint32 arraySize = ARRAYSIZE(md5table) - 1;
-#endif
return (const MD5Table *)bsearch(md5, md5table, arraySize, sizeof(MD5Table), compareMD5Table);
}
@@ -886,11 +882,9 @@ PluginError Engine_SCUMM_create(OSystem *syst, Engine **engine) {
*engine = new ScummEngine_v70he(syst, res);
break;
#endif
-#ifndef PALMOS_68K
case 61:
*engine = new ScummEngine_v60he(syst, res);
break;
-#endif
default:
*engine = new ScummEngine_v6(syst, res);
}
@@ -913,16 +907,3 @@ PluginError Engine_SCUMM_create(OSystem *syst, Engine **engine) {
REGISTER_PLUGIN(SCUMM, "Scumm Engine",
"LucasArts SCUMM Games (C) LucasArts\n"
"Humongous SCUMM Games (C) Humongous" );
-
-#ifdef PALMOS_68K
-#include "scumm_globals.h"
-
-_GINIT(Scumm_md5table)
-_GSETPTR(md5table, GBVARS_MD5TABLE_INDEX, MD5Table, GBVARS_SCUMM)
-_GEND
-
-_GRELEASE(Scumm_md5table)
-_GRELEASEPTR(GBVARS_MD5TABLE_INDEX, GBVARS_SCUMM)
-_GEND
-
-#endif
diff --git a/engines/scumm/detection.h b/engines/scumm/detection.h
index d0fefe3a29..bc67aafb7e 100644
--- a/engines/scumm/detection.h
+++ b/engines/scumm/detection.h
@@ -18,8 +18,8 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
- * $URL:https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/branches/gsoc2007-fsnode/engines/scumm/detection.h $
- * $Id:detection.h 26949 2007-05-26 20:23:24Z david_corrales $
+ * $URL$
+ * $Id$
*
*/
diff --git a/engines/scumm/detection_tables.h b/engines/scumm/detection_tables.h
index acde4e5ad0..70118b9baf 100644
--- a/engines/scumm/detection_tables.h
+++ b/engines/scumm/detection_tables.h
@@ -18,8 +18,8 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
- * $URL:https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/branches/gsoc2007-fsnode/engines/scumm/detection_tables.h $
- * $Id:detection_tables.h 26949 2007-05-26 20:23:24Z david_corrales $
+ * $URL$
+ * $Id$
*
*/
@@ -37,11 +37,7 @@
//#include "scumm/intern.h"
//#include "scumm/he/intern_he.h"
-#ifdef PALMOS_68K
-#include "extras/palm-scumm-md5.h"
-#else
#include "scumm/scumm-md5.h"
-#endif
namespace Scumm {
@@ -399,6 +395,7 @@ static const GameFilenamePattern gameFilenamesTable[] = {
{ "maniac", "Maniac Mansion (SW).prg", kGenUnchanged, Common::SE_SWE, Common::kPlatformNES, "NES" },
{ "maniac", "Maniac Mansion (U).prg", kGenUnchanged, Common::EN_USA, Common::kPlatformNES, "NES" },
{ "maniac", "Maniac Mansion (G).prg", kGenUnchanged, Common::DE_DEU, Common::kPlatformNES, "NES" },
+ { "maniac", "Maniac Mansion (Sp).prg", kGenUnchanged, Common::ES_ESP, Common::kPlatformNES, "NES" },
{ "zak", "%02d.LFL", kGenRoomNum, UNK_LANG, UNK, 0 },
{ "zak", "zak1.d64", kGenUnchanged, UNK_LANG, Common::kPlatformC64, 0 }, // ... and zak2.d64
diff --git a/engines/scumm/dialogs.cpp b/engines/scumm/dialogs.cpp
index 85a72cb090..1666578c4c 100644
--- a/engines/scumm/dialogs.cpp
+++ b/engines/scumm/dialogs.cpp
@@ -81,11 +81,6 @@ struct ResString {
char string[80];
};
-#ifdef PALMOS_68K
-static const ResString *string_map_table_v7;
-static const ResString *string_map_table_v6;
-static const ResString *string_map_table_v5;
-#else
static const ResString string_map_table_v8[] = {
{0, "/BT_100/Please insert disk %d. Press ENTER"},
{0, "/BT__003/Unable to Find %s, (%s %d) Press Button."},
@@ -216,7 +211,6 @@ static const ResString string_map_table_v345[] = {
{20, "Select a game to LOAD"},
{28, "Game title"}
};
-#endif
#pragma mark -
@@ -967,20 +961,3 @@ void Indy3IQPointsDialog::handleKeyDown(Common::KeyState state) {
}
} // End of namespace Scumm
-
-#ifdef PALMOS_68K
-#include "scumm_globals.h"
-
-_GINIT(Dialogs)
-_GSETPTR(Scumm::string_map_table_v7, GBVARS_STRINGMAPTABLEV7_INDEX, Scumm::ResString, GBVARS_SCUMM)
-_GSETPTR(Scumm::string_map_table_v6, GBVARS_STRINGMAPTABLEV6_INDEX, Scumm::ResString, GBVARS_SCUMM)
-_GSETPTR(Scumm::string_map_table_v5, GBVARS_STRINGMAPTABLEV5_INDEX, Scumm::ResString, GBVARS_SCUMM)
-_GEND
-
-_GRELEASE(Dialogs)
-_GRELEASEPTR(GBVARS_STRINGMAPTABLEV7_INDEX, GBVARS_SCUMM)
-_GRELEASEPTR(GBVARS_STRINGMAPTABLEV6_INDEX, GBVARS_SCUMM)
-_GRELEASEPTR(GBVARS_STRINGMAPTABLEV5_INDEX, GBVARS_SCUMM)
-_GEND
-
-#endif
diff --git a/engines/scumm/file.cpp b/engines/scumm/file.cpp
index 2c7f9ead5b..b80be63d32 100644
--- a/engines/scumm/file.cpp
+++ b/engines/scumm/file.cpp
@@ -24,9 +24,6 @@
*/
#include "scumm/file.h"
-#include "common/endian.h"
-#include "common/util.h"
-#include "common/md5.h"
#include "scumm/scumm.h"
@@ -196,1275 +193,6 @@ uint32 ScummFile::write(const void *, uint32) {
}
#pragma mark -
-#pragma mark --- ScummNESFile ---
-#pragma mark -
-
-enum ResType {
- NES_UNKNOWN,
- NES_GLOBDATA,
- NES_ROOM,
- NES_SCRIPT,
- NES_SOUND,
- NES_COSTUME,
- NES_ROOMGFX,
- NES_COSTUMEGFX,
- NES_SPRPALS,
- NES_SPRDESC,
- NES_SPRLENS,
- NES_SPROFFS,
- NES_SPRDATA,
- NES_CHARSET,
- NES_PREPLIST
-};
-
-struct ScummNESFile::Resource {
- uint32 offset;
- uint16 length;
- ResType type;
-};
-
-ScummNESFile::ScummNESFile() : _stream(0), _buf(0), _ROMset(kROMsetNum) {
-}
-
-uint32 ScummNESFile::write(const void *, uint32) {
- error("ScummNESFile does not support writing!");
- return 0;
-}
-
-void ScummNESFile::setEnc(byte enc) {
- _stream->setEnc(enc);
-}
-
-#ifdef PALMOS_68K
-static const ScummNESFile::Resource *res_roomgfx_usa;
-static const ScummNESFile::Resource *res_roomgfx_eur;
-static const ScummNESFile::Resource *res_roomgfx_swe;
-static const ScummNESFile::Resource *res_roomgfx_fra;
-static const ScummNESFile::Resource *res_roomgfx_ger;
-#else
-static const ScummNESFile::Resource res_roomgfx_usa[40] = {
- { 0x04001, 0x03C9, NES_ROOMGFX }, { 0x043CA, 0x069E, NES_ROOMGFX }, { 0x04A68, 0x0327, NES_ROOMGFX }, { 0x04D8F, 0x053B, NES_ROOMGFX }, { 0x052CA, 0x06BE, NES_ROOMGFX },
- { 0x05988, 0x0682, NES_ROOMGFX }, { 0x0600A, 0x0778, NES_ROOMGFX }, { 0x06782, 0x0517, NES_ROOMGFX }, { 0x06C99, 0x07FB, NES_ROOMGFX }, { 0x07494, 0x07BE, NES_ROOMGFX },
- { 0x08001, 0x07A5, NES_ROOMGFX }, { 0x087A6, 0x06DD, NES_ROOMGFX }, { 0x08E83, 0x04EA, NES_ROOMGFX }, { 0x0936D, 0x0846, NES_ROOMGFX }, { 0x09BB3, 0x08C8, NES_ROOMGFX },
- { 0x0A47B, 0x0844, NES_ROOMGFX }, { 0x0ACBF, 0x0515, NES_ROOMGFX }, { 0x0B1D4, 0x0799, NES_ROOMGFX }, { 0x0B96D, 0x04BB, NES_ROOMGFX }, { 0x07C52, 0x0319, NES_ROOMGFX },
- { 0x0C001, 0x0464, NES_ROOMGFX }, { 0x0C465, 0x076D, NES_ROOMGFX }, { 0x0CBD2, 0x0827, NES_ROOMGFX }, { 0x0D3F9, 0x0515, NES_ROOMGFX }, { 0x0D90E, 0x064E, NES_ROOMGFX },
- { 0x0DF5C, 0x0775, NES_ROOMGFX }, { 0x0E6D1, 0x06DD, NES_ROOMGFX }, { 0x0EDAE, 0x0376, NES_ROOMGFX }, { 0x0F124, 0x05F7, NES_ROOMGFX }, { 0x0F71B, 0x0787, NES_ROOMGFX },
- { 0x10001, 0x02D6, NES_ROOMGFX }, { 0x102D7, 0x06A3, NES_ROOMGFX }, { 0x1097A, 0x099F, NES_ROOMGFX }, { 0x11319, 0x0361, NES_ROOMGFX }, { 0x1167A, 0x0489, NES_ROOMGFX },
- { 0x11B03, 0x0437, NES_ROOMGFX }, { 0x11F3A, 0x084D, NES_ROOMGFX }, { 0x0BE28, 0x0199, NES_ROOMGFX }, { 0x12787, 0x09A7, NES_ROOMGFX }, { 0x1312E, 0x037A, NES_ROOMGFX }
-};
-static const ScummNESFile::Resource res_roomgfx_eur[40] = {
- { 0x04001, 0x03B9, NES_ROOMGFX }, { 0x043BA, 0x069E, NES_ROOMGFX }, { 0x04A58, 0x0327, NES_ROOMGFX }, { 0x04D7F, 0x053B, NES_ROOMGFX }, { 0x052BA, 0x06BE, NES_ROOMGFX },
- { 0x05978, 0x0682, NES_ROOMGFX }, { 0x05FFA, 0x0778, NES_ROOMGFX }, { 0x06772, 0x0517, NES_ROOMGFX }, { 0x06C89, 0x07FB, NES_ROOMGFX }, { 0x07484, 0x07BE, NES_ROOMGFX },
- { 0x08001, 0x07A5, NES_ROOMGFX }, { 0x087A6, 0x06DD, NES_ROOMGFX }, { 0x08E83, 0x04EA, NES_ROOMGFX }, { 0x0936D, 0x0846, NES_ROOMGFX }, { 0x09BB3, 0x08C8, NES_ROOMGFX },
- { 0x0A47B, 0x0844, NES_ROOMGFX }, { 0x0ACBF, 0x0515, NES_ROOMGFX }, { 0x0B1D4, 0x0799, NES_ROOMGFX }, { 0x0B96D, 0x04BB, NES_ROOMGFX }, { 0x07C42, 0x0319, NES_ROOMGFX },
- { 0x0C001, 0x0464, NES_ROOMGFX }, { 0x0C465, 0x076D, NES_ROOMGFX }, { 0x0CBD2, 0x0827, NES_ROOMGFX }, { 0x0D3F9, 0x0515, NES_ROOMGFX }, { 0x0D90E, 0x064E, NES_ROOMGFX },
- { 0x0DF5C, 0x0775, NES_ROOMGFX }, { 0x0E6D1, 0x06DD, NES_ROOMGFX }, { 0x0EDAE, 0x0376, NES_ROOMGFX }, { 0x0F124, 0x05F7, NES_ROOMGFX }, { 0x0F71B, 0x0787, NES_ROOMGFX },
- { 0x10001, 0x02D6, NES_ROOMGFX }, { 0x102D7, 0x06A3, NES_ROOMGFX }, { 0x1097A, 0x099F, NES_ROOMGFX }, { 0x11319, 0x0361, NES_ROOMGFX }, { 0x1167A, 0x0489, NES_ROOMGFX },
- { 0x11B03, 0x0437, NES_ROOMGFX }, { 0x11F3A, 0x084D, NES_ROOMGFX }, { 0x12787, 0x0199, NES_ROOMGFX }, { 0x12920, 0x09A7, NES_ROOMGFX }, { 0x132C7, 0x037A, NES_ROOMGFX }
-};
-static const ScummNESFile::Resource res_roomgfx_swe[40] = {
- { 0x04001, 0x03F0, NES_ROOMGFX }, { 0x043F1, 0x069E, NES_ROOMGFX }, { 0x04A8F, 0x0327, NES_ROOMGFX }, { 0x04DB6, 0x053B, NES_ROOMGFX }, { 0x052F1, 0x06BE, NES_ROOMGFX },
- { 0x059AF, 0x0682, NES_ROOMGFX }, { 0x06031, 0x0778, NES_ROOMGFX }, { 0x067A9, 0x0517, NES_ROOMGFX }, { 0x06CC0, 0x07FB, NES_ROOMGFX }, { 0x074BB, 0x07BE, NES_ROOMGFX },
- { 0x08001, 0x07A5, NES_ROOMGFX }, { 0x087A6, 0x06DD, NES_ROOMGFX }, { 0x08E83, 0x04EA, NES_ROOMGFX }, { 0x0936D, 0x07E2, NES_ROOMGFX }, { 0x09B4F, 0x0791, NES_ROOMGFX },
- { 0x0A2E0, 0x07B5, NES_ROOMGFX }, { 0x0AA95, 0x0515, NES_ROOMGFX }, { 0x0AFAA, 0x0799, NES_ROOMGFX }, { 0x0B743, 0x04BF, NES_ROOMGFX }, { 0x0BC02, 0x0319, NES_ROOMGFX },
- { 0x0C001, 0x0464, NES_ROOMGFX }, { 0x0C465, 0x072C, NES_ROOMGFX }, { 0x0CB91, 0x0827, NES_ROOMGFX }, { 0x0D3B8, 0x0515, NES_ROOMGFX }, { 0x0D8CD, 0x064E, NES_ROOMGFX },
- { 0x0DF1B, 0x0775, NES_ROOMGFX }, { 0x0E690, 0x06DD, NES_ROOMGFX }, { 0x0ED6D, 0x0376, NES_ROOMGFX }, { 0x0F0E3, 0x05F7, NES_ROOMGFX }, { 0x0F6DA, 0x0791, NES_ROOMGFX },
- { 0x07C79, 0x02D6, NES_ROOMGFX }, { 0x10001, 0x06A3, NES_ROOMGFX }, { 0x106A4, 0x0921, NES_ROOMGFX }, { 0x10FC5, 0x0361, NES_ROOMGFX }, { 0x11326, 0x0489, NES_ROOMGFX },
- { 0x117AF, 0x0437, NES_ROOMGFX }, { 0x11BE6, 0x084F, NES_ROOMGFX }, { 0x12435, 0x0199, NES_ROOMGFX }, { 0x125CE, 0x0947, NES_ROOMGFX }, { 0x12F15, 0x037A, NES_ROOMGFX }
-};
-static const ScummNESFile::Resource res_roomgfx_fra[40] = {
- { 0x04001, 0x0426, NES_ROOMGFX }, { 0x04427, 0x069E, NES_ROOMGFX }, { 0x04AC5, 0x0327, NES_ROOMGFX }, { 0x04DEC, 0x053B, NES_ROOMGFX }, { 0x05327, 0x06BE, NES_ROOMGFX },
- { 0x059E5, 0x0682, NES_ROOMGFX }, { 0x06067, 0x0778, NES_ROOMGFX }, { 0x067DF, 0x0517, NES_ROOMGFX }, { 0x06CF6, 0x07FB, NES_ROOMGFX }, { 0x074F1, 0x07BE, NES_ROOMGFX },
- { 0x08001, 0x07A5, NES_ROOMGFX }, { 0x087A6, 0x06DD, NES_ROOMGFX }, { 0x08E83, 0x04EA, NES_ROOMGFX }, { 0x0936D, 0x07E2, NES_ROOMGFX }, { 0x09B4F, 0x0791, NES_ROOMGFX },
- { 0x0A2E0, 0x07B5, NES_ROOMGFX }, { 0x0AA95, 0x0515, NES_ROOMGFX }, { 0x0AFAA, 0x0799, NES_ROOMGFX }, { 0x0B743, 0x04BB, NES_ROOMGFX }, { 0x0BBFE, 0x0319, NES_ROOMGFX },
- { 0x0C001, 0x0464, NES_ROOMGFX }, { 0x0C465, 0x072C, NES_ROOMGFX }, { 0x0CB91, 0x0827, NES_ROOMGFX }, { 0x0D3B8, 0x0515, NES_ROOMGFX }, { 0x0D8CD, 0x064E, NES_ROOMGFX },
- { 0x0DF1B, 0x0775, NES_ROOMGFX }, { 0x0E690, 0x06DD, NES_ROOMGFX }, { 0x0ED6D, 0x0376, NES_ROOMGFX }, { 0x0F0E3, 0x05F7, NES_ROOMGFX }, { 0x0F6DA, 0x0787, NES_ROOMGFX },
- { 0x10001, 0x02D6, NES_ROOMGFX }, { 0x102D7, 0x06A3, NES_ROOMGFX }, { 0x1097A, 0x0921, NES_ROOMGFX }, { 0x1129B, 0x0361, NES_ROOMGFX }, { 0x115FC, 0x0489, NES_ROOMGFX },
- { 0x11A85, 0x0437, NES_ROOMGFX }, { 0x11EBC, 0x070D, NES_ROOMGFX }, { 0x07CAF, 0x0199, NES_ROOMGFX }, { 0x125C9, 0x0947, NES_ROOMGFX }, { 0x12F10, 0x037A, NES_ROOMGFX }
-};
-static const ScummNESFile::Resource res_roomgfx_ger[40] = {
- { 0x04001, 0x0406, NES_ROOMGFX }, { 0x04407, 0x069E, NES_ROOMGFX }, { 0x04AA5, 0x0327, NES_ROOMGFX }, { 0x04DCC, 0x053B, NES_ROOMGFX }, { 0x05307, 0x06BE, NES_ROOMGFX },
- { 0x059C5, 0x0682, NES_ROOMGFX }, { 0x06047, 0x0778, NES_ROOMGFX }, { 0x067BF, 0x0517, NES_ROOMGFX }, { 0x06CD6, 0x07FB, NES_ROOMGFX }, { 0x074D1, 0x07BE, NES_ROOMGFX },
- { 0x08001, 0x07A5, NES_ROOMGFX }, { 0x087A6, 0x06DD, NES_ROOMGFX }, { 0x08E83, 0x04EA, NES_ROOMGFX }, { 0x0936D, 0x07E2, NES_ROOMGFX }, { 0x09B4F, 0x0791, NES_ROOMGFX },
- { 0x0A2E0, 0x07B5, NES_ROOMGFX }, { 0x0AA95, 0x0515, NES_ROOMGFX }, { 0x0AFAA, 0x0799, NES_ROOMGFX }, { 0x0B743, 0x04BB, NES_ROOMGFX }, { 0x0BBFE, 0x0319, NES_ROOMGFX },
- { 0x0C001, 0x0464, NES_ROOMGFX }, { 0x0C465, 0x072C, NES_ROOMGFX }, { 0x0CB91, 0x0827, NES_ROOMGFX }, { 0x0D3B8, 0x0515, NES_ROOMGFX }, { 0x0D8CD, 0x064E, NES_ROOMGFX },
- { 0x0DF1B, 0x0775, NES_ROOMGFX }, { 0x0E690, 0x06DD, NES_ROOMGFX }, { 0x0ED6D, 0x0376, NES_ROOMGFX }, { 0x0F0E3, 0x05F7, NES_ROOMGFX }, { 0x0F6DA, 0x0787, NES_ROOMGFX },
- { 0x07C8F, 0x02D6, NES_ROOMGFX }, { 0x10001, 0x06A3, NES_ROOMGFX }, { 0x106A4, 0x0921, NES_ROOMGFX }, { 0x10FC5, 0x0361, NES_ROOMGFX }, { 0x11326, 0x0489, NES_ROOMGFX },
- { 0x117AF, 0x0437, NES_ROOMGFX }, { 0x11BE6, 0x07A0, NES_ROOMGFX }, { 0x12386, 0x0199, NES_ROOMGFX }, { 0x1251F, 0x0947, NES_ROOMGFX }, { 0x12E66, 0x037A, NES_ROOMGFX }
-};
-#endif
-static const ScummNESFile::Resource *res_roomgfx[ScummNESFile::kROMsetNum] = {
- res_roomgfx_usa,
- res_roomgfx_eur,
- res_roomgfx_swe,
- res_roomgfx_fra,
- res_roomgfx_ger,
-};
-
-#ifdef PALMOS_68K
-static const ScummNESFile::Resource *res_costumegfx_usa;
-static const ScummNESFile::Resource *res_costumegfx_eur;
-static const ScummNESFile::Resource *res_costumegfx_swe;
-static const ScummNESFile::Resource *res_costumegfx_fra;
-static const ScummNESFile::Resource *res_costumegfx_ger;
-#else
-static const ScummNESFile::Resource res_costumegfx_usa[2] = { { 0x30001, 0x0EB8, NES_COSTUMEGFX }, { 0x2F9F1, 0x0340, NES_COSTUMEGFX } };
-static const ScummNESFile::Resource res_costumegfx_eur[2] = { { 0x30001, 0x0EB8, NES_COSTUMEGFX }, { 0x2F9F1, 0x0340, NES_COSTUMEGFX } };
-static const ScummNESFile::Resource res_costumegfx_swe[2] = { { 0x2EFE1, 0x0EB8, NES_COSTUMEGFX }, { 0x30001, 0x0340, NES_COSTUMEGFX } };
-static const ScummNESFile::Resource res_costumegfx_fra[2] = { { 0x30001, 0x0EB8, NES_COSTUMEGFX }, { 0x2F608, 0x0340, NES_COSTUMEGFX } };
-static const ScummNESFile::Resource res_costumegfx_ger[2] = { { 0x30001, 0x0EB8, NES_COSTUMEGFX }, { 0x2F4CE, 0x0340, NES_COSTUMEGFX } };
-#endif
-static const ScummNESFile::Resource *res_costumegfx[ScummNESFile::kROMsetNum] = {
- res_costumegfx_usa,
- res_costumegfx_eur,
- res_costumegfx_swe,
- res_costumegfx_fra,
- res_costumegfx_ger,
-};
-
-#ifdef PALMOS_68K
-static const ScummNESFile::Resource *res_rooms_usa;
-static const ScummNESFile::Resource *res_rooms_eur;
-static const ScummNESFile::Resource *res_rooms_swe;
-static const ScummNESFile::Resource *res_rooms_fra;
-static const ScummNESFile::Resource *res_rooms_ger;
-#else
-static const ScummNESFile::Resource res_rooms_usa[55] = {
- { 0x00000, 0x0000, NES_ROOM }, { 0x14001, 0x0D0C, NES_ROOM }, { 0x134A8, 0x04B3, NES_ROOM }, { 0x15397, 0x0849, NES_ROOM }, { 0x15C68, 0x0685, NES_ROOM },
- { 0x16381, 0x0715, NES_ROOM }, { 0x1395B, 0x04E7, NES_ROOM }, { 0x16CE8, 0x0AC0, NES_ROOM }, { 0x18001, 0x06BA, NES_ROOM }, { 0x17AED, 0x03CB, NES_ROOM },
- { 0x18BE7, 0x0663, NES_ROOM }, { 0x192A6, 0x0580, NES_ROOM }, { 0x19A44, 0x0443, NES_ROOM }, { 0x1A106, 0x0563, NES_ROOM }, { 0x1A669, 0x0446, NES_ROOM },
- { 0x1AAAF, 0x03A7, NES_ROOM }, { 0x1AE56, 0x07E3, NES_ROOM }, { 0x1B699, 0x0692, NES_ROOM }, { 0x1C001, 0x0B49, NES_ROOM }, { 0x1CD09, 0x04C6, NES_ROOM },
- { 0x1D4C2, 0x0568, NES_ROOM }, { 0x1DF6C, 0x0514, NES_ROOM }, { 0x1E8FA, 0x05CC, NES_ROOM }, { 0x1EF83, 0x0389, NES_ROOM }, { 0x1F5E4, 0x0723, NES_ROOM },
- { 0x20001, 0x049A, NES_ROOM }, { 0x20511, 0x04F8, NES_ROOM }, { 0x21666, 0x05CB, NES_ROOM }, { 0x21DD6, 0x046B, NES_ROOM }, { 0x222F0, 0x0460, NES_ROOM },
- { 0x227B6, 0x0909, NES_ROOM }, { 0x24001, 0x0366, NES_ROOM }, { 0x23BDF, 0x03CA, NES_ROOM }, { 0x247DB, 0x050D, NES_ROOM }, { 0x25ACF, 0x0346, NES_ROOM },
- { 0x1BDBD, 0x01CA, NES_ROOM }, { 0x25E15, 0x0457, NES_ROOM }, { 0x2626C, 0x0547, NES_ROOM }, { 0x267B3, 0x064A, NES_ROOM }, { 0x1FD72, 0x024B, NES_ROOM },
- { 0x2739A, 0x01FA, NES_ROOM }, { 0x2766D, 0x0219, NES_ROOM }, { 0x28001, 0x02F4, NES_ROOM }, { 0x284D6, 0x045C, NES_ROOM }, { 0x289A3, 0x09CF, NES_ROOM },
- { 0x293C6, 0x05A0, NES_ROOM }, { 0x27B65, 0x0201, NES_ROOM }, { 0x2ADD1, 0x0325, NES_ROOM }, { 0x2B339, 0x01FC, NES_ROOM }, { 0x2B535, 0x02A9, NES_ROOM },
- { 0x2B7DE, 0x02DE, NES_ROOM }, { 0x2C001, 0x03CE, NES_ROOM }, { 0x2BBC0, 0x0205, NES_ROOM }, { 0x2C53A, 0x0170, NES_ROOM }, { 0x13E42, 0x0169, NES_ROOM }
-};
-static const ScummNESFile::Resource res_rooms_eur[55] = {
- { 0x00000, 0x0000, NES_ROOM }, { 0x14001, 0x0D0C, NES_ROOM }, { 0x13641, 0x04B3, NES_ROOM }, { 0x15397, 0x0849, NES_ROOM }, { 0x15C68, 0x0685, NES_ROOM },
- { 0x16381, 0x0715, NES_ROOM }, { 0x16CE8, 0x04E7, NES_ROOM }, { 0x18001, 0x0ABF, NES_ROOM }, { 0x171CF, 0x06BA, NES_ROOM }, { 0x13AF4, 0x03D2, NES_ROOM },
- { 0x18E1A, 0x0663, NES_ROOM }, { 0x194D9, 0x04A9, NES_ROOM }, { 0x19BA0, 0x0443, NES_ROOM }, { 0x1A262, 0x047C, NES_ROOM }, { 0x1A6DE, 0x0446, NES_ROOM },
- { 0x1AB24, 0x03A7, NES_ROOM }, { 0x1AECB, 0x07E3, NES_ROOM }, { 0x1B70E, 0x0692, NES_ROOM }, { 0x1C001, 0x0ACA, NES_ROOM }, { 0x1CC8A, 0x04C6, NES_ROOM },
- { 0x1D443, 0x0568, NES_ROOM }, { 0x1DEED, 0x0514, NES_ROOM }, { 0x1E87B, 0x05CC, NES_ROOM }, { 0x1EF04, 0x0389, NES_ROOM }, { 0x1F565, 0x0723, NES_ROOM },
- { 0x20001, 0x049A, NES_ROOM }, { 0x20511, 0x04F8, NES_ROOM }, { 0x21666, 0x05D5, NES_ROOM }, { 0x21DE0, 0x046B, NES_ROOM }, { 0x222FA, 0x0460, NES_ROOM },
- { 0x227C0, 0x0909, NES_ROOM }, { 0x24001, 0x0366, NES_ROOM }, { 0x247DB, 0x03CA, NES_ROOM }, { 0x24BA5, 0x050D, NES_ROOM }, { 0x23BE9, 0x0346, NES_ROOM },
- { 0x17DB5, 0x01CA, NES_ROOM }, { 0x25E99, 0x0457, NES_ROOM }, { 0x262F0, 0x0547, NES_ROOM }, { 0x26837, 0x064A, NES_ROOM }, { 0x1FCF3, 0x024B, NES_ROOM },
- { 0x2741E, 0x01FA, NES_ROOM }, { 0x276F1, 0x0219, NES_ROOM }, { 0x28001, 0x02F4, NES_ROOM }, { 0x284D6, 0x045C, NES_ROOM }, { 0x289A3, 0x09CF, NES_ROOM },
- { 0x293C6, 0x05A0, NES_ROOM }, { 0x27BE9, 0x0201, NES_ROOM }, { 0x2ADE3, 0x0325, NES_ROOM }, { 0x2B34B, 0x01FC, NES_ROOM }, { 0x2B547, 0x02A9, NES_ROOM },
- { 0x2B7F0, 0x02DE, NES_ROOM }, { 0x2C001, 0x03CE, NES_ROOM }, { 0x2BBD2, 0x0205, NES_ROOM }, { 0x2C53A, 0x0170, NES_ROOM }, { 0x2BDD7, 0x0169, NES_ROOM }
-};
-static const ScummNESFile::Resource res_rooms_swe[55] = {
- { 0x00000, 0x0000, NES_ROOM }, { 0x14001, 0x0D12, NES_ROOM }, { 0x1328F, 0x04B3, NES_ROOM }, { 0x15367, 0x0859, NES_ROOM }, { 0x13742, 0x0694, NES_ROOM },
- { 0x15C45, 0x0707, NES_ROOM }, { 0x1658F, 0x04E0, NES_ROOM }, { 0x16A6F, 0x0AC8, NES_ROOM }, { 0x18001, 0x06C7, NES_ROOM }, { 0x1789C, 0x03EA, NES_ROOM },
- { 0x18C09, 0x0649, NES_ROOM }, { 0x192AE, 0x04AB, NES_ROOM }, { 0x19982, 0x0447, NES_ROOM }, { 0x1A04D, 0x047E, NES_ROOM }, { 0x1A4CB, 0x0444, NES_ROOM },
- { 0x1A90F, 0x03B9, NES_ROOM }, { 0x1ACC8, 0x07E9, NES_ROOM }, { 0x1B511, 0x06A4, NES_ROOM }, { 0x1C001, 0x0B1A, NES_ROOM }, { 0x1CCFD, 0x0486, NES_ROOM },
- { 0x1D482, 0x0579, NES_ROOM }, { 0x1DF61, 0x051E, NES_ROOM }, { 0x1E8EC, 0x05CF, NES_ROOM }, { 0x1EF73, 0x0398, NES_ROOM }, { 0x1F5F0, 0x071A, NES_ROOM },
- { 0x20001, 0x049C, NES_ROOM }, { 0x2051E, 0x051E, NES_ROOM }, { 0x21725, 0x05D5, NES_ROOM }, { 0x21EA5, 0x047F, NES_ROOM }, { 0x223D1, 0x0460, NES_ROOM },
- { 0x22897, 0x090D, NES_ROOM }, { 0x24001, 0x0378, NES_ROOM }, { 0x247C9, 0x03CA, NES_ROOM }, { 0x24B93, 0x050D, NES_ROOM }, { 0x25267, 0x0346, NES_ROOM },
- { 0x17CD0, 0x01CA, NES_ROOM }, { 0x255AD, 0x0453, NES_ROOM }, { 0x25A00, 0x053E, NES_ROOM }, { 0x25F3E, 0x0647, NES_ROOM }, { 0x1BC49, 0x024B, NES_ROOM },
- { 0x26B58, 0x01FA, NES_ROOM }, { 0x26E27, 0x0217, NES_ROOM }, { 0x27345, 0x02F4, NES_ROOM }, { 0x27829, 0x045C, NES_ROOM }, { 0x28001, 0x098A, NES_ROOM },
- { 0x289DF, 0x05A1, NES_ROOM }, { 0x2A442, 0x0201, NES_ROOM }, { 0x2A6E9, 0x0325, NES_ROOM }, { 0x1FD75, 0x01FC, NES_ROOM }, { 0x2AC64, 0x02A9, NES_ROOM },
- { 0x2AF0D, 0x02D1, NES_ROOM }, { 0x2B2E6, 0x03CC, NES_ROOM }, { 0x23D61, 0x0205, NES_ROOM }, { 0x2B818, 0x0168, NES_ROOM }, { 0x27CF6, 0x0169, NES_ROOM }
-};
-static const ScummNESFile::Resource res_rooms_fra[55] = {
- { 0x00000, 0x0000, NES_ROOM }, { 0x14001, 0x0D76, NES_ROOM }, { 0x1328A, 0x04C6, NES_ROOM }, { 0x15451, 0x0885, NES_ROOM }, { 0x13750, 0x0693, NES_ROOM },
- { 0x15D68, 0x0709, NES_ROOM }, { 0x166D4, 0x0528, NES_ROOM }, { 0x16BFC, 0x0ACC, NES_ROOM }, { 0x18001, 0x06E2, NES_ROOM }, { 0x17A63, 0x03E5, NES_ROOM },
- { 0x18C3B, 0x066A, NES_ROOM }, { 0x19301, 0x049E, NES_ROOM }, { 0x199C8, 0x044B, NES_ROOM }, { 0x1A0B1, 0x0478, NES_ROOM }, { 0x1A529, 0x043F, NES_ROOM },
- { 0x1A968, 0x03C8, NES_ROOM }, { 0x1AD30, 0x086F, NES_ROOM }, { 0x1B5FF, 0x069B, NES_ROOM }, { 0x1C001, 0x0AA9, NES_ROOM }, { 0x1CC97, 0x049E, NES_ROOM },
- { 0x1D42C, 0x05A8, NES_ROOM }, { 0x1DF71, 0x054E, NES_ROOM }, { 0x1E9D1, 0x0606, NES_ROOM }, { 0x1F0A2, 0x039A, NES_ROOM }, { 0x1F74E, 0x071C, NES_ROOM },
- { 0x20001, 0x04B5, NES_ROOM }, { 0x2052E, 0x04FF, NES_ROOM }, { 0x2172E, 0x05DB, NES_ROOM }, { 0x21EAD, 0x0489, NES_ROOM }, { 0x223E1, 0x0465, NES_ROOM },
- { 0x228AC, 0x0957, NES_ROOM }, { 0x24001, 0x037E, NES_ROOM }, { 0x2481A, 0x03CA, NES_ROOM }, { 0x24BE4, 0x050D, NES_ROOM }, { 0x252C0, 0x0346, NES_ROOM },
- { 0x1BD30, 0x01CA, NES_ROOM }, { 0x25606, 0x046D, NES_ROOM }, { 0x25A73, 0x055A, NES_ROOM }, { 0x25FCD, 0x0654, NES_ROOM }, { 0x26C98, 0x024B, NES_ROOM },
- { 0x26EE3, 0x01FA, NES_ROOM }, { 0x271DD, 0x0217, NES_ROOM }, { 0x27713, 0x02F4, NES_ROOM }, { 0x28001, 0x045C, NES_ROOM }, { 0x284CE, 0x0975, NES_ROOM },
- { 0x28E97, 0x05E6, NES_ROOM }, { 0x27C3A, 0x0201, NES_ROOM }, { 0x2A9D6, 0x0325, NES_ROOM }, { 0x2AF88, 0x01FC, NES_ROOM }, { 0x2B184, 0x02A9, NES_ROOM },
- { 0x2B42D, 0x02DF, NES_ROOM }, { 0x2B818, 0x03EC, NES_ROOM }, { 0x2BD67, 0x0209, NES_ROOM }, { 0x2C001, 0x0168, NES_ROOM }, { 0x2C4BF, 0x0169, NES_ROOM }
-};
-static const ScummNESFile::Resource res_rooms_ger[55] = {
- { 0x00000, 0x0000, NES_ROOM }, { 0x14001, 0x0D63, NES_ROOM }, { 0x131E0, 0x04A9, NES_ROOM }, { 0x13689, 0x086B, NES_ROOM }, { 0x15421, 0x06A8, NES_ROOM },
- { 0x15B5D, 0x0731, NES_ROOM }, { 0x16507, 0x0501, NES_ROOM }, { 0x16A08, 0x0AE9, NES_ROOM }, { 0x18001, 0x06DA, NES_ROOM }, { 0x17880, 0x03D0, NES_ROOM },
- { 0x18C7B, 0x0651, NES_ROOM }, { 0x19328, 0x04A7, NES_ROOM }, { 0x199FE, 0x0447, NES_ROOM }, { 0x1A0F1, 0x0486, NES_ROOM }, { 0x1A577, 0x045D, NES_ROOM },
- { 0x1A9D4, 0x03AE, NES_ROOM }, { 0x1AD82, 0x0840, NES_ROOM }, { 0x1B622, 0x06C3, NES_ROOM }, { 0x1C001, 0x0B07, NES_ROOM }, { 0x1CD05, 0x0494, NES_ROOM },
- { 0x1D4A5, 0x05AC, NES_ROOM }, { 0x1DFD6, 0x0524, NES_ROOM }, { 0x1E9C0, 0x05F7, NES_ROOM }, { 0x1F09A, 0x038E, NES_ROOM }, { 0x1F75F, 0x0733, NES_ROOM },
- { 0x20001, 0x04A9, NES_ROOM }, { 0x2052A, 0x052E, NES_ROOM }, { 0x2177C, 0x0621, NES_ROOM }, { 0x21F57, 0x0495, NES_ROOM }, { 0x2249A, 0x045E, NES_ROOM },
- { 0x2295E, 0x0951, NES_ROOM }, { 0x24001, 0x036E, NES_ROOM }, { 0x247F9, 0x03CA, NES_ROOM }, { 0x24BC3, 0x050D, NES_ROOM }, { 0x252A8, 0x0346, NES_ROOM },
- { 0x17CA2, 0x01CA, NES_ROOM }, { 0x255EE, 0x046F, NES_ROOM }, { 0x25A5D, 0x054D, NES_ROOM }, { 0x25FAA, 0x064B, NES_ROOM }, { 0x26BE2, 0x024B, NES_ROOM },
- { 0x26E2D, 0x01FA, NES_ROOM }, { 0x2710F, 0x0217, NES_ROOM }, { 0x27663, 0x02F4, NES_ROOM }, { 0x28001, 0x045C, NES_ROOM }, { 0x284CE, 0x0A8F, NES_ROOM },
- { 0x28FB1, 0x05FF, NES_ROOM }, { 0x27B69, 0x0201, NES_ROOM }, { 0x2AAA9, 0x0325, NES_ROOM }, { 0x1BD7C, 0x01FC, NES_ROOM }, { 0x2B031, 0x02A9, NES_ROOM },
- { 0x2B2DA, 0x02D8, NES_ROOM }, { 0x2B6D2, 0x03D2, NES_ROOM }, { 0x2BC0D, 0x020D, NES_ROOM }, { 0x2C001, 0x0168, NES_ROOM }, { 0x27E11, 0x0169, NES_ROOM }
-};
-#endif
-static const ScummNESFile::Resource *res_rooms[ScummNESFile::kROMsetNum] = {
- res_rooms_usa,
- res_rooms_eur,
- res_rooms_swe,
- res_rooms_fra,
- res_rooms_ger,
-};
-
-#ifdef PALMOS_68K
-static const ScummNESFile::Resource *res_scripts_usa;
-static const ScummNESFile::Resource *res_scripts_eur;
-static const ScummNESFile::Resource *res_scripts_swe;
-static const ScummNESFile::Resource *res_scripts_fra;
-static const ScummNESFile::Resource *res_scripts_ger;
-#else
-static const ScummNESFile::Resource res_scripts_usa[179] = {
- { 0x00000, 0x0000, NES_SCRIPT }, { 0x29966, 0x044D, NES_SCRIPT }, { 0x29DB3, 0x0207, NES_SCRIPT }, { 0x29FBA, 0x009F, NES_SCRIPT }, { 0x2A059, 0x03F4, NES_SCRIPT },
- { 0x2A44D, 0x01A1, NES_SCRIPT }, { 0x00000, 0x0000, NES_SCRIPT }, { 0x2A5EE, 0x004A, NES_SCRIPT }, { 0x00000, 0x0000, NES_SCRIPT }, { 0x2A638, 0x0005, NES_SCRIPT },
- { 0x2C6AA, 0x000D, NES_SCRIPT }, { 0x2C6B7, 0x000D, NES_SCRIPT }, { 0x186BB, 0x0040, NES_SCRIPT }, { 0x186FB, 0x0016, NES_SCRIPT }, { 0x1B639, 0x0046, NES_SCRIPT },
- { 0x1EEC6, 0x00BD, NES_SCRIPT }, { 0x21C31, 0x0055, NES_SCRIPT }, { 0x177A8, 0x0027, NES_SCRIPT }, { 0x1FD07, 0x0027, NES_SCRIPT }, { 0x1FD2E, 0x0027, NES_SCRIPT },
- { 0x1BD2B, 0x0022, NES_SCRIPT }, { 0x15BE0, 0x0088, NES_SCRIPT }, { 0x22241, 0x0020, NES_SCRIPT }, { 0x22261, 0x008F, NES_SCRIPT }, { 0x1924A, 0x002B, NES_SCRIPT },
- { 0x1CB4A, 0x0061, NES_SCRIPT }, { 0x1CBAB, 0x003C, NES_SCRIPT }, { 0x1CBE7, 0x0042, NES_SCRIPT }, { 0x1CC29, 0x004F, NES_SCRIPT }, { 0x2049B, 0x0076, NES_SCRIPT },
- { 0x16A96, 0x0035, NES_SCRIPT }, { 0x16ACB, 0x001C, NES_SCRIPT }, { 0x16AE7, 0x0014, NES_SCRIPT }, { 0x16AFB, 0x001C, NES_SCRIPT }, { 0x16B17, 0x0027, NES_SCRIPT },
- { 0x16B3E, 0x01AA, NES_SCRIPT }, { 0x1D1CF, 0x0096, NES_SCRIPT }, { 0x1D265, 0x010E, NES_SCRIPT }, { 0x1D373, 0x001C, NES_SCRIPT }, { 0x1D38F, 0x0056, NES_SCRIPT },
- { 0x1D3E5, 0x0072, NES_SCRIPT }, { 0x1E480, 0x0028, NES_SCRIPT }, { 0x1E4A8, 0x017D, NES_SCRIPT }, { 0x1E625, 0x0229, NES_SCRIPT }, { 0x28932, 0x0071, NES_SCRIPT },
- { 0x17EB8, 0x004D, NES_SCRIPT }, { 0x162ED, 0x0039, NES_SCRIPT }, { 0x18711, 0x028B, NES_SCRIPT }, { 0x1899C, 0x00BB, NES_SCRIPT }, { 0x18A57, 0x018B, NES_SCRIPT },
- { 0x00000, 0x0000, NES_SCRIPT }, { 0x19E87, 0x00ED, NES_SCRIPT }, { 0x21C86, 0x00F6, NES_SCRIPT }, { 0x1E84E, 0x009B, NES_SCRIPT }, { 0x21D7C, 0x0047, NES_SCRIPT },
- { 0x2C6C4, 0x004D, NES_SCRIPT }, { 0x16326, 0x0024, NES_SCRIPT }, { 0x14D0D, 0x0014, NES_SCRIPT }, { 0x177CF, 0x0059, NES_SCRIPT }, { 0x17828, 0x0109, NES_SCRIPT },
- { 0x17931, 0x0009, NES_SCRIPT }, { 0x14D21, 0x01B6, NES_SCRIPT }, { 0x2B0F6, 0x0243, NES_SCRIPT }, { 0x230BF, 0x067F, NES_SCRIPT }, { 0x2C711, 0x001C, NES_SCRIPT },
- { 0x2C72D, 0x001A, NES_SCRIPT }, { 0x2C747, 0x0021, NES_SCRIPT }, { 0x2C768, 0x0024, NES_SCRIPT }, { 0x2C78C, 0x0017, NES_SCRIPT }, { 0x2C7A3, 0x0017, NES_SCRIPT },
- { 0x2C7BA, 0x0014, NES_SCRIPT }, { 0x2C7CE, 0x0024, NES_SCRIPT }, { 0x00000, 0x0000, NES_SCRIPT }, { 0x2C7F2, 0x0011, NES_SCRIPT }, { 0x1793A, 0x009D, NES_SCRIPT },
- { 0x22750, 0x0066, NES_SCRIPT }, { 0x14ED7, 0x0075, NES_SCRIPT }, { 0x1F30C, 0x0120, NES_SCRIPT }, { 0x1FD55, 0x001D, NES_SCRIPT }, { 0x1F42C, 0x008F, NES_SCRIPT },
- { 0x1F4BB, 0x0097, NES_SCRIPT }, { 0x179D7, 0x006A, NES_SCRIPT }, { 0x17A41, 0x0030, NES_SCRIPT }, { 0x1F552, 0x0092, NES_SCRIPT }, { 0x2C803, 0x00CC, NES_SCRIPT },
- { 0x2C8CF, 0x00BA, NES_SCRIPT }, { 0x2C989, 0x0088, NES_SCRIPT }, { 0x20A09, 0x01B0, NES_SCRIPT }, { 0x20BB9, 0x0168, NES_SCRIPT }, { 0x20D21, 0x006C, NES_SCRIPT },
- { 0x20D8D, 0x0037, NES_SCRIPT }, { 0x20DC4, 0x00E4, NES_SCRIPT }, { 0x20EA8, 0x0045, NES_SCRIPT }, { 0x20EED, 0x00E1, NES_SCRIPT }, { 0x20FCE, 0x00F6, NES_SCRIPT },
- { 0x210C4, 0x0141, NES_SCRIPT }, { 0x21205, 0x0183, NES_SCRIPT }, { 0x21388, 0x0034, NES_SCRIPT }, { 0x213BC, 0x00A9, NES_SCRIPT }, { 0x24367, 0x011B, NES_SCRIPT },
- { 0x1BD4D, 0x0070, NES_SCRIPT }, { 0x1CC78, 0x0091, NES_SCRIPT }, { 0x29372, 0x0054, NES_SCRIPT }, { 0x19F74, 0x00CE, NES_SCRIPT }, { 0x1A042, 0x0077, NES_SCRIPT },
- { 0x14F4C, 0x0057, NES_SCRIPT }, { 0x27886, 0x02DF, NES_SCRIPT }, { 0x1DA2A, 0x0219, NES_SCRIPT }, { 0x1DC43, 0x00F9, NES_SCRIPT }, { 0x1DD3C, 0x0056, NES_SCRIPT },
- { 0x1DD92, 0x01C2, NES_SCRIPT }, { 0x14FA3, 0x004D, NES_SCRIPT }, { 0x27594, 0x00D9, NES_SCRIPT }, { 0x21DC3, 0x0013, NES_SCRIPT }, { 0x2A63D, 0x00F0, NES_SCRIPT },
- { 0x24482, 0x00E7, NES_SCRIPT }, { 0x21465, 0x00F2, NES_SCRIPT }, { 0x24569, 0x002B, NES_SCRIPT }, { 0x2C3CF, 0x010F, NES_SCRIPT }, { 0x24594, 0x00AA, NES_SCRIPT },
- { 0x24CE8, 0x0DAB, NES_SCRIPT }, { 0x1B67F, 0x000D, NES_SCRIPT }, { 0x1B68C, 0x000D, NES_SCRIPT }, { 0x2373E, 0x017C, NES_SCRIPT }, { 0x282F5, 0x01E1, NES_SCRIPT },
- { 0x238BA, 0x0153, NES_SCRIPT }, { 0x23A0D, 0x019C, NES_SCRIPT }, { 0x23BA9, 0x0016, NES_SCRIPT }, { 0x2C4DE, 0x005C, NES_SCRIPT }, { 0x23BBF, 0x0020, NES_SCRIPT },
- { 0x27D66, 0x00A5, NES_SCRIPT }, { 0x2A72D, 0x034D, NES_SCRIPT }, { 0x14FF0, 0x00E3, NES_SCRIPT }, { 0x2BABC, 0x005F, NES_SCRIPT }, { 0x00000, 0x0000, NES_SCRIPT },
- { 0x25A93, 0x003C, NES_SCRIPT }, { 0x1E8E9, 0x0011, NES_SCRIPT }, { 0x1634A, 0x0018, NES_SCRIPT }, { 0x26DFD, 0x001F, NES_SCRIPT }, { 0x26E1C, 0x0054, NES_SCRIPT },
- { 0x26E70, 0x0149, NES_SCRIPT }, { 0x26FB9, 0x004B, NES_SCRIPT }, { 0x27004, 0x017D, NES_SCRIPT }, { 0x27181, 0x0027, NES_SCRIPT }, { 0x271A8, 0x0041, NES_SCRIPT },
- { 0x271E9, 0x01B1, NES_SCRIPT }, { 0x16362, 0x001F, NES_SCRIPT }, { 0x2463E, 0x002A, NES_SCRIPT }, { 0x150D3, 0x019E, NES_SCRIPT }, { 0x19275, 0x0031, NES_SCRIPT },
- { 0x17A71, 0x007C, NES_SCRIPT }, { 0x21557, 0x00DC, NES_SCRIPT }, { 0x1D457, 0x0018, NES_SCRIPT }, { 0x1D46F, 0x0053, NES_SCRIPT }, { 0x18BE2, 0x0005, NES_SCRIPT },
- { 0x15271, 0x011B, NES_SCRIPT }, { 0x1538C, 0x000B, NES_SCRIPT }, { 0x24668, 0x0138, NES_SCRIPT }, { 0x247A0, 0x0014, NES_SCRIPT }, { 0x1DF54, 0x0018, NES_SCRIPT },
- { 0x247B4, 0x0027, NES_SCRIPT }, { 0x1A0B9, 0x004D, NES_SCRIPT }, { 0x00000, 0x0000, NES_SCRIPT }, { 0x2BB1B, 0x00A5, NES_SCRIPT }, { 0x2AA7A, 0x00C1, NES_SCRIPT },
- { 0x2AB3B, 0x0140, NES_SCRIPT }, { 0x19826, 0x00BF, NES_SCRIPT }, { 0x198E5, 0x014D, NES_SCRIPT }, { 0x19A32, 0x0012, NES_SCRIPT }, { 0x2AC7B, 0x0005, NES_SCRIPT },
- { 0x2AC80, 0x0005, NES_SCRIPT }, { 0x2AC85, 0x0005, NES_SCRIPT }, { 0x2AC8A, 0x0005, NES_SCRIPT }, { 0x2AC8F, 0x0005, NES_SCRIPT }, { 0x21633, 0x0033, NES_SCRIPT },
- { 0x2AC94, 0x0005, NES_SCRIPT }, { 0x00000, 0x0000, NES_SCRIPT }, { 0x2AC99, 0x009C, NES_SCRIPT }, { 0x2AD35, 0x009C, NES_SCRIPT }
-};
-static const ScummNESFile::Resource res_scripts_eur[179] = {
- { 0x00000, 0x0000, NES_SCRIPT }, { 0x29966, 0x044D, NES_SCRIPT }, { 0x29DB3, 0x0207, NES_SCRIPT }, { 0x29FBA, 0x009F, NES_SCRIPT }, { 0x2A059, 0x03F4, NES_SCRIPT },
- { 0x2A44D, 0x01A1, NES_SCRIPT }, { 0x00000, 0x0000, NES_SCRIPT }, { 0x2A5EE, 0x005C, NES_SCRIPT }, { 0x00000, 0x0000, NES_SCRIPT }, { 0x2A64A, 0x0005, NES_SCRIPT },
- { 0x2C6AA, 0x000D, NES_SCRIPT }, { 0x2C6B7, 0x000D, NES_SCRIPT }, { 0x17889, 0x0040, NES_SCRIPT }, { 0x178C9, 0x0016, NES_SCRIPT }, { 0x1B6AE, 0x0046, NES_SCRIPT },
- { 0x1EE47, 0x00BD, NES_SCRIPT }, { 0x21C3B, 0x0055, NES_SCRIPT }, { 0x18AC0, 0x0027, NES_SCRIPT }, { 0x1FC88, 0x0027, NES_SCRIPT }, { 0x1FCAF, 0x0027, NES_SCRIPT },
- { 0x1BDA0, 0x0022, NES_SCRIPT }, { 0x15BE0, 0x0088, NES_SCRIPT }, { 0x2224B, 0x0020, NES_SCRIPT }, { 0x2226B, 0x008F, NES_SCRIPT }, { 0x1947D, 0x002B, NES_SCRIPT },
- { 0x1CACB, 0x0061, NES_SCRIPT }, { 0x1CB2C, 0x003C, NES_SCRIPT }, { 0x1CB68, 0x0042, NES_SCRIPT }, { 0x1CBAA, 0x004F, NES_SCRIPT }, { 0x2049B, 0x0076, NES_SCRIPT },
- { 0x16A96, 0x0035, NES_SCRIPT }, { 0x16ACB, 0x001C, NES_SCRIPT }, { 0x16AE7, 0x0014, NES_SCRIPT }, { 0x16AFB, 0x001C, NES_SCRIPT }, { 0x16B17, 0x0027, NES_SCRIPT },
- { 0x16B3E, 0x01AA, NES_SCRIPT }, { 0x1D150, 0x0096, NES_SCRIPT }, { 0x1D1E6, 0x010E, NES_SCRIPT }, { 0x1D2F4, 0x001C, NES_SCRIPT }, { 0x1D310, 0x0056, NES_SCRIPT },
- { 0x1D366, 0x0072, NES_SCRIPT }, { 0x1E401, 0x0028, NES_SCRIPT }, { 0x1E429, 0x017D, NES_SCRIPT }, { 0x1E5A6, 0x0229, NES_SCRIPT }, { 0x28932, 0x0071, NES_SCRIPT },
- { 0x13EC6, 0x004D, NES_SCRIPT }, { 0x162ED, 0x0039, NES_SCRIPT }, { 0x178DF, 0x028B, NES_SCRIPT }, { 0x17B6A, 0x00BB, NES_SCRIPT }, { 0x17C25, 0x018B, NES_SCRIPT },
- { 0x00000, 0x0000, NES_SCRIPT }, { 0x19FE3, 0x00ED, NES_SCRIPT }, { 0x21C90, 0x00F6, NES_SCRIPT }, { 0x1E7CF, 0x009B, NES_SCRIPT }, { 0x21D86, 0x0047, NES_SCRIPT },
- { 0x2C6C4, 0x004D, NES_SCRIPT }, { 0x16326, 0x0024, NES_SCRIPT }, { 0x14D0D, 0x0014, NES_SCRIPT }, { 0x18AE7, 0x0059, NES_SCRIPT }, { 0x18B40, 0x011E, NES_SCRIPT },
- { 0x18C5E, 0x0009, NES_SCRIPT }, { 0x14D21, 0x01B6, NES_SCRIPT }, { 0x2B108, 0x0243, NES_SCRIPT }, { 0x230C9, 0x067F, NES_SCRIPT }, { 0x2C711, 0x001C, NES_SCRIPT },
- { 0x2C72D, 0x001A, NES_SCRIPT }, { 0x2C747, 0x0021, NES_SCRIPT }, { 0x2C768, 0x0024, NES_SCRIPT }, { 0x2C78C, 0x0017, NES_SCRIPT }, { 0x2C7A3, 0x0017, NES_SCRIPT },
- { 0x2C7BA, 0x0014, NES_SCRIPT }, { 0x2C7CE, 0x0024, NES_SCRIPT }, { 0x00000, 0x0000, NES_SCRIPT }, { 0x2C7F2, 0x0011, NES_SCRIPT }, { 0x18C67, 0x009D, NES_SCRIPT },
- { 0x2275A, 0x0066, NES_SCRIPT }, { 0x14ED7, 0x0075, NES_SCRIPT }, { 0x1F28D, 0x0120, NES_SCRIPT }, { 0x1FCD6, 0x001D, NES_SCRIPT }, { 0x1F3AD, 0x008F, NES_SCRIPT },
- { 0x1F43C, 0x0097, NES_SCRIPT }, { 0x18D04, 0x006A, NES_SCRIPT }, { 0x18D6E, 0x0030, NES_SCRIPT }, { 0x1F4D3, 0x0092, NES_SCRIPT }, { 0x2C803, 0x00CC, NES_SCRIPT },
- { 0x2C8CF, 0x00BA, NES_SCRIPT }, { 0x2C989, 0x0088, NES_SCRIPT }, { 0x20A09, 0x01B0, NES_SCRIPT }, { 0x20BB9, 0x0168, NES_SCRIPT }, { 0x20D21, 0x006C, NES_SCRIPT },
- { 0x20D8D, 0x0037, NES_SCRIPT }, { 0x20DC4, 0x00E4, NES_SCRIPT }, { 0x20EA8, 0x0045, NES_SCRIPT }, { 0x20EED, 0x00E1, NES_SCRIPT }, { 0x20FCE, 0x00F6, NES_SCRIPT },
- { 0x210C4, 0x0141, NES_SCRIPT }, { 0x21205, 0x0183, NES_SCRIPT }, { 0x21388, 0x0034, NES_SCRIPT }, { 0x213BC, 0x00A9, NES_SCRIPT }, { 0x24367, 0x011B, NES_SCRIPT },
- { 0x1BDC2, 0x0070, NES_SCRIPT }, { 0x1CBF9, 0x0091, NES_SCRIPT }, { 0x29372, 0x0054, NES_SCRIPT }, { 0x1A0D0, 0x00CE, NES_SCRIPT }, { 0x1A19E, 0x0077, NES_SCRIPT },
- { 0x14F4C, 0x0057, NES_SCRIPT }, { 0x2790A, 0x02DF, NES_SCRIPT }, { 0x1D9AB, 0x0219, NES_SCRIPT }, { 0x1DBC4, 0x00F9, NES_SCRIPT }, { 0x1DCBD, 0x0056, NES_SCRIPT },
- { 0x1DD13, 0x01C2, NES_SCRIPT }, { 0x14FA3, 0x004D, NES_SCRIPT }, { 0x27618, 0x00D9, NES_SCRIPT }, { 0x21DCD, 0x0013, NES_SCRIPT }, { 0x2A64F, 0x00F0, NES_SCRIPT },
- { 0x24482, 0x00E7, NES_SCRIPT }, { 0x21465, 0x00F2, NES_SCRIPT }, { 0x24569, 0x002B, NES_SCRIPT }, { 0x2C3CF, 0x010F, NES_SCRIPT }, { 0x24594, 0x00AA, NES_SCRIPT },
- { 0x250B2, 0x0DAB, NES_SCRIPT }, { 0x1B6F4, 0x000D, NES_SCRIPT }, { 0x1B701, 0x000D, NES_SCRIPT }, { 0x23748, 0x017C, NES_SCRIPT }, { 0x282F5, 0x01E1, NES_SCRIPT },
- { 0x238C4, 0x0153, NES_SCRIPT }, { 0x23A17, 0x019C, NES_SCRIPT }, { 0x23BB3, 0x0016, NES_SCRIPT }, { 0x2C4DE, 0x005C, NES_SCRIPT }, { 0x23BC9, 0x0020, NES_SCRIPT },
- { 0x27DEA, 0x00A5, NES_SCRIPT }, { 0x2A73F, 0x034D, NES_SCRIPT }, { 0x14FF0, 0x00E3, NES_SCRIPT }, { 0x2BACE, 0x005F, NES_SCRIPT }, { 0x00000, 0x0000, NES_SCRIPT },
- { 0x25E5D, 0x003C, NES_SCRIPT }, { 0x1E86A, 0x0011, NES_SCRIPT }, { 0x1634A, 0x0018, NES_SCRIPT }, { 0x26E81, 0x001F, NES_SCRIPT }, { 0x26EA0, 0x0054, NES_SCRIPT },
- { 0x26EF4, 0x0149, NES_SCRIPT }, { 0x2703D, 0x004B, NES_SCRIPT }, { 0x27088, 0x017D, NES_SCRIPT }, { 0x27205, 0x0027, NES_SCRIPT }, { 0x2722C, 0x0041, NES_SCRIPT },
- { 0x2726D, 0x01B1, NES_SCRIPT }, { 0x16362, 0x001F, NES_SCRIPT }, { 0x2463E, 0x002A, NES_SCRIPT }, { 0x150D3, 0x019E, NES_SCRIPT }, { 0x194A8, 0x0031, NES_SCRIPT },
- { 0x18D9E, 0x007C, NES_SCRIPT }, { 0x21557, 0x00DC, NES_SCRIPT }, { 0x1D3D8, 0x0018, NES_SCRIPT }, { 0x1D3F0, 0x0053, NES_SCRIPT }, { 0x17DB0, 0x0005, NES_SCRIPT },
- { 0x15271, 0x011B, NES_SCRIPT }, { 0x1538C, 0x000B, NES_SCRIPT }, { 0x24668, 0x0138, NES_SCRIPT }, { 0x247A0, 0x0014, NES_SCRIPT }, { 0x1DED5, 0x0018, NES_SCRIPT },
- { 0x247B4, 0x0027, NES_SCRIPT }, { 0x1A215, 0x004D, NES_SCRIPT }, { 0x00000, 0x0000, NES_SCRIPT }, { 0x2BB2D, 0x00A5, NES_SCRIPT }, { 0x2AA8C, 0x00C1, NES_SCRIPT },
- { 0x2AB4D, 0x0140, NES_SCRIPT }, { 0x19982, 0x00BF, NES_SCRIPT }, { 0x19A41, 0x014D, NES_SCRIPT }, { 0x19B8E, 0x0012, NES_SCRIPT }, { 0x2AC8D, 0x0005, NES_SCRIPT },
- { 0x2AC92, 0x0005, NES_SCRIPT }, { 0x2AC97, 0x0005, NES_SCRIPT }, { 0x2AC9C, 0x0005, NES_SCRIPT }, { 0x2ACA1, 0x0005, NES_SCRIPT }, { 0x21633, 0x0033, NES_SCRIPT },
- { 0x2ACA6, 0x0005, NES_SCRIPT }, { 0x00000, 0x0000, NES_SCRIPT }, { 0x2ACAB, 0x009C, NES_SCRIPT }, { 0x2AD47, 0x009C, NES_SCRIPT }
-};
-static const ScummNESFile::Resource res_scripts_swe[179] = {
- { 0x00000, 0x0000, NES_SCRIPT }, { 0x28F80, 0x043B, NES_SCRIPT }, { 0x293BB, 0x0209, NES_SCRIPT }, { 0x295C4, 0x00AB, NES_SCRIPT }, { 0x2966F, 0x03FD, NES_SCRIPT },
- { 0x29A6C, 0x01A1, NES_SCRIPT }, { 0x00000, 0x0000, NES_SCRIPT }, { 0x29C0D, 0x005C, NES_SCRIPT }, { 0x00000, 0x0000, NES_SCRIPT }, { 0x29C69, 0x0005, NES_SCRIPT },
- { 0x2B980, 0x000D, NES_SCRIPT }, { 0x2B98D, 0x000D, NES_SCRIPT }, { 0x186C8, 0x0040, NES_SCRIPT }, { 0x18708, 0x0016, NES_SCRIPT }, { 0x1B4B1, 0x0046, NES_SCRIPT },
- { 0x1EEBB, 0x00B8, NES_SCRIPT }, { 0x21CFA, 0x005C, NES_SCRIPT }, { 0x17537, 0x0027, NES_SCRIPT }, { 0x1FD0A, 0x0027, NES_SCRIPT }, { 0x1FD31, 0x0027, NES_SCRIPT },
- { 0x1BBB5, 0x0022, NES_SCRIPT }, { 0x15BC0, 0x0085, NES_SCRIPT }, { 0x22324, 0x001E, NES_SCRIPT }, { 0x22342, 0x008F, NES_SCRIPT }, { 0x19252, 0x002B, NES_SCRIPT },
- { 0x1CB1B, 0x006D, NES_SCRIPT }, { 0x1CB88, 0x004C, NES_SCRIPT }, { 0x1CBD4, 0x0044, NES_SCRIPT }, { 0x1CC18, 0x0053, NES_SCRIPT }, { 0x2049D, 0x0081, NES_SCRIPT },
- { 0x1634C, 0x0035, NES_SCRIPT }, { 0x16381, 0x001C, NES_SCRIPT }, { 0x1639D, 0x0014, NES_SCRIPT }, { 0x163B1, 0x001C, NES_SCRIPT }, { 0x163CD, 0x0027, NES_SCRIPT },
- { 0x163F4, 0x019B, NES_SCRIPT }, { 0x1D183, 0x0094, NES_SCRIPT }, { 0x1D217, 0x0117, NES_SCRIPT }, { 0x1D32E, 0x001C, NES_SCRIPT }, { 0x1D34A, 0x0056, NES_SCRIPT },
- { 0x1D3A0, 0x0072, NES_SCRIPT }, { 0x1E47F, 0x0028, NES_SCRIPT }, { 0x1E4A7, 0x0175, NES_SCRIPT }, { 0x1E61C, 0x022B, NES_SCRIPT }, { 0x27C85, 0x0071, NES_SCRIPT },
- { 0x17C86, 0x004A, NES_SCRIPT }, { 0x13DD6, 0x0039, NES_SCRIPT }, { 0x1871E, 0x0270, NES_SCRIPT }, { 0x1898E, 0x00C0, NES_SCRIPT }, { 0x18A4E, 0x01B6, NES_SCRIPT },
- { 0x00000, 0x0000, NES_SCRIPT }, { 0x19DC9, 0x00EE, NES_SCRIPT }, { 0x21D56, 0x00F5, NES_SCRIPT }, { 0x1E847, 0x0094, NES_SCRIPT }, { 0x21E4B, 0x0047, NES_SCRIPT },
- { 0x2B99A, 0x004D, NES_SCRIPT }, { 0x13E0F, 0x0024, NES_SCRIPT }, { 0x14D13, 0x0014, NES_SCRIPT }, { 0x1755E, 0x0054, NES_SCRIPT }, { 0x175B2, 0x011A, NES_SCRIPT },
- { 0x176CC, 0x0009, NES_SCRIPT }, { 0x14D27, 0x01B9, NES_SCRIPT }, { 0x2AA0E, 0x0256, NES_SCRIPT }, { 0x231A4, 0x06D2, NES_SCRIPT }, { 0x2B9E7, 0x001D, NES_SCRIPT },
- { 0x2BA04, 0x0016, NES_SCRIPT }, { 0x2BA1A, 0x002D, NES_SCRIPT }, { 0x2BA47, 0x0027, NES_SCRIPT }, { 0x2BA6E, 0x0016, NES_SCRIPT }, { 0x2BA84, 0x0014, NES_SCRIPT },
- { 0x2BA98, 0x0015, NES_SCRIPT }, { 0x2BAAD, 0x0029, NES_SCRIPT }, { 0x00000, 0x0000, NES_SCRIPT }, { 0x2BAD6, 0x0010, NES_SCRIPT }, { 0x176D5, 0x00A2, NES_SCRIPT },
- { 0x22831, 0x0066, NES_SCRIPT }, { 0x14EE0, 0x0077, NES_SCRIPT }, { 0x1F30B, 0x011A, NES_SCRIPT }, { 0x1FD58, 0x001D, NES_SCRIPT }, { 0x1F425, 0x0095, NES_SCRIPT },
- { 0x1F4BA, 0x009E, NES_SCRIPT }, { 0x17777, 0x006F, NES_SCRIPT }, { 0x177E6, 0x002F, NES_SCRIPT }, { 0x1F558, 0x0098, NES_SCRIPT }, { 0x2BAE6, 0x00C4, NES_SCRIPT },
- { 0x2BBAA, 0x00AE, NES_SCRIPT }, { 0x2BC58, 0x0088, NES_SCRIPT }, { 0x20A3C, 0x01BB, NES_SCRIPT }, { 0x20BF7, 0x0197, NES_SCRIPT }, { 0x20D8E, 0x006E, NES_SCRIPT },
- { 0x20DFC, 0x0028, NES_SCRIPT }, { 0x20E24, 0x00EA, NES_SCRIPT }, { 0x20F0E, 0x0049, NES_SCRIPT }, { 0x20F57, 0x00E7, NES_SCRIPT }, { 0x2103E, 0x010C, NES_SCRIPT },
- { 0x2114A, 0x0151, NES_SCRIPT }, { 0x2129B, 0x01B0, NES_SCRIPT }, { 0x2144B, 0x0034, NES_SCRIPT }, { 0x2147F, 0x00A9, NES_SCRIPT }, { 0x24379, 0x010E, NES_SCRIPT },
- { 0x1BBD7, 0x0072, NES_SCRIPT }, { 0x1CC6B, 0x0092, NES_SCRIPT }, { 0x2898B, 0x0054, NES_SCRIPT }, { 0x19EB7, 0x00D3, NES_SCRIPT }, { 0x19F8A, 0x0077, NES_SCRIPT },
- { 0x14F57, 0x0057, NES_SCRIPT }, { 0x2703E, 0x0307, NES_SCRIPT }, { 0x1D9FB, 0x024F, NES_SCRIPT }, { 0x1DC4A, 0x00E4, NES_SCRIPT }, { 0x1DD2E, 0x0059, NES_SCRIPT },
- { 0x1DD87, 0x01C2, NES_SCRIPT }, { 0x14FAE, 0x004D, NES_SCRIPT }, { 0x26D52, 0x00D5, NES_SCRIPT }, { 0x21E92, 0x0013, NES_SCRIPT }, { 0x29C6E, 0x00F0, NES_SCRIPT },
- { 0x24487, 0x00E0, NES_SCRIPT }, { 0x21528, 0x00F2, NES_SCRIPT }, { 0x24567, 0x0023, NES_SCRIPT }, { 0x2B6B2, 0x010B, NES_SCRIPT }, { 0x2458A, 0x00A1, NES_SCRIPT },
- { 0x250A0, 0x018B, NES_SCRIPT }, { 0x1B4F7, 0x000D, NES_SCRIPT }, { 0x1B504, 0x000D, NES_SCRIPT }, { 0x23876, 0x018E, NES_SCRIPT }, { 0x27639, 0x01F0, NES_SCRIPT },
- { 0x23A04, 0x017B, NES_SCRIPT }, { 0x23B7F, 0x01AC, NES_SCRIPT }, { 0x23D2B, 0x0016, NES_SCRIPT }, { 0x2B7BD, 0x005B, NES_SCRIPT }, { 0x23D41, 0x0020, NES_SCRIPT },
- { 0x2A643, 0x00A6, NES_SCRIPT }, { 0x29D5E, 0x0399, NES_SCRIPT }, { 0x14FFB, 0x00D2, NES_SCRIPT }, { 0x2B1DE, 0x0063, NES_SCRIPT }, { 0x00000, 0x0000, NES_SCRIPT },
- { 0x2522B, 0x003C, NES_SCRIPT }, { 0x1E8DB, 0x0011, NES_SCRIPT }, { 0x13E33, 0x0018, NES_SCRIPT }, { 0x26585, 0x001F, NES_SCRIPT }, { 0x265A4, 0x0054, NES_SCRIPT },
- { 0x265F8, 0x017D, NES_SCRIPT }, { 0x26775, 0x004B, NES_SCRIPT }, { 0x267C0, 0x0165, NES_SCRIPT }, { 0x26925, 0x0027, NES_SCRIPT }, { 0x2694C, 0x0041, NES_SCRIPT },
- { 0x2698D, 0x01CB, NES_SCRIPT }, { 0x13E4B, 0x001F, NES_SCRIPT }, { 0x2462B, 0x002A, NES_SCRIPT }, { 0x150CD, 0x0187, NES_SCRIPT }, { 0x1927D, 0x0031, NES_SCRIPT },
- { 0x17815, 0x0087, NES_SCRIPT }, { 0x2161A, 0x00D8, NES_SCRIPT }, { 0x1D412, 0x0018, NES_SCRIPT }, { 0x1D42A, 0x0058, NES_SCRIPT }, { 0x18C04, 0x0005, NES_SCRIPT },
- { 0x15254, 0x0108, NES_SCRIPT }, { 0x1535C, 0x000B, NES_SCRIPT }, { 0x24655, 0x0139, NES_SCRIPT }, { 0x2478E, 0x0014, NES_SCRIPT }, { 0x1DF49, 0x0018, NES_SCRIPT },
- { 0x247A2, 0x0027, NES_SCRIPT }, { 0x1A001, 0x004C, NES_SCRIPT }, { 0x00000, 0x0000, NES_SCRIPT }, { 0x2B241, 0x00A5, NES_SCRIPT }, { 0x2A0F7, 0x00B5, NES_SCRIPT },
- { 0x2A1AC, 0x0140, NES_SCRIPT }, { 0x19759, 0x00CA, NES_SCRIPT }, { 0x19823, 0x014D, NES_SCRIPT }, { 0x19970, 0x0012, NES_SCRIPT }, { 0x2A2EC, 0x0005, NES_SCRIPT },
- { 0x2A2F1, 0x0005, NES_SCRIPT }, { 0x2A2F6, 0x0005, NES_SCRIPT }, { 0x2A2FB, 0x0005, NES_SCRIPT }, { 0x2A300, 0x0005, NES_SCRIPT }, { 0x216F2, 0x0033, NES_SCRIPT },
- { 0x2A305, 0x0005, NES_SCRIPT }, { 0x00000, 0x0000, NES_SCRIPT }, { 0x2A30A, 0x009C, NES_SCRIPT }, { 0x2A3A6, 0x009C, NES_SCRIPT }
-};
-static const ScummNESFile::Resource res_scripts_fra[179] = {
- { 0x00000, 0x0000, NES_SCRIPT }, { 0x2947D, 0x0480, NES_SCRIPT }, { 0x298FD, 0x0226, NES_SCRIPT }, { 0x29B23, 0x0092, NES_SCRIPT }, { 0x29BB5, 0x040C, NES_SCRIPT },
- { 0x29FC1, 0x01A1, NES_SCRIPT }, { 0x00000, 0x0000, NES_SCRIPT }, { 0x2A162, 0x005C, NES_SCRIPT }, { 0x00000, 0x0000, NES_SCRIPT }, { 0x2A1BE, 0x0005, NES_SCRIPT },
- { 0x2C169, 0x000D, NES_SCRIPT }, { 0x2C176, 0x000D, NES_SCRIPT }, { 0x186E3, 0x0040, NES_SCRIPT }, { 0x18723, 0x0016, NES_SCRIPT }, { 0x1B59F, 0x0046, NES_SCRIPT },
- { 0x1EFD7, 0x00CB, NES_SCRIPT }, { 0x21D09, 0x0054, NES_SCRIPT }, { 0x176C8, 0x0027, NES_SCRIPT }, { 0x1FE6A, 0x0027, NES_SCRIPT }, { 0x1FE91, 0x0027, NES_SCRIPT },
- { 0x1BC9A, 0x0022, NES_SCRIPT }, { 0x15CD6, 0x0092, NES_SCRIPT }, { 0x22336, 0x001C, NES_SCRIPT }, { 0x22352, 0x008F, NES_SCRIPT }, { 0x192A5, 0x002B, NES_SCRIPT },
- { 0x1CAAA, 0x0069, NES_SCRIPT }, { 0x1CB13, 0x0054, NES_SCRIPT }, { 0x1CB67, 0x0048, NES_SCRIPT }, { 0x1CBAF, 0x0058, NES_SCRIPT }, { 0x204B6, 0x0078, NES_SCRIPT },
- { 0x16471, 0x0035, NES_SCRIPT }, { 0x164A6, 0x001C, NES_SCRIPT }, { 0x164C2, 0x0014, NES_SCRIPT }, { 0x164D6, 0x001C, NES_SCRIPT }, { 0x164F2, 0x0027, NES_SCRIPT },
- { 0x16519, 0x01BB, NES_SCRIPT }, { 0x1D135, 0x008D, NES_SCRIPT }, { 0x1D1C2, 0x0119, NES_SCRIPT }, { 0x1D2DB, 0x001C, NES_SCRIPT }, { 0x1D2F7, 0x0056, NES_SCRIPT },
- { 0x1D34D, 0x0072, NES_SCRIPT }, { 0x1E4BF, 0x0028, NES_SCRIPT }, { 0x1E4E7, 0x01E0, NES_SCRIPT }, { 0x1E6C7, 0x0241, NES_SCRIPT }, { 0x2845D, 0x0071, NES_SCRIPT },
- { 0x17E48, 0x004C, NES_SCRIPT }, { 0x13DE3, 0x0039, NES_SCRIPT }, { 0x18739, 0x0296, NES_SCRIPT }, { 0x189CF, 0x00C2, NES_SCRIPT }, { 0x18A91, 0x01A5, NES_SCRIPT },
- { 0x00000, 0x0000, NES_SCRIPT }, { 0x19E13, 0x00F3, NES_SCRIPT }, { 0x21D5D, 0x00F6, NES_SCRIPT }, { 0x1E908, 0x00B8, NES_SCRIPT }, { 0x21E53, 0x0047, NES_SCRIPT },
- { 0x2C183, 0x004D, NES_SCRIPT }, { 0x13E1C, 0x0024, NES_SCRIPT }, { 0x14D77, 0x0014, NES_SCRIPT }, { 0x176EF, 0x0059, NES_SCRIPT }, { 0x17748, 0x013F, NES_SCRIPT },
- { 0x17887, 0x0009, NES_SCRIPT }, { 0x14D8B, 0x01D4, NES_SCRIPT }, { 0x2ACFB, 0x028D, NES_SCRIPT }, { 0x23203, 0x0779, NES_SCRIPT }, { 0x2C1D0, 0x001B, NES_SCRIPT },
- { 0x2C1EB, 0x001F, NES_SCRIPT }, { 0x2C20A, 0x0024, NES_SCRIPT }, { 0x2C22E, 0x0019, NES_SCRIPT }, { 0x2C247, 0x0018, NES_SCRIPT }, { 0x2C25F, 0x001D, NES_SCRIPT },
- { 0x2C27C, 0x0016, NES_SCRIPT }, { 0x2C292, 0x0027, NES_SCRIPT }, { 0x00000, 0x0000, NES_SCRIPT }, { 0x2C2B9, 0x0011, NES_SCRIPT }, { 0x17890, 0x00AA, NES_SCRIPT },
- { 0x22846, 0x0066, NES_SCRIPT }, { 0x14F5F, 0x0083, NES_SCRIPT }, { 0x1F43C, 0x013A, NES_SCRIPT }, { 0x1FEB8, 0x001D, NES_SCRIPT }, { 0x1F576, 0x0098, NES_SCRIPT },
- { 0x1F60E, 0x009B, NES_SCRIPT }, { 0x1793A, 0x006E, NES_SCRIPT }, { 0x179A8, 0x0033, NES_SCRIPT }, { 0x1F6A9, 0x00A5, NES_SCRIPT }, { 0x2C2CA, 0x00BA, NES_SCRIPT },
- { 0x2C384, 0x00AC, NES_SCRIPT }, { 0x2C430, 0x008F, NES_SCRIPT }, { 0x20A2D, 0x01BE, NES_SCRIPT }, { 0x20BEB, 0x0158, NES_SCRIPT }, { 0x20D43, 0x0079, NES_SCRIPT },
- { 0x20DBC, 0x002B, NES_SCRIPT }, { 0x20DE7, 0x00E8, NES_SCRIPT }, { 0x20ECF, 0x004A, NES_SCRIPT }, { 0x20F19, 0x0110, NES_SCRIPT }, { 0x21029, 0x0136, NES_SCRIPT },
- { 0x2115F, 0x0152, NES_SCRIPT }, { 0x212B1, 0x01B3, NES_SCRIPT }, { 0x21464, 0x0032, NES_SCRIPT }, { 0x21496, 0x00A9, NES_SCRIPT }, { 0x2437F, 0x0133, NES_SCRIPT },
- { 0x1BCBC, 0x0074, NES_SCRIPT }, { 0x1CC07, 0x0090, NES_SCRIPT }, { 0x28E43, 0x0054, NES_SCRIPT }, { 0x19F06, 0x00DB, NES_SCRIPT }, { 0x19FE1, 0x0080, NES_SCRIPT },
- { 0x14FE2, 0x0057, NES_SCRIPT }, { 0x273F4, 0x031F, NES_SCRIPT }, { 0x1D9D4, 0x0238, NES_SCRIPT }, { 0x1DC0C, 0x00FE, NES_SCRIPT }, { 0x1DD0A, 0x005A, NES_SCRIPT },
- { 0x1DD64, 0x01F5, NES_SCRIPT }, { 0x15039, 0x004D, NES_SCRIPT }, { 0x270DD, 0x0100, NES_SCRIPT }, { 0x21E9A, 0x0013, NES_SCRIPT }, { 0x2A1C3, 0x00F0, NES_SCRIPT },
- { 0x244B2, 0x00E4, NES_SCRIPT }, { 0x2153F, 0x00EC, NES_SCRIPT }, { 0x24596, 0x0033, NES_SCRIPT }, { 0x2BC04, 0x0108, NES_SCRIPT }, { 0x245C9, 0x009F, NES_SCRIPT },
- { 0x250F1, 0x0193, NES_SCRIPT }, { 0x1B5E5, 0x000D, NES_SCRIPT }, { 0x1B5F2, 0x000D, NES_SCRIPT }, { 0x2397C, 0x0199, NES_SCRIPT }, { 0x27A07, 0x0233, NES_SCRIPT },
- { 0x23B15, 0x0171, NES_SCRIPT }, { 0x23C86, 0x01BC, NES_SCRIPT }, { 0x23E42, 0x0016, NES_SCRIPT }, { 0x2BD0C, 0x005B, NES_SCRIPT }, { 0x23E58, 0x0020, NES_SCRIPT },
- { 0x27E3B, 0x00B9, NES_SCRIPT }, { 0x2A2B3, 0x03D3, NES_SCRIPT }, { 0x15086, 0x00E4, NES_SCRIPT }, { 0x2B70C, 0x0067, NES_SCRIPT }, { 0x00000, 0x0000, NES_SCRIPT },
- { 0x25284, 0x003C, NES_SCRIPT }, { 0x1E9C0, 0x0011, NES_SCRIPT }, { 0x13E40, 0x0018, NES_SCRIPT }, { 0x26621, 0x001F, NES_SCRIPT }, { 0x26640, 0x0054, NES_SCRIPT },
- { 0x26694, 0x0173, NES_SCRIPT }, { 0x26807, 0x004B, NES_SCRIPT }, { 0x26852, 0x0190, NES_SCRIPT }, { 0x269E2, 0x0027, NES_SCRIPT }, { 0x26A09, 0x0041, NES_SCRIPT },
- { 0x26A4A, 0x024E, NES_SCRIPT }, { 0x13E58, 0x001F, NES_SCRIPT }, { 0x24668, 0x002A, NES_SCRIPT }, { 0x1516A, 0x01C9, NES_SCRIPT }, { 0x192D0, 0x0031, NES_SCRIPT },
- { 0x179DB, 0x0088, NES_SCRIPT }, { 0x2162B, 0x00D0, NES_SCRIPT }, { 0x1D3BF, 0x0018, NES_SCRIPT }, { 0x1D3D7, 0x0055, NES_SCRIPT }, { 0x18C36, 0x0005, NES_SCRIPT },
- { 0x15333, 0x0113, NES_SCRIPT }, { 0x15446, 0x000B, NES_SCRIPT }, { 0x24692, 0x014D, NES_SCRIPT }, { 0x247DF, 0x0014, NES_SCRIPT }, { 0x1DF59, 0x0018, NES_SCRIPT },
- { 0x247F3, 0x0027, NES_SCRIPT }, { 0x1A061, 0x0050, NES_SCRIPT }, { 0x00000, 0x0000, NES_SCRIPT }, { 0x2B773, 0x00A5, NES_SCRIPT }, { 0x2A686, 0x00BA, NES_SCRIPT },
- { 0x2A740, 0x0140, NES_SCRIPT }, { 0x1979F, 0x00CA, NES_SCRIPT }, { 0x19869, 0x014D, NES_SCRIPT }, { 0x199B6, 0x0012, NES_SCRIPT }, { 0x2A880, 0x0005, NES_SCRIPT },
- { 0x2A885, 0x0005, NES_SCRIPT }, { 0x2A88A, 0x0005, NES_SCRIPT }, { 0x2A88F, 0x0005, NES_SCRIPT }, { 0x2A894, 0x0005, NES_SCRIPT }, { 0x216FB, 0x0033, NES_SCRIPT },
- { 0x2A899, 0x0005, NES_SCRIPT }, { 0x00000, 0x0000, NES_SCRIPT }, { 0x2A89E, 0x009C, NES_SCRIPT }, { 0x2A93A, 0x009C, NES_SCRIPT }
-};
-static const ScummNESFile::Resource res_scripts_ger[179] = {
- { 0x00000, 0x0000, NES_SCRIPT }, { 0x295B0, 0x045A, NES_SCRIPT }, { 0x29A0A, 0x0218, NES_SCRIPT }, { 0x29C22, 0x00B1, NES_SCRIPT }, { 0x29CD3, 0x0408, NES_SCRIPT },
- { 0x2A0DB, 0x01A1, NES_SCRIPT }, { 0x00000, 0x0000, NES_SCRIPT }, { 0x2A27C, 0x005C, NES_SCRIPT }, { 0x00000, 0x0000, NES_SCRIPT }, { 0x2A2D8, 0x0005, NES_SCRIPT },
- { 0x2C169, 0x000D, NES_SCRIPT }, { 0x2C176, 0x000D, NES_SCRIPT }, { 0x186DB, 0x0040, NES_SCRIPT }, { 0x1871B, 0x0016, NES_SCRIPT }, { 0x1B5C2, 0x0046, NES_SCRIPT },
- { 0x1EFB7, 0x00E3, NES_SCRIPT }, { 0x21D9D, 0x0069, NES_SCRIPT }, { 0x174F1, 0x0027, NES_SCRIPT }, { 0x1FE92, 0x0027, NES_SCRIPT }, { 0x1FEB9, 0x0027, NES_SCRIPT },
- { 0x1BCE5, 0x0022, NES_SCRIPT }, { 0x13EF4, 0x0087, NES_SCRIPT }, { 0x223EC, 0x001F, NES_SCRIPT }, { 0x2240B, 0x008F, NES_SCRIPT }, { 0x192CC, 0x002B, NES_SCRIPT },
- { 0x1CB08, 0x006E, NES_SCRIPT }, { 0x1CB76, 0x004E, NES_SCRIPT }, { 0x1CBC4, 0x004D, NES_SCRIPT }, { 0x1CC11, 0x0059, NES_SCRIPT }, { 0x204AA, 0x0080, NES_SCRIPT },
- { 0x1628E, 0x0035, NES_SCRIPT }, { 0x162C3, 0x001C, NES_SCRIPT }, { 0x162DF, 0x0014, NES_SCRIPT }, { 0x162F3, 0x001C, NES_SCRIPT }, { 0x1630F, 0x0027, NES_SCRIPT },
- { 0x16336, 0x01D1, NES_SCRIPT }, { 0x1D199, 0x00A0, NES_SCRIPT }, { 0x1D239, 0x011C, NES_SCRIPT }, { 0x1D355, 0x001C, NES_SCRIPT }, { 0x1D371, 0x0056, NES_SCRIPT },
- { 0x1D3C7, 0x0072, NES_SCRIPT }, { 0x1E4FA, 0x0028, NES_SCRIPT }, { 0x1E522, 0x019D, NES_SCRIPT }, { 0x1E6BF, 0x023B, NES_SCRIPT }, { 0x2845D, 0x0071, NES_SCRIPT },
- { 0x17C50, 0x0052, NES_SCRIPT }, { 0x15AC9, 0x0039, NES_SCRIPT }, { 0x18731, 0x02E7, NES_SCRIPT }, { 0x18A18, 0x00BC, NES_SCRIPT }, { 0x18AD4, 0x01A2, NES_SCRIPT },
- { 0x00000, 0x0000, NES_SCRIPT }, { 0x19E45, 0x00F8, NES_SCRIPT }, { 0x21E06, 0x00F7, NES_SCRIPT }, { 0x1E8FA, 0x00B5, NES_SCRIPT }, { 0x21EFD, 0x0047, NES_SCRIPT },
- { 0x2C183, 0x004D, NES_SCRIPT }, { 0x15B02, 0x0024, NES_SCRIPT }, { 0x14D64, 0x0014, NES_SCRIPT }, { 0x17518, 0x005E, NES_SCRIPT }, { 0x17576, 0x0125, NES_SCRIPT },
- { 0x1769B, 0x0009, NES_SCRIPT }, { 0x14D78, 0x01C7, NES_SCRIPT }, { 0x2ADCE, 0x0263, NES_SCRIPT }, { 0x232AF, 0x077F, NES_SCRIPT }, { 0x2C1D0, 0x001E, NES_SCRIPT },
- { 0x2C1EE, 0x0024, NES_SCRIPT }, { 0x2C212, 0x002E, NES_SCRIPT }, { 0x2C240, 0x0022, NES_SCRIPT }, { 0x2C262, 0x0013, NES_SCRIPT }, { 0x2C275, 0x001E, NES_SCRIPT },
- { 0x2C293, 0x0016, NES_SCRIPT }, { 0x2C2A9, 0x0027, NES_SCRIPT }, { 0x00000, 0x0000, NES_SCRIPT }, { 0x2C2D0, 0x0012, NES_SCRIPT }, { 0x176A4, 0x00A4, NES_SCRIPT },
- { 0x228F8, 0x0066, NES_SCRIPT }, { 0x14F3F, 0x007F, NES_SCRIPT }, { 0x1F428, 0x013A, NES_SCRIPT }, { 0x1FEE0, 0x001D, NES_SCRIPT }, { 0x1F562, 0x00A0, NES_SCRIPT },
- { 0x1F602, 0x00A4, NES_SCRIPT }, { 0x17748, 0x0076, NES_SCRIPT }, { 0x177BE, 0x0036, NES_SCRIPT }, { 0x1F6A6, 0x00B9, NES_SCRIPT }, { 0x2C2E2, 0x00CB, NES_SCRIPT },
- { 0x2C3AD, 0x00B7, NES_SCRIPT }, { 0x2C464, 0x008A, NES_SCRIPT }, { 0x20A58, 0x01BD, NES_SCRIPT }, { 0x20C15, 0x0181, NES_SCRIPT }, { 0x20D96, 0x0078, NES_SCRIPT },
- { 0x20E0E, 0x003C, NES_SCRIPT }, { 0x20E4A, 0x00E9, NES_SCRIPT }, { 0x20F33, 0x0046, NES_SCRIPT }, { 0x20F79, 0x00F6, NES_SCRIPT }, { 0x2106F, 0x0118, NES_SCRIPT },
- { 0x21187, 0x015B, NES_SCRIPT }, { 0x212E2, 0x01AC, NES_SCRIPT }, { 0x2148E, 0x003F, NES_SCRIPT }, { 0x214CD, 0x00A9, NES_SCRIPT }, { 0x2436F, 0x0126, NES_SCRIPT },
- { 0x1BD07, 0x0075, NES_SCRIPT }, { 0x1CC6A, 0x009B, NES_SCRIPT }, { 0x28F5D, 0x0054, NES_SCRIPT }, { 0x19F3D, 0x00E1, NES_SCRIPT }, { 0x1A01E, 0x0086, NES_SCRIPT },
- { 0x14FBE, 0x0057, NES_SCRIPT }, { 0x27326, 0x033D, NES_SCRIPT }, { 0x1DA51, 0x023B, NES_SCRIPT }, { 0x1DC8C, 0x00FB, NES_SCRIPT }, { 0x1DD87, 0x0056, NES_SCRIPT },
- { 0x1DDDD, 0x01E1, NES_SCRIPT }, { 0x15015, 0x004D, NES_SCRIPT }, { 0x27027, 0x00E8, NES_SCRIPT }, { 0x21F44, 0x0013, NES_SCRIPT }, { 0x2A2DD, 0x00F0, NES_SCRIPT },
- { 0x24495, 0x00F8, NES_SCRIPT }, { 0x21576, 0x00F9, NES_SCRIPT }, { 0x2458D, 0x002B, NES_SCRIPT }, { 0x2BAA4, 0x010F, NES_SCRIPT }, { 0x245B8, 0x00A5, NES_SCRIPT },
- { 0x250D0, 0x019C, NES_SCRIPT }, { 0x1B608, 0x000D, NES_SCRIPT }, { 0x1B615, 0x000D, NES_SCRIPT }, { 0x23A2E, 0x0185, NES_SCRIPT }, { 0x27957, 0x0212, NES_SCRIPT },
- { 0x23BB3, 0x0158, NES_SCRIPT }, { 0x23D0B, 0x01C4, NES_SCRIPT }, { 0x23ECF, 0x0016, NES_SCRIPT }, { 0x2BBB3, 0x005A, NES_SCRIPT }, { 0x23EE5, 0x0020, NES_SCRIPT },
- { 0x27D6A, 0x00A7, NES_SCRIPT }, { 0x2A3CD, 0x038C, NES_SCRIPT }, { 0x15062, 0x00F6, NES_SCRIPT }, { 0x2B5B2, 0x007B, NES_SCRIPT }, { 0x00000, 0x0000, NES_SCRIPT },
- { 0x2526C, 0x003C, NES_SCRIPT }, { 0x1E9AF, 0x0011, NES_SCRIPT }, { 0x15B26, 0x0018, NES_SCRIPT }, { 0x265F5, 0x001F, NES_SCRIPT }, { 0x26614, 0x0054, NES_SCRIPT },
- { 0x26668, 0x018E, NES_SCRIPT }, { 0x267F6, 0x004B, NES_SCRIPT }, { 0x26841, 0x0196, NES_SCRIPT }, { 0x269D7, 0x0027, NES_SCRIPT }, { 0x269FE, 0x0041, NES_SCRIPT },
- { 0x26A3F, 0x01A3, NES_SCRIPT }, { 0x15B3E, 0x001F, NES_SCRIPT }, { 0x2465D, 0x002A, NES_SCRIPT }, { 0x15158, 0x0198, NES_SCRIPT }, { 0x192F7, 0x0031, NES_SCRIPT },
- { 0x177F4, 0x008C, NES_SCRIPT }, { 0x2166F, 0x00DA, NES_SCRIPT }, { 0x1D439, 0x0018, NES_SCRIPT }, { 0x1D451, 0x0054, NES_SCRIPT }, { 0x18C76, 0x0005, NES_SCRIPT },
- { 0x152F0, 0x0126, NES_SCRIPT }, { 0x15416, 0x000B, NES_SCRIPT }, { 0x24687, 0x0137, NES_SCRIPT }, { 0x247BE, 0x0014, NES_SCRIPT }, { 0x1DFBE, 0x0018, NES_SCRIPT },
- { 0x247D2, 0x0027, NES_SCRIPT }, { 0x1A0A4, 0x004D, NES_SCRIPT }, { 0x00000, 0x0000, NES_SCRIPT }, { 0x2B62D, 0x00A5, NES_SCRIPT }, { 0x2A759, 0x00BA, NES_SCRIPT },
- { 0x2A813, 0x0140, NES_SCRIPT }, { 0x197CF, 0x00D0, NES_SCRIPT }, { 0x1989F, 0x014D, NES_SCRIPT }, { 0x199EC, 0x0012, NES_SCRIPT }, { 0x2A953, 0x0005, NES_SCRIPT },
- { 0x2A958, 0x0005, NES_SCRIPT }, { 0x2A95D, 0x0005, NES_SCRIPT }, { 0x2A962, 0x0005, NES_SCRIPT }, { 0x2A967, 0x0005, NES_SCRIPT }, { 0x21749, 0x0033, NES_SCRIPT },
- { 0x2A96C, 0x0005, NES_SCRIPT }, { 0x00000, 0x0000, NES_SCRIPT }, { 0x2A971, 0x009C, NES_SCRIPT }, { 0x2AA0D, 0x009C, NES_SCRIPT }
-};
-#endif
-static const ScummNESFile::Resource *res_scripts[ScummNESFile::kROMsetNum] = {
- res_scripts_usa,
- res_scripts_eur,
- res_scripts_swe,
- res_scripts_fra,
- res_scripts_ger,
-};
-
-#ifdef PALMOS_68K
-static const ScummNESFile::Resource *res_sounds_usa;
-static const ScummNESFile::Resource *res_sounds_eur;
-static const ScummNESFile::Resource *res_sounds_swe;
-static const ScummNESFile::Resource *res_sounds_fra;
-static const ScummNESFile::Resource *res_sounds_ger;
-#else
-static const ScummNESFile::Resource res_sounds_usa[82] = {
- { 0x0FFE8, 0x000A, NES_SOUND }, { 0x30ECA, 0x0832, NES_SOUND }, { 0x30ECA, 0x0832, NES_SOUND }, { 0x30ECA, 0x0832, NES_SOUND }, { 0x30ECA, 0x0832, NES_SOUND },
- { 0x30ECA, 0x0832, NES_SOUND }, { 0x17FCA, 0x0011, NES_SOUND }, { 0x27E0B, 0x0073, NES_SOUND }, { 0x17FDB, 0x0011, NES_SOUND }, { 0x17FEC, 0x0011, NES_SOUND },
- { 0x27E7E, 0x0056, NES_SOUND }, { 0x27ED4, 0x001F, NES_SOUND }, { 0x23FEE, 0x0011, NES_SOUND }, { 0x0FFF2, 0x000A, NES_SOUND }, { 0x27EF3, 0x000A, NES_SOUND },
- { 0x27EFD, 0x0019, NES_SOUND }, { 0x27F16, 0x004B, NES_SOUND }, { 0x27F61, 0x000A, NES_SOUND }, { 0x27F6B, 0x000F, NES_SOUND }, { 0x27F7A, 0x001D, NES_SOUND },
- { 0x27F97, 0x0045, NES_SOUND }, { 0x27FDC, 0x000F, NES_SOUND }, { 0x2FD42, 0x001B, NES_SOUND }, { 0x2FD5D, 0x0033, NES_SOUND }, { 0x27FEB, 0x0011, NES_SOUND },
- { 0x2BFEF, 0x000F, NES_SOUND }, { 0x2FD90, 0x0075, NES_SOUND }, { 0x2FE05, 0x0014, NES_SOUND }, { 0x0FFE8, 0x000A, NES_SOUND }, { 0x2FE19, 0x00FF, NES_SOUND },
- { 0x2FF18, 0x000F, NES_SOUND }, { 0x2FF27, 0x000F, NES_SOUND }, { 0x2FF36, 0x0092, NES_SOUND }, { 0x2FF36, 0x0092, NES_SOUND }, { 0x2FFC8, 0x002D, NES_SOUND },
- { 0x316FC, 0x00F8, NES_SOUND }, { 0x317F4, 0x0016, NES_SOUND }, { 0x3180A, 0x0011, NES_SOUND }, { 0x3181B, 0x004B, NES_SOUND }, { 0x31866, 0x0011, NES_SOUND },
- { 0x31877, 0x003B, NES_SOUND }, { 0x318B2, 0x008A, NES_SOUND }, { 0x3193C, 0x0011, NES_SOUND }, { 0x3194D, 0x000F, NES_SOUND }, { 0x3195C, 0x00A2, NES_SOUND },
- { 0x319FE, 0x00D3, NES_SOUND }, { 0x31AD1, 0x0097, NES_SOUND }, { 0x2BFEF, 0x000F, NES_SOUND }, { 0x3195C, 0x00A2, NES_SOUND }, { 0x31B68, 0x05D1, NES_SOUND },
- { 0x31B68, 0x05D1, NES_SOUND }, { 0x32139, 0x0011, NES_SOUND }, { 0x0FFE8, 0x000A, NES_SOUND }, { 0x2FD90, 0x0075, NES_SOUND }, { 0x27ED4, 0x001F, NES_SOUND },
- { 0x3214A, 0x098E, NES_SOUND }, { 0x3181B, 0x004B, NES_SOUND }, { 0x32AD8, 0x0011, NES_SOUND }, { 0x30ECA, 0x0832, NES_SOUND }, { 0x32AE9, 0x000F, NES_SOUND },
- { 0x32AF8, 0x002F, NES_SOUND }, { 0x32B27, 0x001D, NES_SOUND }, { 0x32B44, 0x0018, NES_SOUND }, { 0x32B5C, 0x0016, NES_SOUND }, { 0x32B72, 0x001B, NES_SOUND },
- { 0x32B8D, 0x0088, NES_SOUND }, { 0x32C15, 0x0065, NES_SOUND }, { 0x32C7A, 0x0065, NES_SOUND }, { 0x32CDF, 0x0073, NES_SOUND }, { 0x32D52, 0x00F9, NES_SOUND },
- { 0x32E4B, 0x049E, NES_SOUND }, { 0x34001, 0x0EA8, NES_SOUND }, { 0x332E9, 0x0B18, NES_SOUND }, { 0x34EA9, 0x0B9C, NES_SOUND }, { 0x35A45, 0x0C6B, NES_SOUND },
- { 0x366B0, 0x0E56, NES_SOUND }, { 0x38001, 0x0C70, NES_SOUND }, { 0x38C71, 0x0DEC, NES_SOUND }, { 0x39A5D, 0x0B77, NES_SOUND }, { 0x37506, 0x042F, NES_SOUND },
- { 0x3A5D4, 0x0AC5, NES_SOUND }, { 0x3B099, 0x0BE4, NES_SOUND }
-};
-static const ScummNESFile::Resource res_sounds_eur[82] = {
- { 0x0BF54, 0x000A, NES_SOUND }, { 0x30ECA, 0x0832, NES_SOUND }, { 0x30ECA, 0x0832, NES_SOUND }, { 0x30ECA, 0x0832, NES_SOUND }, { 0x30ECA, 0x0832, NES_SOUND },
- { 0x30ECA, 0x0832, NES_SOUND }, { 0x0BF5E, 0x0011, NES_SOUND }, { 0x27ECB, 0x0073, NES_SOUND }, { 0x0BF6F, 0x0011, NES_SOUND }, { 0x0FF5D, 0x0011, NES_SOUND },
- { 0x316FC, 0x0056, NES_SOUND }, { 0x13F4E, 0x001F, NES_SOUND }, { 0x0FF6E, 0x0011, NES_SOUND }, { 0x13F6D, 0x000A, NES_SOUND }, { 0x1BF47, 0x000A, NES_SOUND },
- { 0x1BF51, 0x0019, NES_SOUND }, { 0x31752, 0x004B, NES_SOUND }, { 0x1BF6A, 0x000A, NES_SOUND }, { 0x27F3E, 0x000F, NES_SOUND }, { 0x27F4D, 0x001D, NES_SOUND },
- { 0x3179D, 0x0045, NES_SOUND }, { 0x27F6A, 0x000F, NES_SOUND }, { 0x2BF40, 0x001B, NES_SOUND }, { 0x317E2, 0x0033, NES_SOUND }, { 0x2BF5B, 0x0011, NES_SOUND },
- { 0x2BF6C, 0x000F, NES_SOUND }, { 0x31815, 0x0075, NES_SOUND }, { 0x2FF6C, 0x0014, NES_SOUND }, { 0x0BF54, 0x000A, NES_SOUND }, { 0x3188A, 0x00FF, NES_SOUND },
- { 0x31989, 0x000F, NES_SOUND }, { 0x31998, 0x000F, NES_SOUND }, { 0x319A7, 0x0092, NES_SOUND }, { 0x319A7, 0x0092, NES_SOUND }, { 0x31A39, 0x002D, NES_SOUND },
- { 0x31A66, 0x00F8, NES_SOUND }, { 0x31B5E, 0x0016, NES_SOUND }, { 0x31B74, 0x0011, NES_SOUND }, { 0x31B85, 0x004B, NES_SOUND }, { 0x31BD0, 0x0011, NES_SOUND },
- { 0x31BE1, 0x003B, NES_SOUND }, { 0x31C1C, 0x008A, NES_SOUND }, { 0x31CA6, 0x0011, NES_SOUND }, { 0x31CB7, 0x000F, NES_SOUND }, { 0x31CC6, 0x00A2, NES_SOUND },
- { 0x31D68, 0x00D3, NES_SOUND }, { 0x31E3B, 0x0097, NES_SOUND }, { 0x2BF6C, 0x000F, NES_SOUND }, { 0x31CC6, 0x00A2, NES_SOUND }, { 0x31ED2, 0x05D1, NES_SOUND },
- { 0x31ED2, 0x05D1, NES_SOUND }, { 0x324A3, 0x0011, NES_SOUND }, { 0x0BF54, 0x000A, NES_SOUND }, { 0x31815, 0x0075, NES_SOUND }, { 0x13F4E, 0x001F, NES_SOUND },
- { 0x324B4, 0x098E, NES_SOUND }, { 0x31B85, 0x004B, NES_SOUND }, { 0x32E42, 0x0011, NES_SOUND }, { 0x30ECA, 0x0832, NES_SOUND }, { 0x32E53, 0x000F, NES_SOUND },
- { 0x32E62, 0x002F, NES_SOUND }, { 0x32E91, 0x001D, NES_SOUND }, { 0x32EAE, 0x0018, NES_SOUND }, { 0x32EC6, 0x0016, NES_SOUND }, { 0x32EDC, 0x001B, NES_SOUND },
- { 0x32EF7, 0x0088, NES_SOUND }, { 0x32F7F, 0x0065, NES_SOUND }, { 0x32FE4, 0x0065, NES_SOUND }, { 0x33049, 0x0073, NES_SOUND }, { 0x330BC, 0x00F9, NES_SOUND },
- { 0x331B5, 0x049E, NES_SOUND }, { 0x34001, 0x0EA8, NES_SOUND }, { 0x34EA9, 0x0B18, NES_SOUND }, { 0x359C1, 0x0B9C, NES_SOUND }, { 0x3655D, 0x0C6B, NES_SOUND },
- { 0x38001, 0x0E56, NES_SOUND }, { 0x371C8, 0x0C70, NES_SOUND }, { 0x38E57, 0x0DEC, NES_SOUND }, { 0x39C43, 0x0B77, NES_SOUND }, { 0x33653, 0x042F, NES_SOUND },
- { 0x3A7BA, 0x0AC5, NES_SOUND }, { 0x3B27F, 0x0BE4, NES_SOUND }
-};
-static const ScummNESFile::Resource res_sounds_swe[82] = {
- { 0x0BF58, 0x000A, NES_SOUND }, { 0x30352, 0x0832, NES_SOUND }, { 0x30352, 0x0832, NES_SOUND }, { 0x30352, 0x0832, NES_SOUND }, { 0x30352, 0x0832, NES_SOUND },
- { 0x30352, 0x0832, NES_SOUND }, { 0x0BF62, 0x0011, NES_SOUND }, { 0x27E5F, 0x0073, NES_SOUND }, { 0x17F5A, 0x0011, NES_SOUND }, { 0x17F6B, 0x0011, NES_SOUND },
- { 0x27ED2, 0x0056, NES_SOUND }, { 0x1BF55, 0x001F, NES_SOUND }, { 0x23F66, 0x0011, NES_SOUND }, { 0x0BF73, 0x000A, NES_SOUND }, { 0x1BF74, 0x000A, NES_SOUND },
- { 0x27F28, 0x0019, NES_SOUND }, { 0x2BF0A, 0x004B, NES_SOUND }, { 0x1FF71, 0x000A, NES_SOUND }, { 0x27F41, 0x000F, NES_SOUND }, { 0x27F50, 0x001D, NES_SOUND },
- { 0x2FEAA, 0x0045, NES_SOUND }, { 0x27F6D, 0x000F, NES_SOUND }, { 0x2BF55, 0x001B, NES_SOUND }, { 0x2FEEF, 0x0033, NES_SOUND }, { 0x2FF22, 0x0011, NES_SOUND },
- { 0x2BF70, 0x000F, NES_SOUND }, { 0x30B84, 0x0075, NES_SOUND }, { 0x2FF33, 0x0014, NES_SOUND }, { 0x0BF58, 0x000A, NES_SOUND }, { 0x30BF9, 0x00FF, NES_SOUND },
- { 0x2FF47, 0x000F, NES_SOUND }, { 0x2FF56, 0x000F, NES_SOUND }, { 0x30CF8, 0x0092, NES_SOUND }, { 0x30CF8, 0x0092, NES_SOUND }, { 0x30D8A, 0x002D, NES_SOUND },
- { 0x30DB7, 0x00F8, NES_SOUND }, { 0x2FF65, 0x0016, NES_SOUND }, { 0x30EAF, 0x0011, NES_SOUND }, { 0x30EC0, 0x004B, NES_SOUND }, { 0x30F0B, 0x0011, NES_SOUND },
- { 0x30F1C, 0x003B, NES_SOUND }, { 0x30F57, 0x008A, NES_SOUND }, { 0x30FE1, 0x0011, NES_SOUND }, { 0x30FF2, 0x000F, NES_SOUND }, { 0x31001, 0x00A2, NES_SOUND },
- { 0x310A3, 0x00D3, NES_SOUND }, { 0x31176, 0x0097, NES_SOUND }, { 0x2BF70, 0x000F, NES_SOUND }, { 0x31001, 0x00A2, NES_SOUND }, { 0x3120D, 0x05D1, NES_SOUND },
- { 0x3120D, 0x05D1, NES_SOUND }, { 0x317DE, 0x0011, NES_SOUND }, { 0x0BF58, 0x000A, NES_SOUND }, { 0x30B84, 0x0075, NES_SOUND }, { 0x1BF55, 0x001F, NES_SOUND },
- { 0x317EF, 0x098E, NES_SOUND }, { 0x30EC0, 0x004B, NES_SOUND }, { 0x3217D, 0x0011, NES_SOUND }, { 0x30352, 0x0832, NES_SOUND }, { 0x3218E, 0x000F, NES_SOUND },
- { 0x3219D, 0x002F, NES_SOUND }, { 0x321CC, 0x001D, NES_SOUND }, { 0x321E9, 0x0018, NES_SOUND }, { 0x32201, 0x0016, NES_SOUND }, { 0x32217, 0x001B, NES_SOUND },
- { 0x32232, 0x0088, NES_SOUND }, { 0x322BA, 0x0065, NES_SOUND }, { 0x3231F, 0x0065, NES_SOUND }, { 0x32384, 0x0073, NES_SOUND }, { 0x323F7, 0x00F9, NES_SOUND },
- { 0x324F0, 0x049E, NES_SOUND }, { 0x3298E, 0x0EA8, NES_SOUND }, { 0x34001, 0x0B18, NES_SOUND }, { 0x34B19, 0x0B9C, NES_SOUND }, { 0x356B5, 0x0C6B, NES_SOUND },
- { 0x36320, 0x0E56, NES_SOUND }, { 0x37176, 0x0C70, NES_SOUND }, { 0x38001, 0x0DEC, NES_SOUND }, { 0x38DED, 0x0B77, NES_SOUND }, { 0x33836, 0x042F, NES_SOUND },
- { 0x39964, 0x0AC5, NES_SOUND }, { 0x3A429, 0x0BE4, NES_SOUND }
-};
-static const ScummNESFile::Resource res_sounds_fra[82] = {
- { 0x07F74, 0x000A, NES_SOUND }, { 0x30ECA, 0x0832, NES_SOUND }, { 0x30ECA, 0x0832, NES_SOUND }, { 0x30ECA, 0x0832, NES_SOUND }, { 0x30ECA, 0x0832, NES_SOUND },
- { 0x30ECA, 0x0832, NES_SOUND }, { 0x0BF6C, 0x0011, NES_SOUND }, { 0x1BEFA, 0x0073, NES_SOUND }, { 0x17F10, 0x0011, NES_SOUND }, { 0x17F21, 0x0011, NES_SOUND },
- { 0x1FED5, 0x0056, NES_SOUND }, { 0x17F32, 0x001F, NES_SOUND }, { 0x17F51, 0x0011, NES_SOUND }, { 0x0FF76, 0x000A, NES_SOUND }, { 0x17F62, 0x000A, NES_SOUND },
- { 0x1FF2B, 0x0019, NES_SOUND }, { 0x23E78, 0x004B, NES_SOUND }, { 0x17F6C, 0x000A, NES_SOUND }, { 0x1BF6D, 0x000F, NES_SOUND }, { 0x1FF44, 0x001D, NES_SOUND },
- { 0x23EC3, 0x0045, NES_SOUND }, { 0x1FF61, 0x000F, NES_SOUND }, { 0x23F08, 0x001B, NES_SOUND }, { 0x23F23, 0x0033, NES_SOUND }, { 0x23F56, 0x0011, NES_SOUND },
- { 0x1FF70, 0x000F, NES_SOUND }, { 0x27EF4, 0x0075, NES_SOUND }, { 0x23F67, 0x0014, NES_SOUND }, { 0x07F74, 0x000A, NES_SOUND }, { 0x2FB83, 0x00FF, NES_SOUND },
- { 0x27F69, 0x000F, NES_SOUND }, { 0x2BF70, 0x000F, NES_SOUND }, { 0x2FC82, 0x0092, NES_SOUND }, { 0x2FC82, 0x0092, NES_SOUND }, { 0x2FD14, 0x002D, NES_SOUND },
- { 0x2FD41, 0x00F8, NES_SOUND }, { 0x2FE39, 0x0016, NES_SOUND }, { 0x2FE4F, 0x0011, NES_SOUND }, { 0x2FE60, 0x004B, NES_SOUND }, { 0x2FEAB, 0x0011, NES_SOUND },
- { 0x2FEBC, 0x003B, NES_SOUND }, { 0x316FC, 0x008A, NES_SOUND }, { 0x2FEF7, 0x0011, NES_SOUND }, { 0x2FF08, 0x000F, NES_SOUND }, { 0x31786, 0x00A2, NES_SOUND },
- { 0x31828, 0x00D3, NES_SOUND }, { 0x318FB, 0x0097, NES_SOUND }, { 0x1FF70, 0x000F, NES_SOUND }, { 0x31786, 0x00A2, NES_SOUND }, { 0x31992, 0x05D1, NES_SOUND },
- { 0x31992, 0x05D1, NES_SOUND }, { 0x2FF17, 0x0011, NES_SOUND }, { 0x07F74, 0x000A, NES_SOUND }, { 0x27EF4, 0x0075, NES_SOUND }, { 0x17F32, 0x001F, NES_SOUND },
- { 0x31F63, 0x098E, NES_SOUND }, { 0x2FE60, 0x004B, NES_SOUND }, { 0x2FF28, 0x0011, NES_SOUND }, { 0x30ECA, 0x0832, NES_SOUND }, { 0x2FF39, 0x000F, NES_SOUND },
- { 0x2FF48, 0x002F, NES_SOUND }, { 0x328F1, 0x001D, NES_SOUND }, { 0x3290E, 0x0018, NES_SOUND }, { 0x32926, 0x0016, NES_SOUND }, { 0x3293C, 0x001B, NES_SOUND },
- { 0x32957, 0x0088, NES_SOUND }, { 0x329DF, 0x0065, NES_SOUND }, { 0x32A44, 0x0065, NES_SOUND }, { 0x32AA9, 0x0073, NES_SOUND }, { 0x32B1C, 0x00F9, NES_SOUND },
- { 0x32C15, 0x049E, NES_SOUND }, { 0x330B3, 0x0EA8, NES_SOUND }, { 0x34001, 0x0B18, NES_SOUND }, { 0x34B19, 0x0B9C, NES_SOUND }, { 0x356B5, 0x0C6B, NES_SOUND },
- { 0x36320, 0x0E56, NES_SOUND }, { 0x37176, 0x0C70, NES_SOUND }, { 0x38001, 0x0DEC, NES_SOUND }, { 0x38DED, 0x0B77, NES_SOUND }, { 0x39964, 0x042F, NES_SOUND },
- { 0x39D93, 0x0AC5, NES_SOUND }, { 0x3A858, 0x0BE4, NES_SOUND }
-};
-static const ScummNESFile::Resource res_sounds_ger[82] = {
- { 0x0BF6D, 0x000A, NES_SOUND }, { 0x30ECA, 0x0832, NES_SOUND }, { 0x30ECA, 0x0832, NES_SOUND }, { 0x30ECA, 0x0832, NES_SOUND }, { 0x30ECA, 0x0832, NES_SOUND },
- { 0x30ECA, 0x0832, NES_SOUND }, { 0x23F05, 0x0011, NES_SOUND }, { 0x2FA49, 0x0073, NES_SOUND }, { 0x23F16, 0x0011, NES_SOUND }, { 0x23F27, 0x0011, NES_SOUND },
- { 0x2FABC, 0x0056, NES_SOUND }, { 0x23F38, 0x001F, NES_SOUND }, { 0x23F57, 0x0011, NES_SOUND }, { 0x0FF76, 0x000A, NES_SOUND }, { 0x17F71, 0x000A, NES_SOUND },
- { 0x2BF2F, 0x0019, NES_SOUND }, { 0x2FB12, 0x004B, NES_SOUND }, { 0x23F68, 0x000A, NES_SOUND }, { 0x2BF48, 0x000F, NES_SOUND }, { 0x2BF57, 0x001D, NES_SOUND },
- { 0x2FB5D, 0x0045, NES_SOUND }, { 0x2FBA2, 0x000F, NES_SOUND }, { 0x2FBB1, 0x001B, NES_SOUND }, { 0x2FBCC, 0x0033, NES_SOUND }, { 0x2FBFF, 0x0011, NES_SOUND },
- { 0x2FC10, 0x000F, NES_SOUND }, { 0x2FC1F, 0x0075, NES_SOUND }, { 0x2FC94, 0x0014, NES_SOUND }, { 0x0BF6D, 0x000A, NES_SOUND }, { 0x2FCA8, 0x00FF, NES_SOUND },
- { 0x2FDA7, 0x000F, NES_SOUND }, { 0x2FDB6, 0x000F, NES_SOUND }, { 0x2FDC5, 0x0092, NES_SOUND }, { 0x2FDC5, 0x0092, NES_SOUND }, { 0x2FE57, 0x002D, NES_SOUND },
- { 0x2FE84, 0x00F8, NES_SOUND }, { 0x316FC, 0x0016, NES_SOUND }, { 0x31712, 0x0011, NES_SOUND }, { 0x31723, 0x004B, NES_SOUND }, { 0x3176E, 0x0011, NES_SOUND },
- { 0x3177F, 0x003B, NES_SOUND }, { 0x317BA, 0x008A, NES_SOUND }, { 0x31844, 0x0011, NES_SOUND }, { 0x31855, 0x000F, NES_SOUND }, { 0x31864, 0x00A2, NES_SOUND },
- { 0x31906, 0x00D3, NES_SOUND }, { 0x319D9, 0x0097, NES_SOUND }, { 0x2FC10, 0x000F, NES_SOUND }, { 0x31864, 0x00A2, NES_SOUND }, { 0x31A70, 0x05D1, NES_SOUND },
- { 0x31A70, 0x05D1, NES_SOUND }, { 0x32041, 0x0011, NES_SOUND }, { 0x0BF6D, 0x000A, NES_SOUND }, { 0x2FC1F, 0x0075, NES_SOUND }, { 0x23F38, 0x001F, NES_SOUND },
- { 0x32052, 0x098E, NES_SOUND }, { 0x31723, 0x004B, NES_SOUND }, { 0x329E0, 0x0011, NES_SOUND }, { 0x30ECA, 0x0832, NES_SOUND }, { 0x329F1, 0x000F, NES_SOUND },
- { 0x32A00, 0x002F, NES_SOUND }, { 0x32A2F, 0x001D, NES_SOUND }, { 0x32A4C, 0x0018, NES_SOUND }, { 0x32A64, 0x0016, NES_SOUND }, { 0x32A7A, 0x001B, NES_SOUND },
- { 0x32A95, 0x0088, NES_SOUND }, { 0x32B1D, 0x0065, NES_SOUND }, { 0x32B82, 0x0065, NES_SOUND }, { 0x32BE7, 0x0073, NES_SOUND }, { 0x32C5A, 0x00F9, NES_SOUND },
- { 0x32D53, 0x049E, NES_SOUND }, { 0x34001, 0x0EA8, NES_SOUND }, { 0x331F1, 0x0B18, NES_SOUND }, { 0x34EA9, 0x0B9C, NES_SOUND }, { 0x35A45, 0x0C6B, NES_SOUND },
- { 0x366B0, 0x0E56, NES_SOUND }, { 0x38001, 0x0C70, NES_SOUND }, { 0x38C71, 0x0DEC, NES_SOUND }, { 0x39A5D, 0x0B77, NES_SOUND }, { 0x37506, 0x042F, NES_SOUND },
- { 0x3A5D4, 0x0AC5, NES_SOUND }, { 0x3B099, 0x0BE4, NES_SOUND }
-};
-#endif
-static const ScummNESFile::Resource *res_sounds[ScummNESFile::kROMsetNum] = {
- res_sounds_usa,
- res_sounds_eur,
- res_sounds_swe,
- res_sounds_fra,
- res_sounds_ger,
-};
-
-#ifdef PALMOS_68K
-static const ScummNESFile::Resource *res_costumes_usa;
-static const ScummNESFile::Resource *res_costumes_eur;
-static const ScummNESFile::Resource *res_costumes_swe;
-static const ScummNESFile::Resource *res_costumes_fra;
-static const ScummNESFile::Resource *res_costumes_ger;
-#else
-static const ScummNESFile::Resource res_costumes_usa[25] = {
- { 0x17F05, 0x0055, NES_COSTUME }, { 0x17F05, 0x0055, NES_COSTUME }, { 0x17F05, 0x0055, NES_COSTUME }, { 0x17F05, 0x0055, NES_COSTUME }, { 0x17F05, 0x0055, NES_COSTUME },
- { 0x17F05, 0x0055, NES_COSTUME }, { 0x17F05, 0x0055, NES_COSTUME }, { 0x17F05, 0x0055, NES_COSTUME }, { 0x13FAB, 0x004B, NES_COSTUME }, { 0x17F05, 0x0055, NES_COSTUME },
- { 0x17F05, 0x0055, NES_COSTUME }, { 0x17F05, 0x0055, NES_COSTUME }, { 0x17F5A, 0x0036, NES_COSTUME }, { 0x17F90, 0x003A, NES_COSTUME }, { 0x17F90, 0x003A, NES_COSTUME },
- { 0x17F05, 0x0055, NES_COSTUME }, { 0x1BF87, 0x003B, NES_COSTUME }, { 0x17F05, 0x0055, NES_COSTUME }, { 0x23FA9, 0x0045, NES_COSTUME }, { 0x1FFBD, 0x0040, NES_COSTUME },
- { 0x1BFC2, 0x003C, NES_COSTUME }, { 0x17F90, 0x003A, NES_COSTUME }, { 0x17F90, 0x003A, NES_COSTUME }, { 0x17F05, 0x0055, NES_COSTUME }, { 0x13FAB, 0x004B, NES_COSTUME }
-};
-static const ScummNESFile::Resource res_costumes_eur[25] = {
- { 0x0BEFF, 0x0055, NES_COSTUME }, { 0x0BEFF, 0x0055, NES_COSTUME }, { 0x0BEFF, 0x0055, NES_COSTUME }, { 0x0BEFF, 0x0055, NES_COSTUME }, { 0x0BEFF, 0x0055, NES_COSTUME },
- { 0x0BEFF, 0x0055, NES_COSTUME }, { 0x0BEFF, 0x0055, NES_COSTUME }, { 0x0BEFF, 0x0055, NES_COSTUME }, { 0x0FEA2, 0x004B, NES_COSTUME }, { 0x0BEFF, 0x0055, NES_COSTUME },
- { 0x0BEFF, 0x0055, NES_COSTUME }, { 0x0BEFF, 0x0055, NES_COSTUME }, { 0x0FEED, 0x0036, NES_COSTUME }, { 0x0FF23, 0x003A, NES_COSTUME }, { 0x0FF23, 0x003A, NES_COSTUME },
- { 0x0BEFF, 0x0055, NES_COSTUME }, { 0x13F13, 0x003B, NES_COSTUME }, { 0x0BEFF, 0x0055, NES_COSTUME }, { 0x23F2F, 0x0045, NES_COSTUME }, { 0x1FF3E, 0x0040, NES_COSTUME },
- { 0x27E8F, 0x003C, NES_COSTUME }, { 0x0FF23, 0x003A, NES_COSTUME }, { 0x0FF23, 0x003A, NES_COSTUME }, { 0x0BEFF, 0x0055, NES_COSTUME }, { 0x0FEA2, 0x004B, NES_COSTUME }
-};
-static const ScummNESFile::Resource res_costumes_swe[25] = {
- { 0x0FEF5, 0x0055, NES_COSTUME }, { 0x0FEF5, 0x0055, NES_COSTUME }, { 0x0FEF5, 0x0055, NES_COSTUME }, { 0x0FEF5, 0x0055, NES_COSTUME }, { 0x0FEF5, 0x0055, NES_COSTUME },
- { 0x0FEF5, 0x0055, NES_COSTUME }, { 0x0FEF5, 0x0055, NES_COSTUME }, { 0x0FEF5, 0x0055, NES_COSTUME }, { 0x17E9A, 0x004B, NES_COSTUME }, { 0x0FEF5, 0x0055, NES_COSTUME },
- { 0x0FEF5, 0x0055, NES_COSTUME }, { 0x0FEF5, 0x0055, NES_COSTUME }, { 0x0FF4A, 0x0036, NES_COSTUME }, { 0x17EE5, 0x003A, NES_COSTUME }, { 0x17EE5, 0x003A, NES_COSTUME },
- { 0x0FEF5, 0x0055, NES_COSTUME }, { 0x17F1F, 0x003B, NES_COSTUME }, { 0x0FEF5, 0x0055, NES_COSTUME }, { 0x1BE94, 0x0045, NES_COSTUME }, { 0x1BED9, 0x0040, NES_COSTUME },
- { 0x1BF19, 0x003C, NES_COSTUME }, { 0x17EE5, 0x003A, NES_COSTUME }, { 0x17EE5, 0x003A, NES_COSTUME }, { 0x0FEF5, 0x0055, NES_COSTUME }, { 0x17E9A, 0x004B, NES_COSTUME }
-};
-static const ScummNESFile::Resource res_costumes_fra[25] = {
- { 0x0BF17, 0x0055, NES_COSTUME }, { 0x0BF17, 0x0055, NES_COSTUME }, { 0x0BF17, 0x0055, NES_COSTUME }, { 0x0BF17, 0x0055, NES_COSTUME }, { 0x0BF17, 0x0055, NES_COSTUME },
- { 0x0BF17, 0x0055, NES_COSTUME }, { 0x0BF17, 0x0055, NES_COSTUME }, { 0x0BF17, 0x0055, NES_COSTUME }, { 0x13E77, 0x004B, NES_COSTUME }, { 0x0BF17, 0x0055, NES_COSTUME },
- { 0x0BF17, 0x0055, NES_COSTUME }, { 0x0BF17, 0x0055, NES_COSTUME }, { 0x07F3E, 0x0036, NES_COSTUME }, { 0x13EC2, 0x003A, NES_COSTUME }, { 0x13EC2, 0x003A, NES_COSTUME },
- { 0x0BF17, 0x0055, NES_COSTUME }, { 0x13EFC, 0x003B, NES_COSTUME }, { 0x0BF17, 0x0055, NES_COSTUME }, { 0x13F37, 0x0045, NES_COSTUME }, { 0x17E94, 0x0040, NES_COSTUME },
- { 0x17ED4, 0x003C, NES_COSTUME }, { 0x13EC2, 0x003A, NES_COSTUME }, { 0x13EC2, 0x003A, NES_COSTUME }, { 0x0BF17, 0x0055, NES_COSTUME }, { 0x13E77, 0x004B, NES_COSTUME }
-};
-static const ScummNESFile::Resource res_costumes_ger[25] = {
- { 0x0FEEB, 0x0055, NES_COSTUME }, { 0x0FEEB, 0x0055, NES_COSTUME }, { 0x0FEEB, 0x0055, NES_COSTUME }, { 0x0FEEB, 0x0055, NES_COSTUME }, { 0x0FEEB, 0x0055, NES_COSTUME },
- { 0x0FEEB, 0x0055, NES_COSTUME }, { 0x0FEEB, 0x0055, NES_COSTUME }, { 0x0FEEB, 0x0055, NES_COSTUME }, { 0x17E6C, 0x004B, NES_COSTUME }, { 0x0FEEB, 0x0055, NES_COSTUME },
- { 0x0FEEB, 0x0055, NES_COSTUME }, { 0x0FEEB, 0x0055, NES_COSTUME }, { 0x0FF40, 0x0036, NES_COSTUME }, { 0x17EB7, 0x003A, NES_COSTUME }, { 0x17EB7, 0x003A, NES_COSTUME },
- { 0x0FEEB, 0x0055, NES_COSTUME }, { 0x17EF1, 0x003B, NES_COSTUME }, { 0x0FEEB, 0x0055, NES_COSTUME }, { 0x17F2C, 0x0045, NES_COSTUME }, { 0x1FEFD, 0x0040, NES_COSTUME },
- { 0x1FF3D, 0x003C, NES_COSTUME }, { 0x17EB7, 0x003A, NES_COSTUME }, { 0x17EB7, 0x003A, NES_COSTUME }, { 0x0FEEB, 0x0055, NES_COSTUME }, { 0x17E6C, 0x004B, NES_COSTUME }
-};
-#endif
-static const ScummNESFile::Resource *res_costumes[ScummNESFile::kROMsetNum] = {
- res_costumes_usa,
- res_costumes_eur,
- res_costumes_swe,
- res_costumes_fra,
- res_costumes_ger,
-};
-
-#ifdef PALMOS_68K
-static const ScummNESFile::Resource *res_globdata_usa;
-static const ScummNESFile::Resource *res_globdata_eur;
-static const ScummNESFile::Resource *res_globdata_swe;
-static const ScummNESFile::Resource *res_globdata_fra;
-static const ScummNESFile::Resource *res_globdata_ger;
-#else
-static const ScummNESFile::Resource res_globdata_usa[1] = { { 0x2CA11, 0x0307, NES_GLOBDATA } };
-static const ScummNESFile::Resource res_globdata_eur[1] = { { 0x2CA11, 0x0307, NES_GLOBDATA } };
-static const ScummNESFile::Resource res_globdata_swe[1] = { { 0x2C001, 0x0307, NES_GLOBDATA } };
-static const ScummNESFile::Resource res_globdata_fra[1] = { { 0x2C628, 0x0307, NES_GLOBDATA } };
-static const ScummNESFile::Resource res_globdata_ger[1] = { { 0x2C4EE, 0x0307, NES_GLOBDATA } };
-#endif
-static const ScummNESFile::Resource *res_globdata[ScummNESFile::kROMsetNum] = {
- res_globdata_usa,
- res_globdata_eur,
- res_globdata_swe,
- res_globdata_fra,
- res_globdata_ger,
-};
-
-#ifdef PALMOS_68K
-static const ScummNESFile::Resource *res_sprpals_usa;
-static const ScummNESFile::Resource *res_sprpals_eur;
-static const ScummNESFile::Resource *res_sprpals_swe;
-static const ScummNESFile::Resource *res_sprpals_fra;
-static const ScummNESFile::Resource *res_sprpals_ger;
-#else
-// sprite palette data
-static const ScummNESFile::Resource res_sprpals_usa[2] = { { 0x0BFC1, 0x0010, NES_SPRPALS }, { 0x0BFD1, 0x0010, NES_SPRPALS } };
-static const ScummNESFile::Resource res_sprpals_eur[2] = { { 0x07F61, 0x0010, NES_SPRPALS }, { 0x0BEB2, 0x0010, NES_SPRPALS } };
-static const ScummNESFile::Resource res_sprpals_swe[2] = { { 0x07F55, 0x0010, NES_SPRPALS }, { 0x07F65, 0x0010, NES_SPRPALS } };
-static const ScummNESFile::Resource res_sprpals_fra[2] = { { 0x07ED8, 0x0010, NES_SPRPALS }, { 0x07EE8, 0x0010, NES_SPRPALS } };
-static const ScummNESFile::Resource res_sprpals_ger[2] = { { 0x07F6B, 0x0010, NES_SPRPALS }, { 0x0BF17, 0x0010, NES_SPRPALS } };
-#endif
-static const ScummNESFile::Resource *res_sprpals[ScummNESFile::kROMsetNum] = {
- res_sprpals_usa,
- res_sprpals_eur,
- res_sprpals_swe,
- res_sprpals_fra,
- res_sprpals_ger,
-};
-
-#ifdef PALMOS_68K
-static const ScummNESFile::Resource *res_sprdesc_usa;
-static const ScummNESFile::Resource *res_sprdesc_eur;
-static const ScummNESFile::Resource *res_sprdesc_swe;
-static const ScummNESFile::Resource *res_sprdesc_fra;
-static const ScummNESFile::Resource *res_sprdesc_ger;
-#else
-// associates costume IDs with sprite sets (indexes into SPRLENS/SPROFFS)
-static const ScummNESFile::Resource res_sprdesc_usa[2] = { { 0x0FFB7, 0x0031, NES_SPRDESC }, { 0x0BFE1, 0x0009, NES_SPRDESC } };
-static const ScummNESFile::Resource res_sprdesc_eur[2] = { { 0x0BEC2, 0x0031, NES_SPRDESC }, { 0x07F71, 0x0009, NES_SPRDESC } };
-static const ScummNESFile::Resource res_sprdesc_swe[2] = { { 0x0BF1B, 0x0031, NES_SPRDESC }, { 0x07F75, 0x0009, NES_SPRDESC } };
-static const ScummNESFile::Resource res_sprdesc_fra[2] = { { 0x07EF8, 0x0031, NES_SPRDESC }, { 0x07F29, 0x0009, NES_SPRDESC } };
-static const ScummNESFile::Resource res_sprdesc_ger[2] = { { 0x0BF27, 0x0031, NES_SPRDESC }, { 0x0BF58, 0x0009, NES_SPRDESC } };
-#endif
-static const ScummNESFile::Resource *res_sprdesc[ScummNESFile::kROMsetNum] = {
- res_sprdesc_usa,
- res_sprdesc_eur,
- res_sprdesc_swe,
- res_sprdesc_fra,
- res_sprdesc_ger,
-};
-
-#ifdef PALMOS_68K
-static const ScummNESFile::Resource *res_sprlens_usa;
-static const ScummNESFile::Resource *res_sprlens_eur;
-static const ScummNESFile::Resource *res_sprlens_swe;
-static const ScummNESFile::Resource *res_sprlens_fra;
-static const ScummNESFile::Resource *res_sprlens_ger;
-#else
-// number of sprites in each set (indicates length within SPRDATA)
-static const ScummNESFile::Resource res_sprlens_usa[2] = { { 0x0FEA2, 0x0115, NES_SPRLENS }, { 0x07FF5, 0x0006, NES_SPRLENS } };
-static const ScummNESFile::Resource res_sprlens_eur[2] = { { 0x1BE32, 0x0115, NES_SPRLENS }, { 0x07F5B, 0x0006, NES_SPRLENS } };
-static const ScummNESFile::Resource res_sprlens_swe[2] = { { 0x13E6A, 0x0115, NES_SPRLENS }, { 0x07F4F, 0x0006, NES_SPRLENS } };
-static const ScummNESFile::Resource res_sprlens_fra[2] = { { 0x0FE61, 0x0115, NES_SPRLENS }, { 0x07ED2, 0x0006, NES_SPRLENS } };
-static const ScummNESFile::Resource res_sprlens_ger[2] = { { 0x2BE1A, 0x0115, NES_SPRLENS }, { 0x07F65, 0x0006, NES_SPRLENS } };
-#endif
-static const ScummNESFile::Resource *res_sprlens[ScummNESFile::kROMsetNum] = {
- res_sprlens_usa,
- res_sprlens_eur,
- res_sprlens_swe,
- res_sprlens_fra,
- res_sprlens_ger,
-};
-
-#ifdef PALMOS_68K
-static const ScummNESFile::Resource *res_sproffs_usa;
-static const ScummNESFile::Resource *res_sproffs_eur;
-static const ScummNESFile::Resource *res_sproffs_swe;
-static const ScummNESFile::Resource *res_sproffs_fra;
-static const ScummNESFile::Resource *res_sproffs_ger;
-#else
-// offset of each sprite set (indexes into SPRDATA)
-static const ScummNESFile::Resource res_sproffs_usa[2] = { { 0x2BDC5, 0x022A, NES_SPROFFS }, { 0x0BFEA, 0x000C, NES_SPROFFS } };
-static const ScummNESFile::Resource res_sproffs_eur[2] = { { 0x2FD42, 0x022A, NES_SPROFFS }, { 0x0BEF3, 0x000C, NES_SPROFFS } };
-static const ScummNESFile::Resource res_sproffs_swe[2] = { { 0x2BCE0, 0x022A, NES_SPROFFS }, { 0x0BF4C, 0x000C, NES_SPROFFS } };
-static const ScummNESFile::Resource res_sproffs_fra[2] = { { 0x2F959, 0x022A, NES_SPROFFS }, { 0x07F32, 0x000C, NES_SPROFFS } };
-static const ScummNESFile::Resource res_sproffs_ger[2] = { { 0x2F81F, 0x022A, NES_SPROFFS }, { 0x0BF61, 0x000C, NES_SPROFFS } };
-#endif
-static const ScummNESFile::Resource *res_sproffs[ScummNESFile::kROMsetNum] = {
- res_sproffs_usa,
- res_sproffs_eur,
- res_sproffs_swe,
- res_sproffs_fra,
- res_sproffs_ger,
-};
-
-#ifdef PALMOS_68K
-static const ScummNESFile::Resource *res_sprdata_usa;
-static const ScummNESFile::Resource *res_sprdata_eur;
-static const ScummNESFile::Resource *res_sprdata_swe;
-static const ScummNESFile::Resource *res_sprdata_fra;
-static const ScummNESFile::Resource *res_sprdata_ger;
-#else
-// sprite data sets (packed NES sprite data)
-static const ScummNESFile::Resource res_sprdata_usa[2] = { { 0x2CE11, 0x2BE0, NES_SPRDATA }, { 0x07F6B, 0x008A, NES_SPRDATA } };
-static const ScummNESFile::Resource res_sprdata_eur[2] = { { 0x2CE11, 0x2BE0, NES_SPRDATA }, { 0x0BE28, 0x008A, NES_SPRDATA } };
-static const ScummNESFile::Resource res_sprdata_swe[2] = { { 0x2C401, 0x2BE0, NES_SPRDATA }, { 0x0FE6B, 0x008A, NES_SPRDATA } };
-static const ScummNESFile::Resource res_sprdata_fra[2] = { { 0x2CA28, 0x2BE0, NES_SPRDATA }, { 0x07E48, 0x008A, NES_SPRDATA } };
-static const ScummNESFile::Resource res_sprdata_ger[2] = { { 0x2C8EE, 0x2BE0, NES_SPRDATA }, { 0x0FE61, 0x008A, NES_SPRDATA } };
-static const ScummNESFile::Resource *res_sprdata[ScummNESFile::kROMsetNum] = {
- res_sprdata_usa,
- res_sprdata_eur,
- res_sprdata_swe,
- res_sprdata_fra,
- res_sprdata_ger,
-};
-#endif
-
-#ifdef PALMOS_68K
-static const ScummNESFile::Resource *res_charset_usa;
-static const ScummNESFile::Resource *res_charset_eur;
-static const ScummNESFile::Resource *res_charset_swe;
-static const ScummNESFile::Resource *res_charset_fra;
-static const ScummNESFile::Resource *res_charset_ger;
-#else
-static const ScummNESFile::Resource res_charset_usa[1] = { { 0x3F6EE, 0x0090, NES_CHARSET } };
-static const ScummNESFile::Resource res_charset_eur[1] = { { 0x3F724, 0x0090, NES_CHARSET } };
-static const ScummNESFile::Resource res_charset_swe[1] = { { 0x3F739, 0x0090, NES_CHARSET } };
-static const ScummNESFile::Resource res_charset_fra[1] = { { 0x3F739, 0x0090, NES_CHARSET } };
-static const ScummNESFile::Resource res_charset_ger[1] = { { 0x3F739, 0x0090, NES_CHARSET } };
-#endif
-static const ScummNESFile::Resource *res_charset[ScummNESFile::kROMsetNum] = {
- res_charset_usa,
- res_charset_eur,
- res_charset_swe,
- res_charset_fra,
- res_charset_ger,
-};
-
-#ifdef PALMOS_68K
-static const ScummNESFile::Resource *res_preplist_usa;
-static const ScummNESFile::Resource *res_preplist_eur;
-static const ScummNESFile::Resource *res_preplist_swe;
-static const ScummNESFile::Resource *res_preplist_fra;
-static const ScummNESFile::Resource *res_preplist_ger;
-#else
-static const ScummNESFile::Resource res_preplist_usa[1] = { { 0x3FB5A, 0x000E, NES_PREPLIST } };
-static const ScummNESFile::Resource res_preplist_eur[1] = { { 0x3FB90, 0x000E, NES_PREPLIST } };
-static const ScummNESFile::Resource res_preplist_swe[1] = { { 0x3FBA9, 0x000E, NES_PREPLIST } };
-static const ScummNESFile::Resource res_preplist_fra[1] = { { 0x3FBAF, 0x0010, NES_PREPLIST } };
-static const ScummNESFile::Resource res_preplist_ger[1] = { { 0x3FBAB, 0x000F, NES_PREPLIST } };
-#endif
-static const ScummNESFile::Resource *res_preplist[ScummNESFile::kROMsetNum] = {
- res_preplist_usa,
- res_preplist_eur,
- res_preplist_swe,
- res_preplist_fra,
- res_preplist_ger,
-};
-
-uint16 write_byte(Common::WriteStream *out, byte val) {
- val ^= 0xFF;
- if (out != 0)
- out->writeByte(val);
- return 1;
-}
-
-uint16 write_word(Common::WriteStream *out, uint16 val) {
- val ^= 0xFFFF;
- if (out != 0)
- out->writeUint16LE(val);
- return 2;
-}
-
-byte ScummNESFile::fileReadByte() {
- byte b = 0;
- File::read(&b, 1);
- return b;
-}
-
-uint16 ScummNESFile::fileReadUint16LE() {
- uint16 a = fileReadByte();
- uint16 b = fileReadByte();
- return a | (b << 8);
-}
-
-uint16 ScummNESFile::extractResource(Common::WriteStream *output, const Resource *res) {
- uint16 len, i, j;
- byte val;
- byte cnt;
- uint16 reslen = 0;
-
- if (res == NULL)
- error("extract_resource - no resource specified");
-
- if ((res->offset == 0) && (res->length == 0))
- return 0; /* there are 8 scripts that are zero bytes long, so we should skip them */
-
- File::seek(res->offset,SEEK_SET);
-
- switch (res->type) {
- case NES_GLOBDATA:
- len = res->length;
-
- for (i = 0; i < len; i++)
- reslen += write_byte(output, fileReadByte());
-
- break;
-
- case NES_ROOMGFX:
- case NES_COSTUMEGFX:
- reslen += write_word(output, (uint16)(res->length + 2));
- len = fileReadByte();
- reslen += write_byte(output, (byte)len);
-
- if (!len)
- len = 256;
- len = len << 4;
-
- for (i = 0; i < len;) {
- reslen += write_byte(output, cnt = fileReadByte());
- for (j = 0; j < (cnt & 0x7F); j++, i++)
- if ((cnt & 0x80) || (j == 0))
- reslen += write_byte(output, fileReadByte());
- }
-
- if (File::pos() - res->offset != res->length)
- error("extract_resource - length mismatch while extracting graphics resource (was %04X, should be %04X)", File::pos() - res->offset, res->length);
-
- break;
-
- case NES_ROOM:
- case NES_SCRIPT:
- len = fileReadUint16LE();
-
- if (len != res->length)
- error("extract_resource - length mismatch while extracting room/script resource (was %04X, should be %04X)", len, res->length);
-
- File::seek(-2, SEEK_CUR);
-
- for (i = 0; i < len; i++)
- reslen += write_byte(output, fileReadByte());
-
- break;
-
- case NES_SOUND:
- len = res->length + 2;
- val = fileReadByte();
- cnt = fileReadByte();
-
- if ((val == 2) && (cnt == 100)) {
- reslen += write_word(output, len);
- reslen += write_byte(output, val);
- reslen += write_byte(output, cnt);
-
- cnt = fileReadByte();
- reslen += write_byte(output, cnt);
- for (i = 0; i < cnt; i++)
- reslen += write_byte(output, fileReadByte());
- for (i = 0; i < cnt; i++)
- reslen += write_byte(output, fileReadByte());
-
- while (1) {
- reslen += write_byte(output, val = fileReadByte());
- if (val >= 0xFE)
- break;
- }
- } else if (((val == 0) || (val == 1) || (val == 4)) && (cnt == 10)) {
- reslen += write_word(output, len);
- reslen += write_byte(output, val);
- reslen += write_byte(output, cnt);
- while (1) {
- reslen += write_byte(output, val = fileReadByte());
-
- if (val >= 0xFE)
- break;
-
- if (val >= 0x10)
- reslen += write_byte(output, fileReadByte());
- else {
- reslen += write_byte(output, fileReadByte());
- reslen += write_byte(output, fileReadByte());
- reslen += write_byte(output, fileReadByte());
- reslen += write_byte(output, fileReadByte());
- }
- }
- } else
- error("extract_resource - unknown sound type %d/%d detected",val,cnt);
-
- if (File::pos() - res->offset != res->length)
- error("extract_resource - length mismatch while extracting sound resource (was %04X, should be %04X)", File::pos() - res->offset, res->length);
-
- break;
-
- case NES_COSTUME:
- case NES_SPRPALS:
- case NES_SPRDESC:
- case NES_SPRLENS:
- case NES_SPROFFS:
- case NES_SPRDATA:
- case NES_CHARSET:
- len = res->length;
- reslen += write_word(output, (uint16)(len + 2));
-
- for (i = 0; i < len; i++)
- reslen += write_byte(output, fileReadByte());
-
- break;
-
- case NES_PREPLIST:
- len = res->length;
- reslen += write_word(output, 0x002A);
-
- reslen += write_byte(output, ' ');
- for (i = 1; i < 8; i++)
- reslen += write_byte(output, 0);
-
- for (j = 0; j < 4; j++)
- {
- reslen += write_byte(output,' ');
- for (i = 1; (val = fileReadByte()); i++)
- reslen += write_byte(output, val);
- for (; i < 8; i++)
- reslen += write_byte(output, 0);
- }
- break;
-
- default:
- error("extract_resource - unknown resource type %d specified!", res->type);
- }
-
- return reslen;
-}
-
-struct ScummNESFile::LFLEntry {
- const Resource **type;
- int index;
-};
-
-// based on structure of Classic PC Maniac Mansion LFL files
-// (roomgfx resources are arranged in order, one per file,
-// after the room blocks)
-static const ScummNESFile::LFLEntry lfl_01[] = { {res_rooms, 1}, {res_roomgfx, 1}, {res_scripts, 57}, {res_scripts, 61}, {res_scripts, 76}, {res_scripts, 105}, {res_scripts, 111}, {res_sounds, 5}, {res_scripts, 132}, {res_scripts, 148}, {res_scripts, 155}, {res_scripts, 156}, {res_sounds, 39}, {NULL, 0} };
-static const ScummNESFile::LFLEntry lfl_02[] = { {res_rooms, 2}, {res_roomgfx, 2}, {NULL, 0} };
-static const ScummNESFile::LFLEntry lfl_03[] = { {res_rooms, 3}, {res_roomgfx, 3}, {res_scripts, 21}, {res_sounds, 26}, {NULL, 0} };
-static const ScummNESFile::LFLEntry lfl_04[] = { {res_rooms, 4}, {res_roomgfx, 4}, {res_scripts, 46}, {res_scripts, 56}, {res_scripts, 137}, {res_scripts, 146}, {res_sounds, 12}, {res_sounds, 11}, {res_sounds, 13}, {res_sounds, 42}, {NULL, 0} };
-static const ScummNESFile::LFLEntry lfl_05[] = { {res_rooms, 5}, {res_roomgfx, 5}, {res_scripts, 30}, {res_scripts, 31}, {res_scripts, 32}, {res_scripts, 33}, {res_scripts, 34}, {res_scripts, 35}, {res_sounds, 22}, {res_sounds, 23}, {res_sounds, 24}, {res_sounds, 21}, {res_sounds, 46}, {NULL, 0} };
-static const ScummNESFile::LFLEntry lfl_06[] = { {res_rooms, 6}, {res_roomgfx, 6}, {NULL, 0} };
-static const ScummNESFile::LFLEntry lfl_07[] = { {res_rooms, 7}, {res_roomgfx, 7}, {res_scripts, 17}, {res_scripts, 58}, {res_scripts, 59}, {res_scripts, 60}, {res_scripts, 74}, {res_scripts, 81}, {res_scripts, 82}, {res_scripts, 150}, {res_sounds, 14}, {res_sounds, 15}, {res_sounds, 16}, {res_sounds, 17}, {NULL, 0} };
-static const ScummNESFile::LFLEntry lfl_08[] = { {res_rooms, 8}, {res_roomgfx, 8}, {res_scripts, 7}, {res_scripts, 12}, {res_scripts, 13}, {res_scripts, 47}, {res_scripts, 48}, {res_scripts, 49}, {res_scripts, 154}, {res_sounds, 32}, {res_sounds, 33}, {res_sounds, 36}, {NULL, 0} };
-static const ScummNESFile::LFLEntry lfl_09[] = { {res_rooms, 9}, {res_roomgfx, 9}, {res_scripts, 10}, {res_scripts, 11}, {res_scripts, 45}, {res_scripts, 55}, {res_scripts, 84}, {res_scripts, 85}, {res_scripts, 86}, {NULL, 0} };
-static const ScummNESFile::LFLEntry lfl_10[] = { {res_rooms, 10}, {res_roomgfx, 10}, {res_scripts, 24}, {res_scripts, 149}, {res_sounds, 28}, {NULL, 0} };
-static const ScummNESFile::LFLEntry lfl_11[] = { {res_rooms, 11}, {res_roomgfx, 11}, {res_scripts, 166}, {res_scripts, 167}, {res_scripts, 168}, {NULL, 0} };
-static const ScummNESFile::LFLEntry lfl_12[] = { {res_rooms, 12}, {res_roomgfx, 12}, {res_scripts, 51}, {res_scripts, 103}, {res_scripts, 104}, {res_scripts, 161}, {res_sounds, 63}, {res_costumes, 14}, {NULL, 0} };
-static const ScummNESFile::LFLEntry lfl_13[] = { {res_rooms, 13}, {res_roomgfx, 13}, {NULL, 0} };
-static const ScummNESFile::LFLEntry lfl_14[] = { {res_rooms, 14}, {res_roomgfx, 14}, {NULL, 0} };
-static const ScummNESFile::LFLEntry lfl_15[] = { {res_rooms, 15}, {res_roomgfx, 15}, {res_sounds, 27}, {NULL, 0} };
-static const ScummNESFile::LFLEntry lfl_16[] = { {res_rooms, 16}, {res_roomgfx, 16}, {res_scripts, 14}, {res_scripts, 121}, {res_scripts, 122}, {res_sounds, 40}, {res_sounds, 64}, {res_sounds, 68}, {NULL, 0} };
-static const ScummNESFile::LFLEntry lfl_17[] = { {res_rooms, 17}, {res_roomgfx, 17}, {res_scripts, 20}, {res_scripts, 100}, {res_sounds, 25}, {res_sounds, 44}, {res_sounds, 2}, {res_sounds, 50}, {res_sounds, 52}, {NULL, 0} };
-static const ScummNESFile::LFLEntry lfl_18[] = { {res_rooms, 18}, {res_roomgfx, 18}, {res_scripts, 25}, {res_scripts, 26}, {res_scripts, 27}, {res_scripts, 28}, {res_scripts, 64}, {res_scripts, 65}, {res_scripts, 66}, {res_scripts, 67}, {res_scripts, 68}, {res_scripts, 69}, {res_scripts, 70}, {res_scripts, 71}, {res_scripts, 73}, {res_scripts, 101}, {res_sounds, 35}, {NULL, 0} };
-static const ScummNESFile::LFLEntry lfl_19[] = { {res_rooms, 19}, {res_roomgfx, 19}, {res_scripts, 36}, {res_scripts, 37}, {res_scripts, 38}, {res_scripts, 39}, {res_scripts, 40}, {res_scripts, 152}, {res_scripts, 153}, {res_costumes, 10}, {NULL, 0} };
-static const ScummNESFile::LFLEntry lfl_20[] = { {res_rooms, 20}, {res_roomgfx, 20}, {res_scripts, 107}, {res_scripts, 108}, {res_scripts, 109}, {res_scripts, 110}, {res_scripts, 159}, {NULL, 0} };
-static const ScummNESFile::LFLEntry lfl_21[] = { {res_rooms, 21}, {res_roomgfx, 21}, {res_scripts, 41}, {res_scripts, 42}, {res_scripts, 43}, {res_scripts, 53}, {res_scripts, 136}, {res_sounds, 29}, {res_sounds, 20}, {res_sounds, 37}, {NULL, 0} };
-static const ScummNESFile::LFLEntry lfl_22[] = { {res_rooms, 22}, {res_roomgfx, 22}, {res_scripts, 15}, {NULL, 0} };
-static const ScummNESFile::LFLEntry lfl_23[] = { {res_rooms, 23}, {res_roomgfx, 23}, {res_scripts, 77}, {res_scripts, 79}, {res_scripts, 80}, {res_scripts, 83}, {res_sounds, 41}, {NULL, 0} };
-static const ScummNESFile::LFLEntry lfl_24[] = { {res_rooms, 24}, {res_roomgfx, 24}, {res_scripts, 18}, {res_scripts, 19}, {res_scripts, 78}, {res_sounds, 7}, {res_sounds, 3}, {res_sounds, 18}, {res_sounds, 34}, {res_costumes, 12}, {NULL, 0} };
-static const ScummNESFile::LFLEntry lfl_25[] = { {res_rooms, 25}, {res_roomgfx, 25}, {res_scripts, 29}, {res_sounds, 30}, {res_sounds, 31}, {NULL, 0} };
-static const ScummNESFile::LFLEntry lfl_26[] = { {res_rooms, 26}, {res_roomgfx, 26}, {res_scripts, 87}, {res_scripts, 88}, {res_scripts, 89}, {res_scripts, 90}, {res_scripts, 91}, {res_scripts, 92}, {res_scripts, 93}, {res_scripts, 94}, {res_scripts, 95}, {res_scripts, 96}, {res_scripts, 97}, {res_scripts, 98}, {res_scripts, 116}, {res_scripts, 151}, {res_scripts, 174}, {res_costumes, 11}, {NULL, 0} };
-static const ScummNESFile::LFLEntry lfl_27[] = { {res_rooms, 27}, {res_roomgfx, 27}, {res_scripts, 16}, {res_scripts, 52}, {res_scripts, 54}, {res_scripts, 113}, {res_sounds, 45}, {res_costumes, 19}, {NULL, 0} };
-static const ScummNESFile::LFLEntry lfl_28[] = { {res_rooms, 28}, {res_roomgfx, 28}, {res_scripts, 22}, {res_scripts, 23}, {NULL, 0} };
-static const ScummNESFile::LFLEntry lfl_29[] = { {res_rooms, 29}, {res_roomgfx, 29}, {res_scripts, 75}, {res_sounds, 43}, {NULL, 0} };
-static const ScummNESFile::LFLEntry lfl_30[] = { {res_rooms, 30}, {res_roomgfx, 30}, {res_scripts, 63}, {res_sounds, 0}, {res_scripts, 123}, {res_scripts, 125}, {res_scripts, 126}, {res_scripts, 127}, {res_scripts, 129}, {res_sounds, 55}, {res_sounds, 59}, {res_sounds, 60}, {res_costumes, 8}, {NULL, 0} };
-static const ScummNESFile::LFLEntry lfl_31[] = { {res_rooms, 31}, {res_roomgfx, 31}, {res_scripts, 99}, {res_scripts, 115}, {res_scripts, 117}, {res_scripts, 119}, {res_scripts, 147}, {res_scripts, 157}, {res_scripts, 158}, {res_scripts, 160}, {res_costumes, 13}, {res_costumes, 9}, {res_costumes, 23}, {res_costumes, 24}, {NULL, 0} };
-static const ScummNESFile::LFLEntry lfl_32[] = { {res_rooms, 32}, {res_roomgfx, 32}, {res_costumes, 15}, {NULL, 0} };
-static const ScummNESFile::LFLEntry lfl_33[] = { {res_rooms, 33}, {res_roomgfx, 33}, {res_scripts, 120}, {res_scripts, 135}, {res_sounds, 56}, {res_sounds, 57}, {res_sounds, 58}, {res_sounds, 1}, {res_costumes, 22}, {NULL, 0} };
-static const ScummNESFile::LFLEntry lfl_34[] = { {res_rooms, 34}, {res_roomgfx, 34}, {NULL, 0} };
-static const ScummNESFile::LFLEntry lfl_35[] = { {res_rooms, 35}, {res_roomgfx, 35}, {NULL, 0} };
-static const ScummNESFile::LFLEntry lfl_36[] = { {res_rooms, 36}, {res_roomgfx, 36}, {res_sounds, 10}, {res_sounds, 4}, {NULL, 0} };
-static const ScummNESFile::LFLEntry lfl_37[] = { {res_rooms, 37}, {res_roomgfx, 37}, {NULL, 0} };
-static const ScummNESFile::LFLEntry lfl_38[] = { {res_rooms, 38}, {res_roomgfx, 38}, {res_scripts, 138}, {res_scripts, 139}, {res_scripts, 140}, {res_scripts, 141}, {res_scripts, 142}, {res_scripts, 143}, {res_scripts, 144}, {res_scripts, 145}, {NULL, 0} };
-static const ScummNESFile::LFLEntry lfl_39[] = { {res_rooms, 39}, {res_roomgfx, 39}, {NULL, 0} };
-static const ScummNESFile::LFLEntry lfl_40[] = { {res_rooms, 40}, {res_roomgfx, 0}, {res_scripts, 112}, {res_costumes, 17}, {NULL, 0} };
-static const ScummNESFile::LFLEntry lfl_41[] = { {res_rooms, 41}, {res_scripts, 106}, {res_sounds, 47}, {res_sounds, 48}, {res_sounds, 53}, {res_sounds, 49}, {res_sounds, 51}, {NULL, 0} };
-static const ScummNESFile::LFLEntry lfl_42[] = { {res_rooms, 42}, {res_scripts, 124}, {res_costumes, 18}, {NULL, 0} };
-static const ScummNESFile::LFLEntry lfl_43[] = { {res_rooms, 43}, {res_scripts, 44}, {res_sounds, 19}, {NULL, 0} };
-static const ScummNESFile::LFLEntry lfl_44[] = { {res_rooms, 44}, {res_scripts, 102}, {res_sounds, 6}, {res_sounds, 38}, {res_sounds, 8}, {res_sounds, 9}, {res_costumes, 1}, {res_costumes, 2}, {res_costumes, 5}, {res_costumes, 6}, {res_costumes, 3}, {res_costumes, 4}, {res_costumes, 7}, {NULL, 0} };
-static const ScummNESFile::LFLEntry lfl_45[] = { {res_rooms, 45}, {res_scripts, 1}, {res_scripts, 2}, {res_scripts, 3}, {res_scripts, 4}, {res_scripts, 5}, {res_scripts, 9}, {res_scripts, 114}, {res_scripts, 131}, {res_scripts, 164}, {res_scripts, 165}, {res_scripts, 169}, {res_scripts, 170}, {res_scripts, 171}, {res_scripts, 172}, {res_scripts, 173}, {res_scripts, 175}, {res_sounds, 54}, {NULL, 0} };
-static const ScummNESFile::LFLEntry lfl_46[] = { {res_rooms, 46}, {res_scripts, 130}, {res_sounds, 65}, {res_costumes, 0}, {res_costumes, 21}, {NULL, 0} };
-static const ScummNESFile::LFLEntry lfl_47[] = { {res_rooms, 47}, {res_scripts, 62}, {res_sounds, 69}, {NULL, 0} };
-static const ScummNESFile::LFLEntry lfl_48[] = { {res_rooms, 48}, {NULL, 0} };
-static const ScummNESFile::LFLEntry lfl_49[] = { {res_rooms, 49}, {NULL, 0} };
-static const ScummNESFile::LFLEntry lfl_50[] = { {res_rooms, 50}, {res_scripts, 133}, {res_scripts, 163}, {NULL, 0} };
-static const ScummNESFile::LFLEntry lfl_51[] = { {res_rooms, 51}, {res_scripts, 118}, {res_scripts, 128}, {res_sounds, 61}, {res_sounds, 62}, {res_sounds, 67}, {res_sounds, 66}, {res_costumes, 16}, {res_costumes, 20}, {NULL, 0} };
-static const ScummNESFile::LFLEntry lfl_52[] = { {res_rooms, 52}, {NULL, 0} };
-// remaining 'standard' resources (not used by any of the original LFL files)
-static const ScummNESFile::LFLEntry lfl_53[] = { {res_rooms, 53}, {res_scripts, 177}, {res_scripts, 178}, {res_sounds, 70}, {res_sounds, 71}, {res_sounds, 72}, {res_sounds, 73}, {res_sounds, 74}, {res_sounds, 75}, {res_sounds, 76}, {res_sounds, 77}, {res_sounds, 78}, {res_sounds, 79}, {res_sounds, 80}, {res_sounds, 81}, {NULL, 0} };
-// all 'non-standard' resources (the costume-related stuff)
-static const ScummNESFile::LFLEntry lfl_54[] = { {res_rooms, 54}, {res_sprdesc, 0}, {res_sprdesc, 1}, {res_sprlens, 0}, {res_sprlens, 1}, {res_sproffs, 0}, {res_sproffs, 1}, {res_sprdata, 0}, {res_sprdata, 1}, {res_costumegfx, 0}, {res_costumegfx, 1}, {res_sprpals, 0}, {res_sprpals, 1}, {res_charset, 0}, {res_preplist, 0}, {NULL, 0} };
-
-struct ScummNESFile::LFL {
- int num;
- const ScummNESFile::LFLEntry *entries;
-};
-
-static const ScummNESFile::LFL lfls[] = {
- { 1, lfl_01 },
- { 2, lfl_02 },
- { 3, lfl_03 },
- { 4, lfl_04 },
- { 5, lfl_05 },
- { 6, lfl_06 },
- { 7, lfl_07 },
- { 8, lfl_08 },
- { 9, lfl_09 },
- { 10, lfl_10 },
- { 11, lfl_11 },
- { 12, lfl_12 },
- { 13, lfl_13 },
- { 14, lfl_14 },
- { 15, lfl_15 },
- { 16, lfl_16 },
- { 17, lfl_17 },
- { 18, lfl_18 },
- { 19, lfl_19 },
- { 20, lfl_20 },
- { 21, lfl_21 },
- { 22, lfl_22 },
- { 23, lfl_23 },
- { 24, lfl_24 },
- { 25, lfl_25 },
- { 26, lfl_26 },
- { 27, lfl_27 },
- { 28, lfl_28 },
- { 29, lfl_29 },
- { 30, lfl_30 },
- { 31, lfl_31 },
- { 32, lfl_32 },
- { 33, lfl_33 },
- { 34, lfl_34 },
- { 35, lfl_35 },
- { 36, lfl_36 },
- { 37, lfl_37 },
- { 38, lfl_38 },
- { 39, lfl_39 },
- { 40, lfl_40 },
- { 41, lfl_41 },
- { 42, lfl_42 },
- { 43, lfl_43 },
- { 44, lfl_44 },
- { 45, lfl_45 },
- { 46, lfl_46 },
- { 47, lfl_47 },
- { 48, lfl_48 },
- { 49, lfl_49 },
- { 50, lfl_50 },
- { 51, lfl_51 },
- { 52, lfl_52 },
- { 53, lfl_53 },
- { 54, lfl_54 },
- { -1, NULL }
-};
-
-#include "common/pack-start.h" // START STRUCT PACKING
-
-struct _lfl_index {
- byte room_lfl[55];
- uint16 room_addr[55];
- byte costume_lfl[80];
- uint16 costume_addr[80];
- byte script_lfl[200];
- uint16 script_addr[200];
- byte sound_lfl[100];
- uint16 sound_addr[100];
-} PACKED_STRUCT;
-
-#include "common/pack-end.h" // END STRUCT PACKING
-
-_lfl_index lfl_index;
-
-bool ScummNESFile::generateResource(int res) {
- const LFL *lfl = &lfls[res - 1];
- int j;
- int bufsize = 2;
-
- for (j = 0; lfl->entries[j].type != NULL; j++)
- bufsize += extractResource(0, &lfl->entries[j].type[_ROMset][lfl->entries[j].index]);
-
- free(_buf);
- _buf = (byte *)calloc(1, bufsize);
-
- Common::MemoryWriteStream out(_buf, bufsize);
-
- for (j = 0; lfl->entries[j].type != NULL; j++) {
- const Resource *entry = &lfl->entries[j].type[_ROMset][lfl->entries[j].index];
- extractResource(&out, entry);
- }
- write_byte(&out, 0xD1);
- write_byte(&out, 0xF5);
-
- if (_stream)
- delete _stream;
-
- _stream = new Common::MemoryReadStream(_buf, bufsize);
-
- return true;
-}
-
-bool ScummNESFile::generateIndex() {
- int i, j;
-
- for (i = 0; lfls[i].num != -1; i++) {
- const LFL *lfl = &lfls[i];
- uint16 respos = 0;
-
- for (j = 0; lfl->entries[j].type != NULL; j++) {
- const LFLEntry *entry = &lfl->entries[j];
-
- switch (entry->type[_ROMset][entry->index].type) {
- case NES_ROOM:
- lfl_index.room_lfl[entry->index] = lfl->num;
- lfl_index.room_addr[entry->index] = TO_LE_16(respos);
- break;
- case NES_COSTUME:
- lfl_index.costume_lfl[entry->index] = lfl->num;
- lfl_index.costume_addr[entry->index] = TO_LE_16(respos);
- break;
- case NES_SPRDESC:
- lfl_index.costume_lfl[entry->index + 25] = lfl->num;
- lfl_index.costume_addr[entry->index + 25] = TO_LE_16(respos);
- break;
- case NES_SPRLENS:
- lfl_index.costume_lfl[entry->index + 27] = lfl->num;
- lfl_index.costume_addr[entry->index + 27] = TO_LE_16(respos);
- break;
- case NES_SPROFFS:
- lfl_index.costume_lfl[entry->index + 29] = lfl->num;
- lfl_index.costume_addr[entry->index + 29] = TO_LE_16(respos);
- break;
- case NES_SPRDATA:
- lfl_index.costume_lfl[entry->index + 31] = lfl->num;
- lfl_index.costume_addr[entry->index + 31] = TO_LE_16(respos);
- break;
- case NES_COSTUMEGFX:
- lfl_index.costume_lfl[entry->index + 33] = lfl->num;
- lfl_index.costume_addr[entry->index + 33] = TO_LE_16(respos);
- break;
- case NES_SPRPALS:
- lfl_index.costume_lfl[entry->index + 35] = lfl->num;
- lfl_index.costume_addr[entry->index + 35] = TO_LE_16(respos);
- break;
- case NES_ROOMGFX:
- lfl_index.costume_lfl[entry->index + 37] = lfl->num;
- lfl_index.costume_addr[entry->index + 37] = TO_LE_16(respos);
- break;
- case NES_SCRIPT:
- lfl_index.script_lfl[entry->index] = lfl->num;
- lfl_index.script_addr[entry->index] = TO_LE_16(respos);
- break;
- case NES_SOUND:
- lfl_index.sound_lfl[entry->index] = lfl->num;
- lfl_index.sound_addr[entry->index] = TO_LE_16(respos);
- break;
- case NES_CHARSET:
- lfl_index.costume_lfl[77] = lfl->num;
- lfl_index.costume_addr[77] = TO_LE_16(respos);
- break;
- case NES_PREPLIST:
- lfl_index.costume_lfl[78] = lfl->num;
- lfl_index.costume_addr[78] = TO_LE_16(respos);
- break;
- default:
- error("Unindexed entry found!");
- break;
- }
- respos += extractResource(0, &entry->type[_ROMset][entry->index]);
- }
- }
-
- int bufsize = 2;
-
- bufsize += 775;
- bufsize += sizeof(lfl_index);
-
- free(_buf);
- _buf = (byte *)calloc(1, bufsize);
-
- Common::MemoryWriteStream out(_buf, bufsize);
-
- write_byte(&out, 0x43);
- write_byte(&out, 0x46);
-
- extractResource(&out, &res_globdata[_ROMset][0]);
-
- for (i = 0; i < (int)sizeof(lfl_index); i++)
- write_byte(&out, ((byte *)&lfl_index)[i]);
-
- if (_stream)
- delete _stream;
-
- _stream = new Common::MemoryReadStream(_buf, bufsize);
-
- return true;
-}
-
-bool ScummNESFile::open(const Common::String &filename, AccessMode mode) {
-
- if (_ROMset == kROMsetNum) {
- char md5str[32+1];
- if (Common::md5_file_string(filename.c_str(), md5str)) {
-
- if (!strcmp(md5str, "3905799e081b80a61d4460b7b733c206")) {
- _ROMset = kROMsetUSA;
- debug(1, "ROM contents verified as Maniac Mansion (USA)");
- } else if (!strcmp(md5str, "d8d07efcb88f396bee0b402b10c3b1c9")) {
- _ROMset = kROMsetEurope;
- debug(1, "ROM contents verified as Maniac Mansion (Europe)");
- } else if (!strcmp(md5str, "22d07d6c386c9c25aca5dac2a0c0d94b")) {
- _ROMset = kROMsetSweden;
- debug(1, "ROM contents verified as Maniac Mansion (Sweden)");
- } else if (!strcmp(md5str, "81bbfa181184cb494e7a81dcfa94fbd9")) {
- _ROMset = kROMsetFrance;
- debug(2, "ROM contents verified as Maniac Mansion (France)");
- } else if (!strcmp(md5str, "257f8c14d8c584f7ddd601bcb00920c7")) {
- _ROMset = kROMsetGermany;
- debug(2, "ROM contents verified as Maniac Mansion (Germany)");
- } else {
- error("Unsupported Maniac Mansion ROM, md5: %s", md5str);
- return false;
- }
- } else {
- return false;
- }
- }
-
- if (File::open(filename, mode)) {
- if (_stream)
- delete _stream;
- _stream = 0;
-
- free(_buf);
- _buf = 0;
-
- return true;
- } else {
- return false;
- }
-}
-
-void ScummNESFile::close() {
- if (_stream)
- delete _stream;
- _stream = 0;
-
- free(_buf);
- _buf = 0;
-
- File::close();
-}
-
-bool ScummNESFile::openSubFile(const Common::String &filename) {
- assert(isOpen());
-
- const char *ext = strrchr(filename.c_str(), '.');
- char resNum[3];
- int res;
-
- // We always have file name in form of XX.lfl
- resNum[0] = ext[-2];
- resNum[1] = ext[-1];
- resNum[2] = 0;
-
- res = atoi(resNum);
-
- if (res == 0) {
- return generateIndex();
- } else {
- return generateResource(res);
- }
-}
-
-#pragma mark -
#pragma mark --- ScummDiskImage ---
#pragma mark -
@@ -1487,6 +215,20 @@ static const int zakResourcesPerFile[59] = {
};
+static uint16 write_byte(Common::WriteStream *out, byte val) {
+ val ^= 0xFF;
+ if (out != 0)
+ out->writeByte(val);
+ return 1;
+}
+
+static uint16 write_word(Common::WriteStream *out, uint16 val) {
+ val ^= 0xFFFF;
+ if (out != 0)
+ out->writeUint16LE(val);
+ return 2;
+}
+
ScummDiskImage::ScummDiskImage(const char *disk1, const char *disk2, GameSettings game) : _stream(0), _buf(0) {
_disk1 = disk1;
_disk2 = disk2;
diff --git a/engines/scumm/file.h b/engines/scumm/file.h
index 18b7b8fb18..10ab031c7e 100644
--- a/engines/scumm/file.h
+++ b/engines/scumm/file.h
@@ -70,50 +70,6 @@ public:
uint32 write(const void *dataPtr, uint32 dataSize);
};
-class ScummNESFile : public BaseScummFile {
-public:
- enum ROMset {
- kROMsetUSA,
- kROMsetEurope,
- kROMsetSweden,
- kROMsetFrance,
- kROMsetGermany,
- kROMsetNum
- };
-
- struct Resource;
- struct LFLEntry;
- struct LFL;
-
-private:
- Common::MemoryReadStream *_stream;
- ROMset _ROMset;
- byte *_buf;
-
- bool generateIndex();
- bool generateResource(int res);
- uint16 extractResource(Common::WriteStream *out, const Resource *res);
-
- byte fileReadByte();
- uint16 fileReadUint16LE();
-
-public:
- ScummNESFile();
- void setEnc(byte value);
-
- bool open(const Common::String &filename, AccessMode mode = kFileReadMode);
- bool openSubFile(const Common::String &filename);
-
- void close();
- bool eof() { return _stream->eos(); }
- uint32 pos() { return _stream->pos(); }
- uint32 size() { return _stream->size(); }
- void seek(int32 offs, int whence = SEEK_SET) { _stream->seek(offs, whence); }
- uint32 read(void *dataPtr, uint32 dataSize) { return _stream->read(dataPtr, dataSize); }
- uint32 write(const void *dataPtr, uint32 dataSize);
-};
-
-
class ScummDiskImage : public BaseScummFile {
private:
Common::MemoryReadStream *_stream;
diff --git a/engines/scumm/file_nes.cpp b/engines/scumm/file_nes.cpp
new file mode 100644
index 0000000000..88b4253a1d
--- /dev/null
+++ b/engines/scumm/file_nes.cpp
@@ -0,0 +1,1317 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#include "scumm/file_nes.h"
+#include "common/endian.h"
+#include "common/md5.h"
+
+using Common::File;
+
+namespace Scumm {
+
+#pragma mark -
+#pragma mark --- ScummNESFile ---
+#pragma mark -
+
+enum ResType {
+ NES_UNKNOWN,
+ NES_GLOBDATA,
+ NES_ROOM,
+ NES_SCRIPT,
+ NES_SOUND,
+ NES_COSTUME,
+ NES_ROOMGFX,
+ NES_COSTUMEGFX,
+ NES_SPRPALS,
+ NES_SPRDESC,
+ NES_SPRLENS,
+ NES_SPROFFS,
+ NES_SPRDATA,
+ NES_CHARSET,
+ NES_PREPLIST
+};
+
+struct ScummNESFile::Resource {
+ uint32 offset;
+ uint16 length;
+ ResType type;
+};
+
+ScummNESFile::ScummNESFile() : _stream(0), _buf(0), _ROMset(kROMsetNum) {
+}
+
+uint32 ScummNESFile::write(const void *, uint32) {
+ error("ScummNESFile does not support writing!");
+ return 0;
+}
+
+void ScummNESFile::setEnc(byte enc) {
+ _stream->setEnc(enc);
+}
+
+static const ScummNESFile::Resource res_roomgfx_usa[40] = {
+ { 0x04001, 0x03C9, NES_ROOMGFX }, { 0x043CA, 0x069E, NES_ROOMGFX }, { 0x04A68, 0x0327, NES_ROOMGFX }, { 0x04D8F, 0x053B, NES_ROOMGFX }, { 0x052CA, 0x06BE, NES_ROOMGFX },
+ { 0x05988, 0x0682, NES_ROOMGFX }, { 0x0600A, 0x0778, NES_ROOMGFX }, { 0x06782, 0x0517, NES_ROOMGFX }, { 0x06C99, 0x07FB, NES_ROOMGFX }, { 0x07494, 0x07BE, NES_ROOMGFX },
+ { 0x08001, 0x07A5, NES_ROOMGFX }, { 0x087A6, 0x06DD, NES_ROOMGFX }, { 0x08E83, 0x04EA, NES_ROOMGFX }, { 0x0936D, 0x0846, NES_ROOMGFX }, { 0x09BB3, 0x08C8, NES_ROOMGFX },
+ { 0x0A47B, 0x0844, NES_ROOMGFX }, { 0x0ACBF, 0x0515, NES_ROOMGFX }, { 0x0B1D4, 0x0799, NES_ROOMGFX }, { 0x0B96D, 0x04BB, NES_ROOMGFX }, { 0x07C52, 0x0319, NES_ROOMGFX },
+ { 0x0C001, 0x0464, NES_ROOMGFX }, { 0x0C465, 0x076D, NES_ROOMGFX }, { 0x0CBD2, 0x0827, NES_ROOMGFX }, { 0x0D3F9, 0x0515, NES_ROOMGFX }, { 0x0D90E, 0x064E, NES_ROOMGFX },
+ { 0x0DF5C, 0x0775, NES_ROOMGFX }, { 0x0E6D1, 0x06DD, NES_ROOMGFX }, { 0x0EDAE, 0x0376, NES_ROOMGFX }, { 0x0F124, 0x05F7, NES_ROOMGFX }, { 0x0F71B, 0x0787, NES_ROOMGFX },
+ { 0x10001, 0x02D6, NES_ROOMGFX }, { 0x102D7, 0x06A3, NES_ROOMGFX }, { 0x1097A, 0x099F, NES_ROOMGFX }, { 0x11319, 0x0361, NES_ROOMGFX }, { 0x1167A, 0x0489, NES_ROOMGFX },
+ { 0x11B03, 0x0437, NES_ROOMGFX }, { 0x11F3A, 0x084D, NES_ROOMGFX }, { 0x0BE28, 0x0199, NES_ROOMGFX }, { 0x12787, 0x09A7, NES_ROOMGFX }, { 0x1312E, 0x037A, NES_ROOMGFX }
+};
+static const ScummNESFile::Resource res_roomgfx_eur[40] = {
+ { 0x04001, 0x03B9, NES_ROOMGFX }, { 0x043BA, 0x069E, NES_ROOMGFX }, { 0x04A58, 0x0327, NES_ROOMGFX }, { 0x04D7F, 0x053B, NES_ROOMGFX }, { 0x052BA, 0x06BE, NES_ROOMGFX },
+ { 0x05978, 0x0682, NES_ROOMGFX }, { 0x05FFA, 0x0778, NES_ROOMGFX }, { 0x06772, 0x0517, NES_ROOMGFX }, { 0x06C89, 0x07FB, NES_ROOMGFX }, { 0x07484, 0x07BE, NES_ROOMGFX },
+ { 0x08001, 0x07A5, NES_ROOMGFX }, { 0x087A6, 0x06DD, NES_ROOMGFX }, { 0x08E83, 0x04EA, NES_ROOMGFX }, { 0x0936D, 0x0846, NES_ROOMGFX }, { 0x09BB3, 0x08C8, NES_ROOMGFX },
+ { 0x0A47B, 0x0844, NES_ROOMGFX }, { 0x0ACBF, 0x0515, NES_ROOMGFX }, { 0x0B1D4, 0x0799, NES_ROOMGFX }, { 0x0B96D, 0x04BB, NES_ROOMGFX }, { 0x07C42, 0x0319, NES_ROOMGFX },
+ { 0x0C001, 0x0464, NES_ROOMGFX }, { 0x0C465, 0x076D, NES_ROOMGFX }, { 0x0CBD2, 0x0827, NES_ROOMGFX }, { 0x0D3F9, 0x0515, NES_ROOMGFX }, { 0x0D90E, 0x064E, NES_ROOMGFX },
+ { 0x0DF5C, 0x0775, NES_ROOMGFX }, { 0x0E6D1, 0x06DD, NES_ROOMGFX }, { 0x0EDAE, 0x0376, NES_ROOMGFX }, { 0x0F124, 0x05F7, NES_ROOMGFX }, { 0x0F71B, 0x0787, NES_ROOMGFX },
+ { 0x10001, 0x02D6, NES_ROOMGFX }, { 0x102D7, 0x06A3, NES_ROOMGFX }, { 0x1097A, 0x099F, NES_ROOMGFX }, { 0x11319, 0x0361, NES_ROOMGFX }, { 0x1167A, 0x0489, NES_ROOMGFX },
+ { 0x11B03, 0x0437, NES_ROOMGFX }, { 0x11F3A, 0x084D, NES_ROOMGFX }, { 0x12787, 0x0199, NES_ROOMGFX }, { 0x12920, 0x09A7, NES_ROOMGFX }, { 0x132C7, 0x037A, NES_ROOMGFX }
+};
+static const ScummNESFile::Resource res_roomgfx_swe[40] = {
+ { 0x04001, 0x03F0, NES_ROOMGFX }, { 0x043F1, 0x069E, NES_ROOMGFX }, { 0x04A8F, 0x0327, NES_ROOMGFX }, { 0x04DB6, 0x053B, NES_ROOMGFX }, { 0x052F1, 0x06BE, NES_ROOMGFX },
+ { 0x059AF, 0x0682, NES_ROOMGFX }, { 0x06031, 0x0778, NES_ROOMGFX }, { 0x067A9, 0x0517, NES_ROOMGFX }, { 0x06CC0, 0x07FB, NES_ROOMGFX }, { 0x074BB, 0x07BE, NES_ROOMGFX },
+ { 0x08001, 0x07A5, NES_ROOMGFX }, { 0x087A6, 0x06DD, NES_ROOMGFX }, { 0x08E83, 0x04EA, NES_ROOMGFX }, { 0x0936D, 0x07E2, NES_ROOMGFX }, { 0x09B4F, 0x0791, NES_ROOMGFX },
+ { 0x0A2E0, 0x07B5, NES_ROOMGFX }, { 0x0AA95, 0x0515, NES_ROOMGFX }, { 0x0AFAA, 0x0799, NES_ROOMGFX }, { 0x0B743, 0x04BF, NES_ROOMGFX }, { 0x0BC02, 0x0319, NES_ROOMGFX },
+ { 0x0C001, 0x0464, NES_ROOMGFX }, { 0x0C465, 0x072C, NES_ROOMGFX }, { 0x0CB91, 0x0827, NES_ROOMGFX }, { 0x0D3B8, 0x0515, NES_ROOMGFX }, { 0x0D8CD, 0x064E, NES_ROOMGFX },
+ { 0x0DF1B, 0x0775, NES_ROOMGFX }, { 0x0E690, 0x06DD, NES_ROOMGFX }, { 0x0ED6D, 0x0376, NES_ROOMGFX }, { 0x0F0E3, 0x05F7, NES_ROOMGFX }, { 0x0F6DA, 0x0791, NES_ROOMGFX },
+ { 0x07C79, 0x02D6, NES_ROOMGFX }, { 0x10001, 0x06A3, NES_ROOMGFX }, { 0x106A4, 0x0921, NES_ROOMGFX }, { 0x10FC5, 0x0361, NES_ROOMGFX }, { 0x11326, 0x0489, NES_ROOMGFX },
+ { 0x117AF, 0x0437, NES_ROOMGFX }, { 0x11BE6, 0x084F, NES_ROOMGFX }, { 0x12435, 0x0199, NES_ROOMGFX }, { 0x125CE, 0x0947, NES_ROOMGFX }, { 0x12F15, 0x037A, NES_ROOMGFX }
+};
+static const ScummNESFile::Resource res_roomgfx_fra[40] = {
+ { 0x04001, 0x0426, NES_ROOMGFX }, { 0x04427, 0x069E, NES_ROOMGFX }, { 0x04AC5, 0x0327, NES_ROOMGFX }, { 0x04DEC, 0x053B, NES_ROOMGFX }, { 0x05327, 0x06BE, NES_ROOMGFX },
+ { 0x059E5, 0x0682, NES_ROOMGFX }, { 0x06067, 0x0778, NES_ROOMGFX }, { 0x067DF, 0x0517, NES_ROOMGFX }, { 0x06CF6, 0x07FB, NES_ROOMGFX }, { 0x074F1, 0x07BE, NES_ROOMGFX },
+ { 0x08001, 0x07A5, NES_ROOMGFX }, { 0x087A6, 0x06DD, NES_ROOMGFX }, { 0x08E83, 0x04EA, NES_ROOMGFX }, { 0x0936D, 0x07E2, NES_ROOMGFX }, { 0x09B4F, 0x0791, NES_ROOMGFX },
+ { 0x0A2E0, 0x07B5, NES_ROOMGFX }, { 0x0AA95, 0x0515, NES_ROOMGFX }, { 0x0AFAA, 0x0799, NES_ROOMGFX }, { 0x0B743, 0x04BB, NES_ROOMGFX }, { 0x0BBFE, 0x0319, NES_ROOMGFX },
+ { 0x0C001, 0x0464, NES_ROOMGFX }, { 0x0C465, 0x072C, NES_ROOMGFX }, { 0x0CB91, 0x0827, NES_ROOMGFX }, { 0x0D3B8, 0x0515, NES_ROOMGFX }, { 0x0D8CD, 0x064E, NES_ROOMGFX },
+ { 0x0DF1B, 0x0775, NES_ROOMGFX }, { 0x0E690, 0x06DD, NES_ROOMGFX }, { 0x0ED6D, 0x0376, NES_ROOMGFX }, { 0x0F0E3, 0x05F7, NES_ROOMGFX }, { 0x0F6DA, 0x0787, NES_ROOMGFX },
+ { 0x10001, 0x02D6, NES_ROOMGFX }, { 0x102D7, 0x06A3, NES_ROOMGFX }, { 0x1097A, 0x0921, NES_ROOMGFX }, { 0x1129B, 0x0361, NES_ROOMGFX }, { 0x115FC, 0x0489, NES_ROOMGFX },
+ { 0x11A85, 0x0437, NES_ROOMGFX }, { 0x11EBC, 0x070D, NES_ROOMGFX }, { 0x07CAF, 0x0199, NES_ROOMGFX }, { 0x125C9, 0x0947, NES_ROOMGFX }, { 0x12F10, 0x037A, NES_ROOMGFX }
+};
+static const ScummNESFile::Resource res_roomgfx_ger[40] = {
+ { 0x04001, 0x0406, NES_ROOMGFX }, { 0x04407, 0x069E, NES_ROOMGFX }, { 0x04AA5, 0x0327, NES_ROOMGFX }, { 0x04DCC, 0x053B, NES_ROOMGFX }, { 0x05307, 0x06BE, NES_ROOMGFX },
+ { 0x059C5, 0x0682, NES_ROOMGFX }, { 0x06047, 0x0778, NES_ROOMGFX }, { 0x067BF, 0x0517, NES_ROOMGFX }, { 0x06CD6, 0x07FB, NES_ROOMGFX }, { 0x074D1, 0x07BE, NES_ROOMGFX },
+ { 0x08001, 0x07A5, NES_ROOMGFX }, { 0x087A6, 0x06DD, NES_ROOMGFX }, { 0x08E83, 0x04EA, NES_ROOMGFX }, { 0x0936D, 0x07E2, NES_ROOMGFX }, { 0x09B4F, 0x0791, NES_ROOMGFX },
+ { 0x0A2E0, 0x07B5, NES_ROOMGFX }, { 0x0AA95, 0x0515, NES_ROOMGFX }, { 0x0AFAA, 0x0799, NES_ROOMGFX }, { 0x0B743, 0x04BB, NES_ROOMGFX }, { 0x0BBFE, 0x0319, NES_ROOMGFX },
+ { 0x0C001, 0x0464, NES_ROOMGFX }, { 0x0C465, 0x072C, NES_ROOMGFX }, { 0x0CB91, 0x0827, NES_ROOMGFX }, { 0x0D3B8, 0x0515, NES_ROOMGFX }, { 0x0D8CD, 0x064E, NES_ROOMGFX },
+ { 0x0DF1B, 0x0775, NES_ROOMGFX }, { 0x0E690, 0x06DD, NES_ROOMGFX }, { 0x0ED6D, 0x0376, NES_ROOMGFX }, { 0x0F0E3, 0x05F7, NES_ROOMGFX }, { 0x0F6DA, 0x0787, NES_ROOMGFX },
+ { 0x07C8F, 0x02D6, NES_ROOMGFX }, { 0x10001, 0x06A3, NES_ROOMGFX }, { 0x106A4, 0x0921, NES_ROOMGFX }, { 0x10FC5, 0x0361, NES_ROOMGFX }, { 0x11326, 0x0489, NES_ROOMGFX },
+ { 0x117AF, 0x0437, NES_ROOMGFX }, { 0x11BE6, 0x07A0, NES_ROOMGFX }, { 0x12386, 0x0199, NES_ROOMGFX }, { 0x1251F, 0x0947, NES_ROOMGFX }, { 0x12E66, 0x037A, NES_ROOMGFX }
+};
+static const ScummNESFile::Resource res_roomgfx_esp[40] = {
+ { 0x04001, 0x041B, NES_ROOMGFX }, { 0x0441C, 0x069E, NES_ROOMGFX }, { 0x04ABA, 0x0327, NES_ROOMGFX }, { 0x04DE1, 0x053B, NES_ROOMGFX }, { 0x0531C, 0x06BE, NES_ROOMGFX },
+ { 0x059DA, 0x0682, NES_ROOMGFX }, { 0x0605C, 0x0778, NES_ROOMGFX }, { 0x067D4, 0x0517, NES_ROOMGFX }, { 0x06CEB, 0x07FB, NES_ROOMGFX }, { 0x074E6, 0x07BE, NES_ROOMGFX },
+ { 0x08001, 0x07A5, NES_ROOMGFX }, { 0x087A6, 0x06DD, NES_ROOMGFX }, { 0x08E83, 0x04EA, NES_ROOMGFX }, { 0x0936D, 0x07E2, NES_ROOMGFX }, { 0x09B4F, 0x0791, NES_ROOMGFX },
+ { 0x0A2E0, 0x07B5, NES_ROOMGFX }, { 0x0AA95, 0x0515, NES_ROOMGFX }, { 0x0AFAA, 0x0799, NES_ROOMGFX }, { 0x0B743, 0x04B9, NES_ROOMGFX }, { 0x0BBFC, 0x0319, NES_ROOMGFX },
+ { 0x0C001, 0x0464, NES_ROOMGFX }, { 0x0C465, 0x072C, NES_ROOMGFX }, { 0x0CB91, 0x0827, NES_ROOMGFX }, { 0x0D3B8, 0x0515, NES_ROOMGFX }, { 0x0D8CD, 0x064E, NES_ROOMGFX },
+ { 0x0DF1B, 0x0775, NES_ROOMGFX }, { 0x0E690, 0x06DD, NES_ROOMGFX }, { 0x0ED6D, 0x0376, NES_ROOMGFX }, { 0x0F0E3, 0x05F7, NES_ROOMGFX }, { 0x0F6DA, 0x078D, NES_ROOMGFX },
+ { 0x07CA4, 0x02D6, NES_ROOMGFX }, { 0x10001, 0x06A3, NES_ROOMGFX }, { 0x106A4, 0x091F, NES_ROOMGFX }, { 0x10FC3, 0x0361, NES_ROOMGFX }, { 0x11324, 0x0489, NES_ROOMGFX },
+ { 0x117AD, 0x0437, NES_ROOMGFX }, { 0x11BE4, 0x086E, NES_ROOMGFX }, { 0x12452, 0x0199, NES_ROOMGFX }, { 0x125EB, 0x0947, NES_ROOMGFX }, { 0x12F32, 0x037A, NES_ROOMGFX }
+};
+
+static const ScummNESFile::Resource *res_roomgfx[ScummNESFile::kROMsetNum] = {
+ res_roomgfx_usa,
+ res_roomgfx_eur,
+ res_roomgfx_swe,
+ res_roomgfx_fra,
+ res_roomgfx_ger,
+ res_roomgfx_esp,
+};
+
+static const ScummNESFile::Resource res_costumegfx_usa[2] = { { 0x30001, 0x0EB8, NES_COSTUMEGFX }, { 0x2F9F1, 0x0340, NES_COSTUMEGFX } };
+static const ScummNESFile::Resource res_costumegfx_eur[2] = { { 0x30001, 0x0EB8, NES_COSTUMEGFX }, { 0x2F9F1, 0x0340, NES_COSTUMEGFX } };
+static const ScummNESFile::Resource res_costumegfx_swe[2] = { { 0x2EFE1, 0x0EB8, NES_COSTUMEGFX }, { 0x30001, 0x0340, NES_COSTUMEGFX } };
+static const ScummNESFile::Resource res_costumegfx_fra[2] = { { 0x30001, 0x0EB8, NES_COSTUMEGFX }, { 0x2F608, 0x0340, NES_COSTUMEGFX } };
+static const ScummNESFile::Resource res_costumegfx_ger[2] = { { 0x30001, 0x0EB8, NES_COSTUMEGFX }, { 0x2F4CE, 0x0340, NES_COSTUMEGFX } };
+static const ScummNESFile::Resource res_costumegfx_esp[2] = { { 0x30001, 0x0EB8, NES_COSTUMEGFX }, { 0x2F0F6, 0x0340, NES_COSTUMEGFX } };
+
+static const ScummNESFile::Resource *res_costumegfx[ScummNESFile::kROMsetNum] = {
+ res_costumegfx_usa,
+ res_costumegfx_eur,
+ res_costumegfx_swe,
+ res_costumegfx_fra,
+ res_costumegfx_ger,
+ res_costumegfx_esp,
+};
+
+static const ScummNESFile::Resource res_rooms_usa[55] = {
+ { 0x00000, 0x0000, NES_ROOM }, { 0x14001, 0x0D0C, NES_ROOM }, { 0x134A8, 0x04B3, NES_ROOM }, { 0x15397, 0x0849, NES_ROOM }, { 0x15C68, 0x0685, NES_ROOM },
+ { 0x16381, 0x0715, NES_ROOM }, { 0x1395B, 0x04E7, NES_ROOM }, { 0x16CE8, 0x0AC0, NES_ROOM }, { 0x18001, 0x06BA, NES_ROOM }, { 0x17AED, 0x03CB, NES_ROOM },
+ { 0x18BE7, 0x0663, NES_ROOM }, { 0x192A6, 0x0580, NES_ROOM }, { 0x19A44, 0x0443, NES_ROOM }, { 0x1A106, 0x0563, NES_ROOM }, { 0x1A669, 0x0446, NES_ROOM },
+ { 0x1AAAF, 0x03A7, NES_ROOM }, { 0x1AE56, 0x07E3, NES_ROOM }, { 0x1B699, 0x0692, NES_ROOM }, { 0x1C001, 0x0B49, NES_ROOM }, { 0x1CD09, 0x04C6, NES_ROOM },
+ { 0x1D4C2, 0x0568, NES_ROOM }, { 0x1DF6C, 0x0514, NES_ROOM }, { 0x1E8FA, 0x05CC, NES_ROOM }, { 0x1EF83, 0x0389, NES_ROOM }, { 0x1F5E4, 0x0723, NES_ROOM },
+ { 0x20001, 0x049A, NES_ROOM }, { 0x20511, 0x04F8, NES_ROOM }, { 0x21666, 0x05CB, NES_ROOM }, { 0x21DD6, 0x046B, NES_ROOM }, { 0x222F0, 0x0460, NES_ROOM },
+ { 0x227B6, 0x0909, NES_ROOM }, { 0x24001, 0x0366, NES_ROOM }, { 0x23BDF, 0x03CA, NES_ROOM }, { 0x247DB, 0x050D, NES_ROOM }, { 0x25ACF, 0x0346, NES_ROOM },
+ { 0x1BDBD, 0x01CA, NES_ROOM }, { 0x25E15, 0x0457, NES_ROOM }, { 0x2626C, 0x0547, NES_ROOM }, { 0x267B3, 0x064A, NES_ROOM }, { 0x1FD72, 0x024B, NES_ROOM },
+ { 0x2739A, 0x01FA, NES_ROOM }, { 0x2766D, 0x0219, NES_ROOM }, { 0x28001, 0x02F4, NES_ROOM }, { 0x284D6, 0x045C, NES_ROOM }, { 0x289A3, 0x09CF, NES_ROOM },
+ { 0x293C6, 0x05A0, NES_ROOM }, { 0x27B65, 0x0201, NES_ROOM }, { 0x2ADD1, 0x0325, NES_ROOM }, { 0x2B339, 0x01FC, NES_ROOM }, { 0x2B535, 0x02A9, NES_ROOM },
+ { 0x2B7DE, 0x02DE, NES_ROOM }, { 0x2C001, 0x03CE, NES_ROOM }, { 0x2BBC0, 0x0205, NES_ROOM }, { 0x2C53A, 0x0170, NES_ROOM }, { 0x13E42, 0x0169, NES_ROOM }
+};
+static const ScummNESFile::Resource res_rooms_eur[55] = {
+ { 0x00000, 0x0000, NES_ROOM }, { 0x14001, 0x0D0C, NES_ROOM }, { 0x13641, 0x04B3, NES_ROOM }, { 0x15397, 0x0849, NES_ROOM }, { 0x15C68, 0x0685, NES_ROOM },
+ { 0x16381, 0x0715, NES_ROOM }, { 0x16CE8, 0x04E7, NES_ROOM }, { 0x18001, 0x0ABF, NES_ROOM }, { 0x171CF, 0x06BA, NES_ROOM }, { 0x13AF4, 0x03D2, NES_ROOM },
+ { 0x18E1A, 0x0663, NES_ROOM }, { 0x194D9, 0x04A9, NES_ROOM }, { 0x19BA0, 0x0443, NES_ROOM }, { 0x1A262, 0x047C, NES_ROOM }, { 0x1A6DE, 0x0446, NES_ROOM },
+ { 0x1AB24, 0x03A7, NES_ROOM }, { 0x1AECB, 0x07E3, NES_ROOM }, { 0x1B70E, 0x0692, NES_ROOM }, { 0x1C001, 0x0ACA, NES_ROOM }, { 0x1CC8A, 0x04C6, NES_ROOM },
+ { 0x1D443, 0x0568, NES_ROOM }, { 0x1DEED, 0x0514, NES_ROOM }, { 0x1E87B, 0x05CC, NES_ROOM }, { 0x1EF04, 0x0389, NES_ROOM }, { 0x1F565, 0x0723, NES_ROOM },
+ { 0x20001, 0x049A, NES_ROOM }, { 0x20511, 0x04F8, NES_ROOM }, { 0x21666, 0x05D5, NES_ROOM }, { 0x21DE0, 0x046B, NES_ROOM }, { 0x222FA, 0x0460, NES_ROOM },
+ { 0x227C0, 0x0909, NES_ROOM }, { 0x24001, 0x0366, NES_ROOM }, { 0x247DB, 0x03CA, NES_ROOM }, { 0x24BA5, 0x050D, NES_ROOM }, { 0x23BE9, 0x0346, NES_ROOM },
+ { 0x17DB5, 0x01CA, NES_ROOM }, { 0x25E99, 0x0457, NES_ROOM }, { 0x262F0, 0x0547, NES_ROOM }, { 0x26837, 0x064A, NES_ROOM }, { 0x1FCF3, 0x024B, NES_ROOM },
+ { 0x2741E, 0x01FA, NES_ROOM }, { 0x276F1, 0x0219, NES_ROOM }, { 0x28001, 0x02F4, NES_ROOM }, { 0x284D6, 0x045C, NES_ROOM }, { 0x289A3, 0x09CF, NES_ROOM },
+ { 0x293C6, 0x05A0, NES_ROOM }, { 0x27BE9, 0x0201, NES_ROOM }, { 0x2ADE3, 0x0325, NES_ROOM }, { 0x2B34B, 0x01FC, NES_ROOM }, { 0x2B547, 0x02A9, NES_ROOM },
+ { 0x2B7F0, 0x02DE, NES_ROOM }, { 0x2C001, 0x03CE, NES_ROOM }, { 0x2BBD2, 0x0205, NES_ROOM }, { 0x2C53A, 0x0170, NES_ROOM }, { 0x2BDD7, 0x0169, NES_ROOM }
+};
+static const ScummNESFile::Resource res_rooms_swe[55] = {
+ { 0x00000, 0x0000, NES_ROOM }, { 0x14001, 0x0D12, NES_ROOM }, { 0x1328F, 0x04B3, NES_ROOM }, { 0x15367, 0x0859, NES_ROOM }, { 0x13742, 0x0694, NES_ROOM },
+ { 0x15C45, 0x0707, NES_ROOM }, { 0x1658F, 0x04E0, NES_ROOM }, { 0x16A6F, 0x0AC8, NES_ROOM }, { 0x18001, 0x06C7, NES_ROOM }, { 0x1789C, 0x03EA, NES_ROOM },
+ { 0x18C09, 0x0649, NES_ROOM }, { 0x192AE, 0x04AB, NES_ROOM }, { 0x19982, 0x0447, NES_ROOM }, { 0x1A04D, 0x047E, NES_ROOM }, { 0x1A4CB, 0x0444, NES_ROOM },
+ { 0x1A90F, 0x03B9, NES_ROOM }, { 0x1ACC8, 0x07E9, NES_ROOM }, { 0x1B511, 0x06A4, NES_ROOM }, { 0x1C001, 0x0B1A, NES_ROOM }, { 0x1CCFD, 0x0486, NES_ROOM },
+ { 0x1D482, 0x0579, NES_ROOM }, { 0x1DF61, 0x051E, NES_ROOM }, { 0x1E8EC, 0x05CF, NES_ROOM }, { 0x1EF73, 0x0398, NES_ROOM }, { 0x1F5F0, 0x071A, NES_ROOM },
+ { 0x20001, 0x049C, NES_ROOM }, { 0x2051E, 0x051E, NES_ROOM }, { 0x21725, 0x05D5, NES_ROOM }, { 0x21EA5, 0x047F, NES_ROOM }, { 0x223D1, 0x0460, NES_ROOM },
+ { 0x22897, 0x090D, NES_ROOM }, { 0x24001, 0x0378, NES_ROOM }, { 0x247C9, 0x03CA, NES_ROOM }, { 0x24B93, 0x050D, NES_ROOM }, { 0x25267, 0x0346, NES_ROOM },
+ { 0x17CD0, 0x01CA, NES_ROOM }, { 0x255AD, 0x0453, NES_ROOM }, { 0x25A00, 0x053E, NES_ROOM }, { 0x25F3E, 0x0647, NES_ROOM }, { 0x1BC49, 0x024B, NES_ROOM },
+ { 0x26B58, 0x01FA, NES_ROOM }, { 0x26E27, 0x0217, NES_ROOM }, { 0x27345, 0x02F4, NES_ROOM }, { 0x27829, 0x045C, NES_ROOM }, { 0x28001, 0x098A, NES_ROOM },
+ { 0x289DF, 0x05A1, NES_ROOM }, { 0x2A442, 0x0201, NES_ROOM }, { 0x2A6E9, 0x0325, NES_ROOM }, { 0x1FD75, 0x01FC, NES_ROOM }, { 0x2AC64, 0x02A9, NES_ROOM },
+ { 0x2AF0D, 0x02D1, NES_ROOM }, { 0x2B2E6, 0x03CC, NES_ROOM }, { 0x23D61, 0x0205, NES_ROOM }, { 0x2B818, 0x0168, NES_ROOM }, { 0x27CF6, 0x0169, NES_ROOM }
+};
+static const ScummNESFile::Resource res_rooms_fra[55] = {
+ { 0x00000, 0x0000, NES_ROOM }, { 0x14001, 0x0D76, NES_ROOM }, { 0x1328A, 0x04C6, NES_ROOM }, { 0x15451, 0x0885, NES_ROOM }, { 0x13750, 0x0693, NES_ROOM },
+ { 0x15D68, 0x0709, NES_ROOM }, { 0x166D4, 0x0528, NES_ROOM }, { 0x16BFC, 0x0ACC, NES_ROOM }, { 0x18001, 0x06E2, NES_ROOM }, { 0x17A63, 0x03E5, NES_ROOM },
+ { 0x18C3B, 0x066A, NES_ROOM }, { 0x19301, 0x049E, NES_ROOM }, { 0x199C8, 0x044B, NES_ROOM }, { 0x1A0B1, 0x0478, NES_ROOM }, { 0x1A529, 0x043F, NES_ROOM },
+ { 0x1A968, 0x03C8, NES_ROOM }, { 0x1AD30, 0x086F, NES_ROOM }, { 0x1B5FF, 0x069B, NES_ROOM }, { 0x1C001, 0x0AA9, NES_ROOM }, { 0x1CC97, 0x049E, NES_ROOM },
+ { 0x1D42C, 0x05A8, NES_ROOM }, { 0x1DF71, 0x054E, NES_ROOM }, { 0x1E9D1, 0x0606, NES_ROOM }, { 0x1F0A2, 0x039A, NES_ROOM }, { 0x1F74E, 0x071C, NES_ROOM },
+ { 0x20001, 0x04B5, NES_ROOM }, { 0x2052E, 0x04FF, NES_ROOM }, { 0x2172E, 0x05DB, NES_ROOM }, { 0x21EAD, 0x0489, NES_ROOM }, { 0x223E1, 0x0465, NES_ROOM },
+ { 0x228AC, 0x0957, NES_ROOM }, { 0x24001, 0x037E, NES_ROOM }, { 0x2481A, 0x03CA, NES_ROOM }, { 0x24BE4, 0x050D, NES_ROOM }, { 0x252C0, 0x0346, NES_ROOM },
+ { 0x1BD30, 0x01CA, NES_ROOM }, { 0x25606, 0x046D, NES_ROOM }, { 0x25A73, 0x055A, NES_ROOM }, { 0x25FCD, 0x0654, NES_ROOM }, { 0x26C98, 0x024B, NES_ROOM },
+ { 0x26EE3, 0x01FA, NES_ROOM }, { 0x271DD, 0x0217, NES_ROOM }, { 0x27713, 0x02F4, NES_ROOM }, { 0x28001, 0x045C, NES_ROOM }, { 0x284CE, 0x0975, NES_ROOM },
+ { 0x28E97, 0x05E6, NES_ROOM }, { 0x27C3A, 0x0201, NES_ROOM }, { 0x2A9D6, 0x0325, NES_ROOM }, { 0x2AF88, 0x01FC, NES_ROOM }, { 0x2B184, 0x02A9, NES_ROOM },
+ { 0x2B42D, 0x02DF, NES_ROOM }, { 0x2B818, 0x03EC, NES_ROOM }, { 0x2BD67, 0x0209, NES_ROOM }, { 0x2C001, 0x0168, NES_ROOM }, { 0x2C4BF, 0x0169, NES_ROOM }
+};
+static const ScummNESFile::Resource res_rooms_ger[55] = {
+ { 0x00000, 0x0000, NES_ROOM }, { 0x14001, 0x0D63, NES_ROOM }, { 0x131E0, 0x04A9, NES_ROOM }, { 0x13689, 0x086B, NES_ROOM }, { 0x15421, 0x06A8, NES_ROOM },
+ { 0x15B5D, 0x0731, NES_ROOM }, { 0x16507, 0x0501, NES_ROOM }, { 0x16A08, 0x0AE9, NES_ROOM }, { 0x18001, 0x06DA, NES_ROOM }, { 0x17880, 0x03D0, NES_ROOM },
+ { 0x18C7B, 0x0651, NES_ROOM }, { 0x19328, 0x04A7, NES_ROOM }, { 0x199FE, 0x0447, NES_ROOM }, { 0x1A0F1, 0x0486, NES_ROOM }, { 0x1A577, 0x045D, NES_ROOM },
+ { 0x1A9D4, 0x03AE, NES_ROOM }, { 0x1AD82, 0x0840, NES_ROOM }, { 0x1B622, 0x06C3, NES_ROOM }, { 0x1C001, 0x0B07, NES_ROOM }, { 0x1CD05, 0x0494, NES_ROOM },
+ { 0x1D4A5, 0x05AC, NES_ROOM }, { 0x1DFD6, 0x0524, NES_ROOM }, { 0x1E9C0, 0x05F7, NES_ROOM }, { 0x1F09A, 0x038E, NES_ROOM }, { 0x1F75F, 0x0733, NES_ROOM },
+ { 0x20001, 0x04A9, NES_ROOM }, { 0x2052A, 0x052E, NES_ROOM }, { 0x2177C, 0x0621, NES_ROOM }, { 0x21F57, 0x0495, NES_ROOM }, { 0x2249A, 0x045E, NES_ROOM },
+ { 0x2295E, 0x0951, NES_ROOM }, { 0x24001, 0x036E, NES_ROOM }, { 0x247F9, 0x03CA, NES_ROOM }, { 0x24BC3, 0x050D, NES_ROOM }, { 0x252A8, 0x0346, NES_ROOM },
+ { 0x17CA2, 0x01CA, NES_ROOM }, { 0x255EE, 0x046F, NES_ROOM }, { 0x25A5D, 0x054D, NES_ROOM }, { 0x25FAA, 0x064B, NES_ROOM }, { 0x26BE2, 0x024B, NES_ROOM },
+ { 0x26E2D, 0x01FA, NES_ROOM }, { 0x2710F, 0x0217, NES_ROOM }, { 0x27663, 0x02F4, NES_ROOM }, { 0x28001, 0x045C, NES_ROOM }, { 0x284CE, 0x0A8F, NES_ROOM },
+ { 0x28FB1, 0x05FF, NES_ROOM }, { 0x27B69, 0x0201, NES_ROOM }, { 0x2AAA9, 0x0325, NES_ROOM }, { 0x1BD7C, 0x01FC, NES_ROOM }, { 0x2B031, 0x02A9, NES_ROOM },
+ { 0x2B2DA, 0x02D8, NES_ROOM }, { 0x2B6D2, 0x03D2, NES_ROOM }, { 0x2BC0D, 0x020D, NES_ROOM }, { 0x2C001, 0x0168, NES_ROOM }, { 0x27E11, 0x0169, NES_ROOM }
+};
+static const ScummNESFile::Resource res_rooms_esp[55] = {
+ { 0x00000, 0x0000, NES_ROOM }, { 0x14001, 0x0D05, NES_ROOM }, { 0x132AC, 0x04B0, NES_ROOM }, { 0x153AB, 0x087B, NES_ROOM }, { 0x1375C, 0x06B3, NES_ROOM },
+ { 0x15CB1, 0x0729, NES_ROOM }, { 0x16625, 0x04F0, NES_ROOM }, { 0x16B15, 0x0AD4, NES_ROOM }, { 0x18001, 0x06ED, NES_ROOM }, { 0x17936, 0x03DE, NES_ROOM },
+ { 0x18C3E, 0x0671, NES_ROOM }, { 0x1930B, 0x04C4, NES_ROOM }, { 0x199EC, 0x0452, NES_ROOM }, { 0x1A0DA, 0x048F, NES_ROOM }, { 0x1A569, 0x0449, NES_ROOM },
+ { 0x1A9B2, 0x03A8, NES_ROOM }, { 0x1AD5A, 0x0846, NES_ROOM }, { 0x1B600, 0x0686, NES_ROOM }, { 0x1C001, 0x0B58, NES_ROOM }, { 0x1CD42, 0x049C, NES_ROOM },
+ { 0x1D4ED, 0x0586, NES_ROOM }, { 0x1DFE9, 0x0526, NES_ROOM }, { 0x1E9C9, 0x05CE, NES_ROOM }, { 0x1F04B, 0x0390, NES_ROOM }, { 0x1F6CA, 0x073C, NES_ROOM },
+ { 0x20001, 0x04CB, NES_ROOM }, { 0x20543, 0x0530, NES_ROOM }, { 0x2171B, 0x05FC, NES_ROOM }, { 0x21EBE, 0x0470, NES_ROOM }, { 0x223DC, 0x045C, NES_ROOM },
+ { 0x2289E, 0x0928, NES_ROOM }, { 0x24001, 0x036C, NES_ROOM }, { 0x247EC, 0x03CA, NES_ROOM }, { 0x24BB6, 0x050D, NES_ROOM }, { 0x25283, 0x0346, NES_ROOM },
+ { 0x17D60, 0x01CA, NES_ROOM }, { 0x255C9, 0x0462, NES_ROOM }, { 0x25A2B, 0x055C, NES_ROOM }, { 0x25F87, 0x0659, NES_ROOM }, { 0x1BD19, 0x024B, NES_ROOM },
+ { 0x26B8A, 0x01F7, NES_ROOM }, { 0x26E5D, 0x0217, NES_ROOM }, { 0x2736A, 0x02F4, NES_ROOM }, { 0x27845, 0x045C, NES_ROOM }, { 0x28001, 0x0969, NES_ROOM },
+ { 0x289BE, 0x058E, NES_ROOM }, { 0x2A418, 0x0201, NES_ROOM }, { 0x2A6BE, 0x0325, NES_ROOM }, { 0x23D84, 0x01FC, NES_ROOM }, { 0x2AC46, 0x02A9, NES_ROOM },
+ { 0x2AEEF, 0x02C9, NES_ROOM }, { 0x2B2C0, 0x03D2, NES_ROOM }, { 0x27D12, 0x0207, NES_ROOM }, { 0x2B7FC, 0x0168, NES_ROOM }, { 0x2BD06, 0x0169, NES_ROOM }
+};
+
+static const ScummNESFile::Resource *res_rooms[ScummNESFile::kROMsetNum] = {
+ res_rooms_usa,
+ res_rooms_eur,
+ res_rooms_swe,
+ res_rooms_fra,
+ res_rooms_ger,
+ res_rooms_esp,
+};
+
+static const ScummNESFile::Resource res_scripts_usa[179] = {
+ { 0x00000, 0x0000, NES_SCRIPT }, { 0x29966, 0x044D, NES_SCRIPT }, { 0x29DB3, 0x0207, NES_SCRIPT }, { 0x29FBA, 0x009F, NES_SCRIPT }, { 0x2A059, 0x03F4, NES_SCRIPT },
+ { 0x2A44D, 0x01A1, NES_SCRIPT }, { 0x00000, 0x0000, NES_SCRIPT }, { 0x2A5EE, 0x004A, NES_SCRIPT }, { 0x00000, 0x0000, NES_SCRIPT }, { 0x2A638, 0x0005, NES_SCRIPT },
+ { 0x2C6AA, 0x000D, NES_SCRIPT }, { 0x2C6B7, 0x000D, NES_SCRIPT }, { 0x186BB, 0x0040, NES_SCRIPT }, { 0x186FB, 0x0016, NES_SCRIPT }, { 0x1B639, 0x0046, NES_SCRIPT },
+ { 0x1EEC6, 0x00BD, NES_SCRIPT }, { 0x21C31, 0x0055, NES_SCRIPT }, { 0x177A8, 0x0027, NES_SCRIPT }, { 0x1FD07, 0x0027, NES_SCRIPT }, { 0x1FD2E, 0x0027, NES_SCRIPT },
+ { 0x1BD2B, 0x0022, NES_SCRIPT }, { 0x15BE0, 0x0088, NES_SCRIPT }, { 0x22241, 0x0020, NES_SCRIPT }, { 0x22261, 0x008F, NES_SCRIPT }, { 0x1924A, 0x002B, NES_SCRIPT },
+ { 0x1CB4A, 0x0061, NES_SCRIPT }, { 0x1CBAB, 0x003C, NES_SCRIPT }, { 0x1CBE7, 0x0042, NES_SCRIPT }, { 0x1CC29, 0x004F, NES_SCRIPT }, { 0x2049B, 0x0076, NES_SCRIPT },
+ { 0x16A96, 0x0035, NES_SCRIPT }, { 0x16ACB, 0x001C, NES_SCRIPT }, { 0x16AE7, 0x0014, NES_SCRIPT }, { 0x16AFB, 0x001C, NES_SCRIPT }, { 0x16B17, 0x0027, NES_SCRIPT },
+ { 0x16B3E, 0x01AA, NES_SCRIPT }, { 0x1D1CF, 0x0096, NES_SCRIPT }, { 0x1D265, 0x010E, NES_SCRIPT }, { 0x1D373, 0x001C, NES_SCRIPT }, { 0x1D38F, 0x0056, NES_SCRIPT },
+ { 0x1D3E5, 0x0072, NES_SCRIPT }, { 0x1E480, 0x0028, NES_SCRIPT }, { 0x1E4A8, 0x017D, NES_SCRIPT }, { 0x1E625, 0x0229, NES_SCRIPT }, { 0x28932, 0x0071, NES_SCRIPT },
+ { 0x17EB8, 0x004D, NES_SCRIPT }, { 0x162ED, 0x0039, NES_SCRIPT }, { 0x18711, 0x028B, NES_SCRIPT }, { 0x1899C, 0x00BB, NES_SCRIPT }, { 0x18A57, 0x018B, NES_SCRIPT },
+ { 0x00000, 0x0000, NES_SCRIPT }, { 0x19E87, 0x00ED, NES_SCRIPT }, { 0x21C86, 0x00F6, NES_SCRIPT }, { 0x1E84E, 0x009B, NES_SCRIPT }, { 0x21D7C, 0x0047, NES_SCRIPT },
+ { 0x2C6C4, 0x004D, NES_SCRIPT }, { 0x16326, 0x0024, NES_SCRIPT }, { 0x14D0D, 0x0014, NES_SCRIPT }, { 0x177CF, 0x0059, NES_SCRIPT }, { 0x17828, 0x0109, NES_SCRIPT },
+ { 0x17931, 0x0009, NES_SCRIPT }, { 0x14D21, 0x01B6, NES_SCRIPT }, { 0x2B0F6, 0x0243, NES_SCRIPT }, { 0x230BF, 0x067F, NES_SCRIPT }, { 0x2C711, 0x001C, NES_SCRIPT },
+ { 0x2C72D, 0x001A, NES_SCRIPT }, { 0x2C747, 0x0021, NES_SCRIPT }, { 0x2C768, 0x0024, NES_SCRIPT }, { 0x2C78C, 0x0017, NES_SCRIPT }, { 0x2C7A3, 0x0017, NES_SCRIPT },
+ { 0x2C7BA, 0x0014, NES_SCRIPT }, { 0x2C7CE, 0x0024, NES_SCRIPT }, { 0x00000, 0x0000, NES_SCRIPT }, { 0x2C7F2, 0x0011, NES_SCRIPT }, { 0x1793A, 0x009D, NES_SCRIPT },
+ { 0x22750, 0x0066, NES_SCRIPT }, { 0x14ED7, 0x0075, NES_SCRIPT }, { 0x1F30C, 0x0120, NES_SCRIPT }, { 0x1FD55, 0x001D, NES_SCRIPT }, { 0x1F42C, 0x008F, NES_SCRIPT },
+ { 0x1F4BB, 0x0097, NES_SCRIPT }, { 0x179D7, 0x006A, NES_SCRIPT }, { 0x17A41, 0x0030, NES_SCRIPT }, { 0x1F552, 0x0092, NES_SCRIPT }, { 0x2C803, 0x00CC, NES_SCRIPT },
+ { 0x2C8CF, 0x00BA, NES_SCRIPT }, { 0x2C989, 0x0088, NES_SCRIPT }, { 0x20A09, 0x01B0, NES_SCRIPT }, { 0x20BB9, 0x0168, NES_SCRIPT }, { 0x20D21, 0x006C, NES_SCRIPT },
+ { 0x20D8D, 0x0037, NES_SCRIPT }, { 0x20DC4, 0x00E4, NES_SCRIPT }, { 0x20EA8, 0x0045, NES_SCRIPT }, { 0x20EED, 0x00E1, NES_SCRIPT }, { 0x20FCE, 0x00F6, NES_SCRIPT },
+ { 0x210C4, 0x0141, NES_SCRIPT }, { 0x21205, 0x0183, NES_SCRIPT }, { 0x21388, 0x0034, NES_SCRIPT }, { 0x213BC, 0x00A9, NES_SCRIPT }, { 0x24367, 0x011B, NES_SCRIPT },
+ { 0x1BD4D, 0x0070, NES_SCRIPT }, { 0x1CC78, 0x0091, NES_SCRIPT }, { 0x29372, 0x0054, NES_SCRIPT }, { 0x19F74, 0x00CE, NES_SCRIPT }, { 0x1A042, 0x0077, NES_SCRIPT },
+ { 0x14F4C, 0x0057, NES_SCRIPT }, { 0x27886, 0x02DF, NES_SCRIPT }, { 0x1DA2A, 0x0219, NES_SCRIPT }, { 0x1DC43, 0x00F9, NES_SCRIPT }, { 0x1DD3C, 0x0056, NES_SCRIPT },
+ { 0x1DD92, 0x01C2, NES_SCRIPT }, { 0x14FA3, 0x004D, NES_SCRIPT }, { 0x27594, 0x00D9, NES_SCRIPT }, { 0x21DC3, 0x0013, NES_SCRIPT }, { 0x2A63D, 0x00F0, NES_SCRIPT },
+ { 0x24482, 0x00E7, NES_SCRIPT }, { 0x21465, 0x00F2, NES_SCRIPT }, { 0x24569, 0x002B, NES_SCRIPT }, { 0x2C3CF, 0x010F, NES_SCRIPT }, { 0x24594, 0x00AA, NES_SCRIPT },
+ { 0x24CE8, 0x0DAB, NES_SCRIPT }, { 0x1B67F, 0x000D, NES_SCRIPT }, { 0x1B68C, 0x000D, NES_SCRIPT }, { 0x2373E, 0x017C, NES_SCRIPT }, { 0x282F5, 0x01E1, NES_SCRIPT },
+ { 0x238BA, 0x0153, NES_SCRIPT }, { 0x23A0D, 0x019C, NES_SCRIPT }, { 0x23BA9, 0x0016, NES_SCRIPT }, { 0x2C4DE, 0x005C, NES_SCRIPT }, { 0x23BBF, 0x0020, NES_SCRIPT },
+ { 0x27D66, 0x00A5, NES_SCRIPT }, { 0x2A72D, 0x034D, NES_SCRIPT }, { 0x14FF0, 0x00E3, NES_SCRIPT }, { 0x2BABC, 0x005F, NES_SCRIPT }, { 0x00000, 0x0000, NES_SCRIPT },
+ { 0x25A93, 0x003C, NES_SCRIPT }, { 0x1E8E9, 0x0011, NES_SCRIPT }, { 0x1634A, 0x0018, NES_SCRIPT }, { 0x26DFD, 0x001F, NES_SCRIPT }, { 0x26E1C, 0x0054, NES_SCRIPT },
+ { 0x26E70, 0x0149, NES_SCRIPT }, { 0x26FB9, 0x004B, NES_SCRIPT }, { 0x27004, 0x017D, NES_SCRIPT }, { 0x27181, 0x0027, NES_SCRIPT }, { 0x271A8, 0x0041, NES_SCRIPT },
+ { 0x271E9, 0x01B1, NES_SCRIPT }, { 0x16362, 0x001F, NES_SCRIPT }, { 0x2463E, 0x002A, NES_SCRIPT }, { 0x150D3, 0x019E, NES_SCRIPT }, { 0x19275, 0x0031, NES_SCRIPT },
+ { 0x17A71, 0x007C, NES_SCRIPT }, { 0x21557, 0x00DC, NES_SCRIPT }, { 0x1D457, 0x0018, NES_SCRIPT }, { 0x1D46F, 0x0053, NES_SCRIPT }, { 0x18BE2, 0x0005, NES_SCRIPT },
+ { 0x15271, 0x011B, NES_SCRIPT }, { 0x1538C, 0x000B, NES_SCRIPT }, { 0x24668, 0x0138, NES_SCRIPT }, { 0x247A0, 0x0014, NES_SCRIPT }, { 0x1DF54, 0x0018, NES_SCRIPT },
+ { 0x247B4, 0x0027, NES_SCRIPT }, { 0x1A0B9, 0x004D, NES_SCRIPT }, { 0x00000, 0x0000, NES_SCRIPT }, { 0x2BB1B, 0x00A5, NES_SCRIPT }, { 0x2AA7A, 0x00C1, NES_SCRIPT },
+ { 0x2AB3B, 0x0140, NES_SCRIPT }, { 0x19826, 0x00BF, NES_SCRIPT }, { 0x198E5, 0x014D, NES_SCRIPT }, { 0x19A32, 0x0012, NES_SCRIPT }, { 0x2AC7B, 0x0005, NES_SCRIPT },
+ { 0x2AC80, 0x0005, NES_SCRIPT }, { 0x2AC85, 0x0005, NES_SCRIPT }, { 0x2AC8A, 0x0005, NES_SCRIPT }, { 0x2AC8F, 0x0005, NES_SCRIPT }, { 0x21633, 0x0033, NES_SCRIPT },
+ { 0x2AC94, 0x0005, NES_SCRIPT }, { 0x00000, 0x0000, NES_SCRIPT }, { 0x2AC99, 0x009C, NES_SCRIPT }, { 0x2AD35, 0x009C, NES_SCRIPT }
+};
+static const ScummNESFile::Resource res_scripts_eur[179] = {
+ { 0x00000, 0x0000, NES_SCRIPT }, { 0x29966, 0x044D, NES_SCRIPT }, { 0x29DB3, 0x0207, NES_SCRIPT }, { 0x29FBA, 0x009F, NES_SCRIPT }, { 0x2A059, 0x03F4, NES_SCRIPT },
+ { 0x2A44D, 0x01A1, NES_SCRIPT }, { 0x00000, 0x0000, NES_SCRIPT }, { 0x2A5EE, 0x005C, NES_SCRIPT }, { 0x00000, 0x0000, NES_SCRIPT }, { 0x2A64A, 0x0005, NES_SCRIPT },
+ { 0x2C6AA, 0x000D, NES_SCRIPT }, { 0x2C6B7, 0x000D, NES_SCRIPT }, { 0x17889, 0x0040, NES_SCRIPT }, { 0x178C9, 0x0016, NES_SCRIPT }, { 0x1B6AE, 0x0046, NES_SCRIPT },
+ { 0x1EE47, 0x00BD, NES_SCRIPT }, { 0x21C3B, 0x0055, NES_SCRIPT }, { 0x18AC0, 0x0027, NES_SCRIPT }, { 0x1FC88, 0x0027, NES_SCRIPT }, { 0x1FCAF, 0x0027, NES_SCRIPT },
+ { 0x1BDA0, 0x0022, NES_SCRIPT }, { 0x15BE0, 0x0088, NES_SCRIPT }, { 0x2224B, 0x0020, NES_SCRIPT }, { 0x2226B, 0x008F, NES_SCRIPT }, { 0x1947D, 0x002B, NES_SCRIPT },
+ { 0x1CACB, 0x0061, NES_SCRIPT }, { 0x1CB2C, 0x003C, NES_SCRIPT }, { 0x1CB68, 0x0042, NES_SCRIPT }, { 0x1CBAA, 0x004F, NES_SCRIPT }, { 0x2049B, 0x0076, NES_SCRIPT },
+ { 0x16A96, 0x0035, NES_SCRIPT }, { 0x16ACB, 0x001C, NES_SCRIPT }, { 0x16AE7, 0x0014, NES_SCRIPT }, { 0x16AFB, 0x001C, NES_SCRIPT }, { 0x16B17, 0x0027, NES_SCRIPT },
+ { 0x16B3E, 0x01AA, NES_SCRIPT }, { 0x1D150, 0x0096, NES_SCRIPT }, { 0x1D1E6, 0x010E, NES_SCRIPT }, { 0x1D2F4, 0x001C, NES_SCRIPT }, { 0x1D310, 0x0056, NES_SCRIPT },
+ { 0x1D366, 0x0072, NES_SCRIPT }, { 0x1E401, 0x0028, NES_SCRIPT }, { 0x1E429, 0x017D, NES_SCRIPT }, { 0x1E5A6, 0x0229, NES_SCRIPT }, { 0x28932, 0x0071, NES_SCRIPT },
+ { 0x13EC6, 0x004D, NES_SCRIPT }, { 0x162ED, 0x0039, NES_SCRIPT }, { 0x178DF, 0x028B, NES_SCRIPT }, { 0x17B6A, 0x00BB, NES_SCRIPT }, { 0x17C25, 0x018B, NES_SCRIPT },
+ { 0x00000, 0x0000, NES_SCRIPT }, { 0x19FE3, 0x00ED, NES_SCRIPT }, { 0x21C90, 0x00F6, NES_SCRIPT }, { 0x1E7CF, 0x009B, NES_SCRIPT }, { 0x21D86, 0x0047, NES_SCRIPT },
+ { 0x2C6C4, 0x004D, NES_SCRIPT }, { 0x16326, 0x0024, NES_SCRIPT }, { 0x14D0D, 0x0014, NES_SCRIPT }, { 0x18AE7, 0x0059, NES_SCRIPT }, { 0x18B40, 0x011E, NES_SCRIPT },
+ { 0x18C5E, 0x0009, NES_SCRIPT }, { 0x14D21, 0x01B6, NES_SCRIPT }, { 0x2B108, 0x0243, NES_SCRIPT }, { 0x230C9, 0x067F, NES_SCRIPT }, { 0x2C711, 0x001C, NES_SCRIPT },
+ { 0x2C72D, 0x001A, NES_SCRIPT }, { 0x2C747, 0x0021, NES_SCRIPT }, { 0x2C768, 0x0024, NES_SCRIPT }, { 0x2C78C, 0x0017, NES_SCRIPT }, { 0x2C7A3, 0x0017, NES_SCRIPT },
+ { 0x2C7BA, 0x0014, NES_SCRIPT }, { 0x2C7CE, 0x0024, NES_SCRIPT }, { 0x00000, 0x0000, NES_SCRIPT }, { 0x2C7F2, 0x0011, NES_SCRIPT }, { 0x18C67, 0x009D, NES_SCRIPT },
+ { 0x2275A, 0x0066, NES_SCRIPT }, { 0x14ED7, 0x0075, NES_SCRIPT }, { 0x1F28D, 0x0120, NES_SCRIPT }, { 0x1FCD6, 0x001D, NES_SCRIPT }, { 0x1F3AD, 0x008F, NES_SCRIPT },
+ { 0x1F43C, 0x0097, NES_SCRIPT }, { 0x18D04, 0x006A, NES_SCRIPT }, { 0x18D6E, 0x0030, NES_SCRIPT }, { 0x1F4D3, 0x0092, NES_SCRIPT }, { 0x2C803, 0x00CC, NES_SCRIPT },
+ { 0x2C8CF, 0x00BA, NES_SCRIPT }, { 0x2C989, 0x0088, NES_SCRIPT }, { 0x20A09, 0x01B0, NES_SCRIPT }, { 0x20BB9, 0x0168, NES_SCRIPT }, { 0x20D21, 0x006C, NES_SCRIPT },
+ { 0x20D8D, 0x0037, NES_SCRIPT }, { 0x20DC4, 0x00E4, NES_SCRIPT }, { 0x20EA8, 0x0045, NES_SCRIPT }, { 0x20EED, 0x00E1, NES_SCRIPT }, { 0x20FCE, 0x00F6, NES_SCRIPT },
+ { 0x210C4, 0x0141, NES_SCRIPT }, { 0x21205, 0x0183, NES_SCRIPT }, { 0x21388, 0x0034, NES_SCRIPT }, { 0x213BC, 0x00A9, NES_SCRIPT }, { 0x24367, 0x011B, NES_SCRIPT },
+ { 0x1BDC2, 0x0070, NES_SCRIPT }, { 0x1CBF9, 0x0091, NES_SCRIPT }, { 0x29372, 0x0054, NES_SCRIPT }, { 0x1A0D0, 0x00CE, NES_SCRIPT }, { 0x1A19E, 0x0077, NES_SCRIPT },
+ { 0x14F4C, 0x0057, NES_SCRIPT }, { 0x2790A, 0x02DF, NES_SCRIPT }, { 0x1D9AB, 0x0219, NES_SCRIPT }, { 0x1DBC4, 0x00F9, NES_SCRIPT }, { 0x1DCBD, 0x0056, NES_SCRIPT },
+ { 0x1DD13, 0x01C2, NES_SCRIPT }, { 0x14FA3, 0x004D, NES_SCRIPT }, { 0x27618, 0x00D9, NES_SCRIPT }, { 0x21DCD, 0x0013, NES_SCRIPT }, { 0x2A64F, 0x00F0, NES_SCRIPT },
+ { 0x24482, 0x00E7, NES_SCRIPT }, { 0x21465, 0x00F2, NES_SCRIPT }, { 0x24569, 0x002B, NES_SCRIPT }, { 0x2C3CF, 0x010F, NES_SCRIPT }, { 0x24594, 0x00AA, NES_SCRIPT },
+ { 0x250B2, 0x0DAB, NES_SCRIPT }, { 0x1B6F4, 0x000D, NES_SCRIPT }, { 0x1B701, 0x000D, NES_SCRIPT }, { 0x23748, 0x017C, NES_SCRIPT }, { 0x282F5, 0x01E1, NES_SCRIPT },
+ { 0x238C4, 0x0153, NES_SCRIPT }, { 0x23A17, 0x019C, NES_SCRIPT }, { 0x23BB3, 0x0016, NES_SCRIPT }, { 0x2C4DE, 0x005C, NES_SCRIPT }, { 0x23BC9, 0x0020, NES_SCRIPT },
+ { 0x27DEA, 0x00A5, NES_SCRIPT }, { 0x2A73F, 0x034D, NES_SCRIPT }, { 0x14FF0, 0x00E3, NES_SCRIPT }, { 0x2BACE, 0x005F, NES_SCRIPT }, { 0x00000, 0x0000, NES_SCRIPT },
+ { 0x25E5D, 0x003C, NES_SCRIPT }, { 0x1E86A, 0x0011, NES_SCRIPT }, { 0x1634A, 0x0018, NES_SCRIPT }, { 0x26E81, 0x001F, NES_SCRIPT }, { 0x26EA0, 0x0054, NES_SCRIPT },
+ { 0x26EF4, 0x0149, NES_SCRIPT }, { 0x2703D, 0x004B, NES_SCRIPT }, { 0x27088, 0x017D, NES_SCRIPT }, { 0x27205, 0x0027, NES_SCRIPT }, { 0x2722C, 0x0041, NES_SCRIPT },
+ { 0x2726D, 0x01B1, NES_SCRIPT }, { 0x16362, 0x001F, NES_SCRIPT }, { 0x2463E, 0x002A, NES_SCRIPT }, { 0x150D3, 0x019E, NES_SCRIPT }, { 0x194A8, 0x0031, NES_SCRIPT },
+ { 0x18D9E, 0x007C, NES_SCRIPT }, { 0x21557, 0x00DC, NES_SCRIPT }, { 0x1D3D8, 0x0018, NES_SCRIPT }, { 0x1D3F0, 0x0053, NES_SCRIPT }, { 0x17DB0, 0x0005, NES_SCRIPT },
+ { 0x15271, 0x011B, NES_SCRIPT }, { 0x1538C, 0x000B, NES_SCRIPT }, { 0x24668, 0x0138, NES_SCRIPT }, { 0x247A0, 0x0014, NES_SCRIPT }, { 0x1DED5, 0x0018, NES_SCRIPT },
+ { 0x247B4, 0x0027, NES_SCRIPT }, { 0x1A215, 0x004D, NES_SCRIPT }, { 0x00000, 0x0000, NES_SCRIPT }, { 0x2BB2D, 0x00A5, NES_SCRIPT }, { 0x2AA8C, 0x00C1, NES_SCRIPT },
+ { 0x2AB4D, 0x0140, NES_SCRIPT }, { 0x19982, 0x00BF, NES_SCRIPT }, { 0x19A41, 0x014D, NES_SCRIPT }, { 0x19B8E, 0x0012, NES_SCRIPT }, { 0x2AC8D, 0x0005, NES_SCRIPT },
+ { 0x2AC92, 0x0005, NES_SCRIPT }, { 0x2AC97, 0x0005, NES_SCRIPT }, { 0x2AC9C, 0x0005, NES_SCRIPT }, { 0x2ACA1, 0x0005, NES_SCRIPT }, { 0x21633, 0x0033, NES_SCRIPT },
+ { 0x2ACA6, 0x0005, NES_SCRIPT }, { 0x00000, 0x0000, NES_SCRIPT }, { 0x2ACAB, 0x009C, NES_SCRIPT }, { 0x2AD47, 0x009C, NES_SCRIPT }
+};
+static const ScummNESFile::Resource res_scripts_swe[179] = {
+ { 0x00000, 0x0000, NES_SCRIPT }, { 0x28F80, 0x043B, NES_SCRIPT }, { 0x293BB, 0x0209, NES_SCRIPT }, { 0x295C4, 0x00AB, NES_SCRIPT }, { 0x2966F, 0x03FD, NES_SCRIPT },
+ { 0x29A6C, 0x01A1, NES_SCRIPT }, { 0x00000, 0x0000, NES_SCRIPT }, { 0x29C0D, 0x005C, NES_SCRIPT }, { 0x00000, 0x0000, NES_SCRIPT }, { 0x29C69, 0x0005, NES_SCRIPT },
+ { 0x2B980, 0x000D, NES_SCRIPT }, { 0x2B98D, 0x000D, NES_SCRIPT }, { 0x186C8, 0x0040, NES_SCRIPT }, { 0x18708, 0x0016, NES_SCRIPT }, { 0x1B4B1, 0x0046, NES_SCRIPT },
+ { 0x1EEBB, 0x00B8, NES_SCRIPT }, { 0x21CFA, 0x005C, NES_SCRIPT }, { 0x17537, 0x0027, NES_SCRIPT }, { 0x1FD0A, 0x0027, NES_SCRIPT }, { 0x1FD31, 0x0027, NES_SCRIPT },
+ { 0x1BBB5, 0x0022, NES_SCRIPT }, { 0x15BC0, 0x0085, NES_SCRIPT }, { 0x22324, 0x001E, NES_SCRIPT }, { 0x22342, 0x008F, NES_SCRIPT }, { 0x19252, 0x002B, NES_SCRIPT },
+ { 0x1CB1B, 0x006D, NES_SCRIPT }, { 0x1CB88, 0x004C, NES_SCRIPT }, { 0x1CBD4, 0x0044, NES_SCRIPT }, { 0x1CC18, 0x0053, NES_SCRIPT }, { 0x2049D, 0x0081, NES_SCRIPT },
+ { 0x1634C, 0x0035, NES_SCRIPT }, { 0x16381, 0x001C, NES_SCRIPT }, { 0x1639D, 0x0014, NES_SCRIPT }, { 0x163B1, 0x001C, NES_SCRIPT }, { 0x163CD, 0x0027, NES_SCRIPT },
+ { 0x163F4, 0x019B, NES_SCRIPT }, { 0x1D183, 0x0094, NES_SCRIPT }, { 0x1D217, 0x0117, NES_SCRIPT }, { 0x1D32E, 0x001C, NES_SCRIPT }, { 0x1D34A, 0x0056, NES_SCRIPT },
+ { 0x1D3A0, 0x0072, NES_SCRIPT }, { 0x1E47F, 0x0028, NES_SCRIPT }, { 0x1E4A7, 0x0175, NES_SCRIPT }, { 0x1E61C, 0x022B, NES_SCRIPT }, { 0x27C85, 0x0071, NES_SCRIPT },
+ { 0x17C86, 0x004A, NES_SCRIPT }, { 0x13DD6, 0x0039, NES_SCRIPT }, { 0x1871E, 0x0270, NES_SCRIPT }, { 0x1898E, 0x00C0, NES_SCRIPT }, { 0x18A4E, 0x01B6, NES_SCRIPT },
+ { 0x00000, 0x0000, NES_SCRIPT }, { 0x19DC9, 0x00EE, NES_SCRIPT }, { 0x21D56, 0x00F5, NES_SCRIPT }, { 0x1E847, 0x0094, NES_SCRIPT }, { 0x21E4B, 0x0047, NES_SCRIPT },
+ { 0x2B99A, 0x004D, NES_SCRIPT }, { 0x13E0F, 0x0024, NES_SCRIPT }, { 0x14D13, 0x0014, NES_SCRIPT }, { 0x1755E, 0x0054, NES_SCRIPT }, { 0x175B2, 0x011A, NES_SCRIPT },
+ { 0x176CC, 0x0009, NES_SCRIPT }, { 0x14D27, 0x01B9, NES_SCRIPT }, { 0x2AA0E, 0x0256, NES_SCRIPT }, { 0x231A4, 0x06D2, NES_SCRIPT }, { 0x2B9E7, 0x001D, NES_SCRIPT },
+ { 0x2BA04, 0x0016, NES_SCRIPT }, { 0x2BA1A, 0x002D, NES_SCRIPT }, { 0x2BA47, 0x0027, NES_SCRIPT }, { 0x2BA6E, 0x0016, NES_SCRIPT }, { 0x2BA84, 0x0014, NES_SCRIPT },
+ { 0x2BA98, 0x0015, NES_SCRIPT }, { 0x2BAAD, 0x0029, NES_SCRIPT }, { 0x00000, 0x0000, NES_SCRIPT }, { 0x2BAD6, 0x0010, NES_SCRIPT }, { 0x176D5, 0x00A2, NES_SCRIPT },
+ { 0x22831, 0x0066, NES_SCRIPT }, { 0x14EE0, 0x0077, NES_SCRIPT }, { 0x1F30B, 0x011A, NES_SCRIPT }, { 0x1FD58, 0x001D, NES_SCRIPT }, { 0x1F425, 0x0095, NES_SCRIPT },
+ { 0x1F4BA, 0x009E, NES_SCRIPT }, { 0x17777, 0x006F, NES_SCRIPT }, { 0x177E6, 0x002F, NES_SCRIPT }, { 0x1F558, 0x0098, NES_SCRIPT }, { 0x2BAE6, 0x00C4, NES_SCRIPT },
+ { 0x2BBAA, 0x00AE, NES_SCRIPT }, { 0x2BC58, 0x0088, NES_SCRIPT }, { 0x20A3C, 0x01BB, NES_SCRIPT }, { 0x20BF7, 0x0197, NES_SCRIPT }, { 0x20D8E, 0x006E, NES_SCRIPT },
+ { 0x20DFC, 0x0028, NES_SCRIPT }, { 0x20E24, 0x00EA, NES_SCRIPT }, { 0x20F0E, 0x0049, NES_SCRIPT }, { 0x20F57, 0x00E7, NES_SCRIPT }, { 0x2103E, 0x010C, NES_SCRIPT },
+ { 0x2114A, 0x0151, NES_SCRIPT }, { 0x2129B, 0x01B0, NES_SCRIPT }, { 0x2144B, 0x0034, NES_SCRIPT }, { 0x2147F, 0x00A9, NES_SCRIPT }, { 0x24379, 0x010E, NES_SCRIPT },
+ { 0x1BBD7, 0x0072, NES_SCRIPT }, { 0x1CC6B, 0x0092, NES_SCRIPT }, { 0x2898B, 0x0054, NES_SCRIPT }, { 0x19EB7, 0x00D3, NES_SCRIPT }, { 0x19F8A, 0x0077, NES_SCRIPT },
+ { 0x14F57, 0x0057, NES_SCRIPT }, { 0x2703E, 0x0307, NES_SCRIPT }, { 0x1D9FB, 0x024F, NES_SCRIPT }, { 0x1DC4A, 0x00E4, NES_SCRIPT }, { 0x1DD2E, 0x0059, NES_SCRIPT },
+ { 0x1DD87, 0x01C2, NES_SCRIPT }, { 0x14FAE, 0x004D, NES_SCRIPT }, { 0x26D52, 0x00D5, NES_SCRIPT }, { 0x21E92, 0x0013, NES_SCRIPT }, { 0x29C6E, 0x00F0, NES_SCRIPT },
+ { 0x24487, 0x00E0, NES_SCRIPT }, { 0x21528, 0x00F2, NES_SCRIPT }, { 0x24567, 0x0023, NES_SCRIPT }, { 0x2B6B2, 0x010B, NES_SCRIPT }, { 0x2458A, 0x00A1, NES_SCRIPT },
+ { 0x250A0, 0x018B, NES_SCRIPT }, { 0x1B4F7, 0x000D, NES_SCRIPT }, { 0x1B504, 0x000D, NES_SCRIPT }, { 0x23876, 0x018E, NES_SCRIPT }, { 0x27639, 0x01F0, NES_SCRIPT },
+ { 0x23A04, 0x017B, NES_SCRIPT }, { 0x23B7F, 0x01AC, NES_SCRIPT }, { 0x23D2B, 0x0016, NES_SCRIPT }, { 0x2B7BD, 0x005B, NES_SCRIPT }, { 0x23D41, 0x0020, NES_SCRIPT },
+ { 0x2A643, 0x00A6, NES_SCRIPT }, { 0x29D5E, 0x0399, NES_SCRIPT }, { 0x14FFB, 0x00D2, NES_SCRIPT }, { 0x2B1DE, 0x0063, NES_SCRIPT }, { 0x00000, 0x0000, NES_SCRIPT },
+ { 0x2522B, 0x003C, NES_SCRIPT }, { 0x1E8DB, 0x0011, NES_SCRIPT }, { 0x13E33, 0x0018, NES_SCRIPT }, { 0x26585, 0x001F, NES_SCRIPT }, { 0x265A4, 0x0054, NES_SCRIPT },
+ { 0x265F8, 0x017D, NES_SCRIPT }, { 0x26775, 0x004B, NES_SCRIPT }, { 0x267C0, 0x0165, NES_SCRIPT }, { 0x26925, 0x0027, NES_SCRIPT }, { 0x2694C, 0x0041, NES_SCRIPT },
+ { 0x2698D, 0x01CB, NES_SCRIPT }, { 0x13E4B, 0x001F, NES_SCRIPT }, { 0x2462B, 0x002A, NES_SCRIPT }, { 0x150CD, 0x0187, NES_SCRIPT }, { 0x1927D, 0x0031, NES_SCRIPT },
+ { 0x17815, 0x0087, NES_SCRIPT }, { 0x2161A, 0x00D8, NES_SCRIPT }, { 0x1D412, 0x0018, NES_SCRIPT }, { 0x1D42A, 0x0058, NES_SCRIPT }, { 0x18C04, 0x0005, NES_SCRIPT },
+ { 0x15254, 0x0108, NES_SCRIPT }, { 0x1535C, 0x000B, NES_SCRIPT }, { 0x24655, 0x0139, NES_SCRIPT }, { 0x2478E, 0x0014, NES_SCRIPT }, { 0x1DF49, 0x0018, NES_SCRIPT },
+ { 0x247A2, 0x0027, NES_SCRIPT }, { 0x1A001, 0x004C, NES_SCRIPT }, { 0x00000, 0x0000, NES_SCRIPT }, { 0x2B241, 0x00A5, NES_SCRIPT }, { 0x2A0F7, 0x00B5, NES_SCRIPT },
+ { 0x2A1AC, 0x0140, NES_SCRIPT }, { 0x19759, 0x00CA, NES_SCRIPT }, { 0x19823, 0x014D, NES_SCRIPT }, { 0x19970, 0x0012, NES_SCRIPT }, { 0x2A2EC, 0x0005, NES_SCRIPT },
+ { 0x2A2F1, 0x0005, NES_SCRIPT }, { 0x2A2F6, 0x0005, NES_SCRIPT }, { 0x2A2FB, 0x0005, NES_SCRIPT }, { 0x2A300, 0x0005, NES_SCRIPT }, { 0x216F2, 0x0033, NES_SCRIPT },
+ { 0x2A305, 0x0005, NES_SCRIPT }, { 0x00000, 0x0000, NES_SCRIPT }, { 0x2A30A, 0x009C, NES_SCRIPT }, { 0x2A3A6, 0x009C, NES_SCRIPT }
+};
+static const ScummNESFile::Resource res_scripts_fra[179] = {
+ { 0x00000, 0x0000, NES_SCRIPT }, { 0x2947D, 0x0480, NES_SCRIPT }, { 0x298FD, 0x0226, NES_SCRIPT }, { 0x29B23, 0x0092, NES_SCRIPT }, { 0x29BB5, 0x040C, NES_SCRIPT },
+ { 0x29FC1, 0x01A1, NES_SCRIPT }, { 0x00000, 0x0000, NES_SCRIPT }, { 0x2A162, 0x005C, NES_SCRIPT }, { 0x00000, 0x0000, NES_SCRIPT }, { 0x2A1BE, 0x0005, NES_SCRIPT },
+ { 0x2C169, 0x000D, NES_SCRIPT }, { 0x2C176, 0x000D, NES_SCRIPT }, { 0x186E3, 0x0040, NES_SCRIPT }, { 0x18723, 0x0016, NES_SCRIPT }, { 0x1B59F, 0x0046, NES_SCRIPT },
+ { 0x1EFD7, 0x00CB, NES_SCRIPT }, { 0x21D09, 0x0054, NES_SCRIPT }, { 0x176C8, 0x0027, NES_SCRIPT }, { 0x1FE6A, 0x0027, NES_SCRIPT }, { 0x1FE91, 0x0027, NES_SCRIPT },
+ { 0x1BC9A, 0x0022, NES_SCRIPT }, { 0x15CD6, 0x0092, NES_SCRIPT }, { 0x22336, 0x001C, NES_SCRIPT }, { 0x22352, 0x008F, NES_SCRIPT }, { 0x192A5, 0x002B, NES_SCRIPT },
+ { 0x1CAAA, 0x0069, NES_SCRIPT }, { 0x1CB13, 0x0054, NES_SCRIPT }, { 0x1CB67, 0x0048, NES_SCRIPT }, { 0x1CBAF, 0x0058, NES_SCRIPT }, { 0x204B6, 0x0078, NES_SCRIPT },
+ { 0x16471, 0x0035, NES_SCRIPT }, { 0x164A6, 0x001C, NES_SCRIPT }, { 0x164C2, 0x0014, NES_SCRIPT }, { 0x164D6, 0x001C, NES_SCRIPT }, { 0x164F2, 0x0027, NES_SCRIPT },
+ { 0x16519, 0x01BB, NES_SCRIPT }, { 0x1D135, 0x008D, NES_SCRIPT }, { 0x1D1C2, 0x0119, NES_SCRIPT }, { 0x1D2DB, 0x001C, NES_SCRIPT }, { 0x1D2F7, 0x0056, NES_SCRIPT },
+ { 0x1D34D, 0x0072, NES_SCRIPT }, { 0x1E4BF, 0x0028, NES_SCRIPT }, { 0x1E4E7, 0x01E0, NES_SCRIPT }, { 0x1E6C7, 0x0241, NES_SCRIPT }, { 0x2845D, 0x0071, NES_SCRIPT },
+ { 0x17E48, 0x004C, NES_SCRIPT }, { 0x13DE3, 0x0039, NES_SCRIPT }, { 0x18739, 0x0296, NES_SCRIPT }, { 0x189CF, 0x00C2, NES_SCRIPT }, { 0x18A91, 0x01A5, NES_SCRIPT },
+ { 0x00000, 0x0000, NES_SCRIPT }, { 0x19E13, 0x00F3, NES_SCRIPT }, { 0x21D5D, 0x00F6, NES_SCRIPT }, { 0x1E908, 0x00B8, NES_SCRIPT }, { 0x21E53, 0x0047, NES_SCRIPT },
+ { 0x2C183, 0x004D, NES_SCRIPT }, { 0x13E1C, 0x0024, NES_SCRIPT }, { 0x14D77, 0x0014, NES_SCRIPT }, { 0x176EF, 0x0059, NES_SCRIPT }, { 0x17748, 0x013F, NES_SCRIPT },
+ { 0x17887, 0x0009, NES_SCRIPT }, { 0x14D8B, 0x01D4, NES_SCRIPT }, { 0x2ACFB, 0x028D, NES_SCRIPT }, { 0x23203, 0x0779, NES_SCRIPT }, { 0x2C1D0, 0x001B, NES_SCRIPT },
+ { 0x2C1EB, 0x001F, NES_SCRIPT }, { 0x2C20A, 0x0024, NES_SCRIPT }, { 0x2C22E, 0x0019, NES_SCRIPT }, { 0x2C247, 0x0018, NES_SCRIPT }, { 0x2C25F, 0x001D, NES_SCRIPT },
+ { 0x2C27C, 0x0016, NES_SCRIPT }, { 0x2C292, 0x0027, NES_SCRIPT }, { 0x00000, 0x0000, NES_SCRIPT }, { 0x2C2B9, 0x0011, NES_SCRIPT }, { 0x17890, 0x00AA, NES_SCRIPT },
+ { 0x22846, 0x0066, NES_SCRIPT }, { 0x14F5F, 0x0083, NES_SCRIPT }, { 0x1F43C, 0x013A, NES_SCRIPT }, { 0x1FEB8, 0x001D, NES_SCRIPT }, { 0x1F576, 0x0098, NES_SCRIPT },
+ { 0x1F60E, 0x009B, NES_SCRIPT }, { 0x1793A, 0x006E, NES_SCRIPT }, { 0x179A8, 0x0033, NES_SCRIPT }, { 0x1F6A9, 0x00A5, NES_SCRIPT }, { 0x2C2CA, 0x00BA, NES_SCRIPT },
+ { 0x2C384, 0x00AC, NES_SCRIPT }, { 0x2C430, 0x008F, NES_SCRIPT }, { 0x20A2D, 0x01BE, NES_SCRIPT }, { 0x20BEB, 0x0158, NES_SCRIPT }, { 0x20D43, 0x0079, NES_SCRIPT },
+ { 0x20DBC, 0x002B, NES_SCRIPT }, { 0x20DE7, 0x00E8, NES_SCRIPT }, { 0x20ECF, 0x004A, NES_SCRIPT }, { 0x20F19, 0x0110, NES_SCRIPT }, { 0x21029, 0x0136, NES_SCRIPT },
+ { 0x2115F, 0x0152, NES_SCRIPT }, { 0x212B1, 0x01B3, NES_SCRIPT }, { 0x21464, 0x0032, NES_SCRIPT }, { 0x21496, 0x00A9, NES_SCRIPT }, { 0x2437F, 0x0133, NES_SCRIPT },
+ { 0x1BCBC, 0x0074, NES_SCRIPT }, { 0x1CC07, 0x0090, NES_SCRIPT }, { 0x28E43, 0x0054, NES_SCRIPT }, { 0x19F06, 0x00DB, NES_SCRIPT }, { 0x19FE1, 0x0080, NES_SCRIPT },
+ { 0x14FE2, 0x0057, NES_SCRIPT }, { 0x273F4, 0x031F, NES_SCRIPT }, { 0x1D9D4, 0x0238, NES_SCRIPT }, { 0x1DC0C, 0x00FE, NES_SCRIPT }, { 0x1DD0A, 0x005A, NES_SCRIPT },
+ { 0x1DD64, 0x01F5, NES_SCRIPT }, { 0x15039, 0x004D, NES_SCRIPT }, { 0x270DD, 0x0100, NES_SCRIPT }, { 0x21E9A, 0x0013, NES_SCRIPT }, { 0x2A1C3, 0x00F0, NES_SCRIPT },
+ { 0x244B2, 0x00E4, NES_SCRIPT }, { 0x2153F, 0x00EC, NES_SCRIPT }, { 0x24596, 0x0033, NES_SCRIPT }, { 0x2BC04, 0x0108, NES_SCRIPT }, { 0x245C9, 0x009F, NES_SCRIPT },
+ { 0x250F1, 0x0193, NES_SCRIPT }, { 0x1B5E5, 0x000D, NES_SCRIPT }, { 0x1B5F2, 0x000D, NES_SCRIPT }, { 0x2397C, 0x0199, NES_SCRIPT }, { 0x27A07, 0x0233, NES_SCRIPT },
+ { 0x23B15, 0x0171, NES_SCRIPT }, { 0x23C86, 0x01BC, NES_SCRIPT }, { 0x23E42, 0x0016, NES_SCRIPT }, { 0x2BD0C, 0x005B, NES_SCRIPT }, { 0x23E58, 0x0020, NES_SCRIPT },
+ { 0x27E3B, 0x00B9, NES_SCRIPT }, { 0x2A2B3, 0x03D3, NES_SCRIPT }, { 0x15086, 0x00E4, NES_SCRIPT }, { 0x2B70C, 0x0067, NES_SCRIPT }, { 0x00000, 0x0000, NES_SCRIPT },
+ { 0x25284, 0x003C, NES_SCRIPT }, { 0x1E9C0, 0x0011, NES_SCRIPT }, { 0x13E40, 0x0018, NES_SCRIPT }, { 0x26621, 0x001F, NES_SCRIPT }, { 0x26640, 0x0054, NES_SCRIPT },
+ { 0x26694, 0x0173, NES_SCRIPT }, { 0x26807, 0x004B, NES_SCRIPT }, { 0x26852, 0x0190, NES_SCRIPT }, { 0x269E2, 0x0027, NES_SCRIPT }, { 0x26A09, 0x0041, NES_SCRIPT },
+ { 0x26A4A, 0x024E, NES_SCRIPT }, { 0x13E58, 0x001F, NES_SCRIPT }, { 0x24668, 0x002A, NES_SCRIPT }, { 0x1516A, 0x01C9, NES_SCRIPT }, { 0x192D0, 0x0031, NES_SCRIPT },
+ { 0x179DB, 0x0088, NES_SCRIPT }, { 0x2162B, 0x00D0, NES_SCRIPT }, { 0x1D3BF, 0x0018, NES_SCRIPT }, { 0x1D3D7, 0x0055, NES_SCRIPT }, { 0x18C36, 0x0005, NES_SCRIPT },
+ { 0x15333, 0x0113, NES_SCRIPT }, { 0x15446, 0x000B, NES_SCRIPT }, { 0x24692, 0x014D, NES_SCRIPT }, { 0x247DF, 0x0014, NES_SCRIPT }, { 0x1DF59, 0x0018, NES_SCRIPT },
+ { 0x247F3, 0x0027, NES_SCRIPT }, { 0x1A061, 0x0050, NES_SCRIPT }, { 0x00000, 0x0000, NES_SCRIPT }, { 0x2B773, 0x00A5, NES_SCRIPT }, { 0x2A686, 0x00BA, NES_SCRIPT },
+ { 0x2A740, 0x0140, NES_SCRIPT }, { 0x1979F, 0x00CA, NES_SCRIPT }, { 0x19869, 0x014D, NES_SCRIPT }, { 0x199B6, 0x0012, NES_SCRIPT }, { 0x2A880, 0x0005, NES_SCRIPT },
+ { 0x2A885, 0x0005, NES_SCRIPT }, { 0x2A88A, 0x0005, NES_SCRIPT }, { 0x2A88F, 0x0005, NES_SCRIPT }, { 0x2A894, 0x0005, NES_SCRIPT }, { 0x216FB, 0x0033, NES_SCRIPT },
+ { 0x2A899, 0x0005, NES_SCRIPT }, { 0x00000, 0x0000, NES_SCRIPT }, { 0x2A89E, 0x009C, NES_SCRIPT }, { 0x2A93A, 0x009C, NES_SCRIPT }
+};
+static const ScummNESFile::Resource res_scripts_ger[179] = {
+ { 0x00000, 0x0000, NES_SCRIPT }, { 0x295B0, 0x045A, NES_SCRIPT }, { 0x29A0A, 0x0218, NES_SCRIPT }, { 0x29C22, 0x00B1, NES_SCRIPT }, { 0x29CD3, 0x0408, NES_SCRIPT },
+ { 0x2A0DB, 0x01A1, NES_SCRIPT }, { 0x00000, 0x0000, NES_SCRIPT }, { 0x2A27C, 0x005C, NES_SCRIPT }, { 0x00000, 0x0000, NES_SCRIPT }, { 0x2A2D8, 0x0005, NES_SCRIPT },
+ { 0x2C169, 0x000D, NES_SCRIPT }, { 0x2C176, 0x000D, NES_SCRIPT }, { 0x186DB, 0x0040, NES_SCRIPT }, { 0x1871B, 0x0016, NES_SCRIPT }, { 0x1B5C2, 0x0046, NES_SCRIPT },
+ { 0x1EFB7, 0x00E3, NES_SCRIPT }, { 0x21D9D, 0x0069, NES_SCRIPT }, { 0x174F1, 0x0027, NES_SCRIPT }, { 0x1FE92, 0x0027, NES_SCRIPT }, { 0x1FEB9, 0x0027, NES_SCRIPT },
+ { 0x1BCE5, 0x0022, NES_SCRIPT }, { 0x13EF4, 0x0087, NES_SCRIPT }, { 0x223EC, 0x001F, NES_SCRIPT }, { 0x2240B, 0x008F, NES_SCRIPT }, { 0x192CC, 0x002B, NES_SCRIPT },
+ { 0x1CB08, 0x006E, NES_SCRIPT }, { 0x1CB76, 0x004E, NES_SCRIPT }, { 0x1CBC4, 0x004D, NES_SCRIPT }, { 0x1CC11, 0x0059, NES_SCRIPT }, { 0x204AA, 0x0080, NES_SCRIPT },
+ { 0x1628E, 0x0035, NES_SCRIPT }, { 0x162C3, 0x001C, NES_SCRIPT }, { 0x162DF, 0x0014, NES_SCRIPT }, { 0x162F3, 0x001C, NES_SCRIPT }, { 0x1630F, 0x0027, NES_SCRIPT },
+ { 0x16336, 0x01D1, NES_SCRIPT }, { 0x1D199, 0x00A0, NES_SCRIPT }, { 0x1D239, 0x011C, NES_SCRIPT }, { 0x1D355, 0x001C, NES_SCRIPT }, { 0x1D371, 0x0056, NES_SCRIPT },
+ { 0x1D3C7, 0x0072, NES_SCRIPT }, { 0x1E4FA, 0x0028, NES_SCRIPT }, { 0x1E522, 0x019D, NES_SCRIPT }, { 0x1E6BF, 0x023B, NES_SCRIPT }, { 0x2845D, 0x0071, NES_SCRIPT },
+ { 0x17C50, 0x0052, NES_SCRIPT }, { 0x15AC9, 0x0039, NES_SCRIPT }, { 0x18731, 0x02E7, NES_SCRIPT }, { 0x18A18, 0x00BC, NES_SCRIPT }, { 0x18AD4, 0x01A2, NES_SCRIPT },
+ { 0x00000, 0x0000, NES_SCRIPT }, { 0x19E45, 0x00F8, NES_SCRIPT }, { 0x21E06, 0x00F7, NES_SCRIPT }, { 0x1E8FA, 0x00B5, NES_SCRIPT }, { 0x21EFD, 0x0047, NES_SCRIPT },
+ { 0x2C183, 0x004D, NES_SCRIPT }, { 0x15B02, 0x0024, NES_SCRIPT }, { 0x14D64, 0x0014, NES_SCRIPT }, { 0x17518, 0x005E, NES_SCRIPT }, { 0x17576, 0x0125, NES_SCRIPT },
+ { 0x1769B, 0x0009, NES_SCRIPT }, { 0x14D78, 0x01C7, NES_SCRIPT }, { 0x2ADCE, 0x0263, NES_SCRIPT }, { 0x232AF, 0x077F, NES_SCRIPT }, { 0x2C1D0, 0x001E, NES_SCRIPT },
+ { 0x2C1EE, 0x0024, NES_SCRIPT }, { 0x2C212, 0x002E, NES_SCRIPT }, { 0x2C240, 0x0022, NES_SCRIPT }, { 0x2C262, 0x0013, NES_SCRIPT }, { 0x2C275, 0x001E, NES_SCRIPT },
+ { 0x2C293, 0x0016, NES_SCRIPT }, { 0x2C2A9, 0x0027, NES_SCRIPT }, { 0x00000, 0x0000, NES_SCRIPT }, { 0x2C2D0, 0x0012, NES_SCRIPT }, { 0x176A4, 0x00A4, NES_SCRIPT },
+ { 0x228F8, 0x0066, NES_SCRIPT }, { 0x14F3F, 0x007F, NES_SCRIPT }, { 0x1F428, 0x013A, NES_SCRIPT }, { 0x1FEE0, 0x001D, NES_SCRIPT }, { 0x1F562, 0x00A0, NES_SCRIPT },
+ { 0x1F602, 0x00A4, NES_SCRIPT }, { 0x17748, 0x0076, NES_SCRIPT }, { 0x177BE, 0x0036, NES_SCRIPT }, { 0x1F6A6, 0x00B9, NES_SCRIPT }, { 0x2C2E2, 0x00CB, NES_SCRIPT },
+ { 0x2C3AD, 0x00B7, NES_SCRIPT }, { 0x2C464, 0x008A, NES_SCRIPT }, { 0x20A58, 0x01BD, NES_SCRIPT }, { 0x20C15, 0x0181, NES_SCRIPT }, { 0x20D96, 0x0078, NES_SCRIPT },
+ { 0x20E0E, 0x003C, NES_SCRIPT }, { 0x20E4A, 0x00E9, NES_SCRIPT }, { 0x20F33, 0x0046, NES_SCRIPT }, { 0x20F79, 0x00F6, NES_SCRIPT }, { 0x2106F, 0x0118, NES_SCRIPT },
+ { 0x21187, 0x015B, NES_SCRIPT }, { 0x212E2, 0x01AC, NES_SCRIPT }, { 0x2148E, 0x003F, NES_SCRIPT }, { 0x214CD, 0x00A9, NES_SCRIPT }, { 0x2436F, 0x0126, NES_SCRIPT },
+ { 0x1BD07, 0x0075, NES_SCRIPT }, { 0x1CC6A, 0x009B, NES_SCRIPT }, { 0x28F5D, 0x0054, NES_SCRIPT }, { 0x19F3D, 0x00E1, NES_SCRIPT }, { 0x1A01E, 0x0086, NES_SCRIPT },
+ { 0x14FBE, 0x0057, NES_SCRIPT }, { 0x27326, 0x033D, NES_SCRIPT }, { 0x1DA51, 0x023B, NES_SCRIPT }, { 0x1DC8C, 0x00FB, NES_SCRIPT }, { 0x1DD87, 0x0056, NES_SCRIPT },
+ { 0x1DDDD, 0x01E1, NES_SCRIPT }, { 0x15015, 0x004D, NES_SCRIPT }, { 0x27027, 0x00E8, NES_SCRIPT }, { 0x21F44, 0x0013, NES_SCRIPT }, { 0x2A2DD, 0x00F0, NES_SCRIPT },
+ { 0x24495, 0x00F8, NES_SCRIPT }, { 0x21576, 0x00F9, NES_SCRIPT }, { 0x2458D, 0x002B, NES_SCRIPT }, { 0x2BAA4, 0x010F, NES_SCRIPT }, { 0x245B8, 0x00A5, NES_SCRIPT },
+ { 0x250D0, 0x019C, NES_SCRIPT }, { 0x1B608, 0x000D, NES_SCRIPT }, { 0x1B615, 0x000D, NES_SCRIPT }, { 0x23A2E, 0x0185, NES_SCRIPT }, { 0x27957, 0x0212, NES_SCRIPT },
+ { 0x23BB3, 0x0158, NES_SCRIPT }, { 0x23D0B, 0x01C4, NES_SCRIPT }, { 0x23ECF, 0x0016, NES_SCRIPT }, { 0x2BBB3, 0x005A, NES_SCRIPT }, { 0x23EE5, 0x0020, NES_SCRIPT },
+ { 0x27D6A, 0x00A7, NES_SCRIPT }, { 0x2A3CD, 0x038C, NES_SCRIPT }, { 0x15062, 0x00F6, NES_SCRIPT }, { 0x2B5B2, 0x007B, NES_SCRIPT }, { 0x00000, 0x0000, NES_SCRIPT },
+ { 0x2526C, 0x003C, NES_SCRIPT }, { 0x1E9AF, 0x0011, NES_SCRIPT }, { 0x15B26, 0x0018, NES_SCRIPT }, { 0x265F5, 0x001F, NES_SCRIPT }, { 0x26614, 0x0054, NES_SCRIPT },
+ { 0x26668, 0x018E, NES_SCRIPT }, { 0x267F6, 0x004B, NES_SCRIPT }, { 0x26841, 0x0196, NES_SCRIPT }, { 0x269D7, 0x0027, NES_SCRIPT }, { 0x269FE, 0x0041, NES_SCRIPT },
+ { 0x26A3F, 0x01A3, NES_SCRIPT }, { 0x15B3E, 0x001F, NES_SCRIPT }, { 0x2465D, 0x002A, NES_SCRIPT }, { 0x15158, 0x0198, NES_SCRIPT }, { 0x192F7, 0x0031, NES_SCRIPT },
+ { 0x177F4, 0x008C, NES_SCRIPT }, { 0x2166F, 0x00DA, NES_SCRIPT }, { 0x1D439, 0x0018, NES_SCRIPT }, { 0x1D451, 0x0054, NES_SCRIPT }, { 0x18C76, 0x0005, NES_SCRIPT },
+ { 0x152F0, 0x0126, NES_SCRIPT }, { 0x15416, 0x000B, NES_SCRIPT }, { 0x24687, 0x0137, NES_SCRIPT }, { 0x247BE, 0x0014, NES_SCRIPT }, { 0x1DFBE, 0x0018, NES_SCRIPT },
+ { 0x247D2, 0x0027, NES_SCRIPT }, { 0x1A0A4, 0x004D, NES_SCRIPT }, { 0x00000, 0x0000, NES_SCRIPT }, { 0x2B62D, 0x00A5, NES_SCRIPT }, { 0x2A759, 0x00BA, NES_SCRIPT },
+ { 0x2A813, 0x0140, NES_SCRIPT }, { 0x197CF, 0x00D0, NES_SCRIPT }, { 0x1989F, 0x014D, NES_SCRIPT }, { 0x199EC, 0x0012, NES_SCRIPT }, { 0x2A953, 0x0005, NES_SCRIPT },
+ { 0x2A958, 0x0005, NES_SCRIPT }, { 0x2A95D, 0x0005, NES_SCRIPT }, { 0x2A962, 0x0005, NES_SCRIPT }, { 0x2A967, 0x0005, NES_SCRIPT }, { 0x21749, 0x0033, NES_SCRIPT },
+ { 0x2A96C, 0x0005, NES_SCRIPT }, { 0x00000, 0x0000, NES_SCRIPT }, { 0x2A971, 0x009C, NES_SCRIPT }, { 0x2AA0D, 0x009C, NES_SCRIPT }
+};
+static const ScummNESFile::Resource res_scripts_esp[179] = {
+ { 0x00000, 0x0000, NES_SCRIPT }, { 0x28F4C, 0x0457, NES_SCRIPT }, { 0x293A3, 0x0213, NES_SCRIPT }, { 0x295B6, 0x009C, NES_SCRIPT }, { 0x29652, 0x03FE, NES_SCRIPT },
+ { 0x29A50, 0x01A1, NES_SCRIPT }, { 0x00000, 0x0000, NES_SCRIPT }, { 0x29BF1, 0x005C, NES_SCRIPT }, { 0x00000, 0x0000, NES_SCRIPT }, { 0x29C4D, 0x0005, NES_SCRIPT },
+ { 0x2B964, 0x000D, NES_SCRIPT }, { 0x2B971, 0x000D, NES_SCRIPT }, { 0x186EE, 0x0040, NES_SCRIPT }, { 0x1872E, 0x0016, NES_SCRIPT }, { 0x1B5A0, 0x0046, NES_SCRIPT },
+ { 0x1EF97, 0x00B4, NES_SCRIPT }, { 0x21D17, 0x0056, NES_SCRIPT }, { 0x175E9, 0x0027, NES_SCRIPT }, { 0x1FE06, 0x0027, NES_SCRIPT }, { 0x1FE2D, 0x0027, NES_SCRIPT },
+ { 0x1BC86, 0x0022, NES_SCRIPT }, { 0x15C26, 0x008B, NES_SCRIPT }, { 0x2232E, 0x001F, NES_SCRIPT }, { 0x2234D, 0x008F, NES_SCRIPT }, { 0x192AF, 0x002B, NES_SCRIPT },
+ { 0x1CB59, 0x006B, NES_SCRIPT }, { 0x1CBC4, 0x0045, NES_SCRIPT }, { 0x1CC09, 0x0046, NES_SCRIPT }, { 0x1CC4F, 0x005D, NES_SCRIPT }, { 0x204CC, 0x0077, NES_SCRIPT },
+ { 0x163DA, 0x0035, NES_SCRIPT }, { 0x1640F, 0x001C, NES_SCRIPT }, { 0x1642B, 0x0014, NES_SCRIPT }, { 0x1643F, 0x001C, NES_SCRIPT }, { 0x1645B, 0x0027, NES_SCRIPT },
+ { 0x16482, 0x01A3, NES_SCRIPT }, { 0x1D1DE, 0x009E, NES_SCRIPT }, { 0x1D27C, 0x011A, NES_SCRIPT }, { 0x1D396, 0x001C, NES_SCRIPT }, { 0x1D3B2, 0x0056, NES_SCRIPT },
+ { 0x1D408, 0x0072, NES_SCRIPT }, { 0x1E50F, 0x0028, NES_SCRIPT }, { 0x1E537, 0x0199, NES_SCRIPT }, { 0x1E6D0, 0x0240, NES_SCRIPT }, { 0x27CA1, 0x0071, NES_SCRIPT },
+ { 0x17D14, 0x004C, NES_SCRIPT }, { 0x13E0F, 0x0039, NES_SCRIPT }, { 0x18744, 0x02B9, NES_SCRIPT }, { 0x189FD, 0x00B9, NES_SCRIPT }, { 0x18AB6, 0x0183, NES_SCRIPT },
+ { 0x00000, 0x0000, NES_SCRIPT }, { 0x19E3E, 0x00F0, NES_SCRIPT }, { 0x21D6D, 0x00F7, NES_SCRIPT }, { 0x1E910, 0x00A8, NES_SCRIPT }, { 0x21E64, 0x0047, NES_SCRIPT },
+ { 0x2B97E, 0x004D, NES_SCRIPT }, { 0x13E48, 0x0024, NES_SCRIPT }, { 0x14D06, 0x0014, NES_SCRIPT }, { 0x17610, 0x005B, NES_SCRIPT }, { 0x1766B, 0x0111, NES_SCRIPT },
+ { 0x1777C, 0x0009, NES_SCRIPT }, { 0x14D1A, 0x01C9, NES_SCRIPT }, { 0x2A9E3, 0x0263, NES_SCRIPT }, { 0x231C6, 0x06D6, NES_SCRIPT }, { 0x2B9CB, 0x001C, NES_SCRIPT },
+ { 0x2B9E7, 0x001C, NES_SCRIPT }, { 0x2BA03, 0x0025, NES_SCRIPT }, { 0x2BA28, 0x0023, NES_SCRIPT }, { 0x2BA4B, 0x002A, NES_SCRIPT }, { 0x2BA75, 0x0033, NES_SCRIPT },
+ { 0x2BAA8, 0x0016, NES_SCRIPT }, { 0x2BABE, 0x0024, NES_SCRIPT }, { 0x00000, 0x0000, NES_SCRIPT }, { 0x2BAE2, 0x0011, NES_SCRIPT }, { 0x17785, 0x00A2, NES_SCRIPT },
+ { 0x22838, 0x0066, NES_SCRIPT }, { 0x14EE3, 0x0079, NES_SCRIPT }, { 0x1F3DB, 0x010F, NES_SCRIPT }, { 0x1FE54, 0x001D, NES_SCRIPT }, { 0x1F4EA, 0x00A2, NES_SCRIPT },
+ { 0x1F58C, 0x0097, NES_SCRIPT }, { 0x17827, 0x0061, NES_SCRIPT }, { 0x17888, 0x0032, NES_SCRIPT }, { 0x1F623, 0x00A7, NES_SCRIPT }, { 0x2BAF3, 0x00CD, NES_SCRIPT },
+ { 0x2BBC0, 0x00BD, NES_SCRIPT }, { 0x2BC7D, 0x0089, NES_SCRIPT }, { 0x20A73, 0x01C2, NES_SCRIPT }, { 0x20C35, 0x016E, NES_SCRIPT }, { 0x20DA3, 0x006F, NES_SCRIPT },
+ { 0x20E12, 0x0037, NES_SCRIPT }, { 0x20E49, 0x00EC, NES_SCRIPT }, { 0x20F35, 0x0047, NES_SCRIPT }, { 0x20F7C, 0x00F8, NES_SCRIPT }, { 0x21074, 0x0102, NES_SCRIPT },
+ { 0x21176, 0x0133, NES_SCRIPT }, { 0x212A9, 0x0197, NES_SCRIPT }, { 0x21440, 0x002D, NES_SCRIPT }, { 0x2146D, 0x00A9, NES_SCRIPT }, { 0x2436D, 0x0125, NES_SCRIPT },
+ { 0x1BCA8, 0x0071, NES_SCRIPT }, { 0x1CCAC, 0x0096, NES_SCRIPT }, { 0x2896A, 0x0054, NES_SCRIPT }, { 0x19F2E, 0x00DF, NES_SCRIPT }, { 0x1A00D, 0x007F, NES_SCRIPT },
+ { 0x14F5C, 0x0057, NES_SCRIPT }, { 0x27074, 0x02F6, NES_SCRIPT }, { 0x1DA73, 0x023A, NES_SCRIPT }, { 0x1DCAD, 0x00E8, NES_SCRIPT }, { 0x1DD95, 0x0059, NES_SCRIPT },
+ { 0x1DDEE, 0x01E3, NES_SCRIPT }, { 0x14FB3, 0x004D, NES_SCRIPT }, { 0x26D81, 0x00DC, NES_SCRIPT }, { 0x21EAB, 0x0013, NES_SCRIPT }, { 0x29C52, 0x00F0, NES_SCRIPT },
+ { 0x24492, 0x00E4, NES_SCRIPT }, { 0x21516, 0x00EE, NES_SCRIPT }, { 0x24576, 0x002D, NES_SCRIPT }, { 0x2B692, 0x010D, NES_SCRIPT }, { 0x245A3, 0x00AC, NES_SCRIPT },
+ { 0x250C3, 0x0184, NES_SCRIPT }, { 0x1B5E6, 0x000D, NES_SCRIPT }, { 0x1B5F3, 0x000D, NES_SCRIPT }, { 0x2389C, 0x0182, NES_SCRIPT }, { 0x2765E, 0x01E7, NES_SCRIPT },
+ { 0x23A1E, 0x017A, NES_SCRIPT }, { 0x23B98, 0x01B6, NES_SCRIPT }, { 0x23D4E, 0x0016, NES_SCRIPT }, { 0x2B79F, 0x005D, NES_SCRIPT }, { 0x23D64, 0x0020, NES_SCRIPT },
+ { 0x2A619, 0x00A5, NES_SCRIPT }, { 0x29D42, 0x038F, NES_SCRIPT }, { 0x15000, 0x00ED, NES_SCRIPT }, { 0x2B1B8, 0x0063, NES_SCRIPT }, { 0x00000, 0x0000, NES_SCRIPT },
+ { 0x25247, 0x003C, NES_SCRIPT }, { 0x1E9B8, 0x0011, NES_SCRIPT }, { 0x13E6C, 0x0018, NES_SCRIPT }, { 0x265E0, 0x001F, NES_SCRIPT }, { 0x265FF, 0x0054, NES_SCRIPT },
+ { 0x26653, 0x0147, NES_SCRIPT }, { 0x2679A, 0x004B, NES_SCRIPT }, { 0x267E5, 0x0184, NES_SCRIPT }, { 0x26969, 0x0027, NES_SCRIPT }, { 0x26990, 0x0041, NES_SCRIPT },
+ { 0x269D1, 0x01B9, NES_SCRIPT }, { 0x13E84, 0x001F, NES_SCRIPT }, { 0x2464F, 0x002A, NES_SCRIPT }, { 0x150ED, 0x01A4, NES_SCRIPT }, { 0x192DA, 0x0031, NES_SCRIPT },
+ { 0x178BA, 0x007C, NES_SCRIPT }, { 0x21604, 0x00E4, NES_SCRIPT }, { 0x1D47A, 0x0018, NES_SCRIPT }, { 0x1D492, 0x005B, NES_SCRIPT }, { 0x18C39, 0x0005, NES_SCRIPT },
+ { 0x15291, 0x010F, NES_SCRIPT }, { 0x153A0, 0x000B, NES_SCRIPT }, { 0x24679, 0x0138, NES_SCRIPT }, { 0x247B1, 0x0014, NES_SCRIPT }, { 0x1DFD1, 0x0018, NES_SCRIPT },
+ { 0x247C5, 0x0027, NES_SCRIPT }, { 0x1A08C, 0x004E, NES_SCRIPT }, { 0x00000, 0x0000, NES_SCRIPT }, { 0x2B21B, 0x00A5, NES_SCRIPT }, { 0x2A0D1, 0x00B1, NES_SCRIPT },
+ { 0x2A182, 0x0140, NES_SCRIPT }, { 0x197CF, 0x00BE, NES_SCRIPT }, { 0x1988D, 0x014D, NES_SCRIPT }, { 0x199DA, 0x0012, NES_SCRIPT }, { 0x2A2C2, 0x0005, NES_SCRIPT },
+ { 0x2A2C7, 0x0005, NES_SCRIPT }, { 0x2A2CC, 0x0005, NES_SCRIPT }, { 0x2A2D1, 0x0005, NES_SCRIPT }, { 0x2A2D6, 0x0005, NES_SCRIPT }, { 0x216E8, 0x0033, NES_SCRIPT },
+ { 0x2A2DB, 0x0005, NES_SCRIPT }, { 0x00000, 0x0000, NES_SCRIPT }, { 0x2A2E0, 0x009C, NES_SCRIPT }, { 0x2A37C, 0x009C, NES_SCRIPT }
+};
+
+static const ScummNESFile::Resource *res_scripts[ScummNESFile::kROMsetNum] = {
+ res_scripts_usa,
+ res_scripts_eur,
+ res_scripts_swe,
+ res_scripts_fra,
+ res_scripts_ger,
+ res_scripts_esp,
+};
+
+static const ScummNESFile::Resource res_sounds_usa[82] = {
+ { 0x0FFE8, 0x000A, NES_SOUND }, { 0x30ECA, 0x0832, NES_SOUND }, { 0x30ECA, 0x0832, NES_SOUND }, { 0x30ECA, 0x0832, NES_SOUND }, { 0x30ECA, 0x0832, NES_SOUND },
+ { 0x30ECA, 0x0832, NES_SOUND }, { 0x17FCA, 0x0011, NES_SOUND }, { 0x27E0B, 0x0073, NES_SOUND }, { 0x17FDB, 0x0011, NES_SOUND }, { 0x17FEC, 0x0011, NES_SOUND },
+ { 0x27E7E, 0x0056, NES_SOUND }, { 0x27ED4, 0x001F, NES_SOUND }, { 0x23FEE, 0x0011, NES_SOUND }, { 0x0FFF2, 0x000A, NES_SOUND }, { 0x27EF3, 0x000A, NES_SOUND },
+ { 0x27EFD, 0x0019, NES_SOUND }, { 0x27F16, 0x004B, NES_SOUND }, { 0x27F61, 0x000A, NES_SOUND }, { 0x27F6B, 0x000F, NES_SOUND }, { 0x27F7A, 0x001D, NES_SOUND },
+ { 0x27F97, 0x0045, NES_SOUND }, { 0x27FDC, 0x000F, NES_SOUND }, { 0x2FD42, 0x001B, NES_SOUND }, { 0x2FD5D, 0x0033, NES_SOUND }, { 0x27FEB, 0x0011, NES_SOUND },
+ { 0x2BFEF, 0x000F, NES_SOUND }, { 0x2FD90, 0x0075, NES_SOUND }, { 0x2FE05, 0x0014, NES_SOUND }, { 0x0FFE8, 0x000A, NES_SOUND }, { 0x2FE19, 0x00FF, NES_SOUND },
+ { 0x2FF18, 0x000F, NES_SOUND }, { 0x2FF27, 0x000F, NES_SOUND }, { 0x2FF36, 0x0092, NES_SOUND }, { 0x2FF36, 0x0092, NES_SOUND }, { 0x2FFC8, 0x002D, NES_SOUND },
+ { 0x316FC, 0x00F8, NES_SOUND }, { 0x317F4, 0x0016, NES_SOUND }, { 0x3180A, 0x0011, NES_SOUND }, { 0x3181B, 0x004B, NES_SOUND }, { 0x31866, 0x0011, NES_SOUND },
+ { 0x31877, 0x003B, NES_SOUND }, { 0x318B2, 0x008A, NES_SOUND }, { 0x3193C, 0x0011, NES_SOUND }, { 0x3194D, 0x000F, NES_SOUND }, { 0x3195C, 0x00A2, NES_SOUND },
+ { 0x319FE, 0x00D3, NES_SOUND }, { 0x31AD1, 0x0097, NES_SOUND }, { 0x2BFEF, 0x000F, NES_SOUND }, { 0x3195C, 0x00A2, NES_SOUND }, { 0x31B68, 0x05D1, NES_SOUND },
+ { 0x31B68, 0x05D1, NES_SOUND }, { 0x32139, 0x0011, NES_SOUND }, { 0x0FFE8, 0x000A, NES_SOUND }, { 0x2FD90, 0x0075, NES_SOUND }, { 0x27ED4, 0x001F, NES_SOUND },
+ { 0x3214A, 0x098E, NES_SOUND }, { 0x3181B, 0x004B, NES_SOUND }, { 0x32AD8, 0x0011, NES_SOUND }, { 0x30ECA, 0x0832, NES_SOUND }, { 0x32AE9, 0x000F, NES_SOUND },
+ { 0x32AF8, 0x002F, NES_SOUND }, { 0x32B27, 0x001D, NES_SOUND }, { 0x32B44, 0x0018, NES_SOUND }, { 0x32B5C, 0x0016, NES_SOUND }, { 0x32B72, 0x001B, NES_SOUND },
+ { 0x32B8D, 0x0088, NES_SOUND }, { 0x32C15, 0x0065, NES_SOUND }, { 0x32C7A, 0x0065, NES_SOUND }, { 0x32CDF, 0x0073, NES_SOUND }, { 0x32D52, 0x00F9, NES_SOUND },
+ { 0x32E4B, 0x049E, NES_SOUND }, { 0x34001, 0x0EA8, NES_SOUND }, { 0x332E9, 0x0B18, NES_SOUND }, { 0x34EA9, 0x0B9C, NES_SOUND }, { 0x35A45, 0x0C6B, NES_SOUND },
+ { 0x366B0, 0x0E56, NES_SOUND }, { 0x38001, 0x0C70, NES_SOUND }, { 0x38C71, 0x0DEC, NES_SOUND }, { 0x39A5D, 0x0B77, NES_SOUND }, { 0x37506, 0x042F, NES_SOUND },
+ { 0x3A5D4, 0x0AC5, NES_SOUND }, { 0x3B099, 0x0BE4, NES_SOUND }
+};
+static const ScummNESFile::Resource res_sounds_eur[82] = {
+ { 0x0BF54, 0x000A, NES_SOUND }, { 0x30ECA, 0x0832, NES_SOUND }, { 0x30ECA, 0x0832, NES_SOUND }, { 0x30ECA, 0x0832, NES_SOUND }, { 0x30ECA, 0x0832, NES_SOUND },
+ { 0x30ECA, 0x0832, NES_SOUND }, { 0x0BF5E, 0x0011, NES_SOUND }, { 0x27ECB, 0x0073, NES_SOUND }, { 0x0BF6F, 0x0011, NES_SOUND }, { 0x0FF5D, 0x0011, NES_SOUND },
+ { 0x316FC, 0x0056, NES_SOUND }, { 0x13F4E, 0x001F, NES_SOUND }, { 0x0FF6E, 0x0011, NES_SOUND }, { 0x13F6D, 0x000A, NES_SOUND }, { 0x1BF47, 0x000A, NES_SOUND },
+ { 0x1BF51, 0x0019, NES_SOUND }, { 0x31752, 0x004B, NES_SOUND }, { 0x1BF6A, 0x000A, NES_SOUND }, { 0x27F3E, 0x000F, NES_SOUND }, { 0x27F4D, 0x001D, NES_SOUND },
+ { 0x3179D, 0x0045, NES_SOUND }, { 0x27F6A, 0x000F, NES_SOUND }, { 0x2BF40, 0x001B, NES_SOUND }, { 0x317E2, 0x0033, NES_SOUND }, { 0x2BF5B, 0x0011, NES_SOUND },
+ { 0x2BF6C, 0x000F, NES_SOUND }, { 0x31815, 0x0075, NES_SOUND }, { 0x2FF6C, 0x0014, NES_SOUND }, { 0x0BF54, 0x000A, NES_SOUND }, { 0x3188A, 0x00FF, NES_SOUND },
+ { 0x31989, 0x000F, NES_SOUND }, { 0x31998, 0x000F, NES_SOUND }, { 0x319A7, 0x0092, NES_SOUND }, { 0x319A7, 0x0092, NES_SOUND }, { 0x31A39, 0x002D, NES_SOUND },
+ { 0x31A66, 0x00F8, NES_SOUND }, { 0x31B5E, 0x0016, NES_SOUND }, { 0x31B74, 0x0011, NES_SOUND }, { 0x31B85, 0x004B, NES_SOUND }, { 0x31BD0, 0x0011, NES_SOUND },
+ { 0x31BE1, 0x003B, NES_SOUND }, { 0x31C1C, 0x008A, NES_SOUND }, { 0x31CA6, 0x0011, NES_SOUND }, { 0x31CB7, 0x000F, NES_SOUND }, { 0x31CC6, 0x00A2, NES_SOUND },
+ { 0x31D68, 0x00D3, NES_SOUND }, { 0x31E3B, 0x0097, NES_SOUND }, { 0x2BF6C, 0x000F, NES_SOUND }, { 0x31CC6, 0x00A2, NES_SOUND }, { 0x31ED2, 0x05D1, NES_SOUND },
+ { 0x31ED2, 0x05D1, NES_SOUND }, { 0x324A3, 0x0011, NES_SOUND }, { 0x0BF54, 0x000A, NES_SOUND }, { 0x31815, 0x0075, NES_SOUND }, { 0x13F4E, 0x001F, NES_SOUND },
+ { 0x324B4, 0x098E, NES_SOUND }, { 0x31B85, 0x004B, NES_SOUND }, { 0x32E42, 0x0011, NES_SOUND }, { 0x30ECA, 0x0832, NES_SOUND }, { 0x32E53, 0x000F, NES_SOUND },
+ { 0x32E62, 0x002F, NES_SOUND }, { 0x32E91, 0x001D, NES_SOUND }, { 0x32EAE, 0x0018, NES_SOUND }, { 0x32EC6, 0x0016, NES_SOUND }, { 0x32EDC, 0x001B, NES_SOUND },
+ { 0x32EF7, 0x0088, NES_SOUND }, { 0x32F7F, 0x0065, NES_SOUND }, { 0x32FE4, 0x0065, NES_SOUND }, { 0x33049, 0x0073, NES_SOUND }, { 0x330BC, 0x00F9, NES_SOUND },
+ { 0x331B5, 0x049E, NES_SOUND }, { 0x34001, 0x0EA8, NES_SOUND }, { 0x34EA9, 0x0B18, NES_SOUND }, { 0x359C1, 0x0B9C, NES_SOUND }, { 0x3655D, 0x0C6B, NES_SOUND },
+ { 0x38001, 0x0E56, NES_SOUND }, { 0x371C8, 0x0C70, NES_SOUND }, { 0x38E57, 0x0DEC, NES_SOUND }, { 0x39C43, 0x0B77, NES_SOUND }, { 0x33653, 0x042F, NES_SOUND },
+ { 0x3A7BA, 0x0AC5, NES_SOUND }, { 0x3B27F, 0x0BE4, NES_SOUND }
+};
+static const ScummNESFile::Resource res_sounds_swe[82] = {
+ { 0x0BF58, 0x000A, NES_SOUND }, { 0x30352, 0x0832, NES_SOUND }, { 0x30352, 0x0832, NES_SOUND }, { 0x30352, 0x0832, NES_SOUND }, { 0x30352, 0x0832, NES_SOUND },
+ { 0x30352, 0x0832, NES_SOUND }, { 0x0BF62, 0x0011, NES_SOUND }, { 0x27E5F, 0x0073, NES_SOUND }, { 0x17F5A, 0x0011, NES_SOUND }, { 0x17F6B, 0x0011, NES_SOUND },
+ { 0x27ED2, 0x0056, NES_SOUND }, { 0x1BF55, 0x001F, NES_SOUND }, { 0x23F66, 0x0011, NES_SOUND }, { 0x0BF73, 0x000A, NES_SOUND }, { 0x1BF74, 0x000A, NES_SOUND },
+ { 0x27F28, 0x0019, NES_SOUND }, { 0x2BF0A, 0x004B, NES_SOUND }, { 0x1FF71, 0x000A, NES_SOUND }, { 0x27F41, 0x000F, NES_SOUND }, { 0x27F50, 0x001D, NES_SOUND },
+ { 0x2FEAA, 0x0045, NES_SOUND }, { 0x27F6D, 0x000F, NES_SOUND }, { 0x2BF55, 0x001B, NES_SOUND }, { 0x2FEEF, 0x0033, NES_SOUND }, { 0x2FF22, 0x0011, NES_SOUND },
+ { 0x2BF70, 0x000F, NES_SOUND }, { 0x30B84, 0x0075, NES_SOUND }, { 0x2FF33, 0x0014, NES_SOUND }, { 0x0BF58, 0x000A, NES_SOUND }, { 0x30BF9, 0x00FF, NES_SOUND },
+ { 0x2FF47, 0x000F, NES_SOUND }, { 0x2FF56, 0x000F, NES_SOUND }, { 0x30CF8, 0x0092, NES_SOUND }, { 0x30CF8, 0x0092, NES_SOUND }, { 0x30D8A, 0x002D, NES_SOUND },
+ { 0x30DB7, 0x00F8, NES_SOUND }, { 0x2FF65, 0x0016, NES_SOUND }, { 0x30EAF, 0x0011, NES_SOUND }, { 0x30EC0, 0x004B, NES_SOUND }, { 0x30F0B, 0x0011, NES_SOUND },
+ { 0x30F1C, 0x003B, NES_SOUND }, { 0x30F57, 0x008A, NES_SOUND }, { 0x30FE1, 0x0011, NES_SOUND }, { 0x30FF2, 0x000F, NES_SOUND }, { 0x31001, 0x00A2, NES_SOUND },
+ { 0x310A3, 0x00D3, NES_SOUND }, { 0x31176, 0x0097, NES_SOUND }, { 0x2BF70, 0x000F, NES_SOUND }, { 0x31001, 0x00A2, NES_SOUND }, { 0x3120D, 0x05D1, NES_SOUND },
+ { 0x3120D, 0x05D1, NES_SOUND }, { 0x317DE, 0x0011, NES_SOUND }, { 0x0BF58, 0x000A, NES_SOUND }, { 0x30B84, 0x0075, NES_SOUND }, { 0x1BF55, 0x001F, NES_SOUND },
+ { 0x317EF, 0x098E, NES_SOUND }, { 0x30EC0, 0x004B, NES_SOUND }, { 0x3217D, 0x0011, NES_SOUND }, { 0x30352, 0x0832, NES_SOUND }, { 0x3218E, 0x000F, NES_SOUND },
+ { 0x3219D, 0x002F, NES_SOUND }, { 0x321CC, 0x001D, NES_SOUND }, { 0x321E9, 0x0018, NES_SOUND }, { 0x32201, 0x0016, NES_SOUND }, { 0x32217, 0x001B, NES_SOUND },
+ { 0x32232, 0x0088, NES_SOUND }, { 0x322BA, 0x0065, NES_SOUND }, { 0x3231F, 0x0065, NES_SOUND }, { 0x32384, 0x0073, NES_SOUND }, { 0x323F7, 0x00F9, NES_SOUND },
+ { 0x324F0, 0x049E, NES_SOUND }, { 0x3298E, 0x0EA8, NES_SOUND }, { 0x34001, 0x0B18, NES_SOUND }, { 0x34B19, 0x0B9C, NES_SOUND }, { 0x356B5, 0x0C6B, NES_SOUND },
+ { 0x36320, 0x0E56, NES_SOUND }, { 0x37176, 0x0C70, NES_SOUND }, { 0x38001, 0x0DEC, NES_SOUND }, { 0x38DED, 0x0B77, NES_SOUND }, { 0x33836, 0x042F, NES_SOUND },
+ { 0x39964, 0x0AC5, NES_SOUND }, { 0x3A429, 0x0BE4, NES_SOUND }
+};
+static const ScummNESFile::Resource res_sounds_fra[82] = {
+ { 0x07F74, 0x000A, NES_SOUND }, { 0x30ECA, 0x0832, NES_SOUND }, { 0x30ECA, 0x0832, NES_SOUND }, { 0x30ECA, 0x0832, NES_SOUND }, { 0x30ECA, 0x0832, NES_SOUND },
+ { 0x30ECA, 0x0832, NES_SOUND }, { 0x0BF6C, 0x0011, NES_SOUND }, { 0x1BEFA, 0x0073, NES_SOUND }, { 0x17F10, 0x0011, NES_SOUND }, { 0x17F21, 0x0011, NES_SOUND },
+ { 0x1FED5, 0x0056, NES_SOUND }, { 0x17F32, 0x001F, NES_SOUND }, { 0x17F51, 0x0011, NES_SOUND }, { 0x0FF76, 0x000A, NES_SOUND }, { 0x17F62, 0x000A, NES_SOUND },
+ { 0x1FF2B, 0x0019, NES_SOUND }, { 0x23E78, 0x004B, NES_SOUND }, { 0x17F6C, 0x000A, NES_SOUND }, { 0x1BF6D, 0x000F, NES_SOUND }, { 0x1FF44, 0x001D, NES_SOUND },
+ { 0x23EC3, 0x0045, NES_SOUND }, { 0x1FF61, 0x000F, NES_SOUND }, { 0x23F08, 0x001B, NES_SOUND }, { 0x23F23, 0x0033, NES_SOUND }, { 0x23F56, 0x0011, NES_SOUND },
+ { 0x1FF70, 0x000F, NES_SOUND }, { 0x27EF4, 0x0075, NES_SOUND }, { 0x23F67, 0x0014, NES_SOUND }, { 0x07F74, 0x000A, NES_SOUND }, { 0x2FB83, 0x00FF, NES_SOUND },
+ { 0x27F69, 0x000F, NES_SOUND }, { 0x2BF70, 0x000F, NES_SOUND }, { 0x2FC82, 0x0092, NES_SOUND }, { 0x2FC82, 0x0092, NES_SOUND }, { 0x2FD14, 0x002D, NES_SOUND },
+ { 0x2FD41, 0x00F8, NES_SOUND }, { 0x2FE39, 0x0016, NES_SOUND }, { 0x2FE4F, 0x0011, NES_SOUND }, { 0x2FE60, 0x004B, NES_SOUND }, { 0x2FEAB, 0x0011, NES_SOUND },
+ { 0x2FEBC, 0x003B, NES_SOUND }, { 0x316FC, 0x008A, NES_SOUND }, { 0x2FEF7, 0x0011, NES_SOUND }, { 0x2FF08, 0x000F, NES_SOUND }, { 0x31786, 0x00A2, NES_SOUND },
+ { 0x31828, 0x00D3, NES_SOUND }, { 0x318FB, 0x0097, NES_SOUND }, { 0x1FF70, 0x000F, NES_SOUND }, { 0x31786, 0x00A2, NES_SOUND }, { 0x31992, 0x05D1, NES_SOUND },
+ { 0x31992, 0x05D1, NES_SOUND }, { 0x2FF17, 0x0011, NES_SOUND }, { 0x07F74, 0x000A, NES_SOUND }, { 0x27EF4, 0x0075, NES_SOUND }, { 0x17F32, 0x001F, NES_SOUND },
+ { 0x31F63, 0x098E, NES_SOUND }, { 0x2FE60, 0x004B, NES_SOUND }, { 0x2FF28, 0x0011, NES_SOUND }, { 0x30ECA, 0x0832, NES_SOUND }, { 0x2FF39, 0x000F, NES_SOUND },
+ { 0x2FF48, 0x002F, NES_SOUND }, { 0x328F1, 0x001D, NES_SOUND }, { 0x3290E, 0x0018, NES_SOUND }, { 0x32926, 0x0016, NES_SOUND }, { 0x3293C, 0x001B, NES_SOUND },
+ { 0x32957, 0x0088, NES_SOUND }, { 0x329DF, 0x0065, NES_SOUND }, { 0x32A44, 0x0065, NES_SOUND }, { 0x32AA9, 0x0073, NES_SOUND }, { 0x32B1C, 0x00F9, NES_SOUND },
+ { 0x32C15, 0x049E, NES_SOUND }, { 0x330B3, 0x0EA8, NES_SOUND }, { 0x34001, 0x0B18, NES_SOUND }, { 0x34B19, 0x0B9C, NES_SOUND }, { 0x356B5, 0x0C6B, NES_SOUND },
+ { 0x36320, 0x0E56, NES_SOUND }, { 0x37176, 0x0C70, NES_SOUND }, { 0x38001, 0x0DEC, NES_SOUND }, { 0x38DED, 0x0B77, NES_SOUND }, { 0x39964, 0x042F, NES_SOUND },
+ { 0x39D93, 0x0AC5, NES_SOUND }, { 0x3A858, 0x0BE4, NES_SOUND }
+};
+static const ScummNESFile::Resource res_sounds_ger[82] = {
+ { 0x0BF6D, 0x000A, NES_SOUND }, { 0x30ECA, 0x0832, NES_SOUND }, { 0x30ECA, 0x0832, NES_SOUND }, { 0x30ECA, 0x0832, NES_SOUND }, { 0x30ECA, 0x0832, NES_SOUND },
+ { 0x30ECA, 0x0832, NES_SOUND }, { 0x23F05, 0x0011, NES_SOUND }, { 0x2FA49, 0x0073, NES_SOUND }, { 0x23F16, 0x0011, NES_SOUND }, { 0x23F27, 0x0011, NES_SOUND },
+ { 0x2FABC, 0x0056, NES_SOUND }, { 0x23F38, 0x001F, NES_SOUND }, { 0x23F57, 0x0011, NES_SOUND }, { 0x0FF76, 0x000A, NES_SOUND }, { 0x17F71, 0x000A, NES_SOUND },
+ { 0x2BF2F, 0x0019, NES_SOUND }, { 0x2FB12, 0x004B, NES_SOUND }, { 0x23F68, 0x000A, NES_SOUND }, { 0x2BF48, 0x000F, NES_SOUND }, { 0x2BF57, 0x001D, NES_SOUND },
+ { 0x2FB5D, 0x0045, NES_SOUND }, { 0x2FBA2, 0x000F, NES_SOUND }, { 0x2FBB1, 0x001B, NES_SOUND }, { 0x2FBCC, 0x0033, NES_SOUND }, { 0x2FBFF, 0x0011, NES_SOUND },
+ { 0x2FC10, 0x000F, NES_SOUND }, { 0x2FC1F, 0x0075, NES_SOUND }, { 0x2FC94, 0x0014, NES_SOUND }, { 0x0BF6D, 0x000A, NES_SOUND }, { 0x2FCA8, 0x00FF, NES_SOUND },
+ { 0x2FDA7, 0x000F, NES_SOUND }, { 0x2FDB6, 0x000F, NES_SOUND }, { 0x2FDC5, 0x0092, NES_SOUND }, { 0x2FDC5, 0x0092, NES_SOUND }, { 0x2FE57, 0x002D, NES_SOUND },
+ { 0x2FE84, 0x00F8, NES_SOUND }, { 0x316FC, 0x0016, NES_SOUND }, { 0x31712, 0x0011, NES_SOUND }, { 0x31723, 0x004B, NES_SOUND }, { 0x3176E, 0x0011, NES_SOUND },
+ { 0x3177F, 0x003B, NES_SOUND }, { 0x317BA, 0x008A, NES_SOUND }, { 0x31844, 0x0011, NES_SOUND }, { 0x31855, 0x000F, NES_SOUND }, { 0x31864, 0x00A2, NES_SOUND },
+ { 0x31906, 0x00D3, NES_SOUND }, { 0x319D9, 0x0097, NES_SOUND }, { 0x2FC10, 0x000F, NES_SOUND }, { 0x31864, 0x00A2, NES_SOUND }, { 0x31A70, 0x05D1, NES_SOUND },
+ { 0x31A70, 0x05D1, NES_SOUND }, { 0x32041, 0x0011, NES_SOUND }, { 0x0BF6D, 0x000A, NES_SOUND }, { 0x2FC1F, 0x0075, NES_SOUND }, { 0x23F38, 0x001F, NES_SOUND },
+ { 0x32052, 0x098E, NES_SOUND }, { 0x31723, 0x004B, NES_SOUND }, { 0x329E0, 0x0011, NES_SOUND }, { 0x30ECA, 0x0832, NES_SOUND }, { 0x329F1, 0x000F, NES_SOUND },
+ { 0x32A00, 0x002F, NES_SOUND }, { 0x32A2F, 0x001D, NES_SOUND }, { 0x32A4C, 0x0018, NES_SOUND }, { 0x32A64, 0x0016, NES_SOUND }, { 0x32A7A, 0x001B, NES_SOUND },
+ { 0x32A95, 0x0088, NES_SOUND }, { 0x32B1D, 0x0065, NES_SOUND }, { 0x32B82, 0x0065, NES_SOUND }, { 0x32BE7, 0x0073, NES_SOUND }, { 0x32C5A, 0x00F9, NES_SOUND },
+ { 0x32D53, 0x049E, NES_SOUND }, { 0x34001, 0x0EA8, NES_SOUND }, { 0x331F1, 0x0B18, NES_SOUND }, { 0x34EA9, 0x0B9C, NES_SOUND }, { 0x35A45, 0x0C6B, NES_SOUND },
+ { 0x366B0, 0x0E56, NES_SOUND }, { 0x38001, 0x0C70, NES_SOUND }, { 0x38C71, 0x0DEC, NES_SOUND }, { 0x39A5D, 0x0B77, NES_SOUND }, { 0x37506, 0x042F, NES_SOUND },
+ { 0x3A5D4, 0x0AC5, NES_SOUND }, { 0x3B099, 0x0BE4, NES_SOUND }
+};
+static const ScummNESFile::Resource res_sounds_esp[82] = {
+ { 0x13F63, 0x000A, NES_SOUND }, { 0x2F671, 0x0832, NES_SOUND }, { 0x2F671, 0x0832, NES_SOUND }, { 0x2F671, 0x0832, NES_SOUND }, { 0x2F671, 0x0832, NES_SOUND },
+ { 0x2F671, 0x0832, NES_SOUND }, { 0x13F6D, 0x0011, NES_SOUND }, { 0x1FEED, 0x0073, NES_SOUND }, { 0x17F6F, 0x0011, NES_SOUND }, { 0x1BF64, 0x0011, NES_SOUND },
+ { 0x27F19, 0x0056, NES_SOUND }, { 0x1FF60, 0x001F, NES_SOUND }, { 0x27F6F, 0x0011, NES_SOUND }, { 0x1BF75, 0x000A, NES_SOUND }, { 0x2BE6F, 0x000A, NES_SOUND },
+ { 0x2BE79, 0x0019, NES_SOUND }, { 0x2BE92, 0x004B, NES_SOUND }, { 0x2BEDD, 0x000A, NES_SOUND }, { 0x2BEE7, 0x000F, NES_SOUND }, { 0x2BEF6, 0x001D, NES_SOUND },
+ { 0x2BF13, 0x0045, NES_SOUND }, { 0x2BF58, 0x000F, NES_SOUND }, { 0x2FEA3, 0x001B, NES_SOUND }, { 0x2FEBE, 0x0033, NES_SOUND }, { 0x2BF67, 0x0011, NES_SOUND },
+ { 0x2FEF1, 0x000F, NES_SOUND }, { 0x2FF00, 0x0075, NES_SOUND }, { 0x30ECA, 0x0014, NES_SOUND }, { 0x13F63, 0x000A, NES_SOUND }, { 0x30EDE, 0x00FF, NES_SOUND },
+ { 0x30FDD, 0x000F, NES_SOUND }, { 0x30FEC, 0x000F, NES_SOUND }, { 0x30FFB, 0x0092, NES_SOUND }, { 0x30FFB, 0x0092, NES_SOUND }, { 0x3108D, 0x002D, NES_SOUND },
+ { 0x310BA, 0x00F8, NES_SOUND }, { 0x311B2, 0x0016, NES_SOUND }, { 0x311C8, 0x0011, NES_SOUND }, { 0x311D9, 0x004B, NES_SOUND }, { 0x31224, 0x0011, NES_SOUND },
+ { 0x31235, 0x003B, NES_SOUND }, { 0x31270, 0x008A, NES_SOUND }, { 0x312FA, 0x0011, NES_SOUND }, { 0x3130B, 0x000F, NES_SOUND }, { 0x3131A, 0x00A2, NES_SOUND },
+ { 0x313BC, 0x00D3, NES_SOUND }, { 0x3148F, 0x0097, NES_SOUND }, { 0x2FEF1, 0x000F, NES_SOUND }, { 0x3131A, 0x00A2, NES_SOUND }, { 0x31526, 0x05D1, NES_SOUND },
+ { 0x31526, 0x05D1, NES_SOUND }, { 0x31AF7, 0x0011, NES_SOUND }, { 0x13F63, 0x000A, NES_SOUND }, { 0x2FF00, 0x0075, NES_SOUND }, { 0x1FF60, 0x001F, NES_SOUND },
+ { 0x31B08, 0x098E, NES_SOUND }, { 0x311D9, 0x004B, NES_SOUND }, { 0x32496, 0x0011, NES_SOUND }, { 0x2F671, 0x0832, NES_SOUND }, { 0x324A7, 0x000F, NES_SOUND },
+ { 0x324B6, 0x002F, NES_SOUND }, { 0x324E5, 0x001D, NES_SOUND }, { 0x32502, 0x0018, NES_SOUND }, { 0x3251A, 0x0016, NES_SOUND }, { 0x32530, 0x001B, NES_SOUND },
+ { 0x3254B, 0x0088, NES_SOUND }, { 0x325D3, 0x0065, NES_SOUND }, { 0x32638, 0x0065, NES_SOUND }, { 0x3269D, 0x0073, NES_SOUND }, { 0x32710, 0x00F9, NES_SOUND },
+ { 0x32809, 0x049E, NES_SOUND }, { 0x32CA7, 0x0EA8, NES_SOUND }, { 0x34001, 0x0B18, NES_SOUND }, { 0x34B19, 0x0B9C, NES_SOUND }, { 0x356B5, 0x0C6B, NES_SOUND },
+ { 0x36320, 0x0E56, NES_SOUND }, { 0x37176, 0x0C70, NES_SOUND }, { 0x38001, 0x0DEC, NES_SOUND }, { 0x38DED, 0x0B77, NES_SOUND }, { 0x33B4F, 0x042F, NES_SOUND },
+ { 0x39964, 0x0AC5, NES_SOUND }, { 0x3A429, 0x0BE4, NES_SOUND }
+};
+
+static const ScummNESFile::Resource *res_sounds[ScummNESFile::kROMsetNum] = {
+ res_sounds_usa,
+ res_sounds_eur,
+ res_sounds_swe,
+ res_sounds_fra,
+ res_sounds_ger,
+ res_sounds_esp,
+};
+
+static const ScummNESFile::Resource res_costumes_usa[25] = {
+ { 0x17F05, 0x0055, NES_COSTUME }, { 0x17F05, 0x0055, NES_COSTUME }, { 0x17F05, 0x0055, NES_COSTUME }, { 0x17F05, 0x0055, NES_COSTUME }, { 0x17F05, 0x0055, NES_COSTUME },
+ { 0x17F05, 0x0055, NES_COSTUME }, { 0x17F05, 0x0055, NES_COSTUME }, { 0x17F05, 0x0055, NES_COSTUME }, { 0x13FAB, 0x004B, NES_COSTUME }, { 0x17F05, 0x0055, NES_COSTUME },
+ { 0x17F05, 0x0055, NES_COSTUME }, { 0x17F05, 0x0055, NES_COSTUME }, { 0x17F5A, 0x0036, NES_COSTUME }, { 0x17F90, 0x003A, NES_COSTUME }, { 0x17F90, 0x003A, NES_COSTUME },
+ { 0x17F05, 0x0055, NES_COSTUME }, { 0x1BF87, 0x003B, NES_COSTUME }, { 0x17F05, 0x0055, NES_COSTUME }, { 0x23FA9, 0x0045, NES_COSTUME }, { 0x1FFBD, 0x0040, NES_COSTUME },
+ { 0x1BFC2, 0x003C, NES_COSTUME }, { 0x17F90, 0x003A, NES_COSTUME }, { 0x17F90, 0x003A, NES_COSTUME }, { 0x17F05, 0x0055, NES_COSTUME }, { 0x13FAB, 0x004B, NES_COSTUME }
+};
+static const ScummNESFile::Resource res_costumes_eur[25] = {
+ { 0x0BEFF, 0x0055, NES_COSTUME }, { 0x0BEFF, 0x0055, NES_COSTUME }, { 0x0BEFF, 0x0055, NES_COSTUME }, { 0x0BEFF, 0x0055, NES_COSTUME }, { 0x0BEFF, 0x0055, NES_COSTUME },
+ { 0x0BEFF, 0x0055, NES_COSTUME }, { 0x0BEFF, 0x0055, NES_COSTUME }, { 0x0BEFF, 0x0055, NES_COSTUME }, { 0x0FEA2, 0x004B, NES_COSTUME }, { 0x0BEFF, 0x0055, NES_COSTUME },
+ { 0x0BEFF, 0x0055, NES_COSTUME }, { 0x0BEFF, 0x0055, NES_COSTUME }, { 0x0FEED, 0x0036, NES_COSTUME }, { 0x0FF23, 0x003A, NES_COSTUME }, { 0x0FF23, 0x003A, NES_COSTUME },
+ { 0x0BEFF, 0x0055, NES_COSTUME }, { 0x13F13, 0x003B, NES_COSTUME }, { 0x0BEFF, 0x0055, NES_COSTUME }, { 0x23F2F, 0x0045, NES_COSTUME }, { 0x1FF3E, 0x0040, NES_COSTUME },
+ { 0x27E8F, 0x003C, NES_COSTUME }, { 0x0FF23, 0x003A, NES_COSTUME }, { 0x0FF23, 0x003A, NES_COSTUME }, { 0x0BEFF, 0x0055, NES_COSTUME }, { 0x0FEA2, 0x004B, NES_COSTUME }
+};
+static const ScummNESFile::Resource res_costumes_swe[25] = {
+ { 0x0FEF5, 0x0055, NES_COSTUME }, { 0x0FEF5, 0x0055, NES_COSTUME }, { 0x0FEF5, 0x0055, NES_COSTUME }, { 0x0FEF5, 0x0055, NES_COSTUME }, { 0x0FEF5, 0x0055, NES_COSTUME },
+ { 0x0FEF5, 0x0055, NES_COSTUME }, { 0x0FEF5, 0x0055, NES_COSTUME }, { 0x0FEF5, 0x0055, NES_COSTUME }, { 0x17E9A, 0x004B, NES_COSTUME }, { 0x0FEF5, 0x0055, NES_COSTUME },
+ { 0x0FEF5, 0x0055, NES_COSTUME }, { 0x0FEF5, 0x0055, NES_COSTUME }, { 0x0FF4A, 0x0036, NES_COSTUME }, { 0x17EE5, 0x003A, NES_COSTUME }, { 0x17EE5, 0x003A, NES_COSTUME },
+ { 0x0FEF5, 0x0055, NES_COSTUME }, { 0x17F1F, 0x003B, NES_COSTUME }, { 0x0FEF5, 0x0055, NES_COSTUME }, { 0x1BE94, 0x0045, NES_COSTUME }, { 0x1BED9, 0x0040, NES_COSTUME },
+ { 0x1BF19, 0x003C, NES_COSTUME }, { 0x17EE5, 0x003A, NES_COSTUME }, { 0x17EE5, 0x003A, NES_COSTUME }, { 0x0FEF5, 0x0055, NES_COSTUME }, { 0x17E9A, 0x004B, NES_COSTUME }
+};
+static const ScummNESFile::Resource res_costumes_fra[25] = {
+ { 0x0BF17, 0x0055, NES_COSTUME }, { 0x0BF17, 0x0055, NES_COSTUME }, { 0x0BF17, 0x0055, NES_COSTUME }, { 0x0BF17, 0x0055, NES_COSTUME }, { 0x0BF17, 0x0055, NES_COSTUME },
+ { 0x0BF17, 0x0055, NES_COSTUME }, { 0x0BF17, 0x0055, NES_COSTUME }, { 0x0BF17, 0x0055, NES_COSTUME }, { 0x13E77, 0x004B, NES_COSTUME }, { 0x0BF17, 0x0055, NES_COSTUME },
+ { 0x0BF17, 0x0055, NES_COSTUME }, { 0x0BF17, 0x0055, NES_COSTUME }, { 0x07F3E, 0x0036, NES_COSTUME }, { 0x13EC2, 0x003A, NES_COSTUME }, { 0x13EC2, 0x003A, NES_COSTUME },
+ { 0x0BF17, 0x0055, NES_COSTUME }, { 0x13EFC, 0x003B, NES_COSTUME }, { 0x0BF17, 0x0055, NES_COSTUME }, { 0x13F37, 0x0045, NES_COSTUME }, { 0x17E94, 0x0040, NES_COSTUME },
+ { 0x17ED4, 0x003C, NES_COSTUME }, { 0x13EC2, 0x003A, NES_COSTUME }, { 0x13EC2, 0x003A, NES_COSTUME }, { 0x0BF17, 0x0055, NES_COSTUME }, { 0x13E77, 0x004B, NES_COSTUME }
+};
+static const ScummNESFile::Resource res_costumes_ger[25] = {
+ { 0x0FEEB, 0x0055, NES_COSTUME }, { 0x0FEEB, 0x0055, NES_COSTUME }, { 0x0FEEB, 0x0055, NES_COSTUME }, { 0x0FEEB, 0x0055, NES_COSTUME }, { 0x0FEEB, 0x0055, NES_COSTUME },
+ { 0x0FEEB, 0x0055, NES_COSTUME }, { 0x0FEEB, 0x0055, NES_COSTUME }, { 0x0FEEB, 0x0055, NES_COSTUME }, { 0x17E6C, 0x004B, NES_COSTUME }, { 0x0FEEB, 0x0055, NES_COSTUME },
+ { 0x0FEEB, 0x0055, NES_COSTUME }, { 0x0FEEB, 0x0055, NES_COSTUME }, { 0x0FF40, 0x0036, NES_COSTUME }, { 0x17EB7, 0x003A, NES_COSTUME }, { 0x17EB7, 0x003A, NES_COSTUME },
+ { 0x0FEEB, 0x0055, NES_COSTUME }, { 0x17EF1, 0x003B, NES_COSTUME }, { 0x0FEEB, 0x0055, NES_COSTUME }, { 0x17F2C, 0x0045, NES_COSTUME }, { 0x1FEFD, 0x0040, NES_COSTUME },
+ { 0x1FF3D, 0x003C, NES_COSTUME }, { 0x17EB7, 0x003A, NES_COSTUME }, { 0x17EB7, 0x003A, NES_COSTUME }, { 0x0FEEB, 0x0055, NES_COSTUME }, { 0x17E6C, 0x004B, NES_COSTUME }
+};
+static const ScummNESFile::Resource res_costumes_esp[25] = {
+ { 0x0FEF1, 0x0055, NES_COSTUME }, { 0x0FEF1, 0x0055, NES_COSTUME }, { 0x0FEF1, 0x0055, NES_COSTUME }, { 0x0FEF1, 0x0055, NES_COSTUME }, { 0x0FEF1, 0x0055, NES_COSTUME },
+ { 0x0FEF1, 0x0055, NES_COSTUME }, { 0x0FEF1, 0x0055, NES_COSTUME }, { 0x0FEF1, 0x0055, NES_COSTUME }, { 0x13EA3, 0x004B, NES_COSTUME }, { 0x0FEF1, 0x0055, NES_COSTUME },
+ { 0x0FEF1, 0x0055, NES_COSTUME }, { 0x0FEF1, 0x0055, NES_COSTUME }, { 0x0FF46, 0x0036, NES_COSTUME }, { 0x13EEE, 0x003A, NES_COSTUME }, { 0x13EEE, 0x003A, NES_COSTUME },
+ { 0x0FEF1, 0x0055, NES_COSTUME }, { 0x13F28, 0x003B, NES_COSTUME }, { 0x0FEF1, 0x0055, NES_COSTUME }, { 0x17F2A, 0x0045, NES_COSTUME }, { 0x1FE71, 0x0040, NES_COSTUME },
+ { 0x1FEB1, 0x003C, NES_COSTUME }, { 0x13EEE, 0x003A, NES_COSTUME }, { 0x13EEE, 0x003A, NES_COSTUME }, { 0x0FEF1, 0x0055, NES_COSTUME }, { 0x13EA3, 0x004B, NES_COSTUME }
+};
+
+static const ScummNESFile::Resource *res_costumes[ScummNESFile::kROMsetNum] = {
+ res_costumes_usa,
+ res_costumes_eur,
+ res_costumes_swe,
+ res_costumes_fra,
+ res_costumes_ger,
+ res_costumes_esp,
+};
+
+static const ScummNESFile::Resource res_globdata_usa[1] = { { 0x2CA11, 0x0307, NES_GLOBDATA } };
+static const ScummNESFile::Resource res_globdata_eur[1] = { { 0x2CA11, 0x0307, NES_GLOBDATA } };
+static const ScummNESFile::Resource res_globdata_swe[1] = { { 0x2C001, 0x0307, NES_GLOBDATA } };
+static const ScummNESFile::Resource res_globdata_fra[1] = { { 0x2C628, 0x0307, NES_GLOBDATA } };
+static const ScummNESFile::Resource res_globdata_ger[1] = { { 0x2C4EE, 0x0307, NES_GLOBDATA } };
+static const ScummNESFile::Resource res_globdata_esp[1] = { { 0x2C001, 0x0307, NES_GLOBDATA } };
+
+static const ScummNESFile::Resource *res_globdata[ScummNESFile::kROMsetNum] = {
+ res_globdata_usa,
+ res_globdata_eur,
+ res_globdata_swe,
+ res_globdata_fra,
+ res_globdata_ger,
+ res_globdata_esp,
+};
+
+// sprite palette data
+static const ScummNESFile::Resource res_sprpals_usa[2] = { { 0x0BFC1, 0x0010, NES_SPRPALS }, { 0x0BFD1, 0x0010, NES_SPRPALS } };
+static const ScummNESFile::Resource res_sprpals_eur[2] = { { 0x07F61, 0x0010, NES_SPRPALS }, { 0x0BEB2, 0x0010, NES_SPRPALS } };
+static const ScummNESFile::Resource res_sprpals_swe[2] = { { 0x07F55, 0x0010, NES_SPRPALS }, { 0x07F65, 0x0010, NES_SPRPALS } };
+static const ScummNESFile::Resource res_sprpals_fra[2] = { { 0x07ED8, 0x0010, NES_SPRPALS }, { 0x07EE8, 0x0010, NES_SPRPALS } };
+static const ScummNESFile::Resource res_sprpals_ger[2] = { { 0x07F6B, 0x0010, NES_SPRPALS }, { 0x0BF17, 0x0010, NES_SPRPALS } };
+static const ScummNESFile::Resource res_sprpals_esp[2] = { { 0x0BF15, 0x0010, NES_SPRPALS }, { 0x0BF25, 0x0010, NES_SPRPALS } };
+
+static const ScummNESFile::Resource *res_sprpals[ScummNESFile::kROMsetNum] = {
+ res_sprpals_usa,
+ res_sprpals_eur,
+ res_sprpals_swe,
+ res_sprpals_fra,
+ res_sprpals_ger,
+ res_sprpals_esp,
+};
+
+// associates costume IDs with sprite sets (indexes into SPRLENS/SPROFFS)
+static const ScummNESFile::Resource res_sprdesc_usa[2] = { { 0x0FFB7, 0x0031, NES_SPRDESC }, { 0x0BFE1, 0x0009, NES_SPRDESC } };
+static const ScummNESFile::Resource res_sprdesc_eur[2] = { { 0x0BEC2, 0x0031, NES_SPRDESC }, { 0x07F71, 0x0009, NES_SPRDESC } };
+static const ScummNESFile::Resource res_sprdesc_swe[2] = { { 0x0BF1B, 0x0031, NES_SPRDESC }, { 0x07F75, 0x0009, NES_SPRDESC } };
+static const ScummNESFile::Resource res_sprdesc_fra[2] = { { 0x07EF8, 0x0031, NES_SPRDESC }, { 0x07F29, 0x0009, NES_SPRDESC } };
+static const ScummNESFile::Resource res_sprdesc_ger[2] = { { 0x0BF27, 0x0031, NES_SPRDESC }, { 0x0BF58, 0x0009, NES_SPRDESC } };
+static const ScummNESFile::Resource res_sprdesc_esp[2] = { { 0x0BF35, 0x0031, NES_SPRDESC }, { 0x0BF66, 0x0009, NES_SPRDESC } };
+
+static const ScummNESFile::Resource *res_sprdesc[ScummNESFile::kROMsetNum] = {
+ res_sprdesc_usa,
+ res_sprdesc_eur,
+ res_sprdesc_swe,
+ res_sprdesc_fra,
+ res_sprdesc_ger,
+ res_sprdesc_esp,
+};
+
+// number of sprites in each set (indicates length within SPRDATA)
+static const ScummNESFile::Resource res_sprlens_usa[2] = { { 0x0FEA2, 0x0115, NES_SPRLENS }, { 0x07FF5, 0x0006, NES_SPRLENS } };
+static const ScummNESFile::Resource res_sprlens_eur[2] = { { 0x1BE32, 0x0115, NES_SPRLENS }, { 0x07F5B, 0x0006, NES_SPRLENS } };
+static const ScummNESFile::Resource res_sprlens_swe[2] = { { 0x13E6A, 0x0115, NES_SPRLENS }, { 0x07F4F, 0x0006, NES_SPRLENS } };
+static const ScummNESFile::Resource res_sprlens_fra[2] = { { 0x0FE61, 0x0115, NES_SPRLENS }, { 0x07ED2, 0x0006, NES_SPRLENS } };
+static const ScummNESFile::Resource res_sprlens_ger[2] = { { 0x2BE1A, 0x0115, NES_SPRLENS }, { 0x07F65, 0x0006, NES_SPRLENS } };
+static const ScummNESFile::Resource res_sprlens_esp[2] = { { 0x2EFE1, 0x0115, NES_SPRLENS }, { 0x07F7A, 0x0006, NES_SPRLENS } };
+
+static const ScummNESFile::Resource *res_sprlens[ScummNESFile::kROMsetNum] = {
+ res_sprlens_usa,
+ res_sprlens_eur,
+ res_sprlens_swe,
+ res_sprlens_fra,
+ res_sprlens_ger,
+ res_sprlens_esp,
+};
+
+// offset of each sprite set (indexes into SPRDATA)
+static const ScummNESFile::Resource res_sproffs_usa[2] = { { 0x2BDC5, 0x022A, NES_SPROFFS }, { 0x0BFEA, 0x000C, NES_SPROFFS } };
+static const ScummNESFile::Resource res_sproffs_eur[2] = { { 0x2FD42, 0x022A, NES_SPROFFS }, { 0x0BEF3, 0x000C, NES_SPROFFS } };
+static const ScummNESFile::Resource res_sproffs_swe[2] = { { 0x2BCE0, 0x022A, NES_SPROFFS }, { 0x0BF4C, 0x000C, NES_SPROFFS } };
+static const ScummNESFile::Resource res_sproffs_fra[2] = { { 0x2F959, 0x022A, NES_SPROFFS }, { 0x07F32, 0x000C, NES_SPROFFS } };
+static const ScummNESFile::Resource res_sproffs_ger[2] = { { 0x2F81F, 0x022A, NES_SPROFFS }, { 0x0BF61, 0x000C, NES_SPROFFS } };
+static const ScummNESFile::Resource res_sproffs_esp[2] = { { 0x2F447, 0x022A, NES_SPROFFS }, { 0x0BF6F, 0x000C, NES_SPROFFS } };
+
+static const ScummNESFile::Resource *res_sproffs[ScummNESFile::kROMsetNum] = {
+ res_sproffs_usa,
+ res_sproffs_eur,
+ res_sproffs_swe,
+ res_sproffs_fra,
+ res_sproffs_ger,
+ res_sproffs_esp,
+};
+
+// sprite data sets (packed NES sprite data)
+static const ScummNESFile::Resource res_sprdata_usa[2] = { { 0x2CE11, 0x2BE0, NES_SPRDATA }, { 0x07F6B, 0x008A, NES_SPRDATA } };
+static const ScummNESFile::Resource res_sprdata_eur[2] = { { 0x2CE11, 0x2BE0, NES_SPRDATA }, { 0x0BE28, 0x008A, NES_SPRDATA } };
+static const ScummNESFile::Resource res_sprdata_swe[2] = { { 0x2C401, 0x2BE0, NES_SPRDATA }, { 0x0FE6B, 0x008A, NES_SPRDATA } };
+static const ScummNESFile::Resource res_sprdata_fra[2] = { { 0x2CA28, 0x2BE0, NES_SPRDATA }, { 0x07E48, 0x008A, NES_SPRDATA } };
+static const ScummNESFile::Resource res_sprdata_ger[2] = { { 0x2C8EE, 0x2BE0, NES_SPRDATA }, { 0x0FE61, 0x008A, NES_SPRDATA } };
+static const ScummNESFile::Resource res_sprdata_esp[2] = { { 0x2C401, 0x2BE0, NES_SPRDATA }, { 0x0FE67, 0x008A, NES_SPRDATA } };
+static const ScummNESFile::Resource *res_sprdata[ScummNESFile::kROMsetNum] = {
+ res_sprdata_usa,
+ res_sprdata_eur,
+ res_sprdata_swe,
+ res_sprdata_fra,
+ res_sprdata_ger,
+ res_sprdata_esp,
+};
+
+static const ScummNESFile::Resource res_charset_usa[1] = { { 0x3F6EE, 0x0090, NES_CHARSET } };
+static const ScummNESFile::Resource res_charset_eur[1] = { { 0x3F724, 0x0090, NES_CHARSET } };
+static const ScummNESFile::Resource res_charset_swe[1] = { { 0x3F739, 0x0090, NES_CHARSET } };
+static const ScummNESFile::Resource res_charset_fra[1] = { { 0x3F739, 0x0090, NES_CHARSET } };
+static const ScummNESFile::Resource res_charset_ger[1] = { { 0x3F739, 0x0090, NES_CHARSET } };
+static const ScummNESFile::Resource res_charset_esp[1] = { { 0x3F739, 0x0090, NES_CHARSET } };
+
+static const ScummNESFile::Resource *res_charset[ScummNESFile::kROMsetNum] = {
+ res_charset_usa,
+ res_charset_eur,
+ res_charset_swe,
+ res_charset_fra,
+ res_charset_ger,
+ res_charset_esp,
+};
+
+static const ScummNESFile::Resource res_preplist_usa[1] = { { 0x3FB5A, 0x000E, NES_PREPLIST } };
+static const ScummNESFile::Resource res_preplist_eur[1] = { { 0x3FB90, 0x000E, NES_PREPLIST } };
+static const ScummNESFile::Resource res_preplist_swe[1] = { { 0x3FBA9, 0x000E, NES_PREPLIST } };
+static const ScummNESFile::Resource res_preplist_fra[1] = { { 0x3FBAF, 0x0010, NES_PREPLIST } };
+static const ScummNESFile::Resource res_preplist_ger[1] = { { 0x3FBAB, 0x000F, NES_PREPLIST } };
+static const ScummNESFile::Resource res_preplist_esp[1] = { { 0x3FBAE, 0x000F, NES_PREPLIST } };
+
+static const ScummNESFile::Resource *res_preplist[ScummNESFile::kROMsetNum] = {
+ res_preplist_usa,
+ res_preplist_eur,
+ res_preplist_swe,
+ res_preplist_fra,
+ res_preplist_ger,
+ res_preplist_esp,
+};
+
+static uint16 write_byte(Common::WriteStream *out, byte val) {
+ val ^= 0xFF;
+ if (out != 0)
+ out->writeByte(val);
+ return 1;
+}
+
+static uint16 write_word(Common::WriteStream *out, uint16 val) {
+ val ^= 0xFFFF;
+ if (out != 0)
+ out->writeUint16LE(val);
+ return 2;
+}
+
+byte ScummNESFile::fileReadByte() {
+ byte b = 0;
+ File::read(&b, 1);
+ return b;
+}
+
+uint16 ScummNESFile::fileReadUint16LE() {
+ uint16 a = fileReadByte();
+ uint16 b = fileReadByte();
+ return a | (b << 8);
+}
+
+uint16 ScummNESFile::extractResource(Common::WriteStream *output, const Resource *res) {
+ uint16 len, i, j;
+ byte val;
+ byte cnt;
+ uint16 reslen = 0;
+
+ if (res == NULL)
+ error("extract_resource - no resource specified");
+
+ if ((res->offset == 0) && (res->length == 0))
+ return 0; /* there are 8 scripts that are zero bytes long, so we should skip them */
+
+ File::seek(res->offset,SEEK_SET);
+
+ switch (res->type) {
+ case NES_GLOBDATA:
+ len = res->length;
+
+ for (i = 0; i < len; i++)
+ reslen += write_byte(output, fileReadByte());
+
+ break;
+
+ case NES_ROOMGFX:
+ case NES_COSTUMEGFX:
+ reslen += write_word(output, (uint16)(res->length + 2));
+ len = fileReadByte();
+ reslen += write_byte(output, (byte)len);
+
+ if (!len)
+ len = 256;
+ len = len << 4;
+
+ for (i = 0; i < len;) {
+ reslen += write_byte(output, cnt = fileReadByte());
+ for (j = 0; j < (cnt & 0x7F); j++, i++)
+ if ((cnt & 0x80) || (j == 0))
+ reslen += write_byte(output, fileReadByte());
+ }
+
+ if (File::pos() - res->offset != res->length)
+ error("extract_resource - length mismatch while extracting graphics resource (was %04X, should be %04X)", File::pos() - res->offset, res->length);
+
+ break;
+
+ case NES_ROOM:
+ case NES_SCRIPT:
+ len = fileReadUint16LE();
+
+ if (len != res->length)
+ error("extract_resource - length mismatch while extracting room/script resource (was %04X, should be %04X)", len, res->length);
+
+ File::seek(-2, SEEK_CUR);
+
+ for (i = 0; i < len; i++)
+ reslen += write_byte(output, fileReadByte());
+
+ break;
+
+ case NES_SOUND:
+ len = res->length + 2;
+ val = fileReadByte();
+ cnt = fileReadByte();
+
+ if ((val == 2) && (cnt == 100)) {
+ reslen += write_word(output, len);
+ reslen += write_byte(output, val);
+ reslen += write_byte(output, cnt);
+
+ cnt = fileReadByte();
+ reslen += write_byte(output, cnt);
+ for (i = 0; i < cnt; i++)
+ reslen += write_byte(output, fileReadByte());
+ for (i = 0; i < cnt; i++)
+ reslen += write_byte(output, fileReadByte());
+
+ while (1) {
+ reslen += write_byte(output, val = fileReadByte());
+ if (val >= 0xFE)
+ break;
+ }
+ } else if (((val == 0) || (val == 1) || (val == 4)) && (cnt == 10)) {
+ reslen += write_word(output, len);
+ reslen += write_byte(output, val);
+ reslen += write_byte(output, cnt);
+ while (1) {
+ reslen += write_byte(output, val = fileReadByte());
+
+ if (val >= 0xFE)
+ break;
+
+ if (val >= 0x10)
+ reslen += write_byte(output, fileReadByte());
+ else {
+ reslen += write_byte(output, fileReadByte());
+ reslen += write_byte(output, fileReadByte());
+ reslen += write_byte(output, fileReadByte());
+ reslen += write_byte(output, fileReadByte());
+ }
+ }
+ } else
+ error("extract_resource - unknown sound type %d/%d detected",val,cnt);
+
+ if (File::pos() - res->offset != res->length)
+ error("extract_resource - length mismatch while extracting sound resource (was %04X, should be %04X)", File::pos() - res->offset, res->length);
+
+ break;
+
+ case NES_COSTUME:
+ case NES_SPRPALS:
+ case NES_SPRDESC:
+ case NES_SPRLENS:
+ case NES_SPROFFS:
+ case NES_SPRDATA:
+ case NES_CHARSET:
+ len = res->length;
+ reslen += write_word(output, (uint16)(len + 2));
+
+ for (i = 0; i < len; i++)
+ reslen += write_byte(output, fileReadByte());
+
+ break;
+
+ case NES_PREPLIST:
+ len = res->length;
+ reslen += write_word(output, 0x002A);
+
+ reslen += write_byte(output, ' ');
+ for (i = 1; i < 8; i++)
+ reslen += write_byte(output, 0);
+
+ for (j = 0; j < 4; j++) {
+ reslen += write_byte(output,' ');
+ for (i = 1; (val = fileReadByte()); i++)
+ reslen += write_byte(output, val);
+ for (; i < 8; i++)
+ reslen += write_byte(output, 0);
+ }
+ break;
+
+ default:
+ error("extract_resource - unknown resource type %d specified!", res->type);
+ }
+
+ return reslen;
+}
+
+struct ScummNESFile::LFLEntry {
+ const Resource **type;
+ int index;
+};
+
+// based on structure of Classic PC Maniac Mansion LFL files
+// (roomgfx resources are arranged in order, one per file,
+// after the room blocks)
+static const ScummNESFile::LFLEntry lfl_01[] = { {res_rooms, 1}, {res_roomgfx, 1}, {res_scripts, 57}, {res_scripts, 61}, {res_scripts, 76}, {res_scripts, 105}, {res_scripts, 111}, {res_sounds, 5}, {res_scripts, 132}, {res_scripts, 148}, {res_scripts, 155}, {res_scripts, 156}, {res_sounds, 39}, {NULL, 0} };
+static const ScummNESFile::LFLEntry lfl_02[] = { {res_rooms, 2}, {res_roomgfx, 2}, {NULL, 0} };
+static const ScummNESFile::LFLEntry lfl_03[] = { {res_rooms, 3}, {res_roomgfx, 3}, {res_scripts, 21}, {res_sounds, 26}, {NULL, 0} };
+static const ScummNESFile::LFLEntry lfl_04[] = { {res_rooms, 4}, {res_roomgfx, 4}, {res_scripts, 46}, {res_scripts, 56}, {res_scripts, 137}, {res_scripts, 146}, {res_sounds, 12}, {res_sounds, 11}, {res_sounds, 13}, {res_sounds, 42}, {NULL, 0} };
+static const ScummNESFile::LFLEntry lfl_05[] = { {res_rooms, 5}, {res_roomgfx, 5}, {res_scripts, 30}, {res_scripts, 31}, {res_scripts, 32}, {res_scripts, 33}, {res_scripts, 34}, {res_scripts, 35}, {res_sounds, 22}, {res_sounds, 23}, {res_sounds, 24}, {res_sounds, 21}, {res_sounds, 46}, {NULL, 0} };
+static const ScummNESFile::LFLEntry lfl_06[] = { {res_rooms, 6}, {res_roomgfx, 6}, {NULL, 0} };
+static const ScummNESFile::LFLEntry lfl_07[] = { {res_rooms, 7}, {res_roomgfx, 7}, {res_scripts, 17}, {res_scripts, 58}, {res_scripts, 59}, {res_scripts, 60}, {res_scripts, 74}, {res_scripts, 81}, {res_scripts, 82}, {res_scripts, 150}, {res_sounds, 14}, {res_sounds, 15}, {res_sounds, 16}, {res_sounds, 17}, {NULL, 0} };
+static const ScummNESFile::LFLEntry lfl_08[] = { {res_rooms, 8}, {res_roomgfx, 8}, {res_scripts, 7}, {res_scripts, 12}, {res_scripts, 13}, {res_scripts, 47}, {res_scripts, 48}, {res_scripts, 49}, {res_scripts, 154}, {res_sounds, 32}, {res_sounds, 33}, {res_sounds, 36}, {NULL, 0} };
+static const ScummNESFile::LFLEntry lfl_09[] = { {res_rooms, 9}, {res_roomgfx, 9}, {res_scripts, 10}, {res_scripts, 11}, {res_scripts, 45}, {res_scripts, 55}, {res_scripts, 84}, {res_scripts, 85}, {res_scripts, 86}, {NULL, 0} };
+static const ScummNESFile::LFLEntry lfl_10[] = { {res_rooms, 10}, {res_roomgfx, 10}, {res_scripts, 24}, {res_scripts, 149}, {res_sounds, 28}, {NULL, 0} };
+static const ScummNESFile::LFLEntry lfl_11[] = { {res_rooms, 11}, {res_roomgfx, 11}, {res_scripts, 166}, {res_scripts, 167}, {res_scripts, 168}, {NULL, 0} };
+static const ScummNESFile::LFLEntry lfl_12[] = { {res_rooms, 12}, {res_roomgfx, 12}, {res_scripts, 51}, {res_scripts, 103}, {res_scripts, 104}, {res_scripts, 161}, {res_sounds, 63}, {res_costumes, 14}, {NULL, 0} };
+static const ScummNESFile::LFLEntry lfl_13[] = { {res_rooms, 13}, {res_roomgfx, 13}, {NULL, 0} };
+static const ScummNESFile::LFLEntry lfl_14[] = { {res_rooms, 14}, {res_roomgfx, 14}, {NULL, 0} };
+static const ScummNESFile::LFLEntry lfl_15[] = { {res_rooms, 15}, {res_roomgfx, 15}, {res_sounds, 27}, {NULL, 0} };
+static const ScummNESFile::LFLEntry lfl_16[] = { {res_rooms, 16}, {res_roomgfx, 16}, {res_scripts, 14}, {res_scripts, 121}, {res_scripts, 122}, {res_sounds, 40}, {res_sounds, 64}, {res_sounds, 68}, {NULL, 0} };
+static const ScummNESFile::LFLEntry lfl_17[] = { {res_rooms, 17}, {res_roomgfx, 17}, {res_scripts, 20}, {res_scripts, 100}, {res_sounds, 25}, {res_sounds, 44}, {res_sounds, 2}, {res_sounds, 50}, {res_sounds, 52}, {NULL, 0} };
+static const ScummNESFile::LFLEntry lfl_18[] = { {res_rooms, 18}, {res_roomgfx, 18}, {res_scripts, 25}, {res_scripts, 26}, {res_scripts, 27}, {res_scripts, 28}, {res_scripts, 64}, {res_scripts, 65}, {res_scripts, 66}, {res_scripts, 67}, {res_scripts, 68}, {res_scripts, 69}, {res_scripts, 70}, {res_scripts, 71}, {res_scripts, 73}, {res_scripts, 101}, {res_sounds, 35}, {NULL, 0} };
+static const ScummNESFile::LFLEntry lfl_19[] = { {res_rooms, 19}, {res_roomgfx, 19}, {res_scripts, 36}, {res_scripts, 37}, {res_scripts, 38}, {res_scripts, 39}, {res_scripts, 40}, {res_scripts, 152}, {res_scripts, 153}, {res_costumes, 10}, {NULL, 0} };
+static const ScummNESFile::LFLEntry lfl_20[] = { {res_rooms, 20}, {res_roomgfx, 20}, {res_scripts, 107}, {res_scripts, 108}, {res_scripts, 109}, {res_scripts, 110}, {res_scripts, 159}, {NULL, 0} };
+static const ScummNESFile::LFLEntry lfl_21[] = { {res_rooms, 21}, {res_roomgfx, 21}, {res_scripts, 41}, {res_scripts, 42}, {res_scripts, 43}, {res_scripts, 53}, {res_scripts, 136}, {res_sounds, 29}, {res_sounds, 20}, {res_sounds, 37}, {NULL, 0} };
+static const ScummNESFile::LFLEntry lfl_22[] = { {res_rooms, 22}, {res_roomgfx, 22}, {res_scripts, 15}, {NULL, 0} };
+static const ScummNESFile::LFLEntry lfl_23[] = { {res_rooms, 23}, {res_roomgfx, 23}, {res_scripts, 77}, {res_scripts, 79}, {res_scripts, 80}, {res_scripts, 83}, {res_sounds, 41}, {NULL, 0} };
+static const ScummNESFile::LFLEntry lfl_24[] = { {res_rooms, 24}, {res_roomgfx, 24}, {res_scripts, 18}, {res_scripts, 19}, {res_scripts, 78}, {res_sounds, 7}, {res_sounds, 3}, {res_sounds, 18}, {res_sounds, 34}, {res_costumes, 12}, {NULL, 0} };
+static const ScummNESFile::LFLEntry lfl_25[] = { {res_rooms, 25}, {res_roomgfx, 25}, {res_scripts, 29}, {res_sounds, 30}, {res_sounds, 31}, {NULL, 0} };
+static const ScummNESFile::LFLEntry lfl_26[] = { {res_rooms, 26}, {res_roomgfx, 26}, {res_scripts, 87}, {res_scripts, 88}, {res_scripts, 89}, {res_scripts, 90}, {res_scripts, 91}, {res_scripts, 92}, {res_scripts, 93}, {res_scripts, 94}, {res_scripts, 95}, {res_scripts, 96}, {res_scripts, 97}, {res_scripts, 98}, {res_scripts, 116}, {res_scripts, 151}, {res_scripts, 174}, {res_costumes, 11}, {NULL, 0} };
+static const ScummNESFile::LFLEntry lfl_27[] = { {res_rooms, 27}, {res_roomgfx, 27}, {res_scripts, 16}, {res_scripts, 52}, {res_scripts, 54}, {res_scripts, 113}, {res_sounds, 45}, {res_costumes, 19}, {NULL, 0} };
+static const ScummNESFile::LFLEntry lfl_28[] = { {res_rooms, 28}, {res_roomgfx, 28}, {res_scripts, 22}, {res_scripts, 23}, {NULL, 0} };
+static const ScummNESFile::LFLEntry lfl_29[] = { {res_rooms, 29}, {res_roomgfx, 29}, {res_scripts, 75}, {res_sounds, 43}, {NULL, 0} };
+static const ScummNESFile::LFLEntry lfl_30[] = { {res_rooms, 30}, {res_roomgfx, 30}, {res_scripts, 63}, {res_sounds, 0}, {res_scripts, 123}, {res_scripts, 125}, {res_scripts, 126}, {res_scripts, 127}, {res_scripts, 129}, {res_sounds, 55}, {res_sounds, 59}, {res_sounds, 60}, {res_costumes, 8}, {NULL, 0} };
+static const ScummNESFile::LFLEntry lfl_31[] = { {res_rooms, 31}, {res_roomgfx, 31}, {res_scripts, 99}, {res_scripts, 115}, {res_scripts, 117}, {res_scripts, 119}, {res_scripts, 147}, {res_scripts, 157}, {res_scripts, 158}, {res_scripts, 160}, {res_costumes, 13}, {res_costumes, 9}, {res_costumes, 23}, {res_costumes, 24}, {NULL, 0} };
+static const ScummNESFile::LFLEntry lfl_32[] = { {res_rooms, 32}, {res_roomgfx, 32}, {res_costumes, 15}, {NULL, 0} };
+static const ScummNESFile::LFLEntry lfl_33[] = { {res_rooms, 33}, {res_roomgfx, 33}, {res_scripts, 120}, {res_scripts, 135}, {res_sounds, 56}, {res_sounds, 57}, {res_sounds, 58}, {res_sounds, 1}, {res_costumes, 22}, {NULL, 0} };
+static const ScummNESFile::LFLEntry lfl_34[] = { {res_rooms, 34}, {res_roomgfx, 34}, {NULL, 0} };
+static const ScummNESFile::LFLEntry lfl_35[] = { {res_rooms, 35}, {res_roomgfx, 35}, {NULL, 0} };
+static const ScummNESFile::LFLEntry lfl_36[] = { {res_rooms, 36}, {res_roomgfx, 36}, {res_sounds, 10}, {res_sounds, 4}, {NULL, 0} };
+static const ScummNESFile::LFLEntry lfl_37[] = { {res_rooms, 37}, {res_roomgfx, 37}, {NULL, 0} };
+static const ScummNESFile::LFLEntry lfl_38[] = { {res_rooms, 38}, {res_roomgfx, 38}, {res_scripts, 138}, {res_scripts, 139}, {res_scripts, 140}, {res_scripts, 141}, {res_scripts, 142}, {res_scripts, 143}, {res_scripts, 144}, {res_scripts, 145}, {NULL, 0} };
+static const ScummNESFile::LFLEntry lfl_39[] = { {res_rooms, 39}, {res_roomgfx, 39}, {NULL, 0} };
+static const ScummNESFile::LFLEntry lfl_40[] = { {res_rooms, 40}, {res_roomgfx, 0}, {res_scripts, 112}, {res_costumes, 17}, {NULL, 0} };
+static const ScummNESFile::LFLEntry lfl_41[] = { {res_rooms, 41}, {res_scripts, 106}, {res_sounds, 47}, {res_sounds, 48}, {res_sounds, 53}, {res_sounds, 49}, {res_sounds, 51}, {NULL, 0} };
+static const ScummNESFile::LFLEntry lfl_42[] = { {res_rooms, 42}, {res_scripts, 124}, {res_costumes, 18}, {NULL, 0} };
+static const ScummNESFile::LFLEntry lfl_43[] = { {res_rooms, 43}, {res_scripts, 44}, {res_sounds, 19}, {NULL, 0} };
+static const ScummNESFile::LFLEntry lfl_44[] = { {res_rooms, 44}, {res_scripts, 102}, {res_sounds, 6}, {res_sounds, 38}, {res_sounds, 8}, {res_sounds, 9}, {res_costumes, 1}, {res_costumes, 2}, {res_costumes, 5}, {res_costumes, 6}, {res_costumes, 3}, {res_costumes, 4}, {res_costumes, 7}, {NULL, 0} };
+static const ScummNESFile::LFLEntry lfl_45[] = { {res_rooms, 45}, {res_scripts, 1}, {res_scripts, 2}, {res_scripts, 3}, {res_scripts, 4}, {res_scripts, 5}, {res_scripts, 9}, {res_scripts, 114}, {res_scripts, 131}, {res_scripts, 164}, {res_scripts, 165}, {res_scripts, 169}, {res_scripts, 170}, {res_scripts, 171}, {res_scripts, 172}, {res_scripts, 173}, {res_scripts, 175}, {res_sounds, 54}, {NULL, 0} };
+static const ScummNESFile::LFLEntry lfl_46[] = { {res_rooms, 46}, {res_scripts, 130}, {res_sounds, 65}, {res_costumes, 0}, {res_costumes, 21}, {NULL, 0} };
+static const ScummNESFile::LFLEntry lfl_47[] = { {res_rooms, 47}, {res_scripts, 62}, {res_sounds, 69}, {NULL, 0} };
+static const ScummNESFile::LFLEntry lfl_48[] = { {res_rooms, 48}, {NULL, 0} };
+static const ScummNESFile::LFLEntry lfl_49[] = { {res_rooms, 49}, {NULL, 0} };
+static const ScummNESFile::LFLEntry lfl_50[] = { {res_rooms, 50}, {res_scripts, 133}, {res_scripts, 163}, {NULL, 0} };
+static const ScummNESFile::LFLEntry lfl_51[] = { {res_rooms, 51}, {res_scripts, 118}, {res_scripts, 128}, {res_sounds, 61}, {res_sounds, 62}, {res_sounds, 67}, {res_sounds, 66}, {res_costumes, 16}, {res_costumes, 20}, {NULL, 0} };
+static const ScummNESFile::LFLEntry lfl_52[] = { {res_rooms, 52}, {NULL, 0} };
+// remaining 'standard' resources (not used by any of the original LFL files)
+static const ScummNESFile::LFLEntry lfl_53[] = { {res_rooms, 53}, {res_scripts, 177}, {res_scripts, 178}, {res_sounds, 70}, {res_sounds, 71}, {res_sounds, 72}, {res_sounds, 73}, {res_sounds, 74}, {res_sounds, 75}, {res_sounds, 76}, {res_sounds, 77}, {res_sounds, 78}, {res_sounds, 79}, {res_sounds, 80}, {res_sounds, 81}, {NULL, 0} };
+// all 'non-standard' resources (the costume-related stuff)
+static const ScummNESFile::LFLEntry lfl_54[] = { {res_rooms, 54}, {res_sprdesc, 0}, {res_sprdesc, 1}, {res_sprlens, 0}, {res_sprlens, 1}, {res_sproffs, 0}, {res_sproffs, 1}, {res_sprdata, 0}, {res_sprdata, 1}, {res_costumegfx, 0}, {res_costumegfx, 1}, {res_sprpals, 0}, {res_sprpals, 1}, {res_charset, 0}, {res_preplist, 0}, {NULL, 0} };
+
+struct ScummNESFile::LFL {
+ int num;
+ const ScummNESFile::LFLEntry *entries;
+};
+
+static const ScummNESFile::LFL lfls[] = {
+ { 1, lfl_01 },
+ { 2, lfl_02 },
+ { 3, lfl_03 },
+ { 4, lfl_04 },
+ { 5, lfl_05 },
+ { 6, lfl_06 },
+ { 7, lfl_07 },
+ { 8, lfl_08 },
+ { 9, lfl_09 },
+ { 10, lfl_10 },
+ { 11, lfl_11 },
+ { 12, lfl_12 },
+ { 13, lfl_13 },
+ { 14, lfl_14 },
+ { 15, lfl_15 },
+ { 16, lfl_16 },
+ { 17, lfl_17 },
+ { 18, lfl_18 },
+ { 19, lfl_19 },
+ { 20, lfl_20 },
+ { 21, lfl_21 },
+ { 22, lfl_22 },
+ { 23, lfl_23 },
+ { 24, lfl_24 },
+ { 25, lfl_25 },
+ { 26, lfl_26 },
+ { 27, lfl_27 },
+ { 28, lfl_28 },
+ { 29, lfl_29 },
+ { 30, lfl_30 },
+ { 31, lfl_31 },
+ { 32, lfl_32 },
+ { 33, lfl_33 },
+ { 34, lfl_34 },
+ { 35, lfl_35 },
+ { 36, lfl_36 },
+ { 37, lfl_37 },
+ { 38, lfl_38 },
+ { 39, lfl_39 },
+ { 40, lfl_40 },
+ { 41, lfl_41 },
+ { 42, lfl_42 },
+ { 43, lfl_43 },
+ { 44, lfl_44 },
+ { 45, lfl_45 },
+ { 46, lfl_46 },
+ { 47, lfl_47 },
+ { 48, lfl_48 },
+ { 49, lfl_49 },
+ { 50, lfl_50 },
+ { 51, lfl_51 },
+ { 52, lfl_52 },
+ { 53, lfl_53 },
+ { 54, lfl_54 },
+ { -1, NULL }
+};
+
+#include "common/pack-start.h" // START STRUCT PACKING
+
+struct _lfl_index {
+ byte room_lfl[55];
+ uint16 room_addr[55];
+ byte costume_lfl[80];
+ uint16 costume_addr[80];
+ byte script_lfl[200];
+ uint16 script_addr[200];
+ byte sound_lfl[100];
+ uint16 sound_addr[100];
+} PACKED_STRUCT;
+
+#include "common/pack-end.h" // END STRUCT PACKING
+
+_lfl_index lfl_index;
+
+bool ScummNESFile::generateResource(int res) {
+ const LFL *lfl = &lfls[res - 1];
+ int j;
+ int bufsize = 2;
+
+ for (j = 0; lfl->entries[j].type != NULL; j++)
+ bufsize += extractResource(0, &lfl->entries[j].type[_ROMset][lfl->entries[j].index]);
+
+ free(_buf);
+ _buf = (byte *)calloc(1, bufsize);
+
+ Common::MemoryWriteStream out(_buf, bufsize);
+
+ for (j = 0; lfl->entries[j].type != NULL; j++) {
+ const Resource *entry = &lfl->entries[j].type[_ROMset][lfl->entries[j].index];
+ extractResource(&out, entry);
+ }
+ write_byte(&out, 0xD1);
+ write_byte(&out, 0xF5);
+
+ if (_stream)
+ delete _stream;
+
+ _stream = new Common::MemoryReadStream(_buf, bufsize);
+
+ return true;
+}
+
+bool ScummNESFile::generateIndex() {
+ int i, j;
+
+ for (i = 0; lfls[i].num != -1; i++) {
+ const LFL *lfl = &lfls[i];
+ uint16 respos = 0;
+
+ for (j = 0; lfl->entries[j].type != NULL; j++) {
+ const LFLEntry *entry = &lfl->entries[j];
+
+ switch (entry->type[_ROMset][entry->index].type) {
+ case NES_ROOM:
+ lfl_index.room_lfl[entry->index] = lfl->num;
+ lfl_index.room_addr[entry->index] = TO_LE_16(respos);
+ break;
+ case NES_COSTUME:
+ lfl_index.costume_lfl[entry->index] = lfl->num;
+ lfl_index.costume_addr[entry->index] = TO_LE_16(respos);
+ break;
+ case NES_SPRDESC:
+ lfl_index.costume_lfl[entry->index + 25] = lfl->num;
+ lfl_index.costume_addr[entry->index + 25] = TO_LE_16(respos);
+ break;
+ case NES_SPRLENS:
+ lfl_index.costume_lfl[entry->index + 27] = lfl->num;
+ lfl_index.costume_addr[entry->index + 27] = TO_LE_16(respos);
+ break;
+ case NES_SPROFFS:
+ lfl_index.costume_lfl[entry->index + 29] = lfl->num;
+ lfl_index.costume_addr[entry->index + 29] = TO_LE_16(respos);
+ break;
+ case NES_SPRDATA:
+ lfl_index.costume_lfl[entry->index + 31] = lfl->num;
+ lfl_index.costume_addr[entry->index + 31] = TO_LE_16(respos);
+ break;
+ case NES_COSTUMEGFX:
+ lfl_index.costume_lfl[entry->index + 33] = lfl->num;
+ lfl_index.costume_addr[entry->index + 33] = TO_LE_16(respos);
+ break;
+ case NES_SPRPALS:
+ lfl_index.costume_lfl[entry->index + 35] = lfl->num;
+ lfl_index.costume_addr[entry->index + 35] = TO_LE_16(respos);
+ break;
+ case NES_ROOMGFX:
+ lfl_index.costume_lfl[entry->index + 37] = lfl->num;
+ lfl_index.costume_addr[entry->index + 37] = TO_LE_16(respos);
+ break;
+ case NES_SCRIPT:
+ lfl_index.script_lfl[entry->index] = lfl->num;
+ lfl_index.script_addr[entry->index] = TO_LE_16(respos);
+ break;
+ case NES_SOUND:
+ lfl_index.sound_lfl[entry->index] = lfl->num;
+ lfl_index.sound_addr[entry->index] = TO_LE_16(respos);
+ break;
+ case NES_CHARSET:
+ lfl_index.costume_lfl[77] = lfl->num;
+ lfl_index.costume_addr[77] = TO_LE_16(respos);
+ break;
+ case NES_PREPLIST:
+ lfl_index.costume_lfl[78] = lfl->num;
+ lfl_index.costume_addr[78] = TO_LE_16(respos);
+ break;
+ default:
+ error("Unindexed entry found!");
+ break;
+ }
+ respos += extractResource(0, &entry->type[_ROMset][entry->index]);
+ }
+ }
+
+ int bufsize = 2;
+
+ bufsize += 775;
+ bufsize += sizeof(lfl_index);
+
+ free(_buf);
+ _buf = (byte *)calloc(1, bufsize);
+
+ Common::MemoryWriteStream out(_buf, bufsize);
+
+ write_byte(&out, 0x43);
+ write_byte(&out, 0x46);
+
+ extractResource(&out, &res_globdata[_ROMset][0]);
+
+ for (i = 0; i < (int)sizeof(lfl_index); i++)
+ write_byte(&out, ((byte *)&lfl_index)[i]);
+
+ if (_stream)
+ delete _stream;
+
+ _stream = new Common::MemoryReadStream(_buf, bufsize);
+
+ return true;
+}
+
+bool ScummNESFile::open(const Common::String &filename, AccessMode mode) {
+
+ if (_ROMset == kROMsetNum) {
+ char md5str[32+1];
+ if (Common::md5_file_string(filename.c_str(), md5str)) {
+
+ if (!strcmp(md5str, "3905799e081b80a61d4460b7b733c206")) {
+ _ROMset = kROMsetUSA;
+ debug(1, "ROM contents verified as Maniac Mansion (USA)");
+ } else if (!strcmp(md5str, "d8d07efcb88f396bee0b402b10c3b1c9")) {
+ _ROMset = kROMsetEurope;
+ debug(1, "ROM contents verified as Maniac Mansion (Europe)");
+ } else if (!strcmp(md5str, "22d07d6c386c9c25aca5dac2a0c0d94b")) {
+ _ROMset = kROMsetSweden;
+ debug(1, "ROM contents verified as Maniac Mansion (Sweden)");
+ } else if (!strcmp(md5str, "81bbfa181184cb494e7a81dcfa94fbd9")) {
+ _ROMset = kROMsetFrance;
+ debug(2, "ROM contents verified as Maniac Mansion (France)");
+ } else if (!strcmp(md5str, "257f8c14d8c584f7ddd601bcb00920c7")) {
+ _ROMset = kROMsetGermany;
+ debug(2, "ROM contents verified as Maniac Mansion (Germany)");
+ } else if (!strcmp(md5str, "f163cf53f7850e43fb482471e5c52e1a")) {
+ _ROMset = kROMsetSpain;
+ debug(2, "ROM contents verified as Maniac Mansion (Spain)");
+ } else {
+ error("Unsupported Maniac Mansion ROM, md5: %s", md5str);
+ return false;
+ }
+ } else {
+ return false;
+ }
+ }
+
+ if (File::open(filename, mode)) {
+ if (_stream)
+ delete _stream;
+ _stream = 0;
+
+ free(_buf);
+ _buf = 0;
+
+ return true;
+ } else {
+ return false;
+ }
+}
+
+void ScummNESFile::close() {
+ if (_stream)
+ delete _stream;
+ _stream = 0;
+
+ free(_buf);
+ _buf = 0;
+
+ File::close();
+}
+
+bool ScummNESFile::openSubFile(const Common::String &filename) {
+ assert(isOpen());
+
+ const char *ext = strrchr(filename.c_str(), '.');
+ char resNum[3];
+ int res;
+
+ // We always have file name in form of XX.lfl
+ resNum[0] = ext[-2];
+ resNum[1] = ext[-1];
+ resNum[2] = 0;
+
+ res = atoi(resNum);
+
+ if (res == 0) {
+ return generateIndex();
+ } else {
+ return generateResource(res);
+ }
+}
+
+
+} // End of namespace Scumm
diff --git a/engines/scumm/file_nes.h b/engines/scumm/file_nes.h
new file mode 100644
index 0000000000..d601c2c496
--- /dev/null
+++ b/engines/scumm/file_nes.h
@@ -0,0 +1,81 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#ifndef SCUMM_FILE_NES_H
+#define SCUMM_FILE_NES_H
+
+#include "common/file.h"
+
+#include "scumm/file.h"
+
+namespace Scumm {
+
+class ScummNESFile : public BaseScummFile {
+public:
+ enum ROMset {
+ kROMsetUSA,
+ kROMsetEurope,
+ kROMsetSweden,
+ kROMsetFrance,
+ kROMsetGermany,
+ kROMsetSpain,
+ kROMsetNum
+ };
+
+ struct Resource;
+ struct LFLEntry;
+ struct LFL;
+
+private:
+ Common::MemoryReadStream *_stream;
+ ROMset _ROMset;
+ byte *_buf;
+
+ bool generateIndex();
+ bool generateResource(int res);
+ uint16 extractResource(Common::WriteStream *out, const Resource *res);
+
+ byte fileReadByte();
+ uint16 fileReadUint16LE();
+
+public:
+ ScummNESFile();
+ void setEnc(byte value);
+
+ bool open(const Common::String &filename, AccessMode mode = kFileReadMode);
+ bool openSubFile(const Common::String &filename);
+
+ void close();
+ bool eof() { return _stream->eos(); }
+ uint32 pos() { return _stream->pos(); }
+ uint32 size() { return _stream->size(); }
+ void seek(int32 offs, int whence = SEEK_SET) { _stream->seek(offs, whence); }
+ uint32 read(void *dataPtr, uint32 dataSize) { return _stream->read(dataPtr, dataSize); }
+ uint32 write(const void *dataPtr, uint32 dataSize);
+};
+
+} // End of namespace Scumm
+
+#endif
diff --git a/engines/scumm/gfx.cpp b/engines/scumm/gfx.cpp
index c1e06609b9..8d111492a2 100644
--- a/engines/scumm/gfx.cpp
+++ b/engines/scumm/gfx.cpp
@@ -51,6 +51,7 @@ static void copy8Col(byte *dst, int dstPitch, const byte *src, int height);
static void clear8Col(byte *dst, int dstPitch, int height);
static void ditherHerc(byte *src, byte *hercbuf, int srcPitch, int *x, int *y, int *width, int *height);
+static void scale2x(byte *dst, int dstPitch, const byte *src, int srcPitch, int w, int h);
struct StripTable {
int offsets[160];
@@ -90,9 +91,6 @@ struct TransitionEffect {
byte stripTable[16]; // ditto
};
-#ifdef PALMOS_68K
-static const TransitionEffect *transitionEffects;
-#else
static const TransitionEffect transitionEffects[6] = {
// Iris effect (looks like an opening/closing camera iris)
{
@@ -197,7 +195,6 @@ static const TransitionEffect transitionEffects[6] = {
}
};
-#endif
Gdi::Gdi(ScummEngine *vm) : _vm(vm) {
@@ -322,7 +319,7 @@ void ScummEngine::initScreens(int b, int h) {
void ScummEngine::initVirtScreen(VirtScreenNumber slot, int top, int width, int height, bool twobufs,
bool scrollable) {
- VirtScreen *vs = &virtscr[slot];
+ VirtScreen *vs = &_virtscr[slot];
int size;
assert(height >= 0);
@@ -378,7 +375,7 @@ void ScummEngine::initVirtScreen(VirtScreenNumber slot, int top, int width, int
}
VirtScreen *ScummEngine::findVirtScreen(int y) {
- VirtScreen *vs = virtscr;
+ VirtScreen *vs = _virtscr;
int i;
for (i = 0; i < 3; i++, vs++) {
@@ -390,7 +387,7 @@ VirtScreen *ScummEngine::findVirtScreen(int y) {
}
void ScummEngine::markRectAsDirty(VirtScreenNumber virt, int left, int right, int top, int bottom, int dirtybit) {
- VirtScreen *vs = &virtscr[virt];
+ VirtScreen *vs = &_virtscr[virt];
int lp, rp;
if (left > right || top > bottom)
@@ -456,7 +453,7 @@ void ScummEngine::drawDirtyScreenParts() {
// Update game area ("stage")
if (camera._last.x != camera._cur.x || (_game.version >= 7 && (camera._cur.y != camera._last.y))) {
// Camera moved: redraw everything
- VirtScreen *vs = &virtscr[kMainVirtScreen];
+ VirtScreen *vs = &_virtscr[kMainVirtScreen];
drawStripToScreen(vs, 0, vs->w, 0, vs->h);
vs->setDirtyRange(vs->h, 0);
} else {
@@ -501,7 +498,7 @@ void ScummEngine_v6::drawDirtyScreenParts() {
* a full blit is done, otherwise only the visible dirty areas are updated.
*/
void ScummEngine::updateDirtyScreen(VirtScreenNumber slot) {
- VirtScreen *vs = &virtscr[slot];
+ VirtScreen *vs = &_virtscr[slot];
// Do nothing for unused virtual screens
if (vs->h == 0)
@@ -745,7 +742,7 @@ void ditherHerc(byte *src, byte *hercbuf, int srcPitch, int *x, int *y, int *wid
*height = dsty - *y;
}
-void ScummEngine::scale2x(byte *dst, int dstPitch, const byte *src, int srcPitch, int w, int h) {
+void scale2x(byte *dst, int dstPitch, const byte *src, int srcPitch, int w, int h) {
byte *dstL1 = dst;
byte *dstL2 = dst + dstPitch;
@@ -779,7 +776,7 @@ void ScummEngine::initBGBuffers(int height) {
// Resize main virtual screen in V7 games. This is necessary
// because in V7, rooms may be higher than one screen, so we have
// to accomodate for that.
- initVirtScreen(kMainVirtScreen, virtscr[0].topline, _screenWidth, height, true, true);
+ initVirtScreen(kMainVirtScreen, _virtscr[kMainVirtScreen].topline, _screenWidth, height, true, true);
}
if (_game.heversion >= 70)
@@ -903,7 +900,7 @@ void ScummEngine_v71he::redrawBGAreas() {
byte *room = getResourceAddress(rtRoomImage, _roomResource) + _IM00_offs;
if (_fullRedraw) {
_bgNeedsRedraw = false;
- _gdi->drawBMAPBg(room, &virtscr[0]);
+ _gdi->drawBMAPBg(room, &_virtscr[kMainVirtScreen]);
}
drawRoomObjects(0);
@@ -929,7 +926,7 @@ void ScummEngine::redrawBGStrip(int start, int num) {
else
room = getResourceAddress(rtRoom, _roomResource);
- _gdi->drawBitmap(room + _IM00_offs, &virtscr[0], s, 0, _roomWidth, virtscr[0].h, s, num, 0);
+ _gdi->drawBitmap(room + _IM00_offs, &_virtscr[kMainVirtScreen], s, 0, _roomWidth, _virtscr[kMainVirtScreen].h, s, num, 0);
}
void ScummEngine::restoreBackground(Common::Rect rect, byte backColor) {
@@ -987,7 +984,7 @@ void ScummEngine::restoreCharsetBg() {
// restoreBackground(), but was changed to only restore those parts which are
// currently covered by the charset mask.
- VirtScreen *vs = &virtscr[_charset->_textScreenID];
+ VirtScreen *vs = &_virtscr[_charset->_textScreenID];
if (!vs->h)
return;
@@ -1022,7 +1019,7 @@ void ScummEngine::clearTextSurface() {
}
byte *ScummEngine::getMaskBuffer(int x, int y, int z) {
- return _gdi->getMaskBuffer((x + virtscr[0].xstart) / 8, y, z);
+ return _gdi->getMaskBuffer((x + _virtscr[kMainVirtScreen].xstart) / 8, y, z);
}
byte *Gdi::getMaskBuffer(int x, int y, int z) {
@@ -1223,7 +1220,7 @@ void ScummEngine_v5::clearFlashlight() {
void ScummEngine_v5::drawFlashlight() {
int i, j, x, y;
- VirtScreen *vs = &virtscr[kMainVirtScreen];
+ VirtScreen *vs = &_virtscr[kMainVirtScreen];
// Remove the flash light first if it was previously drawn
if (_flashlight.isDrawn) {
@@ -1923,7 +1920,7 @@ void Gdi::drawBMAPObject(const byte *ptr, VirtScreen *vs, int obj, int x, int y,
if (code == 8 || code == 9) {
Common::Rect rScreen(0, 0, vs->w, vs->h);
- byte *dst = (byte *)_vm->virtscr[0].backBuf + scrX;
+ byte *dst = (byte *)_vm->_virtscr[kMainVirtScreen].backBuf + scrX;
Wiz::copyWizImage(dst, bmap_ptr, vs->w, vs->h, x - scrX, y, w, h, &rScreen);
}
@@ -1943,7 +1940,7 @@ void Gdi::drawBMAPObject(const byte *ptr, VirtScreen *vs, int obj, int x, int y,
void ScummEngine_v70he::restoreBackgroundHE(Common::Rect rect, int dirtybit) {
byte *src, *dst;
- VirtScreen *vs = &virtscr[0];
+ VirtScreen *vs = &_virtscr[kMainVirtScreen];
if (rect.top > vs->h || rect.bottom < 0)
return;
@@ -1969,12 +1966,12 @@ void ScummEngine_v70he::restoreBackgroundHE(Common::Rect rect, int dirtybit) {
if (rw == 0 || rh == 0)
return;
- src = virtscr[0].getBackPixels(rect.left, rect.top);
- dst = virtscr[0].getPixels(rect.left, rect.top);
+ src = _virtscr[kMainVirtScreen].getBackPixels(rect.left, rect.top);
+ dst = _virtscr[kMainVirtScreen].getPixels(rect.left, rect.top);
assert(rw <= _screenWidth && rw > 0);
assert(rh <= _screenHeight && rh > 0);
- blit(dst, virtscr[0].pitch, src, virtscr[0].pitch, rw, rh);
+ blit(dst, _virtscr[kMainVirtScreen].pitch, src, _virtscr[kMainVirtScreen].pitch, rw, rh);
markRectAsDirty(kMainVirtScreen, rect, dirtybit);
}
#endif
@@ -1983,7 +1980,7 @@ void ScummEngine_v70he::restoreBackgroundHE(Common::Rect rect, int dirtybit) {
* Reset the background behind an actor or blast object.
*/
void Gdi::resetBackground(int top, int bottom, int strip) {
- VirtScreen *vs = &_vm->virtscr[0];
+ VirtScreen *vs = &_vm->_virtscr[kMainVirtScreen];
byte *backbuff_ptr, *bgbak_ptr;
int numLinesToProcess;
@@ -3162,7 +3159,7 @@ void ScummEngine::fadeIn(int effect) {
// that broke the FOA intro. Probably other things as well.
//
// Hopefully it's safe to do it at this point, at least.
- virtscr[0].setDirtyRange(0, 0);
+ _virtscr[kMainVirtScreen].setDirtyRange(0, 0);
transitionEffect(effect - 1);
break;
case 128:
@@ -3180,7 +3177,7 @@ void ScummEngine::fadeIn(int effect) {
dissolveEffect(1, 1);
break;
case 135:
- dissolveEffect(1, virtscr[0].h);
+ dissolveEffect(1, _virtscr[kMainVirtScreen].h);
break;
default:
error("Unknown screen effect, %d", effect);
@@ -3189,7 +3186,7 @@ void ScummEngine::fadeIn(int effect) {
}
void ScummEngine::fadeOut(int effect) {
- VirtScreen *vs = &virtscr[0];
+ VirtScreen *vs = &_virtscr[kMainVirtScreen];
vs->setDirtyRange(0, 0);
if (_game.version < 7)
@@ -3226,7 +3223,7 @@ void ScummEngine::fadeOut(int effect) {
dissolveEffect(1, 1);
break;
case 135:
- dissolveEffect(1, virtscr[0].h);
+ dissolveEffect(1, _virtscr[kMainVirtScreen].h);
break;
default:
error("fadeOut: default case %d", effect);
@@ -3256,7 +3253,7 @@ void ScummEngine::transitionEffect(int a) {
int i, j;
int bottom;
int l, t, r, b;
- const int height = MIN((int)virtscr[0].h, _screenHeight);
+ const int height = MIN((int)_virtscr[kMainVirtScreen].h, _screenHeight);
const int delay = (VAR_FADE_DELAY != 0xFF) ? VAR(VAR_FADE_DELAY) * kFadeDelay : kPictureDelay;
for (i = 0; i < 16; i++) {
@@ -3278,8 +3275,8 @@ void ScummEngine::transitionEffect(int a) {
if (t == b) {
while (l <= r) {
if (l >= 0 && l < _gdi->_numStrips && t < bottom) {
- virtscr[0].tdirty[l] = _screenTop + t * 8;
- virtscr[0].bdirty[l] = _screenTop + (b + 1) * 8;
+ _virtscr[kMainVirtScreen].tdirty[l] = _screenTop + t * 8;
+ _virtscr[kMainVirtScreen].bdirty[l] = _screenTop + (b + 1) * 8;
}
l++;
}
@@ -3290,8 +3287,8 @@ void ScummEngine::transitionEffect(int a) {
b = bottom;
if (t < 0)
t = 0;
- virtscr[0].tdirty[l] = _screenTop + t * 8;
- virtscr[0].bdirty[l] = _screenTop + (b + 1) * 8;
+ _virtscr[kMainVirtScreen].tdirty[l] = _screenTop + t * 8;
+ _virtscr[kMainVirtScreen].bdirty[l] = _screenTop + (b + 1) * 8;
}
updateDirtyScreen(kMainVirtScreen);
}
@@ -3314,16 +3311,7 @@ void ScummEngine::transitionEffect(int a) {
* dissolveEffect(virtsrc[0].width, 1) produces a line-by-line dissolve
*/
void ScummEngine::dissolveEffect(int width, int height) {
-#ifdef PALMOS_68K
- // Remove this dissolve effect for now on PalmOS since it is a bit
- // too slow using 68k emulation
- if (width == 1 && height == 1) {
- waitForTimer(30);
- return;
- }
-#endif
-
- VirtScreen *vs = &virtscr[0];
+ VirtScreen *vs = &_virtscr[kMainVirtScreen];
int *offsets;
int blits_before_refresh, blits;
int x, y;
@@ -3432,7 +3420,7 @@ void ScummEngine::dissolveEffect(int width, int height) {
}
void ScummEngine::scrollEffect(int dir) {
- VirtScreen *vs = &virtscr[0];
+ VirtScreen *vs = &_virtscr[kMainVirtScreen];
int x, y;
int step;
@@ -3557,15 +3545,3 @@ void ScummEngine::unkScreenEffect6() {
} // End of namespace Scumm
-#ifdef PALMOS_68K
-#include "scumm_globals.h"
-
-_GINIT(Gfx)
-_GSETPTR(Scumm::transitionEffects, GBVARS_TRANSITIONEFFECTS_INDEX, Scumm::TransitionEffect, GBVARS_SCUMM)
-_GEND
-
-_GRELEASE(Gfx)
-_GRELEASEPTR(GBVARS_TRANSITIONEFFECTS_INDEX, GBVARS_SCUMM)
-_GEND
-
-#endif
diff --git a/engines/scumm/gfx.h b/engines/scumm/gfx.h
index fb8da562c8..4e92fad0fd 100644
--- a/engines/scumm/gfx.h
+++ b/engines/scumm/gfx.h
@@ -84,7 +84,7 @@ enum VirtScreenNumber {
struct VirtScreen : Graphics::Surface {
/**
* The unique id of this screen (corresponds to its position in the
- * ScummEngine:virtscr array).
+ * ScummEngine:_virtscr array).
*/
VirtScreenNumber number;
diff --git a/engines/scumm/he/animation_he.cpp b/engines/scumm/he/animation_he.cpp
index 3bc2f3e5d7..3c7d742ba2 100644
--- a/engines/scumm/he/animation_he.cpp
+++ b/engines/scumm/he/animation_he.cpp
@@ -89,7 +89,7 @@ void MoviePlayer::handleNextFrame() {
return;
}
- VirtScreen *pvs = &_vm->virtscr[kMainVirtScreen];
+ VirtScreen *pvs = &_vm->_virtscr[kMainVirtScreen];
decodeNextFrame();
diff --git a/engines/scumm/he/floodfill_he.cpp b/engines/scumm/he/floodfill_he.cpp
index 1fdd11fce8..ea2043d69f 100644
--- a/engines/scumm/he/floodfill_he.cpp
+++ b/engines/scumm/he/floodfill_he.cpp
@@ -179,7 +179,7 @@ skip:
void floodFill(FloodFillParameters *ffp, ScummEngine_v90he *vm) {
uint8 *dst;
- VirtScreen *vs = &vm->virtscr[kMainVirtScreen];
+ VirtScreen *vs = &vm->_virtscr[kMainVirtScreen];
if (ffp->flags & 0x8000) {
dst = vs->getBackPixels(0, vs->topline);
} else {
diff --git a/engines/scumm/he/script_v60he.cpp b/engines/scumm/he/script_v60he.cpp
index baee2f3e49..0b9c94fe18 100644
--- a/engines/scumm/he/script_v60he.cpp
+++ b/engines/scumm/he/script_v60he.cpp
@@ -801,7 +801,7 @@ void ScummEngine_v60he::o60_kernelSetFunctions() {
void ScummEngine_v60he::virtScreenLoad(int resIdx, int x1, int y1, int x2, int y2) {
vsUnpackCtx ctx;
memset(&ctx, 0, sizeof(ctx));
- VirtScreen &vs = virtscr[kMainVirtScreen];
+ VirtScreen &vs = _virtscr[kMainVirtScreen];
ArrayHeader *ah = (ArrayHeader *)getResourceAddress(rtString, resIdx);
virtScreenLoadUnpack(&ctx, ah->data);
@@ -875,7 +875,7 @@ void ScummEngine_v60he::o60_kernelGetFunctions() {
int ScummEngine_v60he::virtScreenSave(byte *dst, int x1, int y1, int x2, int y2) {
int packedSize = 0;
- VirtScreen &vs = virtscr[kMainVirtScreen];
+ VirtScreen &vs = _virtscr[kMainVirtScreen];
for (int j = y1; j <= y2; ++j) {
uint8 *p = vs.getBackPixels(x1, j - vs.topline);
diff --git a/engines/scumm/he/sprite_he.cpp b/engines/scumm/he/sprite_he.cpp
index 8e6f3ce4c2..15698dedba 100644
--- a/engines/scumm/he/sprite_he.cpp
+++ b/engines/scumm/he/sprite_he.cpp
@@ -1120,7 +1120,7 @@ void Sprite::resetBackground() {
}
void Sprite::setRedrawFlags(bool checkZOrder) {
- VirtScreen *vs = &_vm->virtscr[kMainVirtScreen];
+ VirtScreen *vs = &_vm->_virtscr[kMainVirtScreen];
for (int i = 0; i < _numSpritesToProcess; ++i) {
SpriteInfo *spi = _activeSpritesTable[i];
if (!(spi->flags & kSFNeedRedraw)) {
diff --git a/engines/scumm/he/wiz_he.cpp b/engines/scumm/he/wiz_he.cpp
index 549e4480f6..a99f3b1ad5 100644
--- a/engines/scumm/he/wiz_he.cpp
+++ b/engines/scumm/he/wiz_he.cpp
@@ -1009,7 +1009,7 @@ static int wizPackType0(uint8 *dst, const uint8 *src, int srcPitch, const Common
void Wiz::captureWizImage(int resNum, const Common::Rect& r, bool backBuffer, int compType) {
debug(5, "ScummEngine_v72he::captureWizImage(%d, %d, [%d,%d,%d,%d])", resNum, compType, r.left, r.top, r.right, r.bottom);
uint8 *src = NULL;
- VirtScreen *pvs = &_vm->virtscr[kMainVirtScreen];
+ VirtScreen *pvs = &_vm->_virtscr[kMainVirtScreen];
if (backBuffer) {
src = pvs->getBackPixels(0, 0);
} else {
@@ -1182,7 +1182,7 @@ uint8 *Wiz::drawWizImage(int resNum, int state, int x1, int y1, int zorder, int
assert(dst);
getWizImageDim(dstResNum, 0, cw, ch);
} else {
- VirtScreen *pvs = &_vm->virtscr[kMainVirtScreen];
+ VirtScreen *pvs = &_vm->_virtscr[kMainVirtScreen];
if (flags & kWIFMarkBufferDirty) {
dst = pvs->getPixels(0, pvs->topline);
} else {
@@ -1377,7 +1377,7 @@ void Wiz::drawWizPolygonTransform(int resNum, int state, Common::Point *wp, int
if (srcWizBuf) {
uint8 *dst;
int32 dstw, dsth, dstpitch, wizW, wizH;
- VirtScreen *pvs = &_vm->virtscr[kMainVirtScreen];
+ VirtScreen *pvs = &_vm->_virtscr[kMainVirtScreen];
int transColor = (_vm->VAR_WIZ_TCOLOR != 0xFF) ? _vm->VAR(_vm->VAR_WIZ_TCOLOR) : 5;
if (dstResNum) {
diff --git a/engines/scumm/imuse_digi/dimuse.h b/engines/scumm/imuse_digi/dimuse.h
index dca9baac60..caff9958f3 100644
--- a/engines/scumm/imuse_digi/dimuse.h
+++ b/engines/scumm/imuse_digi/dimuse.h
@@ -237,16 +237,6 @@ struct imuseFtSeqTable {
byte volume;
};
-#ifdef PALMOS_68K
-extern const imuseRoomMap *_digStateMusicMap;
-extern const imuseDigTable *_digStateMusicTable;
-extern const imuseDigTable *_digSeqMusicTable;
-extern const imuseComiTable *_comiStateMusicTable;
-extern const imuseComiTable *_comiSeqMusicTable;
-extern const imuseFtStateTable *_ftStateMusicTable;
-extern const imuseFtSeqTable *_ftSeqMusicTable;
-extern const imuseFtNames *_ftSeqNames;
-#else
extern const imuseRoomMap _digStateMusicMap[];
extern const imuseDigTable _digStateMusicTable[];
extern const imuseDigTable _digSeqMusicTable[];
@@ -255,7 +245,6 @@ extern const imuseComiTable _comiSeqMusicTable[];
extern const imuseFtStateTable _ftStateMusicTable[];
extern const imuseFtSeqTable _ftSeqMusicTable[];
extern const imuseFtNames _ftSeqNames[];
-#endif
} // End of namespace Scumm
diff --git a/engines/scumm/imuse_digi/dimuse_codecs.cpp b/engines/scumm/imuse_digi/dimuse_codecs.cpp
index 17082f5256..b79c7111f9 100644
--- a/engines/scumm/imuse_digi/dimuse_codecs.cpp
+++ b/engines/scumm/imuse_digi/dimuse_codecs.cpp
@@ -62,9 +62,6 @@ uint32 decode12BitsSample(const byte *src, byte **dst, uint32 size) {
static byte _imcTableEntryBitCount[89];
-#ifdef PALMOS_68K
-static const int16 *imcTable;
-#else
static const int16 imcTable[89] = {
7, 8, 9, 10, 11, 12, 13, 14,
16, 17, 19, 21, 23, 25, 28, 31,
@@ -79,7 +76,6 @@ static const int16 imcTable[89] = {
15289,16818,18500,20350,22385,24623,27086,29794,
32767
};
-#endif
static const byte imxOtherTable[6][64] = {
{
@@ -651,16 +647,3 @@ int32 decompressCodec(int32 codec, byte *compInput, byte *compOutput, int32 inpu
} // End of namespace BundleCodecs
} // End of namespace Scumm
-
-#ifdef PALMOS_68K
-#include "scumm_globals.h"
-
-_GINIT(DimuseCodecs)
-_GSETPTR(Scumm::BundleCodecs::imcTable, GBVARS_IMCTABLE_INDEX, int16, GBVARS_SCUMM)
-_GEND
-
-_GRELEASE(DimuseCodecs)
-_GRELEASEPTR(GBVARS_IMCTABLE_INDEX, GBVARS_SCUMM)
-_GEND
-
-#endif
diff --git a/engines/scumm/imuse_digi/dimuse_tables.cpp b/engines/scumm/imuse_digi/dimuse_tables.cpp
index 0b014b5f5e..9c56063557 100644
--- a/engines/scumm/imuse_digi/dimuse_tables.cpp
+++ b/engines/scumm/imuse_digi/dimuse_tables.cpp
@@ -27,16 +27,6 @@
namespace Scumm {
-#ifdef PALMOS_68K
-const imuseRoomMap *_digStateMusicMap;
-const imuseDigTable *_digStateMusicTable;
-const imuseDigTable *_digSeqMusicTable;
-const imuseComiTable *_comiStateMusicTable;
-const imuseComiTable *_comiSeqMusicTable;
-const imuseFtStateTable *_ftStateMusicTable;
-const imuseFtSeqTable *_ftSeqMusicTable;
-const imuseFtNames *_ftSeqNames;
-#else
const imuseRoomMap _digStateMusicMap[] = {
{0, 0, 0, 0, 0, 0 },
{1, 0, 0, 0, 0, 0 },
@@ -852,33 +842,5 @@ const imuseFtSeqTable _ftSeqMusicTable[] = {
{"legavox", 2, 127},
{"chances", 2, 90 },
};
-#endif
} // End of namespace Scumm
-
-#ifdef PALMOS_68K
-#include "scumm_globals.h"
-
-_GINIT(DimuseTables)
-_GSETPTR(Scumm::_digStateMusicMap, GBVARS_DIGSTATEMUSICMAP_INDEX, Scumm::imuseRoomMap , GBVARS_SCUMM)
-_GSETPTR(Scumm::_digStateMusicTable, GBVARS_DIGSTATEMUSICTABLE_INDEX, Scumm::imuseDigTable , GBVARS_SCUMM)
-_GSETPTR(Scumm::_digSeqMusicTable, GBVARS_DIGSEQMUSICTABLE_INDEX, Scumm::imuseDigTable , GBVARS_SCUMM)
-_GSETPTR(Scumm::_comiStateMusicTable, GBVARS_COMISTATEMUSICTABLE_INDEX, Scumm::imuseComiTable , GBVARS_SCUMM)
-_GSETPTR(Scumm::_comiSeqMusicTable, GBVARS_COMISEQMUSICTABLE_INDEX, Scumm::imuseComiTable , GBVARS_SCUMM)
-_GSETPTR(Scumm::_ftStateMusicTable, GBVARS_FTSTATEMUSICTABLE_INDEX, Scumm::imuseFtStateTable, GBVARS_SCUMM)
-_GSETPTR(Scumm::_ftSeqMusicTable, GBVARS_FTSEQMUSICTABLE_INDEX, Scumm::imuseFtSeqTable , GBVARS_SCUMM)
-_GSETPTR(Scumm::_ftSeqNames, GBVARS_FTSEQNAMES_INDEX, Scumm::imuseFtNames , GBVARS_SCUMM)
-_GEND
-
-_GRELEASE(DimuseTables)
-_GRELEASEPTR(GBVARS_DIGSTATEMUSICMAP_INDEX , GBVARS_SCUMM)
-_GRELEASEPTR(GBVARS_DIGSTATEMUSICTABLE_INDEX , GBVARS_SCUMM)
-_GRELEASEPTR(GBVARS_DIGSEQMUSICTABLE_INDEX , GBVARS_SCUMM)
-_GRELEASEPTR(GBVARS_COMISTATEMUSICTABLE_INDEX , GBVARS_SCUMM)
-_GRELEASEPTR(GBVARS_COMISEQMUSICTABLE_INDEX , GBVARS_SCUMM)
-_GRELEASEPTR(GBVARS_FTSTATEMUSICTABLE_INDEX , GBVARS_SCUMM)
-_GRELEASEPTR(GBVARS_FTSEQMUSICTABLE_INDEX , GBVARS_SCUMM)
-_GRELEASEPTR(GBVARS_FTSEQNAMES_INDEX , GBVARS_SCUMM)
-_GEND
-
-#endif
diff --git a/engines/scumm/input.cpp b/engines/scumm/input.cpp
index 6647e9fe8d..94fafc78de 100644
--- a/engines/scumm/input.cpp
+++ b/engines/scumm/input.cpp
@@ -249,14 +249,15 @@ void ScummEngine::processInput() {
if (_mouse.y > _screenHeight-1)
_mouse.y = _screenHeight-1;
- _virtualMouse.x = _mouse.x + virtscr[0].xstart;
- _virtualMouse.y = _mouse.y - virtscr[0].topline;
+ VirtScreen *vs = &_virtscr[kMainVirtScreen];
+ _virtualMouse.x = _mouse.x + vs->xstart;
+ _virtualMouse.y = _mouse.y - vs->topline;
if (_game.version >= 7)
_virtualMouse.y += _screenTop;
if (_virtualMouse.y < 0)
_virtualMouse.y = -1;
- if (_virtualMouse.y >= virtscr[0].h)
+ if (_virtualMouse.y >= vs->h)
_virtualMouse.y = -1;
//
diff --git a/engines/scumm/insane/insane.cpp b/engines/scumm/insane/insane.cpp
index 252407913e..af09daff96 100644
--- a/engines/scumm/insane/insane.cpp
+++ b/engines/scumm/insane/insane.cpp
@@ -1169,8 +1169,6 @@ int Insane::smlayer_loadCostume(int id, int phase) {
_vm->ensureResourceLoaded(rtCostume, resid);
_vm->_res->setResourceCounter(rtCostume, resid, 1);
- // smlayer_lock(rtCostume, resid); // FIXME
-
if (phase == 1) {
_objArray1Idx2++;
_objArray1[_objArray1Idx2] = id;
diff --git a/engines/scumm/insane/insane_scenes.cpp b/engines/scumm/insane/insane_scenes.cpp
index 5843e85f0f..0cf6623664 100644
--- a/engines/scumm/insane/insane_scenes.cpp
+++ b/engines/scumm/insane/insane_scenes.cpp
@@ -171,7 +171,7 @@ void Insane::runScene(int arraynum) {
writeArray(339, _enemy[EN_VULTF2].isEmpty);
writeArray(340, _enemy[EN_VULTM2].isEmpty);
}
- // insane_unlock(); // FIXME
+
_vm->_sound->stopAllSounds(); // IMUSE_StopAllSounds();
}
@@ -328,8 +328,7 @@ int Insane::loadSceneData(int scene, int flag, int phase) {
int retvalue = 1;
debugC(DEBUG_INSANE, "Insane::loadSceneData(%d, %d, %d)", scene, flag, phase);
- //if (phase == 1) /// FIXME
- // insane_unlock();
+
switch (scene) {
case 1:
smlayer_loadSound(88, flag, phase);
diff --git a/engines/scumm/module.mk b/engines/scumm/module.mk
index a340f564b3..2d70b167ea 100644
--- a/engines/scumm/module.mk
+++ b/engines/scumm/module.mk
@@ -14,6 +14,7 @@ MODULE_OBJS := \
detection.o \
dialogs.o \
file.o \
+ file_nes.o \
gfx.o \
he/script_v60he.o \
he/sound_he.o \
diff --git a/engines/scumm/object.cpp b/engines/scumm/object.cpp
index a88c56bc5a..128270538d 100644
--- a/engines/scumm/object.cpp
+++ b/engines/scumm/object.cpp
@@ -156,11 +156,14 @@ void ScummEngine::setOwnerOf(int obj, int owner) {
}
void ScummEngine::clearOwnerOf(int obj) {
- int i, j;
+ int i;
uint16 *a;
+ // Stop the associated object script code (else crashes might occurs)
stopObjectScript(obj);
+ // If the object is "owned" by a the current room, we scan the
+ // object list and (only if it's a floating object) nuke it.
if (getOwner(obj) == OF_OWNER_ROOM) {
for (i = 0; i < _numLocalObjects; i++) {
if (_objs[i].obj_nr == obj && _objs[i].fl_object_index) {
@@ -170,26 +173,28 @@ void ScummEngine::clearOwnerOf(int obj) {
_objs[i].fl_object_index = 0;
}
}
- return;
- }
-
- for (i = 0; i < _numInventory; i++) {
- if (_inventory[i] == obj) {
- j = whereIsObject(obj);
- if (j == WIO_INVENTORY) {
+ } else {
+
+ // Alternatively, scan the inventory to see if the object is in there...
+ for (i = 0; i < _numInventory; i++) {
+ if (_inventory[i] == obj) {
+ assert(WIO_INVENTORY == whereIsObject(obj));
+ // Found the object! Nuke it from the inventory.
_res->nukeResource(rtInventory, i);
_inventory[i] = 0;
- }
- a = _inventory;
- for (i = 0; i < _numInventory - 1; i++, a++) {
- if (!a[0] && a[1]) {
- a[0] = a[1];
- a[1] = 0;
- _res->address[rtInventory][i] = _res->address[rtInventory][i + 1];
- _res->address[rtInventory][i + 1] = NULL;
+
+ // Now fill up the gap removing the object from the inventory created.
+ a = _inventory;
+ for (i = 0; i < _numInventory - 1; i++, a++) {
+ if (!_inventory[i] && _inventory[i+1]) {
+ _inventory[i] = _inventory[i+1];
+ _inventory[i+1] = 0;
+ _res->address[rtInventory][i] = _res->address[rtInventory][i + 1];
+ _res->address[rtInventory][i + 1] = NULL;
+ }
}
+ break;
}
- return;
}
}
}
@@ -583,11 +588,7 @@ void ScummEngine::drawObject(int obj, int arg) {
return;
ptr = getOBIMFromObjectData(od);
-
- if (_game.features & GF_OLD_BUNDLE)
- ptr += 0;
- else
- ptr = getObjectImage(ptr, getState(od.obj_nr));
+ ptr = getObjectImage(ptr, getState(od.obj_nr));
if (!ptr)
return;
@@ -619,10 +620,10 @@ void ScummEngine::drawObject(int obj, int arg) {
#ifndef DISABLE_HE
if (_game.heversion >= 70 && findResource(MKID_BE('SMAP'), ptr) == NULL)
- _gdi->drawBMAPObject(ptr, &virtscr[0], obj, od.x_pos, od.y_pos, od.width, od.height);
+ _gdi->drawBMAPObject(ptr, &_virtscr[kMainVirtScreen], obj, od.x_pos, od.y_pos, od.width, od.height);
else
#endif
- _gdi->drawBitmap(ptr, &virtscr[0], x, ypos, width * 8, height, x - xpos, numstrip, flags);
+ _gdi->drawBitmap(ptr, &_virtscr[kMainVirtScreen], x, ypos, width * 8, height, x - xpos, numstrip, flags);
}
}
@@ -1394,7 +1395,9 @@ void ScummEngine::findObjectInRoom(FindObjectInRoom *fo, byte findWhat, uint id,
if (id2 == (uint16)id) {
if (findWhat & foCodeHeader) {
fo->obcd = obcdptr;
- fo->cdhd = (const CodeHeader *)(obcdptr + 10); // TODO - FIXME
+ // We assume that the code header starts at a fixed offset.
+ // A bit hackish, but works reasonably well.
+ fo->cdhd = (const CodeHeader *)(obcdptr + 10);
}
if (findWhat & foImageHeader) {
fo->obim = obimptr;
@@ -1626,7 +1629,7 @@ void ScummEngine_v6::drawBlastObject(BlastObject *eo) {
int objnum;
BompDrawData bdd;
- vs = &virtscr[0];
+ vs = &_virtscr[kMainVirtScreen];
assertRange(30, eo->number, _numGlobalObjects - 1, "blast object");
@@ -1704,7 +1707,7 @@ void ScummEngine_v6::removeBlastObjects() {
}
void ScummEngine_v6::removeBlastObject(BlastObject *eo) {
- VirtScreen *vs = &virtscr[0];
+ VirtScreen *vs = &_virtscr[kMainVirtScreen];
Common::Rect r;
int left_strip, right_strip;
diff --git a/engines/scumm/player_v2.cpp b/engines/scumm/player_v2.cpp
index ae7985011b..82bb2cb4ec 100644
--- a/engines/scumm/player_v2.cpp
+++ b/engines/scumm/player_v2.cpp
@@ -44,16 +44,6 @@ namespace Scumm {
#define FB_WNOISE 0x12000 /* feedback for white noise */
#define FB_PNOISE 0x08000 /* feedback for periodic noise */
-#ifdef PALMOS_68K
-const uint8 *note_lengths;
-static const uint16 *hull_offsets;
-static const int16 *hulls;
-static const uint16 *freqmod_lengths;
-static const uint16 *freqmod_offsets;
-static const int8 *freqmod_table;
-static const uint16 *spk_freq_table;
-static const uint16 *pcjr_freq_table;
-#else
const uint8 note_lengths[] = {
0,
0, 0, 2,
@@ -341,7 +331,6 @@ static const uint16 pcjr_freq_table[12] = {
65472, 61760, 58304, 55040, 52032, 49024,
46272, 43648, 41216, 38912, 36736, 34624
};
-#endif
Player_V2::Player_V2(ScummEngine *scumm, Audio::Mixer *mixer, bool pcjr) {
@@ -977,30 +966,3 @@ void Player_V2::mutex_down() {
}
} // End of namespace Scumm
-
-#ifdef PALMOS_68K
-#include "scumm_globals.h"
-
-_GINIT(PlayerV2)
-_GSETPTR(Scumm::note_lengths, GBVARS_NOTELENGTHS_INDEX, uint8, GBVARS_SCUMM)
-_GSETPTR(Scumm::hull_offsets, GBVARS_HULLOFFSETS_INDEX, uint16, GBVARS_SCUMM)
-_GSETPTR(Scumm::hulls, GBVARS_HULLS_INDEX, int16, GBVARS_SCUMM)
-_GSETPTR(Scumm::freqmod_lengths, GBVARS_FREQMODLENGTHS_INDEX, uint16, GBVARS_SCUMM)
-_GSETPTR(Scumm::freqmod_offsets, GBVARS_FREQMODOFFSETS_INDEX, uint16, GBVARS_SCUMM)
-_GSETPTR(Scumm::freqmod_table, GBVARS_FREQMODTABLE_INDEX, int8, GBVARS_SCUMM)
-_GSETPTR(Scumm::spk_freq_table, GBVARS_SPKFREQTABLE_INDEX, uint16, GBVARS_SCUMM)
-_GSETPTR(Scumm::pcjr_freq_table, GBVARS_PCJRFREQTABLE_INDEX, uint16, GBVARS_SCUMM)
-_GEND
-
-_GRELEASE(PlayerV2)
-_GRELEASEPTR(GBVARS_NOTELENGTHS_INDEX, GBVARS_SCUMM)
-_GRELEASEPTR(GBVARS_HULLOFFSETS_INDEX, GBVARS_SCUMM)
-_GRELEASEPTR(GBVARS_HULLS_INDEX, GBVARS_SCUMM)
-_GRELEASEPTR(GBVARS_FREQMODLENGTHS_INDEX, GBVARS_SCUMM)
-_GRELEASEPTR(GBVARS_FREQMODOFFSETS_INDEX, GBVARS_SCUMM)
-_GRELEASEPTR(GBVARS_FREQMODTABLE_INDEX, GBVARS_SCUMM)
-_GRELEASEPTR(GBVARS_SPKFREQTABLE_INDEX, GBVARS_SCUMM)
-_GRELEASEPTR(GBVARS_PCJRFREQTABLE_INDEX, GBVARS_SCUMM)
-_GEND
-
-#endif
diff --git a/engines/scumm/player_v2a.cpp b/engines/scumm/player_v2a.cpp
index 7096021be9..ceabbc7d95 100644
--- a/engines/scumm/player_v2a.cpp
+++ b/engines/scumm/player_v2a.cpp
@@ -32,20 +32,15 @@ namespace Scumm {
#define BASE_FREQUENCY 3579545
-#ifdef PALMOS_68K
-static uint32 *CRCtable = NULL;
-#else
static uint32 CRCtable[256];
-#endif
-static void InitCRC (void)
-{
+
+static void InitCRC (void) {
const uint32 poly = 0xEDB88320;
int i, j;
uint32 n;
- for (i = 0; i < 256; i++)
- {
+ for (i = 0; i < 256; i++) {
n = i;
for (j = 0; j < 8; j++)
n = (n & 1) ? ((n >> 1) ^ poly) : (n >> 1);
@@ -53,8 +48,7 @@ static void InitCRC (void)
}
}
-static uint32 GetCRC (byte *data, int len)
-{
+static uint32 GetCRC (byte *data, int len) {
uint32 CRC = 0xFFFFFFFF;
int i;
for (i = 0; i < len; i++)
@@ -1116,8 +1110,7 @@ public:
}
virtual bool update() {
assert(_id);
- if (_curfreq >= _freq2)
- {
+ if (_curfreq >= _freq2) {
_mod->setChannelFreq(_id, BASE_FREQUENCY / _curfreq);
_curfreq -= _bendrate;
if (--_bendctr)
@@ -1125,9 +1118,7 @@ public:
_bendrate--;
if (_bendrate < 2)
_bendrate = 2;
- }
- else
- {
+ } else {
if (!--_holdctr)
return false;
}
@@ -1163,15 +1154,12 @@ public:
}
virtual bool update() {
assert(_id);
- if (!_loop)
- {
+ if (!_loop) {
_vol--;
if (_vol)
_mod->setChannelVol(_id, _vol);
else return false;
- }
- else if (!--_loop)
- {
+ } else if (!--_loop) {
_mod->stopChannel(_id);
char *tmp_data = (char *)malloc(_size2);
memcpy(tmp_data, _data + _offset2, _size2);
@@ -1309,9 +1297,6 @@ Player_V2A::Player_V2A(ScummEngine *scumm, Audio::Mixer *mixer) {
int i;
_vm = scumm;
-#ifdef PALMOS_68K
- if (!CRCtable) CRCtable = (uint32 *)calloc(256, sizeof(uint32));
-#endif
InitCRC();
for (i = 0; i < V2A_MAXSLOTS; i++) {
@@ -1325,9 +1310,6 @@ Player_V2A::Player_V2A(ScummEngine *scumm, Audio::Mixer *mixer) {
Player_V2A::~Player_V2A() {
delete _mod;
-#ifdef PALMOS_68K
- free(CRCtable);
-#endif
}
void Player_V2A::setMusicVolume (int vol) {
diff --git a/engines/scumm/resource.cpp b/engines/scumm/resource.cpp
index 88df9da6c7..d96ecc58f6 100644
--- a/engines/scumm/resource.cpp
+++ b/engines/scumm/resource.cpp
@@ -597,7 +597,7 @@ void ScummEngine::ensureResourceLoaded(int type, int i) {
i = _resourceMapper[i & 0x7F];
}
- // FIXME - TODO: This check used to be "i==0". However, that causes
+ // FIXME: This check used to be "i==0". However, that causes
// problems when using this function to ensure charset 0 is loaded.
// This is done for many games, e.g. Zak256 or Indy3 (EGA and VGA).
// For now we restrict the check to anything which is not a charset.
diff --git a/engines/scumm/saveload.cpp b/engines/scumm/saveload.cpp
index 3f638946c4..0e485e226a 100644
--- a/engines/scumm/saveload.cpp
+++ b/engines/scumm/saveload.cpp
@@ -344,7 +344,7 @@ bool ScummEngine::loadState(int slot, bool compat) {
// Restore the virtual screens and force a fade to black.
initScreens(0, _screenHeight);
- VirtScreen *vs = &virtscr[kMainVirtScreen];
+ VirtScreen *vs = &_virtscr[kMainVirtScreen];
memset(vs->getPixels(0, 0), 0, vs->pitch * vs->h);
vs->setDirtyRange(0, vs->h);
updateDirtyScreen(kMainVirtScreen);
diff --git a/engines/scumm/script_v0.cpp b/engines/scumm/script_v0.cpp
index 62e5cee03b..143e926604 100644
--- a/engines/scumm/script_v0.cpp
+++ b/engines/scumm/script_v0.cpp
@@ -527,9 +527,9 @@ void ScummEngine_v0::drawSentence() {
}
_string[2].charset = 1;
- _string[2].ypos = virtscr[kVerbVirtScreen].topline;
+ _string[2].ypos = _virtscr[kVerbVirtScreen].topline;
_string[2].xpos = 0;
- _string[2].right = virtscr[kVerbVirtScreen].w - 1;
+ _string[2].right = _virtscr[kVerbVirtScreen].w - 1;
_string[2].color = 16;
byte string[80];
@@ -550,10 +550,10 @@ void ScummEngine_v0::drawSentence() {
}
string[i] = 0;
- sentenceline.top = virtscr[kVerbVirtScreen].topline;
- sentenceline.bottom = virtscr[kVerbVirtScreen].topline + 8;
+ sentenceline.top = _virtscr[kVerbVirtScreen].topline;
+ sentenceline.bottom = _virtscr[kVerbVirtScreen].topline + 8;
sentenceline.left = 0;
- sentenceline.right = virtscr[kVerbVirtScreen].w - 1;
+ sentenceline.right = _virtscr[kVerbVirtScreen].w - 1;
restoreBackground(sentenceline);
drawString(2, (byte*)string);
diff --git a/engines/scumm/script_v2.cpp b/engines/scumm/script_v2.cpp
index 767d9495cc..532acc98a3 100644
--- a/engines/scumm/script_v2.cpp
+++ b/engines/scumm/script_v2.cpp
@@ -1053,9 +1053,9 @@ void ScummEngine_v2::o2_drawSentence() {
}
_string[2].charset = 1;
- _string[2].ypos = virtscr[kVerbVirtScreen].topline;
+ _string[2].ypos = _virtscr[kVerbVirtScreen].topline;
_string[2].xpos = 0;
- _string[2].right = virtscr[kVerbVirtScreen].w - 1;
+ _string[2].right = _virtscr[kVerbVirtScreen].w - 1;
if (_game.platform == Common::kPlatformNES) {
_string[2].xpos = 16;
_string[2].color = 0;
@@ -1087,15 +1087,15 @@ void ScummEngine_v2::o2_drawSentence() {
string[i] = 0;
if (_game.platform == Common::kPlatformNES) {
- sentenceline.top = virtscr[kVerbVirtScreen].topline;
- sentenceline.bottom = virtscr[kVerbVirtScreen].topline + 16;
+ sentenceline.top = _virtscr[kVerbVirtScreen].topline;
+ sentenceline.bottom = _virtscr[kVerbVirtScreen].topline + 16;
sentenceline.left = 16;
- sentenceline.right = virtscr[kVerbVirtScreen].w - 1;
+ sentenceline.right = _virtscr[kVerbVirtScreen].w - 1;
} else {
- sentenceline.top = virtscr[kVerbVirtScreen].topline;
- sentenceline.bottom = virtscr[kVerbVirtScreen].topline + 8;
+ sentenceline.top = _virtscr[kVerbVirtScreen].topline;
+ sentenceline.bottom = _virtscr[kVerbVirtScreen].topline + 8;
sentenceline.left = 0;
- sentenceline.right = virtscr[kVerbVirtScreen].w - 1;
+ sentenceline.right = _virtscr[kVerbVirtScreen].w - 1;
}
restoreBackground(sentenceline);
@@ -1590,9 +1590,9 @@ void ScummEngine_v2::setUserState(byte state) {
// Hide all verbs and inventory
Common::Rect rect;
- rect.top = virtscr[kVerbVirtScreen].topline;
- rect.bottom = virtscr[kVerbVirtScreen].topline + 8 * 88;
- rect.right = virtscr[kVerbVirtScreen].w - 1;
+ rect.top = _virtscr[kVerbVirtScreen].topline;
+ rect.bottom = _virtscr[kVerbVirtScreen].topline + 8 * 88;
+ rect.right = _virtscr[kVerbVirtScreen].w - 1;
if (_game.platform == Common::kPlatformNES) {
rect.left = 16;
} else {
diff --git a/engines/scumm/script_v5.cpp b/engines/scumm/script_v5.cpp
index c4f7937aa4..3cd71bac08 100644
--- a/engines/scumm/script_v5.cpp
+++ b/engines/scumm/script_v5.cpp
@@ -2929,8 +2929,8 @@ void ScummEngine_v5::o5_oldRoomEffect() {
// For now, we force a redraw of the screen background. This
// way the Zak end credits seem to work mostly correct.
- VirtScreen *vs = &virtscr[0];
- restoreBackground(Common::Rect(0,vs->topline, vs->w, vs->topline + vs->h));
+ VirtScreen *vs = &_virtscr[kMainVirtScreen];
+ restoreBackground(Common::Rect(0, vs->topline, vs->w, vs->topline + vs->h));
vs->setDirtyRange(0, vs->h);
updateDirtyScreen(kMainVirtScreen);
diff --git a/engines/scumm/script_v6.cpp b/engines/scumm/script_v6.cpp
index 7e0d705377..e436489f25 100644
--- a/engines/scumm/script_v6.cpp
+++ b/engines/scumm/script_v6.cpp
@@ -2715,7 +2715,7 @@ void ScummEngine_v6::o6_kernelGetFunctions() {
int i;
int slot;
Actor *a;
- VirtScreen *vs = &virtscr[0];
+ VirtScreen *vs = &_virtscr[kMainVirtScreen];
getStackList(args, ARRAYSIZE(args));
diff --git a/engines/scumm/scumm-md5.h b/engines/scumm/scumm-md5.h
index 4f6b2477c6..69d2bea3e0 100644
--- a/engines/scumm/scumm-md5.h
+++ b/engines/scumm/scumm-md5.h
@@ -1,5 +1,5 @@
/*
- This file was generated by the md5table tool on Fri Jul 20 21:25:14 2007
+ This file was generated by the md5table tool on Mon Aug 13 12:40:13 2007
DO NOT EDIT MANUALLY!
*/
@@ -104,9 +104,9 @@ static const MD5Table md5table[] = {
{ "2232b0b9411575b1f9961713ebc9de61", "balloon", "HE 80", "", -1, Common::ES_ESP, Common::kPlatformWindows },
{ "225e18566e810c634bf7de63e7568e3e", "mustard", "", "", -1, Common::EN_USA, Common::kPlatformUnknown },
{ "22c9eb04455440131ffc157aeb8d40a8", "fbear", "HE 70", "Demo", -1, Common::EN_ANY, Common::kPlatformWindows },
- { "22d07d6c386c9c25aca5dac2a0c0d94b", "maniac", "NES", "", -1, Common::SE_SWE, Common::kPlatformNES },
+ { "22d07d6c386c9c25aca5dac2a0c0d94b", "maniac", "NES", "", 262144, Common::SE_SWE, Common::kPlatformNES },
{ "22f4ea88a09da12df9308ba30bcb7d0f", "loom", "EGA", "EGA", -1, Common::EN_ANY, Common::kPlatformPC },
- { "257f8c14d8c584f7ddd601bcb00920c7", "maniac", "NES", "", -1, Common::DE_DEU, Common::kPlatformNES },
+ { "257f8c14d8c584f7ddd601bcb00920c7", "maniac", "NES", "", 262144, Common::DE_DEU, Common::kPlatformNES },
{ "2723fea3dae0cb47768c424b145ae0e7", "tentacle", "", "Floppy", 7932, Common::EN_ANY, Common::kPlatformPC },
{ "27b3a4224ad63d5b04627595c1c1a025", "zak", "V2", "V2", -1, Common::IT_ITA, Common::kPlatformAmiga },
{ "28d24a33448fab6795850bc9f159a4a2", "atlantis", "", "Demo", 11170, Common::JA_JPN, Common::kPlatformFMTowns },
@@ -147,7 +147,7 @@ static const MD5Table md5table[] = {
{ "37ff1b308999c4cca7319edfcc1280a0", "puttputt", "HE 70", "Demo", 8269, Common::EN_ANY, Common::kPlatformWindows },
{ "3824e60cdf639d22f6df92a03dc4b131", "fbear", "HE 61", "", 7732, Common::EN_ANY, Common::kPlatformPC },
{ "387a544b8b10b26912d8413bab63a853", "monkey2", "", "Demo", -1, Common::EN_ANY, Common::kPlatformPC },
- { "3905799e081b80a61d4460b7b733c206", "maniac", "NES", "", -1, Common::EN_GRB, Common::kPlatformNES },
+ { "3905799e081b80a61d4460b7b733c206", "maniac", "NES", "", 262144, Common::EN_GRB, Common::kPlatformNES },
{ "3938ee1aa4433fca9d9308c9891172b1", "zak", "FM-TOWNS", "Demo", -1, Common::EN_ANY, Common::kPlatformFMTowns },
{ "399b217b0c8d65d0398076da486363a9", "indy3", "VGA", "VGA", 6295, Common::DE_DEU, Common::kPlatformPC },
{ "39cb9dec16fa16f38d79acd80effb059", "loom", "EGA", "EGA", -1, Common::FR_FRA, Common::kPlatformAmiga },
@@ -312,7 +312,7 @@ static const MD5Table md5table[] = {
{ "7f945525abcd48015adf1632637a44a1", "pajama", "", "Demo", -1, Common::FR_FRA, Common::kPlatformUnknown },
{ "7fc6cdb46b4c9d384c52327f4bca6416", "football", "", "", -1, Common::EN_ANY, Common::kPlatformUnknown },
{ "810a9da887aefa597b0cf3c77d262897", "BluesABCTime", "", "Demo", -1, Common::EN_ANY, Common::kPlatformUnknown },
- { "81bbfa181184cb494e7a81dcfa94fbd9", "maniac", "NES", "", -1, Common::FR_FRA, Common::kPlatformNES },
+ { "81bbfa181184cb494e7a81dcfa94fbd9", "maniac", "NES", "", 262144, Common::FR_FRA, Common::kPlatformNES },
{ "8299d9b8a1b0e7b881bae7a9971dc5e2", "zak", "V2", "Demo", 1916, Common::EN_ANY, Common::kPlatformAtariST },
{ "8368f552b1e3eba559f8d559bcc4cadb", "freddi3", "", "", -1, Common::UNK_LANG, Common::kPlatformUnknown },
{ "83cedbe26aa8b58988e984e3d34cac8e", "freddi3", "HE 99", "", -1, Common::DE_DEU, Common::kPlatformUnknown },
@@ -414,6 +414,7 @@ static const MD5Table md5table[] = {
{ "b5298a5c15ffbe8b381d51ea4e26d35c", "freddi4", "HE 99", "", -1, Common::DE_DEU, Common::kPlatformUnknown },
{ "b597e0403cc0002f69170e6caba7edd9", "indy3", "EGA", "EGA Demo", 5361, Common::EN_ANY, Common::kPlatformPC },
{ "b628506f7def772e40de0aa5440fb8e1", "activity", "HE 70", "", -1, Common::EN_ANY, Common::kPlatformWindows },
+ { "b7d37d6b786b5a22deea3b038eca96ca", "maniac", "NES", "extracted", 2082, Common::ES_ESP, Common::kPlatformNES },
{ "b886b0a5d909c7158a914e1d7c1c6c65", "loom", "EGA", "EGA", -1, Common::FR_FRA, Common::kPlatformPC },
{ "b8955d7d23b4972229060d1592489fef", "freddicove", "HE 100", "", -1, Common::NL_NLD, Common::kPlatformUnknown },
{ "b9ba19ce376efc69be78ef3baef8d2b9", "monkey", "CD", "", -1, Common::EN_ANY, Common::kPlatformMacintosh },
@@ -426,6 +427,7 @@ static const MD5Table md5table[] = {
{ "bf8b52fdd9a69c67f34e8e9fec72661c", "farm", "HE 71", "Demo", -1, Common::EN_ANY, Common::kPlatformWindows },
{ "bfdf584b01503f0762baded581f6a0a2", "SoccerMLS", "", "", -1, Common::EN_ANY, Common::kPlatformWindows },
{ "c0039ad982999c92d0de81910d640fa0", "freddi", "HE 71", "", -1, Common::NL_NLD, Common::kPlatformWindows },
+ { "c0d5c89550381ac433624fedad5e1100", "loom", "PC-Engine", "", -1, Common::JA_JPN, Common::kPlatformPCEngine },
{ "c13225cb1bbd3bc9fe578301696d8021", "monkey", "SEGA", "", -1, Common::EN_ANY, Common::kPlatformSegaCD },
{ "c24c490373aeb48fbd54caa8e7ae376d", "loom", "No Adlib", "EGA", -1, Common::DE_DEU, Common::kPlatformAtariST },
{ "c25755b08a8d0d47695e05f1e2111bfc", "freddi4", "", "Demo", -1, Common::EN_USA, Common::kPlatformUnknown },
@@ -488,7 +490,7 @@ static const MD5Table md5table[] = {
{ "d7b247c26bf1f01f8f7daf142be84de3", "balloon", "HE 99", "Updated", -1, Common::EN_ANY, Common::kPlatformWindows },
{ "d831f7c048574dd9d5d85db2a1468099", "maniac", "C64", "", -1, Common::EN_ANY, Common::kPlatformC64 },
{ "d8323015ecb8b10bf53474f6e6b0ae33", "dig", "", "", 16304, Common::UNK_LANG, Common::kPlatformUnknown },
- { "d8d07efcb88f396bee0b402b10c3b1c9", "maniac", "NES", "", -1, Common::EN_USA, Common::kPlatformNES },
+ { "d8d07efcb88f396bee0b402b10c3b1c9", "maniac", "NES", "", 262144, Common::EN_USA, Common::kPlatformNES },
{ "d917f311a448e3cc7239c31bddb00dd2", "samnmax", "", "CD", 9080, Common::EN_ANY, Common::kPlatformUnknown },
{ "d9d0dd93d16ab4dec55cabc2b86bbd17", "samnmax", "", "Demo", 6478, Common::EN_ANY, Common::kPlatformPC },
{ "da09e666fc8f5b78d7b0ac65d1a3b56e", "monkey2", "", "", 11135, Common::EN_ANY, Common::kPlatformFMTowns },
@@ -537,6 +539,7 @@ static const MD5Table md5table[] = {
{ "f049e38c1f8302b5db6170f1872af89a", "monkey", "CD", "CD", 8955, Common::ES_ESP, Common::kPlatformPC },
{ "f06e66fd45b2f8b0f4a2833ff4476050", "fbpack", "", "", -1, Common::HB_ISR, Common::kPlatformPC },
{ "f08145577e4f13584cc90b3d6e9caa55", "pajama3", "", "Demo", -1, Common::NL_NLD, Common::kPlatformUnknown },
+ { "f163cf53f7850e43fb482471e5c52e1a", "maniac", "NES", "", 262144, Common::ES_ESP, Common::kPlatformNES },
{ "f1b0e0d587b85052de5534a3847e68fe", "water", "HE 99", "Updated", -1, Common::EN_ANY, Common::kPlatformUnknown },
{ "f237bf8a5ef9af78b2a6a4f3901da341", "pajama", "", "Demo", 18354, Common::EN_ANY, Common::kPlatformUnknown },
{ "f27b1ba0eadaf2a6617b2b58192d1dbf", "samnmax", "", "Floppy", -1, Common::DE_DEU, Common::kPlatformPC },
diff --git a/engines/scumm/scumm.cpp b/engines/scumm/scumm.cpp
index e54060c9e1..60911a97dd 100644
--- a/engines/scumm/scumm.cpp
+++ b/engines/scumm/scumm.cpp
@@ -41,6 +41,7 @@
#include "scumm/debugger.h"
#include "scumm/dialogs.h"
#include "scumm/file.h"
+#include "scumm/file_nes.h"
#include "scumm/imuse/imuse.h"
#include "scumm/imuse_digi/dimuse.h"
#include "scumm/smush/smush_mixer.h"
@@ -227,7 +228,7 @@ ScummEngine::ScummEngine(OSystem *syst, const DetectorResult &dr)
_roomWidth = 0;
_screenHeight = 0;
_screenWidth = 0;
- memset(virtscr, 0, sizeof(virtscr));
+ memset(_virtscr, 0, sizeof(_virtscr));
memset(&camera, 0, sizeof(CameraData));
memset(_colorCycle, 0, sizeof(_colorCycle));
memset(_colorUsedByCycle, 0, sizeof(_colorUsedByCycle));
@@ -1196,12 +1197,7 @@ void ScummEngine::setupScumm() {
}
int maxHeapThreshold = -1;
-#ifdef PALMOS_68K
- if (_game.features & GF_NEW_COSTUMES)
- maxHeapThreshold = gVars->memory[kMemScummNewCostGames];
- else
- maxHeapThreshold = gVars->memory[kMemScummOldCostGames];
-#else
+
if (_game.features & GF_NEW_COSTUMES) {
// Since the new costumes are very big, we increase the heap limit, to avoid having
// to constantly reload stuff from the data files.
@@ -1209,7 +1205,7 @@ void ScummEngine::setupScumm() {
} else {
maxHeapThreshold = 550000;
}
-#endif
+
_res->setHeapThreshold(400000, maxHeapThreshold);
#if (defined(PALMOS_ARM) || defined(PALMOS_DEBUG) || defined(__GP32__))
@@ -1381,7 +1377,7 @@ void ScummEngine::resetScumm() {
}
camera._follows = 0;
- virtscr[0].xstart = 0;
+ _virtscr[0].xstart = 0;
_mouse.x = 104;
_mouse.y = 56;
diff --git a/engines/scumm/scumm.h b/engines/scumm/scumm.h
index 18c2275029..2a155c7e02 100644
--- a/engines/scumm/scumm.h
+++ b/engines/scumm/scumm.h
@@ -917,7 +917,7 @@ protected:
public:
int _roomHeight, _roomWidth;
int _screenHeight, _screenWidth;
- VirtScreen virtscr[4]; // Virtual screen areas
+ VirtScreen _virtscr[4]; // Virtual screen areas
CameraData camera; // 'Camera' - viewport
int _screenStartStrip, _screenEndStrip;
@@ -1031,7 +1031,6 @@ protected:
void updateDirtyScreen(VirtScreenNumber slot);
void drawStripToScreen(VirtScreen *vs, int x, int w, int t, int b);
void ditherCGA(byte *dst, int dstPitch, int x, int y, int width, int height) const;
- void scale2x(byte *dst, int dstPitch, const byte *src, int srcPitch, int w, int h);
public:
VirtScreen *findVirtScreen(int y);
diff --git a/engines/scumm/smush/codec47.cpp b/engines/scumm/smush/codec47.cpp
index 6904e96c11..739c7308d3 100644
--- a/engines/scumm/smush/codec47.cpp
+++ b/engines/scumm/smush/codec47.cpp
@@ -88,9 +88,6 @@ static const int8 codec47_table_big2[] = {
0, 0, 0, 0, 1, 3, 4, 6, 7, 7, 7, 7, 6, 4, 3, 1,
};
-#ifdef PALMOS_68K
-static const int8 *codec47_table;
-#else
static const int8 codec47_table[] = {
0, 0, -1, -43, 6, -43, -9, -42, 13, -41,
-16, -40, 19, -39, -23, -36, 26, -34, -2, -33,
@@ -144,7 +141,6 @@ static const int8 codec47_table[] = {
23, 36, -19, 39, 16, 40, -13, 41, 9, 42,
-6, 43, 1, 43, 0, 0, 0, 0, 0, 0
};
-#endif
void Codec47Decoder::makeTablesInterpolation(int param) {
int32 variable1, variable2;
@@ -617,16 +613,3 @@ bool Codec47Decoder::decode(byte *dst, const byte *src) {
}
} // End of namespace Scumm
-
-#ifdef PALMOS_68K
-#include "scumm_globals.h"
-
-_GINIT(Codec47)
-_GSETPTR(Scumm::codec47_table, GBVARS_CODEC47TABLE_INDEX, int8, GBVARS_SCUMM)
-_GEND
-
-_GRELEASE(Codec47)
-_GRELEASEPTR(GBVARS_CODEC47TABLE_INDEX, GBVARS_SCUMM)
-_GEND
-
-#endif
diff --git a/engines/scumm/smush/smush_player.cpp b/engines/scumm/smush/smush_player.cpp
index ce39302e25..612f2771db 100644
--- a/engines/scumm/smush/smush_player.cpp
+++ b/engines/scumm/smush/smush_player.cpp
@@ -265,6 +265,8 @@ SmushPlayer::~SmushPlayer() {
}
void SmushPlayer::init(int32 speed) {
+ VirtScreen *vs = &_vm->_virtscr[kMainVirtScreen];
+
_frame = 0;
_speed = speed;
_endOfFile = false;
@@ -273,7 +275,7 @@ void SmushPlayer::init(int32 speed) {
_vm->_smushActive = true;
_vm->setDirtyColors(0, 255);
- _dst = _vm->virtscr[0].getPixels(0, 0);
+ _dst = vs->getPixels(0, 0);
// HACK HACK HACK: This is an *evil* trick, beware!
// We do this to fix bug #1037052. A proper solution would change all the
@@ -281,10 +283,10 @@ void SmushPlayer::init(int32 speed) {
// However, since a lot of the SMUSH code currently assumes the screen
// width and pitch to be equal, this will require lots of changes. So
// we resort to this hackish solution for now.
- _origPitch = _vm->virtscr[0].pitch;
+ _origPitch = vs->pitch;
_origNumStrips = _vm->_gdi->_numStrips;
- _vm->virtscr[0].pitch = _vm->virtscr[0].w;
- _vm->_gdi->_numStrips = _vm->virtscr[0].w / 8;
+ vs->pitch = vs->w;
+ _vm->_gdi->_numStrips = vs->w / 8;
_vm->_mixer->stopHandle(_compressedFileSoundHandle);
_vm->_mixer->stopHandle(_IACTchannel);
@@ -319,7 +321,7 @@ void SmushPlayer::release() {
// HACK HACK HACK: This is an *evil* trick, beware! See above for
// some explanation.
- _vm->virtscr[0].pitch = _origPitch;
+ _vm->_virtscr[kMainVirtScreen].pitch = _origPitch;
_vm->_gdi->_numStrips = _origNumStrips;
delete _codec37;
diff --git a/engines/scumm/string.cpp b/engines/scumm/string.cpp
index 32fdf0e04e..83b4e90cf6 100644
--- a/engines/scumm/string.cpp
+++ b/engines/scumm/string.cpp
@@ -456,7 +456,7 @@ void ScummEngine::CHARSET_1() {
if (a && _string[0].overhead) {
int s;
- _string[0].xpos = a->getPos().x - virtscr[0].xstart;
+ _string[0].xpos = a->getPos().x - _virtscr[kMainVirtScreen].xstart;
_string[0].ypos = a->getPos().y - a->getElevation() - _screenTop;
if (_game.version <= 5) {
@@ -586,7 +586,7 @@ void ScummEngine::CHARSET_1() {
_nextTop += _charset->getFontHeight();
}
if (_game.version > 3) {
- // FIXME - is this really needed?
+ // FIXME: is this really needed?
_charset->_disableOffsX = true;
}
continue;
@@ -678,7 +678,7 @@ void ScummEngine_v8::CHARSET_1() {
if (a && _string[0].overhead) {
int s;
- _string[0].xpos = a->getPos().x - virtscr[0].xstart;
+ _string[0].xpos = a->getPos().x - _virtscr[kMainVirtScreen].xstart;
s = a->_scalex * a->_talkPosX / 255;
_string[0].xpos += (a->_talkPosX - s) / 2 + s;
diff --git a/engines/scumm/thumbnail.cpp b/engines/scumm/thumbnail.cpp
index 01255f1c1d..360d0de932 100644
--- a/engines/scumm/thumbnail.cpp
+++ b/engines/scumm/thumbnail.cpp
@@ -99,7 +99,7 @@ Graphics::Surface *ScummEngine::loadThumbnail(Common::InSaveFile *file) {
void ScummEngine::saveThumbnail(Common::OutSaveFile *file) {
Graphics::Surface thumb;
-#if !defined(PALMOS_68K) || !defined(__DS__)
+#if !defined(__DS__)
if (!createThumbnailFromScreen(&thumb))
#endif
thumb.create(kThumbnailWidth, kThumbnailHeight2, sizeof(uint16));
diff --git a/engines/scumm/verbs.cpp b/engines/scumm/verbs.cpp
index 56ee454240..3c5713d241 100644
--- a/engines/scumm/verbs.cpp
+++ b/engines/scumm/verbs.cpp
@@ -86,7 +86,7 @@ static const VerbSettings v0VerbTable_German[] = {
};
void ScummEngine_v0::resetVerbs() {
- VirtScreen *virt = &virtscr[kVerbVirtScreen];
+ VirtScreen *virt = &_virtscr[kVerbVirtScreen];
VerbSlot *vs;
int i;
@@ -121,7 +121,7 @@ void ScummEngine_v0::resetVerbs() {
}
void ScummEngine_v0::setNewKidVerbs() {
- VirtScreen *virt = &virtscr[kVerbVirtScreen];
+ VirtScreen *virt = &_virtscr[kVerbVirtScreen];
VerbSlot *vs;
int i;
@@ -283,7 +283,7 @@ void ScummEngine_v2::initNESMouseOver() {
}
void ScummEngine_v2::checkV2MouseOver(Common::Point pos) {
- VirtScreen *vs = &virtscr[kVerbVirtScreen];
+ VirtScreen *vs = &_virtscr[kVerbVirtScreen];
Common::Rect rect;
byte *ptr, *dst;
int i, x, y, new_box = -1;
@@ -346,7 +346,7 @@ void ScummEngine_v2::checkV2Inventory(int x, int y) {
int inventoryArea = (_game.platform == Common::kPlatformNES) ? 48: 32;
int object = 0;
- y -= virtscr[kVerbVirtScreen].topline;
+ y -= _virtscr[kVerbVirtScreen].topline;
if ((y < inventoryArea) || !(_mouseAndKeyboardStat & MBS_LEFT_CLICK))
return;
@@ -391,7 +391,7 @@ void ScummEngine_v2::checkV2Inventory(int x, int y) {
}
void ScummEngine_v2::redrawV2Inventory() {
- VirtScreen *vs = &virtscr[kVerbVirtScreen];
+ VirtScreen *vs = &_virtscr[kVerbVirtScreen];
int i;
int max_inv;
Common::Rect inventoryBox;
@@ -405,7 +405,7 @@ void ScummEngine_v2::redrawV2Inventory() {
// Clear on all invocations
inventoryBox.top = vs->topline + inventoryArea;
- inventoryBox.bottom = vs->topline + virtscr[kVerbVirtScreen].h;
+ inventoryBox.bottom = vs->topline + vs->h;
inventoryBox.left = 0;
inventoryBox.right = vs->w;
restoreBackground(inventoryBox);
@@ -1014,8 +1014,8 @@ void ScummEngine::setVerbObject(uint room, uint object, uint verb) {
} else if (_game.features & GF_SMALL_HEADER) {
for (i = (_numLocalObjects-1); i > 0; i--) {
if (_objs[i].obj_nr == object) {
- // FIXME - the only thing we need from the OBCD is the image size!
- // So we could use almost the same code (save for offsets)
+ // FIXME: the only thing we need from the OBCD is the image size!
+ // So we could use almost the same code (except for offsets)
// as in the GF_OLD_BUNDLE code. But of course that would break save games
// unless we insert special conversion code... <sigh>
findObjectInRoom(&foir, foImageHeader, object, room);
diff --git a/engines/sky/hufftext.cpp b/engines/sky/hufftext.cpp
index b3e299d00c..677ea4817e 100644
--- a/engines/sky/hufftext.cpp
+++ b/engines/sky/hufftext.cpp
@@ -27,17 +27,6 @@
namespace Sky {
-#ifdef PALMOS_68K
-const HuffTree *Text::_huffTree_00109;
-const HuffTree *Text::_huffTree_00267;
-const HuffTree *Text::_huffTree_00288;
-const HuffTree *Text::_huffTree_00303;
-const HuffTree *Text::_huffTree_00331;
-const HuffTree *Text::_huffTree_00348;
-const HuffTree *Text::_huffTree_00365;
-const HuffTree *Text::_huffTree_00368;
-const HuffTree *Text::_huffTree_00372;
-#else
const HuffTree Text::_huffTree_00109[] = {
{ 1, 22, 0 },
{ 2, 9, 0 },
@@ -2015,35 +2004,5 @@ const HuffTree Text::_huffTree_00372[] = {
{ 0, 0, 148 },
{ 0, 0, '!' },
};
-#endif
} // End of namespace Sky
-
-#ifdef PALMOS_68K
-#include "scumm_globals.h"
-
-_GINIT(Sky_Hufftext)
-_GSETPTR(Sky::Text::_huffTree_00109, GBVARS_HUFFTREE_00109_INDEX, const Sky::HuffTree, GBVARS_QUEEN)
-_GSETPTR(Sky::Text::_huffTree_00267, GBVARS_HUFFTREE_00267_INDEX, const Sky::HuffTree, GBVARS_QUEEN)
-_GSETPTR(Sky::Text::_huffTree_00288, GBVARS_HUFFTREE_00288_INDEX, const Sky::HuffTree, GBVARS_QUEEN)
-_GSETPTR(Sky::Text::_huffTree_00303, GBVARS_HUFFTREE_00303_INDEX, const Sky::HuffTree, GBVARS_QUEEN)
-_GSETPTR(Sky::Text::_huffTree_00331, GBVARS_HUFFTREE_00331_INDEX, const Sky::HuffTree, GBVARS_QUEEN)
-_GSETPTR(Sky::Text::_huffTree_00348, GBVARS_HUFFTREE_00348_INDEX, const Sky::HuffTree, GBVARS_QUEEN)
-_GSETPTR(Sky::Text::_huffTree_00365, GBVARS_HUFFTREE_00365_INDEX, const Sky::HuffTree, GBVARS_QUEEN)
-_GSETPTR(Sky::Text::_huffTree_00368, GBVARS_HUFFTREE_00368_INDEX, const Sky::HuffTree, GBVARS_QUEEN)
-_GSETPTR(Sky::Text::_huffTree_00372, GBVARS_HUFFTREE_00372_INDEX, const Sky::HuffTree, GBVARS_QUEEN)
-_GEND
-
-_GRELEASE(Sky_Hufftext)
-_GRELEASEPTR(GBVARS_HUFFTREE_00109_INDEX, GBVARS_QUEEN)
-_GRELEASEPTR(GBVARS_HUFFTREE_00267_INDEX, GBVARS_QUEEN)
-_GRELEASEPTR(GBVARS_HUFFTREE_00288_INDEX, GBVARS_QUEEN)
-_GRELEASEPTR(GBVARS_HUFFTREE_00303_INDEX, GBVARS_QUEEN)
-_GRELEASEPTR(GBVARS_HUFFTREE_00331_INDEX, GBVARS_QUEEN)
-_GRELEASEPTR(GBVARS_HUFFTREE_00348_INDEX, GBVARS_QUEEN)
-_GRELEASEPTR(GBVARS_HUFFTREE_00365_INDEX, GBVARS_QUEEN)
-_GRELEASEPTR(GBVARS_HUFFTREE_00368_INDEX, GBVARS_QUEEN)
-_GRELEASEPTR(GBVARS_HUFFTREE_00372_INDEX, GBVARS_QUEEN)
-_GEND
-
-#endif
diff --git a/engines/sky/text.h b/engines/sky/text.h
index be09f5a437..dd73b51db4 100644
--- a/engines/sky/text.h
+++ b/engines/sky/text.h
@@ -96,7 +96,6 @@ private:
static const uint16 _patchLangIdx[8];
static const uint16 _patchLangNum[8];
-#ifndef PALMOS_68K
static const HuffTree _huffTree_00109[]; // trees moved to hufftext.cpp
static const HuffTree _huffTree_00267[];
static const HuffTree _huffTree_00288[];
@@ -106,18 +105,6 @@ private:
static const HuffTree _huffTree_00365[];
static const HuffTree _huffTree_00368[];
static const HuffTree _huffTree_00372[];
-#else
-public:
- static const HuffTree *_huffTree_00109; // trees moved to hufftext.cpp
- static const HuffTree *_huffTree_00267;
- static const HuffTree *_huffTree_00288;
- static const HuffTree *_huffTree_00303;
- static const HuffTree *_huffTree_00331;
- static const HuffTree *_huffTree_00348;
- static const HuffTree *_huffTree_00365;
- static const HuffTree *_huffTree_00368;
- static const HuffTree *_huffTree_00372;
-#endif
};
} // End of namespace Sky
diff --git a/engines/sword1/logic.cpp b/engines/sword1/logic.cpp
index 7c15d66a46..60103ba5f9 100644
--- a/engines/sword1/logic.cpp
+++ b/engines/sword1/logic.cpp
@@ -317,8 +317,7 @@ int Logic::logicArAnimate(Object *compact, uint32 id) {
}
compact->o_walk_pc++;
- if (route[compact->o_walk_pc].frame == 512) //end of sequence
- {
+ if (route[compact->o_walk_pc].frame == 512) { //end of sequence
compact->o_logic = LOGIC_script;
if (((_scriptVars[GEORGE_WALKING] == 2) || (_scriptVars[GEORGE_WALKING] == 1)) &&
(id == PLAYER)) {
diff --git a/engines/sword1/router.cpp b/engines/sword1/router.cpp
index 685e11fd32..6478674eb2 100644
--- a/engines/sword1/router.cpp
+++ b/engines/sword1/router.cpp
@@ -130,8 +130,7 @@ int32 Router::routeFinder(int32 id, Object *megaObject, int32 x, int32 y, int32
slowInFrames = 0;
slowOutFrames = 0;
- if (megaId == GEORGE)
- {
+ if (megaId == GEORGE) {
turnFramesLeft = 3 * _framesPerChar + NO_DIRECTIONS + 2 * SLOW_IN + 4 * SLOW_OUT;
turnFramesRight = 3 * _framesPerChar + NO_DIRECTIONS + 2 * SLOW_IN + 4 * SLOW_OUT + NO_DIRECTIONS;
walkFramesLeft = _framesPerChar + NO_DIRECTIONS;
@@ -703,8 +702,7 @@ void Router::slidyWalkAnimator(WalkData *walkAnim) {
// TURN TO START THE WALK
//****************************************************************************
// rotate if we need to
- if (lastDir != currentDir)
- {
+ if (lastDir != currentDir) {
// get the direction to turn
turnDir = currentDir - lastDir;
if ( turnDir < 0)
@@ -717,10 +715,8 @@ void Router::slidyWalkAnimator(WalkData *walkAnim) {
// rotate to new walk direction
// for george and nico put in a head turn at the start
- if ((megaId == GEORGE) || (megaId == NICO))
- {
- if ( turnDir < 0) // new frames for turn frames 29oct95jps
- {
+ if ((megaId == GEORGE) || (megaId == NICO)) {
+ if ( turnDir < 0) { // new frames for turn frames 29oct95jps
module = turnFramesLeft + lastDir;
} else {
module = turnFramesRight + lastDir;
@@ -734,11 +730,9 @@ void Router::slidyWalkAnimator(WalkData *walkAnim) {
}
// rotate till were facing new dir then go back 45 degrees
- while (lastDir != currentDir)
- {
+ while (lastDir != currentDir) {
lastDir += turnDir;
- if ( turnDir < 0) // new frames for turn frames 29oct95jps
- {
+ if ( turnDir < 0) { // new frames for turn frames 29oct95jps
if ( lastDir < 0)
lastDir += NO_DIRECTIONS;
module = turnFramesLeft + lastDir;
@@ -774,8 +768,7 @@ void Router::slidyWalkAnimator(WalkData *walkAnim) {
lastDir = 99;// this ensures that we don't put in turn frames for the start
currentDir = 99;// this ensures that we don't put in turn frames for the start
do {
- while (_modularPath[p].num == 0)
- {
+ while (_modularPath[p].num == 0) {
p = p + 1;
if (currentDir != 99)
lastRealDir = currentDir;
@@ -784,8 +777,7 @@ void Router::slidyWalkAnimator(WalkData *walkAnim) {
}
//calculate average amount to lose in each step on the way to the next _node
currentDir = _modularPath[p].dir;
- if (currentDir < NO_DIRECTIONS)
- {
+ if (currentDir < NO_DIRECTIONS) {
module = currentDir * _framesPerStep * 2 + left;
if (left == 0)
left = _framesPerStep;
@@ -814,22 +806,18 @@ void Router::slidyWalkAnimator(WalkData *walkAnim) {
errorX = errorX * stepX;
errorY = _modularPath[p].y - moduleY;
errorY = errorY * stepY;
- if ((errorX < 0) || (errorY < 0))
- {
+ if ((errorX < 0) || (errorY < 0)) {
_modularPath[p].num = 0; // the end of the path
// okay those last steps took us past our target but do we want to scoot or moonwalk
frames = stepCount - lastCount;
errorX = _modularPath[p].x - walkAnim[stepCount-1].x;
errorY = _modularPath[p].y - walkAnim[stepCount-1].y;
- if (frames > _framesPerStep)
- {
+ if (frames > _framesPerStep) {
lastErrorX = _modularPath[p].x - walkAnim[stepCount-7].x;
lastErrorY = _modularPath[p].y - walkAnim[stepCount-7].y;
- if (stepX==0)
- {
- if (3*ABS(lastErrorY) < ABS(errorY)) //the last stop was closest
- {
+ if (stepX==0) {
+ if (3*ABS(lastErrorY) < ABS(errorY)) { //the last stop was closest
stepCount -= _framesPerStep;
if (left == 0)
left = _framesPerStep;
@@ -837,8 +825,7 @@ void Router::slidyWalkAnimator(WalkData *walkAnim) {
left = 0;
}
} else {
- if (3*ABS(lastErrorX) < ABS(errorX)) //the last stop was closest
- {
+ if (3*ABS(lastErrorX) < ABS(errorX)) { //the last stop was closest
stepCount -= _framesPerStep;
if (left == 0)
left = _framesPerStep;
@@ -850,8 +837,7 @@ void Router::slidyWalkAnimator(WalkData *walkAnim) {
errorX = _modularPath[p].x - walkAnim[stepCount-1].x;
errorY = _modularPath[p].y - walkAnim[stepCount-1].y;
// okay we've reached the end but we still have an error
- if (errorX != 0)
- {
+ if (errorX != 0) {
frameCount = 0;
frames = stepCount - lastCount;
do {
@@ -859,8 +845,7 @@ void Router::slidyWalkAnimator(WalkData *walkAnim) {
walkAnim[lastCount + frameCount - 1].x += errorX*frameCount/frames;
} while (frameCount<frames);
}
- if (errorY != 0)
- {
+ if (errorY != 0) {
frameCount = 0;
frames = stepCount - lastCount;
do {
@@ -874,25 +859,20 @@ void Router::slidyWalkAnimator(WalkData *walkAnim) {
if (currentDir != 99)
lastRealDir = currentDir;
// check each turn condition in turn
- if (((lastDir != 99) && (currentDir != 99)) && (megaId == GEORGE)) // only for george
- {
+ if (((lastDir != 99) && (currentDir != 99)) && (megaId == GEORGE)) { // only for george
lastDir = currentDir - lastDir;//1 and -7 going right -1 and 7 going left
- if (((lastDir == -1) || (lastDir == 7)) || ((lastDir == -2) || (lastDir == 6)))
- {
+ if (((lastDir == -1) || (lastDir == 7)) || ((lastDir == -2) || (lastDir == 6))) {
// turn at the end of the last walk
frame = lastCount - _framesPerStep;
- do
- {
+ do {
walkAnim[frame].frame += 104;//turning left
frame += 1;
} while (frame < lastCount );
}
- if (((lastDir == 1) || (lastDir == -7)) || ((lastDir == 2) || (lastDir == -6)))
- {
+ if (((lastDir == 1) || (lastDir == -7)) || ((lastDir == 2) || (lastDir == -6))) {
// turn at the end of the current walk
frame = lastCount - _framesPerStep;
- do
- {
+ do {
walkAnim[frame].frame += 200; //was 60 now 116
frame += 1;
} while (frame < lastCount );
@@ -912,8 +892,7 @@ void Router::slidyWalkAnimator(WalkData *walkAnim) {
- if (lastRealDir == 99)
- {
+ if (lastRealDir == 99) {
error("SlidyWalkAnimatorlast direction error\n");
}
//****************************************************************************
@@ -924,8 +903,7 @@ void Router::slidyWalkAnimator(WalkData *walkAnim) {
// We've done the walk now put in any turns at the end
- if (_targetDir == NO_DIRECTIONS) // stand in the last direction
- {
+ if (_targetDir == NO_DIRECTIONS) { // stand in the last direction
module = standFrames + lastRealDir;
_targetDir = lastRealDir;
walkAnim[stepCount].frame = module;
@@ -935,10 +913,8 @@ void Router::slidyWalkAnimator(WalkData *walkAnim) {
walkAnim[stepCount].y = moduleY;
stepCount += 1;
}
- if (_targetDir == 9)
- {
- if (stepCount == 0)
- {
+ if (_targetDir == 9) {
+ if (stepCount == 0) {
module = _framesPerChar + lastRealDir;
walkAnim[stepCount].frame = module;
walkAnim[stepCount].step = 0;
@@ -947,8 +923,7 @@ void Router::slidyWalkAnimator(WalkData *walkAnim) {
walkAnim[stepCount].y = moduleY;
stepCount += 1;
}
- } else if (_targetDir != lastRealDir) // rotate to _targetDir
- {
+ } else if (_targetDir != lastRealDir) { // rotate to _targetDir
// rotate to target direction
turnDir = _targetDir - lastRealDir;
if ( turnDir < 0)
@@ -961,10 +936,8 @@ void Router::slidyWalkAnimator(WalkData *walkAnim) {
// rotate to target direction
// for george and nico put in a head turn at the start
- if ((megaId == GEORGE) || (megaId == NICO))
- {
- if ( turnDir < 0) // new frames for turn frames 29oct95jps
- {
+ if ((megaId == GEORGE) || (megaId == NICO)) {
+ if ( turnDir < 0) { // new frames for turn frames 29oct95jps
module = turnFramesLeft + lastDir;
} else {
module = turnFramesRight + lastDir;
@@ -978,11 +951,9 @@ void Router::slidyWalkAnimator(WalkData *walkAnim) {
}
// rotate if we need to
- while (lastRealDir != _targetDir)
- {
+ while (lastRealDir != _targetDir) {
lastRealDir += turnDir;
- if ( turnDir < 0) // new frames for turn frames 29oct95jps
- {
+ if ( turnDir < 0) { // new frames for turn frames 29oct95jps
if ( lastRealDir < 0)
lastRealDir += NO_DIRECTIONS;
module = turnFramesLeft + lastRealDir;
@@ -1000,8 +971,7 @@ void Router::slidyWalkAnimator(WalkData *walkAnim) {
}
module = standFrames + lastRealDir;
walkAnim[stepCount-1].frame = module;
- } else // just stand at the end
- {
+ } else { // just stand at the end
module = standFrames + lastRealDir;
walkAnim[stepCount].frame = module;
walkAnim[stepCount].step = 0;
@@ -1150,8 +1120,7 @@ int32 Router::solidWalkAnimator(WalkData *walkAnim) {
// TURN TO START THE WALK
//****************************************************************************
// rotate if we need to
- if (lastDir != currentDir)
- {
+ if (lastDir != currentDir) {
// get the direction to turn
turnDir = currentDir - lastDir;
if ( turnDir < 0)
@@ -1164,10 +1133,8 @@ int32 Router::solidWalkAnimator(WalkData *walkAnim) {
// rotate to new walk direction
// for george and nico put in a head turn at the start
- if ((megaId == GEORGE) || (megaId == NICO))
- {
- if ( turnDir < 0) // new frames for turn frames 29oct95jps
- {
+ if ((megaId == GEORGE) || (megaId == NICO)) {
+ if ( turnDir < 0) { // new frames for turn frames 29oct95jps
module = turnFramesLeft + lastDir;
} else {
module = turnFramesRight + lastDir;
@@ -1181,11 +1148,9 @@ int32 Router::solidWalkAnimator(WalkData *walkAnim) {
}
// rotate till were facing new dir then go back 45 degrees
- while (lastDir != currentDir)
- {
+ while (lastDir != currentDir) {
lastDir += turnDir;
- if ( turnDir < 0) // new frames for turn frames 29oct95jps
- {
+ if ( turnDir < 0) { // new frames for turn frames 29oct95jps
if ( lastDir < 0)
lastDir += NO_DIRECTIONS;
module = turnFramesLeft + lastDir;
@@ -1882,8 +1847,7 @@ int32 Router::checkTarget(int32 x, int32 y) {
// * THE SETUP ROUTINES
// ****************************************************************************
-int32 Router::LoadWalkResources(Object *megaObject, int32 x, int32 y, int32 dir)
-{
+int32 Router::LoadWalkResources(Object *megaObject, int32 x, int32 y, int32 dir) {
WalkGridHeader floorHeader;
int32 i;
uint8 *fPolygrid;
@@ -1915,8 +1879,7 @@ int32 Router::LoadWalkResources(Object *megaObject, int32 x, int32 y, int32 dir)
fPolygrid += sizeof(WalkGridHeader);
_nBars = _resMan->getUint32(floorHeader.numBars);
- if (_nBars >= O_GRID_SIZE)
- {
+ if (_nBars >= O_GRID_SIZE) {
#ifdef DEBUG //check for id > number in file,
error("RouteFinder Error too many _bars %d", _nBars);
#endif
@@ -1925,8 +1888,7 @@ int32 Router::LoadWalkResources(Object *megaObject, int32 x, int32 y, int32 dir)
_nNodes = _resMan->getUint32(floorHeader.numNodes)+1; //array starts at 0 begins at a start _node has nnodes nodes and a target _node
- if (_nNodes >= O_GRID_SIZE)
- {
+ if (_nNodes >= O_GRID_SIZE) {
#ifdef DEBUG //check for id > number in file,
error("RouteFinder Error too many nodes %d", _nNodes);
#endif
diff --git a/engines/sword1/sound.h b/engines/sword1/sound.h
index fafc9c2d06..da793bc45a 100644
--- a/engines/sword1/sound.h
+++ b/engines/sword1/sound.h
@@ -118,12 +118,8 @@ private:
char _filePath[100];
static const char _musicList[270];
static const uint16 _roomsFixedFx[TOTAL_ROOMS][TOTAL_FX_PER_ROOM];
-#ifdef PALMOS_68K
-public:
- static const FxDef *_fxList;
-#else
static const FxDef _fxList[312];
-#endif
+
};
} // End of namespace Sword1
diff --git a/engines/sword1/staticres.cpp b/engines/sword1/staticres.cpp
index 08e6a108c4..63a1ce35ef 100644
--- a/engines/sword1/staticres.cpp
+++ b/engines/sword1/staticres.cpp
@@ -2894,9 +2894,6 @@ const char Music::_tuneList[TOTAL_TUNES][8] = {
"rm3d", // DONE 269 ONe the scene change after the Grand Master says, "George, we have watched you..." This one might need a bit of fiddling to get it to match to the fisticuffs.
};
-#ifdef PALMOS_68K
-const FxDef *Sound::_fxList;
-#else
const FxDef Sound::_fxList[312] = {
// 0
{
@@ -6445,7 +6442,7 @@ const FxDef Sound::_fxList[312] = {
},
//------------------------
};
-#endif
+
//--------------------------------------------------------------------------------------
// Continuous & random background sound effects for each location
@@ -7156,16 +7153,3 @@ const uint8 *Logic::_helperData[] = {
};
} // End of namespace Sword1
-
-#ifdef PALMOS_68K
-#include "scumm_globals.h"
-
-_GINIT(Sword1_fxList)
-_GSETPTR(Sword1::Sound::_fxList, GBVARS_FXLIST_INDEX, Sword1::FxDef, GBVARS_SWORD1)
-_GEND
-
-_GRELEASE(Sword1_fxList)
-_GRELEASEPTR(GBVARS_FXLIST_INDEX, GBVARS_SWORD1)
-_GEND
-
-#endif
diff --git a/engines/touche/detection.cpp b/engines/touche/detection.cpp
index 2860d832dd..8e8de71e9c 100644
--- a/engines/touche/detection.cpp
+++ b/engines/touche/detection.cpp
@@ -18,8 +18,8 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
- * $URL:https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/branches/gsoc2007-fsnode/engines/touche/detection.cpp $
- * $Id:detection.cpp 26949 2007-05-26 20:23:24Z david_corrales $
+ * $URL$
+ * $Id$
*
*/
diff --git a/engines/touche/touche.cpp b/engines/touche/touche.cpp
index c67b1e9be3..f3d1f33dfd 100644
--- a/engines/touche/touche.cpp
+++ b/engines/touche/touche.cpp
@@ -148,10 +148,7 @@ void ToucheEngine::restart() {
_waitingSetKeyCharNum3 = -1;
_currentEpisodeNum = 0;
- _newEpisodeNum = ConfMan.getInt("boot_param");
- if (_newEpisodeNum == 0) {
- _newEpisodeNum = kStartupEpisode;
- }
+ _newEpisodeNum = kStartupEpisode;
_newMusicNum = 0;
_currentMusicNum = 0;
@@ -252,15 +249,22 @@ void ToucheEngine::mainLoop() {
readConfigurationSettings();
+ _inp_leftMouseButtonPressed = false;
+ _inp_rightMouseButtonPressed = false;
+
if (ConfMan.hasKey("save_slot")) {
loadGameState(ConfMan.getInt("save_slot"));
- _newEpisodeNum = _currentEpisodeNum;
+ _newEpisodeNum = 0;
+ resetSortedKeyCharsTable();
+ showCursor(true);
+ } else {
+ _newEpisodeNum = ConfMan.getInt("boot_param");
+ if (_newEpisodeNum == 0) {
+ _newEpisodeNum = kStartupEpisode;
+ }
+ showCursor(_newEpisodeNum != kStartupEpisode);
}
- _inp_leftMouseButtonPressed = false;
- _inp_rightMouseButtonPressed = false;
- showCursor(_newEpisodeNum != kStartupEpisode);
-
uint32 frameTimeStamp = _system->getMillis();
for (uint32 cycleCounter = 0; _flagsTable[611] == 0; ++cycleCounter) {
if ((cycleCounter % 3) == 0) {