aboutsummaryrefslogtreecommitdiff
path: root/engines
diff options
context:
space:
mode:
authorDavid Corrales2007-08-05 19:34:20 +0000
committerDavid Corrales2007-08-05 19:34:20 +0000
commit6856535010bd2fa4449bcfde1c88dc06cd46e26f (patch)
treeb81a2234c2beff0312c93e039d6cafda4babeca6 /engines
parent1400d28bfb37fc94f3c44dec0a4d0cef65fb8fb7 (diff)
parentec1803f838d5efc7decf75c05a1fb4a9633751e5 (diff)
downloadscummvm-rg350-6856535010bd2fa4449bcfde1c88dc06cd46e26f.tar.gz
scummvm-rg350-6856535010bd2fa4449bcfde1c88dc06cd46e26f.tar.bz2
scummvm-rg350-6856535010bd2fa4449bcfde1c88dc06cd46e26f.zip
Merged fsnode with trunk: r27971:28460
svn-id: r28462
Diffstat (limited to 'engines')
-rw-r--r--engines/agi/agi.cpp78
-rw-r--r--engines/agi/agi.h120
-rw-r--r--engines/agi/detection.cpp227
-rw-r--r--engines/agi/graphics.cpp258
-rw-r--r--engines/agi/graphics.h10
-rw-r--r--engines/agi/keyboard.cpp8
-rw-r--r--engines/agi/menu.cpp8
-rw-r--r--engines/agi/predictive.cpp17
-rw-r--r--engines/agi/saveload.cpp26
-rw-r--r--engines/agi/sound.cpp180
-rw-r--r--engines/agi/text.cpp4
-rw-r--r--engines/agos/agos.cpp18
-rw-r--r--engines/agos/agos.h5
-rw-r--r--engines/agos/detection_tables.h26
-rw-r--r--engines/agos/input.cpp2
-rw-r--r--engines/agos/items.cpp28
-rw-r--r--engines/agos/res_snd.cpp55
-rw-r--r--engines/agos/saveload.cpp10
-rw-r--r--engines/agos/sound.cpp12
-rw-r--r--engines/agos/zones.cpp27
-rw-r--r--engines/drascula/detection.cpp183
-rw-r--r--engines/drascula/drascula.cpp6859
-rw-r--r--engines/drascula/drascula.h702
-rw-r--r--engines/drascula/module.mk14
-rw-r--r--engines/drascula/texts.h753
-rw-r--r--engines/engines.mk6
-rw-r--r--engines/gob/cdrom.cpp17
-rw-r--r--engines/gob/coktelvideo.cpp1289
-rw-r--r--engines/gob/coktelvideo.h313
-rw-r--r--engines/gob/dataio.cpp151
-rw-r--r--engines/gob/dataio.h47
-rw-r--r--engines/gob/detection.cpp719
-rw-r--r--engines/gob/draw.cpp85
-rw-r--r--engines/gob/draw.h19
-rw-r--r--engines/gob/draw_v2.cpp39
-rw-r--r--engines/gob/game.cpp103
-rw-r--r--engines/gob/game.h8
-rw-r--r--engines/gob/game_v1.cpp3
-rw-r--r--engines/gob/game_v2.cpp61
-rw-r--r--engines/gob/global.cpp2
-rw-r--r--engines/gob/gob.cpp289
-rw-r--r--engines/gob/gob.h44
-rw-r--r--engines/gob/goblin.cpp3
-rw-r--r--engines/gob/goblin_v2.cpp3
-rw-r--r--engines/gob/goblin_v3.cpp3
-rw-r--r--engines/gob/imd.cpp1249
-rw-r--r--engines/gob/imd.h143
-rw-r--r--engines/gob/init.cpp27
-rw-r--r--engines/gob/inter.cpp2
-rw-r--r--engines/gob/inter.h42
-rw-r--r--engines/gob/inter_bargon.cpp42
-rw-r--r--engines/gob/inter_v1.cpp51
-rw-r--r--engines/gob/inter_v2.cpp197
-rw-r--r--engines/gob/inter_v3.cpp12
-rw-r--r--engines/gob/inter_v4.cpp786
-rw-r--r--engines/gob/map.cpp2
-rw-r--r--engines/gob/module.mk6
-rw-r--r--engines/gob/mult.h20
-rw-r--r--engines/gob/mult_v1.cpp12
-rw-r--r--engines/gob/mult_v2.cpp59
-rw-r--r--engines/gob/saveload.h9
-rw-r--r--engines/gob/saveload_v2.cpp4
-rw-r--r--engines/gob/saveload_v3.cpp39
-rw-r--r--engines/gob/scenery.cpp2
-rw-r--r--engines/gob/util.cpp17
-rw-r--r--engines/gob/video.cpp14
-rw-r--r--engines/gob/video.h1
-rw-r--r--engines/gob/videoplayer.cpp333
-rw-r--r--engines/gob/videoplayer.h86
-rw-r--r--engines/kyra/animator_v1.cpp (renamed from engines/kyra/animator.cpp)6
-rw-r--r--engines/kyra/animator_v1.h (renamed from engines/kyra/animator.h)6
-rw-r--r--engines/kyra/animator_v2.cpp313
-rw-r--r--engines/kyra/debugger.cpp53
-rw-r--r--engines/kyra/debugger.h11
-rw-r--r--engines/kyra/detection.cpp2
-rw-r--r--engines/kyra/gui_v1.cpp (renamed from engines/kyra/gui.cpp)342
-rw-r--r--engines/kyra/gui_v2.cpp198
-rw-r--r--engines/kyra/items_v1.cpp (renamed from engines/kyra/items.cpp)128
-rw-r--r--engines/kyra/items_v2.cpp56
-rw-r--r--engines/kyra/kyra.cpp993
-rw-r--r--engines/kyra/kyra.h891
-rw-r--r--engines/kyra/kyra_v1.cpp977
-rw-r--r--engines/kyra/kyra_v1.h765
-rw-r--r--engines/kyra/kyra_v2.cpp1187
-rw-r--r--engines/kyra/kyra_v2.h375
-rw-r--r--engines/kyra/kyra_v3.cpp18
-rw-r--r--engines/kyra/kyra_v3.h11
-rw-r--r--engines/kyra/module.mk20
-rw-r--r--engines/kyra/resource.cpp17
-rw-r--r--engines/kyra/resource.h5
-rw-r--r--engines/kyra/saveload_v1.cpp (renamed from engines/kyra/saveload.cpp)31
-rw-r--r--engines/kyra/scene.cpp1325
-rw-r--r--engines/kyra/scene_v1.cpp1282
-rw-r--r--engines/kyra/scene_v2.cpp867
-rw-r--r--engines/kyra/screen.cpp81
-rw-r--r--engines/kyra/screen.h26
-rw-r--r--engines/kyra/screen_v1.cpp53
-rw-r--r--engines/kyra/screen_v1.h48
-rw-r--r--engines/kyra/screen_v2.cpp561
-rw-r--r--engines/kyra/screen_v2.h84
-rw-r--r--engines/kyra/script.cpp209
-rw-r--r--engines/kyra/script.h94
-rw-r--r--engines/kyra/script_v1.cpp329
-rw-r--r--engines/kyra/script_v2.cpp430
-rw-r--r--engines/kyra/seqplayer.cpp3
-rw-r--r--engines/kyra/seqplayer.h7
-rw-r--r--engines/kyra/sequences_v1.cpp156
-rw-r--r--engines/kyra/sequences_v2.cpp1
-rw-r--r--engines/kyra/sound.cpp115
-rw-r--r--engines/kyra/sound.h7
-rw-r--r--engines/kyra/sound_v1.cpp140
-rw-r--r--engines/kyra/sprites.cpp6
-rw-r--r--engines/kyra/sprites.h9
-rw-r--r--engines/kyra/staticres.cpp192
-rw-r--r--engines/kyra/text.cpp365
-rw-r--r--engines/kyra/text_v1.cpp399
-rw-r--r--engines/kyra/timer.cpp393
-rw-r--r--engines/kyra/timer.h93
-rw-r--r--engines/kyra/timer_v1.cpp180
-rw-r--r--engines/kyra/timer_v2.cpp80
-rw-r--r--engines/kyra/util.h63
-rw-r--r--engines/kyra/wsamovie.cpp101
-rw-r--r--engines/kyra/wsamovie.h18
-rw-r--r--engines/lure/game.cpp11
-rw-r--r--engines/lure/game.h2
-rw-r--r--engines/lure/hotspots.cpp88
-rw-r--r--engines/lure/hotspots.h7
-rw-r--r--engines/lure/luredefs.h2
-rw-r--r--engines/lure/res_struct.cpp15
-rw-r--r--engines/lure/res_struct.h10
-rw-r--r--engines/lure/room.cpp47
-rw-r--r--engines/lure/screen.cpp37
-rw-r--r--engines/lure/screen.h3
-rw-r--r--engines/parallaction/animation.cpp4
-rw-r--r--engines/parallaction/archive.cpp208
-rw-r--r--engines/parallaction/callables.cpp460
-rw-r--r--engines/parallaction/callables_br.cpp60
-rw-r--r--engines/parallaction/callables_ns.cpp718
-rw-r--r--engines/parallaction/commands.cpp7
-rw-r--r--engines/parallaction/detection.cpp50
-rw-r--r--engines/parallaction/dialogue.cpp6
-rw-r--r--engines/parallaction/disk.h122
-rw-r--r--engines/parallaction/disk_br.cpp134
-rw-r--r--engines/parallaction/disk_ns.cpp (renamed from engines/parallaction/disk.cpp)364
-rw-r--r--engines/parallaction/font.cpp4
-rw-r--r--engines/parallaction/graphics.cpp189
-rw-r--r--engines/parallaction/graphics.h25
-rw-r--r--engines/parallaction/intro.cpp320
-rw-r--r--engines/parallaction/inventory.cpp129
-rw-r--r--engines/parallaction/inventory.h13
-rw-r--r--engines/parallaction/location.cpp10
-rw-r--r--engines/parallaction/menu.cpp155
-rw-r--r--engines/parallaction/menu.h1
-rw-r--r--engines/parallaction/module.mk10
-rw-r--r--engines/parallaction/parallaction.cpp117
-rw-r--r--engines/parallaction/parallaction.h116
-rw-r--r--engines/parallaction/parallaction_br.cpp66
-rw-r--r--engines/parallaction/parallaction_ns.cpp78
-rw-r--r--engines/parallaction/saveload.cpp6
-rw-r--r--engines/parallaction/sound.cpp2
-rw-r--r--engines/parallaction/sound.h16
-rw-r--r--engines/parallaction/staticres.cpp355
-rw-r--r--engines/parallaction/walk.cpp58
-rw-r--r--engines/parallaction/zone.cpp28
-rw-r--r--engines/queen/sound.cpp12
-rw-r--r--engines/saga/actor.cpp37
-rw-r--r--engines/saga/actor.h7
-rw-r--r--engines/saga/animation.cpp36
-rw-r--r--engines/saga/animation.h3
-rw-r--r--engines/saga/detection.cpp34
-rw-r--r--engines/saga/detection_tables.h1016
-rw-r--r--engines/saga/displayinfo.h2
-rw-r--r--engines/saga/events.cpp41
-rw-r--r--engines/saga/events.h3
-rw-r--r--engines/saga/font.cpp8
-rw-r--r--engines/saga/gfx.cpp10
-rw-r--r--engines/saga/ihnm_introproc.cpp146
-rw-r--r--engines/saga/image.cpp1
-rw-r--r--engines/saga/interface.cpp180
-rw-r--r--engines/saga/isomap.cpp2
-rw-r--r--engines/saga/ite_introproc.cpp1
-rw-r--r--engines/saga/list.h2
-rw-r--r--engines/saga/music.cpp160
-rw-r--r--engines/saga/music.h2
-rw-r--r--engines/saga/objectmap.cpp1
-rw-r--r--engines/saga/puzzle.h2
-rw-r--r--engines/saga/render.cpp1
-rw-r--r--engines/saga/rscfile.cpp230
-rw-r--r--engines/saga/rscfile.h2
-rw-r--r--engines/saga/saga.cpp6
-rw-r--r--engines/saga/saga.h5
-rw-r--r--engines/saga/sagaresnames.h34
-rw-r--r--engines/saga/saveload.cpp13
-rw-r--r--engines/saga/scene.cpp202
-rw-r--r--engines/saga/scene.h7
-rw-r--r--engines/saga/script.cpp4
-rw-r--r--engines/saga/script.h9
-rw-r--r--engines/saga/sfuncs.cpp182
-rw-r--r--engines/saga/sndres.cpp29
-rw-r--r--engines/saga/sound.cpp21
-rw-r--r--engines/saga/sprite.cpp14
-rw-r--r--engines/scumm/charset.cpp109
-rw-r--r--engines/scumm/detection.cpp7
-rw-r--r--engines/scumm/detection_tables.h4
-rw-r--r--engines/scumm/gfx.cpp317
-rwxr-xr-xengines/scumm/gfxARM.s120
-rw-r--r--engines/scumm/imuse_digi/dimuse.cpp47
-rw-r--r--engines/scumm/imuse_digi/dimuse.h2
-rw-r--r--engines/scumm/imuse_digi/dimuse_script.cpp10
-rw-r--r--engines/scumm/imuse_digi/dimuse_sndmgr.cpp284
-rw-r--r--engines/scumm/imuse_digi/dimuse_sndmgr.h70
-rw-r--r--engines/scumm/imuse_digi/dimuse_track.cpp31
-rw-r--r--engines/scumm/input.cpp5
-rw-r--r--engines/scumm/module.mk5
-rw-r--r--engines/scumm/scumm-md5.h6
-rw-r--r--engines/scumm/scumm.cpp28
-rw-r--r--engines/scumm/scumm.h4
-rw-r--r--engines/scumm/smush/smush_player.cpp7
-rw-r--r--engines/scumm/sound.cpp15
-rw-r--r--engines/scumm/string.cpp16
-rw-r--r--engines/sword1/music.cpp4
-rw-r--r--engines/sword1/sound.cpp12
-rw-r--r--engines/sword2/music.cpp54
-rw-r--r--engines/touche/graphics.cpp64
-rw-r--r--engines/touche/midi.cpp9
-rw-r--r--engines/touche/midi.h5
-rw-r--r--engines/touche/opcodes.cpp10
-rw-r--r--engines/touche/resource.cpp26
-rw-r--r--engines/touche/saveload.cpp12
-rw-r--r--engines/touche/staticres.cpp11
-rw-r--r--engines/touche/touche.cpp107
-rw-r--r--engines/touche/touche.h6
232 files changed, 27845 insertions, 10191 deletions
diff --git a/engines/agi/agi.cpp b/engines/agi/agi.cpp
index 0839b7de99..1c1c53dee7 100644
--- a/engines/agi/agi.cpp
+++ b/engines/agi/agi.cpp
@@ -178,7 +178,7 @@ void AgiEngine::processEvents() {
case Common::KEYCODE_MINUS:
key = '-';
break;
- case Common::KEYCODE_9:
+ case Common::KEYCODE_TAB:
key = 0x0009;
break;
case Common::KEYCODE_F1:
@@ -448,6 +448,12 @@ int AgiEngine::agiInit() {
loadGame(saveNameBuffer, false); // Do not check game id
}
+#ifdef __DS__
+ // Normally, the engine loads the predictive text dictionary when the predictive dialog
+ // is shown. On the DS version, the word completion feature needs the dictionary too.
+ loadDict();
+#endif
+
return ec;
}
@@ -535,6 +541,67 @@ static const GameSettings agiSettings[] = {
{NULL, NULL, 0, 0, NULL}
};
+AgiTextColor AgiButtonStyle::getColor(bool hasFocus, bool pressed, bool positive) const {
+ if (_amigaStyle) {
+ if (positive) {
+ if (pressed) { // Positive pressed Amiga-style button
+ if (_olderAgi) {
+ return AgiTextColor(amigaBlack, amigaOrange);
+ } else {
+ return AgiTextColor(amigaBlack, amigaPurple);
+ }
+ } else { // Positive unpressed Amiga-style button
+ return AgiTextColor(amigaWhite, amigaGreen);
+ }
+ } else { // _amigaStyle && !positive
+ if (pressed) { // Negative pressed Amiga-style button
+ return AgiTextColor(amigaBlack, amigaCyan);
+ } else { // Negative unpressed Amiga-style button
+ return AgiTextColor(amigaWhite, amigaRed);
+ }
+ }
+ } else { // PC-style button
+ if (hasFocus || pressed) { // A pressed or in focus PC-style button
+ return AgiTextColor(pcWhite, pcBlack);
+ } else { // An unpressed PC-style button without focus
+ return AgiTextColor(pcBlack, pcWhite);
+ }
+ }
+}
+
+AgiTextColor AgiButtonStyle::getColor(bool hasFocus, bool pressed, int baseFgColor, int baseBgColor) const {
+ return getColor(hasFocus, pressed, AgiTextColor(baseFgColor, baseBgColor));
+}
+
+AgiTextColor AgiButtonStyle::getColor(bool hasFocus, bool pressed, const AgiTextColor &baseColor) const {
+ if (hasFocus || pressed)
+ return baseColor.swap();
+ else
+ return baseColor;
+}
+
+int AgiButtonStyle::getTextOffset(bool hasFocus, bool pressed) const {
+ return (pressed && !_amigaStyle) ? 1 : 0;
+}
+
+bool AgiButtonStyle::getBorder(bool hasFocus, bool pressed) const {
+ return _amigaStyle && !_authenticAmiga && (hasFocus || pressed);
+}
+
+void AgiButtonStyle::setAmigaStyle(bool amigaStyle, bool olderAgi, bool authenticAmiga) {
+ _amigaStyle = amigaStyle;
+ _olderAgi = olderAgi;
+ _authenticAmiga = authenticAmiga;
+}
+
+void AgiButtonStyle::setPcStyle(bool pcStyle) {
+ setAmigaStyle(!pcStyle);
+}
+
+AgiButtonStyle::AgiButtonStyle(Common::RenderMode renderMode) {
+ setAmigaStyle(renderMode == Common::kRenderAmiga);
+}
+
AgiEngine::AgiEngine(OSystem *syst) : Engine(syst) {
// Setup mixer
@@ -635,6 +702,8 @@ void AgiEngine::initialize() {
}
}
+ _buttonStyle = AgiButtonStyle(_renderMode);
+ _defaultButtonStyle = AgiButtonStyle();
_console = new Console(this);
_gfx = new GfxMgr(this);
_sound = new SoundMgr(this, _mixer);
@@ -676,6 +745,13 @@ void AgiEngine::initialize() {
}
AgiEngine::~AgiEngine() {
+ // If the engine hasn't been initialized yet via AgiEngine::initialize(), don't attempt to free any resources,
+ // as they haven't been allocated. Fixes bug #1742432 - AGI: Engine crashes if no game is detected
+ if (_game.state == STATE_INIT) {
+ delete _rnd; // delete _rnd, as it is allocated in the constructor, not in initialize()
+ return;
+ }
+
agiDeinit();
_sound->deinitSound();
delete _sound;
diff --git a/engines/agi/agi.h b/engines/agi/agi.h
index 01db2acb23..f37b61478e 100644
--- a/engines/agi/agi.h
+++ b/engines/agi/agi.h
@@ -81,6 +81,7 @@ typedef signed int Err;
#define MSG_BOX_COLOUR 0x0f /* White */
#define MSG_BOX_TEXT 0x00 /* Black */
#define MSG_BOX_LINE 0x04 /* Red */
+#define BUTTON_BORDER 0x00 /* Black */
#define STATUS_FG 0x00 /* Black */
#define STATUS_BG 0x0f /* White */
@@ -110,7 +111,9 @@ enum AgiGameFeatures {
GF_AGI256_2 = (1 << 3),
GF_AGIPAL = (1 << 4),
GF_MACGOLDRUSH = (1 << 5),
- GF_FANMADE = (1 << 6)
+ GF_FANMADE = (1 << 6),
+ GF_MENUS = (1 << 7),
+ GF_ESCPAUSE = (1 << 8)
};
enum AgiGameID {
@@ -153,6 +156,7 @@ enum AGIErrors {
errNoLoopsInView,
errViewDataError,
errNoGameList,
+ errIOError,
errUnk = 127
};
@@ -317,6 +321,118 @@ struct AgiBlock {
uint8 *buffer; /* used for window background */
};
+/** AGI text color (Background and foreground color). */
+struct AgiTextColor {
+ /** Creates an AGI text color. Uses black text on white background by default. */
+ AgiTextColor(int fgColor = 0x00, int bgColor = 0x0F) : fg(fgColor), bg(bgColor) {}
+
+ /** Get an AGI text color with swapped foreground and background color. */
+ AgiTextColor swap() const { return AgiTextColor(bg, fg); }
+
+ int fg; ///< Foreground color (Used for text).
+ int bg; ///< Background color (Used for text's background).
+};
+
+/**
+ * AGI button style (Amiga or PC).
+ *
+ * Supports positive and negative button types (Used with Amiga-style only):
+ * Positive buttons do what the dialog was opened for.
+ * Negative buttons cancel what the dialog was opened for.
+ * Restart-dialog example: Restart-button is positive, Cancel-button negative.
+ * Paused-dialog example: Continue-button is positive.
+ */
+struct AgiButtonStyle {
+// Public constants etc
+public:
+ static const int
+ // Amiga colors (Indexes into the Amiga-ish palette)
+ amigaBlack = 0x00, ///< Accurate, is #000000 (24-bit RGB)
+ amigaWhite = 0x0F, ///< Practically accurate, is close to #FFFFFF (24-bit RGB)
+ amigaGreen = 0x02, ///< Quite accurate, should be #008A00 (24-bit RGB)
+ amigaOrange = 0x0C, ///< Inaccurate, too much blue, should be #FF7500 (24-bit RGB)
+ amigaPurple = 0x0D, ///< Inaccurate, too much green, should be #FF00FF (24-bit RGB)
+ amigaRed = 0x04, ///< Quite accurate, should be #BD0000 (24-bit RGB)
+ amigaCyan = 0x0B, ///< Inaccurate, too much red, should be #00FFDE (24-bit RGB)
+ // PC colors (Indexes into the EGA-palette)
+ pcBlack = 0x00,
+ pcWhite = 0x0F;
+
+// Public methods
+public:
+ /**
+ * Get the color of the button with the given state and type using current style.
+ *
+ * @param hasFocus True if button has focus, false otherwise.
+ * @param pressed True if button is being pressed, false otherwise.
+ * @param positive True if button is positive, false if button is negative. Only matters for Amiga-style buttons.
+ */
+ AgiTextColor getColor(bool hasFocus, bool pressed, bool positive = true) const;
+
+ /**
+ * Get the color of a button with the given base color and state ignoring current style.
+ * Swaps foreground and background color when the button has focus or is being pressed.
+ *
+ * @param hasFocus True if button has focus, false otherwise.
+ * @param pressed True if button is being pressed, false otherwise.
+ * @param baseFgColor Foreground color of the button when it has no focus and is not being pressed.
+ * @param baseBgColor Background color of the button when it has no focus and is not being pressed.
+ */
+ AgiTextColor getColor(bool hasFocus, bool pressed, int baseFgColor, int baseBgColor) const;
+
+ /**
+ * Get the color of a button with the given base color and state ignoring current style.
+ * Swaps foreground and background color when the button has focus or is being pressed.
+ *
+ * @param hasFocus True if button has focus, false otherwise.
+ * @param pressed True if button is being pressed, false otherwise.
+ * @param baseColor Color of the button when it has no focus and is not being pressed.
+ */
+ AgiTextColor getColor(bool hasFocus, bool pressed, const AgiTextColor &baseColor) const;
+
+ /**
+ * How many pixels to offset the shown text diagonally down and to the right.
+ * Currently only used for pressed PC-style buttons.
+ */
+ int getTextOffset(bool hasFocus, bool pressed) const;
+
+ /**
+ * Show border around the button?
+ * Currently border is only used for in focus or pressed Amiga-style buttons
+ * when in inauthentic Amiga-style mode.
+ */
+ bool getBorder(bool hasFocus, bool pressed) const;
+
+ /**
+ * Set Amiga-button style.
+ *
+ * @param amigaStyle Set Amiga-button style if true, otherwise set PC-button style.
+ * @param olderAgi If true then use older AGI style in Amiga-mode, otherwise use newer.
+ * @param authenticAmiga If true then don't use a border around buttons in Amiga-mode, otherwise use.
+ */
+ void setAmigaStyle(bool amigaStyle = true, bool olderAgi = false, bool authenticAmiga = false);
+
+ /**
+ * Set PC-button style.
+ * @param pcStyle Set PC-button style if true, otherwise set default Amiga-button style.
+ */
+ void setPcStyle(bool pcStyle = true);
+
+// Public constructors
+public:
+ /**
+ * Create a button style based on the given rendering mode.
+ * @param renderMode If Common::kRenderAmiga then creates default Amiga-button style, otherwise PC-style.
+ */
+ AgiButtonStyle(Common::RenderMode renderMode = Common::kRenderDefault);
+
+// Private member variables
+private:
+ bool _amigaStyle; ///< Use Amiga-style buttons if true, otherwise use PC-style buttons.
+ bool _olderAgi; ///< Use older AGI style in Amiga-style mode.
+ bool _authenticAmiga; ///< Don't use border around buttons in Amiga-style mode.
+};
+
#define EGO_VIEW_TABLE 0
#define HORIZON 36
#define _WIDTH 160
@@ -594,6 +710,8 @@ public:
int _oldMode;
Menu* _menu;
+ AgiButtonStyle _buttonStyle;
+ AgiButtonStyle _defaultButtonStyle;
char _lastSentence[40];
diff --git a/engines/agi/detection.cpp b/engines/agi/detection.cpp
index 1ab59c0806..79e3be3238 100644
--- a/engines/agi/detection.cpp
+++ b/engines/agi/detection.cpp
@@ -125,7 +125,7 @@ static const AGIGameDescription gameDescriptions[] = {
{
- // Sarien Name == AGI Demo 1 (PC) 05/87 [AGI 2.425]
+ // AGI Demo 1 (PC) 05/87 [AGI 2.425]
{
"agidemo",
"Demo 1 1987-05-20",
@@ -142,7 +142,7 @@ static const AGIGameDescription gameDescriptions[] = {
{
- // Sarien Name == AGI Demo 2 (IIgs) 1.0C (Censored)
+ // AGI Demo 2 (IIgs) 1.0C (Censored)
{
"agidemo",
"Demo 2 1987-11-24 1.0C",
@@ -159,7 +159,7 @@ static const AGIGameDescription gameDescriptions[] = {
{
- // Sarien Name == AGI Demo 2 (PC 3.5") 11/87 [AGI 2.915]
+ // AGI Demo 2 (PC 3.5") 11/87 [AGI 2.915]
{
"agidemo",
"Demo 2 1987-11-24 3.5\"",
@@ -176,7 +176,7 @@ static const AGIGameDescription gameDescriptions[] = {
{
- // Sarien Name == AGI Demo 2 (PC 5.25") 11/87 [v1] [AGI 2.915]
+ // AGI Demo 2 (PC 5.25") 11/87 [v1] [AGI 2.915]
{
"agidemo",
"Demo 2 1987-11-24 [version 1] 5.25\"",
@@ -193,7 +193,7 @@ static const AGIGameDescription gameDescriptions[] = {
{
- // Sarien Name == AGI Demo 2 (PC 5.25") 01/88 [v2] [AGI 2.917]
+ // AGI Demo 2 (PC 5.25") 01/88 [v2] [AGI 2.917]
{
"agidemo",
"Demo 2 1988-01-25 [version 2] 5.25\"",
@@ -210,7 +210,7 @@ static const AGIGameDescription gameDescriptions[] = {
{
- // Sarien Name == AGI Demo 3 (PC) 09/88 [AGI 3.002.102]
+ // AGI Demo 3 (PC) 09/88 [AGI 3.002.102]
{
"agidemo",
"Demo 3 1988-09-13",
@@ -227,7 +227,7 @@ static const AGIGameDescription gameDescriptions[] = {
{
- // Sarien Name == Black Cauldron (Amiga) 2.00 6/14/87
+ // Black Cauldron (Amiga) 2.00 6/14/87
{
"bc",
"2.00 1987-06-14",
@@ -244,7 +244,8 @@ static const AGIGameDescription gameDescriptions[] = {
{
- // Sarien Name == Black Cauldron (Apple IIgs) 1.0O 2/24/89 (CE)
+ // Black Cauldron (Apple IIgs) 1.0O 2/24/89 (CE)
+ // Menus not tested
{
"bc",
"1.0O 1989-02-24 (CE)",
@@ -261,7 +262,7 @@ static const AGIGameDescription gameDescriptions[] = {
{
- // Sarien Name == Black Cauldron (PC) 2.00 6/14/87 [AGI 2.439]
+ // Black Cauldron (PC) 2.00 6/14/87 [AGI 2.439]
{
"bc",
"2.00 1987-06-14",
@@ -278,7 +279,7 @@ static const AGIGameDescription gameDescriptions[] = {
{
- // Sarien Name == Black Cauldron (PC 5.25") 2.10 11/10/88 [AGI 3.002.098]
+ // Black Cauldron (PC 5.25") 2.10 11/10/88 [AGI 3.002.098]
{
"bc",
"2.10 1988-11-10 5.25\"",
@@ -297,7 +298,8 @@ static const AGIGameDescription gameDescriptions[] = {
// These aren't supposed to work now as they require unsupported agi engine 2.01
#if 0
{
- // Sarien Name == Donald Duck's Playground (Amiga) 1.0C
+ // Donald Duck's Playground (Amiga) 1.0C
+ // Menus not tested
{
"ddp",
"1.0C 1987-04-27",
@@ -314,7 +316,8 @@ static const AGIGameDescription gameDescriptions[] = {
{
- // Sarien Name == Donald Duck's Playground (ST) 1.0A 8/8/86
+ // Donald Duck's Playground (ST) 1.0A 8/8/86
+ // Menus not tested
{
"ddp",
"1.0A 1986-08-08",
@@ -332,6 +335,7 @@ static const AGIGameDescription gameDescriptions[] = {
{
// reported by Filippos (thebluegr) in bugreport #1654500
+ // Menus not tested
{
"ddp",
"1.0C 1986-06-09", // verify date
@@ -348,7 +352,7 @@ static const AGIGameDescription gameDescriptions[] = {
#endif
{
- // Sarien Name == Gold Rush! (Amiga) 1.01 1/13/89 aka 2.05 3/9/89 # 2.316
+ // Gold Rush! (Amiga) 1.01 1/13/89 aka 2.05 3/9/89 # 2.316
{
"goldrush",
"1.01 1989-01-13 aka 2.05 1989-03-09",
@@ -365,7 +369,8 @@ static const AGIGameDescription gameDescriptions[] = {
{
- // Sarien Name == Gold Rush! (Apple IIgs) 1.0M 2/28/89 (CE) aka 2.01 12/22/88
+ // Gold Rush! (Apple IIgs) 1.0M 2/28/89 (CE) aka 2.01 12/22/88
+ // Menus not tested
{
"goldrush",
"1.0M 1989-02-28 (CE) aka 2.01 1988-12-22",
@@ -382,7 +387,7 @@ static const AGIGameDescription gameDescriptions[] = {
{
- // Sarien Name == Gold Rush! (ST) 1.01 1/13/89 aka 2.01 12/22/88
+ // Gold Rush! (ST) 1.01 1/13/89 aka 2.01 12/22/88
{
"goldrush",
"1.01 1989-01-13 aka 2.01 1988-12-22",
@@ -399,7 +404,7 @@ static const AGIGameDescription gameDescriptions[] = {
{
- // Sarien Name == Gold Rush! (PC 5.25") 2.01 12/22/88 [AGI 3.002.149]
+ // Gold Rush! (PC 5.25") 2.01 12/22/88 [AGI 3.002.149]
{
"goldrush",
"2.01 1988-12-22 5.25\"",
@@ -416,7 +421,7 @@ static const AGIGameDescription gameDescriptions[] = {
{
- // Sarien Name == Gold Rush! (PC 3.5") 2.01 12/22/88 [AGI 3.002.149]
+ // Gold Rush! (PC 3.5") 2.01 12/22/88 [AGI 3.002.149]
{
"goldrush",
"2.01 1988-12-22 3.5\"",
@@ -433,7 +438,7 @@ static const AGIGameDescription gameDescriptions[] = {
{
- // Sarien Name == Gold Rush! (PC 5.25") 2.01 12/22/88 [AGI 3.002.149]
+ // Gold Rush! (PC 5.25") 2.01 12/22/88 [AGI 3.002.149]
{
"goldrush",
"2.01 1988-12-22",
@@ -454,7 +459,8 @@ static const AGIGameDescription gameDescriptions[] = {
{
- // Sarien Name == King's Quest 1 (Amiga) 1.0U # 2.082
+ // King's Quest 1 (Amiga) 1.0U # 2.082
+ // The original game did not have menus, they are enabled under ScummVM
{
"kq1",
"1.0U 1986",
@@ -465,13 +471,14 @@ static const AGIGameDescription gameDescriptions[] = {
},
GID_KQ1,
GType_V2,
- 0,
+ GF_MENUS,
0x2440,
},
{
- // Sarien Name == King's Quest 1 (ST) 1.0V
+ // King's Quest 1 (ST) 1.0V
+ // The original game did not have menus, they are enabled under ScummVM
{
"kq1",
"1.0V 1986",
@@ -482,13 +489,14 @@ static const AGIGameDescription gameDescriptions[] = {
},
GID_KQ1,
GType_V2,
- 0,
+ GF_MENUS,
0x2272,
},
{
- // Sarien Name == King's Quest 1 (IIgs) 1.0S-88223
+ // King's Quest 1 (IIgs) 1.0S-88223
+ // Menus not tested
{
"kq1",
"1.0S 1988-02-23",
@@ -505,7 +513,7 @@ static const AGIGameDescription gameDescriptions[] = {
{
- // Sarien Name == King's Quest 1 (Mac) 2.0C
+ // King's Quest 1 (Mac) 2.0C
{
"kq1",
"2.0C 1987-03-26",
@@ -522,7 +530,7 @@ static const AGIGameDescription gameDescriptions[] = {
{
- // Sarien Name == King's Quest 1 (PC 5.25"/3.5") 2.0F [AGI 2.917]
+ // King's Quest 1 (PC 5.25"/3.5") 2.0F [AGI 2.917]
{
"kq1",
"2.0F 1987-05-05 5.25\"/3.5\"",
@@ -539,7 +547,7 @@ static const AGIGameDescription gameDescriptions[] = {
{
- // Sarien Name == King's Quest 2 (IIgs) 2.0A 6/16/88 (CE)
+ // King's Quest 2 (IIgs) 2.0A 6/16/88 (CE)
{
"kq2",
"2.0A 1988-06-16 (CE)",
@@ -556,7 +564,7 @@ static const AGIGameDescription gameDescriptions[] = {
{
- // Sarien Name == King's Quest 2 (Amiga) 2.0J (Broken)
+ // King's Quest 2 (Amiga) 2.0J (Broken)
{
"kq2",
"2.0J 1987-01-29 [OBJECT decrypted]",
@@ -573,7 +581,7 @@ static const AGIGameDescription gameDescriptions[] = {
{
- // Sarien Name == King's Quest 2 (Mac) 2.0R
+ // King's Quest 2 (Mac) 2.0R
{
"kq2",
"2.0R 1988-03-23",
@@ -607,7 +615,7 @@ static const AGIGameDescription gameDescriptions[] = {
{
- // Sarien Name == King's Quest 2 (PC 5.25"/3.5") 2.2 [AGI 2.426]
+ // King's Quest 2 (PC 5.25"/3.5") 2.2 [AGI 2.426]
{
"kq2",
"2.2 1987-05-07 5.25\"/3.5\"",
@@ -624,7 +632,8 @@ static const AGIGameDescription gameDescriptions[] = {
{
- // Sarien Name == King's Quest 3 (Amiga) 1.01 11/8/86
+ // King's Quest 3 (Amiga) 1.01 11/8/86
+ // The original game did not have menus, they are enabled under ScummVM
{
"kq3",
"1.01 1986-11-08",
@@ -635,13 +644,14 @@ static const AGIGameDescription gameDescriptions[] = {
},
GID_KQ3,
GType_V2,
- 0,
+ GF_MENUS,
0x2440,
},
{
- // Sarien Name == King's Quest 3 (ST) 1.02 11/18/86
+ // King's Quest 3 (ST) 1.02 11/18/86
+ // Does not have menus, crashes if menus are enforced. Therefore, ESC pauses the game
{
"kq3",
"1.02 1986-11-18",
@@ -652,13 +662,13 @@ static const AGIGameDescription gameDescriptions[] = {
},
GID_KQ3,
GType_V2,
- 0,
+ GF_ESCPAUSE,
0x2272,
},
{
- // Sarien Name == King's Quest 3 (Mac) 2.14 3/15/88
+ // King's Quest 3 (Mac) 2.14 3/15/88
{
"kq3",
"2.14 1988-03-15",
@@ -675,7 +685,7 @@ static const AGIGameDescription gameDescriptions[] = {
{
- // Sarien Name == King's Quest 3 (IIgs) 2.0A 8/28/88 (CE)
+ // King's Quest 3 (IIgs) 2.0A 8/28/88 (CE)
{
"kq3",
"2.0A 1988-08-28 (CE)",
@@ -692,7 +702,7 @@ static const AGIGameDescription gameDescriptions[] = {
{
- // Sarien Name == King's Quest 3 (Amiga) 2.15 11/15/89 # 2.333
+ // King's Quest 3 (Amiga) 2.15 11/15/89 # 2.333
{
"kq3",
"2.15 1989-11-15",
@@ -709,7 +719,8 @@ static const AGIGameDescription gameDescriptions[] = {
{
- // Sarien Name == King's Quest 3 (PC) 1.01 11/08/86 [AGI 2.272]
+ // King's Quest 3 (PC) 1.01 11/08/86 [AGI 2.272]
+ // Does not have menus, crashes if menus are enforced. Therefore, ESC pauses the game
{
"kq3",
"1.01 1986-11-08",
@@ -720,13 +731,13 @@ static const AGIGameDescription gameDescriptions[] = {
},
GID_KQ3,
GType_V2,
- 0,
+ GF_ESCPAUSE,
0x2272,
},
{
- // Sarien Name == King's Quest 3 (PC 5.25") 2.00 5/25/87 [AGI 2.435]
+ // King's Quest 3 (PC 5.25") 2.00 5/25/87 [AGI 2.435]
{
"kq3",
"2.00 1987-05-25 5.25\"",
@@ -743,7 +754,8 @@ static const AGIGameDescription gameDescriptions[] = {
{
- // Sarien Name == King's Quest 3 (Mac) 2.14 3/15/88
+ // King's Quest 3 (Mac) 2.14 3/15/88
+ // Menus not tested
{
"kq3",
"2.14 1988-03-15 5.25\"",
@@ -760,7 +772,7 @@ static const AGIGameDescription gameDescriptions[] = {
{
- // Sarien Name == King's Quest 3 (PC 3.5") 2.14 3/15/88 [AGI 2.936]
+ // King's Quest 3 (PC 3.5") 2.14 3/15/88 [AGI 2.936]
{
"kq3",
"2.14 1988-03-15 3.5\"",
@@ -777,7 +789,7 @@ static const AGIGameDescription gameDescriptions[] = {
{
- // Sarien Name == King's Quest 4 (PC 5.25") 2.3 9/27/88 [AGI 3.002.086]
+ // King's Quest 4 (PC 5.25") 2.3 9/27/88 [AGI 3.002.086]
{
"kq4",
"2.3 1988-09-27",
@@ -794,7 +806,8 @@ static const AGIGameDescription gameDescriptions[] = {
{
- // Sarien Name == King's Quest 4 (IIgs) 1.0K 11/22/88 (CE)
+ // King's Quest 4 (IIgs) 1.0K 11/22/88 (CE)
+ // Menus not tested
{
"kq4",
"1.0K 1988-11-22",
@@ -811,7 +824,7 @@ static const AGIGameDescription gameDescriptions[] = {
{
- // Sarien Name == King's Quest 4 (PC 3.5") 2.0 7/27/88 [AGI 3.002.086]
+ // King's Quest 4 (PC 3.5") 2.0 7/27/88 [AGI 3.002.086]
{
"kq4",
"2.0 1988-07-27 3.5\"",
@@ -828,7 +841,8 @@ static const AGIGameDescription gameDescriptions[] = {
{
- // Sarien Name == King's Quest 4 (PC 3.5") 2.2 9/27/88 [AGI 3.002.086]
+ // King's Quest 4 (PC 3.5") 2.2 9/27/88 [AGI 3.002.086]
+ // Menus not tested
{
"kq4",
"2.2 1988-09-27 3.5\"",
@@ -845,7 +859,8 @@ static const AGIGameDescription gameDescriptions[] = {
{
- // Sarien Name == King's Quest 4 demo (PC) [AGI 3.002.102]
+ // King's Quest 4 demo (PC) [AGI 3.002.102]
+ // Menus not tested
{
"kq4",
"Demo 1988-12-20",
@@ -862,7 +877,7 @@ static const AGIGameDescription gameDescriptions[] = {
{
- // Sarien Name == Leisure Suit Larry 1 (PC 5.25"/3.5") 1.00 6/1/87 [AGI 2.440]
+ // Leisure Suit Larry 1 (PC 5.25"/3.5") 1.00 6/1/87 [AGI 2.440]
{
"lsl1",
"1.00 1987-06-01 5.25\"/3.5\"",
@@ -879,7 +894,7 @@ static const AGIGameDescription gameDescriptions[] = {
{
- // Sarien Name == Leisure Suit Larry 1 (ST) 1.04 6/18/87
+ // Leisure Suit Larry 1 (ST) 1.04 6/18/87
{
"lsl1",
"1.04 1987-06-18",
@@ -896,7 +911,7 @@ static const AGIGameDescription gameDescriptions[] = {
{
- // Sarien Name == Leisure Suit Larry 1 (Amiga) 1.05 6/26/87 # x.yyy
+ // Leisure Suit Larry 1 (Amiga) 1.05 6/26/87 # x.yyy
{
"lsl1",
"1.05 1987-06-26",
@@ -913,7 +928,7 @@ static const AGIGameDescription gameDescriptions[] = {
{
- // Sarien Name == Leisure Suit Larry 1 (IIgs) 1.0E
+ // Leisure Suit Larry 1 (IIgs) 1.0E
{
"lsl1",
"1.0E 1987",
@@ -930,7 +945,7 @@ static const AGIGameDescription gameDescriptions[] = {
{
- // Sarien Name == Leisure Suit Larry 1 (Mac) 1.05 6/26/87
+ // Leisure Suit Larry 1 (Mac) 1.05 6/26/87
{
"lsl1",
"1.05 1987-06-26",
@@ -947,7 +962,7 @@ static const AGIGameDescription gameDescriptions[] = {
{
- // Sarien Name == Manhunter NY (ST) 1.03 10/20/88
+ // Manhunter NY (ST) 1.03 10/20/88
{
"mh1",
"1.03 1988-10-20",
@@ -964,7 +979,7 @@ static const AGIGameDescription gameDescriptions[] = {
{
- // Sarien Name == Manhunter NY (IIgs) 2.0E 10/05/88 (CE)
+ // Manhunter NY (IIgs) 2.0E 10/05/88 (CE)
{
"mh1",
"2.0E 1988-10-05 (CE)",
@@ -981,7 +996,7 @@ static const AGIGameDescription gameDescriptions[] = {
{
- // Sarien Name == Manhunter NY (Amiga) 1.06 3/18/89
+ // Manhunter NY (Amiga) 1.06 3/18/89
{
"mh1",
"1.06 1989-03-18",
@@ -999,7 +1014,7 @@ static const AGIGameDescription gameDescriptions[] = {
{
// reported by Filippos (thebluegr) in bugreport #1654500
- // Sarien Name == Manhunter NY (PC 5.25") 1.22 8/31/88 [AGI 3.002.107]
+ // Manhunter NY (PC 5.25") 1.22 8/31/88 [AGI 3.002.107]
{
"mh1",
"1.22 1988-08-31",
@@ -1016,7 +1031,7 @@ static const AGIGameDescription gameDescriptions[] = {
{
- // Sarien Name == Manhunter NY (PC 3.5") 1.22 8/31/88 [AGI 3.002.102]
+ // Manhunter NY (PC 3.5") 1.22 8/31/88 [AGI 3.002.102]
{
"mh1",
"1.22 1988-08-31",
@@ -1033,7 +1048,7 @@ static const AGIGameDescription gameDescriptions[] = {
{
- // Sarien Name == Manhunter SF (ST) 1.0 7/29/89
+ // Manhunter SF (ST) 1.0 7/29/89
{
"mh2",
"1.0 1989-07-29",
@@ -1050,7 +1065,7 @@ static const AGIGameDescription gameDescriptions[] = {
{
- // Sarien Name == Manhunter SF (Amiga) 3.06 8/17/89 # 2.333
+ // Manhunter SF (Amiga) 3.06 8/17/89 # 2.333
{
"mh2",
"3.06 1989-08-17",
@@ -1067,7 +1082,7 @@ static const AGIGameDescription gameDescriptions[] = {
{
- // Sarien Name == Manhunter SF (PC 5.25") 3.03 8/17/89 [AGI 3.002.149]
+ // Manhunter SF (PC 5.25") 3.03 8/17/89 [AGI 3.002.149]
{
"mh2",
"3.03 1989-08-17 5.25\"",
@@ -1084,7 +1099,7 @@ static const AGIGameDescription gameDescriptions[] = {
{
- // Sarien Name == Manhunter SF (PC 3.5") 3.02 7/26/89 [AGI 3.002.149]
+ // Manhunter SF (PC 3.5") 3.02 7/26/89 [AGI 3.002.149]
{
"mh2",
"3.02 1989-07-26 3.5\"",
@@ -1099,9 +1114,11 @@ static const AGIGameDescription gameDescriptions[] = {
0x3149,
},
-
+#if 0
{
- // Sarien Name == Mixed-Up Mother Goose (Amiga) 1.1
+ // Mixed-Up Mother Goose (Amiga) 1.1
+ // Problematic: crashes
+ // Menus not tested
{
"mixedup",
"1.1 1986-12-10",
@@ -1115,10 +1132,10 @@ static const AGIGameDescription gameDescriptions[] = {
0,
0x3086,
},
-
+#endif
{
- // Sarien Name == Mixed Up Mother Goose (IIgs)
+ // Mixed Up Mother Goose (IIgs)
{
"mixedup",
"1987",
@@ -1135,7 +1152,7 @@ static const AGIGameDescription gameDescriptions[] = {
{
- // Sarien Name == Mixed-Up Mother Goose (PC) [AGI 2.915]
+ // Mixed-Up Mother Goose (PC) [AGI 2.915]
{
"mixedup",
"1987-11-10",
@@ -1153,7 +1170,8 @@ static const AGIGameDescription gameDescriptions[] = {
#if 0
{
- // Sarien Name == Mixed Up Mother Goose (PC) [AGI 2.915] (Broken)
+ // Mixed Up Mother Goose (PC) [AGI 2.915] (Broken)
+ // Menus not tested
{
"mixedup",
"[corrupt/OBJECT from disk 1]",
@@ -1171,7 +1189,7 @@ static const AGIGameDescription gameDescriptions[] = {
{
- // Sarien Name == Police Quest 1 (PC) 2.0E 11/17/87 [AGI 2.915]
+ // Police Quest 1 (PC) 2.0E 11/17/87 [AGI 2.915]
{
"pq1",
"2.0E 1987-11-17",
@@ -1188,7 +1206,7 @@ static const AGIGameDescription gameDescriptions[] = {
{
- // Sarien Name == Police Quest 1 (Mac) 2.0G 12/3/87
+ // Police Quest 1 (Mac) 2.0G 12/3/87
{
"pq1",
"2.0G 1987-12-03",
@@ -1205,7 +1223,7 @@ static const AGIGameDescription gameDescriptions[] = {
{
- // Sarien Name == Police Quest 1 (IIgs) 2.0B-88421
+ // Police Quest 1 (IIgs) 2.0B-88421
{
"pq1",
"2.0B 1988-04-21",
@@ -1222,7 +1240,7 @@ static const AGIGameDescription gameDescriptions[] = {
{
- // Sarien Name == Police Quest 1 (Amiga) 2.0B 2/22/89 # 2.310
+ // Police Quest 1 (Amiga) 2.0B 2/22/89 # 2.310
{
"pq1",
"2.0B 1989-02-22",
@@ -1239,7 +1257,7 @@ static const AGIGameDescription gameDescriptions[] = {
{
- // Sarien Name == Police Quest 1 (IIgs) 2.0A-88318
+ // Police Quest 1 (IIgs) 2.0A-88318
{
"pq1",
"2.0A 1988-03-18",
@@ -1256,7 +1274,7 @@ static const AGIGameDescription gameDescriptions[] = {
{
- // Sarien Name == Police Quest 1 (PC) 2.0A 10/23/87 [AGI 2.903/2.911]
+ // Police Quest 1 (PC) 2.0A 10/23/87 [AGI 2.903/2.911]
{
"pq1",
"2.0A 1987-10-23",
@@ -1273,7 +1291,7 @@ static const AGIGameDescription gameDescriptions[] = {
{
- // Sarien Name == Police Quest 1 (Mac) 2.0G 12/3/87
+ // Police Quest 1 (Mac) 2.0G 12/3/87
{
"pq1",
"2.0G 1987-12-03 5.25\"/ST",
@@ -1307,7 +1325,8 @@ static const AGIGameDescription gameDescriptions[] = {
{
- // Sarien Name == Space Quest 1 (ST) 1.1A
+ // Space Quest 1 (ST) 1.1A
+ // The original game did not have menus, they are enabled under ScummVM
{
"sq1",
"1.1A 1986-02-06",
@@ -1318,13 +1337,14 @@ static const AGIGameDescription gameDescriptions[] = {
},
GID_SQ1,
GType_V2,
- 0,
+ GF_MENUS,
0x2440,
},
{
- // Sarien Name == Space Quest 1 (PC) 1.1A [AGI 2.272]
+ // Space Quest 1 (PC) 1.1A [AGI 2.272]
+ // The original game did not have menus, they are enabled under ScummVM
{
"sq1",
"1.1A 1986-11-13",
@@ -1335,13 +1355,14 @@ static const AGIGameDescription gameDescriptions[] = {
},
GID_SQ1,
GType_V2,
- 0,
+ GF_MENUS,
0x2272,
},
{
- // Sarien Name == Space Quest 1 (Amiga) 1.2 # 2.082
+ // Space Quest 1 (Amiga) 1.2 # 2.082
+ // The original game did not have menus, they are enabled under ScummVM
{
"sq1",
"1.2 1986",
@@ -1352,13 +1373,13 @@ static const AGIGameDescription gameDescriptions[] = {
},
GID_SQ1,
GType_V2,
- 0,
+ GF_MENUS,
0x2440,
},
{
- // Sarien Name == Space Quest 1 (Mac) 1.5D
+ // Space Quest 1 (Mac) 1.5D
{
"sq1",
"1.5D 1987-04-02",
@@ -1375,7 +1396,7 @@ static const AGIGameDescription gameDescriptions[] = {
{
- // Sarien Name == Space Quest 1 (IIgs) 2.2
+ // Space Quest 1 (IIgs) 2.2
{
"sq1",
"2.2 1987",
@@ -1392,7 +1413,8 @@ static const AGIGameDescription gameDescriptions[] = {
{
- // Sarien Name == Space Quest 1 (PC) 1.0X [AGI 2.089]
+ // Space Quest 1 (PC) 1.0X [AGI 2.089]
+ // Does not have menus, crashes if menus are enforced. Therefore, ESC pauses the game
{
"sq1",
"1.0X 1986-09-24",
@@ -1403,30 +1425,14 @@ static const AGIGameDescription gameDescriptions[] = {
},
GID_SQ1,
GType_V2,
- 0,
+ GF_ESCPAUSE,
0x2089,
},
- {
- // Sarien Name == Space Quest 1 (PC) 1.1A [AGI 2.272]
- {
- "sq1",
- "1.1A 1986-11-13",
- AD_ENTRY1("logdir", "8d8c20ab9f4b6e4817698637174a1cb6"),
- Common::EN_ANY,
- Common::kPlatformPC,
- Common::ADGF_NO_FLAGS
- },
- GID_SQ1,
- GType_V2,
- 0,
- 0x2272,
- },
-
{
- // Sarien Name == Space Quest 1 (PC 5.25"/3.5") 2.2 [AGI 2.426/2.917]
+ // Space Quest 1 (PC 5.25"/3.5") 2.2 [AGI 2.426/2.917]
{
"sq1",
"2.2 1987-05-07 5.25\"/3.5\"",
@@ -1444,7 +1450,7 @@ static const AGIGameDescription gameDescriptions[] = {
{
- // Sarien Name == Space Quest 2 (PC 3.5") 2.0D [AGI 2.936]
+ // Space Quest 2 (PC 3.5") 2.0D [AGI 2.936]
{
"sq2",
"2.0D 1988-03-14 3.5\"",
@@ -1461,7 +1467,7 @@ static const AGIGameDescription gameDescriptions[] = {
{
- // Sarien Name == Space Quest 2 (IIgs) 2.0A 7/25/88 (CE)
+ // Space Quest 2 (IIgs) 2.0A 7/25/88 (CE)
{
"sq2",
"2.0A 1988-07-25 (CE)",
@@ -1478,7 +1484,7 @@ static const AGIGameDescription gameDescriptions[] = {
{
- // Sarien Name == Space Quest 2 (Amiga) 2.0F
+ // Space Quest 2 (Amiga) 2.0F
{
"sq2",
"2.0F 1986-12-09 [VOL.2->PICTURE.16 broken]",
@@ -1499,7 +1505,7 @@ static const AGIGameDescription gameDescriptions[] = {
{
- // Sarien Name == Space Quest 2 (Mac) 2.0D
+ // Space Quest 2 (Mac) 2.0D
{
"sq2",
"2.0D 1988-04-04",
@@ -1517,7 +1523,7 @@ static const AGIGameDescription gameDescriptions[] = {
{
// reported by Filippos (thebluegr) in bugreport #1654500
- // Sarien Name == Space Quest 2 (PC 5.25") 2.0A [AGI 2.912]
+ // Space Quest 2 (PC 5.25") 2.0A [AGI 2.912]
{
"sq2",
"2.0A 1987-11-06 5.25\"",
@@ -1534,7 +1540,7 @@ static const AGIGameDescription gameDescriptions[] = {
{
- // Sarien Name == Space Quest 2 (PC 3.5") 2.0A [AGI 2.912]
+ // Space Quest 2 (PC 3.5") 2.0A [AGI 2.912]
{
"sq2",
"2.0A 1987-11-06 3.5\"",
@@ -1551,7 +1557,8 @@ static const AGIGameDescription gameDescriptions[] = {
{
- // Sarien Name == Space Quest 2 (PC 5.25"/ST) 2.0C/A [AGI 2.915]
+ // Space Quest 2 (PC 5.25"/ST) 2.0C/A [AGI 2.915]
+ // Menus not tested
{
"sq2",
"2.0C/A 5.25\"/ST",
@@ -1568,7 +1575,7 @@ static const AGIGameDescription gameDescriptions[] = {
{
- // Sarien Name == Space Quest 2 (PC 3.5") 2.0F [AGI 2.936]
+ // Space Quest 2 (PC 3.5") 2.0F [AGI 2.936]
{
"sq2",
"2.0F 1989-01-05 3.5\"",
@@ -1585,7 +1592,7 @@ static const AGIGameDescription gameDescriptions[] = {
{
- // Sarien Name == Xmas Card 1986 (PC) [AGI 2.272]
+ // Xmas Card 1986 (PC) [AGI 2.272]
{
"xmascard",
"1986-11-13 [version 1]",
@@ -1675,7 +1682,7 @@ static const AGIGameDescription gameDescriptions[] = {
FANMADE("Good Man (demo v3.41)", "3facd8a8f856b7b6e0f6c3200274d88c"),
{
- // Sarien Name == Groza
+ // Groza
{
"agi-fanmade",
"Groza (russian) [AGDS sample]",
diff --git a/engines/agi/graphics.cpp b/engines/agi/graphics.cpp
index 54f1783d83..b6430e0f81 100644
--- a/engines/agi/graphics.cpp
+++ b/engines/agi/graphics.cpp
@@ -68,6 +68,158 @@ uint8 egaPalette[16 * 3] = {
};
/**
+ * Atari ST AGI palette.
+ * Used by all of the tested Atari ST AGI games
+ * from Donald Duck's Playground (1986) to Manhunter II (1989).
+ * 16 RGB colors. 3 bits per color component.
+ */
+uint8 atariStAgiPalette[16 * 3] = {
+ 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x7,
+ 0x0, 0x4, 0x0,
+ 0x0, 0x5, 0x4,
+ 0x5, 0x0, 0x0,
+ 0x5, 0x3, 0x6,
+ 0x4, 0x3, 0x0,
+ 0x5, 0x5, 0x5,
+ 0x3, 0x3, 0x2,
+ 0x0, 0x5, 0x7,
+ 0x0, 0x6, 0x0,
+ 0x0, 0x7, 0x6,
+ 0x7, 0x2, 0x3,
+ 0x7, 0x4, 0x7,
+ 0x7, 0x7, 0x4,
+ 0x7, 0x7, 0x7
+};
+
+/**
+ * Second generation Apple IIGS AGI palette.
+ * A 16-color, 12-bit RGB palette.
+ *
+ * Used by at least the following Apple IIGS AGI versions:
+ * 1.003 (Leisure Suit Larry I v1.0E, intro says 1987)
+ * 1.005 (AGI Demo 2 1987-06-30?)
+ * 1.006 (King's Quest I v1.0S 1988-02-23)
+ * 1.007 (Police Quest I v2.0B 1988-04-21 8:00am)
+ * 1.013 (King's Quest II v2.0A 1988-06-16 (CE))
+ * 1.013 (Mixed-Up Mother Goose v2.0A 1988-05-31 10:00am)
+ * 1.014 (King's Quest III v2.0A 1988-08-28 (CE))
+ * 1.014 (Space Quest II v2.0A, LOGIC.141 says 1988)
+ * 2.004 (Manhunter I v2.0E 1988-10-05 (CE))
+ * 2.006 (King's Quest IV v1.0K 1988-11-22 (CE))
+ * 3.001 (Black Cauldron v1.0O 1989-02-24 (CE))
+ * 3.003 (Gold Rush! v1.0M 1989-02-28 (CE))
+ */
+uint8 appleIIgsAgiPaletteV2[16 * 3] = {
+ 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0xF,
+ 0x0, 0x8, 0x0,
+ 0x0, 0xD, 0xB,
+ 0xC, 0x0, 0x0,
+ 0xB, 0x7, 0xD,
+ 0x8, 0x5, 0x0,
+ 0xB, 0xB, 0xB,
+ 0x7, 0x7, 0x7,
+ 0x0, 0xB, 0xF,
+ 0x0, 0xE, 0x0,
+ 0x0, 0xF, 0xD,
+ 0xF, 0x9, 0x8,
+ 0xD, 0x9, 0xF, // Only this differs from the 1st generation palette
+ 0xE, 0xE, 0x0,
+ 0xF, 0xF, 0xF
+};
+
+/**
+ * First generation Amiga & Apple IIGS AGI palette.
+ * A 16-color, 12-bit RGB palette.
+ *
+ * Used by at least the following Amiga AGI versions:
+ * 2.082 (King's Quest I v1.0U 1986)
+ * 2.082 (Space Quest I v1.2 1986)
+ * 2.090 (King's Quest III v1.01 1986-11-08)
+ * 2.107 (King's Quest II v2.0J 1987-01-29)
+ * x.yyy (Black Cauldron v2.00 1987-06-14)
+ * x.yyy (Larry I v1.05 1987-06-26)
+ *
+ * Also used by at least the following Apple IIGS AGI versions:
+ * 1.002 (Space Quest I, intro says v2.2 1987)
+ */
+uint8 amigaAgiPaletteV1[16 * 3] = {
+ 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0xF,
+ 0x0, 0x8, 0x0,
+ 0x0, 0xD, 0xB,
+ 0xC, 0x0, 0x0,
+ 0xB, 0x7, 0xD,
+ 0x8, 0x5, 0x0,
+ 0xB, 0xB, 0xB,
+ 0x7, 0x7, 0x7,
+ 0x0, 0xB, 0xF,
+ 0x0, 0xE, 0x0,
+ 0x0, 0xF, 0xD,
+ 0xF, 0x9, 0x8,
+ 0xF, 0x7, 0x0,
+ 0xE, 0xE, 0x0,
+ 0xF, 0xF, 0xF
+};
+
+/**
+ * Second generation Amiga AGI palette.
+ * A 16-color, 12-bit RGB palette.
+ *
+ * Used by at least the following Amiga AGI versions:
+ * 2.202 (Space Quest II v2.0F. Intro says 1988. ScummVM 0.10.0 detects as 1986-12-09)
+ */
+uint8 amigaAgiPaletteV2[16 * 3] = {
+ 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0xF,
+ 0x0, 0x8, 0x0,
+ 0x0, 0xD, 0xB,
+ 0xC, 0x0, 0x0,
+ 0xB, 0x7, 0xD,
+ 0x8, 0x5, 0x0,
+ 0xB, 0xB, 0xB,
+ 0x7, 0x7, 0x7,
+ 0x0, 0xB, 0xF,
+ 0x0, 0xE, 0x0,
+ 0x0, 0xF, 0xD,
+ 0xF, 0x9, 0x8,
+ 0xD, 0x0, 0xF,
+ 0xE, 0xE, 0x0,
+ 0xF, 0xF, 0xF
+};
+
+/**
+ * Third generation Amiga AGI palette.
+ * A 16-color, 12-bit RGB palette.
+ *
+ * Used by at least the following Amiga AGI versions:
+ * 2.310 (Police Quest I v2.0B 1989-02-22)
+ * 2.316 (Gold Rush! v2.05 1989-03-09)
+ * x.yyy (Manhunter I v1.06 1989-03-18)
+ * 2.333 (Manhunter II v3.06 1989-08-17)
+ * 2.333 (King's Quest III v2.15 1989-11-15)
+ */
+uint8 amigaAgiPaletteV3[16 * 3] = {
+ 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0xB,
+ 0x0, 0xB, 0x0,
+ 0x0, 0xB, 0xB,
+ 0xB, 0x0, 0x0,
+ 0xB, 0x0, 0xB,
+ 0xC, 0x7, 0x0,
+ 0xB, 0xB, 0xB,
+ 0x7, 0x7, 0x7,
+ 0x0, 0x0, 0xF,
+ 0x0, 0xF, 0x0,
+ 0x0, 0xF, 0xF,
+ 0xF, 0x0, 0x0,
+ 0xF, 0x0, 0xF,
+ 0xF, 0xF, 0x0,
+ 0xF, 0xF, 0xF
+};
+
+/**
* 16 color amiga-ish palette.
*/
uint8 newPalette[16 * 3] = {
@@ -554,13 +706,42 @@ void GfxMgr::printCharacter(int x, int y, char c, int fg, int bg) {
}
/**
- * Draw button
+ * Draw a default style button.
+ * Swaps background and foreground color if button is in focus or being pressed.
* @param x x coordinate of the button
* @param y y coordinate of the button
* @param a set if the button has focus
* @param p set if the button is pressed
+ * @param fgcolor foreground color of the button when it is neither in focus nor being pressed
+ * @param bgcolor background color of the button when it is neither in focus nor being pressed
*/
-void GfxMgr::drawButton(int x, int y, const char *s, int a, int p, int fgcolor, int bgcolor) {
+void GfxMgr::drawDefaultStyleButton(int x, int y, const char *s, int a, int p, int fgcolor, int bgcolor) {
+ int textOffset = _vm->_defaultButtonStyle.getTextOffset(a > 0, p > 0);
+ AgiTextColor color = _vm->_defaultButtonStyle.getColor (a > 0, p > 0, fgcolor, bgcolor);
+ bool border = _vm->_defaultButtonStyle.getBorder (a > 0, p > 0);
+
+ rawDrawButton(x, y, s, color.fg, color.bg, border, textOffset);
+}
+
+/**
+ * Draw a button using the currently chosen style.
+ * Amiga-style is used for the Amiga-rendering mode, PC-style is used otherwise.
+ * @param x x coordinate of the button
+ * @param y y coordinate of the button
+ * @param hasFocus set if the button has focus
+ * @param pressed set if the button is pressed
+ * @param positive set if button is positive, otherwise button is negative (Only matters with Amiga-style buttons)
+ * TODO: Make Amiga-style buttons a bit wider as they were in Amiga AGI games.
+ */
+void GfxMgr::drawCurrentStyleButton(int x, int y, const char *label, bool hasFocus, bool pressed, bool positive) {
+ int textOffset = _vm->_buttonStyle.getTextOffset(hasFocus, pressed);
+ AgiTextColor color = _vm->_buttonStyle.getColor(hasFocus, pressed, positive);
+ bool border = _vm->_buttonStyle.getBorder(hasFocus, pressed);
+
+ rawDrawButton(x, y, label, color.fg, color.bg, border, textOffset);
+}
+
+void GfxMgr::rawDrawButton(int x, int y, const char *s, int fgcolor, int bgcolor, bool border, int textOffset) {
int len = strlen(s);
int x1, y1, x2, y2;
@@ -569,8 +750,12 @@ void GfxMgr::drawButton(int x, int y, const char *s, int a, int p, int fgcolor,
x2 = x + CHAR_COLS * len + 2;
y2 = y + CHAR_LINES + 2;
+ // Draw a filled rectangle that's larger than the button. Used for drawing
+ // a border around the button as the button itself is drawn after this.
+ drawRectangle(x1, y1, x2, y2, border ? BUTTON_BORDER : MSG_BOX_COLOUR);
+
while (*s) {
- putTextCharacter(0, x + (!!p), y + (!!p), *s++, a ? bgcolor : fgcolor, a ? fgcolor : bgcolor);
+ putTextCharacter(0, x + textOffset, y + textOffset, *s++, fgcolor, bgcolor);
x += CHAR_COLS;
}
@@ -623,39 +808,26 @@ int GfxMgr::keypress() {
/**
* Initialize the color palette
- * This function initializes the color palette using the specified 16-color
+ * This function initializes the color palette using the specified
* RGB palette.
- * @param p A pointer to the 16-color RGB palette.
+ * @param p A pointer to the source RGB palette.
+ * @param colorCount Count of colors in the source palette.
+ * @param fromBits Bits per source color component.
+ * @param toBits Bits per destination color component.
*/
-void GfxMgr::initPalette(uint8 *p) {
- int i;
-
- for (i = 0; i < 48; i++) {
- _palette[i] = p[i];
+void GfxMgr::initPalette(uint8 *p, uint colorCount, uint fromBits, uint toBits) {
+ const uint srcMax = (1 << fromBits) - 1;
+ const uint destMax = (1 << toBits) - 1;
+ for (uint col = 0; col < colorCount; col++) {
+ for (uint comp = 0; comp < 3; comp++) { // Convert RGB components
+ _palette[col * 4 + comp] = (p[col * 3 + comp] * destMax) / srcMax;
+ }
+ _palette[col * 4 + 3] = 0; // Set alpha to zero
}
}
void GfxMgr::gfxSetPalette() {
- int i;
- byte pal[256 * 4];
-
- if (!(_vm->getFeatures() & (GF_AGI256 | GF_AGI256_2))) {
- for (i = 0; i < 16; i++) {
- pal[i * 4 + 0] = _palette[i * 3 + 0] << 2;
- pal[i * 4 + 1] = _palette[i * 3 + 1] << 2;
- pal[i * 4 + 2] = _palette[i * 3 + 2] << 2;
- pal[i * 4 + 3] = 0;
- }
- g_system->setPalette(pal, 0, 16);
- } else {
- for (i = 0; i < 256; i++) {
- pal[i * 4 + 0] = vgaPalette[i * 3 + 0];
- pal[i * 4 + 1] = vgaPalette[i * 3 + 1];
- pal[i * 4 + 2] = vgaPalette[i * 3 + 2];
- pal[i * 4 + 3] = 0;
- }
- g_system->setPalette(pal, 0, 256);
- }
+ g_system->setPalette(_palette, 0, 256);
}
//Gets AGIPAL Data
@@ -739,7 +911,27 @@ static const byte sciMouseCursor[] = {
};
/**
- * RGBA-palette for the black and white SCI-style arrow cursor.
+ * A black and white Apple IIGS style arrow cursor (9x11).
+ * 0 = Transparent.
+ * 1 = Black (#000000 in 24-bit RGB).
+ * 2 = White (#FFFFFF in 24-bit RGB).
+ */
+static const byte appleIIgsMouseCursor[] = {
+ 2,2,0,0,0,0,0,0,0,
+ 2,1,2,0,0,0,0,0,0,
+ 2,1,1,2,0,0,0,0,0,
+ 2,1,1,1,2,0,0,0,0,
+ 2,1,1,1,1,2,0,0,0,
+ 2,1,1,1,1,1,2,0,0,
+ 2,1,1,1,1,1,1,2,0,
+ 2,1,1,1,1,1,1,1,2,
+ 2,1,1,2,1,1,2,2,0,
+ 2,2,2,0,2,1,1,2,0,
+ 0,0,0,0,0,2,2,2,0
+};
+
+/**
+ * RGBA-palette for the black and white SCI and Apple IIGS arrow cursors.
*/
static const byte sciMouseCursorPalette[] = {
0x00, 0x00, 0x00, 0x00, // Black
@@ -819,7 +1011,9 @@ void GfxMgr::setCursor(bool amigaStyleCursor) {
* @see deinit_video()
*/
int GfxMgr::initVideo() {
- if (_vm->_renderMode == Common::kRenderEGA)
+ if (_vm->getFeatures() & (GF_AGI256 | GF_AGI256_2))
+ initPalette(vgaPalette, 256, 8);
+ else if (_vm->_renderMode == Common::kRenderEGA)
initPalette(egaPalette);
else
initPalette(newPalette);
diff --git a/engines/agi/graphics.h b/engines/agi/graphics.h
index b1f9c0e1d7..e06af90f5d 100644
--- a/engines/agi/graphics.h
+++ b/engines/agi/graphics.h
@@ -41,7 +41,7 @@ class GfxMgr {
private:
AgiEngine *_vm;
- uint8 _palette[16 * 3];
+ uint8 _palette[256 * 4];
uint8 *_agiScreen;
unsigned char *_screen;
@@ -50,6 +50,9 @@ private:
uint8 _agipalPalette[16 * 3];
int _agipalFileNum;
+private:
+ void rawDrawButton(int x, int y, const char *s, int fgcolor, int bgcolor, bool border, int textOffset);
+
public:
GfxMgr(AgiEngine *vm);
@@ -74,12 +77,13 @@ public:
void clearScreen(int);
void clearConsoleScreen(int);
void drawBox(int, int, int, int, int, int, int);
- void drawButton(int, int, const char *, int, int, int fgcolor = 0, int bgcolor = 0);
+ void drawDefaultStyleButton(int, int, const char *, int, int, int fgcolor = 0, int bgcolor = 0);
+ void drawCurrentStyleButton(int x, int y, const char *label, bool hasFocus, bool pressed = false, bool positive = true);
int testButton(int, int, const char *);
void drawRectangle(int, int, int, int, int);
void saveBlock(int, int, int, int, uint8 *);
void restoreBlock(int, int, int, int, uint8 *);
- void initPalette(uint8 *);
+ void initPalette(uint8 *p, uint colorCount = 16, uint fromBits = 6, uint toBits = 8);
void setAGIPal(int);
int getAGIPalFileNum();
void drawFrame(int x1, int y1, int x2, int y2, int c1, int c2);
diff --git a/engines/agi/keyboard.cpp b/engines/agi/keyboard.cpp
index 3acc81ddff..2b7559f754 100644
--- a/engines/agi/keyboard.cpp
+++ b/engines/agi/keyboard.cpp
@@ -107,8 +107,10 @@ int AgiEngine::handleController(int key) {
VtEntry *v = &_game.viewTable[0];
int i;
- /* AGI 3.149 games and The Black Cauldron need KEY_ESCAPE to use menus */
- if (key == 0 || (key == KEY_ESCAPE && agiGetRelease() != 0x3149 && getGameID() != GID_BC) )
+ // AGI 3.149 games and The Black Cauldron need KEY_ESCAPE to use menus
+ // Games with the GF_ESCPAUSE flag need KEY_ESCAPE to pause the game
+ if (key == 0 ||
+ (key == KEY_ESCAPE && agiGetRelease() != 0x3149 && getGameID() != GID_BC && !(getFeatures() & GF_ESCPAUSE)) )
return false;
if ((getGameID() == GID_MH1 || getGameID() == GID_MH2) && (key == KEY_ENTER) &&
@@ -127,7 +129,7 @@ int AgiEngine::handleController(int key) {
}
if (key == BUTTON_LEFT) {
- if (getflag(fMenusWork) && g_mouse.y <= CHAR_LINES) {
+ if ((getflag(fMenusWork) || (getFeatures() & GF_MENUS)) && g_mouse.y <= CHAR_LINES) {
newInputMode(INPUT_MENU);
return true;
}
diff --git a/engines/agi/menu.cpp b/engines/agi/menu.cpp
index 5edaaf0ded..7aa7f5e55d 100644
--- a/engines/agi/menu.cpp
+++ b/engines/agi/menu.cpp
@@ -267,7 +267,7 @@ bool Menu::keyhandler(int key) {
static int menuActive = false;
static int buttonUsed = 0;
- if (!_vm->getflag(fMenusWork))
+ if (!_vm->getflag(fMenusWork) && !(_vm->getFeatures() & GF_MENUS))
return false;
if (!menuActive) {
@@ -351,6 +351,12 @@ bool Menu::keyhandler(int key) {
debugC(6, kDebugLevelMenu | kDebugLevelInput, "event %d registered", d->event);
_vm->_game.evKeyp[d->event].occured = true;
_vm->_game.evKeyp[d->event].data = d->event;
+ // In LSL1, event 0x20 is set when changing the game speed to normal via the menu
+ // Do not set the event data to 0x20, as this event is then incorrectly triggered
+ // when the spacebar is pressed, which has a keycode equal to 0x20 as well
+ // Fixes bug #1751390 - "LSL: after changing game speed, space key turn unfunctional"
+ if (d->event == 0x20)
+ _vm->_game.evKeyp[d->event].data = d->event + 1;
goto exit_menu;
}
}
diff --git a/engines/agi/predictive.cpp b/engines/agi/predictive.cpp
index 67ebed5f05..eef4360cbf 100644
--- a/engines/agi/predictive.cpp
+++ b/engines/agi/predictive.cpp
@@ -30,6 +30,10 @@
#include "common/func.h"
#include "common/config-manager.h"
+#ifdef __DS__
+#include "wordcompletion.h"
+#endif
+
namespace Agi {
#define kModePre 0
@@ -200,9 +204,9 @@ bool AgiEngine::predictiveDialog(void) {
color2 = 7;
}
if (i == 14) {
- _gfx->drawButton(bx[i], by[i], modes[mode], i == active, 0, color1, color2);
+ _gfx->drawDefaultStyleButton(bx[i], by[i], modes[mode], i == active, 0, color1, color2);
} else {
- _gfx->drawButton(bx[i], by[i], buttons[i], i == active, 0, color1, color2);
+ _gfx->drawDefaultStyleButton(bx[i], by[i], buttons[i], i == active, 0, color1, color2);
}
}
@@ -521,6 +525,10 @@ void AgiEngine::loadDict(void) {
while ((ptr = strchr(ptr, '\n'))) {
*ptr = 0;
ptr++;
+#ifdef __DS__
+ // Pass the line on to the DS word list
+ DS::addAutoCompleteLine(_predictiveDictLine[i - 1]);
+#endif
_predictiveDictLine[i++] = ptr;
}
if (_predictiveDictLine[lines - 1][0] == 0)
@@ -529,6 +537,11 @@ void AgiEngine::loadDict(void) {
_predictiveDictLineCount = lines;
debug("Loaded %d lines", _predictiveDictLineCount);
+#ifdef __DS__
+ // Sort the DS word completion list, to allow for a binary chop later (in the ds backend)
+ DS::sortAutoCompleteWordList();
+#endif
+
uint32 time3 = _system->getMillis();
printf("Time to parse pred.dic: %d, total: %d\n", time3-time2, time3-time1);
}
diff --git a/engines/agi/saveload.cpp b/engines/agi/saveload.cpp
index 9144dae96c..05ce80b1a3 100644
--- a/engines/agi/saveload.cpp
+++ b/engines/agi/saveload.cpp
@@ -55,6 +55,7 @@ int AgiEngine::saveGame(const char *fileName, const char *description) {
int i;
struct ImageStackElement *ptr = _imageStack;
Common::OutSaveFile *out;
+ int result = errOK;
debugC(3, kDebugLevelMain | kDebugLevelSavegame, "AgiEngine::saveGame(%s, %s)", fileName, description);
if (!(out = _saveFileMan->openForSaving(fileName))) {
@@ -206,14 +207,15 @@ int AgiEngine::saveGame(const char *fileName, const char *description) {
out->writeSint16BE(_gfx->getAGIPalFileNum());
out->finalize();
- if (out->ioFailed())
+ if (out->ioFailed()) {
warning("Can't write file '%s'. (Disk full?)", fileName);
- else
+ result = errIOError;
+ } else
debugC(1, kDebugLevelMain | kDebugLevelSavegame, "Saved game %s in file %s", description, fileName);
delete out;
debugC(3, kDebugLevelMain | kDebugLevelSavegame, "Closed %s", fileName);
- return errOK;
+ return result;
}
int AgiEngine::loadGame(const char *fileName, bool checkId) {
@@ -516,7 +518,7 @@ int AgiEngine::selectSlot() {
buttonY = (vm + 17) * CHAR_LINES;
for (i = 0; i < 2; i++)
- _gfx->drawButton(buttonX[i], buttonY, buttonText[i], 0, 0, MSG_BOX_TEXT, MSG_BOX_COLOUR);
+ _gfx->drawCurrentStyleButton(buttonX[i], buttonY, buttonText[i], false, false, i == 0);
AllowSyntheticEvents on(this);
int oldFirstSlot = _firstSlot + 1;
@@ -751,20 +753,24 @@ int AgiEngine::saveGameDialog() {
sprintf(fileName, "%s", getSavegameFilename(slot));
debugC(8, kDebugLevelMain | kDebugLevelResources, "file is [%s]", fileName);
- saveGame(fileName, desc);
+ int result = saveGame(fileName, desc);
- messageBox("Game saved.");
+ if (result == errOK)
+ messageBox("Game saved.");
+ else
+ messageBox("Error saving game.");
- return errOK;
+ return result;
}
int AgiEngine::saveGameSimple() {
char fileName[MAX_PATH];
sprintf(fileName, "%s", getSavegameFilename(0));
- saveGame(fileName, "Default savegame");
-
- return errOK;
+ int result = saveGame(fileName, "Default savegame");
+ if (result != errOK)
+ messageBox("Error saving game.");
+ return result;
}
int AgiEngine::loadGameDialog() {
diff --git a/engines/agi/sound.cpp b/engines/agi/sound.cpp
index 954cca8f8f..b083b77440 100644
--- a/engines/agi/sound.cpp
+++ b/engines/agi/sound.cpp
@@ -40,26 +40,43 @@ namespace Agi {
#ifdef USE_IIGS_SOUND
-/**
- * AGI engine sound envelope structure.
- */
-struct SoundEnvelope {
+struct IIgsEnvelopeSegment {
uint8 bp;
- uint8 incHi;
- uint8 inc_lo;
+ uint16 inc; ///< 8b.8b fixed point, big endian?
};
-struct SoundWavelist {
+#define ENVELOPE_SEGMENT_COUNT 8
+struct IIgsEnvelope {
+ IIgsEnvelopeSegment seg[ENVELOPE_SEGMENT_COUNT];
+};
+
+// 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;
- uint8 relHi;
- uint8 relLo;
+ uint16 relPitch; ///< 8b.8b fixed point, big endian?
};
-struct SoundInstrument {
- struct SoundEnvelope env[8];
+#define MAX_WAVE_COUNT 8
+struct IIgsInstrumentHeader {
+ IIgsEnvelope env;
uint8 relseg;
uint8 priority;
uint8 bendrange;
@@ -68,19 +85,19 @@ struct SoundInstrument {
uint8 spare;
uint8 wac;
uint8 wbc;
- struct SoundWavelist wal[8];
- struct SoundWavelist wbl[8];
+ IIgsWaveInfo wal[MAX_WAVE_COUNT];
+ IIgsWaveInfo wbl[MAX_WAVE_COUNT];
};
-struct SoundIIgsSample {
- uint8 typeLo;
- uint8 typeHi;
- uint8 srateLo;
- uint8 srateHi;
- uint16 unknown[2];
- uint8 sizeLo;
- uint8 sizeHi;
- uint16 unknown2[13];
+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;
};
#if 0
@@ -89,6 +106,117 @@ static int numInstruments;
static uint8 *wave;
#endif
+bool readIIgsEnvelope(IIgsEnvelope &envelope, Common::SeekableReadStream &stream) {
+ for (int segNum = 0; segNum < ENVELOPE_SEGMENT_COUNT; segNum++) {
+ envelope.seg[segNum].bp = stream.readByte();
+ envelope.seg[segNum].inc = stream.readUint16BE();
+ }
+ 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();
+ 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();
+}
+
+/**
+ * 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);
+}
+
+/**
+ * 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);
+
+ // 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);
+ }
+ }
+
+ // 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();
+ }
+
+ return result;
+}
+
#endif
static int playing;
@@ -169,7 +297,7 @@ void SoundMgr::unloadSound(int resnum) {
}
void SoundMgr::decodeSound(int resnum) {
-#ifdef USE_IIGS_SOUND
+#if 0
int type, size;
int16 *buf;
uint8 *src;
@@ -190,12 +318,12 @@ void SoundMgr::decodeSound(int resnum) {
_vm->_game.sounds[resnum].rdata = (uint8 *) buf;
free(src);
}
-#endif /* USE_IIGS_SOUND */
+#endif
}
void SoundMgr::startSound(int resnum, int flag) {
int i, type;
-#ifdef USE_IIGS_SOUND
+#if 0
struct SoundIIgsSample *smp;
#endif
@@ -218,7 +346,7 @@ void SoundMgr::startSound(int resnum, int flag) {
song = (uint8 *)_vm->_game.sounds[resnum].rdata;
switch (type) {
-#ifdef USE_IIGS_SOUND
+#if 0
case AGI_SOUND_SAMPLE:
debugC(3, kDebugLevelSound, "IIGS sample");
smp = (struct SoundIIgsSample *)_vm->_game.sounds[resnum].rdata;
diff --git a/engines/agi/text.cpp b/engines/agi/text.cpp
index 565e94fa26..1d653a9415 100644
--- a/engines/agi/text.cpp
+++ b/engines/agi/text.cpp
@@ -364,7 +364,7 @@ int AgiEngine::selectionBox(const char *m, const char **b) {
debugC(4, kDebugLevelText, "waiting...");
for (;;) {
for (i = 0; b[i]; i++)
- _gfx->drawButton(bx[i], by[i], b[i], i == active, 0, MSG_BOX_TEXT, MSG_BOX_COLOUR);
+ _gfx->drawCurrentStyleButton(bx[i], by[i], b[i], i == active, false, i == 0);
_gfx->pollTimer(); /* msdos driver -> does nothing */
key = doPollKeyboard();
@@ -555,7 +555,7 @@ char *AgiEngine::agiSprintf(const char *s) {
break;
case 's':
i = strtoul(s, NULL, 10);
- safeStrcat(p, _game.strings[i]);
+ safeStrcat(p, agiSprintf(_game.strings[i]));
break;
case 'm':
i = strtoul(s, NULL, 10) - 1;
diff --git a/engines/agos/agos.cpp b/engines/agos/agos.cpp
index ae7f692c3f..76e4378982 100644
--- a/engines/agos/agos.cpp
+++ b/engines/agos/agos.cpp
@@ -148,10 +148,6 @@ AGOSEngine::AGOSEngine(OSystem *syst)
_itemArraySize = 0;
_itemArrayInited = 0;
- _itemHeapPtr = 0;
- _itemHeapCurPos = 0;
- _itemHeapSize = 0;
-
_iconFilePtr = 0;
_codePtr = 0;
@@ -824,7 +820,7 @@ void AGOSEngine_Waxworks::setupGame() {
_numTextBoxes = 10;
_numVars = 255;
- _numMusic = 9;
+ _numMusic = 26;
AGOSEngine::setupGame();
}
@@ -920,7 +916,11 @@ AGOSEngine::~AGOSEngine() {
_midi.close();
- free(_itemHeapPtr - _itemHeapCurPos);
+ for (uint i = 0; i < _itemHeap.size(); i++) {
+ delete [] _itemHeap[i];
+ }
+ _itemHeap.clear();
+
free(_tablesHeapPtr - _tablesHeapCurPos);
free(_gameOffsetsPtr);
@@ -1054,7 +1054,11 @@ void AGOSEngine::shutdown() {
_midi.close();
- free(_itemHeapPtr - _itemHeapCurPos);
+ for (uint i = 0; i < _itemHeap.size(); i++) {
+ delete [] _itemHeap[i];
+ }
+ _itemHeap.clear();
+
free(_tablesHeapPtr - _tablesHeapCurPos);
free(_gameOffsetsPtr);
diff --git a/engines/agos/agos.h b/engines/agos/agos.h
index d233d0bfeb..bf64a3bf84 100644
--- a/engines/agos/agos.h
+++ b/engines/agos/agos.h
@@ -28,6 +28,7 @@
#include "engines/engine.h"
+#include "common/array.h"
#include "common/keyboard.h"
#include "common/rect.h"
#include "common/util.h"
@@ -231,9 +232,7 @@ protected:
uint _itemArraySize;
uint _itemArrayInited;
- byte *_itemHeapPtr;
- uint _itemHeapCurPos;
- uint _itemHeapSize;
+ Common::Array<byte *> _itemHeap;
byte *_iconFilePtr;
diff --git a/engines/agos/detection_tables.h b/engines/agos/detection_tables.h
index 5efcaa3b86..988de6729b 100644
--- a/engines/agos/detection_tables.h
+++ b/engines/agos/detection_tables.h
@@ -542,6 +542,32 @@ static const AGOSGameDescription gameDescriptions[] = {
GF_OLD_BUNDLE | GF_CRUNCHED | GF_CRUNCHED_GAMEPC | GF_PLANAR
},
+ // Waxworks - German Amiga Floppy
+ {
+ {
+ "waxworks",
+ "Floppy",
+
+ {
+ { "gameamiga", GAME_BASEFILE, "2938a17103de603c4c6f05e6a433b365", -1},
+ { "icon.pkd", GAME_ICONFILE, "4822a91c18b1b2005ac17fc617f7dcbe", -1},
+ { "menus.dat", GAME_MENUFILE, "3409eeb8ca8b46fc04da99de67573f5e", -1},
+ { "start", GAME_RESTFILE, "b575b336e741dde1725edd4079d5ab67", -1},
+ { "stripped.txt", GAME_STRFILE, "6faaebff2786216900061eeb978f10af", -1},
+ { "tbllist", GAME_TBLFILE, "95c44bfc380770a6b6dd0dfcc69e80a0", -1},
+ { "xtbllist", GAME_XTBLFILE, "6c7b3db345d46349a5226f695c03e20f", -1},
+ { NULL, 0, NULL, 0}
+ },
+ Common::DE_DEU,
+ Common::kPlatformAmiga,
+ Common::ADGF_NO_FLAGS
+ },
+
+ GType_WW,
+ GID_WAXWORKS,
+ GF_OLD_BUNDLE | GF_CRUNCHED | GF_CRUNCHED_GAMEPC | GF_PLANAR
+ },
+
// Waxworks - English DOS Floppy Demo
{
{
diff --git a/engines/agos/input.cpp b/engines/agos/input.cpp
index 0f1c234b79..a86cad9b94 100644
--- a/engines/agos/input.cpp
+++ b/engines/agos/input.cpp
@@ -196,7 +196,7 @@ void AGOSEngine::waitForInput() {
for (;;) {
if ((getGameType() == GType_SIMON1 || getGameType() == GType_SIMON2) &&
- _keyPressed.keycode == Common::KEYCODE_HASH)
+ _keyPressed.keycode == Common::KEYCODE_F10)
displayBoxStars();
if (processSpecialKeys()) {
if ((getGameType() == GType_PP && getGameId() != GID_DIMP) ||
diff --git a/engines/agos/items.cpp b/engines/agos/items.cpp
index 9a46b6e8ac..b2e722d681 100644
--- a/engines/agos/items.cpp
+++ b/engines/agos/items.cpp
@@ -42,24 +42,15 @@ Child *AGOSEngine::allocateChildBlock(Item *i, uint type, uint size) {
}
byte *AGOSEngine::allocateItem(uint size) {
- byte *org = _itemHeapPtr;
- size = (size + sizeof(void*) - 1) & ~(sizeof(void*) - 1);
+ byte *item = new byte[size];
- _itemHeapPtr += size;
- _itemHeapCurPos += size;
-
- if (_itemHeapCurPos > _itemHeapSize)
- error("allocateItem: Itemheap overflow");
-
- return org;
+ memset(item, 0, size);
+ _itemHeap.push_back(item);
+ return item;
}
void AGOSEngine::allocItemHeap() {
- _itemHeapSize = _itemMemSize;
- _itemHeapCurPos = 0;
- _itemHeapPtr = (byte *)calloc(_itemMemSize, 1);
- if (!_itemHeapPtr)
- error("Out Of Memory - Items");
+ _itemHeap.clear();
}
bool AGOSEngine::hasIcon(Item *item) {
@@ -391,8 +382,13 @@ int AGOSEngine::wordMatch(Item *item, int16 a, int16 n) {
}
Item *AGOSEngine::derefItem(uint item) {
- if (item >= _itemArraySize)
- error("derefItem: invalid item %d", item);
+ // Occurs when loading item store from restart state in
+ // Elvira 2 (Amiga/AtariST) and Waxworks (Amiga).
+ if (item >= _itemArraySize) {
+ debug(0, "derefItem: invalid item %d", item);
+ return NULL;
+ }
+
return _itemArrayPtr[item];
}
diff --git a/engines/agos/res_snd.cpp b/engines/agos/res_snd.cpp
index 779ed67e58..beea0de473 100644
--- a/engines/agos/res_snd.cpp
+++ b/engines/agos/res_snd.cpp
@@ -139,9 +139,56 @@ void AGOSEngine::loadMusic(uint16 music) {
_nextMusicToPlay = -1;
}
+struct ModuleOffs {
+ uint8 tune;
+ uint8 fileNum;
+ uint32 offs;
+};
+
+static const ModuleOffs amigaWaxworksOffs[20] = {
+ // Pyramid
+ {2, 2, 0, },
+ {3, 2, 50980},
+ {4, 2, 56160},
+ {5, 2, 62364},
+ {6, 2, 73688},
+
+ // Zombie
+ {8, 8, 0},
+ {11, 8, 51156},
+ {12, 8, 56336},
+ {13, 8, 65612},
+ {14, 8, 68744},
+
+ // Mine
+ {9, 9, 0},
+ {15, 9, 47244},
+ {16, 9, 52424},
+ {17, 9, 59652},
+ {18, 9, 62784},
+
+ // Jack
+ {10, 10, 0},
+ {19, 10, 42054},
+ {20, 10, 47234},
+ {21, 10, 49342},
+ {22, 10, 51450},
+};
+
void AGOSEngine::playModule(uint16 music) {
char filename[15];
File f;
+ uint32 offs = 0;
+
+ if (getPlatform() == Common::kPlatformAmiga && getGameType() == GType_WW) {
+ // Multiple tunes are stored in music files for main locations
+ for (uint i = 0; i < 20; i++) {
+ if (amigaWaxworksOffs[i].tune == music) {
+ music = amigaWaxworksOffs[i].fileNum;
+ offs = amigaWaxworksOffs[i].offs;
+ }
+ }
+ }
if (getGameType() == GType_ELVIRA1 && getFeatures() & GF_DEMO)
sprintf(filename, "elvira2");
@@ -159,21 +206,21 @@ void AGOSEngine::playModule(uint16 music) {
if (!(getGameType() == GType_ELVIRA1 && getFeatures() & GF_DEMO) &&
getFeatures() & GF_CRUNCHED) {
- uint srcSize = f.size();
+ uint32 srcSize = f.size();
byte *srcBuf = (byte *)malloc(srcSize);
if (f.read(srcBuf, srcSize) != srcSize)
error("playModule: Read failed");
- uint dstSize = READ_BE_UINT32(srcBuf + srcSize - 4);
+ uint32 dstSize = READ_BE_UINT32(srcBuf + srcSize - 4);
byte *dstBuf = (byte *)malloc(dstSize);
decrunchFile(srcBuf, dstBuf, srcSize);
free(srcBuf);
Common::MemoryReadStream stream(dstBuf, dstSize);
- audioStream = Audio::makeProtrackerStream(&stream, _mixer->getOutputRate());
+ audioStream = Audio::makeProtrackerStream(&stream, offs);
free(dstBuf);
} else {
- audioStream = Audio::makeProtrackerStream(&f, _mixer->getOutputRate());
+ audioStream = Audio::makeProtrackerStream(&f);
}
_mixer->playInputStream(Audio::Mixer::kMusicSoundType, &_modHandle, audioStream);
diff --git a/engines/agos/saveload.cpp b/engines/agos/saveload.cpp
index 61c640d7c5..f7c2d4846f 100644
--- a/engines/agos/saveload.cpp
+++ b/engines/agos/saveload.cpp
@@ -1190,7 +1190,7 @@ bool AGOSEngine_Elvira2::loadGame(const char *filename, bool restartMode) {
addTimeEvent(timeout, subroutine_id);
}
- if (getGameType() == GType_WW) {
+ if (getGameType() == GType_WW && getPlatform() == Common::kPlatformPC) {
// TODO Load room state data
for (uint s = 0; s <= _numRoomStates; s++) {
f->readUint16BE();
@@ -1202,7 +1202,8 @@ bool AGOSEngine_Elvira2::loadGame(const char *filename, bool restartMode) {
for (num = _itemArrayInited - 1; num; num--) {
Item *item = _itemArrayPtr[item_index++], *parent_item;
- if (getGameType() == GType_ELVIRA2) {
+ if ((getGameType() == GType_WW && getPlatform() == Common::kPlatformAmiga) ||
+ getGameType() == GType_ELVIRA2) {
parent_item = derefItem(readItemID(f));
setItemParent(item, parent_item);
} else {
@@ -1342,7 +1343,7 @@ bool AGOSEngine_Elvira2::saveGame(uint slot, const char *caption) {
f->writeUint16BE(te->subroutine_id);
}
- if (getGameType() == GType_WW) {
+ if (getGameType() == GType_WW && getPlatform() == Common::kPlatformPC) {
// TODO Save room state data
for (uint s = 0; s <= _numRoomStates; s++) {
f->writeUint16BE(0);
@@ -1354,7 +1355,8 @@ bool AGOSEngine_Elvira2::saveGame(uint slot, const char *caption) {
for (num_item = _itemArrayInited - 1; num_item; num_item--) {
Item *item = _itemArrayPtr[item_index++];
- if (getGameType() == GType_ELVIRA2) {
+ if ((getGameType() == GType_WW && getPlatform() == Common::kPlatformAmiga) ||
+ getGameType() == GType_ELVIRA2) {
writeItemID(f, item->parent);
} else {
f->writeUint16BE(item->parent);
diff --git a/engines/agos/sound.cpp b/engines/agos/sound.cpp
index 7165e3cbff..a735f54c29 100644
--- a/engines/agos/sound.cpp
+++ b/engines/agos/sound.cpp
@@ -292,7 +292,9 @@ Audio::AudioStream *MP3Sound::makeAudioStream(uint sound) {
uint32 size = _offsets[sound + i] - _offsets[sound];
- return Audio::makeMP3Stream(_file, size);
+ Common::MemoryReadStream *tmp = _file->readStream(size);
+ assert(tmp);
+ return Audio::makeMP3Stream(tmp, true);
}
void MP3Sound::playSound(uint sound, uint loopSound, Audio::Mixer::SoundType type, Audio::SoundHandle *handle, byte flags, int vol) {
@@ -321,7 +323,9 @@ Audio::AudioStream *VorbisSound::makeAudioStream(uint sound) {
uint32 size = _offsets[sound + i] - _offsets[sound];
- return Audio::makeVorbisStream(_file, size);
+ Common::MemoryReadStream *tmp = _file->readStream(size);
+ assert(tmp);
+ return Audio::makeVorbisStream(tmp, true);
}
void VorbisSound::playSound(uint sound, uint loopSound, Audio::Mixer::SoundType type, Audio::SoundHandle *handle, byte flags, int vol) {
@@ -350,7 +354,9 @@ Audio::AudioStream *FlacSound::makeAudioStream(uint sound) {
uint32 size = _offsets[sound + i] - _offsets[sound];
- return Audio::makeFlacStream(_file, size);
+ Common::MemoryReadStream *tmp = _file->readStream(size);
+ assert(tmp);
+ return Audio::makeFlacStream(tmp, true);
}
void FlacSound::playSound(uint sound, uint loopSound, Audio::Mixer::SoundType type, Audio::SoundHandle *handle, byte flags, int vol) {
diff --git a/engines/agos/zones.cpp b/engines/agos/zones.cpp
index a1de03e66c..d40e1da1de 100644
--- a/engines/agos/zones.cpp
+++ b/engines/agos/zones.cpp
@@ -44,6 +44,25 @@ void AGOSEngine::unfreezeBottom() {
_vgaFrozenBase = _vgaRealBase;
}
+static const uint8 zoneTable[160] = {
+ 0, 0, 2, 2, 2, 2, 0, 2, 2, 2,
+ 3, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+ 3, 3, 3, 1, 3, 0, 0, 0, 1, 0,
+ 2, 0, 3, 0, 3, 3, 0, 1, 1, 0,
+ 1, 2, 2, 2, 0, 2, 2, 2, 0, 2,
+ 1, 2, 2, 2, 0, 2, 2, 2, 2, 2,
+ 2, 2, 2, 1, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 0, 2, 0, 3, 2, 2, 2, 3,
+ 2, 3, 3, 3, 1, 3, 3, 1, 1, 0,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 0, 0, 2, 2, 0,
+ 0, 2, 0, 2, 2, 2, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 2, 2, 2, 2, 2,
+ 2, 0, 2, 0, 0, 2, 2, 0, 2, 2,
+ 2, 2, 2, 2, 2, 0, 0, 0, 0, 0,
+};
+
void AGOSEngine::loadZone(uint16 zoneNum) {
VgaPointersEntry *vpe;
@@ -56,7 +75,13 @@ void AGOSEngine::loadZone(uint16 zoneNum) {
// Loading order is important
// due to resource managment
- loadVGAVideoFile(zoneNum, 2);
+ if (getPlatform() == Common::kPlatformAmiga && getGameType() == GType_WW &&
+ zoneTable[zoneNum] == 3) {
+ uint8 num = (zoneNum >= 85) ? 94 : 18;
+ loadVGAVideoFile(num, 2);
+ } else {
+ loadVGAVideoFile(zoneNum, 2);
+ }
vpe->vgaFile2 = _block;
vpe->vgaFile2End = _blockEnd;
diff --git a/engines/drascula/detection.cpp b/engines/drascula/detection.cpp
new file mode 100644
index 0000000000..d875a52d71
--- /dev/null
+++ b/engines/drascula/detection.cpp
@@ -0,0 +1,183 @@
+/* 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 "base/plugins.h"
+
+#include "common/advancedDetector.h"
+#include "common/file.h"
+
+#include "drascula/drascula.h"
+
+
+namespace Drascula {
+
+struct DrasculaGameDescription {
+ Common::ADGameDescription desc;
+
+ int gameID;
+ int gameType;
+ uint32 features;
+ uint16 version;
+};
+
+uint32 DrasculaEngine::getGameID() const {
+ return _gameDescription->gameID;
+}
+
+uint32 DrasculaEngine::getFeatures() const {
+ return _gameDescription->features;
+}
+
+Common::Platform DrasculaEngine::getPlatform() const {
+ return _gameDescription->desc.platform;
+}
+
+uint16 DrasculaEngine::getVersion() const {
+ return _gameDescription->version;
+}
+
+}
+
+static const PlainGameDescriptor drasculaGames[] = {
+ {"drascula", "Drascula game"},
+
+ {0, 0}
+};
+
+
+namespace Drascula {
+
+static const DrasculaGameDescription gameDescriptions[] = {
+
+ {
+ // Drascula English version
+ {
+ "drascula",
+ "English",
+ AD_ENTRY1("14.ald", "09b2735953edcd43af115c65ae00b10e"),
+ Common::EN_ANY,
+ Common::kPlatformPC,
+ Common::ADGF_NO_FLAGS
+ },
+ 0,
+ 0,
+ 0,
+ 0,
+ },
+
+ {
+ // Drascula Spanish version
+ {
+ "drascula",
+ "Spanish",
+ AD_ENTRY1("14.ald", "0746ed1a5cc8d9728f790c29813f4b43"),
+ Common::ES_ESP,
+ Common::kPlatformPC,
+ Common::ADGF_NO_FLAGS
+ },
+ 0,
+ 0,
+ 0,
+ 0,
+ },
+
+ { AD_TABLE_END_MARKER, 0, 0, 0, 0 }
+};
+
+/**
+ * The fallback game descriptor used by the Drascula engine's fallbackDetector.
+ * Contents of this struct are to be overwritten by the fallbackDetector.
+ */
+static DrasculaGameDescription g_fallbackDesc = {
+ {
+ "", // Not used by the fallback descriptor, it uses the EncapsulatedADGameDesc's gameid
+ "", // Not used by the fallback descriptor, it uses the EncapsulatedADGameDesc's extra
+ AD_ENTRY1(0, 0), // This should always be AD_ENTRY1(0, 0) in the fallback descriptor
+ Common::UNK_LANG,
+ Common::kPlatformPC,
+ Common::ADGF_NO_FLAGS
+ },
+ 0,
+ 0,
+ 0,
+ 0,
+};
+
+Common::EncapsulatedADGameDesc fallbackDetector(const FSList *fslist) {
+ // Set the default values for the fallback descriptor's ADGameDescription part.
+ g_fallbackDesc.desc.language = Common::UNK_LANG;
+ g_fallbackDesc.desc.platform = Common::kPlatformPC;
+ g_fallbackDesc.desc.flags = Common::ADGF_NO_FLAGS;
+
+ // Set default values for the fallback descriptor's DrasculaGameDescription part.
+ g_fallbackDesc.gameID = 0;
+ g_fallbackDesc.features = 0;
+ g_fallbackDesc.version = 0;
+
+ Common::EncapsulatedADGameDesc result;
+
+ return result;
+}
+
+} // End of namespace Drascula
+
+static const Common::ADParams detectionParams = {
+ // Pointer to ADGameDescription or its superset structure
+ (const byte *)Drascula::gameDescriptions,
+ // Size of that superset structure
+ sizeof(Drascula::DrasculaGameDescription),
+ // Number of bytes to compute MD5 sum for
+ 5000,
+ // List of all engine targets
+ drasculaGames,
+ // Structure for autoupgrading obsolete targets
+ 0,
+ // Name of single gameid (optional)
+ "drascula",
+ // List of files for file-based fallback detection (optional)
+ 0,
+ // Fallback callback
+ Drascula::fallbackDetector,
+ // Flags
+ Common::kADFlagAugmentPreferredTarget
+};
+
+ADVANCED_DETECTOR_DEFINE_PLUGIN(DRASCULA, Drascula::DrasculaEngine, detectionParams);
+
+REGISTER_PLUGIN(DRASCULA, "Drascula Engine", "Drascula Engine (C) 2000 Alcachofa Soft, 1996 (C) Digital Dreams Multimedia, 1994 (C) Emilio de Paz");
+
+namespace Drascula {
+
+bool DrasculaEngine::initGame() {
+ Common::EncapsulatedADGameDesc encapsulatedDesc = Common::AdvancedDetector::detectBestMatchingGame(detectionParams);
+ _gameDescription = (const DrasculaGameDescription *)(encapsulatedDesc.realDesc);
+
+ return (_gameDescription != 0);
+}
+
+} // End of namespace Drascula
+
diff --git a/engines/drascula/drascula.cpp b/engines/drascula/drascula.cpp
new file mode 100644
index 0000000000..df433e12f0
--- /dev/null
+++ b/engines/drascula/drascula.cpp
@@ -0,0 +1,6859 @@
+/* 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/keyboard.h"
+#include "common/file.h"
+#include "common/savefile.h"
+#include "common/config-manager.h"
+
+#include "base/plugins.h"
+#include "base/version.h"
+
+#include "sound/mixer.h"
+
+#include "drascula/drascula.h"
+#include "drascula/texts.h"
+
+namespace Drascula {
+
+struct GameSettings {
+ const char *gameid;
+ const char *description;
+ byte id;
+ uint32 features;
+ const char *detectname;
+};
+
+static const GameSettings drasculaSettings[] = {
+ {"drascula", "Drascula game", 0, 0, 0},
+
+ {NULL, NULL, 0, 0, NULL}
+};
+
+DrasculaEngine::DrasculaEngine(OSystem *syst) : Engine(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 = drasculaSettings; g->gameid; ++g)
+ if (!scumm_stricmp(g->gameid, gameid))
+ _gameId = g->id;
+
+ _rnd = new Common::RandomSource();
+
+ int cd_num = ConfMan.getInt("cdrom");
+ if (cd_num >= 0)
+ _system->openCD(cd_num);
+}
+
+DrasculaEngine::~DrasculaEngine() {
+ salir_al_dos(0);
+
+ delete _rnd;
+}
+
+static int x_obj[44] = {0, X_OBJ1, X_OBJ2, X_OBJ3, X_OBJ4, X_OBJ5, X_OBJ6, X_OBJ7, X_OBJ8, X_OBJ9, X_OBJ10,
+ X_OBJ11, X_OBJ12, X_OBJ13, X_OBJ14, X_OBJ15, X_OBJ16, X_OBJ17, X_OBJ18, X_OBJ19, X_OBJ20,
+ X_OBJ21, X_OBJ22, X_OBJ23, X_OBJ24, X_OBJ25, X_OBJ26, X_OBJ27, X_OBJ28, X_OBJ29, X_OBJ30,
+ X_OBJ31, X_OBJ32, X_OBJ33, X_OBJ34, X_OBJ35, X_OBJ36, X_OBJ37, X_OBJ38, X_OBJ39, X_OBJ40,
+ X_OBJ41, X_OBJ42, X_OBJ43};
+static int y_obj[44] = {0, Y_OBJ1, Y_OBJ2, Y_OBJ3, Y_OBJ4, Y_OBJ5, Y_OBJ6, Y_OBJ7, Y_OBJ8, Y_OBJ9, Y_OBJ10,
+ Y_OBJ11, Y_OBJ12, Y_OBJ13, Y_OBJ14, Y_OBJ15, Y_OBJ16, Y_OBJ17, Y_OBJ18, Y_OBJ19, Y_OBJ20,
+ Y_OBJ21, Y_OBJ22, Y_OBJ23, Y_OBJ24, Y_OBJ25, Y_OBJ26, Y_OBJ27, Y_OBJ28, Y_OBJ29, Y_OBJ30,
+ Y_OBJ31, Y_OBJ32, Y_OBJ33, Y_OBJ34, Y_OBJ35, Y_OBJ36, Y_OBJ37, Y_OBJ38, Y_OBJ39, Y_OBJ40,
+ Y_OBJ41, Y_OBJ42, Y_OBJ43};
+static int x_pol[44] = {0, 1, 42, 83, 124, 165, 206, 247, 83, 1, 206,
+ 1, 42, 83, 124, 165, 206, 247, 83, 1, 206,
+ 247, 83, 165, 1, 206, 42, 124, 83, 1, 247,
+ 83, 165, 1, 206, 42, 124, 83, 1, 247, 42,
+ 1, 165, 206};
+static int y_pol[44] = {0, 1, 1, 1, 1, 1, 1, 1, 27, 27, 1,
+ 27, 27, 27, 27, 27, 27, 27, 1, 1, 27,
+ 1, 1, 1, 1, 1, 27, 27, 27, 27, 27,
+ 1, 1, 1, 1, 1, 27, 27, 27, 27, 27,
+ 27, 1, 1};
+static int x_barra[] = {6, 51, 96, 141, 186, 232, 276, 321};
+static int x1d_menu[] = {280, 40, 80, 120, 160, 200, 240, 0, 40, 80, 120,
+ 160, 200, 240, 0, 40, 80, 120, 160, 200, 240, 0,
+ 40, 80, 120, 160, 200, 240, 0};
+static int y1d_menu[] = {0, 0, 0, 0, 0, 0, 0, 25, 25, 25, 25, 25, 25, 25,
+ 50, 50, 50, 50, 50, 50, 50, 75, 75, 75, 75, 75, 75, 75, 100};
+static int frame_x[20] = {43, 87, 130, 173, 216, 259};
+static int interf_x[] ={ 1, 65, 129, 193, 1, 65, 129 };
+static int interf_y[] ={ 51, 51, 51, 51, 83, 83, 83 };
+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()) {
+ GUIErrorMessage("No valid games were found in the specified directory.");
+ return -1;
+ }
+
+ // Initialize backend
+ _system->beginGFXTransaction();
+ initCommonGFX(false);
+ _system->initSize(320, 200);
+ _system->endGFXTransaction();
+
+ return 0;
+}
+
+
+int DrasculaEngine::go() {
+ num_ejec = 1;
+
+ for (;;) {
+ VGA = (byte *)malloc(320 * 200);
+ memset(VGA, 0, 64000);
+
+ lleva_objeto = 0;
+ menu_bar = 0; menu_scr = 0; hay_nombre = 0;
+ frame_y = 0;
+ hare_x = -1; hare_se_mueve = 0; sentido_hare = 3; num_frame = 0; hare_se_ve = 1;
+ comprueba_flags = 1;
+ rompo = 0; rompo2 = 0;
+ anda_a_objeto = 0;
+ paso_x = PASO_HARE_X; paso_y = PASO_HARE_Y;
+ alto_hare = ALTO_PERSONAJE; ancho_hare = ANCHO_PERSONAJE; alto_pies = PIES_HARE;
+ alto_habla = ALTO_HABLA_HARE; ancho_habla = ANCHO_HABLA_HARE;
+ hay_respuesta = 0;
+ conta_ciego_vez = 0;
+ cambio_de_color = 0;
+ rompo_y_salgo = 0;
+ vb_x = 120; sentido_vb = 1; vb_se_mueve = 0; frame_vb = 1;
+ frame_piano = 0;
+ frame_borracho = 0;
+ frame_velas = 0;
+ cont_sv = 0;
+ term_int = 0;
+ cual_ejec = 0; hay_que_load = 0;
+ corta_musica = 0;
+ hay_seleccion = 0;
+ Leng = 0;
+ UsingMem = 0;
+ GlobalSpeed = 0;
+ frame_ciego = 0;
+ frame_ronquido = 0;
+ frame_murcielago = 0;
+ c_mirar = 0;
+ c_poder = 0;
+
+ asigna_memoria();
+ carga_info();
+
+ lee_dibujos("95.alg");
+ descomprime_dibujo(dir_mesa, 1);
+
+ lee_dibujos("96.alg");
+ descomprime_dibujo(dir_hare_frente, COMPLETA);
+ if (num_ejec == 1) {
+ 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("pts.alg");
+ descomprime_dibujo(dir_dibujo2, 1);
+ }
+ strcpy(nombre_icono[1], "look");
+ strcpy(nombre_icono[2], "take");
+ strcpy(nombre_icono[3], "open");
+ strcpy(nombre_icono[4], "close");
+ strcpy(nombre_icono[5], "talk");
+ strcpy(nombre_icono[6], "push");
+
+ paleta_hare();
+ if (escoba()) {
+ salir_al_dos(0);
+ break;
+ }
+ salir_al_dos(0);
+ }
+ return 0;
+}
+
+void DrasculaEngine::salir_al_dos(int r) {
+ if (hay_sb == 1)
+ ctvd_end();
+ borra_pantalla();
+ Negro();
+ MusicFadeout();
+ stopmusic();
+ libera_memoria();
+ free(VGA);
+}
+
+void DrasculaEngine::asigna_memoria() {
+ dir_zona_pantalla = (byte *)malloc(64000);
+ assert(dir_zona_pantalla);
+ dir_dibujo1 = (byte *)malloc(64000);
+ assert(dir_dibujo1);
+ dir_hare_fondo = (byte *)malloc(64000);
+ assert(dir_hare_fondo);
+ dir_dibujo3 = (byte *)malloc(64000);
+ assert(dir_dibujo3);
+ dir_dibujo2 = (byte *)malloc(64000);
+ assert(dir_dibujo2);
+ dir_mesa = (byte *)malloc(64000);
+ assert(dir_mesa);
+ dir_hare_dch = (byte *)malloc(64000);
+ assert(dir_hare_dch);
+ dir_hare_frente = (byte *)malloc(64000);
+ assert(dir_hare_frente);
+}
+
+void DrasculaEngine::libera_memoria() {
+ free(dir_zona_pantalla);
+ free(dir_dibujo1);
+ free(dir_hare_fondo);
+ free(dir_dibujo2);
+ free(dir_mesa);
+ free(dir_dibujo3);
+ free(dir_hare_dch);
+ free(dir_hare_frente);
+}
+
+void DrasculaEngine::carga_info() {
+ hay_sb = 1;
+ con_voces = 0;
+ hay_que_load = 0;
+}
+
+void DrasculaEngine::lee_dibujos(const char *NamePcc) {
+ unsigned int con, x = 0;
+ unsigned int fExit = 0;
+ byte ch, rep;
+ Common::File file;
+ byte *auxPun;
+
+ file.open(NamePcc);
+ if (!file.isOpen())
+ error("missing game data %s %c", NamePcc, 7);
+
+ Buffer_pcx = (byte *)malloc(65000);
+ auxPun = Buffer_pcx;
+ file.seek(128);
+ while (!fExit) {
+ ch = file.readByte();
+ rep = 1;
+ if ((ch & 192) == 192) {
+ rep = (ch & 63);
+ ch = file.readByte();
+ }
+ for (con = 0; con < rep; con++) {
+ *auxPun++ = ch;
+ x++;
+ if (x > 64000)
+ fExit = 1;
+ }
+ }
+
+ file.read(cPal, 768);
+ file.close();
+}
+
+void DrasculaEngine::descomprime_dibujo(byte *dir_escritura, int plt) {
+ memcpy(dir_escritura, Buffer_pcx, 64000);
+ free(Buffer_pcx);
+ asigna_rgb((byte *)cPal, plt);
+ if (plt > 1)
+ funde_rgb(plt);
+}
+
+void DrasculaEngine::paleta_hare() {
+ int color, componente;
+
+ for (color = 235; color < 253; color++)
+ for (componente = 0; componente < 3; componente++)
+ palHare[color][componente] = palJuego[color][componente];
+
+}
+
+void DrasculaEngine::hare_oscuro() {
+ int color, componente;
+
+ for (color = 235; color < 253; color++ )
+ for (componente = 0; componente < 3; componente++)
+ palJuego[color][componente] = palHareOscuro[color][componente];
+
+ ActualizaPaleta();
+}
+
+void DrasculaEngine::asigna_rgb(byte *dir_lectura, int plt) {
+ int x, cnt = 0;
+
+ for (x = 0; x < plt; x++) {
+ palJuego[x][0] = dir_lectura[cnt++] / 4;
+ palJuego[x][1] = dir_lectura[cnt++] / 4;
+ palJuego[x][2] = dir_lectura[cnt++] / 4;
+ }
+ ActualizaPaleta();
+}
+
+void DrasculaEngine::funde_rgb(int plt) {}
+
+void DrasculaEngine::Negro() {
+ int color, componente;
+ DacPalette256 palNegra;
+
+ for (color = 0; color < 256; color++)
+ for (componente = 0; componente < 3; componente++)
+ palNegra[color][componente] = 0;
+
+ palNegra[254][0] = 0x3F;
+ palNegra[254][1] = 0x3F;
+ palNegra[254][2] = 0x15;
+
+ setvgapalette256((byte *)&palNegra);
+}
+
+void DrasculaEngine::ActualizaPaleta() {
+ setvgapalette256((byte *)&palJuego);
+}
+
+void DrasculaEngine::setvgapalette256(byte *PalBuf) {
+ byte pal[256 * 4];
+ int i;
+
+ for (i = 0; i < 256; i++) {
+ pal[i * 4 + 0] = PalBuf[i * 3 + 0] * 4;
+ pal[i * 4 + 1] = PalBuf[i * 3 + 1] * 4;
+ pal[i * 4 + 2] = PalBuf[i * 3 + 2] * 4;
+ pal[i * 4 + 3] = 0;
+ }
+ _system->setPalette(pal, 0, 256);
+ _system->updateScreen();
+}
+
+void DrasculaEngine::DIBUJA_FONDO(int xorg, int yorg, int xdes, int ydes, int Ancho,
+ int Alto, byte *Origen, byte *Destino) {
+ int x;
+ Destino += xdes + ydes * 320;
+ Origen += xorg + yorg * 320;
+ for (x = 0; x < Alto; x++) {
+ memcpy(Destino, Origen, Ancho);
+ Destino += 320;
+ Origen += 320;
+ }
+}
+
+void DrasculaEngine::DIBUJA_BLOQUE(int xorg, int yorg, int xdes, int ydes, int Ancho,
+ int Alto, byte *Origen, byte *Destino) {
+ int y, x;
+
+ Destino += xdes + ydes * 320;
+ Origen += xorg + yorg * 320;
+
+ for (y = 0; y < Alto; y++)
+ for (x = 0; x < Ancho; x++)
+ if (Origen[x + y * 320] != 255)
+ Destino[x + y * 320] = Origen[x + y * 320];
+}
+
+void DrasculaEngine::DIBUJA_BLOQUE_CUT(int *Array, byte *Origen, byte *Destino) {
+ int y, x;
+ int xorg = Array[0];
+ int yorg = Array[1];
+ int xdes = Array[2];
+ int ydes = Array[3];
+ int Ancho = Array[4];
+ int Alto = Array[5];
+
+ if (ydes < 0) {
+ yorg += -ydes;
+ Alto += ydes;
+ ydes = 0;
+ }
+ if (xdes < 0) {
+ xorg += -xdes;
+ Ancho += xdes;
+ xdes = 0;
+ }
+ if ((xdes + Ancho) > 319)
+ Ancho -= (xdes + Ancho) - 320;
+ if ((ydes + Alto) > 199)
+ Alto -= (ydes + Alto) - 200;
+
+ Destino += xdes + ydes * 320;
+ Origen += xorg + yorg * 320;
+
+ for (y = 0; y < Alto; y++)
+ for (x = 0; x < Ancho; x++)
+ if (Origen[x + y * 320] != 255)
+ Destino[x + y * 320] = Origen[x + y * 320];
+}
+
+void DrasculaEngine::VUELCA_PANTALLA(int xorg, int yorg, int xdes, int ydes, int Ancho, int Alto, byte *Buffer) {
+ int x;
+ byte *ptr = VGA;
+
+ ptr += xdes + ydes * 320;
+ Buffer += xorg + yorg * 320;
+ for (x = 0; x < Alto; x++) {
+ memcpy(ptr, Buffer, Ancho);
+ ptr += 320;
+ Buffer += 320;
+ }
+
+ _system->copyRectToScreen((const byte *)VGA, 320, 0, 0, 320, 200);
+ _system->updateScreen();
+}
+
+bool DrasculaEngine::escoba() {
+ int soc, l, n;
+
+ dir_texto = dir_mesa;
+
+ musica_antes = -1;
+
+ soc = 0;
+ for (l = 0; l < 6; l++) {
+ soc = soc + ANCHO_PERSONAJE;
+ frame_x[l] = soc;
+ }
+
+ for (n = 1; n < 43; n++)
+ objetos_que_tengo[n] = 0;
+
+ for (n = 0; n < NUM_BANDERAS; n++)
+ flags[n] = 0;
+
+ if (num_ejec == 2) {
+ flags[16] = 1;
+ flags[17] = 1;
+ flags[27] = 1;
+ }
+
+ for (n = 1; n < 7; n++)
+ objetos_que_tengo[n] = n;
+
+ if (num_ejec == 1) {
+ agarra_objeto(28);
+ buffer_teclado();
+
+ if (hay_que_load == 0)
+ animacion_1_1();
+
+ sin_verbo();
+ lee_dibujos("2aux62.alg");
+ descomprime_dibujo(dir_dibujo2, 1);
+ sentido_hare = 1;
+ obj_saliendo = 104;
+ if (hay_que_load != 0)
+ para_cargar(nom_partida);
+ else {
+ carga_escoba_1("62.ald");
+ hare_x = -20;
+ hare_y = 56;
+ lleva_al_hare(65, 145);
+ }
+ } else if (num_ejec == 2) {
+ suma_objeto(28);
+ buffer_teclado();
+ sentido_hare = 3;
+ obj_saliendo = 162;
+ if (hay_que_load == 0)
+ carga_escoba_2("14.ald");
+ else
+ para_cargar(nom_partida);
+ }
+
+bucles:
+ if (hare_se_mueve == 0) {
+ paso_x = PASO_HARE_X;
+ paso_y = PASO_HARE_Y;
+ }
+ if (hare_se_mueve == 0 && anda_a_objeto == 1) {
+ sentido_hare = sentido_final;
+ anda_a_objeto = 0;
+ }
+
+ if (num_ejec == 2) {
+ if ((!strcmp(num_room, "3.alg")) && (hare_x == 279) && (hare_y + alto_hare == 101))
+ animacion_1_2();
+ else if ((!strcmp(num_room, "14.alg")) && (hare_x == 214) && (hare_y + alto_hare == 121))
+ lleva_al_hare(190, 130);
+ else if ((!strcmp(num_room, "14.alg")) && (hare_x == 246) && (hare_y + alto_hare == 112))
+ lleva_al_hare(190, 130);
+ }
+
+ mueve_cursor();
+ VUELCA_PANTALLA(0, 0, 0, 0, 320, 200, dir_zona_pantalla);
+ if (music_status() == 0 && musica_room != 0)
+ playmusic(musica_room);
+
+ MirarRaton();
+
+ if (menu_scr == 0 && lleva_objeto == 1)
+ comprueba_objetos();
+
+ if (boton_dch == 1 && menu_scr == 1) {
+ if (num_ejec == 1)
+ lee_dibujos("99.alg");
+ else if (num_ejec == 2)
+ lee_dibujos(fondo_y_menu);
+ descomprime_dibujo(dir_hare_fondo, 1);
+ setvgapalette256((byte *)&palJuego);
+ menu_scr = 0;
+ espera_soltar();
+ 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");
+ descomprime_dibujo(dir_hare_fondo, 1);
+ menu_scr = 1;
+ espera_soltar();
+ sin_verbo();
+ cont_sv = 0;
+ }
+
+ if (boton_izq == 1 && menu_bar == 1) {
+ elige_en_barra();
+ cont_sv = 0;
+ } else if (boton_izq == 1 && lleva_objeto == 0) {
+ if (comprueba1())
+ return true;
+ cont_sv = 0;
+ } else if (boton_izq == 1 && lleva_objeto == 1) {
+ comprueba2();
+ cont_sv = 0;
+ }
+
+ if (y_raton < 24 && menu_scr == 0)
+ menu_bar = 1;
+ else
+ menu_bar = 0;
+
+ Common::KeyCode key = getscan();
+ if (key == Common::KEYCODE_F1 && menu_scr == 0) {
+ elige_verbo(1);
+ cont_sv = 0;
+ } else if (key == Common::KEYCODE_F2 && menu_scr == 0) {
+ elige_verbo(2);
+ cont_sv = 0;
+ } else if (key == Common::KEYCODE_F3 && menu_scr == 0) {
+ elige_verbo(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;
+ } else if (key == Common::KEYCODE_F6 && menu_scr == 0) {
+ elige_verbo(6);
+ cont_sv = 0;
+ } else if (key == Common::KEYCODE_F9) {
+ mesa();
+ cont_sv = 0;
+ } else if (key == Common::KEYCODE_F10) {
+ saves();
+ cont_sv = 0;
+ } else if (key == Common::KEYCODE_F8) {
+ sin_verbo();
+ 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;
+ } 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;
+ } else if (key == Common::KEYCODE_DELETE) {
+ confirma_go();
+ cont_sv = 0;
+ } else if (key == Common::KEYCODE_ESCAPE) {
+ confirma_salir();
+ cont_sv = 0;
+ } else if (cont_sv == 1500) {
+ salva_pantallas();
+ cont_sv = 0;
+ } else
+ cont_sv++;
+ goto bucles;
+}
+
+void DrasculaEngine::agarra_objeto(int objeto) {
+ lee_dibujos("icons.alg");
+ descomprime_dibujo(dir_hare_fondo, 1);
+ elige_objeto(objeto);
+ lee_dibujos("99.alg");
+ descomprime_dibujo(dir_hare_fondo, 1);
+}
+
+void DrasculaEngine::elige_objeto(int objeto) {
+ 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;
+}
+
+int DrasculaEngine::resta_objeto(int osj) {
+ int h, q = 0;
+
+ for (h = 1; h < 43; h++) {
+ if (objetos_que_tengo[h] == osj) {
+ objetos_que_tengo[h] = 0;
+ q = 1;
+ break;
+ }
+ }
+
+ if (q == 1)
+ return 0;
+ else
+ return 1;
+}
+
+void DrasculaEngine::animacion_1_1() {
+ int l, l2, p;
+ int pos_pixel[6];
+
+ while (term_int == 0) {
+ playmusic(29);
+ fliplay("logoddm.bin", 9);
+ if ((term_int == 1) || (getscan() == Common::KEYCODE_ESCAPE))
+ break;
+ delay(600);
+ if ((term_int == 1) || (getscan() == Common::KEYCODE_ESCAPE))
+ break;
+ borra_pantalla();
+ delay(340);
+ if ((term_int == 1) || (getscan() == Common::KEYCODE_ESCAPE))
+ break;
+ playmusic(26);
+ delay(500);
+ if ((term_int == 1) || (getscan() == Common::KEYCODE_ESCAPE))
+ break;
+ fliplay("logoalc.bin", 8);
+ if ((term_int == 1) || (getscan() == Common::KEYCODE_ESCAPE))
+ break;
+ borra_pantalla();
+ lee_dibujos("cielo.alg");
+ descomprime_dibujo(dir_zona_pantalla, 256);
+ Negro();
+ VUELCA_PANTALLA(0, 0, 0, 0, 320, 200, dir_zona_pantalla);
+ FundeDelNegro(2);
+ if ((term_int == 1) || (getscan() == Common::KEYCODE_ESCAPE))
+ break;
+ delay(900);
+ if ((term_int == 1) || (getscan() == Common::KEYCODE_ESCAPE))
+ break;
+ color_abc(ROJO);
+ centra_texto("Transilvanya, 1993 d.c.", 160, 100);
+ VUELCA_PANTALLA(0, 0, 0, 0, 320, 200, dir_zona_pantalla);
+ if ((term_int == 1) || (getscan() == Common::KEYCODE_ESCAPE))
+ break;
+ delay(1000);
+ if ((term_int == 1) || (getscan() == Common::KEYCODE_ESCAPE))
+ break;
+ delay(1200);
+ if ((term_int == 1) || (getscan() == Common::KEYCODE_ESCAPE))
+ break;
+
+ fliplay("scrollb.bin", 9);
+
+ if ((term_int == 1) || (getscan() == Common::KEYCODE_ESCAPE))
+ break;
+ borra_pantalla();
+ comienza_sound("s5.als");
+ if ((term_int == 1) || (getscan() == Common::KEYCODE_ESCAPE))
+ break;
+ anima("scr2.bin", 17);
+ if ((term_int == 1) || (getscan() == Common::KEYCODE_ESCAPE))
+ break;
+ fin_sound_corte();
+ anima("scr3.bin", 17);
+ if ((term_int == 1) || (getscan() == Common::KEYCODE_ESCAPE))
+ break;
+ lee_dibujos("cielo2.alg");
+ descomprime_dibujo(dir_zona_pantalla, 256);
+ VUELCA_PANTALLA(0, 0, 0, 0, 320, 200, dir_zona_pantalla);
+ if ((term_int == 1) || (getscan() == Common::KEYCODE_ESCAPE))
+ break;
+ FundeAlNegro(1);
+ if ((term_int == 1) || (getscan() == Common::KEYCODE_ESCAPE))
+ break;
+ borra_pantalla();
+
+ lee_dibujos("96.alg");
+ descomprime_dibujo(dir_hare_frente, COMPLETA);
+ lee_dibujos("103.alg");
+ descomprime_dibujo(dir_dibujo1, MEDIA);
+ lee_dibujos("104.alg");
+ descomprime_dibujo(dir_dibujo3, 1);
+ lee_dibujos("aux104.alg");
+ descomprime_dibujo(dir_dibujo2, 1);
+
+ playmusic(4);
+ if ((term_int == 1) || (getscan() == Common::KEYCODE_ESCAPE))
+ break;
+ delay(400);
+ if ((term_int == 1) || (getscan() == Common::KEYCODE_ESCAPE))
+ break;
+
+ for (l2 = 0; l2 < 3; l2++)
+ for (l = 0; l < 7; l++) {
+ DIBUJA_FONDO(0, 0, 0, 0, 320, 200, dir_dibujo1, dir_zona_pantalla);
+ DIBUJA_FONDO(interf_x[l], interf_y[l], 156, 45, 63, 31, dir_dibujo2, dir_zona_pantalla);
+ VUELCA_PANTALLA(0, 0, 0, 0, 320, 200, dir_zona_pantalla);
+ if (getscan() == Common::KEYCODE_ESCAPE) {
+ term_int = 1;
+ break;
+ }
+ pausa(3);
+ }
+ if ((term_int == 1) || (getscan() == Common::KEYCODE_ESCAPE))
+ break;
+
+ l2 = 0; p = 0;
+ pos_pixel[3] = 45;
+ pos_pixel[4] = 63;
+ pos_pixel[5] = 31;
+
+ for (l = 0; l < 180; l++) {
+ DIBUJA_FONDO(0, 0, 320 - l, 0, l, 200, dir_dibujo3, dir_zona_pantalla);
+ DIBUJA_FONDO(l, 0, 0, 0, 320 - l, 200, dir_dibujo1, dir_zona_pantalla);
+
+ pos_pixel[0] = interf_x[l2];
+ pos_pixel[1] = interf_y[l2];
+ pos_pixel[2] = 156 - l;
+
+ DIBUJA_BLOQUE_CUT(pos_pixel, dir_dibujo2, dir_zona_pantalla);
+ VUELCA_PANTALLA(0, 0, 0, 0, 320, 200, dir_zona_pantalla);
+ p++;
+ if (p == 6) {
+ p = 0;
+ l2++;
+ }
+ if (l2 == 7)
+ l2 = 0;
+ if (getscan() == Common::KEYCODE_ESCAPE) {
+ term_int = 1;
+ break;
+ }
+ }
+ if ((term_int == 1) || (getscan() == Common::KEYCODE_ESCAPE))
+ break;
+ DIBUJA_FONDO(0, 0, 0, 0, 320, 200, dir_zona_pantalla, dir_dibujo1);
+
+ habla_dr_grande(TEXTD1, "D1.als");
+ if ((term_int == 1) || (getscan() == Common::KEYCODE_ESCAPE))
+ break;
+
+ borra_pantalla();
+
+ lee_dibujos("100.alg");
+ descomprime_dibujo(dir_dibujo1, MEDIA);
+ lee_dibujos("auxigor.alg");
+ descomprime_dibujo(dir_hare_frente, 1);
+ lee_dibujos("auxdr.alg");
+ descomprime_dibujo(dir_hare_fondo, 1);
+ sentido_dr = 0;
+ x_dr = 129;
+ y_dr = 95;
+ sentido_igor = 1;
+ x_igor = 66;
+ y_igor = 97;
+
+ DIBUJA_FONDO(0, 0, 0, 0, 320, 200, dir_dibujo1, dir_zona_pantalla);
+ pon_igor();
+ pon_dr();
+ VUELCA_PANTALLA(0, 0, 0, 0, 320, 200, dir_zona_pantalla);
+ habla_igor_dch(TEXTI8, "I8.als");
+ if ((term_int == 1) || (getscan() == Common::KEYCODE_ESCAPE))
+ break;
+ DIBUJA_FONDO(0, 0, 0, 0, 320, 200, dir_dibujo1, dir_zona_pantalla);
+ pon_igor();
+ pon_dr();
+ VUELCA_PANTALLA(0, 0, 0, 0, 320, 200, dir_zona_pantalla);
+ habla_dr_izq(TEXTD2, "d2.als");
+ if ((term_int == 1) || (getscan() == Common::KEYCODE_ESCAPE))
+ break;
+ habla_dr_izq(TEXTD3, "d3.als");
+ if ((term_int == 1) || (getscan() == Common::KEYCODE_ESCAPE))
+ break;
+ anima("lib.bin", 16);
+ if ((term_int == 1) || (getscan() == Common::KEYCODE_ESCAPE))
+ break;
+ anima("lib2.bin", 16);
+ if ((term_int == 1) || (getscan() == Common::KEYCODE_ESCAPE))
+ break;
+ borra_pantalla();
+ color_solo = ROJO;
+ lee_dibujos("plan1.alg");
+ descomprime_dibujo(dir_zona_pantalla, MEDIA);
+ VUELCA_PANTALLA(0, 0, 0, 0, 320, 200, dir_zona_pantalla);
+ pausa(10);
+ habla_solo(TEXTD4,"d4.als");
+ if ((term_int == 1) || (getscan() == Common::KEYCODE_ESCAPE))
+ break;
+ lee_dibujos("plan1.alg");
+ descomprime_dibujo(dir_zona_pantalla, MEDIA);
+ VUELCA_PANTALLA(0, 0, 0, 0, 320, 200, dir_zona_pantalla);
+ habla_solo(TEXTD5, "d5.als");
+ if ((term_int == 1) || (getscan() == Common::KEYCODE_ESCAPE))
+ break;
+ anima("lib2.bin", 16);
+ if ((term_int == 1) || (getscan() == Common::KEYCODE_ESCAPE))
+ break;
+ borra_pantalla();
+ lee_dibujos("plan2.alg");
+ descomprime_dibujo(dir_zona_pantalla, MEDIA);
+ VUELCA_PANTALLA(0, 0, 0, 0, 320, 200, dir_zona_pantalla);
+ pausa(20);
+ habla_solo(TEXTD6, "d6.als");
+ if ((term_int == 1) || (getscan() == Common::KEYCODE_ESCAPE))
+ break;
+ anima("lib2.bin", 16);
+ if ((term_int == 1) || (getscan() == Common::KEYCODE_ESCAPE))
+ break;
+ borra_pantalla();
+ lee_dibujos("plan3.alg");
+ descomprime_dibujo(dir_zona_pantalla, MEDIA);
+ VUELCA_PANTALLA(0, 0, 0, 0, 320, 200, dir_zona_pantalla);
+ pausa(20);
+ if ((term_int == 1) || (getscan() == Common::KEYCODE_ESCAPE))
+ break;
+ habla_solo(TEXTD7, "d7.als");
+ if ((term_int == 1) || (getscan() == Common::KEYCODE_ESCAPE))
+ break;
+ lee_dibujos("plan3.alg");
+ descomprime_dibujo(dir_zona_pantalla, MEDIA);
+ VUELCA_PANTALLA(0, 0, 0, 0, 320, 200, dir_zona_pantalla);
+ habla_solo(TEXTD8, "d8.als");
+ if ((term_int == 1) || (getscan() == Common::KEYCODE_ESCAPE))
+ break;
+ borra_pantalla();
+ lee_dibujos("100.alg");
+ descomprime_dibujo(dir_dibujo1, MEDIA);
+ MusicFadeout();
+ stopmusic();
+ if ((term_int == 1) || (getscan() == Common::KEYCODE_ESCAPE))
+ break;
+ habla_igor_dch(TEXTI9, "I9.als");
+ if ((term_int == 1) || (getscan() == Common::KEYCODE_ESCAPE))
+ break;
+ habla_dr_izq(TEXTD9, "d9.als");
+ if ((term_int == 1) || (getscan() == Common::KEYCODE_ESCAPE))
+ break;
+ habla_igor_dch(TEXTI10, "I10.als");
+ if ((term_int == 1) || (getscan() == Common::KEYCODE_ESCAPE))
+ break;
+ playmusic(11);
+ habla_dr_izq(TEXTD10, "d10.als");
+ if ((term_int == 1) || (getscan() == Common::KEYCODE_ESCAPE))
+ break;
+ anima("rayo1.bin", 16);
+ if ((term_int == 1) || (getscan() == Common::KEYCODE_ESCAPE))
+ break;
+ comienza_sound("s5.als");
+ anima("rayo2.bin", 15);
+ if ((term_int == 1) || (getscan() == Common::KEYCODE_ESCAPE))
+ break;
+ anima("frel2.bin", 16);
+ if ((term_int == 1) || (getscan() == Common::KEYCODE_ESCAPE))
+ break;
+ anima("frel.bin", 16);
+ if ((term_int == 1) || (getscan() == Common::KEYCODE_ESCAPE))
+ break;
+ anima("frel.bin", 16);
+ if ((term_int == 1) || (getscan() == Common::KEYCODE_ESCAPE))
+ break;
+ fin_sound_corte();
+ borra_pantalla();
+ Negro();
+ playmusic(23);
+ FundeDelNegro(0);
+ if ((term_int == 1) || (getscan() == Common::KEYCODE_ESCAPE))
+ break;
+ sentido_dr = 1;
+ habla_igor_dch(TEXTI1, "I1.als");
+ if ((term_int == 1) || (getscan() == Common::KEYCODE_ESCAPE))
+ break;
+ habla_dr_dch(TEXTD11, "d11.als");
+ if ((term_int == 1) || (getscan() == Common::KEYCODE_ESCAPE))
+ break;
+ sentido_dr = 3;
+ DIBUJA_FONDO(0, 0, 0, 0, 320, 200, dir_dibujo1, dir_zona_pantalla);
+ pon_igor();
+ pon_dr();
+ VUELCA_PANTALLA(0, 0, 0, 0, 320, 200, dir_zona_pantalla);
+ pausa(1);
+ sentido_dr = 0;
+ DIBUJA_FONDO(0, 0, 0, 0, 320, 200, dir_dibujo1, dir_zona_pantalla);
+ pon_igor();
+ pon_dr();
+ VUELCA_PANTALLA(0, 0, 0, 0, 320, 200, dir_zona_pantalla);
+ habla_dr_izq(TEXTD12, "d12.als");
+ if ((term_int == 1) || (getscan() == Common::KEYCODE_ESCAPE))
+ break;
+ sentido_dr = 3;
+ DIBUJA_FONDO(0, 0, 0, 0, 320, 200, dir_dibujo1, dir_zona_pantalla);
+ pon_igor();
+ pon_dr();
+ VUELCA_PANTALLA(0, 0, 0, 0, 320, 200, dir_zona_pantalla);
+ pausa(1);
+ sentido_dr = 1;
+ DIBUJA_FONDO(0, 0, 0, 0, 320, 200, dir_dibujo1, dir_zona_pantalla);
+ pon_igor();
+ pon_dr();
+ VUELCA_PANTALLA(0, 0, 0, 0, 320, 200, dir_zona_pantalla);
+ habla_igor_dch(TEXTI2, "I2.als");
+ if ((term_int == 1) || (getscan() == Common::KEYCODE_ESCAPE))
+ break;
+ pausa(13);
+ habla_dr_dch(TEXTD13,"d13.als");
+ if ((term_int == 1) || (getscan() == Common::KEYCODE_ESCAPE))
+ break;
+ sentido_dr = 3;
+ DIBUJA_FONDO(0, 0, 0, 0, 320, 200, dir_dibujo1, dir_zona_pantalla);
+ pon_igor();
+ pon_dr();
+ VUELCA_PANTALLA(0, 0, 0, 0, 320, 200, dir_zona_pantalla);
+ pausa(1);
+ sentido_dr = 0;
+ DIBUJA_FONDO(0, 0, 0, 0, 320, 200, dir_dibujo1, dir_zona_pantalla);
+ pon_igor();
+ pon_dr();
+ VUELCA_PANTALLA(0, 0, 0, 0, 320, 200, dir_zona_pantalla);
+ habla_dr_izq(TEXTD14, "d14.als");
+ if ((term_int == 1) || (getscan() == Common::KEYCODE_ESCAPE))
+ break;
+ habla_igor_dch(TEXTI3, "I3.als");
+ if ((term_int == 1) || (getscan() == Common::KEYCODE_ESCAPE))
+ break;
+ habla_dr_izq(TEXTD15, "d15.als");
+ if ((term_int == 1) || (getscan() == Common::KEYCODE_ESCAPE))
+ break;
+ habla_igor_dch(TEXTI4, "I4.als");
+ if ((term_int == 1) || (getscan() == Common::KEYCODE_ESCAPE))
+ break;
+ habla_dr_izq(TEXTD16, "d16.als");
+ if ((term_int == 1) || (getscan() == Common::KEYCODE_ESCAPE))
+ break;
+ habla_igor_dch(TEXTI5, "I5.als");
+ if ((term_int == 1) || (getscan() == Common::KEYCODE_ESCAPE))
+ break;
+ sentido_igor = 3;
+ habla_dr_izq(TEXTD17, "d17.als");
+ if ((term_int == 1) || (getscan() == Common::KEYCODE_ESCAPE))
+ break;
+ pausa(18);
+ if ((term_int == 1) || (getscan() == Common::KEYCODE_ESCAPE))
+ break;
+ habla_igor_frente(TEXTI6, "I6.als");
+ if ((term_int == 1) || (getscan() == Common::KEYCODE_ESCAPE))
+ break;
+ FundeAlNegro(0);
+ if ((term_int == 1) || (getscan() == Common::KEYCODE_ESCAPE))
+ break;
+ borra_pantalla();
+
+ playmusic(2);
+ pausa(5);
+ fliplay("intro.bin", 12);
+ term_int = 1;
+ }
+ borra_pantalla();
+ lee_dibujos("96.alg");
+ descomprime_dibujo(dir_hare_frente, COMPLETA);
+ lee_dibujos("99.alg");
+ descomprime_dibujo(dir_hare_fondo, 1);
+}
+
+bool DrasculaEngine::animacion_2_1() {
+ int l;
+
+ lleva_al_hare(231, 91);
+ hare_se_ve = 0;
+
+ term_int = 0;
+
+ for (;;) {
+ if ((term_int == 1) || (getscan() == Common::KEYCODE_ESCAPE))
+ break;
+
+ anima("ag.bin", 14);
+ if ((term_int == 1) || (getscan() == Common::KEYCODE_ESCAPE))
+ break;
+
+ lee_dibujos("an11y13.alg");
+ descomprime_dibujo(dir_hare_dch, 1);
+ if ((term_int == 1) || (getscan() == Common::KEYCODE_ESCAPE))
+ break;
+
+ habla_tabernero(TEXTT22, "T22.als");
+ if ((term_int == 1) || (getscan() == Common::KEYCODE_ESCAPE))
+ break;
+
+ lee_dibujos("97.alg");
+ descomprime_dibujo(dir_hare_dch, 1);
+ if ((term_int == 1) || (getscan() == Common::KEYCODE_ESCAPE))
+ break;
+
+ pausa(4);
+ comienza_sound("s1.als");
+ hipo(18);
+ fin_sound();
+ if ((term_int == 1) || (getscan() == Common::KEYCODE_ESCAPE))
+ break;
+
+ borra_pantalla();
+ stopmusic();
+ corta_musica = 1;
+ memset(dir_zona_pantalla, 0, 64000);
+ color_solo = BLANCO;
+ pausa(80);
+
+ if ((term_int == 1) || (getscan() == Common::KEYCODE_ESCAPE))
+ break;
+ habla_solo(TEXTBJ1, "BJ1.als");
+ if ((term_int == 1) || (getscan() == Common::KEYCODE_ESCAPE))
+ break;
+ borra_pantalla();
+ lee_dibujos("bj.alg");
+ descomprime_dibujo(dir_zona_pantalla, MEDIA);
+ if ((term_int == 1) || (getscan() == Common::KEYCODE_ESCAPE))
+ break;
+ Negro();
+ VUELCA_PANTALLA(0, 0, 0, 0, 320, 200, dir_zona_pantalla);
+ FundeDelNegro(1);
+ if ((term_int == 1) || (getscan() == Common::KEYCODE_ESCAPE))
+ break;
+ color_solo = AMARILLO;
+ habla_solo(TEXT214, "214.als");
+ if ((term_int == 1) || (getscan() == Common::KEYCODE_ESCAPE))
+ break;
+ borra_pantalla();
+
+ lee_dibujos("16.alg");
+ descomprime_dibujo(dir_dibujo1, MEDIA);
+ if ((term_int == 1) || (getscan() == Common::KEYCODE_ESCAPE))
+ break;
+ lee_dibujos("auxbj.alg");
+ descomprime_dibujo(dir_dibujo3, 1);
+ if ((term_int == 1) || (getscan() == Common::KEYCODE_ESCAPE))
+ break;
+
+ strcpy(num_room,"16.alg");
+
+ if ((term_int == 1) || (getscan() == Common::KEYCODE_ESCAPE))
+ break;
+ for (l = 0; l < 200; l++)
+ factor_red[l] = 99;
+ x_bj = 170;
+ y_bj = 90;
+ sentido_bj = 0;
+ hare_x = 91;
+ hare_y = 95;
+ sentido_hare = 1;
+ hare_se_ve = 1;
+ if ((term_int == 1) || (getscan() == Common::KEYCODE_ESCAPE))
+ break;
+
+ lee_dibujos("97g.alg");
+ descomprime_dibujo(dir_hare_dch, 1);
+ if ((term_int == 1) || (getscan() == Common::KEYCODE_ESCAPE))
+ break;
+
+ anima("lev.bin", 15);
+ if ((term_int == 1) || (getscan() == Common::KEYCODE_ESCAPE))
+ break;
+
+ lleva_al_hare(100 + ancho_hare / 2, 99 + alto_hare);
+ if ((term_int == 1) || (getscan() == Common::KEYCODE_ESCAPE))
+ break;
+ sentido_hare = 1;
+ hare_x = 100;
+ hare_y = 95;
+
+ habla_bj(TEXTBJ2, "BJ2.als");
+ hablar(TEXT215, "215.als");
+ habla_bj(TEXTBJ3, "BJ3.als");
+ hablar(TEXT216, "216.als");
+ habla_bj(TEXTBJ4, "BJ4.als");
+ habla_bj(TEXTBJ5, "BJ5.als");
+ habla_bj(TEXTBJ6, "BJ6.als");
+ hablar(TEXT217, "217.als");
+ habla_bj(TEXTBJ7, "BJ7.als");
+ hablar(TEXT218, "218.als");
+ habla_bj(TEXTBJ8, "BJ8.als");
+ hablar(TEXT219, "219.als");
+ habla_bj(TEXTBJ9, "BJ9.als");
+ hablar(TEXT220, "220.als");
+ hablar(TEXT221, "221.als");
+ habla_bj(TEXTBJ10, "BJ10.als");
+ hablar(TEXT222, "222.als");
+ anima("gaf.bin", 15);
+ anima("bjb.bin", 14);
+ playmusic(9);
+ if ((term_int == 1) || (getscan() == Common::KEYCODE_ESCAPE))
+ break;
+ lee_dibujos("97.alg");
+ if ((term_int == 1) || (getscan() == Common::KEYCODE_ESCAPE))
+ break;
+ descomprime_dibujo(dir_hare_dch, 1);
+ if ((term_int == 1) || (getscan() == Common::KEYCODE_ESCAPE))
+ break;
+ refresca_pantalla();
+ VUELCA_PANTALLA(0, 0, 0, 0, 320, 200, dir_zona_pantalla);
+ if ((term_int == 1) || (getscan() == Common::KEYCODE_ESCAPE))
+ break;
+ pausa(120);
+ if ((term_int == 1) || (getscan() == Common::KEYCODE_ESCAPE))
+ break;
+ habla_solo(TEXT223, "223.als");
+ if ((term_int == 1) || (getscan() == Common::KEYCODE_ESCAPE))
+ break;
+ color_solo = BLANCO;
+ refresca_pantalla();
+ if ((term_int == 1) || (getscan() == Common::KEYCODE_ESCAPE))
+ break;
+ VUELCA_PANTALLA(0, 0, 0, 0, 320, 200, dir_zona_pantalla);
+ pausa(110);
+ habla_solo(TEXTBJ11, "BJ11.als");
+ if ((term_int == 1) || (getscan() == Common::KEYCODE_ESCAPE))
+ break;
+ refresca_pantalla();
+ if ((term_int == 1) || (getscan() == Common::KEYCODE_ESCAPE))
+ break;
+ VUELCA_PANTALLA(0, 0, 0, 0, 320, 200, dir_zona_pantalla);
+ if ((term_int == 1) || (getscan() == Common::KEYCODE_ESCAPE))
+ break;
+ pausa(118);
+ if ((term_int == 1) || (getscan() == Common::KEYCODE_ESCAPE))
+ break;
+ lleva_al_hare(132, 97 + alto_hare);
+ pausa(60);
+ if ((term_int == 1) || (getscan() == Common::KEYCODE_ESCAPE))
+ break;
+ hablar(TEXT224, "224.als");
+ if ((term_int == 1) || (getscan() == Common::KEYCODE_ESCAPE))
+ break;
+ habla_bj(TEXTBJ12, "BJ12.als");
+ lleva_al_hare(157, 98 + alto_hare);
+ if ((term_int == 1) || (getscan() == Common::KEYCODE_ESCAPE))
+ break;
+ anima("bes.bin", 16);
+ playmusic(11);
+ anima("rap.bin", 16);
+ if ((term_int == 1) || (getscan() == Common::KEYCODE_ESCAPE))
+ break;
+ sentido_hare = 3;
+ strcpy(num_room, "no_bj.alg");
+ if ((term_int == 1) || (getscan() == Common::KEYCODE_ESCAPE))
+ break;
+ pausa(8);
+ refresca_pantalla();
+ VUELCA_PANTALLA(0, 0, 0, 0, 320, 200, dir_zona_pantalla);
+ hablar(TEXT225, "225.als");
+ pausa(76);
+ if ((term_int == 1) || (getscan() == Common::KEYCODE_ESCAPE))
+ break;
+ sentido_hare = 1;
+ refresca_pantalla();
+ VUELCA_PANTALLA(0, 0, 0, 0, 320, 200, dir_zona_pantalla);
+ hablar(TEXT226, "226.als");
+ if ((term_int == 1) || (getscan() == Common::KEYCODE_ESCAPE))
+ break;
+ refresca_pantalla();
+ VUELCA_PANTALLA(0, 0, 0, 0, 320, 200, dir_zona_pantalla);
+ pausa(30);
+ if ((term_int == 1) || (getscan() == Common::KEYCODE_ESCAPE))
+ break;
+ hablar(TEXT227,"227.als");
+ FundeAlNegro(0);
+ break;
+ }
+
+ num_ejec = 2;
+ return true;
+}
+
+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);
+
+ lleva_objeto = 0;
+ hay_nombre = 0;
+}
+
+void DrasculaEngine::para_cargar(char nom_game[]) {
+ musica_antes = musica_room;
+ menu_scr = 0;
+ if (num_ejec == 2)
+ 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);
+ }
+ sin_verbo();
+}
+
+static char *getLine(Common::File *fp, char *buf, int len) {
+ int c;
+ char *b;
+
+ for (;;) {
+ b = buf;
+ while (!fp->eos()) {
+ c = fp->readByte() ^ 0xff;
+ if (c == '\r')
+ continue;
+ if (c == '\n')
+ break;
+ if (b - buf >= (len - 1))
+ break;
+ *b++ = c;
+ }
+ *b = '\0';
+ if (fp->eos() && b == buf)
+ return NULL;
+ if (b != buf)
+ break;
+ }
+ return buf;
+}
+
+void DrasculaEngine::carga_escoba_1(const char *nom_fich) {
+ int l, obj_salir;
+ float chiquez, pequegnez = 0;
+ char para_codificar[13];
+ char buffer[256];
+
+ hay_nombre = 0;
+
+ strcpy(para_codificar, nom_fich);
+ canal_p(para_codificar);
+ strcpy(datos_actuales, nom_fich);
+
+ buffer_teclado();
+
+ ald = new Common::File;
+ ald->open(nom_fich);
+ if (!ald->isOpen()) {
+ error("missing data file");
+ }
+ 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", &objs_room);
+
+ for (l = 0; l < objs_room; l++) {
+ getLine(ald, buffer, size);
+ sscanf(buffer, "%d", &num_obj[l]);
+ getLine(ald, buffer, size);
+ sscanf(buffer, "%s", nombre_obj[l]);
+ getLine(ald, buffer, size);
+ sscanf(buffer, "%d", &x1[l]);
+ getLine(ald, buffer, size);
+ sscanf(buffer, "%d", &y1[l]);
+ getLine(ald, buffer, size);
+ sscanf(buffer, "%d", &x2[l]);
+ getLine(ald, buffer, size);
+ sscanf(buffer, "%d", &y2[l]);
+ getLine(ald, buffer, size);
+ sscanf(buffer, "%d", &sitiobj_x[l]);
+ getLine(ald, buffer, size);
+ sscanf(buffer, "%d", &sitiobj_y[l]);
+ getLine(ald, buffer, size);
+ sscanf(buffer, "%d", &sentidobj[l]);
+ 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;
+
+ 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();
+
+ ald = new Common::File;
+ ald->open(nom_fich);
+ if (!ald->isOpen()) {
+ error("missing data file");
+ }
+ 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:
+
+ getLine(ald, buffer, size);
+ sscanf(buffer, "%d", &objs_room);
+
+ for (l = 0; l < objs_room; l++) {
+ getLine(ald, buffer, size);
+ sscanf(buffer, "%d", &num_obj[l]);
+ getLine(ald, buffer, size);
+ sscanf(buffer, "%s", nombre_obj[l]);
+ getLine(ald, buffer, size);
+ sscanf(buffer, "%d", &x1[l]);
+ getLine(ald, buffer, size);
+ sscanf(buffer, "%d", &y1[l]);
+ getLine(ald, buffer, size);
+ sscanf(buffer, "%d", &x2[l]);
+ getLine(ald, buffer, size);
+ sscanf(buffer, "%d", &y2[l]);
+ getLine(ald, buffer, size);
+ sscanf(buffer, "%d", &sitiobj_x[l]);
+ getLine(ald, buffer, size);
+ sscanf(buffer, "%d", &sitiobj_y[l]);
+ getLine(ald, buffer, size);
+ sscanf(buffer, "%d", &sentidobj[l]);
+ 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);
+
+ 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);
+
+ strcpy(fondo_y_menu,"99.alg");
+ }
+
+ 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;
+ }
+ hare_se_mueve = 0;
+
+ 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;
+
+ color_abc(VERDE_CLARO);
+
+ soc = 0;
+ for (l = 0; l < 6; l++) {
+ soc = soc + ancho_hare;
+ frame_x[l] = soc;
+ }
+
+ actualiza_datos();
+
+ 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)
+ musica_room = 0;
+ else if (!strcmp(num_room, "15.alg") && flags[5] == 1)
+ musica_room = 0;
+
+ if (musica_antes != musica_room && musica_room != 0)
+ playmusic(musica_room);
+ if (musica_room == 0)
+ 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();
+
+ refresca_pantalla();
+}
+
+void DrasculaEngine::borra_pantalla() {
+ memset(VGA, 0, 64000);
+ _system->copyRectToScreen((const byte *)VGA, 320, 0, 0, 320, 200);
+ _system->updateScreen();
+}
+
+void DrasculaEngine::lleva_al_hare(int punto_x, int punto_y) {
+ sitio_x = punto_x;
+ sitio_y = punto_y;
+ empieza_andar();
+
+ for(;;) {
+ refresca_pantalla();
+ VUELCA_PANTALLA(0, 0, 0, 0, 320, 200, dir_zona_pantalla);
+ if (hare_se_mueve == 0)
+ break;
+ }
+
+ if (anda_a_objeto == 1) {
+ anda_a_objeto = 0;
+ sentido_hare = sentido_final;
+ }
+ refresca_pantalla();
+ VUELCA_PANTALLA(0, 0, 0, 0, 320, 200, dir_zona_pantalla);
+}
+
+void DrasculaEngine::mueve_cursor() {
+ int pos_cursor[8];
+
+ DIBUJA_FONDO(0, 0, 0, 0, 320, 200, dir_dibujo1, dir_zona_pantalla);
+
+ actualiza_refresco_antes();
+ pon_hare();
+ actualiza_refresco();
+
+ if (!strcmp(texto_nombre, "hacker") && hay_nombre == 1) {
+ if (_color != ROJO && menu_scr == 0)
+ color_abc(ROJO);
+ } else if (menu_scr == 0 && _color != VERDE_CLARO)
+ color_abc(VERDE_CLARO);
+ if (hay_nombre == 1 && menu_scr == 0)
+ centra_texto(texto_nombre, x_raton, y_raton);
+ if (menu_scr == 1)
+ menu_sin_volcar();
+ else if (menu_bar == 1)
+ barra_menu();
+
+ pos_cursor[0] = 0;
+ pos_cursor[1] = 0;
+ pos_cursor[2] = x_raton - 20;
+ pos_cursor[3] = y_raton - 17;
+ pos_cursor[4] = ANCHOBJ;
+ pos_cursor[5] = ALTOBJ;
+ DIBUJA_BLOQUE_CUT(pos_cursor, dir_dibujo3, dir_zona_pantalla);
+}
+
+void DrasculaEngine::comprueba_objetos() {
+ int l, veo = 0;
+
+ 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 && espuerta[l] == 0) {
+ strcpy(texto_nombre, nombre_obj[l]);
+ hay_nombre = 1;
+ veo = 1;
+ }
+ }
+
+ if (num_ejec == 1)
+ 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) {
+ strcpy(texto_nombre, "hacker");
+ hay_nombre = 1;
+ veo = 1;
+ }
+ else 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) {
+ strcpy(texto_nombre, "hacker");
+ hay_nombre = 1;
+ veo = 1;
+ }
+
+ if (veo == 0)
+ hay_nombre = 0;
+}
+
+void DrasculaEngine::espera_soltar() {
+ update_events();
+}
+
+void DrasculaEngine::MirarRaton() {
+ update_events();
+}
+
+void DrasculaEngine::elige_en_barra() {
+ int n, num_verbo = -1;
+
+ for (n = 0; n < 7; n++)
+ if (x_raton > x_barra[n] && x_raton < x_barra[n + 1])
+ num_verbo = n;
+
+ if (num_verbo < 1)
+ sin_verbo();
+ else
+ elige_verbo(num_verbo);
+}
+
+bool DrasculaEngine::comprueba1() {
+ int l;
+
+ if (menu_scr == 1)
+ saca_objeto();
+ else {
+ for (l = 0; l < objs_room; l++) {
+ if (x_raton >= x1[l] && y_raton >= y1[l]
+ && x_raton <= x2[l] && y_raton <= y2[l] && rompo == 0) {
+ if (sal_de_la_habitacion(l))
+ return true;
+ if (rompo == 1)
+ break;
+ }
+ }
+
+ if (x_raton > hare_x && y_raton > hare_y
+ && x_raton < hare_x + ancho_hare && y_raton < hare_y + alto_hare)
+ rompo = 1;
+
+ for (l = 0; l < objs_room; l++) {
+ if (x_raton > x1[l] && y_raton > y1[l]
+ && x_raton < x2[l] && y_raton < y2[l] && rompo == 0) {
+ sitio_x = sitiobj_x[l];
+ sitio_y = sitiobj_y[l];
+ sentido_final = sentidobj[l];
+ rompo = 1;
+ anda_a_objeto = 1;
+ empieza_andar();
+ }
+ }
+
+ if (rompo == 0) {
+ sitio_x = x_raton;
+ sitio_y = y_raton;
+
+ if (sitio_x < suelo_x1)
+ sitio_x = suelo_x1;
+ if (sitio_x > suelo_x2)
+ sitio_x = suelo_x2;
+ if (sitio_y < suelo_y1 + alto_pies)
+ sitio_y = suelo_y1 + alto_pies;
+ if (sitio_y > suelo_y2)
+ sitio_y = suelo_y2;
+
+ empieza_andar();
+ }
+ rompo = 0;
+ }
+
+ return false;
+}
+
+void DrasculaEngine::comprueba2() {
+ int l;
+
+ if (menu_scr == 1)
+ coge_objeto();
+ else {
+ if (!strcmp(texto_nombre, "hacker") && hay_nombre == 1)
+ banderas(50);
+ else
+ 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) {
+ sentido_final = sentidobj[l];
+ anda_a_objeto = 1;
+ lleva_al_hare(sitiobj_x[l], sitiobj_y[l]);
+ banderas(num_obj[l]);
+ }
+ }
+ }
+}
+
+Common::KeyCode DrasculaEngine::getscan() {
+ update_events();
+
+ return _keyPressed.keycode;
+}
+
+void DrasculaEngine::update_events() {
+ Common::Event event;
+ Common::EventManager *eventMan = _system->getEventManager();
+
+ AudioCD.updateCD();
+
+ while (eventMan->pollEvent(event)) {
+ switch (event.type) {
+ case Common::EVENT_KEYDOWN:
+ _keyPressed = event.kbd;
+ break;
+ case Common::EVENT_KEYUP:
+ _keyPressed.keycode = Common::KEYCODE_INVALID;
+ break;
+ case Common::EVENT_MOUSEMOVE:
+ x_raton = event.mouse.x;
+ y_raton = event.mouse.y;
+ break;
+ case Common::EVENT_LBUTTONDOWN:
+ boton_izq = 1;
+ break;
+ case Common::EVENT_LBUTTONUP:
+ boton_izq = 0;
+ break;
+ case Common::EVENT_RBUTTONDOWN:
+ boton_dch = 1;
+ break;
+ case Common::EVENT_RBUTTONUP:
+ boton_dch = 0;
+ break;
+ case Common::EVENT_QUIT:
+ // TODO
+ salir_al_dos(0);
+ exit(0);
+ break;
+ default:
+ break;
+ }
+ }
+}
+
+void DrasculaEngine::elige_verbo(int verbo) {
+ int c = 171;
+
+ if (menu_scr == 1)
+ c = 0;
+ if (lleva_objeto == 1)
+ suma_objeto(objeto_que_lleva);
+
+ DIBUJA_FONDO(ANCHOBJ * verbo, c, 0, 0, ANCHOBJ, ALTOBJ, dir_hare_fondo, dir_dibujo3);
+
+ lleva_objeto = 1;
+ objeto_que_lleva = verbo;
+}
+
+void DrasculaEngine::mesa() {
+ int nivel_master, nivel_voc, nivel_cd;
+
+ DIBUJA_BLOQUE(1, 56, 73, 63, 177, 97, dir_mesa, dir_zona_pantalla);
+ VUELCA_PANTALLA(73, 63, 73, 63, 177, 97, dir_zona_pantalla);
+
+ for (;;) {
+ nivel_master = 72 + 61 - ((_mixer->getVolumeForSoundType(Audio::Mixer::kPlainSoundType) / 16) * 4);
+ nivel_voc = 72 + 61 - ((_mixer->getVolumeForSoundType(Audio::Mixer::kSFXSoundType) / 16) * 4);
+ nivel_cd = 72 + 61 - ((_mixer->getVolumeForSoundType(Audio::Mixer::kMusicSoundType) / 16) * 4);
+
+ refresca_pantalla();
+
+ DIBUJA_BLOQUE(1, 56, 73, 63, 177, 97, dir_mesa, dir_zona_pantalla);
+
+ DIBUJA_FONDO(183, 56, 82, nivel_master, 39, 2 + ((_mixer->getVolumeForSoundType(Audio::Mixer::kPlainSoundType) / 16) * 4), dir_mesa, dir_zona_pantalla);
+ DIBUJA_FONDO(183, 56, 138, nivel_voc, 39, 2 + ((_mixer->getVolumeForSoundType(Audio::Mixer::kSFXSoundType) / 16) * 4), dir_mesa, dir_zona_pantalla);
+ DIBUJA_FONDO(183, 56, 194, nivel_cd, 39, 2 + ((_mixer->getVolumeForSoundType(Audio::Mixer::kMusicSoundType) / 16) * 4), dir_mesa, dir_zona_pantalla);
+
+ cursor_mesa();
+
+ VUELCA_PANTALLA(0, 0, 0, 0, 320, 200, dir_zona_pantalla);
+
+ MirarRaton();
+
+ if (boton_dch == 1)
+ break;
+ if (boton_izq == 1) {
+ if (x_raton > 80 && x_raton < 121) {
+ int vol = _mixer->getVolumeForSoundType(Audio::Mixer::kPlainSoundType) / 16;
+ if (y_raton < nivel_master && vol < 15)
+ vol++;
+ if (y_raton > nivel_master && vol > 0)
+ vol--;
+ _mixer->setVolumeForSoundType(Audio::Mixer::kPlainSoundType, vol * 16);
+ }
+
+ if (x_raton > 136 && x_raton < 178) {
+ int vol = _mixer->getVolumeForSoundType(Audio::Mixer::kSFXSoundType) / 16;
+ if (y_raton < nivel_voc && vol < 15)
+ vol++;
+ if (y_raton > nivel_voc && vol > 0)
+ vol--;
+ _mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, vol * 16);
+ }
+
+ if (x_raton > 192 && x_raton < 233) {
+ int vol = _mixer->getVolumeForSoundType(Audio::Mixer::kMusicSoundType) / 16;
+ if (y_raton < nivel_cd && vol < 15)
+ vol++;
+ if (y_raton > nivel_cd && vol > 0)
+ vol--;
+ _mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, vol * 16);
+ }
+ }
+
+ }
+
+ espera_soltar();
+}
+
+void DrasculaEngine::saves() {
+ char nombres[10][23];
+ char fichero[13];
+ int n, n2, num_sav, y = 27;
+ Common::InSaveFile *sav;
+
+ borra_pantalla();
+
+ if (!(sav = _saveFileMan->openForLoading("saves.epa"))) {
+ error("Can't open saves.epa file.");
+ }
+ for (n = 0; n < NUM_SAVES; n++)
+ sav->read(nombres[n], 23);
+ delete sav;
+
+ lee_dibujos("savescr.alg");
+ descomprime_dibujo(dir_dibujo1, MEDIA);
+
+ color_abc(VERDE_CLARO);
+
+ for (;;) {
+ y = 27;
+ DIBUJA_FONDO(0, 0, 0, 0, 320, 200, dir_dibujo1, dir_zona_pantalla);
+ for (n = 0; n < NUM_SAVES; n++) {
+ print_abc(nombres[n], 116, y);
+ y = y + 9;
+ }
+ print_abc(select, 117, 15);
+ cursor_mesa();
+ VUELCA_PANTALLA(0, 0, 0, 0, 320, 200, dir_zona_pantalla);
+ y = 27;
+
+ MirarRaton();
+
+ if (boton_izq == 1) {
+ 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]);
+
+ if (strcmp(select, "*"))
+ hay_seleccion = 1;
+ else {
+ introduce_nombre();
+ strcpy(nombres[n], select);
+ if (hay_seleccion == 1) {
+ if (n == 0)
+ strcpy(fichero, "gsave01");
+ if (n == 1)
+ strcpy(fichero, "gsave02");
+ if (n == 2)
+ strcpy(fichero, "gsave03");
+ if (n == 3)
+ strcpy(fichero, "gsave04");
+ if (n == 4)
+ strcpy(fichero, "gsave05");
+ if (n == 5)
+ strcpy(fichero, "gsave06");
+ if (n == 6)
+ strcpy(fichero, "gsave07");
+ if (n == 7)
+ strcpy(fichero, "gsave08");
+ if (n == 8)
+ strcpy(fichero, "gsave09");
+ if (n == 9)
+ strcpy(fichero, "gsave10");
+ para_grabar(fichero);
+ Common::OutSaveFile *tsav;
+ if (!(tsav = _saveFileMan->openForSaving("saves.epa"))) {
+ error("Can't open saves.epa file.");
+ }
+ for (n = 0; n < NUM_SAVES; n++)
+ tsav->write(nombres[n], 23);
+ tsav->finalize();
+ delete tsav;
+ }
+ }
+
+ print_abc(select, 117, 15);
+ y = 27;
+ for (n2 = 0; n2 < NUM_SAVES; n2++) {
+ print_abc(nombres[n2], 116, y);
+ y = y + 9;
+ }
+ if (hay_seleccion == 1) {
+ if (n == 0)
+ strcpy(fichero, "gsave01");
+ if (n == 1)
+ strcpy(fichero, "gsave02");
+ if (n == 2)
+ strcpy(fichero, "gsave03");
+ if (n == 3)
+ strcpy(fichero, "gsave04");
+ if (n == 4)
+ strcpy(fichero, "gsave05");
+ if (n == 5)
+ strcpy(fichero, "gsave06");
+ if (n == 6)
+ strcpy(fichero, "gsave07");
+ if (n == 7)
+ strcpy(fichero, "gsave08");
+ if (n == 8)
+ strcpy(fichero, "gsave09");
+ if (n == 9)
+ strcpy(fichero, "gsave10");}
+ num_sav = n;
+ }
+ }
+
+ if (x_raton > 117 && y_raton > 15 && x_raton < 295 && y_raton < 24 && hay_seleccion == 1) {
+ introduce_nombre();
+ strcpy(nombres[num_sav], select);
+ print_abc(select, 117, 15);
+ y = 27;
+ for (n2 = 0; n2 < NUM_SAVES; n2++) {
+ print_abc(nombres[n2], 116, y);
+ y = y + 9;
+ }
+ }
+
+ if (x_raton > 125 && y_raton > 123 && x_raton < 199 && y_raton < 149 && hay_seleccion == 1) {
+ para_cargar(fichero);
+ break;
+ } else if (x_raton > 208 && y_raton > 123 && x_raton < 282 && y_raton < 149 && hay_seleccion == 1) {
+ para_grabar(fichero);
+ Common::OutSaveFile *tsav;
+ if (!(tsav = _saveFileMan->openForSaving("saves.epa"))) {
+ error("Can't open saves.epa file.");
+ }
+ for (n = 0; n < NUM_SAVES; n++)
+ tsav->write(nombres[n], 23);
+ tsav->finalize();
+ delete tsav;
+ } 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);
+ }
+ VUELCA_PANTALLA(0, 0, 0, 0, 320, 200, dir_zona_pantalla);
+ delay(400);
+ }
+ y = 26;
+ }
+
+ borra_pantalla();
+ lee_dibujos(num_room);
+ descomprime_dibujo(dir_dibujo1, MEDIA);
+ buffer_teclado();
+ hay_seleccion = 0;
+}
+
+void DrasculaEngine::print_abc(const char *dicho, int x_pantalla, int y_pantalla) {
+ int pos_texto[8];
+ int y_de_letra = 0, x_de_letra = 0, h, longitud;
+ longitud = strlen(dicho);
+
+ for (h = 0; h < longitud; h++) {
+ y_de_letra = Y_ABC;
+ char c = toupper(dicho[h]);
+ if (c == 'A')
+ x_de_letra = X_A;
+ else if (c == 'B')
+ x_de_letra = X_B;
+ else if (c == 'C')
+ x_de_letra = X_C;
+ else if (c == 'D')
+ x_de_letra = X_D;
+ else if (c == 'E')
+ x_de_letra = X_E;
+ else if (c == 'F')
+ x_de_letra = X_F;
+ else if (c == 'G')
+ x_de_letra = X_G;
+ else if (c == 'H')
+ x_de_letra = X_H;
+ else if (c == 'I')
+ x_de_letra = X_I;
+ else if (c == 'J')
+ x_de_letra = X_J;
+ else if (c == 'K')
+ x_de_letra = X_K;
+ else if (c == 'L')
+ x_de_letra = X_L;
+ else if (c == 'M')
+ x_de_letra = X_M;
+ else if (c == 'N')
+ x_de_letra = X_N;
+//TODO else if (c == '¥')
+// x_de_letra = X_GN;
+ else if (c == '¤')
+ x_de_letra = X_GN;
+ else if (c == 'O')
+ x_de_letra = X_O;
+ else if (c == 'P')
+ x_de_letra = X_P;
+ else if (c == 'Q')
+ x_de_letra = X_Q;
+ else if (c == 'R')
+ x_de_letra = X_R;
+ else if (c == 'S')
+ x_de_letra = X_S;
+ else if (c == 'T')
+ x_de_letra = X_T;
+ else if (c == 'U')
+ x_de_letra = X_U;
+ else if (c == 'V')
+ x_de_letra = X_V;
+ else if (c == 'W')
+ x_de_letra = X_W;
+ else if (c == 'X')
+ x_de_letra = X_X;
+ else if (c == 'Y')
+ x_de_letra = X_Y;
+ else if (c == 'Z')
+ x_de_letra = X_Z;
+ else if (/*c == 0xa7 ||*/ c == ' ')
+ x_de_letra = ESPACIO;
+ else {
+ y_de_letra = Y_SIGNOS;
+ if (c == '.')
+ x_de_letra = X_PUNTO;
+ else if (c == ',')
+ x_de_letra = X_COMA;
+ else if (c == '-')
+ x_de_letra = X_GUION;
+ else if (c == '?')
+ x_de_letra = X_CIERRA_INTERROGACION;
+//TODO else if (c == '¨')
+// x_de_letra = X_ABRE_INTERROGACION;
+ else if (c == '"')
+ x_de_letra = X_COMILLAS;
+ else if (c == '!')
+ x_de_letra = X_CIERRA_EXCLAMACION;
+//TODO else if (c == '­')
+// x_de_letra = X_ABRE_EXCLAMACION;
+ else if (c == ';')
+ x_de_letra = X_PUNTO_Y_COMA;
+ else if (c == '>')
+ x_de_letra = X_MAYOR_QUE;
+ else if (c == '<')
+ x_de_letra = X_MENOR_QUE;
+ else if (c == '$')
+ x_de_letra = X_DOLAR;
+ else if (c == '%')
+ x_de_letra = X_POR_CIENTO;
+ else if (c == ':')
+ x_de_letra = X_DOS_PUNTOS;
+ else if (c == '&')
+ x_de_letra = X_AND;
+ else if (c == '/')
+ x_de_letra = X_BARRA;
+ else if (c == '(')
+ x_de_letra = X_ABRE_PARENTESIS;
+ else if (c == ')')
+ x_de_letra = X_CIERRA_PARENTESIS;
+ else if (c == '*')
+ x_de_letra = X_ASTERISCO;
+ else if (c == '+')
+ x_de_letra = X_MAS;
+ else if (c == '1')
+ x_de_letra = X_N1;
+ else if (c == '2')
+ x_de_letra = X_N2;
+ else if (c == '3')
+ x_de_letra = X_N3;
+ else if (c == '4')
+ x_de_letra = X_N4;
+ else if (c == '5')
+ x_de_letra = X_N5;
+ else if (c == '6')
+ x_de_letra = X_N6;
+ else if (c == '7')
+ x_de_letra = X_N7;
+ else if (c == '8')
+ x_de_letra = X_N8;
+ else if (c == '9')
+ x_de_letra = X_N9;
+ else if (c == '0')
+ x_de_letra = X_N0;
+ else
+ y_de_letra = Y_ACENTOS;
+/*
+ if (c == ' ')
+ x_de_letra = X_A;
+ else if (c == '‚')
+ x_de_letra = X_B;
+ else if (c == '¡')
+ x_de_letra = X_C;
+ else if (c == '¢')
+ x_de_letra = X_D;
+ else if (c == '£')
+ x_de_letra = X_E;
+ else if (c == '…')
+ x_de_letra = X_F;
+ else if (c == 'Š')
+ x_de_letra = X_G;
+ else if (c == '')
+ x_de_letra = X_H;
+ else if (c == '•')
+ x_de_letra = X_I;
+ else if (c == '—')
+ x_de_letra = X_J;
+ else if (c == 'ƒ')
+ x_de_letra = X_K;
+ else if (c == 'ˆ')
+ x_de_letra = X_L;
+ else if (c == 'Œ')
+ x_de_letra = X_M;
+ else if (c == '“')
+ x_de_letra = X_N;
+ else if (c == '–')
+ x_de_letra = X_GN;
+ else if (c == '\'')
+ x_de_letra = X_O;
+ else if (c == '€')
+ x_de_letra = X_P;
+ else if (c == '‡')
+ x_de_letra = X_P;
+ else if (c == 'µ')
+ x_de_letra = X_A;
+ else if (c == '')
+ x_de_letra = X_B;
+ else if (c == 'Ö')
+ x_de_letra = X_C;
+ else if (c == 'à')
+ x_de_letra = X_D;
+ else if (c == 'é')
+ x_de_letra = X_E;
+ else if (c == '·')
+ x_de_letra = X_F;
+ else if (c == 'Ô')
+ x_de_letra = X_G;
+ else if (c == 'Þ')
+ x_de_letra = X_H;
+ else if (c == 'ã')
+ x_de_letra = X_I;
+ else if (c == 'ë')
+ x_de_letra = X_J;
+ else if (c == '¶')
+ x_de_letra = X_K;
+ else if (c == 'Ò')
+ x_de_letra = X_L;
+ else if (c == '×')
+ x_de_letra = X_M;
+ else if (c == 'â')
+ x_de_letra = X_N;
+ else if (c == 'ê')
+ x_de_letra = X_GN;
+*/ }
+
+ pos_texto[0] = x_de_letra;
+ pos_texto[1] = y_de_letra;
+ pos_texto[2] = x_pantalla;
+ pos_texto[3] = y_pantalla;
+ pos_texto[4] = ANCHO_LETRAS;
+ pos_texto[5] = ALTO_LETRAS;
+
+ DIBUJA_BLOQUE_CUT(pos_texto, dir_texto, dir_zona_pantalla);
+
+ x_pantalla = x_pantalla + ANCHO_LETRAS;
+ if (x_pantalla > 317) {
+ x_pantalla = 0;
+ y_pantalla = y_pantalla + ALTO_LETRAS + 2;
+ }
+ }
+}
+
+void DrasculaEngine::delay(int ms) {
+ _system->delayMillis(ms * 2); // originaly was 1
+}
+
+void DrasculaEngine::confirma_go() {
+ byte key;
+
+ color_abc(ROJO);
+ refresca_pantalla();
+ centra_texto(SYS0, 160, 87);
+ VUELCA_PANTALLA(0, 0, 0, 0, 320, 200, dir_zona_pantalla);
+
+ for (;;) {
+ key = getscan();
+ if (key != 0)
+ break;
+ }
+
+ if (key == Common::KEYCODE_DELETE) {
+ stopmusic();
+ carga_partida("gsave00");
+ }
+}
+
+void DrasculaEngine::confirma_salir() {
+ byte key;
+
+ color_abc(ROJO);
+ refresca_pantalla();
+ centra_texto(SYS1, 160, 87);
+ VUELCA_PANTALLA(0, 0, 0, 0, 320, 200, dir_zona_pantalla);
+
+ for (;;) {
+ key = getscan();
+ if (key != 0)
+ break;
+ }
+
+ if (key == Common::KEYCODE_ESCAPE) {
+ stopmusic();
+ salir_al_dos(0);
+ }
+}
+
+void DrasculaEngine::salva_pantallas() {
+ int xr, yr;
+
+ borra_pantalla();
+
+ lee_dibujos("sv.alg");
+ descomprime_dibujo(dir_dibujo1, MEDIA);
+ //TODO inicio_ghost();
+ //TODO carga_ghost();
+
+ MirarRaton();
+ xr = x_raton;
+ yr = y_raton;
+
+ for (;;) {
+ //TODO efecto(dir_dibujo1);
+ MirarRaton();
+ if (boton_dch == 1 || boton_izq == 1)
+ break;
+ if (x_raton != xr)
+ break;
+ if (y_raton != yr)
+ break;
+ }
+ //TODO fin_ghost();
+ lee_dibujos(num_room);
+ descomprime_dibujo(dir_dibujo1, MEDIA);
+}
+
+void DrasculaEngine::fliplay(const char *filefli, int vel) {
+ OpenSSN(filefli, vel);
+ while (PlayFrameSSN() && (!term_int)) {
+ if (getscan() == Common::KEYCODE_ESCAPE)
+ term_int = 1;
+ }
+ EndSSN();
+}
+
+void DrasculaEngine::FundeDelNegro(int VelocidadDeFundido) {
+ char fundido;
+ unsigned int color, componente;
+
+ DacPalette256 palFundido;
+
+ for (fundido = 0; fundido < 64; fundido++) {
+ for (color = 0; color < 256; color++) {
+ for (componente = 0; componente < 3; componente++) {
+ palFundido[color][componente] = LimitaVGA(palJuego[color][componente] - 63 + fundido);
+ }
+ }
+ pausa(VelocidadDeFundido);
+
+ setvgapalette256((byte *)&palFundido);
+ }
+}
+
+void DrasculaEngine::color_abc(int cl) {
+ _color = cl;
+
+ if (cl == 0) {
+ palJuego[254][0] = 0;
+ palJuego[254][1] = 0;
+ palJuego[254][2] = 0;
+ } else if (cl == 1) {
+ palJuego[254][0] = 0x10;
+ palJuego[254][1] = 0x3E;
+ palJuego[254][2] = 0x28;
+ } else if (cl == 3) {
+ palJuego[254][0] = 0x16;
+ palJuego[254][1] = 0x3F;
+ palJuego[254][2] = 0x16;
+ } else if (cl == 4) {
+ palJuego[254][0] = 0x9;
+ palJuego[254][1] = 0x3F;
+ palJuego[254][2] = 0x12;
+ } else if (cl == 5) {
+ palJuego[254][0] = 0x3F;
+ palJuego[254][1] = 0x3F;
+ palJuego[254][2] = 0x15;
+ } else if (cl == 7) {
+ palJuego[254][0] = 0x38;
+ palJuego[254][1] = 0;
+ palJuego[254][2] = 0;
+ } else if (cl == 8) {
+ palJuego[254][0] = 0x3F;
+ palJuego[254][1] = 0x27;
+ palJuego[254][2] = 0x0B;
+ } else if (cl == 9) {
+ palJuego[254][0] = 0x2A;
+ palJuego[254][1] = 0;
+ palJuego[254][2] = 0x2A;
+ } else if (cl == 10) {
+ palJuego[254][0] = 0x30;
+ palJuego[254][1] = 0x30;
+ palJuego[254][2] = 0x30;
+ } else if (cl == 11) {
+ palJuego[254][0] = 98;
+ palJuego[254][1] = 91;
+ palJuego[254][2] = 100;
+ };
+
+ setvgapalette256((byte *)&palJuego);
+}
+
+char DrasculaEngine::LimitaVGA(char valor) {
+ return (valor & 0x3F) * (valor > 0);
+}
+
+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];
+ int h, fil, x_texto3, x_texto2, x_texto1, conta_f = 0, ya = 0;
+
+ strcpy(m1, " ");
+ strcpy(m2, " ");
+ strcpy(m3, " ");
+ strcpy(bb, " ");
+
+ for (h = 0; h < 10; h++)
+ strcpy(mb[h], " ");
+
+ if (x_texto > 160)
+ ya = 1;
+
+ strcpy(m1, mensaje);
+ if (x_texto < 60)
+ x_texto = 60;
+ if (x_texto > 255)
+ x_texto = 255;
+
+ x_texto1 = x_texto;
+
+ if (ya == 1)
+ x_texto1 = 315 - x_texto;
+
+ x_texto2 = (strlen(m1) / 2) * ANCHO_LETRAS;
+
+tut:
+ strcpy(bb, m1);
+ scumm_strrev(bb);
+
+ if (x_texto1 < x_texto2) {
+ strcpy(m3, strrchr(m1, ' '));
+ strcpy(m1, strstr(bb, " "));
+ scumm_strrev(m1);
+ m1[strlen(m1) - 1] = '\0';
+ strcat(m3, m2);
+ strcpy(m2, m3);
+ };
+
+ x_texto2 = (strlen(m1) / 2) * ANCHO_LETRAS;
+ if (x_texto1 < x_texto2)
+ goto tut;
+ strcpy(mb[conta_f], m1);
+
+ if (!strcmp(m2, ""))
+ goto imprimir;
+ scumm_strrev(m2);
+ m2[strlen(m2) - 1] = '\0';
+ scumm_strrev(m2);
+ strcpy(m1, m2);
+ strcpy(m2, "");
+ conta_f++;
+
+ goto tut;
+
+imprimir:
+
+ fil = y_texto - (((conta_f + 3) * ALTO_LETRAS));
+
+ for (h = 0; h < conta_f + 1; h++) {
+ x_texto3 = strlen(mb[h]) / 2;
+ print_abc(mb[h], ((x_texto) - x_texto3 * ANCHO_LETRAS) - 1, fil);
+ fil = fil + ALTO_LETRAS + 2;
+ }
+}
+
+void DrasculaEngine::comienza_sound(const char *fichero) {
+ if (hay_sb == 1) {
+ sku = new Common::File;
+ sku->open(fichero);
+ if (!sku->isOpen()) {
+ error("no puedo abrir archivo de voz");
+ }
+ }
+ ctvd_init(2);
+ ctvd_speaker(1);
+ ctvd_output(sku);
+}
+
+void DrasculaEngine::anima(const char *animacion, int FPS) {
+ Common::File FileIn;
+ unsigned j;
+ int NFrames = 1;
+ int cnt = 2;
+
+ AuxBuffLast = (byte *)malloc(65000);
+ AuxBuffDes = (byte *)malloc(65000);
+
+ FileIn.open(animacion);
+
+ if (!FileIn.isOpen()) {
+ error("No encuentro un fichero de animacion.");
+ }
+
+ FileIn.read(&NFrames, sizeof(NFrames));
+ FileIn.read(&Leng, sizeof(Leng));
+ AuxBuffOrg = (byte *)malloc(Leng);
+ FileIn.read(AuxBuffOrg, Leng);
+ FileIn.read(cPal, 768);
+ carga_pcx(AuxBuffOrg);
+ free(AuxBuffOrg);
+ memcpy(VGA, AuxBuffDes, 64000);
+ _system->copyRectToScreen((const byte *)VGA, 320, 0, 0, 320, 200);
+ _system->updateScreen();
+ set_dac(cPal);
+ memcpy(AuxBuffLast, AuxBuffDes, 64000);
+ WaitForNext(FPS);
+ while (cnt < NFrames) {
+ FileIn.read(&Leng, sizeof(Leng));
+ AuxBuffOrg = (byte *)malloc(Leng);
+ FileIn.read(AuxBuffOrg, Leng);
+ FileIn.read(cPal, 768);
+ carga_pcx(AuxBuffOrg);
+ free(AuxBuffOrg);
+ for (j = 0;j < 64000; j++) {
+ VGA[j] = AuxBuffLast[j] = AuxBuffDes[j] ^ AuxBuffLast[j];
+ }
+ _system->copyRectToScreen((const byte *)VGA, 320, 0, 0, 320, 200);
+ _system->updateScreen();
+ WaitForNext(FPS);
+ cnt++;
+ byte key = getscan();
+ if (key == Common::KEYCODE_ESCAPE)
+ term_int = 1;
+ if (key != 0)
+ break;
+ }
+ free(AuxBuffLast);
+ free(AuxBuffDes);
+ FileIn.close();
+}
+
+void DrasculaEngine::animafin_sound_corte() {
+ if (hay_sb == 1) {
+ ctvd_stop();
+ delete sku;
+ ctvd_terminate();
+ }
+}
+
+void DrasculaEngine::FundeAlNegro(int VelocidadDeFundido) {
+ char fundido;
+ unsigned int color, componente;
+
+ DacPalette256 palFundido;
+
+ for (fundido = 63; fundido >= 0; fundido--) {
+ for (color = 0; color < 256; color++) {
+ for (componente = 0; componente < 3; componente++) {
+ palFundido[color][componente] = LimitaVGA(palJuego[color][componente] - 63 + fundido);
+ }
+ }
+ pausa(VelocidadDeFundido);
+
+ setvgapalette256((byte *)&palFundido);
+ }
+}
+
+void DrasculaEngine::pausa(int cuanto) {
+ _system->delayMillis(cuanto * 30); // was originaly 2
+}
+
+void DrasculaEngine::habla_dr_grande(const char *dicho, const char *filename) {
+ int tiempou;
+ long tiempol;
+ int x_habla[4] = {47, 93, 139, 185};
+ int cara;
+ int l = 0;
+
+ int longitud;
+ longitud = strlen(dicho);
+
+ tiempol = _system->getMillis();
+ tiempou = (unsigned int)tiempol / 2;
+ _rnd->setSeed(tiempou);
+
+ buffer_teclado();
+
+ 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(3);
+ DIBUJA_FONDO(0, 0, 0, 0, 320, 200, dir_dibujo1, dir_zona_pantalla);
+ DIBUJA_FONDO(interf_x[l] + 24, interf_y[l], 0, 45, 39, 31, dir_dibujo2, dir_zona_pantalla);
+ DIBUJA_FONDO(x_habla[cara], 1, 171, 68, 45, 48, dir_dibujo2, dir_zona_pantalla);
+ l++;
+ if (l == 7)
+ l = 0;
+
+ if (con_voces == 0)
+ centra_texto(dicho, 191, 69);
+
+ VUELCA_PANTALLA(0, 0, 0, 0, 320, 200, dir_zona_pantalla);
+
+ pausa(3);
+
+ byte key = getscan();
+ if (key == Common::KEYCODE_ESCAPE)
+ term_int = 1;
+
+ 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;
+ }
+}
+
+void DrasculaEngine::pon_igor() {
+ int pos_igor[6];
+
+ pos_igor[0] = 1;
+ 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;
+ pos_igor[5] = 61;
+
+ DIBUJA_BLOQUE_CUT(pos_igor, dir_hare_frente, dir_zona_pantalla);
+}
+
+void DrasculaEngine::pon_dr() {
+ int pos_dr[6];
+
+ if (sentido_dr == 1)
+ pos_dr[0] = 47;
+ else if (sentido_dr == 0)
+ pos_dr[0] = 1;
+ else if (sentido_dr == 3)
+ pos_dr[0] = 93;
+ pos_dr[1] = 122;
+ pos_dr[2] = x_dr;
+ pos_dr[3] = y_dr;
+ pos_dr[4] = 45;
+ pos_dr[5] = 77;
+
+ DIBUJA_BLOQUE_CUT(pos_dr, dir_hare_fondo, dir_zona_pantalla);
+}
+
+void DrasculaEngine::pon_bj() {
+ int pos_bj[6];
+
+ if (sentido_bj == 3)
+ pos_bj[0] = 10;
+ else if (sentido_bj == 0)
+ pos_bj[0] = 37;
+ pos_bj[1] = 99;
+ pos_bj[2] = x_bj;
+ pos_bj[3] = y_bj;
+ pos_bj[4] = 26;
+ pos_bj[5] = 76;
+
+ DIBUJA_BLOQUE_CUT(pos_bj, dir_dibujo3, dir_zona_pantalla);
+}
+
+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 cara;
+
+ int longitud;
+ longitud = strlen(dicho);
+
+ tiempol = time (NULL);
+ 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();
+
+ pon_igor();
+ pon_dr();
+ 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);
+
+ 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);
+
+ pausa(3);
+
+ byte key = getscan();
+ if (key == Common::KEYCODE_ESCAPE)
+ term_int = 1;
+ 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);
+ pon_igor();
+ pon_dr();
+ VUELCA_PANTALLA(0, 0, 0, 0, 320, 200, dir_zona_pantalla);
+}
+
+void DrasculaEngine::habla_dr_izq(const char *dicho, const char *filename) {
+ int tiempou;
+ long tiempol;
+
+ int x_habla[8] = { 1, 40, 79, 118, 157, 196, 235, 274 };
+ int cara;
+
+ int longitud;
+ longitud = strlen(dicho);
+
+ tiempol = _system->getMillis();
+ tiempou = (unsigned int)tiempol / 2;
+ _rnd->setSeed(tiempou);
+
+ buffer_teclado();
+
+ 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(7);
+
+ DIBUJA_FONDO(0, 0, 0, 0, 320, 200, dir_dibujo1, dir_zona_pantalla);
+
+ actualiza_refresco_antes();
+
+ pon_igor();
+ 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);
+
+ actualiza_refresco();
+
+ if (con_voces == 0)
+ centra_texto(dicho, x_dr + 19, y_dr);
+
+ VUELCA_PANTALLA(0, 0, 0, 0, 320, 200, dir_zona_pantalla);
+
+ pausa(3);
+
+ byte key = getscan();
+ if (key == Common::KEYCODE_ESCAPE)
+ term_int = 1;
+ 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);
+ pon_igor();
+ pon_dr();
+ VUELCA_PANTALLA(0, 0, 0, 0, 320, 200, dir_zona_pantalla);
+}
+
+void DrasculaEngine::habla_dr_dch(const char *dicho, const char *filename) {
+ int tiempou;
+ long tiempol;
+
+ int x_habla[8] = { 1, 40, 79, 118, 157, 196, 235, 274 };
+ int cara;
+
+ int longitud;
+ longitud = strlen(dicho);
+
+ tiempol = _system->getMillis();
+ tiempou = (unsigned int)tiempol / 2;
+ _rnd->setSeed(tiempou);
+
+ buffer_teclado();
+
+ 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(7);
+
+ DIBUJA_FONDO(0, 0, 0, 0, 320, 200, dir_dibujo1, dir_zona_pantalla);
+ actualiza_refresco_antes();
+
+ pon_igor();
+ 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);
+
+ actualiza_refresco();
+
+ if (con_voces == 0)
+ centra_texto(dicho, x_dr + 19, y_dr);
+
+ VUELCA_PANTALLA(0, 0, 0, 0, 320, 200, dir_zona_pantalla);
+
+ pausa(3);
+
+ byte key = getscan();
+ if (key == Common::KEYCODE_ESCAPE)
+ term_int = 1;
+ 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);
+ pon_igor();
+ pon_dr();
+ VUELCA_PANTALLA(0, 0, 0, 0, 320, 200, dir_zona_pantalla);
+}
+
+void DrasculaEngine::habla_solo(const char *dicho, const char *filename) {
+ int tiempou;
+ long tiempol;
+
+ int longitud;
+ longitud = strlen(dicho);
+
+ tiempol = _system->getMillis();
+ tiempou = (unsigned int)tiempol / 2;
+ _rnd->setSeed(tiempou);
+
+ color_abc(color_solo);
+
+ 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:
+
+ if (con_voces == 0)
+ centra_texto(dicho, 156, 90);
+ VUELCA_PANTALLA(0, 0, 0, 0, 320, 200, dir_zona_pantalla);
+
+ byte key = getscan();
+ if (key == Common::KEYCODE_ESCAPE)
+ term_int = 1;
+ 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;
+ }
+}
+
+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 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();
+
+ 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);
+
+ 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);
+
+ pausa(3);
+
+ byte key = getscan();
+ if (key == Common::KEYCODE_ESCAPE)
+ term_int = 1;
+ 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);
+ pon_igor();
+ pon_dr();
+ VUELCA_PANTALLA(0, 0, 0, 0, 320, 200, dir_zona_pantalla);
+}
+
+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 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:
+
+ if (music_status() == 0)
+ playmusic(musica_room);
+
+ 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], 2, 121, 44, 21, 24, dir_hare_dch, 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);
+
+ byte 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::hipo(int contador) {
+ int y = 0, sentido = 0;
+
+ contador = contador;
+
+comienza:
+ contador--;
+
+ refresca_pantalla();
+ VUELCA_PANTALLA(0, 1, 0, y, 320, 198, dir_zona_pantalla);
+
+ if (sentido == 0)
+ y++;
+ else
+ y--;
+ if (y == 2)
+ sentido = 1;
+ if (y == 0)
+ sentido = 0;
+ if (contador > 0)
+ goto comienza;
+
+ refresca_pantalla();
+ VUELCA_PANTALLA(0, 0, 0, 0, 320, 200, dir_zona_pantalla);
+}
+
+void DrasculaEngine::fin_sound() {
+ delay(1);
+
+ if (hay_sb == 1) {
+ while (LookForFree() != 0);
+ delete sku;
+ }
+}
+
+void DrasculaEngine::habla_bj(const char *dicho, const char *filename) {
+ int tiempou;
+ long tiempol;
+
+ int x_habla[5] = { 64, 92, 120, 148, 176};
+ 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(x_bj + 2, y_bj - 1, x_bj + 2, y_bj - 1, 27, 40,
+ dir_dibujo1, dir_zona_pantalla);
+
+ DIBUJA_BLOQUE(x_habla[cara], 99, x_bj + 2, y_bj - 1, 27, 40,
+ dir_dibujo3, dir_zona_pantalla);
+ pon_hare();
+ actualiza_refresco();
+
+ if (con_voces == 0)
+ centra_texto(dicho, x_bj + 7, y_bj);
+
+ VUELCA_PANTALLA(0, 0, 0, 0, 320, 200, dir_zona_pantalla);
+
+ pausa(3);
+
+ byte key = getscan();
+ if (key == Common::KEYCODE_ESCAPE)
+ term_int = 1;
+ 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::hablar(const char *dicho, const char *filename) {
+ int tiempou;
+ long tiempol;
+
+ int suma_1_pixel = 1;
+
+ int y_mask_habla = 170;
+ int x_habla_dch[6] = { 1, 25, 49, 73, 97, 121 };
+ int x_habla_izq[6] = { 145, 169, 193, 217, 241, 265 };
+ int cara;
+
+ int longitud;
+ longitud = strlen(dicho);
+
+ tiempol = _system->getMillis();
+ tiempou = (unsigned int)tiempol / 2;
+ _rnd->setSeed(tiempou);
+
+ if (factor_red[hare_y + alto_hare] == 100)
+ suma_1_pixel = 0;
+
+ if (num_ejec == 2)
+ 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(5);
+
+ DIBUJA_FONDO(0, 0, 0, 0, 320, 200, dir_dibujo1, dir_zona_pantalla);
+
+ 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);
+ else if (num_ejec == 2)
+ 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);
+ else if (num_ejec == 2)
+ DIBUJA_FONDO(ANCHOBJ + 1, 0, hare_x, hare_y,
+ ancho_hare, alto_habla - 1,
+ dir_dibujo3, dir_zona_pantalla);
+
+ 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,
+ 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,
+ 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],
+ 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,
+ dir_hare_dch, dir_zona_pantalla);
+ actualiza_refresco();
+ } else if (sentido_hare == 2) {
+ reduce_hare_chico(x_habla_izq[cara], y_mask_habla,
+ suma_1_pixel + hare_x + 12 * factor_red[hare_y + alto_hare] / 100,
+ hare_y, ancho_habla, alto_habla, factor_red[hare_y + alto_hare],
+ dir_hare_frente, dir_zona_pantalla);
+ actualiza_refresco();
+ } else if (sentido_hare == 3) {
+ reduce_hare_chico(x_habla_dch[cara], y_mask_habla,
+ suma_1_pixel + hare_x + 8 * factor_red[hare_y + alto_hare] / 100,
+ hare_y, ancho_habla,alto_habla, factor_red[hare_y + alto_hare],
+ dir_hare_frente, dir_zona_pantalla);
+ actualiza_refresco();
+ }
+
+ if (con_voces == 0)
+ centra_texto(dicho, hare_x, hare_y);
+
+ VUELCA_PANTALLA(0, 0, 0, 0, 320, 200, dir_zona_pantalla);
+
+ pausa(3);
+
+ byte key = getscan();
+ if (num_ejec == 1)
+ if (key == Common::KEYCODE_ESCAPE)
+ term_int = 1;
+ 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);
+
+ if (num_ejec == 1)
+ if (music_status() == 0 && flags[11] == 0 && corta_musica == 0)
+ playmusic(musica_room);
+}
+
+void DrasculaEngine::playmusic(int p) {
+ AudioCD.stop();
+ AudioCD.play(p - 1, 1, 0, 0);
+}
+
+void DrasculaEngine::stopmusic() {
+ AudioCD.stop();
+}
+
+int DrasculaEngine::music_status() {
+ return AudioCD.isPlaying();
+}
+
+void DrasculaEngine::refresca_pantalla() {
+ DIBUJA_FONDO(0, 0, 0, 0, 320, 200, dir_dibujo1, dir_zona_pantalla);
+ actualiza_refresco_antes();
+ pon_hare();
+ actualiza_refresco();
+}
+
+void DrasculaEngine::carga_partida(const char *nom_game) {
+ int l, n_ejec2;
+ Common::InSaveFile *sav;
+
+ canal_p(nom_game);
+ if (!(sav = _saveFileMan->openForLoading("nom_game"))) {
+ error("missing savegame file");
+ }
+
+ n_ejec2 = sav->readSint32LE();
+ if (n_ejec2 != num_ejec) {
+ canal_p(nom_game);
+ strcpy(nom_partida, nom_game);
+ error("TODO");
+ salir_al_dos(n_ejec2);
+ }
+ sav->read(datos_actuales, 20);
+ hare_x = sav->readSint32LE();
+ hare_y = sav->readSint32LE();
+ sentido_hare = sav->readSint32LE();
+
+ for (l = 1; l < 43; l++) {
+ objetos_que_tengo[l] = sav->readSint32LE();
+ }
+
+ for (l = 0; l < NUM_BANDERAS; l++) {
+ flags[l] = sav->readSint32LE();
+ }
+
+ lleva_objeto = sav->readSint32LE();
+ objeto_que_lleva = sav->readSint32LE();
+
+ canal_p(nom_game);
+}
+
+void DrasculaEngine::canal_p(const char *fich){
+ return;
+ // TODO
+
+ Common::File ald2, ald3;
+
+ char fich2[13];
+ char car;
+
+ strcpy(fich2, "top");
+
+ ald3.open(fich);
+ if (!ald3.isOpen()) {
+ error("no puedo abrir el archivo codificado");
+ }
+
+ ald2.open(fich2, Common::File::kFileWriteMode);
+ if (!ald2.isOpen()) {
+ error("no puedo abrir el archivo destino");
+ }
+
+ car = ald3.readByte();
+ while (!ald3.eos()) {
+ ald2.writeByte(codifica(car));
+ car = ald3.readByte();
+ }
+
+ ald2.close();
+ ald3.close();
+ remove(fich);
+ rename(fich2, fich);
+}
+
+void DrasculaEngine::puertas_cerradas (int l) {
+ if (num_ejec == 1)
+ 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;
+}
+
+void DrasculaEngine::color_hare() {
+ int color, componente;
+
+ for (color = 235; color < 253; color++) {
+ for (componente = 0; componente < 3; componente++) {
+ palJuego[color][componente] = palHare[color][componente];
+ }
+ }
+ ActualizaPaleta();
+}
+
+void DrasculaEngine::funde_hare(int oscuridad) {
+ char fundido;
+ unsigned int color, componente;
+
+ for (fundido = oscuridad; fundido >= 0; fundido--) {
+ for (color = 235; color < 253; color++) {
+ for (componente = 0; componente < 3; componente++)
+ palJuego[color][componente] = LimitaVGA(palJuego[color][componente] - 8 + fundido);
+ }
+ }
+
+ ActualizaPaleta();
+}
+
+void DrasculaEngine::paleta_hare_claro() {
+ int color, componente;
+
+ for (color = 235; color < 253; color++) {
+ for (componente = 0; componente < 3; componente++)
+ palHareClaro[color][componente] = palJuego[color][componente];
+ }
+}
+
+void DrasculaEngine::paleta_hare_oscuro() {
+ int color, componente;
+
+ for (color = 235; color < 253; color++) {
+ for (componente = 0; componente < 3; componente++)
+ palHareOscuro[color][componente] = palJuego[color][componente];
+ }
+}
+
+void DrasculaEngine::hare_claro() {
+ int color, componente;
+
+ for (color = 235; color < 253; color++) {
+ for (componente = 0; componente < 3; componente++)
+ palJuego[color][componente] = palHareClaro[color][componente];
+ }
+
+ ActualizaPaleta();
+}
+
+void DrasculaEngine::empieza_andar() {
+ hare_se_mueve = 1;
+
+ 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 ((sitio_x < hare_x) && (sitio_y <= (hare_y + alto_hare)))
+ cuadrante_1();
+ else if ((sitio_x < hare_x) && (sitio_y > (hare_y + alto_hare)))
+ cuadrante_3();
+ else if ((sitio_x > hare_x + ancho_hare) && (sitio_y <= (hare_y + alto_hare)))
+ cuadrante_2();
+ else if ((sitio_x > hare_x + ancho_hare) && (sitio_y > (hare_y + alto_hare)))
+ cuadrante_4();
+ else if (sitio_y < hare_y + alto_hare)
+ anda_parriba();
+ else if (sitio_y > hare_y + alto_hare)
+ anda_pabajo();
+ }
+ conta_vez = vez();
+}
+
+void DrasculaEngine::actualiza_refresco() {
+ if (!strcmp(num_room, "63.alg"))
+ refresca_63();
+ else if (!strcmp(num_room, "62.alg"))
+ refresca_62();
+ else if (!strcmp(num_room, "3.alg"))
+ refresca_3();
+ else if (!strcmp(num_room, "2.alg"))
+ refresca_2();
+ else if (!strcmp(num_room, "4.alg"))
+ refresca_4();
+ else if (!strcmp(num_room, "5.alg"))
+ refresca_5();
+ else if (!strcmp(num_room, "15.alg"))
+ refresca_15();
+ else if (!strcmp(num_room, "17.alg"))
+ refresca_17();
+ else if (!strcmp(num_room, "18.alg"))
+ refresca_18();
+ else if (!strcmp(num_room, "10.alg"))
+ mapa();
+}
+
+void DrasculaEngine::actualiza_refresco_antes() {
+ if (!strcmp(num_room, "62.alg"))
+ refresca_62_antes();
+ else if (!strcmp(num_room, "1.alg"))
+ refresca_1_antes();
+ else if (!strcmp(num_room, "3.alg"))
+ refresca_3_antes();
+ else if (!strcmp(num_room, "5.alg"))
+ refresca_5_antes();
+ else if (!strcmp(num_room, "6.alg"))
+ refresca_6_antes();
+ else if (!strcmp(num_room, "7.alg"))
+ refresca_7_antes();
+ else if (!strcmp(num_room, "9.alg"))
+ refresca_9_antes();
+ else if (!strcmp(num_room, "12.alg"))
+ refresca_12_antes();
+ else if (!strcmp(num_room, "14.alg"))
+ refresca_14_antes();
+ else if (!strcmp(num_room, "16.alg"))
+ if (num_ejec == 1)
+ pon_bj();
+ else if (num_ejec == 2) {
+ refresca_16_antes();
+ }
+ else if (!strcmp(num_room,"17.alg"))
+ refresca_17_antes();
+ else if (!strcmp(num_room,"18.alg"))
+ refresca_18_antes();
+}
+
+void DrasculaEngine::pon_hare() {
+ int pos_hare[6];
+ int r;
+
+ if (hare_se_mueve == 1 && paso_x == PASO_HARE_X) {
+ for (r = 0; r < paso_x; r++) {
+ if (num_ejec == 1) {
+ if (sentido_hare == 0 && sitio_x - r == hare_x + ancho_hare / 2) {
+ hare_se_mueve = 0;
+ paso_x = PASO_HARE_X;
+ paso_y = PASO_HARE_Y;
+ }
+ if (sentido_hare == 1 && sitio_x + r == hare_x + ancho_hare / 2) {
+ hare_se_mueve = 0;
+ paso_x = PASO_HARE_X;
+ paso_y = PASO_HARE_Y;
+ hare_x = sitio_x - ancho_hare / 2;
+ hare_y = sitio_y - alto_hare;
+ }
+ } else if (num_ejec == 2) {
+ if (sentido_hare == 0 && sitio_x - r == hare_x) {
+ hare_se_mueve = 0;
+ paso_x = PASO_HARE_X;
+ paso_y = PASO_HARE_Y;
+ }
+ if (sentido_hare == 1 && sitio_x + r == hare_x + ancho_hare) {
+ hare_se_mueve = 0;
+ paso_x = PASO_HARE_X;
+ paso_y = PASO_HARE_Y;
+ hare_x = sitio_x - ancho_hare + 4;
+ hare_y = sitio_y - alto_hare;
+ }
+ }
+ }
+ }
+ if (hare_se_mueve == 1 && paso_y == PASO_HARE_Y) {
+ for (r = 0; r < paso_y; r++) {
+ if (sentido_hare == 2 && sitio_y - r == hare_y + alto_hare) {
+ hare_se_mueve = 0;
+ paso_x = PASO_HARE_X;
+ paso_y = PASO_HARE_Y;
+ }
+ if (sentido_hare == 3 && sitio_y + r == hare_y + alto_hare) {
+ hare_se_mueve = 0;
+ paso_x = PASO_HARE_X;
+ paso_y = PASO_HARE_Y;
+ }
+ }
+ }
+
+ if (num_ejec == 1)
+ if (hare_se_ve == 0)
+ goto no_vuelco;
+
+ if (hare_se_mueve == 0) {
+ pos_hare[0] = 0;
+ 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) {
+ pos_hare[4] = ancho_hare;
+ pos_hare[5] = alto_hare;
+ }
+
+ 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)
+ DIBUJA_BLOQUE_CUT(pos_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 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)
+ DIBUJA_BLOQUE_CUT(pos_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)
+ DIBUJA_BLOQUE_CUT(pos_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) {
+ pos_hare[4] = ancho_hare;
+ pos_hare[5] = alto_hare;
+ }
+ 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)
+ DIBUJA_BLOQUE_CUT(pos_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 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)
+ DIBUJA_BLOQUE_CUT(pos_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)
+ DIBUJA_BLOQUE_CUT(pos_hare, dir_hare_frente, dir_zona_pantalla);
+
+no_vuelco:
+ aumenta_num_frame();
+ }
+}
+
+void DrasculaEngine::menu_sin_volcar() {
+ int h, n, x;
+ char texto_icono[13];
+
+ x = sobre_que_objeto();
+ strcpy(texto_icono, nombre_icono[x]);
+
+ for (n = 1; n < 43; n++) {
+ 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);
+
+ DIBUJA_BLOQUE(x1d_menu[h], y1d_menu[h], x_obj[n], y_obj[n],
+ ANCHOBJ, ALTOBJ, dir_hare_fondo, dir_zona_pantalla);
+ }
+
+ if (x < 7)
+ print_abc(texto_icono, x_obj[x] - 2, y_obj[x] - 7);
+}
+
+void DrasculaEngine::barra_menu() {
+ int n, sobre_verbo = 1;
+
+ 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);
+ sobre_verbo = 1;
+ }
+}
+
+void DrasculaEngine::saca_objeto() {
+ int h = 0, n;
+
+ refresca_pantalla();
+
+ for (n = 1; n < 43; n++){
+ if (sobre_que_objeto() == n) {
+ h = objetos_que_tengo[n];
+ objetos_que_tengo[n] = 0;
+ if (h != 0)
+ lleva_objeto = 1;
+ }
+ }
+
+ espera_soltar();
+
+ if (lleva_objeto == 1)
+ elige_objeto(h);
+}
+
+bool DrasculaEngine::sal_de_la_habitacion(int l) {
+ char salgo[13];
+
+ if (num_ejec == 1) {
+ if (num_obj[l] == 105 && flags[0] == 0)
+ hablar(TEXT442, "442.als");
+ else {
+ 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] == 105)
+ if (animacion_2_1())
+ return true;
+ borra_pantalla();
+ strcpy(salgo, alapantallakeva[l]);
+ strcat(salgo, ".ald");
+ hare_x = -1;
+ carga_escoba_1(salgo);
+ }
+ }
+ } else if (num_ejec == 2) {
+ puertas_cerradas(l);
+ if (espuerta[l] != 0) {
+ lleva_al_hare(sitiobj_x[l], sitiobj_y[l]);
+ hare_se_mueve = 0;
+ sentido_hare = sentido_alkeva[l];
+ obj_saliendo = alapuertakeva[l];
+ rompo = 1;
+ 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();
+ if (num_obj[l] == 146 && flags[39] == 1) {
+ flags[5] = 1;
+ flags[11] = 1;
+ }
+ if (num_obj[l] == 176 && flags[29] == 1) {
+ flags[29] = 0;
+ resta_objeto(23);
+ suma_objeto(11);
+ }
+ borra_pantalla();
+ ald->close();
+ strcpy(salgo, alapantallakeva[l]);
+ strcat(salgo, ".ald");
+ hare_x =- 1;
+ carga_escoba_2(salgo);
+ }
+ }
+
+ return false;
+}
+
+void DrasculaEngine::coge_objeto() {
+ int h, n;
+ h = objeto_que_lleva;
+ comprueba_flags = 1;
+
+ refresca_pantalla();
+ menu_sin_volcar();
+ VUELCA_PANTALLA(0, 0, 0, 0, 320, 200, dir_zona_pantalla);
+
+ if (objeto_que_lleva < 7)
+ goto usando_verbos;
+
+ for (n = 1; n < 43; n++) {
+ if (sobre_que_objeto() == n && objetos_que_tengo[n] == 0) {
+ objetos_que_tengo[n] = h;
+ lleva_objeto = 0;
+ comprueba_flags = 0;
+ }
+ }
+
+usando_verbos:
+
+ if (comprueba_flags == 1) {
+ comprueba_banderas_menu();
+ }
+ espera_soltar();
+ if (lleva_objeto == 0)
+ sin_verbo();
+}
+
+void DrasculaEngine::banderas(int fl) {
+ hare_se_mueve = 0;
+ refresca_pantalla();
+ VUELCA_PANTALLA(0, 0, 0, 0, 320, 200, dir_zona_pantalla);
+
+ 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;
+ } else {
+ if (objeto_que_lleva == MIRAR && fl == 50)
+ hablar(TEXT308, "308.als");
+ else if (objeto_que_lleva == ABRIR && fl == 50)
+ hablar(TEXT310, "310.als" );
+ else if (objeto_que_lleva == CERRAR && fl == 50)
+ hablar(TEXT311, "311.als" );
+ else if (objeto_que_lleva == MOVER && fl == 50)
+ hablar(TEXT312, "312.als" );
+ 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"))
+ pantalla_62(fl);
+ else if (!strcmp(num_room, "63.alg"))
+ pantalla_63(fl);
+ else
+ hay_respuesta = 0;
+ }
+ if (hay_respuesta == 0 && hay_nombre == 1)
+ pantalla_0();
+ else if (hay_respuesta == 0 && menu_scr == 1)
+ pantalla_0();
+}
+
+void DrasculaEngine::cursor_mesa() {
+ int pos_cursor[8];
+
+ pos_cursor[0] = 225;
+ pos_cursor[1] = 56;
+ pos_cursor[2] = x_raton - 20;
+ pos_cursor[3] = y_raton - 12;
+ pos_cursor[4] = 40;
+ pos_cursor[5] = 25;
+
+ DIBUJA_BLOQUE_CUT(pos_cursor, dir_mesa, dir_zona_pantalla);
+}
+
+void DrasculaEngine::introduce_nombre() {
+ Common::KeyCode key;
+ int v = 0, h = 0;
+ char select2[23];
+ strcpy(select2, " ");
+ for (;;) {
+ buffer_teclado();
+ select2[v] = '-';
+ DIBUJA_FONDO(115, 14, 115, 14, 176, 9, dir_dibujo1, dir_zona_pantalla);
+ print_abc(select2, 117, 15);
+ VUELCA_PANTALLA(0, 0, 0, 0, 320, 200, dir_zona_pantalla);
+ key = getscan();
+ if (key != 0) {
+ if (key == Common::KEYCODE_q)
+ select2[v] = 'q';
+ else if (key == Common::KEYCODE_w)
+ select2[v] = 'w';
+ else if (key == Common::KEYCODE_e)
+ select2[v] = 'e';
+ else if (key == Common::KEYCODE_r)
+ select2[v] = 'r';
+ else if (key == Common::KEYCODE_t)
+ select2[v] = 't';
+ else if (key == Common::KEYCODE_y)
+ select2[v] = 'y';
+ else if (key == Common::KEYCODE_u)
+ select2[v] = 'u';
+ else if (key == Common::KEYCODE_i)
+ select2[v] = 'i';
+ else if (key == Common::KEYCODE_o)
+ select2[v] = 'o';
+ else if (key == Common::KEYCODE_p)
+ select2[v] = 'p';
+ else if (key == Common::KEYCODE_a)
+ select2[v] = 'a';
+ else if (key == Common::KEYCODE_s)
+ select2[v] = 's';
+ else if (key == Common::KEYCODE_d)
+ select2[v] = 'd';
+ else if (key == Common::KEYCODE_f)
+ select2[v] = 'f';
+ else if (key == Common::KEYCODE_g)
+ select2[v] = 'g';
+ else if (key == Common::KEYCODE_h)
+ select2[v] = 'h';
+ else if (key == Common::KEYCODE_j)
+ select2[v] = 'j';
+ else if (key == Common::KEYCODE_k)
+ select2[v] = 'k';
+ else if (key == Common::KEYCODE_l)
+ select2[v] = 'l';
+ else if ((key == Common::KEYCODE_LCTRL) || (key == Common::KEYCODE_RCTRL))
+ select2[v] = '¤';
+ else if (key == Common::KEYCODE_z)
+ select2[v] = 'z';
+ else if (key == Common::KEYCODE_x)
+ select2[v] = 'x';
+ else if (key == Common::KEYCODE_c)
+ select2[v] = 'c';
+ else if (key == Common::KEYCODE_v)
+ select2[v] = 'v';
+ else if (key == Common::KEYCODE_b)
+ select2[v] = 'b';
+ else if (key == Common::KEYCODE_n)
+ select2[v] = 'n';
+ else if (key == Common::KEYCODE_m)
+ select2[v] = 'm';
+ else if (key == Common::KEYCODE_1)
+ select2[v] = '1';
+ else if (key == Common::KEYCODE_2)
+ select2[v] = '2';
+ else if (key == Common::KEYCODE_3)
+ select2[v] = '3';
+ else if (key == Common::KEYCODE_4)
+ select2[v] = '4';
+ else if (key == Common::KEYCODE_5)
+ select2[v] = '5';
+ else if (key == Common::KEYCODE_6)
+ select2[v] = '6';
+ else if (key == Common::KEYCODE_7)
+ select2[v] = '7';
+ else if (key == Common::KEYCODE_8)
+ select2[v] = '8';
+ else if (key == Common::KEYCODE_9)
+ select2[v] = '9';
+ else if (key == Common::KEYCODE_0)
+ select2[v] = '0';
+ else if (key == Common::KEYCODE_SPACE)
+ select2[v] = '§';
+ else if (key == ESC)
+ break;
+ else if (key == Common::KEYCODE_RETURN) {
+ select2[v] = '\0';
+ h = 1;
+ break;
+ } else if (key == Common::KEYCODE_BACKSPACE)
+ select2[v] = '\0';
+ else
+ v--;
+
+ if (key == Common::KEYCODE_BACKSPACE)
+ v--;
+ else
+ v++;
+ }
+ if (v == 22)
+ v = 21;
+ else if (v == -1)
+ v = 0;
+ }
+ if (h == 1) {
+ strcpy(select, select2);
+ hay_seleccion = 1;
+ }
+}
+
+void DrasculaEngine::para_grabar(char nom_game[]) {
+ graba_partida(nom_game);
+ comienza_sound("99.als");
+ fin_sound();
+}
+
+void DrasculaEngine::OpenSSN(const char *Name, int Pause) {
+ MiVideoSSN = (byte *)malloc(64256);
+ GlobalSpeed = CLOCKS_PER_SEC / Pause;
+ FrameSSN = 0;
+ UsingMem = 0;
+ if (MiVideoSSN == NULL)
+ return;
+ _Sesion = new Common::File;
+ _Sesion->open(Name);
+ mSesion = TryInMem(_Sesion);
+ LastFrame = clock();
+}
+
+int DrasculaEngine::PlayFrameSSN() {
+ int Exit = 0;
+ int Lengt;
+ byte *BufferSSN;
+
+ if (!UsingMem)
+ _Sesion->read(&CHUNK, 1);
+ else {
+ memcpy(&CHUNK, mSesion, 1);
+ 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:
+ 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) {
+ BufferSSN = (byte *)malloc(Lengt);
+ _Sesion->read(BufferSSN, Lengt);
+ } else {
+ BufferSSN = (byte *)malloc(Lengt);
+ memcpy(BufferSSN, mSesion, Lengt);
+ mSesion += Lengt;
+ }
+ 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);
+ } 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;
+ }
+ return (!Exit);
+}
+
+void DrasculaEngine::EndSSN() {
+ free(MiVideoSSN);
+ if (UsingMem)
+ free(pointer);
+ else {
+ _Sesion->close();
+ delete _Sesion;
+ }
+}
+
+byte *DrasculaEngine::TryInMem(Common::File *Sesion) {
+ int Lengt;
+
+ Sesion->seek(0, SEEK_END);
+ Lengt = Sesion->pos();
+ Sesion->seek(0, SEEK_SET);
+ pointer = (byte *)malloc(Lengt);
+ if (pointer == NULL)
+ return NULL;
+ Sesion->read(pointer, Lengt);
+ UsingMem = 1;
+ Sesion->close();
+ delete Sesion;
+ return pointer;
+}
+
+void DrasculaEngine::set_dacSSN(byte *PalBuf) {
+ setvgapalette256((byte *)PalBuf);
+}
+
+void DrasculaEngine::Des_OFF(byte *BufferOFF, byte *MiVideoOFF, int Lenght) {
+ int x = 0;
+ unsigned char Reps;
+ int Offset;
+
+ memset(MiVideoSSN, 0, 64000);
+ while (x < Lenght) {
+ Offset = BufferOFF[x] + BufferOFF[x + 1] * 256;
+ Reps = BufferOFF[x + 2];
+ memcpy(MiVideoOFF + Offset, &BufferOFF[x + 3], Reps);
+ x += 3 + Reps;
+ }
+}
+
+void DrasculaEngine::Des_RLE(byte *BufferRLE, byte *MiVideoRLE) {
+ signed int con = 0;
+ unsigned int X = 0;
+ unsigned int fExit = 0;
+ char ch, rep;
+ while (!fExit) {
+ ch = *BufferRLE++;
+ rep = 1;
+ if ((ch & 192) == 192) {
+ rep = (ch & 63);
+ ch =* BufferRLE++;
+ }
+ for (con = 0; con < rep; con++) {
+ *MiVideoRLE++ = ch;
+ X++;
+ if (X > 64000)
+ fExit = 1;
+ }
+ }
+}
+
+void DrasculaEngine::MixVideo(byte *OldScreen, byte *NewScreen) {
+ int x;
+ for (x = 0; x < 64000; x++)
+ OldScreen[x] ^= NewScreen[x];
+}
+
+void DrasculaEngine::WaitFrameSSN() {
+ while (clock() < LastFrame + GlobalSpeed) {};
+ LastFrame = LastFrame + GlobalSpeed;
+}
+
+byte *DrasculaEngine::carga_pcx(byte *NamePcc) {
+ signed int con = 0;
+ unsigned int X = 0;
+ unsigned int fExit = 0;
+ char ch, rep;
+ byte *AuxPun;
+
+ AuxPun = AuxBuffDes;
+
+ while (!fExit) {
+ ch = *NamePcc++;
+ rep = 1;
+ if ((ch & 192) == 192) {
+ rep = (ch & 63);
+ ch = *NamePcc++;
+ }
+ for (con = 0; con< rep; con++) {
+ *AuxPun++ = ch;
+ X++;
+ if (X > 64000)
+ fExit = 1;
+ }
+ }
+ return AuxBuffDes;
+}
+
+void DrasculaEngine::set_dac(byte *dac) {
+ setvgapalette256((byte *)dac);
+}
+
+void DrasculaEngine::WaitForNext(int FPS) {
+ _system->delayMillis(1000 / FPS);
+}
+
+float DrasculaEngine::vez() {
+ return _system->getMillis() / 20; // originaly was 1
+}
+
+void DrasculaEngine::reduce_hare_chico(int xx1, int yy1, int xx2, int yy2, int ancho, int alto, int factor, byte *dir_inicio, byte *dir_fin) {
+ float suma_x, suma_y;
+ int n, m;
+ float pixel_x, pixel_y;
+ int pos_pixel[6];
+
+ nuevo_ancho = (ancho * factor) / 100;
+ nuevo_alto = (alto * factor) / 100;
+
+ suma_x = ancho / nuevo_ancho;
+ suma_y = alto / nuevo_alto;
+
+ pixel_x = xx1;
+ pixel_y = yy1;
+
+ 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;
+ pos_pixel[3] = yy2 + n;
+ pos_pixel[4] = 1;
+ pos_pixel[5] = 1;
+
+ DIBUJA_BLOQUE_CUT(pos_pixel, dir_inicio, dir_fin);
+
+ pixel_x = pixel_x + suma_x;
+ }
+ pixel_x = xx1;
+ pixel_y = pixel_y + suma_y;
+ }
+}
+
+char DrasculaEngine::codifica(char car) {
+ return ~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)
+ distancia_x = hare_x + ancho_hare - sitio_x;
+
+ distancia_y = (hare_y + alto_hare) - sitio_y;
+
+ if (distancia_x < distancia_y) {
+ direccion_hare = 0;
+ sentido_hare = 2;
+ paso_x = (int)distancia_x / ((int)distancia_y / PASO_HARE_Y);
+ } else {
+ direccion_hare = 7;
+ sentido_hare = 0;
+ paso_y = (int)distancia_y / ((int)distancia_x / PASO_HARE_X);
+ }
+}
+
+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)
+ distancia_x = abs(hare_x + ancho_hare - sitio_x);
+
+ distancia_y = (hare_y + alto_hare) - sitio_y;
+
+ if (distancia_x < distancia_y) {
+ direccion_hare = 1;
+ sentido_hare = 2;
+ paso_x = (int)distancia_x / ((int)distancia_y / PASO_HARE_Y);
+ } else {
+ direccion_hare = 2;
+ sentido_hare = 1;
+ paso_y = (int)distancia_y / ((int)distancia_x / PASO_HARE_X);
+ }
+}
+
+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)
+ distancia_x = hare_x + ancho_hare - sitio_x;
+
+ distancia_y = sitio_y - (hare_y + alto_hare);
+
+ if (distancia_x < distancia_y) {
+ direccion_hare = 5;
+ sentido_hare = 3;
+ paso_x = (int)distancia_x / ((int)distancia_y / PASO_HARE_Y);
+ } else {
+ direccion_hare = 6;
+ sentido_hare = 0;
+ paso_y = (int)distancia_y / ((int)distancia_x / PASO_HARE_X);
+ }
+}
+
+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)
+ distancia_x = abs(hare_x + ancho_hare - sitio_x);
+
+ distancia_y = sitio_y - (hare_y + alto_hare);
+
+ if (distancia_x <distancia_y) {
+ direccion_hare = 4;
+ sentido_hare = 3;
+ paso_x = (int)distancia_x / ((int)distancia_y / PASO_HARE_Y);
+ } else {
+ direccion_hare = 3;
+ sentido_hare = 1;
+ paso_y = (int)distancia_y / ((int)distancia_x / PASO_HARE_X);
+ }
+}
+
+void DrasculaEngine::refresca_62() {
+ int borracho_x[] = { 1, 42, 83, 124, 165, 206, 247, 1 };
+
+ DIBUJA_BLOQUE(1, 1, 0, 0, 62, 142, dir_dibujo2, dir_zona_pantalla);
+
+ if (hare_y + alto_hare < 89) {
+ DIBUJA_BLOQUE(205, 1, 180, 9, 82, 80, dir_dibujo3, dir_zona_pantalla);
+ DIBUJA_FONDO(borracho_x[frame_borracho], 82, 170, 50, 40, 53, dir_dibujo3, dir_zona_pantalla);
+ }
+}
+
+void DrasculaEngine::refresca_63() {
+ DIBUJA_BLOQUE(1, 154, 83, 122, 131, 44, dir_dibujo3, dir_zona_pantalla);
+}
+
+void DrasculaEngine::refresca_62_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 diferencia;
+
+ DIBUJA_FONDO(123, velas_y[frame_velas], 142, 14, 39, 13, dir_dibujo3, dir_zona_pantalla);
+ DIBUJA_FONDO(cirio_x[frame_velas], 146, 311, 80, 4, 8, dir_dibujo3, dir_zona_pantalla);
+
+ if (parpadeo == 5)
+ DIBUJA_FONDO(1, 149, 127, 52, 9, 5, dir_dibujo3, dir_zona_pantalla);
+
+ if (hare_x > 101 && hare_x < 155)
+ DIBUJA_FONDO(31, 138, 178, 51, 18, 16, dir_dibujo3, dir_zona_pantalla);
+
+ if (flags[11] == 0)
+ DIBUJA_FONDO(pianista_x[frame_piano], 157, 245, 130, 29, 42, dir_dibujo3, dir_zona_pantalla);
+ else if (flags[5] == 0)
+ DIBUJA_FONDO(145, 139, 228, 112, 47, 60, dir_hare_dch, dir_zona_pantalla);
+ else
+ DIBUJA_FONDO(165, 140, 229, 117, 43, 59, dir_dibujo3, dir_zona_pantalla);
+
+ if (flags[12] == 1)
+ DIBUJA_FONDO(borracho_x[frame_borracho], 82, 170, 50, 40, 53, dir_dibujo3, dir_zona_pantalla);
+
+ diferencia = (int)vez() - conta_ciego_vez;
+ if (diferencia > 6) {
+ if (flags[12] == 1) {
+ frame_borracho++;
+ if (frame_borracho == 8) {
+ frame_borracho = 0;
+ flags[12] = 0;
+ }
+ } else if ((_rnd->getRandomNumber(94) == 15) && (flags[13] == 0))
+ flags[12] = 1;
+
+ frame_velas++;
+ if (frame_velas == 3)
+ frame_velas = 0;
+ frame_piano++;
+ if (frame_piano == 9)
+ frame_piano = 0;
+ parpadeo = _rnd->getRandomNumber(10);
+ conta_ciego_vez = (int)vez();
+ }
+}
+
+void DrasculaEngine::graba_partida(char nom_game[]) {
+ Common::OutSaveFile *out;
+ int l;
+
+ if (!(out = _saveFileMan->openForSaving(nom_game))) {
+ error("no puedo abrir el archivo");
+ }
+ out->writeSint32LE(num_ejec);
+ out->write(datos_actuales, 20);
+ out->writeSint32LE(hare_x);
+ out->writeSint32LE(hare_y);
+ out->writeSint32LE(sentido_hare);
+
+ for (l = 1; l < 43; l++) {
+ out->writeSint32LE(objetos_que_tengo[l]);
+ }
+
+ for (l = 0; l < NUM_BANDERAS; l++) {
+ out->writeSint32LE(flags[l]);
+ }
+
+ out->writeSint32LE(lleva_objeto);
+ out->writeSint32LE(objeto_que_lleva);
+
+ out->finalize();
+ if (out->ioFailed())
+ warning("Can't write file '%s'. (Disk full?)", nom_game);
+
+ delete out;
+ canal_p(nom_game);
+}
+
+void DrasculaEngine::aumenta_num_frame() {
+ diff_vez = vez() - conta_vez;
+
+ if (diff_vez >= 5.7) {
+ conta_vez = vez();
+ num_frame++;
+ if (num_frame == 6)
+ num_frame = 0;
+
+ if (direccion_hare == 0) {
+ hare_x = hare_x - paso_x;
+ hare_y = hare_y - paso_y;
+ } else if (direccion_hare == 7) {
+ hare_x = hare_x - paso_x;
+ hare_y = hare_y - paso_y;
+ } else if (direccion_hare == 1) {
+ hare_x = hare_x + paso_x;
+ hare_y = hare_y - paso_y;
+ } else if (direccion_hare == 2) {
+ hare_x = hare_x + paso_x;
+ hare_y = hare_y - paso_y;
+ } else if (direccion_hare == 3) {
+ hare_x = hare_x + paso_x;
+ hare_y = hare_y + paso_y;
+ } else if (direccion_hare == 4) {
+ hare_x = hare_x + paso_x;
+ hare_y = hare_y + paso_y;
+ } else if (direccion_hare == 5) {
+ hare_x = hare_x - paso_x;
+ hare_y = hare_y + paso_y;
+ } else if (direccion_hare == 6) {
+ hare_x = hare_x - paso_x;
+ hare_y = hare_y + paso_y;
+ }
+ }
+
+ if (num_ejec == 1) {
+ diferencia_y = alto_hare - (int)nuevo_alto;
+ diferencia_x = ancho_hare - (int)nuevo_ancho;
+ hare_y = hare_y + diferencia_y;
+ hare_x = hare_x + diferencia_x;
+ alto_hare = (int)nuevo_alto;
+ ancho_hare = (int)nuevo_ancho;
+ }
+}
+
+int DrasculaEngine::sobre_que_objeto() {
+ int n;
+
+ for (n = 1; n < 43; n++) {
+ if (x_raton > x_obj[n] && y_raton > y_obj[n]
+ && x_raton < x_obj[n] + ANCHOBJ && y_raton < y_obj[n] + ALTOBJ)
+ break;
+ }
+
+ return n;
+}
+
+void DrasculaEngine::comprueba_banderas_menu() {
+ int h, n;
+
+ for (n = 0; n < 43; n++){
+ if (sobre_que_objeto() == n) {
+ h = objetos_que_tengo[n];
+ if (h != 0)
+ banderas(h);
+ }
+ }
+}
+
+void DrasculaEngine::pantalla_0() {
+ if (objeto_que_lleva == MIRAR) {
+ if (num_ejec == 1)
+ hablar(TEXT54, "54.als");
+ else if (num_ejec == 2) {
+ 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)
+ if (num_ejec == 1)
+ hablar(TEXT11, "11.als" );
+ else if (num_ejec == 2) {
+ 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 {
+ if (num_ejec == 1)
+ hablar(TEXT11, "11.als");
+ else if (num_ejec == 1) {
+ hablar(poder_t[c_poder], poder_v[c_poder]);
+ c_poder++;
+ if (c_poder == 6)
+ c_poder = 0;
+ }
+ }
+}
+
+void DrasculaEngine::pantalla_62(int fl) {
+ if (objeto_que_lleva == HABLAR && fl == 53)
+ conversa("op_13.cal");
+ else if (objeto_que_lleva == HABLAR && fl == 52 && flags[0] == 0)
+ animacion_3_2();
+ else if (objeto_que_lleva == HABLAR && fl == 52 && flags[0] == 1)
+ hablar(TEXT109, "109.als");
+ else if (objeto_que_lleva == HABLAR && fl == 54)
+ animacion_4_1();
+ else if (objeto_que_lleva == MIRAR && fl == 100)
+ hablar(TEXT168, "168.als");
+ else if (objeto_que_lleva == HABLAR && fl == 100)
+ hablar(TEXT169, "169.als");
+ else if (objeto_que_lleva == COGER && fl == 100)
+ hablar(TEXT170, "170.als");
+ else if (objeto_que_lleva == MIRAR && fl == 101)
+ hablar(TEXT171, "171.als");
+ else if (objeto_que_lleva == MIRAR && fl == 102)
+ hablar(TEXT167, "167.als");
+ else if (objeto_que_lleva == MIRAR && fl == 103)
+ hablar(TEXT166, "166.als");
+ else hay_respuesta = 0;
+}
+
+void DrasculaEngine::pantalla_63(int fl) {
+ if (objeto_que_lleva == MIRAR && fl == 110)
+ hablar(TEXT172, "172.als");
+ else if (objeto_que_lleva == MIRAR && fl == 109)
+ hablar(TEXT173, "173.als");
+ else if (objeto_que_lleva == MOVER && fl == 109)
+ hablar(TEXT174, "174.als");
+ else if (objeto_que_lleva == MIRAR && fl == 108)
+ hablar(TEXT334, "334.als");
+ else if (objeto_que_lleva == HABLAR && fl == 108)
+ hablar(TEXT333, "333.als");
+ else
+ hay_respuesta = 0;
+}
+
+void DrasculaEngine::conversa(const char *nom_fich) {
+ int h;
+ int juego1 = 1, juego2 = 1, juego3 = 1, juego4 = 1;
+ char frase1[78];
+ char frase2[78];
+ char frase3[78];
+ char frase4[78];
+ char para_codificar[13];
+ char suena1[13];
+ char suena2[13];
+ char suena3[13];
+ char suena4[13];
+ int longitud;
+ int respuesta1;
+ int respuesta2;
+ int respuesta3;
+ int usado1 = 0;
+ int usado2 = 0;
+ int usado3 = 0;
+ char buffer[256];
+
+ rompo_y_salgo = 0;
+
+ strcpy(para_codificar, nom_fich);
+ canal_p(para_codificar);
+
+ ald = new Common::File;
+ ald->open(nom_fich);
+ if (!ald->isOpen()) {
+ error("missing data file");
+ }
+ int size = ald->size();
+
+ getLine(ald, buffer, size);
+ sscanf(buffer, "%s", frase1);
+ getLine(ald, buffer, size);
+ sscanf(buffer, "%s", frase2);
+ getLine(ald, buffer, size);
+ sscanf(buffer, "%s", frase3);
+ getLine(ald, buffer, size);
+ sscanf(buffer, "%s", frase4);
+ getLine(ald, buffer, size);
+ sscanf(buffer, "%s", suena1);
+ getLine(ald, buffer, size);
+ sscanf(buffer, "%s", suena2);
+ getLine(ald, buffer, size);
+ sscanf(buffer, "%s", suena3);
+ getLine(ald, buffer, size);
+ sscanf(buffer, "%s", suena4);
+ getLine(ald, buffer, size);
+ sscanf(buffer, "%d", &respuesta1);
+ getLine(ald, buffer, size);
+ sscanf(buffer, "%d", &respuesta2);
+ getLine(ald, buffer, size);
+ sscanf(buffer, "%d", &respuesta3);
+ delete ald;
+ canal_p(para_codificar);
+
+ if (num_ejec == 2 && !strcmp(nom_fich, "op_5.cal") && flags[38] == 1 && flags[33] == 1) {
+ strcpy(frase3, TEXT405);
+ strcpy(suena3, "405.als");
+ respuesta3 = 31;
+ }
+
+ longitud = strlen(frase1);
+ for (h = 0; h < longitud; h++)
+ if (frase1[h] == (char)0xa7)
+ frase1[h] = ' ';
+
+ longitud = strlen(frase2);
+ for (h = 0; h < longitud; h++)
+ if (frase2[h] == (char)0xa7)
+ frase2[h] = ' ';
+
+ longitud = strlen(frase3);
+ for (h = 0; h < longitud; h++)
+ if (frase3[h] == (char)0xa7)
+ frase3[h] = ' ';
+
+ longitud = strlen(frase4);
+ for (h = 0; h < longitud; h++)
+ if (frase4[h] == (char)0xa7)
+ frase4[h] = ' ';
+
+ lee_dibujos("car.alg");
+ descomprime_dibujo(dir_hare_fondo,1);
+/* TODO
+ ent.w.ax = 8;
+ ent.w.cx = 1;
+ ent.w.dx = 31;
+ int386(0x33, &ent, &sal);
+*/
+ color_abc(VERDE_CLARO);
+
+bucle_opc:
+
+ refresca_pantalla();
+
+ if (num_ejec == 1)
+ if (music_status() == 0 && flags[11] == 0)
+ playmusic(musica_room);
+ else if (num_ejec == 2)
+ if (music_status() == 0 && flags[11] == 0 && musica_room != 0)
+ playmusic(musica_room);
+
+ MirarRaton();
+
+ if ( y_raton > 0 && y_raton < 9) {
+ if (usado1 == 1 && _color != BLANCO)
+ color_abc(BLANCO);
+ else if (usado1 == 0 && _color != VERDE_CLARO)
+ color_abc(VERDE_CLARO);
+ } else if (y_raton > 8 && y_raton < 17) {
+ if (usado2 == 1 && _color != BLANCO)
+ color_abc(BLANCO);
+ else if (usado2 == 0 && _color != VERDE_CLARO)
+ color_abc(VERDE_CLARO);
+ } else if (y_raton > 16 && y_raton < 25) {
+ if (usado3 == 1 && _color != BLANCO)
+ color_abc(BLANCO);
+ else if (usado3 == 0 && _color != VERDE_CLARO)
+ color_abc(VERDE_CLARO);
+ } else if (_color != VERDE_CLARO)
+ color_abc(VERDE_CLARO);
+
+ if (y_raton > 0 && y_raton < 9)
+ juego1 = 2;
+ else if (y_raton > 8 && y_raton < 17)
+ juego2 = 2;
+ else if (y_raton > 16 && y_raton < 25)
+ juego3 = 2;
+ else if (y_raton > 24 && y_raton < 33)
+ juego4 = 2;
+
+ print_abc_opc(frase1, 1, 2, juego1);
+ print_abc_opc(frase2, 1, 10, juego2);
+ print_abc_opc(frase3, 1, 18, juego3);
+ print_abc_opc(frase4, 1, 26, juego4);
+
+ VUELCA_PANTALLA(0, 0, 0, 0, 320, 200, dir_zona_pantalla);
+
+ if ((boton_izq == 1) && (juego1 == 2)) {
+ usado1 = 1;
+ hablar(frase1, suena1);
+ responde(respuesta1);
+ } else if ((boton_izq == 1) && (juego2 == 2)) {
+ usado2 = 1;
+ hablar(frase2, suena2);
+ responde(respuesta2);
+ } else if ((boton_izq == 1) && (juego3 == 2)) {
+ usado3 = 1;
+ hablar(frase3, suena3);
+ responde(respuesta3);
+ } else if ((boton_izq == 1) && (juego4 == 2)) {
+ hablar(frase4, suena4);
+ rompo_y_salgo = 1;
+ }
+
+ if (boton_izq == 1)
+ color_abc(VERDE_CLARO);
+
+ if (usado1 == 0)
+ juego1 = 1;
+ else
+ juego1 = 3;
+ if (usado2 == 0)
+ juego2 = 1;
+ else
+ juego2 = 3;
+ if (usado3 == 0)
+ juego3 = 1;
+ else
+ juego3 = 3;
+
+ juego4 = 1;
+
+ if (rompo_y_salgo == 0)
+ goto bucle_opc;
+
+ if (num_ejec == 1)
+ lee_dibujos("99.alg");
+ else if (num_ejec == 2)
+ lee_dibujos(fondo_y_menu);
+ descomprime_dibujo(dir_hare_fondo, 1);
+ sin_verbo();
+}
+
+void DrasculaEngine::animacion_3_1() {
+ lee_dibujos("an11y13.alg");
+ descomprime_dibujo(dir_hare_dch, 1);
+
+ hablar(TEXT192, "192.als");
+ habla_tabernero(TEXTT1, "t1.als");
+ hablar(TEXT193, "193.als");
+ habla_tabernero(TEXTT2, "t2.als");
+ hablar(TEXT194, "194.als");
+ habla_tabernero(TEXTT3, "t3.als");
+ hablar(TEXT195, "195.als");
+ habla_tabernero(TEXTT4, "t4.als");
+ hablar(TEXT196, "196.als");
+ habla_tabernero(TEXTT5, "t5.als");
+ habla_tabernero(TEXTT6, "t6.als");
+ hablar(TEXT197, "197.als");
+ habla_tabernero(TEXTT7, "t7.als");
+ hablar(TEXT198, "198.als");
+ habla_tabernero(TEXTT8, "t8.als");
+ hablar(TEXT199, "199.als");
+ habla_tabernero(TEXTT9, "t9.als");
+ hablar(TEXT200, "200.als");
+ hablar(TEXT201, "201.als");
+ hablar(TEXT202, "202.als");
+
+ flags[0] = 1;
+
+ lee_dibujos("97.alg");
+ descomprime_dibujo(dir_hare_dch, 1);
+}
+
+void DrasculaEngine::animacion_4_1() {
+ lee_dibujos("an12.alg");
+ descomprime_dibujo(dir_hare_dch, 1);
+
+ hablar(TEXT205,"205.als");
+
+ actualiza_refresco_antes();
+
+ DIBUJA_FONDO(1, 139, 228, 112, 47, 60, dir_hare_dch, dir_zona_pantalla);
+ VUELCA_PANTALLA(228,112, 228,112, 47,60, dir_zona_pantalla);
+
+ pausa(3);
+
+ actualiza_refresco_antes();
+
+ DIBUJA_FONDO(49, 139, 228, 112, 47, 60, dir_hare_dch, dir_zona_pantalla);
+ pon_hare();
+
+ VUELCA_PANTALLA(0, 0, 0, 0, 320, 200, dir_zona_pantalla);
+
+ pausa(3);
+ stopmusic();
+ flags[11] = 1;
+
+ habla_pianista(TEXTP1, "p1.als");
+ hablar(TEXT206, "206.als");
+ habla_pianista(TEXTP2, "p2.als");
+ hablar(TEXT207, "207.als");
+ habla_pianista(TEXTP3, "p3.als");
+ hablar(TEXT208, "208.als");
+ habla_pianista(TEXTP4, "p4.als");
+ hablar(TEXT209, "209.als");
+
+ flags[11] = 0;
+ lee_dibujos("97.alg");
+ descomprime_dibujo(dir_hare_dch, 1);
+}
+
+void DrasculaEngine::print_abc_opc(const char *dicho, int x_pantalla, int y_pantalla, int juego) {
+ int pos_texto[6];
+ int y_de_signos, y_de_letra, x_de_letra = 0, h, longitud;
+ longitud = strlen(dicho);
+
+ for (h = 0; h < longitud; h++) {
+ if (juego == 1) {
+ y_de_letra = Y_ABC_OPC_1;
+ y_de_signos = Y_SIGNOS_OPC_1;
+ } else if (juego == 3) {
+ y_de_letra = Y_ABC_OPC_3;
+ y_de_signos = Y_SIGNOS_OPC_3;
+ } else {
+ y_de_letra = Y_ABC_OPC_2;
+ y_de_signos = Y_SIGNOS_OPC_2;
+ }
+
+ char c = toupper(dicho[h]);
+ if (c == 'A')
+ x_de_letra = X_A_OPC;
+// else if (c == 'µ')
+// x_de_letra = X_A_OPC;
+// else if (c == '·')
+// x_de_letra = X_A_OPC;
+// else if (c == '¶')
+// x_de_letra = X_A_OPC;
+ else if (c == 'B'
+ )x_de_letra = X_B_OPC;
+ else if (c == 'C')
+ x_de_letra = X_C_OPC;
+// else if (c == '€')
+// x_de_letra = X_C_OPC;
+// else if (c == '‡')
+// x_de_letra = X_C_OPC;
+ else if (c == 'D')
+ x_de_letra = X_D_OPC;
+ else if (c == 'E')
+ x_de_letra = X_E_OPC;
+// else if (c == '')
+// x_de_letra = X_E_OPC;
+// else if (c == 'Ô')
+// x_de_letra = X_E_OPC;
+// else if (c == 'Ò')
+// x_de_letra = X_E_OPC;
+ else if (c == 'F')
+ x_de_letra = X_F_OPC;
+ else if (c == 'G')
+ x_de_letra = X_G_OPC;
+ else if (c == 'H')
+ x_de_letra = X_H_OPC;
+ else if (c == 'I')
+ x_de_letra = X_I_OPC;
+// else if (c == 'Ö')
+// x_de_letra = X_I_OPC;
+// else if (c == 'Þ')
+// x_de_letra = X_I_OPC;
+// else if (c == '×')
+// x_de_letra = X_I_OPC;
+ else if (c == 'J')
+ x_de_letra = X_J_OPC;
+ else if (c == 'K')
+ x_de_letra = X_K_OPC;
+ else if (c == 'L')
+ x_de_letra = X_L_OPC;
+ else if (c == 'M')
+ x_de_letra = X_M_OPC;
+ else if (c == 'N')
+ x_de_letra = X_N_OPC;
+// else if (c == ''')
+// x_de_letra = X_GN_OPC;
+ else if (c == 'O')
+ x_de_letra = X_O_OPC;
+// else if (c == 'à')
+// x_de_letra = X_O_OPC;
+// else if (c == 'â')
+// x_de_letra = X_O_OPC;
+// else if (c == 'ã')
+// x_de_letra = X_O_OPC;
+ else if (c == 'P')
+ x_de_letra = X_P_OPC;
+ else if (c == 'Q')
+ x_de_letra = X_Q_OPC;
+ else if (c == 'R')
+ x_de_letra = X_R_OPC;
+ else if (c == 'S')
+ x_de_letra = X_S_OPC;
+ else if (c == 'T')
+ x_de_letra = X_T_OPC;
+ else if (c == 'U')
+ x_de_letra = X_U_OPC;
+// else if (c == 'ë')
+// x_de_letra = X_U_OPC;
+// else if (c == 'ê')
+// x_de_letra = X_U_OPC;
+// else if (c == 'é')
+// x_de_letra = X_U_OPC;
+ else if (c == 'V')
+ x_de_letra = X_V_OPC;
+ else if (c == 'W')
+ x_de_letra = X_W_OPC;
+ else if (c == 'X')
+ x_de_letra = X_X_OPC;
+ else if (c == 'Y')
+ x_de_letra = X_Y_OPC;
+ else if (c == 'Z')
+ x_de_letra = X_Z_OPC;
+// else if (c == ' ')
+// x_de_letra = ESPACIO_OPC;
+ else
+ y_de_letra = y_de_signos;
+
+ if (c == '.')
+ x_de_letra = X_PUNTO_OPC;
+ else if (c == ',')
+ x_de_letra = X_COMA_OPC;
+ else if (c == '-')
+ x_de_letra = X_GUION_OPC;
+ else if (c == '?')
+ x_de_letra = X_CIERRA_INTERROGACION_OPC;
+// else if (c == '¨')
+// x_de_letra = X_ABRE_INTERROGACION_OPC;
+ else if (c == '"')
+ x_de_letra = X_COMILLAS_OPC;
+// else if (c == '!')
+// x_de_letra = X_CIERRA_EXCLAMACION_OPC;
+ else if (c == '­')
+ x_de_letra = X_ABRE_EXCLAMACION_OPC;
+ else if (c == ';')
+ x_de_letra = X_PUNTO_Y_COMA_OPC;
+ else if (c == '>')
+ x_de_letra = X_MAYOR_QUE_OPC;
+ else if (c == '<')
+ x_de_letra = X_MENOR_QUE_OPC;
+ else if (c == '$')
+ x_de_letra = X_DOLAR_OPC;
+ else if (c == '%')
+ x_de_letra = X_POR_CIENTO_OPC;
+ else if (c == ':')
+ x_de_letra = X_DOS_PUNTOS_OPC;
+ else if (c == '&')
+ x_de_letra = X_AND_OPC;
+ else if (c == '/')
+ x_de_letra = X_BARRA_OPC;
+ else if (c == '(')
+ x_de_letra = X_ABRE_PARENTESIS_OPC;
+ else if (c == ')')
+ x_de_letra = X_CIERRA_PARENTESIS_OPC;
+ else if (c == '*')
+ x_de_letra = X_ASTERISCO_OPC;
+ else if (c == '+')
+ x_de_letra = X_MAS_OPC;
+ else if (c == '1')
+ x_de_letra = X_N1_OPC;
+ else if (c == '2')
+ x_de_letra = X_N2_OPC;
+ else if (c == '3')
+ x_de_letra = X_N3_OPC;
+ else if (c == '4')
+ x_de_letra = X_N4_OPC;
+ else if (c == '5')
+ x_de_letra = X_N5_OPC;
+ else if (c == '6')
+ x_de_letra = X_N6_OPC;
+ else if (c == '7')
+ x_de_letra = X_N7_OPC;
+ else if (c == '8')
+ x_de_letra = X_N8_OPC;
+ else if (c == '9')
+ x_de_letra = X_N9_OPC;
+ else if (c == '0')
+ x_de_letra = X_N0_OPC;
+
+ pos_texto[0] = x_de_letra;
+ pos_texto[1] = y_de_letra;
+ pos_texto[2] = x_pantalla;
+ pos_texto[3] = y_pantalla;
+ pos_texto[4] = ANCHO_LETRAS_OPC;
+ pos_texto[5] = ALTO_LETRAS_OPC;
+
+ DIBUJA_BLOQUE_CUT(pos_texto, dir_hare_fondo, dir_zona_pantalla);
+
+ x_pantalla = x_pantalla + ANCHO_LETRAS_OPC;
+ }
+}
+
+void DrasculaEngine::responde(int funcion) {
+ if (funcion == 10)
+ habla_borracho(TEXTB1, "B1.als");
+ else if (funcion == 11)
+ habla_borracho(TEXTB2, "B2.als");
+ else if (funcion == 12)
+ habla_borracho(TEXTB3, "B3.als");
+ else if (funcion == 8)
+ animacion_8();
+ else if (funcion == 9)
+ animacion_9();
+ else if (funcion == 10)
+ animacion_10();
+ else if (funcion == 15)
+ animacion_15();
+ else if (funcion == 16)
+ animacion_16();
+ else if (funcion == 17)
+ animacion_17();
+ else if (funcion == 19)
+ animacion_19();
+ else if (funcion == 20)
+ animacion_20();
+ else if (funcion == 21)
+ animacion_21();
+ else if (funcion == 23)
+ animacion_23();
+ else if (funcion == 28)
+ animacion_28();
+ else if (funcion == 29)
+ animacion_29();
+ else if (funcion == 30)
+ animacion_30();
+ else if (funcion == 31)
+ animacion_31();
+}
+
+void DrasculaEngine::habla_pianista(const char *dicho, const char *filename) {
+ int tiempou;
+ long tiempol;
+ int x_habla[4] = { 97, 145, 193, 241};
+ 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], 139, 228, 112, 47, 60,
+ dir_hare_dch, dir_zona_pantalla);
+ pon_hare();
+ actualiza_refresco();
+
+ if (con_voces == 0)
+ centra_texto(dicho, 221, 128);
+
+ VUELCA_PANTALLA(0, 0, 0, 0, 320, 200, dir_zona_pantalla);
+
+ pausa(3);
+
+ byte 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_borracho(const char *dicho, const char *filename) {
+ int tiempou;
+ long tiempol;
+
+ int x_habla[8] = { 1, 21, 41, 61, 81, 101, 121, 141 };
+ int cara;
+ int longitud;
+ longitud = strlen(dicho);
+
+ tiempol = _system->getMillis();
+ tiempou = (unsigned int)tiempol / 2;
+ _rnd->setSeed(tiempou);
+
+ lee_dibujos("an11y13.alg");
+ descomprime_dibujo(dir_hare_frente, 1);
+
+ flags[13] = 1;
+
+bebiendo:
+
+ if (flags[12] == 1) {
+ refresca_pantalla();
+ VUELCA_PANTALLA(0, 0, 0, 0, 320, 200, dir_zona_pantalla);
+ goto bebiendo;
+ }
+
+ buffer_teclado();
+
+ color_abc(VERDE_OSCURO);
+
+ if (hay_sb == 1) {
+ sku = new Common::File;
+ sku->open(filename);
+ if (!sku->isOpen()) {
+ error("no puedo abrir archivo de voz\n");
+ }
+ 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], 29, 177, 50, 19, 19, dir_hare_frente, dir_zona_pantalla);
+ pon_hare();
+ actualiza_refresco();
+
+ if (con_voces == 0)
+ centra_texto(dicho, 181, 54);
+
+ VUELCA_PANTALLA(0, 0, 0, 0, 320, 200, dir_zona_pantalla);
+
+ pausa(3);
+
+ byte 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);
+
+ flags[13] = 0;
+ lee_dibujos("96.alg");
+ descomprime_dibujo(dir_hare_frente, 1);
+
+ if (music_status() == 0 && flags[11] == 0)
+ playmusic(musica_room);
+}
+
+void DrasculaEngine::suma_objeto(int osj) {
+ int h, puesto = 0;
+
+ for (h = 1; h < 43; h++) {
+ if (objetos_que_tengo[h] == osj)
+ puesto = 1;
+ }
+
+ if (puesto == 0) {
+ for (h = 1; h < 43; h++) {
+ if (objetos_que_tengo[h] == 0) {
+ objetos_que_tengo[h]=osj;
+ puesto = 1;
+ break;
+ }
+ }
+ }
+}
+
+void DrasculaEngine::fin_sound_corte() {
+ if (hay_sb == 1) {
+ ctvd_stop();
+ delete sku;
+ ctvd_terminate();
+ }
+}
+
+void DrasculaEngine::MusicFadeout() {
+ int org_vol = _mixer->getVolumeForSoundType(Audio::Mixer::kMusicSoundType);
+ for (;;) {
+ int vol = _mixer->getVolumeForSoundType(Audio::Mixer::kMusicSoundType);
+ vol -= 10;
+ if (vol < 0)
+ vol = 0;
+ _mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, vol);
+ if (vol == 0)
+ break;
+ update_events();
+ _system->updateScreen();
+ _system->delayMillis(50);
+ }
+ AudioCD.stop();
+ _system->delayMillis(100);
+ _mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, org_vol);
+}
+
+void DrasculaEngine::ctvd_end() {
+ _mixer->stopHandle(_soundHandle);
+}
+
+void DrasculaEngine::ctvd_stop() {
+ _mixer->stopHandle(_soundHandle);
+}
+
+void DrasculaEngine::ctvd_terminate() {
+// _mixer->stopHandle(_soundHandle);
+}
+
+void DrasculaEngine::ctvd_speaker(int flag) {}
+
+void DrasculaEngine::ctvd_output(Common::File *file_handle) {}
+
+void DrasculaEngine::ctvd_init(int b) {
+ int soundSize = sku->size();
+ byte *soundData = (byte *)malloc(soundSize);
+ sku->seek(32);
+ sku->read(soundData, soundSize);
+ _mixer->playRaw(Audio::Mixer::kSFXSoundType, &_soundHandle, soundData, soundSize - 64,
+ 11025, Audio::Mixer::FLAG_AUTOFREE | Audio::Mixer::FLAG_UNSIGNED);
+}
+
+int DrasculaEngine::LookForFree() {
+ return _mixer->isSoundHandleActive(_soundHandle);
+}
+
+void DrasculaEngine::actualiza_datos() {
+ if (!strcmp(num_room,"2.alg") && flags[40] == 0)
+ visible[3] = 0;
+ else if (!strcmp(num_room, "3.alg") && flags[3] == 1)
+ visible[8] = 0;
+ else if (!strcmp(num_room, "6.alg") && flags[1] == 1 && flags[10] == 0) {
+ visible[2] = 0;
+ visible[4] = 1;
+ } else if (!strcmp(num_room, "7.alg") && flags[35] == 1)
+ visible[3] = 0;
+ else if (!strcmp(num_room, "14.alg") && flags[5] == 1)
+ visible[4] = 0;
+ else if (!strcmp(num_room, "18.alg") && flags[28] == 1)
+ visible[2] = 0;
+}
+
+void DrasculaEngine::animacion_1_2() {
+ lleva_al_hare(178, 121);
+ lleva_al_hare(169, 135);
+}
+
+void DrasculaEngine::animacion_2_2() {
+ int n, x=0;
+
+ sentido_hare = 0;
+ DIBUJA_FONDO(0, 0, 0, 0, 320, 200, dir_dibujo1, dir_zona_pantalla);
+ pon_hare();
+ actualiza_refresco();
+ VUELCA_PANTALLA(0, 0, 0, 0, 320, 200, dir_zona_pantalla);
+ lee_dibujos("an2_1.alg");
+ descomprime_dibujo(dir_hare_frente, 1);
+ lee_dibujos("an2_2.alg");
+ descomprime_dibujo(dir_hare_dch, 1);
+
+ DIBUJA_FONDO(0, 0, 0, 0, 320, 200, dir_dibujo1, dir_zona_pantalla);
+ DIBUJA_FONDO(1, 1, 201, 87, 50, 52, dir_hare_frente, dir_zona_pantalla);
+ VUELCA_PANTALLA(0, 0, 0, 0, 320, 200, dir_zona_pantalla);
+ for (n = 0; n < 6; n++) {
+ x++;
+ DIBUJA_FONDO(x, 1, 201, 87, 50, 52, dir_hare_frente, dir_zona_pantalla);
+ VUELCA_PANTALLA(201,87, 201,87, 50,52, dir_zona_pantalla);
+ x = x + 50;
+ pausa(3);
+ }
+
+ x = 0;
+
+ for (n = 0; n < 6; n++) {
+ x++;
+ DIBUJA_FONDO(x, 55, 201, 87, 50, 52, dir_hare_frente, dir_zona_pantalla);
+ VUELCA_PANTALLA(201, 87, 201, 87, 50, 52, dir_zona_pantalla);
+ x = x + 50;
+ pausa(3);
+ }
+
+ x = 0;
+
+ for (n = 0; n < 6; n++){
+ x++;
+ DIBUJA_FONDO(x, 109, 201, 87, 50, 52, dir_hare_frente, dir_zona_pantalla);
+ VUELCA_PANTALLA(201, 87, 201, 87, 50, 52, dir_zona_pantalla);
+ x = x + 50;
+ pausa(3);
+ }
+
+ x = 0;
+ comienza_sound("s2.als");
+
+ for (n = 0; n < 6; n++) {
+ x++;
+ DIBUJA_FONDO(x, 1, 201, 87, 50, 52, dir_hare_dch, dir_zona_pantalla);
+ VUELCA_PANTALLA(201,87, 201,87, 50,52, dir_zona_pantalla);
+ x = x + 50;
+ pausa(3);
+ }
+
+ x = 0;
+
+ for (n = 0; n < 6; n++) {
+ x++;
+ DIBUJA_FONDO(x, 55, 201, 87, 50, 52, dir_hare_dch, dir_zona_pantalla);
+ VUELCA_PANTALLA(201, 87, 201, 87, 50, 52, dir_zona_pantalla);
+ x = x + 50;
+ pausa(3);
+ }
+ x = 0;
+
+ for (n = 0; n < 2; n++) {
+ x++;
+ DIBUJA_FONDO(x, 109, 201, 87, 50, 52, dir_hare_dch, dir_zona_pantalla);
+ VUELCA_PANTALLA(201, 87, 201, 87, 50, 52, dir_zona_pantalla);
+ x = x + 50;
+ pausa(3);
+ }
+
+ DIBUJA_FONDO(0, 0, 0, 0, 320, 200, dir_dibujo1, dir_zona_pantalla);
+ VUELCA_PANTALLA(0, 0, 0, 0, 320, 200, dir_zona_pantalla);
+
+ fin_sound();
+
+ pausa (4);
+
+ comienza_sound("s1.als");
+ hipo_sin_nadie(12);
+ fin_sound();
+ }
+
+void DrasculaEngine::animacion_3_2() {
+ lleva_al_hare(163, 106);
+ lleva_al_hare(287, 101);
+ sentido_hare = 0;
+}
+
+void DrasculaEngine::animacion_4_2() {
+ stopmusic();
+ flags[9] = 1;
+
+ pausa(12);
+ hablar(TEXTD56, "d56.als" );
+ pausa(8);
+
+ borra_pantalla();
+ lee_dibujos("ciego1.alg");
+ descomprime_dibujo(dir_dibujo1, MEDIA);
+ lee_dibujos("ciego2.alg");
+ descomprime_dibujo(dir_dibujo3, 1);
+ lee_dibujos("ciego3.alg");
+ descomprime_dibujo(dir_hare_dch, 1);
+ lee_dibujos("ciego4.alg");
+ descomprime_dibujo(dir_hare_fondo, 1);
+ lee_dibujos("ciego5.alg");
+ descomprime_dibujo(dir_hare_frente, 1);
+
+ DIBUJA_FONDO(0, 0, 0, 0, 320, 200, dir_dibujo1, dir_zona_pantalla);
+ VUELCA_PANTALLA(0, 0, 0, 0, 320, 200, dir_zona_pantalla);
+
+ pausa(10);
+
+ habla_ciego(TEXTD68, "d68.als", "44472225500022227555544444664447222550002222755554444466");
+ pausa(5);
+ habla_hacker(TEXTD57, "d57.als");
+ pausa(6);
+ habla_ciego(TEXTD69,"d69.als","444722255000222275555444446655033336666664464402256555005504450005446");
+ pausa(4);
+ habla_hacker(TEXTD58,"d58.als");
+ habla_ciego(TEXTD70,"d70.als", "4447222550002222755554444466550333226220044644550044755665500440006655556666655044744656550446470046");
+ delay(14);
+ habla_hacker(TEXTD59,"d59.als");
+ habla_ciego(TEXTD71,"d71.als", "550330227556444744446660004446655544444722255000222275555444446644444");
+ habla_hacker(TEXTD60,"d60.als");
+ habla_ciego(TEXTD72,"d72.als", "55033022755644455550444744400044504447222550002222755554444466000");
+ habla_hacker(TEXTD61,"d61.als");
+ habla_ciego(TEXTD73,"d73.als", "55033022755644444447227444466644444722255000222275555444446664404446554440055655022227500544446044444446");
+ habla_hacker(TEXTD62,"d62.als");
+ habla_ciego(TEXTD74,"d74.als", "55033022755644444472244472225500022227555544444662550002222755444446666055522275550005550022200222000222666");
+ habla_hacker(TEXTD63,"d63.als");
+ habla_ciego(TEXTD75,"d75.als", "44447774444555500222205550444444466666225266444755444722255000222275555444446633223220044022203336227555770550444660557220553302224477777550550550222635533000662220002275572227025555");
+ DIBUJA_FONDO(0, 0, 0, 0, 320, 200, dir_dibujo1, dir_zona_pantalla);
+ VUELCA_PANTALLA(0, 0, 0, 0, 320, 200, dir_zona_pantalla);
+ _system->delayMillis(1);
+ habla_hacker(TEXTD64, "d64.als");
+ habla_ciego(TEXTD76, "d76.als", "5555500004445550330244472225500022227555544444662755644446666005204402266222003332222774440446665555005550335544444");
+
+ DIBUJA_FONDO(0, 0, 0, 0, 320, 200, dir_dibujo1, dir_zona_pantalla);
+ VUELCA_PANTALLA(0, 0, 0, 0, 320, 200, dir_zona_pantalla);
+
+ pausa(14);
+
+ borra_pantalla();
+
+ playmusic(musica_room);
+ lee_dibujos("9.alg");
+ descomprime_dibujo(dir_dibujo1, MEDIA);
+ lee_dibujos("aux9.alg");
+ descomprime_dibujo(dir_dibujo3, 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);
+ sin_verbo();
+
+ flags[9] = 0;
+ flags[4] = 1;
+}
+
+void DrasculaEngine::animacion_8() {
+ habla_pianista(TEXTP6, "P6.als");
+ hablar(TEXT358, "358.als");
+ habla_pianista(TEXTP7, "P7.als");
+ habla_pianista(TEXTP8, "P8.als");
+}
+
+void DrasculaEngine::animacion_9() {
+ habla_pianista(TEXTP9, "P9.als");
+ habla_pianista(TEXTP10, "P10.als");
+ habla_pianista(TEXTP11, "P11.als");
+}
+
+void DrasculaEngine::animacion_10() {
+ habla_pianista(TEXTP12, "P12.als");
+ hablar(TEXT361, "361.als");
+ pausa(40);
+ habla_pianista(TEXTP13, "P13.als");
+ hablar(TEXT362, "362.als");
+ habla_pianista(TEXTP14, "P14.als");
+ hablar(TEXT363, "363.als");
+ habla_pianista(TEXTP15, "P15.als");
+ hablar(TEXT364, "364.als");
+ habla_pianista(TEXTP16, "P16.als");
+}
+
+void DrasculaEngine::animacion_14() {
+ int n, pos_cabina[6];
+ int l = 0;
+
+ lee_dibujos("an14_2.alg");
+ 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;
+
+ for (n = -160; n <= 0; n = n + 5 + l) {
+ DIBUJA_FONDO(0, 0, 0, 0, 320, 200, dir_dibujo1, dir_zona_pantalla);
+ actualiza_refresco_antes();
+ pon_hare();
+ pon_vb();
+ pos_cabina[3] = n;
+ DIBUJA_BLOQUE_CUT(pos_cabina, dir_hare_fondo, dir_zona_pantalla);
+ actualiza_refresco();
+ VUELCA_PANTALLA(0, 0, 0, 0, 320, 200, dir_zona_pantalla);
+ l = l + 1;
+ }
+
+ flags[24] = 1;
+
+ descomprime_dibujo(dir_dibujo1, 1);
+
+ comienza_sound("s7.als");
+ hipo(15);
+
+ fin_sound();
+
+ lee_dibujos("99.alg");
+ descomprime_dibujo(dir_hare_fondo, 1);
+}
+
+void DrasculaEngine::animacion_15() {
+ habla_borracho(TEXTB8, "B8.als");
+ pausa(7);
+ habla_borracho(TEXTB9, "B9.als");
+ habla_borracho(TEXTB10, "B10.als");
+ habla_borracho(TEXTB11, "B11.als");
+}
+
+void DrasculaEngine::animacion_16() {
+ int l;
+
+ habla_borracho(TEXTB12, "B12.als");
+ hablar(TEXT371, "371.als");
+
+ borra_pantalla();
+
+ playmusic(32);
+ int key = getscan();
+ if (key != 0)
+ goto asco;
+
+ color_abc(VERDE_OSCURO);
+
+ lee_dibujos("his1.alg");
+ descomprime_dibujo(dir_dibujo1, MEDIA);
+ DIBUJA_FONDO(0, 0, 0, 0, 320, 200, dir_dibujo1, dir_zona_pantalla);
+ centra_texto(HIS1, 180, 180);
+ VUELCA_PANTALLA(0, 0, 0, 0, 320, 200, dir_zona_pantalla);
+ key = getscan();
+ if (key != 0)
+ goto asco;
+
+ _system->delayMillis(4);
+ key = getscan();
+ if (key != 0)
+ goto asco;
+
+ FundeAlNegro(1);
+ key = getscan();
+ if (key != 0)
+ goto asco;
+
+ borra_pantalla();
+ lee_dibujos("his2.alg");
+ 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);
+ key = getscan();
+ if (key != 0)
+ goto asco;
+
+ _system->delayMillis(4);
+ key = getscan();
+ if (key != 0)
+ goto asco;
+
+ FundeAlNegro(1);
+ key = getscan();
+ if (key != 0)
+ goto asco;
+
+ borra_pantalla();
+ lee_dibujos("his3.alg");
+ descomprime_dibujo(dir_dibujo1, MEDIA);
+ DIBUJA_FONDO(0, 0, 0, 0, 320, 200, dir_dibujo1, dir_zona_pantalla);
+ centra_texto(HIS3, 180, 180);
+ VUELCA_PANTALLA(0, 0, 0, 0, 320, 200, dir_zona_pantalla);
+ key = getscan();
+ if (key != 0)
+ goto asco;
+
+ _system->delayMillis(4);
+ key = getscan();
+ if (key != 0)
+ goto asco;
+
+ FundeAlNegro(1);
+
+ borra_pantalla();
+ lee_dibujos("his4_1.alg");
+ descomprime_dibujo(dir_dibujo1, MEDIA);
+ lee_dibujos("his4_2.alg");
+ descomprime_dibujo(dir_dibujo3, 1);
+
+ DIBUJA_FONDO(0, 0, 0, 0, 320, 200, dir_dibujo3, dir_zona_pantalla);
+ centra_texto(HIS1, 180, 180);
+ VUELCA_PANTALLA(0, 0, 0, 0, 320, 200, dir_zona_pantalla);
+ key = getscan();
+ if (key != 0)
+ goto asco;
+
+ _system->delayMillis(4);
+ key = getscan();
+ if (key != 0)
+ goto asco;
+
+ 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);
+ key = getscan();
+ if (key != 0)
+ goto asco;
+ }
+
+ pausa(5);
+ FundeAlNegro(2);
+ borra_pantalla();
+
+asco:
+ lee_dibujos(pantalla_disco);
+ descomprime_dibujo(dir_dibujo3, 1);
+ lee_dibujos(num_room);
+ descomprime_dibujo(dir_dibujo1, MEDIA);
+ Negro();
+ refresca_pantalla();
+ VUELCA_PANTALLA(0, 0, 0, 0, 320, 200, dir_zona_pantalla);
+ FundeDelNegro(0);
+ if (musica_room != 0)
+ playmusic(musica_room);
+ else
+ stopmusic();
+}
+
+void DrasculaEngine::animacion_17() {
+ habla_borracho(TEXTB13, "B13.als");
+ habla_borracho(TEXTB14, "B14.als");
+ flags[40] = 1;
+}
+
+void DrasculaEngine::animacion_19() {
+ habla_vbpuerta(TEXTVB5, "VB5.als");
+}
+
+void DrasculaEngine::animacion_20() {
+ habla_vbpuerta(TEXTVB7, "VB7.als");
+ habla_vbpuerta(TEXTVB8, "VB8.als");
+ hablar(TEXT383, "383.als");
+ habla_vbpuerta(TEXTVB9, "VB9.als");
+ hablar(TEXT384, "384.als");
+ habla_vbpuerta(TEXTVB10, "VB10.als");
+ hablar(TEXT385, "385.als");
+ habla_vbpuerta(TEXTVB11, "VB11.als");
+ if (flags[23] == 0) {
+ hablar(TEXT350, "350.als");
+ habla_vbpuerta(TEXTVB57, "VB57.als");
+ } else {
+ hablar(TEXT386, "386.als");
+ habla_vbpuerta(TEXTVB12, "VB12.als");
+ flags[18] = 0;
+ flags[14] = 1;
+ abre_puerta(15, 1);
+ sal_de_la_habitacion(1);
+ animacion_23();
+ sal_de_la_habitacion(0);
+ flags[21] = 0;
+ flags[24] = 0;
+ sentido_vb = 1;
+ vb_x = 120;
+
+ rompo_y_salgo = 1;
+ }
+}
+
+void DrasculaEngine::animacion_21() {
+ habla_vbpuerta(TEXTVB6, "VB6.als");
+}
+
+void DrasculaEngine::animacion_23() {
+ lee_dibujos("an24.alg");
+ descomprime_dibujo(dir_hare_frente, 1);
+
+ flags[21] = 1;
+
+ if (flags[25] == 0) {
+ habla_vb(TEXTVB13, "VB13.als");
+ habla_vb(TEXTVB14, "VB14.als");
+ pausa(10);
+ hablar(TEXT387, "387.als");
+ }
+
+ habla_vb(TEXTVB15, "VB15.als");
+ lleva_vb(42);
+ sentido_vb = 1;
+ habla_vb(TEXTVB16, "VB16.als");
+ sentido_vb = 2;
+ lleva_al_hare(157, 147);
+ lleva_al_hare(131, 149);
+ sentido_hare = 0;
+ animacion_14();
+ if (flags[25] == 0)
+ habla_vb(TEXTVB17, "VB17.als");
+ pausa(8);
+ sentido_vb = 1;
+ habla_vb(TEXTVB18, "VB18.als");
+
+ if (flags[29] == 0)
+ animacion_23_anexo();
+ else
+ animacion_23_anexo2();
+
+ sentido_vb = 2;
+ animacion_25();
+ lleva_vb(99);
+
+ if (flags[29] == 0) {
+ habla_vb(TEXTVB19, "VB19.als");
+ if (flags[25] == 0) {
+ habla_vb(TEXTVB20,"VB20.als");
+ if (resta_objeto(7) == 0)
+ flags[30] = 1;
+ if (resta_objeto(18) == 0)
+ flags[31] = 1;
+ if (resta_objeto(19) == 0)
+ flags[32] = 1;
+ }
+ habla_vb(TEXTVB21, "VB21.als");
+ } else
+ animacion_27();
+
+ flags[25] = 1;
+ rompo_y_salgo = 1;
+}
+
+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};
+
+ lee_dibujos("an23.alg");
+ descomprime_dibujo(dir_hare_fondo, 1);
+
+ for (n = 0; n < 34; n++) {
+ DIBUJA_BLOQUE(p_x, p_y, p_x, p_y, 36, 74, dir_dibujo1, dir_zona_pantalla);
+ DIBUJA_BLOQUE(x[n], y[n], p_x, p_y, 36, 74, dir_hare_fondo, dir_zona_pantalla);
+ actualiza_refresco();
+ VUELCA_PANTALLA(p_x, p_y, p_x, p_y, 36, 74, dir_zona_pantalla);
+ pausa(5);
+ }
+
+ lee_dibujos("99.alg");
+ descomprime_dibujo(dir_hare_fondo, 1);
+}
+
+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};
+
+ pausa(50);
+
+ lee_dibujos("an23_2.alg");
+ descomprime_dibujo(dir_hare_fondo, 1);
+
+ for (n = 0; n < 14; n++) {
+ DIBUJA_BLOQUE(p_x, p_y, p_x, p_y, 33, 71, dir_dibujo1, dir_zona_pantalla);
+ DIBUJA_BLOQUE(x[n], y[n], p_x, p_y, 33, 71, dir_hare_fondo, dir_zona_pantalla);
+ actualiza_refresco();
+ VUELCA_PANTALLA(p_x,p_y, p_x,p_y, 33,71, dir_zona_pantalla);
+ pausa(5);
+ }
+
+ lee_dibujos("99.alg");
+ descomprime_dibujo(dir_hare_fondo,1);
+}
+
+void DrasculaEngine::animacion_25() {
+ int n, pos_cabina[6];
+
+ lee_dibujos("an14_2.alg");
+ descomprime_dibujo(dir_hare_fondo, 1);
+ lee_dibujos("18.alg");
+ descomprime_dibujo(dir_dibujo1, 1);
+
+ pos_cabina[0] = 150;
+ pos_cabina[1] = 6;
+ pos_cabina[2] = 69;
+ pos_cabina[3] = 0;
+ pos_cabina[4] = 158;
+ pos_cabina[5] = 161;
+
+ flags[24] = 0;
+
+ comienza_sound("s6.als");
+
+ for (n = 0; n >= -160; n = n - 8) {
+ DIBUJA_FONDO(0, 0, 0, 0, 320, 200, dir_dibujo1, dir_zona_pantalla);
+
+ actualiza_refresco_antes();
+ pon_hare();
+ pon_vb();
+
+ pos_cabina[3] = n;
+
+ DIBUJA_BLOQUE_CUT(pos_cabina, dir_hare_fondo, dir_zona_pantalla);
+
+ actualiza_refresco();
+ VUELCA_PANTALLA(0,0, 0,0, 320,200, dir_zona_pantalla);
+ }
+
+ fin_sound();
+
+ lee_dibujos("99.alg");
+ descomprime_dibujo(dir_hare_fondo, 1);
+}
+
+void DrasculaEngine::animacion_27() {
+ flags[22] = 1;
+
+ sin_verbo();
+ resta_objeto(23);
+ suma_objeto(11);
+
+ habla_vb(TEXTVB23, "VB23.als");
+ habla_vb(TEXTVB24, "VB24.als");
+ if (flags[30] == 1)
+ suma_objeto(7);
+ if (flags[31] == 1)
+ suma_objeto(18);
+ if (flags[32] == 1)
+ suma_objeto(19);
+ habla_vb(TEXTVB25,"VB25.als");
+ habla_vb(TEXTVB26,"VB26.als");
+}
+
+void DrasculaEngine::animacion_28(){
+ habla_vb(TEXTVB27, "VB27.als");
+ habla_vb(TEXTVB28, "VB28.als");
+ habla_vb(TEXTVB29, "VB29.als");
+ habla_vb(TEXTVB30, "VB30.als");
+}
+
+void DrasculaEngine::animacion_29(){
+ if (flags[33] == 0) {
+ habla_vb(TEXTVB32, "VB32.als");
+ hablar(TEXT398, "398.als");
+ habla_vb(TEXTVB33, "VB33.als");
+ hablar(TEXT399, "399.als");
+ habla_vb(TEXTVB34, "VB34.als");
+ habla_vb(TEXTVB35, "VB35.als");
+ hablar(TEXT400, "400.als");
+ habla_vb(TEXTVB36, "VB36.als");
+ habla_vb(TEXTVB37, "VB37.als");
+ hablar(TEXT386, "386.als");
+ habla_vb(TEXTVB38, "VB38.als");
+ habla_vb(TEXTVB39, "VB39.als");
+ hablar(TEXT401, "401.als");
+ habla_vb(TEXTVB40, "VB40.als");
+ habla_vb(TEXTVB41, "VB41.als");
+ flags[33] = 1;
+ } else
+ habla_vb(TEXTVB43, "VB43.als");
+
+ hablar(TEXT402, "402.als");
+ habla_vb(TEXTVB42, "VB42.als");
+
+ if (flags[38] == 0) {
+ hablar(TEXT403, "403.als");
+ rompo_y_salgo = 1;
+ } else
+ hablar(TEXT386, "386.als");
+}
+
+void DrasculaEngine::animacion_30(){
+ habla_vb(TEXTVB31, "VB31.als");
+ hablar(TEXT396, "396.als");
+}
+
+void DrasculaEngine::animacion_31(){
+ habla_vb(TEXTVB44, "VB44.als");
+ lleva_vb(-50);
+ pausa(15);
+ lleva_al_hare(159, 140);
+ lee_dibujos("99.alg");
+ descomprime_dibujo(dir_hare_fondo, 1);
+ sentido_hare = 2;
+ refresca_pantalla();
+ VUELCA_PANTALLA(0, 0, 0, 0, 320, 200, dir_zona_pantalla);
+ pausa(78);
+ sentido_hare = 0;
+ refresca_pantalla();
+ VUELCA_PANTALLA(0, 0, 0, 0, 320, 200, dir_zona_pantalla);
+ pausa(22);
+ hablar(TEXT406, "406.als");
+ lleva_vb(98);
+ habla_vb(TEXTVB45, "VB45.als");
+ habla_vb(TEXTVB46, "VB46.als");
+ habla_vb(TEXTVB47, "VB47.als");
+ hablar(TEXT407, "407.als");
+ habla_vb(TEXTVB48, "VB48.als");
+ habla_vb(TEXTVB49, "VB49.als");
+ hablar(TEXT408, "408.als");
+ habla_vb(TEXTVB50, "VB50.als");
+ habla_vb(TEXTVB51, "VB51.als");
+ hablar(TEXT409, "409.als");
+ habla_vb(TEXTVB52, "VB52.als");
+ habla_vb(TEXTVB53, "VB53.als");
+ pausa(12);
+ habla_vb(TEXTVB54, "VB54.als");
+ habla_vb(TEXTVB55, "VB55.als");
+ hablar(TEXT410, "410.als");
+ habla_vb(TEXTVB56, "VB56.als");
+
+ rompo_y_salgo = 1;
+
+ flags[38] = 0;
+ flags[36] = 1;
+ sin_verbo();
+ resta_objeto(8);
+ resta_objeto(13);
+ resta_objeto(15);
+ resta_objeto(16);
+ resta_objeto(17);
+ suma_objeto(20);
+}
+
+void DrasculaEngine::animacion_35() {
+ int n, x = 0;
+
+ lleva_al_hare(96, 165);
+ lleva_al_hare(79, 165);
+
+ refresca_pantalla();
+ VUELCA_PANTALLA(0, 0, 0, 0, 320, 200, dir_zona_pantalla);
+
+ lee_dibujos("an35_1.alg");
+ descomprime_dibujo(dir_hare_fondo, 1);
+ lee_dibujos("an35_2.alg");
+ descomprime_dibujo(dir_hare_frente, 1);
+
+ for (n = 0; n < 6; n++) {
+ x++;
+ DIBUJA_FONDO(x, 1, 70, 90, 46, 80, dir_hare_fondo, dir_zona_pantalla);
+ VUELCA_PANTALLA(70,90, 70,90, 46,80,dir_zona_pantalla);
+ x = x + 46;
+ pausa(3);
+ }
+ x = 0;
+
+ for (n = 0; n < 6; n++) {
+ x++;
+ DIBUJA_FONDO(x, 82, 70, 90, 46, 80, dir_hare_fondo, dir_zona_pantalla);
+ VUELCA_PANTALLA(70, 90, 70, 90, 46, 80, dir_zona_pantalla);
+ x = x + 46;
+ pausa(3);
+ }
+
+ x = 0;
+
+ for (n = 0; n < 6; n++) {
+ x++;
+ DIBUJA_FONDO(x, 1, 70, 90, 46, 80, dir_hare_frente, dir_zona_pantalla);
+ VUELCA_PANTALLA(70, 90, 70, 90, 46, 80, dir_zona_pantalla);
+
+ x = x + 46;
+
+ pausa(3);
+ }
+ x = 0;
+
+ for (n = 0; n < 2; n++) {
+ x++;
+ DIBUJA_FONDO(x, 82, 70, 90, 46, 80, dir_hare_frente, dir_zona_pantalla);
+ VUELCA_PANTALLA(70, 90, 70,90, 46, 80,dir_zona_pantalla);
+ x = x + 46;
+ pausa(3);
+ }
+
+ DIBUJA_FONDO(0, 0, 0, 0, 320, 200, dir_dibujo1, dir_zona_pantalla);
+
+ VUELCA_PANTALLA(0, 0, 0, 0, 320, 200, dir_zona_pantalla);
+
+ pausa(19);
+
+ comienza_sound("s1.als");
+ hipo_sin_nadie(18);
+ fin_sound();
+
+ pausa(10);
+
+ FundeAlNegro(2);
+
+ // TODO
+ salir_al_dos(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 cara;
+
+ int longitud;
+ longitud = strlen(dicho);
+
+ tiempol = _system->getMillis();
+ tiempou = (unsigned int)tiempol / 2;
+ _rnd->setSeed(tiempou);
+
+ buffer_teclado();
+
+ color_abc(VON_BRAUN);
+
+ 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);
+ }
+
+ DIBUJA_FONDO(vb_x + 5, 64, ANCHOBJ + 1, 0, 25, 27, dir_dibujo1, dir_dibujo3);
+
+bucless:
+
+ if (sentido_vb == 1) {
+ cara = _rnd->getRandomNumber(5);
+ DIBUJA_FONDO(0, 0, 0, 0, 320, 200, dir_dibujo1, dir_zona_pantalla);
+
+ pon_hare();
+ pon_vb();
+
+ DIBUJA_FONDO(ANCHOBJ + 1, 0, vb_x + 5, 64, 25, 27, dir_dibujo3, dir_zona_pantalla);
+ DIBUJA_BLOQUE(x_habla[cara], 34, vb_x + 5, 64, 25, 27, dir_hare_frente, dir_zona_pantalla);
+ actualiza_refresco();
+ }
+
+ if (con_voces == 0)
+ centra_texto(dicho, vb_x, 66);
+
+ 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);
+ if (music_status() == 0 && flags[11] == 0 && musica_room != 0)
+ playmusic(musica_room);
+}
+
+void DrasculaEngine::habla_vbpuerta(const char *dicho, const char *filename) {
+ int tiempou;
+ long tiempol;
+
+ int longitud;
+ longitud = strlen(dicho);
+
+ tiempol = _system->getMillis();
+ tiempou = (unsigned int)tiempol / 2;
+ _rnd->setSeed(tiempou);
+
+ buffer_teclado();
+
+ color_abc(VON_BRAUN);
+
+ 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:
+
+ refresca_pantalla();
+ if (con_voces == 0)
+ centra_texto(dicho, 150, 80);
+ VUELCA_PANTALLA(0, 0, 0, 0, 320, 200, dir_zona_pantalla);
+
+ 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);
+ if (music_status() == 0 && flags[11] == 0 && musica_room != 0)
+ playmusic(musica_room);
+}
+
+void DrasculaEngine::habla_ciego(const char *dicho, const char *filename, const char *sincronia) {
+ byte *num_cara;
+ int p;
+ int pos_ciego[6];
+ int cara = 0;
+
+ int longitud;
+ longitud = strlen(dicho);
+
+ buffer_teclado();
+
+ 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);
+
+ 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);
+ }
+
+ pos_ciego[1] = 2;
+ pos_ciego[2] = 73;
+ pos_ciego[3] = 1;
+ pos_ciego[4] = 126;
+ pos_ciego[5] = 149;
+
+bucless:
+ DIBUJA_FONDO(0, 0, 0, 0, 320, 200, dir_dibujo1, dir_zona_pantalla);
+ pos_ciego[5] = 149;
+ if (sincronia[p] == '0')
+ cara = 0;
+ if (sincronia[p] == '1')
+ cara = 1;
+ if (sincronia[p] == '2')
+ cara = 2;
+ if (sincronia[p] == '3')
+ cara = 3;
+ if (sincronia[p] == '4')
+ cara = 4;
+ if (sincronia[p] == '5')
+ cara = 5;
+ if (sincronia[p] == '6')
+ cara = 6;
+ if (sincronia[p] == '7')
+ cara = 7;
+
+ if (cara == 0 || cara == 2 || cara == 4 || cara == 6)
+ pos_ciego[0] = 1;
+ else
+ pos_ciego[0] = 132;
+
+ if (cara == 0)
+ num_cara = dir_dibujo3;
+ else if (cara == 1)
+ num_cara = dir_dibujo3;
+ else if (cara == 2)
+ num_cara = dir_hare_dch;
+ else if (cara == 3)
+ num_cara = dir_hare_dch;
+ else if (cara == 4)
+ num_cara = dir_hare_fondo;
+ else if (cara == 5)
+ num_cara = dir_hare_fondo;
+ else {
+ num_cara = dir_hare_frente;
+ pos_ciego[5] = 146;
+ }
+
+ DIBUJA_BLOQUE_CUT( pos_ciego, num_cara, dir_zona_pantalla);
+
+ if (con_voces == 0)
+ centra_texto(dicho, 310, 71);
+
+ VUELCA_PANTALLA(0, 0, 0, 0, 320, 200, dir_zona_pantalla);
+ pausa(2);
+ p++;
+
+ 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;
+ }
+}
+
+void DrasculaEngine::habla_hacker(const char *dicho, const char *filename) {
+ int tiempou;
+ long tiempol;
+
+ int longitud;
+ longitud = strlen(dicho);
+
+ tiempol = _system->getMillis();
+ tiempou = (unsigned int)tiempol / 2;
+ _rnd->setSeed(tiempou);
+
+ buffer_teclado();
+
+ DIBUJA_FONDO(0, 0, 0, 0, 320, 200, dir_dibujo1, dir_zona_pantalla);
+ VUELCA_PANTALLA(0, 0, 0, 0, 320, 200, dir_zona_pantalla);
+
+ 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:
+ if (con_voces == 0)
+ centra_texto(dicho, 156, 170);
+ VUELCA_PANTALLA(0, 0, 0, 0, 320, 200, dir_zona_pantalla);
+
+ int key = getscan();
+ if (key!=0)
+ ctvd_stop();
+ if (hay_sb == 1) {
+ if (LookForFree() != 0)
+ goto bucless;
+ delete sku;
+ ctvd_terminate();
+ } else {
+ longitud = longitud - 2;
+ if (longitud > 0)
+ goto bucless;
+ }
+
+ key = 0;
+}
+
+void DrasculaEngine::anda_pabajo() {
+ direccion_hare = 4;
+ sentido_hare = 3;
+ paso_x = 0;
+}
+
+void DrasculaEngine::anda_parriba() {
+ direccion_hare = 0;
+ sentido_hare = 2;
+ paso_x = 0;
+}
+
+void DrasculaEngine::pon_vb() {
+ int pos_vb[6];
+
+ if (vb_se_mueve == 0) {
+ pos_vb[0] = 256;
+ pos_vb[1] = 129;
+ pos_vb[2] = vb_x;
+ pos_vb[3] = 66;
+ pos_vb[4] = 33;
+ pos_vb[5] = 69;
+ if (sentido_vb == 0)
+ pos_vb[0] = 222;
+ else if (sentido_vb == 1)
+ pos_vb[0] = 188;
+ } else {
+ pos_vb[2] = vb_x;
+ pos_vb[3] = 66;
+ pos_vb[4] = 28;
+ pos_vb[5] = 68;
+
+ if (sentido_vb == 0) {
+ pos_vb[0] = frame_vb;
+ pos_vb[1] = 62;
+ } else {
+ pos_vb[0] = frame_vb;
+ pos_vb[1] = 131;
+ }
+
+ frame_vb = frame_vb + 29;
+ if (frame_vb > 146)
+ frame_vb = 1;
+ }
+
+ DIBUJA_BLOQUE_CUT(pos_vb, dir_hare_frente, dir_zona_pantalla);
+}
+
+void DrasculaEngine::lleva_vb(int punto_x) {
+ if (punto_x < vb_x)
+ sentido_vb = 0;
+ else
+ sentido_vb = 1;
+
+ vb_se_mueve = 1;
+
+ for (;;) {
+ refresca_pantalla();
+ VUELCA_PANTALLA(0, 0, 0, 0, 320, 200, dir_zona_pantalla);
+ if (sentido_vb == 0) {
+ vb_x = vb_x - 5;
+ if (vb_x <= punto_x)
+ break;
+ } else {
+ vb_x = vb_x + 5;
+ if (vb_x >= punto_x)
+ break;
+ }
+ pausa(5);
+ }
+
+ vb_se_mueve = 0;
+}
+
+void DrasculaEngine::hipo_sin_nadie(int contador){
+ int y = 0, sentido = 0;
+ contador = contador;
+
+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 (sentido == 0)
+ y++;
+ else
+ y--;
+ if (y == 2)
+ sentido = 1;
+ if (y == 0)
+ sentido = 0;
+ if (contador > 0)
+ goto comienza;
+
+ 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::abre_puerta(int nflag, int n_puerta) {
+ if (flags[nflag] == 0) {
+ comienza_sound("s3.als");
+ flags[nflag] = 1;
+ if (n_puerta != NO_PUERTA)
+ puertas_cerradas(n_puerta);
+ refresca_pantalla();
+ VUELCA_PANTALLA(0, 0, 0, 0, 320, 200, dir_zona_pantalla);
+ fin_sound();
+ sin_verbo();
+ }
+}
+
+void DrasculaEngine::mapa() {
+ int l, veo = 0;
+
+ 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;
+ }
+ }
+
+ if (veo == 0)
+ hay_nombre = 0;
+}
+
+void DrasculaEngine::refresca_1_antes() {
+ int cambio_col_antes = cambio_de_color;
+
+ if (hare_x > 98 && hare_x < 153)
+ cambio_de_color = 1;
+ else
+ cambio_de_color = 0;
+
+ if (cambio_col_antes != cambio_de_color && cambio_de_color == 1)
+ hare_oscuro();
+ if (cambio_col_antes != cambio_de_color && cambio_de_color == 0)
+ hare_claro();
+
+ if (flags[8] == 0)
+ DIBUJA_FONDO(2, 158, 208, 67, 27, 40, dir_dibujo3, dir_zona_pantalla);
+}
+
+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};
+
+ if (frame_murcielago == 41)
+ frame_murcielago = 0;
+
+ pos_murci[0] = murci_x[frame_murcielago];
+ pos_murci[1] = murci_y[frame_murcielago];
+
+ if (frame_murcielago < 22) {
+ pos_murci[4] = 37;
+ pos_murci[5] = 21;
+ } else if (frame_murcielago > 27) {
+ pos_murci[4] = 57;
+ pos_murci[5] = 36;
+ } else {
+ pos_murci[4] = 47;
+ pos_murci[5] = 22;
+ }
+
+ pos_murci[2] = 239;
+ pos_murci[3] = 19;
+
+ DIBUJA_BLOQUE_CUT(pos_murci, dir_dibujo3, dir_zona_pantalla);
+ diferencia = vez() - conta_ciego_vez;
+ if (diferencia >= 6) {
+ frame_murcielago++;
+ conta_ciego_vez = vez();
+ }
+
+ DIBUJA_BLOQUE(29, 37, 58, 114, 57, 39, dir_dibujo3, dir_zona_pantalla);
+ mapa();
+}
+
+void DrasculaEngine::refresca_3_antes() {
+ if (flags[3] == 1)
+ DIBUJA_FONDO(258, 110, 85, 44, 23, 53, dir_dibujo3, dir_zona_pantalla);
+}
+
+void DrasculaEngine::refresca_3() {
+ if (hare_y + alto_hare < 118)
+ DIBUJA_BLOQUE(129, 110, 194, 36, 126, 88, dir_dibujo3, dir_zona_pantalla);
+ DIBUJA_BLOQUE(47, 57, 277, 143, 43, 50, dir_dibujo3, dir_zona_pantalla);
+}
+
+void DrasculaEngine::refresca_4() {
+ int cambio_col_antes = cambio_de_color;
+ if (hare_x > 190)
+ cambio_de_color = 1;
+ else
+ cambio_de_color=0;
+
+ if (cambio_col_antes != cambio_de_color && cambio_de_color == 1)
+ hare_oscuro();
+ if (cambio_col_antes != cambio_de_color && cambio_de_color == 0)
+ hare_claro();
+}
+
+void DrasculaEngine::refresca_5() {
+ DIBUJA_BLOQUE(114, 130, 211, 87, 109, 69, dir_dibujo3, dir_zona_pantalla);
+}
+
+void DrasculaEngine::refresca_15() {
+ DIBUJA_BLOQUE(1, 154, 83, 122, 131, 44, dir_dibujo3, dir_zona_pantalla);
+}
+
+void DrasculaEngine::refresca_17() {
+ DIBUJA_BLOQUE(48, 135, 78, 139, 80, 30, dir_dibujo3, dir_zona_pantalla);
+}
+
+void DrasculaEngine::refresca_18() {
+ if (flags[24] == 1)
+ DIBUJA_BLOQUE(177, 1, 69, 29, 142, 130, dir_dibujo3, dir_zona_pantalla);
+ DIBUJA_BLOQUE(105, 132, 109, 108, 196, 65, dir_dibujo3, dir_zona_pantalla);
+}
+
+void DrasculaEngine::refresca_5_antes(){
+ if (flags[8] == 0)
+ DIBUJA_FONDO(256, 152, 208, 67, 27, 40, dir_dibujo3, dir_zona_pantalla);
+}
+
+void DrasculaEngine::refresca_6_antes() {
+ 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;
+
+ if (cambio_col_antes != cambio_de_color && cambio_de_color == 1)
+ hare_oscuro();
+ if (cambio_col_antes != cambio_de_color && cambio_de_color == 0)
+ hare_claro();
+
+ if (flags[1] == 0)
+ DIBUJA_FONDO(97, 117, 34, 148, 36, 31, dir_dibujo3, dir_zona_pantalla);
+ if (flags[0] == 0)
+ DIBUJA_FONDO(3, 103, 185, 69, 23, 76, dir_dibujo3, dir_zona_pantalla);
+ if (flags[2] == 0)
+ DIBUJA_FONDO(28, 100, 219, 72, 64, 97, dir_dibujo3, dir_zona_pantalla);
+}
+
+void DrasculaEngine::refresca_7_antes() {
+ if (flags[35] == 0)
+ DIBUJA_FONDO(1, 72, 158, 162, 19, 12, dir_dibujo3, dir_zona_pantalla);
+}
+
+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 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;
+ if (diferencia >= 11) {
+ frame_ciego++;
+ conta_ciego_vez = vez();
+ }
+ if (frame_ciego == 9)
+ frame_ciego = 0;
+ } else
+ frame_ciego=3;
+}
+
+void DrasculaEngine::refresca_12_antes() {
+ if (flags[16] == 0)
+ DIBUJA_FONDO(1, 131, 106, 117, 55, 68, dir_dibujo3, dir_zona_pantalla);
+}
+
+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 diferencia;
+
+ DIBUJA_FONDO(123, velas_y[frame_velas], 142, 14, 39, 13, dir_dibujo3, dir_zona_pantalla);
+ DIBUJA_FONDO(cirio_x[frame_velas], 146, 311, 80, 4, 8, dir_dibujo3, dir_zona_pantalla);
+
+ if (parpadeo == 5)
+ DIBUJA_FONDO(1, 149, 127, 52, 9, 5, dir_dibujo3, dir_zona_pantalla);
+ if (hare_x > 101 && hare_x < 155)
+ DIBUJA_FONDO(31, 138, 178, 51, 18, 16, dir_dibujo3, dir_zona_pantalla);
+ if (flags[11] == 0)
+ DIBUJA_FONDO(pianista_x[frame_piano], 157, 245, 130, 29, 42, dir_dibujo3, dir_zona_pantalla);
+ else if (flags[5] == 0)
+ DIBUJA_FONDO(145, 139, 228, 112, 47, 60, dir_hare_dch, dir_zona_pantalla);
+ else
+ DIBUJA_FONDO(165, 140, 229, 117, 43, 59, dir_dibujo3, dir_zona_pantalla);
+
+ 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;
+ if (diferencia > 6) {
+ if (flags[12] == 1) {
+ frame_borracho++;
+ if (frame_borracho == 8) {
+ frame_borracho = 0;
+ flags[12] = 0;
+ }
+ } else if ((_rnd->getRandomNumber(94) == 15) && (flags[13] == 0))
+ flags[12] = 1;
+
+ frame_velas++;
+ if (frame_velas == 3)
+ frame_velas = 0;
+ frame_piano++;
+ if (frame_piano == 9)
+ frame_piano = 0;
+ parpadeo = _rnd->getRandomNumber(10);
+ conta_ciego_vez=vez();
+ }
+}
+
+void DrasculaEngine::refresca_16_antes() {
+ if (flags[17] == 0)
+ DIBUJA_FONDO(1, 103, 24, 72, 33, 95, dir_dibujo3, dir_zona_pantalla);
+ if (flags[19] == 1)
+ DIBUJA_FONDO(37, 151, 224, 115, 56, 47, dir_dibujo3, dir_zona_pantalla);
+}
+
+void DrasculaEngine::refresca_17_antes() {
+ if (flags[15] == 1)
+ DIBUJA_FONDO(1, 135, 108, 65, 44, 63, dir_dibujo3, dir_zona_pantalla);
+}
+
+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};
+
+ if (flags[21] == 0) {
+ DIBUJA_FONDO(1, 69, 120, 58, 56, 61, dir_dibujo3, dir_zona_pantalla);
+ DIBUJA_FONDO(ronquido_x[frame_ronquido], ronquido_y[frame_ronquido], 124, 59, 40, 37, dir_dibujo3, dir_zona_pantalla);
+ } else
+ pon_vb();
+
+ diferencia = vez() - conta_ciego_vez;
+ if (diferencia > 9) {
+ frame_ronquido++;
+ if (frame_ronquido == 16)
+ frame_ronquido = 0;
+ conta_ciego_vez = vez();
+ }
+}
+
+
+
+} // End of namespace Drascula
diff --git a/engines/drascula/drascula.h b/engines/drascula/drascula.h
new file mode 100644
index 0000000000..d8e49ba930
--- /dev/null
+++ b/engines/drascula/drascula.h
@@ -0,0 +1,702 @@
+/* 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 DRASCULA_H
+#define DRASCULA_H
+
+#include "common/stdafx.h"
+#include "common/scummsys.h"
+#include "common/endian.h"
+#include "common/util.h"
+#include "common/file.h"
+#include "common/savefile.h"
+#include "common/system.h"
+#include "common/hash-str.h"
+#include "common/events.h"
+#include "common/keyboard.h"
+
+#include "sound/audiostream.h"
+#include "sound/mixer.h"
+#include "sound/voc.h"
+#include "sound/audiocd.h"
+
+#include "engines/engine.h"
+
+namespace Drascula {
+
+enum DrasculaGameFeatures {
+};
+
+struct DrasculaGameDescription;
+
+#define NUM_SAVES 10
+#define NUM_BANDERAS 50
+#define ESC 0x01
+#define F1 0x3B
+#define F2 0x3C
+#define F3 0x3D
+#define F4 0x3E
+#define F5 0x3F
+#define F6 0x40
+#define F8 0x42
+#define F9 0x43
+#define F10 0x44
+#define MIRAR 1
+#define COGER 2
+#define ABRIR 3
+#define CERRAR 4
+#define HABLAR 5
+#define MOVER 6
+#define INICISOUND 6
+#define FINALSOUND 8
+#define FINDRV 9
+#define DIF_MASK 55
+#define ANCHOBJ 40
+#define ALTOBJ 25
+
+#define X_OBJ1 5
+#define Y_OBJ1 10
+#define X_OBJ2 50
+#define Y_OBJ2 10
+#define X_OBJ3 95
+#define Y_OBJ3 10
+#define X_OBJ4 140
+#define Y_OBJ4 10
+#define X_OBJ5 185
+#define Y_OBJ5 10
+#define X_OBJ6 230
+#define Y_OBJ6 10
+#define X_OBJ7 275
+#define Y_OBJ7 10
+#define X_OBJ8 5
+#define Y_OBJ8 40
+#define X_OBJ9 50
+#define Y_OBJ9 40
+#define X_OBJ10 95
+#define Y_OBJ10 40
+#define X_OBJ11 140
+#define Y_OBJ11 40
+#define X_OBJ12 185
+#define Y_OBJ12 40
+#define X_OBJ13 230
+#define Y_OBJ13 40
+#define X_OBJ14 275
+#define Y_OBJ14 40
+#define X_OBJ15 5
+#define Y_OBJ15 70
+#define X_OBJ16 50
+#define Y_OBJ16 70
+#define X_OBJ17 95
+#define Y_OBJ17 70
+#define X_OBJ18 140
+#define Y_OBJ18 70
+#define X_OBJ19 185
+#define Y_OBJ19 70
+#define X_OBJ20 230
+#define Y_OBJ20 70
+#define X_OBJ21 275
+#define Y_OBJ21 70
+#define X_OBJ22 5
+#define Y_OBJ22 100
+#define X_OBJ23 50
+#define Y_OBJ23 100
+#define X_OBJ24 95
+#define Y_OBJ24 100
+#define X_OBJ25 140
+#define Y_OBJ25 100
+#define X_OBJ26 185
+#define Y_OBJ26 100
+#define X_OBJ27 230
+#define Y_OBJ27 100
+#define X_OBJ28 275
+#define Y_OBJ28 100
+#define X_OBJ29 5
+#define Y_OBJ29 130
+#define X_OBJ30 50
+#define Y_OBJ30 130
+#define X_OBJ31 95
+#define Y_OBJ31 130
+#define X_OBJ32 140
+#define Y_OBJ32 130
+#define X_OBJ33 185
+#define Y_OBJ33 130
+#define X_OBJ34 230
+#define Y_OBJ34 130
+#define X_OBJ35 275
+#define Y_OBJ35 130
+#define X_OBJ36 5
+#define Y_OBJ36 160
+#define X_OBJ37 50
+#define Y_OBJ37 160
+#define X_OBJ38 95
+#define Y_OBJ38 160
+#define X_OBJ39 140
+#define Y_OBJ39 160
+#define X_OBJ40 185
+#define Y_OBJ40 160
+#define X_OBJ41 230
+#define Y_OBJ41 160
+#define X_OBJ42 275
+#define Y_OBJ42 160
+#define X_OBJ43 275
+#define Y_OBJ43 160
+
+#define DIF_MASK_HARE 72
+#define DIF_MASK_ABC 22
+#define ANCHO_LETRAS 8
+#define ALTO_LETRAS 6
+
+#define Y_ABC 158
+#define Y_SIGNOS 169
+#define Y_ACENTOS 180
+
+#define X_A 6
+#define X_B 15
+#define X_C 24
+#define X_D 33
+#define X_E 42
+#define X_F 51
+#define X_G 60
+#define X_H 69
+#define X_I 78
+#define X_J 87
+#define X_K 96
+#define X_L 105
+#define X_M 114
+#define X_N 123
+#define X_GN 132
+#define X_O 141
+#define X_P 150
+#define X_Q 159
+#define X_R 168
+#define X_S 177
+#define X_T 186
+#define X_U 195
+#define X_V 204
+#define X_W 213
+#define X_X 222
+#define X_Y 231
+#define X_Z 240
+#define X_PUNTO 6
+#define X_COMA 15
+#define X_GUION 24
+#define X_CIERRA_INTERROGACION 33
+#define X_ABRE_INTERROGACION 42
+#define X_COMILLAS 51
+#define X_CIERRA_EXCLAMACION 60
+#define X_ABRE_EXCLAMACION 69
+#define X_PUNTO_Y_COMA 78
+#define X_MAYOR_QUE 87
+#define X_MENOR_QUE 96
+#define X_DOLAR 105
+#define X_POR_CIENTO 114
+#define X_DOS_PUNTOS 123
+#define X_AND 132
+#define X_BARRA 141
+#define X_ABRE_PARENTESIS 150
+#define X_CIERRA_PARENTESIS 159
+#define X_ASTERISCO 168
+#define X_MAS 177
+#define X_N1 186
+#define X_N2 195
+#define X_N3 204
+#define X_N4 213
+#define X_N5 222
+#define X_N6 231
+#define X_N7 240
+#define X_N8 249
+#define X_N9 258
+#define X_N0 267
+#define ESPACIO 250
+#define ALTO_HABLA_HARE 25
+#define ANCHO_HABLA_HARE 23
+#define VON_BRAUN 1
+#define AZUL_OSCURO 2
+#define VERDE_CLARO 3
+#define VERDE_OSCURO 4
+#define AMARILLO 5
+#define NARANJA 6
+#define ROJO 7
+#define MARRON 8
+#define MORADO 9
+#define BLANCO 10
+#define ROSA 11
+#define PASO_HARE_X 8
+#define PASO_HARE_Y 3
+#define ALTO_PERSONAJE 70
+#define ANCHO_PERSONAJE 43
+#define PIES_HARE 12
+
+#define ANCHO_LETRAS_OPC 6
+#define ALTO_LETRAS_OPC 5
+#define Y_ABC_OPC_1 6
+#define Y_SIGNOS_OPC_1 15
+#define Y_ABC_OPC_2 31
+#define Y_SIGNOS_OPC_2 40
+#define Y_ABC_OPC_3 56
+#define Y_SIGNOS_OPC_3 65
+#define X_A_OPC 10
+#define X_B_OPC 17
+#define X_C_OPC 24
+#define X_D_OPC 31
+#define X_E_OPC 38
+#define X_F_OPC 45
+#define X_G_OPC 52
+#define X_H_OPC 59
+#define X_I_OPC 66
+#define X_J_OPC 73
+#define X_K_OPC 80
+#define X_L_OPC 87
+#define X_M_OPC 94
+#define X_N_OPC 101
+#define X_GN_OPC 108
+#define X_O_OPC 115
+#define X_P_OPC 122
+#define X_Q_OPC 129
+#define X_R_OPC 136
+#define X_S_OPC 143
+#define X_T_OPC 150
+#define X_U_OPC 157
+#define X_V_OPC 164
+#define X_W_OPC 171
+#define X_X_OPC 178
+#define X_Y_OPC 185
+#define X_Z_OPC 192
+#define ESPACIO_OPC 199
+#define X_PUNTO_OPC 10
+#define X_COMA_OPC 17
+#define X_GUION_OPC 24
+#define X_CIERRA_INTERROGACION_OPC 31
+#define X_ABRE_INTERROGACION_OPC 38
+#define X_COMILLAS_OPC 45
+#define X_CIERRA_EXCLAMACION_OPC 52
+#define X_ABRE_EXCLAMACION_OPC 59
+#define X_PUNTO_Y_COMA_OPC 66
+#define X_MAYOR_QUE_OPC 73
+#define X_MENOR_QUE_OPC 80
+#define X_DOLAR_OPC 87
+#define X_POR_CIENTO_OPC 94
+#define X_DOS_PUNTOS_OPC 101
+#define X_AND_OPC 108
+#define X_BARRA_OPC 115
+#define X_ABRE_PARENTESIS_OPC 122
+#define X_CIERRA_PARENTESIS_OPC 129
+#define X_ASTERISCO_OPC 136
+#define X_MAS_OPC 143
+#define X_N1_OPC 150
+#define X_N2_OPC 157
+#define X_N3_OPC 164
+#define X_N4_OPC 171
+#define X_N5_OPC 178
+#define X_N6_OPC 185
+#define X_N7_OPC 192
+#define X_N8_OPC 199
+#define X_N9_OPC 206
+#define X_N0_OPC 213
+#define NO_PUERTA 99
+
+#define INIT_FRAME 0
+#define CMP_RLE 1
+#define CMP_OFF 2
+#define END_ANIM 3
+#define SET_PALET 4
+#define MOUSE_KEY 5
+#define EMPTY_FRAME 6
+
+#define COMPLETA 256
+#define MEDIA 128
+
+class DrasculaEngine : public ::Engine {
+ int _gameId;
+ Common::KeyState _keyPressed;
+
+protected:
+
+ int init();
+ int go();
+// void shutdown();
+
+ bool initGame();
+
+public:
+ DrasculaEngine(OSystem *syst);
+ virtual ~DrasculaEngine();
+ int getGameId() {
+ return _gameId;
+ }
+
+ Common::RandomSource *_rnd;
+ const DrasculaGameDescription *_gameDescription;
+ uint32 getGameID() const;
+ uint32 getFeatures() const;
+ uint16 getVersion() const;
+ Common::Platform getPlatform() const;
+ void update_events();
+
+ Audio::SoundHandle _soundHandle;
+
+ void asigna_memoria();
+ void libera_memoria();
+ void carga_info();
+ void salir_al_dos(int r);
+
+ void lee_dibujos(const char *);
+ void descomprime_dibujo(byte *dir_escritura, int plt);
+
+ typedef char DacPalette256[256][3];
+
+ void asigna_rgb(byte *dir_lectura, int plt);
+ void funde_rgb(int plt);
+ void paleta_hare();
+ void ActualizaPaleta();
+ void setvgapalette256(byte *PalBuf);
+ void DIBUJA_FONDO(int xorg, int yorg, int xdes, int ydes, int Ancho,
+ int Alto, byte *Origen, byte *Destino);
+ void DIBUJA_BLOQUE(int xorg, int yorg, int xdes, int ydes, int Ancho,
+ int Alto, byte *Origen, byte *Destino);
+ void DIBUJA_BLOQUE_CUT(int *Array, byte *Origen, byte *Destino);
+ void VUELCA_PANTALLA(int xorg, int yorg, int xdes, int ydes, int Ancho, int Alto, byte *Buffer);
+
+ DacPalette256 palJuego;
+ DacPalette256 palHare;
+ DacPalette256 palHareClaro;
+ DacPalette256 palHareOscuro;
+
+ byte *VGA;
+
+ byte *dir_dibujo1;
+ byte *dir_hare_fondo;
+ byte *dir_dibujo3;
+ byte *dir_dibujo2;
+ byte *dir_mesa;
+ byte *dir_hare_dch;
+ byte *dir_zona_pantalla;
+ byte *dir_hare_frente;
+ byte *dir_texto;
+ byte *dir_pendulo;
+
+ byte cPal[768];
+ byte *Buffer_pcx;
+ long LenFile;
+
+ Common::File *ald, *sku;
+
+ int hay_sb;
+ int nivel_osc, musica_antes, musica_room;
+ char num_room[20], pantalla_disco[20];
+ char datos_actuales[20];
+ int objs_room;
+ char fondo_y_menu[20];
+
+ char nombre_obj[30][20];
+ char nombre_icono[14][20];
+
+ int num_obj[40], visible[40], espuerta[40];
+ int sitiobj_x[40], sitiobj_y[40], sentidobj[40];
+ int objetos_que_tengo[50];
+ 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 con_voces;
+ int menu_bar, menu_scr, hay_nombre;
+ char texto_nombre[20];
+ int frame_ciego;
+ int frame_ronquido;
+ int frame_murcielago;
+ int c_mirar;
+ int c_poder;
+
+ int flags[NUM_BANDERAS];
+
+ int frame_y;
+ int hare_x, hare_y, hare_se_mueve, direccion_hare, sentido_hare, num_frame, hare_se_ve;
+ int sitio_x, sitio_y, comprueba_flags;
+ int rompo, rompo2;
+ int paso_x, paso_y;
+ int alto_hare, ancho_hare, alto_pies;
+ int alto_habla, ancho_habla;
+ int suelo_x1, suelo_y1, suelo_x2, suelo_y2;
+ int cerca, lejos;
+ int sentido_final, anda_a_objeto;
+ int obj_saliendo;
+ float diff_vez, conta_vez;
+ int hay_respuesta;
+ int conta_ciego_vez;
+ int cambio_de_color;
+ int rompo_y_salgo;
+ int vb_x, sentido_vb, vb_se_mueve, frame_vb;
+ float nuevo_alto, nuevo_ancho;
+ int diferencia_x, diferencia_y;
+ int factor_red[202];
+ int frame_piano;
+ int frame_borracho;
+ int frame_velas;
+ int color_solo;
+ int parpadeo;
+ int x_igor, y_igor, sentido_igor;
+ int x_dr, y_dr, sentido_dr;
+ int x_bj, y_bj, sentido_bj;
+ int cont_sv;
+ int term_int;
+ int num_ejec;
+ int cual_ejec, hay_que_load;
+ char nom_partida[13];
+ int _color;
+ int corta_musica;
+ char select[23];
+ int hay_seleccion;
+ int x_raton;
+ int y_raton;
+ int y_raton_ant;
+ int boton_izq;
+ int boton_dch;
+
+ bool escoba();
+ void Negro();
+ void habla_vb(const char *, const char *);
+ void habla_vbpuerta(const char *dicho, const char *filename);
+ void habla_ciego(const char *, const char *, const char *);
+ void habla_hacker(const char *, const char *);
+ void agarra_objeto(int);
+ void anda_parriba();
+ void anda_pabajo();
+ void pon_vb();
+ void lleva_vb(int punto_x);
+ void hipo_sin_nadie(int contador);
+ void abre_puerta(int nflag, int n_puerta);
+ void mapa();
+ void buffer_teclado() { }
+ void animacion_1_1();
+ bool animacion_2_1();
+ void animacion_1_2();
+ void animacion_2_2();
+ void animacion_3_1();
+ void animacion_4_1();
+ void animacion_3_2();
+ void animacion_4_2();
+ void animacion_7();
+ void animacion_8();
+ void animacion_9();
+ void animacion_10();
+ void animacion_11();
+ void animacion_12();
+ void animacion_13();
+ void animacion_14();
+ void animacion_15();
+ void animacion_16();
+ void animacion_17();
+ void animacion_18();
+ void animacion_19();
+ void animacion_20();
+ void animacion_21();
+ void animacion_22();
+ void animacion_23();
+ void animacion_23_anexo();
+ void animacion_23_anexo2();
+ void animacion_24();
+ void animacion_25();
+ void animacion_26();
+ void animacion_27();
+ void animacion_28();
+ void animacion_29();
+ void animacion_30();
+ void animacion_31();
+ void animacion_32();
+ void animacion_33();
+ void animacion_34();
+ void animacion_35();
+ void animacion_36();
+
+ void refresca_1_antes();
+ void refresca_2();
+ void refresca_3();
+ void refresca_3_antes();
+ void refresca_4();
+ void refresca_5();
+ void refresca_5_antes();
+ void refresca_6_antes();
+ void refresca_7_antes();
+ void refresca_9_antes();
+ void refresca_12_antes();
+ void refresca_14_antes();
+ void refresca_15();
+ void refresca_16_antes();
+ void refresca_17_antes();
+ void refresca_17();
+ void refresca_18_antes();
+ void refresca_18();
+ void hare_oscuro();
+
+
+ void sin_verbo();
+ void para_cargar(char[]);
+ void carga_escoba_1(const char *);
+ void carga_escoba_2(const char *);
+ void borra_pantalla();
+ void lleva_al_hare(int, int);
+ void mueve_cursor();
+ void comprueba_objetos();
+ void espera_soltar();
+ void MirarRaton();
+ void elige_en_barra();
+ bool comprueba1();
+ void comprueba2();
+ Common::KeyCode getscan();
+ void elige_verbo(int);
+ void mesa();
+ void saves();
+ void print_abc(const char *, int, int);
+ void delay(int ms);
+ void confirma_go();
+ void confirma_salir();
+ void salva_pantallas();
+ void elige_objeto(int objeto);
+ void suma_objeto(int);
+ int resta_objeto(int osj);
+ void fliplay(const char *filefli, int vel);
+ void FundeDelNegro(int VelocidadDeFundido);
+ char LimitaVGA(char valor);
+ void color_abc(int cl);
+ void centra_texto(const char *,int,int);
+ void comienza_sound(const char *);
+ void anima(const char *animacion, int FPS);
+ void fin_sound_corte();
+ void FundeAlNegro(int VelocidadDeFundido);
+ void pausa(int);
+ void habla_dr_grande(const char *dicho, const char *filename);
+ void pon_igor();
+ void pon_bj();
+ void pon_dr();
+ void habla_igor_dch(const char *dicho, const char *filename);
+ void habla_dr_dch(const char *dicho, const char *filename);
+ void habla_dr_izq(const char *dicho, const char *filename);
+ void habla_solo(const char *, const char *);
+ void habla_igor_frente(const char *, const char *);
+ void habla_tabernero(const char *dicho, const char *filename);
+ void hipo(int);
+ void fin_sound();
+ void habla_bj(const char *, const char *);
+ void hablar(const char *, const char *);
+ void playmusic(int p);
+ void stopmusic();
+ int music_status();
+ void refresca_pantalla();
+ void carga_partida(const char *);
+ void canal_p(const char *);
+ void puertas_cerradas(int);
+ void animafin_sound_corte();
+ void color_hare();
+ void funde_hare(int oscuridad);
+ void paleta_hare_claro();
+ void paleta_hare_oscuro();
+ void hare_claro();
+ void actualiza_datos();
+ void empieza_andar();
+ void actualiza_refresco();
+ void actualiza_refresco_antes();
+ void pon_hare();
+ void menu_sin_volcar();
+ void barra_menu();
+ void saca_objeto();
+ bool sal_de_la_habitacion(int);
+ void coge_objeto();
+ void banderas(int);
+ void cursor_mesa();
+ void introduce_nombre();
+ void para_grabar(char[]);
+ int LookForFree();
+ void OpenSSN(const char *Name, int Pause);
+ void WaitFrameSSN();
+ void MixVideo(byte *OldScreen, byte *NewScreen);
+ void Des_RLE(byte *BufferRLE, byte *MiVideoRLE);
+ void Des_OFF(byte *BufferOFF, byte *MiVideoOFF, int Lenght);
+ void set_dacSSN(byte *dacSSN);
+ byte *TryInMem(Common::File *Sesion);
+ void EndSSN();
+ int PlayFrameSSN();
+
+ byte *AuxBuffOrg;
+ byte *AuxBuffLast;
+ byte *AuxBuffDes;
+ int Leng;
+
+ byte *pointer;
+ int UsingMem;
+ Common::File *_Sesion;
+ byte CHUNK;
+ byte CMP, dacSSN[768];
+ byte *MiVideoSSN;
+ byte *mSesion;
+ int FrameSSN;
+ int GlobalSpeed;
+ int LastFrame;
+
+ byte *carga_pcx(byte *NamePcc);
+ void set_dac(byte *dac);
+ void WaitForNext(int FPS);
+ float vez();
+ void reduce_hare_chico(int, int, int, int, int, int, int, byte *, byte *);
+ char codifica(char);
+ void cuadrante_1();
+ void cuadrante_2();
+ void cuadrante_3();
+ void cuadrante_4();
+ void refresca_62();
+ void refresca_62_antes();
+ void refresca_63();
+ void graba_partida(char[]);
+ void aumenta_num_frame();
+ int sobre_que_objeto();
+ void comprueba_banderas_menu();
+ void pantalla_0();
+ void pantalla_62(int);
+ void pantalla_63(int);
+ void conversa(const char *);
+ void print_abc_opc(const char *, int, int, int);
+ void responde(int);
+ void habla_borracho(const char *dicho, const char *filename);
+ void habla_pianista(const char *dicho, const char *filename);
+
+ void MusicFadeout();
+ void ctvd_end();
+ void ctvd_stop();
+ void ctvd_terminate();
+ void ctvd_speaker(int flag);
+ void ctvd_output(Common::File *file_handle);
+ void ctvd_init(int b);
+
+
+
+
+private:
+
+public:
+
+};
+
+} // End of namespace Drascula
+
+#endif /* DRASCULA_H */
diff --git a/engines/drascula/module.mk b/engines/drascula/module.mk
new file mode 100644
index 0000000000..51fb965915
--- /dev/null
+++ b/engines/drascula/module.mk
@@ -0,0 +1,14 @@
+MODULE := engines/drascula
+
+MODULE_OBJS = \
+ detection.o \
+ drascula.o
+
+
+# This module can be built as a plugin
+ifdef BUILD_PLUGINS
+PLUGIN := 1
+endif
+
+# Include common rules
+include $(srcdir)/rules.mk
diff --git a/engines/drascula/texts.h b/engines/drascula/texts.h
new file mode 100644
index 0000000000..4c457f5ac3
--- /dev/null
+++ b/engines/drascula/texts.h
@@ -0,0 +1,753 @@
+#define TEXT1 "Its the second biggest door I've seen in my life."
+#define TEXT2 "Not really."
+#define TEXT3 "The church is all boarded up, it must have been abandoned several years ago."
+#define TEXT4 "I haven't opened it."
+#define TEXT5 "What should I do, should I pull it off?"
+#define TEXT6 "Hi there door, I'm going to make you a door-frame."
+#define TEXT7 "It's too much for me."
+#define TEXT8 "There's a window stopping the game from working properly."
+#define TEXT9 "I can't."
+#define TEXT10 "Yes, that's done."
+#define TEXT11 "Why?"
+#define TEXT12 "Hi window, are you doing anything tonight?"
+#define TEXT13 "Not without permission from the Town Hall."
+#define TEXT14 "If only this window wasn't boarded up..."
+#define TEXT15 "Yoo-Hoo window!"
+#define TEXT16 "Hi there."
+#define TEXT17 "Like Microchof's."
+#define TEXT18 "I can't reach."
+#define TEXT19 "It's alright where it is."
+#define TEXT21 "Its a coffin in the shape of a cross."
+#define TEXT22 "No thanks."
+#define TEXT23 "Hi dead man. No, don't get up for my sake."
+#define TEXT24 "Yes, just like in poltergeist"
+#define TEXT27 "I'll be back in fifteen minutes"
+#define TEXT28 "Forbidden to put up posters."
+#define TEXT29 "It's uncle Evaristo's tomb."
+#define TEXT30 "Its locked."
+#define TEXT31 "I've got one."
+#define TEXT32 "Yoo Hoo, uncle Everisto!"
+#define TEXT33 "There's no reply."
+#define TEXT34 "It's not well parked."
+#define TEXT35 "It's a door."
+#define TEXT36 "A drawer in the table."
+#define TEXT37 "A suspicious wardrobe."
+#define TEXT38 "Hi wardrobe, how are you?"
+#define TEXT41 "It's an ancient candelabrum."
+#define TEXT42 "It must have been here ever since Yule Brinner had hair on his head."
+#define TEXT43 "No, its a relic."
+#define TEXT44 "Its a nice altarpiece."
+#define TEXT46 "ha, ha, ha."
+#define TEXT48 "No."
+#define TEXT50 "Ha, He, Hi, Ho, Hu, great!"
+#define TEXT54 "I can't see anything in particular."
+#define TEXT55 "It's Fern n, the plant."
+#define TEXT56 "It's one of the fences spikes"
+#define TEXT57 "Hey! There's a packet of matches under here."
+#define TEXT58 "Look! a packet of Kleenex, and one's still unused."
+#define TEXT59 "There isn't anything else in the bucket."
+#define TEXT60 "It's a blind man who can't see."
+#define TEXT65 "That's a great deal of money."
+#define TEXTD56 "Hi blind man. How it's going?"
+#define TEXTD57 "How do you know I'm a foreigner?"
+#define TEXTD58 "You look blind. You're wearing dark glasses like Stevie Wonder."
+#define TEXTD59 "Look, I'm sorry, I didn't know you could see."
+#define TEXTD60 "But haven't you just told me you weren't blind."
+#define TEXTD61 "But if you can't see."
+#define TEXTD62 "Ooookay. Sorry. In that case, Hi there sightless person."
+#define TEXTD63 "I'm John Hacker. You must be one of those characters who will help me out in exchange for an object. Aren't you? Eh? Aren't you?"
+#define TEXTD64 "Uuuum, excuse me for asking blin... Sightless person! But what sort of job is that, to give sickles in exchange for money while you play the accordion?"
+#define TEXTD65 "Ah yes, I suppose that's true. Goodbye sightless person ...blind man (under his breath)."
+#define TEXTD66 "Here is the large amount of money you asked me for."
+#define TEXTD67 "You better have had."
+#define TEXTD68 "Hi there foreigner."
+#define TEXTD69 "And how do you know I'm blind?"
+#define TEXTD70 "And I'm not kidding you but your's are like Woody Allen's."
+#define TEXTD71 "No, I can't see."
+#define TEXTD72 "And I'm not."
+#define TEXTD73 "Oh of course. Just cos I can't see, you accuse me of being blind."
+#define TEXTD74 "Hi there foreigner! What are you doing in Transylvania?"
+#define TEXTD75 "That's right, foreigner. In exchange for a large sum of money I'll give you a sickle for when you might need it."
+#define TEXTD76 " !!!!!!!!!!!!!!!!!!!!!!!!"
+#define TEXTD77 "Because you told me before, didn't you?"
+#define TEXTD78 "Thanks foreigner. Here's the sickle in exchange. You'll find it really useful later on, honestly."
+#define TEXT100 "THERE IS NOTHING SPECIAL ABOUT IT"
+#define TEXT101 "IT'S NOT UNUSUAL"
+#define TEXT102 "HEY, WHAT'S UP MAN?"
+#define TEXT103 "HI"
+#define TEXT104 "NOTHING NEW?"
+#define TEXT105 "HOW IS THE FAMILY?"
+#define TEXT106 "THAT IS JUST LIKE YOU!"
+#define TEXT107 "BUT HOW DO I GET THAT?"
+#define TEXT108 "MY RELIGION DOES NOT ALLOW ME"
+#define TEXT109 "IT'D BE BETTER NOT"
+#define TEXT110 "YEAH, SURE MAN!"
+#define TEXT111 "NO WAY"
+#define TEXT112 "IMPOSSIBLE "
+#define TEXT113 "THIS WILL NOT OPEN "
+#define TEXT114 "I CAN'T DO IT BY MYSELF"
+#define TEXT115 "I COULD DO IT IF I WANTED TO, BUT I JUST FEEL A LITTLE LAZY "
+#define TEXT116 "I DO NOT SEE THE REASON "
+#define TEXT117 "IT'S A QUITE NICE BRAIN "
+#define TEXT118 "AND SO BRAIN, WHAT ARE YOU UP TONIGHT? "
+#define TEXT119 "NO, IT MUST BE KEPT SOMEWHERE AWAY FROM THE MUTANT ACTION OF THE ATMOSPHERE"
+#define TEXT120 "HE IS VERY STIFF, JUST LIKE MY BOSS "
+#define TEXT121 "A VERY SHARP STICK"
+#define TEXT122 "YOU FAITHFUL SHARP-PAINTED STICK, NOBLE TRANSILVAAANIAN OAK TREE"
+#define TEXT123 "DAMN, I HAVE TO CUT MY NAILS! "
+#define TEXT124 "B.J. IS IN THERE... SHE IS A REALLY HOT CHICK! "
+#define TEXT125 "IT IS FIRMLY LOCKED "
+#define TEXT126 "\"SAVE AWAY LOCKS LTD.\""
+#define TEXT127 "IT IS THE TYPICAL SKELETON YOU FIND IN THE DUNGEONS OF ALL THE GAMES"
+#define TEXT128 "IT IS COMMONLY USED TO COMMUNICATE ELECTRICITY TO THE MACHINES CONNECTED TO IT "
+#define TEXT129 "IT IS ABSOLUTELY HAND MADE BECAUSE THE JAPANESE MAKE THEM POCKET SIZE "
+#define TEXT130 "I HAVE ONLY SEEN IN MY LIFE ANOTHER THING AS UGLY AS THIS ONE "
+#define TEXT131 "FORGET IT. I AM NOT GOING TO TELL HIM ANYTHING IN CASE HE GETS MAD "
+#define TEXT132 "IT SEEMS QUITE RATIONAL "
+#define TEXT133 "IT IS A PICTURE OF PLATO WRITING HIS LOST DIALOGUE "
+#define TEXT134 "I AM NOT ONE OF THOSE WHO TALKS TO POSTERS "
+#define TEXT135 "THAT'S A VERY CUTE DESK "
+#define TEXT136 "IT IS A VAMPIRES HUNTER'S DIPLOMA OFFICIALLY APPROVED BY OXFORD UNIVERSITY "
+#define TEXT137 "IT'S A DARK NIGHT WITH FULL MOON "
+#define TEXT138 "IT SEEMS LIKE THESE SCREWS ARE NOT MUCH TWISTED "
+#define TEXT139 "DON'T LOOK NOW, BUT I THINK THAT A HIDDEN CAMERA IS FOCUSING ON ME "
+#define TEXT140 "THAT'S A VERY MODERN STICK DETECTOR "
+#define TEXT141 "NO. THE LABORATORY IS ON THE SECOND FLOOR "
+#define TEXT142 "A NICE BEDSIDE TABLE "
+#define TEXT143 "IT'S A LOT OF MONEY THAT CAN'T BE MISSING IN ANY VALUABLE ADVENTURE "
+#define TEXT144 "IF I WERE A RICH MAN, DUBIDUBIDUBIDUBIDUBIDUBIDUBIDU "
+#define TEXT145 "THOSE ARE STRANGE LEAVES. THEY MUST HAVE BROUGHT THEM FROM SOUTH AMERICA OR AROUND THERE "
+#define TEXT146 "I DON'T THINK THEY WOULD ANSWER ME "
+#define TEXT147 "THAT'S A BEAUTIFUL WOODEN CRUCIFIX. THE ICON DOESN'T REALLY GET ALL THE BEAUTY WITHIN IT"
+#define TEXT148 "I ONLY PRAY BEFORE I GO TO BED "
+#define TEXT149 "HEY, THIS PIKE SEEMS A LITTLE BIT LOOSE! "
+#define TEXT150 "I HOPE YOU WON'T COMPLAIN ABOUT GETTING NO CLUES FROM ME "
+#define TEXT151 "IT'S A QUITE CONVENTIONAL PIKE "
+#define TEXT152 "THEY ARE CUTE, THOUGH THEY ARE COVERED WITH A LITTLE BIT OF SHIT "
+#define TEXT153 "NO, THEY WON'T HEAR ME. HA,HA,HA THIS IS GREAT! "
+#define TEXT154 "\"SLEEPING BEAUTY\" FROM CHAIKOSKY, OR CHOIFRUSKY, OR WHATEVER IT IS"
+#define TEXT155 "VERY TEMPTING "
+#define TEXT156 "NO, I'M NOT ONE OF THOSE WHO PUT USED BUBBLE GUMS IN THEIR MOUTH "
+#define TEXT157 "THAT'S A VERY NICE SICKLE. I WONDER WHERE THE HAMMER MAY BE "
+#define TEXT158 "TOBACCO MANUFACTURERS WARN ABOUT HEALTH BEING SERIOUSLY DAMAGED BY SANITARY AUTHORITIES"
+#define TEXT159 "AN ABSOLUTELY NORMAL CANDLE, INCLUDING WAX AND EVERYTHING "
+#define TEXT160 "THESE TWO SHINY COINS DO REALLY GLITTER! "
+#define TEXT161 "THIS SHINY COIN DOES REALLY GLITTER! "
+#define TEXT162 "WITH THIS I WILL BE IMMUNE AGAINST VAMPIRE'S BITES"
+#define TEXT163 "NO, IT'S IS NOT THE RIGHT MOMENT YET "
+#define TEXT164 "THERE IS A ONE THOUSAND BILL AND A COUPLE COINS "
+#define TEXT165 "IT SAYS \"PLEASE, DO NOT THROW FOOD TO THE PIANIST\""
+#define TEXT166 "OMELET, 200. FRIED FISH, 150, MAYONNAISE POTATOES, 225"
+#define TEXT167 "BEST BURGERS ON THIS SIDE OF THE DANUBE, ONLY FOR 325!"
+#define TEXT168 "THAT'S A NICE SKULL WITH A VERY PENETRATING LOOK, HA, HA, HA, HA, THAT WAS GOOD!"
+#define TEXT169 "HI SKULL, YOU REMIND ME OF UNCLE HAMLET "
+#define TEXT170 "I HAVE THE HABIT OF NOT TOUCHING THINGS THAT HAVE BEEN ALIVE "
+#define TEXT171 "IT'S A BIN "
+#define TEXT172 "IT'S A BET FOR TONIGHT'S GAME "
+#define TEXT173 "I WONDER WHAT THERE IS BEHIND THAT "
+#define TEXT174 "HEY, THAT CURTAIN IS NOT MOVING!"
+#define TEXT175 "MAN, THIS CASTLE IS REALLY GLOOMY "
+#define TEXT176 "I CAN'T, HE IS TOO FAR AWAY TO HEAR ME "
+#define TEXT177 "IT'S THE TYPICAL TRANSILVANIAN FOREST, WITH TREES "
+#define TEXT178 "MAN YOU REALLY SAY STUPID THINGS, AND THIS IS TOO DARK! "
+#define TEXT179 "GARCIA, CANDY STORE. SWEETS AND BUBBLE GUM"
+#define TEXT180 "A VERY NICE DOOR "
+#define TEXT181 "IT'S CLOSED "
+#define TEXT182 "A COMPLETELY LOCKED BARREL "
+#define TEXT184 "AREN'T THESE BUGS REALLY CUTE? "
+#define TEXT185 "BSSST, PUSSYCAT... LITTLE CAT"
+#define TEXT186 "THERE IS NO ANSWER "
+#define TEXT187 "THE MOON IS A SATELLITE THAT TURNS AROUND THE EARTH WITH A REVOLUTION PERIOD OF 28 DAYS"
+#define TEXT188 "HI, LOONY MOON "
+#define TEXT189 "IT'S TOTALLY BLOCKED UP WITH PLANKS"
+#define TEXT190 "IT'S IMPOSSIBLE. NOT EVEN THAT TOUGH GUY FROM TV COULD OPEN THIS "
+#define TEXT191 "HEY! THE SHADOW OF THAT CYPRESS LOOKS PROLONGED TO ME! "
+#define TEXT192 "YOU, BARTENDER...!! "
+#define TEXT193 "I WOULD LIKE TO HAVE A ROOM PLEASE "
+#define TEXT194 "DO YOU KNOW WHERE I CAN FIND THE SO CALLED DRASCULA? "
+#define TEXT195 "YES, SO WHAT? "
+#define TEXT196 "SO? "
+#define TEXT197 "IS...THAT RIGHT? "
+#define TEXT198 "GOOD QUESTION. NOW, LET ME TELL YOU MY STORY. LOOK... "
+#define TEXT199 "IT'S JUST FIVE MINUTES "
+#define TEXT200 "I'M JOHN HACKER AND I REPRESENT A BRITISH PROPERTY COMPANY "
+#define TEXT201 "AS FAR AS I KNOW, COUNT DRASCULA WANTS TO BUY SOME PIECES OF LAND IN GIBRALTAR AND MY COMPANY SENT ME HERE TO NEGOTIATE THE SELLING "
+#define TEXT202 "I THINK I'M GOING BACK TO MY MUM'S TOMORROW FIRST THING IN THE MORNING "
+#define TEXT203 "BEAUTIFUL NIGHT, HUH? "
+#define TEXT204 "NO, NOTHING "
+#define TEXT205 "YOU...PIANIST...!!!! "
+#define TEXT206 "BEAUTIFUL NIGHT "
+#define TEXT207 "AND IT'S NOT EVEN COLD OR ANYTHING "
+#define TEXT208 "ALL RIGHT, I'LL JUST LET YOU GO ON PLAYING "
+#define TEXT209 "WELL THEN "
+#define TEXT210 "HI BOSS, HOW ARE YOU? "
+#define TEXT211 "AND HOW IS THE FAMILY? "
+#define TEXT212 "THIS IS QUITE GROOVY, HUH? "
+#define TEXT213 "I'D BETTER NOT SAY ANYTHING "
+#define TEXT214 "THERE IS NO PLACE LIKE HOME. THERE IS NO...WHAT?, BUT YOU ARE NOT AUNT EMMA. AS A MATTER OF FACT, I DON'T HAVE ANY AUNT EMMA! "
+#define TEXT215 "YES, SO DOES MINE. YOU CAN CALL ME ANYTHING YOU WANT, BUT IF YOU CALL ME JHONNY, I'LL COME TO YOU LIKE A DOG "
+#define TEXT216 "AREN'T I JUST A FUNNY GUY, HUH?. BY THE WAY, WHERE AM I? "
+#define TEXT217 "YES "
+#define TEXT218 "SHOOT...! "
+#define TEXT219 "OH, SURE...OF COURSE! "
+#define TEXT220 "WELL, THANKS VERY MUCH FOR YOUR HELP. I WON'T BOTHER YOU ANYMORE IF YOU PLEASE TELL ME WHERE THE DOOR IS... "
+#define TEXT221 "IT'S BECAUSE THE KNOCK MUST HAVE AFFECTED MY BRAIN...I CAN'T SEE A THING... "
+#define TEXT222 "WELL...THAT DOESN'T MATTER. I ALWAYS CARRY AN SPARE ONE. "
+#define TEXT223 "WOW, WHAT A HOT CHICK!! I DIDN'T NOTICE!, BUT OF COURSE, I WASN'T WEARING MY GLASSES "
+#define TEXT224 "HEY... "
+#define TEXT225 "AND ALL THIIIISSS??? "
+#define TEXT226 "DON'T WORRY B.J. HONEY, I'LL SAVE YOU FROM FALLING INTO HIS CLUTCHES... "
+#define TEXT227 "YOU REALLY GOT ME MAD MAN... "
+#define TEXT228 "AHHH A WEREWOLF!! DIE YOU DAMNED EVIL! "
+#define TEXT229 "YES, WELL... "
+#define TEXT230 "YES, WELL...I THINK I'LL JUST GO ON MY WAY. EXCUSE ME "
+#define TEXT231 "WHAT? "
+#define TEXT232 "TO TELL YOU THE TRUTH...ON SECOND THOUGHTS...I DON'T REALLY THINK SO. "
+#define TEXT233 "AND SO TELL ME YOU ERUDITE PHILOSOPHER, IS THERE ANY RELATIONSHIP CAUSE-AND-EFFECT BETWEEN SILLY AND BILLY?"
+#define TEXT234 "OK, OK, FORGET IT. I DON'T EVEN KNOW WHU I SAID ANYTHING ABOUT IT "
+#define TEXT235 "WHAT ARE YOU DONIG HERE PHILOSPOZING INSTEAD OF BEING EATING SOME PEOPLE "
+#define TEXT236 "HOW come? "
+#define TEXT237 "HEY, COULD YOU SAY AGAIN ALL THAT ABOUT PRE-EVOLUTIONARY RELATIONSHIPS? "
+#define TEXT238 "YES, MAN. ALL THAT STUFF YOU TOLD ME ABOUT NEFORE. I DIDN'D GET IT VERY WELL, YOU KNOW. "
+#define TEXT239 "NO, I'D RATHER NOT SAY ANYTHING, IN CASE HE GETS ANGRY OR SOMETHING... "
+#define TEXT240 "HELLO? "
+#define TEXT241 "YES, WHAT'S UP? "
+#define TEXT242 "WELL, NOW THAT YOU MENTION IT, I'LL TELL YOU THAT... "
+#define TEXT244 "WELL, THANKS FOR CALLING. BY THE WAY, THIS IS NOT THE CASE, OF COURSE, BUT WHAT COULD HAPPEN IF A VAMPIRE GOT THE RECIPE BY ANY CHANCE? "
+#define TEXT245 "WELL ANYWAY. LISTEN, DOESN'T THIS LOOK TO YOU LIKE A LOT OF CRAP TO END UP SOON WITH THE GAME?. WELL, MAYBE NOT. "
+#define TEXT246 "IT'S EMPTY! "
+#define TEXT247 "WHY DID YOU TAKE MY ONLY LOVE, B.J. , AWAY FROM ME?. LIFE HAS NO MEANING FOR WITHOUT HER "
+#define TEXT248 "HER BRAIN!!? "
+#define TEXT249 "TO TELL YOU THE TRUTH, I THINK I HAD JUST ENOUGH WITH YOUR OF YOUR LITTLE MONSTER. "
+#define TEXT250 "OH PLEASE, HOLLY VIRGIN, DON'T LET ANYTHING WORSE HAPPEN TO ME!! "
+#define TEXT251 "YOU ARE NOT GOING TO GET YOUR WAY. I'M SURE SUPERMAN WILL CAME AND RESCUE ME!"
+#define TEXT252 "WHAT A SHIT OF GAME IS THIS IN WHICH THE PROTAGONIST DIES! "
+#define TEXT253 "HEY, WAIT A SECOND!, WHAT ABOUT MY LAST WISH? "
+#define TEXT254 "HA. HA, I'M NOW IMMUNIZED AGAINST YOU DAMNED EVIL!. THIS CIGARETTE IS AN ANTI-VAMPIRE BREW THAT VON BRAUN GAVE TO ME "
+#define TEXT255 "YES SURE, BUT YOU'LL NEVER GET ME TO GIVE YOU THE RECIPE "
+#define TEXT256 "APART FROM CREATING TORTURE, I CAN ALSO STAND IT.. "
+#define TEXT257 "OH, NO PLEASE! I'LL TALK, BUT PLEASE, DON'T DO THAT TO ME! "
+#define TEXT258 "ALL RIGHT THEN. I TOLD YOU WHAT YOU WANTED TO KNOW. NOW SET B.J. AND ME FREE AND LEAVE US ALONE! "
+#define TEXT259 "WHAT ARE YOU DOING HERE B.J.?. WHERE IS DRASCULA? "
+#define TEXT260 "WHAT A MEAN GUY!. JUST BECAUSE HE BELONGS TO THE NOBILITY HE THINKS HE IS ENTITLED TO SLEEP WITH ANYBODY HE FEELS LIKE. "
+#define TEXT261 "DOWN WITH ARISTOCRATIC DESPOTISM!! "
+#define TEXT262 "POOR PEOPLE OF THE WORLD FOR EVER..!! "
+#define TEXT263 "AND AS I CAN SEE HE HAS CHAINED YOU UP WITH LOCKS AND ALL THAT STUFF, HUH? "
+#define TEXT264 "WELL, ALL RIGHT. DO YOU HAVE A HAIRPIN OVER THERE? "
+#define TEXT265 "ALL RIGHT, OK, DON'T GET MAD. I'LL THINK ABOUT SOMETHING "
+#define TEXT266 "YOU...BARTENDER!! "
+#define TEXT267 "HOW IS THE GAME GOING? "
+#define TEXT268 "WHO? "
+#define TEXT269 "CAN'T YOU SEE DRASCULA IS HERE? "
+#define TEXT270 "THEN, LET'S END UP WITH HIM, RIGHT? "
+#define TEXT271 "GIVE ME A SCOTCH ON THE ROCKS "
+#define TEXT272 "NOTHING, I JUST FORGOT WHAT I WAS GOING TO SAY... "
+#define TEXT273 "EITHER YOU GET ME A SCOTCH ON THE ROCKS OR I'LL PLAY THE PIANO UNTIL THE GAME IS OVER "
+#define TEXT274 "WHEN IS THE MATCH GOING TO BE OVER? "
+#define TEXT275 "GOOD EVENING"
+#define TEXT276 "AND SO IGOR, HOW ARE YOU FEELING...A LITTLE HUMPED...?. HA, HA, HA, THAT WAS FUNNY! "
+#define TEXT277 "WHAT ARE YOU SUPPOSED TO BE DOING? "
+#define TEXT278 "WELL, NO. "
+#define TEXT279 "THEN WEAR GLASSES. "
+#define TEXT280 "WHAT IS ALL THAT ABOUT THE SUPERNATURAL ORGY? "
+#define TEXT281 "OK, OK, STOP IT. I THINK I CAN GET THE PICTURE. "
+#define TEXT282 "COULDN'T YOU TELL ME WHERE DRASCULA IS? "
+#define TEXT283 "OH...PLEASE...COME ON...! "
+#define TEXT284 "WHY NOT? "
+#define TEXT285 "OH...BUT DIES HE SLEEP AT NIGHT? "
+#define TEXT286 "WELL, I HOPE YOU GET LUCKY "
+#define TEXT287 "I HAVE TO TALK TO HIM... "
+#define TEXT288 "YOOUUU...SKELETOOOONN..!!! "
+#define TEXT289 "GOOD HEAVENS!, IT'S A DEAD MAN TALKING! "
+#define TEXT290 "TELL HOW DID YOU GET TO END UP HERE "
+#define TEXT291 "AND WHY WOULD DRASCULA WANT TO CREATE A MONSTER? "
+#define TEXT292 "WHAT'S YOUR NAME, MY SKELETON FRIEND? "
+#define TEXT293 "HEY, DON'T YOU WANT ANYTHING TO EAT? "
+#define TEXT294 "I BET YOUR STOMACH IS PRETTY EMPTY...HA, HA,HA! "
+#define TEXT295 "THE THING IS THAT I DON'T FEEL LIKE TALKING RIGHT NOW "
+#define TEXT296 "I HOPE SOMEONE F...(WHISTLE) YOU...,AND YOUR F...(WHISTLE) SON OF (WHISTLE TWICE) "
+#define TEXT297 "I REALLY LOVED HER. I KNOW SHE WASN'T MUCH OF A WONDER, BUT NOBODY'S PERFECT, RIGHT? "
+#define TEXT298 "BESIDES. SHE REALLY HAD ONE OF THOSE GREAT BODIES THAT YOU NEVER FORGET... "
+#define TEXT299 "I'LL NEVER BE THE SAME AGAIN. I WILL SHUT MYSELF AWAY IN A MONASTERY, AND WILL LET MY LIFE JUST FLOW... "
+#define TEXT300 "NOTHING WILL GET ME OUT OF THIS MYSTERY BECAUSE..."
+#define TEXT301 "WHOSE?. WHOSE? "
+#define TEXT302 "I WANT TO BECOME A PIRATE "
+#define TEXT303 "I WANT TO BECOME A PROGRAMMER "
+#define TEXT304 "TELL ME SOMETHING ABOUT PELAYO "
+#define TEXT305 "I'LL JUST GO ON PLAYING, AND I'LL FORGET I SAW YOU. "
+#define TEXT306 "WHOSE STUPID IDEA COULD THIS BE? "
+#define TEXT307 "IT'S LIKE MY GRANDMOTHER'S HANDBAG "
+#define TEXT308 "JESUS, AREN'T I JUST REALLY COOL MAN...! "
+#define TEXT309 "THE MORE I SEE MYSELF, THE MORE I LOVE ME "
+#define TEXT310 "HOW DO I LOCK MYSELF THEN? "
+#define TEXT311 "I'LL HAVE TO OPEN ME FIRST, RIGHT? "
+#define TEXT312 "I'M ALL RIGHT WHERE I AM "
+#define TEXT313 "I GOT ME "
+#define TEXT314 "HI, MYSELF! "
+#define TEXT315 "I'LL WEAR THEM WHEN THE RIGHT TIME COMES "
+#define TEXT316 "I CAN'T SEE ANYTHING SPECIAL ABOUT IT "
+#define TEXT317 "IT'S ALL RIGHT WHERE IT IS "
+#define TEXT318 "AND WHAT FOR? "
+#define TEXT319 "I CAN'T "
+#define TEXT320 "HI, YOU! "
+#define TEXT321 "IT'S UNCLE DESIDERIO'S PANTHEON! "
+#define TEXT322 "YOOUU...UNCLE DESIDERIOOOO!! "
+#define TEXT323 "NO, I DON'T WANT TO CUT MYSELF AGAIN "
+#define TEXT324 "AHHH,,,EXCUS.... "
+#define TEXT325 "JAMM. AHH... "
+#define TEXT326 "YES...WOF, WOF "
+#define TEXT327 "LOOK, THERE'S A PIECE OF BUBBLE GUM STUCK HERE. "
+#define TEXT328 "THIS IS THE PORTABLILINE I GOT LAST CHRISTMAS "
+#define TEXT329 "IT'S VERY HIGH! "
+#define TEXT330 "COME OUT TO THE BALCONY MY JULIET!! "
+#define TEXT331 "YOU ARE THE LIGHT THAT ILLUMINATES MY WAY! "
+#define TEXT332 "HEY, DOOR!, WHAT'S THE MATTER? "
+#define TEXT333 "YOOOUU, CIGARETTE SPENDING MACHINEEE! "
+#define TEXT334 "IT'S A CIGARETTE SPENDING MACHINE "
+#define TEXT335 "I HAVE ANOTHER COIN INSIDE "
+#define TEXT336 "NO, I JUST DECIDED TO QUIT SMOKING AND DRINKING ALCOHOL "
+#define TEXT337 "I WILL DEVOTE MYSELF TO WOMEN FROM NO ON "
+#define TEXT338 "THIS IS A TRICK! NOTHING CAME OUT! "
+#define TEXT339 "AT LAST! "
+#define TEXT340 "JUST A TRUNK "
+#define TEXT341 "HELLO TRUNK, YOUR NAME IS JUST LIKE MY COUSIN FRANK... "
+#define TEXT342 "I'VE FOUND B.J.'S HANDBAG! "
+#define TEXT343 "OH MY GOD! DON'T GET MY IMAGE REFLECTED! I'M A VAMPIRE! "
+#define TEXT344 "OH...JESUS, IT'S JUST A DRAWING! "
+#define TEXT345 "LITTLE MIRROR, TELL ME, WHO IS THE MOST BEAUTIFUL IN THE WHOLE KINGDOM? "
+#define TEXT346 "HE WON'T OPEN "
+#define TEXT347 "ALL RIGHT. I GOT THE EAR-PLUGS ON "
+#define TEXT348 "IT'S A VAMPIRE'S HUNTER DIPLOMA, officially approved by oxford university "
+#define TEXT349 "NOT YET. THERE ARE STILL SOME INGREDIENTS MISSING. IT'S NOT WORTH WAKING HIM UP "
+#define TEXT350 "BUT I DON'T HAVE MONEY "
+#define TEXT351 "IT'S A BRITISH LAMP "
+#define TEXT352 "HELP ME OUT HERE BARTENDER!! "
+#define TEXT353 "A VAMPIRE CAME IN AND TOOK MY GIRLFRIEND AWAY!! "
+#define TEXT354 "BUT, AREN'T YOU GOING TO HELP ME!!?? "
+#define TEXT355 "DEAD?, WHAT DO YOU MEAN DEAD? "
+#define TEXT356 "AAHH.... "
+#define TEXT357 "A VAMPIRE HAS KIDNAPPED THE GIRL IN ROOM 501 "
+#define TEXT358 "BUT YOU HAVE TO HELP ME OUT! "
+#define TEXT359 "CAN'T YOU PLAY ONE FROM BLUR? "
+#define TEXT360 "HOW CAN YOU STAY HERE ALL DAY PLAYING THE SAME SONG ALL THE TIME? "
+#define TEXT361 "AND THEN, HOW CAN YOU HEAR ME? "
+#define TEXT362 "PLEASE, LEND ME THE ERA-PLUGS. "
+#define TEXT363 "COME ON, I'LL GIVE THEM BACK TO YOU RIGHT AWAY "
+#define TEXT364 "COOOMEE OONNN... "
+#define TEXT365 "WELL GOODBYE, I HAVE TO KILL A VAMPIRE. "
+#define TEXT367 "WHAT'S YOUR LANGUAGE, TRASILVANIAN? "
+#define TEXT368 "WHO IS UNCLE DESIDERIO? "
+#define TEXT369 "BUT, WHAT'S THE MATTER WITH THAT DRASCULA? "
+#define TEXT370 "WHO IS THAT GUY NAMED VON BRAUN? "
+#define TEXT371 "AND WHY DOESN'T HE DO IT? "
+#define TEXT372 "AND WHERE CAN I FIND VON BRAUN? "
+#define TEXT373 "WELL, THANKS AND GOODBYE. HOPE YOU SLEEP IT OFF JUST FINE. "
+#define TEXT374 "WE'D BETTER CALL FIRST "
+#define TEXT375 "ARE YOU PROFESSOR BRAUN? "
+#define TEXT376 "AND COULD YOU TELL ME WHERE I CA...? "
+#define TEXT377 "I DON'T BELIEVE HE IS GANIMEDES THE DWARF "
+#define TEXT378 "PROFESSOR!! "
+#define TEXT379 "PLEASE HELP ME!. THE LIFE OF MY GIRLFRIEND DEPENDS ON YOU!! "
+#define TEXT380 "WELL, ALL RIGHT. I DON'T NEED YOUR HELP "
+#define TEXT381 "ALL RIGHT. I'M LEAVING "
+#define TEXT382 "DON'T DE AFRAID. WE WILL BEAT DRASCULA TOGETHER. "
+#define TEXT383 "THEN WHY DON'T YOU HELP ME? "
+#define TEXT384 "I GOT THEM "
+#define TEXT385 "YES, I GOT THEM!! "
+#define TEXT386 "ALL RIGHT "
+#define TEXT387 "AHH....YES "
+#define TEXT388 "I HAVE COME TO GET INTO THAT CABIN AGAIN "
+#define TEXT389 "I AM READY TO FACE YOUR TEST"
+#define TEXT390 "ALL RIGHT OLD MAN. I CAME FOR MY MONEY "
+#define TEXT391 "NO, NOTHING. I WAS JUST LEAVING "
+#define TEXT392 "SORRY..."
+#define TEXT393 "DO YOU LIKE THIS BOOK?. IT HAS SOME SCORES FROM TCHAIKOWSKY "
+#define TEXT394 "HOW CAN I KILL A VAMPIRE?"
+#define TEXT395 "HAS ANYBODY TOLD YOU THAT SLEEPING IN A BAD POSITION IS NOT GOOD FOR YOU? "
+#define TEXT396 "THAT'S WHAT MY MUM ALWAYS TELL ME "
+#define TEXT397 "WHY WOULDN'T DRASCULA KILL YOU? "
+#define TEXT398 "AND WHAT WAS IT? "
+#define TEXT399 "GREAT! YOU HAVE AN IMMUNIZING BREW"
+#define TEXT400 "SO? "
+#define TEXT401 "ALL RIGHT "
+#define TEXT402 "CAN YOU REPEAT WHAT I NEED FOR THAT BREW "
+#define TEXT403 "WELL, I'LL RUSH OUT TO GET IT "
+#define TEXT404 "HEY, WHAT HAPPENED WITH THE PIANIST? "
+#define TEXT405 "I HAVE ALL THE INGREDIENTS OF THAT BREW "
+#define TEXT406 "JUST A QUESTION. WHAT IS ALL THAT ABOUT THE ALUCSARD ETEREUM? "
+#define TEXT407 "HELLO, HELLO... "
+#define TEXT408 "AND WHERE IS THAT CAVERN? "
+#define TEXT409 "WHAT HAPPENS? DIDN'T YOU HAVE TO GO TO THE COURT? "
+#define TEXT410 "...BUT... IF I MEET MORE VAMPIRES? "
+#define TEXT411 "IT'S A VAMPIRE THAT DOESN'T LET ME COME THROUGH "
+#define TEXT412 "HE LOOKS LIKE YODA, BUT A LITTLE TALLER "
+#define TEXT413 "HEY YODA, IF YOU JUST LET ME GO ON MY WAY, I'LL GIVE YOU A PENNY "
+#define TEXT414 "OK, OK, YOU GET MAD ABOUT NOTHING MAN "
+#define TEXT415 "HAS ANYBODY TOLD YOU THAT YOU LOOK LIKE YODA?"
+#define TEXT416 "HI VAMPIRE, IT'S A BEAUTIFUL NIGHT, HUH? "
+#define TEXT417 "ARE YOU A VAMPIRE OR AN OIL PAINTING? "
+#define TEXT418 "I'D BETTER NOT SAY ANYTHING, IN CASE YOU GET MAD "
+#define TEXT419 "IT'S LOCKED "
+#define TEXT420 "THE MAGPIE WOULD STICK OUT MY EYES IF I TRIED! "
+#define TEXT421 "OH MY GOD. IT'S LOCKED...THAT'S SCARY, HUH?"
+#define TEXT422 "THE HINGES ARE RUSTY "
+#define TEXT423 "THERE IS ONLY ONE CAN OF FLOUR IN THERE "
+#define TEXT424 "THAT TOOK AWAY THE RUST "
+#define TEXT425 "I HAVE FOUND A PINE STICK "
+#define TEXT426 "I'LL TAKE THIS THICKER ONE "
+#define TEXT427 "WELL, I THINK I CAN GET RID OF THIS STUPID DISGUISE "
+#define TEXT428 "\"PASSAGE TO TOWERS CLOSED FOR REPAIRS. PLEASE USE MAIN ENTRANCE. SORRY FOR THE INCONVENIENCE\""
+#define TEXT429 "...HE IS PALE, HE HAS FANGS AND WEARS A TOUPE AND HE SURE IS DRASCULA! "
+#define TEXT430 "IT'S B.J.! ARE YOU ALL RIGHT B.J.? "
+#define TEXT431 "YES, I KNOW SHE IS STUPID, BUT I'M SO LONELY "
+#define TEXT432 "YOU DON'T HAVE A KEY AROUND THERE, DO YOU?"
+#define TEXT433 "I BET YOU DON'T HAVE A PICKLOCK AROUND! "
+#define TEXT434 "GIVE ME A HAIRPIN, I'M GOING TO PLAY MCGYVER HERE! "
+#define TEXT435 "DON'T GO ANYWHERE. I'LL BE RIGHT BACK "
+#define TEXT436 "SHOOT! IT'S BROKEN! "
+#define TEXT437 "OLEEEE! I EVEN SHAVED DUDE! "
+#define TEXT438 "YES, DARLING? "
+#define TEXT439 "HE'S NOT ARRIVED YET "
+#define TEXT440 "THE PIANIST IS NOT HERE "
+#define TEXT441 "A TRANSYLVANIAN SCOTCH ON THE ROCKS "
+#define TEXT442 "I DON'T HAVE A ROOM YET "
+#define TEXT443 "IT LOOKS LIKE HE GOT STUCK IN THE BATH AND DECIDED TO RUN A BAR "
+#define TEXT444 "HE WAS DRUNK AS A SAILOR "
+#define TEXT445 "THAT HAIR...REMINDS ME OF SOMEBODY "
+#define TEXT446 "IT'S A RAW-BONED SKELETON "
+#define TEXT447 "LOOK! THERE'S MIGUEL BOSE! "
+#define TEXT448 "HE'S ASLEEP. IT'D BE A SHAME WAKING HIM UP."
+#define TEXT449 "HE'S UGLIER THAN EMILIO DE PAZ "
+#define TEXT450 "A PINE-WOODEN COFFIN "
+#define TEXT451 "HE IS GOING TO CUT ME IN LITTLE SLICES. JUST LIKE A SAUSAGE "
+#define TEXT452 "I DON'T LIKE PENDULAE. I'D RATHER PREFER ARTICHOKES. "
+#define TEXT453 "I CAN'T MAKE IT. I'M HANDCUFFED "
+#define TEXT454 "IT'S OBVIOUSLY A SECRET DOOR. "
+#define TEXT455 "THEY IGNORE ME "
+#define TEXT456 "COME ON..! "
+#define TEXT457 "WHEN I READ THE SCRIPT IT WAS SUPPOSED TO MOVE, BUT THE BUDGET GOT CRAZY AND THEY COULDN'T AFFORD TO PAY THE GYM, SO THAT I NEVER GOT TOUGH. END OF STORY. "
+#define TEXT458 "IT SEEMS A LITTLE LOOSE FROM THE WALL "
+#define TEXT459 "I DON'T THINK IS GOING TO HELP ME ANYWAY. IT'S TOO WET TO LIGHT IT "
+#define TEXT460 "TO WEST WING? NO WAY! NOBODY KNOWS WHAT YOU CAN FIND THERE!! "
+#define TEXT461 "SHE'S GOT NICE TRANSILVANIAN REASONS "
+#define TEXT463 "IT'S A SHAME THERE ISN'T A ROASTED LAMB IN THERE "
+#define TEXT464 "LAST TIME I OPENED AN OVEN I BLEW UP THE HOUSE "
+#define TEXT465 "THAT'S THE TRANSILVANIAN FOOTBALL BADGE. "
+#define TEXT466 "WHAT FOR? TO PUT IT ON MY HEAD "
+#define TEXT467 "I DON'T THINK THESE TOWERS ARE THE OPENING KIND "
+#define TEXT468 "I DON'T WANT TO KNOW WHAT KIND OF FOOD IS IN THERE! "
+#define TEXT469 "IT LOOKS IMPRESSIONIST TO ME... "
+#define TEXT470 "THE NIGHT IS FALLING OVER ALL OF US...THAT'S SCARY, ISN'T IT? "
+#define TEXT471 "IT'S STUCK! "
+#define TEXT472 "IT'S THE KING. YOU DIDN'T IMAGINE THAT, DID YOU! "
+#define TEXT473 "NO, I ALREADY HAVE ONE AT HOME TO FEED."
+#define TEXT474 "A SHELF WITH BOOKS AND SOME OTHER THINGS. "
+#define TEXT475 "BUT WHO CAN I CALL AT THIS TIME? "
+#define TEXT476 "\"HOW TO MAKE THE TAX RETURN FORMS\". HOW INTERESTING!"
+#define TEXT477 "I ALREADY HAVE ONE AT HOME. I THINK IT'S A WORLDWIDE BEST SELLER "
+#define TEXT478 "A COMPLETELY NORMAL KEY "
+#define TEXT479 "I THINK SHE IS NOT FROM AROUND HERE "
+#define TEXT480 "HEY, THEY'RE FANG-LIKE FRENCH FRIES! I LOVE IT! "
+#define TEXT481 "I DON'T THINK THIS IS THE RIGHT TIME TO EAT THAT CRAP KNOWING THAT MY GIRLFRIEND HAS BEEN KIDNAPPED BY THE MOST EVIL PERSON EVER ON EARTH "
+#define TEXT482 "I'M HAVING A GREAT TIME KILLING VAMPIRES WITH THIS THING! "
+#define TEXT483 "LET'S SEE IF ANOTHER ONE COMES SOON! "
+#define TEXT484 "NO, IT HAS TO BE WITH A DIRTY AND STINKY VAMPIRE, JUST LIKE THE ONE I KILLED BEFORE "
+#define TEXT485 "THIS IS THE ONE AND ONLY WIG ELVIS USED WHEN HE GOT BALD"
+#define TEXT486 "IT'S FLOUR, BUT DON'T ASK ME ANY COMMERCIAL NAMES. "
+#define TEXT487 "MAYBE ANOTHER TIME, OK? "
+#define TEXT488 "THAT'S A GREAT AXE, IT'S A SHAME THERE IS NO VAMPIRE'S HEAD AROUND HERE, HUH? "
+#define TEXT489 "NO. I'M REALLY A GOOD PERSON. "
+#define TEXT490 "IT'S MARGARET'S THATCHER DEODORANT...HA, HA, HA...!! "
+#define TEXT491 "THAT'S A PRETTY CUTE CLOAK "
+#define TEXT493 "JUST LIKE ALL BRANCHES FROM ANY TREE IN THE WORLD, THERE IS NOTHING SPECIAL. "
+#define TEXT494 "HEY, THAT'S AMAZING! A ROPE WITHIN THIS TYPE OF ADVENTURE!"
+#define TEXT495 "I WONDER WHAT WE COULD USE IT FOR... "
+#define TEXT496 "A ROPE TIED TO A BRANCH OR THE OTHER WAY AROUND, HOWEVER YOU WANT TO PUT IT..."
+#define TEXT497 " IT LOOKS LIKE THIS MAGPIE IS EVIL-MINDED"
+#define TEXT498 "FORGET IT, I'M NOT SAYING ANYTHING IN CASE HE GETS MAD "
+#define TEXT499 "SHE LOOKS DEAD, BUT SHE REALLY ISN'T, HUH? "
+#define TEXT500 "NO ANIMAL WAS HARMED DURING THE PRODUCTION OF THIS GAME "
+#define TEXTB1 "I'M HERE, DRINKING "
+#define TEXTB10 "FROM TIME TO TIME HE COMES DOWN TO THE VILLAGE AND TAKES SOMEONE WITH HIM.. "
+#define TEXTB11 "A LITTLE WHILE AFTER WE JUST A FEW FOUND BODY PARTS. I THINK HE IS DEALING WITH ORGANS OR SOMETHING LIKE THAT"
+#define TEXTB12 "THE ONLY PERSON IN THE VILLAGE WHO KNOWS HOW TO END UP WITH DRASCULA IS A CULTIVATED PERSON "
+#define TEXTB13 "HE LIVES IN A LOG-CABIN OUT OF TOWN, EVER SINCE DRASCULA BEAT HIM UP. "
+#define TEXTB14 "HE IS THE ONLY ONE WHO COULD HELP US WITH DRASCULA, AND HE DOESN'T WANT TO HEAR ABOUT US. HOW DO YOU LIKE THAT? "
+#define TEXTB2 "THEY ARE ALL DEAD, THANKS. BURPP... "
+#define TEXTB3 "YES, SURE... "
+#define TEXTB4 "SHE FEELS ATTRACTED TO UNCLE DESIDERIO. "
+#define TEXTB5 "EVEN BETTER, UNCLE DESIDERIO'S DEAD BODY. "
+#define TEXTB6 "MY UNCLE. HE WENT TO CASTLE AND NEVER CAME BACK "
+#define TEXTB7 "WELL, HE CAME BACK JUST A LITTLE. IF ONLY VON BRAUN HADN'T SCREWED THINGS UP MY UNCLE WOULD BE DRINKING WITH US NOW. "
+#define TEXTB8 "NOTHING... "
+#define TEXTB9 "WELL, YES !. THAT MEAN MAN HAS TERRIFIED US ALL. "
+#define TEXTBJ1 "ARE YOU ALL RIGHT?. HEY, COME ON, WAKE UP! CAN YOU HEAR ME ? ARE YOU DEAD? "
+#define TEXTBJ10 "OH, NO...! IT WASN'T THE HIT, HA, HA. I JUST STEEPED ON YOUR GLASSES BY ACCIDENT "
+#define TEXTBJ11 "YOU REALLY LOOK GOOD WITH THOSE GLASSES. I KNOW HE'S NOT FERNANDO LANCHA, BUT I FIND HIM ATTRACTIVE... "
+#define TEXTBJ12 "YES, YES, I DO...COME ON, HOLD ME AND KISS ME TIGHT "
+#define TEXTBJ13 "OH JHONNY, HONEY, THANKS GOD YOU'RE HERE...THAT DAMNED DRASCULA TIED ME UP TO THE BED AND THEN HE'S GONE DOWNSTAIRS TO SEE THE FOOTBALL GAME. "
+#define TEXTBJ14 "YES, IT'S TRUE. PLEASE, SET ME FREE "
+#define TEXTBJ15 "NO, I'M SORRY. I USED THEM ALL IN THE TOWER WHEN I WAS TRYING TO LIBERATE WHILE YOU LET ME DOWN. "
+#define TEXTBJ16 "JOHNNY, IS THAT YOU?. OH, GOD, GREAT! I KNEW YOU'D COME! "
+#define TEXTBJ17 "YOU DON'T EVEN KNOW HOW MUCH THAT EVIL DRASCULA HAS MADE ME SUFFER "
+#define TEXTBJ18 "FIRSTLY HE BROUGHT ME FLYING OVER HER AND THEN PUT ME IN THIS DISGUSTING ROOM WITHOUT EVEN A MIRROR OR ANYTHING "
+#define TEXTBJ19 "I'M TELLING YOU!, AND THE WORSE PART IS THAT HE DIDN'T EVEN APOLOGIZE, NOT EVEN ONCE "
+#define TEXTBJ2 "NO, MY NAME IS BIlLIE JEAN, BUT YOU CAN CALL ME B. J., IT'S SHORTER "
+#define TEXTBJ20 "JHONNY HONEY, WHERE ARE YOU? "
+#define TEXTBJ21 "I'M READY TO LEAVE DEAR. "
+#define TEXTBJ22 "WAIT, I'M GOING TO TAKE A LOOK...NO DARLING, I'M SORRY "
+#define TEXTBJ23 "THERE YOU GO... "
+#define TEXTBJ24 "\"DEAR JOHNNY\""
+#define TEXTBJ25 "I'LL NEVER FORGET YOU BUT I HAVE REALIZED THAT THIS JUST COULDN'T WORK OUT RIGHT. TO BE HONEST WITH YOU I'LL TELL YOU THAT THERE IS ANOTHER MAN. HE IS TALLER, STRONGER... "
+#define TEXTBJ26 "AND HE HAS ALSO RESCUED ME FROM DRASCULA. HE HAS ASKED ME TO MARRY HIM, AND I HAVE ACCEPTED. "
+#define TEXTBJ27 "BYE JHONNY. PLEASE DON'T TRY TO FIND SOME KIND OF EXPLANATION. YOU KNOW LOVE IS BLIND AND HAS ITS OWN WAYS "
+#define TEXTBJ28 "I HOPE THERE WON'T BE HARD FEELINGS BETWEEN US. REMEMBER THAT I STILL LOVE YOU, BUT ONLY AS A FRIEND "
+#define TEXTBJ3 "HA, HA...! THAT WAS A GOOD ONE! "
+#define TEXTBJ4 "WELL, JHONNY. YOU SEE, I WAS HERE JUST READY TO GO TO BED WHEN I HEARD THIS STRONG NOISE DOWN THE CORRIDOR. "
+#define TEXTBJ5 "I DIDN'T PAY ATTENTION AT FIRST, BUT AFTER ABOUT TWO HOURS OR SO I COULDN'T SLEEP AND WENT OUT FOR A WALK. "
+#define TEXTBJ6 "AS I OPENED THE DOOR I WAS SHOCKED TO FIND YOU THERE, LYING ON THE FLOOR. I THOUGHT YOU WERE DEAD, I SWEAR...HA, HA, SILLY BILLY. "
+#define TEXTBJ7 "I WAS GOING TO GIVE YOU THE KISS OF LIFE BUT IT WASN'T NECESSARY BECAUSE YOU STARTED TO TALK "
+#define TEXTBJ8 "YOU SAID SOMETHING ABOUT A SCARECROW. I WAS VERY SCARED, YOU KNOW. IT'S A REAL SHOCK WHEN A DEAD PERSON STARTS TALKING RIGHT? "
+#define TEXTBJ9 "ISN'T THAT RIGHT?, WELL, THEN I MANAGED TO BRING YOU TO MY ROOM THE BEST WAY I COULD. I PUT YOU IN BED...AND THAT'S ALL...HA, HA, HA... "
+#define TEXTD1 "HEY IGOR, HOW ARE THINGS? "
+#define TEXTD10 "THE TIME HAS COME ! TURN ON THE ALKALINE BATTERIES' SWITCH. "
+#define TEXTD11 "DAMNED IT! WHAT WENT WRONG? "
+#define TEXTD12 "ARE YOU SURE YOU CHECKED IT ALL AND THERE WAS NOTHING MISSING?. YOU'VE BEEN LATELY MESSING AROUND WITH THAT STUFF ABOUT TAXES AND I DON'T KNOW MAN... "
+#define TEXTD13 "YOU STUPID THING! YOU FORGOT TO CONNECT THE INDIFIBULATOR. THE SCREWS HAVE PROBABLY MAGNETIZED AND HIS BRAIN BURNT "
+#define TEXTD14 "YOU ARE DEAD, YOU ARE DEAD...WAIT TILL I GET YOU! "
+#define TEXTD15 "SHUT UP! I'LL GET ANOTHER BRAIN TOMORROW AND THEN WE WILL REPEAT THE EXPERIMENT "
+#define TEXTD16 "THIS TIME I'LL GET A WOMAN'S BRAIN. SHINY AND NOT USED YET...HA, HA, HA, GOODIE ONE! "
+#define TEXTD17 "SO WHAT? I'M THE BAD GUY, RIGHT? SO I CAN BE AS FULL OF MACHISMO AS I WANT, ALL RIGHT?. AND IF YOU SAY SOMETHING AGAIN I'LL TURN YOUR HUMP BACK TO FRONT!"
+#define TEXTD18 "HA, HA, HA. YOU FELL TOOO!! WHAT IS IT, ARE YOU ALL STUPID IN THIS COUNTRY?. DIDN'T YOU READ THE SIGN SAYING \"DRASCULA DOES NOT SLEEP HERE\"? IGOR, YOU ARE GOING TO PAY FOR DARING TO FIGHT AGAINST ME!"
+#define TEXTD19 "AND SO, TELL ME , YOU STUPID HUMAN. HOW COME YOU WANT TO DESTROY ME? "
+#define TEXTD2 "IT'S ALWAYS THE SAME STORY. EVERYTIME THERE'S A GOOD GAME ON THE SATELLITE! ANYWAY, WE'LL GO SEE IT IN THE BAR, AS USUAL "
+#define TEXTD20 "THAT'S BEAUTIFUL!. IF IT WASN'T BECAUSE IT MAKES ME LAUGH, I WOULD CRY. "
+#define TEXTD21 "OUR GIRLFRIEND'S BRAIN TO HELP ME CONQUERING THE WORLD "
+#define TEXTD22 "YES, SURE! I'LL TAKE IT FROM HER AND GIVE IT TO MY FRUSKYNSTEIN. THE WORLD WILL BE MINE WITH IT, HA, HA. "
+#define TEXTD23 "NO WHAT!?. YOU'RE DEAD, MAN! I'M GOING TO...YOU REALLY GOT ME ANGRY MAN...COME ON, PREPARE TO DIE! "
+#define TEXTD24 "HA, HA, HA. NOT EVEN IN YOUR WILDEST DREAMS! "
+#define TEXTD25 "YES, ISN'T IT? HA, HA, "
+#define TEXTD26 "ALL RIGHT, ALL RIGHT. BUT DO IT QUICKLY, OK? "
+#define TEXTD27 "PUT THAT CIGARETTE OUT NOW! I CAN'T STAND YOU ANYMORE! "
+#define TEXTD28 "AND SO, DOES THAT BREW HAVE THE OPPOSITE EFFECT? "
+#define TEXTD29 "WELL, WE'LL SEE THAT "
+#define TEXTD3 "IGOR LISTEN CAREFULLY MAN, WE ARE GOING TO START WITH PHASE NUMBER ONE OF MY PLAN TO CONQUER THE WORLD. "
+#define TEXTD30 "OK, LET'S SEE IT. IGOR, BRING ME THE CD \"SCRATCHING YOUR NAILS ALL OVER THE BLACKBOARD\""
+#define TEXTD31 "NO WAY. THE GIRL STAYS WITH ME. YOU RE STAYING THERE UNTIL THE PENDULUM CUTS YOU INTO THIN SLICES. HA, HA, HA. "
+#define TEXTD32 "MAN I'M I JUST BAD... COME ON IGOR, LET'S MAKE THE BREW AND CONQUER THE WORLD."
+#define TEXTD33 "WHAT HAPPENS NOW? "
+#define TEXTD34 "YES, WHAT?...OH, DAMNED, THE GAME! "
+#define TEXTD35 "I FORGOT ABOUT THAT. GET THE GIRL AND LET'S GO AND SEE HIM. WE CAN CONQUER THE WORLD LATER. "
+#define TEXTD36 "THANKS MAN, I WAS THIRSTY "
+#define TEXTD37 "OH, THE CRUCIFIX!!...THE CRUCIFIX...! "
+#define TEXTD38 "I DIDN'T NOTICE ABOUT THAT BEAUTIFUL CRUCIFIX! "
+#define TEXTD39 "LEAVE ME ALONE!, I'M WATCHING THE GAME "
+#define TEXTD4 "FIRST WE'LL CAPTURE ONE OF THE STORM'S LIGHTNINGS AND WE'LL DEMAGNETIZE IT WITH OUR INDIFIBULATOR. THE ELECTRICITY WILL COME THROUGH TO MY MONSTER AND HE'LL GET ALIVE! "
+#define TEXTD5 "IF EVERYTHING WORKS OUT ALL RIGHT, THIS WILL BE THE BEGINNING OF A GREAT ARMY THAT WILL CONQUER THE WORLD FOR ME. HA, HA,. "
+#define TEXTD6 "THE MONSTERS WILL DESTROY ALL THE ARMY'S WEAPONS IN THE WORLD, MEANWHILE, WE'LL BE SAFE IN THE PIECES OF LAND I BOUGHT IN GIBRALTAR."
+#define TEXTD7 "WE'LL SET UP A COUP. GOVERNMENTS ALL OVER THE WORLD WILL BE UNCOVERED AND THEIR COUNTRIES WILL SURRENDER TO ME! "
+#define TEXTD8 "I'LL BECOME THE FIRST BAD GUY IN HISTORY TO MAKE IT ! HA, HA ! "
+#define TEXTD9 "I'M NOT TALKING TO YOU, IDIOT! I'M JUST GIVING YOU THE PLOT. ALL RIGHT, EVERYTHING READY?"
+#define TEXTE1 "YOU...HEY YOU! "
+#define TEXTE10 "YEAH, IT'S YOU "
+#define TEXTE11 "WHY DO ALL ADVENTURE GAMES END UP WITH A SUNRISE OR A SUNSET? "
+#define TEXTE12 "DO ALL THESE NAMES BELONG TO THE CREATORS OF THE GAME?"
+#define TEXTE13 "AREN'T THEY ASHAMED TO BE SEEN BY EVERYBODY? "
+#define TEXTE14 "JESUS, THAT EMILIO DE PAZ IS EVERYWHERE!! "
+#define TEXTE15 "REALLY? "
+#define TEXTE16 "YES "
+#define TEXTE17 "WELL, DON'T MAKE A FUSS ABOUT IT. "
+#define TEXTE18 "HEY WEREWOLF, BY THE WAY... "
+#define TEXTE19 "DIDN'T YOU FALL OFF A WINDOW AND GOT BADLY HURT "
+#define TEXTE2 "DON'T GIVE ME THAT CRAP ABOUT A DEAD BODY OK? "
+#define TEXTE20 "IF AT LEAST IT WASN'T ALWAYS THE SAME ONES... "
+#define TEXTE21 "HE'S BEEN OUT FOUR TIMES ALREADY. "
+#define TEXTE22 "I'D LIKE TO BE A MODEL "
+#define TEXTE23 "ALL RIGHT, AND WHAT ARE YOU GOING TO DO? "
+#define TEXTE3 "I'M ALIVE. IT'S JUST THAT I'M STARVING. "
+#define TEXTE4 "WELL, YOU SEE. I WAS THE DRUNKARD OF THE VILLAGE, JUST KEEPING UP WITH THE FAMILY TRADITION, YOU KNOW?, ONE NIGHT DRASCULA KIDNAPPED ME TO TAKE MY ORGANS AWAY. "
+#define TEXTE5 "SINCE ALCOHOL STILL KEEPS ME QUITE YOUNG, I'M HERE LIKE A SCRAP YARD. EVERYTIMR HE NEEDS SOMETHING FOR THE MONSTER HE IS CREATING, HE JUST COMES AND TAKES IT FROM ME."
+#define TEXTE6 "IT HURT AT FIRST, BUT I DON'T CARE ANYMORE "
+#define TEXTE7 "I DON'T KNOW. I GUESS IT'S HIS GRADUATE PROJECT. "
+#define TEXTE8 "I'M DESIDERIO, AND I CAN HELP YOU IN ANYTHING YOU NEED. "
+#define TEXTE9 "THE TRUTH IS THAT I DON'T REALLY FEEL LIKE IT, BUT THANKS VERY MUCH ANYWAY SIR. "
+#define TEXTI1 "MASTER, I THINK THIS IS NOT WORKING "
+#define TEXTI10 "YES, MY MASTER "
+#define TEXTI11 "MASTER "
+#define TEXTI12 "DO YOU KNOW WHAT TIME IS IT ? "
+#define TEXTI13 "WHAT?, OH, THAT SCARED ME !. YOU ARE THE \"NIGHT-CLEANING GUY\", RIGHT?"
+#define TEXTI14 "I'M IGOR, THE VALET. YOU CAN START WITH THE BALL ROOM. THERE'S BEEN A SUPER NATURAL ORGY YESTERDAY AND IT LOOKS LIKE SHIT. "
+#define TEXTI15 "IF YOU NEED ANYTHING, JUST BUY IT. "
+#define TEXTI16 "IT'S THE TAX RETURN APPLICATION FORM, CAN'T YOU SEE IT? "
+#define TEXTI17 "NEITHER DO I. FIRST OF ALL THE NUMBERS ARE VERY SMALL AND ALSO I CAN'T SEE MUCH AT THIS DISTANCE.. "
+#define TEXTI18 "NO WAY!. THEY MAKE ME LOOK UGLY. "
+#define TEXTI19 "OH, WELL. IT'S JUST LIKE A CRAZY PARTY THAT THE MASTER ORGANIZES WITH HIS FRIENDS EACH TIME SOME IDIOT COMES ALONG TRYING TO KILL HIM."
+#define TEXTI2 "I AM POSITIVE, MASTER "
+#define TEXTI20 "THEY TAKE HIS EYES OUT. THEN, POUR SOME LEMON JUICE SO THAT IT ITCHES TO DEATH, AND THEN... "
+#define TEXTI21 "NO"
+#define TEXTI22 "WHAT DO YOU MEAN WHY NOT? DO YOU KNOW WHAT TIME IT IS? "
+#define TEXTI23 "YES, IT'S WINTER "
+#define TEXTI24 "SEE YOU LATER "
+#define TEXTI25 "DON'T EVEN THINK ABOUT IT! "
+#define TEXTI26 "WELL, THAT'S ENOUGH FOR TODAY. I'M GOING TO HAVE SUPPER "
+#define TEXTI27 "MAN, I ALWAYS FORGET TO LOCK IT, RIGHT? "
+#define TEXTI28 "THE HELL WITH IT! "
+#define TEXTI29 "WHAT?. OH, YOU SCARED ME MASTER, I THOUGHT YOU WERE ASLEEP. "
+#define TEXTI3 "I'M SORRY MASTER "
+#define TEXTI30 "OH, BY THE WAY, I TOOK THE LIVING-ROOM KEYS SO THAT YOU CAN WATCH THE EARLY MORNING CARTOONS WITHOUT WAKING ME UP. "
+#define TEXTI31 "YOU'VE GOT ANOTHER COLD MASTER? DAMN IT!. I TOLD YOU TO GET SOME HEATING IN HERE... "
+#define TEXTI32 "ALL RIGHT, JUST TAKE YOUR ASPIRIN AND GO TO BED TO SWEAT FOR A WHILE. GOOD NIGHT "
+#define TEXTI4 "ARE YOU GOING TO BRING HERE ANOTHER CRAZY SCIENTIST? I'LL TELL YOU THAT THE LABORATORY IS ALREADY PACKED UP, AND BESIDES, THEY'RE ALL OUT OF DATE. "
+#define TEXTI5 "HUSH MASTER, THE FEMINIST COULD HEAR YOU"
+#define TEXTI6 "DAMNED IT! "
+#define TEXTI7 "I DIDN'T EXPECT YOU SO SOON, MASTER."
+#define TEXTI8 "QUITE BAD MASTER. THERE MUST BE SOME PROBLEMS WITH THE SATELLITE AND I JUST CAN'T RECEIVE ANYTHING. BESIDES THERE ARE SOME INTERFERENCES BECAUSE OF THE STORM."
+#define TEXTI9 "WHAT DO I KNOW, MASTER? "
+#define TEXTL1 "WAIT A MINUTE. ARE YOU GOING TO LET OURSELVES BE GUIDED BY OUR MOST PRIMITIVE INSTINCTS JUST BECAUSE WE BELONG TO DIFFERENT RACES AND THE SOCIAL SITUATION IS TELLING US TO DO SO? "
+#define TEXTL10 "PUKE! HUNTING AS A WAY TO SURVIVE IS AN INCOMPATIBLE ARCHAIC THING FOR A SUPERIOR BEING LIKE ME. BESIDES, I'VE BECOME A VEGETARIAN"
+#define TEXTL11 "IT JUST HAPPENS THAT I WAS ACTUALLY EATING A GUY AND I STARTED TO BETHINK AND GET TO THE ABOVE MENTIONED THOUGHT. "
+#define TEXTL12 "IT TOOK ME A LONG TIME TO QUIT OLD HABITS BUT AT LEAST MY IRASCIBLE SOUL BIT UP THE CONCUPISCIBLE ONE, AND EVER SINCE, I'VE NEVER EATEN MEAT AGAIN "
+#define TEXTL13 "NOT EVEN THE PLEASURE OF SUCKING UP THE BONE, FEELING THE TASTE OF THE SKIN AND THAT SWEET TASTE OF MARROW...THAT JUST TAKES YOU TO HEAVENLY PLACES. "
+#define TEXTL14 "IT DOESN'T REALLY GET TO ME AT ALL. "
+#define TEXTL15 "WHAT? "
+#define TEXTL16 "I DON'T KNOW WHAT YOU'RE TALKING ABOUT, YOU EPHEMERAL CREATURE "
+#define TEXTL17 "I'M NOT INTERESTED "
+#define TEXTL18 "I DON'T KNOW ABOUT THE OTHER GAMES, BUT WE COULD USE THIS BEAUTIFUL SCREEN."
+#define TEXTL2 "AREN'T WE TIED BY SENSE WHICH IS THE MOST POWERFUL WEAPON AS WELL AS THE MOST PRECIOUS GIFT? "
+#define TEXTL20 "I'D CARE... "
+#define TEXTL21 "NO. IT'S JUST THE SON, THE FATHER, THE GRANDFATHER AND A FRIEND, WHO ARE CALLED LIKE THAT."
+#define TEXTL22 "BUT, IT IS GOING TO LOOK LIKE THE GAME WAS MADE BY FIVE PEOPLE. "
+#define TEXTL23 "THESE ARE PROMISING GUYS "
+#define TEXTL24 "THAT'S A GOOD ONE! A GOOD ONE!"
+#define TEXTL25 "PLEASE, CALL ME CONSTANTINO "
+#define TEXTL26 "IT WASN'T ME MAN. IT WAS \"EL COYOTE\", MY TWIN"
+#define TEXTL27 "JESUS, THESE ARE REALLY LONG CREDIT TITLES "
+#define TEXTL28 "I STOPPED COUNTING A LONG TIME AGO "
+#define TEXTL29 "WHAT WILL BECOME OF YOU NOW, DESIDERIO? "
+#define TEXTL3 "OH, IF WE ALL LET OUR THOUGHTS GUIDE OUR WAY IN LIFE WITHOUT LEAVING SOME ROOM FOR FEELINGS WHICH ARE PRECISELY WHAT LET'S OUR PRE-EVOLUTIVE INSTINCTS COME OUT! "
+#define TEXTL30 "BUT, YOU SHOULD LOSE SOME WEIGHT "
+#define TEXTL31 "I'LL JUST RETIRE TO THE TIBET AND THINK ABOUT THE MEANING OF LIFE "
+#define TEXTL4 "ANSWER ME, EPHEMERAL CREATURE. WOULDN'T WE ALL BE HAPPIER WITH THOSE EMOTIONAL BOUNDINGS? "
+#define TEXTL5 "YOU ARE NOT GETTING THROUGH "
+#define TEXTL6 "THIS IS A VERY CLEAR EXAMPLE, YOU SEE?: YOU WANT TO GET THROUGH AND GO AHEAD WITH YOUR ADVENTURE, AND I WON'T LET YOU DO THAT"
+#define TEXTL7 "WILL THAT BE A CONTROVERSIAL POINT BETWEEN US THAT HAVE JUST MET? "
+#define TEXTL8 "WELL THEN "
+#define TEXTL9 "WELL, THAT DEPENDS ON WHAT WE TAKE A RELATIONSHIP FOR. SOME AUTHORS DEFEND... "
+#define TEXTP1 "HI "
+#define TEXTP10 "I'M A CONSERVATOIRE PIANIST AND THE BARTENDER WON'T BUY MORE SCORES FOR ME "
+#define TEXTP11 "OH GOD, I REALLY LOVE CLASSIC MUSIC! "
+#define TEXTP12 "IT'S BECAUSE I'M WEARING EAR-PLUGS"
+#define TEXTP13 "IT'S BECAUSE I CAN LIP-READ "
+#define TEXTP14 "NOOO "
+#define TEXTP15 "NO! I'M NOT TAKING THIS ANY LONGER! "
+#define TEXTP16 "NO WAYYYYY! "
+#define TEXTP17 "WHAT?, OF COURSE I'M INTERESTED "
+#define TEXTP18 "THANKS GOD! I CAN PLAY A DIFFERENT SONG NOW! "
+#define TEXTP19 "I GUESS YOU CAN KEEP MY EAR-PLUGS "
+#define TEXTP2 "YES SIR. IT'S BEAUTIFUL "
+#define TEXTP3 "NO, NO. HE WON'T DO IT "
+#define TEXTP4 "ALL RIGHT THEN "
+#define TEXTP5 "REALLY? "
+#define TEXTP6 "AND? "
+#define TEXTP7 "I'M SORRY. THE PIANIST UNION TRADE DOESN'T ALLOW ME TO SAVE GIRLS FROM VAMPIRES' CLUTCHES "
+#define TEXTP8 "IF YOU HAD BEEN KIDNAPPED BY THE WEREWOLF..."
+#define TEXTP9 "I CAN ONLY PLAY THIS SONG "
+#define TEXTT1 "WHAT HAPPENS, WHAT'S THE MATTER? "
+#define TEXTT10 "THEY'RE WINNING "
+#define TEXTT11 "LEAVE ALONE, ALL RIGHT? "
+#define TEXTT12 "OF COURSE. I'M NOT BLIND "
+#define TEXTT13 "THE TRADITION IN THIS VILLAGE IS TO FORGET ALL HARD FEELINGS WHENEVER THERE IS A GAME, SO AS TO CHEER UP THE LOCAL TEAM "
+#define TEXTT14 "AND PLEASE, SHUT UP FOR GOD'S SAKE. I CAN'T HEAR ANYTHING! "
+#define TEXTT15 "COME ON, LEAVE ME ALONE AND DON'T BOTHER ME ANYMORE "
+#define TEXTT16 "IT HAS JUST STARTED! AND SHUT UP! "
+#define TEXTT17 "OK, OK, I THOUGHT SOMETHING WAS GOING ON. "
+#define TEXTT18 "IT DOESN'T MATTER, ANYWAY. SHE'LL PROBABLY BE DEAD BY NOW. "
+#define TEXTT19 "HE JUST STARTED PLAYING CLASSIC MUSIC, AND I COULDN'T STAND IT "
+#define TEXTT2 "OK. ROOM 512. UPSTAIRS. THE KEY IS ON THE DOOR "
+#define TEXTT20 "SINCE I'M PAYING HIM FOR PLAYING WHATEVER I WISH, I JUST FIRED HIM. "
+#define TEXTT21 "AND THEN, HE GOT FRESH WITH ME. JESUS!, HE LOOKED SO NICE AND INNOCENT...WHAT A HYPOCRITE! "
+#define TEXTT22 "BY THE WAY, BE CAREFUL BECAUSE I JUST WAXED THE FLOOR. "
+#define TEXTT23 "SHUT UP! WE'RE WATCHING THE GAME! "
+#define TEXTT24 "OH, COME ON! TAKE IT! "
+#define TEXTT3 "COUNT DRASCULA!!? "
+#define TEXTT4 "NO, NOTHING. THAT GUY HAS A BAD REPUTATION OVER HERE. "
+#define TEXTT5 "WELL, THERE ARE ALL KINDS OF STORIES GOING AROUND ABOUT HIM, SOME SAY HE IS A VAMPIRE WHO KIDNAPS PEOPLE TO SUCK UP THEIR BLOOD. "
+#define TEXTT6 "HOWEVER, SOME OTHERS SAY THAT HE IS JUST AN ORGAN-DEALER AND THAT IS THE REASON WHY THERE ARE BODY PARTS ALL OVER THE PLACE."
+#define TEXTT7 "BUT OF COURSE, THOSE ARE JUST RUMORS. HE'S PROBABLY BOTH THINGS. BY THE WAY, WHY DO YOU WANT TO MEET HIM? "
+#define TEXTT8 "NO, FORGET IT. I'M REALLY BUSY... "
+#define TEXTT9 "WELL, OK. BUT JUST BECAUSE I WANT TO DO IT, NOT BECAUSE YOU TELL ME TO. "
+#define TEXTVB1 "WHO THE HELL IS CALLING AT THIS TIME ? "
+#define TEXTVB10 "YOU DON'T HAVE THEM "
+#define TEXTVB11 "I'M SURE YOU WOULDN'T BET ALL YOUR MONEY ON IT, HUH? "
+#define TEXTVB12 "WELL, ALL RIGHT, COME ON IN "
+#define TEXTVB13 "IF YOU REALLY MEAN TO FACE DRASCULA, YOU'VE GOT TO BE ABLE TO TAKE ALL TYPES OF CREAKING AND VAMPIRE-LIKE NOISES "
+#define TEXTVB14 "IS THAT CLEAR? "
+#define TEXTVB15 "OK, WAIT A MINUTE "
+#define TEXTVB16 "STAND IN THE CENTER OF THE ROOM, PLEASE "
+#define TEXTVB17 "WHERE DID I PUT THAT RECORD CALLED \"NAILS SCRATCHING THE BLACKBOARD\"?"
+#define TEXTVB18 "ALL RIGHT. LET'S GET TO IT. "
+#define TEXTVB19 "YOU ARE USELESS. YOU SEE...?, JUST LIKE THE REST!! "
+#define TEXTVB2 "OH, ..OH, NO, NO....I'M...GANIMEDES THE DWARF. PROFESSOR VON BRAUN DOESN'T LIVE HERE ANYMORE. "
+#define TEXTVB20 "JUST GIVE ME NOW THE MONEY YOU LOST AND GET OUT OF HERE "
+#define TEXTVB21 "AND DON'T COME BACK UNTIL YOU ARE ABSOLUTELY READY "
+#define TEXTVB22 "WHAT DO YOU WANT NOW? "
+#define TEXTVB23 "I HAVE TO ADMIT IT. YOU REALLY GOT WHAT IT TAKES TO FIGHT AGAINST THE VAMPIRES. "
+#define TEXTVB24 "HEY, TAKE YOUR MONEY. I ADMIT IT WHEN I MAKE A MISTAKE... "
+#define TEXTVB25 "LEAVE ME ALONE NOW, I WANT TO GET SOME SLEEP. "
+#define TEXTVB26 "WHENEVER YOU ARE READY TO FIGHT AGAINST THE VAMPIRES, JUST COME BACK AND I'LL HELP YOU OUT. "
+#define TEXTVB27 "OH, THAT'S EASY. JUST USING THE LIGHT OF ONE CRUCIFIX IS ENOUGH TO DESTROY HIM. "
+#define TEXTVB28 "YOU HAVE TO BE EXTRA CAREFUL WITH DRASCULA, HIS FRISISNOTICS POWERS HAVE MADE OF HIM THE MOST POWERFUL VAMPIRE "
+#define TEXTVB29 "YOU'D BE LOST IF IT WASN'T FOR THE... "
+#define TEXTVB3 "NO, I DON'T KNOW WHERE IT IS !! "
+#define TEXTVB30 "...BREW! "
+#define TEXTVB31 "YEAH, YOU'RE RIGHT! I MIGHT HAVE SOME PROBLEMS WITH MY BACK IN THE FUTURE IF I KEEP ON SLEEPING THIS WAY "
+#define TEXTVB32 "WELL, OK, I UNDERSTAND HE WAS A BETTER OPPONENT THAN ME, BUT YOU HAVE TO ADMIT THAT THE DISCOVERY I MADE ABOUT ANTI-VAMPIRE TECHNIQUES WAS WHAT ACTUALLY PROTECTED ME. "
+#define TEXTVB33 "I'VE FOUND THIS IMMUNIZING BREW THAT KEEPS YOU SAFE FROM ANY VAMPIRES' BITE OR AGAINST HIS FRISISNOTICS POWERS."
+#define TEXTVB34 "NO, NO, EXCUSE ME. I HAD IT ONCE BUT IT'S VERY DANGEROUS TO HAVE A BREW OF THAT TYPE. CAN YOU IMAGINE WHAT COULD HAPPEN IF A VAMPIRE GOT IT? "
+#define TEXTVB35 "HE'D BE IMMUNIZED AGAINST GARLIC, THE CRUCIFIX, THE SUNSHINE LIGHT...I JUST HAD TO GET RID OF WHAT WAS LEFT FROM IT. TO DO IT I USED THIS SCIENTIFIC METHOD OF THROWING IT IN THE LAVATORY"
+#define TEXTVB36 "DON'T WORRY, I REMEMBER EXACTLY HOW TO MAKE THAT BREW. "
+#define TEXTVB37 "I NEED GARLIC, BUT I ALREADY HAVE THEM. HOWEVER YOU'LL HAVE TO GET ME SOME WAX, BUBBLE GUM AND CIGARETTE PAPER OR PERHAPS A NAPKING OR SOMETHING ALIKE "
+#define TEXTVB38 "OH...AND OF COURSE THE MOST IMPORTANT INGREDIENT. LEAVES FROM A VERY STRANGE PLANT CALLED FERNAN. "
+#define TEXTVB39 "IT'S A CLIMBING PLANT WHICH LEAVES HAVE MAGIC POWERS IF THEY'RE CUT WITH A GOLDEN SICKLE. "
+#define TEXTVB4 "GET OUT!! "
+#define TEXTVB40 "SO THAT AS SOON AS YOU HAVE THESE FIVE THINGS, JUST COME HERE AND I'LL MAKE THE BREW. "
+#define TEXTVB41 "YOU'LL BE READY THEN TO FIGHT AGAINST DRASCULA "
+#define TEXTVB42 "REMEMBER: WAX, NICOTINE, A PIECE OF BUBBLE GUM, A PAPER AND SOME FERNAN'S LEAVES CUT WITH A GOLDEN SICKLE."
+#define TEXTVB43 "I TOLD YOU! IT WAS JUST BECAUSE OF THE BREW! "
+#define TEXTVB44 "OH, ALL RIGHT. I'M GOING TO MAKE MYSELF A...THE BREW. JUST A MOMENT, OK? "
+#define TEXTVB45 "IT'S A PROTECTING SPELL AGAINST VAMPIRES. "
+#define TEXTVB46 "I PUT IT THERE IN ORDER TO PRETEND THAT THE SKETCHER DIDN'T FORGET TO DRAW THE WINDOW YOU CAN SEE FROM OUTSIDE. "
+#define TEXTVB47 "ALL RIGHT, THE FIRST THING YOU MUST KNOW IS THE WAY TO DRASCULA'S CASTLE. "
+#define TEXTVB48 "THERE IS A CAVERN THAT GETS YOU STRAIGHT FROM THE CASTLE. IGOR, THE CRAZY ELVIS' FUN, TAKES IT TO GET TO THE VILLAGE EACH MORNING. "
+#define TEXTVB49 "BE CAREFUL THOUGH, THERE IS A VAMPIRE ALWAYS WATCHING OVER IT. YOU'LL HAVE TO GET RID OF HIM. "
+#define TEXTVB5 "IT'S TOO LATE NOW, YOU IDIOT!! IT ALWAYS IS "
+#define TEXTVB50 "THERE IS AN OLD WELL RIGHT BY THE CEMETERY CHURCH "
+#define TEXTVB51 "IT WAS USED A LONG TIME AGO FOR WITCHCRAFT TRIALS "
+#define TEXTVB52 "THEY THREW THE WITCHES IN THE WELL. IF THEY DROWNED THEY WERE REAL WITCHES. IF THEY DIDN'T, THEY WEREN'T. "
+#define TEXTVB53 "WE THREW ONE ONCE AND SHE DIDN'T DROWN, I GUESS SHE WASN'T A WITCH "
+#define TEXTVB54 "ANYWAY. THERE IS YOUR BREW. HOWEVER, I ONLY GOT TO MAKE ENOUGH JUST FOR ONE PERSON "
+#define TEXTVB55 "YOU'D BETTER SMOKE IT RIGHT BEFORE YOU FIGHT AGAINST DRASCULA "
+#define TEXTVB56 "COME ON, RUN! "
+#define TEXTVB57 "OH, JUST EXCUSES...! "
+#define TEXTVB58 "ARE YOU JOHN HACKER? I'M DOCTOR VON BRAUN "
+#define TEXTVB59 "LISTEN TO ME, THIS IS VERY IMPORTANT. IT'S ABOUT THE BREW"
+#define TEXTVB6 "I COULDN'T AGREE MORE. "
+#define TEXTVB60 "SHUT UP AND LET ME TALK. I JUST FOUND THIS BOOK ABOUT ANTI-VAMPIRE BREWS WARNING AGAINST MIXING THE JOINT WITH ANY ALCOHOLIC DRINK BEFORE YOU"
+#define TEXTVB61 "ALCOHOL REACTS WHEN MIXED WITH BREW, SO THAT IT CANCELS OUT ITS EFFECTS JUST IN A FEW SECONDS. "
+#define TEXTVB62 "I'M SORRY, BUT I HAVE TO HANG UP RIGHT NOW. THE POLICE IS LOOKING FOR ME, THEY THINK I'M A PUSHER. STUPID, ISN'T IT?. ANYWAY, BYE AND GOOD LUCK SAVING THE WORLD! "
+#define TEXTVB7 "ME, SCARED? "
+#define TEXTVB8 "LISTEN HERE, DUDE. YOU'RE RIGHT NOW TALKING TO THE ONLY PERSON WHO KNOWS THE SECRET TO FIGHT AGAINST THE VAMPIRE."
+#define TEXTVB9 "YOU NEED TO HAVE SPECIAL SKILLS TO FIGHT AGAINST A VAMPIRE. NOT EVERYBODY CAN DO IT "
+#define SYS0 "PRESS SUPR AGAIN TO restart"
+#define SYS1 "press ESC again to exit"
+#define SYS2 "VOiCES only"
+#define SYS3 "VOices and TEXT"
+
+#define HIS1 "A long time ago, it seems that Drascula killed Von Braun's wife, and then, as he intended to face the count, Von Braun started to investigate all he found vampires."
+#define HIS2 "When he thought he was ready, he came up to the castle and had a very violent encounter with Drascula."
+#define HIS3 "Nobody knows exactly what happened there. Although Von Braun lost, Drascula could not kill him."
+#define HIS4 "Von Braun felt humiliated by his defect, run away from the castle and has never dared to face Drascula ever again."
+
+
+
+
diff --git a/engines/engines.mk b/engines/engines.mk
index b141d66585..2d6031ff12 100644
--- a/engines/engines.mk
+++ b/engines/engines.mk
@@ -96,3 +96,9 @@ DEFINES += -DDISABLE_CRUISE
else
MODULES += engines/cruise
endif
+
+ifdef DISABLE_DRASCULA
+DEFINES += -DDISABLE_DRASCULA
+else
+MODULES += engines/drascula
+endif
diff --git a/engines/gob/cdrom.cpp b/engines/gob/cdrom.cpp
index 6b32720cff..2ee8595ad3 100644
--- a/engines/gob/cdrom.cpp
+++ b/engines/gob/cdrom.cpp
@@ -68,29 +68,30 @@ void CDROM::readLIC(const char *fname) {
_vm->_dataIO->getUnpackedData(tmp);
handle = _vm->_dataIO->openData(tmp);
+ DataStream *stream = _vm->_dataIO->openAsStream(handle, true);
- version = _vm->_dataIO->readUint16(handle);
- startChunk = _vm->_dataIO->readUint16(handle);
- _numTracks = _vm->_dataIO->readUint16(handle);
+ version = stream->readUint16LE();
+ startChunk = stream->readUint16LE();
+ _numTracks = stream->readUint16LE();
if (version != 3)
error("%s: Unknown version %d", fname, version);
- _vm->_dataIO->seekData(handle, 50, SEEK_SET);
+ stream->seek(50);
for (int i = 0; i < startChunk; i++) {
- pos = _vm->_dataIO->readUint16(handle);
+ pos = stream->readUint16LE();
if (!pos)
break;
- _vm->_dataIO->seekData(handle, pos, SEEK_CUR);
+ stream->skip(pos);
}
_LICbuffer = new byte[_numTracks * 22];
- _vm->_dataIO->readData(handle, _LICbuffer, _numTracks * 22);
+ stream->read(_LICbuffer, _numTracks * 22);
- _vm->_dataIO->closeData(handle);
+ delete stream;
}
void CDROM::freeLICbuffer() {
diff --git a/engines/gob/coktelvideo.cpp b/engines/gob/coktelvideo.cpp
new file mode 100644
index 0000000000..16df54d85f
--- /dev/null
+++ b/engines/gob/coktelvideo.cpp
@@ -0,0 +1,1289 @@
+/* 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/endian.h"
+#include "common/system.h"
+
+#include "gob/coktelvideo.h"
+
+namespace Gob {
+
+Imd::Imd() {
+ clear(false);
+}
+
+Imd::~Imd() {
+ clear();
+}
+
+bool Imd::load(Common::SeekableReadStream &stream) {
+ unload();
+
+ _stream = &stream;
+
+ // Version
+ uint16 handle = _stream->readUint16LE();
+ _version = _stream->readByte();
+
+ // Version checking
+ if ((handle != 0) || (_version < 2)) {
+ warning("IMD Version incorrect (%d,%X)", handle, _version);
+ unload();
+ return false;
+ }
+
+ // Rest header
+ _features = _stream->readByte();
+ _framesCount = _stream->readUint16LE();
+ _x = _stream->readSint16LE();
+ _y = _stream->readSint16LE();
+ _width = _stream->readSint16LE();
+ _height = _stream->readSint16LE();
+ _flags = _stream->readUint16LE();
+ _firstFramePos = _stream->readUint16LE();
+
+ // IMDs always have video
+ _features |= kFeaturesVideo;
+
+ // Palette
+ _stream->read((byte *) _palette, 768);
+
+ // Standard coordinates
+ if (_version >= 3) {
+ _stdX = _stream->readUint16LE();
+ if (_stdX > 1) {
+ warning("IMD: More than one standard coordinate quad found (%d)", _stdX);
+ unload();
+ return false;
+ }
+ if (_stdX != 0) {
+ _stdX = _stream->readSint16LE();
+ _stdY = _stream->readSint16LE();
+ _stdWidth = _stream->readSint16LE();
+ _stdHeight = _stream->readSint16LE();
+ _features |= kFeaturesStdCoords;
+ } else
+ _stdX = -1;
+ } else
+ _stdX = -1;
+
+ // Offset to frame positions table
+ uint32 framesPosPos = 0;
+ if (_version >= 4) {
+ framesPosPos = _stream->readUint32LE();
+ if (framesPosPos != 0) {
+ _framesPos = new uint32[_framesCount];
+ assert(_framesPos);
+ _features |= kFeaturesFramesPos;
+ }
+ }
+
+ // Offset to frame coordinates
+ uint32 framesCoordsPos = 0;
+ if (_features & kFeaturesFrameCoords)
+ framesCoordsPos = _stream->readUint32LE();
+
+ // Sound
+ if (_features & kFeaturesSound) {
+ _soundFreq = _stream->readSint16LE();
+ _soundSliceSize = _stream->readSint16LE();
+ _soundSlicesCount = _stream->readSint16LE();
+
+ if (_soundFreq < 0)
+ _soundFreq = -_soundFreq;
+
+ if (_soundSlicesCount < 0)
+ _soundSlicesCount = -_soundSlicesCount - 1;
+
+ if (_soundSlicesCount > 40) {
+ warning("IMD: More than 40 sound slices found (%d)", _soundSlicesCount);
+ unload();
+ return false;
+ }
+
+ _soundSliceLength = 1000 / (_soundFreq / _soundSliceSize);
+ _frameLength = _soundSliceLength;
+
+ _soundStage = 1;
+ _hasSound = true;
+
+ _audioStream = Audio::makeAppendableAudioStream(_soundFreq, 0);
+ } else
+ _frameLength = 1000 / 12; // 12 FPS for a video without sound
+
+ // Sizes of the frame data and extra video buffer
+ if (_features & kFeaturesDataSize) {
+ _frameDataSize = _stream->readUint16LE();
+ if (_frameDataSize == 0) {
+ _frameDataSize = _stream->readUint32LE();
+ _vidBufferSize = _stream->readUint32LE();
+ } else
+ _vidBufferSize = _stream->readUint16LE();
+ } else {
+ _frameDataSize = _width * _height + 500;
+ if (!(_flags & 0x100) || (_flags & 0x1000))
+ _vidBufferSize = _frameDataSize;
+ }
+
+ // Frame positions table
+ if (_framesPos) {
+ _stream->seek(framesPosPos, SEEK_SET);
+ for (int i = 0; i < _framesCount; i++)
+ _framesPos[i] = _stream->readUint32LE();
+ }
+
+ // Frame coordinates table
+ if (_features & kFeaturesFrameCoords) {
+ _stream->seek(framesCoordsPos, SEEK_SET);
+ _frameCoords = new Coord[_framesCount];
+ assert(_frameCoords);
+ for (int i = 0; i < _framesCount; i++) {
+ _frameCoords[i].left = _stream->readSint16LE();
+ _frameCoords[i].top = _stream->readSint16LE();
+ _frameCoords[i].right = _stream->readSint16LE();
+ _frameCoords[i].bottom = _stream->readSint16LE();
+ }
+ }
+
+ // Seek to the first frame
+ _stream->seek(_firstFramePos, SEEK_SET);
+
+ // Allocating working memory
+ _frameData = new byte[_frameDataSize + 500];
+ assert(_frameData);
+ memset(_frameData, 0, _frameDataSize + 500);
+ _vidBuffer = new byte[_vidBufferSize + 500];
+ assert(_vidBuffer);
+ memset(_vidBuffer, 0, _vidBufferSize + 500);
+
+ return true;
+}
+
+void Imd::unload() {
+ clear();
+}
+
+void Imd::setXY(int16 x, int16 y) {
+ // Adjusting the standard coordinates
+ if (_stdX != -1) {
+ if (x >= 0)
+ _stdX = _stdX - _x + x;
+ if (y >= 0)
+ _stdY = _stdY - _y + y;
+ }
+
+ // Going through the coordinate table as well
+ if (_frameCoords) {
+ for (int i = 0; i < _framesCount; i++) {
+ if (_frameCoords[i].left != -1) {
+ if (x >= 0) {
+ _frameCoords[i].left = _frameCoords[i].left - _x + x;
+ _frameCoords[i].right = _frameCoords[i].right - _x + x;
+ }
+ if (y >= 0) {
+ _frameCoords[i].top = _frameCoords[i].top - _y + y;
+ _frameCoords[i].bottom = _frameCoords[i].bottom - _y + y;
+ }
+ }
+ }
+ }
+
+ if (x >= 0)
+ _x = x;
+ if (y >= 0)
+ _y = y;
+}
+
+void Imd::setVideoMemory(byte *vidMem, uint16 width, uint16 height) {
+ deleteVidMem();
+
+ _hasOwnVidMem = false;
+ _vidMem = vidMem;
+ _vidMemWidth = width;
+ _vidMemHeight = height;
+}
+
+void Imd::setVideoMemory() {
+ deleteVidMem();
+
+ if ((_width > 0) && (_height > 0)) {
+ setXY(0, 0);
+ _hasOwnVidMem = true;
+ _vidMem = new byte[_width * _height];
+ _vidMemWidth = _width;
+ _vidMemHeight = _height;
+ }
+}
+
+void Imd::enableSound(Audio::Mixer &mixer) {
+ // Only possible on the first frame
+ if (_curFrame > 0)
+ return;
+
+ _mixer = &mixer;
+ _soundEnabled = true;
+}
+
+void Imd::disableSound() {
+ if (_audioStream) {
+
+ if (_soundStage == 2) {
+ _audioStream->finish();
+ _mixer->stopHandle(_audioHandle);
+ } else
+ delete _audioStream;
+
+ _audioStream = 0;
+ _soundStage = 0;
+ }
+ _soundEnabled = false;
+ _mixer = 0;
+}
+
+void Imd::seekFrame(int32 frame, int16 whence, bool restart) {
+ if (!_stream)
+ // Nothing to do
+ return;
+
+ // Find the frame to which to seek
+ if (whence == SEEK_CUR)
+ frame += _curFrame;
+ else if (whence == SEEK_END)
+ frame = _framesCount - frame - 1;
+ else if (whence != SEEK_SET)
+ return;
+
+ if ((frame < 0) || (frame >= _framesCount) || (frame == _curFrame))
+ // Nothing to do
+ return;
+
+ // Try every possible way to find a file offset to that frame
+ uint32 framePos = 0;
+ if (frame == 0) {
+ framePos = _firstFramePos;
+ } else if (frame == 1) {
+ framePos = _firstFramePos;
+ _stream->seek(framePos, SEEK_SET);
+ framePos += _stream->readUint16LE() + 4;
+ } else if (_framesPos) {
+ framePos = _framesPos[frame];
+ } else if (restart && (_soundStage == 0)) {
+ for (int i = ((frame > _curFrame) ? _curFrame : 0); i <= frame; i++)
+ processFrame(i);
+ } else
+ error("Frame %d is not directly accessible", frame);
+
+ // Seek
+ _stream->seek(framePos);
+ _curFrame = frame;
+}
+
+CoktelVideo::State Imd::nextFrame() {
+ return processFrame(_curFrame);
+}
+
+void Imd::waitEndFrame() {
+ if (_soundEnabled && _hasSound) {
+ if (_soundStage != 2)
+ return;
+
+ if (_skipFrames == 0) {
+ int32 waitTime = (_curFrame * _soundSliceLength) -
+ (g_system->getMillis() - _soundStartTime);
+
+ if (waitTime < 0) {
+ _skipFrames = -waitTime / _soundSliceLength;
+ warning("Video A/V sync broken, skipping %d frame(s)", _skipFrames + 1);
+ } else if (waitTime > 0)
+ g_system->delayMillis(waitTime);
+
+ } else
+ _skipFrames--;
+ } else
+ g_system->delayMillis(_frameLength);
+}
+
+void Imd::copyCurrentFrame(byte *dest, uint16 x, uint16 y, uint16 width, int16 transp) {
+ if (!_vidMem)
+ return;
+
+ dest += width * y;
+
+ uint16 copyWidth = MIN<int16>(width - x, _width);
+ uint16 destPitch = width - x;
+ byte *vidMem = _vidMem;
+
+ if (transp < 0) {
+ // No transparency
+ if ((x > 0) || (_width != width)) {
+ // Copy row-by-row
+ for (int i = 0; i < _height; i++) {
+ dest += x;
+ memcpy(dest, vidMem, copyWidth);
+ dest += destPitch;
+ vidMem += _width;
+ }
+
+ } else
+ // Dimensions fit, copy everything at once
+ memcpy(dest, _vidMem, _width * _height);
+
+ return;
+ }
+
+ // Transparency, copy per pixel
+ for (int i = 0; i < _height; i++) {
+ byte *s = vidMem;
+ byte *d = dest;
+
+ d += x;
+ for (int j = 0; j < _width; j++) {
+ if (*s != transp)
+ *d = *s;
+
+ s++;
+ d++;
+ }
+
+ dest += width;;
+ vidMem += _width;
+ }
+}
+
+void Imd::deleteVidMem(bool del) {
+ if (del) {
+ if (_hasOwnVidMem)
+ delete[] _vidMem;
+ }
+
+ _hasOwnVidMem = false;
+ _vidMem = 0;
+ _vidMemWidth = _vidMemHeight = 0;
+}
+
+void Imd::clear(bool del) {
+ if (del) {
+ delete[] _framesPos;
+ delete[] _frameCoords;
+ delete[] _frameData;
+ delete[] _vidBuffer;
+
+ disableSound();
+ }
+
+ _stream = 0;
+
+ _version = 0;
+ _features = 0;
+ _flags = 0;
+ _x = _y = _width = _height = 0;
+ _stdX = _stdY = _stdWidth = _stdHeight = 0;
+ _framesCount = _curFrame = 0;
+ _framesPos = 0;
+ _firstFramePos = 0;
+ _frameCoords = 0;
+
+ _frameDataSize = _vidBufferSize = 0;
+ _frameData = _vidBuffer = 0;
+
+ memset(_palette, 0, 768);
+
+ deleteVidMem(del);
+
+ _hasSound = false;
+ _soundEnabled = false;
+ _soundStage = 0;
+ _soundStartTime = 0;
+ _skipFrames = 0;
+
+ _soundFlags = 0;
+ _soundFreq = 0;
+ _soundSliceSize = 0;
+ _soundSlicesCount = 0;
+ _soundSliceLength = 0;
+
+ _audioStream = 0;
+
+ _frameLength = 0;
+ _lastFrameTime = 0;
+}
+
+CoktelVideo::State Imd::processFrame(uint16 frame) {
+ State state;
+ uint32 cmd = 0;
+ bool hasNextCmd = false;
+ bool startSound = false;
+
+ if (!_stream || (frame >= _framesCount)) {
+ state.flags = kStateBreak;
+ return state;
+ }
+
+ if (frame != _curFrame) {
+ state.flags |= kStateSeeked;
+ seekFrame(frame);
+ }
+
+ if (!_vidMem)
+ setVideoMemory();
+
+ state.left = _x;
+ state.top = _y;
+ state.right = _width + state.left - 1;
+ state.bottom = _height + state.top - 1;
+
+ do {
+ if (frame != 0) {
+ if (_stdX != -1) {
+ state.left = _stdX;
+ state.top = _stdY;
+ state.right = _stdWidth + state.left - 1;
+ state.bottom = _stdHeight + state.top - 1;
+ state.flags |= kStateStdCoords;
+ }
+ if (_frameCoords &&
+ (_frameCoords[frame].left != -1)) {
+ state.left = _frameCoords[frame].left;
+ state.top = _frameCoords[frame].top;
+ state.right = _frameCoords[frame].right;
+ state.bottom = _frameCoords[frame].bottom;
+ state.flags |= kStateFrameCoords;
+ }
+ }
+
+ cmd = _stream->readUint16LE();
+
+ if ((cmd & 0xFFF8) == 0xFFF0) {
+ if (cmd == 0xFFF0) {
+ _stream->seek(2, SEEK_CUR);
+ cmd = _stream->readUint16LE();
+ }
+
+ if (cmd == 0xFFF1) {
+ state.flags = kStateBreak;
+ continue;
+ } else if (cmd == 0xFFF2) { // Skip (16 bit)
+ cmd = _stream->readUint16LE();
+ _stream->seek(cmd, SEEK_CUR);
+ state.flags = kStateBreak;
+ continue;
+ } else if (cmd == 0xFFF3) { // Skip (32 bit)
+ cmd = _stream->readUint32LE();
+ _stream->seek(cmd, SEEK_CUR);
+ state.flags = kStateBreak;
+ continue;
+ }
+ }
+
+ if (_soundStage != 0) {
+ byte *soundBuf;
+
+ // Next sound slice data
+ if (cmd == 0xFF00) {
+
+ if (!hasNextCmd && _soundEnabled) {
+ soundBuf = new byte[_soundSliceSize];
+ assert(soundBuf);
+
+ _stream->read(soundBuf, _soundSliceSize);
+ unsignedToSigned(soundBuf, _soundSliceSize);
+ _audioStream->queueBuffer(soundBuf, _soundSliceSize);
+ } else
+ _stream->seek(_soundSliceSize, SEEK_CUR);
+
+ cmd = _stream->readUint16LE();
+
+ // Initial sound data (all slices)
+ } else if (cmd == 0xFF01) {
+ int dataLength = _soundSliceSize * _soundSlicesCount;
+
+ if (!hasNextCmd && _soundEnabled) {
+ soundBuf = new byte[dataLength];
+ assert(soundBuf);
+
+ _stream->read(soundBuf, dataLength);
+ unsignedToSigned(soundBuf, dataLength);
+
+ if (_soundStage == 1)
+ startSound = true;
+
+ _audioStream->queueBuffer(soundBuf, dataLength);
+ } else
+ _stream->seek(dataLength, SEEK_CUR);
+
+ cmd = _stream->readUint16LE();
+
+ // Empty sound slice
+ } else if (!hasNextCmd && (_soundEnabled)) {
+ soundBuf = new byte[_soundSliceSize];
+ assert(soundBuf);
+
+ memset(soundBuf, 0, _soundSliceSize);
+
+ _audioStream->queueBuffer(soundBuf, _soundSliceSize);
+ }
+ }
+
+ // Set palette
+ if (cmd == 0xFFF4) {
+ _stream->seek(2, SEEK_CUR);
+ state.flags |= kStatePalette;
+ _stream->read(_palette, 768);
+ cmd = _stream->readUint16LE();
+ }
+
+ hasNextCmd = false;
+
+ // Jump to frame
+ if (cmd == 0xFFFD) {
+
+ frame = _stream->readSint16LE();
+ if (_framesPos) {
+ _curFrame = frame;
+ _stream->seek(_framesPos[frame], SEEK_SET);
+
+ hasNextCmd = true;
+ state.flags |= kStateJump;
+ }
+
+ } else if (cmd == 0xFFFC) {
+
+ state.flags |= 1;
+ cmd = _stream->readUint32LE();
+ _stream->read(_frameData, cmd + 2);
+
+ if (_vidMemWidth <= state.right) {
+ state.left = 0;
+ state.right -= state.left;
+ }
+ if (_vidMemWidth <= state.right)
+ state.right = _vidMemWidth - 1;
+ if (_vidMemHeight <= state.bottom) {
+ state.top = 0;
+ state.bottom -= state.top;
+ }
+ if (_vidMemHeight <= state.bottom)
+ state.bottom = _vidMemHeight -1;
+
+ state.flags |= renderFrame(state.left, state.top, state.right, state.bottom);
+ state.flags |= _frameData[0];
+
+ // Frame video data
+ } else if (cmd != 0) {
+
+ _stream->read(_frameData, cmd + 2);
+
+ state.flags |= renderFrame(state.left, state.top, state.right, state.bottom);
+ state.flags |= _frameData[0];
+
+ } else
+ state.flags |= kStateNoVideoData;
+
+ } while (hasNextCmd);
+
+ if (startSound && _soundEnabled) {
+ _mixer->playInputStream(Audio::Mixer::kSFXSoundType, &_audioHandle, _audioStream);
+ _soundStartTime = g_system->getMillis();
+ _skipFrames = 0;
+ _soundStage = 2;
+ }
+
+ _curFrame++;
+ if ((_curFrame == _framesCount) && (_soundStage == 2)) {
+ _audioStream->finish();
+ _mixer->stopHandle(_audioHandle);
+ _audioStream = 0;
+ _soundStage = 0;
+ }
+
+ _lastFrameTime = g_system->getMillis();
+ return state;
+}
+
+uint32 Imd::renderFrame(int16 left, int16 top, int16 right, int16 bottom) {
+ if (!_frameData || !_vidMem || (_width <= 0) || (_height <= 0))
+ return 0;
+
+ uint32 retVal = 0;
+ int16 width = right - left + 1;
+ int16 height = bottom - top + 1;
+ int16 sW = _vidMemWidth;
+ byte *dataPtr = _frameData;
+ byte *imdVidMem = _vidMem + sW * top + left;
+ byte *srcPtr;
+ uint8 type = *dataPtr++;
+
+ if (type & 0x10) { // Palette data
+ // One byte index
+ int index = *dataPtr++;
+ // 16 entries with each 3 bytes (RGB)
+ memcpy(_palette + index * 3, dataPtr, MIN((255 - index) * 3, 48));
+
+ retVal = kStatePalette;
+ dataPtr += 48;
+ type ^= 0x10;
+ }
+
+ srcPtr = dataPtr;
+
+ if (type & 0x80) { // Frame data is compressed
+ srcPtr = _vidBuffer;
+ type &= 0x7F;
+ if ((type == 2) && (width == sW)) {
+ deLZ77(imdVidMem, dataPtr);
+ return retVal;
+ } else
+ deLZ77(srcPtr, dataPtr);
+ }
+
+ uint16 pixCount, pixWritten;
+ byte *imdVidMemBak;
+
+ if (type == 2) { // Whole block
+ for (int i = 0; i < height; i++) {
+ memcpy(imdVidMem, srcPtr, width);
+ srcPtr += width;
+ imdVidMem += sW;
+ }
+ } else if (type == 1) { // Sparse block
+ imdVidMemBak = imdVidMem;
+ for (int i = 0; i < height; i++) {
+ pixWritten = 0;
+ while (pixWritten < width) {
+ pixCount = *srcPtr++;
+ if (pixCount & 0x80) { // data
+ pixCount = MIN((pixCount & 0x7F) + 1, width - pixWritten);
+ memcpy(imdVidMem, srcPtr, pixCount);
+
+ pixWritten += pixCount;
+ imdVidMem += pixCount;
+ srcPtr += pixCount;
+ } else { // "hole"
+ pixCount = (pixCount + 1) % 256;
+ pixWritten += pixCount;
+ imdVidMem += pixCount;
+ }
+ }
+ imdVidMemBak += sW;
+ imdVidMem = imdVidMemBak;
+ }
+ } else if (type == 0x42) { // Whole quarter-wide block
+ for (int i = 0; i < height; i++) {
+ imdVidMemBak = imdVidMem;
+
+ for (int j = 0; j < width; j += 4, imdVidMem += 4, srcPtr++)
+ memset(imdVidMem, *srcPtr, 4);
+
+ imdVidMemBak += sW;
+ imdVidMem = imdVidMemBak;
+ }
+ } else if ((type & 0xF) == 2) { // Whole half-high block
+ for (; height > 1; height -= 2, imdVidMem += sW + sW, srcPtr += width) {
+ memcpy(imdVidMem, srcPtr, width);
+ memcpy(imdVidMem + sW, srcPtr, width);
+ }
+ if (height == -1)
+ memcpy(imdVidMem, srcPtr, width);
+ } else { // Sparse half-high block
+ imdVidMemBak = imdVidMem;
+ for (int i = 0; i < height; i += 2) {
+ pixWritten = 0;
+ while (pixWritten < width) {
+ pixCount = *srcPtr++;
+ if (pixCount & 0x80) { // data
+ pixCount = MIN((pixCount & 0x7F) + 1, width - pixWritten);
+ memcpy(imdVidMem, srcPtr, pixCount);
+ memcpy(imdVidMem + sW, srcPtr, pixCount);
+
+ pixWritten += pixCount;
+ imdVidMem += pixCount;
+ srcPtr += pixCount;
+ } else { // "hole"
+ pixCount = (pixCount + 1) % 256;
+ pixWritten += pixCount;
+ imdVidMem += pixCount;
+ }
+ }
+ imdVidMemBak += sW + sW;
+ imdVidMem = imdVidMemBak;
+ }
+ }
+
+ return retVal;
+}
+
+void Imd::deLZ77(byte *dest, byte *src) {
+ int i;
+ byte buf[4370];
+ uint16 chunkLength;
+ uint16 frameLength;
+ uint16 bufPos1;
+ uint16 bufPos2;
+ uint16 tmp;
+ uint8 chunkBitField;
+ uint8 chunkCount;
+ bool mode;
+
+ frameLength = READ_LE_UINT32(src);
+ src += 4;
+
+ if ((READ_LE_UINT16(src) == 0x1234) && (READ_LE_UINT16(src + 2) == 0x5678)) {
+ src += 4;
+ bufPos1 = 273;
+ mode = 1; // 123Ch (cmp al, 12h)
+ } else {
+ bufPos1 = 4078;
+ mode = 0; // 275h (jnz +2)
+ }
+
+ memset(buf, 32, bufPos1);
+ chunkCount = 1;
+ chunkBitField = 0;
+
+ while (frameLength > 0) {
+ chunkCount--;
+ if (chunkCount == 0) {
+ tmp = *src++;
+ chunkCount = 8;
+ chunkBitField = tmp;
+ }
+ if (chunkBitField % 2) {
+ chunkBitField >>= 1;
+ buf[bufPos1] = *src;
+ *dest++ = *src++;
+ bufPos1 = (bufPos1 + 1) % 4096;
+ frameLength--;
+ continue;
+ }
+ chunkBitField >>= 1;
+
+ tmp = READ_LE_UINT16(src);
+ src += 2;
+ chunkLength = ((tmp & 0xF00) >> 8) + 3;
+
+ if ((mode && ((chunkLength & 0xFF) == 0x12)) ||
+ (!mode && (chunkLength == 0)))
+ chunkLength = *src++ + 0x12;
+
+ bufPos2 = (tmp & 0xFF) + ((tmp >> 4) & 0x0F00);
+ if (((tmp + chunkLength) >= 4096) ||
+ ((chunkLength + bufPos1) >= 4096)) {
+
+ for (i = 0; i < chunkLength; i++, dest++) {
+ *dest = buf[bufPos2];
+ buf[bufPos1] = buf[bufPos2];
+ bufPos1 = (bufPos1 + 1) % 4096;
+ bufPos2 = (bufPos2 + 1) % 4096;
+ }
+
+ } else if (((tmp + chunkLength) < bufPos1) ||
+ ((chunkLength + bufPos1) < bufPos2)) {
+
+ memcpy(dest, buf + bufPos2, chunkLength);
+ memmove(buf + bufPos1, buf + bufPos2, chunkLength);
+
+ dest += chunkLength;
+ bufPos1 += chunkLength;
+ bufPos2 += chunkLength;
+
+ } else {
+
+ for (i = 0; i < chunkLength; i++, dest++, bufPos1++, bufPos2++) {
+ *dest = buf[bufPos2];
+ buf[bufPos1] = buf[bufPos2];
+ }
+
+ }
+ frameLength -= chunkLength;
+
+ }
+}
+
+const uint16 Vmd::_tableDPCM[128] = {
+ 0x0000, 0x0008, 0x0010, 0x0020, 0x0030, 0x0040, 0x0050, 0x0060, 0x0070, 0x0080,
+ 0x0090, 0x00A0, 0x00B0, 0x00C0, 0x00D0, 0x00E0, 0x00F0, 0x0100, 0x0110, 0x0120,
+ 0x0130, 0x0140, 0x0150, 0x0160, 0x0170, 0x0180, 0x0190, 0x01A0, 0x01B0, 0x01C0,
+ 0x01D0, 0x01E0, 0x01F0, 0x0200, 0x0208, 0x0210, 0x0218, 0x0220, 0x0228, 0x0230,
+ 0x0238, 0x0240, 0x0248, 0x0250, 0x0258, 0x0260, 0x0268, 0x0270, 0x0278, 0x0280,
+ 0x0288, 0x0290, 0x0298, 0x02A0, 0x02A8, 0x02B0, 0x02B8, 0x02C0, 0x02C8, 0x02D0,
+ 0x02D8, 0x02E0, 0x02E8, 0x02F0, 0x02F8, 0x0300, 0x0308, 0x0310, 0x0318, 0x0320,
+ 0x0328, 0x0330, 0x0338, 0x0340, 0x0348, 0x0350, 0x0358, 0x0360, 0x0368, 0x0370,
+ 0x0378, 0x0380, 0x0388, 0x0390, 0x0398, 0x03A0, 0x03A8, 0x03B0, 0x03B8, 0x03C0,
+ 0x03C8, 0x03D0, 0x03D8, 0x03E0, 0x03E8, 0x03F0, 0x03F8, 0x0400, 0x0440, 0x0480,
+ 0x04C0, 0x0500, 0x0540, 0x0580, 0x05C0, 0x0600, 0x0640, 0x0680, 0x06C0, 0x0700,
+ 0x0740, 0x0780, 0x07C0, 0x0800, 0x0900, 0x0A00, 0x0B00, 0x0C00, 0x0D00, 0x0E00,
+ 0x0F00, 0x1000, 0x1400, 0x1800, 0x1C00, 0x2000, 0x3000, 0x4000
+};
+
+Vmd::Vmd() {
+ clear(false);
+}
+
+Vmd::~Vmd() {
+ clear();
+}
+
+bool Vmd::load(Common::SeekableReadStream &stream) {
+ unload();
+
+ _stream = &stream;
+
+ uint16 headerLength = _stream->readUint16LE();
+ uint16 handle = _stream->readUint16LE();
+ _version = _stream->readUint16LE();
+
+ // Version checking
+ if ((headerLength != 814) || (handle != 0) || (_version != 1)) {
+ warning("VMD Version incorrect (%d, %d, %d)", headerLength, handle, _version);
+ unload();
+ return false;
+ }
+
+ _framesCount = _stream->readUint16LE();
+
+ _x = _stream->readSint16LE();
+ _y = _stream->readSint16LE();
+ _width = _stream->readSint16LE();
+ _height = _stream->readSint16LE();
+ if ((_width != 0) && (_height != 0)) {
+ _hasVideo = true;
+ _features |= kFeaturesVideo;
+ } else
+ _hasVideo = false;
+
+ _flags = _stream->readUint16LE();
+ _partsPerFrame = _stream->readUint16LE();
+ _firstFramePos = _stream->readUint32LE();
+ _stream->skip(4); // Unknown
+
+ _stream->read((byte *) _palette, 768);
+
+ _frameDataSize = _stream->readUint32LE();
+ _vidBufferSize = _stream->readUint32LE();
+
+ if (_hasVideo) {
+ if (_frameDataSize == 0)
+ _frameDataSize = _width * _height + 500;
+ if (_vidBufferSize == 0)
+ _vidBufferSize = _frameDataSize;
+
+ _frameData = new byte[_frameDataSize];
+ assert(_frameData);
+ memset(_frameData, 0, _frameDataSize);
+ _vidBuffer = new byte[_vidBufferSize];
+ assert(_vidBuffer);
+ memset(_vidBuffer, 0, _vidBufferSize);
+ }
+
+ _soundFreq = _stream->readSint16LE();
+ _soundSliceSize = _stream->readSint16LE();
+ _soundSlicesCount = _stream->readSint16LE();
+ _soundFlags = _stream->readUint16LE();
+ _hasSound = (_soundFreq != 0);
+
+ if (_hasSound) {
+ _features |= kFeaturesSound;
+
+ _soundStereo = (_soundFlags & 0x8000) ? 1 : ((_soundFlags & 0x200) ? 2 : 0);
+ if (_soundStereo > 0) {
+ warning("TODO: VMD stereo");
+ unload();
+ return false;
+ }
+
+ if (_soundSliceSize < 0) {
+ _soundBytesPerSample = 2;
+ _soundSliceSize = -_soundSliceSize;
+ }
+
+ _soundSliceLength = (uint16) (1000.0 /
+ ((double) _soundFreq / (double) _soundSliceSize));
+
+ _frameLength = _soundSliceLength;
+
+ _soundStage = 1;
+ _audioStream = Audio::makeAppendableAudioStream(_soundFreq,
+ (_soundBytesPerSample == 2) ? Audio::Mixer::FLAG_16BITS : 0);
+ } else
+ _frameLength = 1000 / 12; // 12 FPS for a video without sound
+
+ uint32 frameInfoOffset = _stream->readUint32LE();
+
+ _stream->seek(frameInfoOffset);
+ _frames = new Frame[_framesCount];
+ for (uint16 i = 0; i < _framesCount; i++) {
+ _frames[i].parts = new Part[_partsPerFrame];
+ _stream->skip(2); // Unknown
+ _frames[i].offset = _stream->readUint32LE();
+ }
+ for (uint16 i = 0; i < _framesCount; i++) {
+ for (uint16 j = 0; j < _partsPerFrame; j++) {
+
+ _frames[i].parts[j].type = (PartType) _stream->readByte();
+ _stream->skip(1); // Unknown
+ _frames[i].parts[j].size = _stream->readUint32LE();
+
+ if (_frames[i].parts[j].type == kPartTypeAudio) {
+
+ _frames[i].parts[j].flags = _stream->readByte();
+ _stream->skip(9); // Unknow
+
+ } else if (_frames[i].parts[j].type == kPartTypeVideo) {
+
+ _frames[i].parts[j].left = _stream->readUint16LE();
+ _frames[i].parts[j].top = _stream->readUint16LE();
+ _frames[i].parts[j].right = _stream->readUint16LE();
+ _frames[i].parts[j].bottom = _stream->readUint16LE();
+ _stream->skip(1); // Unknown
+ _frames[i].parts[j].flags = _stream->readByte();
+
+ } else {
+ // Unknow type
+ _stream->skip(10);
+ }
+
+ }
+ }
+
+ return true;
+}
+
+void Vmd::unload() {
+ clear();
+}
+
+void Vmd::setXY(int16 x, int16 y) {
+
+ for (int i = 0; i < _framesCount; i++) {
+ for (int j = 0; j < _partsPerFrame; j++) {
+
+ if (_frames[i].parts[j].type == kPartTypeVideo) {
+ if (x >= 0) {
+ _frames[i].parts[j].left = _frames[i].parts[j].left - _x + x;
+ _frames[i].parts[j].right = _frames[i].parts[j].right - _x + x;
+ }
+ if (y >= 0) {
+ _frames[i].parts[j].top = _frames[i].parts[j].top - _y + y;
+ _frames[i].parts[j].bottom = _frames[i].parts[j].bottom - _y + y;
+ }
+ }
+
+ }
+ }
+
+ if (x >= 0)
+ _x = x;
+ if (y >= 0)
+ _y = y;
+}
+
+void Vmd::seekFrame(int32 frame, int16 whence, bool restart) {
+ if (!_stream)
+ // Nothing to do
+ return;
+
+ // Find the frame to which to seek
+ if (whence == SEEK_CUR)
+ frame += _curFrame;
+ else if (whence == SEEK_END)
+ frame = _framesCount - frame - 1;
+ else if (whence != SEEK_SET)
+ return;
+
+ if ((frame < 0) || (frame >= _framesCount))
+ // Nothing to do
+ return;
+
+ // Seek
+ _stream->seek(_frames[frame].offset);
+ _curFrame = frame;
+}
+
+CoktelVideo::State Vmd::nextFrame() {
+ State state;
+
+ state = processFrame(_curFrame);
+ _curFrame++;
+ return state;
+}
+
+void Vmd::clear(bool del) {
+ Imd::clear(del);
+
+ if (del) {
+ delete[] _frames;
+ }
+
+ _hasVideo = true;
+
+ _partsPerFrame = 0;
+ _frames = 0;
+
+ _soundBytesPerSample = 1;
+ _soundStereo = 0;
+}
+
+CoktelVideo::State Vmd::processFrame(uint16 frame) {
+ State state;
+ bool startSound = false;
+
+ seekFrame(frame);
+
+ state.flags |= kStateNoVideoData;
+ state.left = 0x7FFF;
+ state.right = 0x7FFF;
+ state.top = 0;
+ state.bottom = 0;
+
+ if (!_vidMem)
+ setVideoMemory();
+
+ for (uint16 i = 0; i < _partsPerFrame; i++) {
+ Part &part = _frames[frame].parts[i];
+
+ if (part.type == kPartTypeAudio) {
+ // Next sound slice data
+ if (part.flags == 1) {
+
+ if (_soundEnabled)
+ filledSoundSlice(part.size);
+ else
+ _stream->skip(part.size);
+
+ // Initial sound data (all slices)
+ } else if (part.flags == 2) {
+
+ if (_soundEnabled) {
+ uint32 mask = _stream->readUint32LE();
+ filledSoundSlices(part.size - 4, mask);
+
+ if (_soundStage == 1)
+ startSound = true;
+
+ } else
+ _stream->skip(part.size);
+
+ // Empty sound slice
+ } else if (part.flags == 3) {
+
+ if (_soundEnabled && (part.size > 0))
+ emptySoundSlice(part.size);
+ else
+ _stream->skip(part.size);
+
+ }
+
+ } else if (part.type == kPartTypeVideo) {
+ state.flags &= ~kStateNoVideoData;
+
+ // New palette
+ if (part.flags & 2) {
+ uint8 index = _stream->readByte();
+ uint8 count = _stream->readByte();
+
+ _stream->read(_palette + index * 3, (count + 1) * 3);
+ _stream->skip((255 - count) * 3);
+
+ state.flags |= kStatePalette;
+ }
+
+ _stream->read(_frameData, part.size);
+ if (renderFrame(part.left, part.top, part.right, part.bottom)) {
+ // Rendering succeeded, merging areas
+ state.left = MIN(state.left, part.left);
+ state.top = MIN(state.top, part.top);
+ state.right = MAX(state.right, part.right);
+ state.bottom = MAX(state.bottom, part.bottom);
+ }
+
+ } else if (part.type == 4) {
+ // Unknown
+ _stream->skip(part.size);
+ } else {
+ // Unknow type
+// warning("Unknown frame part type %d, size %d (%d of %d)", part.type, part.size, i + 1, _partsPerFrame);
+ }
+ }
+
+ if (startSound && _soundEnabled) {
+ _mixer->playInputStream(Audio::Mixer::kSFXSoundType, &_audioHandle, _audioStream);
+ _soundStartTime = g_system->getMillis();
+ _skipFrames = 0;
+ _soundStage = 2;
+ }
+
+ if ((_curFrame == (_framesCount - 1)) && (_soundStage == 2)) {
+ _audioStream->finish();
+ _mixer->stopHandle(_audioHandle);
+ _audioStream = 0;
+ _soundStage = 0;
+ }
+
+ _lastFrameTime = g_system->getMillis();
+ return state;
+}
+
+uint32 Vmd::renderFrame(int16 left, int16 top, int16 right, int16 bottom) {
+ if (!_frameData || !_vidMem || (_width <= 0) || (_height <= 0))
+ return 0;
+
+ int16 width = right - left + 1;
+ int16 height = bottom - top + 1;
+ int16 sW = _vidMemWidth;
+ byte *dataPtr = _frameData;
+ byte *imdVidMem = _vidMem + sW * top + left;
+ byte *srcPtr;
+ uint8 type = *dataPtr++;
+
+ srcPtr = dataPtr;
+
+ if (type & 0x80) { // Frame data is compressed
+ srcPtr = _vidBuffer;
+ type &= 0x7F;
+ if ((type == 2) && (width == sW)) {
+ deLZ77(imdVidMem, dataPtr);
+ return 1;
+ } else
+ deLZ77(srcPtr, dataPtr);
+ }
+
+ uint16 pixCount, pixWritten;
+ byte *imdVidMemBak;
+
+ if (type == 1) { // Sparse block
+ imdVidMemBak = imdVidMem;
+ for (int i = 0; i < height; i++) {
+ pixWritten = 0;
+ while (pixWritten < width) {
+ pixCount = *srcPtr++;
+ if (pixCount & 0x80) { // data
+ pixCount = MIN((pixCount & 0x7F) + 1, width - pixWritten);
+ memcpy(imdVidMem, srcPtr, pixCount);
+
+ pixWritten += pixCount;
+ imdVidMem += pixCount;
+ srcPtr += pixCount;
+ } else { // "hole"
+ pixCount = (pixCount + 1) % 256;
+ pixWritten += pixCount;
+ imdVidMem += pixCount;
+ }
+ }
+ imdVidMemBak += sW;
+ imdVidMem = imdVidMemBak;
+ }
+ } else if (type == 2) { // Whole block
+ for (int i = 0; i < height; i++) {
+ memcpy(imdVidMem, srcPtr, width);
+ srcPtr += width;
+ imdVidMem += sW;
+ }
+ } else if (type == 3) { // RLE block
+ warning("Frame render method 3: RLE block");
+ return 0;
+ } else {
+ warning("Unkown frame rendering method %d (0x%X)", type, type);
+ return 0;
+ }
+
+ return 1;
+}
+
+void Vmd::emptySoundSlice(uint32 size) {
+ byte *soundBuf = new byte[size];
+ assert(soundBuf);
+
+ memset(soundBuf, 0, size);
+
+ _audioStream->queueBuffer(soundBuf, size);
+}
+
+void Vmd::soundSlice8bit(uint32 size) {
+ byte *soundBuf = new byte[size];
+ assert(soundBuf);
+
+ _stream->read(soundBuf, size);
+ unsignedToSigned(soundBuf, size);
+
+ _audioStream->queueBuffer(soundBuf, size);
+}
+
+void Vmd::soundSlice16bit(uint32 size, int16 &init) {
+ byte *dataBuf = new byte[size];
+ byte *soundBuf = new byte[size * 2];
+
+ _stream->read(dataBuf, size);
+ deDPCM(soundBuf, dataBuf, init, size);
+ _audioStream->queueBuffer(soundBuf, size * 2);
+
+ delete[] dataBuf;
+}
+
+void Vmd::filledSoundSlice(uint32 size) {
+ if (_soundBytesPerSample == 1) {
+ soundSlice8bit(size);
+ } else if (_soundBytesPerSample == 2) {
+ int16 init = _stream->readSint16LE();
+ soundSlice16bit(size - 1, init);
+ }
+}
+
+void Vmd::filledSoundSlices(uint32 size, uint32 mask) {
+ if (_soundBytesPerSample == 1) {
+ soundSlice8bit(size);
+ return;
+ }
+
+ for (int i = 0; i < (_soundSlicesCount - 1); i++) {
+
+ if (mask & 1)
+ emptySoundSlice(_soundSliceSize * 2);
+ else {
+ int16 init = _stream->readSint16LE();
+ soundSlice16bit(_soundSliceSize, init);
+ }
+
+ mask >>= 1;
+ }
+
+}
+
+void Vmd::deDPCM(byte *soundBuf, byte *dataBuf, int16 &init, uint32 n) {
+ int16 *out = (int16 *) soundBuf;
+
+ int32 s = init;
+ for (uint32 i = 0; i < n; i++) {
+ if(dataBuf[i] & 0x80)
+ s -= _tableDPCM[dataBuf[i] & 0x7F];
+ else
+ s += _tableDPCM[dataBuf[i]];
+
+ s = CLIP<int32>(s, -32768, 32767);
+ *out++ = TO_BE_16(s);
+ }
+}
+
+} // End of namespace Gob
diff --git a/engines/gob/coktelvideo.h b/engines/gob/coktelvideo.h
new file mode 100644
index 0000000000..a4e5452cce
--- /dev/null
+++ b/engines/gob/coktelvideo.h
@@ -0,0 +1,313 @@
+/* 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 GOB_COKTELVIDEO_H
+#define GOB_COKTELVIDEO_H
+
+#include "common/stream.h"
+#include "sound/mixer.h"
+#include "sound/audiostream.h"
+
+namespace Gob {
+
+/** Common interface for handling Coktel Vision videos and derivated formats. */
+class CoktelVideo {
+public:
+ enum Features {
+ kFeaturesNone = 0,
+ /** Has an own palette. */
+ kFeaturesPalette = 8,
+ /** Suggests a data size. */
+ kFeaturesDataSize = 0x20,
+ /** Has sound. */
+ kFeaturesSound = 0x40,
+ /** Has specific frame coordinates. */
+ kFeaturesFrameCoords = 0x80,
+ /** Has general standard coordinates. */
+ kFeaturesStdCoords = 0x100,
+ /** Has a frame positions table. */
+ kFeaturesFramesPos = 0x200,
+ /** Has video. */
+ kFeaturesVideo = 0x400
+ };
+
+ enum StateFlags {
+ kStateNone = 0,
+ /** Changed the palette. */
+ kStatePalette = 0x10,
+ /** Performed a jump to another frame. */
+ kStateJump = 0x200,
+ /** Updated according to the specific frame coordinates. */
+ kStateFrameCoords = 0x400,
+ /** Got no frame data. */
+ kStateNoVideoData = 0x800,
+ /** Updated according to the general standard coordinates. */
+ kStateStdCoords = 0x1000,
+ /** Had to explicitely seek to the frame. */
+ kStateSeeked = 0x2000,
+ /** Reached a break-point. */
+ kStateBreak = 0x8000
+ };
+
+ struct State {
+ /** Left-most value of the updated rectangle. */
+ int16 left;
+ /** Top-most value of the updated rectangle. */
+ int16 top;
+ /** Right-most value of the updated rectangle. */
+ int16 right;
+ /** Bottom-most value of the updated rectangle. */
+ int16 bottom;
+ /** Set accordingly to what was done. */
+ uint32 flags;
+
+ State() : left(0), top(0), right(0), bottom(0), flags(0) { }
+ };
+
+ virtual ~CoktelVideo() { }
+
+ /** Returns the features the loaded video possesses. */
+ virtual uint16 getFeatures() const = 0;
+ /** Returns the x coordinate of the video. */
+ virtual int16 getX() const = 0;
+ /** Returns the y coordinate of the video. */
+ virtual int16 getY() const = 0;
+ /** Returns the width of the video. */
+ virtual int16 getWidth() const = 0;
+ /** Returns the height of the video. */
+ virtual int16 getHeight() const = 0;
+ /** Returns the number of frames the loaded video has. */
+ virtual uint16 getFramesCount() const = 0;
+ /** Returns the current frame number.
+ *
+ * This is the current frame after the last nextFrame()-call,
+ * i.e. it's 0 after loading, 1 after the first nextFrame()-call, etc..
+ */
+ virtual uint16 getCurrentFrame() const = 0;
+ /** Returns the frame rate. */
+ virtual int16 getFrameRate() const = 0;
+ /** Returns the number of frames the video lags behind the audio. */
+ virtual uint32 getSyncLag() const = 0;
+ /** Returns the current frame's palette. */
+ virtual const byte *getPalette() const = 0;
+
+ /** Load a video out of a stream. */
+ virtual bool load(Common::SeekableReadStream &stream) = 0;
+ /** Unload the currently loaded video. */
+ virtual void unload() = 0;
+
+ /** Set the coordinations where to draw the video. */
+ virtual void setXY(int16 x, int16 y) = 0;
+ /** Use a specific memory block as video memory. */
+ virtual void setVideoMemory(byte *vidMem, uint16 width, uint16 height) = 0;
+ /** Use an own memory block as video memory. */
+ virtual void setVideoMemory() = 0;
+
+ /** Play sound (if the IMD has sound). */
+ virtual void enableSound(Audio::Mixer &mixer) = 0;
+ /** Don't play sound or stop currently playing sound. */
+ virtual void disableSound() = 0;
+
+ /** Seek to a specific frame.
+ *
+ * @param frame The frame to which to seek.
+ * @param whence The offset from whence the frame is given.
+ * @param restart Restart the video to reach an otherwise inaccessible frame?
+ */
+ virtual void seekFrame(int32 frame, int16 whence = SEEK_SET, bool restart = false) = 0;
+
+ /** Render the next frame. */
+ virtual State nextFrame() = 0;
+ /** Wait for the frame to end. */
+ virtual void waitEndFrame() = 0;
+
+ /** Copy the current frame.
+ *
+ * @param dest The memory to which to copy the current frame
+ * @param x The x position to where to copy.
+ * @param y The y position to where to copy.
+ * @param pitch The buffer's width.
+ * @param transp Which color should be seen as transparent?
+ */
+ virtual void copyCurrentFrame(byte *dest, uint16 x, uint16 y, uint16 width, int16 transp = -1) = 0;
+};
+
+/** Coktel Vision's IMD files.
+ */
+class Imd : public CoktelVideo {
+public:
+ Imd();
+ ~Imd();
+
+ uint16 getFeatures() const { return _features; }
+ int16 getX() const { return _x; }
+ int16 getY() const { return _y; }
+ int16 getWidth() const { return _width; }
+ int16 getHeight() const { return _height; }
+ uint16 getFramesCount() const { return _framesCount; }
+ uint16 getCurrentFrame() const { return _curFrame; }
+ int16 getFrameRate() const { if (_hasSound) return 1000 / _soundSliceLength; return 12; }
+ uint32 getSyncLag() const { return _skipFrames; }
+ const byte *getPalette() const { return _palette; }
+
+ bool load(Common::SeekableReadStream &stream);
+ void unload();
+
+ void setXY(int16 x, int16 y);
+ void setVideoMemory(byte *vidMem, uint16 width, uint16 height);
+ void setVideoMemory();
+
+ void enableSound(Audio::Mixer &mixer);
+ void disableSound();
+
+ void seekFrame(int32 frame, int16 whence = SEEK_SET, bool restart = false);
+
+ State nextFrame();
+ void waitEndFrame();
+
+ void copyCurrentFrame(byte *dest, uint16 x, uint16 y, uint16 width, int16 transp = -1);
+
+protected:
+ struct Coord {
+ int16 left;
+ int16 top;
+ int16 right;
+ int16 bottom;
+ } PACKED_STRUCT;
+
+ Common::SeekableReadStream *_stream;
+ uint16 _version;
+ uint16 _features;
+ uint16 _flags;
+ int16 _x, _y, _width, _height;
+ int16 _stdX, _stdY, _stdWidth, _stdHeight;
+ uint16 _framesCount, _curFrame;
+ uint32 *_framesPos;
+ uint32 _firstFramePos;
+ Coord *_frameCoords;
+
+ uint32 _frameDataSize, _vidBufferSize;
+ byte *_frameData, *_vidBuffer;
+
+ byte _palette[768];
+
+ bool _hasOwnVidMem;
+ byte *_vidMem;
+ uint16 _vidMemWidth, _vidMemHeight;
+
+ bool _hasSound;
+ bool _soundEnabled;
+ uint8 _soundStage; // (0: no sound, 1: loaded, 2: playing)
+ uint32 _soundStartTime;
+ uint32 _skipFrames;
+
+ uint16 _soundFlags;
+ int16 _soundFreq;
+ int16 _soundSliceSize;
+ int16 _soundSlicesCount;
+ uint16 _soundSliceLength;
+
+ Audio::AppendableAudioStream *_audioStream;
+ Audio::SoundHandle _audioHandle;
+
+ uint32 _frameLength;
+ uint32 _lastFrameTime;
+
+ Audio::Mixer *_mixer;
+
+ void unsignedToSigned(byte *buffer, int length) {
+ while (length-- > 0) *buffer++ ^= 0x80;
+ }
+
+ void deleteVidMem(bool del = true);
+ void clear(bool del = true);
+
+ State processFrame(uint16 frame);
+ uint32 renderFrame(int16 left, int16 top, int16 right, int16 bottom);
+ void deLZ77(byte *dest, byte *src);
+};
+
+class Vmd : public Imd {
+public:
+ Vmd();
+ ~Vmd();
+
+ bool load(Common::SeekableReadStream &stream);
+ void unload();
+
+ void setXY(int16 x, int16 y);
+
+ void seekFrame(int32 frame, int16 whence = SEEK_SET, bool restart = false);
+
+ State nextFrame();
+
+protected:
+ enum PartType {
+ kPartTypeAudio = 1,
+ kPartTypeVideo = 2
+ };
+ struct Part {
+ PartType type;
+ uint32 size;
+ int16 left;
+ int16 top;
+ int16 right;
+ int16 bottom;
+ byte flags;
+ } PACKED_STRUCT;
+ struct Frame {
+ uint32 offset;
+ Part *parts;
+
+ Frame() : parts(0) { }
+ ~Frame() { delete[] parts; }
+ } PACKED_STRUCT;
+
+ static const uint16 _tableDPCM[128];
+
+ bool _hasVideo;
+
+ uint16 _partsPerFrame;
+ Frame *_frames;
+
+ byte _soundBytesPerSample;
+ byte _soundStereo; // (0: mono, 1: old-style stereo, 2: new-style stereo)
+
+ void clear(bool del = true);
+
+ State processFrame(uint16 frame);
+ uint32 renderFrame(int16 left, int16 top, int16 right, int16 bottom);
+
+ void emptySoundSlice(uint32 size);
+ void soundSlice8bit(uint32 size);
+ void soundSlice16bit(uint32 size, int16 &init);
+ void filledSoundSlice(uint32 size);
+ void filledSoundSlices(uint32 size, uint32 mask);
+ void deDPCM(byte *soundBuf, byte *dataBuf, int16 &init, uint32 n);
+};
+
+} // End of namespace Gob
+
+#endif // GOB_COKTELVIDEO_H
diff --git a/engines/gob/dataio.cpp b/engines/gob/dataio.cpp
index 7ded953427..361627caf4 100644
--- a/engines/gob/dataio.cpp
+++ b/engines/gob/dataio.cpp
@@ -33,6 +33,92 @@
namespace Gob {
+DataStream::DataStream(DataIO &io, int16 handle, uint32 dSize, bool dispose) {
+ _io = &io;
+ _handle = handle;
+ _size = dSize;
+ _dispose = dispose;
+
+ _data = 0;
+ _stream = 0;
+}
+
+DataStream::DataStream(byte *buf, uint32 dSize, bool dispose) {
+ _data = buf;
+ _size = dSize;
+ _stream = new Common::MemoryReadStream(_data, _size);
+ _dispose = dispose;
+
+ _io = 0;
+ _handle = -1;
+}
+
+DataStream::~DataStream() {
+ delete _stream;
+
+ if (_dispose) {
+ delete[] _data;
+ if ((_handle >= 0) && _io)
+ _io->closeData(_handle);
+ }
+}
+
+uint32 DataStream::pos() const {
+ if (_stream)
+ return _stream->pos();
+
+ uint32 resPos = _io->getChunkPos(_handle);
+ if (resPos != 0xFFFFFFFF)
+ return resPos;
+
+ return _io->file_getHandle(_handle)->pos();
+}
+
+uint32 DataStream::size() const {
+ if (_stream)
+ return _stream->size();
+
+ return _size;
+}
+
+void DataStream::seek(int32 offset, int whence) {
+ if (_stream)
+ _stream->seek(offset, whence);
+
+ int32 resPos = _io->seekChunk(_handle, offset, whence);
+ if (resPos != -1)
+ return;
+
+ _io->file_getHandle(_handle)->seek(offset, whence);
+}
+
+bool DataStream::eos() const {
+ if (_stream)
+ return _stream->eos();
+
+ return pos() >= size();
+}
+
+uint32 DataStream::read(void *dataPtr, uint32 dataSize) {
+ if (_stream)
+ return _stream->read(dataPtr, dataSize);
+
+ if ((_handle < 50) || (_handle >= 128))
+ return _io->file_getHandle(_handle)->read((byte *) dataPtr, dataSize);
+
+ byte *data = (byte *) dataPtr;
+ uint32 haveRead = 0;
+ while (dataSize > 0x3FFF) {
+ _io->readChunk(_handle, (byte *) data, 0x3FFF);
+ dataSize -= 0x3FFF;
+ data += 0x3FFF;
+ haveRead += 0x3FFF;
+ }
+ _io->readChunk(_handle, (byte *) data, dataSize);
+
+ return haveRead + dataSize;
+}
+
DataIO::DataIO(GobEngine *vm) : _vm(vm) {
for (int i = 0; i < MAX_DATA_FILES; i++) {
_dataFiles[i] = 0;
@@ -115,6 +201,10 @@ Common::File *DataIO::file_getHandle(int16 handle) {
return &_filesHandles[handle];
}
+const Common::File *DataIO::file_getHandle(int16 handle) const {
+ return &_filesHandles[handle];
+}
+
int16 DataIO::file_open(const char *path, Common::File::AccessMode mode) {
int16 i;
@@ -226,7 +316,7 @@ int16 DataIO::seekChunk(int16 handle, int32 pos, int16 from) {
return _chunkPos[file * MAX_SLOT_COUNT + slot];
}
-uint32 DataIO::getChunkPos(int16 handle) {
+uint32 DataIO::getChunkPos(int16 handle) const {
int16 file;
int16 slot;
@@ -390,39 +480,23 @@ int16 DataIO::openData(const char *path, Common::File::AccessMode mode) {
return file_open(path, mode);
}
-int32 DataIO::readData(int16 handle, byte *buf, uint16 size) {
- int32 res;
-
- res = readChunk(handle, buf, size);
- if (res >= 0)
- return res;
-
- return file_getHandle(handle)->read(buf, size);
-}
+DataStream *DataIO::openAsStream(int16 handle, bool dispose) {
+ uint32 curPos = getPos(handle);
+ seekData(handle, 0, SEEK_END);
+ uint32 size = getPos(handle);
+ seekData(handle, curPos, SEEK_SET);
-byte DataIO::readByte(int16 handle) {
- byte buf;
-
- readData(handle, &buf, 1);
- return ((byte) buf);
+ return new DataStream(*this, handle, size, dispose);
}
-uint16 DataIO::readUint16(int16 handle) {
- byte buf[2];
-
- readData(handle, buf, 2);
- return READ_LE_UINT16(buf);
-}
-
-uint32 DataIO::readUint32(int16 handle) {
- byte buf[4];
+uint32 DataIO::getPos(int16 handle) {
+ uint32 resPos;
- readData(handle, buf, 4);
- return READ_LE_UINT32(buf);
-}
+ resPos = getChunkPos(handle);
+ if (resPos != 0xFFFFFFFF)
+ return resPos;
-int32 DataIO::writeData(int16 handle, byte *buf, uint16 size) {
- return file_getHandle(handle)->write(buf, size);
+ return file_getHandle(handle)->pos();
}
void DataIO::seekData(int16 handle, int32 pos, int16 from) {
@@ -435,14 +509,14 @@ void DataIO::seekData(int16 handle, int32 pos, int16 from) {
file_getHandle(handle)->seek(pos, from);
}
-uint32 DataIO::getPos(int16 handle) {
- uint32 resPos;
+int32 DataIO::readData(int16 handle, byte *buf, uint16 size) {
+ int32 res;
- resPos = getChunkPos(handle);
- if (resPos != 0xFFFFFFFF)
- return resPos;
+ res = readChunk(handle, buf, size);
+ if (res >= 0)
+ return res;
- return file_getHandle(handle)->pos();
+ return file_getHandle(handle)->read(buf, size);
}
int32 DataIO::getDataSize(const char *name) {
@@ -492,4 +566,11 @@ byte *DataIO::getData(const char *path) {
return data;
}
+DataStream *DataIO::getDataStream(const char *path) {
+ uint32 size = getDataSize(path);
+ byte *data = getData(path);
+
+ return new DataStream(data, size);
+}
+
} // End of namespace Gob
diff --git a/engines/gob/dataio.h b/engines/gob/dataio.h
index 3ea29c0efe..b30a389865 100644
--- a/engines/gob/dataio.h
+++ b/engines/gob/dataio.h
@@ -35,7 +35,33 @@ namespace Gob {
#define MAX_FILES 30
#define MAX_DATA_FILES 8
-#define MAX_SLOT_COUNT 4
+#define MAX_SLOT_COUNT 8
+
+class DataIO;
+
+class DataStream : public Common::SeekableReadStream {
+public:
+ DataStream(DataIO &io, int16 handle, uint32 dSize, bool dispose = false);
+ DataStream(byte *buf, uint32 dSize, bool dispose = true);
+ virtual ~DataStream();
+
+ virtual uint32 pos() const;
+ virtual uint32 size() const;
+
+ virtual void seek(int32 offset, int whence = SEEK_SET);
+
+ virtual bool eos() const;
+
+ virtual uint32 read(void *dataPtr, uint32 dataSize);
+
+private:
+ DataIO *_io;
+ int16 _handle;
+ uint32 _size;
+ byte *_data;
+ Common::MemoryReadStream *_stream;
+ bool _dispose;
+};
class DataIO {
public:
@@ -55,15 +81,11 @@ public:
void closeData(int16 handle);
int16 openData(const char *path,
Common::File::AccessMode mode = Common::File::kFileReadMode);
- int32 readData(int16 handle, byte *buf, uint16 size);
- byte readByte(int16 handle);
- uint16 readUint16(int16 handle);
- uint32 readUint32(int16 handle);
- int32 writeData(int16 handle, byte *buf, uint16 size);
- void seekData(int16 handle, int32 pos, int16 from);
- uint32 getPos(int16 handle);
+ DataStream *openAsStream(int16 handle, bool dispose = false);
+
int32 getDataSize(const char *name);
byte *getData(const char *path);
+ DataStream *getDataStream(const char *path);
DataIO(class GobEngine *vm);
~DataIO();
@@ -85,13 +107,20 @@ protected:
int16 file_open(const char *path,
Common::File::AccessMode mode = Common::File::kFileReadMode);
Common::File *file_getHandle(int16 handle);
+ const Common::File *file_getHandle(int16 handle) const;
int16 getChunk(const char *chunkName);
char freeChunk(int16 handle);
int32 readChunk(int16 handle, byte *buf, uint16 size);
int16 seekChunk(int16 handle, int32 pos, int16 from);
- uint32 getChunkPos(int16 handle);
+ uint32 getChunkPos(int16 handle) const;
int32 getChunkSize(const char *chunkName);
+
+ uint32 getPos(int16 handle);
+ void seekData(int16 handle, int32 pos, int16 from);
+ int32 readData(int16 handle, byte *buf, uint16 size);
+
+friend class DataStream;
};
} // End of namespace Gob
diff --git a/engines/gob/detection.cpp b/engines/gob/detection.cpp
index 1c275185ca..7faef57cc1 100644
--- a/engines/gob/detection.cpp
+++ b/engines/gob/detection.cpp
@@ -34,7 +34,8 @@ namespace Gob {
struct GOBGameDescription {
Common::ADGameDescription desc;
- uint32 features;
+ GameType gameType;
+ int32 features;
const char *startTotBase;
};
@@ -48,11 +49,15 @@ static const PlainGameDescriptor gobGames[] = {
{"gob1cd", "Gobliiins CD"},
{"gob2", "Gobliins 2"},
{"gob2cd", "Gobliins 2 CD"},
+ {"ween", "Ween: The Prophecy"},
+ {"bargon", "Bargon Attack"},
+ {"ajworld", "A.J's World of Discovery"},
{"gob3", "Goblins Quest 3"},
{"gob3cd", "Goblins Quest 3 CD"},
- {"bargon", "Bargon Attack"},
- {"ween", "Ween: The Prophecy"},
+ {"lostintime", "Lost in Time"},
+ {"inca2", "Inca II: Wiracocha"},
{"woodruff", "The Bizarre Adventures of Woodruff and the Schnibble"},
+// {"dynasty", "The Last Dynasty"},
{0, 0}
};
@@ -74,7 +79,8 @@ static const GOBGameDescription gameDescriptions[] = {
kPlatformPC,
Common::ADGF_NO_FLAGS
},
- GF_GOB1 | GF_EGA,
+ kGameTypeGob1,
+ kFeaturesEGA,
"intro"
},
{
@@ -86,7 +92,8 @@ static const GOBGameDescription gameDescriptions[] = {
kPlatformPC,
Common::ADGF_NO_FLAGS
},
- GF_GOB1 | GF_EGA,
+ kGameTypeGob1,
+ kFeaturesEGA,
"intro"
},
{ // Supplied by Theruler76 in bug report #1201233
@@ -98,7 +105,8 @@ static const GOBGameDescription gameDescriptions[] = {
kPlatformPC,
Common::ADGF_NO_FLAGS
},
- GF_GOB1,
+ kGameTypeGob1,
+ kFeaturesNone,
"intro"
},
{ // CD 1.000 version.
@@ -110,7 +118,8 @@ static const GOBGameDescription gameDescriptions[] = {
kPlatformPC,
Common::ADGF_NO_FLAGS
},
- GF_GOB1 | GF_CD,
+ kGameTypeGob1,
+ kFeaturesCD,
"intro"
},
{ // CD 1.000 version.
@@ -122,7 +131,8 @@ static const GOBGameDescription gameDescriptions[] = {
kPlatformPC,
Common::ADGF_NO_FLAGS
},
- GF_GOB1 | GF_CD,
+ kGameTypeGob1,
+ kFeaturesCD,
"intro"
},
{ // CD 1.000 version.
@@ -134,7 +144,8 @@ static const GOBGameDescription gameDescriptions[] = {
kPlatformPC,
Common::ADGF_NO_FLAGS
},
- GF_GOB1 | GF_CD,
+ kGameTypeGob1,
+ kFeaturesCD,
"intro"
},
{ // CD 1.000 version.
@@ -146,7 +157,8 @@ static const GOBGameDescription gameDescriptions[] = {
kPlatformPC,
Common::ADGF_NO_FLAGS
},
- GF_GOB1 | GF_CD,
+ kGameTypeGob1,
+ kFeaturesCD,
"intro"
},
{ // CD 1.000 version.
@@ -158,7 +170,8 @@ static const GOBGameDescription gameDescriptions[] = {
kPlatformPC,
Common::ADGF_NO_FLAGS
},
- GF_GOB1 | GF_CD,
+ kGameTypeGob1,
+ kFeaturesCD,
"intro"
},
{ // CD 1.02 version. Multilingual
@@ -170,7 +183,8 @@ static const GOBGameDescription gameDescriptions[] = {
kPlatformPC,
Common::ADGF_NO_FLAGS
},
- GF_GOB1 | GF_CD,
+ kGameTypeGob1,
+ kFeaturesCD,
"intro"
},
{ // CD 1.02 version. Multilingual
@@ -182,7 +196,8 @@ static const GOBGameDescription gameDescriptions[] = {
kPlatformPC,
Common::ADGF_NO_FLAGS
},
- GF_GOB1 | GF_CD,
+ kGameTypeGob1,
+ kFeaturesCD,
"intro"
},
{ // CD 1.02 version. Multilingual
@@ -194,7 +209,8 @@ static const GOBGameDescription gameDescriptions[] = {
kPlatformPC,
Common::ADGF_NO_FLAGS
},
- GF_GOB1 | GF_CD,
+ kGameTypeGob1,
+ kFeaturesCD,
"intro"
},
{ // CD 1.02 version. Multilingual
@@ -206,7 +222,8 @@ static const GOBGameDescription gameDescriptions[] = {
kPlatformPC,
Common::ADGF_NO_FLAGS
},
- GF_GOB1 | GF_CD,
+ kGameTypeGob1,
+ kFeaturesCD,
"intro"
},
{ // CD 1.02 version. Multilingual
@@ -218,7 +235,8 @@ static const GOBGameDescription gameDescriptions[] = {
kPlatformPC,
Common::ADGF_NO_FLAGS
},
- GF_GOB1 | GF_CD,
+ kGameTypeGob1,
+ kFeaturesCD,
"intro"
},
{
@@ -230,7 +248,8 @@ static const GOBGameDescription gameDescriptions[] = {
kPlatformAmiga,
Common::ADGF_DEMO
},
- GF_GOB1,
+ kGameTypeGob1,
+ kFeaturesNone,
"intro"
},
{
@@ -242,7 +261,8 @@ static const GOBGameDescription gameDescriptions[] = {
kPlatformPC,
Common::ADGF_DEMO
},
- GF_GOB1,
+ kGameTypeGob1,
+ kFeaturesNone,
"intro"
},
{ // Supplied by paul66 in bug report #1652352
@@ -254,7 +274,8 @@ static const GOBGameDescription gameDescriptions[] = {
kPlatformMacintosh,
Common::ADGF_NO_FLAGS
},
- GF_GOB1,
+ kGameTypeGob1,
+ kFeaturesAdlib,
"intro"
},
{ // Supplied by paul66 in bug report #1652352
@@ -266,7 +287,8 @@ static const GOBGameDescription gameDescriptions[] = {
kPlatformMacintosh,
Common::ADGF_NO_FLAGS
},
- GF_GOB1,
+ kGameTypeGob1,
+ kFeaturesAdlib,
"intro"
},
{ // Supplied by paul66 in bug report #1652352
@@ -278,7 +300,8 @@ static const GOBGameDescription gameDescriptions[] = {
kPlatformMacintosh,
Common::ADGF_NO_FLAGS
},
- GF_GOB1,
+ kGameTypeGob1,
+ kFeaturesAdlib,
"intro"
},
{ // Supplied by paul66 in bug report #1652352
@@ -290,7 +313,8 @@ static const GOBGameDescription gameDescriptions[] = {
kPlatformMacintosh,
Common::ADGF_NO_FLAGS
},
- GF_GOB1,
+ kGameTypeGob1,
+ kFeaturesAdlib,
"intro"
},
{ // Supplied by paul66 in bug report #1652352
@@ -302,7 +326,8 @@ static const GOBGameDescription gameDescriptions[] = {
kPlatformMacintosh,
Common::ADGF_NO_FLAGS
},
- GF_GOB1,
+ kGameTypeGob1,
+ kFeaturesAdlib,
"intro"
},
{
@@ -314,7 +339,8 @@ static const GOBGameDescription gameDescriptions[] = {
kPlatformPC,
Common::ADGF_NO_FLAGS
},
- GF_GOB2,
+ kGameTypeGob2,
+ kFeaturesAdlib,
"intro"
},
{ // Supplied by arcepi in bug report #1659884
@@ -326,7 +352,8 @@ static const GOBGameDescription gameDescriptions[] = {
kPlatformPC,
Common::ADGF_NO_FLAGS
},
- GF_GOB2,
+ kGameTypeGob2,
+ kFeaturesAdlib,
"intro"
},
{
@@ -338,7 +365,8 @@ static const GOBGameDescription gameDescriptions[] = {
kPlatformPC,
Common::ADGF_NO_FLAGS
},
- GF_GOB2,
+ kGameTypeGob2,
+ kFeaturesAdlib,
"intro"
},
{ // Supplied by fac76 in bug report #1673397
@@ -354,7 +382,8 @@ static const GOBGameDescription gameDescriptions[] = {
kPlatformMacintosh,
Common::ADGF_NO_FLAGS
},
- GF_GOB2,
+ kGameTypeGob2,
+ kFeaturesAdlib,
"intro"
},
{
@@ -366,7 +395,8 @@ static const GOBGameDescription gameDescriptions[] = {
kPlatformPC,
Common::ADGF_NO_FLAGS
},
- GF_GOB2,
+ kGameTypeGob2,
+ kFeaturesAdlib,
"intro"
},
{
@@ -378,7 +408,8 @@ static const GOBGameDescription gameDescriptions[] = {
kPlatformPC,
Common::ADGF_NO_FLAGS
},
- GF_GOB2,
+ kGameTypeGob2,
+ kFeaturesAdlib,
"intro"
},
{
@@ -390,7 +421,8 @@ static const GOBGameDescription gameDescriptions[] = {
kPlatformPC,
Common::ADGF_NO_FLAGS
},
- GF_GOB2,
+ kGameTypeGob2,
+ kFeaturesAdlib,
"intro"
},
{
@@ -402,7 +434,8 @@ static const GOBGameDescription gameDescriptions[] = {
kPlatformAmiga,
Common::ADGF_NO_FLAGS
},
- GF_GOB2,
+ kGameTypeGob2,
+ kFeaturesNone,
"intro"
},
{ // Supplied by blackwhiteeagle in bug report #1605235
@@ -414,7 +447,8 @@ static const GOBGameDescription gameDescriptions[] = {
kPlatformPC,
Common::ADGF_NO_FLAGS
},
- GF_GOB2,
+ kGameTypeGob2,
+ kFeaturesAdlib,
"intro"
},
{ // Supplied by bgk in bug report #1706861
@@ -426,7 +460,8 @@ static const GOBGameDescription gameDescriptions[] = {
kPlatformAtariST,
Common::ADGF_NO_FLAGS
},
- GF_GOB2,
+ kGameTypeGob2,
+ kFeaturesNone,
"intro"
},
{
@@ -438,7 +473,8 @@ static const GOBGameDescription gameDescriptions[] = {
kPlatformPC,
Common::ADGF_NO_FLAGS
},
- GF_GOB2 | GF_CD,
+ kGameTypeGob2,
+ kFeaturesCD,
"intro"
},
{
@@ -450,7 +486,8 @@ static const GOBGameDescription gameDescriptions[] = {
kPlatformPC,
Common::ADGF_NO_FLAGS
},
- GF_GOB2 | GF_CD,
+ kGameTypeGob2,
+ kFeaturesCD,
"intro"
},
{
@@ -462,7 +499,8 @@ static const GOBGameDescription gameDescriptions[] = {
kPlatformPC,
Common::ADGF_NO_FLAGS
},
- GF_GOB2 | GF_CD,
+ kGameTypeGob2,
+ kFeaturesCD,
"intro"
},
{
@@ -474,7 +512,8 @@ static const GOBGameDescription gameDescriptions[] = {
kPlatformPC,
Common::ADGF_NO_FLAGS
},
- GF_GOB2 | GF_CD,
+ kGameTypeGob2,
+ kFeaturesCD,
"intro"
},
{
@@ -486,7 +525,8 @@ static const GOBGameDescription gameDescriptions[] = {
kPlatformPC,
Common::ADGF_NO_FLAGS
},
- GF_GOB2 | GF_CD,
+ kGameTypeGob2,
+ kFeaturesCD,
"intro"
},
{
@@ -498,7 +538,8 @@ static const GOBGameDescription gameDescriptions[] = {
kPlatformPC,
Common::ADGF_NO_FLAGS
},
- GF_GOB2 | GF_CD,
+ kGameTypeGob2,
+ kFeaturesCD,
"intro"
},
{
@@ -510,7 +551,8 @@ static const GOBGameDescription gameDescriptions[] = {
kPlatformPC,
Common::ADGF_DEMO
},
- GF_GOB2,
+ kGameTypeGob2,
+ kFeaturesAdlib,
"usa"
},
{
@@ -522,7 +564,8 @@ static const GOBGameDescription gameDescriptions[] = {
kPlatformPC,
Common::ADGF_DEMO
},
- GF_GOB2,
+ kGameTypeGob2,
+ kFeaturesAdlib,
"intro"
},
{
@@ -534,7 +577,8 @@ static const GOBGameDescription gameDescriptions[] = {
kPlatformPC,
Common::ADGF_DEMO
},
- GF_GOB2,
+ kGameTypeGob2,
+ kFeaturesAdlib,
"intro"
},
{
@@ -546,7 +590,8 @@ static const GOBGameDescription gameDescriptions[] = {
kPlatformPC,
Common::ADGF_NO_FLAGS
},
- GF_GOB2,
+ kGameTypeWeen,
+ kFeaturesAdlib,
"intro"
},
{
@@ -558,7 +603,8 @@ static const GOBGameDescription gameDescriptions[] = {
kPlatformPC,
Common::ADGF_NO_FLAGS
},
- GF_GOB2,
+ kGameTypeWeen,
+ kFeaturesAdlib,
"intro"
},
{ // Supplied by cybot_tmin in bug report #1667743
@@ -570,19 +616,42 @@ static const GOBGameDescription gameDescriptions[] = {
kPlatformPC,
Common::ADGF_NO_FLAGS
},
- GF_GOB2,
+ kGameTypeWeen,
+ kFeaturesAdlib,
"intro"
},
{ // Supplied by vampir_raziel in bug report #1658373
{
"ween",
"",
- AD_ENTRY1s("intro.stk", "bfd9d02faf3d8d60a2cf744f95eb48dd", 456570),
+ {
+ {"intro.stk", 0, "bfd9d02faf3d8d60a2cf744f95eb48dd", 456570},
+ {"ween.ins", 0, "d2cb24292c9ddafcad07e23382027218", 87800},
+ {NULL, 0, NULL, 0}
+ },
EN_GRB,
kPlatformAmiga,
Common::ADGF_NO_FLAGS
},
- GF_GOB2,
+ kGameTypeWeen,
+ kFeaturesNone,
+ "intro"
+ },
+ { // Supplied by pwigren in bug report #1764174
+ {
+ "ween",
+ "",
+ {
+ {"intro.stk", 0, "bfd9d02faf3d8d60a2cf744f95eb48dd", 456570},
+ {"music__5.snd", 0, "7d1819b9981ecddd53d3aacbc75f1cc8", 13446},
+ {NULL, 0, NULL, 0}
+ },
+ EN_GRB,
+ kPlatformAtariST,
+ Common::ADGF_NO_FLAGS
+ },
+ kGameTypeWeen,
+ kFeaturesNone,
"intro"
},
{ // Supplied by vampir_raziel in bug report #1658373
@@ -594,7 +663,8 @@ static const GOBGameDescription gameDescriptions[] = {
kPlatformAmiga,
Common::ADGF_NO_FLAGS
},
- GF_GOB2,
+ kGameTypeWeen,
+ kFeaturesNone,
"intro"
},
{ // Supplied by vampir_raziel in bug report #1658373
@@ -606,7 +676,8 @@ static const GOBGameDescription gameDescriptions[] = {
kPlatformAmiga,
Common::ADGF_NO_FLAGS
},
- GF_GOB2,
+ kGameTypeWeen,
+ kFeaturesNone,
"intro"
},
{ // Supplied by vampir_raziel in bug report #1658373
@@ -618,7 +689,8 @@ static const GOBGameDescription gameDescriptions[] = {
kPlatformAmiga,
Common::ADGF_NO_FLAGS
},
- GF_GOB2,
+ kGameTypeWeen,
+ kFeaturesNone,
"intro"
},
{
@@ -630,7 +702,8 @@ static const GOBGameDescription gameDescriptions[] = {
kPlatformAtariST,
Common::ADGF_NO_FLAGS
},
- GF_GOB2,
+ kGameTypeWeen,
+ kFeaturesNone,
"intro"
},
{
@@ -642,7 +715,8 @@ static const GOBGameDescription gameDescriptions[] = {
kPlatformPC,
Common::ADGF_NO_FLAGS
},
- GF_GOB2,
+ kGameTypeWeen,
+ kFeaturesAdlib,
"intro"
},
{ // Supplied by cartman_ on #scummvm
@@ -654,7 +728,8 @@ static const GOBGameDescription gameDescriptions[] = {
kPlatformPC,
Common::ADGF_NO_FLAGS
},
- GF_GOB2,
+ kGameTypeWeen,
+ kFeaturesAdlib,
"intro"
},
{ // Supplied by glorfindel in bugreport #1722142
@@ -666,7 +741,8 @@ static const GOBGameDescription gameDescriptions[] = {
kPlatformPC,
Common::ADGF_NO_FLAGS
},
- GF_GOB2,
+ kGameTypeWeen,
+ kFeaturesAdlib,
"intro"
},
{
@@ -678,7 +754,8 @@ static const GOBGameDescription gameDescriptions[] = {
kPlatformPC,
Common::ADGF_DEMO
},
- GF_GOB2,
+ kGameTypeWeen,
+ kFeaturesAdlib,
"show"
},
{
@@ -690,7 +767,8 @@ static const GOBGameDescription gameDescriptions[] = {
kPlatformPC,
Common::ADGF_DEMO
},
- GF_GOB2,
+ kGameTypeWeen,
+ kFeaturesAdlib,
"show"
},
{
@@ -702,7 +780,8 @@ static const GOBGameDescription gameDescriptions[] = {
kPlatformPC,
Common::ADGF_NO_FLAGS
},
- GF_BARGON,
+ kGameTypeBargon,
+ kFeaturesNone,
"intro"
},
{ // Supplied by Trekky in the forums
@@ -714,7 +793,8 @@ static const GOBGameDescription gameDescriptions[] = {
kPlatformAtariST,
Common::ADGF_NO_FLAGS
},
- GF_BARGON,
+ kGameTypeBargon,
+ kFeaturesNone,
"intro"
},
{ // Supplied by cesardark in bug #1681649
@@ -726,7 +806,8 @@ static const GOBGameDescription gameDescriptions[] = {
kPlatformPC,
Common::ADGF_NO_FLAGS
},
- GF_BARGON,
+ kGameTypeBargon,
+ kFeaturesNone,
"intro"
},
{ // Supplied by paul66 in bug #1692667
@@ -738,7 +819,21 @@ static const GOBGameDescription gameDescriptions[] = {
kPlatformPC,
Common::ADGF_NO_FLAGS
},
- GF_BARGON,
+ kGameTypeBargon,
+ kFeaturesNone,
+ "intro"
+ },
+ { // Supplied by pwigren in bugreport #1764174
+ {
+ "bargon",
+ "",
+ AD_ENTRY1s("intro.stk", "569d679fe41d49972d34c9fce5930dda", 269825),
+ EN_ANY,
+ kPlatformAmiga,
+ Common::ADGF_NO_FLAGS
+ },
+ kGameTypeBargon,
+ kFeaturesNone,
"intro"
},
{ // Supplied by glorfindel in bugreport #1722142
@@ -750,7 +845,112 @@ static const GOBGameDescription gameDescriptions[] = {
kPlatformPC,
Common::ADGF_NO_FLAGS
},
- GF_BARGON,
+ kGameTypeBargon,
+ kFeaturesNone,
+ "intro"
+ },
+ {
+ {
+ "ajworld",
+ "",
+ AD_ENTRY1s("intro.stk", "e453bea7b28a67c930764d945f64d898", 3913628),
+ EN_ANY,
+ kPlatformPC,
+ Common::ADGF_NO_FLAGS
+ },
+ kGameTypeGob2,
+ kFeaturesAdlib,
+ "intro"
+ },
+ {
+ {
+ "lostintime",
+ "",
+ AD_ENTRY1s("intro.stk", "7b7f48490dedc8a7cb999388e2fadbe3", 3930674),
+ EN_USA,
+ kPlatformPC,
+ Common::ADGF_NO_FLAGS
+ },
+ kGameTypeLostInTime,
+ kFeaturesAdlib,
+ "intro"
+ },
+ {
+ {
+ "lostintime",
+ "",
+ AD_ENTRY1s("intro.stk", "6263d09e996c1b4e84ef2d650b820e57", 4831170),
+ EN_USA,
+ kPlatformPC,
+ Common::ADGF_NO_FLAGS
+ },
+ kGameTypeLostInTime,
+ kFeaturesCD,
+ "intro"
+ },
+ {
+ {
+ "lostintime",
+ "",
+ AD_ENTRY1s("intro.stk", "6263d09e996c1b4e84ef2d650b820e57", 4831170),
+ FR_FRA,
+ kPlatformPC,
+ Common::ADGF_NO_FLAGS
+ },
+ kGameTypeLostInTime,
+ kFeaturesCD,
+ "intro"
+ },
+ {
+ {
+ "lostintime",
+ "",
+ AD_ENTRY1s("intro.stk", "6263d09e996c1b4e84ef2d650b820e57", 4831170),
+ IT_ITA,
+ kPlatformPC,
+ Common::ADGF_NO_FLAGS
+ },
+ kGameTypeLostInTime,
+ kFeaturesCD,
+ "intro"
+ },
+ {
+ {
+ "lostintime",
+ "",
+ AD_ENTRY1s("intro.stk", "6263d09e996c1b4e84ef2d650b820e57", 4831170),
+ DE_DEU,
+ kPlatformPC,
+ Common::ADGF_NO_FLAGS
+ },
+ kGameTypeLostInTime,
+ kFeaturesCD,
+ "intro"
+ },
+ {
+ {
+ "lostintime",
+ "",
+ AD_ENTRY1s("intro.stk", "6263d09e996c1b4e84ef2d650b820e57", 4831170),
+ ES_ESP,
+ kPlatformPC,
+ Common::ADGF_NO_FLAGS
+ },
+ kGameTypeLostInTime,
+ kFeaturesCD,
+ "intro"
+ },
+ {
+ {
+ "lostintime",
+ "",
+ AD_ENTRY1s("intro.stk", "6263d09e996c1b4e84ef2d650b820e57", 4831170),
+ EN_GRB,
+ kPlatformPC,
+ Common::ADGF_NO_FLAGS
+ },
+ kGameTypeLostInTime,
+ kFeaturesCD,
"intro"
},
{
@@ -762,7 +962,8 @@ static const GOBGameDescription gameDescriptions[] = {
kPlatformPC,
Common::ADGF_NO_FLAGS
},
- GF_GOB3,
+ kGameTypeGob3,
+ kFeaturesAdlib,
"intro"
},
{ // Supplied by fac76 in bug report #1742716
@@ -778,7 +979,8 @@ static const GOBGameDescription gameDescriptions[] = {
kPlatformMacintosh,
Common::ADGF_NO_FLAGS
},
- GF_GOB3,
+ kGameTypeGob3,
+ kFeaturesAdlib,
"intro"
},
{
@@ -790,7 +992,8 @@ static const GOBGameDescription gameDescriptions[] = {
kPlatformPC,
Common::ADGF_NO_FLAGS
},
- GF_GOB3,
+ kGameTypeGob3,
+ kFeaturesAdlib,
"intro"
},
{ // Supplied by paul66 in bug report #1652352
@@ -802,7 +1005,8 @@ static const GOBGameDescription gameDescriptions[] = {
kPlatformPC,
Common::ADGF_NO_FLAGS
},
- GF_GOB3,
+ kGameTypeGob3,
+ kFeaturesAdlib,
"intro"
},
{
@@ -814,7 +1018,8 @@ static const GOBGameDescription gameDescriptions[] = {
kPlatformPC,
Common::ADGF_NO_FLAGS
},
- GF_GOB3,
+ kGameTypeGob3,
+ kFeaturesAdlib,
"intro"
},
{ // Supplied by Paranoimia on #scummvm
@@ -826,7 +1031,8 @@ static const GOBGameDescription gameDescriptions[] = {
kPlatformPC,
Common::ADGF_NO_FLAGS
},
- GF_GOB3,
+ kGameTypeGob3,
+ kFeaturesAdlib,
"intro"
},
{
@@ -838,7 +1044,8 @@ static const GOBGameDescription gameDescriptions[] = {
kPlatformPC,
Common::ADGF_NO_FLAGS
},
- GF_GOB3,
+ kGameTypeGob3,
+ kFeaturesAdlib,
"intro"
},
{
@@ -850,7 +1057,8 @@ static const GOBGameDescription gameDescriptions[] = {
kPlatformPC,
Common::ADGF_NO_FLAGS
},
- GF_GOB3,
+ kGameTypeGob3,
+ kFeaturesAdlib,
"intro"
},
{
@@ -862,7 +1070,8 @@ static const GOBGameDescription gameDescriptions[] = {
kPlatformAmiga,
Common::ADGF_NO_FLAGS
},
- GF_GOB3,
+ kGameTypeGob3,
+ kFeaturesNone,
"menu"
},
{
@@ -874,7 +1083,8 @@ static const GOBGameDescription gameDescriptions[] = {
kPlatformAmiga,
Common::ADGF_NO_FLAGS
},
- GF_GOB3,
+ kGameTypeGob3,
+ kFeaturesNone,
"menu"
},
{
@@ -886,7 +1096,8 @@ static const GOBGameDescription gameDescriptions[] = {
kPlatformPC,
Common::ADGF_NO_FLAGS
},
- GF_GOB3 | GF_CD,
+ kGameTypeGob3,
+ kFeaturesCD,
"intro"
},
{ // Supplied by paul66 and noizert in bug reports #1652352 and #1691230
@@ -898,7 +1109,8 @@ static const GOBGameDescription gameDescriptions[] = {
kPlatformPC,
Common::ADGF_NO_FLAGS
},
- GF_GOB3 | GF_CD,
+ kGameTypeGob3,
+ kFeaturesCD,
"intro"
},
{ // Supplied by paul66 and noizert in bug reports #1652352 and #1691230
@@ -910,7 +1122,8 @@ static const GOBGameDescription gameDescriptions[] = {
kPlatformPC,
Common::ADGF_NO_FLAGS
},
- GF_GOB3 | GF_CD,
+ kGameTypeGob3,
+ kFeaturesCD,
"intro"
},
{ // Supplied by paul66 and noizert in bug reports #1652352 and #1691230
@@ -922,7 +1135,8 @@ static const GOBGameDescription gameDescriptions[] = {
kPlatformPC,
Common::ADGF_NO_FLAGS
},
- GF_GOB3 | GF_CD,
+ kGameTypeGob3,
+ kFeaturesCD,
"intro"
},
{ // Supplied by paul66 and noizert in bug reports #1652352 and #1691230
@@ -934,7 +1148,8 @@ static const GOBGameDescription gameDescriptions[] = {
kPlatformPC,
Common::ADGF_NO_FLAGS
},
- GF_GOB3 | GF_CD,
+ kGameTypeGob3,
+ kFeaturesCD,
"intro"
},
{ // Supplied by paul66 and noizert in bug reports #1652352 and #1691230
@@ -946,7 +1161,8 @@ static const GOBGameDescription gameDescriptions[] = {
kPlatformPC,
Common::ADGF_NO_FLAGS
},
- GF_GOB3 | GF_CD,
+ kGameTypeGob3,
+ kFeaturesCD,
"intro"
},
{
@@ -958,7 +1174,8 @@ static const GOBGameDescription gameDescriptions[] = {
kPlatformPC,
Common::ADGF_DEMO
},
- GF_GOB3,
+ kGameTypeGob3,
+ kFeaturesAdlib,
"intro"
},
{
@@ -970,7 +1187,8 @@ static const GOBGameDescription gameDescriptions[] = {
kPlatformPC,
Common::ADGF_DEMO
},
- GF_GOB3,
+ kGameTypeGob3,
+ kFeaturesAdlib,
"intro"
},
{
@@ -982,7 +1200,8 @@ static const GOBGameDescription gameDescriptions[] = {
kPlatformPC,
Common::ADGF_DEMO
},
- GF_GOB3,
+ kGameTypeGob3,
+ kFeaturesAdlib,
"intro"
},
{
@@ -994,7 +1213,73 @@ static const GOBGameDescription gameDescriptions[] = {
kPlatformPC,
Common::ADGF_DEMO
},
- GF_GOB3,
+ kGameTypeGob3,
+ kFeaturesAdlib,
+ "intro"
+ },
+ {
+ {
+ "inca2",
+ "",
+ AD_ENTRY1s("intro.stk", "47c3b452767c4f49ea7b109143e77c30", 916828),
+ EN_USA,
+ kPlatformPC,
+ Common::ADGF_NO_FLAGS
+ },
+ kGameTypeGob3,
+ kFeaturesCD,
+ "intro"
+ },
+ {
+ {
+ "inca2",
+ "",
+ AD_ENTRY1s("intro.stk", "47c3b452767c4f49ea7b109143e77c30", 916828),
+ DE_DEU,
+ kPlatformPC,
+ Common::ADGF_NO_FLAGS
+ },
+ kGameTypeGob3,
+ kFeaturesCD,
+ "intro"
+ },
+ {
+ {
+ "inca2",
+ "",
+ AD_ENTRY1s("intro.stk", "47c3b452767c4f49ea7b109143e77c30", 916828),
+ FR_FRA,
+ kPlatformPC,
+ Common::ADGF_NO_FLAGS
+ },
+ kGameTypeGob3,
+ kFeaturesCD,
+ "intro"
+ },
+ {
+ {
+ "inca2",
+ "",
+ AD_ENTRY1s("intro.stk", "47c3b452767c4f49ea7b109143e77c30", 916828),
+ IT_ITA,
+ kPlatformPC,
+ Common::ADGF_NO_FLAGS
+ },
+ kGameTypeGob3,
+ kFeaturesCD,
+ "intro"
+ },
+ {
+ {
+ "inca2",
+ "",
+ AD_ENTRY1s("intro.stk", "47c3b452767c4f49ea7b109143e77c30", 916828),
+ ES_ESP,
+ kPlatformPC,
+ Common::ADGF_NO_FLAGS
+ },
+ kGameTypeGob3,
+ kFeaturesCD,
"intro"
},
{
@@ -1002,11 +1287,64 @@ static const GOBGameDescription gameDescriptions[] = {
"woodruff",
"",
AD_ENTRY1s("intro.stk", "dccf9d31cb720b34d75487408821b77e", 20296390),
- UNK_LANG,
+ EN_GRB,
+ kPlatformPC,
+ Common::ADGF_NO_FLAGS
+ },
+ kGameTypeWoodruff,
+ kFeatures640,
+ "intro"
+ },
+ {
+ {
+ "woodruff",
+ "",
+ AD_ENTRY1s("intro.stk", "dccf9d31cb720b34d75487408821b77e", 20296390),
+ DE_DEU,
kPlatformPC,
Common::ADGF_NO_FLAGS
},
- GF_WOODRUFF,
+ kGameTypeWoodruff,
+ kFeatures640,
+ "intro"
+ },
+ {
+ {
+ "woodruff",
+ "",
+ AD_ENTRY1s("intro.stk", "dccf9d31cb720b34d75487408821b77e", 20296390),
+ FR_FRA,
+ kPlatformPC,
+ Common::ADGF_NO_FLAGS
+ },
+ kGameTypeWoodruff,
+ kFeatures640,
+ "intro"
+ },
+ {
+ {
+ "woodruff",
+ "",
+ AD_ENTRY1s("intro.stk", "dccf9d31cb720b34d75487408821b77e", 20296390),
+ IT_ITA,
+ kPlatformPC,
+ Common::ADGF_NO_FLAGS
+ },
+ kGameTypeWoodruff,
+ kFeatures640,
+ "intro"
+ },
+ {
+ {
+ "woodruff",
+ "",
+ AD_ENTRY1s("intro.stk", "dccf9d31cb720b34d75487408821b77e", 20296390),
+ ES_ESP,
+ kPlatformPC,
+ Common::ADGF_NO_FLAGS
+ },
+ kGameTypeWoodruff,
+ kFeatures640,
"intro"
},
{
@@ -1014,11 +1352,64 @@ static const GOBGameDescription gameDescriptions[] = {
"woodruff",
"",
AD_ENTRY1s("intro.stk", "b50fee012a5abcd0ac2963e1b4b56bec", 20298108),
- EN_USA,
+ EN_GRB,
+ kPlatformPC,
+ Common::ADGF_NO_FLAGS
+ },
+ kGameTypeWoodruff,
+ kFeatures640,
+ "intro"
+ },
+ {
+ {
+ "woodruff",
+ "",
+ AD_ENTRY1s("intro.stk", "b50fee012a5abcd0ac2963e1b4b56bec", 20298108),
+ DE_DEU,
+ kPlatformPC,
+ Common::ADGF_NO_FLAGS
+ },
+ kGameTypeWoodruff,
+ kFeatures640,
+ "intro"
+ },
+ {
+ {
+ "woodruff",
+ "",
+ AD_ENTRY1s("intro.stk", "b50fee012a5abcd0ac2963e1b4b56bec", 20298108),
+ FR_FRA,
+ kPlatformPC,
+ Common::ADGF_NO_FLAGS
+ },
+ kGameTypeWoodruff,
+ kFeatures640,
+ "intro"
+ },
+ {
+ {
+ "woodruff",
+ "",
+ AD_ENTRY1s("intro.stk", "b50fee012a5abcd0ac2963e1b4b56bec", 20298108),
+ IT_ITA,
kPlatformPC,
Common::ADGF_NO_FLAGS
},
- GF_WOODRUFF,
+ kGameTypeWoodruff,
+ kFeatures640,
+ "intro"
+ },
+ {
+ {
+ "woodruff",
+ "",
+ AD_ENTRY1s("intro.stk", "b50fee012a5abcd0ac2963e1b4b56bec", 20298108),
+ ES_ESP,
+ kPlatformPC,
+ Common::ADGF_NO_FLAGS
+ },
+ kGameTypeWoodruff,
+ kFeatures640,
"intro"
},
{
@@ -1030,10 +1421,128 @@ static const GOBGameDescription gameDescriptions[] = {
kPlatformPC,
Common::ADGF_NO_FLAGS
},
- GF_WOODRUFF,
+ kGameTypeWoodruff,
+ kFeatures640,
+ "intro"
+ },
+ { // Supplied by jvprat on #scummvm
+ {
+ "woodruff",
+ "",
+ AD_ENTRY1s("intro.stk", "270529d9b8cce770b1575908a3800b52", 20296452),
+ ES_ESP,
+ kPlatformPC,
+ Common::ADGF_NO_FLAGS
+ },
+ kGameTypeWoodruff,
+ kFeatures640,
"intro"
},
- { AD_TABLE_END_MARKER, 0, NULL }
+ { // Supplied by jvprat on #scummvm
+ {
+ "woodruff",
+ "",
+ AD_ENTRY1s("intro.stk", "270529d9b8cce770b1575908a3800b52", 20296452),
+ EN_GRB,
+ kPlatformPC,
+ Common::ADGF_NO_FLAGS
+ },
+ kGameTypeWoodruff,
+ kFeatures640,
+ "intro"
+ },
+ { // Supplied by jvprat on #scummvm
+ {
+ "woodruff",
+ "",
+ AD_ENTRY1s("intro.stk", "270529d9b8cce770b1575908a3800b52", 20296452),
+ DE_DEU,
+ kPlatformPC,
+ Common::ADGF_NO_FLAGS
+ },
+ kGameTypeWoodruff,
+ kFeatures640,
+ "intro"
+ },
+ { // Supplied by jvprat on #scummvm
+ {
+ "woodruff",
+ "",
+ AD_ENTRY1s("intro.stk", "270529d9b8cce770b1575908a3800b52", 20296452),
+ FR_FRA,
+ kPlatformPC,
+ Common::ADGF_NO_FLAGS
+ },
+ kGameTypeWoodruff,
+ kFeatures640,
+ "intro"
+ },
+ { // Supplied by jvprat on #scummvm
+ {
+ "woodruff",
+ "",
+ AD_ENTRY1s("intro.stk", "270529d9b8cce770b1575908a3800b52", 20296452),
+ IT_ITA,
+ kPlatformPC,
+ Common::ADGF_NO_FLAGS
+ },
+ kGameTypeWoodruff,
+ kFeatures640,
+ "intro"
+ },
+ { // Supplied by Hkz on #scummvm
+ {
+ "woodruff",
+ "",
+ AD_ENTRY1s("intro.stk", "f4c344023b073782d2fddd9d8b515318", 7069736),
+ IT_ITA,
+ kPlatformPC,
+ Common::ADGF_NO_FLAGS
+ },
+ kGameTypeWoodruff,
+ kFeatures640,
+ "intro"
+ },
+ { // Supplied by Hkz on #scummvm
+ {
+ "woodruff",
+ "",
+ AD_ENTRY1s("intro.stk", "f4c344023b073782d2fddd9d8b515318", 7069736),
+ DE_DEU,
+ kPlatformPC,
+ Common::ADGF_NO_FLAGS
+ },
+ kGameTypeWoodruff,
+ kFeatures640,
+ "intro"
+ },
+ { // Supplied by Hkz on #scummvm
+ {
+ "woodruff",
+ "",
+ AD_ENTRY1s("intro.stk", "f4c344023b073782d2fddd9d8b515318", 7069736),
+ FR_FRA,
+ kPlatformPC,
+ Common::ADGF_NO_FLAGS
+ },
+ kGameTypeWoodruff,
+ kFeatures640,
+ "intro"
+ },
+ /*{
+ {
+ "dynasty",
+ "",
+ AD_ENTRY1s("intro.stk", "6190e32404b672f4bbbc39cf76f41fda", 2511470),
+ EN_USA,
+ kPlatformPC,
+ Common::ADGF_NO_FLAGS
+ },
+ kGameTypeWoodruff,
+ kFeatures640,
+ "intro"
+ },*/
+ { AD_TABLE_END_MARKER, kGameTypeNone, kFeaturesNone, NULL }
};
static const GOBGameDescription fallbackDescs[] = {
@@ -1046,7 +1555,8 @@ static const GOBGameDescription fallbackDescs[] = {
kPlatformPC,
Common::ADGF_NO_FLAGS
},
- GF_GOB1,
+ kGameTypeGob1,
+ kFeaturesNone,
"intro"
},
{
@@ -1058,7 +1568,8 @@ static const GOBGameDescription fallbackDescs[] = {
kPlatformPC,
Common::ADGF_NO_FLAGS
},
- GF_GOB1 | GF_CD,
+ kGameTypeGob1,
+ kFeaturesCD,
"intro"
},
{
@@ -1070,7 +1581,8 @@ static const GOBGameDescription fallbackDescs[] = {
kPlatformPC,
Common::ADGF_NO_FLAGS
},
- GF_GOB2,
+ kGameTypeGob2,
+ kFeaturesAdlib,
"intro"
},
{
@@ -1082,7 +1594,8 @@ static const GOBGameDescription fallbackDescs[] = {
kPlatformPC,
Common::ADGF_NO_FLAGS
},
- GF_GOB2 | GF_CD,
+ kGameTypeGob2,
+ kFeaturesCD,
"intro"
},
{
@@ -1094,7 +1607,8 @@ static const GOBGameDescription fallbackDescs[] = {
kPlatformPC,
Common::ADGF_NO_FLAGS
},
- GF_BARGON,
+ kGameTypeBargon,
+ kFeaturesNone,
"intro"
},
{
@@ -1106,7 +1620,8 @@ static const GOBGameDescription fallbackDescs[] = {
kPlatformPC,
Common::ADGF_NO_FLAGS
},
- GF_GOB3,
+ kGameTypeGob3,
+ kFeaturesAdlib,
"intro"
},
{
@@ -1118,7 +1633,21 @@ static const GOBGameDescription fallbackDescs[] = {
kPlatformPC,
Common::ADGF_NO_FLAGS
},
- GF_GOB3 | GF_CD,
+ kGameTypeGob3,
+ kFeaturesCD,
+ "intro"
+ },
+ {
+ {
+ "woodruff",
+ "unknown",
+ AD_ENTRY1(0, 0),
+ UNK_LANG,
+ kPlatformPC,
+ Common::ADGF_NO_FLAGS
+ },
+ kGameTypeWoodruff,
+ kFeatures640,
"intro"
},
};
@@ -1132,6 +1661,7 @@ static const ADFileBasedFallback fileBased[] = {
{ &fallbackDescs[4], { "intro.stk", "scaa.imd", "scba.imd", "scbf.imd", 0 } },
{ &fallbackDescs[5], { "intro.stk", "imd.itk", 0 } },
{ &fallbackDescs[6], { "intro.stk", "mus_gob3.lic", 0 } },
+ { &fallbackDescs[7], { "intro.stk", "woodruff.itk", 0 } },
{ 0, { 0 } }
};
@@ -1186,6 +1716,7 @@ bool GobEngine::detectGame() {
strcat(_startTot0, "0.tot");
}
+ _gameType = gd->gameType;
_features = gd->features;
_language = gd->desc.language;
_platform = gd->desc.platform;
diff --git a/engines/gob/draw.cpp b/engines/gob/draw.cpp
index bc5b205bd1..acf4d5765b 100644
--- a/engines/gob/draw.cpp
+++ b/engines/gob/draw.cpp
@@ -33,6 +33,7 @@
#include "gob/game.h"
#include "gob/inter.h"
#include "gob/video.h"
+#include "gob/palanim.h"
namespace Gob {
@@ -411,4 +412,88 @@ void Draw::forceBlit(bool backwards) {
0, 0, 0);
}
+const int16 Draw::_wobbleTable[360] = {
+ 0x0000, 0x011D, 0x023B, 0x0359, 0x0476, 0x0593, 0x06B0, 0x07CC, 0x08E8,
+ 0x0A03, 0x0B1D, 0x0C36, 0x0D4E, 0x0E65, 0x0F7B, 0x1090, 0x11A4, 0x12B6,
+ 0x13C6, 0x14D6, 0x15E3, 0x16EF, 0x17F9, 0x1901, 0x1A07, 0x1B0C, 0x1C0E,
+ 0x1D0E, 0x1E0B, 0x1F07, 0x2000, 0x20F6, 0x21EA, 0x22DB, 0x23C9, 0x24B5,
+ 0x259E, 0x2684, 0x2766, 0x2846, 0x2923, 0x29FC, 0x2AD3, 0x2BA5, 0x2C75,
+ 0x2D41, 0x2E09, 0x2ECE, 0x2F8F, 0x304D, 0x3106, 0x31BC, 0x326E, 0x331C,
+ 0x33C6, 0x346C, 0x350E, 0x35AC, 0x3646, 0x36DB, 0x376C, 0x37F9, 0x3882,
+ 0x3906, 0x3985, 0x3A00, 0x3A77, 0x3AE9, 0x3B56, 0x3BBF, 0x3C23, 0x3C83,
+ 0x3CDE, 0x3D34, 0x3D85, 0x3DD1, 0x3E19, 0x3E5C, 0x3E99, 0x3ED2, 0x3F07,
+ 0x3F36, 0x3F60, 0x3F85, 0x3FA6, 0x3FC1, 0x3FD8, 0x3FE9, 0x3FF6, 0x3FFD,
+ 0x4000, 0x3FFD, 0x3FF6, 0x3FE9, 0x3FD8, 0x3FC1, 0x3FA6, 0x3F85, 0x3F60,
+ 0x3F36, 0x3F07, 0x3ED2, 0x3E99, 0x3E5C, 0x3E19, 0x3DD1, 0x3D85, 0x3D34,
+ 0x3CDE, 0x3C83, 0x3C23, 0x3BBF, 0x3B56, 0x3AE9, 0x3A77, 0x3A00, 0x3985,
+ 0x3906, 0x3882, 0x37F9, 0x376C, 0x36DB, 0x3646, 0x35AC, 0x350E, 0x346C,
+ 0x33C6, 0x331C, 0x326E, 0x31BC, 0x3106, 0x304D, 0x2F8F, 0x2ECE, 0x2E09,
+ 0x2D41, 0x2C75, 0x2BA5, 0x2AD3, 0x29FC, 0x2923, 0x2846, 0x2766, 0x2684,
+ 0x259E, 0x24B5, 0x23C9, 0x22DB, 0x21EA, 0x20F6, 0x1FFF, 0x1F07, 0x1E0B,
+ 0x1D0E, 0x1C0E, 0x1B0C, 0x1A07, 0x1901, 0x17F9, 0x16EF, 0x15E3, 0x14D6,
+ 0x13C6, 0x12B6, 0x11A4, 0x1090, 0x0F7B, 0x0E65, 0x0D4E, 0x0C36, 0x0B1D,
+ 0x0A03, 0x08E8, 0x07CC, 0x06B0, 0x0593, 0x0476, 0x0359, 0x023B, 0x011D
+ -0x0000, -0x011D, -0x023B, -0x0359, -0x0476, -0x0593, -0x06B0, -0x07CC, -0x08E8,
+ -0x0A03, -0x0B1D, -0x0C36, -0x0D4E, -0x0E65, -0x0F7B, -0x1090, -0x11A4, -0x12B6,
+ -0x13C6, -0x14D6, -0x15E3, -0x16EF, -0x17F9, -0x1901, -0x1A07, -0x1B0C, -0x1C0E,
+ -0x1D0E, -0x1E0B, -0x1F07, -0x2000, -0x20F6, -0x21EA, -0x22DB, -0x23C9, -0x24B5,
+ -0x259E, -0x2684, -0x2766, -0x2846, -0x2923, -0x29FC, -0x2AD3, -0x2BA5, -0x2C75,
+ -0x2D41, -0x2E09, -0x2ECE, -0x2F8F, -0x304D, -0x3106, -0x31BC, -0x326E, -0x331C,
+ -0x33C6, -0x346C, -0x350E, -0x35AC, -0x3646, -0x36DB, -0x376C, -0x37F9, -0x3882,
+ -0x3906, -0x3985, -0x3A00, -0x3A77, -0x3AE9, -0x3B56, -0x3BBF, -0x3C23, -0x3C83,
+ -0x3CDE, -0x3D34, -0x3D85, -0x3DD1, -0x3E19, -0x3E5C, -0x3E99, -0x3ED2, -0x3F07,
+ -0x3F36, -0x3F60, -0x3F85, -0x3FA6, -0x3FC1, -0x3FD8, -0x3FE9, -0x3FF6, -0x3FFD,
+ -0x4000, -0x3FFD, -0x3FF6, -0x3FE9, -0x3FD8, -0x3FC1, -0x3FA6, -0x3F85, -0x3F60,
+ -0x3F36, -0x3F07, -0x3ED2, -0x3E99, -0x3E5C, -0x3E19, -0x3DD1, -0x3D85, -0x3D34,
+ -0x3CDE, -0x3C83, -0x3C23, -0x3BBF, -0x3B56, -0x3AE9, -0x3A77, -0x3A00, -0x3985,
+ -0x3906, -0x3882, -0x37F9, -0x376C, -0x36DB, -0x3646, -0x35AC, -0x350E, -0x346C,
+ -0x33C6, -0x331C, -0x326E, -0x31BC, -0x3106, -0x304D, -0x2F8F, -0x2ECE, -0x2E09,
+ -0x2D41, -0x2C75, -0x2BA5, -0x2AD3, -0x29FC, -0x2923, -0x2846, -0x2766, -0x2684,
+ -0x259E, -0x24B5, -0x23C9, -0x22DB, -0x21EA, -0x20F6, -0x1FFF, -0x1F07, -0x1E0B,
+ -0x1D0E, -0x1C0E, -0x1B0C, -0x1A07, -0x1901, -0x17F9, -0x16EF, -0x15E3, -0x14D6,
+ -0x13C6, -0x12B6, -0x11A4, -0x1090, -0x0F7B, -0x0E65, -0x0D4E, -0x0C36, -0x0B1D,
+ -0x0A03, -0x08E8, -0x07CC, -0x06B0, -0x0593, -0x0476, -0x0359, -0x023B, -0x011D
+};
+
+void Draw::wobble(SurfaceDesc *surfDesc) {
+ int16 amplitude = 32;
+ uint16 curFrame = 0;
+ uint16 frameWobble = 0;
+ uint16 rowWobble = 0;
+ int8 *offsets = new int8[_vm->_height];
+
+ _vm->_palAnim->fade(_vm->_global->_pPaletteDesc, 0, -1);
+
+ while (amplitude > 0) {
+ rowWobble = frameWobble;
+ frameWobble = (frameWobble + 20) % 360;
+
+ for (uint16 y = 0; y < _vm->_height; y++) {
+ offsets[y] = amplitude +
+ ((_wobbleTable[rowWobble] * amplitude) / 0x4000);
+
+ rowWobble = (rowWobble + 20) % 360;
+ }
+
+ if (curFrame++ & 16)
+ amplitude--;
+
+ for (uint16 y = 0; y < _vm->_height; y++)
+ _vm->_video->drawSprite(surfDesc, _frontSurface,
+ 0, y, _vm->_width - 1, y, offsets[y], y, 0);
+
+ _vm->_palAnim->fadeStep(0);
+ _vm->_video->waitRetrace();
+ }
+
+ _vm->_video->drawSprite(surfDesc, _frontSurface,
+ 0, 0, _vm->_width - 1, _vm->_height - 1, 0, 0, 0);
+
+ _applyPal = false;
+ _invalidatedCount = 0;
+ _noInvalidated = true;
+
+ delete[] offsets;
+}
+
} // End of namespace Gob
diff --git a/engines/gob/draw.h b/engines/gob/draw.h
index e37ecda334..4bf59856be 100644
--- a/engines/gob/draw.h
+++ b/engines/gob/draw.h
@@ -32,13 +32,15 @@ namespace Gob {
#define SPRITES_COUNT 50
-#define RENDERFLAG_NOINVALIDATE 0x001
-#define RENDERFLAG_CAPTUREPUSH 0x002
-#define RENDERFLAG_COLLISIONS 0x004
-#define RENDERFLAG_CAPTUREPOP 0x008
-#define RENDERFLAG_USEDELTAS 0x010
-#define RENDERFLAG_NOBLITINVALIDATED 0x200
-#define RENDERFLAG_SKIPOPTIONALTEXT 0x400
+#define RENDERFLAG_NOINVALIDATE 0x0001
+#define RENDERFLAG_CAPTUREPUSH 0x0002
+#define RENDERFLAG_COLLISIONS 0x0004
+#define RENDERFLAG_CAPTUREPOP 0x0008
+#define RENDERFLAG_USEDELTAS 0x0010
+#define RENDERFLAG_NOBLITINVALIDATED 0x0200
+#define RENDERFLAG_SKIPOPTIONALTEXT 0x0400
+#define RENDERFLAG_FROMSPLIT 0x0800
+#define RENDERFLAG_DOUBLECOORDS 0x1000
class Draw {
public:
@@ -151,6 +153,9 @@ public:
int32 getSpriteRectSize(int16 index);
void forceBlit(bool backwards = false);
+ static const int16 _wobbleTable[360];
+ void wobble(SurfaceDesc *surfDesc);
+
virtual void initScreen() = 0;
virtual void closeScreen() = 0;
virtual void blitCursor() = 0;
diff --git a/engines/gob/draw_v2.cpp b/engines/gob/draw_v2.cpp
index c45bd0de27..55585f5619 100644
--- a/engines/gob/draw_v2.cpp
+++ b/engines/gob/draw_v2.cpp
@@ -197,7 +197,12 @@ void Draw_v2::printTotText(int16 id) {
int16 rectLeft, rectTop, rectRight, rectBottom;
int16 size;
- if (!_vm->_game->_totTextData || !_vm->_game->_totTextData->dataPtr)
+ id &= 0xFFF;
+
+ if (!_vm->_game->_totTextData || !_vm->_game->_totTextData->dataPtr ||
+ (id >= _vm->_game->_totTextData->itemsCount) ||
+ (_vm->_game->_totTextData->items[id].offset == -1) ||
+ (_vm->_game->_totTextData->items[id].size == 0))
return;
_vm->validateLanguage();
@@ -210,10 +215,34 @@ void Draw_v2::printTotText(int16 id) {
if ((_renderFlags & RENDERFLAG_SKIPOPTIONALTEXT) && (ptr[1] & 0x80))
return;
- destX = READ_LE_UINT16(ptr) & 0x7FFF;
- destY = READ_LE_UINT16(ptr + 2);
- spriteRight = READ_LE_UINT16(ptr + 4);
- spriteBottom = READ_LE_UINT16(ptr + 6);
+ if (_renderFlags & RENDERFLAG_DOUBLECOORDS) {
+ destX = (READ_LE_UINT16(ptr) & 0x7FFF) * 2;
+ spriteRight = READ_LE_UINT16(ptr + 4) * 2 + 1;
+ } else {
+ destX = READ_LE_UINT16(ptr) & 0x7FFF;
+ spriteRight = READ_LE_UINT16(ptr + 4);
+ }
+
+ if (_renderFlags & RENDERFLAG_FROMSPLIT) {
+ destY = _vm->_video->_splitHeight1;
+ spriteBottom = READ_LE_UINT16(ptr + 6) - READ_LE_UINT16(ptr + 2);
+ if (_renderFlags & RENDERFLAG_DOUBLECOORDS)
+ spriteBottom *= 3;
+ spriteBottom += _vm->_video->_splitHeight1;
+ if (_renderFlags & RENDERFLAG_DOUBLECOORDS) {
+ spriteBottom += _backDeltaX;
+ destY += _backDeltaX;
+ }
+ } else {
+ if (_renderFlags & RENDERFLAG_DOUBLECOORDS) {
+ destY = READ_LE_UINT16(ptr + 2) * 2;
+ spriteBottom = READ_LE_UINT16(ptr + 6) * 2;
+ } else {
+ destY = READ_LE_UINT16(ptr + 2);
+ spriteBottom = READ_LE_UINT16(ptr + 6);
+ }
+ }
+
ptr += 8;
if (_renderFlags & RENDERFLAG_CAPTUREPUSH) {
diff --git a/engines/gob/game.cpp b/engines/gob/game.cpp
index 795484ef0e..37817c12a3 100644
--- a/engines/gob/game.cpp
+++ b/engines/gob/game.cpp
@@ -140,8 +140,18 @@ byte *Game::loadExtData(int16 itemId, int16 *pResWidth,
size = item->size;
isPacked = (item->width & 0x8000) != 0;
- if (pResWidth != 0) {
+ if ((pResWidth != 0) && (pResHeight != 0)) {
*pResWidth = item->width & 0x7FFF;
+
+ if (*pResWidth & 0x4000)
+ size += 1 << 16;
+ if (*pResWidth & 0x2000)
+ size += 2 << 16;
+ if (*pResWidth & 0x1000)
+ size += 4 << 16;
+
+ *pResWidth &= 0xFFF;
+
*pResHeight = item->height;
debugC(7, kDebugFileIO, "loadExtData(%d, %d, %d)",
itemId, *pResWidth, *pResHeight);
@@ -164,8 +174,10 @@ byte *Game::loadExtData(int16 itemId, int16 *pResWidth,
} else
handle = _extHandle;
+ DataStream *stream = _vm->_dataIO->openAsStream(handle);
+
debugC(7, kDebugFileIO, "off: %d size: %d", offset, tableSize);
- _vm->_dataIO->seekData(handle, offset + tableSize, SEEK_SET);
+ stream->seek(offset + tableSize);
realSize = size;
if (isPacked)
dataBuf = new byte[size + 2];
@@ -175,11 +187,13 @@ byte *Game::loadExtData(int16 itemId, int16 *pResWidth,
dataPtr = dataBuf;
while (size > 32000) {
// BUG: huge->far conversion. Need normalization?
- _vm->_dataIO->readData(handle, dataPtr, 32000);
+ stream->read(dataPtr, 32000);
size -= 32000;
dataPtr += 32000;
}
- _vm->_dataIO->readData(handle, dataPtr, size);
+ stream->read(dataPtr, size);
+
+ delete stream;
if (commonHandle != -1) {
_vm->_dataIO->closeData(commonHandle);
_extHandle = _vm->_dataIO->openData(_curExtFile);
@@ -315,11 +329,12 @@ void Game::evaluateScroll(int16 x, int16 y) {
}
int16 cursorRight = x + _vm->_draw->_cursorWidth;
- int16 screenRight = _vm->_draw->_scrollOffsetX + 320;
+ int16 screenRight = _vm->_draw->_scrollOffsetX + _vm->_width;
int16 cursorBottom = y + _vm->_draw->_cursorHeight;
- int16 screenBottom = _vm->_draw->_scrollOffsetY + 200;
+ int16 screenBottom = _vm->_draw->_scrollOffsetY + _vm->_height;
- if ((cursorRight >= 320) && (screenRight < _vm->_video->_surfWidth)) {
+ if ((cursorRight >= _vm->_width) &&
+ (screenRight < _vm->_video->_surfWidth)) {
uint16 off;
off = MIN(_vm->_draw->_cursorWidth,
@@ -328,8 +343,8 @@ void Game::evaluateScroll(int16 x, int16 y) {
_vm->_draw->_scrollOffsetX += off;
- _vm->_util->setMousePos(320 - _vm->_draw->_cursorWidth, y);
- } else if ((cursorBottom >= (200 - _vm->_video->_splitHeight2)) &&
+ _vm->_util->setMousePos(_vm->_width - _vm->_draw->_cursorWidth, y);
+ } else if ((cursorBottom >= (_vm->_height - _vm->_video->_splitHeight2)) &&
(screenBottom < _vm->_video->_surfHeight)) {
uint16 off;
@@ -339,7 +354,7 @@ void Game::evaluateScroll(int16 x, int16 y) {
_vm->_draw->_scrollOffsetY += off;
- _vm->_util->setMousePos(x, 200 - _vm->_video->_splitHeight2 -
+ _vm->_util->setMousePos(x, _vm->_height - _vm->_video->_splitHeight2 -
_vm->_draw->_cursorHeight);
}
@@ -368,10 +383,12 @@ int16 Game::checkKeys(int16 *pMouseX, int16 *pMouseY,
_vm->_inter->_soundEndTimeKey = 0;
}
- _vm->_util->getMouseState(pMouseX, pMouseY, pButtons);
+ if (pMouseX && pMouseY && pButtons) {
+ _vm->_util->getMouseState(pMouseX, pMouseY, pButtons);
- if (*pButtons == 3)
- *pButtons = 0;
+ if (*pButtons == 3)
+ *pButtons = 0;
+ }
return _vm->_util->checkKey();
}
@@ -408,23 +425,26 @@ void Game::loadExtTable(void) {
if (_extHandle < 0)
return;
- count = _vm->_dataIO->readUint16(_extHandle);
+ DataStream *stream = _vm->_dataIO->openAsStream(_extHandle);
+ count = stream->readUint16LE();
- _vm->_dataIO->seekData(_extHandle, 0, SEEK_SET);
+ stream->seek(0);
_extTable = new ExtTable;
_extTable->items = 0;
if (count)
_extTable->items = new ExtItem[count];
- _extTable->itemsCount = _vm->_dataIO->readUint16(_extHandle);
- _extTable->unknown = _vm->_dataIO->readByte(_extHandle);
+ _extTable->itemsCount = stream->readUint16LE();
+ _extTable->unknown = stream->readByte();
for (int i = 0; i < count; i++) {
- _extTable->items[i].offset = _vm->_dataIO->readUint32(_extHandle);
- _extTable->items[i].size = _vm->_dataIO->readUint16(_extHandle);
- _extTable->items[i].width = _vm->_dataIO->readUint16(_extHandle);
- _extTable->items[i].height = _vm->_dataIO->readUint16(_extHandle);
+ _extTable->items[i].offset = stream->readUint32LE();
+ _extTable->items[i].size = stream->readUint16LE();
+ _extTable->items[i].width = stream->readUint16LE();
+ _extTable->items[i].height = stream->readUint16LE();
}
+
+ delete stream;
}
void Game::loadImFile(void) {
@@ -544,7 +564,7 @@ void Game::switchTotSub(int16 index, int16 skipPlay) {
int16 newPos = _curBackupPos - index - ((index >= 0) ? 1 : 0);
// WORKAROUND: Some versions don't make the MOVEMENT menu item unselectable
// in the dreamland screen, resulting in a crash when it's clicked.
- if ((_vm->_features & GF_GOB2) && (index == -1) && (skipPlay == 7) &&
+ if ((_vm->getGameType() == kGameTypeGob2) && (index == -1) && (skipPlay == 7) &&
!scumm_stricmp(_curTotFileArray[newPos], "gob06.tot"))
return;
@@ -652,7 +672,7 @@ int16 Game::openLocTextFile(char *locTextFile, int language) {
return _vm->_dataIO->openData(locTextFile);
}
-byte *Game::loadLocTexts(void) {
+byte *Game::loadLocTexts(int32 *dataSize) {
char locTextFile[20];
int16 handle;
int i;
@@ -661,23 +681,48 @@ byte *Game::loadLocTexts(void) {
handle = openLocTextFile(locTextFile, _vm->_global->_languageWanted);
if (handle >= 0) {
+
_foundTotLoc = true;
_vm->_global->_language = _vm->_global->_languageWanted;
- }
- else if (!_foundTotLoc) {
- for (i = 0; i < 10; i++) {
- handle = openLocTextFile(locTextFile, i);
+
+ } else if (!_foundTotLoc) {
+ bool found = false;
+
+ if (_vm->_global->_languageWanted == 2) {
+ handle = openLocTextFile(locTextFile, 5);
+ if (handle >= 0) {
+ _vm->_global->_language = 5;
+ found = true;
+ }
+ } else if (_vm->_global->_languageWanted == 5) {
+ handle = openLocTextFile(locTextFile, 2);
if (handle >= 0) {
- _vm->_global->_language = i;
- break;
+ _vm->_global->_language = 2;
+ found = true;
+ }
+ }
+
+ if (!found) {
+ for (i = 0; i < 10; i++) {
+ handle = openLocTextFile(locTextFile, i);
+ if (handle >= 0) {
+ _vm->_global->_language = i;
+ break;
+ }
}
}
+
}
+
debugC(1, kDebugFileIO, "Using language %d for %s",
_vm->_global->_language, _curTotFile);
if (handle >= 0) {
_vm->_dataIO->closeData(handle);
+
+ if (dataSize)
+ *dataSize = _vm->_dataIO->getDataSize(locTextFile);
+
return _vm->_dataIO->getData(locTextFile);
}
return 0;
diff --git a/engines/gob/game.h b/engines/gob/game.h
index 2181d219f2..c83497eaeb 100644
--- a/engines/gob/game.h
+++ b/engines/gob/game.h
@@ -147,11 +147,14 @@ public:
void evaluateScroll(int16 x, int16 y);
- int16 checkKeys(int16 *pMousex, int16 *pMouseY, int16 *pButtons, char handleMouse);
+ int16 checkKeys(int16 *pMousex = 0, int16 *pMouseY = 0,
+ int16 *pButtons = 0, char handleMouse = 0);
void start(void);
void totSub(int8 flags, const char *newTotFile);
void switchTotSub(int16 index, int16 skipPlay);
+ void freeCollision(int16 id);
+
virtual void playTot(int16 skipPlay) = 0;
virtual void clearCollisions(void) = 0;
@@ -215,13 +218,12 @@ protected:
int16 adjustKey(int16 key);
- byte *loadLocTexts(void);
+ byte *loadLocTexts(int32 *dataSize = 0);
int32 loadTotFile(const char *path);
void loadExtTable(void);
void loadImFile(void);
void setCollisions(void);
- void freeCollision(int16 id);
void collSub(uint16 offset);
void collAreaSub(int16 index, int8 enter);
int16 openLocTextFile(char *locTextFile, int language);
diff --git a/engines/gob/game_v1.cpp b/engines/gob/game_v1.cpp
index 6ba68553c7..9c18ec1151 100644
--- a/engines/gob/game_v1.cpp
+++ b/engines/gob/game_v1.cpp
@@ -911,7 +911,8 @@ void Game_v1::collisionsBlock(void) {
_shouldPushColls = 0;
_vm->_global->_inter_execPtr = savedIP;
deltaTime = timeVal -
- (_vm->_util->getTimeKey() - timeKey);
+ ((_vm->_util->getTimeKey() - timeKey)
+ - _vm->_video->_lastRetraceLength);
if (deltaTime < 2)
deltaTime = 2;
diff --git a/engines/gob/game_v2.cpp b/engines/gob/game_v2.cpp
index 245c1f4544..7e87b9e8f8 100644
--- a/engines/gob/game_v2.cpp
+++ b/engines/gob/game_v2.cpp
@@ -1,27 +1,27 @@
-/* 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$
- *
- */
+ /* 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/endian.h"
@@ -34,13 +34,13 @@
#include "gob/dataio.h"
#include "gob/draw.h"
#include "gob/goblin.h"
-#include "gob/imd.h"
#include "gob/inter.h"
#include "gob/mult.h"
#include "gob/parse.h"
#include "gob/scenery.h"
#include "gob/sound.h"
#include "gob/video.h"
+#include "gob/videoplayer.h"
namespace Gob {
@@ -101,6 +101,7 @@ void Game_v2::playTot(int16 skipPlay) {
_extTable = 0;
_extHandle = -1;
+ _vm->_draw->_cursorHotspotXVar = -1;
_totToLoad[0] = 0;
if ((_curTotFile[0] == 0) && (_totFileData == 0))
@@ -134,12 +135,16 @@ void Game_v2::playTot(int16 skipPlay) {
totTextLoc = false;
if (READ_LE_UINT32(filePtr) != (uint32) -1) {
_totTextData = new TotTextTable;
+
+ int32 size;
+
if (READ_LE_UINT32(filePtr) == 0) {
- _totTextData->dataPtr = loadLocTexts();
+ _totTextData->dataPtr = loadLocTexts(&size);
totTextLoc = true;
} else {
_totTextData->dataPtr =
(_totFileData + READ_LE_UINT32(_totFileData + 0x30));
+ size = totSize;
_vm->_global->_language = _vm->_global->_languageWanted;
}
@@ -147,7 +152,7 @@ void Game_v2::playTot(int16 skipPlay) {
if (_totTextData->dataPtr != 0) {
Common::MemoryReadStream totTextData(_totTextData->dataPtr,
4294967295U);
- _totTextData->itemsCount = totTextData.readSint16LE();
+ _totTextData->itemsCount = totTextData.readSint16LE() & 0x3FFF;
_totTextData->items = new TotTextItem[_totTextData->itemsCount];
for (int i = 0; i < _totTextData->itemsCount; ++i) {
@@ -267,7 +272,7 @@ void Game_v2::playTot(int16 skipPlay) {
_vm->_snd->freeSample(_soundSamples[i]);
}
- _vm->_imdPlayer->closeImd();
+ _vm->_vidPlayer->closeVideo();
if (_totToLoad[0] == 0)
break;
diff --git a/engines/gob/global.cpp b/engines/gob/global.cpp
index ec2fa6b043..f3bc0611fd 100644
--- a/engines/gob/global.cpp
+++ b/engines/gob/global.cpp
@@ -112,7 +112,7 @@ Global::Global(GobEngine *vm) : _vm(vm) {
_setAllPalette = false;
_dontSetPalette = false;
- _primarySurfDesc = new SurfaceDesc(0x13, 320, 200);
+ _primarySurfDesc = 0;
_debugFlag = 0;
_inVM = 0;
diff --git a/engines/gob/gob.cpp b/engines/gob/gob.cpp
index 32caca31d8..d9385b1b0f 100644
--- a/engines/gob/gob.cpp
+++ b/engines/gob/gob.cpp
@@ -48,7 +48,7 @@
#include "gob/parse.h"
#include "gob/scenery.h"
#include "gob/music.h"
-#include "gob/imd.h"
+#include "gob/videoplayer.h"
#include "gob/saveload.h"
namespace Gob {
@@ -68,6 +68,16 @@ const Common::Language GobEngine::_gobToScummVMLang[] = {
};
GobEngine::GobEngine(OSystem *syst) : Engine(syst) {
+ _vm = this;
+
+ _snd = 0; _adlib = 0; _mult = 0;
+ _game = 0; _global = 0; _cdrom = 0;
+ _dataIO = 0; _goblin = 0; _vidPlayer = 0;
+ _init = 0; _inter = 0; _map = 0;
+ _palAnim = 0; _parse = 0; _scenery = 0;
+ _draw = 0; _util = 0; _video = 0;
+ _saveLoad = 0;
+
// Setup mixer
if (!_mixer->isReady()) {
warning("Sound initialization failed.");
@@ -94,25 +104,7 @@ GobEngine::~GobEngine() {
// Stop all mixer streams (except for the permanent ones).
_vm->_mixer->stopAll();
- delete _snd;
- delete _adlib;
- delete _mult;
- delete _game;
- delete _global;
- delete _cdrom;
- delete _dataIO;
- delete _goblin;
- delete _imdPlayer;
- delete _init;
- delete _inter;
- delete _map;
- delete _palAnim;
- delete _parse;
- delete _scenery;
- delete _draw;
- delete _util;
- delete _video;
- delete _saveLoad;
+ deinitGameParts();
delete[] _startTot;
delete[] _startTot0;
}
@@ -129,15 +121,23 @@ void GobEngine::shutdown() {
void GobEngine::validateLanguage() {
if (_vm->_global->_languageWanted != _vm->_global->_language) {
- warning("Your game version doesn't support the requested language");
- warning("Using the first language available: %s",
- getLangDesc(_vm->_global->_language));
+ warning("Your game version doesn't support the requested language %s",
+ getLangDesc(_vm->_global->_languageWanted));
+
+ if (((_vm->_global->_languageWanted == 2) && (_vm->_global->_language == 5)) ||
+ ((_vm->_global->_languageWanted == 5) && (_vm->_global->_language == 2)))
+ warning("Using %s instead", getLangDesc(_vm->_global->_language));
+ else
+ warning("Using the first language available: %s",
+ getLangDesc(_vm->_global->_language));
+
_vm->_global->_languageWanted = _vm->_global->_language;
}
}
void GobEngine::validateVideoMode(int16 videoMode) {
- if ((videoMode != 0x13) && (videoMode != 0x14))
+ if ((videoMode != 0x10) && (videoMode != 0x13) &&
+ (videoMode != 0x14) && (videoMode != 0x18))
error("Video mode 0x%X is not supported!", videoMode);
}
@@ -148,82 +148,18 @@ int GobEngine::init() {
return -1;
}
- _adlib = 0;
- _saveLoad = 0;
- _global = new Global(this);
- _util = new Util(this);
- _dataIO = new DataIO(this);
- _palAnim = new PalAnim(this);
- _imdPlayer = new ImdPlayer(this);
- _cdrom = new CDROM(this);
- _snd = new Snd(this);
- if (_features & Gob::GF_GOB1) {
- _init = new Init_v1(this);
- _video = new Video_v1(this);
- _inter = new Inter_v1(this);
- _parse = new Parse_v1(this);
- _mult = new Mult_v1(this);
- _draw = new Draw_v1(this);
- _game = new Game_v1(this);
- _map = new Map_v1(this);
- _goblin = new Goblin_v1(this);
- _scenery = new Scenery_v1(this);
- } else if (_features & Gob::GF_GOB2) {
- _init = new Init_v2(this);
- _video = new Video_v2(this);
- _inter = new Inter_v2(this);
- _parse = new Parse_v2(this);
- _mult = new Mult_v2(this);
- _draw = new Draw_v2(this);
- _game = new Game_v2(this);
- _map = new Map_v2(this);
- _goblin = new Goblin_v2(this);
- _scenery = new Scenery_v2(this);
- _saveLoad = new SaveLoad_v2(this, _targetName.c_str());
- } else if (_features & Gob::GF_BARGON) {
- _init = new Init_v2(this);
- _video = new Video_v2(this);
- _inter = new Inter_Bargon(this);
- _parse = new Parse_v2(this);
- _mult = new Mult_v2(this);
- _draw = new Draw_Bargon(this);
- _game = new Game_v2(this);
- _map = new Map_v2(this);
- _goblin = new Goblin_v2(this);
- _scenery = new Scenery_v2(this);
- _saveLoad = new SaveLoad_v2(this, _targetName.c_str());
- } else if (_features & Gob::GF_GOB3) {
- _init = new Init_v3(this);
- _video = new Video_v2(this);
- _inter = new Inter_v3(this);
- _parse = new Parse_v2(this);
- _mult = new Mult_v2(this);
- _draw = new Draw_v2(this);
- _game = new Game_v2(this);
- _map = new Map_v2(this);
- _goblin = new Goblin_v3(this);
- _scenery = new Scenery_v2(this);
- _saveLoad = new SaveLoad_v3(this, _targetName.c_str());
- } else
- error("GobEngine::init(): Unknown version of game engine");
-
- _noMusic = MidiDriver::parseMusicDriver(ConfMan.get("music_driver")) == MD_NULL;
- if (!_noMusic && !(_platform == Common::kPlatformAmiga) &&
- !(_platform == Common::kPlatformAtariST) &&
- (((_platform == Common::kPlatformMacintosh) && (_features & Gob::GF_GOB1)) ||
- (_features & Gob::GF_GOB2) || (_features & Gob::GF_GOB3)))
- _adlib = new Adlib(this);
- _vm = this;
-
- _map->init();
+ if (!initGameParts()) {
+ GUIErrorMessage("GobEngine::init(): Unknown version of game engine");
+ return -1;
+ }
_system->beginGFXTransaction();
- initCommonGFX(false);
- _system->initSize(320, 200);
+ _system->initSize(_width, _height);
+ initCommonGFX(is640());
_system->endGFXTransaction();
// On some systems it's not safe to run CD audio games from the CD.
- if (_features & GF_CD)
+ if (isCD())
checkCD();
int cd_num = ConfMan.getInt("cdrom");
@@ -293,4 +229,167 @@ int GobEngine::init() {
return 0;
}
+bool GobEngine::initGameParts() {
+ _adlib = 0;
+ _saveLoad = 0;
+
+ _global = new Global(this);
+ _util = new Util(this);
+ _dataIO = new DataIO(this);
+ _palAnim = new PalAnim(this);
+ _vidPlayer = new VideoPlayer(this);
+ _cdrom = new CDROM(this);
+ _snd = new Snd(this);
+
+ switch (_gameType) {
+ case kGameTypeGob1:
+ _init = new Init_v1(this);
+ _video = new Video_v1(this);
+ _inter = new Inter_v1(this);
+ _parse = new Parse_v1(this);
+ _mult = new Mult_v1(this);
+ _draw = new Draw_v1(this);
+ _game = new Game_v1(this);
+ _map = new Map_v1(this);
+ _goblin = new Goblin_v1(this);
+ _scenery = new Scenery_v1(this);
+ break;
+
+ case kGameTypeGob2:
+ _init = new Init_v2(this);
+ _video = new Video_v2(this);
+ _inter = new Inter_v2(this);
+ _parse = new Parse_v2(this);
+ _mult = new Mult_v2(this);
+ _draw = new Draw_v2(this);
+ _game = new Game_v2(this);
+ _map = new Map_v2(this);
+ _goblin = new Goblin_v2(this);
+ _scenery = new Scenery_v2(this);
+ _saveLoad = new SaveLoad_v2(this, _targetName.c_str());
+ break;
+
+ case kGameTypeBargon:
+ _init = new Init_v2(this);
+ _video = new Video_v2(this);
+ _inter = new Inter_Bargon(this);
+ _parse = new Parse_v2(this);
+ _mult = new Mult_v2(this);
+ _draw = new Draw_Bargon(this);
+ _game = new Game_v2(this);
+ _map = new Map_v2(this);
+ _goblin = new Goblin_v2(this);
+ _scenery = new Scenery_v2(this);
+ _saveLoad = new SaveLoad_v2(this, _targetName.c_str());
+ break;
+
+ case kGameTypeWeen:
+ _init = new Init_v2(this);
+ _video = new Video_v2(this);
+ _inter = new Inter_v2(this);
+ _parse = new Parse_v2(this);
+ _mult = new Mult_v2(this);
+ _draw = new Draw_v2(this);
+ _game = new Game_v2(this);
+ _map = new Map_v2(this);
+ _goblin = new Goblin_v2(this);
+ _scenery = new Scenery_v2(this);
+ _saveLoad = new SaveLoad_v2(this, _targetName.c_str());
+ break;
+
+ case kGameTypeGob3:
+ _init = new Init_v3(this);
+ _video = new Video_v2(this);
+ _inter = new Inter_v3(this);
+ _parse = new Parse_v2(this);
+ _mult = new Mult_v2(this);
+ _draw = new Draw_v2(this);
+ _game = new Game_v2(this);
+ _map = new Map_v2(this);
+ _goblin = new Goblin_v3(this);
+ _scenery = new Scenery_v2(this);
+ _saveLoad = new SaveLoad_v3(this, _targetName.c_str());
+ break;
+
+ case kGameTypeLostInTime:
+ _init = new Init_v3(this);
+ _video = new Video_v2(this);
+ _inter = new Inter_v3(this);
+ _parse = new Parse_v2(this);
+ _mult = new Mult_v2(this);
+ _draw = new Draw_v2(this);
+ _game = new Game_v2(this);
+ _map = new Map_v2(this);
+ _goblin = new Goblin_v3(this);
+ _scenery = new Scenery_v2(this);
+ _saveLoad = new SaveLoad_v3(this, _targetName.c_str(), 4768, 0, 50);
+ break;
+
+ case kGameTypeWoodruff:
+ _init = new Init_v3(this);
+ _video = new Video_v2(this);
+ _inter = new Inter_v4(this);
+ _parse = new Parse_v2(this);
+ _mult = new Mult_v2(this);
+ _draw = new Draw_v2(this);
+ _game = new Game_v2(this);
+ _map = new Map_v2(this);
+ _goblin = new Goblin_v3(this);
+ _scenery = new Scenery_v2(this);
+ _saveLoad = new SaveLoad_v3(this, _targetName.c_str());
+ break;
+
+ default:
+ deinitGameParts();
+ return false;
+ break;
+ }
+
+ _noMusic = MidiDriver::parseMusicDriver(ConfMan.get("music_driver")) == MD_NULL;
+ if (!_noMusic && hasAdlib())
+ _adlib = new Adlib(this);
+
+ _map->init();
+
+ if (is640()) {
+ _video->_surfWidth = _width = 640;
+ _video->_surfHeight = _video->_splitHeight1 = _height = 480;
+ _global->_mouseMaxCol = 640;
+ _global->_mouseMaxRow = 480;
+ _mode = 0x18;
+ _global->_primarySurfDesc = new SurfaceDesc(0x18, 640, 480);
+ } else {
+ _video->_surfWidth = _width = 320;
+ _video->_surfHeight = _video->_splitHeight1 = _height = 200;
+ _global->_mouseMaxCol = 320;
+ _global->_mouseMaxRow = 200;
+ _mode = 0x14;
+ _global->_primarySurfDesc = new SurfaceDesc(0x14, 320, 200);
+ }
+
+ return true;
+}
+
+void GobEngine::deinitGameParts() {
+ delete _snd; _snd = 0;
+ delete _adlib; _adlib = 0;
+ delete _mult; _mult = 0;
+ delete _game; _game = 0;
+ delete _global; _global = 0;
+ delete _cdrom; _cdrom = 0;
+ delete _dataIO; _dataIO = 0;
+ delete _goblin; _goblin = 0;
+ delete _vidPlayer; _vidPlayer = 0;
+ delete _init; _init = 0;
+ delete _inter; _inter = 0;
+ delete _map; _map = 0;
+ delete _palAnim; _palAnim = 0;
+ delete _parse; _parse = 0;
+ delete _scenery; _scenery = 0;
+ delete _draw; _draw = 0;
+ delete _util; _util = 0;
+ delete _video; _video = 0;
+ delete _saveLoad; _saveLoad = 0;
+}
+
} // End of namespace Gob
diff --git a/engines/gob/gob.h b/engines/gob/gob.h
index 97ee312bff..d573dc3a89 100644
--- a/engines/gob/gob.h
+++ b/engines/gob/gob.h
@@ -42,7 +42,7 @@ class Draw;
class CDROM;
class DataIO;
class Goblin;
-class ImdPlayer;
+class VideoPlayer;
class Init;
class Inter;
class Map;
@@ -78,14 +78,23 @@ class Adlib;
#define VAR(var) READ_VAR_UINT32(var)
#define VAR_ADDRESS(var) ((uint32 *) VARP((var) << 2))
-enum {
- GF_GOB1 = 1 << 0,
- GF_GOB2 = 1 << 1,
- GF_GOB3 = 1 << 2,
- GF_WOODRUFF = 1 << 3,
- GF_BARGON = 1 << 4,
- GF_CD = 1 << 5,
- GF_EGA = 1 << 6
+enum GameType {
+ kGameTypeNone = 0,
+ kGameTypeGob1,
+ kGameTypeGob2,
+ kGameTypeGob3,
+ kGameTypeWoodruff,
+ kGameTypeBargon,
+ kGameTypeWeen,
+ kGameTypeLostInTime
+};
+
+enum Features {
+ kFeaturesNone = 0,
+ kFeaturesCD = 1 << 0,
+ kFeaturesEGA = 1 << 1,
+ kFeaturesAdlib = 1 << 2,
+ kFeatures640 = 1 << 3
};
enum {
@@ -165,6 +174,9 @@ protected:
int go();
int init();
+ bool initGameParts();
+ void deinitGameParts();
+
bool detectGame();
public:
@@ -172,9 +184,15 @@ public:
Common::RandomSource _rnd;
+ GameType _gameType;
int32 _features;
Common::Language _language;
Common::Platform _platform;
+
+ uint16 _width;
+ uint16 _height;
+ uint8 _mode;
+
char *_startTot;
char *_startTot0;
bool _copyProtection;
@@ -199,7 +217,7 @@ public:
Inter *_inter;
SaveLoad *_saveLoad;
Adlib *_adlib;
- ImdPlayer *_imdPlayer;
+ VideoPlayer *_vidPlayer;
void shutdown();
@@ -211,6 +229,12 @@ public:
void validateLanguage();
void validateVideoMode(int16 videoMode);
+ GameType getGameType() { return _gameType; }
+ bool isCD() { return (_features & kFeaturesCD) != 0; }
+ bool isEGA() { return (_features & kFeaturesEGA) != 0; }
+ bool is640() { return (_features & kFeatures640) != 0; }
+ bool hasAdlib() { return (_features & kFeaturesAdlib) != 0; }
+
GobEngine(OSystem *syst);
virtual ~GobEngine();
};
diff --git a/engines/gob/goblin.cpp b/engines/gob/goblin.cpp
index 418b31e2ee..1db741bd44 100644
--- a/engines/gob/goblin.cpp
+++ b/engines/gob/goblin.cpp
@@ -1698,6 +1698,9 @@ void Goblin::playSounds(Mult::Mult_Object *obj) {
int16 sndSlot;
int16 frame;
+ if (!obj->goblinStates)
+ return;
+
animData = obj->pAnimData;
for (int i = 1; i <= obj->goblinStates[animData->state][0].dataCount; i++) {
diff --git a/engines/gob/goblin_v2.cpp b/engines/gob/goblin_v2.cpp
index 67e9f65444..608b0f0790 100644
--- a/engines/gob/goblin_v2.cpp
+++ b/engines/gob/goblin_v2.cpp
@@ -314,6 +314,9 @@ void Goblin_v2::moveAdvance(Mult::Mult_Object *obj, Gob_Object *gobDesc,
int16 state;
int16 layer;
+ if (!obj->goblinStates)
+ return;
+
movePathFind(obj, 0, 0);
playSounds(obj);
diff --git a/engines/gob/goblin_v3.cpp b/engines/gob/goblin_v3.cpp
index 002ef7b749..f4aa872fa1 100644
--- a/engines/gob/goblin_v3.cpp
+++ b/engines/gob/goblin_v3.cpp
@@ -115,6 +115,9 @@ void Goblin_v3::placeObject(Gob_Object *objDesc, char animated,
Mult::Mult_Object &obj = _vm->_mult->_objects[index];
Mult::Mult_AnimData &objAnim = *(obj.pAnimData);
+ if (!obj.goblinStates)
+ return;
+
if ((state != -1) && (obj.goblinStates[state] != 0)) {
if (state == 8)
objAnim.curLookDir = 0;
diff --git a/engines/gob/imd.cpp b/engines/gob/imd.cpp
deleted file mode 100644
index 395fb01f9b..0000000000
--- a/engines/gob/imd.cpp
+++ /dev/null
@@ -1,1249 +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/endian.h"
-
-#include "gob/gob.h"
-#include "gob/imd.h"
-#include "gob/global.h"
-#include "gob/util.h"
-#include "gob/dataio.h"
-#include "gob/draw.h"
-#include "gob/game.h"
-#include "gob/inter.h"
-#include "gob/palanim.h"
-#include "gob/sound.h"
-#include "gob/video.h"
-
-namespace Gob {
-
-ImdPlayer::ImdPlayer(GobEngine *vm) : _vm(vm) {
- _curImd = 0;
- _curFile[0] = 0;
-
- _curX = 0;
- _curY = 0;
- _left = 0;
- _top = 0;
- _right = 0;
- _bottom = 0;
-
- _frameData = 0;
- _vidBuffer = 0;
-
- _frontSurf = 21;
- _backSurf = 21;
- _frontMem = 0;
- _frameDelay = 0;
-
- _noSound = true;
-
- _soundStartTime = 0;
- _skipFrames = 0;
-
- _soundFreq = 0;
- _soundSliceSize = 0;
- _soundSlicesCount = 0;
-
- _soundSliceLength = 0;
- _soundStage = 0;
-
- _audioStream = 0;
-}
-
-ImdPlayer::~ImdPlayer() {
- if (_curImd) {
- delete[] _curImd->palette;
- delete[] _curImd->framesPos;
- delete[] _curImd->frameCoords;
- delete[] _curImd->extraPalette;
- }
- delete[] _frameData;
- delete[] _vidBuffer;
- delete[] _frontMem;
- delete _curImd;
-}
-
-// flag bits: 0 = read and set palette
-// 1 = read palette
-ImdPlayer::Imd *ImdPlayer::loadImdFile(const char *path, SurfaceDesc *surfDesc, int8 flags) {
- Imd *imdPtr;
- int16 handle;
- char buf[18];
- uint32 framesPosPos = 0;
- uint32 framesCordsPos = 0;
-
- strncpy0(buf, path, 17);
- if (!strchr(buf, '.')) {
- buf[13] = 0;
- strcat(buf, ".IMD");
- }
-
- handle = _vm->_dataIO->openData(buf);
-
- if (handle < 0) {
- warning("Can't open IMD \"%s\"", buf);
- return 0;
- }
-
- imdPtr = new Imd;
- assert(imdPtr);
- memset(imdPtr, 0, sizeof(Imd));
-
- imdPtr->handle = _vm->_dataIO->readUint16(handle);
- imdPtr->verMin = _vm->_dataIO->readUint16(handle);
- imdPtr->framesCount = _vm->_dataIO->readUint16(handle);
- imdPtr->x = _vm->_dataIO->readUint16(handle);
- imdPtr->y = _vm->_dataIO->readUint16(handle);
- imdPtr->width = _vm->_dataIO->readUint16(handle);
- imdPtr->height = _vm->_dataIO->readUint16(handle);
- imdPtr->field_E = _vm->_dataIO->readUint16(handle);
- imdPtr->curFrame = _vm->_dataIO->readUint16(handle);
-
- if ((imdPtr->handle != 0) || ((imdPtr->verMin & 0xFF) < 2)) {
- warning("%s: Version incorrect (%d,%X)", buf, imdPtr->handle, imdPtr->verMin);
- _vm->_dataIO->closeData(handle);
- delete imdPtr;
- return 0;
- }
-
- imdPtr->handle = handle;
- imdPtr->surfDesc = surfDesc;
- imdPtr->firstFramePos = imdPtr->curFrame;
- imdPtr->curFrame = 0;
-
- if ((imdPtr->verMin & 0x800) && ((flags & 3) != 3))
- imdPtr->extraPalette = new Video::Color[256];
-
- if (flags & 3) {
- imdPtr->palette = new Video::Color[256];
- assert(imdPtr->palette);
- _vm->_dataIO->readData(handle, (byte *) imdPtr->palette, 768);
- } else
- _vm->_dataIO->seekData(handle, 768, SEEK_CUR);
-
- if ((flags & 3) == 1)
- _vm->_video->setPalette(imdPtr->palette);
-
- if ((imdPtr->verMin & 0xFF) >= 3) {
- imdPtr->stdX = _vm->_dataIO->readUint16(handle);
- if (imdPtr->stdX > 1) {
- warning("%s: More than one standard coordinate quad found (%d)",
- buf, imdPtr->stdX);
- finishImd(imdPtr);
- return 0;
- }
- if (imdPtr->stdX != 0) {
- imdPtr->stdX = _vm->_dataIO->readUint16(handle);
- imdPtr->stdY = _vm->_dataIO->readUint16(handle);
- imdPtr->stdWidth = _vm->_dataIO->readUint16(handle);
- imdPtr->stdHeight = _vm->_dataIO->readUint16(handle);
- } else
- imdPtr->stdX = -1;
- } else
- imdPtr->stdX = -1;
-
- if ((imdPtr->verMin & 0xFF) >= 4) {
- framesPosPos = _vm->_dataIO->readUint32(handle);
- if (framesPosPos != 0) {
- imdPtr->framesPos = new int32[imdPtr->framesCount];
- assert(imdPtr->framesPos);
- }
- }
-
- if (imdPtr->verMin & 0x8000)
- framesCordsPos = _vm->_dataIO->readUint32(handle);
-
- _noSound = true;
- _soundStage = 0;
- if (imdPtr->verMin & 0x4000) {
- _soundFreq = _vm->_dataIO->readUint16(handle);
- _soundSliceSize = _vm->_dataIO->readUint16(handle);
- _soundSlicesCount = _vm->_dataIO->readUint16(handle);
-
- if (_soundFreq < 0)
- _soundFreq = -_soundFreq;
-
- if (_soundSlicesCount < 0)
- _soundSlicesCount = -_soundSlicesCount - 1;
-
- if (_soundSlicesCount > 40) {
- warning("%s: More than 40 sound slices found (%d)",
- buf, _soundSlicesCount);
- finishImd(imdPtr);
- return 0;
- }
-
- _soundSliceLength = 1000 / (_soundFreq / _soundSliceSize);
-
- _soundStage = 1;
- _noSound = false;
-
- _audioStream = Audio::makeAppendableAudioStream(_soundFreq, 0);
- }
-
- if (imdPtr->verMin & 0x2000) {
- imdPtr->frameDataSize = _vm->_dataIO->readUint16(handle);
- if (imdPtr->frameDataSize == 0) {
- imdPtr->frameDataSize = _vm->_dataIO->readUint32(handle);
- imdPtr->vidBufferSize = _vm->_dataIO->readUint32(handle);
- } else
- imdPtr->vidBufferSize = _vm->_dataIO->readUint16(handle);
- } else {
- imdPtr->frameDataSize = imdPtr->width * imdPtr->height + 500;
- if (!(imdPtr->field_E & 0x100) || (imdPtr->field_E & 0x1000))
- imdPtr->vidBufferSize = imdPtr->frameDataSize;
- }
-
- if (imdPtr->framesPos) {
- _vm->_dataIO->seekData(handle, framesPosPos, SEEK_SET);
- for (int i = 0; i < imdPtr->framesCount; i++)
- imdPtr->framesPos[i] = _vm->_dataIO->readUint32(handle);
- }
-
- if (imdPtr->verMin & 0x8000) {
- _vm->_dataIO->seekData(handle, framesCordsPos, SEEK_SET);
- imdPtr->frameCoords = new ImdCoord[imdPtr->framesCount];
- assert(imdPtr->frameCoords);
- for (int i = 0; i < imdPtr->framesCount; i++) {
- imdPtr->frameCoords[i].left = _vm->_dataIO->readUint16(handle);
- imdPtr->frameCoords[i].top = _vm->_dataIO->readUint16(handle);
- imdPtr->frameCoords[i].right = _vm->_dataIO->readUint16(handle);
- imdPtr->frameCoords[i].bottom = _vm->_dataIO->readUint16(handle);
- }
- }
-
- _vm->_dataIO->seekData(handle, imdPtr->firstFramePos, SEEK_SET);
- return imdPtr;
-}
-
-void ImdPlayer::finishImd(ImdPlayer::Imd *&imdPtr) {
- if (!imdPtr)
- return;
-
- if (_soundStage == 2)
- _vm->_snd->stopSound(0);
-
- _vm->_dataIO->closeData(imdPtr->handle);
-
- delete[] imdPtr->frameCoords;
- delete[] imdPtr->palette;
- delete[] imdPtr->framesPos;
- delete[] imdPtr->extraPalette;
-
- delete imdPtr;
-
- if (_audioStream) {
- _audioStream->finish();
- _vm->_mixer->stopHandle(_audioHandle);
- _audioStream = 0;
- }
-}
-
-int8 ImdPlayer::openImd(const char *path, int16 x, int16 y,
- int16 startFrame, int16 flags) {
- const char *src;
- byte *vidMem;
- SurfaceDesc *surfDesc;
-
- if (!_curImd)
- _curFile[0] = 0;
-
- src = strrchr(path, '\\');
- src = !src ? path : src + 1;
-
- if ((path[0] != 0) && scumm_stricmp(_curFile, src)) {
- closeImd();
-
- _curImd = loadImdFile(path, 0, 3);
- if (!_curImd)
- return 0;
-
- _curX = _curImd->x;
- _curY = _curImd->y;
- strncpy0(_curFile, src, 17);
-
- delete[] _frameData;
- _frameData = new byte[_curImd->frameDataSize + 500];
- assert(_frameData);
- memset(_frameData, 0, _curImd->frameDataSize + 500);
-
- delete[] _vidBuffer;
- _vidBuffer = new byte[_curImd->vidBufferSize + 500];
- assert(_vidBuffer);
- memset(_vidBuffer, 0, _curImd->vidBufferSize + 500);
-
- if (!(flags & 0x100)) {
-
- if (_vm->_global->_videoMode == 0x14) {
-
- _backSurf = (flags & 0x80) ? 20 : 21;
- if (!(_curImd->field_E & 0x100) || (_curImd->field_E & 0x2000)) {
- setXY(_curImd, 0, 0);
- _curImd->surfDesc =
- _vm->_video->initSurfDesc(0x13,
- _curImd->width, _curImd->height, 0);
- } else {
- _curImd->surfDesc = _vm->_draw->_spritesArray[_frontSurf];
- if ((x != -1) || (y != -1)) {
- _curX = x != -1 ? x : _curX;
- _curY = y != -1 ? y : _curY;
- setXY(_curImd, _curX, _curY);
- }
- }
-
- if (flags & 0x40) {
- _curX = x != -1 ? x : _curX;
- _curY = y != -1 ? y : _curY;
- if (_curImd->surfDesc->_vidMode == 0x14) {
- surfDesc = _vm->_video->initSurfDesc(0x13,
- _curImd->width, _curImd->height, 0);
- _vm->_video->drawSprite(_vm->_draw->_spritesArray[21],
- surfDesc, _curX, _curY,
- _curX + _curImd->width - 1, _curY + _curImd->height - 1,
- 0, 0, 0);
-
- vidMem = _curImd->surfDesc->getVidMem();
- for (int i = 0; i < _curImd->height; i++)
- for (int j = 0; j < _curImd->width; j++, vidMem++) {
- *(vidMem) = *(surfDesc->getVidMem() +
- (j / 4) + (surfDesc->getWidth() / 4 * i));
- }
- surfDesc = 0;
- }
- }
-
- } else {
- if ((x != -1) || (y != -1)) {
- _curX = (x != -1) ? x : _curX;
- _curY = (y != -1) ? y : _curY;
- setXY(_curImd, _curX, _curY);
- }
- _backSurf = (flags & 0x80) ? 20 : 21;
- _curImd->surfDesc = _vm->_draw->_spritesArray[_backSurf];
- }
-
- }
- }
-
- if (!_curImd)
- return 0;
-
- if (startFrame == -1) {
- closeImd();
- return 0;
- }
-
- _curX = (x != -1) ? x : _curX;
- _curY = (y != -1) ? y : _curY;
-
- WRITE_VAR(7, _curImd->framesCount);
-
- return 1;
-}
-
-void ImdPlayer::closeImd(void) {
- finishImd(_curImd);
-
- delete[] _frameData;
- delete[] _vidBuffer;
- _frameData = 0;
- _vidBuffer = 0;
-
- _curImd = 0;
-}
-
-void ImdPlayer::setXY(ImdPlayer::Imd *imdPtr, int16 x, int16 y) {
- int i;
-
- if (imdPtr->stdX != -1) {
- imdPtr->stdX = imdPtr->stdX - imdPtr->x + x;
- imdPtr->stdY = imdPtr->stdY - imdPtr->y + y;
- }
-
- if (imdPtr->frameCoords) {
- for (i = 0; i < imdPtr->framesCount; i++) {
- if (imdPtr->frameCoords[i].left != -1) {
- imdPtr->frameCoords[i].left =
- imdPtr->frameCoords[i].left - imdPtr->x + x;
- imdPtr->frameCoords[i].top =
- imdPtr->frameCoords[i].top - imdPtr->y + y;
- imdPtr->frameCoords[i].right =
- imdPtr->frameCoords[i].right - imdPtr->x + x;
- imdPtr->frameCoords[i].bottom =
- imdPtr->frameCoords[i].bottom - imdPtr->y + y;
- }
- }
- }
-
- imdPtr->x = x;
- imdPtr->y = y;
-}
-
-void ImdPlayer::drawFrame(Imd *imdPtr, int16 frame, int16 x, int16 y,
- SurfaceDesc *dest) {
- if (!dest)
- dest = _vm->_draw->_frontSurface;
-
- if (frame == 0)
- _vm->_video->drawSprite(imdPtr->surfDesc, dest, 0, 0,
- imdPtr->width - 1, imdPtr->height - 1, x, y, 0);
- else if (imdPtr->frameCoords && (imdPtr->frameCoords[frame].left != -1))
- _vm->_video->drawSprite(imdPtr->surfDesc, dest,
- imdPtr->frameCoords[frame].left, imdPtr->frameCoords[frame].top,
- imdPtr->frameCoords[frame].right, imdPtr->frameCoords[frame].bottom,
- imdPtr->frameCoords[frame].left + x,
- imdPtr->frameCoords[frame].top + y, 0);
- else if (imdPtr->stdX != -1)
- _vm->_video->drawSprite(imdPtr->surfDesc, dest,
- imdPtr->stdX, imdPtr->stdY, imdPtr->stdX + imdPtr->stdWidth - 1,
- imdPtr->stdY + imdPtr->stdHeight - 1, x + imdPtr->stdX,
- y + imdPtr->stdY, 0);
- else
- _vm->_video->drawSprite(imdPtr->surfDesc, dest, 0, 0,
- imdPtr->width - 1, imdPtr->height - 1, x, y, 0);
-}
-
-void ImdPlayer::renderFrame(Imd *imdPtr) {
- int16 imdX, imdY;
- int16 imdW, imdH;
- int16 sW;
- uint16 pixCount, pixWritten;
- uint8 type;
- byte *imdVidMem;
- byte *imdVidMemBak;
- byte *dataPtr = 0;
- byte *srcPtr = 0;
-
- dataPtr = _frameData;
- imdX = imdPtr->x;
- imdY = imdPtr->y;
- imdW = imdPtr->width;
- imdH = imdPtr->height;
- sW = imdPtr->surfDesc->getWidth();
- imdVidMem = imdPtr->surfDesc->getVidMem() + sW * imdY + imdX;
-
- type = *dataPtr++;
- srcPtr = dataPtr;
-
- if (type & 0x10) { // Palette data
- type ^= 0x10;
- dataPtr += 49;
- }
-
- srcPtr = dataPtr;
- if (type & 0x80) { // Frame data is compressed
- srcPtr = _vidBuffer;
- type &= 0x7F;
- if ((type == 2) && (imdW == sW)) {
- frameUncompressor(imdVidMem, dataPtr);
- return;
- } else
- frameUncompressor(srcPtr, dataPtr);
- }
-
- if (type == 2) { // Whole block
- for (int i = 0; i < imdH; i++) {
- memcpy(imdVidMem, srcPtr, imdW);
- srcPtr += imdW;
- imdVidMem += sW;
- }
- } else if (type == 1) { // Sparse block
- imdVidMemBak = imdVidMem;
- for (int i = 0; i < imdH; i++) {
- pixWritten = 0;
- while (pixWritten < imdW) {
- pixCount = *srcPtr++;
- if (pixCount & 0x80) { // data
- pixCount = MIN((pixCount & 0x7F) + 1, imdW - pixWritten);
- memcpy(imdVidMem, srcPtr, pixCount);
-
- pixWritten += pixCount;
- imdVidMem += pixCount;
- srcPtr += pixCount;
- } else { // "hole"
- pixCount = (pixCount + 1) % 256;
- pixWritten += pixCount;
- imdVidMem += pixCount;
- }
- }
- imdVidMemBak += sW;
- imdVidMem = imdVidMemBak;
- }
- } else if (type == 0x42) { // Whole quarter-wide block
- for (int i = 0; i < imdH; i++) {
- imdVidMemBak = imdVidMem;
-
- for (int j = 0; j < imdW; j += 4, imdVidMem += 4, srcPtr++)
- memset(imdVidMem, *srcPtr, 4);
-
- imdVidMemBak += sW;
- imdVidMem = imdVidMemBak;
- }
- } else if ((type & 0xF) == 2) { // Whole half-high block
- for (; imdH > 1; imdH -= 2, imdVidMem += sW + sW, srcPtr += imdW) {
- memcpy(imdVidMem, srcPtr, imdW);
- memcpy(imdVidMem + sW, srcPtr, imdW);
- }
- if (imdH == -1)
- memcpy(imdVidMem, srcPtr, imdW);
- } else { // Sparse half-high block
- imdVidMemBak = imdVidMem;
- for (int i = 0; i < imdH; i += 2) {
- pixWritten = 0;
- while (pixWritten < imdW) {
- pixCount = *srcPtr++;
- if (pixCount & 0x80) { // data
- pixCount = MIN((pixCount & 0x7F) + 1, imdW - pixWritten);
- memcpy(imdVidMem, srcPtr, pixCount);
- memcpy(imdVidMem + sW, srcPtr, pixCount);
-
- pixWritten += pixCount;
- imdVidMem += pixCount;
- srcPtr += pixCount;
- } else { // "hole"
- pixCount = (pixCount + 1) % 256;
- pixWritten += pixCount;
- imdVidMem += pixCount;
- }
- }
- imdVidMemBak += sW + sW;
- imdVidMem = imdVidMemBak;
- }
- }
-}
-
-void ImdPlayer::frameUncompressor(byte *dest, byte *src) {
- int i;
- byte buf[4370];
- uint16 chunkLength;
- uint16 frameLength;
- uint16 bufPos1;
- uint16 bufPos2;
- uint16 tmp;
- uint8 chunkBitField;
- uint8 chunkCount;
- bool mode;
-
- frameLength = READ_LE_UINT16(src);
- src += 4;
-
- if ((READ_LE_UINT16(src) == 0x1234) && (READ_LE_UINT16(src + 2) == 0x5678)) {
- src += 4;
- bufPos1 = 273;
- mode = 1; // 123Ch (cmp al, 12h)
- } else {
- bufPos1 = 4078;
- mode = 0; // 275h (jnz +2)
- }
-
- memset(buf, 32, bufPos1);
- chunkCount = 1;
- chunkBitField = 0;
-
- while (frameLength > 0) {
- chunkCount--;
- if (chunkCount == 0) {
- tmp = *src++;
- chunkCount = 8;
- chunkBitField = tmp;
- }
- if (chunkBitField % 2) {
- chunkBitField >>= 1;
- buf[bufPos1] = *src;
- *dest++ = *src++;
- bufPos1 = (bufPos1 + 1) % 4096;
- frameLength--;
- continue;
- }
- chunkBitField >>= 1;
-
- tmp = READ_LE_UINT16(src);
- src += 2;
- chunkLength = ((tmp & 0xF00) >> 8) + 3;
-
- if ((mode && ((chunkLength & 0xFF) == 0x12)) ||
- (!mode && (chunkLength == 0)))
- chunkLength = *src++ + 0x12;
-
- bufPos2 = (tmp & 0xFF) + ((tmp >> 4) & 0x0F00);
- if (((tmp + chunkLength) >= 4096) ||
- ((chunkLength + bufPos1) >= 4096)) {
-
- for (i = 0; i < chunkLength; i++, dest++) {
- *dest = buf[bufPos2];
- buf[bufPos1] = buf[bufPos2];
- bufPos1 = (bufPos1 + 1) % 4096;
- bufPos2 = (bufPos2 + 1) % 4096;
- }
-
- } else if (((tmp + chunkLength) < bufPos1) ||
- ((chunkLength + bufPos1) < bufPos2)) {
-
- memcpy(dest, buf + bufPos2, chunkLength);
- memmove(buf + bufPos1, buf + bufPos2, chunkLength);
-
- dest += chunkLength;
- bufPos1 += chunkLength;
- bufPos2 += chunkLength;
-
- } else {
-
- for (i = 0; i < chunkLength; i++, dest++, bufPos1++, bufPos2++) {
- *dest = buf[bufPos2];
- buf[bufPos1] = buf[bufPos2];
- }
-
- }
- frameLength -= chunkLength;
-
- }
-}
-
-void ImdPlayer::play(const char *path, int16 x, int16 y, bool interruptible) {
- int16 mouseX;
- int16 mouseY;
- int16 buttons;
-
- _vm->_util->setFrameRate(12);
- if (!openImd(path, x, y, 0, 2))
- return;
-
- _vm->_video->fillRect(_vm->_draw->_frontSurface, x, y,
- x + _curImd->width - 1, y + _curImd->height - 1, 0);
-
- for (int i = 0; i < _curImd->framesCount; i++) {
- play(i, 4, 0, 255, 0, _curImd->framesCount - 1);
-
- if (_vm->_quitRequested || (interruptible &&
- (_vm->_game->checkKeys(&mouseX, &mouseY, &buttons, 0) == 0x11B)))
- break;
- }
-
- closeImd();
-}
-
-void ImdPlayer::play(const char *path, int16 x, int16 y, int16 startFrame,
- int16 frames, bool fade, bool interruptible) {
- int16 mouseX;
- int16 mouseY;
- int16 buttons = 0;
- int endFrame;
-
- _vm->_util->setFrameRate(12);
- if (!openImd(path, x, y, 0, 0))
- return;
-
- _vm->_video->fillRect(_vm->_draw->_frontSurface, x, y,
- x + _curImd->width - 1, y + _curImd->height - 1, 0);
-
- if (fade)
- _vm->_palAnim->fade(0, -2, 0);
-
- endFrame = frames > 0 ? frames : _curImd->framesCount;
- for (int i = startFrame; i < endFrame; i++) {
- view(_curImd, i);
- drawFrame(_curImd, i, x, y);
- if (fade) {
- _vm->_palAnim->fade(_vm->_global->_pPaletteDesc, -2, 0);
- fade = false;
- }
- _vm->_video->waitRetrace();
-
- if (_vm->_quitRequested || (interruptible &&
- (_vm->_game->checkKeys(&mouseX, &mouseY, &buttons, 0) == 0x11B))) {
- _vm->_palAnim->fade(0, -2, 0);
- _vm->_video->clearSurf(_vm->_draw->_frontSurface);
- memset((char *) _vm->_draw->_vgaPalette, 0, 768);
-
- WRITE_VAR(4, buttons);
- WRITE_VAR(0, 0x11B);
- WRITE_VAR(57, (uint32) -1);
- break;
- }
-
- _vm->_util->waitEndFrame();
- }
-
- if (frames < 0) {
- endFrame = _curImd->framesCount + frames;
- for (int i = _curImd->framesCount - 1; i >= endFrame; i--) {
- seekFrame(_curImd, i, SEEK_SET, true);
- drawFrame(_curImd, i, x, y);
- _vm->_video->waitRetrace();
-
- if (_vm->_quitRequested || (interruptible &&
- (_vm->_game->checkKeys(&mouseX, &mouseY, &buttons, 0) == 0x11B))) {
- _vm->_palAnim->fade(0, -2, 0);
- _vm->_video->clearSurf(_vm->_draw->_frontSurface);
- memset((char *) _vm->_draw->_vgaPalette, 0, 768);
-
- WRITE_VAR(4, buttons);
- WRITE_VAR(0, 0x11B);
- WRITE_VAR(57, (uint32) -1);
- break;
- }
-
- _vm->_util->waitEndFrame();
- }
- }
-
- closeImd();
-}
-
-void ImdPlayer::play(int16 frame, uint16 palCmd,
- int16 palStart, int16 palEnd, int16 palFrame, int16 lastFrame) {
- uint32 viewRet = 0;
- SurfaceDesc *surfDescBak;
- bool modifiedPal = false;
-
- _vm->_draw->_showCursor = 0;
-
- if ((frame < 0) || (frame > lastFrame))
- return;
-
- palCmd &= 0x3F;
- if ((frame == palFrame) || ((frame == lastFrame) && (palCmd == 8))) {
- modifiedPal = true;
- _vm->_draw->_applyPal = true;
-
- if (palCmd >= 4)
- copyPalette(palStart, palEnd);
- }
-
- if (modifiedPal && (palCmd == 8) && (_backSurf == 20))
- _vm->_video->setFullPalette(_vm->_global->_pPaletteDesc);
-
- if (_curImd->surfDesc) {
- if (_curImd->surfDesc->_vidMode == 0x14) {
-
- if ((_frontMem == _vm->_draw->_frontSurface->getVidMem()) &&
- (_frontSurf == 20)) {
- _vm->_draw->_frontSurface->swap(_vm->_draw->_backSurface);
- viewRet = view(_curImd, frame);
- _vm->_draw->_frontSurface->swap(_vm->_draw->_backSurface);
- } else
- viewRet = view(_curImd, frame);
-
- if (_frontSurf == 21)
- _vm->_draw->invalidateRect(_left, _top, _right, _bottom);
-
- } else {
- if ((_curImd->field_E & 0x100) &&
- (_vm->_global->_videoMode == 0x14) &&
- (_frontSurf == 20) &&
- (checkFrameType(_curImd, frame) & 0x8000) &&
- (_backSurf == 21)) {
-
- surfDescBak = _curImd->surfDesc;
- if (_frontMem == _vm->_draw->_spritesArray[20]->getVidMem())
- _curImd->surfDesc = _vm->_draw->_spritesArray[21];
- else
- _curImd->surfDesc = _vm->_draw->_spritesArray[20];
- setXY(_curImd, _curX, _curY);
- viewRet = view(_curImd, frame);
- _curImd->surfDesc = surfDescBak;
- setXY(_curImd, 0, 0);
-
- } else {
- viewRet = view(_curImd, frame);
- if (!(viewRet & 0x800))
- drawFrame(frame);
- }
- }
- } else
- viewRet = view(_curImd, frame);
-
- if (modifiedPal && (palCmd == 16)) {
- if (_backSurf == 21)
- _vm->_draw->forceBlit();
- _vm->_palAnim->fade(_vm->_global->_pPaletteDesc, -2, 0);
- _vm->_draw->_noInvalidated = true;
- }
-
- if (viewRet & 0x10) {
- copyPalette(palStart, palEnd);
-
- if (_backSurf == 20)
- _vm->_video->setFullPalette(_vm->_global->_pPaletteDesc);
- else
- _vm->_draw->_applyPal = true;
- }
-
- if (modifiedPal && (palCmd == 8) && (_backSurf == 21))
- _vm->_video->setFullPalette(_vm->_global->_pPaletteDesc);
-
- if (!(viewRet & 0x800)) {
- if (_vm->_draw->_cursorIndex == -1) {
- if (_frontSurf == 20)
- flipFrontMem();
- else
- _vm->_draw->blitInvalidated();
- } else
- _vm->_draw->animateCursor(-1);
- }
-
- if (modifiedPal && ((palCmd == 2) || (palCmd == 4)))
- _vm->_palAnim->fade(_vm->_global->_pPaletteDesc, -2, 0);
-
- // To allow quitting, etc. during IMDs
- _vm->_util->processInput();
- if (_vm->_quitRequested)
- return;
-
- if (_soundStage != 2) {
- if (viewRet & 0x800) {
- if (_frameDelay == 0)
- _vm->_util->delay(30);
- else {
- _frameDelay -= 30;
- if (_frameDelay < 0)
- _frameDelay = 0;
- }
- } else
- _vm->_util->waitEndFrame();
- }
-
- _vm->_inter->animPalette();
-}
-
-inline void ImdPlayer::drawFrame(int16 frame) {
- if (_backSurf == 21) {
-
- if (_vm->_global->_videoMode == 0x14) {
- if (_frontSurf == 21) {
- _vm->_draw->_frontSurface->swap(_vm->_draw->_spritesArray[21]);
- drawFrame(_curImd, frame, _curX, _curY);
- _vm->_draw->_frontSurface->swap(_vm->_draw->_spritesArray[21]);
- _vm->_draw->invalidateRect(_curX + _left, _curY + _top,
- _curX + _right, _curY + _bottom);
- } else {
- if (_frontMem == _vm->_draw->_spritesArray[20]->getVidMem()) {
- _vm->_draw->_frontSurface->swap(_vm->_draw->_spritesArray[21]);
- drawFrame(_curImd, frame, _curX, _curY);
- _vm->_draw->_frontSurface->swap(_vm->_draw->_spritesArray[21]);
- } else
- drawFrame(_curImd, frame, _curX, _curY);
- }
- } else
- _vm->_draw->invalidateRect(_left, _top, _right, _bottom);
-
- } else if (_vm->_global->_videoMode == 0x14)
- drawFrame(_curImd, frame, _curX, _curY);
-}
-
-inline void ImdPlayer::copyPalette(int16 palStart, int16 palEnd) {
- if ((palStart == -1) || (palEnd == -1))
- memcpy((char *) _vm->_global->_pPaletteDesc->vgaPal,
- (char *) _curImd->palette, 768);
- else
- memcpy(((char *) (_vm->_global->_pPaletteDesc->vgaPal)) +
- palStart * 3, ((char *) (_curImd->palette)) + palStart * 3,
- (palEnd - palStart + 1) * 3);
-}
-
-inline void ImdPlayer::flipFrontMem() {
- if (_frontMem == _vm->_draw->_frontSurface->getVidMem())
- _frontMem = _vm->_draw->_backSurface->getVidMem();
- else
- _frontMem = _vm->_draw->_frontSurface->getVidMem();
-}
-
-uint16 ImdPlayer::checkFrameType(Imd *imdPtr, int16 frame) {
- uint16 retVal = 0;
- uint32 posBak;
- uint32 tmp;
- uint16 cmd;
- int16 frameBak;
-
- if (!imdPtr)
- return 0x8000;
-
- posBak = _vm->_dataIO->getPos(imdPtr->handle);
- frameBak = imdPtr->curFrame;
-
- if (imdPtr->curFrame != frame) {
- retVal |= 0x2000;
- seekFrame(imdPtr, frame, SEEK_SET);
- }
-
- do {
- if (frame != 0) {
- if (imdPtr->stdX != -1)
- retVal |= 0x1000;
- if (imdPtr->frameCoords && (imdPtr->frameCoords[frame].left != -1))
- retVal |= 0x400;
- }
-
- cmd = _vm->_dataIO->readUint16(imdPtr->handle);
-
- if ((cmd & 0xFFF8) == 0xFFF0) {
- if (cmd == 0xFFF0) {
- _vm->_dataIO->seekData(imdPtr->handle, 2, SEEK_CUR);
- cmd = _vm->_dataIO->readUint16(imdPtr->handle);
- }
-
- if (cmd == 0xFFF1) {
- retVal = 0x8000;
- continue;
- } else if (cmd == 0xFFF2) { // Skip (16 bit)
- cmd = _vm->_dataIO->readUint16(imdPtr->handle);
- _vm->_dataIO->seekData(imdPtr->handle, cmd, SEEK_CUR);
- retVal = 0x8000;
- continue;
- } else if (cmd == 0xFFF3) { // Skip (32 bit)
- tmp = _vm->_dataIO->readUint32(imdPtr->handle);
- _vm->_dataIO->seekData(imdPtr->handle, cmd, SEEK_CUR);
- retVal = 0x8000;
- continue;
- }
- }
-
- // Jump to frame
- if (cmd == 0xFFFD) {
- frame = _vm->_dataIO->readUint16(imdPtr->handle);
- if (imdPtr->framesPos) {
- _vm->_dataIO->seekData(imdPtr->handle,
- imdPtr->framesPos[frame], SEEK_SET);
- retVal |= 0x200;
- continue;
- }
- break;
- }
-
- // Next sound slice data
- if (cmd == 0xFF00) {
- _vm->_dataIO->seekData(imdPtr->handle,
- _soundSliceSize, SEEK_CUR);
- cmd = _vm->_dataIO->readUint16(imdPtr->handle);
- // Initial sound data (all slices)
- } else if (cmd == 0xFF01) {
- _vm->_dataIO->seekData(imdPtr->handle,
- _soundSliceSize * _soundSlicesCount, SEEK_CUR);
- cmd = _vm->_dataIO->readUint16(imdPtr->handle);
- }
-
- // Frame video data
- if (cmd != 0) {
- _vm->_dataIO->readData(imdPtr->handle, _frameData, 5);
- retVal |= _frameData[0];
- } else
- retVal |= 0x800;
-
- break;
-
- } while (true);
-
- _vm->_dataIO->seekData(imdPtr->handle, posBak, SEEK_SET);
- imdPtr->curFrame = frameBak;
- return retVal;
-}
-
-void ImdPlayer::seekFrame(Imd *imdPtr, int16 frame, int16 from, bool restart) {
- uint32 framePos = 0;
-
- if (!imdPtr)
- return;
-
- if (from == SEEK_CUR)
- frame += imdPtr->curFrame;
- else if (from == SEEK_END)
- frame = imdPtr->framesCount - frame - 1;
-
- if (frame >= imdPtr->framesCount)
- return;
-
- if (frame == 0) {
- framePos = imdPtr->firstFramePos;
- } else if (frame == 1) {
- framePos = imdPtr->firstFramePos;
- _vm->_dataIO->seekData(imdPtr->handle, framePos, SEEK_SET);
- framePos += _vm->_dataIO->readUint16(imdPtr->handle) + 4;
- } else if (imdPtr->framesPos) {
- framePos = imdPtr->framesPos[frame];
- } else if (restart && (_soundStage == 0)) {
- for (int i = 0; i <= frame; i++)
- view(_curImd, i);
- } else
- error("%s: Frame %d is not directly accessible", _curFile, frame);
-
- _vm->_dataIO->seekData(imdPtr->handle, framePos, SEEK_SET);
- imdPtr->curFrame = frame;
-}
-
-uint32 ImdPlayer::view(Imd *imdPtr, int16 frame) {
- uint32 retVal = 0;
- uint32 cmd = 0;
- int16 xBak, yBak, heightBak, widthBak;
- bool hasNextCmd = false;
- bool startSound = false;
-
- if (!imdPtr)
- return 0x8000;
-
- if (frame != imdPtr->curFrame) {
- retVal |= 0x2000;
- seekFrame(imdPtr, frame, SEEK_SET);
- }
-
- _left = xBak = imdPtr->x;
- _top = yBak = imdPtr->y;
- _bottom = heightBak= imdPtr->height;
- _right = widthBak = imdPtr->width;
- _right += _left - 1;
- _bottom += _top - 1;
-
- if ((frame == 0) && (imdPtr->verMin & 0x800))
- _vm->_video->setPalette(imdPtr->palette);
-
- do {
- if (frame != 0) {
- if (imdPtr->stdX != -1) {
- _left = imdPtr->x = imdPtr->stdX;
- _top = imdPtr->y = imdPtr->stdY;
- _right = imdPtr->width = imdPtr->stdWidth;
- _bottom = imdPtr->height = imdPtr->stdHeight;
- _right += _left - 1;
- _bottom += _top - 1;
- retVal |= 0x1000;
- }
- if (imdPtr->frameCoords &&
- (imdPtr->frameCoords[frame].left != -1)) {
- _left = imdPtr->x = imdPtr->frameCoords[frame].left;
- _top = imdPtr->y = imdPtr->frameCoords[frame].top;
- _right = imdPtr->width =
- imdPtr->frameCoords[frame].right - imdPtr->x + 1;
- _bottom = imdPtr->height =
- imdPtr->frameCoords[frame].bottom - imdPtr->y + 1;
- _right += _left - 1;
- _bottom += _top - 1;
- retVal |= 0x400;
- }
- }
-
- cmd = _vm->_dataIO->readUint16(imdPtr->handle);
-
- if ((cmd & 0xFFF8) == 0xFFF0) {
- if (cmd == 0xFFF0) {
- _vm->_dataIO->seekData(imdPtr->handle, 2, SEEK_CUR);
- cmd = _vm->_dataIO->readUint16(imdPtr->handle);
- }
-
- if (cmd == 0xFFF1) {
- retVal = 0x8000;
- continue;
- } else if (cmd == 0xFFF2) { // Skip (16 bit)
- cmd = _vm->_dataIO->readUint16(imdPtr->handle);
- _vm->_dataIO->seekData(imdPtr->handle, cmd, SEEK_CUR);
- retVal = 0x8000;
- continue;
- } else if (cmd == 0xFFF3) { // Skip (32 bit)
- cmd = _vm->_dataIO->readUint32(imdPtr->handle);
- _vm->_dataIO->seekData(imdPtr->handle, cmd, SEEK_CUR);
- retVal = 0x8000;
- continue;
- }
- }
-
- if (_soundStage != 0) {
- byte *soundBuf;
-
- if (!hasNextCmd)
- waitEndSoundSlice();
-
- // Next sound slice data
- if (cmd == 0xFF00) {
-
- if (!hasNextCmd && !_noSound) {
- soundBuf = new byte[_soundSliceSize];
- assert(soundBuf);
-
- _vm->_dataIO->readData(imdPtr->handle, soundBuf,
- _soundSliceSize);
- _vm->_snd->convToSigned(soundBuf, _soundSliceSize);
- _audioStream->queueBuffer(soundBuf, _soundSliceSize);
- } else
- _vm->_dataIO->seekData(imdPtr->handle,
- _soundSliceSize, SEEK_CUR);
-
- cmd = _vm->_dataIO->readUint16(imdPtr->handle);
-
- // Initial sound data (all slices)
- } else if (cmd == 0xFF01) {
- int dataLength = _soundSliceSize * _soundSlicesCount;
-
- if (!hasNextCmd && !_noSound) {
- soundBuf = new byte[dataLength];
- assert(soundBuf);
-
- _vm->_dataIO->readData(imdPtr->handle, soundBuf, dataLength);
- _vm->_snd->convToSigned(soundBuf, dataLength);
-
- _soundStage = 1;
- startSound = true;
- _audioStream->queueBuffer(soundBuf, dataLength);
- } else
- _vm->_dataIO->seekData(imdPtr->handle, dataLength, SEEK_CUR);
-
- cmd = _vm->_dataIO->readUint16(imdPtr->handle);
-
- // Empty sound slice
- } else if (!hasNextCmd && (!_noSound)) {
- soundBuf = new byte[_soundSliceSize];
- assert(soundBuf);
-
- memset(soundBuf, 0, _soundSliceSize);
- _audioStream->queueBuffer(soundBuf, _soundSliceSize);
- }
- }
-
- // Set palette
- if (cmd == 0xFFF4) {
- _vm->_dataIO->seekData(imdPtr->handle, 2, SEEK_CUR);
- retVal |= 0x10;
- if (imdPtr->extraPalette) {
- _vm->_dataIO->readData(imdPtr->handle,
- (byte *) imdPtr->extraPalette, 768);
- _vm->_video->setPalette(imdPtr->extraPalette);
- } else if (imdPtr->palette)
- _vm->_dataIO->readData(imdPtr->handle,
- (byte *) imdPtr->palette, 768);
- else
- _vm->_dataIO->readData(imdPtr->handle, _frameData, 768);
-
- cmd = _vm->_dataIO->readUint16(imdPtr->handle);
- }
-
- hasNextCmd = false;
-
- // Jump to frame
- if (cmd == 0xFFFD) {
-
- frame = _vm->_dataIO->readUint16(imdPtr->handle);
- if (imdPtr->framesPos) {
- imdPtr->curFrame = frame;
- _vm->_dataIO->seekData(imdPtr->handle,
- imdPtr->framesPos[frame], SEEK_SET);
-
- hasNextCmd = true;
- retVal |= 0x200;
- }
-
- } else if (cmd == 0xFFFC) {
-
- retVal |= 1;
- cmd = _vm->_dataIO->readUint32(imdPtr->handle);
- _vm->_dataIO->readData(imdPtr->handle, _frameData, cmd + 2);
-
- if (imdPtr->surfDesc) {
- int16 left = imdPtr->x;
- int16 top = imdPtr->y;
- int16 right = imdPtr->width + left;
- int16 bottom = imdPtr->height + top;
-
- if (imdPtr->surfDesc->getWidth() < right) {
- left = 0;
- right = imdPtr->width;
- }
- if (imdPtr->surfDesc->getWidth() < right)
- right = imdPtr->surfDesc->getWidth();
- if (imdPtr->surfDesc->getHeight() < bottom) {
- top = 0;
- bottom = imdPtr->height;
- }
- if (imdPtr->surfDesc->getHeight() < bottom)
- bottom = imdPtr->surfDesc->getHeight();
-
- imdPtr->x = left;
- imdPtr->y = top;
- imdPtr->height = bottom - top;
- imdPtr->width = right - left;
-
- renderFrame(imdPtr);
- }
-
- retVal |= _frameData[0];
-
- // Frame video data
- } else if (cmd != 0) {
-
- _vm->_dataIO->readData(imdPtr->handle, _frameData, cmd + 2);
- if (imdPtr->surfDesc)
- renderFrame(imdPtr);
-
- retVal |= _frameData[0];
-
- } else
- retVal |= 0x800;
-
- } while (hasNextCmd);
-
- if (startSound) {
- _vm->_snd->stopSound(0);
- _vm->_mixer->playInputStream(Audio::Mixer::kSFXSoundType, &_audioHandle, _audioStream);
- _soundStartTime = _vm->_util->getTimeKey();
- _skipFrames = 0;
- _soundStage = 2;
- }
-
- imdPtr->x = xBak;
- imdPtr->y = yBak;
- imdPtr->width = widthBak;
- imdPtr->height = heightBak;
-
- imdPtr->curFrame++;
- if ((imdPtr->curFrame == imdPtr->framesCount) && (_soundStage == 2)) {
- waitEndSoundSlice();
- _audioStream->finish();
- _vm->_mixer->stopHandle(_audioHandle);
- _audioStream = 0;
- }
-
- return retVal;
-}
-
-inline void ImdPlayer::waitEndSoundSlice() {
- if (_soundStage != 2)
- return;
-
- if (_skipFrames == 0) {
-
- _vm->_video->retrace();
-
- int32 waitTime = (_curImd->curFrame * _soundSliceLength) -
- (_vm->_util->getTimeKey() - _soundStartTime);
-
- if (waitTime < 0) {
- _skipFrames = -waitTime / _soundSliceLength;
- warning("IMD A/V sync broken, skipping %d frame(s)", _skipFrames + 1);
- } else if (waitTime > 0)
- _vm->_util->delay(waitTime);
-
- } else
- _skipFrames--;
-}
-
-} // End of namespace Gob
diff --git a/engines/gob/imd.h b/engines/gob/imd.h
deleted file mode 100644
index 27d95cd579..0000000000
--- a/engines/gob/imd.h
+++ /dev/null
@@ -1,143 +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$
- *
- */
-
-#ifndef GOB_IMD_H
-#define GOB_IMD_H
-
-#include "gob/video.h"
-#include "gob/sound.h"
-
-namespace Gob {
-
-class ImdPlayer {
-public:
-
-#include "common/pack-start.h" // START STRUCT PACKING
-
- struct ImdCoord {
- int16 left;
- int16 top;
- int16 right;
- int16 bottom;
- } PACKED_STRUCT;
-
- struct Imd {
- int16 handle;
- int16 verMin;
- int16 framesCount;
- int16 x;
- int16 y;
- int16 width;
- int16 height;
- int16 field_E;
- int16 curFrame;
- Video::Color *palette;
- SurfaceDesc *surfDesc;
- int32 *framesPos;
- int32 firstFramePos;
- int16 stdX;
- int16 stdY;
- int16 stdWidth;
- int16 stdHeight;
- ImdCoord *frameCoords;
- int32 frameDataSize;
- int32 vidBufferSize;
- Video::Color *extraPalette;
- } PACKED_STRUCT;
-
-#include "common/pack-end.h" // END STRUCT PACKING
-
- Imd *_curImd;
- byte _frontSurf;
- int8 _backSurf;
- byte *_frontMem;
- int32 _frameDelay;
-
- uint8 _soundStage; // (0: no sound, 1: loaded, 2: playing)
-
- ImdPlayer(GobEngine *vm);
- virtual ~ImdPlayer();
-
- Imd *loadImdFile(const char *path, SurfaceDesc *surfDesc, int8 flags);
- void finishImd(Imd *&imdPtr);
-
- int8 openImd(const char *path, int16 x, int16 y,
- int16 startFrame, int16 flags);
- void closeImd(void);
-
- void play(int16 frame, uint16 palCmd, int16 palStart, int16 palEnd,
- int16 palFrame, int16 lastFrame);
- void play(const char *path, int16 x, int16 y, bool interruptible);
- void play(const char *path, int16 x, int16 y, int16 startFrame,
- int16 frames, bool fade, bool interruptible);
-
-protected:
- char _curFile[18];
-
- int16 _curX;
- int16 _curY;
- int16 _left;
- int16 _top;
- int16 _right;
- int16 _bottom;
-
- byte *_frameData;
- byte *_vidBuffer;
-
- bool _noSound;
-
- uint32 _soundStartTime;
- uint32 _skipFrames;
-
- int16 _soundFreq;
- uint16 _soundSliceSize;
- int16 _soundSlicesCount;
- uint16 _soundSliceLength;
-
- Audio::AppendableAudioStream *_audioStream;
- Audio::SoundHandle _audioHandle;
-
- GobEngine *_vm;
-
- void copyPalette(int16 palStart, int16 palEnd);
- void flipFrontMem();
- void drawFrame(int16 frame);
- void setXY(Imd *imdPtr, int16 x, int16 y);
-
- void seekFrame(Imd *imdPtr, int16 frame, int16 from, bool restart = false);
- uint16 checkFrameType(Imd *imdPtr, int16 frame);
- void drawFrame(Imd *imdPtr, int16 frame, int16 x, int16 y,
- SurfaceDesc *dest = 0);
-
- uint32 view(ImdPlayer::Imd *imdPtr, int16 arg_4);
- void renderFrame(Imd *imdPtr);
- void frameUncompressor(byte *dest, byte *src);
-
- void waitEndSoundSlice();
-};
-
-} // End of namespace Gob
-
-#endif // GOB_IMD_H
diff --git a/engines/gob/init.cpp b/engines/gob/init.cpp
index 2f1dbe5326..4712a19a5d 100644
--- a/engines/gob/init.cpp
+++ b/engines/gob/init.cpp
@@ -37,7 +37,7 @@
#include "gob/palanim.h"
#include "gob/sound.h"
#include "gob/video.h"
-#include "gob/imd.h"
+#include "gob/videoplayer.h"
namespace Gob {
@@ -147,10 +147,12 @@ void Init::initGame(const char *totName) {
handle = _vm->_dataIO->openData(buffer);
if (handle >= 0) {
- // Get variables count
- _vm->_dataIO->seekData(handle, 0x2C, SEEK_SET);
- varsCount = _vm->_dataIO->readUint16(handle);
- _vm->_dataIO->closeData(handle);
+ DataStream *stream = _vm->_dataIO->openAsStream(handle, true);
+
+ stream->seek(0x2C);
+ varsCount = stream->readUint16LE();
+
+ delete stream;
_vm->_global->_inter_variables = new byte[varsCount * 4];
_vm->_global->_inter_variablesSizes = new byte[varsCount * 4];
@@ -167,14 +169,23 @@ void Init::initGame(const char *totName) {
_vm->_dataIO->closeData(imdHandle);
_vm->_draw->initScreen();
_vm->_draw->_cursorIndex = -1;
+
_vm->_util->longDelay(200); // Letting everything settle
- _vm->_imdPlayer->play("coktel", -1, -1, true);
+
+ if (_vm->_vidPlayer->openVideo("coktel.imd")) {
+ _vm->_vidPlayer->play();
+ _vm->_vidPlayer->closeVideo();
+ }
+
_vm->_draw->closeScreen();
} else if ((imdHandle = _vm->_dataIO->openData("coktel.clt")) >= 0) {
_vm->_draw->initScreen();
+
+ stream = _vm->_dataIO->openAsStream(imdHandle, true);
_vm->_util->clearPalette();
- _vm->_dataIO->readData(imdHandle, (byte *) _vm->_draw->_vgaPalette, 768);
- _vm->_dataIO->closeData(imdHandle);
+ stream->read((byte *) _vm->_draw->_vgaPalette, 768);
+ delete stream;
+
imdHandle = _vm->_dataIO->openData("coktel.ims");
if (imdHandle >= 0) {
byte *sprBuf;
diff --git a/engines/gob/inter.cpp b/engines/gob/inter.cpp
index 1f529b7634..4da3746681 100644
--- a/engines/gob/inter.cpp
+++ b/engines/gob/inter.cpp
@@ -209,7 +209,7 @@ void Inter::funcBlock(int16 retFlag) {
// WORKAROUND:
// The EGA version of gob1 doesn't add a delay after showing
// images between levels. We manually add it here.
- if ((_vm->_features & GF_GOB1) && (_vm->_features & GF_EGA)) {
+ if ((_vm->getGameType() == kGameTypeGob1) && _vm->isEGA()) {
int addr = _vm->_global->_inter_execPtr-_vm->_game->_totFileData;
if ((startaddr == 0x18B4 && addr == 0x1A7F && // Zombie
!strncmp(_vm->_game->_curTotFile, "avt005.tot", 10)) ||
diff --git a/engines/gob/inter.h b/engines/gob/inter.h
index fe84741eed..a7317492ad 100644
--- a/engines/gob/inter.h
+++ b/engines/gob/inter.h
@@ -342,6 +342,7 @@ protected:
virtual void checkSwitchTable(byte **ppExec);
void o2_playMult();
+ void o2_freeMultKeys();
void o2_setRenderFlags();
void o2_multSub();
void o2_initMult();
@@ -378,6 +379,8 @@ protected:
bool o2_evaluateStore(OpFuncParams &params);
bool o2_printText(OpFuncParams &params);
bool o2_animPalInit(OpFuncParams &params);
+ bool o2_addCollision(OpFuncParams &params);
+ bool o2_freeCollision(OpFuncParams &params);
bool o2_goblinFunc(OpFuncParams &params);
bool o2_createSprite(OpFuncParams &params);
bool o2_stopSound(OpFuncParams &params);
@@ -478,6 +481,45 @@ protected:
bool o3_checkData(OpFuncParams &params);
bool o3_readData(OpFuncParams &params);
bool o3_writeData(OpFuncParams &params);
+
+ void o3_wobble(OpGobParams &params);
+};
+
+class Inter_v4 : public Inter_v3 {
+public:
+ Inter_v4(GobEngine *vm);
+ virtual ~Inter_v4() {}
+
+protected:
+ typedef void (Inter_v4::*OpcodeDrawProcV4)();
+ typedef bool (Inter_v4::*OpcodeFuncProcV4)(OpFuncParams &);
+ typedef void (Inter_v4::*OpcodeGoblinProcV4)(OpGobParams &);
+ struct OpcodeDrawEntryV4 {
+ OpcodeDrawProcV4 proc;
+ const char *desc;
+ };
+ struct OpcodeFuncEntryV4 {
+ OpcodeFuncProcV4 proc;
+ const char *desc;
+ };
+ struct OpcodeGoblinEntryV4 {
+ OpcodeGoblinProcV4 proc;
+ const char *desc;
+ };
+ const OpcodeDrawEntryV4 *_opcodesDrawV4;
+ const OpcodeFuncEntryV4 *_opcodesFuncV4;
+ const OpcodeGoblinEntryV4 *_opcodesGoblinV4;
+ static const int _goblinFuncLookUp[][2];
+
+ virtual void setupOpcodes();
+ virtual void executeDrawOpcode(byte i);
+ virtual bool executeFuncOpcode(byte i, byte j, OpFuncParams &params);
+ virtual void executeGoblinOpcode(int i, OpGobParams &params);
+ virtual const char *getOpcodeDrawDesc(byte i);
+ virtual const char *getOpcodeFuncDesc(byte i, byte j);
+ virtual const char *getOpcodeGoblinDesc(int i);
+
+ void o4_playVmdOrMusic();
};
} // End of namespace Gob
diff --git a/engines/gob/inter_bargon.cpp b/engines/gob/inter_bargon.cpp
index ffbe9e45ea..492ea198a1 100644
--- a/engines/gob/inter_bargon.cpp
+++ b/engines/gob/inter_bargon.cpp
@@ -33,10 +33,10 @@
#include "gob/dataio.h"
#include "gob/draw.h"
#include "gob/game.h"
-#include "gob/imd.h"
#include "gob/palanim.h"
#include "gob/sound.h"
#include "gob/video.h"
+#include "gob/videoplayer.h"
namespace Gob {
@@ -717,11 +717,17 @@ const char *Inter_Bargon::getOpcodeGoblinDesc(int i) {
}
void Inter_Bargon::oBargon_intro0(OpGobParams &params) {
- _vm->_imdPlayer->play("scaa", 0, 160, 0, 92, 0, 1);
+ if (_vm->_vidPlayer->openVideo("scaa", 0, 160)) {
+ _vm->_vidPlayer->play(0, 92, 27, 0, 0, 0);
+ _vm->_vidPlayer->closeVideo();
+ }
}
void Inter_Bargon::oBargon_intro1(OpGobParams &params) {
- _vm->_imdPlayer->play("scaa", 0, 160, 0, -23, 1, 1);
+ if (_vm->_vidPlayer->openVideo("scaa", 0, 160)) {
+ _vm->_vidPlayer->play(0, -1, 27, 0, 0, 0, 0, 0, true, 23);
+ _vm->_vidPlayer->closeVideo();
+ }
}
void Inter_Bargon::oBargon_intro2(OpGobParams &params) {
@@ -813,27 +819,45 @@ void Inter_Bargon::oBargon_intro3(OpGobParams &params) {
}
void Inter_Bargon::oBargon_intro4(OpGobParams &params) {
- _vm->_imdPlayer->play("scba", 191, 54, 0, 0, 1, 1);
+ if (_vm->_vidPlayer->openVideo("scba", 191, 54)) {
+ _vm->_vidPlayer->play(0, -1, 27, 0, 0, 0, 0, 0, true);
+ _vm->_vidPlayer->closeVideo();
+ }
}
void Inter_Bargon::oBargon_intro5(OpGobParams &params) {
- _vm->_imdPlayer->play("scbb", 191, 54, 0, 0, 0, 1);
+ if (_vm->_vidPlayer->openVideo("scbb", 191, 54)) {
+ _vm->_vidPlayer->play(0, -1, 27, 0, 0, 0);
+ _vm->_vidPlayer->closeVideo();
+ }
}
void Inter_Bargon::oBargon_intro6(OpGobParams &params) {
- _vm->_imdPlayer->play("scbc", 191, 54, 0, 0, 0, 1);
+ if (_vm->_vidPlayer->openVideo("scbc", 191, 54)) {
+ _vm->_vidPlayer->play(0, -1, 27, 0, 0, 0);
+ _vm->_vidPlayer->closeVideo();
+ }
}
void Inter_Bargon::oBargon_intro7(OpGobParams &params) {
- _vm->_imdPlayer->play("scbf", 191, 54, 0, 0, 0, 1);
+ if (_vm->_vidPlayer->openVideo("scbf", 191, 54)) {
+ _vm->_vidPlayer->play(0, -1, 27, 0, 0, 0);
+ _vm->_vidPlayer->closeVideo();
+ }
}
void Inter_Bargon::oBargon_intro8(OpGobParams &params) {
- _vm->_imdPlayer->play("scbc", 191, 54, 0, 0, 0, 1);
+ if (_vm->_vidPlayer->openVideo("scbc", 191, 54)) {
+ _vm->_vidPlayer->play(0, -1, 27, 0, 0, 0);
+ _vm->_vidPlayer->closeVideo();
+ }
}
void Inter_Bargon::oBargon_intro9(OpGobParams &params) {
- _vm->_imdPlayer->play("scbd", 191, 54, 0, 0, 0, 1);
+ if (_vm->_vidPlayer->openVideo("scbd", 191, 54)) {
+ _vm->_vidPlayer->play(0, -1, 27, 0, 0, 0);
+ _vm->_vidPlayer->closeVideo();
+ }
}
} // End of namespace Gob
diff --git a/engines/gob/inter_v1.cpp b/engines/gob/inter_v1.cpp
index a3277047e7..9f30d9dea2 100644
--- a/engines/gob/inter_v1.cpp
+++ b/engines/gob/inter_v1.cpp
@@ -1136,13 +1136,13 @@ bool Inter_v1::o1_callSub(OpFuncParams &params) {
}
// Skipping the copy protection screen in Gobliiins
- if (!_vm->_copyProtection && (_vm->_features & GF_GOB1) && (offset == 3905)
+ if (!_vm->_copyProtection && (_vm->getGameType() == kGameTypeGob1) && (offset == 3905)
&& !scumm_stricmp(_vm->_game->_curTotFile, _vm->_startTot)) {
debugC(2, kDebugGameFlow, "Skipping copy protection screen");
return false;
}
// Skipping the copy protection screen in Gobliins 2
- if (!_vm->_copyProtection && (_vm->_features & GF_GOB2) && (offset == 1746)
+ if (!_vm->_copyProtection && (_vm->getGameType() == kGameTypeGob2) && (offset == 1746)
&& !scumm_stricmp(_vm->_game->_curTotFile, _vm->_startTot0)) {
debugC(2, kDebugGameFlow, "Skipping copy protection screen");
return false;
@@ -1174,6 +1174,10 @@ bool Inter_v1::o1_loadCursor(OpFuncParams &params) {
id = load16();
index = (int8) *_vm->_global->_inter_execPtr++;
+
+ if ((index * _vm->_draw->_cursorWidth) >= _vm->_draw->_cursorSprites->getWidth())
+ return false;
+
itemPtr = &_vm->_game->_totResourceTable->items[id];
offset = itemPtr->offset;
@@ -1613,7 +1617,7 @@ bool Inter_v1::o1_palLoad(OpFuncParams &params) {
_vm->_global->_pPaletteDesc->unused1 = _vm->_draw->_unusedPalette1;
if (_vm->_global->_videoMode < 0x13) {
- _vm->_global->_pPaletteDesc->vgaPal = _vm->_draw->_vgaSmallPalette;
+ _vm->_global->_pPaletteDesc->vgaPal = _vm->_draw->_vgaPalette;
_vm->_palAnim->fade(_vm->_global->_pPaletteDesc, 0, 0);
return false;
}
@@ -1650,8 +1654,9 @@ bool Inter_v1::o1_keyFunc(OpFuncParams &params) {
// WORKAROUND for bug #1726130: Ween busy-waits in the intro for a counter
// to become 5000. We deliberately slow down busy-waiting, so we shorten
// the counting, too.
- if (((_vm->_global->_inter_execPtr - _vm->_game->_totFileData) == 729) &&
- (VAR(59) < 4000) && !scumm_stricmp(_vm->_game->_curTotFile, "intro5.tot"))
+ if ((_vm->getGameType() == kGameTypeWeen) && (VAR(59) < 4000) &&
+ ((_vm->_global->_inter_execPtr - _vm->_game->_totFileData) == 729) &&
+ !scumm_stricmp(_vm->_game->_curTotFile, "intro5.tot"))
WRITE_VAR(59, 4000);
switch (cmd) {
@@ -1700,6 +1705,10 @@ bool Inter_v1::o1_capturePush(OpFuncParams &params) {
top = _vm->_parse->parseValExpr();
width = _vm->_parse->parseValExpr();
height = _vm->_parse->parseValExpr();
+
+ if ((width < 0) || (height < 0))
+ return false;
+
_vm->_game->capturePush(left, top, width, height);
(*_vm->_scenery->_pCaptureCounter)++;
return false;
@@ -1887,7 +1896,9 @@ bool Inter_v1::o1_copySprite(OpFuncParams &params) {
}
bool Inter_v1::o1_fillRect(OpFuncParams &params) {
- _vm->_draw->_destSurface = load16();
+ int16 destSurf;
+
+ _vm->_draw->_destSurface = destSurf = load16();
_vm->_draw->_destSpriteX = _vm->_parse->parseValExpr();
_vm->_draw->_destSpriteY = _vm->_parse->parseValExpr();
@@ -1895,6 +1906,19 @@ bool Inter_v1::o1_fillRect(OpFuncParams &params) {
_vm->_draw->_spriteBottom = _vm->_parse->parseValExpr();
_vm->_draw->_backColor = _vm->_parse->parseValExpr();
+
+ if (!_vm->_draw->_spritesArray[(destSurf > 100) ? (destSurf - 80) : destSurf])
+ return false;
+
+ if (_vm->_draw->_spriteRight < 0) {
+ _vm->_draw->_destSpriteX += _vm->_draw->_spriteRight - 1;
+ _vm->_draw->_spriteRight = -_vm->_draw->_spriteRight + 2;
+ }
+ if (_vm->_draw->_spriteBottom < 0) {
+ _vm->_draw->_destSpriteY += _vm->_draw->_spriteBottom - 1;
+ _vm->_draw->_spriteBottom = -_vm->_draw->_spriteBottom + 2;
+ }
+
_vm->_draw->spriteOperation(DRAW_FILLRECT);
return false;
}
@@ -2201,22 +2225,23 @@ bool Inter_v1::o1_readData(OpFuncParams &params) {
WRITE_VAR(1, 1);
handle = _vm->_dataIO->openData(_vm->_global->_inter_resStr);
if (handle >= 0) {
+ DataStream *stream = _vm->_dataIO->openAsStream(handle, true);
+
_vm->_draw->animateCursor(4);
if (offset < 0)
- _vm->_dataIO->seekData(handle, -offset - 1, SEEK_END);
+ stream->seek(-offset - 1, SEEK_END);
else
- _vm->_dataIO->seekData(handle, offset, SEEK_SET);
+ stream->seek(offset);
if (((dataVar >> 2) == 59) && (size == 4))
- WRITE_VAR(59, _vm->_dataIO->readUint32(handle));
+ WRITE_VAR(59, stream->readUint32LE());
else
- retSize = _vm->_dataIO->readData(handle,
- _vm->_global->_inter_variables + dataVar, size);
-
- _vm->_dataIO->closeData(handle);
+ retSize = stream->read(_vm->_global->_inter_variables + dataVar, size);
if (retSize == size)
WRITE_VAR(1, 0);
+
+ delete stream;
}
if (_vm->_game->_extHandle >= 0)
diff --git a/engines/gob/inter_v2.cpp b/engines/gob/inter_v2.cpp
index d69b6fda97..376aef75d9 100644
--- a/engines/gob/inter_v2.cpp
+++ b/engines/gob/inter_v2.cpp
@@ -38,7 +38,6 @@
#include "gob/draw.h"
#include "gob/game.h"
#include "gob/goblin.h"
-#include "gob/imd.h"
#include "gob/map.h"
#include "gob/mult.h"
#include "gob/parse.h"
@@ -46,6 +45,7 @@
#include "gob/sound.h"
#include "gob/video.h"
#include "gob/saveload.h"
+#include "gob/videoplayer.h"
namespace Gob {
@@ -134,7 +134,7 @@ void Inter_v2::setupOpcodes() {
/* 00 */
OPCODE(o1_loadMult),
OPCODE(o2_playMult),
- OPCODE(o1_freeMultKeys),
+ OPCODE(o2_freeMultKeys),
{NULL, ""},
/* 04 */
{NULL, ""},
@@ -485,8 +485,8 @@ void Inter_v2::setupOpcodes() {
OPCODE(o1_capturePop),
OPCODE(o2_animPalInit),
/* 18 */
- {NULL, ""},
- {NULL, ""},
+ OPCODE(o2_addCollision),
+ OPCODE(o2_freeCollision),
{NULL, ""},
{NULL, ""},
/* 1C */
@@ -826,6 +826,17 @@ void Inter_v2::o2_playMult() {
_vm->_mult->playMult(VAR(57), -1, checkEscape & 0x1, 0);
}
+void Inter_v2::o2_freeMultKeys() {
+ uint16 index = load16();
+
+ if (!_vm->_mult->hasMultData(index))
+ return;
+
+ _vm->_mult->setMultData(index);
+ _vm->_mult->freeMultKeys();
+ _vm->_mult->zeroMultData(index);
+}
+
void Inter_v2::o2_setRenderFlags() {
int16 expr;
@@ -1364,11 +1375,37 @@ void Inter_v2::o2_initScreen() {
width = _vm->_parse->parseValExpr();
height = _vm->_parse->parseValExpr();
+ // Lost in Time switches to 640x400x16 when showing the title screen
+ if (_vm->getGameType() == kGameTypeLostInTime) {
+ if (videoMode == 0x10) {
+ width = _vm->_width = 640;
+ height = _vm->_height = 400;
+ _vm->_global->_colorCount = 16;
+ _vm->_system->beginGFXTransaction();
+ _vm->_system->initSize(_vm->_width, _vm->_height);
+ _vm->initCommonGFX(true);
+ _vm->_system->endGFXTransaction();
+ } else if (_vm->_global->_videoMode == 0x10) {
+ if (width == -1)
+ width = 320;
+ if (height == -1)
+ height = 200;
+
+ _vm->_width = 320;
+ _vm->_height = 200;
+ _vm->_global->_colorCount = 256;
+ _vm->_system->beginGFXTransaction();
+ _vm->_system->initSize(_vm->_width, _vm->_height);
+ _vm->initCommonGFX(false);
+ _vm->_system->endGFXTransaction();
+ }
+ }
+
_vm->_global->_fakeVideoMode = videoMode;
// Some versions require this
if (videoMode == 0xD)
- videoMode = 0x14;
+ videoMode = _vm->_mode;
if ((videoMode == _vm->_global->_videoMode) && (width == -1))
return;
@@ -1378,7 +1415,8 @@ void Inter_v2::o2_initScreen() {
if (height > 0)
_vm->_video->_surfHeight = height;
- _vm->_video->_splitHeight1 = MIN(200, _vm->_video->_surfHeight - offY);
+ _vm->_video->_splitHeight1 =
+ MIN<int16>(_vm->_height, _vm->_video->_surfHeight - offY);
_vm->_video->_splitHeight2 = offY;
_vm->_video->_splitStart = _vm->_video->_surfHeight - offY;
@@ -1414,13 +1452,13 @@ void Inter_v2::o2_scroll() {
int16 curY;
startX = CLIP((int) _vm->_parse->parseValExpr(), 0,
- _vm->_video->_surfWidth - 320);
+ _vm->_video->_surfWidth - _vm->_width);
startY = CLIP((int) _vm->_parse->parseValExpr(), 0,
- _vm->_video->_surfHeight - 200);
+ _vm->_video->_surfHeight - _vm->_height);
endX = CLIP((int) _vm->_parse->parseValExpr(), 0,
- _vm->_video->_surfWidth - 320);
+ _vm->_video->_surfWidth - _vm->_width);
endY = CLIP((int) _vm->_parse->parseValExpr(), 0,
- _vm->_video->_surfHeight - 200);
+ _vm->_video->_surfHeight - _vm->_height);
stepX = _vm->_parse->parseValExpr();
stepY = _vm->_parse->parseValExpr();
@@ -1481,48 +1519,28 @@ void Inter_v2::o2_playImd() {
palEnd = _vm->_parse->parseValExpr();
palCmd = 1 << (flags & 0x3F);
- if (!_vm->_imdPlayer->openImd(imd, x, y, startFrame, flags)) {
+ if ((imd[0] != 0) && !_vm->_vidPlayer->openVideo(imd, x, y, flags)) {
WRITE_VAR(11, -1);
return;
}
close = (lastFrame == -1);
- if (lastFrame < 0)
- lastFrame = _vm->_imdPlayer->_curImd->framesCount - 1;
if (startFrame == -2) {
startFrame = lastFrame = 0;
close = false;
}
- _vm->_game->_preventScroll = true;
- for (int i = startFrame; i <= lastFrame; i++) {
- _vm->_imdPlayer->play(i, palCmd, palStart, palEnd, 0, lastFrame);
- WRITE_VAR(11, i);
-
- if (_vm->_quitRequested)
- break;
-
- if (breakKey != 0) {
- _vm->_util->getMouseState(&_vm->_global->_inter_mouseX,
- &_vm->_global->_inter_mouseY, &_vm->_game->_mouseButtons);
-
- storeKey(_vm->_util->checkKey());
- if (VAR(0) == (unsigned) breakKey) {
- if (_vm->_imdPlayer->_soundStage == 2)
- _vm->_snd->stopSound(0);
- _vm->_game->_preventScroll = false;
- return;
- }
- }
+ if (startFrame >= 0) {
+ _vm->_game->_preventScroll = true;
+ _vm->_vidPlayer->play(startFrame, lastFrame, breakKey, palCmd, palStart, palEnd, 0);
+ _vm->_game->_preventScroll = false;
}
- _vm->_game->_preventScroll = false;
if (close)
- _vm->_imdPlayer->closeImd();
+ _vm->_vidPlayer->closeVideo();
}
void Inter_v2::o2_getImdInfo() {
- ImdPlayer::Imd *imd;
int16 varX, varY;
int16 varFrames;
int16 varWidth, varHeight;
@@ -1533,21 +1551,9 @@ void Inter_v2::o2_getImdInfo() {
varFrames = _vm->_parse->parseVarIndex();
varWidth = _vm->_parse->parseVarIndex();
varHeight = _vm->_parse->parseVarIndex();
- imd = _vm->_imdPlayer->loadImdFile(_vm->_global->_inter_resStr, 0, 2);
- if (!imd) {
- WRITE_VAR_OFFSET(varX, -1);
- WRITE_VAR_OFFSET(varY, -1);
- WRITE_VAR_OFFSET(varFrames, -1);
- WRITE_VAR_OFFSET(varWidth, -1);
- WRITE_VAR_OFFSET(varHeight, -1);
- } else {
- WRITE_VAR_OFFSET(varX, imd->x);
- WRITE_VAR_OFFSET(varY, imd->y);
- WRITE_VAR_OFFSET(varFrames, imd->framesCount);
- WRITE_VAR_OFFSET(varWidth, imd->width);
- WRITE_VAR_OFFSET(varHeight, imd->height);
- }
- _vm->_imdPlayer->finishImd(imd);
+
+ _vm->_vidPlayer->writeVideoInfo(_vm->_global->_inter_resStr, varX, varY,
+ varFrames, varWidth, varHeight);
}
void Inter_v2::o2_openItk() {
@@ -1565,21 +1571,9 @@ void Inter_v2::o2_closeItk() {
}
void Inter_v2::o2_setImdFrontSurf() {
- _vm->_imdPlayer->_frontSurf = 21;
- if (_vm->_global->_videoMode == 0x14) {
- _vm->_imdPlayer->_frontMem = _vm->_draw->_frontSurface->getVidMem();
- _vm->_draw->blitInvalidated();
- _vm->_imdPlayer->_frontSurf = 20;
- }
}
void Inter_v2::o2_resetImdFrontSurf() {
- _vm->_imdPlayer->_frontSurf = 21;
- if (_vm->_imdPlayer->_frontMem) {
- _vm->_imdPlayer->_frontMem = _vm->_draw->_frontSurface->getVidMem();
- _vm->_draw->forceBlit();
- } else
- _vm->_draw->forceBlit(true);
}
bool Inter_v2::o2_evaluateStore(OpFuncParams &params) {
@@ -1721,6 +1715,71 @@ bool Inter_v2::o2_animPalInit(OpFuncParams &params) {
return false;
}
+bool Inter_v2::o2_addCollision(OpFuncParams &params) {
+ int16 id;
+ int16 left, top, width, height;
+ int16 flags;
+ int16 key;
+ int16 funcSub;
+
+ id = _vm->_parse->parseValExpr();
+ funcSub = _vm->_global->_inter_execPtr - _vm->_game->_totFileData;
+ left = _vm->_parse->parseValExpr();
+ top = _vm->_parse->parseValExpr();
+ width = _vm->_parse->parseValExpr();
+ height = _vm->_parse->parseValExpr();
+ flags = _vm->_parse->parseValExpr();
+ key = load16();
+
+ if (key == 0)
+ key = ABS(id) + 41960;
+
+ _vm->_draw->adjustCoords(0, &left, &top);
+ _vm->_draw->adjustCoords(2, &width, &height);
+
+ if (left < 0) {
+ width += left;
+ left = 0;
+ }
+
+ if (top < 0) {
+ height += top;
+ top = 0;
+ }
+
+ int16 index;
+ if (id < 0)
+ index = _vm->_game->addNewCollision(0xD000 - id, left & 0xFFFC, top & 0xFFFC,
+ left + width + 3, top + height + 3, flags, key, 0, 0);
+ else
+ index = _vm->_game->addNewCollision(0xE000 + id, left, top,
+ left + width - 1, top + height - 1, flags, key, 0, 0);
+
+ _vm->_game->_collisionAreas[index].funcSub = funcSub;
+
+ return false;
+}
+
+bool Inter_v2::o2_freeCollision(OpFuncParams &params) {
+ int16 id;
+
+ id = _vm->_parse->parseValExpr();
+ if (id == -2) {
+ for (int i = 0; i < 150; i++) {
+ if ((_vm->_game->_collisionAreas[i].id & 0xF000) == 0xD000)
+ _vm->_game->_collisionAreas[i].left = 0xFFFF;
+ }
+ } else if (id == -1) {
+ for (int i = 0; i < 150; i++) {
+ if ((_vm->_game->_collisionAreas[i].id & 0xF000) == 0xE000)
+ _vm->_game->_collisionAreas[i].left = 0xFFFF;
+ }
+ } else
+ _vm->_game->freeCollision(0xE000 + id);
+
+ return false;
+}
+
bool Inter_v2::o2_goblinFunc(OpFuncParams &params) {
OpGobParams gobParams;
int16 cmd;
@@ -1870,25 +1929,27 @@ bool Inter_v2::o2_readData(OpFuncParams &params) {
if (handle < 0)
return false;
+ DataStream *stream = _vm->_dataIO->openAsStream(handle, true);
+
_vm->_draw->animateCursor(4);
if (offset < 0)
- _vm->_dataIO->seekData(handle, -offset - 1, SEEK_END);
+ stream->seek(-offset - 1, SEEK_END);
else
- _vm->_dataIO->seekData(handle, offset, SEEK_SET);
+ stream->seek(offset);
if (((dataVar >> 2) == 59) && (size == 4)) {
- WRITE_VAR(59, _vm->_dataIO->readUint32(handle));
+ WRITE_VAR(59, stream->readUint32LE());
// The scripts in some versions divide through 256^3 then,
// effectively doing a LE->BE conversion
if ((_vm->_platform != Common::kPlatformPC) && (VAR(59) < 256))
WRITE_VAR(59, SWAP_BYTES_32(VAR(59)));
} else
- retSize = _vm->_dataIO->readData(handle, buf, size);
+ retSize = stream->read(buf, size);
if (retSize == size)
WRITE_VAR(1, 0);
- _vm->_dataIO->closeData(handle);
+ delete stream;
return false;
}
diff --git a/engines/gob/inter_v3.cpp b/engines/gob/inter_v3.cpp
index d3389f2671..51413c839a 100644
--- a/engines/gob/inter_v3.cpp
+++ b/engines/gob/inter_v3.cpp
@@ -122,7 +122,7 @@ void Inter_v3::setupOpcodes() {
/* 00 */
OPCODE(o1_loadMult),
OPCODE(o2_playMult),
- OPCODE(o1_freeMultKeys),
+ OPCODE(o2_freeMultKeys),
{NULL, ""},
/* 04 */
{NULL, ""},
@@ -473,8 +473,8 @@ void Inter_v3::setupOpcodes() {
OPCODE(o1_capturePop),
OPCODE(o2_animPalInit),
/* 18 */
- {NULL, ""},
- {NULL, ""},
+ OPCODE(o2_addCollision),
+ OPCODE(o2_freeCollision),
OPCODE(o3_getTotTextItemPart),
{NULL, ""},
/* 1C */
@@ -594,7 +594,7 @@ void Inter_v3::setupOpcodes() {
{NULL, ""},
{NULL, ""},
{NULL, ""},
- OPCODE(o2_handleGoblins),
+ OPCODE(o3_wobble),
/* 28 */
{NULL, ""},
{NULL, ""},
@@ -894,4 +894,8 @@ bool Inter_v3::o3_copySprite(OpFuncParams &params) {
return false;
}
+void Inter_v3::o3_wobble(OpGobParams &params) {
+ _vm->_draw->wobble(_vm->_draw->_backSurface);
+}
+
} // End of namespace Gob
diff --git a/engines/gob/inter_v4.cpp b/engines/gob/inter_v4.cpp
new file mode 100644
index 0000000000..81f53757a3
--- /dev/null
+++ b/engines/gob/inter_v4.cpp
@@ -0,0 +1,786 @@
+/* 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/endian.h"
+#include "common/file.h"
+
+#include "gob/gob.h"
+#include "gob/inter.h"
+#include "gob/global.h"
+#include "gob/game.h"
+#include "gob/parse.h"
+#include "gob/videoplayer.h"
+
+namespace Gob {
+
+#define OPCODE(x) _OPCODE(Inter_v4, x)
+
+const int Inter_v4::_goblinFuncLookUp[][2] = {
+ {0, 0},
+ {1, 1},
+ {2, 2},
+ {4, 3},
+ {5, 4},
+ {6, 5},
+ {7, 6},
+ {8, 7},
+ {9, 8},
+ {10, 9},
+ {12, 10},
+ {13, 11},
+ {14, 12},
+ {15, 13},
+ {16, 14},
+ {21, 15},
+ {22, 16},
+ {23, 17},
+ {24, 18},
+ {25, 19},
+ {26, 20},
+ {27, 21},
+ {28, 22},
+ {29, 23},
+ {30, 24},
+ {32, 25},
+ {33, 26},
+ {34, 27},
+ {35, 28},
+ {36, 29},
+ {37, 30},
+ {40, 31},
+ {41, 32},
+ {42, 33},
+ {43, 34},
+ {44, 35},
+ {50, 36},
+ {52, 37},
+ {53, 38},
+ {100, 39},
+ {152, 40},
+ {200, 41},
+ {201, 42},
+ {202, 43},
+ {203, 44},
+ {204, 45},
+ {250, 46},
+ {251, 47},
+ {252, 48},
+ {500, 49},
+ {502, 50},
+ {503, 51},
+ {600, 52},
+ {601, 53},
+ {602, 54},
+ {603, 55},
+ {604, 56},
+ {605, 57},
+ {1000, 58},
+ {1001, 59},
+ {1002, 60},
+ {1003, 61},
+ {1004, 62},
+ {1005, 63},
+ {1006, 64},
+ {1008, 65},
+ {1009, 66},
+ {1010, 67},
+ {1011, 68},
+ {1015, 69},
+ {2005, 70}
+};
+
+Inter_v4::Inter_v4(GobEngine *vm) : Inter_v3(vm) {
+ setupOpcodes();
+}
+
+void Inter_v4::setupOpcodes() {
+ static const OpcodeDrawEntryV4 opcodesDraw[256] = {
+ /* 00 */
+ OPCODE(o1_loadMult),
+ OPCODE(o2_playMult),
+ OPCODE(o2_freeMultKeys),
+ {NULL, ""},
+ /* 04 */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ OPCODE(o1_initCursor),
+ /* 08 */
+ OPCODE(o1_initCursorAnim),
+ OPCODE(o1_clearCursorAnim),
+ OPCODE(o2_setRenderFlags),
+ {NULL, ""},
+ /* 0C */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* 10 */
+ OPCODE(o1_loadAnim),
+ OPCODE(o1_freeAnim),
+ OPCODE(o1_updateAnim),
+ OPCODE(o2_multSub),
+ /* 14 */
+ OPCODE(o2_initMult),
+ OPCODE(o1_freeMult),
+ OPCODE(o1_animate),
+ OPCODE(o2_loadMultObject),
+ /* 18 */
+ OPCODE(o1_getAnimLayerInfo),
+ OPCODE(o1_getObjAnimSize),
+ OPCODE(o1_loadStatic),
+ OPCODE(o1_freeStatic),
+ /* 1C */
+ OPCODE(o2_renderStatic),
+ OPCODE(o2_loadCurLayer),
+ {NULL, ""},
+ {NULL, ""},
+ /* 20 */
+ OPCODE(o2_playCDTrack),
+ OPCODE(o2_waitCDTrackEnd),
+ OPCODE(o2_stopCD),
+ OPCODE(o2_readLIC),
+ /* 24 */
+ OPCODE(o2_freeLIC),
+ OPCODE(o2_getCDTrackPos),
+ {NULL, ""},
+ {NULL, ""},
+ /* 28 */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* 2C */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* 30 */
+ OPCODE(o2_loadFontToSprite),
+ OPCODE(o1_freeFontToSprite),
+ {NULL, ""},
+ {NULL, ""},
+ /* 34 */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* 38 */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* 3C */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* 40 */
+ OPCODE(o2_totSub),
+ OPCODE(o2_switchTotSub),
+ OPCODE(o2_copyVars),
+ OPCODE(o2_pasteVars),
+ /* 44 */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* 48 */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* 4C */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* 50 */
+ OPCODE(o2_loadMapObjects),
+ OPCODE(o2_freeGoblins),
+ OPCODE(o2_moveGoblin),
+ OPCODE(o2_writeGoblinPos),
+ /* 54 */
+ OPCODE(o2_stopGoblin),
+ OPCODE(o2_setGoblinState),
+ OPCODE(o2_placeGoblin),
+ {NULL, ""},
+ /* 58 */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* 5C */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* 60 */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* 64 */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* 68 */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* 6C */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* 70 */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* 74 */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* 78 */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* 7C */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* 80 */
+ OPCODE(o2_initScreen),
+ OPCODE(o2_scroll),
+ OPCODE(o2_setScrollOffset),
+ OPCODE(o4_playVmdOrMusic),
+ /* 84 */
+ OPCODE(o2_getImdInfo),
+ OPCODE(o2_openItk),
+ OPCODE(o2_closeItk),
+ OPCODE(o2_setImdFrontSurf),
+ /* 88 */
+ OPCODE(o2_resetImdFrontSurf),
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* 8C */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* 90 */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* 94 */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* 98 */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* 9C */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* A0 */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* A4 */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* A8 */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* AC */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* B0 */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* B4 */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* B8 */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* BC */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* C0 */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* C4 */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* C8 */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* CC */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* D0 */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* D4 */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* D8 */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* DC */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* E0 */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* E4 */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* E8 */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* EC */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* F0 */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* F4 */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* F8 */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* FC */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""}
+ };
+
+ static const OpcodeFuncEntryV4 opcodesFunc[80] = {
+ /* 00 */
+ OPCODE(o1_callSub),
+ OPCODE(o1_callSub),
+ OPCODE(o1_printTotText),
+ OPCODE(o1_loadCursor),
+ /* 04 */
+ {NULL, ""},
+ OPCODE(o1_switch),
+ OPCODE(o1_repeatUntil),
+ OPCODE(o1_whileDo),
+ /* 08 */
+ OPCODE(o1_if),
+ OPCODE(o2_evaluateStore),
+ OPCODE(o1_loadSpriteToPos),
+ {NULL, ""},
+ /* 0C */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* 10 */
+ {NULL, ""},
+ OPCODE(o2_printText),
+ OPCODE(o1_loadTot),
+ OPCODE(o1_palLoad),
+ /* 14 */
+ OPCODE(o1_keyFunc),
+ OPCODE(o1_capturePush),
+ OPCODE(o1_capturePop),
+ OPCODE(o2_animPalInit),
+ /* 18 */
+ OPCODE(o2_addCollision),
+ OPCODE(o2_freeCollision),
+ OPCODE(o3_getTotTextItemPart),
+ {NULL, ""},
+ /* 1C */
+ {NULL, ""},
+ {NULL, ""},
+ OPCODE(o1_drawOperations),
+ OPCODE(o1_setcmdCount),
+ /* 20 */
+ OPCODE(o1_return),
+ OPCODE(o1_renewTimeInVars),
+ OPCODE(o1_speakerOn),
+ OPCODE(o1_speakerOff),
+ /* 24 */
+ OPCODE(o1_putPixel),
+ OPCODE(o2_goblinFunc),
+ OPCODE(o2_createSprite),
+ OPCODE(o1_freeSprite),
+ /* 28 */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* 2C */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* 30 */
+ OPCODE(o1_returnTo),
+ OPCODE(o1_loadSpriteContent),
+ OPCODE(o3_copySprite),
+ OPCODE(o1_fillRect),
+ /* 34 */
+ OPCODE(o1_drawLine),
+ OPCODE(o1_strToLong),
+ OPCODE(o1_invalidate),
+ OPCODE(o1_setBackDelta),
+ /* 38 */
+ OPCODE(o1_playSound),
+ OPCODE(o2_stopSound),
+ OPCODE(o2_loadSound),
+ OPCODE(o1_freeSoundSlot),
+ /* 3C */
+ OPCODE(o1_waitEndPlay),
+ OPCODE(o1_playComposition),
+ OPCODE(o2_getFreeMem),
+ OPCODE(o2_checkData),
+ /* 40 */
+ {NULL, ""},
+ OPCODE(o1_prepareStr),
+ OPCODE(o1_insertStr),
+ OPCODE(o1_cutStr),
+ /* 44 */
+ OPCODE(o1_strstr),
+ OPCODE(o1_istrlen),
+ OPCODE(o1_setMousePos),
+ OPCODE(o1_setFrameRate),
+ /* 48 */
+ OPCODE(o1_animatePalette),
+ OPCODE(o1_animateCursor),
+ OPCODE(o1_blitCursor),
+ OPCODE(o1_loadFont),
+ /* 4C */
+ OPCODE(o1_freeFont),
+ OPCODE(o2_readData),
+ OPCODE(o2_writeData),
+ OPCODE(o1_manageDataFile),
+ };
+
+ static const OpcodeGoblinEntryV4 opcodesGoblin[71] = {
+ /* 00 */
+ OPCODE(o2_loadInfogramesIns),
+ OPCODE(o2_startInfogrames),
+ OPCODE(o2_stopInfogrames),
+ {NULL, ""},
+ /* 04 */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* 08 */
+ {NULL, ""},
+ OPCODE(o2_playInfogrames),
+ {NULL, ""},
+ {NULL, ""},
+ /* 0C */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* 10 */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* 14 */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* 18 */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* 1C */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* 20 */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* 24 */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ OPCODE(o2_handleGoblins),
+ /* 28 */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* 2C */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* 30 */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* 34 */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* 38 */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* 3C */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* 40 */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ /* 44 */
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ };
+
+ _opcodesDrawV4 = opcodesDraw;
+ _opcodesFuncV4 = opcodesFunc;
+ _opcodesGoblinV4 = opcodesGoblin;
+}
+
+void Inter_v4::executeDrawOpcode(byte i) {
+ debugC(1, kDebugDrawOp, "opcodeDraw %d [0x%X] (%s)",
+ i, i, getOpcodeDrawDesc(i));
+
+ OpcodeDrawProcV4 op = _opcodesDrawV4[i].proc;
+
+ if (op == NULL)
+ warning("unimplemented opcodeDraw: %d", i);
+ else
+ (this->*op) ();
+}
+
+bool Inter_v4::executeFuncOpcode(byte i, byte j, OpFuncParams &params) {
+ debugC(1, kDebugFuncOp, "opcodeFunc %d.%d [0x%X.0x%X] (%s)",
+ i, j, i, j, getOpcodeFuncDesc(i, j));
+
+ if ((i > 4) || (j > 15)) {
+ warning("unimplemented opcodeFunc: %d.%d", i, j);
+ return false;
+ }
+
+ OpcodeFuncProcV4 op = _opcodesFuncV4[i*16 + j].proc;
+
+ if (op == NULL)
+ warning("unimplemented opcodeFunc: %d.%d", i, j);
+ else
+ return (this->*op) (params);
+
+ return false;
+}
+
+void Inter_v4::executeGoblinOpcode(int i, OpGobParams &params) {
+ debugC(1, kDebugGobOp, "opcodeGoblin %d [0x%X] (%s)",
+ i, i, getOpcodeGoblinDesc(i));
+
+ OpcodeGoblinProcV4 op = NULL;
+
+ for (int j = 0; j < ARRAYSIZE(_goblinFuncLookUp); j++)
+ if (_goblinFuncLookUp[j][0] == i) {
+ op = _opcodesGoblinV4[_goblinFuncLookUp[j][1]].proc;
+ break;
+ }
+
+ if (op == NULL) {
+ int16 val;
+
+ _vm->_global->_inter_execPtr -= 2;
+ val = load16();
+ _vm->_global->_inter_execPtr += val << 1;
+ } else
+ (this->*op) (params);
+}
+
+const char *Inter_v4::getOpcodeDrawDesc(byte i) {
+ return _opcodesDrawV4[i].desc;
+}
+
+const char *Inter_v4::getOpcodeFuncDesc(byte i, byte j) {
+ if ((i > 4) || (j > 15))
+ return "";
+
+ return _opcodesFuncV4[i*16 + j].desc;
+}
+
+const char *Inter_v4::getOpcodeGoblinDesc(int i) {
+ for (int j = 0; j < ARRAYSIZE(_goblinFuncLookUp); j++)
+ if (_goblinFuncLookUp[j][0] == i)
+ return _opcodesGoblinV4[_goblinFuncLookUp[j][1]].desc;
+ return "";
+}
+
+void Inter_v4::o4_playVmdOrMusic() {
+ char fileName[128];
+ int16 x, y;
+ int16 startFrame;
+ int16 lastFrame;
+ int16 breakKey;
+ int16 flags;
+ int16 palStart;
+ int16 palEnd;
+ uint16 palCmd;
+ bool close;
+
+ evalExpr(0);
+ _vm->_global->_inter_resStr[8] = 0;
+ strncpy0(fileName, _vm->_global->_inter_resStr, 127);
+
+ x = _vm->_parse->parseValExpr();
+ y = _vm->_parse->parseValExpr();
+ startFrame = _vm->_parse->parseValExpr();
+ lastFrame = _vm->_parse->parseValExpr();
+ breakKey = _vm->_parse->parseValExpr();
+ flags = _vm->_parse->parseValExpr();
+ palStart = _vm->_parse->parseValExpr();
+ palEnd = _vm->_parse->parseValExpr();
+ palCmd = 1 << (flags & 0x3F);
+
+ close = false;
+ if (lastFrame == -1) {
+ close = true;
+ } else if (lastFrame == -3) {
+ warning("Woodruff Stub: Video/Music command -3: Play background video %s", fileName);
+// return;
+ } else if (lastFrame == -4) {
+ warning("Woodruff Stub: Video/Music command -4: Play background video %s", fileName);
+ return;
+ } else if (lastFrame == -5) {
+ warning("Woodruff Stub: Video/Music command -5: Stop background music");
+ return;
+ } else if (lastFrame == -6) {
+ warning("Woodruff Stub: Video/Music command -6: Load background video %s", fileName);
+ return;
+ } else if (lastFrame == -8) {
+ warning("Woodruff Stub: Video/Music command -8: Play background video %s", fileName);
+ return;
+ } else if (lastFrame == -9) {
+ warning("Woodruff Stub: Video/Music command -9: Play background music %s (%d-%d)", fileName, palEnd, palStart);
+ return;
+ } else if (lastFrame < 0) {
+ warning("Unknown Video/Music command: %d, %s", lastFrame, fileName);
+ return;
+ }
+
+ if (startFrame == -2) {
+ startFrame = lastFrame = 0;
+ close = false;
+ }
+
+ if ((fileName[0] != 0) && !_vm->_vidPlayer->openVideo(fileName, x, y, flags)) {
+ WRITE_VAR(11, -1);
+ return;
+ }
+
+ if (startFrame >= 0) {
+ _vm->_game->_preventScroll = true;
+ _vm->_vidPlayer->play(startFrame, lastFrame, breakKey, palCmd, palStart, palEnd, 0);
+ _vm->_game->_preventScroll = false;
+ }
+
+ if (close)
+ _vm->_vidPlayer->closeVideo();
+}
+
+} // End of namespace Gob
diff --git a/engines/gob/map.cpp b/engines/gob/map.cpp
index 3c1895d099..5485d66987 100644
--- a/engines/gob/map.cpp
+++ b/engines/gob/map.cpp
@@ -261,7 +261,7 @@ void Map::findNearestWalkable(int16 &gobDestX, int16 &gobDestY,
int i;
mapWidth = _screenWidth / _tilesWidth;
- mapHeight = 200 / _tilesHeight;
+ mapHeight = _vm->_width / _tilesHeight;
direction = 0;
for (i = 1; i <= gobDestX; i++)
diff --git a/engines/gob/module.mk b/engines/gob/module.mk
index db0660fa5c..7571853f27 100644
--- a/engines/gob/module.mk
+++ b/engines/gob/module.mk
@@ -18,7 +18,8 @@ MODULE_OBJS := \
goblin_v1.o \
goblin_v2.o \
goblin_v3.o \
- imd.o \
+ coktelvideo.o \
+ videoplayer.o \
init.o \
init_v1.o \
init_v2.o \
@@ -26,8 +27,9 @@ MODULE_OBJS := \
inter.o \
inter_v1.o \
inter_v2.o \
- inter_v3.o \
inter_bargon.o \
+ inter_v3.o \
+ inter_v4.o \
map.o \
map_v1.o \
map_v2.o \
diff --git a/engines/gob/mult.h b/engines/gob/mult.h
index edfbb682ea..16d9961f89 100644
--- a/engines/gob/mult.h
+++ b/engines/gob/mult.h
@@ -112,7 +112,7 @@ public:
} PACKED_STRUCT;
struct Mult_AnimKey {
- int16 frame;
+ uint16 frame;
int16 layer;
int16 posX;
int16 posY;
@@ -246,8 +246,10 @@ public:
virtual void loadMult(int16 resId) = 0;
virtual void freeMultKeys() = 0;
- virtual void setMultData(uint16 multindex) = 0;
- virtual void multSub(uint16 multindex) = 0;
+ virtual bool hasMultData(uint16 multIndex) = 0;
+ virtual void setMultData(uint16 multIndex) = 0;
+ virtual void zeroMultData(uint16 multIndex) = 0;
+ virtual void multSub(uint16 multIndex) = 0;
virtual void animate() = 0;
Mult(GobEngine *vm);
@@ -299,8 +301,10 @@ public:
virtual void loadMult(int16 resId);
virtual void freeMultKeys();
- virtual void setMultData(uint16 multindex);
- virtual void multSub(uint16 multindex);
+ virtual bool hasMultData(uint16 multIndex);
+ virtual void setMultData(uint16 multIndex);
+ virtual void zeroMultData(uint16 multIndex);
+ virtual void multSub(uint16 multIndex);
virtual void animate();
protected:
@@ -317,8 +321,10 @@ public:
virtual void loadMult(int16 resId);
virtual void freeMultKeys();
- virtual void setMultData(uint16 multindex);
- virtual void multSub(uint16 multindex);
+ virtual bool hasMultData(uint16 multIndex);
+ virtual void setMultData(uint16 multIndex);
+ virtual void zeroMultData(uint16 multIndex);
+ virtual void multSub(uint16 multIndex);
virtual void animate();
protected:
diff --git a/engines/gob/mult_v1.cpp b/engines/gob/mult_v1.cpp
index 45ce9aa8a0..0c367870ac 100644
--- a/engines/gob/mult_v1.cpp
+++ b/engines/gob/mult_v1.cpp
@@ -237,11 +237,19 @@ void Mult_v1::freeMultKeys() {
_multData = 0;
}
-void Mult_v1::setMultData(uint16 multindex) {
+bool Mult_v1::hasMultData(uint16 multIndex) {
error("Switching mults not supported for Gob1");
}
-void Mult_v1::multSub(uint16 multindex) {
+void Mult_v1::setMultData(uint16 multIndex) {
+ error("Switching mults not supported for Gob1");
+}
+
+void Mult_v1::zeroMultData(uint16 multIndex) {
+ error("Switching mults not supported for Gob1");
+}
+
+void Mult_v1::multSub(uint16 multIndex) {
error("Switching mults not supported for Gob1");
}
diff --git a/engines/gob/mult_v2.cpp b/engines/gob/mult_v2.cpp
index f57d5ecb0c..cced4aac63 100644
--- a/engines/gob/mult_v2.cpp
+++ b/engines/gob/mult_v2.cpp
@@ -34,11 +34,11 @@
#include "gob/draw.h"
#include "gob/game.h"
#include "gob/goblin.h"
-#include "gob/imd.h"
#include "gob/inter.h"
#include "gob/parse.h"
#include "gob/scenery.h"
#include "gob/video.h"
+#include "gob/videoplayer.h"
namespace Gob {
@@ -346,28 +346,42 @@ void Mult_v2::freeMultKeys() {
_multData = 0;
}
-void Mult_v2::setMultData(uint16 multindex) {
- if (multindex > 7)
+bool Mult_v2::hasMultData(uint16 multIndex) {
+ if (multIndex > 7)
error("Multindex out of range");
- debugC(4, kDebugGameFlow, "Switching to mult %d", multindex);
- _multData = _multDatas[multindex];
+ return _multDatas[multIndex] != 0;
}
-void Mult_v2::multSub(uint16 multindex) {
+void Mult_v2::setMultData(uint16 multIndex) {
+ if (multIndex > 7)
+ error("Multindex out of range");
+
+ debugC(4, kDebugGameFlow, "Switching to mult %d", multIndex);
+ _multData = _multDatas[multIndex];
+}
+
+void Mult_v2::zeroMultData(uint16 multIndex) {
+ if (multIndex > 7)
+ error("Multindex out of range");
+
+ _multDatas[multIndex] = 0;
+}
+
+void Mult_v2::multSub(uint16 multIndex) {
uint16 flags;
int16 expr;
int16 index;
int16 startFrame, stopFrame, firstFrame;
- flags = multindex;
- multindex = (multindex >> 12) & 0xF;
+ flags = multIndex;
+ multIndex = (multIndex >> 12) & 0xF;
- if (multindex > 7)
+ if (multIndex > 7)
error("Multindex out of range");
- debugC(4, kDebugGameFlow, "Sub mult %d", multindex);
- _multData = _multDatas[multindex];
+ debugC(4, kDebugGameFlow, "Sub mult %d", multIndex);
+ _multData = _multDatas[multIndex];
if (!_multData) {
_vm->_parse->parseValExpr();
@@ -1027,7 +1041,7 @@ void Mult_v2::playImd(const char *imdFile, Mult::Mult_ImdKey &key, int16 dir,
x = y = -1;
if (key.imdFile == -1) {
- _vm->_imdPlayer->closeImd();
+ _vm->_vidPlayer->closeVideo();
_vm->_game->_preventScroll = false;
return;
}
@@ -1045,23 +1059,24 @@ void Mult_v2::playImd(const char *imdFile, Mult::Mult_ImdKey &key, int16 dir,
if ((lastFrame - palFrame) < startFrame)
if (!(key.flags & 0x4000)) {
_vm->_game->_preventScroll = false;
- _vm->_imdPlayer->closeImd();
+ _vm->_vidPlayer->closeVideo();
return;
}
- if (!_vm->_imdPlayer->openImd(imdFile, x, y, 0, flags)) {
+ if (!_vm->_vidPlayer->openVideo(imdFile, x, y, flags)) {
_vm->_game->_preventScroll = false;
return;
}
if (palFrame == -1)
palFrame = 0;
+
if (lastFrame == -1)
- lastFrame = _vm->_imdPlayer->_curImd->framesCount - 1;
+ lastFrame = _vm->_vidPlayer->getFramesCount() - 1;
baseFrame = startFrame % (lastFrame - palFrame + 1);
- _vm->_imdPlayer->play(baseFrame + palFrame, flags & 0x7F,
- palStart, palEnd, palFrame, lastFrame);
+ _vm->_vidPlayer->play(baseFrame + palFrame, baseFrame + palFrame, 0,
+ flags & 0x7F, palStart, palEnd, palFrame, lastFrame);
}
void Mult_v2::advanceObjects(int16 index) {
@@ -1074,13 +1089,19 @@ void Mult_v2::advanceObjects(int16 index) {
return;
for (int i = 0; i < 4; i++) {
+ int obj = _multData->animObjs[index][i];
+
if (_multData->animObjs[index][i] != -1) {
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[_multData->animObjs[index][i]];
+ Mult_Object &animObj = _objects[obj];
Mult_AnimData &animData = *(animObj.pAnimData);
if (key.frame > frame)
@@ -1122,7 +1143,7 @@ void Mult_v2::advanceObjects(int16 index) {
}
}
- if (_multData->animObjs[index][i] != -1) {
+ if (obj != -1) {
int keyIndex = _multData->imdKeysIndices[index][i];
int count = _multData->imdKeysCount[i];
diff --git a/engines/gob/saveload.h b/engines/gob/saveload.h
index b8c9e730dd..d7e45246ad 100644
--- a/engines/gob/saveload.h
+++ b/engines/gob/saveload.h
@@ -136,7 +136,8 @@ class SaveLoad_v3 : public SaveLoad_v2 {
public:
virtual SaveType getSaveType(const char *fileName);
- SaveLoad_v3(GobEngine *vm, const char *targetName);
+ SaveLoad_v3(GobEngine *vm, const char *targetName, uint32 screenshotSize = 19968,
+ int32 indexOffset = 40, int32 screenshotOffset = 80);
virtual ~SaveLoad_v3() {}
protected:
@@ -144,13 +145,15 @@ protected:
bool _firstSizeGame;
int8 _saveSlot;
+ uint32 _screenshotSize;
+ int32 _indexOffset;
+ int32 _screenshotOffset;
+
virtual uint32 getSaveGameSize();
virtual int32 getSizeGame();
- virtual int32 getSizeNotes();
virtual int32 getSizeScreenshot();
virtual bool loadGame(int16 dataVar, int32 size, int32 offset);
- virtual bool loadNotes(int16 dataVar, int32 size, int32 offset);
virtual bool loadScreenshot(int16 dataVar, int32 size, int32 offset);
virtual bool saveGame(int16 dataVar, int32 size, int32 offset);
virtual bool saveNotes(int16 dataVar, int32 size, int32 offset);
diff --git a/engines/gob/saveload_v2.cpp b/engines/gob/saveload_v2.cpp
index 35c3429ab6..13f23cccb6 100644
--- a/engines/gob/saveload_v2.cpp
+++ b/engines/gob/saveload_v2.cpp
@@ -47,6 +47,10 @@ SaveLoad_v2::SaveLoad_v2(GobEngine *vm, const char *targetName) :
}
SaveType SaveLoad_v2::getSaveType(const char *fileName) {
+ const char *backSlash;
+ if ((backSlash = strrchr(fileName, '\\')))
+ fileName = backSlash + 1;
+
if (!scumm_stricmp(fileName, "cat.inf"))
return kSaveGame;
if (!scumm_stricmp(fileName, "cat.cat"))
diff --git a/engines/gob/saveload_v3.cpp b/engines/gob/saveload_v3.cpp
index b376a8a75c..d0f791d8df 100644
--- a/engines/gob/saveload_v3.cpp
+++ b/engines/gob/saveload_v3.cpp
@@ -34,9 +34,14 @@
namespace Gob {
-SaveLoad_v3::SaveLoad_v3(GobEngine *vm, const char *targetName) :
+SaveLoad_v3::SaveLoad_v3(GobEngine *vm, const char *targetName,
+ uint32 screenshotSize, int32 indexOffset, int32 screenshotOffset) :
SaveLoad_v2(vm, targetName) {
+ _screenshotSize = screenshotSize;
+ _indexOffset = indexOffset;
+ _screenshotOffset = screenshotOffset;
+
_saveSlot = -1;
_stagesCount = 3;
@@ -58,12 +63,18 @@ SaveLoad_v3::SaveLoad_v3(GobEngine *vm, const char *targetName) :
}
SaveType SaveLoad_v3::getSaveType(const char *fileName) {
+ const char *backSlash;
+ if ((backSlash = strrchr(fileName, '\\')))
+ fileName = backSlash + 1;
+
if (!scumm_stricmp(fileName, "cat.inf"))
return kSaveGame;
if (!scumm_stricmp(fileName, "ima.inf"))
return kSaveScreenshot;
if (!scumm_stricmp(fileName, "intro.$$$"))
return kSaveTempSprite;
+ if (!scumm_stricmp(fileName, "bloc.inf"))
+ return kSaveNotes;
if (!scumm_stricmp(fileName, "prot"))
return kSaveIgnore;
if (!scumm_stricmp(fileName, "config"))
@@ -77,15 +88,11 @@ uint32 SaveLoad_v3::getSaveGameSize() {
size = 1040 + (READ_LE_UINT32(_vm->_game->_totFileData + 0x2C) * 4) * 2;
if (_useScreenshots)
- size += 19968;
+ size += _screenshotSize;
return size;
}
-int32 SaveLoad_v3::getSizeNotes() {
- return -1;
-}
-
int32 SaveLoad_v3::getSizeGame() {
if (_firstSizeGame) {
_firstSizeGame = false;
@@ -122,7 +129,7 @@ int32 SaveLoad_v3::getSizeScreenshot() {
in = saveMan->openForLoading(setCurSlot(i));
if (in) {
delete in;
- size = (i + 1) * 19968 + 80;
+ size = (i + 1) * _screenshotSize + _screenshotOffset;
break;
}
}
@@ -206,19 +213,15 @@ bool SaveLoad_v3::loadGame(int16 dataVar, int32 size, int32 offset) {
return false;
}
-bool SaveLoad_v3::loadNotes(int16 dataVar, int32 size, int32 offset) {
- return false;
-}
-
bool SaveLoad_v3::loadScreenshot(int16 dataVar, int32 size, int32 offset) {
Common::SaveFileManager *saveMan = g_system->getSavefileManager();
Common::InSaveFile *in;
- int slot = (offset - 80) / 19968;
- int slotR = (offset - 80) % 19968;
+ int slot = (offset - _screenshotOffset) / _screenshotSize;
+ int slotR = (offset - _screenshotOffset) % _screenshotSize;
_useScreenshots = true;
- if ((size == 40) && (offset == 40)) {
+ if ((size == 40) && (offset == _indexOffset)) {
char buf[40];
memset(buf, 0, 40);
@@ -327,16 +330,16 @@ bool SaveLoad_v3::saveGame(int16 dataVar, int32 size, int32 offset) {
}
bool SaveLoad_v3::saveNotes(int16 dataVar, int32 size, int32 offset) {
- return false;
+ return SaveLoad_v2::saveNotes(dataVar, size - 160, offset);
}
bool SaveLoad_v3::saveScreenshot(int16 dataVar, int32 size, int32 offset) {
- int slot = (offset - 80) / 19968;
- int slotR = (offset - 80) % 19968;
+ int slot = (offset - _screenshotOffset) / _screenshotSize;
+ int slotR = (offset - _screenshotOffset) % _screenshotSize;
_useScreenshots = true;
- if ((offset < 80) && (size > 0)) {
+ if ((offset < _screenshotOffset) && (size > 0)) {
return true;
diff --git a/engines/gob/scenery.cpp b/engines/gob/scenery.cpp
index ae04c220d3..95cf90bddc 100644
--- a/engines/gob/scenery.cpp
+++ b/engines/gob/scenery.cpp
@@ -320,7 +320,7 @@ void Scenery::updateStatic(int16 orderFrom, byte index, byte layer) {
int16 top;
int16 bottom;
- if (layer >= _statics[index].layersCount)
+ if ((index >= 10) || layer >= _statics[index].layersCount)
return;
layerPtr = &_statics[index].layers[layer];
diff --git a/engines/gob/util.cpp b/engines/gob/util.cpp
index ff6333aa9e..40acf21f9e 100644
--- a/engines/gob/util.cpp
+++ b/engines/gob/util.cpp
@@ -32,7 +32,6 @@
#include "gob/dataio.h"
#include "gob/draw.h"
#include "gob/game.h"
-#include "gob/imd.h"
#include "gob/sound.h"
#include "gob/video.h"
@@ -50,6 +49,9 @@ uint32 Util::getTimeKey(void) {
}
int16 Util::getRandom(int16 max) {
+ if (max == 0)
+ return 0;
+
return _vm->_rnd.getRandomNumber(max - 1);
}
@@ -126,8 +128,8 @@ void Util::processInput(bool scroll) {
_vm->_global->_speedFactor = MIN(_fastMode + 1, 3);
if (scroll && hasMove) {
- if (y >= (200 - _vm->_video->_splitHeight2)) {
- y = 200 - _vm->_video->_splitHeight2 - 1;
+ if (y >= (_vm->_height - _vm->_video->_splitHeight2)) {
+ y = _vm->_height - _vm->_video->_splitHeight2 - 1;
_vm->_util->setMousePos(x, y);
}
_vm->_game->evaluateScroll(x, y);
@@ -301,7 +303,6 @@ void Util::setFrameRate(int16 rate) {
_vm->_global->_frameWaitTime = 1000 / rate;
_vm->_global->_startFrameTime = getTimeKey();
- _vm->_imdPlayer->_frameDelay = 0;
}
void Util::waitEndFrame() {
@@ -312,17 +313,13 @@ void Util::waitEndFrame() {
time = getTimeKey() - _vm->_global->_startFrameTime;
if ((time > 1000) || (time < 0)) {
_vm->_global->_startFrameTime = getTimeKey();
- _vm->_imdPlayer->_frameDelay = 0;
return;
}
- if (_vm->_global->_frameWaitTime - time > 0) {
- _vm->_imdPlayer->_frameDelay = 0;
- delay(_vm->_global->_frameWaitTime - _vm->_imdPlayer->_frameDelay - time);
- }
+ if ((_vm->_global->_frameWaitTime - time) > 0)
+ delay(_vm->_global->_frameWaitTime - time);
_vm->_global->_startFrameTime = getTimeKey();
- _vm->_imdPlayer->_frameDelay = time - _vm->_global->_frameWaitTime;
}
void Util::setScrollOffset(int16 x, int16 y) {
diff --git a/engines/gob/video.cpp b/engines/gob/video.cpp
index 6f88a5a993..0dc15a8657 100644
--- a/engines/gob/video.cpp
+++ b/engines/gob/video.cpp
@@ -94,6 +94,7 @@ Video::Video(GobEngine *vm) : _vm(vm) {
_splitHeight1 = 200;
_splitHeight2 = 0;
_splitStart = 0;
+ _lastRetraceLength = 0;
_curSparse = 0;
_lastSparse = 0xFFFFFFFF;
@@ -161,26 +162,27 @@ 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) {
g_system->copyRectToScreen(_vm->_global->_primarySurfDesc->getVidMem() +
_scrollOffsetY * _surfWidth + _scrollOffsetX, _surfWidth,
- 0, 0, 320, _splitHeight1);
+ 0, 0, _vm->_width, _splitHeight1);
if (_splitHeight2 > 0)
g_system->copyRectToScreen(_vm->_global->_primarySurfDesc->getVidMem() +
_splitStart * _surfWidth, _surfWidth, 0,
- 200 - _splitHeight2, 320, _splitHeight2);
+ _vm->_height - _splitHeight2, _vm->_width, _splitHeight2);
g_system->updateScreen();
}
+
+ _lastRetraceLength = _vm->_util->getTimeKey() - time;
}
void Video::waitRetrace(bool mouse) {
- uint32 time;
-
- time = _vm->_util->getTimeKey();
retrace(mouse);
- _vm->_util->delay(MAX(1, 10 - (int)(_vm->_util->getTimeKey() - time)));
+ _vm->_util->delay(MAX(1, 10 - (int) _lastRetraceLength));
}
void Video::sparseRetrace(int max) {
diff --git a/engines/gob/video.h b/engines/gob/video.h
index 51d02bd219..dc23bda81e 100644
--- a/engines/gob/video.h
+++ b/engines/gob/video.h
@@ -104,6 +104,7 @@ 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
new file mode 100644
index 0000000000..e72354a169
--- /dev/null
+++ b/engines/gob/videoplayer.cpp
@@ -0,0 +1,333 @@
+/* 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 "gob/videoplayer.h"
+#include "gob/global.h"
+#include "gob/util.h"
+#include "gob/dataio.h"
+#include "gob/video.h"
+#include "gob/draw.h"
+#include "gob/game.h"
+#include "gob/palanim.h"
+#include "gob/inter.h"
+
+namespace Gob {
+
+const char *VideoPlayer::_extensions[] = { "IMD", "VMD" };
+
+VideoPlayer::VideoPlayer(GobEngine *vm) : _vm(vm) {
+ _curFile[0] = 0;
+ _stream = 0;
+ _video = 0;
+ _backSurf = false;
+}
+
+VideoPlayer::~VideoPlayer() {
+ closeVideo();
+}
+
+bool VideoPlayer::openVideo(const char *video, int16 x, int16 y, int16 flags, Type which) {
+ char fileName[256];
+
+ strncpy0(fileName, video, 250);
+
+ char *extStart = strchr(fileName, '.');
+ if (extStart) {
+ // The requested file already has an extension. Verifying.
+
+ int i;
+ for (i = 0; i < ARRAYSIZE(_extensions); i++) {
+ if (!scumm_stricmp(extStart + 1, _extensions[i])) {
+ if ((which != kVideoTypeTry) && (which == ((Type) i))) {
+ warning("Attempted to open video \"%s\", "
+ "but requested a different type", fileName);
+ return false;
+ }
+ which = (Type) i;
+ break;
+ }
+ }
+ if (i >= ARRAYSIZE(_extensions))
+ extStart = 0;
+
+ }
+
+ if (!extStart) {
+ // No or unrecognized extension. Probing.
+
+ int len = strlen(fileName);
+
+ int i;
+ for (i = 0; i < ARRAYSIZE(_extensions); i++) {
+ if ((which == kVideoTypeTry) || (which == ((Type) i))) {
+ int16 handle;
+
+ fileName[len] = '.';
+ fileName[len + 1] = 0;
+ strcat(fileName, _extensions[i]);
+
+ handle = _vm->_dataIO->openData(fileName);
+ if (handle >= 0) {
+ _vm->_dataIO->closeData(handle);
+ which = (Type) i;
+ break;
+ }
+ }
+ }
+ if ((i >= ARRAYSIZE(_extensions)) || (which == kVideoTypeTry)) {
+ fileName[len] = 0;
+ warning("Couldn't open video \"%s\"", fileName);
+ return false;
+ }
+
+ }
+
+ if (scumm_strnicmp(_curFile, fileName, strlen(fileName))) {
+ closeVideo();
+
+ int16 handle = _vm->_dataIO->openData(fileName);
+
+ if (handle < 0) {
+ warning("Couldn't open video \"%s\": No such file", fileName);
+ return false;
+ }
+
+ _stream = _vm->_dataIO->openAsStream(handle, true);
+
+ if (which == kVideoTypeIMD) {
+ _video = new Imd();
+ } else if (which == kVideoTypeVMD) {
+ _video = new Vmd();
+ } else {
+ warning("Couldn't open video \"%s\": Invalid video Type", fileName);
+ closeVideo();
+ return false;
+ }
+
+ if (!_video->load(*_stream)) {
+ warning("While loading video \"%s\"", fileName);
+ closeVideo();
+ return false;
+ }
+
+ _video->setXY(x, y);
+
+ if (!(flags & kFlagNoVideo)) {
+ _backSurf = ((flags & kFlagFrontSurface) == 0);
+ SurfaceDesc::Ptr surf = _vm->_draw->_spritesArray[_backSurf ? 21 : 20];
+ _video->setVideoMemory(surf->getVidMem(), surf->getWidth(), surf->getHeight());
+ } else
+ _video->setVideoMemory();
+
+ _video->enableSound(*_vm->_mixer);
+ }
+
+ if (!_video)
+ return false;
+
+ WRITE_VAR(7, _video->getFramesCount());
+
+ return true;
+}
+
+void VideoPlayer::play(int16 startFrame, int16 lastFrame, int16 breakKey,
+ uint16 palCmd, int16 palStart, int16 palEnd,
+ int16 palFrame, int16 endFrame, bool fade, int16 reverseTo) {
+
+ if (!_video)
+ return;
+
+ breakKey = 27;
+ if (startFrame < 0)
+ startFrame = _video->getCurrentFrame();
+ if (lastFrame < 0)
+ lastFrame = _video->getFramesCount() - 1;
+ if (palFrame < 0)
+ palFrame = startFrame;
+ if (endFrame < 0)
+ endFrame = lastFrame;
+ palCmd &= 0x3F;
+
+ if (_video->getCurrentFrame() != startFrame)
+ _video->seekFrame(startFrame);
+
+ _vm->_draw->_showCursor = 0;
+ _vm->_util->setFrameRate(12);
+
+ if (fade)
+ _vm->_palAnim->fade(0, -2, 0);
+
+ while (startFrame <= lastFrame) {
+ if (doPlay(startFrame, breakKey, palCmd, palStart, palEnd, palFrame, endFrame))
+ break;
+
+ if (fade) {
+ _vm->_palAnim->fade(_vm->_global->_pPaletteDesc, -2, 0);
+ fade = false;
+ }
+
+ _video->waitEndFrame();
+ startFrame++;
+ }
+
+ if (reverseTo >= 0) {
+ int16 toFrame = _video->getFramesCount() - reverseTo;
+ for (int i = _video->getCurrentFrame(); i >= toFrame; i--) {
+ _video->seekFrame(i, SEEK_SET, true);
+ if (doPlay(i, breakKey, 0, 0, 0, 0, 0)) {
+ _vm->_palAnim->fade(0, -2, 0);
+ memset((char *) _vm->_draw->_vgaPalette, 0, 768);
+ }
+ _video->waitEndFrame();
+ }
+ }
+}
+
+int16 VideoPlayer::getFramesCount() const {
+ if (!_video)
+ return 0;
+
+ return _video->getFramesCount();
+}
+
+int16 VideoPlayer::getCurrentFrame() const {
+ if (!_video)
+ return 0;
+
+ return _video->getCurrentFrame();
+}
+
+bool VideoPlayer::doPlay(int16 frame, int16 breakKey,
+ uint16 palCmd, int16 palStart, int16 palEnd,
+ int16 palFrame, int16 endFrame) {
+
+ bool modifiedPal = false;
+
+ if ((frame == palFrame) || ((frame == endFrame) && (palCmd == 8))) {
+ modifiedPal = true;
+ _vm->_draw->_applyPal = true;
+
+ if (palCmd >= 4)
+ copyPalette(palStart, palEnd);
+ }
+
+ if (modifiedPal && (palCmd == 8) && !_backSurf)
+ _vm->_video->setFullPalette(_vm->_global->_pPaletteDesc);
+
+
+ CoktelVideo::State state = _video->nextFrame();
+ WRITE_VAR(11, frame);
+
+
+ if (modifiedPal && (palCmd == 16)) {
+ if (_backSurf)
+ _vm->_draw->forceBlit();
+ _vm->_palAnim->fade(_vm->_global->_pPaletteDesc, -2, 0);
+ _vm->_draw->_noInvalidated = true;
+ }
+
+ if (state.flags & CoktelVideo::kStatePalette) {
+ copyPalette(palStart, palEnd);
+
+ if (!_backSurf)
+ _vm->_video->setFullPalette(_vm->_global->_pPaletteDesc);
+ else
+ _vm->_draw->_applyPal = true;
+ }
+
+ if (modifiedPal && (palCmd == 8) && _backSurf)
+ _vm->_video->setFullPalette(_vm->_global->_pPaletteDesc);
+
+
+ if (_backSurf) {
+ _vm->_draw->invalidateRect(state.left, state.top, state.right, state.bottom);
+ _vm->_draw->blitInvalidated();
+ }
+ _vm->_video->retrace();
+
+
+ if (modifiedPal && ((palCmd == 2) || (palCmd == 4)))
+ _vm->_palAnim->fade(_vm->_global->_pPaletteDesc, -2, 0);
+
+
+ _vm->_util->processInput();
+
+ if (_vm->_quitRequested) {
+ _video->disableSound();
+ return true;
+ }
+
+ if (breakKey != 0) {
+ _vm->_util->getMouseState(&_vm->_global->_inter_mouseX,
+ &_vm->_global->_inter_mouseY, &_vm->_game->_mouseButtons);
+
+ _vm->_inter->storeKey(_vm->_util->checkKey());
+ if (VAR(0) == (unsigned) breakKey) {
+ _video->disableSound();
+ return true;
+ }
+ }
+
+ return false;
+}
+
+void VideoPlayer::copyPalette(int16 palStart, int16 palEnd) {
+ if ((palStart == -1) || (palEnd == -1))
+ memcpy((char *) _vm->_global->_pPaletteDesc->vgaPal,
+ _video->getPalette(), 768);
+ else
+ memcpy(((char *) (_vm->_global->_pPaletteDesc->vgaPal)) +
+ palStart * 3, _video->getPalette() + palStart * 3,
+ (palEnd - palStart + 1) * 3);
+}
+
+void VideoPlayer::writeVideoInfo(const char *video, int16 varX, int16 varY,
+ int16 varFrames, int16 varWidth, int16 varHeight) {
+
+ if (openVideo(video)) {
+ WRITE_VAR_OFFSET(varX, _video->getX());
+ WRITE_VAR_OFFSET(varY, _video->getY());
+ WRITE_VAR_OFFSET(varFrames, _video->getFramesCount());
+ WRITE_VAR_OFFSET(varWidth, _video->getWidth());
+ WRITE_VAR_OFFSET(varHeight, _video->getHeight());
+ closeVideo();
+ } else {
+ WRITE_VAR_OFFSET(varX, -1);
+ WRITE_VAR_OFFSET(varY, -1);
+ WRITE_VAR_OFFSET(varFrames, -1);
+ WRITE_VAR_OFFSET(varWidth, -1);
+ WRITE_VAR_OFFSET(varHeight, -1);
+ }
+}
+
+void VideoPlayer::closeVideo() {
+ delete _video;
+ delete _stream;
+
+ _video = 0;
+ _stream = 0;
+}
+
+} // End of namespace Gob
diff --git a/engines/gob/videoplayer.h b/engines/gob/videoplayer.h
new file mode 100644
index 0000000000..c4c608dc99
--- /dev/null
+++ b/engines/gob/videoplayer.h
@@ -0,0 +1,86 @@
+/* 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 GOB_VIDEOPLAYER_H
+#define GOB_VIDEOPLAYER_H
+
+#include "gob/coktelvideo.h"
+#include "gob/dataio.h"
+
+namespace Gob {
+
+class GobEngine;
+
+class VideoPlayer {
+public:
+ enum Flags {
+ kFlagNone = 0,
+ kFlagFrontSurface = 0x80,
+ kFlagNoVideo = 0x100
+ };
+
+ enum Type {
+ kVideoTypeTry = -1,
+ kVideoTypeIMD = 0,
+ kVideoTypeVMD = 1
+ };
+
+ VideoPlayer(GobEngine *vm);
+ ~VideoPlayer();
+
+ bool openVideo(const char *video, int16 x = -1, int16 y = -1,
+ int16 flags = kFlagFrontSurface, Type which = kVideoTypeTry);
+
+ void play(int16 startFrame = -1, int16 lastFrame = -1, int16 breakKey = 27,
+ uint16 palCmd = 8, int16 palStart = 0, int16 palEnd = 255,
+ int16 palFrame = -1, int16 endFrame = -1, bool fade = false,
+ int16 reverseTo = -1);
+
+ int16 getFramesCount() const;
+ int16 getCurrentFrame() const;
+ void writeVideoInfo(const char *video, int16 varX, int16 varY,
+ int16 varFrames, int16 varWidth, int16 varHeight);
+
+ void closeVideo();
+
+private:
+ static const char *_extensions[];
+
+ GobEngine *_vm;
+
+ char _curFile[256];
+ DataStream *_stream;
+ CoktelVideo *_video;
+ bool _backSurf;
+
+ void copyPalette(int16 palStart = -1, int16 palEnd = -1);
+ bool doPlay(int16 frame, int16 breakKey,
+ uint16 palCmd, int16 palStart, int16 palEnd,
+ int16 palFrame, int16 endFrame);
+};
+
+} // End of namespace Gob
+
+#endif // GOB_VIDEOPLAYER_H
diff --git a/engines/kyra/animator.cpp b/engines/kyra/animator_v1.cpp
index 7683bb6417..4169b59a36 100644
--- a/engines/kyra/animator.cpp
+++ b/engines/kyra/animator_v1.cpp
@@ -26,15 +26,15 @@
#include "common/stdafx.h"
#include "common/endian.h"
-#include "kyra/kyra.h"
+#include "kyra/kyra_v1.h"
#include "kyra/screen.h"
-#include "kyra/animator.h"
+#include "kyra/animator_v1.h"
#include "kyra/sprites.h"
#include "common/system.h"
namespace Kyra {
-ScreenAnimator::ScreenAnimator(KyraEngine *vm, OSystem *system) {
+ScreenAnimator::ScreenAnimator(KyraEngine_v1 *vm, OSystem *system) {
_vm = vm;
_screen = vm->screen();
_initOk = false;
diff --git a/engines/kyra/animator.h b/engines/kyra/animator_v1.h
index e817be86d5..8b554adf12 100644
--- a/engines/kyra/animator.h
+++ b/engines/kyra/animator_v1.h
@@ -27,7 +27,7 @@
#define KYRA_ANIMATOR_H
namespace Kyra {
-class KyraEngine;
+class KyraEngine_v1;
class Screen;
struct AnimObject {
@@ -53,7 +53,7 @@ struct AnimObject {
class ScreenAnimator {
public:
- ScreenAnimator(KyraEngine *vm, OSystem *system);
+ ScreenAnimator(KyraEngine_v1 *vm, OSystem *system);
virtual ~ScreenAnimator();
operator bool() const { return _initOk; }
@@ -101,7 +101,7 @@ public:
int _brandonScaleY;
protected:
- KyraEngine *_vm;
+ KyraEngine_v1 *_vm;
Screen *_screen;
OSystem *_system;
bool _initOk;
diff --git a/engines/kyra/animator_v2.cpp b/engines/kyra/animator_v2.cpp
new file mode 100644
index 0000000000..179bdd140d
--- /dev/null
+++ b/engines/kyra/animator_v2.cpp
@@ -0,0 +1,313 @@
+/* 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 "kyra/kyra_v2.h"
+#include "kyra/wsamovie.h"
+
+namespace Kyra {
+
+void KyraEngine_v2::clearAnimObjects() {
+ memset(_animObjects, 0, sizeof(_animObjects));
+
+ _animObjects[0].index = 0;
+ _animObjects[0].type = 0;
+ _animObjects[0].enabled = 1;
+ _animObjects[0].flags = 0x800;
+ _animObjects[0].width = 32;
+ _animObjects[0].height = 49;
+ _animObjects[0].width2 = 4;
+ _animObjects[0].height2 = 10;
+
+ for (int i = 1; i < 11; ++i) {
+ _animObjects[i].index = i;
+ _animObjects[i].type = 2;
+ }
+
+ for (int i = 11; i <= 40; ++i) {
+ _animObjects[i].index = i;
+ _animObjects[i].type = 1;
+ _animObjects[i].flags = 0x800;
+ _animObjects[i].width = 16;
+ _animObjects[i].height = 16;
+ }
+}
+
+KyraEngine_v2::AnimObj *KyraEngine_v2::initAnimList(AnimObj *list, AnimObj *entry) {
+ entry->nextObject = list;
+ return entry;
+}
+
+KyraEngine_v2::AnimObj *KyraEngine_v2::addToAnimListSorted(AnimObj *list, AnimObj *add) {
+ if (add->yPos1 <= list->yPos1) {
+ add->nextObject = list;
+ return add;
+ }
+
+ AnimObj *cur = list;
+ AnimObj *prev = list;
+ while (add->yPos1 > cur->yPos1) {
+ AnimObj *temp = cur->nextObject;
+ if (!temp)
+ break;
+ prev = cur;
+ cur = temp;
+ }
+
+ if (add->yPos1 <= cur->yPos1) {
+ prev->nextObject = add;
+ add->nextObject = cur;
+ } else {
+ cur->nextObject = add;
+ add->nextObject = 0;
+ }
+ return list;
+}
+
+KyraEngine_v2::AnimObj *KyraEngine_v2::deleteAnimListEntry(AnimObj *list, AnimObj *entry) {
+ if (!list)
+ return 0;
+
+ AnimObj *old = 0;
+ AnimObj *cur = list;
+
+ while (true) {
+ if (cur == entry)
+ break;
+ if (!cur->nextObject)
+ break;
+ old = cur;
+ cur = cur->nextObject;
+ }
+
+ if (cur == list) {
+ if (!cur->nextObject)
+ return 0;
+ cur = cur->nextObject;
+ return cur;
+ }
+
+ if (!cur->nextObject) {
+ if (!old)
+ return 0;
+ old->nextObject = 0;
+ return list;
+ }
+
+ if (cur != entry)
+ return list;
+
+ old->nextObject = entry->nextObject;
+ return list;
+}
+
+void KyraEngine_v2::drawAnimObjects() {
+ for (AnimObj *curObject = _animList; curObject; curObject = curObject->nextObject) {
+ if (!curObject->enabled)
+ continue;
+
+ int x = curObject->xPos2 - (_screen->getScreenDim(2)->sx << 3);
+ int y = curObject->yPos2 - _screen->getScreenDim(2)->sy;
+ int layer = 7;
+
+ if (curObject->flags & 0x800) {
+ if (curObject->animFlags)
+ layer = 0;
+ else
+ layer = getDrawLayer(curObject->xPos1, curObject->yPos1);
+ }
+ curObject->flags |= 0x800;
+
+ if (curObject->index)
+ drawSceneAnimObject(curObject, x, y, layer);
+ else
+ drawCharacterAnimObject(curObject, x, y, layer);
+ }
+}
+
+void KyraEngine_v2::refreshAnimObjects(int force) {
+ for (AnimObj *curObject = _animList; curObject; curObject = curObject->nextObject) {
+ if (!curObject->enabled)
+ continue;
+ if (!curObject->needRefresh && !force)
+ continue;
+
+ int x = curObject->xPos2 - curObject->width2;
+ if (x < 0)
+ x = 0;
+ if (x >= 320)
+ x = 319;
+ int y = curObject->yPos2 - curObject->height2;
+ if (y < 0)
+ y = 0;
+ if (y >= 143)
+ y = 142;
+
+ int width = curObject->width + curObject->width2 + 8;
+ int height = curObject->height + curObject->height2*2;
+ if (width + x > 320)
+ width -= width + x - 322;
+ if (height + y > 143)
+ height -= height + y - 144;
+
+ _screen->hideMouse();
+ _screen->copyRegion(x, y, x, y, width, height, 2, 0, Screen::CR_CLIPPED);
+ _screen->showMouse();
+
+ curObject->needRefresh = false;
+ }
+}
+
+void KyraEngine_v2::refreshAnimObjectsIfNeed() {
+ for (AnimObj *curEntry = _animList; curEntry; curEntry = curEntry->nextObject) {
+ if (curEntry->enabled && curEntry->needRefresh) {
+ restorePage3();
+ drawAnimObjects();
+ refreshAnimObjects(0);
+ _screen->updateScreen();
+ return;
+ }
+ }
+}
+
+void KyraEngine_v2::updateCharacterAnim(int) {
+ Character *c = &_mainCharacter;
+ AnimObj *animState = _animObjects;
+
+ animState->needRefresh = 1;
+ animState->unk8 = 1;
+
+ if (c->facing >= 1 && c->facing <= 3)
+ animState->flags |= 1;
+ else if (c->facing >= 5 && c->facing <= 7)
+ animState->flags &= ~1;
+
+ animState->xPos2 = animState->xPos1 = c->x1;
+ animState->yPos2 = animState->yPos1 = c->y1;
+ animState->shapePtr = _defaultShapeTable[c->animFrame];
+ animState->shapeIndex1 = animState->shapeIndex2 = c->animFrame;
+
+ int xAdd = _shapeDescTable[c->animFrame-9].xAdd;
+ int yAdd = _shapeDescTable[c->animFrame-9].yAdd;
+
+ _charScaleX = _charScaleY = getScale(c->x1, c->y1);
+
+ animState->xPos2 += (xAdd * _charScaleX) >> 8;
+ animState->yPos2 += (yAdd * _charScaleY) >> 8;
+ animState->width2 = 8;
+ animState->height2 = 10;
+
+ _animList = deleteAnimListEntry(_animList, animState);
+ if (_animList)
+ _animList = addToAnimListSorted(_animList, animState);
+ else
+ _animList = initAnimList(_animList, animState);
+
+ updateCharPal(1);
+}
+
+void KyraEngine_v2::updateSceneAnim(int anim, int newFrame) {
+ AnimObj *animObject = &_animObjects[1+anim];
+ if (!animObject->enabled)
+ return;
+
+ animObject->needRefresh = 1;
+ animObject->unk8 = 1;
+ animObject->flags = 0;
+
+ if (_sceneAnims[anim].flags & 2)
+ animObject->flags |= 0x800;
+ else
+ animObject->flags &= ~0x800;
+
+ if (_sceneAnims[anim].flags & 4)
+ animObject->flags |= 1;
+ else
+ animObject->flags &= ~1;
+
+ if (_sceneAnims[anim].flags & 0x20) {
+ animObject->shapePtr = _sceneShapeTable[newFrame];
+ animObject->shapeIndex2 = 0xFFFF;
+ animObject->shapeIndex3 = 0xFFFF;
+ animObject->animNum = 0xFFFF;
+ } else {
+ animObject->shapePtr = 0;
+ animObject->shapeIndex3 = newFrame;
+ animObject->animNum = anim;
+ }
+
+ animObject->xPos1 = _sceneAnims[anim].x;
+ animObject->yPos1 = _sceneAnims[anim].y;
+ animObject->xPos2 = _sceneAnims[anim].x2;
+ animObject->yPos2 = _sceneAnims[anim].y2;
+
+ if (_sceneAnims[anim].flags & 2) {
+ _animList = deleteAnimListEntry(_animList, animObject);
+ if (!_animList)
+ _animList = initAnimList(_animList, animObject);
+ else
+ _animList = addToAnimListSorted(_animList, animObject);
+ }
+}
+
+void KyraEngine_v2::drawSceneAnimObject(AnimObj *obj, int x, int y, int layer) {
+ if (obj->type == 1) {
+ if (obj->shapeIndex1 == 0xFFFF)
+ return;
+ int scale = getScale(obj->xPos1, obj->yPos1);
+ _screen->drawShape(2, getShapePtr(obj->shapeIndex1), x, y, 2, obj->flags | 4, layer, scale, scale);
+ return;
+ }
+
+ if (obj->shapePtr) {
+ _screen->drawShape(2, obj->shapePtr, x, y, 2, obj->flags, layer);
+ } else {
+ if (obj->shapeIndex3 == 0xFFFF || obj->animNum == 0xFFFF)
+ return;
+
+ int flags = 0x4000;
+ if (obj->flags & 0x800)
+ flags |= 0x8000;
+
+ if (_sceneAnims[obj->animNum].wsaFlag) {
+ x = y = 0;
+ } else {
+ x = obj->xPos2;
+ y = obj->yPos2;
+ }
+
+ _sceneAnimMovie[obj->animNum]->setX(x);
+ _sceneAnimMovie[obj->animNum]->setY(y);
+ _sceneAnimMovie[obj->animNum]->setDrawPage(2);
+ _sceneAnimMovie[obj->animNum]->displayFrame(obj->shapeIndex3, int(flags | layer), 0, 0);
+ }
+}
+
+void KyraEngine_v2::drawCharacterAnimObject(AnimObj *obj, int x, int y, int layer) {
+ if (_drawNoShapeFlag || obj->shapeIndex1 == 0xFFFF)
+ return;
+ _screen->drawShape(2, getShapePtr(obj->shapeIndex1), x, y, 2, obj->flags | 4, layer, _charScaleX, _charScaleY);
+}
+
+} // end of namespace Kyra
diff --git a/engines/kyra/debugger.cpp b/engines/kyra/debugger.cpp
index d5909bd8b0..152dc21c61 100644
--- a/engines/kyra/debugger.cpp
+++ b/engines/kyra/debugger.cpp
@@ -27,35 +27,36 @@
#include "common/config-manager.h"
#include "common/system.h"
#include "kyra/debugger.h"
-#include "kyra/kyra.h"
+#include "kyra/kyra_v1.h"
#include "kyra/screen.h"
+#include "kyra/timer.h"
namespace Kyra {
-Debugger::Debugger(KyraEngine *vm)
- : GUI::Debugger() {
+Debugger_v1::Debugger_v1(KyraEngine_v1 *vm)
+ : Debugger(vm) {
_vm = vm;
- DCmd_Register("continue", WRAP_METHOD(Debugger, Cmd_Exit));
- DCmd_Register("enter", WRAP_METHOD(Debugger, cmd_enterRoom));
- DCmd_Register("rooms", WRAP_METHOD(Debugger, cmd_listRooms));
- DCmd_Register("flags", WRAP_METHOD(Debugger, cmd_listFlags));
- DCmd_Register("toggleflag", WRAP_METHOD(Debugger, cmd_toggleFlag));
- DCmd_Register("queryflag", WRAP_METHOD(Debugger, cmd_queryFlag));
- DCmd_Register("timers", WRAP_METHOD(Debugger, cmd_listTimers));
- DCmd_Register("settimercountdown", WRAP_METHOD(Debugger, cmd_setTimerCountdown));
- DCmd_Register("give", WRAP_METHOD(Debugger, cmd_giveItem));
+ DCmd_Register("continue", WRAP_METHOD(Debugger_v1, Cmd_Exit));
+ DCmd_Register("enter", WRAP_METHOD(Debugger_v1, cmd_enterRoom));
+ DCmd_Register("rooms", WRAP_METHOD(Debugger_v1, cmd_listRooms));
+ DCmd_Register("flags", WRAP_METHOD(Debugger_v1, cmd_listFlags));
+ DCmd_Register("toggleflag", WRAP_METHOD(Debugger_v1, cmd_toggleFlag));
+ DCmd_Register("queryflag", WRAP_METHOD(Debugger_v1, cmd_queryFlag));
+ DCmd_Register("timers", WRAP_METHOD(Debugger_v1, cmd_listTimers));
+ DCmd_Register("settimercountdown", WRAP_METHOD(Debugger_v1, cmd_setTimerCountdown));
+ DCmd_Register("give", WRAP_METHOD(Debugger_v1, cmd_giveItem));
}
-void Debugger::preEnter() {
+void Debugger_v1::preEnter() {
//_vm->midi.pause(1);
}
-void Debugger::postEnter() {
+void Debugger_v1::postEnter() {
//_vm->midi.pause(0);
}
-bool Debugger::cmd_enterRoom(int argc, const char **argv) {
+bool Debugger_v1::cmd_enterRoom(int argc, const char **argv) {
uint direction = 0;
if (argc > 1) {
int room = atoi(argv[1]);
@@ -93,7 +94,7 @@ bool Debugger::cmd_enterRoom(int argc, const char **argv) {
return true;
}
-bool Debugger::cmd_listRooms(int argc, const char **argv) {
+bool Debugger_v1::cmd_listRooms(int argc, const char **argv) {
for (int i = 0; i < _vm->_roomTableSize; i++) {
DebugPrintf("%-3i: %-10s", i, _vm->_roomFilenameTable[_vm->_roomTable[i].nameIndex]);
if (!(i % 8))
@@ -104,7 +105,7 @@ bool Debugger::cmd_listRooms(int argc, const char **argv) {
return true;
}
-bool Debugger::cmd_listFlags(int argc, const char **argv) {
+bool Debugger_v1::cmd_listFlags(int argc, const char **argv) {
for (int i = 0; i < (int)sizeof(_vm->_flagsTable)*8; i++) {
DebugPrintf("(%-3i): %-5i", i, _vm->queryGameFlag(i));
if (!(i % 10))
@@ -114,7 +115,7 @@ bool Debugger::cmd_listFlags(int argc, const char **argv) {
return true;
}
-bool Debugger::cmd_toggleFlag(int argc, const char **argv) {
+bool Debugger_v1::cmd_toggleFlag(int argc, const char **argv) {
if (argc > 1) {
uint flag = atoi(argv[1]);
if (_vm->queryGameFlag(flag))
@@ -129,7 +130,7 @@ bool Debugger::cmd_toggleFlag(int argc, const char **argv) {
return true;
}
-bool Debugger::cmd_queryFlag(int argc, const char **argv) {
+bool Debugger_v1::cmd_queryFlag(int argc, const char **argv) {
if (argc > 1) {
uint flag = atoi(argv[1]);
DebugPrintf("Flag %i is %i\n", flag, _vm->queryGameFlag(flag));
@@ -140,19 +141,19 @@ bool Debugger::cmd_queryFlag(int argc, const char **argv) {
return true;
}
-bool Debugger::cmd_listTimers(int argc, const char **argv) {
- for (int i = 0; i < ARRAYSIZE(_vm->_timers); i++)
- DebugPrintf("Timer %-2i: Active: %-3s Countdown: %-6i\n", i, _vm->_timers[i].active ? "Yes" : "No", _vm->_timers[i].countdown);
+bool Debugger_v1::cmd_listTimers(int argc, const char **argv) {
+ for (int i = 0; i < _vm->timer()->count(); i++)
+ DebugPrintf("Timer %-2i: Active: %-3s Countdown: %-6i\n", i, _vm->timer()->isEnabled(i) ? "Yes" : "No", _vm->timer()->getDelay(i));
return true;
}
-bool Debugger::cmd_setTimerCountdown(int argc, const char **argv) {
+bool Debugger_v1::cmd_setTimerCountdown(int argc, const char **argv) {
if (argc > 2) {
uint timer = atoi(argv[1]);
uint countdown = atoi(argv[2]);
- _vm->setTimerCountdown(timer, countdown);
- DebugPrintf("Timer %i now has countdown %i\n", timer, _vm->_timers[timer].countdown);
+ _vm->timer()->setCountdown(timer, countdown);
+ DebugPrintf("Timer %i now has countdown %i\n", timer, _vm->timer()->getDelay(timer));
} else {
DebugPrintf("Syntax: settimercountdown <timer> <countdown>\n");
}
@@ -160,7 +161,7 @@ bool Debugger::cmd_setTimerCountdown(int argc, const char **argv) {
return true;
}
-bool Debugger::cmd_giveItem(int argc, const char **argv) {
+bool Debugger_v1::cmd_giveItem(int argc, const char **argv) {
if (argc == 2) {
int item = atoi(argv[1]);
diff --git a/engines/kyra/debugger.h b/engines/kyra/debugger.h
index 2d0e82c220..16b1e42a58 100644
--- a/engines/kyra/debugger.h
+++ b/engines/kyra/debugger.h
@@ -31,14 +31,21 @@
namespace Kyra {
class KyraEngine;
+class KyraEngine_v1;
class Debugger : public GUI::Debugger {
public:
- Debugger(KyraEngine *vm);
+ Debugger(KyraEngine *vm) {}
virtual ~Debugger() {} // we need this for __SYMBIAN32__ archaic gcc/UIQ
+};
+
+class Debugger_v1 : public Debugger {
+public:
+ Debugger_v1(KyraEngine_v1 *vm);
+ virtual ~Debugger_v1() {} // we need this for __SYMBIAN32__ archaic gcc/UIQ
protected:
- KyraEngine *_vm;
+ KyraEngine_v1 *_vm;
virtual void preEnter();
virtual void postEnter();
diff --git a/engines/kyra/detection.cpp b/engines/kyra/detection.cpp
index e1b5a2b7c3..02b505b177 100644
--- a/engines/kyra/detection.cpp
+++ b/engines/kyra/detection.cpp
@@ -73,6 +73,8 @@ const KYRAGameDescription adGameDescs[] = {
{ { "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
diff --git a/engines/kyra/gui.cpp b/engines/kyra/gui_v1.cpp
index 6fc347158f..b7692cc97d 100644
--- a/engines/kyra/gui.cpp
+++ b/engines/kyra/gui_v1.cpp
@@ -23,11 +23,11 @@
*
*/
-#include "kyra/kyra.h"
+#include "kyra/kyra_v1.h"
#include "kyra/screen.h"
#include "kyra/script.h"
#include "kyra/text.h"
-#include "kyra/animator.h"
+#include "kyra/animator_v1.h"
#include "kyra/sound.h"
#include "common/config-manager.h"
@@ -37,14 +37,14 @@
namespace Kyra {
-void KyraEngine::registerDefaultSettings() {
+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);
}
-void KyraEngine::readSettings() {
+void KyraEngine_v1::readSettings() {
int talkspeed = ConfMan.getInt("talkspeed");
// The default talk speed is 60. This should be mapped to "Normal".
@@ -78,7 +78,7 @@ void KyraEngine::readSettings() {
setWalkspeed(_configWalkspeed);
}
-void KyraEngine::writeSettings() {
+void KyraEngine_v1::writeSettings() {
bool speechMute, subtitles;
int talkspeed;
@@ -130,14 +130,14 @@ void KyraEngine::writeSettings() {
ConfMan.flushToDisk();
}
-void KyraEngine::initMainButtonList() {
+void KyraEngine_v1::initMainButtonList() {
_haveScrollButtons = false;
_buttonList = &_buttonData[0];
for (int i = 0; _buttonDataListPtr[i]; ++i)
_buttonList = initButton(_buttonList, _buttonDataListPtr[i]);
}
-Button *KyraEngine::initButton(Button *list, Button *newButton) {
+Button *KyraEngine_v1::initButton(Button *list, Button *newButton) {
if (!newButton)
return list;
if (!list)
@@ -154,7 +154,7 @@ Button *KyraEngine::initButton(Button *list, Button *newButton) {
return list;
}
-int KyraEngine::buttonInventoryCallback(Button *caller) {
+int KyraEngine_v1::buttonInventoryCallback(Button *caller) {
int itemOffset = caller->specialValue - 2;
uint8 inventoryItem = _currentCharacter->inventoryItems[itemOffset];
if (_itemInHand == -1) {
@@ -198,7 +198,7 @@ int KyraEngine::buttonInventoryCallback(Button *caller) {
return 0;
}
-int KyraEngine::buttonAmuletCallback(Button *caller) {
+int KyraEngine_v1::buttonAmuletCallback(Button *caller) {
if (!(_deathHandler & 8))
return 1;
int jewel = caller->specialValue - 0x14;
@@ -294,7 +294,7 @@ int KyraEngine::buttonAmuletCallback(Button *caller) {
return 1;
}
-void KyraEngine::processButtonList(Button *list) {
+void KyraEngine_v1::processButtonList(Button *list) {
if (_haveScrollButtons) {
if (_mouseWheel < 0)
gui_scrollUp(&_scrollUpButton);
@@ -367,7 +367,7 @@ void KyraEngine::processButtonList(Button *list) {
}
}
-void KyraEngine::processButton(Button *button) {
+void KyraEngine_v1::processButton(Button *button) {
if (!button)
return;
@@ -411,7 +411,7 @@ void KyraEngine::processButton(Button *button) {
(this->*callback)(button);
}
-void KyraEngine::processAllMenuButtons() {
+void KyraEngine_v1::processAllMenuButtons() {
if (!_menuButtonList)
return;
@@ -425,7 +425,7 @@ void KyraEngine::processAllMenuButtons() {
return;
}
-void KyraEngine::processMenuButton(Button *button) {
+void KyraEngine_v1::processMenuButton(Button *button) {
if (!_displayMenu)
return;
@@ -449,7 +449,7 @@ void KyraEngine::processMenuButton(Button *button) {
processButton(button);
}
-int KyraEngine::drawBoxCallback(Button *button) {
+int KyraEngine_v1::drawBoxCallback(Button *button) {
if (!_displayMenu)
return 0;
@@ -460,7 +460,7 @@ int KyraEngine::drawBoxCallback(Button *button) {
return 0;
}
-int KyraEngine::drawShadedBoxCallback(Button *button) {
+int KyraEngine_v1::drawShadedBoxCallback(Button *button) {
if (!_displayMenu)
return 0;
@@ -471,7 +471,7 @@ int KyraEngine::drawShadedBoxCallback(Button *button) {
return 0;
}
-void KyraEngine::setGUILabels() {
+void KyraEngine_v1::setGUILabels() {
int offset = 0;
int offsetOptions = 0;
int offsetMainMenu = 0;
@@ -485,7 +485,7 @@ void KyraEngine::setGUILabels() {
offset = 52;
else if (_flags.lang == Common::DE_DEU)
offset = 30;
- else if (_flags.lang == Common::FR_FRA)
+ else if (_flags.lang == Common::FR_FRA || _flags.lang == Common::IT_ITA)
offset = 6;
offsetOn = offsetMainMenu = offsetOptions = offset;
walkspeedGarbageOffset = 48;
@@ -561,7 +561,7 @@ void KyraEngine::setGUILabels() {
_onCDString = _guiStrings[21];
}
-int KyraEngine::buttonMenuCallback(Button *caller) {
+int KyraEngine_v1::buttonMenuCallback(Button *caller) {
_displayMenu = true;
assert(_guiStrings);
@@ -584,9 +584,9 @@ int KyraEngine::buttonMenuCallback(Button *caller) {
_screen->setPaletteIndex(0xFE, 60, 60, 0);
for (int i = 0; i < 6; i++) {
_menuButtonData[i].process0 = _menuButtonData[i].process1 = _menuButtonData[i].process2 = 4;
- _menuButtonData[i].process0PtrCallback = &KyraEngine::drawShadedBoxCallback;
- _menuButtonData[i].process1PtrCallback = &KyraEngine::drawBoxCallback;
- _menuButtonData[i].process2PtrCallback = &KyraEngine::drawShadedBoxCallback;
+ _menuButtonData[i].process0PtrCallback = &KyraEngine_v1::drawShadedBoxCallback;
+ _menuButtonData[i].process1PtrCallback = &KyraEngine_v1::drawBoxCallback;
+ _menuButtonData[i].process2PtrCallback = &KyraEngine_v1::drawShadedBoxCallback;
}
_screen->savePageToDisk("SEENPAGE.TMP", 0);
@@ -627,7 +627,7 @@ int KyraEngine::buttonMenuCallback(Button *caller) {
return 0;
}
-void KyraEngine::initMenu(Menu &menu) {
+void KyraEngine_v1::initMenu(Menu &menu) {
_menuButtonList = 0;
_screen->hideMouse();
@@ -707,14 +707,14 @@ void KyraEngine::initMenu(Menu &menu) {
_scrollUpButton.x = menu.scrollUpBtnX + menu.x;
_scrollUpButton.y = menu.scrollUpBtnY + menu.y;
- _scrollUpButton.buttonCallback = &KyraEngine::gui_scrollUp;
+ _scrollUpButton.buttonCallback = &KyraEngine_v1::gui_scrollUp;
_scrollUpButton.nextButton = 0;
_menuButtonList = initButton(_menuButtonList, &_scrollUpButton);
processMenuButton(&_scrollUpButton);
_scrollDownButton.x = menu.scrollDownBtnX + menu.x;
_scrollDownButton.y = menu.scrollDownBtnY + menu.y;
- _scrollDownButton.buttonCallback = &KyraEngine::gui_scrollDown;
+ _scrollDownButton.buttonCallback = &KyraEngine_v1::gui_scrollDown;
_scrollDownButton.nextButton = 0;
_menuButtonList = initButton(_menuButtonList, &_scrollDownButton);
processMenuButton(&_scrollDownButton);
@@ -726,7 +726,7 @@ void KyraEngine::initMenu(Menu &menu) {
_screen->updateScreen();
}
-void KyraEngine::calcCoords(Menu &menu) {
+void KyraEngine_v1::calcCoords(Menu &menu) {
assert(menu.nrOfItems < 7);
int widthBackup = _screen->_charWidth;
@@ -798,7 +798,7 @@ void KyraEngine::calcCoords(Menu &menu) {
_screen->_charWidth = widthBackup;
}
-void KyraEngine::gui_getInput() {
+void KyraEngine_v1::gui_getInput() {
Common::Event event;
static uint32 lastScreenUpdate = 0;
uint32 now = _system->getMillis();
@@ -841,22 +841,22 @@ void KyraEngine::gui_getInput() {
_system->delayMillis(3);
}
-int KyraEngine::gui_resumeGame(Button *button) {
- debugC(9, kDebugLevelGUI, "KyraEngine::gui_resumeGame()");
+int KyraEngine_v1::gui_resumeGame(Button *button) {
+ debugC(9, kDebugLevelGUI, "KyraEngine_v1::gui_resumeGame()");
processMenuButton(button);
_displayMenu = false;
return 0;
}
-const char *KyraEngine::getSavegameFilename(int num) {
+const char *KyraEngine_v1::getSavegameFilename(int num) {
static char saveLoadSlot[12];
sprintf(saveLoadSlot, "%s.%.3d", _targetName.c_str(), num);
return saveLoadSlot;
}
-int KyraEngine::getNextSavegameSlot() {
+int KyraEngine_v1::getNextSavegameSlot() {
Common::InSaveFile *in;
for (int i = 1; i < 1000; i++) {
@@ -869,7 +869,7 @@ int KyraEngine::getNextSavegameSlot() {
return 0;
}
-void KyraEngine::setupSavegames(Menu &menu, int num) {
+void KyraEngine_v1::setupSavegames(Menu &menu, int num) {
Common::InSaveFile *in;
static char savenames[5][31];
uint8 startSlot;
@@ -900,8 +900,8 @@ void KyraEngine::setupSavegames(Menu &menu, int num) {
}
}
-int KyraEngine::gui_saveGameMenu(Button *button) {
- debugC(9, kDebugLevelGUI, "KyraEngine::gui_saveGameMenu()");
+int KyraEngine_v1::gui_saveGameMenu(Button *button) {
+ debugC(9, kDebugLevelGUI, "KyraEngine_v1::gui_saveGameMenu()");
processMenuButton(button);
_menu[2].item[5].enabled = true;
@@ -911,7 +911,7 @@ int KyraEngine::gui_saveGameMenu(Button *button) {
_menu[2].menuName = _guiStrings[8]; // Select a position to save to:
_specialSavegameString = _guiStrings[9]; // [ EMPTY SLOT ]
for (int i = 0; i < 5; i++)
- _menu[2].item[i].callback = &KyraEngine::gui_saveGame;
+ _menu[2].item[i].callback = &KyraEngine_v1::gui_saveGame;
_savegameOffset = 0;
setupSavegames(_menu[2], 5);
@@ -940,8 +940,8 @@ int KyraEngine::gui_saveGameMenu(Button *button) {
return 0;
}
-int KyraEngine::gui_loadGameMenu(Button *button) {
- debugC(9, kDebugLevelGUI, "KyraEngine::gui_loadGameMenu()");
+int KyraEngine_v1::gui_loadGameMenu(Button *button) {
+ debugC(9, kDebugLevelGUI, "KyraEngine_v1::gui_loadGameMenu()");
if (_menuDirectlyToLoad) {
_menu[2].item[5].enabled = false;
} else {
@@ -955,7 +955,7 @@ int KyraEngine::gui_loadGameMenu(Button *button) {
_specialSavegameString = _newGameString[0]; //[ START A NEW GAME ]
_menu[2].menuName = _guiStrings[7]; // Which game would you like to reload?
for (int i = 0; i < 5; i++)
- _menu[2].item[i].callback = &KyraEngine::gui_loadGame;
+ _menu[2].item[i].callback = &KyraEngine_v1::gui_loadGame;
_savegameOffset = 0;
setupSavegames(_menu[2], 5);
@@ -987,7 +987,7 @@ int KyraEngine::gui_loadGameMenu(Button *button) {
return 0;
}
-void KyraEngine::gui_redrawTextfield() {
+void KyraEngine_v1::gui_redrawTextfield() {
_screen->fillRect(38, 91, 287, 102, 250);
_text->printText(_savegameName, 38, 92, 253, 0, 0);
@@ -999,7 +999,7 @@ void KyraEngine::gui_redrawTextfield() {
_screen->updateScreen();
}
-void KyraEngine::gui_updateSavegameString() {
+void KyraEngine_v1::gui_updateSavegameString() {
int length;
if (_keyPressed.keycode) {
@@ -1026,8 +1026,8 @@ void KyraEngine::gui_updateSavegameString() {
_keyPressed.reset();
}
-int KyraEngine::gui_saveGame(Button *button) {
- debugC(9, kDebugLevelGUI, "KyraEngine::gui_saveGame()");
+int KyraEngine_v1::gui_saveGame(Button *button) {
+ debugC(9, kDebugLevelGUI, "KyraEngine_v1::gui_saveGame()");
processMenuButton(button);
_gameToLoad = button->specialValue;
@@ -1074,16 +1074,16 @@ int KyraEngine::gui_saveGame(Button *button) {
return 0;
}
-int KyraEngine::gui_savegameConfirm(Button *button) {
- debugC(9, kDebugLevelGUI, "KyraEngine::gui_savegameConfirm()");
+int KyraEngine_v1::gui_savegameConfirm(Button *button) {
+ debugC(9, kDebugLevelGUI, "KyraEngine_v1::gui_savegameConfirm()");
processMenuButton(button);
_displaySubMenu = false;
return 0;
}
-int KyraEngine::gui_loadGame(Button *button) {
- debugC(9, kDebugLevelGUI, "KyraEngine::gui_loadGame()");
+int KyraEngine_v1::gui_loadGame(Button *button) {
+ debugC(9, kDebugLevelGUI, "KyraEngine_v1::gui_loadGame()");
processMenuButton(button);
_displaySubMenu = false;
_gameToLoad = button->specialValue;
@@ -1091,8 +1091,8 @@ int KyraEngine::gui_loadGame(Button *button) {
return 0;
}
-int KyraEngine::gui_cancelSubMenu(Button *button) {
- debugC(9, kDebugLevelGUI, "KyraEngine::gui_cancelLoadGameMenu()");
+int KyraEngine_v1::gui_cancelSubMenu(Button *button) {
+ debugC(9, kDebugLevelGUI, "KyraEngine_v1::gui_cancelLoadGameMenu()");
processMenuButton(button);
_displaySubMenu = false;
_cancelSubMenu = true;
@@ -1100,8 +1100,8 @@ int KyraEngine::gui_cancelSubMenu(Button *button) {
return 0;
}
-int KyraEngine::gui_quitPlaying(Button *button) {
- debugC(9, kDebugLevelGUI, "KyraEngine::gui_quitPlaying()");
+int KyraEngine_v1::gui_quitPlaying(Button *button) {
+ debugC(9, kDebugLevelGUI, "KyraEngine_v1::gui_quitPlaying()");
processMenuButton(button);
if (gui_quitConfirm(_guiStrings[14])) { // Are you sure you want to quit playing?
@@ -1114,8 +1114,8 @@ int KyraEngine::gui_quitPlaying(Button *button) {
return 0;
}
-bool KyraEngine::gui_quitConfirm(const char *str) {
- debugC(9, kDebugLevelGUI, "KyraEngine::gui_quitConfirm()");
+bool KyraEngine_v1::gui_quitConfirm(const char *str) {
+ debugC(9, kDebugLevelGUI, "KyraEngine_v1::gui_quitConfirm()");
_screen->loadPageFromDisk("SEENPAGE.TMP", 0);
_screen->savePageToDisk("SEENPAGE.TMP", 0);
@@ -1139,8 +1139,8 @@ bool KyraEngine::gui_quitConfirm(const char *str) {
return !_cancelSubMenu;
}
-int KyraEngine::gui_quitConfirmYes(Button *button) {
- debugC(9, kDebugLevelGUI, "KyraEngine::gui_quitConfirmYes()");
+int KyraEngine_v1::gui_quitConfirmYes(Button *button) {
+ debugC(9, kDebugLevelGUI, "KyraEngine_v1::gui_quitConfirmYes()");
processMenuButton(button);
_displaySubMenu = false;
_cancelSubMenu = false;
@@ -1148,8 +1148,8 @@ int KyraEngine::gui_quitConfirmYes(Button *button) {
return 0;
}
-int KyraEngine::gui_quitConfirmNo(Button *button) {
- debugC(9, kDebugLevelGUI, "KyraEngine::gui_quitConfirmNo()");
+int KyraEngine_v1::gui_quitConfirmNo(Button *button) {
+ debugC(9, kDebugLevelGUI, "KyraEngine_v1::gui_quitConfirmNo()");
processMenuButton(button);
_displaySubMenu = false;
_cancelSubMenu = true;
@@ -1157,8 +1157,8 @@ int KyraEngine::gui_quitConfirmNo(Button *button) {
return 0;
}
-int KyraEngine::gui_gameControlsMenu(Button *button) {
- debugC(9, kDebugLevelGUI, "KyraEngine::gui_gameControlsMenu()");
+int KyraEngine_v1::gui_gameControlsMenu(Button *button) {
+ debugC(9, kDebugLevelGUI, "KyraEngine_v1::gui_gameControlsMenu()");
readSettings();
@@ -1175,14 +1175,14 @@ int KyraEngine::gui_gameControlsMenu(Button *button) {
}
_menu[5].item[3].labelString = _voiceTextString; //"Voice / Text "
- _menu[5].item[3].callback = &KyraEngine::gui_controlsChangeVoice;
+ _menu[5].item[3].callback = &KyraEngine_v1::gui_controlsChangeVoice;
} else {
//_menu[5].height = 136;
//_menu[5].item[5].y = 110;
_menu[5].item[4].enabled = 0;
_menu[5].item[3].labelString = _textSpeedString; // "Text speed "
- _menu[5].item[3].callback = &KyraEngine::gui_controlsChangeText;
+ _menu[5].item[3].callback = &KyraEngine_v1::gui_controlsChangeText;
}
gui_setupControls(_menu[5]);
@@ -1208,8 +1208,8 @@ int KyraEngine::gui_gameControlsMenu(Button *button) {
return 0;
}
-void KyraEngine::gui_setupControls(Menu &menu) {
- debugC(9, kDebugLevelGUI, "KyraEngine::gui_setupControls()");
+void KyraEngine_v1::gui_setupControls(Menu &menu) {
+ debugC(9, kDebugLevelGUI, "KyraEngine_v1::gui_setupControls()");
switch (_configMusic) {
case 0:
@@ -1299,8 +1299,8 @@ void KyraEngine::gui_setupControls(Menu &menu) {
initMenu(menu);
}
-int KyraEngine::gui_controlsChangeMusic(Button *button) {
- debugC(9, kDebugLevelGUI, "KyraEngine::gui_controlsChangeMusic()");
+int KyraEngine_v1::gui_controlsChangeMusic(Button *button) {
+ debugC(9, kDebugLevelGUI, "KyraEngine_v1::gui_controlsChangeMusic()");
processMenuButton(button);
_configMusic = ++_configMusic % (_flags.platform == Common::kPlatformFMTowns ? 3 : 2);
@@ -1308,8 +1308,8 @@ int KyraEngine::gui_controlsChangeMusic(Button *button) {
return 0;
}
-int KyraEngine::gui_controlsChangeSounds(Button *button) {
- debugC(9, kDebugLevelGUI, "KyraEngine::gui_controlsChangeSounds()");
+int KyraEngine_v1::gui_controlsChangeSounds(Button *button) {
+ debugC(9, kDebugLevelGUI, "KyraEngine_v1::gui_controlsChangeSounds()");
processMenuButton(button);
_configSounds = !_configSounds;
@@ -1317,8 +1317,8 @@ int KyraEngine::gui_controlsChangeSounds(Button *button) {
return 0;
}
-int KyraEngine::gui_controlsChangeWalk(Button *button) {
- debugC(9, kDebugLevelGUI, "KyraEngine::gui_controlsChangeWalk()");
+int KyraEngine_v1::gui_controlsChangeWalk(Button *button) {
+ debugC(9, kDebugLevelGUI, "KyraEngine_v1::gui_controlsChangeWalk()");
processMenuButton(button);
_configWalkspeed = ++_configWalkspeed % 5;
@@ -1327,8 +1327,8 @@ int KyraEngine::gui_controlsChangeWalk(Button *button) {
return 0;
}
-int KyraEngine::gui_controlsChangeText(Button *button) {
- debugC(9, kDebugLevelGUI, "KyraEngine::gui_controlsChangeText()");
+int KyraEngine_v1::gui_controlsChangeText(Button *button) {
+ debugC(9, kDebugLevelGUI, "KyraEngine_v1::gui_controlsChangeText()");
processMenuButton(button);
_configTextspeed = ++_configTextspeed % 4;
@@ -1336,8 +1336,8 @@ int KyraEngine::gui_controlsChangeText(Button *button) {
return 0;
}
-int KyraEngine::gui_controlsChangeVoice(Button *button) {
- debugC(9, kDebugLevelGUI, "KyraEngine::gui_controlsChangeVoice()");
+int KyraEngine_v1::gui_controlsChangeVoice(Button *button) {
+ debugC(9, kDebugLevelGUI, "KyraEngine_v1::gui_controlsChangeVoice()");
processMenuButton(button);
_configVoice = ++_configVoice % 3;
@@ -1345,14 +1345,14 @@ int KyraEngine::gui_controlsChangeVoice(Button *button) {
return 0;
}
-int KyraEngine::gui_controlsApply(Button *button) {
- debugC(9, kDebugLevelGUI, "KyraEngine::gui_controlsApply()");
+int KyraEngine_v1::gui_controlsApply(Button *button) {
+ debugC(9, kDebugLevelGUI, "KyraEngine_v1::gui_controlsApply()");
writeSettings();
return gui_cancelSubMenu(button);
}
-int KyraEngine::gui_scrollUp(Button *button) {
- debugC(9, kDebugLevelGUI, "KyraEngine::gui_scrollUp()");
+int KyraEngine_v1::gui_scrollUp(Button *button) {
+ debugC(9, kDebugLevelGUI, "KyraEngine_v1::gui_scrollUp()");
processMenuButton(button);
if (_savegameOffset > 0) {
@@ -1363,8 +1363,8 @@ int KyraEngine::gui_scrollUp(Button *button) {
return 0;
}
-int KyraEngine::gui_scrollDown(Button *button) {
- debugC(9, kDebugLevelGUI, "KyraEngine::gui_scrollDown()");
+int KyraEngine_v1::gui_scrollDown(Button *button) {
+ debugC(9, kDebugLevelGUI, "KyraEngine_v1::gui_scrollDown()");
processMenuButton(button);
_savegameOffset++;
@@ -1374,7 +1374,7 @@ int KyraEngine::gui_scrollDown(Button *button) {
return 0;
}
-void KyraEngine::gui_processHighlights(Menu &menu) {
+void KyraEngine_v1::gui_processHighlights(Menu &menu) {
int x1, y1, x2, y2;
Common::Point mouse = getMousePos();
@@ -1403,7 +1403,7 @@ void KyraEngine::gui_processHighlights(Menu &menu) {
}
}
-void KyraEngine::gui_redrawText(Menu menu) {
+void KyraEngine_v1::gui_redrawText(Menu menu) {
int textX;
int i = menu.highlightedItem;
@@ -1422,7 +1422,7 @@ void KyraEngine::gui_redrawText(Menu menu) {
_text->printText(menu.item[i].itemString, textX, textY, menu.item[i].textColor, 0, 0);
}
-void KyraEngine::gui_redrawHighlight(Menu menu) {
+void KyraEngine_v1::gui_redrawHighlight(Menu menu) {
int textX;
int i = menu.highlightedItem;
@@ -1441,7 +1441,7 @@ void KyraEngine::gui_redrawHighlight(Menu menu) {
_text->printText(menu.item[i].itemString, textX, textY, menu.item[i].highlightColor, 0, 0);
}
-void KyraEngine::gui_fadePalette() {
+void KyraEngine_v1::gui_fadePalette() {
if (_flags.platform == Common::kPlatformAmiga)
return;
@@ -1461,7 +1461,7 @@ void KyraEngine::gui_fadePalette() {
_screen->fadePalette(_screen->_currentPalette, 2);
}
-void KyraEngine::gui_restorePalette() {
+void KyraEngine_v1::gui_restorePalette() {
if (_flags.platform == Common::kPlatformAmiga)
return;
@@ -1471,169 +1471,35 @@ void KyraEngine::gui_restorePalette() {
#pragma mark -
-// Kyra 2 and 3 main menu
+void KyraEngine_v1::drawAmulet() {
+ debugC(9, kDebugLevelMain, "KyraEngine_v1::drawAmulet()");
+ static const int16 amuletTable1[] = {0x167, 0x162, 0x15D, 0x158, 0x153, 0x150, 0x155, 0x15A, 0x15F, 0x164, 0x145, -1};
+ static const int16 amuletTable3[] = {0x167, 0x162, 0x15D, 0x158, 0x153, 0x14F, 0x154, 0x159, 0x15E, 0x163, 0x144, -1};
+ static const int16 amuletTable2[] = {0x167, 0x162, 0x15D, 0x158, 0x153, 0x152, 0x157, 0x15C, 0x161, 0x166, 0x147, -1};
+ static const int16 amuletTable4[] = {0x167, 0x162, 0x15D, 0x158, 0x153, 0x151, 0x156, 0x15B, 0x160, 0x165, 0x146, -1};
-void KyraEngine::gui_updateMainMenuAnimation() {
- _screen->updateScreen();
-}
-
-bool KyraEngine::gui_mainMenuGetInput() {
- Common::Event event;
-
- while (_eventMan->pollEvent(event)) {
- switch (event.type) {
- case Common::EVENT_QUIT:
- quitGame();
- break;
- case Common::EVENT_LBUTTONUP:
- return true;
- default:
- break;
- }
- }
- return false;
-}
-
-int KyraEngine::gui_handleMainMenu() {
- debugC(9, kDebugLevelMain, "KyraEngine::gui_handleMainMenu()");
- int command = -1;
-
- uint8 colorMap[16];
- memset(colorMap, 0, sizeof(colorMap));
- _screen->setTextColorMap(colorMap);
-
- const char * const *strings = &_mainMenuStrings[_lang << 2];
- Screen::FontId oldFont = _screen->setFont(Screen::FID_8_FNT);
- int charWidthBackUp = _screen->_charWidth;
-
- _screen->_charWidth = -2;
- _screen->setScreenDim(3);
- int backUpX = _screen->_curDim->sx;
- int backUpY = _screen->_curDim->sy;
- int backUpWidth = _screen->_curDim->w;
- int backUpHeight = _screen->_curDim->h;
- _screen->copyRegion(backUpX, backUpY, backUpX, backUpY, backUpWidth, backUpHeight, 0, 3);
-
- int x = _screen->_curDim->sx << 3;
- int y = _screen->_curDim->sy;
- int width = _screen->_curDim->w << 3;
- int height = _screen->_curDim->h;
-
- gui_drawMainBox(x, y, width, height, 1);
- gui_drawMainBox(x + 1, y + 1, width - 2, height - 2, 0);
-
- int selected = 0;
-
- gui_drawMainMenu(strings, selected);
-
- _screen->showMouse();
-
- int fh = _screen->getFontHeight();
- int textPos = ((_screen->_curDim->w >> 1) + _screen->_curDim->sx) << 3;
-
- Common::Rect menuRect(x + 16, y + 4, x + width - 16, y + 4 + fh * 4);
-
- while (!_quitFlag) {
- gui_updateMainMenuAnimation();
- bool mousePressed = gui_mainMenuGetInput();
-
- Common::Point mouse = getMousePos();
- if (menuRect.contains(mouse)) {
- int item = (mouse.y - menuRect.top) / fh;
-
- if (item != selected) {
- gui_printString(strings[selected], textPos, menuRect.top + selected * fh, 0x80, 0, 5);
- gui_printString(strings[item], textPos, menuRect.top + item * fh, 0xFF, 0, 5);
+ resetGameFlag(0xF1);
+ _screen->hideMouse();
- selected = item;
- }
+ int i = 0;
+ while (amuletTable1[i] != -1) {
+ if (queryGameFlag(87))
+ _screen->drawShape(0, _shapes[amuletTable1[i]], _amuletX[0], _amuletY[0], 0, 0);
- if (mousePressed) {
- // TODO: Flash the text
- command = item;
- break;
- }
- }
- _system->delayMillis(10);
- }
-
- if (_quitFlag)
- command = -1;
-
- _screen->copyRegion(backUpX, backUpY, backUpX, backUpY, backUpWidth, backUpHeight, 3, 0);
- _screen->_charWidth = charWidthBackUp;
- _screen->setFont(oldFont);
-
- return command;
-}
-
-void KyraEngine::gui_drawMainMenu(const char * const *strings, int select) {
- debugC(9, kDebugLevelMain, "KyraEngine::gui_drawMainMenu(%p)", (const void*)strings);
- static const uint16 menuTable[] = { 0x01, 0x04, 0x0C, 0x04, 0x00, 0x80, 0xFF, 0x00, 0x01, 0x02, 0x03 };
-
- int top = _screen->_curDim->sy;
- top += menuTable[1];
-
- for (int i = 0; i < menuTable[3]; ++i) {
- int curY = top + i * _screen->getFontHeight();
- int color = (i == select) ? menuTable[6] : menuTable[5];
- gui_printString(strings[i], ((_screen->_curDim->w >> 1) + _screen->_curDim->sx) << 3, curY, color, 0, 5);
- }
-}
+ if (queryGameFlag(89))
+ _screen->drawShape(0, _shapes[amuletTable2[i]], _amuletX[1], _amuletY[1], 0, 0);
-void KyraEngine::gui_drawMainBox(int x, int y, int w, int h, int fill) {
- debugC(9, kDebugLevelMain, "KyraEngine::gui_drawMainBox(%d, %d, %d, %d, %d)", x, y, w, h, fill);
- static const uint8 kyra3ColorTable[] = { 0x16, 0x19, 0x1A, 0x16 };
- static const uint8 kyra2ColorTable[] = { 0x0, 0x19, 0x28, 0xc8 };
-
- const uint8 *colorTable;
- if (_flags.gameID == GI_KYRA3)
- colorTable = kyra3ColorTable;
- else
- colorTable = kyra2ColorTable;
-
- --w; --h;
+ if (queryGameFlag(86))
+ _screen->drawShape(0, _shapes[amuletTable3[i]], _amuletX[2], _amuletY[2], 0, 0);
- if (fill)
- _screen->fillRect(x, y, x+w, y+h, colorTable[0]);
-
- _screen->drawClippedLine(x, y+h, x+w, y+h, colorTable[1]);
- _screen->drawClippedLine(x+w, y, x+w, y+h, colorTable[1]);
- _screen->drawClippedLine(x, y, x+w, y, colorTable[2]);
- _screen->drawClippedLine(x, y, x, y+h, colorTable[2]);
-
- _screen->setPagePixel(_screen->_curPage, x, y+h, colorTable[3]);
- _screen->setPagePixel(_screen->_curPage, x+w, y, colorTable[3]);
-}
+ if (queryGameFlag(88))
+ _screen->drawShape(0, _shapes[amuletTable4[i]], _amuletX[3], _amuletY[3], 0, 0);
-void KyraEngine::gui_printString(const char *format, int x, int y, int col1, int col2, int flags, ...) {
- debugC(9, kDebugLevelMain, "KyraEngine::gui_printString('%s', %d, %d, %d, %d, %d, ...)", format, x, y, col1, col2, flags);
- if (!format)
- return;
-
- char string[512];
- va_list vaList;
- va_start(vaList, flags);
- vsprintf(string, format, vaList);
- va_end(vaList);
-
- if (flags & 1)
- x -= _screen->getTextWidth(string) >> 1;
-
- if (flags & 2)
- x -= _screen->getTextWidth(string);
-
- if (flags & 4) {
- _screen->printText(string, x - 1, y, 240, col2);
- _screen->printText(string, x, y + 1, 240, col2);
+ _screen->updateScreen();
+ delayWithTicks(3);
+ i++;
}
-
- if (flags & 8) {
- _screen->printText(string, x - 1, y, 227, col2);
- _screen->printText(string, x, y + 1, 227, col2);
- }
-
- _screen->printText(string, x, y, col1, col2);
+ _screen->showMouse();
}
} // end of namespace Kyra
diff --git a/engines/kyra/gui_v2.cpp b/engines/kyra/gui_v2.cpp
new file mode 100644
index 0000000000..838d347f8f
--- /dev/null
+++ b/engines/kyra/gui_v2.cpp
@@ -0,0 +1,198 @@
+/* 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 "kyra/kyra.h"
+#include "kyra/kyra_v2.h"
+#include "kyra/screen.h"
+
+namespace Kyra {
+
+void KyraEngine_v2::gui_updateMainMenuAnimation() {
+ _screen->updateScreen();
+}
+
+bool KyraEngine_v2::gui_mainMenuGetInput() {
+ Common::Event event;
+
+ while (_eventMan->pollEvent(event)) {
+ switch (event.type) {
+ case Common::EVENT_QUIT:
+ quitGame();
+ break;
+ case Common::EVENT_LBUTTONUP:
+ return true;
+ default:
+ break;
+ }
+ }
+ return false;
+}
+
+int KyraEngine_v2::gui_handleMainMenu() {
+ debugC(9, kDebugLevelMain, "KyraEngine_v2::gui_handleMainMenu()");
+ int command = -1;
+
+ uint8 colorMap[16];
+ memset(colorMap, 0, sizeof(colorMap));
+ _screen->setTextColorMap(colorMap);
+
+ const char * const *strings = &_mainMenuStrings[_lang << 2];
+ Screen::FontId oldFont = _screen->setFont(Screen::FID_8_FNT);
+ int charWidthBackUp = _screen->_charWidth;
+
+ _screen->_charWidth = -2;
+ if (_flags.gameID == GI_KYRA2)
+ _screen->setScreenDim(11);
+ else
+ _screen->setScreenDim(3);
+ int backUpX = _screen->_curDim->sx;
+ int backUpY = _screen->_curDim->sy;
+ int backUpWidth = _screen->_curDim->w;
+ int backUpHeight = _screen->_curDim->h;
+ _screen->copyRegion(backUpX, backUpY, backUpX, backUpY, backUpWidth, backUpHeight, 0, 3);
+
+ int x = _screen->_curDim->sx << 3;
+ int y = _screen->_curDim->sy;
+ int width = _screen->_curDim->w << 3;
+ int height = _screen->_curDim->h;
+
+ gui_drawMainBox(x, y, width, height, 1);
+ gui_drawMainBox(x + 1, y + 1, width - 2, height - 2, 0);
+
+ int selected = 0;
+
+ gui_drawMainMenu(strings, selected);
+
+ _screen->showMouse();
+
+ int fh = _screen->getFontHeight();
+ int textPos = ((_screen->_curDim->w >> 1) + _screen->_curDim->sx) << 3;
+
+ Common::Rect menuRect(x + 16, y + 4, x + width - 16, y + 4 + fh * 4);
+
+ while (!_quitFlag) {
+ gui_updateMainMenuAnimation();
+ bool mousePressed = gui_mainMenuGetInput();
+
+ Common::Point mouse = getMousePos();
+ if (menuRect.contains(mouse)) {
+ int item = (mouse.y - menuRect.top) / fh;
+
+ if (item != selected) {
+ gui_printString(strings[selected], textPos, menuRect.top + selected * fh, 0x80, 0, 5);
+ gui_printString(strings[item], textPos, menuRect.top + item * fh, 0xFF, 0, 5);
+
+ selected = item;
+ }
+
+ if (mousePressed) {
+ // TODO: Flash the text
+ command = item;
+ break;
+ }
+ }
+ _system->delayMillis(10);
+ }
+
+ if (_quitFlag)
+ command = -1;
+
+ _screen->copyRegion(backUpX, backUpY, backUpX, backUpY, backUpWidth, backUpHeight, 3, 0);
+ _screen->_charWidth = charWidthBackUp;
+ _screen->setFont(oldFont);
+
+ return command;
+}
+
+void KyraEngine_v2::gui_drawMainMenu(const char * const *strings, int select) {
+ debugC(9, kDebugLevelMain, "KyraEngine_v2::gui_drawMainMenu(%p)", (const void*)strings);
+ static const uint16 menuTable[] = { 0x01, 0x04, 0x0C, 0x04, 0x00, 0x80, 0xFF, 0x00, 0x01, 0x02, 0x03 };
+
+ int top = _screen->_curDim->sy;
+ top += menuTable[1];
+
+ for (int i = 0; i < menuTable[3]; ++i) {
+ int curY = top + i * _screen->getFontHeight();
+ int color = (i == select) ? menuTable[6] : menuTable[5];
+ gui_printString(strings[i], ((_screen->_curDim->w >> 1) + _screen->_curDim->sx) << 3, curY, color, 0, 5);
+ }
+}
+
+void KyraEngine_v2::gui_drawMainBox(int x, int y, int w, int h, int fill) {
+ debugC(9, kDebugLevelMain, "KyraEngine_v2::gui_drawMainBox(%d, %d, %d, %d, %d)", x, y, w, h, fill);
+ static const uint8 kyra3ColorTable[] = { 0x16, 0x19, 0x1A, 0x16 };
+ static const uint8 kyra2ColorTable[] = { 0x0, 0x19, 0x28, 0xc8 };
+
+ const uint8 *colorTable;
+ if (_flags.gameID == GI_KYRA3)
+ colorTable = kyra3ColorTable;
+ else
+ colorTable = kyra2ColorTable;
+
+ --w; --h;
+
+ if (fill)
+ _screen->fillRect(x, y, x+w, y+h, colorTable[0]);
+
+ _screen->drawClippedLine(x, y+h, x+w, y+h, colorTable[1]);
+ _screen->drawClippedLine(x+w, y, x+w, y+h, colorTable[1]);
+ _screen->drawClippedLine(x, y, x+w, y, colorTable[2]);
+ _screen->drawClippedLine(x, y, x, y+h, colorTable[2]);
+
+ _screen->setPagePixel(_screen->_curPage, x, y+h, colorTable[3]);
+ _screen->setPagePixel(_screen->_curPage, x+w, y, colorTable[3]);
+}
+
+void KyraEngine_v2::gui_printString(const char *format, int x, int y, int col1, int col2, int flags, ...) {
+ debugC(9, kDebugLevelMain, "KyraEngine_v2::gui_printString('%s', %d, %d, %d, %d, %d, ...)", format, x, y, col1, col2, flags);
+ if (!format)
+ return;
+
+ char string[512];
+ va_list vaList;
+ va_start(vaList, flags);
+ vsprintf(string, format, vaList);
+ va_end(vaList);
+
+ if (flags & 1)
+ x -= _screen->getTextWidth(string) >> 1;
+
+ if (flags & 2)
+ x -= _screen->getTextWidth(string);
+
+ if (flags & 4) {
+ _screen->printText(string, x - 1, y, 240, col2);
+ _screen->printText(string, x, y + 1, 240, col2);
+ }
+
+ if (flags & 8) {
+ _screen->printText(string, x - 1, y, 227, col2);
+ _screen->printText(string, x, y + 1, 227, col2);
+ }
+
+ _screen->printText(string, x, y, col1, col2);
+}
+
+} // end of namespace Kyra
diff --git a/engines/kyra/items.cpp b/engines/kyra/items_v1.cpp
index 2a1a08b7de..84b76c59a6 100644
--- a/engines/kyra/items.cpp
+++ b/engines/kyra/items_v1.cpp
@@ -23,14 +23,14 @@
*
*/
-#include "kyra/kyra.h"
+#include "kyra/kyra_v1.h"
#include "kyra/seqplayer.h"
#include "kyra/screen.h"
#include "kyra/resource.h"
#include "kyra/sound.h"
#include "kyra/sprites.h"
#include "kyra/wsamovie.h"
-#include "kyra/animator.h"
+#include "kyra/animator_v1.h"
#include "kyra/text.h"
#include "common/system.h"
@@ -38,7 +38,7 @@
namespace Kyra {
-int KyraEngine::findDuplicateItemShape(int shape) {
+int KyraEngine_v1::findDuplicateItemShape(int shape) {
static uint8 dupTable[] = {
0x48, 0x46, 0x49, 0x47, 0x4a, 0x46, 0x4b, 0x47,
0x4c, 0x46, 0x4d, 0x47, 0x5b, 0x5a, 0x5c, 0x5a,
@@ -55,8 +55,8 @@ int KyraEngine::findDuplicateItemShape(int shape) {
return -1;
}
-void KyraEngine::addToNoDropRects(int x, int y, int w, int h) {
- debugC(9, kDebugLevelMain, "KyraEngine::addToNoDropRects(%d, %d, %d, %d)", x, y, w, h);
+void KyraEngine_v1::addToNoDropRects(int x, int y, int w, int h) {
+ debugC(9, kDebugLevelMain, "KyraEngine_v1::addToNoDropRects(%d, %d, %d, %d)", x, y, w, h);
for (int rect = 0; rect < 11; ++rect) {
if (_noDropRects[rect].x == -1) {
_noDropRects[rect].x = x;
@@ -68,13 +68,13 @@ void KyraEngine::addToNoDropRects(int x, int y, int w, int h) {
}
}
-void KyraEngine::clearNoDropRects() {
- debugC(9, kDebugLevelMain, "KyraEngine::clearNoDropRects()");
+void KyraEngine_v1::clearNoDropRects() {
+ debugC(9, kDebugLevelMain, "KyraEngine_v1::clearNoDropRects()");
memset(_noDropRects, -1, sizeof(_noDropRects));
}
-byte KyraEngine::findFreeItemInScene(int scene) {
- debugC(9, kDebugLevelMain, "KyraEngine::findFreeItemInScene(%d)", scene);
+byte KyraEngine_v1::findFreeItemInScene(int scene) {
+ debugC(9, kDebugLevelMain, "KyraEngine_v1::findFreeItemInScene(%d)", scene);
assert(scene < _roomTableSize);
Room *room = &_roomTable[scene];
for (int i = 0; i < 12; ++i) {
@@ -84,8 +84,8 @@ byte KyraEngine::findFreeItemInScene(int scene) {
return 0xFF;
}
-byte KyraEngine::findItemAtPos(int x, int y) {
- debugC(9, kDebugLevelMain, "KyraEngine::findItemAtPos(%d, %d)", x, y);
+byte KyraEngine_v1::findItemAtPos(int x, int y) {
+ debugC(9, kDebugLevelMain, "KyraEngine_v1::findItemAtPos(%d, %d)", x, y);
assert(_currentCharacter->sceneId < _roomTableSize);
const uint8 *itemsTable = _roomTable[_currentCharacter->sceneId].itemsTable;
const uint16 *xposOffset = _roomTable[_currentCharacter->sceneId].itemsXPos;
@@ -120,8 +120,8 @@ byte KyraEngine::findItemAtPos(int x, int y) {
return returnValue;
}
-void KyraEngine::placeItemInGenericMapScene(int item, int index) {
- debugC(9, kDebugLevelMain, "KyraEngine::placeItemInGenericMapScene(%d, %d)", item, index);
+void KyraEngine_v1::placeItemInGenericMapScene(int item, int index) {
+ debugC(9, kDebugLevelMain, "KyraEngine_v1::placeItemInGenericMapScene(%d, %d)", item, index);
static const uint16 itemMapSceneMinTable[] = {
0x0000, 0x0011, 0x006D, 0x0025, 0x00C7, 0x0000
};
@@ -175,32 +175,32 @@ void KyraEngine::placeItemInGenericMapScene(int item, int index) {
}
}
-void KyraEngine::createMouseItem(int item) {
- debugC(9, kDebugLevelMain, "KyraEngine::createMouseItem(%d)", item);
+void KyraEngine_v1::createMouseItem(int item) {
+ debugC(9, kDebugLevelMain, "KyraEngine_v1::createMouseItem(%d)", item);
_screen->hideMouse();
setMouseItem(item);
_itemInHand = item;
_screen->showMouse();
}
-void KyraEngine::destroyMouseItem() {
- debugC(9, kDebugLevelMain, "KyraEngine::destroyMouseItem()");
+void KyraEngine_v1::destroyMouseItem() {
+ debugC(9, kDebugLevelMain, "KyraEngine_v1::destroyMouseItem()");
_screen->hideMouse();
_screen->setMouseCursor(1, 1, _shapes[0]);
_itemInHand = -1;
_screen->showMouse();
}
-void KyraEngine::setMouseItem(int item) {
- debugC(9, kDebugLevelMain, "KyraEngine::setMouseItem(%d)", item);
+void KyraEngine_v1::setMouseItem(int item) {
+ debugC(9, kDebugLevelMain, "KyraEngine_v1::setMouseItem(%d)", item);
if (item == -1)
_screen->setMouseCursor(1, 1, _shapes[6]);
else
_screen->setMouseCursor(8, 15, _shapes[216+item]);
}
-void KyraEngine::wipeDownMouseItem(int xpos, int ypos) {
- debugC(9, kDebugLevelMain, "KyraEngine::wipeDownMouseItem(%d, %d)", xpos, ypos);
+void KyraEngine_v1::wipeDownMouseItem(int xpos, int ypos) {
+ debugC(9, kDebugLevelMain, "KyraEngine_v1::wipeDownMouseItem(%d, %d)", xpos, ypos);
if (_itemInHand == -1)
return;
xpos -= 8;
@@ -226,8 +226,8 @@ void KyraEngine::wipeDownMouseItem(int xpos, int ypos) {
_screen->showMouse();
}
-void KyraEngine::setupSceneItems() {
- debugC(9, kDebugLevelMain, "KyraEngine::setupSceneItems()");
+void KyraEngine_v1::setupSceneItems() {
+ debugC(9, kDebugLevelMain, "KyraEngine_v1::setupSceneItems()");
uint16 sceneId = _currentCharacter->sceneId;
assert(sceneId < _roomTableSize);
Room *currentRoom = &_roomTable[sceneId];
@@ -264,8 +264,8 @@ void KyraEngine::setupSceneItems() {
}
}
-int KyraEngine::countItemsInScene(uint16 sceneId) {
- debugC(9, kDebugLevelMain, "KyraEngine::countItemsInScene(%d)", sceneId);
+int KyraEngine_v1::countItemsInScene(uint16 sceneId) {
+ debugC(9, kDebugLevelMain, "KyraEngine_v1::countItemsInScene(%d)", sceneId);
assert(sceneId < _roomTableSize);
Room *currentRoom = &_roomTable[sceneId];
@@ -279,8 +279,8 @@ int KyraEngine::countItemsInScene(uint16 sceneId) {
return items;
}
-int KyraEngine::processItemDrop(uint16 sceneId, uint8 item, int x, int y, int unk1, int unk2) {
- debugC(9, kDebugLevelMain, "KyraEngine::processItemDrop(%d, %d, %d, %d, %d, %d)", sceneId, item, x, y, unk1, unk2);
+int KyraEngine_v1::processItemDrop(uint16 sceneId, uint8 item, int x, int y, int unk1, int unk2) {
+ debugC(9, kDebugLevelMain, "KyraEngine_v1::processItemDrop(%d, %d, %d, %d, %d, %d)", sceneId, item, x, y, unk1, unk2);
int freeItem = -1;
uint8 itemIndex = findItemAtPos(x, y);
if (unk1)
@@ -432,8 +432,8 @@ int KyraEngine::processItemDrop(uint16 sceneId, uint8 item, int x, int y, int un
return 1;
}
-void KyraEngine::exchangeItemWithMouseItem(uint16 sceneId, int itemIndex) {
- debugC(9, kDebugLevelMain, "KyraEngine::exchangeItemWithMouseItem(%d, %d)", sceneId, itemIndex);
+void KyraEngine_v1::exchangeItemWithMouseItem(uint16 sceneId, int itemIndex) {
+ debugC(9, kDebugLevelMain, "KyraEngine_v1::exchangeItemWithMouseItem(%d, %d)", sceneId, itemIndex);
_screen->hideMouse();
_animator->animRemoveGameItem(itemIndex);
assert(sceneId < _roomTableSize);
@@ -452,8 +452,8 @@ void KyraEngine::exchangeItemWithMouseItem(uint16 sceneId, int itemIndex) {
clickEventHandler2();
}
-void KyraEngine::addItemToRoom(uint16 sceneId, uint8 item, int itemIndex, int x, int y) {
- debugC(9, kDebugLevelMain, "KyraEngine::addItemToRoom(%d, %d, %d, %d, %d)", sceneId, item, itemIndex, x, y);
+void KyraEngine_v1::addItemToRoom(uint16 sceneId, uint8 item, int itemIndex, int x, int y) {
+ debugC(9, kDebugLevelMain, "KyraEngine_v1::addItemToRoom(%d, %d, %d, %d, %d)", sceneId, item, itemIndex, x, y);
assert(sceneId < _roomTableSize);
Room *currentRoom = &_roomTable[sceneId];
currentRoom->itemsTable[itemIndex] = item;
@@ -462,8 +462,8 @@ void KyraEngine::addItemToRoom(uint16 sceneId, uint8 item, int itemIndex, int x,
currentRoom->needInit[itemIndex] = 1;
}
-int KyraEngine::checkNoDropRects(int x, int y) {
- debugC(9, kDebugLevelMain, "KyraEngine::checkNoDropRects(%d, %d)", x, y);
+int KyraEngine_v1::checkNoDropRects(int x, int y) {
+ debugC(9, kDebugLevelMain, "KyraEngine_v1::checkNoDropRects(%d, %d)", x, y);
if (_lastProcessedItemHeight < 1 || _lastProcessedItemHeight > 16)
_lastProcessedItemHeight = 16;
if (_noDropRects[0].x == -1)
@@ -492,8 +492,8 @@ int KyraEngine::checkNoDropRects(int x, int y) {
return 0;
}
-int KyraEngine::isDropable(int x, int y) {
- debugC(9, kDebugLevelMain, "KyraEngine::isDropable(%d, %d)", x, y);
+int KyraEngine_v1::isDropable(int x, int y) {
+ debugC(9, kDebugLevelMain, "KyraEngine_v1::isDropable(%d, %d)", x, y);
x -= 8;
y -= 1;
@@ -507,8 +507,8 @@ int KyraEngine::isDropable(int x, int y) {
return 1;
}
-void KyraEngine::itemDropDown(int x, int y, int destX, int destY, byte freeItem, int item) {
- debugC(9, kDebugLevelMain, "KyraEngine::itemDropDown(%d, %d, %d, %d, %d, %d)", x, y, destX, destY, freeItem, item);
+void KyraEngine_v1::itemDropDown(int x, int y, int destX, int destY, byte freeItem, int item) {
+ debugC(9, kDebugLevelMain, "KyraEngine_v1::itemDropDown(%d, %d, %d, %d, %d, %d)", x, y, destX, destY, freeItem, item);
assert(_currentCharacter->sceneId < _roomTableSize);
Room *currentRoom = &_roomTable[_currentCharacter->sceneId];
if (x == destX && y == destY) {
@@ -591,8 +591,8 @@ void KyraEngine::itemDropDown(int x, int y, int destX, int destY, byte freeItem,
_screen->showMouse();
}
-void KyraEngine::dropItem(int unk1, int item, int x, int y, int unk2) {
- debugC(9, kDebugLevelMain, "KyraEngine::dropItem(%d, %d, %d, %d, %d)", unk1, item, x, y, unk2);
+void KyraEngine_v1::dropItem(int unk1, int item, int x, int y, int unk2) {
+ debugC(9, kDebugLevelMain, "KyraEngine_v1::dropItem(%d, %d, %d, %d, %d)", unk1, item, x, y, unk2);
if (processItemDrop(_currentCharacter->sceneId, item, x, y, unk1, unk2))
return;
snd_playSoundEffect(54);
@@ -603,16 +603,16 @@ void KyraEngine::dropItem(int unk1, int item, int x, int y, int unk2) {
drawSentenceCommand(_noDropList[1], 6);
}
-void KyraEngine::itemSpecialFX(int x, int y, int item) {
- debugC(9, kDebugLevelMain, "KyraEngine::itemSpecialFX(%d, %d, %d)", x, y, item);
+void KyraEngine_v1::itemSpecialFX(int x, int y, int item) {
+ debugC(9, kDebugLevelMain, "KyraEngine_v1::itemSpecialFX(%d, %d, %d)", x, y, item);
if (item == 41)
itemSpecialFX1(x, y, item);
else
itemSpecialFX2(x, y, item);
}
-void KyraEngine::itemSpecialFX1(int x, int y, int item) {
- debugC(9, kDebugLevelMain, "KyraEngine::itemSpecialFX1(%d, %d, %d)", x, y, item);
+void KyraEngine_v1::itemSpecialFX1(int x, int y, int item) {
+ debugC(9, kDebugLevelMain, "KyraEngine_v1::itemSpecialFX1(%d, %d, %d)", x, y, item);
uint8 *shape = _shapes[216+item];
x -= 8;
int startY = y;
@@ -632,8 +632,8 @@ void KyraEngine::itemSpecialFX1(int x, int y, int item) {
_screen->showMouse();
}
-void KyraEngine::itemSpecialFX2(int x, int y, int item) {
- debugC(9, kDebugLevelMain, "KyraEngine::itemSpecialFX2(%d, %d, %d)", x, y, item);
+void KyraEngine_v1::itemSpecialFX2(int x, int y, int item) {
+ debugC(9, kDebugLevelMain, "KyraEngine_v1::itemSpecialFX2(%d, %d, %d)", x, y, item);
x -= 8;
y -= 15;
int yAdd = (int8)(((16 - _itemTable[item].height) >> 1) & 0xFF);
@@ -660,8 +660,8 @@ void KyraEngine::itemSpecialFX2(int x, int y, int item) {
restoreItemRect0(x, y);
}
-void KyraEngine::magicOutMouseItem(int animIndex, int itemPos) {
- debugC(9, kDebugLevelMain, "KyraEngine::magicOutMouseItem(%d, %d)", animIndex, itemPos);
+void KyraEngine_v1::magicOutMouseItem(int animIndex, int itemPos) {
+ debugC(9, kDebugLevelMain, "KyraEngine_v1::magicOutMouseItem(%d, %d)", animIndex, itemPos);
int videoPageBackUp = _screen->_curPage;
_screen->_curPage = 0;
int x = 0, y = 0;
@@ -744,8 +744,8 @@ void KyraEngine::magicOutMouseItem(int animIndex, int itemPos) {
_screen->_curPage = videoPageBackUp;
}
-void KyraEngine::magicInMouseItem(int animIndex, int item, int itemPos) {
- debugC(9, kDebugLevelMain, "KyraEngine::magicInMouseItem(%d, %d, %d)", animIndex, item, itemPos);
+void KyraEngine_v1::magicInMouseItem(int animIndex, int item, int itemPos) {
+ debugC(9, kDebugLevelMain, "KyraEngine_v1::magicInMouseItem(%d, %d, %d)", animIndex, item, itemPos);
int videoPageBackUp = _screen->_curPage;
_screen->_curPage = 0;
int x = 0, y = 0;
@@ -817,8 +817,8 @@ void KyraEngine::magicInMouseItem(int animIndex, int item, int itemPos) {
_screen->_curPage = videoPageBackUp;
}
-void KyraEngine::specialMouseItemFX(int shape, int x, int y, int animIndex, int tableIndex, int loopStart, int maxLoops) {
- debugC(9, kDebugLevelMain, "KyraEngine::specialMouseItemFX(%d, %d, %d, %d, %d, %d, %d)", shape, x, y, animIndex, tableIndex, loopStart, maxLoops);
+void KyraEngine_v1::specialMouseItemFX(int shape, int x, int y, int animIndex, int tableIndex, int loopStart, int maxLoops) {
+ debugC(9, kDebugLevelMain, "KyraEngine_v1::specialMouseItemFX(%d, %d, %d, %d, %d, %d, %d)", shape, x, y, animIndex, tableIndex, loopStart, maxLoops);
static const uint8 table1[] = {
0x23, 0x45, 0x55, 0x72, 0x84, 0xCF, 0x00, 0x00
};
@@ -840,8 +840,8 @@ void KyraEngine::specialMouseItemFX(int shape, int x, int y, int animIndex, int
processSpecialMouseItemFX(shape, x, y, tableValue, loopStart, maxLoops);
}
-void KyraEngine::processSpecialMouseItemFX(int shape, int x, int y, int tableValue, int loopStart, int maxLoops) {
- debugC(9, kDebugLevelMain, "KyraEngine::processSpecialMouseItemFX(%d, %d, %d, %d, %d, %d)", shape, x, y, tableValue, loopStart, maxLoops);
+void KyraEngine_v1::processSpecialMouseItemFX(int shape, int x, int y, int tableValue, int loopStart, int maxLoops) {
+ debugC(9, kDebugLevelMain, "KyraEngine_v1::processSpecialMouseItemFX(%d, %d, %d, %d, %d, %d)", shape, x, y, tableValue, loopStart, maxLoops);
uint8 shapeColorTable[16];
uint8 *shapePtr = _shapes[shape] + 10;
if (_flags.useAltShapeHeader)
@@ -859,8 +859,8 @@ void KyraEngine::processSpecialMouseItemFX(int shape, int x, int y, int tableVal
_screen->drawShape(0, _shapes[shape], x, y, 0, 0x8000, shapeColorTable);
}
-void KyraEngine::updatePlayerItemsForScene() {
- debugC(9, kDebugLevelMain, "KyraEngine::updatePlayerItemsForScene()");
+void KyraEngine_v1::updatePlayerItemsForScene() {
+ debugC(9, kDebugLevelMain, "KyraEngine_v1::updatePlayerItemsForScene()");
if (_itemInHand >= 29 && _itemInHand < 33) {
++_itemInHand;
if (_itemInHand > 33)
@@ -900,7 +900,7 @@ void KyraEngine::updatePlayerItemsForScene() {
_screen->showMouse();
}
-void KyraEngine::redrawInventory(int page) {
+void KyraEngine_v1::redrawInventory(int page) {
int videoPageBackUp = _screen->_curPage;
_screen->_curPage = page;
_screen->hideMouse();
@@ -916,26 +916,26 @@ void KyraEngine::redrawInventory(int page) {
_screen->updateScreen();
}
-void KyraEngine::backUpItemRect0(int xpos, int ypos) {
- debugC(9, kDebugLevelMain, "KyraEngine::backUpItemRect0(%d, %d)", xpos, ypos);
+void KyraEngine_v1::backUpItemRect0(int xpos, int ypos) {
+ debugC(9, kDebugLevelMain, "KyraEngine_v1::backUpItemRect0(%d, %d)", xpos, ypos);
_screen->rectClip(xpos, ypos, 3<<3, 24);
_screen->copyRegionToBuffer(_screen->_curPage, xpos, ypos, 3<<3, 24, _itemBkgBackUp[0]);
}
-void KyraEngine::restoreItemRect0(int xpos, int ypos) {
- debugC(9, kDebugLevelMain, "KyraEngine::restoreItemRect0(%d, %d)", xpos, ypos);
+void KyraEngine_v1::restoreItemRect0(int xpos, int ypos) {
+ debugC(9, kDebugLevelMain, "KyraEngine_v1::restoreItemRect0(%d, %d)", xpos, ypos);
_screen->rectClip(xpos, ypos, 3<<3, 24);
_screen->copyBlockToPage(_screen->_curPage, xpos, ypos, 3<<3, 24, _itemBkgBackUp[0]);
}
-void KyraEngine::backUpItemRect1(int xpos, int ypos) {
- debugC(9, kDebugLevelMain, "KyraEngine::backUpItemRect1(%d, %d)", xpos, ypos);
+void KyraEngine_v1::backUpItemRect1(int xpos, int ypos) {
+ debugC(9, kDebugLevelMain, "KyraEngine_v1::backUpItemRect1(%d, %d)", xpos, ypos);
_screen->rectClip(xpos, ypos, 4<<3, 32);
_screen->copyRegionToBuffer(_screen->_curPage, xpos, ypos, 4<<3, 32, _itemBkgBackUp[1]);
}
-void KyraEngine::restoreItemRect1(int xpos, int ypos) {
- debugC(9, kDebugLevelMain, "KyraEngine::restoreItemRect1(%d, %d)", xpos, ypos);
+void KyraEngine_v1::restoreItemRect1(int xpos, int ypos) {
+ debugC(9, kDebugLevelMain, "KyraEngine_v1::restoreItemRect1(%d, %d)", xpos, ypos);
_screen->rectClip(xpos, ypos, 4<<3, 32);
_screen->copyBlockToPage(_screen->_curPage, xpos, ypos, 4<<3, 32, _itemBkgBackUp[1]);
}
diff --git a/engines/kyra/items_v2.cpp b/engines/kyra/items_v2.cpp
new file mode 100644
index 0000000000..fd4c7a5fab
--- /dev/null
+++ b/engines/kyra/items_v2.cpp
@@ -0,0 +1,56 @@
+/* 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 "kyra/kyra_v2.h"
+
+namespace Kyra {
+
+int KyraEngine_v2::findFreeItem() {
+ for (int i = 0; i < 30; ++i) {
+ if (_itemList[i].id == 0xFFFF)
+ return i;
+ }
+ return -1;
+}
+
+int KyraEngine_v2::findItem(uint16 sceneId, int id) {
+ for (int i = 0; i < 30; ++i) {
+ if (_itemList[i].id == id && _itemList[i].sceneId == sceneId)
+ return i;
+ }
+ return -1;
+}
+
+void KyraEngine_v2::resetItemList() {
+ for (int i = 0; i < 30; ++i) {
+ _itemList[i].id = 0xFFFF;
+ _itemList[i].sceneId = 0xFFFF;
+ _itemList[i].x = 0;
+ _itemList[i].y = 0;
+ _itemList[i].unk7 = 0;
+ }
+}
+
+} // end of namespace Kyra
diff --git a/engines/kyra/kyra.cpp b/engines/kyra/kyra.cpp
index 1664ce144f..1d8d7440f0 100644
--- a/engines/kyra/kyra.cpp
+++ b/engines/kyra/kyra.cpp
@@ -26,91 +26,38 @@
#include "common/stdafx.h"
#include "common/config-manager.h"
-#include "common/file.h"
-#include "common/events.h"
-#include "common/system.h"
-#include "common/savefile.h"
-#include "sound/mixer.h"
#include "sound/mididrv.h"
-
-#include "gui/message.h"
+#include "sound/mixer.h"
#include "kyra/kyra.h"
+#include "kyra/sound.h"
#include "kyra/resource.h"
#include "kyra/screen.h"
-#include "kyra/script.h"
-#include "kyra/seqplayer.h"
-#include "kyra/sound.h"
-#include "kyra/sprites.h"
-#include "kyra/wsamovie.h"
-#include "kyra/animator.h"
#include "kyra/text.h"
-#include "kyra/debugger.h"
+#include "kyra/timer.h"
+#include "kyra/script.h"
namespace Kyra {
KyraEngine::KyraEngine(OSystem *system, const GameFlags &flags)
: Engine(system) {
- _flags = flags;
-
- _seq_Forest = _seq_KallakWriting = _seq_KyrandiaLogo = _seq_KallakMalcolm =
- _seq_MalcolmTree = _seq_WestwoodLogo = _seq_Demo1 = _seq_Demo2 = _seq_Demo3 =
- _seq_Demo4 = 0;
-
- _seq_WSATable = _seq_CPSTable = _seq_COLTable = _seq_textsTable = 0;
- _seq_WSATable_Size = _seq_CPSTable_Size = _seq_COLTable_Size = _seq_textsTable_Size = 0;
-
- _roomFilenameTable = _characterImageTable = 0;
- _roomFilenameTableSize = _characterImageTableSize = 0;
- _itemList = _takenList = _placedList = _droppedList = _noDropList = 0;
- _itemList_Size = _takenList_Size = _placedList_Size = _droppedList_Size = _noDropList_Size = 0;
- _putDownFirst = _waitForAmulet = _blackJewel = _poisonGone = _healingTip = 0;
- _putDownFirst_Size = _waitForAmulet_Size = _blackJewel_Size = _poisonGone_Size = _healingTip_Size = 0;
- _thePoison = _fluteString = _wispJewelStrings = _magicJewelString = _flaskFull = _fullFlask = 0;
- _thePoison_Size = _fluteString_Size = _wispJewelStrings_Size = 0;
- _magicJewelString_Size = _flaskFull_Size = _fullFlask_Size = 0;
-
- _defaultShapeTable = 0;
- _healingShapeTable = _healingShape2Table = 0;
- _defaultShapeTableSize = _healingShapeTableSize = _healingShape2TableSize = 0;
- _posionDeathShapeTable = _fluteAnimShapeTable = 0;
- _posionDeathShapeTableSize = _fluteAnimShapeTableSize = 0;
- _winterScrollTable = _winterScroll1Table = _winterScroll2Table = 0;
- _winterScrollTableSize = _winterScroll1TableSize = _winterScroll2TableSize = 0;
- _drinkAnimationTable = _brandonToWispTable = _magicAnimationTable = _brandonStoneTable = 0;
- _drinkAnimationTableSize = _brandonToWispTableSize = _magicAnimationTableSize = _brandonStoneTableSize = 0;
- memset(&_specialPalettes, 0, sizeof(_specialPalettes));
- _debugger = 0;
- _sprites = 0;
- _animator = 0;
- _screen = 0;
_res = 0;
_sound = 0;
- _seq = 0;
- _scriptInterpreter = 0;
_text = 0;
- _npcScriptData = 0;
- _scriptMain = 0;
- _scriptClickData = 0;
- _scriptClick = 0;
- _characterList = 0;
- _movFacingTable = 0;
- memset(_shapes, 0, sizeof(_shapes));
- memset(_movieObjects, 0, sizeof(_movieObjects));
- _finalA = _finalB = _finalC = 0;
- _endSequenceBackUpRect = 0;
- memset(_panPagesTable, 0, sizeof(_panPagesTable));
- _npcScriptData = _scriptClickData = 0;
- _scrollUpButton.process0PtrShape = _scrollUpButton.process1PtrShape = _scrollUpButton.process2PtrShape = 0;
- _scrollDownButton.process0PtrShape = _scrollDownButton.process1PtrShape = _scrollDownButton.process2PtrShape = 0;
- memset(_sceneAnimTable, 0, sizeof(_sceneAnimTable));
+ _staticres = 0;
+ _timer = 0;
+ _scriptInterpreter = 0;
+
+ _flags = flags;
+ _gameSpeed = 60;
+ _tickLength = (uint8)(1000.0 / _gameSpeed);
+
_quitFlag = false;
- _currHeadShape = 0;
-
- _curSfxFile = _curMusicTheme = 0;
-
- memset(&_itemBkgBackUp, 0, sizeof(_itemBkgBackUp));
+
+ _skipFlag = false;
+
+ memset(_flagsTable, 0, sizeof(_flagsTable));
// sets up all engine specific debug levels
Common::addSpecialDebugLevel(kDebugLevelScriptFuncs, "ScriptFuncs", "Script function debug level");
@@ -123,6 +70,7 @@ KyraEngine::KyraEngine(OSystem *system, const GameFlags &flags)
Common::addSpecialDebugLevel(kDebugLevelGUI, "GUI", "GUI debug level");
Common::addSpecialDebugLevel(kDebugLevelSequence, "Sequence", "Sequence debug level");
Common::addSpecialDebugLevel(kDebugLevelMovie, "Movie", "Movie debug level");
+ Common::addSpecialDebugLevel(kDebugLevelTimer, "Timer", "Timer debug level");
}
int KyraEngine::init() {
@@ -133,18 +81,10 @@ int KyraEngine::init() {
_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"));
-
- _screen = new Screen(this, _system);
- assert(_screen);
- if (!_screen->init())
- error("_screen->init() failed");
-
- // for now we prefer Adlib over native MIDI
+
+ // for now we prefer Adlib over native MIDI
int midiDriver = MidiDriver::detectMusicDriver(MDT_MIDI | MDT_ADLIB/* | MDT_PREFER_MIDI*/);
- // TODO: We should play the native Kyra 2 Adlib music, but until that
- // is support, we'll use the automagic MIDI -> Adlib converter.
-
if (_flags.platform == Common::kPlatformFMTowns) {
// no sfx enabled for CD audio music atm
// later on here should be a usage of MixedSoundDriver
@@ -183,155 +123,18 @@ int KyraEngine::init() {
_res = new Resource(this);
assert(_res);
- _sprites = new Sprites(this, _system);
- assert(_sprites);
- _seq = new SeqPlayer(this, _system);
- assert(_seq);
- _animator = new ScreenAnimator(this, _system);
- assert(_animator);
- _animator->init(5, 11, 12);
- assert(*_animator);
- _text = new TextDisplayer(this, _screen);
+ _text = new TextDisplayer(this, this->screen());
assert(_text);
-
_staticres = new StaticResource(this);
assert(_staticres);
if (!_staticres->init())
error("_staticres->init() failed");
-
- initStaticResource();
-
- if (!_sound->init())
- error("Couldn't init sound");
-
- if (_flags.platform == Common::kPlatformFMTowns)
- _sound->setSoundFileList(_soundFilesTowns, _soundFilesTownsCount);
- else
- _sound->setSoundFileList(_soundFiles, _soundFilesCount);
-
- _sound->setVolume(255);
- _sound->loadSoundFile(0);
-
- setupOpcodeTable();
- setupButtonData();
- setupMenu();
-
- _paletteChanged = 1;
- _currentCharacter = 0;
- _characterList = new Character[11];
- assert(_characterList);
- memset(_characterList, 0, sizeof(Character)*11);
-
- for (int i = 0; i < 11; ++i)
- memset(_characterList[i].inventoryItems, 0xFF, sizeof(_characterList[i].inventoryItems));
-
- _characterList[0].sceneId = 5;
- _characterList[0].height = 48;
- _characterList[0].facing = 3;
- _characterList[0].currentAnimFrame = 7;
-
+ _timer = new TimerManager(this, _system);
+ assert(_timer);
_scriptInterpreter = new ScriptHelper(this);
assert(_scriptInterpreter);
- _npcScriptData = new ScriptData;
- memset(_npcScriptData, 0, sizeof(ScriptData));
- assert(_npcScriptData);
- _npcScript = new ScriptState;
- assert(_npcScript);
- memset(_npcScript, 0, sizeof(ScriptState));
-
- _scriptMain = new ScriptState;
- assert(_scriptMain);
- memset(_scriptMain, 0, sizeof(ScriptState));
-
- _scriptClickData = new ScriptData;
- assert(_scriptClickData);
- memset(_scriptClickData, 0, sizeof(ScriptData));
- _scriptClick = new ScriptState;
- assert(_scriptClick);
- memset(_scriptClick, 0, sizeof(ScriptState));
-
- _debugger = new Debugger(this);
- assert(_debugger);
- memset(_shapes, 0, sizeof(_shapes));
-
- for (int i = 0; i < ARRAYSIZE(_movieObjects); ++i)
- _movieObjects[i] = createWSAMovie();
-
- memset(_flagsTable, 0, sizeof(_flagsTable));
-
- _abortWalkFlag = false;
- _abortWalkFlag2 = false;
- _talkingCharNum = -1;
- _charSayUnk3 = -1;
- memset(_currSentenceColor, 0, 3);
- _startSentencePalIndex = -1;
- _fadeText = false;
-
- _cauldronState = 0;
- _crystalState[0] = _crystalState[1] = -1;
-
- _brandonStatusBit = 0;
- _brandonStatusBit0x02Flag = _brandonStatusBit0x20Flag = 10;
- _brandonPosX = _brandonPosY = -1;
- _deathHandler = 0xFF;
- _poisonDeathCounter = 0;
-
- memset(_itemTable, 0, sizeof(_itemTable));
- memset(_exitList, 0xFFFF, sizeof(_exitList));
- _exitListPtr = 0;
- _pathfinderFlag = _pathfinderFlag2 = 0;
- _lastFindWayRet = 0;
- _sceneChangeState = _loopFlag2 = 0;
- _timerNextRun = 0;
-
- _movFacingTable = new int[150];
- assert(_movFacingTable);
- _movFacingTable[0] = 8;
-
- registerDefaultSettings();
- readSettings();
-
- _skipFlag = false;
-
- _marbleVaseItem = -1;
- memset(_foyerItemTable, -1, sizeof(_foyerItemTable));
- _mouseState = _itemInHand = -1;
- _handleInput = false;
-
- _currentRoom = 0xFFFF;
- _scenePhasingFlag = 0;
- _lastProcessedItem = 0;
- _lastProcessedItemHeight = 16;
-
- _unkScreenVar1 = 1;
- _unkScreenVar2 = 0;
- _unkScreenVar3 = 0;
- _unkAmuletVar = 0;
-
- _endSequenceNeedLoading = 1;
- _malcolmFlag = 0;
- _beadStateVar = 0;
- _endSequenceSkipFlag = 0;
- _unkEndSeqVar2 = 0;
- _endSequenceBackUpRect = 0;
- _unkEndSeqVar4 = 0;
- _unkEndSeqVar5 = 0;
- _lastDisplayedPanPage = 0;
- memset(_panPagesTable, 0, sizeof(_panPagesTable));
- _finalA = _finalB = _finalC = 0;
- memset(&_kyragemFadingState, 0, sizeof(_kyragemFadingState));
- _kyragemFadingState.gOffset = 0x13;
- _kyragemFadingState.bOffset = 0x13;
-
- _mousePressFlag = false;
-
- _menuDirectlyToLoad = false;
-
- _lastMusicCommand = 0;
-
- _gameSpeed = 60;
- _tickLength = (uint8)(1000.0 / _gameSpeed);
+ setupOpcodeTable();
_lang = 0;
Common::Language lang = Common::parseLanguage(ConfMan.get("language"));
@@ -363,216 +166,11 @@ int KyraEngine::init() {
}
KyraEngine::~KyraEngine() {
- for (int i = 0; i < ARRAYSIZE(_movieObjects); ++i) {
- if (_movieObjects[i])
- _movieObjects[i]->close();
- delete _movieObjects[i];
- _movieObjects[i] = 0;
- }
-
- closeFinalWsa();
- if (_scriptInterpreter) {
- _scriptInterpreter->unloadScript(_npcScriptData);
- _scriptInterpreter->unloadScript(_scriptClickData);
- }
-
- Common::clearAllSpecialDebugLevels();
-
- delete _debugger;
- delete _sprites;
- delete _animator;
- delete _screen;
delete _res;
delete _sound;
- delete _seq;
- delete _scriptInterpreter;
delete _text;
-
- delete _npcScriptData;
- delete _scriptMain;
-
- delete _scriptClickData;
- delete _scriptClick;
-
- delete [] _characterList;
-
- delete [] _movFacingTable;
-
- delete [] _scrollUpButton.process0PtrShape;
- delete [] _scrollUpButton.process1PtrShape;
- delete [] _scrollUpButton.process2PtrShape;
- delete [] _scrollDownButton.process0PtrShape;
- delete [] _scrollDownButton.process1PtrShape;
- delete [] _scrollDownButton.process2PtrShape;
-
- delete [] _itemBkgBackUp[0];
- delete [] _itemBkgBackUp[1];
-
- for (int i = 0; i < ARRAYSIZE(_shapes); ++i) {
- if (_shapes[i] != 0) {
- delete [] _shapes[i];
- for (int i2 = 0; i2 < ARRAYSIZE(_shapes); i2++) {
- if (_shapes[i2] == _shapes[i] && i2 != i) {
- _shapes[i2] = 0;
- }
- }
- _shapes[i] = 0;
- }
- }
-
- for (int i = 0; i < ARRAYSIZE(_sceneAnimTable); ++i)
- delete [] _sceneAnimTable[i];
-}
-
-int KyraEngine::go() {
- if (_res->getFileSize("6.FNT"))
- _screen->loadFont(Screen::FID_6_FNT, "6.FNT");
- _screen->loadFont(Screen::FID_8_FNT, "8FAT.FNT");
- _screen->setScreenDim(0);
-
- _abortIntroFlag = false;
-
- if (_flags.isDemo) {
- seq_demo();
- } else {
- setGameFlag(0xF3);
- setGameFlag(0xFD);
- setGameFlag(0xEF);
- seq_intro();
- if (_quitFlag)
- return 0;
- if (_skipIntroFlag && _abortIntroFlag)
- resetGameFlag(0xEF);
- startup();
- resetGameFlag(0xEF);
- mainLoop();
- }
- return 0;
-}
-
-
-void KyraEngine::startup() {
- debugC(9, kDebugLevelMain, "KyraEngine::startup()");
- static const uint8 colorMap[] = { 0, 0, 0, 0, 12, 12, 12, 0, 0, 0, 0, 0 };
- _screen->setTextColorMap(colorMap);
-// _screen->setFont(Screen::FID_6_FNT);
- _screen->setAnimBlockPtr(3750);
- memset(_sceneAnimTable, 0, sizeof(_sceneAnimTable));
- loadMouseShapes();
- _currentCharacter = &_characterList[0];
- for (int i = 1; i < 5; ++i)
- _animator->setCharacterDefaultFrame(i);
- for (int i = 5; i <= 10; ++i)
- setCharactersPositions(i);
- _animator->setCharactersHeight();
- resetBrandonPoisonFlags();
- _screen->_curPage = 0;
- // XXX
- for (int i = 0; i < 12; ++i) {
- int size = _screen->getRectSize(3, 24);
- _shapes[361+i] = new byte[size];
- }
-
- _itemBkgBackUp[0] = new uint8[_screen->getRectSize(3, 24)];
- memset(_itemBkgBackUp[0], 0, _screen->getRectSize(3, 24));
- _itemBkgBackUp[1] = new uint8[_screen->getRectSize(4, 32)];
- memset(_itemBkgBackUp[1], 0, _screen->getRectSize(4, 32));
-
- for (int i = 0; i < _roomTableSize; ++i) {
- for (int item = 0; item < 12; ++item) {
- _roomTable[i].itemsTable[item] = 0xFF;
- _roomTable[i].itemsXPos[item] = 0xFFFF;
- _roomTable[i].itemsYPos[item] = 0xFF;
- _roomTable[i].needInit[item] = 0;
- }
- }
-
- loadCharacterShapes();
- loadSpecialEffectShapes();
- loadItems();
- loadButtonShapes();
- initMainButtonList();
- loadMainScreen();
- setupTimers();
- _screen->loadPalette("PALETTE.COL", _screen->_currentPalette);
-
- // XXX
- _animator->initAnimStateList();
- setCharactersInDefaultScene();
-
- if (!_scriptInterpreter->loadScript("_STARTUP.EMC", _npcScriptData, &_opcodes))
- error("Could not load \"_STARTUP.EMC\" script");
- _scriptInterpreter->initScript(_scriptMain, _npcScriptData);
-
- if (!_scriptInterpreter->startScript(_scriptMain, 0))
- error("Could not start script function 0 of script \"_STARTUP.EMC\"");
-
- while (_scriptInterpreter->validScript(_scriptMain))
- _scriptInterpreter->runScript(_scriptMain);
-
- _scriptInterpreter->unloadScript(_npcScriptData);
-
- if (!_scriptInterpreter->loadScript("_NPC.EMC", _npcScriptData, &_opcodes))
- error("Could not load \"_NPC.EMC\" script");
-
- snd_playTheme(1);
- enterNewScene(_currentCharacter->sceneId, _currentCharacter->facing, 0, 0, 1);
-
- if (_abortIntroFlag && _skipIntroFlag) {
- _menuDirectlyToLoad = true;
- _screen->setMouseCursor(1, 1, _shapes[0]);
- _screen->showMouse();
- buttonMenuCallback(0);
- _menuDirectlyToLoad = false;
- } else
- saveGame(getSavegameFilename(0), "New game");
-}
-
-void KyraEngine::mainLoop() {
- debugC(9, kDebugLevelMain, "KyraEngine::mainLoop()");
-
- while (!_quitFlag) {
- int32 frameTime = (int32)_system->getMillis();
- _skipFlag = false;
-
- if (_currentCharacter->sceneId == 210) {
- updateKyragemFading();
- if (seq_playEnd() && _deathHandler != 8)
- break;
- }
-
- if (_deathHandler != 0xFF) {
- snd_playWanderScoreViaMap(0, 1);
- snd_playSoundEffect(49);
- _screen->hideMouse();
- _screen->setMouseCursor(1, 1, _shapes[0]);
- destroyMouseItem();
- _screen->showMouse();
- buttonMenuCallback(0);
- _deathHandler = 0xFF;
- }
-
- if ((_brandonStatusBit & 2) && _brandonStatusBit0x02Flag)
- _animator->animRefreshNPC(0);
-
- if ((_brandonStatusBit & 0x20) && _brandonStatusBit0x20Flag) {
- _animator->animRefreshNPC(0);
- _brandonStatusBit0x20Flag = 0;
- }
-
- _screen->showMouse();
-
- processButtonList(_buttonList);
- updateMousePointer();
- updateGameTimers();
- updateTextFade();
-
- _handleInput = true;
- delay((frameTime + _gameSpeed) - _system->getMillis(), true, true);
- _handleInput = false;
-
- _sound->process();
- }
+ delete _timer;
+ delete _scriptInterpreter;
}
void KyraEngine::quitGame() {
@@ -581,209 +179,15 @@ void KyraEngine::quitGame() {
// Nothing to do here
}
-void KyraEngine::delayUntil(uint32 timestamp, bool updateTimers, bool update, bool isMainLoop) {
- while (_system->getMillis() < timestamp && !_quitFlag) {
- if (updateTimers)
- updateGameTimers();
-
- if (timestamp - _system->getMillis() >= 10)
- delay(10, update, isMainLoop);
- }
-}
-
-void KyraEngine::delay(uint32 amount, bool update, bool isMainLoop) {
- Common::Event event;
- char saveLoadSlot[20];
- char savegameName[14];
-
- uint32 start = _system->getMillis();
- do {
- while (_eventMan->pollEvent(event)) {
- switch (event.type) {
- case Common::EVENT_KEYDOWN:
- if (event.kbd.keycode >= '1' && event.kbd.keycode <= '9' &&
- (event.kbd.flags == Common::KBD_CTRL || event.kbd.flags == Common::KBD_ALT) && isMainLoop) {
- sprintf(saveLoadSlot, "%s.00%d", _targetName.c_str(), event.kbd.keycode - '0');
- if (event.kbd.flags == Common::KBD_CTRL)
- loadGame(saveLoadSlot);
- else {
- sprintf(savegameName, "Quicksave %d", event.kbd.keycode - '0');
- saveGame(saveLoadSlot, savegameName);
- }
- } else if (event.kbd.flags == Common::KBD_CTRL) {
- if (event.kbd.keycode == 'd')
- _debugger->attach();
- else if (event.kbd.keycode == 'q')
- _quitFlag = true;
- } else if (event.kbd.keycode == '.')
- _skipFlag = true;
- else if (event.kbd.keycode == Common::KEYCODE_RETURN || event.kbd.keycode == Common::KEYCODE_SPACE || event.kbd.keycode == Common::KEYCODE_ESCAPE) {
- _abortIntroFlag = true;
- _skipFlag = true;
- }
-
- break;
- case Common::EVENT_MOUSEMOVE:
- _animator->_updateScreen = true;
- break;
- case Common::EVENT_QUIT:
- quitGame();
- break;
- case Common::EVENT_LBUTTONDOWN:
- _mousePressFlag = true;
- break;
- case Common::EVENT_LBUTTONUP:
- _mousePressFlag = false;
-
- if (_abortWalkFlag2)
- _abortWalkFlag = true;
-
- if (_handleInput) {
- _handleInput = false;
- processInput();
- _handleInput = true;
- } else
- _skipFlag = true;
-
- break;
- default:
- break;
- }
- }
-
- if (_debugger->isAttached())
- _debugger->onFrame();
-
- if (update) {
- _sprites->updateSceneAnims();
- _animator->updateAllObjectShapes();
- updateTextFade();
- updateMousePointer();
- }
-
- if (_currentCharacter && _currentCharacter->sceneId == 210 && update)
- updateKyragemFading();
-
- if (_skipFlag && !_abortIntroFlag && !queryGameFlag(0xFE))
- _skipFlag = false;
-
- if (amount > 0 && !_skipFlag && !_quitFlag)
- _system->delayMillis(10);
-
- if (_skipFlag)
- _sound->voiceStop();
- } while (!_skipFlag && _system->getMillis() < start + amount && !_quitFlag);
-}
-
Common::Point KyraEngine::getMousePos() const {
Common::Point mouse = _eventMan->getMousePos();
+
if (_flags.useHiResOverlay) {
mouse.x >>= 1;
mouse.y >>= 1;
}
- return mouse;
-}
-
-void KyraEngine::waitForEvent() {
- bool finished = false;
- Common::Event event;
-
- while (!finished && !_quitFlag) {
- while (_eventMan->pollEvent(event)) {
- switch (event.type) {
- case Common::EVENT_KEYDOWN:
- finished = true;
- break;
- case Common::EVENT_QUIT:
- quitGame();
- break;
- case Common::EVENT_LBUTTONDOWN:
- finished = true;
- _skipFlag = true;
- break;
- default:
- break;
- }
- }
-
- if (_debugger->isAttached())
- _debugger->onFrame();
-
- _system->delayMillis(10);
- }
-}
-
-void KyraEngine::delayWithTicks(int ticks) {
- uint32 nextTime = _system->getMillis() + ticks * _tickLength;
-
- while (_system->getMillis() < nextTime) {
- _sprites->updateSceneAnims();
- _animator->updateAllObjectShapes();
-
- if (_currentCharacter->sceneId == 210) {
- updateKyragemFading();
- seq_playEnd();
- }
-
- if (_skipFlag)
- break;
-
- if (nextTime - _system->getMillis() >= 10)
- delay(10);
- }
-}
-
-#pragma mark -
-#pragma mark - Animation/shape specific code
-#pragma mark -
-
-void KyraEngine::setupShapes123(const Shape *shapeTable, int endShape, int flags) {
- debugC(9, kDebugLevelMain, "KyraEngine::setupShapes123(%p, %d, %d)", (const void *)shapeTable, endShape, flags);
-
- for (int i = 123; i <= 172; ++i)
- _shapes[i] = 0;
-
- uint8 curImage = 0xFF;
- int curPageBackUp = _screen->_curPage;
- _screen->_curPage = 8; // we are using page 8 here in the original page 2 was backuped and then used for this stuff
- int shapeFlags = 2;
- if (flags)
- shapeFlags = 3;
- for (int i = 123; i < 123+endShape; ++i) {
- uint8 newImage = shapeTable[i-123].imageIndex;
- if (newImage != curImage && newImage != 0xFF) {
- assert(_characterImageTable);
- _screen->loadBitmap(_characterImageTable[newImage], 8, 8, 0);
- curImage = newImage;
- }
- _shapes[i] = _screen->encodeShape(shapeTable[i-123].x<<3, shapeTable[i-123].y, shapeTable[i-123].w<<3, shapeTable[i-123].h, shapeFlags);
- assert(i-7 < _defaultShapeTableSize);
- _defaultShapeTable[i-7].xOffset = shapeTable[i-123].xOffset;
- _defaultShapeTable[i-7].yOffset = shapeTable[i-123].yOffset;
- _defaultShapeTable[i-7].w = shapeTable[i-123].w;
- _defaultShapeTable[i-7].h = shapeTable[i-123].h;
- }
- _screen->_curPage = curPageBackUp;
-}
-
-void KyraEngine::freeShapes123() {
- debugC(9, kDebugLevelMain, "KyraEngine::freeShapes123()");
-
- for (int i = 123; i <= 172; ++i) {
- delete [] _shapes[i];
- _shapes[i] = 0;
- }
-}
-
-#pragma mark -
-#pragma mark - Misc stuff
-#pragma mark -
-Movie *KyraEngine::createWSAMovie() {
- if (_flags.platform == Common::kPlatformAmiga)
- return new WSAMovieAmiga(this);
-
- return new WSAMovieV1(this);
+ return mouse;
}
int KyraEngine::setGameFlag(int flag) {
@@ -791,7 +195,7 @@ int KyraEngine::setGameFlag(int flag) {
return 1;
}
-int KyraEngine::queryGameFlag(int flag) {
+int KyraEngine::queryGameFlag(int flag) const {
return ((_flagsTable[flag >> 3] >> (flag & 7)) & 1);
}
@@ -800,344 +204,19 @@ int KyraEngine::resetGameFlag(int flag) {
return 0;
}
-void KyraEngine::setBrandonPoisonFlags(int reset) {
- debugC(9, kDebugLevelMain, "KyraEngine::setBrandonPoisonFlags(%d)", reset);
- _brandonStatusBit |= 1;
-
- if (reset)
- _poisonDeathCounter = 0;
-
- for (int i = 0; i < 0x100; ++i)
- _brandonPoisonFlagsGFX[i] = i;
-
- _brandonPoisonFlagsGFX[0x99] = 0x34;
- _brandonPoisonFlagsGFX[0x9A] = 0x35;
- _brandonPoisonFlagsGFX[0x9B] = 0x37;
- _brandonPoisonFlagsGFX[0x9C] = 0x38;
- _brandonPoisonFlagsGFX[0x9D] = 0x2B;
-}
-
-void KyraEngine::resetBrandonPoisonFlags() {
- debugC(9, kDebugLevelMain, "KyraEngine::resetBrandonPoisonFlags()");
- _brandonStatusBit = 0;
-
- for (int i = 0; i < 0x100; ++i)
- _brandonPoisonFlagsGFX[i] = i;
-}
-
-#pragma mark -
-#pragma mark - Input
-#pragma mark -
-
-void KyraEngine::processInput() {
- Common::Point mouse = getMousePos();
- int xpos = mouse.x;
- int ypos = mouse.y;
-
- debugC(9, kDebugLevelMain, "KyraEngine::processInput(%d, %d)", xpos, ypos);
- _abortWalkFlag2 = false;
-
- if (processInputHelper(xpos, ypos))
- return;
-
- uint8 item = findItemAtPos(xpos, ypos);
- if (item == 0xFF) {
- _changedScene = false;
- int handled = clickEventHandler(xpos, ypos);
- if (_changedScene || handled)
- return;
- }
-
- // XXX _deathHandler specific
- if (ypos <= 158) {
- uint16 exit = 0xFFFF;
- if (xpos < 12) {
- exit = _walkBlockWest;
- } else if (xpos >= 308) {
- exit = _walkBlockEast;
- } else if (ypos >= 136) {
- exit = _walkBlockSouth;
- } else if (ypos < 12) {
- exit = _walkBlockNorth;
- }
-
- if (exit != 0xFFFF) {
- _abortWalkFlag2 = true;
- handleSceneChange(xpos, ypos, 1, 1);
- _abortWalkFlag2 = false;
- return;
- } else {
- int script = checkForNPCScriptRun(xpos, ypos);
- if (script >= 0) {
- runNpcScript(script);
- return;
- }
- if (_itemInHand != -1) {
- if (ypos < 155) {
- if (hasClickedOnExit(xpos, ypos)) {
- _abortWalkFlag2 = true;
- handleSceneChange(xpos, ypos, 1, 1);
- _abortWalkFlag2 = false;
- return;
- }
- dropItem(0, _itemInHand, xpos, ypos, 1);
- }
- } else {
- if (ypos <= 155) {
- _abortWalkFlag2 = true;
- handleSceneChange(xpos, ypos, 1, 1);
- _abortWalkFlag2 = false;
- }
- }
- }
- }
-}
-
-int KyraEngine::processInputHelper(int xpos, int ypos) {
- debugC(9, kDebugLevelMain, "KyraEngine::processInputHelper(%d, %d)", xpos, ypos);
- uint8 item = findItemAtPos(xpos, ypos);
- if (item != 0xFF) {
- if (_itemInHand == -1) {
- _screen->hideMouse();
- _animator->animRemoveGameItem(item);
- snd_playSoundEffect(53);
- assert(_currentCharacter->sceneId < _roomTableSize);
- Room *currentRoom = &_roomTable[_currentCharacter->sceneId];
- int item2 = currentRoom->itemsTable[item];
- currentRoom->itemsTable[item] = 0xFF;
- setMouseItem(item2);
- assert(_itemList && _takenList);
- updateSentenceCommand(_itemList[item2], _takenList[0], 179);
- _itemInHand = item2;
- _screen->showMouse();
- clickEventHandler2();
- return 1;
- } else {
- exchangeItemWithMouseItem(_currentCharacter->sceneId, item);
- return 1;
- }
- }
- return 0;
-}
-
-int KyraEngine::clickEventHandler(int xpos, int ypos) {
- debugC(9, kDebugLevelMain, "KyraEngine::clickEventHandler(%d, %d)", xpos, ypos);
- _scriptInterpreter->initScript(_scriptClick, _scriptClickData);
- _scriptClick->regs[1] = xpos;
- _scriptClick->regs[2] = ypos;
- _scriptClick->regs[3] = 0;
- _scriptClick->regs[4] = _itemInHand;
- _scriptInterpreter->startScript(_scriptClick, 1);
-
- while (_scriptInterpreter->validScript(_scriptClick))
- _scriptInterpreter->runScript(_scriptClick);
-
- return _scriptClick->regs[3];
-}
-
-void KyraEngine::updateMousePointer(bool forceUpdate) {
- int shape = 0;
-
- int newMouseState = 0;
- int newX = 0;
- int newY = 0;
- Common::Point mouse = getMousePos();
- if (mouse.y <= 158) {
- if (mouse.x >= 12) {
- if (mouse.x >= 308) {
- if (_walkBlockEast == 0xFFFF) {
- newMouseState = -2;
- } else {
- newMouseState = -5;
- shape = 3;
- newX = 7;
- newY = 5;
- }
- } else if (mouse.y >= 136) {
- if (_walkBlockSouth == 0xFFFF) {
- newMouseState = -2;
- } else {
- newMouseState = -4;
- shape = 4;
- newX = 5;
- newY = 7;
- }
- } else if (mouse.y < 12) {
- if (_walkBlockNorth == 0xFFFF) {
- newMouseState = -2;
- } else {
- newMouseState = -6;
- shape = 2;
- newX = 5;
- newY = 1;
- }
- }
- } else {
- if (_walkBlockWest == 0xFFFF) {
- newMouseState = -2;
- } else {
- newMouseState = -3;
- newX = 1;
- newY = shape = 5;
- }
- }
- }
-
- if (mouse.x >= _entranceMouseCursorTracks[0] && mouse.y >= _entranceMouseCursorTracks[1]
- && mouse.x <= _entranceMouseCursorTracks[2] && mouse.y <= _entranceMouseCursorTracks[3]) {
- switch (_entranceMouseCursorTracks[4]) {
- case 0:
- newMouseState = -6;
- shape = 2;
- newX = 5;
- newY = 1;
- break;
-
- case 2:
- newMouseState = -5;
- shape = 3;
- newX = 7;
- newY = 5;
- break;
-
- case 4:
- newMouseState = -4;
- shape = 4;
- newX = 5;
- newY = 7;
- break;
-
- case 6:
- newMouseState = -3;
- shape = 5;
- newX = 1;
- newY = 5;
- break;
-
- default:
- break;
- }
- }
-
- if (newMouseState == -2) {
- shape = 6;
- newX = 4;
- newY = 4;
- }
-
- if ((newMouseState && _mouseState != newMouseState) || (newMouseState && forceUpdate)) {
- _mouseState = newMouseState;
- _screen->hideMouse();
- _screen->setMouseCursor(newX, newY, _shapes[shape]);
- _screen->showMouse();
- }
-
- if (!newMouseState) {
- if (_mouseState != _itemInHand || forceUpdate) {
- if (mouse.y > 158 || (mouse.x >= 12 && mouse.x < 308 && mouse.y < 136 && mouse.y >= 12) || forceUpdate) {
- _mouseState = _itemInHand;
- _screen->hideMouse();
- if (_itemInHand == -1) {
- _screen->setMouseCursor(1, 1, _shapes[0]);
- } else {
- _screen->setMouseCursor(8, 15, _shapes[216+_itemInHand]);
- }
- _screen->showMouse();
- }
- }
+void KyraEngine::delayUntil(uint32 timestamp, bool updateTimers, bool update, bool isMainLoop) {
+ while (_system->getMillis() < timestamp && !_quitFlag) {
+ if (timestamp - _system->getMillis() >= 10)
+ delay(10, update, isMainLoop);
}
}
-bool KyraEngine::hasClickedOnExit(int xpos, int ypos) {
- debugC(9, kDebugLevelMain, "KyraEngine::hasClickedOnExit(%d, %d)", xpos, ypos);
- if (xpos < 16 || xpos >= 304)
- return true;
-
- if (ypos < 8)
- return true;
-
- if (ypos < 136 || ypos > 155)
- return false;
-
- return true;
-}
-
-void KyraEngine::clickEventHandler2() {
- debugC(9, kDebugLevelMain, "KyraEngine::clickEventHandler2()");
-
- Common::Point mouse = getMousePos();
-
- _scriptInterpreter->initScript(_scriptClick, _scriptClickData);
- _scriptClick->regs[0] = _currentCharacter->sceneId;
- _scriptClick->regs[1] = mouse.x;
- _scriptClick->regs[2] = mouse.y;
- _scriptClick->regs[4] = _itemInHand;
- _scriptInterpreter->startScript(_scriptClick, 6);
-
- while (_scriptInterpreter->validScript(_scriptClick))
- _scriptInterpreter->runScript(_scriptClick);
-}
-
-int KyraEngine::checkForNPCScriptRun(int xpos, int ypos) {
- debugC(9, kDebugLevelMain, "KyraEngine::checkForNPCScriptRun(%d, %d)", xpos, ypos);
- int returnValue = -1;
- const Character *currentChar = _currentCharacter;
- int charLeft = 0, charRight = 0, charTop = 0, charBottom = 0;
-
- int scaleFactor = _scaleTable[currentChar->y1];
- int addX = (((scaleFactor*8)*3)>>8)>>1;
- int addY = ((scaleFactor*3)<<4)>>8;
-
- charLeft = currentChar->x1 - addX;
- charRight = currentChar->x1 + addX;
- charTop = currentChar->y1 - addY;
- charBottom = currentChar->y1;
-
- if (xpos >= charLeft && charRight >= xpos && charTop <= ypos && charBottom >= ypos)
- return 0;
-
- if (xpos > 304 || xpos < 16)
- return -1;
-
- for (int i = 1; i < 5; ++i) {
- currentChar = &_characterList[i];
-
- if (currentChar->sceneId != _currentCharacter->sceneId)
- continue;
-
- charLeft = currentChar->x1 - 12;
- charRight = currentChar->x1 + 11;
- charTop = currentChar->y1 - 48;
- // if (!i) {
- // charBottom = currentChar->y2 - 16;
- // } else {
- charBottom = currentChar->y1;
- // }
-
- if (xpos < charLeft || xpos > charRight || ypos < charTop || charBottom < ypos)
- continue;
-
- if (returnValue != -1) {
- if (currentChar->y1 >= _characterList[returnValue].y1)
- returnValue = i;
- } else {
- returnValue = i;
- }
- }
-
- return returnValue;
+void KyraEngine::delay(uint32 amount, bool update, bool isMainLoop) {
+ _system->delayMillis(amount);
}
-void KyraEngine::runNpcScript(int func) {
- debugC(9, kDebugLevelMain, "KyraEngine::runNpcScript(%d)", func);
- _scriptInterpreter->initScript(_npcScript, _npcScriptData);
- _scriptInterpreter->startScript(_npcScript, func);
- _npcScript->regs[0] = _currentCharacter->sceneId;
- _npcScript->regs[4] = _itemInHand;
- _npcScript->regs[5] = func;
-
- while (_scriptInterpreter->validScript(_npcScript))
- _scriptInterpreter->runScript(_npcScript);
+void KyraEngine::delayWithTicks(int ticks) {
+ delay(ticks * _tickLength);
}
} // End of namespace Kyra
diff --git a/engines/kyra/kyra.h b/engines/kyra/kyra.h
index bb41a68e6b..8ed546d1ce 100644
--- a/engines/kyra/kyra.h
+++ b/engines/kyra/kyra.h
@@ -31,26 +31,9 @@
#include "common/array.h"
#include "common/events.h"
-namespace Kyra {
+#include "kyra/util.h"
-class Movie;
-class Sound;
-class SoundDigital;
-class SeqPlayer;
-class Resource;
-class PAKFile;
-class Screen;
-class Sprites;
-class ScriptHelper;
-class Debugger;
-class ScreenAnimator;
-class TextDisplayer;
-class KyraEngine;
-class StaticResource;
-
-struct Opcode;
-struct ScriptState;
-struct ScriptData;
+namespace Kyra {
struct GameFlags {
Common::Language lang;
@@ -62,6 +45,11 @@ struct GameFlags {
byte gameID;
};
+struct Rect {
+ int x, y;
+ int x2, y2;
+};
+
enum {
GI_KYRA1 = 0,
GI_KYRA2 = 1,
@@ -71,851 +59,110 @@ enum {
// TODO: this is just the start of makeing the debug output of the kyra engine a bit more useable
// in the future we maybe merge some flags and/or create new ones
enum kDebugLevels {
- kDebugLevelScriptFuncs = 1 << 0, // prints debug output of o1_* functions
+ kDebugLevelScriptFuncs = 1 << 0, // prints debug output of o#_* functions
kDebugLevelScript = 1 << 1, // prints debug output of "ScriptHelper" functions
kDebugLevelSprites = 1 << 2, // prints debug output of "Sprites" functions
kDebugLevelScreen = 1 << 3, // prints debug output of "Screen" functions
kDebugLevelSound = 1 << 4, // prints debug output of "Sound" functions
kDebugLevelAnimator = 1 << 5, // prints debug output of "ScreenAnimator" functions
- kDebugLevelMain = 1 << 6, // prints debug output of common "KyraEngine*" functions && "TextDisplayer" functions
+ kDebugLevelMain = 1 << 6, // prints debug output of common "KyraEngine(_v#)" functions && "TextDisplayer" functions
kDebugLevelGUI = 1 << 7, // prints debug output of "KyraEngine*" gui functions
kDebugLevelSequence = 1 << 8, // prints debug output of "SeqPlayer" functions
- kDebugLevelMovie = 1 << 9 // prints debug output of movie specific funtions
-};
-
-struct Character {
- uint16 sceneId;
- uint8 height;
- uint8 facing;
- uint16 currentAnimFrame;
- uint8 inventoryItems[10];
- int16 x1, y1, x2, y2;
-};
-
-struct Shape {
- uint8 imageIndex;
- int8 xOffset, yOffset;
- uint8 x, y, w, h;
-};
-
-struct Room {
- uint8 nameIndex;
- uint16 northExit;
- uint16 eastExit;
- uint16 southExit;
- uint16 westExit;
- uint8 itemsTable[12];
- uint16 itemsXPos[12];
- uint8 itemsYPos[12];
- uint8 needInit[12];
-};
-
-struct Rect {
- int x, y;
- int x2, y2;
-};
-
-struct Item {
- uint8 unk1;
- uint8 height;
- uint8 unk2;
- uint8 unk3;
-};
-
-struct SeqLoop {
- const uint8 *ptr;
- uint16 count;
-};
-
-struct SceneExits {
- uint16 northXPos;
- uint8 northYPos;
- uint16 eastXPos;
- uint8 eastYPos;
- uint16 southXPos;
- uint8 southYPos;
- uint16 westXPos;
- uint8 westYPos;
-};
-
-struct BeadState {
- int16 x;
- int16 y;
- int16 width;
- int16 height;
- int16 dstX;
- int16 dstY;
- int16 width2;
- int16 unk8;
- int16 unk9;
- int16 tableIndex;
-};
-
-struct Timer {
- uint8 active;
- int32 countdown;
- uint32 nextRun;
- void (KyraEngine::*func)(int timerNum);
-};
-
-struct Button {
- Button *nextButton;
- uint16 specialValue;
- // uint8 unk[4];
- uint8 process0;
- uint8 process1;
- uint8 process2;
- // uint8 unk
- uint16 flags;
- typedef int (KyraEngine::*ButtonCallback)(Button*);
- // using 6 pointers instead of 3 as in the orignal here (safer for use with classes)
- uint8 *process0PtrShape;
- uint8 *process1PtrShape;
- uint8 *process2PtrShape;
- ButtonCallback process0PtrCallback;
- ButtonCallback process1PtrCallback;
- ButtonCallback process2PtrCallback;
- uint16 dimTableIndex;
- uint16 x;
- uint16 y;
- uint16 width;
- uint16 height;
- // uint8 unk[8];
- uint32 flags2;
- ButtonCallback buttonCallback;
- // uint8 unk[8];
+ kDebugLevelMovie = 1 << 9, // prints debug output of movie specific funtions
+ kDebugLevelTimer = 1 << 10 // prints debug output of "TimerManager" functions
};
-struct MenuItem {
- bool enabled;
- uint16 field_1;
- uint8 field_3;
- const char *itemString;
- int16 x;
- int16 field_9;
- uint16 y;
- uint16 width;
- uint16 height;
- uint8 textColor;
- uint8 highlightColor;
- int16 field_12;
- uint8 field_13;
- uint8 bgcolor;
- uint8 color1;
- uint8 color2;
- int (KyraEngine::*callback)(Button*);
- int16 field_1b;
- const char *labelString;
- uint16 labelX;
- uint8 labelY;
- uint8 field_24;
- uint32 field_25;
-};
-
-struct Menu {
- int16 x;
- int16 y;
- uint16 width;
- uint16 height;
- uint8 bgcolor;
- uint8 color1;
- uint8 color2;
- const char *menuName;
- uint8 textColor;
- int16 field_10;
- uint16 field_12;
- uint16 highlightedItem;
- uint8 nrOfItems;
- int16 scrollUpBtnX;
- int16 scrollUpBtnY;
- int16 scrollDownBtnX;
- int16 scrollDownBtnY;
- MenuItem item[6];
-};
+class Screen;
+class Resource;
+class Sound;
+class Movie;
+class TextDisplayer;
+class StaticResource;
+class TimerManager;
+class ScriptHelper;
class KyraEngine : public Engine {
- friend class MusicPlayer;
- friend class Debugger;
- friend class ScreenAnimator;
public:
KyraEngine(OSystem *system, const GameFlags &flags);
virtual ~KyraEngine();
-
+
+ bool quit() const { return _quitFlag; }
+
+ uint8 game() const { return _flags.gameID; }
+ const GameFlags &gameFlags() const { return _flags; }
+
+ // access to Kyra specific functionallity
Resource *resource() { return _res; }
- Screen *screen() { return _screen; }
- ScreenAnimator *animator() { return _animator; }
+ virtual Screen *screen() = 0;
TextDisplayer *text() { return _text; }
Sound *sound() { return _sound; }
StaticResource *staticres() { return _staticres; }
+ TimerManager *timer() { return _timer; }
+
uint32 tickLength() const { return _tickLength; }
- virtual Movie *createWSAMovie();
-
- uint8 game() const { return _flags.gameID; }
- const GameFlags &gameFlags() const { return _flags; }
-
- uint8 **shapes() { return _shapes; }
- Character *currentCharacter() { return _currentCharacter; }
- Character *characterList() { return _characterList; }
- uint16 brandonStatus() { return _brandonStatusBit; }
-
- // TODO: remove me with workaround in animator.cpp l209
- uint16 getScene() { return _currentRoom; }
-
- bool quit() const { return _quitFlag; }
-
- int _paletteChanged;
- Common::RandomSource _rnd;
- int16 _northExitHeight;
-
- typedef void (KyraEngine::*IntroProc)();
-
- // static data access
- const char * const*seqWSATable() { return _seq_WSATable; }
- const char * const*seqCPSTable() { return _seq_CPSTable; }
- const char * const*seqCOLTable() { return _seq_COLTable; }
- const char * const*seqTextsTable() { return _seq_textsTable; }
- const uint8 * const*palTable1() { return &_specialPalettes[0]; }
- const uint8 * const*palTable2() { return &_specialPalettes[29]; }
-
- // sequences
- // -> misc
- bool seq_skipSequence() const;
-
-protected:
- // -> demo
- void seq_demo();
-
- // -> intro
- void seq_intro();
- void seq_introLogos();
- void seq_introStory();
- void seq_introMalcolmTree();
- void seq_introKallakWriting();
- void seq_introKallakMalcolm();
-
- // -> ingame animations
- void seq_createAmuletJewel(int jewel, int page, int noSound, int drawOnly);
- void seq_brandonHealing();
- void seq_brandonHealing2();
- void seq_poisonDeathNow(int now);
- void seq_poisonDeathNowAnim();
- void seq_playFluteAnimation();
- void seq_winterScroll1();
- void seq_winterScroll2();
- void seq_makeBrandonInv();
- void seq_makeBrandonNormal();
- void seq_makeBrandonNormal2();
- void seq_makeBrandonWisp();
- void seq_dispelMagicAnimation();
- void seq_fillFlaskWithWater(int item, int type);
- void seq_playDrinkPotionAnim(int item, int unk2, int flags);
- void seq_brandonToStone();
-
- // -> end fight
- int seq_playEnd();
- void seq_playEnding();
-
- int handleMalcolmFlag();
- int handleBeadState();
- void initBeadState(int x, int y, int x2, int y2, int unk1, BeadState *ptr);
- int processBead(int x, int y, int &x2, int &y2, BeadState *ptr);
-
- // -> credits
- void seq_playCredits();
-
-public:
- // delay
- void delayUntil(uint32 timestamp, bool updateGameTimers = false, bool update = false, bool isMainLoop = false);
- void delay(uint32 millis, bool update = false, bool isMainLoop = false);
- void delayWithTicks(int ticks);
- void waitForEvent();
-
- // TODO
- void quitGame();
-
- void registerDefaultSettings();
- void readSettings();
- void writeSettings();
-
- void snd_playTheme(int file, int track = 0);
- void snd_playVoiceFile(int id);
- void snd_voiceWaitForFinish(bool ingame = true);
- bool snd_voiceIsPlaying();
- void snd_stopVoice();
- void snd_playSoundEffect(int track);
- void snd_playWanderScoreViaMap(int command, int restart);
-
- bool speechEnabled();
- bool textEnabled();
+ virtual Movie *createWSAMovie() = 0;
- void updateGameTimers();
- void clearNextEventTickCount();
- void setTimerCountdown(uint8 timer, int32 countdown);
- void setTimerDelay(uint8 timer, int32 countdown);
- int16 getTimerDelay(uint8 timer);
- void enableTimer(uint8 timer);
- void disableTimer(uint8 timer);
-
- void saveGame(const char *fileName, const char *saveName);
- void loadGame(const char *fileName);
-
- Common::Point getMousePos() const;
+ Common::RandomSource _rnd;
+
+ // quit handling
+ virtual void quitGame();
+ // game flag handling
int setGameFlag(int flag);
- int queryGameFlag(int flag);
+ int queryGameFlag(int flag) const;
int resetGameFlag(int flag);
-protected:
- virtual int go();
- virtual int init();
-
- // input
- void processInput();
- int processInputHelper(int xpos, int ypos);
- int clickEventHandler(int xpos, int ypos);
- void clickEventHandler2();
- void updateMousePointer(bool forceUpdate = false);
- bool hasClickedOnExit(int xpos, int ypos);
-
- // scene
- // -> init
- void loadSceneMsc();
- void startSceneScript(int brandonAlive);
- void setupSceneItems();
- void initSceneData(int facing, int unk1, int brandonAlive);
- void initSceneObjectList(int brandonAlive);
- void initSceneScreen(int brandonAlive);
- void setupSceneResource(int sceneId);
-
- // -> process
- void enterNewScene(int sceneId, int facing, int unk1, int unk2, int brandonAlive);
- int handleSceneChange(int xpos, int ypos, int unk1, int frameReset);
- int processSceneChange(int *table, int unk1, int frameReset);
- int changeScene(int facing);
-
- // -> modification
- void transcendScenes(int roomIndex, int roomName);
- void setSceneFile(int roomIndex, int roomName);
-
- // -> pathfinder
- int findWay(int x, int y, int toX, int toY, int *moveTable, int moveTableSize);
- int findSubPath(int x, int y, int toX, int toY, int *moveTable, int start, int end);
- int getFacingFromPointToPoint(int x, int y, int toX, int toY);
- void changePosTowardsFacing(int &x, int &y, int facing);
- bool lineIsPassable(int x, int y);
- int getMoveTableSize(int *moveTable);
-
- // -> item handling
- // --> misc
- void addItemToRoom(uint16 sceneId, uint8 item, int itemIndex, int x, int y);
-
- // --> drop handling
- void itemDropDown(int x, int y, int destX, int destY, byte freeItem, int item);
- int processItemDrop(uint16 sceneId, uint8 item, int x, int y, int unk1, int unk2);
- void dropItem(int unk1, int item, int x, int y, int unk2);
-
- // --> dropped item handling
- int countItemsInScene(uint16 sceneId);
- void exchangeItemWithMouseItem(uint16 sceneId, int itemIndex);
- byte findFreeItemInScene(int scene);
- byte findItemAtPos(int x, int y);
-
- // --> drop area handling
- void addToNoDropRects(int x, int y, int w, int h);
- void clearNoDropRects();
- int isDropable(int x, int y);
- int checkNoDropRects(int x, int y);
-
- // --> player items handling
- void updatePlayerItemsForScene();
-
- // --> item GFX handling
- void backUpItemRect0(int xpos, int ypos);
- void restoreItemRect0(int xpos, int ypos);
- void backUpItemRect1(int xpos, int ypos);
- void restoreItemRect1(int xpos, int ypos);
-
- // items
- // -> misc
- void placeItemInGenericMapScene(int item, int index);
-
- // -> mouse item
- void createMouseItem(int item);
- void destroyMouseItem();
- void setMouseItem(int item);
-
- // -> graphics effects
- void wipeDownMouseItem(int xpos, int ypos);
- void itemSpecialFX(int x, int y, int item);
- void itemSpecialFX1(int x, int y, int item);
- void itemSpecialFX2(int x, int y, int item);
- void magicOutMouseItem(int animIndex, int itemPos);
- void magicInMouseItem(int animIndex, int item, int itemPos);
- void specialMouseItemFX(int shape, int x, int y, int animIndex, int tableIndex, int loopStart, int maxLoops);
- void processSpecialMouseItemFX(int shape, int x, int y, int tableValue, int loopStart, int maxLoops);
-
- // character
- // -> movement
- void moveCharacterToPos(int character, int facing, int xpos, int ypos);
- void setCharacterPositionWithUpdate(int character);
- int setCharacterPosition(int character, int *facingTable);
- void setCharacterPositionHelper(int character, int *facingTable);
- int getOppositeFacingDirection(int dir);
- void setCharactersPositions(int character);
-
- // -> brandon
- void setBrandonPoisonFlags(int reset);
- void resetBrandonPoisonFlags();
-
- // chat
- // -> process
- void characterSays(int vocFile, const char *chatStr, int8 charNum, int8 chatDuration);
- void waitForChatToFinish(int vocFile, int16 chatDuration, const char *str, uint8 charNum);
-
- // -> initialization
- int initCharacterChat(int8 charNum);
- void backupChatPartnerAnimFrame(int8 charNum);
- void restoreChatPartnerAnimFrame(int8 charNum);
- int8 getChatPartnerNum();
-
- // -> deinitialization
- void endCharacterChat(int8 charNum, int16 arg_4);
-
- // graphics
- // -> misc
- int findDuplicateItemShape(int shape);
- void updateKyragemFading();
-
- // -> interface
- void loadMainScreen(int page = 3);
- void redrawInventory(int page);
-public:
- void drawSentenceCommand(const char *sentence, int unk1);
- void updateSentenceCommand(const char *str1, const char *str2, int unk1);
- void updateTextFade();
-
-protected:
- // -> amulet
- void drawJewelPress(int jewel, int drawSpecial);
- void drawJewelsFadeOutStart();
- void drawJewelsFadeOutEnd(int jewel);
-
- // -> shape handling
- void setupShapes123(const Shape *shapeTable, int endShape, int flags);
- void freeShapes123();
-
- // misc (TODO)
- void startup();
- void mainLoop();
-
- int checkForNPCScriptRun(int xpos, int ypos);
- void runNpcScript(int func);
-
- virtual void setupOpcodeTable() = 0;
- Common::Array<const Opcode*> _opcodes;
-
- void loadMouseShapes();
- void loadCharacterShapes();
- void loadSpecialEffectShapes();
- void loadItems();
- void loadButtonShapes();
- void initMainButtonList();
- void setCharactersInDefaultScene();
- void setupPanPages();
- void freePanPages();
- void closeFinalWsa();
- void setTimer19();
- void setupTimers();
- void timerUpdateHeadAnims(int timerNum);
- void timerSetFlags1(int timerNum);
- void timerSetFlags2(int timerNum);
- void timerSetFlags3(int timerNum);
- void timerCheckAnimFlag1(int timerNum);
- void timerCheckAnimFlag2(int timerNum);
- void checkAmuletAnimFlags();
- void timerRedrawAmulet(int timerNum);
- void timerFadeText(int timerNum);
- void updateAnimFlag1(int timerNum);
- void updateAnimFlag2(int timerNum);
- void drawAmulet();
- void setTextFadeTimerCountdown(int16 countdown);
- void setWalkspeed(uint8 newSpeed);
+ // delay functionallity
+ virtual void delayUntil(uint32 timestamp, bool updateGameTimers = false, bool update = false, bool isMainLoop = false);
+ virtual void delay(uint32 millis, bool update = false, bool isMainLoop = false);
+ virtual void delayWithTicks(int ticks);
- int buttonInventoryCallback(Button *caller);
- int buttonAmuletCallback(Button *caller);
- int buttonMenuCallback(Button *caller);
- int drawBoxCallback(Button *button);
- int drawShadedBoxCallback(Button *button);
- void calcCoords(Menu &menu);
- void initMenu(Menu &menu);
- void setGUILabels();
-
- Button *initButton(Button *list, Button *newButton);
- void processButtonList(Button *list);
- void processButton(Button *button);
- void processMenuButton(Button *button);
- void processAllMenuButtons();
-
- const char *getSavegameFilename(int num);
- void setupSavegames(Menu &menu, int num);
- int getNextSavegameSlot();
-
- int gui_resumeGame(Button *button);
- int gui_loadGameMenu(Button *button);
- int gui_saveGameMenu(Button *button);
- int gui_gameControlsMenu(Button *button);
- int gui_quitPlaying(Button *button);
- int gui_quitConfirmYes(Button *button);
- int gui_quitConfirmNo(Button *button);
- int gui_loadGame(Button *button);
- int gui_saveGame(Button *button);
- int gui_savegameConfirm(Button *button);
- int gui_cancelSubMenu(Button *button);
- int gui_scrollUp(Button *button);
- int gui_scrollDown(Button *button);
- int gui_controlsChangeMusic(Button *button);
- int gui_controlsChangeSounds(Button *button);
- int gui_controlsChangeWalk(Button *button);
- int gui_controlsChangeText(Button *button);
- int gui_controlsChangeVoice(Button *button);
- int gui_controlsApply(Button *button);
-
- bool gui_quitConfirm(const char *str);
- void gui_getInput();
- void gui_redrawText(Menu menu);
- void gui_redrawHighlight(Menu menu);
- void gui_processHighlights(Menu &menu);
- void gui_updateSavegameString();
- void gui_redrawTextfield();
- void gui_fadePalette();
- void gui_restorePalette();
- void gui_setupControls(Menu &menu);
-
- // Kyra 2 and 3 main menu
-
- static const char *_mainMenuStrings[];
- virtual void gui_initMainMenu() {}
- int gui_handleMainMenu();
- virtual void gui_updateMainMenuAnimation();
- void gui_drawMainMenu(const char * const *strings, int select);
- void gui_drawMainBox(int x, int y, int w, int h, int fill);
- bool gui_mainMenuGetInput();
+protected:
+ virtual int go() = 0;
+ virtual int init();
- void gui_printString(const char *string, int x, int y, int col1, int col2, int flags, ...);
-
- GameFlags _flags;
+ // quit Handling
bool _quitFlag;
- bool _skipFlag;
- bool _skipIntroFlag;
- bool _abortIntroFlag;
- bool _menuDirectlyToLoad;
- bool _abortWalkFlag;
- bool _abortWalkFlag2;
- bool _mousePressFlag;
- int8 _mouseWheel;
- uint8 _flagsTable[69];
- uint8 *_itemBkgBackUp[2];
- uint8 *_shapes[373];
- uint16 _gameSpeed;
- uint16 _tickLength;
- int _lang;
- int8 _itemInHand;
- int _mouseState;
- bool _handleInput;
- bool _changedScene;
- int _unkScreenVar1, _unkScreenVar2, _unkScreenVar3;
- int _beadStateVar;
- int _unkAmuletVar;
-
- int _malcolmFlag;
- int _endSequenceSkipFlag;
- int _endSequenceNeedLoading;
- int _unkEndSeqVar2;
- uint8 *_endSequenceBackUpRect;
- int _unkEndSeqVar4;
- int _unkEndSeqVar5;
- int _lastDisplayedPanPage;
- uint8 *_panPagesTable[20];
- Movie *_finalA, *_finalB, *_finalC;
-
- Movie *_movieObjects[10];
-
- uint16 _entranceMouseCursorTracks[8];
- uint16 _walkBlockNorth;
- uint16 _walkBlockEast;
- uint16 _walkBlockSouth;
- uint16 _walkBlockWest;
-
- int32 _scaleMode;
- int16 _scaleTable[145];
-
- Rect _noDropRects[11];
-
- int8 _birthstoneGemTable[4];
- int8 _idolGemsTable[3];
-
- int8 _marbleVaseItem;
- int8 _foyerItemTable[3];
-
- int8 _cauldronState;
- int8 _crystalState[2];
-
- uint16 _brandonStatusBit;
- uint8 _brandonStatusBit0x02Flag;
- uint8 _brandonStatusBit0x20Flag;
- uint8 _brandonPoisonFlagsGFX[256];
- uint8 _deathHandler;
- int16 _brandonInvFlag;
- uint8 _poisonDeathCounter;
- int _brandonPosX;
- int _brandonPosY;
-
- uint16 _currentChatPartnerBackupFrame;
- uint16 _currentCharAnimFrame;
-
- int8 *_sceneAnimTable[50];
-
- Item _itemTable[145];
- int _lastProcessedItem;
- int _lastProcessedItemHeight;
- int16 *_exitListPtr;
- int16 _exitList[11];
- SceneExits _sceneExits;
- uint16 _currentRoom;
- int _scenePhasingFlag;
-
- int _sceneChangeState;
- int _loopFlag2;
-
- int _pathfinderFlag;
- int _pathfinderFlag2;
- int _lastFindWayRet;
- int *_movFacingTable;
-
- int8 _talkingCharNum;
- int8 _charSayUnk2;
- int8 _charSayUnk3;
- int8 _currHeadShape;
- uint8 _currSentenceColor[3];
- int8 _startSentencePalIndex;
- bool _fadeText;
-
- uint8 _configTextspeed;
- uint8 _configWalkspeed;
- int _configMusic;
- bool _configSounds;
- uint8 _configVoice;
-
- int _curMusicTheme;
- int _curSfxFile;
- int16 _lastMusicCommand;
-
+ // intern
Resource *_res;
- Screen *_screen;
- ScreenAnimator *_animator;
Sound *_sound;
- SeqPlayer *_seq;
- Sprites *_sprites;
TextDisplayer *_text;
- ScriptHelper *_scriptInterpreter;
- Debugger *_debugger;
StaticResource *_staticres;
-
- ScriptState *_scriptMain;
-
- ScriptState *_npcScript;
- ScriptData *_npcScriptData;
-
- ScriptState *_scriptClick;
- ScriptData *_scriptClickData;
-
- Character *_characterList;
- Character *_currentCharacter;
-
- Button *_buttonList;
- Button *_menuButtonList;
- bool _displayMenu;
- bool _menuRestoreScreen;
- bool _displaySubMenu;
- bool _cancelSubMenu;
- uint8 _toplevelMenu;
- int _savegameOffset;
- int _gameToLoad;
- char _savegameName[31];
- const char *_specialSavegameString;
- Common::KeyState _keyPressed;
-
- struct KyragemState {
- uint16 nextOperation;
- uint16 rOffset;
- uint16 gOffset;
- uint16 bOffset;
- uint32 timerCount;
- } _kyragemFadingState;
-
- // TODO: get rid of all variables having pointers to the static resources if possible
- // i.e. let them directly use the _staticres functions
- void initStaticResource();
-
- const uint8 *_seq_Forest;
- const uint8 *_seq_KallakWriting;
- const uint8 *_seq_KyrandiaLogo;
- const uint8 *_seq_KallakMalcolm;
- const uint8 *_seq_MalcolmTree;
- const uint8 *_seq_WestwoodLogo;
- const uint8 *_seq_Demo1;
- const uint8 *_seq_Demo2;
- const uint8 *_seq_Demo3;
- const uint8 *_seq_Demo4;
- const uint8 *_seq_Reunion;
-
- const char * const*_seq_WSATable;
- const char * const*_seq_CPSTable;
- const char * const*_seq_COLTable;
- const char * const*_seq_textsTable;
-
- int _seq_WSATable_Size;
- int _seq_CPSTable_Size;
- int _seq_COLTable_Size;
- int _seq_textsTable_Size;
-
- const char * const*_itemList;
- const char * const*_takenList;
- const char * const*_placedList;
- const char * const*_droppedList;
- const char * const*_noDropList;
- const char * const*_putDownFirst;
- const char * const*_waitForAmulet;
- const char * const*_blackJewel;
- const char * const*_poisonGone;
- const char * const*_healingTip;
- const char * const*_thePoison;
- const char * const*_fluteString;
- const char * const*_wispJewelStrings;
- const char * const*_magicJewelString;
- const char * const*_flaskFull;
- const char * const*_fullFlask;
- const char * const*_veryClever;
- const char * const*_homeString;
- const char * const*_newGameString;
+ TimerManager *_timer;
+ ScriptHelper *_scriptInterpreter;
- const char *_voiceTextString;
- const char *_textSpeedString;
- const char *_onString;
- const char *_offString;
- const char *_onCDString;
-
- int _itemList_Size;
- int _takenList_Size;
- int _placedList_Size;
- int _droppedList_Size;
- int _noDropList_Size;
- int _putDownFirst_Size;
- int _waitForAmulet_Size;
- int _blackJewel_Size;
- int _poisonGone_Size;
- int _healingTip_Size;
- int _thePoison_Size;
- int _fluteString_Size;
- int _wispJewelStrings_Size;
- int _magicJewelString_Size;
- int _flaskFull_Size;
- int _fullFlask_Size;
- int _veryClever_Size;
- int _homeString_Size;
- int _newGameString_Size;
+ // game speed
+ bool _skipFlag;
+ uint16 _tickLength;
+ uint16 _gameSpeed;
- const char * const*_characterImageTable;
- int _characterImageTableSize;
-
- const char * const*_guiStrings;
- int _guiStringsSize;
+ // detection
+ GameFlags _flags;
+ int _lang;
- const char * const*_configStrings;
- int _configStringsSize;
-
- Shape *_defaultShapeTable;
- int _defaultShapeTableSize;
-
- const Shape *_healingShapeTable;
- int _healingShapeTableSize;
- const Shape *_healingShape2Table;
- int _healingShape2TableSize;
-
- const Shape *_posionDeathShapeTable;
- int _posionDeathShapeTableSize;
-
- const Shape *_fluteAnimShapeTable;
- int _fluteAnimShapeTableSize;
-
- const Shape *_winterScrollTable;
- int _winterScrollTableSize;
- const Shape *_winterScroll1Table;
- int _winterScroll1TableSize;
- const Shape *_winterScroll2Table;
- int _winterScroll2TableSize;
-
- const Shape *_drinkAnimationTable;
- int _drinkAnimationTableSize;
-
- const Shape *_brandonToWispTable;
- int _brandonToWispTableSize;
-
- const Shape *_magicAnimationTable;
- int _magicAnimationTableSize;
-
- const Shape *_brandonStoneTable;
- int _brandonStoneTableSize;
+ // opcode
+ virtual void setupOpcodeTable() = 0;
+ Common::Array<const Opcode*> _opcodes;
- Room *_roomTable;
- int _roomTableSize;
- const char * const*_roomFilenameTable;
- int _roomFilenameTableSize;
+ // game flags
+ uint8 _flagsTable[100]; // TODO: check this value
- const uint8 *_amuleteAnim;
+ // input
+ Common::Point getMousePos() const;
- const uint8 * const*_specialPalettes;
-
- Timer _timers[34];
- uint32 _timerNextRun;
-
- static const char *_soundFiles[];
- static const int _soundFilesCount;
- static const char *_soundFilesTowns[];
- static const int _soundFilesTownsCount;
+ // pathfinder
+ virtual int findWay(int x, int y, int toX, int toY, int *moveTable, int moveTableSize);
+ int findSubPath(int x, int y, int toX, int toY, int *moveTable, int start, int end);
+ int getFacingFromPointToPoint(int x, int y, int toX, int toY);
+ int getOppositeFacingDirection(int dir);
+ void changePosTowardsFacing(int &x, int &y, int facing);
+ int getMoveTableSize(int *moveTable);
+ virtual bool lineIsPassable(int x, int y) = 0;
- static const int8 _charXPosTable[];
static const int8 _addXPosTable[];
- static const int8 _charYPosTable[];
static const int8 _addYPosTable[];
-
- // positions of the inventory
- static const uint16 _itemPosX[];
- static const uint8 _itemPosY[];
-
- void setupButtonData();
- Button *_buttonData;
- Button **_buttonDataListPtr;
- static Button _menuButtonData[];
- static Button _scrollUpButton;
- static Button _scrollDownButton;
-
- bool _haveScrollButtons;
-
- void setupMenu();
- Menu *_menu;
-
- static const uint8 _magicMouseItemStartFrame[];
- static const uint8 _magicMouseItemEndFrame[];
- static const uint8 _magicMouseItemStartFrame2[];
- static const uint8 _magicMouseItemEndFrame2[];
-
- static const uint16 _amuletX[];
- static const uint16 _amuletY[];
- static const uint16 _amuletX2[];
- static const uint16 _amuletY2[];
};
} // End of namespace Kyra
diff --git a/engines/kyra/kyra_v1.cpp b/engines/kyra/kyra_v1.cpp
index 7fc13a6c38..3c6e257376 100644
--- a/engines/kyra/kyra_v1.cpp
+++ b/engines/kyra/kyra_v1.cpp
@@ -25,15 +25,991 @@
#include "kyra/kyra_v1.h"
+#include "common/file.h"
+#include "common/events.h"
+#include "common/system.h"
+#include "common/savefile.h"
+
+#include "gui/message.h"
+
+#include "kyra/resource.h"
+#include "kyra/screen.h"
+#include "kyra/script.h"
+#include "kyra/seqplayer.h"
+#include "kyra/sound.h"
+#include "kyra/sprites.h"
+#include "kyra/wsamovie.h"
+#include "kyra/animator_v1.h"
+#include "kyra/text.h"
+#include "kyra/debugger.h"
+#include "kyra/timer.h"
+
namespace Kyra {
KyraEngine_v1::KyraEngine_v1(OSystem *system, const GameFlags &flags)
: KyraEngine(system, flags) {
+ _flags = flags;
+
+ _seq_Forest = _seq_KallakWriting = _seq_KyrandiaLogo = _seq_KallakMalcolm =
+ _seq_MalcolmTree = _seq_WestwoodLogo = _seq_Demo1 = _seq_Demo2 = _seq_Demo3 =
+ _seq_Demo4 = 0;
+
+ _seq_WSATable = _seq_CPSTable = _seq_COLTable = _seq_textsTable = 0;
+ _seq_WSATable_Size = _seq_CPSTable_Size = _seq_COLTable_Size = _seq_textsTable_Size = 0;
+
+ _roomFilenameTable = _characterImageTable = 0;
+ _roomFilenameTableSize = _characterImageTableSize = 0;
+ _itemList = _takenList = _placedList = _droppedList = _noDropList = 0;
+ _itemList_Size = _takenList_Size = _placedList_Size = _droppedList_Size = _noDropList_Size = 0;
+ _putDownFirst = _waitForAmulet = _blackJewel = _poisonGone = _healingTip = 0;
+ _putDownFirst_Size = _waitForAmulet_Size = _blackJewel_Size = _poisonGone_Size = _healingTip_Size = 0;
+ _thePoison = _fluteString = _wispJewelStrings = _magicJewelString = _flaskFull = _fullFlask = 0;
+ _thePoison_Size = _fluteString_Size = _wispJewelStrings_Size = 0;
+ _magicJewelString_Size = _flaskFull_Size = _fullFlask_Size = 0;
+
+ _defaultShapeTable = 0;
+ _healingShapeTable = _healingShape2Table = 0;
+ _defaultShapeTableSize = _healingShapeTableSize = _healingShape2TableSize = 0;
+ _posionDeathShapeTable = _fluteAnimShapeTable = 0;
+ _posionDeathShapeTableSize = _fluteAnimShapeTableSize = 0;
+ _winterScrollTable = _winterScroll1Table = _winterScroll2Table = 0;
+ _winterScrollTableSize = _winterScroll1TableSize = _winterScroll2TableSize = 0;
+ _drinkAnimationTable = _brandonToWispTable = _magicAnimationTable = _brandonStoneTable = 0;
+ _drinkAnimationTableSize = _brandonToWispTableSize = _magicAnimationTableSize = _brandonStoneTableSize = 0;
+ memset(&_specialPalettes, 0, sizeof(_specialPalettes));
+ _debugger = 0;
+ _sprites = 0;
+ _animator = 0;
+ _seq = 0;
+ _npcScriptData = 0;
+ _scriptMain = 0;
+ _scriptClickData = 0;
+ _scriptClick = 0;
+ _characterList = 0;
+ _movFacingTable = 0;
+ memset(_shapes, 0, sizeof(_shapes));
+ memset(_movieObjects, 0, sizeof(_movieObjects));
+ _finalA = _finalB = _finalC = 0;
+ _endSequenceBackUpRect = 0;
+ memset(_panPagesTable, 0, sizeof(_panPagesTable));
+ _npcScriptData = _scriptClickData = 0;
+ _scrollUpButton.process0PtrShape = _scrollUpButton.process1PtrShape = _scrollUpButton.process2PtrShape = 0;
+ _scrollDownButton.process0PtrShape = _scrollDownButton.process1PtrShape = _scrollDownButton.process2PtrShape = 0;
+ memset(_sceneAnimTable, 0, sizeof(_sceneAnimTable));
+ _currHeadShape = 0;
+
+ _curSfxFile = _curMusicTheme = 0;
+
+ memset(&_itemBkgBackUp, 0, sizeof(_itemBkgBackUp));
}
KyraEngine_v1::~KyraEngine_v1() {
+ for (int i = 0; i < ARRAYSIZE(_movieObjects); ++i) {
+ if (_movieObjects[i])
+ _movieObjects[i]->close();
+ delete _movieObjects[i];
+ _movieObjects[i] = 0;
+ }
+
+ closeFinalWsa();
+ if (_scriptInterpreter) {
+ _scriptInterpreter->unloadScript(_npcScriptData);
+ _scriptInterpreter->unloadScript(_scriptClickData);
+ }
+
+ Common::clearAllSpecialDebugLevels();
+
+ delete _screen;
+ delete _debugger;
+ delete _sprites;
+ delete _animator;
+ delete _seq;
+
+ delete _npcScriptData;
+ delete _scriptMain;
+
+ delete _scriptClickData;
+ delete _scriptClick;
+
+ delete [] _characterList;
+
+ delete [] _movFacingTable;
+
+ delete [] _scrollUpButton.process0PtrShape;
+ delete [] _scrollUpButton.process1PtrShape;
+ delete [] _scrollUpButton.process2PtrShape;
+ delete [] _scrollDownButton.process0PtrShape;
+ delete [] _scrollDownButton.process1PtrShape;
+ delete [] _scrollDownButton.process2PtrShape;
+
+ delete [] _itemBkgBackUp[0];
+ delete [] _itemBkgBackUp[1];
+
+ for (int i = 0; i < ARRAYSIZE(_shapes); ++i) {
+ if (_shapes[i] != 0) {
+ delete [] _shapes[i];
+ for (int i2 = 0; i2 < ARRAYSIZE(_shapes); i2++) {
+ if (_shapes[i2] == _shapes[i] && i2 != i) {
+ _shapes[i2] = 0;
+ }
+ }
+ _shapes[i] = 0;
+ }
+ }
+
+ for (int i = 0; i < ARRAYSIZE(_sceneAnimTable); ++i)
+ delete [] _sceneAnimTable[i];
+}
+
+int KyraEngine_v1::init() {
+ _screen = new Screen_v1(this, _system);
+ assert(_screen);
+ if (!_screen->init())
+ error("_screen->init() failed");
+
+ KyraEngine::init();
+
+ _sprites = new Sprites(this, _system);
+ assert(_sprites);
+ _seq = new SeqPlayer(this, _system);
+ assert(_seq);
+ _animator = new ScreenAnimator(this, _system);
+ assert(_animator);
+ _animator->init(5, 11, 12);
+ assert(*_animator);
+
+ initStaticResource();
+
+ if (_flags.platform == Common::kPlatformFMTowns)
+ _sound->setSoundFileList(_soundFilesTowns, _soundFilesTownsCount);
+ else
+ _sound->setSoundFileList(_soundFiles, _soundFilesCount);
+
+ if (!_sound->init())
+ error("Couldn't init sound");
+
+ _sound->setVolume(255);
+ _sound->loadSoundFile(0);
+
+ setupTimers();
+ setupButtonData();
+ setupMenu();
+
+ _paletteChanged = 1;
+ _currentCharacter = 0;
+ _characterList = new Character[11];
+ assert(_characterList);
+ memset(_characterList, 0, sizeof(Character)*11);
+
+ for (int i = 0; i < 11; ++i)
+ memset(_characterList[i].inventoryItems, 0xFF, sizeof(_characterList[i].inventoryItems));
+
+ _characterList[0].sceneId = 5;
+ _characterList[0].height = 48;
+ _characterList[0].facing = 3;
+ _characterList[0].currentAnimFrame = 7;
+
+ _npcScriptData = new ScriptData;
+ memset(_npcScriptData, 0, sizeof(ScriptData));
+ assert(_npcScriptData);
+ _npcScript = new ScriptState;
+ assert(_npcScript);
+ memset(_npcScript, 0, sizeof(ScriptState));
+
+ _scriptMain = new ScriptState;
+ assert(_scriptMain);
+ memset(_scriptMain, 0, sizeof(ScriptState));
+
+ _scriptClickData = new ScriptData;
+ assert(_scriptClickData);
+ memset(_scriptClickData, 0, sizeof(ScriptData));
+ _scriptClick = new ScriptState;
+ assert(_scriptClick);
+ memset(_scriptClick, 0, sizeof(ScriptState));
+
+ _debugger = new Debugger_v1(this);
+ assert(_debugger);
+ memset(_shapes, 0, sizeof(_shapes));
+
+ for (int i = 0; i < ARRAYSIZE(_movieObjects); ++i)
+ _movieObjects[i] = createWSAMovie();
+
+ memset(_flagsTable, 0, sizeof(_flagsTable));
+
+ _abortWalkFlag = false;
+ _abortWalkFlag2 = false;
+ _talkingCharNum = -1;
+ _charSayUnk3 = -1;
+ memset(_currSentenceColor, 0, 3);
+ _startSentencePalIndex = -1;
+ _fadeText = false;
+
+ _cauldronState = 0;
+ _crystalState[0] = _crystalState[1] = -1;
+
+ _brandonStatusBit = 0;
+ _brandonStatusBit0x02Flag = _brandonStatusBit0x20Flag = 10;
+ _brandonPosX = _brandonPosY = -1;
+ _deathHandler = 0xFF;
+ _poisonDeathCounter = 0;
+
+ memset(_itemTable, 0, sizeof(_itemTable));
+ memset(_exitList, 0xFFFF, sizeof(_exitList));
+ _exitListPtr = 0;
+ _pathfinderFlag = _pathfinderFlag2 = 0;
+ _lastFindWayRet = 0;
+ _sceneChangeState = _loopFlag2 = 0;
+
+ _movFacingTable = new int[150];
+ assert(_movFacingTable);
+ _movFacingTable[0] = 8;
+
+ registerDefaultSettings();
+ readSettings();
+
+ _skipFlag = false;
+
+ _marbleVaseItem = -1;
+ memset(_foyerItemTable, -1, sizeof(_foyerItemTable));
+ _mouseState = _itemInHand = -1;
+ _handleInput = false;
+
+ _currentRoom = 0xFFFF;
+ _scenePhasingFlag = 0;
+ _lastProcessedItem = 0;
+ _lastProcessedItemHeight = 16;
+
+ _unkScreenVar1 = 1;
+ _unkScreenVar2 = 0;
+ _unkScreenVar3 = 0;
+ _unkAmuletVar = 0;
+
+ _endSequenceNeedLoading = 1;
+ _malcolmFlag = 0;
+ _beadStateVar = 0;
+ _endSequenceSkipFlag = 0;
+ _unkEndSeqVar2 = 0;
+ _endSequenceBackUpRect = 0;
+ _unkEndSeqVar4 = 0;
+ _unkEndSeqVar5 = 0;
+ _lastDisplayedPanPage = 0;
+ memset(_panPagesTable, 0, sizeof(_panPagesTable));
+ _finalA = _finalB = _finalC = 0;
+ memset(&_kyragemFadingState, 0, sizeof(_kyragemFadingState));
+ _kyragemFadingState.gOffset = 0x13;
+ _kyragemFadingState.bOffset = 0x13;
+
+ _mousePressFlag = false;
+
+ _menuDirectlyToLoad = false;
+
+ _lastMusicCommand = 0;
+
+ return 0;
+}
+
+int KyraEngine_v1::go() {
+ if (_res->getFileSize("6.FNT"))
+ _screen->loadFont(Screen::FID_6_FNT, "6.FNT");
+ _screen->loadFont(Screen::FID_8_FNT, "8FAT.FNT");
+ _screen->setScreenDim(0);
+
+ _abortIntroFlag = false;
+
+ if (_flags.isDemo) {
+ seq_demo();
+ } else {
+ setGameFlag(0xF3);
+ setGameFlag(0xFD);
+ setGameFlag(0xEF);
+ seq_intro();
+ if (_quitFlag)
+ return 0;
+ if (_skipIntroFlag && _abortIntroFlag)
+ resetGameFlag(0xEF);
+ startup();
+ resetGameFlag(0xEF);
+ mainLoop();
+ }
+ return 0;
+}
+
+
+void KyraEngine_v1::startup() {
+ debugC(9, kDebugLevelMain, "KyraEngine_v1::startup()");
+ static const uint8 colorMap[] = { 0, 0, 0, 0, 12, 12, 12, 0, 0, 0, 0, 0 };
+ _screen->setTextColorMap(colorMap);
+// _screen->setFont(Screen::FID_6_FNT);
+ _screen->setAnimBlockPtr(3750);
+ memset(_sceneAnimTable, 0, sizeof(_sceneAnimTable));
+ loadMouseShapes();
+ _currentCharacter = &_characterList[0];
+ for (int i = 1; i < 5; ++i)
+ _animator->setCharacterDefaultFrame(i);
+ for (int i = 5; i <= 10; ++i)
+ setCharactersPositions(i);
+ _animator->setCharactersHeight();
+ resetBrandonPoisonFlags();
+ _screen->_curPage = 0;
+ // XXX
+ for (int i = 0; i < 12; ++i) {
+ int size = _screen->getRectSize(3, 24);
+ _shapes[361+i] = new byte[size];
+ }
+
+ _itemBkgBackUp[0] = new uint8[_screen->getRectSize(3, 24)];
+ memset(_itemBkgBackUp[0], 0, _screen->getRectSize(3, 24));
+ _itemBkgBackUp[1] = new uint8[_screen->getRectSize(4, 32)];
+ memset(_itemBkgBackUp[1], 0, _screen->getRectSize(4, 32));
+
+ for (int i = 0; i < _roomTableSize; ++i) {
+ for (int item = 0; item < 12; ++item) {
+ _roomTable[i].itemsTable[item] = 0xFF;
+ _roomTable[i].itemsXPos[item] = 0xFFFF;
+ _roomTable[i].itemsYPos[item] = 0xFF;
+ _roomTable[i].needInit[item] = 0;
+ }
+ }
+
+ loadCharacterShapes();
+ loadSpecialEffectShapes();
+ loadItems();
+ loadButtonShapes();
+ initMainButtonList();
+ loadMainScreen();
+ setupTimers();
+ _screen->loadPalette("PALETTE.COL", _screen->_currentPalette);
+
+ // XXX
+ _animator->initAnimStateList();
+ setCharactersInDefaultScene();
+
+ if (!_scriptInterpreter->loadScript("_STARTUP.EMC", _npcScriptData, &_opcodes))
+ error("Could not load \"_STARTUP.EMC\" script");
+ _scriptInterpreter->initScript(_scriptMain, _npcScriptData);
+
+ if (!_scriptInterpreter->startScript(_scriptMain, 0))
+ error("Could not start script function 0 of script \"_STARTUP.EMC\"");
+
+ while (_scriptInterpreter->validScript(_scriptMain))
+ _scriptInterpreter->runScript(_scriptMain);
+
+ _scriptInterpreter->unloadScript(_npcScriptData);
+
+ if (!_scriptInterpreter->loadScript("_NPC.EMC", _npcScriptData, &_opcodes))
+ error("Could not load \"_NPC.EMC\" script");
+
+ snd_playTheme(1);
+ enterNewScene(_currentCharacter->sceneId, _currentCharacter->facing, 0, 0, 1);
+
+ if (_abortIntroFlag && _skipIntroFlag) {
+ _menuDirectlyToLoad = true;
+ _screen->setMouseCursor(1, 1, _shapes[0]);
+ _screen->showMouse();
+ buttonMenuCallback(0);
+ _menuDirectlyToLoad = false;
+ } else
+ saveGame(getSavegameFilename(0), "New game");
+}
+
+void KyraEngine_v1::mainLoop() {
+ debugC(9, kDebugLevelMain, "KyraEngine_v1::mainLoop()");
+
+ while (!_quitFlag) {
+ int32 frameTime = (int32)_system->getMillis();
+ _skipFlag = false;
+
+ if (_currentCharacter->sceneId == 210) {
+ updateKyragemFading();
+ if (seq_playEnd() && _deathHandler != 8)
+ break;
+ }
+
+ if (_deathHandler != 0xFF) {
+ snd_playWanderScoreViaMap(0, 1);
+ snd_playSoundEffect(49);
+ _screen->hideMouse();
+ _screen->setMouseCursor(1, 1, _shapes[0]);
+ destroyMouseItem();
+ _screen->showMouse();
+ buttonMenuCallback(0);
+ _deathHandler = 0xFF;
+ }
+
+ if ((_brandonStatusBit & 2) && _brandonStatusBit0x02Flag)
+ _animator->animRefreshNPC(0);
+
+ if ((_brandonStatusBit & 0x20) && _brandonStatusBit0x20Flag) {
+ _animator->animRefreshNPC(0);
+ _brandonStatusBit0x20Flag = 0;
+ }
+
+ _screen->showMouse();
+
+ processButtonList(_buttonList);
+ updateMousePointer();
+ _timer->update();
+ updateTextFade();
+
+ _handleInput = true;
+ delay((frameTime + _gameSpeed) - _system->getMillis(), true, true);
+ _handleInput = false;
+
+ _sound->process();
+ }
+}
+
+void KyraEngine_v1::delayUntil(uint32 timestamp, bool updateTimers, bool update, bool isMainLoop) {
+ while (_system->getMillis() < timestamp && !_quitFlag) {
+ if (updateTimers)
+ _timer->update();
+
+ if (timestamp - _system->getMillis() >= 10)
+ delay(10, update, isMainLoop);
+ }
+}
+
+void KyraEngine_v1::delay(uint32 amount, bool update, bool isMainLoop) {
+ Common::Event event;
+ char saveLoadSlot[20];
+ char savegameName[14];
+
+ uint32 start = _system->getMillis();
+ do {
+ while (_eventMan->pollEvent(event)) {
+ switch (event.type) {
+ case Common::EVENT_KEYDOWN:
+ if (event.kbd.keycode >= '1' && event.kbd.keycode <= '9' &&
+ (event.kbd.flags == Common::KBD_CTRL || event.kbd.flags == Common::KBD_ALT) && isMainLoop) {
+ sprintf(saveLoadSlot, "%s.00%d", _targetName.c_str(), event.kbd.keycode - '0');
+ if (event.kbd.flags == Common::KBD_CTRL)
+ loadGame(saveLoadSlot);
+ else {
+ sprintf(savegameName, "Quicksave %d", event.kbd.keycode - '0');
+ saveGame(saveLoadSlot, savegameName);
+ }
+ } else if (event.kbd.flags == Common::KBD_CTRL) {
+ if (event.kbd.keycode == 'd')
+ _debugger->attach();
+ else if (event.kbd.keycode == 'q')
+ _quitFlag = true;
+ } else if (event.kbd.keycode == '.')
+ _skipFlag = true;
+ else if (event.kbd.keycode == Common::KEYCODE_RETURN || event.kbd.keycode == Common::KEYCODE_SPACE || event.kbd.keycode == Common::KEYCODE_ESCAPE) {
+ _abortIntroFlag = true;
+ _skipFlag = true;
+ }
+
+ break;
+ case Common::EVENT_MOUSEMOVE:
+ _animator->_updateScreen = true;
+ break;
+ case Common::EVENT_QUIT:
+ quitGame();
+ break;
+ case Common::EVENT_LBUTTONDOWN:
+ _mousePressFlag = true;
+ break;
+ case Common::EVENT_LBUTTONUP:
+ _mousePressFlag = false;
+
+ if (_abortWalkFlag2)
+ _abortWalkFlag = true;
+
+ if (_handleInput) {
+ _handleInput = false;
+ processInput();
+ _handleInput = true;
+ } else
+ _skipFlag = true;
+
+ break;
+ default:
+ break;
+ }
+ }
+
+ if (_debugger->isAttached())
+ _debugger->onFrame();
+
+ if (update) {
+ _sprites->updateSceneAnims();
+ _animator->updateAllObjectShapes();
+ updateTextFade();
+ updateMousePointer();
+ }
+
+ if (_currentCharacter && _currentCharacter->sceneId == 210 && update)
+ updateKyragemFading();
+
+ if (_skipFlag && !_abortIntroFlag && !queryGameFlag(0xFE))
+ _skipFlag = false;
+
+ if (amount > 0 && !_skipFlag && !_quitFlag)
+ _system->delayMillis(10);
+
+ if (_skipFlag)
+ _sound->voiceStop();
+ } while (!_skipFlag && _system->getMillis() < start + amount && !_quitFlag);
+}
+
+void KyraEngine_v1::waitForEvent() {
+ bool finished = false;
+ Common::Event event;
+
+ while (!finished && !_quitFlag) {
+ while (_eventMan->pollEvent(event)) {
+ switch (event.type) {
+ case Common::EVENT_KEYDOWN:
+ finished = true;
+ break;
+ case Common::EVENT_QUIT:
+ quitGame();
+ break;
+ case Common::EVENT_LBUTTONDOWN:
+ finished = true;
+ _skipFlag = true;
+ break;
+ default:
+ break;
+ }
+ }
+
+ if (_debugger->isAttached())
+ _debugger->onFrame();
+
+ _system->delayMillis(10);
+ }
+}
+
+void KyraEngine_v1::delayWithTicks(int ticks) {
+ uint32 nextTime = _system->getMillis() + ticks * _tickLength;
+
+ while (_system->getMillis() < nextTime) {
+ _sprites->updateSceneAnims();
+ _animator->updateAllObjectShapes();
+
+ if (_currentCharacter->sceneId == 210) {
+ updateKyragemFading();
+ seq_playEnd();
+ }
+
+ if (_skipFlag)
+ break;
+
+ if (nextTime - _system->getMillis() >= 10)
+ delay(10);
+ }
+}
+
+#pragma mark -
+#pragma mark - Animation/shape specific code
+#pragma mark -
+
+void KyraEngine_v1::setupShapes123(const Shape *shapeTable, int endShape, int flags) {
+ debugC(9, kDebugLevelMain, "KyraEngine_v1::setupShapes123(%p, %d, %d)", (const void *)shapeTable, endShape, flags);
+
+ for (int i = 123; i <= 172; ++i)
+ _shapes[i] = 0;
+
+ uint8 curImage = 0xFF;
+ int curPageBackUp = _screen->_curPage;
+ _screen->_curPage = 8; // we are using page 8 here in the original page 2 was backuped and then used for this stuff
+ int shapeFlags = 2;
+ if (flags)
+ shapeFlags = 3;
+ for (int i = 123; i < 123+endShape; ++i) {
+ uint8 newImage = shapeTable[i-123].imageIndex;
+ if (newImage != curImage && newImage != 0xFF) {
+ assert(_characterImageTable);
+ _screen->loadBitmap(_characterImageTable[newImage], 8, 8, 0);
+ curImage = newImage;
+ }
+ _shapes[i] = _screen->encodeShape(shapeTable[i-123].x<<3, shapeTable[i-123].y, shapeTable[i-123].w<<3, shapeTable[i-123].h, shapeFlags);
+ assert(i-7 < _defaultShapeTableSize);
+ _defaultShapeTable[i-7].xOffset = shapeTable[i-123].xOffset;
+ _defaultShapeTable[i-7].yOffset = shapeTable[i-123].yOffset;
+ _defaultShapeTable[i-7].w = shapeTable[i-123].w;
+ _defaultShapeTable[i-7].h = shapeTable[i-123].h;
+ }
+ _screen->_curPage = curPageBackUp;
+}
+
+void KyraEngine_v1::freeShapes123() {
+ debugC(9, kDebugLevelMain, "KyraEngine_v1::freeShapes123()");
+
+ for (int i = 123; i <= 172; ++i) {
+ delete [] _shapes[i];
+ _shapes[i] = 0;
+ }
+}
+
+#pragma mark -
+#pragma mark - Misc stuff
+#pragma mark -
+
+Movie *KyraEngine_v1::createWSAMovie() {
+ if (_flags.platform == Common::kPlatformAmiga)
+ return new WSAMovieAmiga(this);
+
+ return new WSAMovieV1(this);
+}
+
+void KyraEngine_v1::setBrandonPoisonFlags(int reset) {
+ debugC(9, kDebugLevelMain, "KyraEngine_v1::setBrandonPoisonFlags(%d)", reset);
+ _brandonStatusBit |= 1;
+
+ if (reset)
+ _poisonDeathCounter = 0;
+
+ for (int i = 0; i < 0x100; ++i)
+ _brandonPoisonFlagsGFX[i] = i;
+
+ _brandonPoisonFlagsGFX[0x99] = 0x34;
+ _brandonPoisonFlagsGFX[0x9A] = 0x35;
+ _brandonPoisonFlagsGFX[0x9B] = 0x37;
+ _brandonPoisonFlagsGFX[0x9C] = 0x38;
+ _brandonPoisonFlagsGFX[0x9D] = 0x2B;
+}
+
+void KyraEngine_v1::resetBrandonPoisonFlags() {
+ debugC(9, kDebugLevelMain, "KyraEngine_v1::resetBrandonPoisonFlags()");
+ _brandonStatusBit = 0;
+
+ for (int i = 0; i < 0x100; ++i)
+ _brandonPoisonFlagsGFX[i] = i;
+}
+
+#pragma mark -
+#pragma mark - Input
+#pragma mark -
+
+void KyraEngine_v1::processInput() {
+ Common::Point mouse = getMousePos();
+ int xpos = mouse.x;
+ int ypos = mouse.y;
+
+ debugC(9, kDebugLevelMain, "KyraEngine_v1::processInput(%d, %d)", xpos, ypos);
+ _abortWalkFlag2 = false;
+
+ if (processInputHelper(xpos, ypos))
+ return;
+
+ uint8 item = findItemAtPos(xpos, ypos);
+ if (item == 0xFF) {
+ _changedScene = false;
+ int handled = clickEventHandler(xpos, ypos);
+ if (_changedScene || handled)
+ return;
+ }
+
+ // XXX _deathHandler specific
+ if (ypos <= 158) {
+ uint16 exit = 0xFFFF;
+ if (xpos < 12) {
+ exit = _walkBlockWest;
+ } else if (xpos >= 308) {
+ exit = _walkBlockEast;
+ } else if (ypos >= 136) {
+ exit = _walkBlockSouth;
+ } else if (ypos < 12) {
+ exit = _walkBlockNorth;
+ }
+
+ if (exit != 0xFFFF) {
+ _abortWalkFlag2 = true;
+ handleSceneChange(xpos, ypos, 1, 1);
+ _abortWalkFlag2 = false;
+ return;
+ } else {
+ int script = checkForNPCScriptRun(xpos, ypos);
+ if (script >= 0) {
+ runNpcScript(script);
+ return;
+ }
+ if (_itemInHand != -1) {
+ if (ypos < 155) {
+ if (hasClickedOnExit(xpos, ypos)) {
+ _abortWalkFlag2 = true;
+ handleSceneChange(xpos, ypos, 1, 1);
+ _abortWalkFlag2 = false;
+ return;
+ }
+ dropItem(0, _itemInHand, xpos, ypos, 1);
+ }
+ } else {
+ if (ypos <= 155) {
+ _abortWalkFlag2 = true;
+ handleSceneChange(xpos, ypos, 1, 1);
+ _abortWalkFlag2 = false;
+ }
+ }
+ }
+ }
+}
+
+int KyraEngine_v1::processInputHelper(int xpos, int ypos) {
+ debugC(9, kDebugLevelMain, "KyraEngine_v1::processInputHelper(%d, %d)", xpos, ypos);
+ uint8 item = findItemAtPos(xpos, ypos);
+ if (item != 0xFF) {
+ if (_itemInHand == -1) {
+ _screen->hideMouse();
+ _animator->animRemoveGameItem(item);
+ snd_playSoundEffect(53);
+ assert(_currentCharacter->sceneId < _roomTableSize);
+ Room *currentRoom = &_roomTable[_currentCharacter->sceneId];
+ int item2 = currentRoom->itemsTable[item];
+ currentRoom->itemsTable[item] = 0xFF;
+ setMouseItem(item2);
+ assert(_itemList && _takenList);
+ updateSentenceCommand(_itemList[item2], _takenList[0], 179);
+ _itemInHand = item2;
+ _screen->showMouse();
+ clickEventHandler2();
+ return 1;
+ } else {
+ exchangeItemWithMouseItem(_currentCharacter->sceneId, item);
+ return 1;
+ }
+ }
+ return 0;
+}
+
+int KyraEngine_v1::clickEventHandler(int xpos, int ypos) {
+ debugC(9, kDebugLevelMain, "KyraEngine_v1::clickEventHandler(%d, %d)", xpos, ypos);
+ _scriptInterpreter->initScript(_scriptClick, _scriptClickData);
+ _scriptClick->regs[1] = xpos;
+ _scriptClick->regs[2] = ypos;
+ _scriptClick->regs[3] = 0;
+ _scriptClick->regs[4] = _itemInHand;
+ _scriptInterpreter->startScript(_scriptClick, 1);
+
+ while (_scriptInterpreter->validScript(_scriptClick))
+ _scriptInterpreter->runScript(_scriptClick);
+
+ return _scriptClick->regs[3];
+}
+
+void KyraEngine_v1::updateMousePointer(bool forceUpdate) {
+ int shape = 0;
+
+ int newMouseState = 0;
+ int newX = 0;
+ int newY = 0;
+ Common::Point mouse = getMousePos();
+ if (mouse.y <= 158) {
+ if (mouse.x >= 12) {
+ if (mouse.x >= 308) {
+ if (_walkBlockEast == 0xFFFF) {
+ newMouseState = -2;
+ } else {
+ newMouseState = -5;
+ shape = 3;
+ newX = 7;
+ newY = 5;
+ }
+ } else if (mouse.y >= 136) {
+ if (_walkBlockSouth == 0xFFFF) {
+ newMouseState = -2;
+ } else {
+ newMouseState = -4;
+ shape = 4;
+ newX = 5;
+ newY = 7;
+ }
+ } else if (mouse.y < 12) {
+ if (_walkBlockNorth == 0xFFFF) {
+ newMouseState = -2;
+ } else {
+ newMouseState = -6;
+ shape = 2;
+ newX = 5;
+ newY = 1;
+ }
+ }
+ } else {
+ if (_walkBlockWest == 0xFFFF) {
+ newMouseState = -2;
+ } else {
+ newMouseState = -3;
+ newX = 1;
+ newY = shape = 5;
+ }
+ }
+ }
+
+ if (mouse.x >= _entranceMouseCursorTracks[0] && mouse.y >= _entranceMouseCursorTracks[1]
+ && mouse.x <= _entranceMouseCursorTracks[2] && mouse.y <= _entranceMouseCursorTracks[3]) {
+ switch (_entranceMouseCursorTracks[4]) {
+ case 0:
+ newMouseState = -6;
+ shape = 2;
+ newX = 5;
+ newY = 1;
+ break;
+
+ case 2:
+ newMouseState = -5;
+ shape = 3;
+ newX = 7;
+ newY = 5;
+ break;
+
+ case 4:
+ newMouseState = -4;
+ shape = 4;
+ newX = 5;
+ newY = 7;
+ break;
+
+ case 6:
+ newMouseState = -3;
+ shape = 5;
+ newX = 1;
+ newY = 5;
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ if (newMouseState == -2) {
+ shape = 6;
+ newX = 4;
+ newY = 4;
+ }
+
+ if ((newMouseState && _mouseState != newMouseState) || (newMouseState && forceUpdate)) {
+ _mouseState = newMouseState;
+ _screen->hideMouse();
+ _screen->setMouseCursor(newX, newY, _shapes[shape]);
+ _screen->showMouse();
+ }
+
+ if (!newMouseState) {
+ if (_mouseState != _itemInHand || forceUpdate) {
+ if (mouse.y > 158 || (mouse.x >= 12 && mouse.x < 308 && mouse.y < 136 && mouse.y >= 12) || forceUpdate) {
+ _mouseState = _itemInHand;
+ _screen->hideMouse();
+ if (_itemInHand == -1) {
+ _screen->setMouseCursor(1, 1, _shapes[0]);
+ } else {
+ _screen->setMouseCursor(8, 15, _shapes[216+_itemInHand]);
+ }
+ _screen->showMouse();
+ }
+ }
+ }
+}
+
+bool KyraEngine_v1::hasClickedOnExit(int xpos, int ypos) {
+ debugC(9, kDebugLevelMain, "KyraEngine_v1::hasClickedOnExit(%d, %d)", xpos, ypos);
+ if (xpos < 16 || xpos >= 304)
+ return true;
+
+ if (ypos < 8)
+ return true;
+
+ if (ypos < 136 || ypos > 155)
+ return false;
+
+ return true;
+}
+
+void KyraEngine_v1::clickEventHandler2() {
+ debugC(9, kDebugLevelMain, "KyraEngine_v1::clickEventHandler2()");
+
+ Common::Point mouse = getMousePos();
+
+ _scriptInterpreter->initScript(_scriptClick, _scriptClickData);
+ _scriptClick->regs[0] = _currentCharacter->sceneId;
+ _scriptClick->regs[1] = mouse.x;
+ _scriptClick->regs[2] = mouse.y;
+ _scriptClick->regs[4] = _itemInHand;
+ _scriptInterpreter->startScript(_scriptClick, 6);
+
+ while (_scriptInterpreter->validScript(_scriptClick))
+ _scriptInterpreter->runScript(_scriptClick);
+}
+
+int KyraEngine_v1::checkForNPCScriptRun(int xpos, int ypos) {
+ debugC(9, kDebugLevelMain, "KyraEngine_v1::checkForNPCScriptRun(%d, %d)", xpos, ypos);
+ int returnValue = -1;
+ const Character *currentChar = _currentCharacter;
+ int charLeft = 0, charRight = 0, charTop = 0, charBottom = 0;
+
+ int scaleFactor = _scaleTable[currentChar->y1];
+ int addX = (((scaleFactor*8)*3)>>8)>>1;
+ int addY = ((scaleFactor*3)<<4)>>8;
+
+ charLeft = currentChar->x1 - addX;
+ charRight = currentChar->x1 + addX;
+ charTop = currentChar->y1 - addY;
+ charBottom = currentChar->y1;
+
+ if (xpos >= charLeft && charRight >= xpos && charTop <= ypos && charBottom >= ypos)
+ return 0;
+
+ if (xpos > 304 || xpos < 16)
+ return -1;
+
+ for (int i = 1; i < 5; ++i) {
+ currentChar = &_characterList[i];
+
+ if (currentChar->sceneId != _currentCharacter->sceneId)
+ continue;
+
+ charLeft = currentChar->x1 - 12;
+ charRight = currentChar->x1 + 11;
+ charTop = currentChar->y1 - 48;
+ // if (!i) {
+ // charBottom = currentChar->y2 - 16;
+ // } else {
+ charBottom = currentChar->y1;
+ // }
+
+ if (xpos < charLeft || xpos > charRight || ypos < charTop || charBottom < ypos)
+ continue;
+
+ if (returnValue != -1) {
+ if (currentChar->y1 >= _characterList[returnValue].y1)
+ returnValue = i;
+ } else {
+ returnValue = i;
+ }
+ }
+
+ return returnValue;
+}
+
+void KyraEngine_v1::runNpcScript(int func) {
+ debugC(9, kDebugLevelMain, "KyraEngine_v1::runNpcScript(%d)", func);
+ _scriptInterpreter->initScript(_npcScript, _npcScriptData);
+ _scriptInterpreter->startScript(_npcScript, func);
+ _npcScript->regs[0] = _currentCharacter->sceneId;
+ _npcScript->regs[4] = _itemInHand;
+ _npcScript->regs[5] = func;
+
+ while (_scriptInterpreter->validScript(_npcScript))
+ _scriptInterpreter->runScript(_npcScript);
+}
+
+void KyraEngine_v1::checkAmuletAnimFlags() {
+ debugC(9, kDebugLevelMain, "KyraEngine_v1::checkSpecialAnimFlags()");
+
+ if (_brandonStatusBit & 2) {
+ seq_makeBrandonNormal2();
+ _timer->setCountdown(19, 300);
+ }
+
+ if (_brandonStatusBit & 0x20) {
+ seq_makeBrandonNormal();
+ _timer->setCountdown(19, 300);
+ }
}
+typedef Functor1Mem<ScriptState*, int, KyraEngine_v1> OpcodeV1;
#define Opcode(x) OpcodeV1(this, &KyraEngine_v1::x)
void KyraEngine_v1::setupOpcodeTable() {
static const OpcodeV1 opcodeTable[] = {
@@ -232,6 +1208,7 @@ void KyraEngine_v1::setupOpcodeTable() {
Opcode(o1_fillRect),
Opcode(o1_vocUnload),
Opcode(o1_vocLoad),
+ // 0x9c
Opcode(o1_dummy)
};
diff --git a/engines/kyra/kyra_v1.h b/engines/kyra/kyra_v1.h
index e103086dc4..8c9437b6fe 100644
--- a/engines/kyra/kyra_v1.h
+++ b/engines/kyra/kyra_v1.h
@@ -28,16 +28,779 @@
#include "kyra/kyra.h"
#include "kyra/script.h"
+#include "kyra/screen_v1.h"
namespace Kyra {
+class Movie;
+class SoundDigital;
+class SeqPlayer;
+class Sprites;
+class Debugger;
+class ScreenAnimator;
+class TextDisplayer;
+class KyraEngine_v1;
+
+struct Character {
+ uint16 sceneId;
+ uint8 height;
+ uint8 facing;
+ uint16 currentAnimFrame;
+ uint8 inventoryItems[10];
+ int16 x1, y1, x2, y2;
+};
+
+struct Shape {
+ uint8 imageIndex;
+ int8 xOffset, yOffset;
+ uint8 x, y, w, h;
+};
+
+struct Room {
+ uint8 nameIndex;
+ uint16 northExit;
+ uint16 eastExit;
+ uint16 southExit;
+ uint16 westExit;
+ uint8 itemsTable[12];
+ uint16 itemsXPos[12];
+ uint8 itemsYPos[12];
+ uint8 needInit[12];
+};
+
+struct Item {
+ uint8 unk1;
+ uint8 height;
+ uint8 unk2;
+ uint8 unk3;
+};
+
+struct SeqLoop {
+ const uint8 *ptr;
+ uint16 count;
+};
+
+struct SceneExits {
+ uint16 northXPos;
+ uint8 northYPos;
+ uint16 eastXPos;
+ uint8 eastYPos;
+ uint16 southXPos;
+ uint8 southYPos;
+ uint16 westXPos;
+ uint8 westYPos;
+};
+
+struct BeadState {
+ int16 x;
+ int16 y;
+ int16 width;
+ int16 height;
+ int16 dstX;
+ int16 dstY;
+ int16 width2;
+ int16 unk8;
+ int16 unk9;
+ int16 tableIndex;
+};
+
+struct Button {
+ Button *nextButton;
+ uint16 specialValue;
+ // uint8 unk[4];
+ uint8 process0;
+ uint8 process1;
+ uint8 process2;
+ // uint8 unk
+ uint16 flags;
+ typedef int (KyraEngine_v1::*ButtonCallback)(Button*);
+ // using 6 pointers instead of 3 as in the orignal here (safer for use with classes)
+ uint8 *process0PtrShape;
+ uint8 *process1PtrShape;
+ uint8 *process2PtrShape;
+ ButtonCallback process0PtrCallback;
+ ButtonCallback process1PtrCallback;
+ ButtonCallback process2PtrCallback;
+ uint16 dimTableIndex;
+ uint16 x;
+ uint16 y;
+ uint16 width;
+ uint16 height;
+ // uint8 unk[8];
+ uint32 flags2;
+ ButtonCallback buttonCallback;
+ // uint8 unk[8];
+};
+
+struct MenuItem {
+ bool enabled;
+ uint16 field_1;
+ uint8 field_3;
+ const char *itemString;
+ int16 x;
+ int16 field_9;
+ uint16 y;
+ uint16 width;
+ uint16 height;
+ uint8 textColor;
+ uint8 highlightColor;
+ int16 field_12;
+ uint8 field_13;
+ uint8 bgcolor;
+ uint8 color1;
+ uint8 color2;
+ int (KyraEngine_v1::*callback)(Button*);
+ int16 field_1b;
+ const char *labelString;
+ uint16 labelX;
+ uint8 labelY;
+ uint8 field_24;
+ uint32 field_25;
+};
+
+struct Menu {
+ int16 x;
+ int16 y;
+ uint16 width;
+ uint16 height;
+ uint8 bgcolor;
+ uint8 color1;
+ uint8 color2;
+ const char *menuName;
+ uint8 textColor;
+ int16 field_10;
+ uint16 field_12;
+ uint16 highlightedItem;
+ uint8 nrOfItems;
+ int16 scrollUpBtnX;
+ int16 scrollUpBtnY;
+ int16 scrollDownBtnX;
+ int16 scrollDownBtnY;
+ MenuItem item[6];
+};
+
class KyraEngine_v1 : public KyraEngine {
+ friend class MusicPlayer;
+ friend class Debugger_v1;
+ friend class ScreenAnimator;
public:
KyraEngine_v1(OSystem *system, const GameFlags &flags);
~KyraEngine_v1();
+ Screen *screen() { return _screen; }
+ ScreenAnimator *animator() { return _animator; }
+ virtual Movie *createWSAMovie();
+
+ uint8 **shapes() { return _shapes; }
+ Character *currentCharacter() { return _currentCharacter; }
+ Character *characterList() { return _characterList; }
+ uint16 brandonStatus() { return _brandonStatusBit; }
+
+ // TODO: remove me with workaround in animator.cpp l209
+ uint16 getScene() { return _currentRoom; }
+
+ int _paletteChanged;
+ int16 _northExitHeight;
+
+ typedef void (KyraEngine_v1::*IntroProc)();
+
+ // static data access
+ const char * const*seqWSATable() { return _seq_WSATable; }
+ const char * const*seqCPSTable() { return _seq_CPSTable; }
+ const char * const*seqCOLTable() { return _seq_COLTable; }
+ const char * const*seqTextsTable() { return _seq_textsTable; }
+
+ const uint8 * const*palTable1() { return &_specialPalettes[0]; }
+ const uint8 * const*palTable2() { return &_specialPalettes[29]; }
+
+protected:
+ virtual int go();
+ virtual int init();
+
+public:
+ // sequences
+ // -> misc
+ bool seq_skipSequence() const;
+protected:
+ // -> demo
+ void seq_demo();
+
+ // -> intro
+ void seq_intro();
+ void seq_introLogos();
+ void seq_introStory();
+ void seq_introMalcolmTree();
+ void seq_introKallakWriting();
+ void seq_introKallakMalcolm();
+
+ // -> ingame animations
+ void seq_createAmuletJewel(int jewel, int page, int noSound, int drawOnly);
+ void seq_brandonHealing();
+ void seq_brandonHealing2();
+ void seq_poisonDeathNow(int now);
+ void seq_poisonDeathNowAnim();
+ void seq_playFluteAnimation();
+ void seq_winterScroll1();
+ void seq_winterScroll2();
+ void seq_makeBrandonInv();
+ void seq_makeBrandonNormal();
+ void seq_makeBrandonNormal2();
+ void seq_makeBrandonWisp();
+ void seq_dispelMagicAnimation();
+ void seq_fillFlaskWithWater(int item, int type);
+ void seq_playDrinkPotionAnim(int item, int unk2, int flags);
+ void seq_brandonToStone();
+
+ // -> end fight
+ int seq_playEnd();
+ void seq_playEnding();
+
+ int handleMalcolmFlag();
+ int handleBeadState();
+ void initBeadState(int x, int y, int x2, int y2, int unk1, BeadState *ptr);
+ int processBead(int x, int y, int &x2, int &y2, BeadState *ptr);
+
+ // -> credits
+ void seq_playCredits();
+
+public:
+ // delay
+ void delayUntil(uint32 timestamp, bool updateGameTimers = false, bool update = false, bool isMainLoop = false);
+ void delay(uint32 millis, bool update = false, bool isMainLoop = false);
+ void delayWithTicks(int ticks);
+ void waitForEvent();
+
+ // TODO
+ void registerDefaultSettings();
+ void readSettings();
+ void writeSettings();
+
+ void snd_playTheme(int file, int track = 0);
+ void snd_playVoiceFile(int id);
+ void snd_voiceWaitForFinish(bool ingame = true);
+ bool snd_voiceIsPlaying();
+ void snd_stopVoice();
+ void snd_playSoundEffect(int track);
+ void snd_playWanderScoreViaMap(int command, int restart);
+
+ bool speechEnabled();
+ bool textEnabled();
+
+ void saveGame(const char *fileName, const char *saveName);
+ void loadGame(const char *fileName);
+
+protected:
+ // input
+ void processInput();
+ int processInputHelper(int xpos, int ypos);
+ int clickEventHandler(int xpos, int ypos);
+ void clickEventHandler2();
+ void updateMousePointer(bool forceUpdate = false);
+ bool hasClickedOnExit(int xpos, int ypos);
+
+ // scene
+ // -> init
+ void loadSceneMsc();
+ void startSceneScript(int brandonAlive);
+ void setupSceneItems();
+ void initSceneData(int facing, int unk1, int brandonAlive);
+ void initSceneObjectList(int brandonAlive);
+ void initSceneScreen(int brandonAlive);
+ void setupSceneResource(int sceneId);
+
+ // -> process
+ void enterNewScene(int sceneId, int facing, int unk1, int unk2, int brandonAlive);
+ int handleSceneChange(int xpos, int ypos, int unk1, int frameReset);
+ int processSceneChange(int *table, int unk1, int frameReset);
+ int changeScene(int facing);
+
+ // -> modification
+ void transcendScenes(int roomIndex, int roomName);
+ void setSceneFile(int roomIndex, int roomName);
+
+ // -> pathfinder
+ int findWay(int x, int y, int toX, int toY, int *moveTable, int moveTableSize);
+ bool lineIsPassable(int x, int y);
+
+ // -> item handling
+ // --> misc
+ void addItemToRoom(uint16 sceneId, uint8 item, int itemIndex, int x, int y);
+
+ // --> drop handling
+ void itemDropDown(int x, int y, int destX, int destY, byte freeItem, int item);
+ int processItemDrop(uint16 sceneId, uint8 item, int x, int y, int unk1, int unk2);
+ void dropItem(int unk1, int item, int x, int y, int unk2);
+
+ // --> dropped item handling
+ int countItemsInScene(uint16 sceneId);
+ void exchangeItemWithMouseItem(uint16 sceneId, int itemIndex);
+ byte findFreeItemInScene(int scene);
+ byte findItemAtPos(int x, int y);
+
+ // --> drop area handling
+ void addToNoDropRects(int x, int y, int w, int h);
+ void clearNoDropRects();
+ int isDropable(int x, int y);
+ int checkNoDropRects(int x, int y);
+
+ // --> player items handling
+ void updatePlayerItemsForScene();
+
+ // --> item GFX handling
+ void backUpItemRect0(int xpos, int ypos);
+ void restoreItemRect0(int xpos, int ypos);
+ void backUpItemRect1(int xpos, int ypos);
+ void restoreItemRect1(int xpos, int ypos);
+
+ // items
+ // -> misc
+ void placeItemInGenericMapScene(int item, int index);
+
+ // -> mouse item
+ void createMouseItem(int item);
+ void destroyMouseItem();
+ void setMouseItem(int item);
+
+ // -> graphics effects
+ void wipeDownMouseItem(int xpos, int ypos);
+ void itemSpecialFX(int x, int y, int item);
+ void itemSpecialFX1(int x, int y, int item);
+ void itemSpecialFX2(int x, int y, int item);
+ void magicOutMouseItem(int animIndex, int itemPos);
+ void magicInMouseItem(int animIndex, int item, int itemPos);
+ void specialMouseItemFX(int shape, int x, int y, int animIndex, int tableIndex, int loopStart, int maxLoops);
+ void processSpecialMouseItemFX(int shape, int x, int y, int tableValue, int loopStart, int maxLoops);
+
+ // character
+ // -> movement
+ void moveCharacterToPos(int character, int facing, int xpos, int ypos);
+ void setCharacterPositionWithUpdate(int character);
+ int setCharacterPosition(int character, int *facingTable);
+ void setCharacterPositionHelper(int character, int *facingTable);
+ void setCharactersPositions(int character);
+
+ // -> brandon
+ void setBrandonPoisonFlags(int reset);
+ void resetBrandonPoisonFlags();
+
+ // chat
+ // -> process
+ void characterSays(int vocFile, const char *chatStr, int8 charNum, int8 chatDuration);
+ void waitForChatToFinish(int vocFile, int16 chatDuration, const char *str, uint8 charNum);
+
+ // -> initialization
+ int initCharacterChat(int8 charNum);
+ void backupChatPartnerAnimFrame(int8 charNum);
+ void restoreChatPartnerAnimFrame(int8 charNum);
+ int8 getChatPartnerNum();
+
+ // -> deinitialization
+ void endCharacterChat(int8 charNum, int16 arg_4);
+
+ // graphics
+ // -> misc
+ int findDuplicateItemShape(int shape);
+ void updateKyragemFading();
+
+ // -> interface
+ void loadMainScreen(int page = 3);
+ void redrawInventory(int page);
+public:
+ void drawSentenceCommand(const char *sentence, int unk1);
+ void updateSentenceCommand(const char *str1, const char *str2, int unk1);
+ void updateTextFade();
+
+protected:
+ // -> amulet
+ void drawJewelPress(int jewel, int drawSpecial);
+ void drawJewelsFadeOutStart();
+ void drawJewelsFadeOutEnd(int jewel);
+
+ // -> shape handling
+ void setupShapes123(const Shape *shapeTable, int endShape, int flags);
+ void freeShapes123();
+
+ // misc (TODO)
+ void startup();
+ void mainLoop();
+
+ int checkForNPCScriptRun(int xpos, int ypos);
+ void runNpcScript(int func);
+
+ void loadMouseShapes();
+ void loadCharacterShapes();
+ void loadSpecialEffectShapes();
+ void loadItems();
+ void loadButtonShapes();
+ void initMainButtonList();
+ void setCharactersInDefaultScene();
+ void setupPanPages();
+ void freePanPages();
+ void closeFinalWsa();
+
+ //void setTimer19();
+ void setupTimers();
+ void timerUpdateHeadAnims(int timerNum);
+ void timerSetFlags1(int timerNum);
+ void timerSetFlags2(int timerNum);
+ void timerSetFlags3(int timerNum);
+ void timerCheckAnimFlag1(int timerNum);
+ void timerCheckAnimFlag2(int timerNum);
+ void checkAmuletAnimFlags();
+ void timerRedrawAmulet(int timerNum);
+ void timerFadeText(int timerNum);
+ void updateAnimFlag1(int timerNum);
+ void updateAnimFlag2(int timerNum);
+ void drawAmulet();
+ void setTextFadeTimerCountdown(int16 countdown);
+ void setWalkspeed(uint8 newSpeed);
+
+ int buttonInventoryCallback(Button *caller);
+ int buttonAmuletCallback(Button *caller);
+ int buttonMenuCallback(Button *caller);
+ int drawBoxCallback(Button *button);
+ int drawShadedBoxCallback(Button *button);
+ void calcCoords(Menu &menu);
+ void initMenu(Menu &menu);
+ void setGUILabels();
+
+ Button *initButton(Button *list, Button *newButton);
+ void processButtonList(Button *list);
+ void processButton(Button *button);
+ void processMenuButton(Button *button);
+ void processAllMenuButtons();
+
+ const char *getSavegameFilename(int num);
+ void setupSavegames(Menu &menu, int num);
+ int getNextSavegameSlot();
+
+ int gui_resumeGame(Button *button);
+ int gui_loadGameMenu(Button *button);
+ int gui_saveGameMenu(Button *button);
+ int gui_gameControlsMenu(Button *button);
+ int gui_quitPlaying(Button *button);
+ int gui_quitConfirmYes(Button *button);
+ int gui_quitConfirmNo(Button *button);
+ int gui_loadGame(Button *button);
+ int gui_saveGame(Button *button);
+ int gui_savegameConfirm(Button *button);
+ int gui_cancelSubMenu(Button *button);
+ int gui_scrollUp(Button *button);
+ int gui_scrollDown(Button *button);
+ int gui_controlsChangeMusic(Button *button);
+ int gui_controlsChangeSounds(Button *button);
+ int gui_controlsChangeWalk(Button *button);
+ int gui_controlsChangeText(Button *button);
+ int gui_controlsChangeVoice(Button *button);
+ int gui_controlsApply(Button *button);
+
+ bool gui_quitConfirm(const char *str);
+ void gui_getInput();
+ void gui_redrawText(Menu menu);
+ void gui_redrawHighlight(Menu menu);
+ void gui_processHighlights(Menu &menu);
+ void gui_updateSavegameString();
+ void gui_redrawTextfield();
+ void gui_fadePalette();
+ void gui_restorePalette();
+ void gui_setupControls(Menu &menu);
+
+ bool _skipIntroFlag;
+ bool _abortIntroFlag;
+ bool _menuDirectlyToLoad;
+ bool _abortWalkFlag;
+ bool _abortWalkFlag2;
+ bool _mousePressFlag;
+ int8 _mouseWheel;
+ uint8 *_itemBkgBackUp[2];
+ uint8 *_shapes[373];
+ int8 _itemInHand;
+ int _mouseState;
+ bool _handleInput;
+ bool _changedScene;
+ int _unkScreenVar1, _unkScreenVar2, _unkScreenVar3;
+ int _beadStateVar;
+ int _unkAmuletVar;
+
+ int _malcolmFlag;
+ int _endSequenceSkipFlag;
+ int _endSequenceNeedLoading;
+ int _unkEndSeqVar2;
+ uint8 *_endSequenceBackUpRect;
+ int _unkEndSeqVar4;
+ int _unkEndSeqVar5;
+ int _lastDisplayedPanPage;
+ uint8 *_panPagesTable[20];
+ Movie *_finalA, *_finalB, *_finalC;
+
+ Movie *_movieObjects[10];
+
+ uint16 _entranceMouseCursorTracks[8];
+ uint16 _walkBlockNorth;
+ uint16 _walkBlockEast;
+ uint16 _walkBlockSouth;
+ uint16 _walkBlockWest;
+
+ int32 _scaleMode;
+ int16 _scaleTable[145];
+
+ Rect _noDropRects[11];
+
+ int8 _birthstoneGemTable[4];
+ int8 _idolGemsTable[3];
+
+ int8 _marbleVaseItem;
+ int8 _foyerItemTable[3];
+
+ int8 _cauldronState;
+ int8 _crystalState[2];
+
+ uint16 _brandonStatusBit;
+ uint8 _brandonStatusBit0x02Flag;
+ uint8 _brandonStatusBit0x20Flag;
+ uint8 _brandonPoisonFlagsGFX[256];
+ uint8 _deathHandler;
+ int16 _brandonInvFlag;
+ uint8 _poisonDeathCounter;
+ int _brandonPosX;
+ int _brandonPosY;
+
+ uint16 _currentChatPartnerBackupFrame;
+ uint16 _currentCharAnimFrame;
+
+ int8 *_sceneAnimTable[50];
+
+ Item _itemTable[145];
+ int _lastProcessedItem;
+ int _lastProcessedItemHeight;
+
+ int16 *_exitListPtr;
+ int16 _exitList[11];
+ SceneExits _sceneExits;
+ uint16 _currentRoom;
+ int _scenePhasingFlag;
+
+ int _sceneChangeState;
+ int _loopFlag2;
+
+ int _pathfinderFlag;
+ int _pathfinderFlag2;
+ int _lastFindWayRet;
+ int *_movFacingTable;
+
+ int8 _talkingCharNum;
+ int8 _charSayUnk2;
+ int8 _charSayUnk3;
+ int8 _currHeadShape;
+ uint8 _currSentenceColor[3];
+ int8 _startSentencePalIndex;
+ bool _fadeText;
+
+ uint8 _configTextspeed;
+ uint8 _configWalkspeed;
+ int _configMusic;
+ bool _configSounds;
+ uint8 _configVoice;
+
+ int _curMusicTheme;
+ int _curSfxFile;
+ int16 _lastMusicCommand;
+
+ ScreenAnimator *_animator;
+ SeqPlayer *_seq;
+ Sprites *_sprites;
+ Screen_v1 *_screen;
+ Debugger *_debugger;
+
+ ScriptState *_scriptMain;
+
+ ScriptState *_npcScript;
+ ScriptData *_npcScriptData;
+
+ ScriptState *_scriptClick;
+ ScriptData *_scriptClickData;
+
+ Character *_characterList;
+ Character *_currentCharacter;
+
+ Button *_buttonList;
+ Button *_menuButtonList;
+ bool _displayMenu;
+ bool _menuRestoreScreen;
+ bool _displaySubMenu;
+ bool _cancelSubMenu;
+ uint8 _toplevelMenu;
+ int _savegameOffset;
+ int _gameToLoad;
+ char _savegameName[31];
+ const char *_specialSavegameString;
+ Common::KeyState _keyPressed;
+
+ struct KyragemState {
+ uint16 nextOperation;
+ uint16 rOffset;
+ uint16 gOffset;
+ uint16 bOffset;
+ uint32 timerCount;
+ } _kyragemFadingState;
+
+ // TODO: get rid of all variables having pointers to the static resources if possible
+ // i.e. let them directly use the _staticres functions
+ void initStaticResource();
+
+ const uint8 *_seq_Forest;
+ const uint8 *_seq_KallakWriting;
+ const uint8 *_seq_KyrandiaLogo;
+ const uint8 *_seq_KallakMalcolm;
+ const uint8 *_seq_MalcolmTree;
+ const uint8 *_seq_WestwoodLogo;
+ const uint8 *_seq_Demo1;
+ const uint8 *_seq_Demo2;
+ const uint8 *_seq_Demo3;
+ const uint8 *_seq_Demo4;
+ const uint8 *_seq_Reunion;
+
+ const char * const*_seq_WSATable;
+ const char * const*_seq_CPSTable;
+ const char * const*_seq_COLTable;
+ const char * const*_seq_textsTable;
+
+ int _seq_WSATable_Size;
+ int _seq_CPSTable_Size;
+ int _seq_COLTable_Size;
+ int _seq_textsTable_Size;
+
+ const char * const*_itemList;
+ const char * const*_takenList;
+ const char * const*_placedList;
+ const char * const*_droppedList;
+ const char * const*_noDropList;
+ const char * const*_putDownFirst;
+ const char * const*_waitForAmulet;
+ const char * const*_blackJewel;
+ const char * const*_poisonGone;
+ const char * const*_healingTip;
+ const char * const*_thePoison;
+ const char * const*_fluteString;
+ const char * const*_wispJewelStrings;
+ const char * const*_magicJewelString;
+ const char * const*_flaskFull;
+ const char * const*_fullFlask;
+ const char * const*_veryClever;
+ const char * const*_homeString;
+ const char * const*_newGameString;
+
+ const char *_voiceTextString;
+ const char *_textSpeedString;
+ const char *_onString;
+ const char *_offString;
+ const char *_onCDString;
+
+ int _itemList_Size;
+ int _takenList_Size;
+ int _placedList_Size;
+ int _droppedList_Size;
+ int _noDropList_Size;
+ int _putDownFirst_Size;
+ int _waitForAmulet_Size;
+ int _blackJewel_Size;
+ int _poisonGone_Size;
+ int _healingTip_Size;
+ int _thePoison_Size;
+ int _fluteString_Size;
+ int _wispJewelStrings_Size;
+ int _magicJewelString_Size;
+ int _flaskFull_Size;
+ int _fullFlask_Size;
+ int _veryClever_Size;
+ int _homeString_Size;
+ int _newGameString_Size;
+
+ const char * const*_characterImageTable;
+ int _characterImageTableSize;
+
+ const char * const*_guiStrings;
+ int _guiStringsSize;
+
+ const char * const*_configStrings;
+ int _configStringsSize;
+
+ Shape *_defaultShapeTable;
+ int _defaultShapeTableSize;
+
+ const Shape *_healingShapeTable;
+ int _healingShapeTableSize;
+ const Shape *_healingShape2Table;
+ int _healingShape2TableSize;
+
+ const Shape *_posionDeathShapeTable;
+ int _posionDeathShapeTableSize;
+
+ const Shape *_fluteAnimShapeTable;
+ int _fluteAnimShapeTableSize;
+
+ const Shape *_winterScrollTable;
+ int _winterScrollTableSize;
+ const Shape *_winterScroll1Table;
+ int _winterScroll1TableSize;
+ const Shape *_winterScroll2Table;
+ int _winterScroll2TableSize;
+
+ const Shape *_drinkAnimationTable;
+ int _drinkAnimationTableSize;
+
+ const Shape *_brandonToWispTable;
+ int _brandonToWispTableSize;
+
+ const Shape *_magicAnimationTable;
+ int _magicAnimationTableSize;
+
+ const Shape *_brandonStoneTable;
+ int _brandonStoneTableSize;
+
+ Room *_roomTable;
+ int _roomTableSize;
+ const char * const*_roomFilenameTable;
+ int _roomFilenameTableSize;
+
+ const uint8 *_amuleteAnim;
+
+ const uint8 * const*_specialPalettes;
+
+ static const char *_soundFiles[];
+ static const int _soundFilesCount;
+ static const char *_soundFilesTowns[];
+ static const int _soundFilesTownsCount;
+
+ static const int8 _charXPosTable[];
+ static const int8 _charYPosTable[];
+
+ // positions of the inventory
+ static const uint16 _itemPosX[];
+ static const uint8 _itemPosY[];
+
+ void setupButtonData();
+ Button *_buttonData;
+ Button **_buttonDataListPtr;
+ static Button _menuButtonData[];
+ static Button _scrollUpButton;
+ static Button _scrollDownButton;
+
+ bool _haveScrollButtons;
+
+ void setupMenu();
+ Menu *_menu;
+
+ static const uint8 _magicMouseItemStartFrame[];
+ static const uint8 _magicMouseItemEndFrame[];
+ static const uint8 _magicMouseItemStartFrame2[];
+ static const uint8 _magicMouseItemEndFrame2[];
+
+ static const uint16 _amuletX[];
+ static const uint16 _amuletY[];
+ static const uint16 _amuletX2[];
+ static const uint16 _amuletY2[];
protected:
- typedef OpcodeImpl<KyraEngine_v1> OpcodeV1;
void setupOpcodeTable();
// Opcodes
diff --git a/engines/kyra/kyra_v2.cpp b/engines/kyra/kyra_v2.cpp
index 6857b3ac09..317fd218b2 100644
--- a/engines/kyra/kyra_v2.cpp
+++ b/engines/kyra/kyra_v2.cpp
@@ -29,29 +29,64 @@
#include "kyra/resource.h"
#include "kyra/wsamovie.h"
#include "kyra/sound.h"
+#include "kyra/script.h"
+#include "kyra/text.h"
+#include "kyra/timer.h"
#include "common/system.h"
namespace Kyra {
KyraEngine_v2::KyraEngine_v2(OSystem *system, const GameFlags &flags) : KyraEngine(system, flags) {
- memset(_gameShapes, 0, sizeof(_gameShapes));
+ memset(_defaultShapeTable, 0, sizeof(_defaultShapeTable));
_mouseSHPBuf = 0;
+
+ _gamePlayBuffer = 0;
+ _cCodeBuffer = _optionsBuffer = _chapterBuffer = 0;
+
+ _overwriteSceneFacing = false;
+ _mainCharX = _mainCharY = -1;
+ _drawNoShapeFlag = false;
+ _charPalEntry = 0;
+ _itemInHand = -1;
+ _unkSceneScreenFlag1 = false;
+ _noScriptEnter = true;
+ _currentChapter = 0;
+ _newChapterFile = 1;
+ _handItemSet = -1;
+ _lastProcessedSceneScript = 0;
+ _specialSceneScriptRunFlag = false;
+ memset(_animObjects, 0, sizeof(_animObjects));
+ _unkHandleSceneChangeFlag = false;
+ _pathfinderFlag = 0;
+
+ memset(&_sceneScriptData, 0, sizeof(_sceneScriptData));
}
KyraEngine_v2::~KyraEngine_v2() {
delete [] _mouseSHPBuf;
+ delete _screen;
+}
+
+Movie *KyraEngine_v2::createWSAMovie() {
+ return new WSAMovieV2(this);
}
int KyraEngine_v2::init() {
+ _screen = new Screen_v2(this, _system);
+ assert(_screen);
+ if (!_screen->init())
+ error("_screen->init() failed");
+
KyraEngine::init();
+
+ setupTimers();
- if (_res->getFileSize("6.FNT"))
- _screen->loadFont(Screen::FID_6_FNT, "6.FNT");
- if (_res->getFileSize("8FAT.FNT"))
- _screen->loadFont(Screen::FID_8_FNT, "8FAT.FNT");
- _screen->loadFont(Screen::FID_GOLDFONT_FNT, "GOLDFONT.FNT");
- _screen->setAnimBlockPtr(3500);
+ _screen->loadFont(_screen->FID_6_FNT, "6.FNT");
+ _screen->loadFont(_screen->FID_8_FNT, "8FAT.FNT");
+ _screen->loadFont(_screen->FID_GOLDFONT_FNT, "GOLDFONT.FNT");
+ _screen->loadFont(_screen->FID_BOOKFONT_FNT, "BOOKFONT.FNT");
+ _screen->setAnimBlockPtr(3504);
_screen->setScreenDim(0);
assert(_introStringsSize == 21);
@@ -66,11 +101,11 @@ int KyraEngine_v2::init() {
assert(_mouseSHPBuf);
for (int i = 0; i < 2; i++) {
- _gameShapes[i] = _screen->getPtrToShape(_mouseSHPBuf, i);
- assert(_gameShapes[i]);
+ _defaultShapeTable[i] = _screen->getPtrToShape(_mouseSHPBuf, i);
+ assert(_defaultShapeTable[i]);
}
- _screen->setMouseCursor(0, 0, _gameShapes[0]);
+ _screen->setMouseCursor(0, 0, _defaultShapeTable[0]);
return 0;
}
@@ -95,7 +130,7 @@ int KyraEngine_v2::go() {
_res->unloadPakFile("OUTFARM.PAK");
_res->unloadPakFile("FLYTRAP.PAK");
- seq_playSequences(kSequenceVirgin, kSequenceWestwood);
+ //seq_playSequences(kSequenceVirgin, kSequenceWestwood);
mainMenu();
return 0;
@@ -110,6 +145,11 @@ void KyraEngine_v2::mainMenu() {
switch (gui_handleMainMenu()) {
case 0:
+ _screen->showMouse();
+ startup();
+ runLoop();
+ cleanup();
+ running = false;
break;
case 1:
seq_playSequences(kSequenceOverview, kSequenceZanFaun);
@@ -123,7 +163,1130 @@ void KyraEngine_v2::mainMenu() {
break;
}
_screen->hideMouse();
- }
+ }
+}
+
+void KyraEngine_v2::startup() {
+ _screen->_curPage = 0;
+ delete [] _mouseSHPBuf;
+ _mouseSHPBuf = 0;
+
+ memset(_defaultShapeTable, 0, sizeof(_defaultShapeTable));
+ memset(_sceneShapeTable, 0, sizeof(_sceneShapeTable));
+ _gamePlayBuffer = new uint8[46080];
+ _unkBuf500Bytes = new uint8[500];
+
+ loadMouseShapes();
+ loadItemShapes();
+
+ _screen->setMouseCursor(0, 0, getShapePtr(0));
+
+ _screenBuffer = new uint8[64000];
+
+ loadCCodeBuffer("C_CODE.XXX");
+ loadOptionsBuffer("OPTIONS.XXX");
+ loadChapterBuffer(_newChapterFile);
+
+ _unkBuf200kByte = new uint8[200000];
+
+ showMessageFromCCode(265, 150, 0);
+
+ // XXX
+
+ showMessageFromCCode(0, 0, 207);
+
+ // XXX
+
+ _screen->setShapePages(5, 3);
+
+ memset(&_mainCharacter, 0, sizeof(_mainCharacter));
+ _mainCharacter.height = 0x30;
+ _mainCharacter.facing = 4;
+ _mainCharacter.animFrame = 0x12;
+ memset(_mainCharacter.inventory, -1, sizeof(_mainCharacter.inventory));
+
+ memset(_sceneAnims, 0, sizeof(_sceneAnims));
+ for (int i = 0; i < ARRAYSIZE(_sceneAnimMovie); ++i)
+ _sceneAnimMovie[i] = new WSAMovieV2(this);
+ memset(_wsaSlots, 0, sizeof(_wsaSlots));
+ for (int i = 0; i < ARRAYSIZE(_wsaSlots); ++i)
+ _wsaSlots[i] = new WSAMovieV2(this);
+
+ _maskPage = 0;//_screen->getPagePtr(5);
+ _screen->_curPage = 0;
+
+ _objectList = new Object[72];
+ memset(_objectList, 0, sizeof(Object)*72);
+ _shapeDescTable = new ShapeDesc[55];
+ memset(_shapeDescTable, 0, sizeof(ShapeDesc)*55);
+
+ for (int i = 9; i <= 32; ++i) {
+ _shapeDescTable[i-9].unk5 = 30;
+ _shapeDescTable[i-9].unk7 = 55;
+ _shapeDescTable[i-9].xAdd = -15;
+ _shapeDescTable[i-9].yAdd = -50;
+ }
+
+ for (int i = 19; i <= 24; ++i) {
+ _shapeDescTable[i-9].unk7 = 53;
+ _shapeDescTable[i-9].yAdd = -51;
+ }
+
+ _gfxBackUpRect = new uint8[_screen->getRectSize(32, 32)];
+ _itemList = new Item[30];
+ resetItemList();
+ //loadButtonShapes();
+ _loadedZTable = 1;
+ loadZShapes(_loadedZTable);
+ loadInventoryShapes();
+
+ _res->loadFileToBuf("PALETTE.COL", _screen->_currentPalette, 0x300);
+ _screen->loadBitmap("_PLAYFLD.CPS", 3, 3, 0);
+ _screen->copyPage(3, 0);
+ _screen->showMouse();
+ _screen->hideMouse();
+
+ clearAnimObjects();
+
+ // XXX
+
+ _sceneList = new SceneDesc[86];
+ runStartScript(1, 0);
+ loadNPCScript();
+
+ // XXX
+
+ enterNewScene(_mainCharacter.sceneId, _mainCharacter.facing, 0, 0, 1);
+ _screen->showMouse();
+
+ //sub_20EE8(1);
+ //setNextIdleAnimTimer();
+ //XXX
+ _timer->setDelay(0, 5);
+}
+
+void KyraEngine_v2::runLoop() {
+ _screen->updateScreen();
+
+ _quitFlag = false;
+ while (!_quitFlag) {
+ //XXX
+ int inputFlag = checkInput(0/*dword_324C5*/);
+ update();
+ if (inputFlag == 198 || inputFlag == 199) {
+ _unk3 = _handItemSet;
+ Common::Point mouse = getMousePos();
+ handleInput(mouse.x, mouse.y);
+ }
+ //XXX
+ }
+}
+
+void KyraEngine_v2::handleInput(int x, int y) {
+ //setNextIdleAnimTimer();
+ if (_unk5) {
+ _unk5 = 0;
+ return;
+ }
+
+ if (!_screen->isMouseVisible())
+ return;
+
+ if (_unk3 == -2) {
+ //snd_playSfx(13);
+ return;
+ }
+
+ //setNextIdleAnimTimer();
+
+ if (x <= 6 || x >= 312 || y <= 6 || y >= 135) {
+ bool exitOk = false;
+ assert(_unk3 + 6 >= 0);
+ switch (_unk3 + 6) {
+ case 0:
+ if (_sceneExit1 != 0xFFFF)
+ exitOk = true;
+ break;
+
+ case 1:
+ if (_sceneExit2 != 0xFFFF)
+ exitOk = true;
+ break;
+
+ case 2:
+ if (_sceneExit3 != 0xFFFF)
+ exitOk = true;
+ break;
+
+ case 3:
+ if (_sceneExit4 != 0xFFFF)
+ exitOk = true;
+ break;
+
+ default:
+ break;
+ }
+
+ if (exitOk) {
+ inputSceneChange(x, y, 1, 1);
+ return;
+ }
+ }
+
+ if (checkCharCollision(x, y) >= 0 && _unk3 >= -1) {
+ runSceneScript2();
+ return;
+ } else {
+ //XXX
+ }
+
+ //XXX
+
+ inputSceneChange(x, y, 1, 1);
+}
+
+int KyraEngine_v2::update() {
+ refreshAnimObjectsIfNeed();
+ updateMouse();
+ updateSpecialSceneScripts();
+ _timer->update();
+ //sub_274C0();
+ //updateInvWsa();
+ //sub_1574C();
+ //XXX
+ _screen->updateScreen();
+ return 0;
+}
+
+void KyraEngine_v2::updateMouse() {
+ int shapeIndex = 0;
+ int type = 0;
+ int xOffset = 0, yOffset = 0;
+ Common::Point mouse = getMousePos();
+
+ if (mouse.y <= 145) {
+ if (mouse.x <= 6) {
+ if (_sceneExit4 != 0xFFFF) {
+ type = -3;
+ shapeIndex = 4;
+ xOffset = 1;
+ yOffset = 5;
+ } else {
+ type = -2;
+ }
+ } else if (mouse.x >= 312) {
+ if (_sceneExit2 != 0xFFFF) {
+ type = -5;
+ shapeIndex = 2;
+ xOffset = 7;
+ yOffset = 5;
+ } else {
+ type = -2;
+ }
+ } else if (mouse.y >= 135) {
+ if (_sceneExit3 != 0xFFFF) {
+ type = -4;
+ shapeIndex = 3;
+ xOffset = 5;
+ yOffset = 10;
+ } else {
+ type = -2;
+ }
+ } else if (mouse.y <= 6) {
+ if (_sceneExit1 != 0xFFFF) {
+ type = -6;
+ shapeIndex = 1;
+ xOffset = 5;
+ yOffset = 1;
+ } else {
+ type = -2;
+ }
+ }
+ }
+
+ for (int i = 0; i < _specialExitCount; ++i) {
+ if (checkSpecialSceneExit(i, mouse.x, mouse.y)) {
+ switch (_specialExitTable[20+i]) {
+ case 0:
+ type = -6;
+ shapeIndex = 1;
+ xOffset = 5;
+ yOffset = 1;
+ break;
+
+ case 2:
+ type = -5;
+ shapeIndex = 2;
+ xOffset = 7;
+ yOffset = 5;
+ break;
+
+ case 4:
+ type = -4;
+ shapeIndex = 3;
+ xOffset = 5;
+ yOffset = 7;
+ break;
+
+ case 6:
+ type = -3;
+ shapeIndex = 4;
+ xOffset = 1;
+ yOffset = 5;
+ break;
+
+ default:
+ break;
+ }
+ }
+ }
+
+ if (type == -2) {
+ shapeIndex = 5;
+ xOffset = 5;
+ yOffset = 9;
+ }
+
+ if (type != 0 && _handItemSet != type) {
+ _handItemSet = type;
+ _screen->hideMouse();
+ _screen->setMouseCursor(xOffset, yOffset, getShapePtr(shapeIndex));
+ _screen->showMouse();
+ }
+
+ if (type == 0 && _handItemSet != _itemInHand) {
+ if ((mouse.y > 145) || (mouse.x > 6 && mouse.x < 312 && mouse.y > 6 && mouse.y < 135)) {
+ _handItemSet = _itemInHand;
+ _screen->hideMouse();
+ if (_itemInHand == -1)
+ _screen->setMouseCursor(0, 0, getShapePtr(0));
+ else
+ _screen->setMouseCursor(8, 15, getShapePtr(_itemInHand+64));
+ _screen->showMouse();
+ }
+ }
+}
+
+int KyraEngine_v2::checkInput(void *p) {
+ Common::Event event;
+ int keys = 0;
+ while (_eventMan->pollEvent(event)) {
+ switch (event.type) {
+ case Common::EVENT_KEYDOWN:
+ if (event.kbd.keycode == Common::KEYCODE_RETURN)
+ keys = 199;
+ break;
+
+ case Common::EVENT_LBUTTONUP:
+ keys = 198;
+ break;
+
+ case Common::EVENT_QUIT:
+ _quitFlag = true;
+ break;
+
+ default:
+ break;
+ }
+
+ //if ( _debugger->isAttached())
+ // _debugger->onFrame();
+ }
+
+ _system->delayMillis(10);
+ return keys;
+}
+
+void KyraEngine_v2::cleanup() {
+ delete [] _gamePlayBuffer;
+ delete [] _unkBuf500Bytes;
+ delete [] _screenBuffer;
+ delete [] _unkBuf200kByte;
+
+ for (int i = 0; i < ARRAYSIZE(_defaultShapeTable); ++i)
+ delete [] _defaultShapeTable[i];
+ freeSceneShapePtrs();
+
+ delete [] _cCodeBuffer;
+ delete [] _optionsBuffer;
+ delete [] _chapterBuffer;
+
+ delete [] _objectList;
+ delete [] _shapeDescTable;
+
+ delete [] _gfxBackUpRect;
+
+ delete [] _sceneList;
+
+ for (int i = 0; i < ARRAYSIZE(_sceneAnimMovie); ++i)
+ delete _sceneAnimMovie[i];
+ for (int i = 0; i < ARRAYSIZE(_wsaSlots); ++i)
+ delete _wsaSlots[i];
+}
+
+#pragma mark - Localization
+
+void KyraEngine_v2::loadCCodeBuffer(const char *file) {
+ char tempString[13];
+ strcpy(tempString, file);
+ changeFileExtension(tempString);
+
+ delete [] _cCodeBuffer;
+ _cCodeBuffer = _res->fileData(tempString, 0);
+}
+
+void KyraEngine_v2::loadOptionsBuffer(const char *file) {
+ char tempString[13];
+ strcpy(tempString, file);
+ changeFileExtension(tempString);
+
+ delete [] _optionsBuffer;
+ _optionsBuffer = _res->fileData(tempString, 0);
+}
+
+void KyraEngine_v2::loadChapterBuffer(int chapter) {
+ char tempString[14];
+
+ static const char *chapterFilenames[] = {
+ "CH1.XXX", "CH2.XXX", "CH3.XXX", "CH4.XXX", "CH5.XXX"
+ };
+
+ assert(chapter >= 1 && chapter <= ARRAYSIZE(chapterFilenames));
+ strcpy(tempString, chapterFilenames[chapter-1]);
+ changeFileExtension(tempString);
+
+ delete [] _chapterBuffer;
+ _chapterBuffer = _res->fileData(tempString, 0);
+ _currentChapter = chapter;
+}
+
+void KyraEngine_v2::changeFileExtension(char *buffer) {
+ while (*buffer != '.') ++buffer;
+
+ ++buffer;
+ strcpy(buffer, _languageExtension[_lang]);
+}
+
+const uint8 *KyraEngine_v2::getTableEntry(const uint8 *buffer, int id) {
+ return buffer + READ_LE_UINT16(buffer + (id<<1));
+}
+
+const char *KyraEngine_v2::getTableString(int id, const uint8 *buffer, int decode) {
+ const char *string = (const char*)getTableEntry(buffer, id);
+
+ if (decode) {
+ decodeString1(string, _internStringBuf);
+ decodeString2(_internStringBuf, _internStringBuf);
+ string = _internStringBuf;
+ }
+
+ return string;
+}
+
+const char *KyraEngine_v2::getChapterString(int id) {
+ if (_currentChapter != _newChapterFile)
+ loadChapterBuffer(_newChapterFile);
+
+ return getTableString(id, _chapterBuffer, 1);
+}
+
+int KyraEngine_v2::decodeString1(const char *src, char *dst) {
+ static const uint8 decodeTable1[] = {
+ 0x20, 0x65, 0x74, 0x61, 0x69, 0x6E, 0x6F, 0x73, 0x72, 0x6C, 0x68,
+ 0x63, 0x64, 0x75, 0x70, 0x6D
+ };
+
+ static const uint8 decodeTable2[] = {
+ 0x74, 0x61, 0x73, 0x69, 0x6F, 0x20, 0x77, 0x62, 0x20, 0x72, 0x6E,
+ 0x73, 0x64, 0x61, 0x6C, 0x6D, 0x68, 0x20, 0x69, 0x65, 0x6F, 0x72,
+ 0x61, 0x73, 0x6E, 0x72, 0x74, 0x6C, 0x63, 0x20, 0x73, 0x79, 0x6E,
+ 0x73, 0x74, 0x63, 0x6C, 0x6F, 0x65, 0x72, 0x20, 0x64, 0x74, 0x67,
+ 0x65, 0x73, 0x69, 0x6F, 0x6E, 0x72, 0x20, 0x75, 0x66, 0x6D, 0x73,
+ 0x77, 0x20, 0x74, 0x65, 0x70, 0x2E, 0x69, 0x63, 0x61, 0x65, 0x20,
+ 0x6F, 0x69, 0x61, 0x64, 0x75, 0x72, 0x20, 0x6C, 0x61, 0x65, 0x69,
+ 0x79, 0x6F, 0x64, 0x65, 0x69, 0x61, 0x20, 0x6F, 0x74, 0x72, 0x75,
+ 0x65, 0x74, 0x6F, 0x61, 0x6B, 0x68, 0x6C, 0x72, 0x20, 0x65, 0x69,
+ 0x75, 0x2C, 0x2E, 0x6F, 0x61, 0x6E, 0x73, 0x72, 0x63, 0x74, 0x6C,
+ 0x61, 0x69, 0x6C, 0x65, 0x6F, 0x69, 0x72, 0x61, 0x74, 0x70, 0x65,
+ 0x61, 0x6F, 0x69, 0x70, 0x20, 0x62, 0x6D
+ };
+
+ int size = 0;
+ uint cChar = 0;
+ while ((cChar = *src++) != 0) {
+ if (cChar & 0x80) {
+ cChar &= 0x7F;
+ int index = (cChar & 0x78) >> 3;
+ *dst++ = decodeTable1[index];
+ ++size;
+ assert(cChar < sizeof(decodeTable2));
+ cChar = decodeTable2[cChar];
+ }
+
+ *dst++ = cChar;
+ ++size;
+ }
+
+ *dst++ = 0;
+ return size;
+}
+
+void KyraEngine_v2::decodeString2(const char *src, char *dst) {
+ if (!src || !dst)
+ return;
+
+ char out = 0;
+ while ((out = *src) != 0) {
+ if (*src == 0x1B) {
+ ++src;
+ out = *src + 0x7F;
+ }
+ *dst++ = out;
+ ++src;
+ }
+
+ *dst = 0;
+}
+
+#pragma mark -
+
+void KyraEngine_v2::showMessageFromCCode(int id, int16 palIndex, int) {
+ const char *string = getTableString(id, _cCodeBuffer, 1);
+ showMessage(string, palIndex);
+}
+
+void KyraEngine_v2::showMessage(const char *string, int16 palIndex) {
+ _shownMessage = string;
+ _screen->hideMouse();
+ _screen->fillRect(0, 190, 319, 199, 0xCF);
+
+ if (string) {
+ if (palIndex != -1 || _msgUnk1) {
+ palIndex *= 3;
+ memcpy(_messagePal, _screen->_currentPalette + palIndex, 3);
+ memmove(_screen->_currentPalette + 765, _screen->_currentPalette + palIndex, 3);
+ _screen->setScreenPalette(_screen->_currentPalette);
+ }
+
+ int x = _text->getCenterStringX(string, 0, 320);
+ _text->printText(string, x, 190, 255, 207, 0);
+
+ setTimer1DelaySecs(7);
+ }
+
+ _msgUnk1 = 0;
+ _screen->showMouse();
+}
+
+void KyraEngine_v2::showChapterMessage(int id, int16 palIndex) {
+ showMessage(getChapterString(id), palIndex);
+}
+
+void KyraEngine_v2::loadMouseShapes() {
+ _screen->loadBitmap("_MOUSE.CSH", 3, 3, 0);
+
+ for (int i = 0; i <= 8; ++i) {
+ _defaultShapeTable[i] = _screen->makeShapeCopy(_screen->getCPagePtr(3), i);
+ assert(_defaultShapeTable[i]);
+ }
+}
+
+void KyraEngine_v2::loadItemShapes() {
+ _screen->loadBitmap("_ITEMS.CSH", 3, 3, 0);
+
+ for (int i = 64; i <= 239; ++i) {
+ _defaultShapeTable[i] = _screen->makeShapeCopy(_screen->getCPagePtr(3), i-64);
+ assert(_defaultShapeTable[i]);
+ }
+
+ _res->loadFileToBuf("_ITEMHT.DAT", _itemHtDat, sizeof(_itemHtDat));
+ assert(_res->getFileSize("_ITEMHT.DAT") == sizeof(_itemHtDat));
+
+ _screen->_curPage = 0;
+}
+
+void KyraEngine_v2::loadZShapes(int shapes) {
+ char file[10];
+ strcpy(file, "_ZX.SHP");
+
+ _loadedZTable = shapes;
+ file[2] = '0' + shapes;
+
+ uint8 *data = _res->fileData(file, 0);
+ for (int i = 9; i <= 32; ++i) {
+ delete [] _defaultShapeTable[i];
+ _defaultShapeTable[i] = _screen->makeShapeCopy(data, i-9);
+ }
+ delete [] data;
+
+ _loadedZTable = shapes;
+}
+
+void KyraEngine_v2::loadInventoryShapes() {
+ int curPageBackUp = _screen->_curPage;
+ _screen->_curPage = 2;
+
+ _screen->loadBitmap("_PLAYALL.CPS", 3, 3, 0);
+
+ for (int i = 0; i < 10; ++i)
+ _defaultShapeTable[240+i] = _screen->encodeShape(_inventoryX[i], _inventoryY[i], 16, 16, 0);
+
+ _screen->_curPage = curPageBackUp;
+}
+
+void KyraEngine_v2::runStartScript(int script, int unk1) {
+ char filename[14];
+ strcpy(filename, "_START0X.EMC");
+ filename[7] = script + '0';
+
+ ScriptData scriptData;
+ ScriptState scriptState;
+
+ _scriptInterpreter->loadScript(filename, &scriptData, &_opcodes);
+ _scriptInterpreter->initScript(&scriptState, &scriptData);
+ scriptState.regs[6] = unk1;
+ _scriptInterpreter->startScript(&scriptState, 0);
+ while (_scriptInterpreter->validScript(&scriptState))
+ _scriptInterpreter->runScript(&scriptState);
+ _scriptInterpreter->unloadScript(&scriptData);
+}
+
+void KyraEngine_v2::loadNPCScript() {
+ char filename[12];
+ strcpy(filename, "_NPC.EMC");
+
+ switch (_lang) {
+ case 0:
+ filename[5] = 'E';
+ break;
+
+ case 1:
+ filename[5] = 'F';
+ break;
+
+ case 2:
+ filename[5] = 'G';
+ break;
+
+ default:
+ break;
+ };
+
+ _scriptInterpreter->loadScript(filename, &_npcScriptData, &_opcodes);
+}
+
+void KyraEngine_v2::resetScaleTable() {
+ for (int i = 0; i < ARRAYSIZE(_scaleTable); ++i)
+ _scaleTable[i] = 0x100;
+}
+
+void KyraEngine_v2::setScaleTableItem(int item, int data) {
+ if (item >= 1 || item <= 15)
+ _scaleTable[item-1] = (data << 8) / 100;
+}
+
+int KyraEngine_v2::getScale(int x, int y) {
+ return _scaleTable[_screen->getLayer(x, y) - 1];
+}
+
+void KyraEngine_v2::setDrawLayerTableEntry(int entry, int data) {
+ if (entry >= 1 || entry <= 15)
+ _drawLayerTable[entry-1] = data;
+}
+
+int KyraEngine_v2::getDrawLayer(int x, int y) {
+ int layer = _screen->getLayer(x, y);
+ layer = _drawLayerTable[layer-1];
+ if (layer < 0)
+ layer = 0;
+ else if (layer >= 7)
+ layer = 6;
+ return layer;
+}
+
+void KyraEngine_v2::restorePage3() {
+ _screen->copyBlockToPage(2, 0, 0, 320, 144, _gamePlayBuffer);
+}
+
+void KyraEngine_v2::updateCharPal(int unk1) {
+ static bool unkVar1 = false;
+
+ if (!_useCharPal)
+ return;
+
+ int layer = _screen->getLayer(_mainCharacter.x1, _mainCharacter.y1);
+ int palEntry = _charPalTable[layer];
+
+ if (palEntry != _charPalEntry && unk1) {
+ const uint8 *src = &_scenePal[(palEntry << 4) * 3];
+ uint8 *ptr = _screen->getPalette(0) + 336;
+ for (int i = 0; i < 48; ++i) {
+ *ptr -= (*ptr - *src) >> 1;
+ ++ptr;
+ ++src;
+ }
+ _screen->setScreenPalette(_screen->getPalette(0));
+ unkVar1 = true;
+ _charPalEntry = palEntry;
+ } else if (unkVar1 && !unk1) {
+ memcpy(_screen->getPalette(0) + 336, &_scenePal[(palEntry << 4) * 3], 48);
+ _screen->setScreenPalette(_screen->getPalette(0));
+ unkVar1 = false;
+ }
+}
+
+int KyraEngine_v2::inputSceneChange(int x, int y, int unk1, int unk2) {
+ bool refreshNPC = false;
+ uint16 curScene = _mainCharacter.sceneId;
+ _pathfinderFlag = 15;
+
+ if (!_unkHandleSceneChangeFlag) {
+ if (_unk3 == -3) {
+ if (_sceneList[curScene].exit4 != 0xFFFF) {
+ x = 4;
+ y = _sceneEnterY4;
+ _pathfinderFlag = 7;
+ }
+ } else if (_unk3 == -5) {
+ if (_sceneList[curScene].exit2 != 0xFFFF) {
+ x = 316;
+ y = _sceneEnterY2;
+ _pathfinderFlag = 7;
+ }
+ } else if (_unk3 == -6) {
+ if (_sceneList[curScene].exit1 != 0xFFFF) {
+ x = _sceneEnterX1;
+ y = _sceneEnterY1 - 2;
+ _pathfinderFlag = 14;
+ }
+ } else if (_unk3 == -4) {
+ if (_sceneList[curScene].exit3 != 0xFFFF) {
+ x = _sceneEnterX3;
+ y = 147;
+ _pathfinderFlag = 11;
+ }
+ }
+ }
+
+ if (_pathfinderFlag) {
+ if (findItem(curScene, 13) >= 0 && _unk3 <= -3) {
+ //XXX
+ _pathfinderFlag = 0;
+ return 0;
+ } else if (_itemInHand == 72) {
+ //XXX
+ _pathfinderFlag = 0;
+ return 0;
+ } else if (findItem(curScene, 72) >= 0 && _unk3 <= -3) {
+ //XXX
+ _pathfinderFlag = 0;
+ return 0;
+ } else if (0/*XXX*/) {
+ //XXX
+ _pathfinderFlag = 0;
+ return 0;
+ }
+ }
+
+ if (ABS(_mainCharacter.x1 - x) < 4 || ABS(_mainCharacter.y1 - y) < 2)
+ return 0;
+
+ int curX = _mainCharacter.x1 & ~3;
+ int curY = _mainCharacter.y1 & ~1;
+ int dstX = x & ~3;
+ int dstY = y & ~1;
+
+ int wayLength = findWay(curX, curY, dstX, dstY, _movFacingTable, 600);
+ _pathfinderFlag = 0;
+ _timer->disable(5);
+
+ if (wayLength != 0 && wayLength != 0x7D00)
+ refreshNPC = (trySceneChange(_movFacingTable, unk1, unk2) != 0);
+
+ //XXX
+
+ if (refreshNPC)
+ enterNewSceneUnk2(0);
+
+ _pathfinderFlag = 0;
+ return refreshNPC;
+}
+
+bool KyraEngine_v2::checkSpecialSceneExit(int num, int x, int y) {
+ if (_specialExitTable[0+num] > x || _specialExitTable[5+num] > y ||
+ _specialExitTable[10+num] < x || _specialExitTable[15+num] < y)
+ return 0;
+ return 1;
+}
+
+void KyraEngine_v2::moveCharacter(int facing, int x, int y) {
+ _mainCharacter.facing = facing;
+ x &= ~3;
+ y &= ~1;
+
+ _screen->hideMouse();
+ switch (facing) {
+ case 0:
+ while (y < _mainCharacter.y1)
+ updateCharPosWithUpdate();
+ break;
+
+ case 2:
+ while (_mainCharacter.x1 < x)
+ updateCharPosWithUpdate();
+ break;
+
+ case 4:
+ while (y > _mainCharacter.y1)
+ updateCharPosWithUpdate();
+ break;
+
+ case 6:
+ while (_mainCharacter.x1 > x)
+ updateCharPosWithUpdate();
+ break;
+
+ default:
+ break;
+ }
+
+ _screen->showMouse();
+}
+
+int KyraEngine_v2::updateCharPos(int *table) {
+ static uint32 nextUpdate = 0;
+ static const int updateX[] = { 0, 4, 4, 4, 0, -4, -4, -4 };
+ static const int updateY[] = { -2, -2, 0, 2, 2, 2, 0, -2 };
+
+ if (_system->getMillis() < nextUpdate)
+ return 0;
+
+ int facing = _mainCharacter.facing;
+ _mainCharacter.x1 += updateX[facing];
+ _mainCharacter.y1 += updateY[facing];
+ updateCharAnimFrame(0, table);
+ nextUpdate = _system->getMillis() + _timer->getDelay(0) * _tickLength;
+ return 1;
+}
+
+void KyraEngine_v2::updateCharPosWithUpdate() {
+ updateCharPos(0);
+ update();
+}
+
+void KyraEngine_v2::updateCharAnimFrame(int charId, int *table) {
+ static int unkTable1[] = { 0, 0 };
+ static const int unkTable2[] = { 17, 0 };
+ static const int unkTable3[] = { 10, 0 };
+ static const int unkTable4[] = { 24, 0 };
+ static const int unkTable5[] = { 19, 0 };
+ static const int unkTable6[] = { 21, 0 };
+ static const int unkTable7[] = { 31, 0 };
+ static const int unkTable8[] = { 26, 0 };
+
+ Character *character = &_mainCharacter;
+ ++character->animFrame;
+ int facing = character->facing;
+
+ if (table) {
+ if (table[0] != table[-1] && table[-1] == table[1]) {
+ facing = getOppositeFacingDirection(table[-1]);
+ table[0] = table[-1];
+ }
+ }
+
+ if (!facing) {
+ ++unkTable1[charId];
+ } else if (facing == 4) {
+ ++unkTable1[charId+1];
+ } else if (facing == 7 || facing == 1 || facing == 5 || facing == 3) {
+ if (facing == 7 || facing == 1) {
+ if (unkTable1[charId] > 2)
+ facing = 0;
+ } else {
+ if (unkTable1[charId+1] > 2)
+ facing = 4;
+ }
+
+ unkTable1[charId] = 0;
+ unkTable1[charId+1] = 0;
+ }
+
+ if (facing == 0) {
+ if (character->animFrame < unkTable8[charId])
+ character->animFrame = unkTable8[charId];
+
+ if (character->animFrame > unkTable7[charId])
+ character->animFrame = unkTable8[charId];
+ } else if (facing == 4) {
+ if (character->animFrame < unkTable5[charId])
+ character->animFrame = unkTable5[charId];
+
+ if (character->animFrame > unkTable4[charId])
+ character->animFrame = unkTable5[charId];
+ } else {
+ if (character->animFrame > unkTable5[charId])
+ character->animFrame = unkTable6[charId];
+
+ if (character->animFrame == unkTable2[charId])
+ character->animFrame = unkTable3[charId];
+
+ if (character->animFrame > unkTable2[charId])
+ character->animFrame = unkTable3[charId] + 2;
+ }
+
+ updateCharacterAnim(charId);
+}
+
+int KyraEngine_v2::checkCharCollision(int x, int y) {
+ int scale1 = 0, scale2 = 0, scale3 = 0;
+ int x1 = 0, x2 = 0, y1 = 0, y2 = 0;
+ scale1 = getScale(_mainCharacter.x1, _mainCharacter.y1);
+ scale2 = (scale1 * 24) >> 8;
+ scale3 = (scale1 * 48) >> 8;
+
+ x1 = _mainCharacter.x1 - (scale2 >> 1);
+ x2 = _mainCharacter.x1 + (scale2 >> 1);
+ y1 = _mainCharacter.y1 - scale3;
+ y2 = _mainCharacter.y1;
+
+ if (x >= x1 && x <= x2 && y >= y1 && y <= y2)
+ return 0;
+
+ return -1;
+}
+
+#pragma mark -
+
+typedef Functor1Mem<ScriptState*, int, KyraEngine_v2> OpcodeV2;
+#define Opcode(x) OpcodeV2(this, &KyraEngine_v2::x)
+#define OpcodeUnImpl() OpcodeV2(this, 0)
+void KyraEngine_v2::setupOpcodeTable() {
+ static const OpcodeV2 opcodeTable[] = {
+ // 0x00
+ Opcode(o2_setCharacterFacingRefresh),
+ OpcodeUnImpl(),
+ Opcode(o2_defineObject),
+ Opcode(o2_refreshCharacter),
+ // 0x04
+ Opcode(o2_getCharacterX),
+ Opcode(o2_getCharacterY),
+ Opcode(o2_getCharacterFacing),
+ OpcodeUnImpl(),
+ // 0x08
+ Opcode(o2_setSceneComment),
+ OpcodeUnImpl(),
+ OpcodeUnImpl(),
+ OpcodeUnImpl(),
+ // 0x0c
+ OpcodeUnImpl(),
+ OpcodeUnImpl(),
+ OpcodeUnImpl(),
+ OpcodeUnImpl(),
+ // 0x10
+ OpcodeUnImpl(),
+ Opcode(o2_showChapterMessage),
+ OpcodeUnImpl(),
+ OpcodeUnImpl(),
+ // 0x14
+ Opcode(o2_wsaClose),
+ OpcodeUnImpl(),
+ OpcodeUnImpl(),
+ Opcode(o2_displayWsaFrame),
+ // 0x18
+ Opcode(o2_displayWsaSequentialFrames),
+ Opcode(o2_wsaOpen),
+ OpcodeUnImpl(),
+ OpcodeUnImpl(),
+ // 0x1c
+ OpcodeUnImpl(),
+ OpcodeUnImpl(),
+ OpcodeUnImpl(),
+ OpcodeUnImpl(),
+ // 0x20
+ OpcodeUnImpl(),
+ OpcodeUnImpl(),
+ OpcodeUnImpl(),
+ Opcode(o2_defineItem),
+ // 0x24
+ OpcodeUnImpl(),
+ OpcodeUnImpl(),
+ OpcodeUnImpl(),
+ Opcode(o2_queryGameFlag),
+ // 0x28
+ Opcode(o2_resetGameFlag),
+ Opcode(o2_setGameFlag),
+ OpcodeUnImpl(),
+ OpcodeUnImpl(),
+ // 0x2c
+ OpcodeUnImpl(),
+ Opcode(o2_hideMouse),
+ Opcode(o2_addSpecialExit),
+ OpcodeUnImpl(),
+ // 0x30
+ Opcode(o2_showMouse),
+ OpcodeUnImpl(),
+ OpcodeUnImpl(),
+ OpcodeUnImpl(),
+ // 0x34
+ OpcodeUnImpl(),
+ OpcodeUnImpl(),
+ OpcodeUnImpl(),
+ OpcodeUnImpl(),
+ // 0x38
+ Opcode(o2_dummy),
+ OpcodeUnImpl(),
+ Opcode(o2_setScaleTableItem),
+ Opcode(o2_setDrawLayerTableItem),
+ // 0x3c
+ OpcodeUnImpl(),
+ OpcodeUnImpl(),
+ OpcodeUnImpl(),
+ Opcode(o2_drawSceneShapeOnPage),
+ // 0x40
+ OpcodeUnImpl(),
+ OpcodeUnImpl(),
+ Opcode(o2_dummy),
+ OpcodeUnImpl(),
+ // 0x44
+ OpcodeUnImpl(),
+ Opcode(o2_restoreBackBuffer),
+ OpcodeUnImpl(),
+ OpcodeUnImpl(),
+ // 0x48
+ OpcodeUnImpl(),
+ OpcodeUnImpl(),
+ OpcodeUnImpl(),
+ OpcodeUnImpl(),
+ // 0x4c
+ OpcodeUnImpl(),
+ OpcodeUnImpl(),
+ Opcode(o2_dummy),
+ Opcode(o2_dummy),
+ // 0x50
+ OpcodeUnImpl(),
+ OpcodeUnImpl(),
+ OpcodeUnImpl(),
+ OpcodeUnImpl(),
+ // 0x54
+ OpcodeUnImpl(),
+ OpcodeUnImpl(),
+ OpcodeUnImpl(),
+ OpcodeUnImpl(),
+ // 0x58
+ OpcodeUnImpl(),
+ OpcodeUnImpl(),
+ OpcodeUnImpl(),
+ OpcodeUnImpl(),
+ // 0x5c
+ OpcodeUnImpl(),
+ OpcodeUnImpl(),
+ OpcodeUnImpl(),
+ OpcodeUnImpl(),
+ // 0x60
+ Opcode(o2_getRand),
+ OpcodeUnImpl(),
+ OpcodeUnImpl(),
+ OpcodeUnImpl(),
+ // 0x64
+ OpcodeUnImpl(),
+ OpcodeUnImpl(),
+ OpcodeUnImpl(),
+ OpcodeUnImpl(),
+ // 0x68
+ OpcodeUnImpl(),
+ OpcodeUnImpl(),
+ OpcodeUnImpl(),
+ OpcodeUnImpl(),
+ // 0x6c
+ Opcode(o2_encodeShape),
+ Opcode(o2_defineRoomEntrance),
+ OpcodeUnImpl(),
+ Opcode(o2_setSpecialSceneScriptRunTime),
+ // 0x70
+ Opcode(o2_defineSceneAnim),
+ Opcode(o2_updateSceneAnim),
+ Opcode(o2_updateSceneAnim),
+ OpcodeUnImpl(),
+ // 0x74
+ OpcodeUnImpl(),
+ OpcodeUnImpl(),
+ OpcodeUnImpl(),
+ OpcodeUnImpl(),
+ // 0x78
+ OpcodeUnImpl(),
+ Opcode(o2_defineRoom),
+ OpcodeUnImpl(),
+ OpcodeUnImpl(),
+ // 0x7c
+ OpcodeUnImpl(),
+ Opcode(o2_dummy),
+ Opcode(o2_dummy),
+ OpcodeUnImpl(),
+ // 0x80
+ OpcodeUnImpl(),
+ OpcodeUnImpl(),
+ OpcodeUnImpl(),
+ OpcodeUnImpl(),
+ // 0x84
+ OpcodeUnImpl(),
+ OpcodeUnImpl(),
+ OpcodeUnImpl(),
+ OpcodeUnImpl(),
+ // 0x88
+ OpcodeUnImpl(),
+ OpcodeUnImpl(),
+ OpcodeUnImpl(),
+ OpcodeUnImpl(),
+ // 0x8c
+ OpcodeUnImpl(),
+ OpcodeUnImpl(),
+ OpcodeUnImpl(),
+ Opcode(o2_setSpecialSceneScriptState),
+ // 0x90
+ Opcode(o2_clearSpecialSceneScriptState),
+ Opcode(o2_querySpecialSceneScriptState),
+ OpcodeUnImpl(),
+ OpcodeUnImpl(),
+ // 0x94
+ OpcodeUnImpl(),
+ OpcodeUnImpl(),
+ Opcode(o2_wsaClose),
+ OpcodeUnImpl(),
+ // 0x98
+ OpcodeUnImpl(),
+ OpcodeUnImpl(),
+ OpcodeUnImpl(),
+ OpcodeUnImpl(),
+ // 0x9c
+ OpcodeUnImpl(),
+ OpcodeUnImpl(),
+ OpcodeUnImpl(),
+ OpcodeUnImpl(),
+ // 0xa0
+ OpcodeUnImpl(),
+ OpcodeUnImpl(),
+ OpcodeUnImpl(),
+ OpcodeUnImpl(),
+ // 0xa4
+ OpcodeUnImpl(),
+ OpcodeUnImpl(),
+ OpcodeUnImpl(),
+ OpcodeUnImpl(),
+ // 0xa8
+ OpcodeUnImpl(),
+ OpcodeUnImpl(),
+ OpcodeUnImpl(),
+ OpcodeUnImpl(),
+ // 0xac
+ OpcodeUnImpl(),
+ OpcodeUnImpl(),
+ Opcode(o2_dummy),
+ Opcode(o2_dummy),
+ };
+
+ for (int i = 0; i < ARRAYSIZE(opcodeTable); ++i)
+ _opcodes.push_back(&opcodeTable[i]);
}
} // end of namespace Kyra
diff --git a/engines/kyra/kyra_v2.h b/engines/kyra/kyra_v2.h
index a002baec19..c87eeb66d4 100644
--- a/engines/kyra/kyra_v2.h
+++ b/engines/kyra/kyra_v2.h
@@ -26,6 +26,10 @@
#ifndef KYRA_KYRA_V2_H
#define KYRA_KYRA_V2_H
+#include "kyra/kyra.h"
+#include "kyra/script.h"
+#include "kyra/screen_v2.h"
+
namespace Kyra {
enum kSequences {
@@ -82,12 +86,25 @@ class KyraEngine_v2 : public KyraEngine {
public:
KyraEngine_v2(OSystem *system, const GameFlags &flags);
~KyraEngine_v2();
+
+ virtual Screen *screen() { return _screen; }
+ Screen_v2 *screen_v2() { return _screen; }
+
+ Movie *createWSAMovie();
+protected:
+ // Main menu code, also used for Kyra 3
+ static const char *_mainMenuStrings[];
- int go();
-
-private:
- void setupOpcodeTable() {}
+ virtual void gui_initMainMenu() {}
+ int gui_handleMainMenu();
+ virtual void gui_updateMainMenuAnimation();
+ void gui_drawMainMenu(const char * const *strings, int select);
+ void gui_drawMainBox(int x, int y, int w, int h, int fill);
+ bool gui_mainMenuGetInput();
+
+ void gui_printString(const char *string, int x, int y, int col1, int col2, int flags, ...);
+ // intro
void seq_playSequences(int startSeq, int endSeq = -1);
int seq_introWestwood(int seqNum);
int seq_introTitle(int seqNum);
@@ -111,11 +128,14 @@ private:
void seq_setChatEntry(uint16 strIndex, uint16 posX, uint16 posY, int duration, uint16 unk1);
void mainMenu();
+
int init();
+ int go();
+
+ Screen_v2 *_screen;
ActiveWSA *_activeWSA;
ActiveChat *_activeChat;
- uint8 *_gameShapes[50];
uint8 *_mouseSHPBuf;
static const char *_introSoundList[];
@@ -124,6 +144,351 @@ private:
static const int _introStringsSize;
int _introStringsDuration[21];
+
+protected:
+ // game initialization
+ void startup();
+ void runLoop();
+ void cleanup();
+
+ void setupTimers();
+ void setupOpcodeTable();
+
+ void loadMouseShapes();
+ void loadItemShapes();
+
+ // run
+ int update();
+ void updateMouse();
+
+ int checkInput(void *p);
+ void handleInput(int x, int y);
+
+ int inputSceneChange(int x, int y, int unk1, int unk2);
+
+ // gfx/animation specific
+ uint8 *_gamePlayBuffer;
+ void restorePage3();
+
+ uint8 *_screenBuffer;
+ uint8 *_maskPage;
+ uint8 *_gfxBackUpRect;
+
+ uint8 *getShapePtr(int index) { return _defaultShapeTable[index]; }
+ uint8 *_defaultShapeTable[250];
+ uint8 *_sceneShapeTable[50];
+
+ WSAMovieV2 *_wsaSlots[10];
+
+ void freeSceneShapePtrs();
+
+ struct ShapeDesc {
+ uint8 unk0, unk1, unk2, unk3, unk4;
+ uint16 unk5, unk7;
+ int16 xAdd, yAdd;
+ };
+
+ ShapeDesc *_shapeDescTable;
+
+ struct SceneAnim {
+ uint16 flags;
+ int16 x, y;
+ int16 x2, y2;
+ int16 width, height;
+ uint16 unkE;
+ uint16 specialSize;
+ uint16 unk12;
+ int16 shapeIndex;
+ uint16 wsaFlag;
+ char filename[14];
+ };
+
+ SceneAnim _sceneAnims[10];
+ WSAMovieV2 *_sceneAnimMovie[10];
+ bool _specialSceneScriptState[10];
+ ScriptState _sceneSpecialScripts[10];
+ uint32 _sceneSpecialScriptsTimer[10];
+ int _lastProcessedSceneScript;
+ bool _specialSceneScriptRunFlag;
+
+ void updateSpecialSceneScripts();
+ void freeSceneAnims();
+
+ int _loadedZTable;
+ void loadZShapes(int shapes);
+ void loadInventoryShapes();
+
+ void resetScaleTable();
+ void setScaleTableItem(int item, int data);
+ int getScale(int x, int y);
+ uint16 _scaleTable[15];
+
+ void setDrawLayerTableEntry(int entry, int data);
+ int getDrawLayer(int x, int y);
+ int _drawLayerTable[15];
+
+ // animator
+ struct AnimObj {
+ uint16 index;
+ uint16 type;
+ uint16 enabled;
+ uint16 needRefresh;
+ uint16 unk8;
+ uint16 animFlags;
+ uint16 flags;
+ int16 xPos1, yPos1;
+ uint8 *shapePtr;
+ uint16 shapeIndex1;
+ uint16 animNum;
+ uint16 shapeIndex3;
+ uint16 shapeIndex2;
+ uint16 unk1E;
+ uint8 unk20;
+ uint8 unk21;
+ uint8 unk22;
+ uint8 unk23;
+ int16 xPos2, yPos2;
+ int16 xPos3, yPos3;
+ int16 width, height;
+ int16 width2, height2;
+ AnimObj *nextObject;
+ };
+
+ AnimObj _animObjects[42];
+ void clearAnimObjects();
+
+ AnimObj *_animList;
+ bool _drawNoShapeFlag;
+ AnimObj *initAnimList(AnimObj *list, AnimObj *entry);
+ AnimObj *addToAnimListSorted(AnimObj *list, AnimObj *entry);
+ AnimObj *deleteAnimListEntry(AnimObj *list, AnimObj *entry);
+
+ void drawAnimObjects();
+ void drawSceneAnimObject(AnimObj *obj, int x, int y, int drawLayer);
+ void drawCharacterAnimObject(AnimObj *obj, int x, int y, int drawLayer);
+
+ void refreshAnimObjects(int force);
+ void refreshAnimObjectsIfNeed();
+
+ void updateCharacterAnim(int);
+ void updateSceneAnim(int anim, int newFrame);
+
+ // scene
+ struct SceneDesc {
+ char filename[10];
+ uint16 exit1, exit2, exit3, exit4;
+ uint8 flags;
+ uint8 sound;
+ };
+
+ SceneDesc *_sceneList;
+ const char *_sceneCommentString;
+ uint16 _sceneExit1, _sceneExit2, _sceneExit3, _sceneExit4;
+ int _sceneEnterX1, _sceneEnterY1, _sceneEnterX2, _sceneEnterY2,
+ _sceneEnterX3, _sceneEnterY3, _sceneEnterX4, _sceneEnterY4;
+ int _specialExitCount;
+ uint16 _specialExitTable[25];
+ bool checkSpecialSceneExit(int num, int x, int y);
+ uint8 _scenePal[688];
+ bool _overwriteSceneFacing;
+
+ void enterNewScene(uint16 newScene, int facing, int unk1, int unk2, int unk3);
+ void enterNewSceneUnk1(int facing, int unk1, int unk2);
+ void enterNewSceneUnk2(int unk1);
+ void unloadScene();
+
+ void loadScenePal();
+ void loadSceneMsc();
+
+ void startSceneScript(int unk1);
+ void runSceneScript2();
+ void runSceneScript4(int unk1);
+ void runSceneScript7();
+
+ void initSceneAnims(int unk1);
+ void initSceneScreen(int unk1);
+
+ int trySceneChange(int *moveTable, int unk1, int updateChar);
+ int checkSceneChange();
+
+ // pathfinder
+ int _movFacingTable[600];
+ int findWay(int curX, int curY, int dstX, int dstY, int *moveTable, int moveTableSize);
+ bool lineIsPassable(int x, int y);
+ bool directLinePassable(int x, int y, int toX, int toY);
+
+ int pathfinderUnk1(int *moveTable);
+ int pathfinderUnk2(int index, int v1, int v2);
+ int pathfinderUnk3(int tableLen, int x, int y);
+ int pathfinderUnk4(int index, int v);
+ void pathfinderUnk5(int *moveTable, int unk1, int x, int y, int moveTableSize);
+
+ int _pathfinderUnkTable1[400];
+ int _pathfinderUnkTable2[200];
+
+ // item
+ uint8 _itemHtDat[176];
+
+ struct Item {
+ uint16 id;
+ uint16 sceneId;
+ int16 x;
+ int8 y;
+ uint16 unk7;
+ };
+ Item *_itemList;
+
+ int findFreeItem();
+ int findItem(uint16 sceneId, int id);
+ void resetItemList();
+
+ int _itemInHand;
+ int _handItemSet;
+
+ // inventroy
+ static int _inventoryX[];
+ static int _inventoryY[];
+
+ // localization
+ void loadCCodeBuffer(const char *file);
+ void loadOptionsBuffer(const char *file);
+ void loadChapterBuffer(int chapter);
+ uint8 *_optionsBuffer;
+ uint8 *_cCodeBuffer;
+
+ uint8 *_chapterBuffer;
+ int _currentChapter;
+ int _newChapterFile;
+
+ const uint8 *getTableEntry(const uint8 *buffer, int id);
+ const char *getTableString(int id, const uint8 *buffer, int decode);
+ const char *getChapterString(int id);
+ int decodeString1(const char *src, char *dst);
+ void decodeString2(const char *src, char *dst);
+
+ void changeFileExtension(char *buffer);
+
+ char _internStringBuf[200];
+ static const char *_languageExtension[];
+ static const char *_scriptLangExt[];
+
+ // character
+ struct Character {
+ uint16 sceneId;
+ uint16 unk2;
+ uint8 height;
+ uint8 facing;
+ uint16 animFrame;
+ uint8 unk8;
+ uint8 unk9;
+ uint8 unkA;
+ uint16 inventory[20];
+ int16 x1, y1;
+ int16 x2, y2;
+ };
+
+ Character _mainCharacter;
+ bool _useCharPal;
+ int _charPalEntry;
+ uint8 _charPalTable[16];
+ void updateCharPal(int unk1);
+
+ void moveCharacter(int facing, int x, int y);
+ int updateCharPos(int *table);
+ void updateCharPosWithUpdate();
+ void updateCharAnimFrame(int num, int *table);
+
+ int checkCharCollision(int x, int y);
+
+ int _mainCharX, _mainCharY;
+ int _charScaleX, _charScaleY;
+
+ static int _characterFrameTable[];
+
+ // text
+ void showMessageFromCCode(int id, int16 palIndex, int);
+ void showMessage(const char *string, int16 palIndex);
+ void showChapterMessage(int id, int16 palIndex);
+
+ const char *_shownMessage;
+
+ byte _messagePal[3];
+ int _msgUnk1;
+
+ // timer
+ void timerFunc2(int);
+ void timerFunc3(int);
+ void timerFunc4(int);
+ void timerFunc5(int);
+ void timerFunc6(int);
+
+ void setTimer1DelaySecs(int secs);
+
+ // opcodes
+ int o2_setCharacterFacingRefresh(ScriptState *script);
+ int o2_defineObject(ScriptState *script);
+ int o2_refreshCharacter(ScriptState *script);
+ int o2_getCharacterX(ScriptState *script);
+ int o2_getCharacterY(ScriptState *script);
+ int o2_getCharacterFacing(ScriptState *script);
+ int o2_setSceneComment(ScriptState *script);
+ int o2_showChapterMessage(ScriptState *script);
+ int o2_wsaClose(ScriptState *script);
+ int o2_displayWsaFrame(ScriptState *script);
+ int o2_displayWsaSequentialFrames(ScriptState *script);
+ int o2_wsaOpen(ScriptState *script);
+ int o2_defineItem(ScriptState *script);
+ int o2_queryGameFlag(ScriptState *script);
+ int o2_resetGameFlag(ScriptState *script);
+ int o2_setGameFlag(ScriptState *script);
+ int o2_hideMouse(ScriptState *script);
+ int o2_addSpecialExit(ScriptState *script);
+ int o2_showMouse(ScriptState *script);
+ int o2_setScaleTableItem(ScriptState *script);
+ int o2_setDrawLayerTableItem(ScriptState *script);
+ int o2_drawSceneShapeOnPage(ScriptState *script);
+ int o2_restoreBackBuffer(ScriptState *script);
+ int o2_getRand(ScriptState *script);
+ int o2_encodeShape(ScriptState *script);
+ int o2_defineRoomEntrance(ScriptState *script);
+ int o2_setSpecialSceneScriptRunTime(ScriptState *script);
+ int o2_defineSceneAnim(ScriptState *script);
+ int o2_updateSceneAnim(ScriptState *script);
+ int o2_defineRoom(ScriptState *script);
+ int o2_setSpecialSceneScriptState(ScriptState *script);
+ int o2_clearSpecialSceneScriptState(ScriptState *script);
+ int o2_querySpecialSceneScriptState(ScriptState *script);
+ int o2_dummy(ScriptState *script);
+
+ // script
+ void runStartScript(int script, int unk1);
+ void loadNPCScript();
+
+ bool _noScriptEnter;
+
+ ScriptData _npcScriptData;
+
+ ScriptData _sceneScriptData;
+ ScriptState _sceneScriptState;
+
+ // pathfinder
+ int _pathfinderFlag;
+
+ // unk
+ struct Object {
+ char filename[13];
+ uint8 scriptId;
+ int16 x, y;
+ int8 unk12;
+ };
+ Object *_objectList;
+
+ uint8 *_unkBuf500Bytes;
+ uint8 *_unkBuf200kByte;
+ bool _unkFlag1;
+ int _unk3, _unk4, _unk5;
+ bool _unkSceneScreenFlag1;
+ bool _unkHandleSceneChangeFlag;
};
} // end of namespace Kyra
diff --git a/engines/kyra/kyra_v3.cpp b/engines/kyra/kyra_v3.cpp
index eee901598e..32754ecf2f 100644
--- a/engines/kyra/kyra_v3.cpp
+++ b/engines/kyra/kyra_v3.cpp
@@ -38,7 +38,7 @@
#include "graphics/cursorman.h"
namespace Kyra {
-KyraEngine_v3::KyraEngine_v3(OSystem *system, const GameFlags &flags) : KyraEngine(system, flags) {
+KyraEngine_v3::KyraEngine_v3(OSystem *system, const GameFlags &flags) : KyraEngine_v2(system, flags) {
_soundDigital = 0;
_musicSoundChannel = -1;
_menuAudioFile = "TITLE1.AUD";
@@ -87,10 +87,6 @@ KyraEngine_v3::~KyraEngine_v3() {
delete [] _scenesList;
}
-Movie *KyraEngine_v3::createWSAMovie() {
- return new WSAMovieV2(this);
-}
-
int KyraEngine_v3::init() {
KyraEngine::init();
@@ -294,14 +290,14 @@ void KyraEngine_v3::stopMusicTrack() {
int KyraEngine_v3::musicUpdate(int forceRestart) {
debugC(9, kDebugLevelMain, "KyraEngine::unkUpdate(%d)", forceRestart);
- static uint32 timer = 0;
+ static uint32 mTimer = 0;
static uint16 lock = 0;
- if (ABS<int>(_system->getMillis() - timer) > (int)(0x0F * _tickLength)) {
- timer = _system->getMillis();
+ if (ABS<int>(_system->getMillis() - mTimer) > (int)(0x0F * _tickLength)) {
+ mTimer = _system->getMillis();
}
- if (_system->getMillis() < timer && !forceRestart) {
+ if (_system->getMillis() < mTimer && !forceRestart) {
return 1;
}
@@ -315,7 +311,7 @@ int KyraEngine_v3::musicUpdate(int forceRestart) {
}
}
lock = 0;
- timer = _system->getMillis() + 0x0F * _tickLength;
+ mTimer = _system->getMillis() + 0x0F * _tickLength;
}
return 1;
@@ -324,7 +320,7 @@ int KyraEngine_v3::musicUpdate(int forceRestart) {
#pragma mark -
void KyraEngine_v3::gui_initMainMenu() {
- KyraEngine::gui_initMainMenu();
+ KyraEngine_v2::gui_initMainMenu();
_mainMenuFrame = 29;
_mainMenuFrameAdd = 1;
}
diff --git a/engines/kyra/kyra_v3.h b/engines/kyra/kyra_v3.h
index eda382d89a..f9b81b5126 100644
--- a/engines/kyra/kyra_v3.h
+++ b/engines/kyra/kyra_v3.h
@@ -26,20 +26,17 @@
#ifndef KYRA_KYRA_V3_H
#define KYRA_KYRA_V3_H
-#include "kyra/kyra.h"
+#include "kyra/kyra_v2.h"
namespace Kyra {
-// maybe subclass KyraEngine_v2 later
-class WSAMovieV2;
+class SoundDigital;
-class KyraEngine_v3 : public KyraEngine {
+class KyraEngine_v3 : public KyraEngine_v2 {
public:
KyraEngine_v3(OSystem *system, const GameFlags &flags);
~KyraEngine_v3();
-
- Movie *createWSAMovie();
-
+
SoundDigital *soundDigital() { return _soundDigital; }
int go();
diff --git a/engines/kyra/module.mk b/engines/kyra/module.mk
index 8303028b27..0517c393a1 100644
--- a/engines/kyra/module.mk
+++ b/engines/kyra/module.mk
@@ -1,20 +1,28 @@
MODULE := engines/kyra
MODULE_OBJS := \
- animator.o \
+ animator_v1.o \
+ animator_v2.o \
debugger.o \
detection.o \
- gui.o \
- items.o \
+ gui_v1.o \
+ gui_v2.o \
+ items_v1.o \
+ items_v2.o \
kyra.o \
kyra_v1.o \
kyra_v2.o \
kyra_v3.o \
resource.o \
- saveload.o \
+ saveload_v1.o \
scene.o \
+ scene_v1.o \
+ scene_v2.o \
screen.o \
+ screen_v1.o \
+ screen_v2.o \
script_v1.o \
+ script_v2.o \
script.o \
seqplayer.o \
sequences_v1.o \
@@ -23,10 +31,14 @@ MODULE_OBJS := \
sound_digital.o \
sound_towns.o \
sound.o \
+ sound_v1.o \
sprites.o \
staticres.o \
text.o \
+ text_v1.o \
timer.o \
+ timer_v1.o \
+ timer_v2.o \
vqa.o \
wsamovie.o
diff --git a/engines/kyra/resource.cpp b/engines/kyra/resource.cpp
index 2425444be1..cb484b6183 100644
--- a/engines/kyra/resource.cpp
+++ b/engines/kyra/resource.cpp
@@ -42,11 +42,11 @@
namespace Kyra {
namespace {
-struct ResFilenameEqual : public Common::BinaryFunction<ResourceFile*, uint, bool> {
+struct ResFilenameEqual : public Common::UnaryFunction<ResourceFile*, bool> {
uint _filename;
ResFilenameEqual(uint file) : _filename(file) {}
- bool operator()(ResourceFile *f) {
+ bool operator()(const ResourceFile *f) {
return f->filename() == _filename;
}
};
@@ -220,8 +220,11 @@ uint8 *Resource::fileData(const char *file, uint32 *size) const {
bool Resource::getFileHandle(const char *file, uint32 *size, Common::File &filehandle) {
filehandle.close();
- if (filehandle.open(file))
+ if (filehandle.open(file)) {
+ if (size)
+ *size = filehandle.size();
return true;
+ }
uint fileHash = Common::hashit_lower(file);
for (ResIterator start = _pakfiles.begin() ;start != _pakfiles.end(); ++start) {
@@ -229,12 +232,14 @@ bool Resource::getFileHandle(const char *file, uint32 *size, Common::File &fileh
continue;
if ((*start)->getFileHandle(fileHash, filehandle)) {
-
- *size = (*start)->getFileSize(fileHash);
+ uint32 tSize = (*start)->getFileSize(fileHash);
- if (!(*size))
+ if (!tSize)
continue;
+ if (size)
+ *size = tSize;
+
return true;
}
}
diff --git a/engines/kyra/resource.h b/engines/kyra/resource.h
index 19855ed9c9..139a7fa72c 100644
--- a/engines/kyra/resource.h
+++ b/engines/kyra/resource.h
@@ -122,9 +122,8 @@ public:
uint32 getFileSize(const char *file) const;
uint8* fileData(const char *file, uint32 *size) const;
- // it gives back a file handle (used for the speech player)
- // it could be that the needed file is embedded in the returned
- // handle
+ // gives back a file handle
+ // it is possible that the needed file is embedded in the returned handle
bool getFileHandle(const char *file, uint32 *size, Common::File &filehandle);
bool loadFileToBuf(const char *file, void *buf, uint32 maxSize);
diff --git a/engines/kyra/saveload.cpp b/engines/kyra/saveload_v1.cpp
index 95693684a1..c2ceee1d3b 100644
--- a/engines/kyra/saveload.cpp
+++ b/engines/kyra/saveload_v1.cpp
@@ -28,13 +28,14 @@
#include "common/savefile.h"
#include "common/system.h"
-#include "kyra/kyra.h"
-#include "kyra/animator.h"
+#include "kyra/kyra_v1.h"
+#include "kyra/animator_v1.h"
#include "kyra/screen.h"
#include "kyra/resource.h"
#include "kyra/sound.h"
+#include "kyra/timer.h"
-#define CURRENT_VERSION 7
+#define CURRENT_VERSION 8
// TODO: our current savefiles still use the old
// flag system to check the version, we should
@@ -44,7 +45,7 @@
#define GF_FMTOWNS (1 << 2)
namespace Kyra {
-void KyraEngine::loadGame(const char *fileName) {
+void KyraEngine_v1::loadGame(const char *fileName) {
debugC(9, kDebugLevelMain, "loadGame('%s')", fileName);
Common::InSaveFile *in;
@@ -147,14 +148,7 @@ void KyraEngine::loadGame(const char *fileName) {
_poisonDeathCounter = in->readByte();
_animator->_brandonDrawFrame = in->readUint16BE();
- for (int i = 0; i < 32; i++) {
- _timers[i].active = in->readByte();
- _timers[i].countdown = in->readSint32BE();
- _timers[i].nextRun = in->readUint32BE();
- if (_timers[i].nextRun != 0)
- _timers[i].nextRun += _system->getMillis();
- }
- _timerNextRun = 0;
+ _timer->loadDataFromFile(in, version);
memset(_flagsTable, 0, sizeof(_flagsTable));
uint32 flagsSize = in->readUint32BE();
@@ -206,7 +200,7 @@ void KyraEngine::loadGame(const char *fileName) {
if (version >= 7) {
_curSfxFile = in->readByte();
- // In the first version there this entry was introduced,
+ // In the first version when this entry was introduced,
// it wasn't made sure that _curSfxFile was initialized
// so if it's out of bounds we just set it to 0.
if (_curSfxFile >= _soundFilesTownsCount || _curSfxFile < 0)
@@ -266,7 +260,7 @@ void KyraEngine::loadGame(const char *fileName) {
delete in;
}
-void KyraEngine::saveGame(const char *fileName, const char *saveName) {
+void KyraEngine_v1::saveGame(const char *fileName, const char *saveName) {
debugC(9, kDebugLevelMain, "saveGame('%s', '%s')", fileName, saveName);
Common::OutSaveFile *out;
if (_quitFlag) return;
@@ -323,14 +317,7 @@ void KyraEngine::saveGame(const char *fileName, const char *saveName) {
out->writeByte(_poisonDeathCounter);
out->writeUint16BE(_animator->_brandonDrawFrame);
- for (int i = 0; i < 32; i++) {
- out->writeByte(_timers[i].active);
- out->writeSint32BE(_timers[i].countdown);
- if (_system->getMillis() >= _timers[i].nextRun)
- out->writeUint32BE(0);
- else
- out->writeUint32BE(_timers[i].nextRun - _system->getMillis());
- }
+ _timer->saveDataToFile(out);
out->writeUint32BE(sizeof(_flagsTable));
out->write(_flagsTable, sizeof(_flagsTable));
diff --git a/engines/kyra/scene.cpp b/engines/kyra/scene.cpp
index a92fd9ce7c..bf85ab1474 100644
--- a/engines/kyra/scene.cpp
+++ b/engines/kyra/scene.cpp
@@ -11,7 +11,7 @@
* 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
+ * 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
@@ -24,1168 +24,10 @@
*/
#include "kyra/kyra.h"
-#include "kyra/seqplayer.h"
#include "kyra/screen.h"
-#include "kyra/resource.h"
-#include "kyra/sound.h"
-#include "kyra/sprites.h"
-#include "kyra/wsamovie.h"
-#include "kyra/animator.h"
-#include "kyra/text.h"
-#include "kyra/script.h"
-
-#include "common/system.h"
-#include "common/savefile.h"
namespace Kyra {
-void KyraEngine::enterNewScene(int sceneId, int facing, int unk1, int unk2, int brandonAlive) {
- debugC(9, kDebugLevelMain, "KyraEngine::enterNewScene(%d, %d, %d, %d, %d)", sceneId, facing, unk1, unk2, brandonAlive);
- int unkVar1 = 1;
- _screen->hideMouse();
- _handleInput = false;
- _abortWalkFlag = false;
- _abortWalkFlag2 = false;
-
- if (_flags.platform == Common::kPlatformFMTowns) {
- int newSfxFile = -1;
- if (_currentCharacter->sceneId == 7 && sceneId == 24)
- newSfxFile = 2;
- else if (_currentCharacter->sceneId == 25 && sceneId == 109)
- newSfxFile = 3;
- else if (_currentCharacter->sceneId == 120 && sceneId == 37)
- newSfxFile = 4;
- else if (_currentCharacter->sceneId == 52 && sceneId == 199)
- newSfxFile = 5;
- else if (_currentCharacter->sceneId == 37 && sceneId == 120)
- newSfxFile = 3;
- else if (_currentCharacter->sceneId == 109 && sceneId == 25)
- newSfxFile = 2;
- else if (_currentCharacter->sceneId == 24 && sceneId == 7)
- newSfxFile = 1;
-
- if (newSfxFile != -1) {
- _curSfxFile = newSfxFile;
- _sound->loadSoundFile(_curSfxFile);
- }
- }
-
- switch (_currentCharacter->sceneId) {
- case 1:
- if (sceneId == 0) {
- moveCharacterToPos(0, 0, _currentCharacter->x1, 84);
- unkVar1 = 0;
- }
- break;
-
- case 3:
- if (sceneId == 2) {
- moveCharacterToPos(0, 6, 155, _currentCharacter->y1);
- unkVar1 = 0;
- }
- break;
-
- case 26:
- if (sceneId == 27) {
- moveCharacterToPos(0, 6, 155, _currentCharacter->y1);
- unkVar1 = 0;
- }
- break;
-
- case 44:
- if (sceneId == 45) {
- moveCharacterToPos(0, 2, 192, _currentCharacter->y1);
- unkVar1 = 0;
- }
- break;
-
- default:
- break;
- }
-
- if (unkVar1 && unk1) {
- int xpos = _currentCharacter->x1;
- int ypos = _currentCharacter->y1;
- switch (facing) {
- case 0:
- ypos = _currentCharacter->y1 - 6;
- break;
-
- case 2:
- xpos = 336;
- break;
-
- case 4:
- ypos = 143;
- break;
-
- case 6:
- xpos = -16;
- break;
-
- default:
- break;
- }
-
- moveCharacterToPos(0, facing, xpos, ypos);
- }
-
- for (int i = 0; i < ARRAYSIZE(_movieObjects); ++i)
- _movieObjects[i]->close();
-
- if (!brandonAlive) {
- _scriptInterpreter->initScript(_scriptClick, _scriptClickData);
- _scriptInterpreter->startScript(_scriptClick, 5);
- while (_scriptInterpreter->validScript(_scriptClick))
- _scriptInterpreter->runScript(_scriptClick);
- }
-
- memset(_entranceMouseCursorTracks, 0xFFFF, sizeof(uint16)*4);
- _currentCharacter->sceneId = sceneId;
-
- assert(sceneId < _roomTableSize);
- assert(_roomTable[sceneId].nameIndex < _roomFilenameTableSize);
-
- Room *currentRoom = &_roomTable[sceneId];
-
- setupSceneResource(sceneId);
-
- _currentRoom = sceneId;
-
- int tableId = _roomTable[sceneId].nameIndex;
- char fileNameBuffer[32];
- strcpy(fileNameBuffer, _roomFilenameTable[tableId]);
- strcat(fileNameBuffer, ".DAT");
- _sprites->loadDat(fileNameBuffer, _sceneExits);
- _sprites->setupSceneAnims();
- _scriptInterpreter->unloadScript(_scriptClickData);
- loadSceneMsc();
-
- _walkBlockNorth = currentRoom->northExit;
- _walkBlockEast = currentRoom->eastExit;
- _walkBlockSouth = currentRoom->southExit;
- _walkBlockWest = currentRoom->westExit;
-
- if (_walkBlockNorth == 0xFFFF)
- _screen->blockOutRegion(0, 0, 320, (_northExitHeight & 0xFF)+3);
- if (_walkBlockEast == 0xFFFF)
- _screen->blockOutRegion(312, 0, 8, 139);
- if (_walkBlockSouth == 0xFFFF)
- _screen->blockOutRegion(0, 135, 320, 8);
- if (_walkBlockWest == 0xFFFF)
- _screen->blockOutRegion(0, 0, 8, 139);
-
- if (!brandonAlive)
- updatePlayerItemsForScene();
-
- startSceneScript(brandonAlive);
- setupSceneItems();
-
- initSceneData(facing, unk2, brandonAlive);
-
- _loopFlag2 = 0;
- _screen->showMouse();
- if (!brandonAlive)
- seq_poisonDeathNow(0);
- updateMousePointer(true);
- _changedScene = true;
-}
-
-void KyraEngine::transcendScenes(int roomIndex, int roomName) {
- debugC(9, kDebugLevelMain, "KyraEngine::transcendScenes(%d, %d)", roomIndex, roomName);
- assert(roomIndex < _roomTableSize);
-
- if (_flags.isTalkie) {
- char file[32];
- assert(roomIndex < _roomTableSize);
- int tableId = _roomTable[roomIndex].nameIndex;
- assert(tableId < _roomFilenameTableSize);
- strcpy(file, _roomFilenameTable[tableId]);
- strcat(file, ".VRM");
- _res->unloadPakFile(file);
- }
-
- _roomTable[roomIndex].nameIndex = roomName;
- _unkScreenVar2 = 1;
- _unkScreenVar3 = 1;
- _unkScreenVar1 = 0;
- _brandonPosX = _currentCharacter->x1;
- _brandonPosY = _currentCharacter->y1;
- enterNewScene(roomIndex, _currentCharacter->facing, 0, 0, 0);
- _unkScreenVar1 = 1;
- _unkScreenVar2 = 0;
- _unkScreenVar3 = 0;
-}
-
-void KyraEngine::setSceneFile(int roomIndex, int roomName) {
- debugC(9, kDebugLevelMain, "KyraEngine::setSceneFile(%d, %d)", roomIndex, roomName);
- assert(roomIndex < _roomTableSize);
- _roomTable[roomIndex].nameIndex = roomName;
-}
-
-void KyraEngine::moveCharacterToPos(int character, int facing, int xpos, int ypos) {
- debugC(9, kDebugLevelMain, "KyraEngine::moveCharacterToPos(%d, %d, %d, %d)", character, facing, xpos, ypos);
- Character *ch = &_characterList[character];
- ch->facing = facing;
- _screen->hideMouse();
- xpos = (int16)(xpos & 0xFFFC);
- ypos = (int16)(ypos & 0xFFFE);
- disableTimer(19);
- disableTimer(14);
- disableTimer(18);
- uint32 nextFrame = 0;
-
- switch (facing) {
- case 0:
- while (ypos < ch->y1) {
- nextFrame = getTimerDelay(5 + character) * _tickLength + _system->getMillis();
- setCharacterPositionWithUpdate(character);
- delayUntil(nextFrame, true);
- }
- break;
-
- case 2:
- while (ch->x1 < xpos) {
- nextFrame = getTimerDelay(5 + character) * _tickLength + _system->getMillis();
- setCharacterPositionWithUpdate(character);
- delayUntil(nextFrame, true);
- }
- break;
-
- case 4:
- while (ypos > ch->y1) {
- nextFrame = getTimerDelay(5 + character) * _tickLength + _system->getMillis();
- setCharacterPositionWithUpdate(character);
- delayUntil(nextFrame, true);
- }
- break;
-
- case 6:
- while (ch->x1 > xpos) {
- nextFrame = getTimerDelay(5 + character) * _tickLength + _system->getMillis();
- setCharacterPositionWithUpdate(character);
- delayUntil(nextFrame, true);
- }
- break;
-
- default:
- break;
- }
-
- enableTimer(19);
- enableTimer(14);
- enableTimer(18);
- _screen->showMouse();
-}
-
-void KyraEngine::setCharacterPositionWithUpdate(int character) {
- debugC(9, kDebugLevelMain, "KyraEngine::setCharacterPositionWithUpdate(%d)", character);
- setCharacterPosition(character, 0);
- _sprites->updateSceneAnims();
- updateGameTimers();
- _animator->updateAllObjectShapes();
- updateTextFade();
-
- if (_currentCharacter->sceneId == 210)
- updateKyragemFading();
-}
-
-int KyraEngine::setCharacterPosition(int character, int *facingTable) {
- debugC(9, kDebugLevelMain, "KyraEngine::setCharacterPosition(%d, %p)", character, (const void *)facingTable);
-
- if (character == 0) {
- _currentCharacter->x1 += _charXPosTable[_currentCharacter->facing];
- _currentCharacter->y1 += _charYPosTable[_currentCharacter->facing];
- setCharacterPositionHelper(0, facingTable);
- return 1;
- } else {
- _characterList[character].x1 += _charXPosTable[_characterList[character].facing];
- _characterList[character].y1 += _charYPosTable[_characterList[character].facing];
- if (_characterList[character].sceneId == _currentCharacter->sceneId)
- setCharacterPositionHelper(character, 0);
- }
- return 0;
-}
-
-void KyraEngine::setCharacterPositionHelper(int character, int *facingTable) {
- debugC(9, kDebugLevelMain, "KyraEngine::setCharacterPositionHelper(%d, %p)", character, (const void *)facingTable);
- Character *ch = &_characterList[character];
- ++ch->currentAnimFrame;
- int facing = ch->facing;
- if (facingTable) {
- if (*facingTable != *(facingTable - 1)) {
- if (*(facingTable - 1) == *(facingTable + 1)) {
- facing = getOppositeFacingDirection(*(facingTable - 1));
- *facingTable = *(facingTable - 1);
- }
- }
- }
-
- static uint8 facingIsZero[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
- static uint8 facingIsFour[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
-
- if (facing == 0) {
- ++facingIsZero[character];
- } else {
- bool resetTables = false;
- if (facing != 7) {
- if (facing - 1 != 0) {
- if (facing != 4) {
- if (facing == 3 || facing == 5) {
- if (facingIsFour[character] > 2)
- facing = 4;
- resetTables = true;
- }
- } else {
- ++facingIsFour[character];
- }
- } else {
- if (facingIsZero[character] > 2)
- facing = 0;
- resetTables = true;
- }
- } else {
- if (facingIsZero[character] > 2)
- facing = 0;
- resetTables = true;
- }
-
- if (resetTables) {
- facingIsZero[character] = 0;
- facingIsFour[character] = 0;
- }
- }
-
- static const uint16 maxAnimationFrame[] = {
- 0x000F, 0x0031, 0x0055, 0x0000, 0x0000, 0x0000,
- 0x0008, 0x002A, 0x004E, 0x0000, 0x0000, 0x0000,
- 0x0022, 0x0046, 0x006A, 0x0000, 0x0000, 0x0000,
- 0x001D, 0x0041, 0x0065, 0x0000, 0x0000, 0x0000,
- 0x001F, 0x0043, 0x0067, 0x0000, 0x0000, 0x0000,
- 0x0028, 0x004C, 0x0070, 0x0000, 0x0000, 0x0000,
- 0x0023, 0x0047, 0x006B, 0x0000, 0x0000, 0x0000
- };
-
- if (facing == 0) {
- if (maxAnimationFrame[36+character] > ch->currentAnimFrame)
- ch->currentAnimFrame = maxAnimationFrame[36+character];
- if (maxAnimationFrame[30+character] < ch->currentAnimFrame)
- ch->currentAnimFrame = maxAnimationFrame[36+character];
- } else if (facing == 4) {
- if (maxAnimationFrame[18+character] > ch->currentAnimFrame)
- ch->currentAnimFrame = maxAnimationFrame[18+character];
- if (maxAnimationFrame[12+character] < ch->currentAnimFrame)
- ch->currentAnimFrame = maxAnimationFrame[18+character];
- } else {
- if (maxAnimationFrame[18+character] < ch->currentAnimFrame)
- ch->currentAnimFrame = maxAnimationFrame[30+character];
- if (maxAnimationFrame[character] == ch->currentAnimFrame)
- ch->currentAnimFrame = maxAnimationFrame[6+character];
- if (maxAnimationFrame[character] < ch->currentAnimFrame)
- ch->currentAnimFrame = maxAnimationFrame[6+character]+2;
- }
-
- if (character == 0 && (_brandonStatusBit & 0x10))
- ch->currentAnimFrame = 88;
-
- _animator->animRefreshNPC(character);
-}
-
-int KyraEngine::getOppositeFacingDirection(int dir) {
- debugC(9, kDebugLevelMain, "KyraEngine::getOppositeFacingDirection(%d)", dir);
- switch (dir) {
- case 0:
- return 2;
- case 1:
- return 1;
- case 3:
- return 7;
- case 4:
- return 6;
- case 5:
- return 5;
- case 6:
- return 4;
- case 7:
- return 3;
- default:
- break;
- }
- return 0;
-}
-
-void KyraEngine::loadSceneMsc() {
- assert(_currentCharacter->sceneId < _roomTableSize);
- int tableId = _roomTable[_currentCharacter->sceneId].nameIndex;
- assert(tableId < _roomFilenameTableSize);
- char fileNameBuffer[32];
- strcpy(fileNameBuffer, _roomFilenameTable[tableId]);
- strcat(fileNameBuffer, ".MSC");
- _screen->fillRect(0, 0, 319, 199, 0, 5);
- _screen->loadBitmap(fileNameBuffer, 3, 5, 0);
-}
-
-void KyraEngine::startSceneScript(int brandonAlive) {
- debugC(9, kDebugLevelMain, "KyraEngine::startSceneScript(%d)", brandonAlive);
- assert(_currentCharacter->sceneId < _roomTableSize);
- int tableId = _roomTable[_currentCharacter->sceneId].nameIndex;
- assert(tableId < _roomFilenameTableSize);
- char fileNameBuffer[32];
- strcpy(fileNameBuffer, _roomFilenameTable[tableId]);
- strcat(fileNameBuffer, ".CPS");
- _screen->clearPage(3);
- // FIXME: check this hack for amiga version
- _screen->loadBitmap(fileNameBuffer, 3, 3, (_flags.platform == Common::kPlatformAmiga ? _screen->getPalette(0) : 0));
- _sprites->loadSceneShapes();
- _exitListPtr = 0;
-
- _scaleMode = 1;
- for (int i = 0; i < 145; ++i)
- _scaleTable[i] = 256;
-
- clearNoDropRects();
- _scriptInterpreter->initScript(_scriptClick, _scriptClickData);
- strcpy(fileNameBuffer, _roomFilenameTable[tableId]);
- strcat(fileNameBuffer, ".EMC");
- _scriptInterpreter->unloadScript(_scriptClickData);
- _scriptInterpreter->loadScript(fileNameBuffer, _scriptClickData, &_opcodes);
- _scriptInterpreter->startScript(_scriptClick, 0);
- _scriptClick->regs[0] = _currentCharacter->sceneId;
- _scriptClick->regs[7] = brandonAlive;
-
- while (_scriptInterpreter->validScript(_scriptClick))
- _scriptInterpreter->runScript(_scriptClick);
-}
-
-void KyraEngine::initSceneData(int facing, int unk1, int brandonAlive) {
- debugC(9, kDebugLevelMain, "KyraEngine::initSceneData(%d, %d, %d)", facing, unk1, brandonAlive);
-
- int16 xpos2 = 0;
- int setFacing = 1;
-
- int16 xpos = 0, ypos = 0;
-
- if (_brandonPosX == -1 && _brandonPosY == -1) {
- switch (facing + 1) {
- case 0:
- xpos = ypos = -1;
- break;
-
- case 1: case 2: case 8:
- xpos = _sceneExits.southXPos;
- ypos = _sceneExits.southYPos;
- break;
-
- case 3:
- xpos = _sceneExits.westXPos;
- ypos = _sceneExits.westYPos;
- break;
-
- case 4: case 5: case 6:
- xpos = _sceneExits.northXPos;
- ypos = _sceneExits.northYPos;
- break;
-
- case 7:
- xpos = _sceneExits.eastXPos;
- ypos = _sceneExits.eastYPos;
- break;
-
- default:
- break;
- }
-
- if ((uint8)(_northExitHeight & 0xFF) + 2 >= ypos)
- ypos = (_northExitHeight & 0xFF) + 4;
- if (xpos >= 308)
- xpos = 304;
- if ((uint8)(_northExitHeight >> 8) - 2 <= ypos)
- ypos = (_northExitHeight >> 8) - 4;
- if (xpos <= 12)
- xpos = 16;
- }
-
- if (_brandonPosX > -1)
- xpos = _brandonPosX;
- if (_brandonPosY > -1)
- ypos = _brandonPosY;
-
- int16 ypos2 = 0;
- if (_brandonPosX > -1 && _brandonPosY > -1) {
- switch (_currentCharacter->sceneId) {
- case 1:
- _currentCharacter->x1 = xpos;
- _currentCharacter->x2 = xpos;
- _currentCharacter->y1 = ypos;
- _currentCharacter->y2 = ypos;
- facing = 4;
- xpos2 = 192;
- ypos2 = 104;
- setFacing = 0;
- unk1 = 1;
- break;
-
- case 3:
- _currentCharacter->x1 = xpos;
- _currentCharacter->x2 = xpos;
- _currentCharacter->y1 = ypos;
- _currentCharacter->y2 = ypos;
- facing = 2;
- xpos2 = 204;
- ypos2 = 94;
- setFacing = 0;
- unk1 = 1;
- break;
-
- case 26:
- _currentCharacter->x1 = xpos;
- _currentCharacter->x2 = xpos;
- _currentCharacter->y1 = ypos;
- _currentCharacter->y2 = ypos;
- facing = 2;
- xpos2 = 192;
- ypos2 = 128;
- setFacing = 0;
- unk1 = 1;
- break;
-
- case 44:
- _currentCharacter->x1 = xpos;
- _currentCharacter->x2 = xpos;
- _currentCharacter->y1 = ypos;
- _currentCharacter->y2 = ypos;
- facing = 6;
- xpos2 = 156;
- ypos2 = 96;
- setFacing = 0;
- unk1 = 1;
- break;
-
- case 37:
- _currentCharacter->x1 = xpos;
- _currentCharacter->x2 = xpos;
- _currentCharacter->y1 = ypos;
- _currentCharacter->y2 = ypos;
- facing = 2;
- xpos2 = 148;
- ypos2 = 114;
- setFacing = 0;
- unk1 = 1;
- break;
-
- default:
- break;
- }
- }
-
- _brandonPosX = _brandonPosY = -1;
-
- if (unk1 && setFacing) {
- ypos2 = ypos;
- xpos2 = xpos;
- switch (facing) {
- case 0:
- ypos = 142;
- break;
-
- case 2:
- xpos = -16;
- break;
-
- case 4:
- ypos = (uint8)(_northExitHeight & 0xFF) - 4;
- break;
-
- case 6:
- xpos = 336;
- break;
-
- default:
- break;
- }
- }
-
- xpos2 = (int16)(xpos2 & 0xFFFC);
- ypos2 = (int16)(ypos2 & 0xFFFE);
- xpos = (int16)(xpos & 0xFFFC);
- ypos = (int16)(ypos & 0xFFFE);
- _currentCharacter->facing = facing;
- _currentCharacter->x1 = xpos;
- _currentCharacter->x2 = xpos;
- _currentCharacter->y1 = ypos;
- _currentCharacter->y2 = ypos;
-
- initSceneObjectList(brandonAlive);
-
- if (unk1 && brandonAlive == 0)
- moveCharacterToPos(0, facing, xpos2, ypos2);
-
- _scriptClick->regs[4] = _itemInHand;
- _scriptClick->regs[7] = brandonAlive;
- _scriptInterpreter->startScript(_scriptClick, 3);
- while (_scriptInterpreter->validScript(_scriptClick))
- _scriptInterpreter->runScript(_scriptClick);
-}
-
-void KyraEngine::initSceneObjectList(int brandonAlive) {
- debugC(9, kDebugLevelMain, "KyraEngine::initSceneObjectList(%d)", brandonAlive);
- for (int i = 0; i < 28; ++i)
- _animator->actors()[i].active = 0;
-
- int startAnimFrame = 0;
-
- AnimObject *curAnimState = _animator->actors();
- curAnimState->active = 1;
- curAnimState->drawY = _currentCharacter->y1;
- curAnimState->sceneAnimPtr = _shapes[_currentCharacter->currentAnimFrame];
- curAnimState->animFrameNumber = _currentCharacter->currentAnimFrame;
- startAnimFrame = _currentCharacter->currentAnimFrame-7;
- int xOffset = _defaultShapeTable[startAnimFrame].xOffset;
- int yOffset = _defaultShapeTable[startAnimFrame].yOffset;
-
- if (_scaleMode) {
- curAnimState->x1 = _currentCharacter->x1;
- curAnimState->y1 = _currentCharacter->y1;
-
- _animator->_brandonScaleX = _scaleTable[_currentCharacter->y1];
- _animator->_brandonScaleY = _scaleTable[_currentCharacter->y1];
-
- curAnimState->x1 += (_animator->_brandonScaleX * xOffset) >> 8;
- curAnimState->y1 += (_animator->_brandonScaleY * yOffset) >> 8;
- } else {
- curAnimState->x1 = _currentCharacter->x1 + xOffset;
- curAnimState->y1 = _currentCharacter->y1 + yOffset;
- }
-
- curAnimState->x2 = curAnimState->x1;
- curAnimState->y2 = curAnimState->y1;
- curAnimState->refreshFlag = 1;
- curAnimState->bkgdChangeFlag = 1;
- _animator->clearQueue();
- _animator->addObjectToQueue(curAnimState);
-
- int listAdded = 0;
- int addedObjects = 1;
-
- for (int i = 1; i < 5; ++i) {
- Character *ch = &_characterList[i];
- curAnimState = &_animator->actors()[addedObjects];
- if (ch->sceneId != _currentCharacter->sceneId) {
- curAnimState->active = 0;
- curAnimState->refreshFlag = 0;
- curAnimState->bkgdChangeFlag = 0;
- ++addedObjects;
- continue;
- }
-
- curAnimState->drawY = ch->y1;
- curAnimState->sceneAnimPtr = _shapes[ch->currentAnimFrame];
- curAnimState->animFrameNumber = ch->currentAnimFrame;
- startAnimFrame = ch->currentAnimFrame-7;
- xOffset = _defaultShapeTable[startAnimFrame].xOffset;
- yOffset = _defaultShapeTable[startAnimFrame].yOffset;
- if (_scaleMode) {
- curAnimState->x1 = ch->x1;
- curAnimState->y1 = ch->y1;
-
- _animator->_brandonScaleX = _scaleTable[ch->y1];
- _animator->_brandonScaleY = _scaleTable[ch->y1];
-
- curAnimState->x1 += (_animator->_brandonScaleX * xOffset) >> 8;
- curAnimState->y1 += (_animator->_brandonScaleY * yOffset) >> 8;
- } else {
- curAnimState->x1 = ch->x1 + xOffset;
- curAnimState->y1 = ch->y1 + yOffset;
- }
- curAnimState->x2 = curAnimState->x1;
- curAnimState->y2 = curAnimState->y1;
- curAnimState->active = 1;
- curAnimState->refreshFlag = 1;
- curAnimState->bkgdChangeFlag = 1;
-
- if (ch->facing >= 1 && ch->facing <= 3)
- curAnimState->flags |= 1;
- else if (ch->facing >= 5 && ch->facing <= 7)
- curAnimState->flags &= 0xFFFFFFFE;
-
- _animator->addObjectToQueue(curAnimState);
-
- ++addedObjects;
- ++listAdded;
- if (listAdded < 2)
- i = 5;
- }
-
- for (int i = 0; i < 11; ++i) {
- curAnimState = &_animator->sprites()[i];
-
- if (_sprites->_anims[i].play) {
- curAnimState->active = 1;
- curAnimState->refreshFlag = 1;
- curAnimState->bkgdChangeFlag = 1;
- } else {
- curAnimState->active = 0;
- curAnimState->refreshFlag = 0;
- curAnimState->bkgdChangeFlag = 0;
- }
- curAnimState->height = _sprites->_anims[i].height;
- curAnimState->height2 = _sprites->_anims[i].height2;
- curAnimState->width = _sprites->_anims[i].width + 1;
- curAnimState->width2 = _sprites->_anims[i].width2;
- curAnimState->drawY = _sprites->_anims[i].drawY;
- curAnimState->x1 = curAnimState->x2 = _sprites->_anims[i].x;
- curAnimState->y1 = curAnimState->y2 = _sprites->_anims[i].y;
- curAnimState->background = _sprites->_anims[i].background;
- curAnimState->sceneAnimPtr = _sprites->_sceneShapes[_sprites->_anims[i].sprite];
-
- curAnimState->disable = _sprites->_anims[i].disable;
-
- if (_sprites->_anims[i].unk2)
- curAnimState->flags = 0x800;
- else
- curAnimState->flags = 0;
-
- if (_sprites->_anims[i].flipX)
- curAnimState->flags |= 0x1;
-
- _animator->addObjectToQueue(curAnimState);
- }
-
- for (int i = 0; i < 12; ++i) {
- curAnimState = &_animator->items()[i];
- Room *curRoom = &_roomTable[_currentCharacter->sceneId];
- byte curItem = curRoom->itemsTable[i];
- if (curItem != 0xFF) {
- curAnimState->drawY = curRoom->itemsYPos[i];
- curAnimState->sceneAnimPtr = _shapes[216+curItem];
- curAnimState->animFrameNumber = (int16)0xFFFF;
- curAnimState->y1 = curRoom->itemsYPos[i];
- curAnimState->x1 = curRoom->itemsXPos[i];
-
- curAnimState->x1 -= (_animator->fetchAnimWidth(curAnimState->sceneAnimPtr, _scaleTable[curAnimState->drawY])) >> 1;
- curAnimState->y1 -= _animator->fetchAnimHeight(curAnimState->sceneAnimPtr, _scaleTable[curAnimState->drawY]);
-
- curAnimState->x2 = curAnimState->x1;
- curAnimState->y2 = curAnimState->y1;
-
- curAnimState->active = 1;
- curAnimState->refreshFlag = 1;
- curAnimState->bkgdChangeFlag = 1;
-
- _animator->addObjectToQueue(curAnimState);
- } else {
- curAnimState->active = 0;
- curAnimState->refreshFlag = 0;
- curAnimState->bkgdChangeFlag = 0;
- }
- }
-
- _animator->preserveAnyChangedBackgrounds();
- curAnimState = _animator->actors();
- curAnimState->bkgdChangeFlag = 1;
- curAnimState->refreshFlag = 1;
- for (int i = 1; i < 28; ++i) {
- curAnimState = &_animator->objects()[i];
- if (curAnimState->active) {
- curAnimState->bkgdChangeFlag = 1;
- curAnimState->refreshFlag = 1;
- }
- }
- _animator->restoreAllObjectBackgrounds();
- _animator->preserveAnyChangedBackgrounds();
- _animator->prepDrawAllObjects();
- initSceneScreen(brandonAlive);
- _animator->copyChangedObjectsForward(0);
-}
-
-void KyraEngine::initSceneScreen(int brandonAlive) {
- if (_flags.platform == Common::kPlatformAmiga) {
- if (_unkScreenVar1 && !queryGameFlag(0xF0)) {
- memset(_screen->getPalette(2), 0, 32*3);
- if (_currentCharacter->sceneId != 117 || !queryGameFlag(0xB3))
- _screen->setScreenPalette(_screen->getPalette(2));
- }
-
- if (_unkScreenVar2 == 1)
- _screen->shuffleScreen(8, 8, 304, 128, 2, 0, _unkScreenVar3, false);
- else
- _screen->copyRegion(8, 8, 8, 8, 304, 128, 2, 0);
-
- if (_unkScreenVar1 && !queryGameFlag(0xA0)) {
- if (_currentCharacter->sceneId == 45 && _paletteChanged)
- memcpy(_screen->getPalette(0) + 12*3, _screen->getPalette(4) + 12*3, 2);
-
- if (_currentCharacter->sceneId >= 229 && _currentCharacter->sceneId <= 245 && (_brandonStatusBit & 1))
- memcpy(_screen->getPalette(0), _screen->getPalette(0) + 320*3, 64);
-
- _screen->setScreenPalette(_screen->getPalette(0));
- }
- } else {
- if (_unkScreenVar1 && !queryGameFlag(0xA0)) {
- for (int i = 0; i < 60; ++i) {
- uint16 col = _screen->getPalette(0)[684+i];
- col += _screen->getPalette(1)[684+i] << 1;
- col >>= 2;
- _screen->getPalette(0)[684+i] = col;
- }
- _screen->setScreenPalette(_screen->getPalette(0));
- }
-
- if (_unkScreenVar2 == 1)
- _screen->shuffleScreen(8, 8, 304, 128, 2, 0, _unkScreenVar3, false);
- else
- _screen->copyRegion(8, 8, 8, 8, 304, 128, 2, 0);
-
- if (_unkScreenVar1 && _paletteChanged) {
- if (!queryGameFlag(0xA0)) {
- memcpy(_screen->getPalette(0) + 684, _screen->getPalette(1) + 684, 60);
- _screen->setScreenPalette(_screen->getPalette(0));
- } else {
- memset(_screen->getPalette(0), 0, 768);
- }
- }
- }
-
- // really call this here?
- _screen->updateScreen();
-
- if (!_scriptInterpreter->startScript(_scriptClick, 2))
- error("Could not start script function 2 of scene script");
-
- _scriptClick->regs[7] = brandonAlive;
-
- while (_scriptInterpreter->validScript(_scriptClick))
- _scriptInterpreter->runScript(_scriptClick);
-
- setTextFadeTimerCountdown(-1);
- if (_currentCharacter->sceneId == 210) {
- if (_itemInHand != -1)
- magicOutMouseItem(2, -1);
-
- _screen->hideMouse();
- for (int i = 0; i < 10; ++i) {
- if (_currentCharacter->inventoryItems[i] != 0xFF)
- magicOutMouseItem(2, i);
- }
- _screen->showMouse();
- }
-}
-
-int KyraEngine::handleSceneChange(int xpos, int ypos, int unk1, int frameReset) {
- debugC(9, kDebugLevelMain, "KyraEngine::handleSceneChange(%d, %d, %d, %d)", xpos, ypos, unk1, frameReset);
- if (queryGameFlag(0xEF))
- unk1 = 0;
-
- int sceneId = _currentCharacter->sceneId;
- _pathfinderFlag = 0;
-
- if (xpos < 12) {
- if (_roomTable[sceneId].westExit != 0xFFFF) {
- xpos = 12;
- ypos = _sceneExits.westYPos;
- _pathfinderFlag = 7;
- }
- } else if (xpos >= 308) {
- if (_roomTable[sceneId].eastExit != 0xFFFF) {
- xpos = 307;
- ypos = _sceneExits.eastYPos;
- _pathfinderFlag = 13;
- }
- }
-
- if (ypos <= (_northExitHeight&0xFF)+2) {
- if (_roomTable[sceneId].northExit != 0xFFFF) {
- xpos = _sceneExits.northXPos;
- ypos = _northExitHeight & 0xFF;
- _pathfinderFlag = 14;
- }
- } else if (ypos >= 136) {
- if (_roomTable[sceneId].southExit != 0xFFFF) {
- xpos = _sceneExits.southXPos;
- ypos = 136;
- _pathfinderFlag = 11;
- }
- }
-
- int temp = xpos - _currentCharacter->x1;
- if (ABS(temp) < 4) {
- temp = ypos - _currentCharacter->y1;
- if (ABS(temp) < 2)
- return 0;
- }
-
- int x = (int16)(_currentCharacter->x1 & 0xFFFC);
- int y = (int16)(_currentCharacter->y1 & 0xFFFE);
- xpos = (int16)(xpos & 0xFFFC);
- ypos = (int16)(ypos & 0xFFFE);
-
- int ret = findWay(x, y, xpos, ypos, _movFacingTable, 150);
- _pathfinderFlag = 0;
-
- if (ret >= _lastFindWayRet)
- _lastFindWayRet = ret;
-
- if (ret == 0x7D00 || ret == 0)
- return 0;
-
- return processSceneChange(_movFacingTable, unk1, frameReset);
-}
-
-int KyraEngine::processSceneChange(int *table, int unk1, int frameReset) {
- debugC(9, kDebugLevelMain, "KyraEngine::processSceneChange(%p, %d, %d)", (const void *)table, unk1, frameReset);
- if (queryGameFlag(0xEF))
- unk1 = 0;
-
- int *tableStart = table;
- _sceneChangeState = 0;
- _loopFlag2 = 0;
- bool running = true;
- int returnValue = 0;
- uint32 nextFrame = 0;
- _abortWalkFlag = false;
- _mousePressFlag = false;
-
- while (running) {
- if (_abortWalkFlag) {
- *table = 8;
- _currentCharacter->currentAnimFrame = 7;
- _animator->animRefreshNPC(0);
- _animator->updateAllObjectShapes();
- processInput();
- return 0;
- }
- bool forceContinue = false;
- switch (*table) {
- case 0: case 1: case 2:
- case 3: case 4: case 5:
- case 6: case 7:
- _currentCharacter->facing = getOppositeFacingDirection(*table);
- break;
-
- case 8:
- forceContinue = true;
- running = false;
- break;
-
- default:
- ++table;
- forceContinue = true;
- break;
- }
-
- returnValue = changeScene(_currentCharacter->facing);
- if (returnValue) {
- running = false;
- _abortWalkFlag = false;
- }
-
- if (unk1) {
- if (_mousePressFlag) {
- running = false;
- _sceneChangeState = 1;
- }
- }
-
- if (forceContinue || !running)
- continue;
-
- int temp = 0;
- if (table == tableStart || table[1] == 8)
- temp = setCharacterPosition(0, 0);
- else
- temp = setCharacterPosition(0, table);
-
- if (temp)
- ++table;
-
- nextFrame = getTimerDelay(5) * _tickLength + _system->getMillis();
- while (_system->getMillis() < nextFrame) {
- updateGameTimers();
-
- if (_currentCharacter->sceneId == 210) {
- updateKyragemFading();
- if (seq_playEnd() || _beadStateVar == 4 || _beadStateVar == 5) {
- *table = 8;
- running = false;
- break;
- }
- }
-
- if ((nextFrame - _system->getMillis()) >= 10)
- delay(10, true);
- }
- }
-
- if (frameReset && !(_brandonStatusBit & 2))
- _currentCharacter->currentAnimFrame = 7;
-
- _animator->animRefreshNPC(0);
- _animator->updateAllObjectShapes();
- return returnValue;
-}
-
-int KyraEngine::changeScene(int facing) {
- debugC(9, kDebugLevelMain, "KyraEngine::changeScene(%d)", facing);
- if (queryGameFlag(0xEF)) {
- if (_currentCharacter->sceneId == 5)
- return 0;
- }
-
- int xpos = _charXPosTable[facing] + _currentCharacter->x1;
- int ypos = _charYPosTable[facing] + _currentCharacter->y1;
-
- if (xpos >= 12 && xpos <= 308) {
- if (!lineIsPassable(xpos, ypos))
- return false;
- }
-
- if (_exitListPtr) {
- int16 *ptr = _exitListPtr;
- // this loop should be only entered one time, seems to be some hack in the original
- while (true) {
- if (*ptr == -1)
- break;
-
- if (*ptr > _currentCharacter->x1 || _currentCharacter->y1 < ptr[1] || _currentCharacter->x1 > ptr[2] || _currentCharacter->y1 > ptr[3]) {
- ptr += 10;
- break;
- }
-
- _brandonPosX = ptr[6];
- _brandonPosY = ptr[7];
- uint16 sceneId = ptr[5];
- facing = ptr[4];
- int unk1 = ptr[8];
- int unk2 = ptr[9];
-
- if (sceneId == 0xFFFF) {
- switch (facing) {
- case 0:
- sceneId = _roomTable[_currentCharacter->sceneId].northExit;
- break;
-
- case 2:
- sceneId = _roomTable[_currentCharacter->sceneId].eastExit;
- break;
-
- case 4:
- sceneId = _roomTable[_currentCharacter->sceneId].southExit;
- break;
-
- case 6:
- sceneId = _roomTable[_currentCharacter->sceneId].westExit;
- break;
-
- default:
- break;
- }
- }
-
- _currentCharacter->facing = facing;
- _animator->animRefreshNPC(0);
- _animator->updateAllObjectShapes();
- enterNewScene(sceneId, facing, unk1, unk2, 0);
- resetGameFlag(0xEE);
- return 1;
- }
- }
-
- int returnValue = 0;
- facing = 0;
-
- if ((_northExitHeight & 0xFF) + 2 >= ypos || (_northExitHeight & 0xFF) + 2 >= _currentCharacter->y1) {
- facing = 0;
- returnValue = 1;
- }
-
- if (xpos >= 308 || (_currentCharacter->x1 + 4) >= 308) {
- facing = 2;
- returnValue = 1;
- }
-
- if (((_northExitHeight >> 8) & 0xFF) - 2 < ypos || ((_northExitHeight >> 8) & 0xFF) - 2 < _currentCharacter->y1) {
- facing = 4;
- returnValue = 1;
- }
-
- if (xpos <= 12 || _currentCharacter->y1 <= 12) {
- facing = 6;
- returnValue = 1;
- }
-
- if (!returnValue)
- return 0;
-
- uint16 sceneId = 0xFFFF;
- switch (facing) {
- case 0:
- sceneId = _roomTable[_currentCharacter->sceneId].northExit;
- break;
-
- case 2:
- sceneId = _roomTable[_currentCharacter->sceneId].eastExit;
- break;
-
- case 4:
- sceneId = _roomTable[_currentCharacter->sceneId].southExit;
- break;
-
- default:
- sceneId = _roomTable[_currentCharacter->sceneId].westExit;
- break;
- }
-
- if (sceneId == 0xFFFF)
- return 0;
-
- enterNewScene(sceneId, facing, 1, 1, 0);
- return returnValue;
-}
-
-void KyraEngine::setCharactersInDefaultScene() {
- static const uint32 defaultSceneTable[][4] = {
- { 0xFFFF, 0x0004, 0x0003, 0xFFFF },
- { 0xFFFF, 0x0022, 0xFFFF, 0x0000 },
- { 0xFFFF, 0x001D, 0x0021, 0xFFFF },
- { 0xFFFF, 0x0000, 0x0000, 0xFFFF }
- };
-
- for (int i = 1; i < 5; ++i) {
- Character *cur = &_characterList[i];
- //cur->field_20 = 0;
-
- const uint32 *curTable = defaultSceneTable[i-1];
- cur->sceneId = curTable[0];
-
- if (cur->sceneId == _currentCharacter->sceneId)
- //++cur->field_20;
- cur->sceneId = curTable[1/*cur->field_20*/];
-
- //cur->field_23 = curTable[cur->field_20+1];
- }
-}
-
-void KyraEngine::setCharactersPositions(int character) {
- static uint16 initXPosTable[] = {
- 0x3200, 0x0024, 0x2230, 0x2F00, 0x0020, 0x002B,
- 0x00CA, 0x00F0, 0x0082, 0x00A2, 0x0042
- };
- static uint8 initYPosTable[] = {
- 0x00, 0xA2, 0x00, 0x42, 0x00,
- 0x67, 0x67, 0x60, 0x5A, 0x71,
- 0x76
- };
-
- assert(character < ARRAYSIZE(initXPosTable));
- Character *edit = &_characterList[character];
- edit->x1 = edit->x2 = initXPosTable[character];
- edit->y1 = edit->y2 = initYPosTable[character];
-}
-
-#pragma mark -
-#pragma mark - Pathfinder
-#pragma mark -
-
int KyraEngine::findWay(int x, int y, int toX, int toY, int *moveTable, int moveTableSize) {
debugC(9, kDebugLevelMain, "KyraEngine::findWay(%d, %d, %d, %d, %p, %d)", x, y, toX, toY, (const void *)moveTable, moveTableSize);
x &= 0xFFFC; toX &= 0xFFFC;
@@ -1199,8 +41,8 @@ int KyraEngine::findWay(int x, int y, int toX, int toY, int *moveTable, int move
int curX = x;
int curY = y;
- int lastUsedEntry = 0;
int tempValue = 0;
+ int lastUsedEntry = 0;
int *pathTable1 = new int[0x7D0];
int *pathTable2 = new int[0x7D0];
assert(pathTable1 && pathTable2);
@@ -1208,14 +50,14 @@ int KyraEngine::findWay(int x, int y, int toX, int toY, int *moveTable, int move
while (true) {
int newFacing = getFacingFromPointToPoint(x, y, toX, toY);
changePosTowardsFacing(curX, curY, newFacing);
-
+
if (curX == toX && curY == toY) {
if (!lineIsPassable(curX, curY))
break;
moveTable[lastUsedEntry++] = newFacing;
break;
}
-
+
if (lineIsPassable(curX, curY)) {
if (lastUsedEntry == moveTableSize) {
delete [] pathTable1;
@@ -1233,7 +75,7 @@ int KyraEngine::findWay(int x, int y, int toX, int toY, int *moveTable, int move
y = curY;
continue;
}
-
+
int temp = 0;
while (true) {
newFacing = getFacingFromPointToPoint(curX, curY, toX, toY);
@@ -1249,7 +91,7 @@ int KyraEngine::findWay(int x, int y, int toX, int toY, int *moveTable, int move
if (curX != toX || curY != toY)
continue;
}
-
+
if (curX == toX && curY == toY) {
if (!lineIsPassable(curX, curY)) {
tempValue = 0;
@@ -1298,7 +140,7 @@ int KyraEngine::findWay(int x, int y, int toX, int toY, int *moveTable, int move
delete [] pathTable1;
delete [] pathTable2;
moveTable[lastUsedEntry] = 8;
- return getMoveTableSize(moveTable);
+ return lastUsedEntry;
}
int KyraEngine::findSubPath(int x, int y, int toX, int toY, int *moveTable, int start, int end) {
@@ -1312,10 +154,10 @@ int KyraEngine::findSubPath(int x, int y, int toX, int toY, int *moveTable, int
static const int8 addPosTableY[] = { -1, 2, -1, 0, -1, -2, -1, 0, -1, 0, -1, 2, -1, 0, -1, -2 };
// debug specific
- //++unkTable[start];
- //while (_screen->getPalette(0)[unkTable[start]] != 0x0F) {
- // ++unkTable[start];
- //}
+ /*++unkTable[start];
+ while (screen()->getPalette(0)[unkTable[start]] != 0x0F) {
+ ++unkTable[start];
+ }*/
int xpos1 = x, xpos2 = x;
int ypos1 = y, ypos2 = y;
@@ -1338,11 +180,11 @@ int KyraEngine::findSubPath(int x, int y, int toX, int toY, int *moveTable, int
break;
}
// debug drawing
- //if (xpos1 >= 0 && ypos1 >= 0 && xpos1 < 320 && ypos1 < 200) {
- // _screen->setPagePixel(0, xpos1, ypos1, unkTable[start]);
- // _screen->updateScreen();
- // waitTicks(5);
- //}
+ /*if (xpos1 >= 0 && ypos1 >= 0 && xpos1 < 320 && ypos1 < 200) {
+ screen()->setPagePixel(0, xpos1, ypos1, unkTable[start]);
+ screen()->updateScreen();
+ //waitTicks(5);
+ }*/
if (newFacing & 1) {
int temp = xpos1 + addPosTableX[newFacing + start * 8];
if (toX == temp) {
@@ -1363,7 +205,7 @@ int KyraEngine::findSubPath(int x, int y, int toX, int toY, int *moveTable, int
if (xpos1 == xpos2 && ypos1 == ypos2)
break;
-
+
newFacing = facingTable3[start*8 + newFacing];
}
@@ -1394,7 +236,7 @@ int KyraEngine::getFacingFromPointToPoint(int x, int y, int toX, int toY) {
int temp = ydiff;
ydiff = xdiff;
xdiff = temp;
-
+
facingEntry <<= 1;
} else {
facingEntry <<= 1;
@@ -1413,71 +255,36 @@ int KyraEngine::getFacingFromPointToPoint(int x, int y, int toX, int toY) {
return facingTable[facingEntry];
}
+
+int KyraEngine::getOppositeFacingDirection(int dir) {
+ debugC(9, kDebugLevelMain, "KyraEngine::getOppositeFacingDirection(%d)", dir);
+ switch (dir) {
+ case 0:
+ return 2;
+ case 1:
+ return 1;
+ case 3:
+ return 7;
+ case 4:
+ return 6;
+ case 5:
+ return 5;
+ case 6:
+ return 4;
+ case 7:
+ return 3;
+ default:
+ break;
+ }
+ return 0;
+}
+
void KyraEngine::changePosTowardsFacing(int &x, int &y, int facing) {
debugC(9, kDebugLevelMain, "KyraEngine::changePosTowardsFacing(%d, %d, %d)", x, y, facing);
x += _addXPosTable[facing];
y += _addYPosTable[facing];
}
-bool KyraEngine::lineIsPassable(int x, int y) {
- debugC(9, kDebugLevelMain, "KyraEngine::lineIsPassable(%d, %d)", x, y);
- if (queryGameFlag(0xEF)) {
- if (_currentCharacter->sceneId == 5)
- return true;
- }
-
- if (_pathfinderFlag & 2) {
- if (x >= 312)
- return false;
- }
-
- if (_pathfinderFlag & 4) {
- if (y >= 136)
- return false;
- }
-
- if (_pathfinderFlag & 8) {
- if (x < 8)
- return false;
- }
-
- if (_pathfinderFlag2) {
- if (x <= 8 || x >= 312)
- return true;
- if (y < (_northExitHeight & 0xFF) || y > 135)
- return true;
- }
-
- if (y > 137)
- return false;
-
- if (y < 0)
- y = 0;
-
- int ypos = 8;
- if (_scaleMode) {
- ypos = (_scaleTable[y] >> 5) + 1;
- if (8 < ypos)
- ypos = 8;
- }
-
- x -= (ypos >> 1);
-
- int xpos = x;
- int xtemp = xpos + ypos - 1;
- if (x < 0)
- xpos = 0;
-
- if (xtemp > 319)
- xtemp = 319;
-
- for (; xpos < xtemp; ++xpos) {
- if (!_screen->getShapeFlag1(xpos, y))
- return false;
- }
- return true;
-}
-
int KyraEngine::getMoveTableSize(int *moveTable) {
debugC(9, kDebugLevelMain, "KyraEngine::getMoveTableSize(%p)", (const void *)moveTable);
int retValue = 0;
@@ -1573,52 +380,4 @@ int KyraEngine::getMoveTableSize(int *moveTable) {
return retValue;
}
-void KyraEngine::setupSceneResource(int sceneId) {
- debugC(9, kDebugLevelMain, "KyraEngine::setupSceneResource(%d)", sceneId);
- if (!_flags.isTalkie)
- return;
-
- if (_currentRoom != 0xFFFF) {
- assert(_currentRoom < _roomTableSize);
- int tableId = _roomTable[_currentRoom].nameIndex;
- assert(tableId < _roomFilenameTableSize);
-
- // unload our old room
- char file[64];
- strcpy(file, _roomFilenameTable[tableId]);
- strcat(file, ".VRM");
- _res->unloadPakFile(file);
-
- strcpy(file, _roomFilenameTable[tableId]);
- strcat(file, ".PAK");
- _res->unloadPakFile(file);
-
- strcpy(file, _roomFilenameTable[tableId]);
- strcat(file, ".APK");
- _res->unloadPakFile(file);
- }
-
- assert(sceneId < _roomTableSize);
- int tableId = _roomTable[sceneId].nameIndex;
- assert(tableId < _roomFilenameTableSize);
-
- // load our new room
- char file[64];
- strcpy(file, _roomFilenameTable[tableId]);
- strcat(file, ".VRM");
- if (Common::File::exists(file))
- _res->loadPakFile(file);
-
- strcpy(file, _roomFilenameTable[tableId]);
- strcat(file, ".PAK");
- if (Common::File::exists(file))
- _res->loadPakFile(file);
-
- strcpy(file, _roomFilenameTable[tableId]);
- strcat(file, ".APK");
- if (Common::File::exists(file))
- _res->loadPakFile(file);
-}
-
} // end of namespace Kyra
-
diff --git a/engines/kyra/scene_v1.cpp b/engines/kyra/scene_v1.cpp
new file mode 100644
index 0000000000..3754d5e2ab
--- /dev/null
+++ b/engines/kyra/scene_v1.cpp
@@ -0,0 +1,1282 @@
+/* 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 "kyra/kyra_v1.h"
+#include "kyra/seqplayer.h"
+#include "kyra/screen.h"
+#include "kyra/resource.h"
+#include "kyra/sound.h"
+#include "kyra/sprites.h"
+#include "kyra/wsamovie.h"
+#include "kyra/animator_v1.h"
+#include "kyra/text.h"
+#include "kyra/script.h"
+#include "kyra/timer.h"
+
+#include "common/system.h"
+#include "common/savefile.h"
+
+namespace Kyra {
+
+void KyraEngine_v1::enterNewScene(int sceneId, int facing, int unk1, int unk2, int brandonAlive) {
+ debugC(9, kDebugLevelMain, "KyraEngine_v1::enterNewScene(%d, %d, %d, %d, %d)", sceneId, facing, unk1, unk2, brandonAlive);
+ int unkVar1 = 1;
+ _screen->hideMouse();
+ _handleInput = false;
+ _abortWalkFlag = false;
+ _abortWalkFlag2 = false;
+
+ if (_flags.platform == Common::kPlatformFMTowns) {
+ int newSfxFile = -1;
+ if (_currentCharacter->sceneId == 7 && sceneId == 24)
+ newSfxFile = 2;
+ else if (_currentCharacter->sceneId == 25 && sceneId == 109)
+ newSfxFile = 3;
+ else if (_currentCharacter->sceneId == 120 && sceneId == 37)
+ newSfxFile = 4;
+ else if (_currentCharacter->sceneId == 52 && sceneId == 199)
+ newSfxFile = 5;
+ else if (_currentCharacter->sceneId == 37 && sceneId == 120)
+ newSfxFile = 3;
+ else if (_currentCharacter->sceneId == 109 && sceneId == 25)
+ newSfxFile = 2;
+ else if (_currentCharacter->sceneId == 24 && sceneId == 7)
+ newSfxFile = 1;
+
+ if (newSfxFile != -1) {
+ _curSfxFile = newSfxFile;
+ _sound->loadSoundFile(_curSfxFile);
+ }
+ }
+
+ switch (_currentCharacter->sceneId) {
+ case 1:
+ if (sceneId == 0) {
+ moveCharacterToPos(0, 0, _currentCharacter->x1, 84);
+ unkVar1 = 0;
+ }
+ break;
+
+ case 3:
+ if (sceneId == 2) {
+ moveCharacterToPos(0, 6, 155, _currentCharacter->y1);
+ unkVar1 = 0;
+ }
+ break;
+
+ case 26:
+ if (sceneId == 27) {
+ moveCharacterToPos(0, 6, 155, _currentCharacter->y1);
+ unkVar1 = 0;
+ }
+ break;
+
+ case 44:
+ if (sceneId == 45) {
+ moveCharacterToPos(0, 2, 192, _currentCharacter->y1);
+ unkVar1 = 0;
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ if (unkVar1 && unk1) {
+ int xpos = _currentCharacter->x1;
+ int ypos = _currentCharacter->y1;
+ switch (facing) {
+ case 0:
+ ypos = _currentCharacter->y1 - 6;
+ break;
+
+ case 2:
+ xpos = 336;
+ break;
+
+ case 4:
+ ypos = 143;
+ break;
+
+ case 6:
+ xpos = -16;
+ break;
+
+ default:
+ break;
+ }
+
+ moveCharacterToPos(0, facing, xpos, ypos);
+ }
+
+ for (int i = 0; i < ARRAYSIZE(_movieObjects); ++i)
+ _movieObjects[i]->close();
+
+ if (!brandonAlive) {
+ _scriptInterpreter->initScript(_scriptClick, _scriptClickData);
+ _scriptInterpreter->startScript(_scriptClick, 5);
+ while (_scriptInterpreter->validScript(_scriptClick))
+ _scriptInterpreter->runScript(_scriptClick);
+ }
+
+ memset(_entranceMouseCursorTracks, 0xFFFF, sizeof(uint16)*4);
+ _currentCharacter->sceneId = sceneId;
+
+ assert(sceneId < _roomTableSize);
+ assert(_roomTable[sceneId].nameIndex < _roomFilenameTableSize);
+
+ Room *currentRoom = &_roomTable[sceneId];
+
+ setupSceneResource(sceneId);
+
+ _currentRoom = sceneId;
+
+ int tableId = _roomTable[sceneId].nameIndex;
+ char fileNameBuffer[32];
+ strcpy(fileNameBuffer, _roomFilenameTable[tableId]);
+ strcat(fileNameBuffer, ".DAT");
+ _sprites->loadDat(fileNameBuffer, _sceneExits);
+ _sprites->setupSceneAnims();
+ _scriptInterpreter->unloadScript(_scriptClickData);
+ loadSceneMsc();
+
+ _walkBlockNorth = currentRoom->northExit;
+ _walkBlockEast = currentRoom->eastExit;
+ _walkBlockSouth = currentRoom->southExit;
+ _walkBlockWest = currentRoom->westExit;
+
+ if (_walkBlockNorth == 0xFFFF)
+ _screen->blockOutRegion(0, 0, 320, (_northExitHeight & 0xFF)+3);
+ if (_walkBlockEast == 0xFFFF)
+ _screen->blockOutRegion(312, 0, 8, 139);
+ if (_walkBlockSouth == 0xFFFF)
+ _screen->blockOutRegion(0, 135, 320, 8);
+ if (_walkBlockWest == 0xFFFF)
+ _screen->blockOutRegion(0, 0, 8, 139);
+
+ if (!brandonAlive)
+ updatePlayerItemsForScene();
+
+ startSceneScript(brandonAlive);
+ setupSceneItems();
+
+ initSceneData(facing, unk2, brandonAlive);
+
+ _loopFlag2 = 0;
+ _screen->showMouse();
+ if (!brandonAlive)
+ seq_poisonDeathNow(0);
+ updateMousePointer(true);
+ _changedScene = true;
+}
+
+void KyraEngine_v1::transcendScenes(int roomIndex, int roomName) {
+ debugC(9, kDebugLevelMain, "KyraEngine_v1::transcendScenes(%d, %d)", roomIndex, roomName);
+ assert(roomIndex < _roomTableSize);
+
+ if (_flags.isTalkie) {
+ char file[32];
+ assert(roomIndex < _roomTableSize);
+ int tableId = _roomTable[roomIndex].nameIndex;
+ assert(tableId < _roomFilenameTableSize);
+ strcpy(file, _roomFilenameTable[tableId]);
+ strcat(file, ".VRM");
+ _res->unloadPakFile(file);
+ }
+
+ _roomTable[roomIndex].nameIndex = roomName;
+ _unkScreenVar2 = 1;
+ _unkScreenVar3 = 1;
+ _unkScreenVar1 = 0;
+ _brandonPosX = _currentCharacter->x1;
+ _brandonPosY = _currentCharacter->y1;
+ enterNewScene(roomIndex, _currentCharacter->facing, 0, 0, 0);
+ _unkScreenVar1 = 1;
+ _unkScreenVar2 = 0;
+ _unkScreenVar3 = 0;
+}
+
+void KyraEngine_v1::setSceneFile(int roomIndex, int roomName) {
+ debugC(9, kDebugLevelMain, "KyraEngine_v1::setSceneFile(%d, %d)", roomIndex, roomName);
+ assert(roomIndex < _roomTableSize);
+ _roomTable[roomIndex].nameIndex = roomName;
+}
+
+void KyraEngine_v1::moveCharacterToPos(int character, int facing, int xpos, int ypos) {
+ debugC(9, kDebugLevelMain, "KyraEngine_v1::moveCharacterToPos(%d, %d, %d, %d)", character, facing, xpos, ypos);
+ Character *ch = &_characterList[character];
+ ch->facing = facing;
+ _screen->hideMouse();
+ xpos = (int16)(xpos & 0xFFFC);
+ ypos = (int16)(ypos & 0xFFFE);
+ _timer->disable(19);
+ _timer->disable(14);
+ _timer->disable(18);
+ uint32 nextFrame = 0;
+
+ switch (facing) {
+ case 0:
+ while (ypos < ch->y1) {
+ nextFrame = _timer->getDelay(5 + character) * _tickLength + _system->getMillis();
+ setCharacterPositionWithUpdate(character);
+ delayUntil(nextFrame, true);
+ }
+ break;
+
+ case 2:
+ while (ch->x1 < xpos) {
+ nextFrame = _timer->getDelay(5 + character) * _tickLength + _system->getMillis();
+ setCharacterPositionWithUpdate(character);
+ delayUntil(nextFrame, true);
+ }
+ break;
+
+ case 4:
+ while (ypos > ch->y1) {
+ nextFrame = _timer->getDelay(5 + character) * _tickLength + _system->getMillis();
+ setCharacterPositionWithUpdate(character);
+ delayUntil(nextFrame, true);
+ }
+ break;
+
+ case 6:
+ while (ch->x1 > xpos) {
+ nextFrame = _timer->getDelay(5 + character) * _tickLength + _system->getMillis();
+ setCharacterPositionWithUpdate(character);
+ delayUntil(nextFrame, true);
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ _timer->enable(19);
+ _timer->enable(14);
+ _timer->enable(18);
+ _screen->showMouse();
+}
+
+void KyraEngine_v1::setCharacterPositionWithUpdate(int character) {
+ debugC(9, kDebugLevelMain, "KyraEngine_v1::setCharacterPositionWithUpdate(%d)", character);
+ setCharacterPosition(character, 0);
+ _sprites->updateSceneAnims();
+ _timer->update();
+ _animator->updateAllObjectShapes();
+ updateTextFade();
+
+ if (_currentCharacter->sceneId == 210)
+ updateKyragemFading();
+}
+
+int KyraEngine_v1::setCharacterPosition(int character, int *facingTable) {
+ debugC(9, kDebugLevelMain, "KyraEngine_v1::setCharacterPosition(%d, %p)", character, (const void *)facingTable);
+
+ if (character == 0) {
+ _currentCharacter->x1 += _charXPosTable[_currentCharacter->facing];
+ _currentCharacter->y1 += _charYPosTable[_currentCharacter->facing];
+ setCharacterPositionHelper(0, facingTable);
+ return 1;
+ } else {
+ _characterList[character].x1 += _charXPosTable[_characterList[character].facing];
+ _characterList[character].y1 += _charYPosTable[_characterList[character].facing];
+ if (_characterList[character].sceneId == _currentCharacter->sceneId)
+ setCharacterPositionHelper(character, 0);
+ }
+ return 0;
+}
+
+void KyraEngine_v1::setCharacterPositionHelper(int character, int *facingTable) {
+ debugC(9, kDebugLevelMain, "KyraEngine_v1::setCharacterPositionHelper(%d, %p)", character, (const void *)facingTable);
+ Character *ch = &_characterList[character];
+ ++ch->currentAnimFrame;
+ int facing = ch->facing;
+ if (facingTable) {
+ if (*facingTable != *(facingTable - 1)) {
+ if (*(facingTable - 1) == *(facingTable + 1)) {
+ facing = getOppositeFacingDirection(*(facingTable - 1));
+ *facingTable = *(facingTable - 1);
+ }
+ }
+ }
+
+ static uint8 facingIsZero[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
+ static uint8 facingIsFour[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
+
+ if (facing == 0) {
+ ++facingIsZero[character];
+ } else {
+ bool resetTables = false;
+ if (facing != 7) {
+ if (facing - 1 != 0) {
+ if (facing != 4) {
+ if (facing == 3 || facing == 5) {
+ if (facingIsFour[character] > 2)
+ facing = 4;
+ resetTables = true;
+ }
+ } else {
+ ++facingIsFour[character];
+ }
+ } else {
+ if (facingIsZero[character] > 2)
+ facing = 0;
+ resetTables = true;
+ }
+ } else {
+ if (facingIsZero[character] > 2)
+ facing = 0;
+ resetTables = true;
+ }
+
+ if (resetTables) {
+ facingIsZero[character] = 0;
+ facingIsFour[character] = 0;
+ }
+ }
+
+ static const uint16 maxAnimationFrame[] = {
+ 0x000F, 0x0031, 0x0055, 0x0000, 0x0000, 0x0000,
+ 0x0008, 0x002A, 0x004E, 0x0000, 0x0000, 0x0000,
+ 0x0022, 0x0046, 0x006A, 0x0000, 0x0000, 0x0000,
+ 0x001D, 0x0041, 0x0065, 0x0000, 0x0000, 0x0000,
+ 0x001F, 0x0043, 0x0067, 0x0000, 0x0000, 0x0000,
+ 0x0028, 0x004C, 0x0070, 0x0000, 0x0000, 0x0000,
+ 0x0023, 0x0047, 0x006B, 0x0000, 0x0000, 0x0000
+ };
+
+ if (facing == 0) {
+ if (maxAnimationFrame[36+character] > ch->currentAnimFrame)
+ ch->currentAnimFrame = maxAnimationFrame[36+character];
+ if (maxAnimationFrame[30+character] < ch->currentAnimFrame)
+ ch->currentAnimFrame = maxAnimationFrame[36+character];
+ } else if (facing == 4) {
+ if (maxAnimationFrame[18+character] > ch->currentAnimFrame)
+ ch->currentAnimFrame = maxAnimationFrame[18+character];
+ if (maxAnimationFrame[12+character] < ch->currentAnimFrame)
+ ch->currentAnimFrame = maxAnimationFrame[18+character];
+ } else {
+ if (maxAnimationFrame[18+character] < ch->currentAnimFrame)
+ ch->currentAnimFrame = maxAnimationFrame[30+character];
+ if (maxAnimationFrame[character] == ch->currentAnimFrame)
+ ch->currentAnimFrame = maxAnimationFrame[6+character];
+ if (maxAnimationFrame[character] < ch->currentAnimFrame)
+ ch->currentAnimFrame = maxAnimationFrame[6+character]+2;
+ }
+
+ if (character == 0 && (_brandonStatusBit & 0x10))
+ ch->currentAnimFrame = 88;
+
+ _animator->animRefreshNPC(character);
+}
+
+void KyraEngine_v1::loadSceneMsc() {
+ assert(_currentCharacter->sceneId < _roomTableSize);
+ int tableId = _roomTable[_currentCharacter->sceneId].nameIndex;
+ assert(tableId < _roomFilenameTableSize);
+ char fileNameBuffer[32];
+ strcpy(fileNameBuffer, _roomFilenameTable[tableId]);
+ strcat(fileNameBuffer, ".MSC");
+ _screen->fillRect(0, 0, 319, 199, 0, 5);
+ _screen->loadBitmap(fileNameBuffer, 3, 5, 0);
+}
+
+void KyraEngine_v1::startSceneScript(int brandonAlive) {
+ debugC(9, kDebugLevelMain, "KyraEngine_v1::startSceneScript(%d)", brandonAlive);
+ assert(_currentCharacter->sceneId < _roomTableSize);
+ int tableId = _roomTable[_currentCharacter->sceneId].nameIndex;
+ assert(tableId < _roomFilenameTableSize);
+ char fileNameBuffer[32];
+ strcpy(fileNameBuffer, _roomFilenameTable[tableId]);
+ strcat(fileNameBuffer, ".CPS");
+ _screen->clearPage(3);
+ // FIXME: check this hack for amiga version
+ _screen->loadBitmap(fileNameBuffer, 3, 3, (_flags.platform == Common::kPlatformAmiga ? _screen->getPalette(0) : 0));
+ _sprites->loadSceneShapes();
+ _exitListPtr = 0;
+
+ _scaleMode = 1;
+ for (int i = 0; i < 145; ++i)
+ _scaleTable[i] = 256;
+
+ clearNoDropRects();
+ _scriptInterpreter->initScript(_scriptClick, _scriptClickData);
+ strcpy(fileNameBuffer, _roomFilenameTable[tableId]);
+ strcat(fileNameBuffer, ".EMC");
+ _scriptInterpreter->unloadScript(_scriptClickData);
+ _scriptInterpreter->loadScript(fileNameBuffer, _scriptClickData, &_opcodes);
+ _scriptInterpreter->startScript(_scriptClick, 0);
+ _scriptClick->regs[0] = _currentCharacter->sceneId;
+ _scriptClick->regs[7] = brandonAlive;
+
+ while (_scriptInterpreter->validScript(_scriptClick))
+ _scriptInterpreter->runScript(_scriptClick);
+}
+
+void KyraEngine_v1::initSceneData(int facing, int unk1, int brandonAlive) {
+ debugC(9, kDebugLevelMain, "KyraEngine_v1::initSceneData(%d, %d, %d)", facing, unk1, brandonAlive);
+
+ int16 xpos2 = 0;
+ int setFacing = 1;
+
+ int16 xpos = 0, ypos = 0;
+
+ if (_brandonPosX == -1 && _brandonPosY == -1) {
+ switch (facing + 1) {
+ case 0:
+ xpos = ypos = -1;
+ break;
+
+ case 1: case 2: case 8:
+ xpos = _sceneExits.southXPos;
+ ypos = _sceneExits.southYPos;
+ break;
+
+ case 3:
+ xpos = _sceneExits.westXPos;
+ ypos = _sceneExits.westYPos;
+ break;
+
+ case 4: case 5: case 6:
+ xpos = _sceneExits.northXPos;
+ ypos = _sceneExits.northYPos;
+ break;
+
+ case 7:
+ xpos = _sceneExits.eastXPos;
+ ypos = _sceneExits.eastYPos;
+ break;
+
+ default:
+ break;
+ }
+
+ if ((uint8)(_northExitHeight & 0xFF) + 2 >= ypos)
+ ypos = (_northExitHeight & 0xFF) + 4;
+ if (xpos >= 308)
+ xpos = 304;
+ if ((uint8)(_northExitHeight >> 8) - 2 <= ypos)
+ ypos = (_northExitHeight >> 8) - 4;
+ if (xpos <= 12)
+ xpos = 16;
+ }
+
+ if (_brandonPosX > -1)
+ xpos = _brandonPosX;
+ if (_brandonPosY > -1)
+ ypos = _brandonPosY;
+
+ int16 ypos2 = 0;
+ if (_brandonPosX > -1 && _brandonPosY > -1) {
+ switch (_currentCharacter->sceneId) {
+ case 1:
+ _currentCharacter->x1 = xpos;
+ _currentCharacter->x2 = xpos;
+ _currentCharacter->y1 = ypos;
+ _currentCharacter->y2 = ypos;
+ facing = 4;
+ xpos2 = 192;
+ ypos2 = 104;
+ setFacing = 0;
+ unk1 = 1;
+ break;
+
+ case 3:
+ _currentCharacter->x1 = xpos;
+ _currentCharacter->x2 = xpos;
+ _currentCharacter->y1 = ypos;
+ _currentCharacter->y2 = ypos;
+ facing = 2;
+ xpos2 = 204;
+ ypos2 = 94;
+ setFacing = 0;
+ unk1 = 1;
+ break;
+
+ case 26:
+ _currentCharacter->x1 = xpos;
+ _currentCharacter->x2 = xpos;
+ _currentCharacter->y1 = ypos;
+ _currentCharacter->y2 = ypos;
+ facing = 2;
+ xpos2 = 192;
+ ypos2 = 128;
+ setFacing = 0;
+ unk1 = 1;
+ break;
+
+ case 44:
+ _currentCharacter->x1 = xpos;
+ _currentCharacter->x2 = xpos;
+ _currentCharacter->y1 = ypos;
+ _currentCharacter->y2 = ypos;
+ facing = 6;
+ xpos2 = 156;
+ ypos2 = 96;
+ setFacing = 0;
+ unk1 = 1;
+ break;
+
+ case 37:
+ _currentCharacter->x1 = xpos;
+ _currentCharacter->x2 = xpos;
+ _currentCharacter->y1 = ypos;
+ _currentCharacter->y2 = ypos;
+ facing = 2;
+ xpos2 = 148;
+ ypos2 = 114;
+ setFacing = 0;
+ unk1 = 1;
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ _brandonPosX = _brandonPosY = -1;
+
+ if (unk1 && setFacing) {
+ ypos2 = ypos;
+ xpos2 = xpos;
+ switch (facing) {
+ case 0:
+ ypos = 142;
+ break;
+
+ case 2:
+ xpos = -16;
+ break;
+
+ case 4:
+ ypos = (uint8)(_northExitHeight & 0xFF) - 4;
+ break;
+
+ case 6:
+ xpos = 336;
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ xpos2 = (int16)(xpos2 & 0xFFFC);
+ ypos2 = (int16)(ypos2 & 0xFFFE);
+ xpos = (int16)(xpos & 0xFFFC);
+ ypos = (int16)(ypos & 0xFFFE);
+ _currentCharacter->facing = facing;
+ _currentCharacter->x1 = xpos;
+ _currentCharacter->x2 = xpos;
+ _currentCharacter->y1 = ypos;
+ _currentCharacter->y2 = ypos;
+
+ initSceneObjectList(brandonAlive);
+
+ if (unk1 && brandonAlive == 0)
+ moveCharacterToPos(0, facing, xpos2, ypos2);
+
+ _scriptClick->regs[4] = _itemInHand;
+ _scriptClick->regs[7] = brandonAlive;
+ _scriptInterpreter->startScript(_scriptClick, 3);
+ while (_scriptInterpreter->validScript(_scriptClick))
+ _scriptInterpreter->runScript(_scriptClick);
+}
+
+void KyraEngine_v1::initSceneObjectList(int brandonAlive) {
+ debugC(9, kDebugLevelMain, "KyraEngine_v1::initSceneObjectList(%d)", brandonAlive);
+ for (int i = 0; i < 28; ++i)
+ _animator->actors()[i].active = 0;
+
+ int startAnimFrame = 0;
+
+ AnimObject *curAnimState = _animator->actors();
+ curAnimState->active = 1;
+ curAnimState->drawY = _currentCharacter->y1;
+ curAnimState->sceneAnimPtr = _shapes[_currentCharacter->currentAnimFrame];
+ curAnimState->animFrameNumber = _currentCharacter->currentAnimFrame;
+ startAnimFrame = _currentCharacter->currentAnimFrame-7;
+ int xOffset = _defaultShapeTable[startAnimFrame].xOffset;
+ int yOffset = _defaultShapeTable[startAnimFrame].yOffset;
+
+ if (_scaleMode) {
+ curAnimState->x1 = _currentCharacter->x1;
+ curAnimState->y1 = _currentCharacter->y1;
+
+ _animator->_brandonScaleX = _scaleTable[_currentCharacter->y1];
+ _animator->_brandonScaleY = _scaleTable[_currentCharacter->y1];
+
+ curAnimState->x1 += (_animator->_brandonScaleX * xOffset) >> 8;
+ curAnimState->y1 += (_animator->_brandonScaleY * yOffset) >> 8;
+ } else {
+ curAnimState->x1 = _currentCharacter->x1 + xOffset;
+ curAnimState->y1 = _currentCharacter->y1 + yOffset;
+ }
+
+ curAnimState->x2 = curAnimState->x1;
+ curAnimState->y2 = curAnimState->y1;
+ curAnimState->refreshFlag = 1;
+ curAnimState->bkgdChangeFlag = 1;
+ _animator->clearQueue();
+ _animator->addObjectToQueue(curAnimState);
+
+ int listAdded = 0;
+ int addedObjects = 1;
+
+ for (int i = 1; i < 5; ++i) {
+ Character *ch = &_characterList[i];
+ curAnimState = &_animator->actors()[addedObjects];
+ if (ch->sceneId != _currentCharacter->sceneId) {
+ curAnimState->active = 0;
+ curAnimState->refreshFlag = 0;
+ curAnimState->bkgdChangeFlag = 0;
+ ++addedObjects;
+ continue;
+ }
+
+ curAnimState->drawY = ch->y1;
+ curAnimState->sceneAnimPtr = _shapes[ch->currentAnimFrame];
+ curAnimState->animFrameNumber = ch->currentAnimFrame;
+ startAnimFrame = ch->currentAnimFrame-7;
+ xOffset = _defaultShapeTable[startAnimFrame].xOffset;
+ yOffset = _defaultShapeTable[startAnimFrame].yOffset;
+ if (_scaleMode) {
+ curAnimState->x1 = ch->x1;
+ curAnimState->y1 = ch->y1;
+
+ _animator->_brandonScaleX = _scaleTable[ch->y1];
+ _animator->_brandonScaleY = _scaleTable[ch->y1];
+
+ curAnimState->x1 += (_animator->_brandonScaleX * xOffset) >> 8;
+ curAnimState->y1 += (_animator->_brandonScaleY * yOffset) >> 8;
+ } else {
+ curAnimState->x1 = ch->x1 + xOffset;
+ curAnimState->y1 = ch->y1 + yOffset;
+ }
+ curAnimState->x2 = curAnimState->x1;
+ curAnimState->y2 = curAnimState->y1;
+ curAnimState->active = 1;
+ curAnimState->refreshFlag = 1;
+ curAnimState->bkgdChangeFlag = 1;
+
+ if (ch->facing >= 1 && ch->facing <= 3)
+ curAnimState->flags |= 1;
+ else if (ch->facing >= 5 && ch->facing <= 7)
+ curAnimState->flags &= 0xFFFFFFFE;
+
+ _animator->addObjectToQueue(curAnimState);
+
+ ++addedObjects;
+ ++listAdded;
+ if (listAdded < 2)
+ i = 5;
+ }
+
+ for (int i = 0; i < 11; ++i) {
+ curAnimState = &_animator->sprites()[i];
+
+ if (_sprites->_anims[i].play) {
+ curAnimState->active = 1;
+ curAnimState->refreshFlag = 1;
+ curAnimState->bkgdChangeFlag = 1;
+ } else {
+ curAnimState->active = 0;
+ curAnimState->refreshFlag = 0;
+ curAnimState->bkgdChangeFlag = 0;
+ }
+ curAnimState->height = _sprites->_anims[i].height;
+ curAnimState->height2 = _sprites->_anims[i].height2;
+ curAnimState->width = _sprites->_anims[i].width + 1;
+ curAnimState->width2 = _sprites->_anims[i].width2;
+ curAnimState->drawY = _sprites->_anims[i].drawY;
+ curAnimState->x1 = curAnimState->x2 = _sprites->_anims[i].x;
+ curAnimState->y1 = curAnimState->y2 = _sprites->_anims[i].y;
+ curAnimState->background = _sprites->_anims[i].background;
+ curAnimState->sceneAnimPtr = _sprites->_sceneShapes[_sprites->_anims[i].sprite];
+
+ curAnimState->disable = _sprites->_anims[i].disable;
+
+ if (_sprites->_anims[i].unk2)
+ curAnimState->flags = 0x800;
+ else
+ curAnimState->flags = 0;
+
+ if (_sprites->_anims[i].flipX)
+ curAnimState->flags |= 0x1;
+
+ _animator->addObjectToQueue(curAnimState);
+ }
+
+ for (int i = 0; i < 12; ++i) {
+ curAnimState = &_animator->items()[i];
+ Room *curRoom = &_roomTable[_currentCharacter->sceneId];
+ byte curItem = curRoom->itemsTable[i];
+ if (curItem != 0xFF) {
+ curAnimState->drawY = curRoom->itemsYPos[i];
+ curAnimState->sceneAnimPtr = _shapes[216+curItem];
+ curAnimState->animFrameNumber = (int16)0xFFFF;
+ curAnimState->y1 = curRoom->itemsYPos[i];
+ curAnimState->x1 = curRoom->itemsXPos[i];
+
+ curAnimState->x1 -= (_animator->fetchAnimWidth(curAnimState->sceneAnimPtr, _scaleTable[curAnimState->drawY])) >> 1;
+ curAnimState->y1 -= _animator->fetchAnimHeight(curAnimState->sceneAnimPtr, _scaleTable[curAnimState->drawY]);
+
+ curAnimState->x2 = curAnimState->x1;
+ curAnimState->y2 = curAnimState->y1;
+
+ curAnimState->active = 1;
+ curAnimState->refreshFlag = 1;
+ curAnimState->bkgdChangeFlag = 1;
+
+ _animator->addObjectToQueue(curAnimState);
+ } else {
+ curAnimState->active = 0;
+ curAnimState->refreshFlag = 0;
+ curAnimState->bkgdChangeFlag = 0;
+ }
+ }
+
+ _animator->preserveAnyChangedBackgrounds();
+ curAnimState = _animator->actors();
+ curAnimState->bkgdChangeFlag = 1;
+ curAnimState->refreshFlag = 1;
+ for (int i = 1; i < 28; ++i) {
+ curAnimState = &_animator->objects()[i];
+ if (curAnimState->active) {
+ curAnimState->bkgdChangeFlag = 1;
+ curAnimState->refreshFlag = 1;
+ }
+ }
+ _animator->restoreAllObjectBackgrounds();
+ _animator->preserveAnyChangedBackgrounds();
+ _animator->prepDrawAllObjects();
+ initSceneScreen(brandonAlive);
+ _animator->copyChangedObjectsForward(0);
+}
+
+void KyraEngine_v1::initSceneScreen(int brandonAlive) {
+ if (_flags.platform == Common::kPlatformAmiga) {
+ if (_unkScreenVar1 && !queryGameFlag(0xF0)) {
+ memset(_screen->getPalette(2), 0, 32*3);
+ if (_currentCharacter->sceneId != 117 || !queryGameFlag(0xB3))
+ _screen->setScreenPalette(_screen->getPalette(2));
+ }
+
+ if (_unkScreenVar2 == 1)
+ _screen->shuffleScreen(8, 8, 304, 128, 2, 0, _unkScreenVar3, false);
+ else
+ _screen->copyRegion(8, 8, 8, 8, 304, 128, 2, 0);
+
+ if (_unkScreenVar1 && !queryGameFlag(0xA0)) {
+ if (_currentCharacter->sceneId == 45 && _paletteChanged)
+ memcpy(_screen->getPalette(0) + 12*3, _screen->getPalette(4) + 12*3, 2);
+
+ if (_currentCharacter->sceneId >= 229 && _currentCharacter->sceneId <= 245 && (_brandonStatusBit & 1))
+ memcpy(_screen->getPalette(0), _screen->getPalette(0) + 320*3, 64);
+
+ _screen->setScreenPalette(_screen->getPalette(0));
+ }
+ } else {
+ if (_unkScreenVar1 && !queryGameFlag(0xA0)) {
+ for (int i = 0; i < 60; ++i) {
+ uint16 col = _screen->getPalette(0)[684+i];
+ col += _screen->getPalette(1)[684+i] << 1;
+ col >>= 2;
+ _screen->getPalette(0)[684+i] = col;
+ }
+ _screen->setScreenPalette(_screen->getPalette(0));
+ }
+
+ if (_unkScreenVar2 == 1)
+ _screen->shuffleScreen(8, 8, 304, 128, 2, 0, _unkScreenVar3, false);
+ else
+ _screen->copyRegion(8, 8, 8, 8, 304, 128, 2, 0);
+
+ if (_unkScreenVar1 && _paletteChanged) {
+ if (!queryGameFlag(0xA0)) {
+ memcpy(_screen->getPalette(0) + 684, _screen->getPalette(1) + 684, 60);
+ _screen->setScreenPalette(_screen->getPalette(0));
+ } else {
+ memset(_screen->getPalette(0), 0, 768);
+ }
+ }
+ }
+
+ // really call this here?
+ _screen->updateScreen();
+
+ if (!_scriptInterpreter->startScript(_scriptClick, 2))
+ error("Could not start script function 2 of scene script");
+
+ _scriptClick->regs[7] = brandonAlive;
+
+ while (_scriptInterpreter->validScript(_scriptClick))
+ _scriptInterpreter->runScript(_scriptClick);
+
+ setTextFadeTimerCountdown(-1);
+ if (_currentCharacter->sceneId == 210) {
+ if (_itemInHand != -1)
+ magicOutMouseItem(2, -1);
+
+ _screen->hideMouse();
+ for (int i = 0; i < 10; ++i) {
+ if (_currentCharacter->inventoryItems[i] != 0xFF)
+ magicOutMouseItem(2, i);
+ }
+ _screen->showMouse();
+ }
+}
+
+int KyraEngine_v1::handleSceneChange(int xpos, int ypos, int unk1, int frameReset) {
+ debugC(9, kDebugLevelMain, "KyraEngine_v1::handleSceneChange(%d, %d, %d, %d)", xpos, ypos, unk1, frameReset);
+ if (queryGameFlag(0xEF))
+ unk1 = 0;
+
+ int sceneId = _currentCharacter->sceneId;
+ _pathfinderFlag = 0;
+
+ if (xpos < 12) {
+ if (_roomTable[sceneId].westExit != 0xFFFF) {
+ xpos = 12;
+ ypos = _sceneExits.westYPos;
+ _pathfinderFlag = 7;
+ }
+ } else if (xpos >= 308) {
+ if (_roomTable[sceneId].eastExit != 0xFFFF) {
+ xpos = 307;
+ ypos = _sceneExits.eastYPos;
+ _pathfinderFlag = 13;
+ }
+ }
+
+ if (ypos <= (_northExitHeight&0xFF)+2) {
+ if (_roomTable[sceneId].northExit != 0xFFFF) {
+ xpos = _sceneExits.northXPos;
+ ypos = _northExitHeight & 0xFF;
+ _pathfinderFlag = 14;
+ }
+ } else if (ypos >= 136) {
+ if (_roomTable[sceneId].southExit != 0xFFFF) {
+ xpos = _sceneExits.southXPos;
+ ypos = 136;
+ _pathfinderFlag = 11;
+ }
+ }
+
+ int temp = xpos - _currentCharacter->x1;
+ if (ABS(temp) < 4) {
+ temp = ypos - _currentCharacter->y1;
+ if (ABS(temp) < 2)
+ return 0;
+ }
+
+ int x = (int16)(_currentCharacter->x1 & 0xFFFC);
+ int y = (int16)(_currentCharacter->y1 & 0xFFFE);
+ xpos = (int16)(xpos & 0xFFFC);
+ ypos = (int16)(ypos & 0xFFFE);
+
+ int ret = findWay(x, y, xpos, ypos, _movFacingTable, 150);
+ _pathfinderFlag = 0;
+
+ if (ret >= _lastFindWayRet)
+ _lastFindWayRet = ret;
+
+ if (ret == 0x7D00 || ret == 0)
+ return 0;
+
+ return processSceneChange(_movFacingTable, unk1, frameReset);
+}
+
+int KyraEngine_v1::processSceneChange(int *table, int unk1, int frameReset) {
+ debugC(9, kDebugLevelMain, "KyraEngine_v1::processSceneChange(%p, %d, %d)", (const void *)table, unk1, frameReset);
+ if (queryGameFlag(0xEF))
+ unk1 = 0;
+
+ int *tableStart = table;
+ _sceneChangeState = 0;
+ _loopFlag2 = 0;
+ bool running = true;
+ int returnValue = 0;
+ uint32 nextFrame = 0;
+ _abortWalkFlag = false;
+ _mousePressFlag = false;
+
+ while (running) {
+ if (_abortWalkFlag) {
+ *table = 8;
+ _currentCharacter->currentAnimFrame = 7;
+ _animator->animRefreshNPC(0);
+ _animator->updateAllObjectShapes();
+ processInput();
+ return 0;
+ }
+ bool forceContinue = false;
+ switch (*table) {
+ case 0: case 1: case 2:
+ case 3: case 4: case 5:
+ case 6: case 7:
+ _currentCharacter->facing = getOppositeFacingDirection(*table);
+ break;
+
+ case 8:
+ forceContinue = true;
+ running = false;
+ break;
+
+ default:
+ ++table;
+ forceContinue = true;
+ break;
+ }
+
+ returnValue = changeScene(_currentCharacter->facing);
+ if (returnValue) {
+ running = false;
+ _abortWalkFlag = false;
+ }
+
+ if (unk1) {
+ if (_mousePressFlag) {
+ running = false;
+ _sceneChangeState = 1;
+ }
+ }
+
+ if (forceContinue || !running)
+ continue;
+
+ int temp = 0;
+ if (table == tableStart || table[1] == 8)
+ temp = setCharacterPosition(0, 0);
+ else
+ temp = setCharacterPosition(0, table);
+
+ if (temp)
+ ++table;
+
+ nextFrame = _timer->getDelay(5) * _tickLength + _system->getMillis();
+ while (_system->getMillis() < nextFrame) {
+ _timer->update();
+
+ if (_currentCharacter->sceneId == 210) {
+ updateKyragemFading();
+ if (seq_playEnd() || _beadStateVar == 4 || _beadStateVar == 5) {
+ *table = 8;
+ running = false;
+ break;
+ }
+ }
+
+ if ((nextFrame - _system->getMillis()) >= 10)
+ delay(10, true);
+ }
+ }
+
+ if (frameReset && !(_brandonStatusBit & 2))
+ _currentCharacter->currentAnimFrame = 7;
+
+ _animator->animRefreshNPC(0);
+ _animator->updateAllObjectShapes();
+ return returnValue;
+}
+
+int KyraEngine_v1::changeScene(int facing) {
+ debugC(9, kDebugLevelMain, "KyraEngine_v1::changeScene(%d)", facing);
+ if (queryGameFlag(0xEF)) {
+ if (_currentCharacter->sceneId == 5)
+ return 0;
+ }
+
+ int xpos = _charXPosTable[facing] + _currentCharacter->x1;
+ int ypos = _charYPosTable[facing] + _currentCharacter->y1;
+
+ if (xpos >= 12 && xpos <= 308) {
+ if (!lineIsPassable(xpos, ypos))
+ return false;
+ }
+
+ if (_exitListPtr) {
+ int16 *ptr = _exitListPtr;
+ // this loop should be only entered one time, seems to be some hack in the original
+ while (true) {
+ if (*ptr == -1)
+ break;
+
+ if (*ptr > _currentCharacter->x1 || _currentCharacter->y1 < ptr[1] || _currentCharacter->x1 > ptr[2] || _currentCharacter->y1 > ptr[3]) {
+ ptr += 10;
+ break;
+ }
+
+ _brandonPosX = ptr[6];
+ _brandonPosY = ptr[7];
+ uint16 sceneId = ptr[5];
+ facing = ptr[4];
+ int unk1 = ptr[8];
+ int unk2 = ptr[9];
+
+ if (sceneId == 0xFFFF) {
+ switch (facing) {
+ case 0:
+ sceneId = _roomTable[_currentCharacter->sceneId].northExit;
+ break;
+
+ case 2:
+ sceneId = _roomTable[_currentCharacter->sceneId].eastExit;
+ break;
+
+ case 4:
+ sceneId = _roomTable[_currentCharacter->sceneId].southExit;
+ break;
+
+ case 6:
+ sceneId = _roomTable[_currentCharacter->sceneId].westExit;
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ _currentCharacter->facing = facing;
+ _animator->animRefreshNPC(0);
+ _animator->updateAllObjectShapes();
+ enterNewScene(sceneId, facing, unk1, unk2, 0);
+ resetGameFlag(0xEE);
+ return 1;
+ }
+ }
+
+ int returnValue = 0;
+ facing = 0;
+
+ if ((_northExitHeight & 0xFF) + 2 >= ypos || (_northExitHeight & 0xFF) + 2 >= _currentCharacter->y1) {
+ facing = 0;
+ returnValue = 1;
+ }
+
+ if (xpos >= 308 || (_currentCharacter->x1 + 4) >= 308) {
+ facing = 2;
+ returnValue = 1;
+ }
+
+ if (((_northExitHeight >> 8) & 0xFF) - 2 < ypos || ((_northExitHeight >> 8) & 0xFF) - 2 < _currentCharacter->y1) {
+ facing = 4;
+ returnValue = 1;
+ }
+
+ if (xpos <= 12 || _currentCharacter->y1 <= 12) {
+ facing = 6;
+ returnValue = 1;
+ }
+
+ if (!returnValue)
+ return 0;
+
+ uint16 sceneId = 0xFFFF;
+ switch (facing) {
+ case 0:
+ sceneId = _roomTable[_currentCharacter->sceneId].northExit;
+ break;
+
+ case 2:
+ sceneId = _roomTable[_currentCharacter->sceneId].eastExit;
+ break;
+
+ case 4:
+ sceneId = _roomTable[_currentCharacter->sceneId].southExit;
+ break;
+
+ default:
+ sceneId = _roomTable[_currentCharacter->sceneId].westExit;
+ break;
+ }
+
+ if (sceneId == 0xFFFF)
+ return 0;
+
+ enterNewScene(sceneId, facing, 1, 1, 0);
+ return returnValue;
+}
+
+void KyraEngine_v1::setCharactersInDefaultScene() {
+ static const uint32 defaultSceneTable[][4] = {
+ { 0xFFFF, 0x0004, 0x0003, 0xFFFF },
+ { 0xFFFF, 0x0022, 0xFFFF, 0x0000 },
+ { 0xFFFF, 0x001D, 0x0021, 0xFFFF },
+ { 0xFFFF, 0x0000, 0x0000, 0xFFFF }
+ };
+
+ for (int i = 1; i < 5; ++i) {
+ Character *cur = &_characterList[i];
+ //cur->field_20 = 0;
+
+ const uint32 *curTable = defaultSceneTable[i-1];
+ cur->sceneId = curTable[0];
+
+ if (cur->sceneId == _currentCharacter->sceneId)
+ //++cur->field_20;
+ cur->sceneId = curTable[1/*cur->field_20*/];
+
+ //cur->field_23 = curTable[cur->field_20+1];
+ }
+}
+
+void KyraEngine_v1::setCharactersPositions(int character) {
+ static uint16 initXPosTable[] = {
+ 0x3200, 0x0024, 0x2230, 0x2F00, 0x0020, 0x002B,
+ 0x00CA, 0x00F0, 0x0082, 0x00A2, 0x0042
+ };
+ static uint8 initYPosTable[] = {
+ 0x00, 0xA2, 0x00, 0x42, 0x00,
+ 0x67, 0x67, 0x60, 0x5A, 0x71,
+ 0x76
+ };
+
+ assert(character < ARRAYSIZE(initXPosTable));
+ Character *edit = &_characterList[character];
+ edit->x1 = edit->x2 = initXPosTable[character];
+ edit->y1 = edit->y2 = initYPosTable[character];
+}
+
+#pragma mark -
+#pragma mark - Pathfinder
+#pragma mark -
+
+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);
+ return getMoveTableSize(moveTable);
+}
+
+bool KyraEngine_v1::lineIsPassable(int x, int y) {
+ debugC(9, kDebugLevelMain, "KyraEngine_v1::lineIsPassable(%d, %d)", x, y);
+ if (queryGameFlag(0xEF)) {
+ if (_currentCharacter->sceneId == 5)
+ return true;
+ }
+
+ if (_pathfinderFlag & 2) {
+ if (x >= 312)
+ return false;
+ }
+
+ if (_pathfinderFlag & 4) {
+ if (y >= 136)
+ return false;
+ }
+
+ if (_pathfinderFlag & 8) {
+ if (x < 8)
+ return false;
+ }
+
+ if (_pathfinderFlag2) {
+ if (x <= 8 || x >= 312)
+ return true;
+ if (y < (_northExitHeight & 0xFF) || y > 135)
+ return true;
+ }
+
+ if (y > 137)
+ return false;
+
+ if (y < 0)
+ y = 0;
+
+ int ypos = 8;
+ if (_scaleMode) {
+ ypos = (_scaleTable[y] >> 5) + 1;
+ if (8 < ypos)
+ ypos = 8;
+ }
+
+ x -= (ypos >> 1);
+
+ int xpos = x;
+ int xtemp = xpos + ypos - 1;
+ if (x < 0)
+ xpos = 0;
+
+ if (xtemp > 319)
+ xtemp = 319;
+
+ for (; xpos < xtemp; ++xpos) {
+ if (!_screen->getShapeFlag1(xpos, y))
+ return false;
+ }
+ return true;
+}
+
+#pragma mark -
+
+void KyraEngine_v1::setupSceneResource(int sceneId) {
+ debugC(9, kDebugLevelMain, "KyraEngine_v1::setupSceneResource(%d)", sceneId);
+ if (!_flags.isTalkie)
+ return;
+
+ if (_currentRoom != 0xFFFF) {
+ assert(_currentRoom < _roomTableSize);
+ int tableId = _roomTable[_currentRoom].nameIndex;
+ assert(tableId < _roomFilenameTableSize);
+
+ // unload our old room
+ char file[64];
+ strcpy(file, _roomFilenameTable[tableId]);
+ strcat(file, ".VRM");
+ _res->unloadPakFile(file);
+
+ strcpy(file, _roomFilenameTable[tableId]);
+ strcat(file, ".PAK");
+ _res->unloadPakFile(file);
+
+ strcpy(file, _roomFilenameTable[tableId]);
+ strcat(file, ".APK");
+ _res->unloadPakFile(file);
+ }
+
+ assert(sceneId < _roomTableSize);
+ int tableId = _roomTable[sceneId].nameIndex;
+ assert(tableId < _roomFilenameTableSize);
+
+ // load our new room
+ char file[64];
+ strcpy(file, _roomFilenameTable[tableId]);
+ strcat(file, ".VRM");
+ if (Common::File::exists(file))
+ _res->loadPakFile(file);
+
+ strcpy(file, _roomFilenameTable[tableId]);
+ strcat(file, ".PAK");
+ if (Common::File::exists(file))
+ _res->loadPakFile(file);
+
+ strcpy(file, _roomFilenameTable[tableId]);
+ strcat(file, ".APK");
+ if (Common::File::exists(file))
+ _res->loadPakFile(file);
+}
+
+} // end of namespace Kyra
+
diff --git a/engines/kyra/scene_v2.cpp b/engines/kyra/scene_v2.cpp
new file mode 100644
index 0000000000..7863fa6638
--- /dev/null
+++ b/engines/kyra/scene_v2.cpp
@@ -0,0 +1,867 @@
+/* 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 "kyra/kyra_v2.h"
+#include "kyra/screen_v2.h"
+#include "kyra/wsamovie.h"
+
+#include "common/func.h"
+
+namespace Kyra {
+
+void KyraEngine_v2::enterNewScene(uint16 newScene, int facing, int unk1, int unk2, int unk3) {
+ // XXX
+ _screen->hideMouse();
+
+ if (!unk3) {
+ //updateSpecialItems();
+ //displayInvWsaLastFrame();
+ }
+
+ if (unk1) {
+ int x = _mainCharacter.x1;
+ int y = _mainCharacter.y1;
+
+ switch (facing) {
+ case 0:
+ y -= 6;
+ break;
+
+ case 2:
+ x = 335;
+ break;
+
+ case 4:
+ y = 147;
+ break;
+
+ case 6:
+ x = -16;
+ break;
+
+ default:
+ break;
+ }
+
+ moveCharacter(facing, x, y);
+ }
+
+ //XXX sound
+
+ _unkFlag1 = false;
+
+ if (!unk3) {
+ _scriptInterpreter->initScript(&_sceneScriptState, &_sceneScriptData);
+ _scriptInterpreter->startScript(&_sceneScriptState, 5);
+ while (_scriptInterpreter->validScript(&_sceneScriptState))
+ _scriptInterpreter->runScript(&_sceneScriptState);
+ }
+
+ Common::for_each(_wsaSlots, _wsaSlots+ARRAYSIZE(_wsaSlots), Common::mem_fun(&WSAMovieV2::close));
+ _specialExitCount = 0;
+ memset(_specialExitTable, -1, sizeof(_specialExitTable));
+
+ _mainCharacter.sceneId = newScene;
+ _sceneList[newScene].flags &= ~1;
+ loadScenePal();
+ unloadScene();
+ loadSceneMsc();
+
+ SceneDesc &scene = _sceneList[newScene];
+ _sceneExit1 = scene.exit1;
+ _sceneExit2 = scene.exit2;
+ _sceneExit3 = scene.exit3;
+ _sceneExit4 = scene.exit4;
+
+ //XXX sound
+
+ startSceneScript(unk3);
+
+ if (_overwriteSceneFacing) {
+ facing = _mainCharacter.facing;
+ _overwriteSceneFacing = false;
+ }
+
+ enterNewSceneUnk1(facing, unk2, unk3);
+
+ setTimer1DelaySecs(-1);
+ _sceneScriptState.regs[3] = 1;
+ enterNewSceneUnk2(unk3);
+ _screen->showMouse();
+ _unk5 = 0;
+ //setNextIdleAnimTimer();
+}
+
+void KyraEngine_v2::enterNewSceneUnk1(int facing, int unk1, int unk2) {
+ int x = 0, y = 0;
+ int x2 = 0, y2 = 0;
+ bool needProc = true;
+
+ if (_mainCharX == -1 && _mainCharY == -1) {
+ switch (facing+1) {
+ case 1: case 2: case 8:
+ x2 = _sceneEnterX3;
+ y2 = _sceneEnterY3;
+ break;
+
+ case 3:
+ x2 = _sceneEnterX4;
+ y2 = _sceneEnterY4;
+ break;
+
+ case 4: case 5: case 6:
+ x2 = _sceneEnterX1;
+ y2 = _sceneEnterY1;
+ break;
+
+ case 7:
+ x2 = _sceneEnterX2;
+ y2 = _sceneEnterY2;
+ break;
+
+ default:
+ x2 = y2 = -1;
+ break;
+ }
+
+ if (x2 >= 316)
+ x2 = 312;
+ if (y2 >= 141)
+ y2 = 139;
+ if (x2 <= 4)
+ x2 = 8;
+ }
+
+ if (_mainCharX >= 0) {
+ x = x2 = _mainCharX;
+ needProc = false;
+ }
+
+ if (_mainCharY >= 0) {
+ y = y2 = _mainCharY;
+ needProc = false;
+ }
+
+ _mainCharX = _mainCharY = -1;
+
+ if (unk1 && needProc) {
+ x = x2;
+ y = y2;
+
+ switch (facing) {
+ case 0:
+ y2 = 147;
+ break;
+
+ case 2:
+ x2 = -16;
+ break;
+
+ case 4:
+ y2 = y - 4;
+ break;
+
+ case 6:
+ x2 = 335;
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ x2 &= ~3;
+ x &= ~3;
+ y2 &= ~1;
+ y &= ~1;
+
+ _mainCharacter.facing = facing;
+ _mainCharacter.x1 = _mainCharacter.x2 = x2;
+ _mainCharacter.y1 = _mainCharacter.y2 = y2;
+ initSceneAnims(unk2);
+
+ if (!unk2) {
+ //XXX sound
+ }
+
+ if (unk1 && !unk2 && _mainCharacter.animFrame != 32)
+ moveCharacter(facing, x, y);
+}
+
+void KyraEngine_v2::enterNewSceneUnk2(int unk1) {
+ _unk3 = -1;
+
+ if (_mainCharX == -1 && _mainCharY == -1 && _mainCharacter.sceneId != 61 &&
+ !queryGameFlag(0x1F1) && !queryGameFlag(0x192) && !queryGameFlag(0x193) &&
+ _mainCharacter.sceneId != 70 && !queryGameFlag(0x159) && _mainCharacter.sceneId != 37) {
+ _mainCharacter.animFrame = _characterFrameTable[_mainCharacter.facing];
+ updateCharacterAnim(0);
+ refreshAnimObjectsIfNeed();
+ }
+
+ if (!unk1) {
+ runSceneScript4(0);
+ //XXX sub_27158
+ }
+
+ _unk4 = 0;
+ _unk3 = -1;
+}
+
+int KyraEngine_v2::trySceneChange(int *moveTable, int unk1, int updateChar) {
+ bool running = true;
+ bool unkFlag = false;
+ int8 updateType = -1;
+ int changedScene = 0;
+ const int *moveTableStart = moveTable;
+ _unk4 = 0;
+ while (running) {
+ if (*moveTable >= 0 && *moveTable <= 7) {
+ _mainCharacter.facing = getOppositeFacingDirection(*moveTable);
+ unkFlag = true;
+ } else {
+ if (*moveTable == 8) {
+ running = false;
+ } else {
+ ++moveTable;
+ unkFlag = false;
+ }
+ }
+
+ if (checkSceneChange()) {
+ running = false;
+ changedScene = 1;
+ }
+
+ if (unk1) {
+ //XXX
+ }
+
+ if (!unkFlag || !running)
+ continue;
+
+ int ret = 0;
+ if (moveTable == moveTableStart || moveTable[1] == 8)
+ ret = updateCharPos(0);
+ else
+ ret = updateCharPos(moveTable);
+
+ if (ret)
+ ++moveTable;
+
+ ++updateType;
+ if (!updateType) {
+ update();
+ } else if (updateType == 1) {
+ refreshAnimObjectsIfNeed();
+ updateType = -1;
+ }
+ }
+
+ if (updateChar)
+ _mainCharacter.animFrame = _characterFrameTable[_mainCharacter.facing];
+
+ updateCharacterAnim(0);
+ refreshAnimObjectsIfNeed();
+
+ if (!changedScene && !_unk4) {
+ //XXX
+ }
+ return changedScene;
+}
+
+int KyraEngine_v2::checkSceneChange() {
+ SceneDesc &curScene = _sceneList[_mainCharacter.sceneId];
+ int charX = _mainCharacter.x1, charY = _mainCharacter.y1;
+ int facing = 0;
+ int process = 0;
+
+ if (_screen->getLayer(charX, charY) == 1 && _unk3 == -6) {
+ facing = 0;
+ process = 1;
+ } else if (charX >= 316 && _unk3 == -5) {
+ facing = 2;
+ process = 1;
+ } else if (charY >= 142 && _unk3 == -4) {
+ facing = 4;
+ process = 1;
+ } else if (charX <= 4 && _unk3 == -3) {
+ facing = 6;
+ process = 1;
+ }
+
+ if (!process)
+ return 0;
+
+ uint16 newScene = 0xFFFF;
+ switch (facing) {
+ case 0:
+ newScene = curScene.exit1;
+ break;
+
+ case 2:
+ newScene = curScene.exit2;
+ break;
+
+ case 4:
+ newScene = curScene.exit3;
+ break;
+
+ case 6:
+ newScene = curScene.exit4;
+ break;
+
+ default:
+ newScene = _mainCharacter.sceneId;
+ break;
+ }
+
+ if (newScene == 0xFFFF)
+ return 0;
+
+ enterNewScene(newScene, facing, 1, 1, 0);
+ return 1;
+}
+
+void KyraEngine_v2::unloadScene() {
+ _scriptInterpreter->unloadScript(&_sceneScriptData);
+ freeSceneShapePtrs();
+ freeSceneAnims();
+}
+
+void KyraEngine_v2::loadScenePal() {
+ uint16 sceneId = _mainCharacter.sceneId;
+ memcpy(_screen->getPalette(1), _screen->getPalette(0), 768);
+
+ char filename[14];
+ strcpy(filename, _sceneList[sceneId].filename);
+ strcat(filename, ".COL");
+ _screen->loadBitmap(filename, 3, 3, 0);
+ memcpy(_screen->getPalette(1), _screen->getCPagePtr(3), 384);
+ memset(_screen->getPalette(1), 0, 3);
+ memcpy(_scenePal, _screen->getCPagePtr(3)+336, 432);
+}
+
+void KyraEngine_v2::loadSceneMsc() {
+ uint16 sceneId = _mainCharacter.sceneId;
+ char filename[14];
+ strcpy(filename, _sceneList[sceneId].filename);
+ strcat(filename, ".MSC");
+ _screen->loadBitmap(filename, 3, 5, 0);
+}
+
+void KyraEngine_v2::startSceneScript(int unk1) {
+ uint16 sceneId = _mainCharacter.sceneId;
+ char filename[14];
+
+ strcpy(filename, _sceneList[sceneId].filename);
+ if (sceneId == 68 && (queryGameFlag(0x1BC) || queryGameFlag(0x1DC)))
+ strcpy(filename, "DOORX");
+ strcat(filename, ".CPS");
+
+ _screen->loadBitmap(filename, 3, 3, 0);
+ resetScaleTable();
+ _useCharPal = false;
+ memset(_charPalTable, 0, sizeof(_charPalTable));
+ //XXX _unkTable33
+ memset(_specialSceneScriptState, 0, sizeof(_specialSceneScriptState));
+
+ _sceneEnterX1 = 160;
+ _sceneEnterY1 = 0;
+ _sceneEnterX2 = 296;
+ _sceneEnterY2 = 72;
+ _sceneEnterX3 = 160;
+ _sceneEnterY3 = 128;
+ _sceneEnterX4 = 24;
+ _sceneEnterY4 = 72;
+
+ _sceneCommentString = "Undefined scene comment string!";
+ _scriptInterpreter->initScript(&_sceneScriptState, &_sceneScriptData);
+
+ strcpy(filename, _sceneList[sceneId].filename);
+ strcat(filename, ".");
+ strcat(filename, _scriptLangExt[_lang]);
+
+ assert(_res->getFileSize(filename));
+ _scriptInterpreter->loadScript(filename, &_sceneScriptData, &_opcodes);
+ runSceneScript7();
+
+ _scriptInterpreter->startScript(&_sceneScriptState, 0);
+ _sceneScriptState.regs[0] = sceneId;
+ _sceneScriptState.regs[5] = unk1;
+ while (_scriptInterpreter->validScript(&_sceneScriptState))
+ _scriptInterpreter->runScript(&_sceneScriptState);
+
+ memcpy(_gamePlayBuffer, _screen->getCPagePtr(3), 46080);
+
+ for (int i = 0; i < 10; ++i) {
+ _scriptInterpreter->initScript(&_sceneSpecialScripts[i], &_sceneScriptData);
+ _scriptInterpreter->startScript(&_sceneSpecialScripts[i], i+8);
+ _sceneSpecialScriptsTimer[i] = 0;
+ }
+
+ _sceneEnterX1 &= ~3;
+ _sceneEnterX2 &= ~3;
+ _sceneEnterX3 &= ~3;
+ _sceneEnterX4 &= ~3;
+ _sceneEnterY1 &= ~1;
+ _sceneEnterY2 &= ~1;
+ _sceneEnterY3 &= ~1;
+ _sceneEnterY4 &= ~1;
+}
+
+void KyraEngine_v2::runSceneScript2() {
+ _scriptInterpreter->initScript(&_sceneScriptState, &_sceneScriptData);
+ _sceneScriptState.regs[4] = _itemInHand;
+ _scriptInterpreter->startScript(&_sceneScriptState, 2);
+
+ while (_scriptInterpreter->validScript(&_sceneScriptState))
+ _scriptInterpreter->runScript(&_sceneScriptState);
+}
+
+void KyraEngine_v2::runSceneScript4(int unk1) {
+ _sceneScriptState.regs[4] = _itemInHand;
+ _sceneScriptState.regs[5] = unk1;
+
+ _scriptInterpreter->startScript(&_sceneScriptState, 4);
+ while (_scriptInterpreter->validScript(&_sceneScriptState))
+ _scriptInterpreter->runScript(&_sceneScriptState);
+}
+
+void KyraEngine_v2::runSceneScript7() {
+ int oldPage = _screen->_curPage;
+ _screen->_curPage = 2;
+
+ _scriptInterpreter->startScript(&_sceneScriptState, 7);
+ while (_scriptInterpreter->validScript(&_sceneScriptState))
+ _scriptInterpreter->runScript(&_sceneScriptState);
+
+ _screen->_curPage = oldPage;
+}
+
+void KyraEngine_v2::initSceneAnims(int unk1) {
+ for (int i = 0; i < ARRAYSIZE(_animObjects); ++i)
+ _animObjects[i].enabled = 0;
+
+ bool animInit = false;
+
+ AnimObj *animState = &_animObjects[0];
+
+ if (_mainCharacter.animFrame != 32)
+ _mainCharacter.animFrame = _characterFrameTable[_mainCharacter.facing];
+
+ animState->enabled = 1;
+ animState->xPos1 = _mainCharacter.x1;
+ animState->yPos1 = _mainCharacter.y1;
+ animState->shapePtr = _defaultShapeTable[_mainCharacter.animFrame];
+ animState->shapeIndex1 = animState->shapeIndex2 = _mainCharacter.animFrame;
+
+ int frame = _mainCharacter.animFrame - 9;
+ int shapeX = _shapeDescTable[frame].xAdd;
+ int shapeY = _shapeDescTable[frame].yAdd;
+
+ animState->xPos2 = _mainCharacter.x1;
+ animState->yPos2 = _mainCharacter.y1;
+
+ _charScaleX = _charScaleY = getScale(_mainCharacter.x1, _mainCharacter.y1);
+
+ int shapeXScaled = (shapeX * _charScaleX) >> 8;
+ int shapeYScaled = (shapeY * _charScaleY) >> 8;
+
+ animState->xPos2 += shapeXScaled;
+ animState->yPos2 += shapeYScaled;
+ animState->xPos3 = animState->xPos2;
+ animState->yPos3 = animState->yPos2;
+ animState->needRefresh = 1;
+ animState->unk8 = 1;
+
+ _animList = 0;
+
+ AnimObj *charAnimState = animState;
+
+ for (int i = 0; i < 10; ++i) {
+ animState = &_animObjects[i+1];
+ animState->enabled = 0;
+ animState->needRefresh = 0;
+ animState->unk8 = 0;
+
+ if (_sceneAnims[i].flags & 1) {
+ animState->enabled = 1;
+ animState->needRefresh = 1;
+ animState->unk8 = 1;
+ }
+
+ animState->animFlags = _sceneAnims[i].flags & 8;
+
+ if (_sceneAnims[i].flags & 2)
+ animState->flags = 0x800;
+ else
+ animState->flags = 0;
+
+ if (_sceneAnims[i].flags & 4)
+ animState->flags |= 1;
+
+ animState->xPos1 = _sceneAnims[i].x;
+ animState->yPos1 = _sceneAnims[i].y;
+
+ if (_sceneAnims[i].flags & 0x20)
+ animState->shapePtr = _sceneShapeTable[_sceneAnims[i].shapeIndex];
+ else
+ animState->shapePtr = 0;
+
+ if (_sceneAnims[i].flags & 0x40) {
+ animState->shapeIndex3 = _sceneAnims[i].shapeIndex;
+ animState->animNum = i;
+ } else {
+ animState->shapeIndex3 = 0xFFFF;
+ animState->animNum = 0xFFFF;
+ }
+
+ animState->shapeIndex2 = 0xFFFF;
+
+ animState->xPos3 = animState->xPos2 = _sceneAnims[i].x2;
+ animState->yPos3 = animState->yPos2 = _sceneAnims[i].y2;
+ animState->width = _sceneAnims[i].width;
+ animState->height = _sceneAnims[i].height;
+ animState->width2 = animState->height2 = _sceneAnims[i].specialSize;
+
+ if (_sceneAnims[i].flags & 1) {
+ if (animInit) {
+ _animList = addToAnimListSorted(_animList, animState);
+ } else {
+ _animList = initAnimList(_animList, animState);
+ animInit = true;
+ }
+ }
+ }
+
+ if (animInit) {
+ _animList = addToAnimListSorted(_animList, charAnimState);
+ } else {
+ _animList = initAnimList(_animList, charAnimState);
+ animInit = true;
+ }
+
+ for (int i = 0; i < 30; ++i) {
+ animState = &_animObjects[i+11];
+
+ uint16 shapeIndex = _itemList[i].id;
+ if (shapeIndex == 0xFFFF || _itemList[i].sceneId != _mainCharacter.sceneId) {
+ animState->enabled = 0;
+ animState->needRefresh = 0;
+ animState->unk8 = 0;
+ } else {
+ animState->xPos1 = _itemList[i].x;
+ animState->yPos1 = _itemList[i].y;
+ animState->shapePtr = _defaultShapeTable[64+shapeIndex];
+ animState->shapeIndex1 = animState->shapeIndex2 = shapeIndex+64;
+
+ animState->xPos2 = _itemList[i].x;
+ animState->yPos2 = _itemList[i].y;
+ int objectScale = getScale(animState->xPos2, animState->yPos2);
+
+ const uint8 *shape = getShapePtr(animState->shapeIndex1);
+ animState->xPos2 -= (_screen->getShapeScaledWidth(shape, objectScale) >> 1);
+ animState->yPos2 -= (_screen->getShapeScaledHeight(shape, objectScale) >> 1);
+ animState->xPos3 = animState->xPos2;
+ animState->yPos3 = animState->yPos2;
+
+ animState->enabled = 1;
+ animState->needRefresh = 1;
+ animState->unk8 = 1;
+
+ if (animInit) {
+ _animList = addToAnimListSorted(_animList, animState);
+ } else {
+ _animList = initAnimList(_animList, animState);
+ animInit = true;
+ }
+ }
+ }
+
+ _animObjects[0].unk8 = 1;
+ _animObjects[0].needRefresh = 1;
+
+ for (int i = 1; i < 41; ++i) {
+ if (_animObjects[i].enabled) {
+ _animObjects[i].needRefresh = 1;
+ _animObjects[i].unk8 = 1;
+ }
+ }
+
+ restorePage3();
+ drawAnimObjects();
+ _screen->hideMouse();
+ initSceneScreen(unk1);
+ _screen->showMouse();
+ refreshAnimObjects(0);
+}
+
+void KyraEngine_v2::initSceneScreen(int unk1) {
+ if (_unkSceneScreenFlag1) {
+ _screen->copyRegion(0, 0, 0, 0, 320, 144, 2, 0);
+ return;
+ }
+
+ if (_noScriptEnter) {
+ memset(_screen->getPalette(0), 0, 384);
+ _screen->setScreenPalette(_screen->getPalette(0));
+ }
+
+ _screen->copyRegion(0, 0, 0, 0, 320, 144, 2, 0);
+
+ if (_noScriptEnter)
+ memcpy(_screen->getPalette(0), _screen->getPalette(1), 384);
+
+ updateCharPal(0);
+
+ _scriptInterpreter->startScript(&_sceneScriptState, 3);
+ _sceneScriptState.regs[5] = unk1;
+ while (_scriptInterpreter->validScript(&_sceneScriptState))
+ _scriptInterpreter->runScript(&_sceneScriptState);
+}
+
+void KyraEngine_v2::updateSpecialSceneScripts() {
+ uint32 nextTime = _system->getMillis() + _tickLength;
+ const int startScript = _lastProcessedSceneScript;
+
+ while (_system->getMillis() <= nextTime) {
+ if (_sceneSpecialScriptsTimer[_lastProcessedSceneScript] <= _system->getMillis() &&
+ !_specialSceneScriptState[_lastProcessedSceneScript]) {
+ _specialSceneScriptRunFlag = true;
+
+ while (_specialSceneScriptRunFlag && _sceneSpecialScriptsTimer[_lastProcessedSceneScript] <= _system->getMillis())
+ _specialSceneScriptRunFlag = _scriptInterpreter->runScript(&_sceneSpecialScripts[_lastProcessedSceneScript]) != 0;
+ }
+
+ if (!_scriptInterpreter->validScript(&_sceneSpecialScripts[_lastProcessedSceneScript])) {
+ _scriptInterpreter->startScript(&_sceneSpecialScripts[_lastProcessedSceneScript], 8+_lastProcessedSceneScript);
+ _specialSceneScriptRunFlag = false;
+ }
+
+ ++_lastProcessedSceneScript;
+ if (_lastProcessedSceneScript >= 10)
+ _lastProcessedSceneScript = 0;
+
+ if (_lastProcessedSceneScript == startScript)
+ return;
+ }
+}
+
+void KyraEngine_v2::freeSceneShapePtrs() {
+ for (int i = 0; i < ARRAYSIZE(_sceneShapeTable); ++i)
+ delete [] _sceneShapeTable[i];
+ memset(_sceneShapeTable, 0, sizeof(_sceneShapeTable));
+}
+
+void KyraEngine_v2::freeSceneAnims() {
+ Common::for_each(_sceneAnimMovie, _sceneAnimMovie+ARRAYSIZE(_sceneAnimMovie), Common::mem_fun(&WSAMovieV2::close));
+}
+
+#pragma mark -
+#pragma mark - Pathfinder
+#pragma mark -
+
+int KyraEngine_v2::findWay(int x, int y, int toX, int toY, int *moveTable, int moveTableSize) {
+ debugC(9, kDebugLevelMain, "KyraEngine_v2::findWay(%d, %d, %d, %d, %p, %d)", x, y, toX, toY, (const void *)moveTable, moveTableSize);
+ x &= ~3; toX &= ~3;
+ y &= ~1; toY &= ~1;
+ int size = KyraEngine::findWay(x, y, toX, toY, moveTable, moveTableSize);
+ if (size) {
+/*
+ int temp = pathfinderUnk1(moveTable);
+ temp = pathfinderUnk3(temp, x, y);
+ pathfinderUnk5(moveTable, temp, x, y, moveTableSize);
+*/
+ }
+ return getMoveTableSize(moveTable);
+}
+
+bool KyraEngine_v2::lineIsPassable(int x, int y) {
+ debugC(9, kDebugLevelMain, "KyraEngine_v2::lineIsPassable(%d, %d)", x, y);
+ static int unkTable[] = { 1, 1, 1, 1, 1, 2, 4, 6, 8 };
+
+ if (_pathfinderFlag & 2) {
+ if (x >= 320)
+ return false;
+ }
+
+ if (_pathfinderFlag & 4) {
+ if (y >= 144)
+ return false;
+ }
+
+ if (_pathfinderFlag & 8) {
+ if (x < 0)
+ return false;
+ }
+
+ if (y > 143)
+ return false;
+
+ int unk1 = unkTable[getScale(x, y) >> 5];
+
+ if (y < 0)
+ y = 0;
+ x -= unk1 >> 1;
+ if (x < 0)
+ x = 0;
+ int x2 = x + unk1;
+ if (x2 > 320)
+ x2 = 320;
+
+ for (;x < x2; ++x)
+ if (!_screen->getShapeFlag1(x, y))
+ return false;
+
+ return true;
+}
+
+bool KyraEngine_v2::directLinePassable(int x, int y, int toX, int toY) {
+ while (x != toX && y != toY) {
+ int facing = getFacingFromPointToPoint(x, y, toX, toY);
+ x += _addXPosTable[facing];
+ y += _addYPosTable[facing];
+ if (!_screen->getShapeFlag1(x, y))
+ return false;
+ }
+ return true;
+}
+
+int KyraEngine_v2::pathfinderUnk1(int *moveTable) {
+ bool breakLoop = false;
+ int *moveTableCur = moveTable;
+ int oldEntry = *moveTableCur, curEntry = *moveTableCur;
+ int oldX = 0, newX = 0, oldY = 0, newY = 0;
+ int lastEntry = 0;
+ lastEntry = pathfinderUnk2(lastEntry, 0, 0);
+
+ while (*moveTableCur != 8) {
+ oldEntry = curEntry;
+
+ while (true) {
+ curEntry = *moveTableCur;
+ if (curEntry >= 0 && curEntry <= 7)
+ break;
+
+ if (curEntry == 8) {
+ breakLoop = true;
+ break;
+ } else {
+ ++moveTableCur;
+ }
+ }
+
+ if (breakLoop)
+ break;
+
+ oldX = newX;
+ oldY = newY;
+
+ newX += _addXPosTable[curEntry];
+ newY += _addYPosTable[curEntry];
+
+ int temp = ABS(curEntry - oldEntry);
+ if (temp > 4) {
+ temp = 8 - temp;
+ }
+
+ if (temp > 1 || oldEntry != curEntry)
+ lastEntry = pathfinderUnk2(lastEntry, oldX, oldY);
+
+ ++moveTableCur;
+ }
+
+ lastEntry = pathfinderUnk2(lastEntry, newX, newY);
+ _pathfinderUnkTable1[lastEntry*2+0] = -1;
+ _pathfinderUnkTable1[lastEntry*2+1] = -1;
+ return lastEntry;
+}
+
+int KyraEngine_v2::pathfinderUnk2(int index, int v1, int v2) {
+ _pathfinderUnkTable1[index<<1] = v1;
+ _pathfinderUnkTable1[(index<<1)+1] = v2;
+ ++index;
+ if (index >= 199)
+ --index;
+ return index;
+}
+
+int KyraEngine_v2::pathfinderUnk3(int tableLen, int x, int y) {
+ int x1 = 0, y1 = 0;
+ int x2 = 0, y2 = 0;
+ int lastEntry = 0;
+ int index2 = tableLen-1, index1 = 0;
+ while (index2 > index1) {
+ x1 = _pathfinderUnkTable1[index1*2+0] + x;
+ y1 = _pathfinderUnkTable1[index1*2+1] + y;
+ x2 = _pathfinderUnkTable1[index2*2+0] + x;
+ y2 = _pathfinderUnkTable1[index2*2+0] + x;
+
+ if (directLinePassable(x1, y1, x2, y2)) {
+ lastEntry = pathfinderUnk4(lastEntry, index2);
+ if (tableLen-1 == index2)
+ break;
+ index1 = index2;
+ index2 = tableLen-1;
+ } else if (index1+1 == index2) {
+ lastEntry = pathfinderUnk4(lastEntry, index2);
+ index1 = index2;
+ index2 = tableLen-1;
+ } else {
+ --index2;
+ }
+ }
+ return lastEntry;
+}
+
+int KyraEngine_v2::pathfinderUnk4(int index, int v) {
+ _pathfinderUnkTable2[index] = v;
+ ++index;
+ if (index >= 199)
+ --index;
+ return index;
+}
+
+void KyraEngine_v2::pathfinderUnk5(int *moveTable, int tableLen, int x, int y, int moveTableSize) {
+ int x1 = 0, y1 = 0;
+ int x2 = 0, y2 = 0;
+ int index1 = 0, index2 = 0;
+ int sizeLeft = moveTableSize;
+ for (int i = 0; i < tableLen; ++i) {
+ index2 = _pathfinderUnkTable2[i];
+ x1 = _pathfinderUnkTable1[index1*2+0] + x;
+ y1 = _pathfinderUnkTable1[index1*2+1] + y;
+ x2 = _pathfinderUnkTable1[index2*2+0] + x;
+ y2 = _pathfinderUnkTable1[index2*2+0] + x;
+
+ int wayLen = findWay(x1, y1, x2, y2, moveTable, sizeLeft);
+ moveTable += wayLen;
+ sizeLeft -= wayLen; // unlike the original we want to be sure that the size left is correct
+ index1 = index2;
+ }
+}
+
+} // end of namespace Kyra
diff --git a/engines/kyra/screen.cpp b/engines/kyra/screen.cpp
index 641a034eab..a7e9c90824 100644
--- a/engines/kyra/screen.cpp
+++ b/engines/kyra/screen.cpp
@@ -355,46 +355,6 @@ void Screen::fadeToBlack(int delay) {
fadePalette(blackPal, delay);
}
-void Screen::k2IntroFadeToGrey(int delay) {
- debugC(9, kDebugLevelScreen, "Screen::k2IntroFadeToGrey()");
-
- for (int i = 0; i <= 50; ++i) {
- if (i <= 8 || i >= 30) {
- _currentPalette[3 * i + 0] = (_currentPalette[3 * i + 0] +
- _currentPalette[3 * i + 1] +
- _currentPalette[3 * i + 2]) / 3;
- _currentPalette[3 * i + 1] = _currentPalette[3 * i + 0];
- _currentPalette[3 * i + 2] = _currentPalette[3 * i + 0];
- }
- }
-
- // color 71 is the same in both the overview and closeup scenes
- // Converting it to greyscale makes the trees in the closeup look dull
- for (int i = 71; i < 200; ++i) {
- _currentPalette[3 * i + 0] = (_currentPalette[3 * i + 0] +
- _currentPalette[3 * i + 1] +
- _currentPalette[3 * i + 2]) / 3;
- _currentPalette[3 * i + 1] = _currentPalette[3 * i + 0];
- _currentPalette[3 * i + 2] = _currentPalette[3 * i + 0];
- }
- fadePalette(_currentPalette, delay);
- // Make the font color white again
- setPaletteIndex(254, 254, 254, 254);
-}
-
-void Screen::fadeSpecialPalette(int palIndex, int startIndex, int size, int fadeTime) {
- debugC(9, kDebugLevelScreen, "fadeSpecialPalette(%d, %d, %d, %d)", palIndex, startIndex, size, fadeTime);
- assert(_vm->palTable1()[palIndex]);
- assert(_currentPalette);
- uint8 tempPal[768];
- memcpy(tempPal, _currentPalette, 768);
- memcpy(&tempPal[startIndex*3], _vm->palTable1()[palIndex], size*3);
- fadePalette(tempPal, fadeTime*18);
- memcpy(&_currentPalette[startIndex*3], &tempPal[startIndex*3], size*3);
- setScreenPalette(_currentPalette);
- _system->updateScreen();
-}
-
void Screen::fadePalette(const uint8 *palData, int delay) {
debugC(9, kDebugLevelScreen, "Screen::fadePalette(%p, %d)", (const void *)palData, delay);
updateScreen();
@@ -1070,13 +1030,8 @@ void Screen::drawCharANSI(uint8 c, int x, int y) {
void Screen::setScreenDim(int dim) {
debugC(9, kDebugLevelScreen, "Screen::setScreenDim(%d)", dim);
- if (_vm->game() == GI_KYRA1) {
- assert(dim < _screenDimTableCount);
- _curDim = &_screenDimTable[dim];
- } else {
- assert(dim < _screenDimTableCountK3);
- _curDim = &_screenDimTableK3[dim];
- }
+ assert(dim < _screenDimTableCount);
+ _curDim = &_screenDimTable[dim];
// XXX
}
@@ -2693,38 +2648,6 @@ void Screen::loadPalette(const byte *data, uint8 *palData, int bytes) {
}
}
-// kyra3 specific
-
-const uint8 *Screen::getPtrToShape(const uint8 *shpFile, int shape) {
- debugC(9, kDebugLevelScreen, "KyraEngine::getPtrToShape(%p, %d)", (const void *)shpFile, shape);
- uint16 shapes = READ_LE_UINT16(shpFile);
-
- if (shapes <= shape)
- return 0;
-
- uint32 offset = READ_LE_UINT32(shpFile + (shape << 2) + 2);
-
- return shpFile + offset + 2;
-}
-
-uint8 *Screen::getPtrToShape(uint8 *shpFile, int shape) {
- debugC(9, kDebugLevelScreen, "KyraEngine::getPtrToShape(%p, %d)", (void *)shpFile, shape);
- uint16 shapes = READ_LE_UINT16(shpFile);
-
- if (shapes <= shape)
- return 0;
-
- uint32 offset = READ_LE_UINT32(shpFile + (shape << 2) + 2);
-
- return shpFile + offset + 2;
-}
-
-uint16 Screen::getShapeSize(const uint8 *shp) {
- debugC(9, kDebugLevelScreen, "KyraEngine::getShapeSize(%p)", (const void *)shp);
-
- return READ_LE_UINT16(shp+6);
-}
-
// dirty rect handling
void Screen::addDirtyRect(int x, int y, int w, int h) {
diff --git a/engines/kyra/screen.h b/engines/kyra/screen.h
index a60cdbd637..b1a1eb7b1a 100644
--- a/engines/kyra/screen.h
+++ b/engines/kyra/screen.h
@@ -33,7 +33,6 @@ class OSystem;
namespace Kyra {
class KyraEngine;
-class Debugger;
struct Rect;
struct ScreenDim {
@@ -57,7 +56,7 @@ struct Font {
};
class Screen {
- friend class Debugger;
+ friend class Debugger_v1;
public:
enum {
@@ -94,7 +93,7 @@ public:
};
Screen(KyraEngine *vm, OSystem *system);
- ~Screen();
+ virtual ~Screen();
bool init();
@@ -134,9 +133,6 @@ public:
void fadeFromBlack(int delay=0x54);
void fadeToBlack(int delay=0x54);
- void k2IntroFadeToGrey(int delay=0x54);
-
- void fadeSpecialPalette(int palIndex, int startIndex, int size, int fadeTime);
void fadePalette(const uint8 *palData, int delay);
void setPaletteIndex(uint8 index, uint8 red, uint8 green, uint8 blue);
@@ -164,7 +160,7 @@ public:
void setTextColorMap(const uint8 *cmap);
void setTextColor(const uint8 *cmap, int a, int b);
- void setScreenDim(int dim);
+ virtual void setScreenDim(int dim);
// shape handling
uint8 *encodeShape(int x, int y, int w, int h, int flags);
@@ -172,7 +168,7 @@ public:
int setNewShapeHeight(uint8 *shape, int height);
int resetShapeHeight(uint8 *shape);
- void drawShape(uint8 pageNum, const uint8 *shapeData, int x, int y, int sd, int flags, ...);
+ virtual void drawShape(uint8 pageNum, const uint8 *shapeData, int x, int y, int sd, int flags, ...);
// mouse handling
void hideMouse();
@@ -180,7 +176,7 @@ public:
void setMouseCursor(int x, int y, byte *shape);
// rect handling
- int getRectSize(int w, int h);
+ virtual int getRectSize(int w, int h);
void rectClip(int &x, int &y, int w, int h);
@@ -210,6 +206,7 @@ public:
void copyBackgroundBlock(int x, int page, int flag);
void copyBackgroundBlock2(int x);
+ // kyra1 specific?
int getDrawLayer(int x, int y);
int getDrawLayer2(int x, int y, int height);
@@ -234,16 +231,7 @@ public:
static void convertAmigaGfx(uint8 *data, int w, int h, bool offscreen = true);
static void convertAmigaMsc(uint8 *data);
- // maybe subclass screen for kyra3
- static const ScreenDim _screenDimTableK3[];
- static const int _screenDimTableCountK3;
-
- uint8 *getPtrToShape(uint8 *shpFile, int shape);
- const uint8 *getPtrToShape(const uint8 *shpFile, int shape);
-
- uint16 getShapeSize(const uint8 *shp);
-
-private:
+protected:
uint8 *getPagePtr(int pageNum);
void updateDirtyRects();
void updateDirtyRectsOvl();
diff --git a/engines/kyra/screen_v1.cpp b/engines/kyra/screen_v1.cpp
new file mode 100644
index 0000000000..dc0fd798fa
--- /dev/null
+++ b/engines/kyra/screen_v1.cpp
@@ -0,0 +1,53 @@
+/* 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 "kyra/kyra_v1.h"
+#include "kyra/screen_v1.h"
+
+namespace Kyra {
+
+Screen_v1::Screen_v1(KyraEngine_v1 *vm, OSystem *system)
+ : Screen(vm, system) {
+ _vm = vm;
+}
+
+Screen_v1::~Screen_v1() {
+}
+
+void Screen_v1::fadeSpecialPalette(int palIndex, int startIndex, int size, int fadeTime) {
+ debugC(9, kDebugLevelScreen, "Screen_v1::fadeSpecialPalette(%d, %d, %d, %d)", palIndex, startIndex, size, fadeTime);
+
+ assert(_vm->palTable1()[palIndex]);
+ assert(_currentPalette);
+ uint8 tempPal[768];
+ memcpy(tempPal, _currentPalette, 768);
+ memcpy(&tempPal[startIndex*3], _vm->palTable1()[palIndex], size*3);
+ fadePalette(tempPal, fadeTime*18);
+ memcpy(&_currentPalette[startIndex*3], &tempPal[startIndex*3], size*3);
+ setScreenPalette(_currentPalette);
+ _system->updateScreen();
+}
+
+} // end of namespace Kyra
diff --git a/engines/kyra/screen_v1.h b/engines/kyra/screen_v1.h
new file mode 100644
index 0000000000..988e28bfbf
--- /dev/null
+++ b/engines/kyra/screen_v1.h
@@ -0,0 +1,48 @@
+/* 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 KYRA_SCREEN_V1_H
+#define KYRA_SCREEN_V1_H
+
+#include "kyra/screen.h"
+
+namespace Kyra {
+
+class KyraEngine_v1;
+
+class Screen_v1 : public Screen {
+public:
+ Screen_v1(KyraEngine_v1 *vm, OSystem *system);
+ virtual ~Screen_v1();
+
+ void fadeSpecialPalette(int palIndex, int startIndex, int size, int fadeTime);
+
+protected:
+ KyraEngine_v1 *_vm;
+};
+
+} // end of namespace Kyra
+
+#endif
diff --git a/engines/kyra/screen_v2.cpp b/engines/kyra/screen_v2.cpp
new file mode 100644
index 0000000000..83c75585a8
--- /dev/null
+++ b/engines/kyra/screen_v2.cpp
@@ -0,0 +1,561 @@
+/* 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/endian.h"
+
+#include "kyra/kyra_v2.h"
+#include "kyra/screen_v2.h"
+
+namespace Kyra {
+
+Screen_v2::Screen_v2(KyraEngine_v2 *vm, OSystem *system)
+ : Screen(vm, system) {
+ _vm = vm;
+}
+
+Screen_v2::~Screen_v2() {
+}
+
+void Screen_v2::setScreenDim(int dim) {
+ debugC(9, kDebugLevelScreen, "Screen_v2::setScreenDim(%d)", dim);
+ if (_vm->game() == GI_KYRA2) {
+ assert(dim < _screenDimTableCount);
+ _curDim = &_screenDimTable[dim];
+ } else {
+ assert(dim < _screenDimTableCountK3);
+ _curDim = &_screenDimTableK3[dim];
+ }
+}
+
+const ScreenDim *Screen_v2::getScreenDim(int dim) {
+ debugC(9, kDebugLevelScreen, "Screen_v2::getScreenDim(%d)", dim);
+ if (_vm->game() == GI_KYRA2) {
+ assert(dim < _screenDimTableCount);
+ return &_screenDimTable[dim];
+ } else {
+ assert(dim < _screenDimTableCountK3);
+ return &_screenDimTableK3[dim];
+ }
+}
+
+void Screen_v2::k2IntroFadeToGrey(int delay) {
+ debugC(9, kDebugLevelScreen, "Screen_v2::k2IntroFadeToGrey(%d)", delay);
+
+ for (int i = 0; i <= 50; ++i) {
+ if (i <= 8 || i >= 30) {
+ _currentPalette[3 * i + 0] = (_currentPalette[3 * i + 0] +
+ _currentPalette[3 * i + 1] +
+ _currentPalette[3 * i + 2]) / 3;
+ _currentPalette[3 * i + 1] = _currentPalette[3 * i + 0];
+ _currentPalette[3 * i + 2] = _currentPalette[3 * i + 0];
+ }
+ }
+
+ // color 71 is the same in both the overview and closeup scenes
+ // Converting it to greyscale makes the trees in the closeup look dull
+ for (int i = 71; i < 200; ++i) {
+ _currentPalette[3 * i + 0] = (_currentPalette[3 * i + 0] +
+ _currentPalette[3 * i + 1] +
+ _currentPalette[3 * i + 2]) / 3;
+ _currentPalette[3 * i + 1] = _currentPalette[3 * i + 0];
+ _currentPalette[3 * i + 2] = _currentPalette[3 * i + 0];
+ }
+ fadePalette(_currentPalette, delay);
+ // Make the font color white again
+ setPaletteIndex(254, 254, 254, 254);
+}
+
+void Screen_v2::copyWsaRect(int x, int y, int w, int h, int dimState, int plotFunc, const uint8 *src,
+ int unk1, const uint8 *unkPtr1, const uint8 *unkPtr2) {
+ uint8 *dstPtr = getPagePtr(_curPage);
+ uint8 *origDst = dstPtr;
+
+ const ScreenDim *dim = getScreenDim(dimState);
+ int dimX1 = dim->sx << 3;
+ int dimX2 = dim->w << 3;
+ dimX2 += dimX1;
+
+ int dimY1 = dim->sy;
+ int dimY2 = dim->h;
+ dimY2 += dimY1;
+
+ int temp = y - dimY1;
+ if (temp < 0) {
+ if ((temp += h) <= 0)
+ return;
+ else {
+ SWAP(temp, h);
+ y += temp - h;
+ src += (temp - h) * w;
+ }
+ }
+
+ temp = dimY2 - y;
+ if (temp <= 0)
+ return;
+
+ if (temp < h)
+ h = temp;
+
+ int srcOffset = 0;
+ temp = x - dimX1;
+ if (temp < 0) {
+ temp = -temp;
+ srcOffset = temp;
+ x += temp;
+ w -= temp;
+ }
+
+ int srcAdd = 0;
+
+ temp = dimX2 - x;
+ if (temp <= 0)
+ return;
+
+ if (temp < w) {
+ SWAP(w, temp);
+ temp -= w;
+ srcAdd = temp;
+ }
+
+ dstPtr += y * SCREEN_W + x;
+ uint8 *dst = dstPtr;
+
+ if (_curPage == 0 || _curPage == 1)
+ addDirtyRect(x, y, w, h);
+
+ clearOverlayRect(_curPage, x, y, w, h);
+
+ temp = h;
+ while (h--) {
+ src += srcOffset;
+ int cW = w;
+
+ switch (plotFunc) {
+ case 0:
+ memcpy(dst, src, cW);
+ dst += cW; src += cW;
+ break;
+
+ case 1:
+ while (cW--) {
+ uint8 d = *src++;
+ uint8 t = unkPtr1[d];
+ if (t != 0xFF)
+ d = unkPtr2[*dst + (t << 8)];
+ *dst++ = d;
+ }
+ break;
+
+ case 4:
+ while (cW--) {
+ uint8 d = *src++;
+ if (d)
+ *dst = d;
+ ++dst;
+ }
+ break;
+
+ case 5:
+ while (cW--) {
+ uint8 d = *src++;
+ if (d) {
+ uint8 t = unkPtr1[d];
+ if (t != 0xFF)
+ d = unkPtr2[*dst + (t << 8)];
+ *dst = d;
+ }
+ ++dst;
+ }
+ break;
+
+ case 8:
+ case 9:
+ while (cW--) {
+ uint8 d = *src++;
+ uint8 t = _shapePages[0][dst - origDst] & 7;
+ if (unk1 < t)
+ d = _shapePages[1][dst - origDst];
+ *dst++ = d;
+ }
+ break;
+
+ case 12:
+ case 13:
+ while (cW--) {
+ uint8 d = *src++;
+ if (d) {
+ uint8 t = _shapePages[0][dst - origDst] & 7;
+ if (unk1 < t)
+ d = _shapePages[1][dst - origDst];
+ *dst++ = d;
+ } else {
+ d = _shapePages[1][dst - origDst];
+ *dst++ = d;
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ dst = (dstPtr += SCREEN_W);
+ src += srcAdd;
+ }
+}
+
+const uint8 *Screen_v2::getPtrToShape(const uint8 *shpFile, int shape) {
+ debugC(9, kDebugLevelScreen, "Screen_v2::getPtrToShape(%p, %d)", (const void *)shpFile, shape);
+ uint16 shapes = READ_LE_UINT16(shpFile);
+
+ if (shapes <= shape)
+ return 0;
+
+ uint32 offset = READ_LE_UINT32(shpFile + (shape << 2) + 2);
+
+ return shpFile + offset + 2;
+}
+
+uint8 *Screen_v2::getPtrToShape(uint8 *shpFile, int shape) {
+ debugC(9, kDebugLevelScreen, "Screen_v2::getPtrToShape(%p, %d)", (void *)shpFile, shape);
+ uint16 shapes = READ_LE_UINT16(shpFile);
+
+ if (shapes <= shape)
+ return 0;
+
+ uint32 offset = READ_LE_UINT32(shpFile + (shape << 2) + 2);
+
+ return shpFile + offset + 2;
+}
+
+int Screen_v2::getShapeScaledWidth(const uint8 *shpFile, int scale) {
+ int width = READ_LE_UINT16(shpFile+3);
+ return (width * scale) >> 8;
+}
+
+int Screen_v2::getShapeScaledHeight(const uint8 *shpFile, int scale) {
+ int height = shpFile[2];
+ return (height * scale) >> 8;
+}
+
+uint16 Screen_v2::getShapeSize(const uint8 *shp) {
+ debugC(9, kDebugLevelScreen, "Screen_v2::getShapeSize(%p)", (const void *)shp);
+
+ return READ_LE_UINT16(shp+6);
+}
+
+uint8 *Screen_v2::makeShapeCopy(const uint8 *src, int index) {
+ debugC(9, kDebugLevelScreen, "Screen_v2::makeShapeCopy(%p, %d)", (const void *)src, index);
+
+ const uint8 *shape = getPtrToShape(src, index);
+ int size = getShapeSize(shape);
+
+ uint8 *copy = new uint8[size];
+ assert(copy);
+ memcpy(copy, shape, size);
+
+ return copy;
+}
+
+void Screen_v2::drawShape(uint8 page, const uint8 *shape, int x, int y, int sd, int flags, ...) {
+ if (!shape)
+ return;
+
+ if (*shape & 1)
+ flags |= 0x400;
+
+ va_list args;
+ va_start(args, flags);
+
+ static int drawShapeVar1 = 0;
+ static int drawShapeVar2[] = {
+ 1, 3, 2, 5, 4, 3, 2, 1
+ };
+ static int drawShapeVar3 = 1;
+ static int drawShapeVar4 = 0;
+ static int drawShapeVar5 = 0;
+
+ uint8 *table = 0;
+ int tableLoopCount = 0;
+ int drawLayer = 0;
+ const uint8 *table2 = 0;
+ uint8 *table3 = 0;
+ uint8 *table4 = 0;
+
+ if (flags & 0x8000) {
+ table2 = va_arg(args, uint8*);
+ }
+ if (flags & 0x100) {
+ table = va_arg(args, uint8*);
+ tableLoopCount = va_arg(args, int);
+ if (!tableLoopCount)
+ flags &= 0xFFFFFEFF;
+ }
+ if (flags & 0x1000) {
+ table3 = va_arg(args, uint8*);
+ table4 = va_arg(args, uint8*);
+ }
+ if (flags & 0x200) {
+ drawShapeVar1 += 1;
+ drawShapeVar1 &= 7;
+ drawShapeVar3 = drawShapeVar2[drawShapeVar1];
+ drawShapeVar4 = 0;
+ drawShapeVar5 = 256;
+ }
+ if (flags & 0x4000) {
+ drawShapeVar5 = va_arg(args, int);
+ }
+ if (flags & 0x800) {
+ drawLayer = va_arg(args, int);
+ }
+ int scale_w, scale_h;
+ if (flags & 0x04) {
+ scale_w = va_arg(args, int);
+ scale_h = va_arg(args, int);
+ } else {
+ scale_w = 0x100;
+ scale_h = 0x100;
+ }
+
+ int ppc = (flags >> 8) & 0x3F;
+
+ const uint8 *src = shape;
+ uint16 shapeFlags = READ_LE_UINT16(src); src += 2;
+
+ int shapeHeight = *src++;
+ int scaledShapeHeight = (shapeHeight * scale_h) >> 8;
+ if (scaledShapeHeight == 0) {
+ va_end(args);
+ return;
+ }
+
+ int shapeWidth = READ_LE_UINT16(src); src += 2;
+ int scaledShapeWidth = (shapeWidth * scale_w) >> 8;
+ if (scaledShapeWidth == 0) {
+ va_end(args);
+ return;
+ }
+
+ if (flags & 0x20) {
+ x -= scaledShapeWidth >> 1;
+ y -= scaledShapeHeight >> 1;
+ }
+
+ src += 3;
+
+ uint16 frameSize = READ_LE_UINT16(src); src += 2;
+ int colorTableColors = 0x10;
+
+ if (shapeFlags & 4)
+ colorTableColors = *src++;
+
+ if (!(flags & 0x8000) && (shapeFlags & 1))
+ table2 = src;
+
+ if ((shapeFlags & 1) || (flags & 0x400))
+ src += colorTableColors;
+
+ if (!(shapeFlags & 2)) {
+ decodeFrame4(src, _animBlockPtr, frameSize);
+ src = _animBlockPtr;
+ }
+
+ int shapeSize = shapeWidth * shapeHeight;
+ if (_decodeShapeBufferSize < shapeSize) {
+ delete [] _decodeShapeBuffer;
+ _decodeShapeBuffer = new uint8[shapeSize];
+ _decodeShapeBufferSize = shapeSize;
+ }
+ if (!_decodeShapeBuffer) {
+ _decodeShapeBufferSize = 0;
+ va_end(args);
+ return;
+ }
+ memset(_decodeShapeBuffer, 0, _decodeShapeBufferSize);
+ uint8 *decodedShapeFrame = _decodeShapeBuffer;
+
+ for (int j = 0; j < shapeHeight; ++j) {
+ uint8 *dsbNextLine = decodedShapeFrame + shapeWidth;
+ int count = shapeWidth;
+ while (count > 0) {
+ uint8 code = *src++;
+ if (code != 0) {
+ *decodedShapeFrame++ = code;
+ --count;
+ } else {
+ code = *src++;
+ decodedShapeFrame += code;
+ count -= code;
+ }
+ }
+ decodedShapeFrame = dsbNextLine;
+ }
+
+ uint16 sx1 = getScreenDim(sd)->sx << 3;
+ uint16 sy1 = getScreenDim(sd)->sy;
+ uint16 sx2 = sx1 + (getScreenDim(sd)->w << 3);
+ uint16 sy2 = sy1 + getScreenDim(sd)->h;
+ if (flags & 0x10) {
+ x += sx1;
+ y += sy1;
+ }
+
+ int x1, x2;
+ if (x >= 0) {
+ x1 = 0;
+ if (x + scaledShapeWidth < sx2) {
+ x2 = scaledShapeWidth;
+ } else {
+ x2 = sx2 - x;
+ }
+ } else {
+ x2 = scaledShapeWidth;
+ x1 = -x;
+ x = 0;
+ if (x2 > sx2) {
+ x2 = sx2;
+ }
+ }
+
+ int y1, y2;
+ if (y >= 0) {
+ y1 = 0;
+ if (y + scaledShapeHeight < sy2) {
+ y2 = scaledShapeHeight;
+ } else {
+ y2 = sy2 - y;
+ }
+ } else {
+ y2 = scaledShapeHeight;
+ y1 = -y;
+ y = 0;
+ if (y2 > sy2) {
+ y2 = sy2;
+ }
+ }
+
+ uint8 *dst = getPagePtr(page) + y * 320 + x;
+ uint8 *dstStart = getPagePtr(page);
+
+ int scaleYTable[200];
+ for (y = y1; y < y2; ++y) {
+ scaleYTable[y] = (y << 8) / scale_h;
+ }
+ int scaleXTable[320];
+ for (x = x1; x < x2; ++x) {
+ scaleXTable[x] = (x << 8) / scale_w;
+ }
+
+ const uint8 *shapeBuffer = _decodeShapeBuffer;
+ if (flags & 0x02) {
+ shapeBuffer += shapeWidth * (shapeHeight - 1);
+ }
+ if (flags & 0x01) {
+ shapeBuffer += shapeWidth - 1;
+ }
+
+ for (y = y1; y < y2; ++y) {
+ uint8 *dstNextLine = dst + 320;
+ int j = scaleYTable[y];
+ if (flags & 0x02) {
+ j = -j;
+ }
+ for (x = x1; x < x2; ++x) {
+ int xpos = scaleXTable[x];
+ if (flags & 0x01)
+ xpos = -xpos;
+ uint8 color = shapeBuffer[j * shapeWidth + xpos];
+ if (color != 0) {
+ switch (ppc) {
+ case 0:
+ *dst = color;
+ break;
+
+ case 4:
+ *dst = table2[color];
+ break;
+
+ case 8: {
+ int layer = _shapePages[0][dst - dstStart] & 7;
+ if (drawLayer > layer)
+ color = _shapePages[1][dst - dstStart];
+ *dst = color;
+ } break;
+
+ case 12: {
+ int layer = _shapePages[0][dst - dstStart] & 7;
+ if (drawLayer < layer)
+ color = _shapePages[1][dst - dstStart];
+ else
+ color = table2[color];
+ *dst = color;
+ } break;
+
+ default:
+ warning("unhandled ppc: %d", ppc);
+ break;
+ }
+ }
+ ++dst;
+ }
+ dst = dstNextLine;
+ }
+ va_end(args);
+}
+
+int Screen_v2::getRectSize(int w, int h) {
+ if (w > 320 || h > 200)
+ return 0;
+ return w*h;
+}
+
+int Screen_v2::getLayer(int x, int y) {
+ if (x < 0)
+ x = 0;
+ else if (x >= 320)
+ x = 319;
+ if (y < 0)
+ y = 0;
+ else if (y >= 144)
+ y = 143;
+
+ uint8 pixel = *(getCPagePtr(5) + y * 320 + x);
+ pixel &= 0x7F;
+ pixel >>= 3;
+
+ if (pixel < 1)
+ pixel = 1;
+ else if (pixel > 15)
+ pixel = 15;
+ return pixel;
+}
+
+bool Screen_v2::isMouseVisible() const {
+ return _mouseLockCount == 0;
+}
+
+} // end of namespace Kyra
diff --git a/engines/kyra/screen_v2.h b/engines/kyra/screen_v2.h
new file mode 100644
index 0000000000..7912d6b999
--- /dev/null
+++ b/engines/kyra/screen_v2.h
@@ -0,0 +1,84 @@
+/* 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 KYRA_SCREEN_V2_H
+#define KYRA_SCREEN_V2_H
+
+#include "kyra/screen.h"
+
+namespace Kyra {
+
+class KyraEngine_v2;
+
+class Screen_v2 : public Screen {
+public:
+ Screen_v2(KyraEngine_v2 *vm, OSystem *system);
+ virtual ~Screen_v2();
+
+ virtual void setScreenDim(int dim);
+ const ScreenDim *getScreenDim(int dim);
+
+ // palette handling
+ void k2IntroFadeToGrey(int delay=0x54);
+
+ // screen page handling
+ void copyWsaRect(int x, int y, int w, int h, int dimState, int plotFunc, const uint8 *src,
+ int unk1, const uint8 *unkPtr1, const uint8 *unkPtr2);
+
+ // shape handling
+ uint8 *getPtrToShape(uint8 *shpFile, int shape);
+ const uint8 *getPtrToShape(const uint8 *shpFile, int shape);
+
+ int getShapeScaledWidth(const uint8 *shpFile, int scale);
+ int getShapeScaledHeight(const uint8 *shpFile, int scale);
+
+ uint16 getShapeSize(const uint8 *shp);
+
+ uint8 *makeShapeCopy(const uint8 *src, int index);
+
+ void drawShape(uint8 pageNum, const uint8 *shapeData, int x, int y, int sd, int flags, ...);
+
+ // rect handling
+ virtual int getRectSize(int w, int h);
+
+ // layer handling
+ int getLayer(int x, int y);
+
+ // mouse handling
+ bool isMouseVisible() const;
+private:
+ KyraEngine_v2 *_vm;
+
+ static const ScreenDim _screenDimTable[];
+ static const int _screenDimTableCount;
+
+ // maybe subclass screen for kyra3
+ static const ScreenDim _screenDimTableK3[];
+ static const int _screenDimTableCountK3;
+};
+
+} // End of namespace Kyra
+
+#endif
diff --git a/engines/kyra/script.cpp b/engines/kyra/script.cpp
index b43cd3b471..5966fa2c25 100644
--- a/engines/kyra/script.cpp
+++ b/engines/kyra/script.cpp
@@ -40,64 +40,62 @@
namespace Kyra {
ScriptHelper::ScriptHelper(KyraEngine *vm) : _vm(vm) {
#define COMMAND(x) { &ScriptHelper::x, #x }
- // now we create a list of all Command/Opcode procs and so
static CommandEntry commandProcs[] = {
// 0x00
- COMMAND(c1_jmpTo),
- COMMAND(c1_setRetValue),
- COMMAND(c1_pushRetOrPos),
- COMMAND(c1_push),
+ COMMAND(cmd_jmpTo),
+ COMMAND(cmd_setRetValue),
+ COMMAND(cmd_pushRetOrPos),
+ COMMAND(cmd_push),
// 0x04
- COMMAND(c1_push),
- COMMAND(c1_pushReg),
- COMMAND(c1_pushBPNeg),
- COMMAND(c1_pushBPAdd),
+ COMMAND(cmd_push),
+ COMMAND(cmd_pushReg),
+ COMMAND(cmd_pushBPNeg),
+ COMMAND(cmd_pushBPAdd),
// 0x08
- COMMAND(c1_popRetOrPos),
- COMMAND(c1_popReg),
- COMMAND(c1_popBPNeg),
- COMMAND(c1_popBPAdd),
+ COMMAND(cmd_popRetOrPos),
+ COMMAND(cmd_popReg),
+ COMMAND(cmd_popBPNeg),
+ COMMAND(cmd_popBPAdd),
// 0x0C
- COMMAND(c1_addSP),
- COMMAND(c1_subSP),
- COMMAND(c1_execOpcode),
- COMMAND(c1_ifNotJmp),
+ COMMAND(cmd_addSP),
+ COMMAND(cmd_subSP),
+ COMMAND(cmd_execOpcode),
+ COMMAND(cmd_ifNotJmp),
// 0x10
- COMMAND(c1_negate),
- COMMAND(c1_eval),
- COMMAND(c1_setRetAndJmp)
+ COMMAND(cmd_negate),
+ COMMAND(cmd_eval),
+ COMMAND(cmd_setRetAndJmp)
};
_commands = commandProcs;
#undef COMMAND
}
bool ScriptHelper::loadScript(const char *filename, ScriptData *scriptData, const Common::Array<const Opcode*> *opcodes) {
- uint32 size = 0;
- uint8 *data = _vm->resource()->fileData(filename, &size);
- const byte *curData = data;
+ ScriptFileParser file(filename, _vm->resource());
+ if (!file) {
+ error("Couldn't open script file '%s'", filename);
+ return false;
+ }
- uint32 formBlockSize = getFORMBlockSize(curData);
+ uint32 formBlockSize = file.getFORMBlockSize();
if (formBlockSize == (uint32)-1) {
- delete [] data;
error("No FORM chunk found in file: '%s'", filename);
return false;
}
- uint32 chunkSize = getIFFBlockSize(data, curData, size, TEXT_CHUNK);
+ uint32 chunkSize = file.getIFFBlockSize(TEXT_CHUNK);
if (chunkSize != (uint32)-1) {
scriptData->text = new byte[chunkSize];
- if (!loadIFFBlock(data, curData, size, TEXT_CHUNK, scriptData->text, chunkSize)) {
- delete [] data;
+ if (!file.loadIFFBlock(TEXT_CHUNK, scriptData->text, chunkSize)) {
unloadScript(scriptData);
error("Couldn't load TEXT chunk from file: '%s'", filename);
return false;
}
}
- chunkSize = getIFFBlockSize(data, curData, size, ORDR_CHUNK);
+ chunkSize = file.getIFFBlockSize(ORDR_CHUNK);
if (chunkSize == (uint32)-1) {
- delete [] data;
unloadScript(scriptData);
error("No ORDR chunk found in file: '%s'", filename);
return false;
@@ -106,8 +104,7 @@ bool ScriptHelper::loadScript(const char *filename, ScriptData *scriptData, cons
scriptData->ordr = new uint16[chunkSize];
- if (!loadIFFBlock(data, curData, size, ORDR_CHUNK, scriptData->ordr, chunkSize << 1)) {
- delete [] data;
+ if (!file.loadIFFBlock(ORDR_CHUNK, scriptData->ordr, chunkSize << 1)) {
unloadScript(scriptData);
error("Couldn't load ORDR chunk from file: '%s'", filename);
return false;
@@ -116,9 +113,8 @@ bool ScriptHelper::loadScript(const char *filename, ScriptData *scriptData, cons
while (chunkSize--)
scriptData->ordr[chunkSize] = READ_BE_UINT16(&scriptData->ordr[chunkSize]);
- chunkSize = getIFFBlockSize(data, curData, size, DATA_CHUNK);
+ chunkSize = file.getIFFBlockSize(DATA_CHUNK);
if (chunkSize == (uint32)-1) {
- delete [] data;
unloadScript(scriptData);
error("No DATA chunk found in file: '%s'", filename);
return false;
@@ -127,8 +123,7 @@ bool ScriptHelper::loadScript(const char *filename, ScriptData *scriptData, cons
scriptData->data = new uint16[chunkSize];
- if (!loadIFFBlock(data, curData, size, DATA_CHUNK, scriptData->data, chunkSize << 1)) {
- delete [] data;
+ if (!file.loadIFFBlock(DATA_CHUNK, scriptData->data, chunkSize << 1)) {
unloadScript(scriptData);
error("Couldn't load DATA chunk from file: '%s'", filename);
return false;
@@ -139,8 +134,7 @@ bool ScriptHelper::loadScript(const char *filename, ScriptData *scriptData, cons
scriptData->data[chunkSize] = READ_BE_UINT16(&scriptData->data[chunkSize]);
scriptData->opcodes = opcodes;
-
- delete [] data;
+
return true;
}
@@ -172,10 +166,14 @@ bool ScriptHelper::startScript(ScriptState *script, int function) {
if (functionOffset == 0xFFFF)
return false;
- if (_vm->gameFlags().platform == Common::kPlatformFMTowns)
+ if (_vm->game() == GI_KYRA1) {
+ if (_vm->gameFlags().platform == Common::kPlatformFMTowns)
+ script->ip = &script->dataPtr->data[functionOffset+1];
+ else
+ script->ip = &script->dataPtr->data[functionOffset];
+ } else {
script->ip = &script->dataPtr->data[functionOffset+1];
- else
- script->ip = &script->dataPtr->data[functionOffset];
+ }
return true;
}
@@ -217,37 +215,51 @@ bool ScriptHelper::runScript(ScriptState *script) {
return _continue;
}
-uint32 ScriptHelper::getFORMBlockSize(const byte *&data) const {
- static const uint32 chunkName = FORM_CHUNK;
+#pragma mark -
+#pragma mark - ScriptFileParser implementation
+#pragma mark -
+
+void ScriptFileParser::setFile(const char *filename, Resource *res) {
+ destroy();
+
+ if (!res->getFileHandle(filename, &_endOffset, _scriptFile))
+ return;
+ _startOffset = _scriptFile.pos();
+ _endOffset += _startOffset;
+}
+
+void ScriptFileParser::destroy() {
+ _scriptFile.close();
+ _startOffset = _endOffset = 0;
+}
+
+uint32 ScriptFileParser::getFORMBlockSize() {
+ uint32 oldOffset = _scriptFile.pos();
+
+ uint32 data = _scriptFile.readUint32LE();
- if (READ_LE_UINT32(data) != chunkName)
+ if (data != FORM_CHUNK) {
+ _scriptFile.seek(oldOffset);
return (uint32)-1;
+ }
- data += 4;
- uint32 retValue = READ_BE_UINT32(data); data += 4;
- return retValue;
+ data = _scriptFile.readUint32BE();
+ return data;
}
-uint32 ScriptHelper::getIFFBlockSize(const byte *start, const byte *&data, uint32 maxSize, const uint32 chunkName) const {
+uint32 ScriptFileParser::getIFFBlockSize(const uint32 chunkName) {
uint32 size = (uint32)-1;
- bool special = false;
- if (data == (start + maxSize))
- data = start + 0x0C;
+ _scriptFile.seek(_startOffset + 0x0C);
- while (data < (start + maxSize)) {
- uint32 chunk = READ_LE_UINT32(data); data += 4;
- uint32 size_temp = READ_BE_UINT32(data); data += 4;
+ while (_scriptFile.pos() < _endOffset) {
+ uint32 chunk = _scriptFile.readUint32LE();
+ uint32 size_temp = _scriptFile.readUint32BE();
+
if (chunk != chunkName) {
- if (special) {
- data += (size_temp + 1) & 0xFFFFFFFE;
- } else {
- data = start + 0x0C;
- special = true;
- }
+ _scriptFile.seek((size_temp + 1) & (~1), SEEK_CUR);
+ assert(_scriptFile.pos() <= _endOffset);
} else {
- // kill our data
- data = start;
size = size_temp;
break;
}
@@ -256,32 +268,21 @@ uint32 ScriptHelper::getIFFBlockSize(const byte *start, const byte *&data, uint3
return size;
}
-bool ScriptHelper::loadIFFBlock(const byte *start, const byte *&data, uint32 maxSize, const uint32 chunkName, void *loadTo, uint32 ptrSize) const {
- bool special = false;
-
- if (data == (start + maxSize))
- data = start + 0x0C;
+bool ScriptFileParser::loadIFFBlock(const uint32 chunkName, void *loadTo, uint32 ptrSize) {
+ _scriptFile.seek(_startOffset + 0x0C);
+
+ while (_scriptFile.pos() < _endOffset) {
+ uint32 chunk = _scriptFile.readUint32LE();
+ uint32 chunkSize = _scriptFile.readUint32BE();
- while (data < (start + maxSize)) {
- uint32 chunk = READ_LE_UINT32(data); data += 4;
- uint32 chunkSize = READ_BE_UINT32(data); data += 4;
if (chunk != chunkName) {
- if (special) {
- data += (chunkSize + 1) & 0xFFFFFFFE;
- } else {
- data = start + 0x0C;
- special = true;
- }
+ _scriptFile.seek((chunkSize + 1) & (~1), SEEK_CUR);
+ assert(_scriptFile.pos() <= _endOffset);
} else {
uint32 loadSize = 0;
- if (chunkSize < ptrSize)
- loadSize = chunkSize;
- else
- loadSize = ptrSize;
- memcpy(loadTo, data, loadSize);
- chunkSize = (chunkSize + 1) & 0xFFFFFFFE;
- if (chunkSize > loadSize)
- data += (chunkSize - loadSize);
+
+ loadSize = MIN(ptrSize, chunkSize);
+ _scriptFile.read(loadTo, loadSize);
return true;
}
}
@@ -293,15 +294,15 @@ bool ScriptHelper::loadIFFBlock(const byte *start, const byte *&data, uint32 max
#pragma mark - Command implementations
#pragma mark -
-void ScriptHelper::c1_jmpTo(ScriptState* script) {
+void ScriptHelper::cmd_jmpTo(ScriptState* script) {
script->ip = script->dataPtr->data + _parameter;
}
-void ScriptHelper::c1_setRetValue(ScriptState* script) {
+void ScriptHelper::cmd_setRetValue(ScriptState* script) {
script->retValue = _parameter;
}
-void ScriptHelper::c1_pushRetOrPos(ScriptState* script) {
+void ScriptHelper::cmd_pushRetOrPos(ScriptState* script) {
switch (_parameter) {
case 0:
script->stack[--script->sp] = script->retValue;
@@ -320,23 +321,23 @@ void ScriptHelper::c1_pushRetOrPos(ScriptState* script) {
}
}
-void ScriptHelper::c1_push(ScriptState* script) {
+void ScriptHelper::cmd_push(ScriptState* script) {
script->stack[--script->sp] = _parameter;
}
-void ScriptHelper::c1_pushReg(ScriptState* script) {
+void ScriptHelper::cmd_pushReg(ScriptState* script) {
script->stack[--script->sp] = script->regs[_parameter];
}
-void ScriptHelper::c1_pushBPNeg(ScriptState* script) {
+void ScriptHelper::cmd_pushBPNeg(ScriptState* script) {
script->stack[--script->sp] = script->stack[(-(int32)(_parameter + 2)) + script->bp];
}
-void ScriptHelper::c1_pushBPAdd(ScriptState* script) {
+void ScriptHelper::cmd_pushBPAdd(ScriptState* script) {
script->stack[--script->sp] = script->stack[(_parameter - 1) + script->bp];
}
-void ScriptHelper::c1_popRetOrPos(ScriptState* script) {
+void ScriptHelper::cmd_popRetOrPos(ScriptState* script) {
switch (_parameter) {
case 0:
script->retValue = script->stack[script->sp++];
@@ -359,48 +360,48 @@ void ScriptHelper::c1_popRetOrPos(ScriptState* script) {
}
}
-void ScriptHelper::c1_popReg(ScriptState* script) {
+void ScriptHelper::cmd_popReg(ScriptState* script) {
script->regs[_parameter] = script->stack[script->sp++];
}
-void ScriptHelper::c1_popBPNeg(ScriptState* script) {
+void ScriptHelper::cmd_popBPNeg(ScriptState* script) {
script->stack[(-(int32)(_parameter + 2)) + script->bp] = script->stack[script->sp++];
}
-void ScriptHelper::c1_popBPAdd(ScriptState* script) {
+void ScriptHelper::cmd_popBPAdd(ScriptState* script) {
script->stack[(_parameter - 1) + script->bp] = script->stack[script->sp++];
}
-void ScriptHelper::c1_addSP(ScriptState* script) {
+void ScriptHelper::cmd_addSP(ScriptState* script) {
script->sp += _parameter;
}
-void ScriptHelper::c1_subSP(ScriptState* script) {
+void ScriptHelper::cmd_subSP(ScriptState* script) {
script->sp -= _parameter;
}
-void ScriptHelper::c1_execOpcode(ScriptState* script) {
+void ScriptHelper::cmd_execOpcode(ScriptState* script) {
uint8 opcode = _parameter;
assert(script->dataPtr->opcodes);
assert(opcode < script->dataPtr->opcodes->size());
- if ((*script->dataPtr->opcodes)[opcode]) {
+ if ((*script->dataPtr->opcodes)[opcode] && (bool) *(*script->dataPtr->opcodes)[opcode]) {
script->retValue = (*(*script->dataPtr->opcodes)[opcode])(script);
} else {
script->retValue = 0;
- warning("calling unimplemented opcode(0x%.02X)", opcode);
+ warning("calling unimplemented opcode(0x%.02X/%d)", opcode, opcode);
}
}
-void ScriptHelper::c1_ifNotJmp(ScriptState* script) {
+void ScriptHelper::cmd_ifNotJmp(ScriptState* script) {
if (!script->stack[script->sp++]) {
_parameter &= 0x7FFF;
script->ip = script->dataPtr->data + _parameter;
}
}
-void ScriptHelper::c1_negate(ScriptState* script) {
+void ScriptHelper::cmd_negate(ScriptState* script) {
int16 value = script->stack[script->sp];
switch (_parameter) {
case 0:
@@ -424,7 +425,7 @@ void ScriptHelper::c1_negate(ScriptState* script) {
}
}
-void ScriptHelper::c1_eval(ScriptState* script) {
+void ScriptHelper::cmd_eval(ScriptState* script) {
int16 ret = 0;
bool error = false;
@@ -542,7 +543,7 @@ void ScriptHelper::c1_eval(ScriptState* script) {
}
}
-void ScriptHelper::c1_setRetAndJmp(ScriptState* script) {
+void ScriptHelper::cmd_setRetAndJmp(ScriptState* script) {
if (script->sp >= 60) {
_continue = false;
script->ip = 0;
diff --git a/engines/kyra/script.h b/engines/kyra/script.h
index 5e43039110..3396712a24 100644
--- a/engines/kyra/script.h
+++ b/engines/kyra/script.h
@@ -27,33 +27,11 @@
#define KYRA_SCRIPT_H
#include "kyra/kyra.h"
+#include "kyra/util.h"
-namespace Kyra {
-
-struct ScriptState;
-
-struct Opcode {
- virtual ~Opcode() {}
-
- virtual operator bool() const = 0;
-
- virtual int operator()(ScriptState*) const = 0;
-};
+#include "common/file.h"
-template<class T>
-struct OpcodeImpl : public Opcode {
- T *vm;
- typedef int (T::*Callback)(ScriptState*);
- Callback callback;
-
- OpcodeImpl(T *v, Callback c) : Opcode(), vm(v), callback(c) {}
-
- operator bool() const { return callback != 0; }
-
- int operator()(ScriptState *state) const {
- return (vm->*callback)(state);
- }
-};
+namespace Kyra {
struct ScriptData {
byte *text;
@@ -74,6 +52,31 @@ struct ScriptState {
int16 stack[61]; // VM stack
};
+#define stackPos(x) script->stack[script->sp+x]
+#define stackPosString(x) (const char*)&script->dataPtr->text[READ_BE_UINT16(&((uint16 *)script->dataPtr->text)[stackPos(x)])]
+
+class ScriptFileParser {
+public:
+ ScriptFileParser() : _scriptFile(), _startOffset(0), _endOffset(0) {}
+ ScriptFileParser(const char *filename, Resource *res) : _scriptFile(), _startOffset(0), _endOffset(0) { setFile(filename, res); }
+ ~ScriptFileParser() { destroy(); }
+
+ // 'script' must be allocated with new!
+ void setFile(const char *filename, Resource *res);
+
+ operator bool() const { return (_startOffset != _endOffset) && _scriptFile.isOpen(); }
+
+ uint32 getFORMBlockSize();
+ uint32 getIFFBlockSize(const uint32 chunk);
+ bool loadIFFBlock(const uint32 chunk, void *loadTo, uint32 ptrSize);
+private:
+ void destroy();
+
+ Common::File _scriptFile;
+ uint32 _startOffset;
+ uint32 _endOffset;
+};
+
class ScriptHelper {
public:
ScriptHelper(KyraEngine *vm);
@@ -88,10 +91,6 @@ public:
bool runScript(ScriptState *script);
protected:
- uint32 getFORMBlockSize(const byte *&data) const;
- uint32 getIFFBlockSize(const byte *start, const byte *&data, uint32 maxSize, const uint32 chunk) const;
- bool loadIFFBlock(const byte *start, const byte *&data, uint32 maxSize, const uint32 chunk, void *loadTo, uint32 ptrSize) const;
-
KyraEngine *_vm;
int16 _parameter;
bool _continue;
@@ -104,25 +103,24 @@ protected:
const CommandEntry *_commands;
private:
- void c1_jmpTo(ScriptState*);
- void c1_setRetValue(ScriptState*);
- void c1_pushRetOrPos(ScriptState*);
- void c1_push(ScriptState*);
- //void c1_push(); same as 03
- void c1_pushReg(ScriptState*);
- void c1_pushBPNeg(ScriptState*);
- void c1_pushBPAdd(ScriptState*);
- void c1_popRetOrPos(ScriptState*);
- void c1_popReg(ScriptState*);
- void c1_popBPNeg(ScriptState*);
- void c1_popBPAdd(ScriptState*);
- void c1_addSP(ScriptState*);
- void c1_subSP(ScriptState*);
- void c1_execOpcode(ScriptState*);
- void c1_ifNotJmp(ScriptState*);
- void c1_negate(ScriptState*);
- void c1_eval(ScriptState*);
- void c1_setRetAndJmp(ScriptState*);
+ void cmd_jmpTo(ScriptState*);
+ void cmd_setRetValue(ScriptState*);
+ void cmd_pushRetOrPos(ScriptState*);
+ void cmd_push(ScriptState*);
+ void cmd_pushReg(ScriptState*);
+ void cmd_pushBPNeg(ScriptState*);
+ void cmd_pushBPAdd(ScriptState*);
+ void cmd_popRetOrPos(ScriptState*);
+ void cmd_popReg(ScriptState*);
+ void cmd_popBPNeg(ScriptState*);
+ void cmd_popBPAdd(ScriptState*);
+ void cmd_addSP(ScriptState*);
+ void cmd_subSP(ScriptState*);
+ void cmd_execOpcode(ScriptState*);
+ void cmd_ifNotJmp(ScriptState*);
+ void cmd_negate(ScriptState*);
+ void cmd_eval(ScriptState*);
+ void cmd_setRetAndJmp(ScriptState*);
};
} // end of namespace Kyra
diff --git a/engines/kyra/script_v1.cpp b/engines/kyra/script_v1.cpp
index 87123222fb..bd776e2046 100644
--- a/engines/kyra/script_v1.cpp
+++ b/engines/kyra/script_v1.cpp
@@ -25,21 +25,20 @@
#include "common/stdafx.h"
#include "common/endian.h"
+#include "common/system.h"
+
#include "kyra/kyra_v1.h"
#include "kyra/script.h"
#include "kyra/screen.h"
#include "kyra/sprites.h"
#include "kyra/wsamovie.h"
-#include "kyra/animator.h"
+#include "kyra/animator_v1.h"
#include "kyra/text.h"
-#include "common/system.h"
+#include "kyra/timer.h"
namespace Kyra {
-#define stackPos(x) script->stack[script->sp+x]
-#define stackPosString(x) (const char*)&script->dataPtr->text[READ_BE_UINT16(&((uint16 *)script->dataPtr->text)[stackPos(x)])]
-
int KyraEngine_v1::o1_magicInMouseItem(ScriptState *script) {
- debugC(3, kDebugLevelScriptFuncs, "o1_magicInMouseItem(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1));
+ debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1magicInMouseItem(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1));
magicInMouseItem(stackPos(0), stackPos(1), -1);
return 0;
}
@@ -47,10 +46,10 @@ int KyraEngine_v1::o1_magicInMouseItem(ScriptState *script) {
int KyraEngine_v1::o1_characterSays(ScriptState *script) {
_skipFlag = false;
if (_flags.isTalkie) {
- debugC(3, kDebugLevelScriptFuncs, "o1_characterSays(%p) (%d, '%s', %d, %d)", (const void *)script, stackPos(0), stackPosString(1), stackPos(2), stackPos(3));
+ debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1characterSays(%p) (%d, '%s', %d, %d)", (const void *)script, stackPos(0), stackPosString(1), stackPos(2), stackPos(3));
characterSays(stackPos(0), stackPosString(1), stackPos(2), stackPos(3));
} else {
- debugC(3, kDebugLevelScriptFuncs, "o1_characterSays(%p) ('%s', %d, %d)", (const void *)script, stackPosString(0), stackPos(1), stackPos(2));
+ 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) {
@@ -76,7 +75,7 @@ int KyraEngine_v1::o1_characterSays(ScriptState *script) {
}
int KyraEngine_v1::o1_pauseTicks(ScriptState *script) {
- debugC(3, kDebugLevelScriptFuncs, "o1_pauseTicks(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1));
+ debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1pauseTicks(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1));
if (stackPos(1)) {
warning("STUB: special o1_pauseTicks");
// delete this after correct implementing
@@ -88,23 +87,23 @@ int KyraEngine_v1::o1_pauseTicks(ScriptState *script) {
}
int KyraEngine_v1::o1_drawSceneAnimShape(ScriptState *script) {
- debugC(3, kDebugLevelScriptFuncs, "o1_drawSceneAnimShape(%p) (%d, %d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3), stackPos(4));
+ debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1drawSceneAnimShape(%p) (%d, %d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3), stackPos(4));
_screen->drawShape(stackPos(4), _sprites->_sceneShapes[stackPos(0)], stackPos(1), stackPos(2), 0, (stackPos(3) != 0) ? 1 : 0);
return 0;
}
int KyraEngine_v1::o1_queryGameFlag(ScriptState *script) {
- debugC(3, kDebugLevelScriptFuncs, "o1_queryGameFlag(%p) (0x%X)", (const void *)script, stackPos(0));
+ debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1queryGameFlag(%p) (0x%X)", (const void *)script, stackPos(0));
return queryGameFlag(stackPos(0));
}
int KyraEngine_v1::o1_setGameFlag(ScriptState *script) {
- debugC(3, kDebugLevelScriptFuncs, "o1_setGameFlag(%p) (0x%X)", (const void *)script, stackPos(0));
+ debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1setGameFlag(%p) (0x%X)", (const void *)script, stackPos(0));
return setGameFlag(stackPos(0));
}
int KyraEngine_v1::o1_resetGameFlag(ScriptState *script) {
- debugC(3, kDebugLevelScriptFuncs, "o1_resetGameFlag(%p) (0x%X)", (const void *)script, stackPos(0));
+ debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1resetGameFlag(%p) (0x%X)", (const void *)script, stackPos(0));
return resetGameFlag(stackPos(0));
}
@@ -114,7 +113,7 @@ int KyraEngine_v1::o1_runNPCScript(ScriptState *script) {
}
int KyraEngine_v1::o1_setSpecialExitList(ScriptState *script) {
- debugC(3, kDebugLevelScriptFuncs, "o1_setSpecialExitList(%p) (%d, %d, %d, %d, %d, %d, %d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3), stackPos(4), stackPos(5), stackPos(6), stackPos(7), stackPos(8), stackPos(9));
+ debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1setSpecialExitList(%p) (%d, %d, %d, %d, %d, %d, %d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3), stackPos(4), stackPos(5), stackPos(6), stackPos(7), stackPos(8), stackPos(9));
for (int i = 0; i < 10; ++i)
_exitList[i] = stackPos(i);
@@ -124,33 +123,33 @@ int KyraEngine_v1::o1_setSpecialExitList(ScriptState *script) {
}
int KyraEngine_v1::o1_blockInWalkableRegion(ScriptState *script) {
- debugC(3, kDebugLevelScriptFuncs, "o1_blockInWalkableRegion(%p) (%d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3));
+ debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1blockInWalkableRegion(%p) (%d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3));
_screen->blockInRegion(stackPos(0), stackPos(1), stackPos(2)-stackPos(0)+1, stackPos(3)-stackPos(1)+1);
return 0;
}
int KyraEngine_v1::o1_blockOutWalkableRegion(ScriptState *script) {
- debugC(3, kDebugLevelScriptFuncs, "o1_blockOutWalkableRegion(%p) (%d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3));
+ debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1blockOutWalkableRegion(%p) (%d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3));
_screen->blockOutRegion(stackPos(0), stackPos(1), stackPos(2)-stackPos(0)+1, stackPos(3)-stackPos(1)+1);
return 0;
}
int KyraEngine_v1::o1_walkPlayerToPoint(ScriptState *script) {
- debugC(3, kDebugLevelScriptFuncs, "o1_walkPlayerToPoint(%p) (%d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3));
+ debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1walkPlayerToPoint(%p) (%d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3));
int normalTimers = stackPos(2);
if (!normalTimers) {
- disableTimer(19);
- disableTimer(14);
- disableTimer(18);
+ _timer->disable(19);
+ _timer->disable(14);
+ _timer->disable(18);
}
int reinitScript = handleSceneChange(stackPos(0), stackPos(1), stackPos(2), stackPos(3));
if (!normalTimers) {
- enableTimer(19);
- enableTimer(14);
- enableTimer(18);
+ _timer->enable(19);
+ _timer->enable(14);
+ _timer->enable(18);
}
if (reinitScript)
@@ -164,7 +163,7 @@ int KyraEngine_v1::o1_walkPlayerToPoint(ScriptState *script) {
}
int KyraEngine_v1::o1_dropItemInScene(ScriptState *script) {
- debugC(3, kDebugLevelScriptFuncs, "o1_dropItemInScene(%p) (%d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2));
+ debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1dropItemInScene(%p) (%d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2));
int item = stackPos(0);
int xpos = stackPos(1);
int ypos = stackPos(2);
@@ -189,7 +188,7 @@ int KyraEngine_v1::o1_dropItemInScene(ScriptState *script) {
}
int KyraEngine_v1::o1_drawAnimShapeIntoScene(ScriptState *script) {
- debugC(3, kDebugLevelScriptFuncs, "o1_drawAnimShapeIntoScene(%p) (%d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3));
+ debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1drawAnimShapeIntoScene(%p) (%d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3));
_screen->hideMouse();
_animator->restoreAllObjectBackgrounds();
int shape = stackPos(0);
@@ -207,49 +206,49 @@ int KyraEngine_v1::o1_drawAnimShapeIntoScene(ScriptState *script) {
}
int KyraEngine_v1::o1_createMouseItem(ScriptState *script) {
- debugC(3, kDebugLevelScriptFuncs, "o1_createMouseItem(%p) (%d)", (const void *)script, stackPos(0));
+ debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1createMouseItem(%p) (%d)", (const void *)script, stackPos(0));
createMouseItem(stackPos(0));
return 0;
}
int KyraEngine_v1::o1_savePageToDisk(ScriptState *script) {
- debugC(3, kDebugLevelScriptFuncs, "o1_savePageToDisk(%p) ('%s', %d)", (const void *)script, stackPosString(0), stackPos(1));
+ debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1savePageToDisk(%p) ('%s', %d)", (const void *)script, stackPosString(0), stackPos(1));
_screen->savePageToDisk(stackPosString(0), stackPos(1));
return 0;
}
int KyraEngine_v1::o1_sceneAnimOn(ScriptState *script) {
- debugC(3, kDebugLevelScriptFuncs, "o1_sceneAnimOn(%p) (%d)", (const void *)script, stackPos(0));
+ debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1sceneAnimOn(%p) (%d)", (const void *)script, stackPos(0));
_sprites->_anims[stackPos(0)].play = true;
return 0;
}
int KyraEngine_v1::o1_sceneAnimOff(ScriptState *script) {
- debugC(3, kDebugLevelScriptFuncs, "o1_sceneAnimOff(%p) (%d)", (const void *)script, stackPos(0));
+ debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1sceneAnimOff(%p) (%d)", (const void *)script, stackPos(0));
_sprites->_anims[stackPos(0)].play = false;
return 0;
}
int KyraEngine_v1::o1_getElapsedSeconds(ScriptState *script) {
- debugC(3, kDebugLevelScriptFuncs, "o1_getElapsedSeconds(%p) ()", (const void *)script);
+ debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1getElapsedSeconds(%p) ()", (const void *)script);
return _system->getMillis() / 1000;
}
int KyraEngine_v1::o1_mouseIsPointer(ScriptState *script) {
- debugC(3, kDebugLevelScriptFuncs, "o1_mouseIsPointer(%p) ()", (const void *)script);
+ debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1mouseIsPointer(%p) ()", (const void *)script);
if (_itemInHand == -1)
return 1;
return 0;
}
int KyraEngine_v1::o1_destroyMouseItem(ScriptState *script) {
- debugC(3, kDebugLevelScriptFuncs, "o1_destroyMouseItem(%p) ()", (const void *)script);
+ debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1destroyMouseItem(%p) ()", (const void *)script);
destroyMouseItem();
return 0;
}
int KyraEngine_v1::o1_runSceneAnimUntilDone(ScriptState *script) {
- debugC(3, kDebugLevelScriptFuncs, "o1_runSceneAnimUntilDone(%p) (%d)", (const void *)script, stackPos(0));
+ debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1runSceneAnimUntilDone(%p) (%d)", (const void *)script, stackPos(0));
_screen->hideMouse();
_animator->restoreAllObjectBackgrounds();
_sprites->_anims[stackPos(0)].play = true;
@@ -268,59 +267,59 @@ int KyraEngine_v1::o1_runSceneAnimUntilDone(ScriptState *script) {
int KyraEngine_v1::o1_fadeSpecialPalette(ScriptState *script) {
if (_flags.platform == Common::kPlatformAmiga) {
- debugC(3, kDebugLevelScriptFuncs, "o1_fadeSpecialPalette(%p) (%d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2));
+ debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1fadeSpecialPalette(%p) (%d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2));
if (_currentCharacter->sceneId != 45) {
if (stackPos(0) == 13) {
memcpy(_screen->getPalette(0), _screen->getPalette(0) + 384*3, 32*3);
_screen->setScreenPalette(_screen->getPalette(0));
}
} else {
- warning("o1_fadeSpecialPalette not implemented");
+ warning("KyraEngine_v1::o1fadeSpecialPalette not implemented");
}
} else {
- debugC(3, kDebugLevelScriptFuncs, "o1_fadeSpecialPalette(%p) (%d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3));
+ debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1fadeSpecialPalette(%p) (%d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3));
_screen->fadeSpecialPalette(stackPos(0), stackPos(1), stackPos(2), stackPos(3));
}
return 0;
}
int KyraEngine_v1::o1_playAdlibSound(ScriptState *script) {
- debugC(3, kDebugLevelScriptFuncs, "o1_playAdlibSound(%p) (%d)", (const void *)script, stackPos(0));
+ debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1playAdlibSound(%p) (%d)", (const void *)script, stackPos(0));
snd_playSoundEffect(stackPos(0));
return 0;
}
int KyraEngine_v1::o1_playAdlibScore(ScriptState *script) {
- debugC(3, kDebugLevelScriptFuncs, "o1_playAdlibScore(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1));
+ debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1playAdlibScore(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1));
snd_playWanderScoreViaMap(stackPos(0), stackPos(1));
return 0;
}
int KyraEngine_v1::o1_phaseInSameScene(ScriptState *script) {
- debugC(3, kDebugLevelScriptFuncs, "o1_phaseInSameScene(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1));
+ debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1phaseInSameScene(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1));
transcendScenes(stackPos(0), stackPos(1));
return 0;
}
int KyraEngine_v1::o1_setScenePhasingFlag(ScriptState *script) {
- debugC(3, kDebugLevelScriptFuncs, "o1_setScenePhasingFlag(%p) ()", (const void *)script);
+ debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1setScenePhasingFlag(%p) ()", (const void *)script);
_scenePhasingFlag = 1;
return 1;
}
int KyraEngine_v1::o1_resetScenePhasingFlag(ScriptState *script) {
- debugC(3, kDebugLevelScriptFuncs, "o1_resetScenePhasingFlag(%p) ()", (const void *)script);
+ debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1resetScenePhasingFlag(%p) ()", (const void *)script);
_scenePhasingFlag = 0;
return 0;
}
int KyraEngine_v1::o1_queryScenePhasingFlag(ScriptState *script) {
- debugC(3, kDebugLevelScriptFuncs, "o1_queryScenePhasingFlag(%p) ()", (const void *)script);
+ debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1queryScenePhasingFlag(%p) ()", (const void *)script);
return _scenePhasingFlag;
}
int KyraEngine_v1::o1_sceneToDirection(ScriptState *script) {
- debugC(3, kDebugLevelScriptFuncs, "o1_sceneToDirection(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1));
+ debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1sceneToDirection(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1));
assert(stackPos(0) < _roomTableSize);
Room *curRoom = &_roomTable[stackPos(0)];
uint16 returnValue = 0xFFFF;
@@ -350,7 +349,7 @@ int KyraEngine_v1::o1_sceneToDirection(ScriptState *script) {
}
int KyraEngine_v1::o1_setBirthstoneGem(ScriptState *script) {
- debugC(3, kDebugLevelScriptFuncs, "o1_setBirthstoneGem(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1));
+ debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1setBirthstoneGem(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1));
int index = stackPos(0);
if (index < 4 && index >= 0) {
_birthstoneGemTable[index] = stackPos(1);
@@ -360,19 +359,19 @@ int KyraEngine_v1::o1_setBirthstoneGem(ScriptState *script) {
}
int KyraEngine_v1::o1_placeItemInGenericMapScene(ScriptState *script) {
- debugC(3, kDebugLevelScriptFuncs, "o1_placeItemInGenericMapScene(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1));
+ debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1placeItemInGenericMapScene(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1));
placeItemInGenericMapScene(stackPos(0), stackPos(1));
return 0;
}
int KyraEngine_v1::o1_setBrandonStatusBit(ScriptState *script) {
- debugC(3, kDebugLevelScriptFuncs, "o1_setBrandonStatusBit(%p) (%d)", (const void *)script, stackPos(0));
+ debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1setBrandonStatusBit(%p) (%d)", (const void *)script, stackPos(0));
_brandonStatusBit |= stackPos(0);
return 0;
}
int KyraEngine_v1::o1_pauseSeconds(ScriptState *script) {
- debugC(3, kDebugLevelScriptFuncs, "o1_pauseSeconds(%p) (%d)", (const void *)script, stackPos(0));
+ debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1pauseSeconds(%p) (%d)", (const void *)script, stackPos(0));
if (stackPos(0) > 0 && !_skipFlag)
delay(stackPos(0)*1000, true);
_skipFlag = false;
@@ -380,7 +379,7 @@ int KyraEngine_v1::o1_pauseSeconds(ScriptState *script) {
}
int KyraEngine_v1::o1_getCharactersLocation(ScriptState *script) {
- debugC(3, kDebugLevelScriptFuncs, "o1_getCharactersLocation(%p) (%d)", (const void *)script, stackPos(0));
+ debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1getCharactersLocation(%p) (%d)", (const void *)script, stackPos(0));
return _characterList[stackPos(0)].sceneId;
}
@@ -390,31 +389,31 @@ int KyraEngine_v1::o1_runNPCSubscript(ScriptState *script) {
}
int KyraEngine_v1::o1_magicOutMouseItem(ScriptState *script) {
- debugC(3, kDebugLevelScriptFuncs, "o1_magicOutMouseItem(%p) (%d)", (const void *)script, stackPos(0));
+ debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1magicOutMouseItem(%p) (%d)", (const void *)script, stackPos(0));
magicOutMouseItem(stackPos(0), -1);
return 0;
}
int KyraEngine_v1::o1_internalAnimOn(ScriptState *script) {
- debugC(3, kDebugLevelScriptFuncs, "o1_internalAnimOn(%p) (%d)", (const void *)script, stackPos(0));
+ debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1internalAnimOn(%p) (%d)", (const void *)script, stackPos(0));
_animator->sprites()[stackPos(0)].active = 1;
return 0;
}
int KyraEngine_v1::o1_forceBrandonToNormal(ScriptState *script) {
- debugC(3, kDebugLevelScriptFuncs, "o1_forceBrandonToNormal(%p) ()", (const void *)script);
+ debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1forceBrandonToNormal(%p) ()", (const void *)script);
checkAmuletAnimFlags();
return 0;
}
int KyraEngine_v1::o1_poisonDeathNow(ScriptState *script) {
- debugC(3, kDebugLevelScriptFuncs, "o1_poisonDeathNow(%p) ()", (const void *)script);
+ debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1poisonDeathNow(%p) ()", (const void *)script);
seq_poisonDeathNow(1);
return 0;
}
int KyraEngine_v1::o1_setScaleMode(ScriptState *script) {
- debugC(3, kDebugLevelScriptFuncs, "o1_setScaleMode(%p) (%d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3));
+ debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1setScaleMode(%p) (%d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3));
int len = stackPos(0);
int setValue1 = stackPos(1);
int start2 = stackPos(2);
@@ -432,7 +431,7 @@ int KyraEngine_v1::o1_setScaleMode(ScriptState *script) {
}
int KyraEngine_v1::o1_openWSAFile(ScriptState *script) {
- debugC(3, kDebugLevelScriptFuncs, "o1_openWSAFile(%p) ('%s', %d, %d, %d)", (const void *)script, stackPosString(0), stackPos(1), stackPos(2), stackPos(3));
+ debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1openWSAFile(%p) ('%s', %d, %d, %d)", (const void *)script, stackPosString(0), stackPos(1), stackPos(2), stackPos(3));
const char *filename = stackPosString(0);
int wsaIndex = stackPos(1);
@@ -444,7 +443,7 @@ int KyraEngine_v1::o1_openWSAFile(ScriptState *script) {
}
int KyraEngine_v1::o1_closeWSAFile(ScriptState *script) {
- debugC(3, kDebugLevelScriptFuncs, "o1_closeWSAFile(%p) (%d)", (const void *)script, stackPos(0));
+ debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1closeWSAFile(%p) (%d)", (const void *)script, stackPos(0));
int wsaIndex = stackPos(0);
if (_movieObjects[wsaIndex])
@@ -454,7 +453,7 @@ int KyraEngine_v1::o1_closeWSAFile(ScriptState *script) {
}
int KyraEngine_v1::o1_runWSAFromBeginningToEnd(ScriptState *script) {
- debugC(3, kDebugLevelScriptFuncs, "o1_runWSAFromBeginningToEnd(%p) (%d, %d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3), stackPos(4));
+ debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1runWSAFromBeginningToEnd(%p) (%d, %d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3), stackPos(4));
_screen->hideMouse();
@@ -495,7 +494,7 @@ int KyraEngine_v1::o1_runWSAFromBeginningToEnd(ScriptState *script) {
}
int KyraEngine_v1::o1_displayWSAFrame(ScriptState *script) {
- debugC(3, kDebugLevelScriptFuncs, "o1_displayWSAFrame(%p) (%d, %d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3), stackPos(4));
+ debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1displayWSAFrame(%p) (%d, %d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3), stackPos(4));
int frame = stackPos(0);
int xpos = stackPos(1);
int ypos = stackPos(2);
@@ -522,13 +521,13 @@ int KyraEngine_v1::o1_displayWSAFrame(ScriptState *script) {
}
int KyraEngine_v1::o1_enterNewScene(ScriptState *script) {
- debugC(3, kDebugLevelScriptFuncs, "o1_enterNewScene(%p) (%d, %d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3), stackPos(4));
+ debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1enterNewScene(%p) (%d, %d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3), stackPos(4));
enterNewScene(stackPos(0), stackPos(1), stackPos(2), stackPos(3), stackPos(4));
return 0;
}
int KyraEngine_v1::o1_setSpecialEnterXAndY(ScriptState *script) {
- debugC(3, kDebugLevelScriptFuncs, "o1_setSpecialEnterXAndY(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1));
+ debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1setSpecialEnterXAndY(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1));
_brandonPosX = stackPos(0);
_brandonPosY = stackPos(1);
if (_brandonPosX + 1 == 0 && _brandonPosY + 1 == 0)
@@ -537,7 +536,7 @@ int KyraEngine_v1::o1_setSpecialEnterXAndY(ScriptState *script) {
}
int KyraEngine_v1::o1_runWSAFrames(ScriptState *script) {
- debugC(3, kDebugLevelScriptFuncs, "o1_runWSAFrames(%p) (%d, %d, %d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3), stackPos(4), stackPos(5));
+ debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1runWSAFrames(%p) (%d, %d, %d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3), stackPos(4), stackPos(5));
int xpos = stackPos(0);
int ypos = stackPos(1);
int delayTime = stackPos(2);
@@ -564,7 +563,7 @@ int KyraEngine_v1::o1_runWSAFrames(ScriptState *script) {
}
int KyraEngine_v1::o1_popBrandonIntoScene(ScriptState *script) {
- debugC(3, kDebugLevelScriptFuncs, "o1_popBrandonIntoScene(%p) (%d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3));
+ debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1popBrandonIntoScene(%p) (%d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3));
int changeScaleMode = stackPos(3);
int xpos = (int16)(stackPos(0) & 0xFFFC);
int ypos = (int16)(stackPos(1) & 0xFFFE);
@@ -613,7 +612,7 @@ int KyraEngine_v1::o1_popBrandonIntoScene(ScriptState *script) {
}
int KyraEngine_v1::o1_restoreAllObjectBackgrounds(ScriptState *script) {
- debugC(3, kDebugLevelScriptFuncs, "o1_restoreAllObjectBackgrounds(%p) (%d)", (const void *)script, stackPos(0));
+ debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1restoreAllObjectBackgrounds(%p) (%d)", (const void *)script, stackPos(0));
int disable = stackPos(0);
int activeBackup = 0;
if (disable) {
@@ -627,13 +626,13 @@ int KyraEngine_v1::o1_restoreAllObjectBackgrounds(ScriptState *script) {
}
int KyraEngine_v1::o1_setCustomPaletteRange(ScriptState *script) {
- debugC(3, kDebugLevelScriptFuncs, "o1_setCustomPaletteRange(%p) (%d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2));
+ debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1setCustomPaletteRange(%p) (%d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2));
memcpy(_screen->getPalette(1) + stackPos(1)*3, _specialPalettes[stackPos(0)], stackPos(2)*3);
return 0;
}
int KyraEngine_v1::o1_loadPageFromDisk(ScriptState *script) {
- debugC(3, kDebugLevelScriptFuncs, "o1_loadPageFromDisk(%p) ('%s', %d)", (const void *)script, stackPosString(0), stackPos(1));
+ debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1loadPageFromDisk(%p) ('%s', %d)", (const void *)script, stackPosString(0), stackPos(1));
_screen->loadPageFromDisk(stackPosString(0), stackPos(1));
_animator->_updateScreen = true;
return 0;
@@ -641,7 +640,7 @@ int KyraEngine_v1::o1_loadPageFromDisk(ScriptState *script) {
int KyraEngine_v1::o1_customPrintTalkString(ScriptState *script) {
if (_flags.isTalkie) {
- debugC(3, kDebugLevelScriptFuncs, "o1_customPrintTalkString(%p) (%d, '%s', %d, %d, %d)", (const void *)script, stackPos(0), stackPosString(1), stackPos(2), stackPos(3), stackPos(4) & 0xFF);
+ debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1customPrintTalkString(%p) (%d, '%s', %d, %d, %d)", (const void *)script, stackPos(0), stackPosString(1), stackPos(2), stackPos(3), stackPos(4) & 0xFF);
if (speechEnabled()) {
snd_voiceWaitForFinish();
@@ -651,7 +650,7 @@ int KyraEngine_v1::o1_customPrintTalkString(ScriptState *script) {
if (textEnabled())
_text->printTalkTextMessage(stackPosString(1), stackPos(2), stackPos(3), stackPos(4) & 0xFF, 0, 2);
} else {
- debugC(3, kDebugLevelScriptFuncs, "o1_customPrintTalkString(%p) ('%s', %d, %d, %d)", (const void *)script, stackPosString(0), stackPos(1), stackPos(2), stackPos(3) & 0xFF);
+ debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1customPrintTalkString(%p) ('%s', %d, %d, %d)", (const void *)script, stackPosString(0), stackPos(1), stackPos(2), stackPos(3) & 0xFF);
_skipFlag = false;
_text->printTalkTextMessage(stackPosString(0), stackPos(1), stackPos(2), stackPos(3) & 0xFF, 0, 2);
}
@@ -660,7 +659,7 @@ int KyraEngine_v1::o1_customPrintTalkString(ScriptState *script) {
}
int KyraEngine_v1::o1_restoreCustomPrintBackground(ScriptState *script) {
- debugC(3, kDebugLevelScriptFuncs, "o1_restoreCustomPrintBackground(%p) ()", (const void *)script);
+ debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1restoreCustomPrintBackground(%p) ()", (const void *)script);
snd_voiceWaitForFinish();
snd_stopVoice();
_text->restoreTalkTextMessageBkgd(2, 0);
@@ -668,29 +667,29 @@ int KyraEngine_v1::o1_restoreCustomPrintBackground(ScriptState *script) {
}
int KyraEngine_v1::o1_hideMouse(ScriptState *script) {
- debugC(3, kDebugLevelScriptFuncs, "o1_hideMouse(%p) ()", (const void *)script);
+ debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1hideMouse(%p) ()", (const void *)script);
_screen->hideMouse();
return 0;
}
int KyraEngine_v1::o1_showMouse(ScriptState *script) {
- debugC(3, kDebugLevelScriptFuncs, "o1_showMouse(%p) ()", (const void *)script);
+ debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1showMouse(%p) ()", (const void *)script);
_screen->showMouse();
return 0;
}
int KyraEngine_v1::o1_getCharacterX(ScriptState *script) {
- debugC(3, kDebugLevelScriptFuncs, "o1_getCharacterX(%p) (%d)", (const void *)script, stackPos(0));
+ debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1getCharacterX(%p) (%d)", (const void *)script, stackPos(0));
return _characterList[stackPos(0)].x1;
}
int KyraEngine_v1::o1_getCharacterY(ScriptState *script) {
- debugC(3, kDebugLevelScriptFuncs, "o1_getCharacterY(%p) (%d)", (const void *)script, stackPos(0));
+ debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1getCharacterY(%p) (%d)", (const void *)script, stackPos(0));
return _characterList[stackPos(0)].y1;
}
int KyraEngine_v1::o1_changeCharactersFacing(ScriptState *script) {
- debugC(3, kDebugLevelScriptFuncs, "o1_changeCharactersFacing(%p) (%d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2));
+ debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1changeCharactersFacing(%p) (%d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2));
int character = stackPos(0);
int facing = stackPos(1);
int newAnimFrame = stackPos(2);
@@ -708,7 +707,7 @@ int KyraEngine_v1::o1_changeCharactersFacing(ScriptState *script) {
}
int KyraEngine_v1::o1_copyWSARegion(ScriptState *script) {
- debugC(3, kDebugLevelScriptFuncs, "o1_copyWSARegion(%p) (%d, %d, %d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3), stackPos(4), stackPos(5));
+ debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1copyWSARegion(%p) (%d, %d, %d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3), stackPos(4), stackPos(5));
int xpos = stackPos(0);
int ypos = stackPos(1);
int width = stackPos(2);
@@ -721,7 +720,7 @@ int KyraEngine_v1::o1_copyWSARegion(ScriptState *script) {
}
int KyraEngine_v1::o1_printText(ScriptState *script) {
- debugC(3, kDebugLevelScriptFuncs, "o1_printText(%p) ('%s', %d, %d, 0x%X, 0x%X)", (const void *)script, stackPosString(0), stackPos(1), stackPos(2), stackPos(3), stackPos(4));
+ debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1printText(%p) ('%s', %d, %d, 0x%X, 0x%X)", (const void *)script, stackPosString(0), stackPos(1), stackPos(2), stackPos(3), stackPos(4));
if (_flags.lang == Common::JA_JPN && stackPos(3) == 7)
_screen->printText(stackPosString(0), stackPos(1), stackPos(2), 0, 0x80);
else
@@ -731,7 +730,7 @@ int KyraEngine_v1::o1_printText(ScriptState *script) {
}
int KyraEngine_v1::o1_random(ScriptState *script) {
- debugC(3, kDebugLevelScriptFuncs, "o1_random(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1));
+ debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1random(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1));
assert(stackPos(0) < stackPos(1));
return _rnd.getRandomNumberRng(stackPos(0), stackPos(1));
}
@@ -742,7 +741,7 @@ int KyraEngine_v1::o1_loadSoundFile(ScriptState *script) {
}
int KyraEngine_v1::o1_displayWSAFrameOnHidPage(ScriptState *script) {
- debugC(3, kDebugLevelScriptFuncs, "o1_displayWSAFrameOnHidPage(%p) (%d, %d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3), stackPos(4));
+ debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1displayWSAFrameOnHidPage(%p) (%d, %d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3), stackPos(4));
int frame = stackPos(0);
int xpos = stackPos(1);
int ypos = stackPos(2);
@@ -771,7 +770,7 @@ int KyraEngine_v1::o1_displayWSAFrameOnHidPage(ScriptState *script) {
}
int KyraEngine_v1::o1_displayWSASequentialFrames(ScriptState *script) {
- debugC(3, kDebugLevelScriptFuncs, "o1_displayWSASequentialFrames(%p) (%d, %d, %d, %d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3), stackPos(4), stackPos(5), stackPos(6));
+ debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1displayWSASequentialFrames(%p) (%d, %d, %d, %d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3), stackPos(4), stackPos(5), stackPos(6));
int startFrame = stackPos(0);
int endFrame = stackPos(1);
int xpos = stackPos(2);
@@ -847,7 +846,7 @@ int KyraEngine_v1::o1_displayWSASequentialFrames(ScriptState *script) {
}
int KyraEngine_v1::o1_drawCharacterStanding(ScriptState *script) {
- debugC(3, kDebugLevelScriptFuncs, "o1_drawCharacterStanding(%p) (%d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3));
+ debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1drawCharacterStanding(%p) (%d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3));
int character = stackPos(0);
int animFrame = stackPos(1);
int newFacing = stackPos(2);
@@ -862,13 +861,13 @@ int KyraEngine_v1::o1_drawCharacterStanding(ScriptState *script) {
}
int KyraEngine_v1::o1_internalAnimOff(ScriptState *script) {
- debugC(3, kDebugLevelScriptFuncs, "o1_internalAnimOff(%p) (%d)", (const void *)script, stackPos(0));
+ debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1internalAnimOff(%p) (%d)", (const void *)script, stackPos(0));
_animator->sprites()[stackPos(0)].active = 0;
return 0;
}
int KyraEngine_v1::o1_changeCharactersXAndY(ScriptState *script) {
- debugC(3, kDebugLevelScriptFuncs, "o1_changeCharactersXAndY(%p) (%d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2));
+ debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1changeCharactersXAndY(%p) (%d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2));
Character *ch = &_characterList[stackPos(0)];
int16 x = stackPos(1);
int16 y = stackPos(2);
@@ -884,25 +883,25 @@ int KyraEngine_v1::o1_changeCharactersXAndY(ScriptState *script) {
}
int KyraEngine_v1::o1_clearSceneAnimatorBeacon(ScriptState *script) {
- debugC(3, kDebugLevelScriptFuncs, "o1_clearSceneAnimatorBeacon(%p) ()", (const void *)script);
+ debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1clearSceneAnimatorBeacon(%p) ()", (const void *)script);
_sprites->_sceneAnimatorBeaconFlag = 0;
return 0;
}
int KyraEngine_v1::o1_querySceneAnimatorBeacon(ScriptState *script) {
- debugC(3, kDebugLevelScriptFuncs, "o1_querySceneAnimatorBeacon(%p) ()", (const void *)script);
+ debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1querySceneAnimatorBeacon(%p) ()", (const void *)script);
return _sprites->_sceneAnimatorBeaconFlag;
}
int KyraEngine_v1::o1_refreshSceneAnimator(ScriptState *script) {
- debugC(3, kDebugLevelScriptFuncs, "o1_refreshSceneAnimator(%p) ()", (const void *)script);
+ debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1refreshSceneAnimator(%p) ()", (const void *)script);
_sprites->updateSceneAnims();
_animator->updateAllObjectShapes();
return 0;
}
int KyraEngine_v1::o1_placeItemInOffScene(ScriptState *script) {
- debugC(3, kDebugLevelScriptFuncs, "o1_placeItemInOffScene(%p) (%d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3));
+ debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1placeItemInOffScene(%p) (%d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3));
int item = stackPos(0);
int xpos = stackPos(1);
int ypos = stackPos(2);
@@ -921,7 +920,7 @@ int KyraEngine_v1::o1_placeItemInOffScene(ScriptState *script) {
}
int KyraEngine_v1::o1_wipeDownMouseItem(ScriptState *script) {
- debugC(3, kDebugLevelScriptFuncs, "o1_wipeDownMouseItem(%p) (%d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2));
+ debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1wipeDownMouseItem(%p) (%d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2));
_screen->hideMouse();
wipeDownMouseItem(stackPos(1), stackPos(2));
destroyMouseItem();
@@ -930,7 +929,7 @@ int KyraEngine_v1::o1_wipeDownMouseItem(ScriptState *script) {
}
int KyraEngine_v1::o1_placeCharacterInOtherScene(ScriptState *script) {
- debugC(3, kDebugLevelScriptFuncs, "o1_placeCharacterInOtherScene(%p) (%d, %d, %d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3), stackPos(4), stackPos(5));
+ debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1placeCharacterInOtherScene(%p) (%d, %d, %d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3), stackPos(4), stackPos(5));
int id = stackPos(0);
int sceneId = stackPos(1);
int xpos = (int16)(stackPos(2) & 0xFFFC);
@@ -947,7 +946,7 @@ int KyraEngine_v1::o1_placeCharacterInOtherScene(ScriptState *script) {
}
int KyraEngine_v1::o1_getKey(ScriptState *script) {
- debugC(3, kDebugLevelScriptFuncs, "o1_getKey(%p) ()", (const void *)script);
+ debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1getKey(%p) ()", (const void *)script);
waitForEvent();
return 0;
}
@@ -958,7 +957,7 @@ int KyraEngine_v1::o1_specificItemInInventory(ScriptState *script) {
}
int KyraEngine_v1::o1_popMobileNPCIntoScene(ScriptState *script) {
- debugC(3, kDebugLevelScriptFuncs, "o1_popMobileNPCIntoScene(%p) (%d, %d, %d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3), (int16)(stackPos(4) & 0xFFFC), (int8)(stackPos(5) & 0xFE));
+ debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1popMobileNPCIntoScene(%p) (%d, %d, %d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3), (int16)(stackPos(4) & 0xFFFC), (int8)(stackPos(5) & 0xFE));
int character = stackPos(0);
int sceneId = stackPos(1);
int animFrame = stackPos(2);
@@ -994,7 +993,7 @@ int KyraEngine_v1::o1_unhideMobileCharacter(ScriptState *script) {
}
int KyraEngine_v1::o1_setCharactersLocation(ScriptState *script) {
- debugC(3, kDebugLevelScriptFuncs, "o1_setCharactersLocation(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1));
+ debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1setCharactersLocation(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1));
Character *ch = &_characterList[stackPos(0)];
AnimObject *animObj = &_animator->actors()[stackPos(0)];
int newScene = stackPos(1);
@@ -1011,7 +1010,7 @@ int KyraEngine_v1::o1_setCharactersLocation(ScriptState *script) {
}
int KyraEngine_v1::o1_walkCharacterToPoint(ScriptState *script) {
- debugC(3, kDebugLevelScriptFuncs, "o1_walkCharacterToPoint(%p) (%d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2));
+ debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1walkCharacterToPoint(%p) (%d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2));
int character = stackPos(0);
int toX = stackPos(1);
int toY = stackPos(2);
@@ -1078,11 +1077,11 @@ int KyraEngine_v1::o1_walkCharacterToPoint(ScriptState *script) {
setCharacterPosition(character, 0);
++curPos;
- nextFrame = getTimerDelay(5 + character) * _tickLength + _system->getMillis();
+ nextFrame = _timer->getDelay(5 + character) * _tickLength + _system->getMillis();
while (_system->getMillis() < nextFrame) {
_sprites->updateSceneAnims();
updateMousePointer();
- updateGameTimers();
+ _timer->update();
_animator->updateAllObjectShapes();
updateTextFade();
if ((nextFrame - _system->getMillis()) >= 10)
@@ -1093,12 +1092,12 @@ int KyraEngine_v1::o1_walkCharacterToPoint(ScriptState *script) {
}
int KyraEngine_v1::o1_specialEventDisplayBrynnsNote(ScriptState *script) {
- debugC(3, kDebugLevelScriptFuncs, "o1_specialEventDisplayBrynnsNote(%p) ()", (const void *)script);
+ debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1specialEventDisplayBrynnsNote(%p) ()", (const void *)script);
_screen->hideMouse();
_screen->savePageToDisk("HIDPAGE.TMP", 2);
_screen->savePageToDisk("SEENPAGE.TMP", 0);
if (_flags.isTalkie) {
- if (_flags.lang == Common::EN_ANY)
+ if (_flags.lang == Common::EN_ANY || _flags.lang == Common::IT_ITA)
_screen->loadBitmap("NOTEENG.CPS", 3, 3, 0);
else if (_flags.lang == Common::FR_FRA)
_screen->loadBitmap("NOTEFRE.CPS", 3, 3, 0);
@@ -1115,7 +1114,7 @@ int KyraEngine_v1::o1_specialEventDisplayBrynnsNote(ScriptState *script) {
}
int KyraEngine_v1::o1_specialEventRemoveBrynnsNote(ScriptState *script) {
- debugC(3, kDebugLevelScriptFuncs, "o1_specialEventRemoveBrynnsNote(%p) ()", (const void *)script);
+ debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1specialEventRemoveBrynnsNote(%p) ()", (const void *)script);
_screen->hideMouse();
_screen->loadPageFromDisk("SEENPAGE.TMP", 0);
_screen->loadPageFromDisk("HIDPAGE.TMP", 2);
@@ -1126,13 +1125,13 @@ int KyraEngine_v1::o1_specialEventRemoveBrynnsNote(ScriptState *script) {
}
int KyraEngine_v1::o1_setLogicPage(ScriptState *script) {
- debugC(3, kDebugLevelScriptFuncs, "o1_setLogicPage(%p) (%d)", (const void *)script, stackPos(0));
+ debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1setLogicPage(%p) (%d)", (const void *)script, stackPos(0));
_screen->_curPage = stackPos(0);
return stackPos(0);
}
int KyraEngine_v1::o1_fatPrint(ScriptState *script) {
- debugC(3, kDebugLevelScriptFuncs, "o1_fatPrint(%p) ('%s', %d, %d, %d, %d, %d)", (const void *)script, stackPosString(0), stackPos(1), stackPos(2), stackPos(3), stackPos(4), stackPos(5));
+ debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1fatPrint(%p) ('%s', %d, %d, %d, %d, %d)", (const void *)script, stackPosString(0), stackPos(1), stackPos(2), stackPos(3), stackPos(4), stackPos(5));
// Workround for bug #1582672 ("KYRA1: Text crippled and drawn wrong")
// I'm not sure how the original handels this, since it seems to call
@@ -1145,13 +1144,13 @@ int KyraEngine_v1::o1_fatPrint(ScriptState *script) {
}
int KyraEngine_v1::o1_preserveAllObjectBackgrounds(ScriptState *script) {
- debugC(3, kDebugLevelScriptFuncs, "o1_preserveAllObjectBackgrounds(%p) ()", (const void *)script);
+ debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1preserveAllObjectBackgrounds(%p) ()", (const void *)script);
_animator->preserveAllBackgrounds();
return 0;
}
int KyraEngine_v1::o1_updateSceneAnimations(ScriptState *script) {
- debugC(3, kDebugLevelScriptFuncs, "o1_updateSceneAnimations(%p) (%d)", (const void *)script, stackPos(0));
+ debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1updateSceneAnimations(%p) (%d)", (const void *)script, stackPos(0));
int times = stackPos(0);
while (times--) {
_sprites->updateSceneAnims();
@@ -1161,23 +1160,23 @@ int KyraEngine_v1::o1_updateSceneAnimations(ScriptState *script) {
}
int KyraEngine_v1::o1_sceneAnimationActive(ScriptState *script) {
- debugC(3, kDebugLevelScriptFuncs, "o1_sceneAnimationActive(%p) (%d)", (const void *)script, stackPos(0));
+ debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1sceneAnimationActive(%p) (%d)", (const void *)script, stackPos(0));
return _sprites->_anims[stackPos(0)].play;
}
int KyraEngine_v1::o1_setCharactersMovementDelay(ScriptState *script) {
- debugC(3, kDebugLevelScriptFuncs, "o1_setCharactersMovementDelay(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1));
- setTimerDelay(stackPos(0)+5, stackPos(1));
+ debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1setCharactersMovementDelay(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1));
+ _timer->setDelay(stackPos(0)+5, stackPos(1));
return 0;
}
int KyraEngine_v1::o1_getCharactersFacing(ScriptState *script) {
- debugC(3, kDebugLevelScriptFuncs, "o1_getCharactersFacing(%p) (%d)", (const void *)script, stackPos(0));
+ debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1getCharactersFacing(%p) (%d)", (const void *)script, stackPos(0));
return _characterList[stackPos(0)].facing;
}
int KyraEngine_v1::o1_bkgdScrollSceneAndMasksRight(ScriptState *script) {
- debugC(3, kDebugLevelScriptFuncs, "o1_bkgdScrollSceneAndMasksRight(%p) (%d)", (const void *)script, stackPos(0));
+ debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1bkgdScrollSceneAndMasksRight(%p) (%d)", (const void *)script, stackPos(0));
_screen->copyBackgroundBlock(stackPos(0), 2, 0);
_screen->copyBackgroundBlock2(stackPos(0));
// update the whole screen
@@ -1187,13 +1186,13 @@ int KyraEngine_v1::o1_bkgdScrollSceneAndMasksRight(ScriptState *script) {
}
int KyraEngine_v1::o1_dispelMagicAnimation(ScriptState *script) {
- debugC(3, kDebugLevelScriptFuncs, "o1_dispelMagicAnimation(%p) ()", (const void *)script);
+ debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1dispelMagicAnimation(%p) ()", (const void *)script);
seq_dispelMagicAnimation();
return 0;
}
int KyraEngine_v1::o1_findBrightestFireberry(ScriptState *script) {
- debugC(3, kDebugLevelScriptFuncs, "o1_findBrightestFireberry(%p) ()", (const void *)script);
+ debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1findBrightestFireberry(%p) ()", (const void *)script);
if (_currentCharacter->sceneId >= 187 && _currentCharacter->sceneId <= 198)
return 29;
@@ -1237,7 +1236,7 @@ int KyraEngine_v1::o1_findBrightestFireberry(ScriptState *script) {
}
int KyraEngine_v1::o1_setFireberryGlowPalette(ScriptState *script) {
- debugC(3, kDebugLevelScriptFuncs, "o1_setFireberryGlowPalette(%p) (%d)", (const void *)script, stackPos(0));
+ debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1setFireberryGlowPalette(%p) (%d)", (const void *)script, stackPos(0));
int palIndex = 0;
switch (stackPos(0)) {
case 0x1E:
@@ -1274,19 +1273,19 @@ int KyraEngine_v1::o1_setFireberryGlowPalette(ScriptState *script) {
}
int KyraEngine_v1::o1_setDeathHandlerFlag(ScriptState *script) {
- debugC(3, kDebugLevelScriptFuncs, "o1_setDeathHandlerFlag(%p) (%d)", (const void *)script, stackPos(0));
+ debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1setDeathHandlerFlag(%p) (%d)", (const void *)script, stackPos(0));
_deathHandler = stackPos(0);
return 0;
}
int KyraEngine_v1::o1_drinkPotionAnimation(ScriptState *script) {
- debugC(3, kDebugLevelScriptFuncs, "o1_drinkPotionAnimation(%p) (%d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2));
+ debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1drinkPotionAnimation(%p) (%d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2));
seq_playDrinkPotionAnim(stackPos(0), stackPos(1), stackPos(2));
return 0;
}
int KyraEngine_v1::o1_makeAmuletAppear(ScriptState *script) {
- debugC(3, kDebugLevelScriptFuncs, "o1_makeAmuletAppear(%p) ()", (const void *)script);
+ debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1makeAmuletAppear(%p) ()", (const void *)script);
WSAMovieV1 amulet(this);
amulet.open("AMULET.WSA", 1, 0);
amulet.setX(224);
@@ -1327,7 +1326,7 @@ int KyraEngine_v1::o1_makeAmuletAppear(ScriptState *script) {
}
int KyraEngine_v1::o1_drawItemShapeIntoScene(ScriptState *script) {
- debugC(3, kDebugLevelScriptFuncs, "o1_drawItemShapeIntoScene(%p) (%d, %d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3), stackPos(4));
+ debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1drawItemShapeIntoScene(%p) (%d, %d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3), stackPos(4));
int item = stackPos(0);
int x = stackPos(1);
int y = stackPos(2);
@@ -1354,13 +1353,13 @@ int KyraEngine_v1::o1_drawItemShapeIntoScene(ScriptState *script) {
}
int KyraEngine_v1::o1_setCharactersCurrentFrame(ScriptState *script) {
- debugC(3, kDebugLevelScriptFuncs, "o1_setCharactersCurrentFrame(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1));
+ debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1setCharactersCurrentFrame(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1));
_characterList[stackPos(0)].currentAnimFrame = stackPos(1);
return 0;
}
int KyraEngine_v1::o1_waitForConfirmationMouseClick(ScriptState *script) {
- debugC(3, kDebugLevelScriptFuncs, "o1_waitForConfirmationMouseClick(%p) ()", (const void *)script);
+ debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1waitForConfirmationMouseClick(%p) ()", (const void *)script);
// if (mouseEnabled) {
while (!_mousePressFlag) {
updateMousePointer();
@@ -1390,18 +1389,18 @@ int KyraEngine_v1::o1_pageFlip(ScriptState *script) {
}
int KyraEngine_v1::o1_setSceneFile(ScriptState *script) {
- debugC(3, kDebugLevelScriptFuncs, "o1_setSceneFile(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1));
+ debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1setSceneFile(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1));
setSceneFile(stackPos(0), stackPos(1));
return 0;
}
int KyraEngine_v1::o1_getItemInMarbleVase(ScriptState *script) {
- debugC(3, kDebugLevelScriptFuncs, "o1_getItemInMarbleVase(%p) ()", (const void *)script);
+ debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1getItemInMarbleVase(%p) ()", (const void *)script);
return _marbleVaseItem;
}
int KyraEngine_v1::o1_setItemInMarbleVase(ScriptState *script) {
- debugC(3, kDebugLevelScriptFuncs, "o1_setItemInMarbleVase(%p) (%d)", (const void *)script, stackPos(0));
+ debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1setItemInMarbleVase(%p) (%d)", (const void *)script, stackPos(0));
_marbleVaseItem = stackPos(0);
return 0;
}
@@ -1417,7 +1416,7 @@ int KyraEngine_v1::o1_intPrint(ScriptState *script) {
}
int KyraEngine_v1::o1_shakeScreen(ScriptState *script) {
- debugC(3, kDebugLevelScriptFuncs, "o1_shakeScreen(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1));
+ debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1shakeScreen(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1));
int waitTicks = stackPos(1);
int times = stackPos(0);
@@ -1430,57 +1429,57 @@ int KyraEngine_v1::o1_shakeScreen(ScriptState *script) {
}
int KyraEngine_v1::o1_createAmuletJewel(ScriptState *script) {
- debugC(3, kDebugLevelScriptFuncs, "o1_createAmuletJewel(%p) (%d)", (const void *)script, stackPos(0));
+ debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1createAmuletJewel(%p) (%d)", (const void *)script, stackPos(0));
seq_createAmuletJewel(stackPos(0), 0, 0, 0);
return 0;
}
int KyraEngine_v1::o1_setSceneAnimCurrXY(ScriptState *script) {
- debugC(3, kDebugLevelScriptFuncs, "o1_setSceneAnimCurrXY(%p) (%d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2));
+ debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1setSceneAnimCurrXY(%p) (%d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2));
_sprites->_anims[stackPos(0)].x = stackPos(1);
_sprites->_anims[stackPos(0)].y = stackPos(2);
return 0;
}
int KyraEngine_v1::o1_poisonBrandonAndRemaps(ScriptState *script) {
- debugC(3, kDebugLevelScriptFuncs, "o1_poisonBrandonAndRemaps(%p) ()", (const void *)script);
+ debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1poisonBrandonAndRemaps(%p) ()", (const void *)script);
setBrandonPoisonFlags(1);
return 0;
}
int KyraEngine_v1::o1_fillFlaskWithWater(ScriptState *script) {
- debugC(3, kDebugLevelScriptFuncs, "o1_fillFlaskWithWater(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1));
+ debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1fillFlaskWithWater(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1));
seq_fillFlaskWithWater(stackPos(0), stackPos(1));
return 0;
}
int KyraEngine_v1::o1_getCharactersMovementDelay(ScriptState *script) {
- debugC(3, kDebugLevelScriptFuncs, "o1_getCharactersMovementDelay(%p) (%d)", (const void *)script, stackPos(0));
- return getTimerDelay(stackPos(0)+5);
+ debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1getCharactersMovementDelay(%p) (%d)", (const void *)script, stackPos(0));
+ return _timer->getDelay(stackPos(0)+5);
}
int KyraEngine_v1::o1_getBirthstoneGem(ScriptState *script) {
- debugC(3, kDebugLevelScriptFuncs, "o1_getBirthstoneGem(%p) (%d)", (const void *)script, stackPos(0));
+ debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1getBirthstoneGem(%p) (%d)", (const void *)script, stackPos(0));
if (stackPos(0) < 4)
return _birthstoneGemTable[stackPos(0)];
return 0;
}
int KyraEngine_v1::o1_queryBrandonStatusBit(ScriptState *script) {
- debugC(3, kDebugLevelScriptFuncs, "o1_queryBrandonStatusBit(%p) (%d)", (const void *)script, stackPos(0));
+ debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1queryBrandonStatusBit(%p) (%d)", (const void *)script, stackPos(0));
if (_brandonStatusBit & stackPos(0))
return 1;
return 0;
}
int KyraEngine_v1::o1_playFluteAnimation(ScriptState *script) {
- debugC(3, kDebugLevelScriptFuncs, "o1_playFluteAnimation(%p) ()", (const void *)script);
+ debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1playFluteAnimation(%p) ()", (const void *)script);
seq_playFluteAnimation();
return 0;
}
int KyraEngine_v1::o1_playWinterScrollSequence(ScriptState *script) {
- debugC(3, kDebugLevelScriptFuncs, "o1_playWinterScrollSequence(%p) (%d)", (const void *)script, stackPos(0));
+ debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1playWinterScrollSequence(%p) (%d)", (const void *)script, stackPos(0));
if (!stackPos(0))
seq_winterScroll2();
else
@@ -1489,40 +1488,40 @@ int KyraEngine_v1::o1_playWinterScrollSequence(ScriptState *script) {
}
int KyraEngine_v1::o1_getIdolGem(ScriptState *script) {
- debugC(3, kDebugLevelScriptFuncs, "o1_getIdolGem(%p) (%d)", (const void *)script, stackPos(0));
+ debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1getIdolGem(%p) (%d)", (const void *)script, stackPos(0));
return _idolGemsTable[stackPos(0)];
}
int KyraEngine_v1::o1_setIdolGem(ScriptState *script) {
- debugC(3, kDebugLevelScriptFuncs, "o1_setIdolGem(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1));
+ debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1setIdolGem(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1));
_idolGemsTable[stackPos(0)] = stackPos(1);
return 0;
}
int KyraEngine_v1::o1_totalItemsInScene(ScriptState *script) {
- debugC(3, kDebugLevelScriptFuncs, "o1_totalItemsInScene(%p) (%d)", (const void *)script, stackPos(0));
+ debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1totalItemsInScene(%p) (%d)", (const void *)script, stackPos(0));
return countItemsInScene(stackPos(0));
}
int KyraEngine_v1::o1_restoreBrandonsMovementDelay(ScriptState *script) {
- debugC(3, kDebugLevelScriptFuncs, "o1_restoreBrandonsMovementDelay(%p) ()", (const void *)script);
+ debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1restoreBrandonsMovementDelay(%p) ()", (const void *)script);
setWalkspeed(_configWalkspeed);
return 0;
}
int KyraEngine_v1::o1_setMousePos(ScriptState *script) {
- debugC(3, kDebugLevelScriptFuncs, "o1_setMousePos(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1));
+ debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1setMousePos(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1));
_system->warpMouse(stackPos(0), stackPos(1));
return 0;
}
int KyraEngine_v1::o1_getMouseState(ScriptState *script) {
- debugC(3, kDebugLevelScriptFuncs, "o1_getMouseState(%p) ()", (const void *)script);
+ debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1getMouseState(%p) ()", (const void *)script);
return _mouseState;
}
int KyraEngine_v1::o1_setEntranceMouseCursorTrack(ScriptState *script) {
- debugC(3, kDebugLevelScriptFuncs, "o1_setEntranceMouseCursorTrack(%p) (%d, %d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3), stackPos(4));
+ debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1setEntranceMouseCursorTrack(%p) (%d, %d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3), stackPos(4));
_entranceMouseCursorTracks[0] = stackPos(0);
_entranceMouseCursorTracks[1] = stackPos(1);
_entranceMouseCursorTracks[2] = stackPos(0) + stackPos(2) - 1;
@@ -1532,19 +1531,19 @@ int KyraEngine_v1::o1_setEntranceMouseCursorTrack(ScriptState *script) {
}
int KyraEngine_v1::o1_itemAppearsOnGround(ScriptState *script) {
- debugC(3, kDebugLevelScriptFuncs, "o1_itemAppearsOnGround(%p) (%d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2));
+ debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1itemAppearsOnGround(%p) (%d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2));
processItemDrop(_currentCharacter->sceneId, stackPos(0), stackPos(1), stackPos(2), 2, 0);
return 0;
}
int KyraEngine_v1::o1_setNoDrawShapesFlag(ScriptState *script) {
- debugC(3, kDebugLevelScriptFuncs, "o1_setNoDrawShapesFlag(%p) (%d)", (const void *)script, stackPos(0));
+ debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1setNoDrawShapesFlag(%p) (%d)", (const void *)script, stackPos(0));
_animator->_noDrawShapesFlag = stackPos(0);
return 0;
}
int KyraEngine_v1::o1_fadeEntirePalette(ScriptState *script) {
- debugC(3, kDebugLevelScriptFuncs, "o1_fadeEntirePalette(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1));
+ debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1fadeEntirePalette(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1));
int cmd = stackPos(0);
uint8 *fadePal = 0;
@@ -1584,7 +1583,7 @@ int KyraEngine_v1::o1_fadeEntirePalette(ScriptState *script) {
}
int KyraEngine_v1::o1_itemOnGroundHere(ScriptState *script) {
- debugC(3, kDebugLevelScriptFuncs, "o1_itemOnGroundHere(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1));
+ debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1itemOnGroundHere(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1));
assert(stackPos(0) < _roomTableSize);
Room *curRoom = &_roomTable[stackPos(0)];
for (int i = 0; i < 12; ++i) {
@@ -1595,18 +1594,18 @@ int KyraEngine_v1::o1_itemOnGroundHere(ScriptState *script) {
}
int KyraEngine_v1::o1_queryCauldronState(ScriptState *script) {
- debugC(3, kDebugLevelScriptFuncs, "o1_queryCauldronState(%p) ()", (const void *)script);
+ debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1queryCauldronState(%p) ()", (const void *)script);
return _cauldronState;
}
int KyraEngine_v1::o1_setCauldronState(ScriptState *script) {
- debugC(3, kDebugLevelScriptFuncs, "o1_setCauldronState(%p) (%d)", (const void *)script, stackPos(0));
+ debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1setCauldronState(%p) (%d)", (const void *)script, stackPos(0));
_cauldronState = stackPos(0);
return _cauldronState;
}
int KyraEngine_v1::o1_queryCrystalState(ScriptState *script) {
- debugC(3, kDebugLevelScriptFuncs, "o1_queryCrystalState(%p) (%d)", (const void *)script, stackPos(0));
+ debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1queryCrystalState(%p) (%d)", (const void *)script, stackPos(0));
if (!stackPos(0))
return _crystalState[0];
else if (stackPos(0) == 1)
@@ -1615,7 +1614,7 @@ int KyraEngine_v1::o1_queryCrystalState(ScriptState *script) {
}
int KyraEngine_v1::o1_setCrystalState(ScriptState *script) {
- debugC(3, kDebugLevelScriptFuncs, "o1_setCrystalState(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1));
+ debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1setCrystalState(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1));
if (!stackPos(0))
_crystalState[0] = stackPos(1);
else if (stackPos(0) == 1)
@@ -1629,7 +1628,7 @@ int KyraEngine_v1::o1_setPaletteRange(ScriptState *script) {
}
int KyraEngine_v1::o1_shrinkBrandonDown(ScriptState *script) {
- debugC(3, kDebugLevelScriptFuncs, "o1_shrinkBrandonDown(%p) (%d)", (const void *)script, stackPos(0));
+ debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1shrinkBrandonDown(%p) (%d)", (const void *)script, stackPos(0));
int delayTime = stackPos(0);
checkAmuletAnimFlags();
int scaleValue = _scaleTable[_currentCharacter->y1];
@@ -1655,7 +1654,7 @@ int KyraEngine_v1::o1_shrinkBrandonDown(ScriptState *script) {
}
int KyraEngine_v1::o1_growBrandonUp(ScriptState *script) {
- debugC(3, kDebugLevelScriptFuncs, "o1_growBrandonUp(%p) ()", (const void *)script);
+ debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1growBrandonUp(%p) ()", (const void *)script);
int scaleValue = _scaleTable[_currentCharacter->y1];
int scale = 0;
if (_scaleMode)
@@ -1676,26 +1675,26 @@ int KyraEngine_v1::o1_growBrandonUp(ScriptState *script) {
}
int KyraEngine_v1::o1_setBrandonScaleXAndY(ScriptState *script) {
- debugC(3, kDebugLevelScriptFuncs, "o1_setBrandonScaleXAndY(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1));
+ debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1setBrandonScaleXAndY(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1));
_animator->_brandonScaleX = stackPos(0);
_animator->_brandonScaleY = stackPos(1);
return 0;
}
int KyraEngine_v1::o1_resetScaleMode(ScriptState *script) {
- debugC(3, kDebugLevelScriptFuncs, "o1_resetScaleMode(%p) ()", (const void *)script);
+ debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1resetScaleMode(%p) ()", (const void *)script);
_scaleMode = 0;
return 0;
}
int KyraEngine_v1::o1_getScaleDepthTableValue(ScriptState *script) {
- debugC(3, kDebugLevelScriptFuncs, "o1_getScaleDepthTableValue(%p) (%d)", (const void *)script, stackPos(0));
+ debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1getScaleDepthTableValue(%p) (%d)", (const void *)script, stackPos(0));
assert(stackPos(0) < ARRAYSIZE(_scaleTable));
return _scaleTable[stackPos(0)];
}
int KyraEngine_v1::o1_setScaleDepthTableValue(ScriptState *script) {
- debugC(3, kDebugLevelScriptFuncs, "o1_setScaleDepthTableValue(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1));
+ debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1setScaleDepthTableValue(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1));
assert(stackPos(0) < ARRAYSIZE(_scaleTable));
_scaleTable[stackPos(0)] = stackPos(1);
return stackPos(1);
@@ -1703,10 +1702,10 @@ int KyraEngine_v1::o1_setScaleDepthTableValue(ScriptState *script) {
int KyraEngine_v1::o1_message(ScriptState *script) {
if (_flags.isTalkie) {
- debugC(3, kDebugLevelScriptFuncs, "o1_message(%p) (%d, '%s', %d)", (const void *)script, stackPos(0), stackPosString(1), stackPos(2));
+ debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1message(%p) (%d, '%s', %d)", (const void *)script, stackPos(0), stackPosString(1), stackPos(2));
drawSentenceCommand(stackPosString(1), stackPos(2));
} else {
- debugC(3, kDebugLevelScriptFuncs, "o1_message(%p) ('%s', %d)", (const void *)script, stackPosString(0), stackPos(1));
+ debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1message(%p) ('%s', %d)", (const void *)script, stackPosString(0), stackPos(1));
drawSentenceCommand(stackPosString(0), stackPos(1));
}
@@ -1714,38 +1713,38 @@ int KyraEngine_v1::o1_message(ScriptState *script) {
}
int KyraEngine_v1::o1_checkClickOnNPC(ScriptState *script) {
- debugC(3, kDebugLevelScriptFuncs, "o1_checkClickOnNPC(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1));
+ debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1checkClickOnNPC(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1));
return checkForNPCScriptRun(stackPos(0), stackPos(1));
}
int KyraEngine_v1::o1_getFoyerItem(ScriptState *script) {
- debugC(3, kDebugLevelScriptFuncs, "o1_getFoyerItem(%p) (%d)", (const void *)script, stackPos(0));
+ debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1getFoyerItem(%p) (%d)", (const void *)script, stackPos(0));
assert(stackPos(0) < ARRAYSIZE(_foyerItemTable));
return _foyerItemTable[stackPos(0)];
}
int KyraEngine_v1::o1_setFoyerItem(ScriptState *script) {
- debugC(3, kDebugLevelScriptFuncs, "o1_setFoyerItem(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1));
+ debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1setFoyerItem(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1));
assert(stackPos(0) < ARRAYSIZE(_foyerItemTable));
_foyerItemTable[stackPos(0)] = stackPos(1);
return stackPos(1);
}
int KyraEngine_v1::o1_setNoItemDropRegion(ScriptState *script) {
- debugC(3, kDebugLevelScriptFuncs, "o1_setNoItemDropRegion(%p) (%d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3));
+ debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1setNoItemDropRegion(%p) (%d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3));
addToNoDropRects(stackPos(0), stackPos(1), stackPos(2), stackPos(3));
return 0;
}
int KyraEngine_v1::o1_walkMalcolmOn(ScriptState *script) {
- debugC(3, kDebugLevelScriptFuncs, "o1_walkMalcolmOn(%p) ()", (const void *)script);
+ debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1walkMalcolmOn(%p) ()", (const void *)script);
if (!_malcolmFlag)
_malcolmFlag = 1;
return 0;
}
int KyraEngine_v1::o1_passiveProtection(ScriptState *script) {
- debugC(3, kDebugLevelScriptFuncs, "o1_passiveProtection(%p) ()", (const void *)script);
+ debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1passiveProtection(%p) ()", (const void *)script);
return 1;
}
@@ -1755,24 +1754,24 @@ int KyraEngine_v1::o1_setPlayingLoop(ScriptState *script) {
}
int KyraEngine_v1::o1_brandonToStoneSequence(ScriptState *script) {
- debugC(3, kDebugLevelScriptFuncs, "o1_brandonToStoneSequence(%p) ()", (const void *)script);
+ debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1brandonToStoneSequence(%p) ()", (const void *)script);
seq_brandonToStone();
return 0;
}
int KyraEngine_v1::o1_brandonHealingSequence(ScriptState *script) {
- debugC(3, kDebugLevelScriptFuncs, "o1_brandonHealingSequence(%p) ()", (const void *)script);
+ debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1brandonHealingSequence(%p) ()", (const void *)script);
seq_brandonHealing();
return 0;
}
int KyraEngine_v1::o1_protectCommandLine(ScriptState *script) {
- debugC(3, kDebugLevelScriptFuncs, "o1_protectCommandLine(%p) (%d)", (const void *)script, stackPos(0));
+ debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1protectCommandLine(%p) (%d)", (const void *)script, stackPos(0));
return stackPos(0);
}
int KyraEngine_v1::o1_pauseMusicSeconds(ScriptState *script) {
- debugC(3, kDebugLevelScriptFuncs, "o1_pauseMusicSeconds(%p) ()", (const void *)script);
+ debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1pauseMusicSeconds(%p) ()", (const void *)script);
// if music disabled
// return
o1_pauseSeconds(script);
@@ -1785,13 +1784,13 @@ int KyraEngine_v1::o1_resetMaskRegion(ScriptState *script) {
}
int KyraEngine_v1::o1_setPaletteChangeFlag(ScriptState *script) {
- debugC(3, kDebugLevelScriptFuncs, "o1_setPaletteChangeFlag(%p) (%d)", (const void *)script, stackPos(0));
+ debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1setPaletteChangeFlag(%p) (%d)", (const void *)script, stackPos(0));
_paletteChanged = stackPos(0);
return _paletteChanged;
}
int KyraEngine_v1::o1_fillRect(ScriptState *script) {
- debugC(3, kDebugLevelScriptFuncs, "o1_fillRect(%p) (%d, %d, %d, %d, %d, 0x%X)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3), stackPos(4), stackPos(5));
+ debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1fillRect(%p) (%d, %d, %d, %d, %d, 0x%X)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3), stackPos(4), stackPos(5));
int videoPageBackup = _screen->_curPage;
_screen->_curPage = stackPos(0);
_screen->fillRect(stackPos(1), stackPos(2), stackPos(3), stackPos(4), stackPos(5));
@@ -1800,19 +1799,19 @@ int KyraEngine_v1::o1_fillRect(ScriptState *script) {
}
int KyraEngine_v1::o1_vocUnload(ScriptState *script) {
- debugC(3, kDebugLevelScriptFuncs, "o1_vocUnload(%p) ()", (const void *)script);
+ debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1vocUnload(%p) ()", (const void *)script);
// this should unload all voc files (not needed)
return 0;
}
int KyraEngine_v1::o1_vocLoad(ScriptState *script) {
- debugC(3, kDebugLevelScriptFuncs, "o1_vocLoad(%p) (%d)", (const void *)script, stackPos(0));
+ debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1vocLoad(%p) (%d)", (const void *)script, stackPos(0));
// this should load the specified voc file (not needed)
return 0;
}
int KyraEngine_v1::o1_dummy(ScriptState *script) {
- debugC(3, kDebugLevelScriptFuncs, "o1_dummy(%p) ()", (const void *)script);
+ debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v1::o1dummy(%p) ()", (const void *)script);
return 0;
}
diff --git a/engines/kyra/script_v2.cpp b/engines/kyra/script_v2.cpp
new file mode 100644
index 0000000000..3e1bc4ed2f
--- /dev/null
+++ b/engines/kyra/script_v2.cpp
@@ -0,0 +1,430 @@
+/* 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 "kyra/kyra_v2.h"
+#include "kyra/wsamovie.h"
+
+#include "common/endian.h"
+
+namespace Kyra {
+
+int KyraEngine_v2::o2_setCharacterFacingRefresh(ScriptState *script) {
+ debugC(3, kDebugLevelScriptFuncs, "o2_setCharacterFacingRefresh(%p) (-, %d, %d)", (const void *)script, stackPos(1), stackPos(2));
+ int animFrame = stackPos(2);
+ if (animFrame >= 0)
+ _mainCharacter.animFrame = animFrame;
+ _mainCharacter.facing = stackPos(1);
+ updateCharacterAnim(0);
+ refreshAnimObjectsIfNeed();
+ return 0;
+}
+
+int KyraEngine_v2::o2_defineObject(ScriptState *script) {
+ debugC(3, kDebugLevelScriptFuncs, "o2_defineObject(%p) (%d, '%s', %d, %d, %d, %d)", (const void *)script,
+ stackPos(0), stackPosString(1), stackPos(2), stackPos(3), stackPos(4), stackPos(5));
+ Object *object = &_objectList[stackPos(0)];
+ strcpy(object->filename, stackPosString(1));
+ object->scriptId = stackPos(2);
+ object->x = stackPos(3);
+ object->y = stackPos(4);
+ object->unk12 = stackPos(5);
+ return 0;
+}
+
+int KyraEngine_v2::o2_refreshCharacter(ScriptState *script) {
+ debugC(3, kDebugLevelScriptFuncs, "o2_refreshCharacter(%p) (-, %d, %d, %d)", (const void *)script, stackPos(1), stackPos(2), stackPos(3));
+ int unk = stackPos(1);
+ int facing = stackPos(2);
+ int refresh = stackPos(3);
+ if (facing >= 0)
+ _mainCharacter.facing = facing;
+ if (unk >= 0 && unk != 32)
+ _mainCharacter.animFrame = _characterFrameTable[_mainCharacter.facing];
+ updateCharacterAnim(0);
+ if (refresh)
+ refreshAnimObjectsIfNeed();
+ return 0;
+}
+
+int KyraEngine_v2::o2_getCharacterX(ScriptState *script) {
+ debugC(3, kDebugLevelScriptFuncs, "o2_getCharacterX(%p) ()", (const void *)script);
+ return _mainCharacter.x1;
+}
+
+int KyraEngine_v2::o2_getCharacterY(ScriptState *script) {
+ debugC(3, kDebugLevelScriptFuncs, "o2_getCharacterY(%p) ()", (const void *)script);
+ return _mainCharacter.y1;
+}
+
+int KyraEngine_v2::o2_getCharacterFacing(ScriptState *script) {
+ debugC(3, kDebugLevelScriptFuncs, "o2_getCharacterFacing(%p) ()", (const void *)script);
+ return _mainCharacter.facing;
+}
+
+int KyraEngine_v2::o2_setSceneComment(ScriptState *script) {
+ debugC(3, kDebugLevelScriptFuncs, "o2_setSceneComment(%p) ('%s')", (const void *)script, stackPosString(0));
+ _sceneCommentString = stackPosString(0);
+ return 0;
+}
+
+int KyraEngine_v2::o2_showChapterMessage(ScriptState *script) {
+ debugC(3, kDebugLevelScriptFuncs, "o2_showChapterMessage(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1));
+ showChapterMessage(stackPos(0), stackPos(1));
+ return 0;
+}
+
+int KyraEngine_v2::o2_wsaClose(ScriptState *script) {
+ debugC(3, kDebugLevelScriptFuncs, "o2_wsaClose(%p) (%d)", (const void *)script, stackPos(0));
+ assert(stackPos(0) >= 0 && stackPos(0) < ARRAYSIZE(_wsaSlots));
+ _wsaSlots[stackPos(0)]->close();
+ return 0;
+}
+
+int KyraEngine_v2::o2_displayWsaFrame(ScriptState *script) {
+ debugC(3, kDebugLevelScriptFuncs, "o2_displayWsaFrame(%p) (%d, %d, %d, %d, %d, %d, %d, %d, %d)", (const void *)script,
+ stackPos(0), stackPos(1), stackPos(2), stackPos(3), stackPos(4), stackPos(5), stackPos(6), stackPos(7), stackPos(8));
+ int frame = stackPos(0);
+ int x = stackPos(1);
+ int y = stackPos(2);
+ int waitTime = stackPos(3);
+ int slot = stackPos(4);
+ int copyParam = stackPos(5);
+ int doUpdate = stackPos(6);
+ int dstPage = stackPos(7);
+ int backUp = stackPos(8);
+
+ _screen->hideMouse();
+ uint32 endTime = _system->getMillis() + waitTime * _tickLength;
+ _wsaSlots[slot]->setX(x);
+ _wsaSlots[slot]->setY(y);
+ _wsaSlots[slot]->setDrawPage(dstPage);
+ _wsaSlots[slot]->displayFrame(frame, copyParam | 0xC000);
+ _screen->updateScreen();
+
+ if (backUp)
+ memcpy(_gamePlayBuffer, _screen->getCPagePtr(3), 46080);
+
+ while (_system->getMillis() < endTime) {
+ if (doUpdate)
+ update();
+
+ if (endTime - _system->getMillis() >= 10)
+ delay(10);
+ }
+ _screen->showMouse();
+ return 0;
+}
+
+int KyraEngine_v2::o2_displayWsaSequentialFrames(ScriptState *script) {
+ debugC(3, kDebugLevelScriptFuncs, "o2_displayWsaSequentialFrames(%p) (%d, %d, %d, %d, %d, %d, %d, %d)", (const void *)script,
+ stackPos(0), stackPos(1), stackPos(2), stackPos(3), stackPos(4), stackPos(5), stackPos(6), stackPos(7));
+ int startFrame = stackPos(0);
+ int endFrame = stackPos(1);
+ int x = stackPos(2);
+ int y = stackPos(3);
+ int waitTime = stackPos(4);
+ int slot = stackPos(5);
+ int maxTimes = stackPos(6);
+ int copyFlags = stackPos(7);
+
+ if (maxTimes > 1)
+ maxTimes = 1;
+
+ _wsaSlots[slot]->setX(x);
+ _wsaSlots[slot]->setY(y);
+ _wsaSlots[slot]->setDrawPage(0);
+
+ _screen->hideMouse();
+ int curTime = 0;
+ while (curTime < maxTimes) {
+ if (startFrame < endFrame) {
+ for (int i = startFrame; i <= endFrame; ++i) {
+ uint32 endTime = _system->getMillis() + waitTime * _tickLength;
+ _wsaSlots[slot]->displayFrame(i, 0xC000 | copyFlags);
+ _screen->updateScreen();
+
+ do {
+ update();
+
+ if (endTime - _system->getMillis() >= 10)
+ delay(10);
+ } while (_system->getMillis() < endTime);
+ }
+ } else {
+ for (int i = startFrame; i >= endFrame; --i) {
+ uint32 endTime = _system->getMillis() + waitTime * _tickLength;
+ _wsaSlots[slot]->displayFrame(i, 0xC000 | copyFlags);
+ _screen->updateScreen();
+
+ do {
+ update();
+
+ if (endTime - _system->getMillis() >= 10)
+ delay(10);
+ } while (_system->getMillis() < endTime);
+ }
+ }
+
+ ++curTime;
+ }
+ _screen->showMouse();
+ return 0;
+}
+
+int KyraEngine_v2::o2_wsaOpen(ScriptState *script) {
+ debugC(3, kDebugLevelScriptFuncs, "o2_wsaOpen(%p) ('%s', %d)", (const void *)script, stackPosString(0), stackPos(1));
+ assert(stackPos(1) >= 0 && stackPos(1) < ARRAYSIZE(_wsaSlots));
+ _wsaSlots[stackPos(1)]->open(stackPosString(0), 1, 0);
+ return 0;
+}
+
+int KyraEngine_v2::o2_defineItem(ScriptState *script) {
+ debugC(3, kDebugLevelScriptFuncs, "o2_defineItem(%p) (%d, %d, %d, %d)", (const void *)script,
+ stackPos(0), stackPos(1), stackPos(2), stackPos(3));
+ int freeItem = findFreeItem();
+
+ if (freeItem >= 0) {
+ _itemList[freeItem].id = stackPos(0);
+ _itemList[freeItem].x = stackPos(1);
+ _itemList[freeItem].y = stackPos(2);
+ _itemList[freeItem].sceneId = stackPos(3);
+ }
+
+ return freeItem;
+}
+
+int KyraEngine_v2::o2_queryGameFlag(ScriptState *script) {
+ debugC(3, kDebugLevelScriptFuncs, "o2_queryGameFlag(%p) (%d)", (const void *)script, stackPos(0));
+ return queryGameFlag(stackPos(0));
+}
+
+int KyraEngine_v2::o2_resetGameFlag(ScriptState *script) {
+ debugC(3, kDebugLevelScriptFuncs, "o2_resetGameFlag(%p) (%d)", (const void *)script, stackPos(0));
+ return resetGameFlag(stackPos(0));
+}
+
+int KyraEngine_v2::o2_setGameFlag(ScriptState *script) {
+ debugC(3, kDebugLevelScriptFuncs, "o2_setGameFlag(%p) (%d)", (const void *)script, stackPos(0));
+ return setGameFlag(stackPos(0));
+}
+
+int KyraEngine_v2::o2_hideMouse(ScriptState *script) {
+ debugC(3, kDebugLevelScriptFuncs, "o2_hideMouse(%p) ()", (const void *)script);
+ _screen->hideMouse();
+ return 0;
+}
+
+int KyraEngine_v2::o2_addSpecialExit(ScriptState *script) {
+ debugC(3, kDebugLevelScriptFuncs, "o2_addSpecialExit(%p) (%d, %d, %d, %d, %d)", (const void *)script,
+ stackPos(0), stackPos(1), stackPos(2), stackPos(3), stackPos(4));
+ if (_specialExitCount < 5) {
+ _specialExitTable[_specialExitCount+0] = stackPos(0);
+ _specialExitTable[_specialExitCount+5] = stackPos(1);
+ _specialExitTable[_specialExitCount+10] = stackPos(2);
+ _specialExitTable[_specialExitCount+15] = stackPos(3);
+ _specialExitTable[_specialExitCount+20] = stackPos(4);
+ ++_specialExitCount;
+ }
+ return 0;
+}
+
+int KyraEngine_v2::o2_showMouse(ScriptState *script) {
+ debugC(3, kDebugLevelScriptFuncs, "o2_showMouse(%p) ()", (const void *)script);
+ _screen->showMouse();
+ return 0;
+}
+
+int KyraEngine_v2::o2_setScaleTableItem(ScriptState *script) {
+ debugC(3, kDebugLevelScriptFuncs, "o2_setScaleTableItem(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1));
+ setScaleTableItem(stackPos(0), stackPos(1));
+ return 0;
+}
+
+int KyraEngine_v2::o2_setDrawLayerTableItem(ScriptState *script) {
+ debugC(3, kDebugLevelScriptFuncs, "o2_setDrawLayerTableItem(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1));
+ setDrawLayerTableEntry(stackPos(0), stackPos(1));
+ return 0;
+}
+
+int KyraEngine_v2::o2_drawSceneShapeOnPage(ScriptState *script) {
+ debugC(3, kDebugLevelScriptFuncs, "o2_drawSceneShapeOnPage(%p) (%d, %d, %d, %d, %d)", (const void *)script,
+ stackPos(0), stackPos(1), stackPos(2), stackPos(3), stackPos(4));
+ int shape = stackPos(0);
+ int x = stackPos(1);
+ int y = stackPos(2);
+ int flag = stackPos(3);
+ int drawPage = stackPos(4);
+ _screen->drawShape(drawPage, _sceneShapeTable[shape], x, y, 2, flag ? 1 : 0);
+ return 0;
+}
+
+int KyraEngine_v2::o2_restoreBackBuffer(ScriptState *script) {
+ debugC(3, kDebugLevelScriptFuncs, "o2_restoreBackBuffer(%p) (%d)", (const void *)script, stackPos(0));
+ int disable = stackPos(0);
+ int oldState = 0;
+ if (disable) {
+ oldState = _animObjects[0].enabled;
+ _animObjects[0].enabled = 0;
+ }
+ restorePage3();
+ if (disable)
+ _animObjects[0].enabled = oldState;
+ return 0;
+}
+
+int KyraEngine_v2::o2_getRand(ScriptState *script) {
+ debugC(3, kDebugLevelScriptFuncs, "o2_getRand(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1));
+ assert(stackPos(0) < stackPos(1));
+ return _rnd.getRandomNumberRng(stackPos(0), stackPos(1));
+}
+
+int KyraEngine_v2::o2_encodeShape(ScriptState *script) {
+ debugC(3, kDebugLevelScriptFuncs, "o2_encodeShape(%p) (%d, %d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1),
+ stackPos(2), stackPos(3), stackPos(4));
+ _sceneShapeTable[stackPos(0)] = _screen->encodeShape(stackPos(1), stackPos(2), stackPos(3), stackPos(4), 2);
+ return 0;
+}
+
+int KyraEngine_v2::o2_defineRoomEntrance(ScriptState *script) {
+ debugC(3, kDebugLevelScriptFuncs, "o2_defineRoomEntrance(%p) (%d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2));
+ switch (stackPos(0)) {
+ case 0:
+ _sceneEnterX1 = stackPos(1);
+ _sceneEnterY1 = stackPos(2);
+ break;
+
+ case 1:
+ _sceneEnterX2 = stackPos(1);
+ _sceneEnterY2 = stackPos(2);
+ break;
+
+ case 2:
+ _sceneEnterX3 = stackPos(1);
+ _sceneEnterY3 = stackPos(2);
+ break;
+
+ case 3:
+ _sceneEnterX4 = stackPos(1);
+ _sceneEnterY4 = stackPos(2);
+ break;
+
+ default:
+ break;
+ }
+ return 0;
+}
+
+int KyraEngine_v2::o2_setSpecialSceneScriptRunTime(ScriptState *script) {
+ debugC(3, kDebugLevelScriptFuncs, "o2_setSpecialSceneScriptRunTime(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1));
+ assert(stackPos(0) >= 0 && stackPos(0) < 10);
+ _sceneSpecialScriptsTimer[stackPos(0)] = _system->getMillis() + stackPos(1) * _tickLength;
+ return 0;
+}
+
+int KyraEngine_v2::o2_defineSceneAnim(ScriptState *script) {
+ debugC(3, kDebugLevelScriptFuncs, "o2_defineSceneAnim(%p) (%d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, '%s')", (const void *)script,
+ stackPos(0), stackPos(1), stackPos(2), stackPos(3), stackPos(4), stackPos(5), stackPos(6), stackPos(7), stackPos(8),
+ stackPos(9), stackPos(10), stackPos(11), stackPosString(12));
+ int animId = stackPos(0);
+ SceneAnim &anim = _sceneAnims[animId];
+ anim.flags = stackPos(1);
+ anim.x = stackPos(2);
+ anim.y = stackPos(3);
+ anim.x2 = stackPos(4);
+ anim.y2 = stackPos(5);
+ anim.width = stackPos(6);
+ anim.height = stackPos(7);
+ anim.unkE = stackPos(8);
+ anim.specialSize = stackPos(9);
+ anim.unk12 = stackPos(10);
+ anim.shapeIndex = stackPos(11);
+ if (stackPosString(12) != 0)
+ strcpy(anim.filename, stackPosString(12));
+
+ if (anim.flags & 0x40) {
+ if (!_sceneAnimMovie[animId]->open(anim.filename, 1, 0))
+ error("couldn't load '%s'", anim.filename);
+
+ if (_sceneAnimMovie[animId]->xAdd() || _sceneAnimMovie[animId]->yAdd())
+ anim.wsaFlag = 1;
+ else
+ anim.wsaFlag = 0;
+ }
+
+ return 0;
+}
+
+int KyraEngine_v2::o2_updateSceneAnim(ScriptState *script) {
+ debugC(3, kDebugLevelScriptFuncs, "o2_updateSceneAnim(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1));
+ updateSceneAnim(stackPos(0), stackPos(1));
+ _specialSceneScriptRunFlag = false;
+ return 0;
+}
+
+int KyraEngine_v2::o2_defineRoom(ScriptState *script) {
+ debugC(3, kDebugLevelScriptFuncs, "o2_defineRoom(%p) (%d, '%s', %d, %d, %d, %d, %d, %d)", (const void *)script,
+ stackPos(0), stackPosString(1), stackPos(2), stackPos(3), stackPos(4), stackPos(5), stackPos(6), stackPos(7));
+ SceneDesc *scene = &_sceneList[stackPos(0)];
+ strcpy(scene->filename, stackPosString(1));
+ scene->exit1 = stackPos(2);
+ scene->exit2 = stackPos(3);
+ scene->exit3 = stackPos(4);
+ scene->exit4 = stackPos(5);
+ scene->flags = stackPos(6);
+ scene->sound = stackPos(7);
+
+ if (_mainCharacter.sceneId == stackPos(0)) {
+ _sceneExit1 = scene->exit1;
+ _sceneExit2 = scene->exit2;
+ _sceneExit3 = scene->exit3;
+ _sceneExit4 = scene->exit4;
+ }
+
+ return 0;
+}
+
+int KyraEngine_v2::o2_setSpecialSceneScriptState(ScriptState *script) {
+ debugC(3, kDebugLevelScriptFuncs, "o2_setSpecialSceneScriptState(%p) (%d)", (const void *)script, stackPos(0));
+ _specialSceneScriptState[stackPos(0)] = 1;
+ return 1;
+}
+
+int KyraEngine_v2::o2_clearSpecialSceneScriptState(ScriptState *script) {
+ debugC(3, kDebugLevelScriptFuncs, "o2_clearSpecialSceneScriptState(%p) (%d)", (const void *)script, stackPos(0));
+ _specialSceneScriptState[stackPos(0)] = 0;
+ return 0;
+}
+
+int KyraEngine_v2::o2_querySpecialSceneScriptState(ScriptState *script) {
+ debugC(3, kDebugLevelScriptFuncs, "o2_querySpecialSceneScriptState(%p) (%d)", (const void *)script, stackPos(0));
+ return _specialSceneScriptState[stackPos(0)];
+}
+
+int KyraEngine_v2::o2_dummy(ScriptState *script) {
+ debugC(3, kDebugLevelScriptFuncs, "o2_dummy(%p) ()", (const void *)script);
+ return 0;
+}
+
+} // end of namespace Kyra
diff --git a/engines/kyra/seqplayer.cpp b/engines/kyra/seqplayer.cpp
index ba221bf35a..20a98c66c1 100644
--- a/engines/kyra/seqplayer.cpp
+++ b/engines/kyra/seqplayer.cpp
@@ -28,7 +28,6 @@
#include "engines/engine.h"
-#include "kyra/kyra.h"
#include "kyra/resource.h"
#include "kyra/screen.h"
#include "kyra/sound.h"
@@ -41,7 +40,7 @@
namespace Kyra {
-SeqPlayer::SeqPlayer(KyraEngine* vm, OSystem* system) {
+SeqPlayer::SeqPlayer(KyraEngine_v1 *vm, OSystem *system) {
_vm = vm;
_system = system;
diff --git a/engines/kyra/seqplayer.h b/engines/kyra/seqplayer.h
index 0fba0403e4..4636a956e9 100644
--- a/engines/kyra/seqplayer.h
+++ b/engines/kyra/seqplayer.h
@@ -26,11 +26,13 @@
#ifndef KYRA_SEQPLAYER_H
#define KYRA_SEQPLAYER_H
+#include "kyra/kyra_v1.h"
+
namespace Kyra {
class SeqPlayer {
public:
- SeqPlayer(KyraEngine* vm, OSystem* system);
+ SeqPlayer(KyraEngine_v1 *vm, OSystem *system);
~SeqPlayer();
void setCopyViewOffs(bool offs) {
@@ -43,9 +45,8 @@ public:
bool playSequence(const uint8 *seqData, bool skipSeq);
uint8 *setPanPages(int pageNum, int shape);
-
protected:
- KyraEngine *_vm;
+ KyraEngine_v1 *_vm;
OSystem *_system;
Screen *_screen;
Sound *_sound;
diff --git a/engines/kyra/sequences_v1.cpp b/engines/kyra/sequences_v1.cpp
index 1b4c0f680a..3bba3406a8 100644
--- a/engines/kyra/sequences_v1.cpp
+++ b/engines/kyra/sequences_v1.cpp
@@ -25,13 +25,14 @@
#include "kyra/kyra.h"
#include "kyra/seqplayer.h"
-#include "kyra/screen.h"
+#include "kyra/screen_v1.h"
#include "kyra/resource.h"
#include "kyra/sound.h"
#include "kyra/sprites.h"
#include "kyra/wsamovie.h"
-#include "kyra/animator.h"
+#include "kyra/animator_v1.h"
#include "kyra/text.h"
+#include "kyra/timer.h"
#include "common/events.h"
#include "common/system.h"
@@ -39,8 +40,8 @@
namespace Kyra {
-void KyraEngine::seq_demo() {
- debugC(9, kDebugLevelMain, "KyraEngine::seq_demo()");
+void KyraEngine_v1::seq_demo() {
+ debugC(9, kDebugLevelMain, "KyraEngine_v1::seq_demo()");
snd_playTheme(0, 2);
@@ -89,18 +90,18 @@ void KyraEngine::seq_demo() {
_sound->haltTrack();
}
-void KyraEngine::seq_intro() {
- debugC(9, kDebugLevelMain, "KyraEngine::seq_intro()");
+void KyraEngine_v1::seq_intro() {
+ debugC(9, kDebugLevelMain, "KyraEngine_v1::seq_intro()");
if (_flags.isTalkie)
_res->loadPakFile("INTRO.VRM");
static const IntroProc introProcTable[] = {
- &KyraEngine::seq_introLogos,
- &KyraEngine::seq_introStory,
- &KyraEngine::seq_introMalcolmTree,
- &KyraEngine::seq_introKallakWriting,
- &KyraEngine::seq_introKallakMalcolm
+ &KyraEngine_v1::seq_introLogos,
+ &KyraEngine_v1::seq_introStory,
+ &KyraEngine_v1::seq_introMalcolmTree,
+ &KyraEngine_v1::seq_introKallakWriting,
+ &KyraEngine_v1::seq_introKallakMalcolm
};
Common::InSaveFile *in;
@@ -129,8 +130,8 @@ void KyraEngine::seq_intro() {
_res->unloadPakFile("INTRO.VRM");
}
-void KyraEngine::seq_introLogos() {
- debugC(9, kDebugLevelMain, "KyraEngine::seq_introLogos()");
+void KyraEngine_v1::seq_introLogos() {
+ debugC(9, kDebugLevelMain, "KyraEngine_v1::seq_introLogos()");
if (_flags.platform == Common::kPlatformFMTowns) {
_screen->loadBitmap("LOGO.CPS", 3, 3, _screen->_currentPalette);
@@ -231,14 +232,19 @@ void KyraEngine::seq_introLogos() {
_seq->playSequence(_seq_Forest, true);
}
-void KyraEngine::seq_introStory() {
- debugC(9, kDebugLevelMain, "KyraEngine::seq_introStory()");
+void KyraEngine_v1::seq_introStory() {
+ debugC(9, kDebugLevelMain, "KyraEngine_v1::seq_introStory()");
_screen->clearPage(3);
_screen->clearPage(0);
- if (_flags.isTalkie)
- return;
- else if (_flags.lang == Common::EN_ANY && (_flags.platform == Common::kPlatformPC || _flags.platform == Common::kPlatformAmiga))
+ if (_flags.isTalkie) {
+ // HACK: The Italian fan translation uses an special text screen here
+ // so we show it even though it is a talkie version.
+ if (_flags.lang == Common::IT_ITA)
+ _screen->loadBitmap("TEXT_ENG.CPS", 3, 3, 0);
+ else
+ return;
+ } else if (_flags.lang == Common::EN_ANY && (_flags.platform == Common::kPlatformPC || _flags.platform == Common::kPlatformAmiga))
_screen->loadBitmap("TEXT.CPS", 3, 3, _screen->_currentPalette);
else if (_flags.lang == Common::EN_ANY || _flags.lang == Common::JA_JPN)
_screen->loadBitmap("TEXT_ENG.CPS", 3, 3, _screen->_currentPalette);
@@ -273,15 +279,15 @@ void KyraEngine::seq_introStory() {
delay(360 * _tickLength);
}
-void KyraEngine::seq_introMalcolmTree() {
- debugC(9, kDebugLevelMain, "KyraEngine::seq_introMalcolmTree()");
+void KyraEngine_v1::seq_introMalcolmTree() {
+ debugC(9, kDebugLevelMain, "KyraEngine_v1::seq_introMalcolmTree()");
_screen->_curPage = 0;
_screen->clearPage(3);
_seq->playSequence(_seq_MalcolmTree, true);
}
-void KyraEngine::seq_introKallakWriting() {
- debugC(9, kDebugLevelMain, "KyraEngine::seq_introKallakWriting()");
+void KyraEngine_v1::seq_introKallakWriting() {
+ debugC(9, kDebugLevelMain, "KyraEngine_v1::seq_introKallakWriting()");
_seq->makeHandShapes();
_screen->setAnimBlockPtr(5060);
_screen->_charWidth = -2;
@@ -289,13 +295,13 @@ void KyraEngine::seq_introKallakWriting() {
_seq->playSequence(_seq_KallakWriting, true);
}
-void KyraEngine::seq_introKallakMalcolm() {
- debugC(9, kDebugLevelMain, "KyraEngine::seq_introKallakMalcolm()");
+void KyraEngine_v1::seq_introKallakMalcolm() {
+ debugC(9, kDebugLevelMain, "KyraEngine_v1::seq_introKallakMalcolm()");
_screen->clearPage(3);
_seq->playSequence(_seq_KallakMalcolm, true);
}
-void KyraEngine::seq_createAmuletJewel(int jewel, int page, int noSound, int drawOnly) {
+void KyraEngine_v1::seq_createAmuletJewel(int jewel, int page, int noSound, int drawOnly) {
debugC(9, kDebugLevelMain, "seq_createAmuletJewel(%d, %d, %d, %d)", jewel, page, noSound, drawOnly);
static const uint16 specialJewelTable[] = {
0x167, 0x162, 0x15D, 0x158, 0x153, 0xFFFF
@@ -355,7 +361,7 @@ void KyraEngine::seq_createAmuletJewel(int jewel, int page, int noSound, int dra
setGameFlag(0x55+jewel);
}
-void KyraEngine::seq_brandonHealing() {
+void KyraEngine_v1::seq_brandonHealing() {
debugC(9, kDebugLevelMain, "seq_brandonHealing()");
if (!(_deathHandler & 8))
return;
@@ -386,7 +392,7 @@ void KyraEngine::seq_brandonHealing() {
_screen->showMouse();
}
-void KyraEngine::seq_brandonHealing2() {
+void KyraEngine_v1::seq_brandonHealing2() {
debugC(9, kDebugLevelMain, "seq_brandonHealing2()");
_screen->hideMouse();
checkAmuletAnimFlags();
@@ -410,7 +416,7 @@ void KyraEngine::seq_brandonHealing2() {
characterSays(2011, _poisonGone[1], 0, -2);
}
-void KyraEngine::seq_poisonDeathNow(int now) {
+void KyraEngine_v1::seq_poisonDeathNow(int now) {
debugC(9, kDebugLevelMain, "seq_poisonDeathNow(%d)", now);
if (!(_brandonStatusBit & 1))
return;
@@ -431,7 +437,7 @@ void KyraEngine::seq_poisonDeathNow(int now) {
}
}
-void KyraEngine::seq_poisonDeathNowAnim() {
+void KyraEngine_v1::seq_poisonDeathNowAnim() {
debugC(9, kDebugLevelMain, "seq_poisonDeathNowAnim()");
_screen->hideMouse();
checkAmuletAnimFlags();
@@ -472,7 +478,7 @@ void KyraEngine::seq_poisonDeathNowAnim() {
_screen->showMouse();
}
-void KyraEngine::seq_playFluteAnimation() {
+void KyraEngine_v1::seq_playFluteAnimation() {
debugC(9, kDebugLevelMain, "seq_playFluteAnimation()");
_screen->hideMouse();
checkAmuletAnimFlags();
@@ -526,7 +532,7 @@ void KyraEngine::seq_playFluteAnimation() {
}
}
-void KyraEngine::seq_winterScroll1() {
+void KyraEngine_v1::seq_winterScroll1() {
debugC(9, kDebugLevelMain, "seq_winterScroll1()");
_screen->hideMouse();
checkAmuletAnimFlags();
@@ -607,7 +613,7 @@ void KyraEngine::seq_winterScroll1() {
_screen->showMouse();
}
-void KyraEngine::seq_winterScroll2() {
+void KyraEngine_v1::seq_winterScroll2() {
debugC(9, kDebugLevelMain, "seq_winterScroll2()");
_screen->hideMouse();
checkAmuletAnimFlags();
@@ -636,7 +642,7 @@ void KyraEngine::seq_winterScroll2() {
_screen->showMouse();
}
-void KyraEngine::seq_makeBrandonInv() {
+void KyraEngine_v1::seq_makeBrandonInv() {
debugC(9, kDebugLevelMain, "seq_makeBrandonInv()");
if (_deathHandler == 8)
return;
@@ -649,7 +655,7 @@ void KyraEngine::seq_makeBrandonInv() {
_screen->hideMouse();
checkAmuletAnimFlags();
_brandonStatusBit |= 0x20;
- setTimerCountdown(18, 2700);
+ _timer->setCountdown(18, 2700);
_brandonStatusBit |= 0x40;
snd_playSoundEffect(0x77);
_brandonInvFlag = 0;
@@ -662,7 +668,7 @@ void KyraEngine::seq_makeBrandonInv() {
_screen->showMouse();
}
-void KyraEngine::seq_makeBrandonNormal() {
+void KyraEngine_v1::seq_makeBrandonNormal() {
debugC(9, kDebugLevelMain, "seq_makeBrandonNormal()");
_screen->hideMouse();
_brandonStatusBit |= 0x40;
@@ -678,7 +684,7 @@ void KyraEngine::seq_makeBrandonNormal() {
_screen->showMouse();
}
-void KyraEngine::seq_makeBrandonNormal2() {
+void KyraEngine_v1::seq_makeBrandonNormal2() {
debugC(9, kDebugLevelMain, "seq_makeBrandonNormal2()");
_screen->hideMouse();
assert(_brandonToWispTable);
@@ -704,7 +710,7 @@ void KyraEngine::seq_makeBrandonNormal2() {
_screen->showMouse();
}
-void KyraEngine::seq_makeBrandonWisp() {
+void KyraEngine_v1::seq_makeBrandonWisp() {
debugC(9, kDebugLevelMain, "seq_makeBrandonWisp()");
if (_deathHandler == 8)
return;
@@ -727,9 +733,9 @@ void KyraEngine::seq_makeBrandonWisp() {
_brandonStatusBit |= 2;
if (_currentCharacter->sceneId >= 109 && _currentCharacter->sceneId <= 198)
- setTimerCountdown(14, 18000);
+ _timer->setCountdown(14, 18000);
else
- setTimerCountdown(14, 7200);
+ _timer->setCountdown(14, 7200);
_animator->_brandonDrawFrame = 113;
_brandonStatusBit0x02Flag = 1;
@@ -746,7 +752,7 @@ void KyraEngine::seq_makeBrandonWisp() {
_screen->showMouse();
}
-void KyraEngine::seq_dispelMagicAnimation() {
+void KyraEngine_v1::seq_dispelMagicAnimation() {
debugC(9, kDebugLevelMain, "seq_dispelMagicAnimation()");
if (_deathHandler == 8)
return;
@@ -788,7 +794,7 @@ void KyraEngine::seq_dispelMagicAnimation() {
_screen->showMouse();
}
-void KyraEngine::seq_fillFlaskWithWater(int item, int type) {
+void KyraEngine_v1::seq_fillFlaskWithWater(int item, int type) {
debugC(9, kDebugLevelMain, "seq_fillFlaskWithWater(%d, %d)", item, type);
int newItem = -1;
static const uint8 flaskTable1[] = { 0x46, 0x48, 0x4A, 0x4C };
@@ -821,8 +827,8 @@ void KyraEngine::seq_fillFlaskWithWater(int item, int type) {
characterSays(voiceEntries[type], _fullFlask[type], 0, -2);
}
-void KyraEngine::seq_playDrinkPotionAnim(int item, int unk2, int flags) {
- debugC(9, kDebugLevelMain, "KyraEngine::seq_playDrinkPotionAnim(%d, %d, %d)", item, unk2, flags);
+void KyraEngine_v1::seq_playDrinkPotionAnim(int item, int unk2, int flags) {
+ debugC(9, kDebugLevelMain, "KyraEngine_v1::seq_playDrinkPotionAnim(%d, %d, %d)", item, unk2, flags);
uint8 red, green, blue;
switch (item) {
@@ -913,8 +919,8 @@ void KyraEngine::seq_playDrinkPotionAnim(int item, int unk2, int flags) {
_screen->showMouse();
}
-int KyraEngine::seq_playEnd() {
- debugC(9, kDebugLevelMain, "KyraEngine::seq_playEnd()");
+int KyraEngine_v1::seq_playEnd() {
+ debugC(9, kDebugLevelMain, "KyraEngine_v1::seq_playEnd()");
if (_endSequenceSkipFlag)
return 0;
@@ -1006,8 +1012,8 @@ int KyraEngine::seq_playEnd() {
return 0;
}
-void KyraEngine::seq_brandonToStone() {
- debugC(9, kDebugLevelMain, "KyraEngine::seq_brandonToStone()");
+void KyraEngine_v1::seq_brandonToStone() {
+ debugC(9, kDebugLevelMain, "KyraEngine_v1::seq_brandonToStone()");
_screen->hideMouse();
assert(_brandonStoneTable);
setupShapes123(_brandonStoneTable, 14, 0);
@@ -1022,8 +1028,8 @@ void KyraEngine::seq_brandonToStone() {
_screen->showMouse();
}
-void KyraEngine::seq_playEnding() {
- debugC(9, kDebugLevelMain, "KyraEngine::seq_playEnding()");
+void KyraEngine_v1::seq_playEnding() {
+ debugC(9, kDebugLevelMain, "KyraEngine_v1::seq_playEnding()");
if (_quitFlag)
return;
_screen->hideMouse();
@@ -1046,8 +1052,8 @@ void KyraEngine::seq_playEnding() {
seq_playCredits();
}
-void KyraEngine::seq_playCredits() {
- debugC(9, kDebugLevelMain, "KyraEngine::seq_playCredits()");
+void KyraEngine_v1::seq_playCredits() {
+ debugC(9, kDebugLevelMain, "KyraEngine_v1::seq_playCredits()");
static const uint8 colorMap[] = { 0, 0, 0xC, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
static const char stringTerms[] = { 0x5, 0xd, 0x0};
static const int numStrings = 250;
@@ -1203,13 +1209,13 @@ void KyraEngine::seq_playCredits() {
_screen->showMouse();
}
-bool KyraEngine::seq_skipSequence() const {
- debugC(9, kDebugLevelMain, "KyraEngine::seq_skipSequence()");
+bool KyraEngine_v1::seq_skipSequence() const {
+ debugC(9, kDebugLevelMain, "KyraEngine_v1::seq_skipSequence()");
return _quitFlag || _abortIntroFlag;
}
-int KyraEngine::handleMalcolmFlag() {
- debugC(9, kDebugLevelMain, "KyraEngine::handleMalcolmFlag()");
+int KyraEngine_v1::handleMalcolmFlag() {
+ debugC(9, kDebugLevelMain, "KyraEngine_v1::handleMalcolmFlag()");
static uint16 frame = 0;
static uint32 timer1 = 0;
static uint32 timer2 = 0;
@@ -1377,8 +1383,8 @@ int KyraEngine::handleMalcolmFlag() {
return 0;
}
-int KyraEngine::handleBeadState() {
- debugC(9, kDebugLevelMain, "KyraEngine::handleBeadState()");
+int KyraEngine_v1::handleBeadState() {
+ debugC(9, kDebugLevelMain, "KyraEngine_v1::handleBeadState()");
static uint32 timer1 = 0;
static uint32 timer2 = 0;
static BeadState beadState1 = { -1, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
@@ -1597,8 +1603,8 @@ int KyraEngine::handleBeadState() {
return 0;
}
-void KyraEngine::initBeadState(int x, int y, int x2, int y2, int unk, BeadState *ptr) {
- debugC(9, kDebugLevelMain, "KyraEngine::initBeadState(%d, %d, %d, %d, %d, %p)", x, y, x2, y2, unk, (const void *)ptr);
+void KyraEngine_v1::initBeadState(int x, int y, int x2, int y2, int unk, BeadState *ptr) {
+ debugC(9, kDebugLevelMain, "KyraEngine_v1::initBeadState(%d, %d, %d, %d, %d, %p)", x, y, x2, y2, unk, (const void *)ptr);
ptr->unk9 = unk;
int xDiff = x2 - x;
int yDiff = y2 - y;
@@ -1631,8 +1637,8 @@ void KyraEngine::initBeadState(int x, int y, int x2, int y2, int unk, BeadState
ptr->unk8 = unk2;
}
-int KyraEngine::processBead(int x, int y, int &x2, int &y2, BeadState *ptr) {
- debugC(9, kDebugLevelMain, "KyraEngine::processBead(%d, %d, %p, %p, %p)", x, y, (const void *)&x2, (const void *)&y2, (const void *)ptr);
+int KyraEngine_v1::processBead(int x, int y, int &x2, int &y2, BeadState *ptr) {
+ debugC(9, kDebugLevelMain, "KyraEngine_v1::processBead(%d, %d, %p, %p, %p)", x, y, (const void *)&x2, (const void *)&y2, (const void *)ptr);
if (x == ptr->dstX && y == ptr->dstY)
return 1;
@@ -1668,8 +1674,8 @@ int KyraEngine::processBead(int x, int y, int &x2, int &y2, BeadState *ptr) {
return 0;
}
-void KyraEngine::setupPanPages() {
- debugC(9, kDebugLevelMain, "KyraEngine::setupPanPages()");
+void KyraEngine_v1::setupPanPages() {
+ debugC(9, kDebugLevelMain, "KyraEngine_v1::setupPanPages()");
_screen->loadBitmap("BEAD.CPS", 3, 3, 0);
if (_flags.platform == Common::kPlatformMacintosh || _flags.platform == Common::kPlatformAmiga) {
int pageBackUp = _screen->_curPage;
@@ -1697,8 +1703,8 @@ void KyraEngine::setupPanPages() {
}
}
-void KyraEngine::freePanPages() {
- debugC(9, kDebugLevelMain, "KyraEngine::freePanPages()");
+void KyraEngine_v1::freePanPages() {
+ debugC(9, kDebugLevelMain, "KyraEngine_v1::freePanPages()");
delete _endSequenceBackUpRect;
_endSequenceBackUpRect = 0;
for (int i = 0; i <= 19; ++i) {
@@ -1707,8 +1713,8 @@ void KyraEngine::freePanPages() {
}
}
-void KyraEngine::closeFinalWsa() {
- debugC(9, kDebugLevelMain, "KyraEngine::closeFinalWsa()");
+void KyraEngine_v1::closeFinalWsa() {
+ debugC(9, kDebugLevelMain, "KyraEngine_v1::closeFinalWsa()");
delete _finalA;
_finalA = 0;
delete _finalB;
@@ -1719,7 +1725,7 @@ void KyraEngine::closeFinalWsa() {
_endSequenceNeedLoading = 1;
}
-void KyraEngine::updateKyragemFading() {
+void KyraEngine_v1::updateKyragemFading() {
static const uint8 kyraGemPalette[0x28] = {
0x3F, 0x3B, 0x38, 0x34, 0x32, 0x2F, 0x2C, 0x29, 0x25, 0x22,
0x1F, 0x1C, 0x19, 0x16, 0x12, 0x0F, 0x0C, 0x0A, 0x06, 0x03,
@@ -1789,8 +1795,8 @@ void KyraEngine::updateKyragemFading() {
_kyragemFadingState.timerCount = _system->getMillis() + 120 * _tickLength;
}
-void KyraEngine::drawJewelPress(int jewel, int drawSpecial) {
- debugC(9, kDebugLevelMain, "KyraEngine::drawJewelPress(%d, %d)", jewel, drawSpecial);
+void KyraEngine_v1::drawJewelPress(int jewel, int drawSpecial) {
+ debugC(9, kDebugLevelMain, "KyraEngine_v1::drawJewelPress(%d, %d)", jewel, drawSpecial);
_screen->hideMouse();
int shape = 0;
@@ -1814,8 +1820,8 @@ void KyraEngine::drawJewelPress(int jewel, int drawSpecial) {
_screen->showMouse();
}
-void KyraEngine::drawJewelsFadeOutStart() {
- debugC(9, kDebugLevelMain, "KyraEngine::drawJewelsFadeOutStart()");
+void KyraEngine_v1::drawJewelsFadeOutStart() {
+ debugC(9, kDebugLevelMain, "KyraEngine_v1::drawJewelsFadeOutStart()");
static const uint16 jewelTable1[] = { 0x164, 0x15F, 0x15A, 0x155, 0x150, 0xFFFF };
static const uint16 jewelTable2[] = { 0x163, 0x15E, 0x159, 0x154, 0x14F, 0xFFFF };
static const uint16 jewelTable3[] = { 0x166, 0x160, 0x15C, 0x157, 0x152, 0xFFFF };
@@ -1834,8 +1840,8 @@ void KyraEngine::drawJewelsFadeOutStart() {
}
}
-void KyraEngine::drawJewelsFadeOutEnd(int jewel) {
- debugC(9, kDebugLevelMain, "KyraEngine::drawJewelsFadeOutEnd(%d)", jewel);
+void KyraEngine_v1::drawJewelsFadeOutEnd(int jewel) {
+ debugC(9, kDebugLevelMain, "KyraEngine_v1::drawJewelsFadeOutEnd(%d)", jewel);
static const uint16 jewelTable[] = { 0x153, 0x158, 0x15D, 0x162, 0x148, 0xFFFF };
int newDelay = 0;
@@ -1853,7 +1859,7 @@ void KyraEngine::drawJewelsFadeOutEnd(int jewel) {
}
setGameFlag(0xF1);
- setTimerCountdown(19, newDelay);
+ _timer->setCountdown(19, newDelay);
_screen->hideMouse();
for (int i = 0; jewelTable[i] != 0xFFFF; ++i) {
uint16 shape = jewelTable[i];
diff --git a/engines/kyra/sequences_v2.cpp b/engines/kyra/sequences_v2.cpp
index afda1091e6..1c098bf887 100644
--- a/engines/kyra/sequences_v2.cpp
+++ b/engines/kyra/sequences_v2.cpp
@@ -569,6 +569,7 @@ void KyraEngine_v2::seq_loadWSA(int wsaNum, const char *filename, int frameDelay
_activeWSA[wsaNum].movie = new WSAMovieV2(this);
assert(_activeWSA[wsaNum].movie);
_activeWSA[wsaNum].endFrame = _activeWSA[wsaNum].movie->open(filename, 0, _screen->_currentPalette);
+ _activeWSA[wsaNum].movie->flagOldOff(true);
assert(_activeWSA[wsaNum].movie->opened());
_activeWSA[wsaNum].currentFrame = 0;
_activeWSA[wsaNum].frameDelay = frameDelay;
diff --git a/engines/kyra/sound.cpp b/engines/kyra/sound.cpp
index 8deed22091..562754b9c5 100644
--- a/engines/kyra/sound.cpp
+++ b/engines/kyra/sound.cpp
@@ -61,7 +61,9 @@ void Sound::voicePlay(const char *file) {
if (!_compressHandle.isOpen())
continue;
- _currentVocFile = _supportedCodes[i].streamFunc(&_compressHandle, fileSize);
+ Common::MemoryReadStream *tmp = _compressHandle.readStream(fileSize);
+ assert(tmp);
+ _currentVocFile = _supportedCodes[i].streamFunc(tmp, true, 0, 0, 1);
found = true;
break;
}
@@ -432,117 +434,6 @@ void SoundMidiPC::beginFadeOut() {
_fadeStartTime = _vm->_system->getMillis();
}
-#pragma mark -
-
-bool KyraEngine::speechEnabled() {
- return _flags.isTalkie && (_configVoice == 1 || _configVoice == 2);
-}
-
-bool KyraEngine::textEnabled() {
- return !_flags.isTalkie || (_configVoice == 0 || _configVoice == 2);
-}
-
-void KyraEngine::snd_playTheme(int file, int track) {
- debugC(9, kDebugLevelMain | kDebugLevelSound, "KyraEngine::snd_playTheme(%d)", file);
- _curSfxFile = _curMusicTheme = file;
- _sound->loadSoundFile(_curMusicTheme);
- _sound->playTrack(track);
-}
-
-void KyraEngine::snd_playSoundEffect(int track) {
- debugC(9, kDebugLevelMain | kDebugLevelSound, "KyraEngine::snd_playSoundEffect(%d)", track);
- if (_flags.platform == Common::kPlatformFMTowns && track == 49) {
- snd_playWanderScoreViaMap(56, 1);
- return;
- }
- _sound->playSoundEffect(track);
-}
-
-void KyraEngine::snd_playWanderScoreViaMap(int command, int restart) {
- debugC(9, kDebugLevelMain | kDebugLevelSound, "KyraEngine::snd_playWanderScoreViaMap(%d, %d)", command, restart);
- if (restart)
- _lastMusicCommand = -1;
-
- if (_flags.platform == Common::kPlatformFMTowns) {
- if (command == 1) {
- _sound->beginFadeOut();
- } else if (command >= 35 && command <= 38) {
- snd_playSoundEffect(command-20);
- } else if (command >= 2) {
- if (_lastMusicCommand != command) {
- // the original does -2 here we handle this inside _sound->playTrack()
- _sound->playTrack(command);
- }
- } else {
- _sound->haltTrack();
- }
- } else {
- static const int8 soundTable[] = {
- -1, 0, -1, 1, 0, 3, 0, 2,
- 0, 4, 1, 2, 1, 3, 1, 4,
- 1, 92, 1, 6, 1, 7, 2, 2,
- 2, 3, 2, 4, 2, 5, 2, 6,
- 2, 7, 3, 3, 3, 4, 1, 8,
- 1, 9, 4, 2, 4, 3, 4, 4,
- 4, 5, 4, 6, 4, 7, 4, 8,
- 1, 11, 1, 12, 1, 14, 1, 13,
- 4, 9, 5, 12, 6, 2, 6, 6,
- 6, 7, 6, 8, 6, 9, 6, 3,
- 6, 4, 6, 5, 7, 2, 7, 3,
- 7, 4, 7, 5, 7, 6, 7, 7,
- 7, 8, 7, 9, 8, 2, 8, 3,
- 8, 4, 8, 5, 6, 11, 5, 11
- };
- //if (!_disableSound) {
- // XXX
- //}
- assert(command*2+1 < ARRAYSIZE(soundTable));
- if (_curMusicTheme != soundTable[command*2]+1) {
- if (soundTable[command*2] != -1)
- snd_playTheme(soundTable[command*2]+1);
- }
-
- if (command != 1) {
- if (_lastMusicCommand != command) {
- _sound->haltTrack();
- _sound->playTrack(soundTable[command*2+1]);
- }
- } else {
- _sound->beginFadeOut();
- }
- }
-
- _lastMusicCommand = command;
-}
-
-void KyraEngine::snd_playVoiceFile(int id) {
- debugC(9, kDebugLevelMain | kDebugLevelSound, "KyraEngine::snd_playVoiceFile(%d)", id);
- char vocFile[9];
- assert(id >= 0 && id < 9999);
- sprintf(vocFile, "%03d", id);
- _sound->voicePlay(vocFile);
-}
-
-void KyraEngine::snd_voiceWaitForFinish(bool ingame) {
- debugC(9, kDebugLevelMain | kDebugLevelSound, "KyraEngine::snd_voiceWaitForFinish(%d)", ingame);
- while (_sound->voiceIsPlaying() && !_skipFlag) {
- if (ingame)
- delay(10, true);
- else
- _system->delayMillis(10);
- }
-}
-
-void KyraEngine::snd_stopVoice() {
- debugC(9, kDebugLevelMain | kDebugLevelSound, "KyraEngine::snd_stopVoice()");
- _sound->voiceStop();
-}
-
-bool KyraEngine::snd_voiceIsPlaying() {
- debugC(9, kDebugLevelMain | kDebugLevelSound, "KyraEngine::snd_voiceIsPlaying()");
- return _sound->voiceIsPlaying();
-}
-
// static res
const Sound::SpeechCodecs Sound::_supportedCodes[] = {
diff --git a/engines/kyra/sound.h b/engines/kyra/sound.h
index 28a9521112..b6c06b493b 100644
--- a/engines/kyra/sound.h
+++ b/engines/kyra/sound.h
@@ -109,7 +109,12 @@ private:
struct SpeechCodecs {
const char *fileext;
- Audio::AudioStream *(*streamFunc)(Common::File*, uint32);
+ Audio::AudioStream *(*streamFunc)(
+ Common::SeekableReadStream *stream,
+ bool disposeAfterUse,
+ uint32 startTime,
+ uint32 duration,
+ uint numLoops);
};
static const SpeechCodecs _supportedCodes[];
diff --git a/engines/kyra/sound_v1.cpp b/engines/kyra/sound_v1.cpp
new file mode 100644
index 0000000000..3ea86189b2
--- /dev/null
+++ b/engines/kyra/sound_v1.cpp
@@ -0,0 +1,140 @@
+/* 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 "kyra/sound.h"
+#include "kyra/kyra_v1.h"
+
+namespace Kyra {
+
+bool KyraEngine_v1::speechEnabled() {
+ return _flags.isTalkie && (_configVoice == 1 || _configVoice == 2);
+}
+
+bool KyraEngine_v1::textEnabled() {
+ return !_flags.isTalkie || (_configVoice == 0 || _configVoice == 2);
+}
+
+void KyraEngine_v1::snd_playTheme(int file, int track) {
+ debugC(9, kDebugLevelMain | kDebugLevelSound, "KyraEngine_v1::snd_playTheme(%d)", file);
+ _curSfxFile = _curMusicTheme = file;
+ _sound->loadSoundFile(_curMusicTheme);
+ _sound->playTrack(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) {
+ snd_playWanderScoreViaMap(56, 1);
+ return;
+ }
+ _sound->playSoundEffect(track);
+}
+
+void KyraEngine_v1::snd_playWanderScoreViaMap(int command, int restart) {
+ debugC(9, kDebugLevelMain | kDebugLevelSound, "KyraEngine_v1::snd_playWanderScoreViaMap(%d, %d)", command, restart);
+ if (restart)
+ _lastMusicCommand = -1;
+
+ if (_flags.platform == Common::kPlatformFMTowns) {
+ if (command == 1) {
+ _sound->beginFadeOut();
+ } else if (command >= 35 && command <= 38) {
+ snd_playSoundEffect(command-20);
+ } else if (command >= 2) {
+ if (_lastMusicCommand != command) {
+ // the original does -2 here we handle this inside _sound->playTrack()
+ _sound->playTrack(command);
+ }
+ } else {
+ _sound->haltTrack();
+ }
+ } else {
+ static const int8 soundTable[] = {
+ -1, 0, -1, 1, 0, 3, 0, 2,
+ 0, 4, 1, 2, 1, 3, 1, 4,
+ 1, 92, 1, 6, 1, 7, 2, 2,
+ 2, 3, 2, 4, 2, 5, 2, 6,
+ 2, 7, 3, 3, 3, 4, 1, 8,
+ 1, 9, 4, 2, 4, 3, 4, 4,
+ 4, 5, 4, 6, 4, 7, 4, 8,
+ 1, 11, 1, 12, 1, 14, 1, 13,
+ 4, 9, 5, 12, 6, 2, 6, 6,
+ 6, 7, 6, 8, 6, 9, 6, 3,
+ 6, 4, 6, 5, 7, 2, 7, 3,
+ 7, 4, 7, 5, 7, 6, 7, 7,
+ 7, 8, 7, 9, 8, 2, 8, 3,
+ 8, 4, 8, 5, 6, 11, 5, 11
+ };
+ //if (!_disableSound) {
+ // XXX
+ //}
+ assert(command*2+1 < ARRAYSIZE(soundTable));
+ if (_curMusicTheme != soundTable[command*2]+1) {
+ if (soundTable[command*2] != -1)
+ snd_playTheme(soundTable[command*2]+1);
+ }
+
+ if (command != 1) {
+ if (_lastMusicCommand != command) {
+ _sound->haltTrack();
+ _sound->playTrack(soundTable[command*2+1]);
+ }
+ } else {
+ _sound->beginFadeOut();
+ }
+ }
+
+ _lastMusicCommand = command;
+}
+
+void KyraEngine_v1::snd_playVoiceFile(int id) {
+ debugC(9, kDebugLevelMain | kDebugLevelSound, "KyraEngine_v1::snd_playVoiceFile(%d)", id);
+ char vocFile[9];
+ assert(id >= 0 && id < 9999);
+ sprintf(vocFile, "%03d", id);
+ _sound->voicePlay(vocFile);
+}
+
+void KyraEngine_v1::snd_voiceWaitForFinish(bool ingame) {
+ debugC(9, kDebugLevelMain | kDebugLevelSound, "KyraEngine_v1::snd_voiceWaitForFinish(%d)", ingame);
+ while (_sound->voiceIsPlaying() && !_skipFlag) {
+ if (ingame)
+ delay(10, true);
+ else
+ _system->delayMillis(10);
+ }
+}
+
+void KyraEngine_v1::snd_stopVoice() {
+ debugC(9, kDebugLevelMain | kDebugLevelSound, "KyraEngine_v1::snd_stopVoice()");
+ _sound->voiceStop();
+}
+
+bool KyraEngine_v1::snd_voiceIsPlaying() {
+ debugC(9, kDebugLevelMain | kDebugLevelSound, "KyraEngine_v1::snd_voiceIsPlaying()");
+ return _sound->voiceIsPlaying();
+}
+
+} // end of namespace Kyra
diff --git a/engines/kyra/sprites.cpp b/engines/kyra/sprites.cpp
index 0a3f243df2..1a2c7f6146 100644
--- a/engines/kyra/sprites.cpp
+++ b/engines/kyra/sprites.cpp
@@ -29,14 +29,14 @@
#include "common/util.h"
#include "common/system.h"
#include "kyra/screen.h"
-#include "kyra/kyra.h"
+#include "kyra/kyra_v1.h"
#include "kyra/sprites.h"
#include "kyra/resource.h"
-#include "kyra/animator.h"
+#include "kyra/animator_v1.h"
namespace Kyra {
-Sprites::Sprites(KyraEngine *vm, OSystem *system) {
+Sprites::Sprites(KyraEngine_v1 *vm, OSystem *system) {
_vm = vm;
_res = vm->resource();
_screen = vm->screen();
diff --git a/engines/kyra/sprites.h b/engines/kyra/sprites.h
index 179942d519..255d878635 100644
--- a/engines/kyra/sprites.h
+++ b/engines/kyra/sprites.h
@@ -26,6 +26,8 @@
#ifndef KYRA_SPRITES_H
#define KYRA_SPRITES_H
+#include "kyra/kyra_v1.h"
+
namespace Kyra {
#define MAX_NUM_ANIMS 11
@@ -61,10 +63,11 @@ struct Anim {
bool disable;
};
+class KyraEngine_v1;
+
class Sprites {
public:
-
- Sprites(KyraEngine *vm, OSystem *system);
+ Sprites(KyraEngine_v1 *vm, OSystem *system);
~Sprites();
void updateSceneAnims();
@@ -83,7 +86,7 @@ public:
protected:
void freeSceneShapes();
- KyraEngine *_vm;
+ KyraEngine_v1 *_vm;
Resource *_res;
OSystem *_system;
Screen *_screen;
diff --git a/engines/kyra/staticres.cpp b/engines/kyra/staticres.cpp
index 16e3f98791..3cf8648aa8 100644
--- a/engines/kyra/staticres.cpp
+++ b/engines/kyra/staticres.cpp
@@ -27,6 +27,7 @@
#include "common/endian.h"
#include "common/md5.h"
#include "kyra/kyra.h"
+#include "kyra/kyra_v1.h"
#include "kyra/kyra_v2.h"
#include "kyra/kyra_v3.h"
#include "kyra/screen.h"
@@ -617,7 +618,7 @@ uint8 *StaticResource::getFile(const char *name, int &size) {
#pragma mark -
-void KyraEngine::initStaticResource() {
+void KyraEngine_v1::initStaticResource() {
int temp = 0;
_seq_Forest = _staticres->loadRawData(kForestSeq, temp);
_seq_KallakWriting = _staticres->loadRawData(kKallakWritingSeq, temp);
@@ -708,7 +709,7 @@ void KyraEngine::initStaticResource() {
}
}
-void KyraEngine::loadMouseShapes() {
+void KyraEngine_v1::loadMouseShapes() {
_screen->loadBitmap("MOUSE.CPS", 3, 3, 0);
_screen->_curPage = 2;
_shapes[0] = _screen->encodeShape(0, 0, 8, 10, 0);
@@ -724,7 +725,7 @@ void KyraEngine::loadMouseShapes() {
_screen->setShapePages(5, 3);
}
-void KyraEngine::loadCharacterShapes() {
+void KyraEngine_v1::loadCharacterShapes() {
int curImage = 0xFF;
int videoPage = _screen->_curPage;
_screen->_curPage = 2;
@@ -745,7 +746,7 @@ void KyraEngine::loadCharacterShapes() {
_screen->_curPage = videoPage;
}
-void KyraEngine::loadSpecialEffectShapes() {
+void KyraEngine_v1::loadSpecialEffectShapes() {
_screen->loadBitmap("EFFECTS.CPS", 3, 3, 0);
_screen->_curPage = 2;
@@ -763,7 +764,7 @@ void KyraEngine::loadSpecialEffectShapes() {
_shapes[currShape] = _screen->encodeShape((currShape-201) * 16, 106, 16, 16, 1);
}
-void KyraEngine::loadItems() {
+void KyraEngine_v1::loadItems() {
int shape;
_screen->loadBitmap("JEWELS3.CPS", 3, 3, 0);
@@ -817,7 +818,7 @@ void KyraEngine::loadItems() {
delete[] fileData;
}
-void KyraEngine::loadButtonShapes() {
+void KyraEngine_v1::loadButtonShapes() {
_screen->loadBitmap("BUTTONS2.CPS", 3, 3, 0);
_screen->_curPage = 2;
_scrollUpButton.process0PtrShape = _screen->encodeShape(0, 0, 24, 14, 1);
@@ -829,12 +830,12 @@ void KyraEngine::loadButtonShapes() {
_screen->_curPage = 0;
}
-void KyraEngine::loadMainScreen(int page) {
+void KyraEngine_v1::loadMainScreen(int page) {
_screen->clearPage(page);
if (_flags.lang == Common::EN_ANY && !_flags.isTalkie && (_flags.platform == Common::kPlatformPC || _flags.platform == Common::kPlatformAmiga))
_screen->loadBitmap("MAIN15.CPS", page, page, _screen->getPalette(0));
- else if (_flags.lang == Common::EN_ANY || _flags.lang == Common::JA_JPN)
+ else if (_flags.lang == Common::EN_ANY || _flags.lang == Common::JA_JPN || (_flags.isTalkie && _flags.lang == Common::IT_ITA))
_screen->loadBitmap("MAIN_ENG.CPS", page, page, 0);
else if (_flags.lang == Common::FR_FRA)
_screen->loadBitmap("MAIN_FRE.CPS", page, page, 0);
@@ -867,18 +868,43 @@ const ScreenDim Screen::_screenDimTable[] = {
{ 0x03, 0x28, 0x22, 0x46, 0x0F, 0x0D, 0x00, 0x00 }
};
-const int Screen::_screenDimTableCount = ARRAYSIZE(_screenDimTable);
+const int Screen::_screenDimTableCount = ARRAYSIZE(Screen::_screenDimTable);
+
+const ScreenDim Screen_v2::_screenDimTable[] = {
+ { 0x00, 0x00, 0x28, 0xC8, 0xC7, 0xCF, 0x00, 0x00 },
+ { 0x08, 0x48, 0x18, 0x38, 0xC7, 0xCF, 0x00, 0x00 },
+ { 0x00, 0x00, 0x28, 0x90, 0xC7, 0xCF, 0x00, 0x00 },
+ { 0x00, 0xC2, 0x28, 0x06, 0xC7, 0xCF, 0x00, 0x00 },
+ { 0x00, 0x90, 0x28, 0x38, 0x96, 0xCF, 0x00, 0x00 },
+ { 0x01, 0x94, 0x26, 0x30, 0x96, 0x1B, 0x00, 0x00 },
+ { 0x00, 0x90, 0x28, 0x38, 0xC7, 0xCC, 0x00, 0x00 },
+ { 0x01, 0x96, 0x26, 0x32, 0xC7, 0xCC, 0x00, 0x00 },
+ { 0x00, 0x00, 0x28, 0x88, 0xC7, 0xCF, 0x00, 0x00 },
+ { 0x00, 0x08, 0x28, 0xB8, 0xC7, 0xCF, 0x00, 0x00 },
+ { 0x01, 0x28, 0x26, 0x46, 0xC7, 0xCC, 0x00, 0x00 },
+ { 0x0A, 0x96, 0x14, 0x30, 0x19, 0xF0, 0x00, 0x00 } // menu, just present for current menu code
+};
+
+const int Screen_v2::_screenDimTableCount = ARRAYSIZE(Screen_v2::_screenDimTable);
-const ScreenDim Screen::_screenDimTableK3[] = {
+const ScreenDim Screen_v2::_screenDimTableK3[] = {
{ 0x00, 0x00, 0x28, 0xC8, 0xFF, 0xF0, 0x00, 0x00 },
{ 0x08, 0x48, 0x18, 0x38, 0xFF, 0xF0, 0x00, 0x00 },
{ 0x00, 0x00, 0x28, 0xBC, 0xFF, 0xF0, 0x00, 0x00 },
{ 0x0A, 0x96, 0x14, 0x30, 0x19, 0xF0, 0x00, 0x00 }
};
-const int Screen::_screenDimTableCountK3 = ARRAYSIZE(_screenDimTableK3);
+const int Screen_v2::_screenDimTableCountK3 = ARRAYSIZE(Screen_v2::_screenDimTableK3);
+
+const int8 KyraEngine::_addXPosTable[] = {
+ 4, 4, 0, -4, -4, -4, 0, 4
+};
+
+const int8 KyraEngine::_addYPosTable[] = {
+ 0, -2, -2, -2, 0, 2, 2, 2
+};
-const char *KyraEngine::_soundFiles[] = {
+const char *KyraEngine_v1::_soundFiles[] = {
"INTRO",
"KYRA1A",
"KYRA1B",
@@ -891,9 +917,9 @@ const char *KyraEngine::_soundFiles[] = {
"KYRAMISC"
};
-const int KyraEngine::_soundFilesCount = ARRAYSIZE(KyraEngine::_soundFiles);
+const int KyraEngine_v1::_soundFilesCount = ARRAYSIZE(KyraEngine_v1::_soundFiles);
-const char *KyraEngine::_soundFilesTowns[] = {
+const char *KyraEngine_v1::_soundFilesTowns[] = {
"TW_INTRO.SFX",
"TW_SCEN1.SFX",
"TW_SCEN2.SFX",
@@ -902,49 +928,41 @@ const char *KyraEngine::_soundFilesTowns[] = {
"TW_SCEN5.SFX",
};
-const int KyraEngine::_soundFilesTownsCount = ARRAYSIZE(KyraEngine::_soundFilesTowns);
+const int KyraEngine_v1::_soundFilesTownsCount = ARRAYSIZE(KyraEngine_v1::_soundFilesTowns);
-const int8 KyraEngine::_charXPosTable[] = {
+const int8 KyraEngine_v1::_charXPosTable[] = {
0, 4, 4, 4, 0, -4, -4, -4
};
-const int8 KyraEngine::_addXPosTable[] = {
- 4, 4, 0, -4, -4, -4, 0, 4
-};
-
-const int8 KyraEngine::_charYPosTable[] = {
+const int8 KyraEngine_v1::_charYPosTable[] = {
-2, -2, 0, 2, 2, 2, 0, -2
};
-const int8 KyraEngine::_addYPosTable[] = {
- 0, -2, -2, -2, 0, 2, 2, 2
-};
-
-const uint16 KyraEngine::_itemPosX[] = {
+const uint16 KyraEngine_v1::_itemPosX[] = {
95, 115, 135, 155, 175, 95, 115, 135, 155, 175
};
-const uint8 KyraEngine::_itemPosY[] = {
+const uint8 KyraEngine_v1::_itemPosY[] = {
160, 160, 160, 160, 160, 181, 181, 181, 181, 181
};
-void KyraEngine::setupButtonData() {
+void KyraEngine_v1::setupButtonData() {
static Button buttonData[] = {
- { 0, 0x02, /*XXX,*/0, 0, 0, /*XXX,*/ 0x0400, 0, 0, 0, 0, 0, 0, 0, 0x05D, 0x9E, 0x13, 0x14, /*XXX,*/ 0, &KyraEngine::buttonInventoryCallback/*, XXX*/ },
- { 0, 0x01, /*XXX,*/1, 1, 1, /*XXX,*/ 0x0487, 0, 0, 0, 0, 0, 0, 0, 0x009, 0xA4, 0x36, 0x1E, /*XXX,*/ 0, &KyraEngine::buttonMenuCallback/*, XXX*/ },
- { 0, 0x03, /*XXX,*/0, 0, 0, /*XXX,*/ 0x0400, 0, 0, 0, 0, 0, 0, 0, 0x071, 0x9E, 0x13, 0x14, /*XXX,*/ 0, &KyraEngine::buttonInventoryCallback/*, XXX*/ },
- { 0, 0x04, /*XXX,*/0, 0, 0, /*XXX,*/ 0x0400, 0, 0, 0, 0, 0, 0, 0, 0x085, 0x9E, 0x13, 0x14, /*XXX,*/ 0, &KyraEngine::buttonInventoryCallback/*, XXX*/ },
- { 0, 0x05, /*XXX,*/0, 0, 0, /*XXX,*/ 0x0400, 0, 0, 0, 0, 0, 0, 0, 0x099, 0x9E, 0x13, 0x14, /*XXX,*/ 0, &KyraEngine::buttonInventoryCallback/*, XXX*/ },
- { 0, 0x06, /*XXX,*/0, 0, 0, /*XXX,*/ 0x0400, 0, 0, 0, 0, 0, 0, 0, 0x0AD, 0x9E, 0x13, 0x14, /*XXX,*/ 0, &KyraEngine::buttonInventoryCallback/*, XXX*/ },
- { 0, 0x07, /*XXX,*/0, 0, 0, /*XXX,*/ 0x0400, 0, 0, 0, 0, 0, 0, 0, 0x05D, 0xB3, 0x13, 0x14, /*XXX,*/ 0, &KyraEngine::buttonInventoryCallback/*, XXX*/ },
- { 0, 0x08, /*XXX,*/0, 0, 0, /*XXX,*/ 0x0400, 0, 0, 0, 0, 0, 0, 0, 0x071, 0xB3, 0x13, 0x14, /*XXX,*/ 0, &KyraEngine::buttonInventoryCallback/*, XXX*/ },
- { 0, 0x09, /*XXX,*/0, 0, 0, /*XXX,*/ 0x0400, 0, 0, 0, 0, 0, 0, 0, 0x085, 0xB3, 0x13, 0x14, /*XXX,*/ 0, &KyraEngine::buttonInventoryCallback/*, XXX*/ },
- { 0, 0x0A, /*XXX,*/0, 0, 0, /*XXX,*/ 0x0400, 0, 0, 0, 0, 0, 0, 0, 0x099, 0xB3, 0x13, 0x14, /*XXX,*/ 0, &KyraEngine::buttonInventoryCallback/*, XXX*/ },
- { 0, 0x0B, /*XXX,*/0, 0, 0, /*XXX,*/ 0x0400, 0, 0, 0, 0, 0, 0, 0, 0x0AD, 0xB3, 0x13, 0x14, /*XXX,*/ 0, &KyraEngine::buttonInventoryCallback/*, XXX*/ },
- { 0, 0x15, /*XXX,*/1, 1, 1, /*XXX,*/ 0x0487, 0, 0, 0, 0, 0, 0, 0, 0x0FD, 0x9C, 0x1A, 0x12, /*XXX,*/ 0, &KyraEngine::buttonAmuletCallback/*, XXX*/ },
- { 0, 0x16, /*XXX,*/1, 1, 1, /*XXX,*/ 0x0487, 0, 0, 0, 0, 0, 0, 0, 0x0E7, 0xAA, 0x1A, 0x12, /*XXX,*/ 0, &KyraEngine::buttonAmuletCallback/*, XXX*/ },
- { 0, 0x17, /*XXX,*/1, 1, 1, /*XXX,*/ 0x0487, 0, 0, 0, 0, 0, 0, 0, 0x0FD, 0xB5, 0x1A, 0x12, /*XXX,*/ 0, &KyraEngine::buttonAmuletCallback/*, XXX*/ },
- { 0, 0x18, /*XXX,*/1, 1, 1, /*XXX,*/ 0x0487, 0, 0, 0, 0, 0, 0, 0, 0x113, 0xAA, 0x1A, 0x12, /*XXX,*/ 0, &KyraEngine::buttonAmuletCallback/*, XXX*/ }
+ { 0, 0x02, /*XXX,*/0, 0, 0, /*XXX,*/ 0x0400, 0, 0, 0, 0, 0, 0, 0, 0x05D, 0x9E, 0x13, 0x14, /*XXX,*/ 0, &KyraEngine_v1::buttonInventoryCallback/*, XXX*/ },
+ { 0, 0x01, /*XXX,*/1, 1, 1, /*XXX,*/ 0x0487, 0, 0, 0, 0, 0, 0, 0, 0x009, 0xA4, 0x36, 0x1E, /*XXX,*/ 0, &KyraEngine_v1::buttonMenuCallback/*, XXX*/ },
+ { 0, 0x03, /*XXX,*/0, 0, 0, /*XXX,*/ 0x0400, 0, 0, 0, 0, 0, 0, 0, 0x071, 0x9E, 0x13, 0x14, /*XXX,*/ 0, &KyraEngine_v1::buttonInventoryCallback/*, XXX*/ },
+ { 0, 0x04, /*XXX,*/0, 0, 0, /*XXX,*/ 0x0400, 0, 0, 0, 0, 0, 0, 0, 0x085, 0x9E, 0x13, 0x14, /*XXX,*/ 0, &KyraEngine_v1::buttonInventoryCallback/*, XXX*/ },
+ { 0, 0x05, /*XXX,*/0, 0, 0, /*XXX,*/ 0x0400, 0, 0, 0, 0, 0, 0, 0, 0x099, 0x9E, 0x13, 0x14, /*XXX,*/ 0, &KyraEngine_v1::buttonInventoryCallback/*, XXX*/ },
+ { 0, 0x06, /*XXX,*/0, 0, 0, /*XXX,*/ 0x0400, 0, 0, 0, 0, 0, 0, 0, 0x0AD, 0x9E, 0x13, 0x14, /*XXX,*/ 0, &KyraEngine_v1::buttonInventoryCallback/*, XXX*/ },
+ { 0, 0x07, /*XXX,*/0, 0, 0, /*XXX,*/ 0x0400, 0, 0, 0, 0, 0, 0, 0, 0x05D, 0xB3, 0x13, 0x14, /*XXX,*/ 0, &KyraEngine_v1::buttonInventoryCallback/*, XXX*/ },
+ { 0, 0x08, /*XXX,*/0, 0, 0, /*XXX,*/ 0x0400, 0, 0, 0, 0, 0, 0, 0, 0x071, 0xB3, 0x13, 0x14, /*XXX,*/ 0, &KyraEngine_v1::buttonInventoryCallback/*, XXX*/ },
+ { 0, 0x09, /*XXX,*/0, 0, 0, /*XXX,*/ 0x0400, 0, 0, 0, 0, 0, 0, 0, 0x085, 0xB3, 0x13, 0x14, /*XXX,*/ 0, &KyraEngine_v1::buttonInventoryCallback/*, XXX*/ },
+ { 0, 0x0A, /*XXX,*/0, 0, 0, /*XXX,*/ 0x0400, 0, 0, 0, 0, 0, 0, 0, 0x099, 0xB3, 0x13, 0x14, /*XXX,*/ 0, &KyraEngine_v1::buttonInventoryCallback/*, XXX*/ },
+ { 0, 0x0B, /*XXX,*/0, 0, 0, /*XXX,*/ 0x0400, 0, 0, 0, 0, 0, 0, 0, 0x0AD, 0xB3, 0x13, 0x14, /*XXX,*/ 0, &KyraEngine_v1::buttonInventoryCallback/*, XXX*/ },
+ { 0, 0x15, /*XXX,*/1, 1, 1, /*XXX,*/ 0x0487, 0, 0, 0, 0, 0, 0, 0, 0x0FD, 0x9C, 0x1A, 0x12, /*XXX,*/ 0, &KyraEngine_v1::buttonAmuletCallback/*, XXX*/ },
+ { 0, 0x16, /*XXX,*/1, 1, 1, /*XXX,*/ 0x0487, 0, 0, 0, 0, 0, 0, 0, 0x0E7, 0xAA, 0x1A, 0x12, /*XXX,*/ 0, &KyraEngine_v1::buttonAmuletCallback/*, XXX*/ },
+ { 0, 0x17, /*XXX,*/1, 1, 1, /*XXX,*/ 0x0487, 0, 0, 0, 0, 0, 0, 0, 0x0FD, 0xB5, 0x1A, 0x12, /*XXX,*/ 0, &KyraEngine_v1::buttonAmuletCallback/*, XXX*/ },
+ { 0, 0x18, /*XXX,*/1, 1, 1, /*XXX,*/ 0x0487, 0, 0, 0, 0, 0, 0, 0, 0x113, 0xAA, 0x1A, 0x12, /*XXX,*/ 0, &KyraEngine_v1::buttonAmuletCallback/*, XXX*/ }
};
static Button *buttonDataListPtr[] = {
@@ -969,10 +987,10 @@ void KyraEngine::setupButtonData() {
_buttonDataListPtr = buttonDataListPtr;
}
-Button KyraEngine::_scrollUpButton = {0, 0x12, 1, 1, 1, 0x483, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x18, 0x0f, 0, 0};
-Button KyraEngine::_scrollDownButton = {0, 0x13, 1, 1, 1, 0x483, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x18, 0x0f, 0, 0};
+Button KyraEngine_v1::_scrollUpButton = {0, 0x12, 1, 1, 1, 0x483, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x18, 0x0f, 0, 0};
+Button KyraEngine_v1::_scrollDownButton = {0, 0x13, 1, 1, 1, 0x483, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x18, 0x0f, 0, 0};
-Button KyraEngine::_menuButtonData[] = {
+Button KyraEngine_v1::_menuButtonData[] = {
{ 0, 0x0c, /*XXX,*/1, 1, 1, /*XXX,*/ 0x487, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*XXX,*/ 0, 0 /*, XXX*/ },
{ 0, 0x0d, /*XXX,*/1, 1, 1, /*XXX,*/ 0x487, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*XXX,*/ 0, 0 /*, XXX*/ },
{ 0, 0x0e, /*XXX,*/1, 1, 1, /*XXX,*/ 0x487, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*XXX,*/ 0, 0 /*, XXX*/ },
@@ -981,33 +999,33 @@ Button KyraEngine::_menuButtonData[] = {
{ 0, 0x11, /*XXX,*/1, 1, 1, /*XXX,*/ 0x487, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*XXX,*/ 0, 0 /*, XXX*/ }
};
-void KyraEngine::setupMenu() {
+void KyraEngine_v1::setupMenu() {
static Menu menu[] = {
{ -1, -1, 208, 136, 248, 249, 250, 0, 251, -1, 8, 0, 5, -1, -1, -1, -1,
{
{1, 0, 0, 0, -1, -1, 30, 148, 15, 252, 253, 24, 0,
- 248, 249, 250, &KyraEngine::gui_loadGameMenu, -1, 0, 0, 0, 0, 0},
+ 248, 249, 250, &KyraEngine_v1::gui_loadGameMenu, -1, 0, 0, 0, 0, 0},
{1, 0, 0, 0, -1, -1, 47, 148, 15, 252, 253, 24, 0,
- 248, 249, 250, &KyraEngine::gui_saveGameMenu, -1, 0, 0, 0, 0, 0},
+ 248, 249, 250, &KyraEngine_v1::gui_saveGameMenu, -1, 0, 0, 0, 0, 0},
{1, 0, 0, 0, -1, -1, 64, 148, 15, 252, 253, 24, 0,
- 248, 249, 250, &KyraEngine::gui_gameControlsMenu, -1, 0, 0, 0, 0, 0},
+ 248, 249, 250, &KyraEngine_v1::gui_gameControlsMenu, -1, 0, 0, 0, 0, 0},
{1, 0, 0, 0, -1, -1, 81, 148, 15, 252, 253, 24, 0,
- 248, 249, 250, &KyraEngine::gui_quitPlaying, -1, 0, 0, 0, 0, 0},
+ 248, 249, 250, &KyraEngine_v1::gui_quitPlaying, -1, 0, 0, 0, 0, 0},
{1, 0, 0, 0, 86, 0, 110, 92, 15, 252, 253, -1, 255,
- 248, 249, 250, &KyraEngine::gui_resumeGame, -1, 0, 0, 0, 0, 0}
+ 248, 249, 250, &KyraEngine_v1::gui_resumeGame, -1, 0, 0, 0, 0, 0}
}
},
{ -1, -1, 288, 56, 248, 249, 250, 0, 254,-1, 8, 0, 2, -1, -1, -1, -1,
{
{1, 0, 0, 0, 24, 0, 30, 72, 15, 252, 253, -1, 255,
- 248, 249, 250, &KyraEngine::gui_quitConfirmYes, -1, 0, 0, 0, 0, 0},
+ 248, 249, 250, &KyraEngine_v1::gui_quitConfirmYes, -1, 0, 0, 0, 0, 0},
{1, 0, 0, 0, 192, 0, 30, 72, 15, 252, 253, -1, 255,
- 248, 249, 250, &KyraEngine::gui_quitConfirmNo, -1, 0, 0, 0, 0, 0}
+ 248, 249, 250, &KyraEngine_v1::gui_quitConfirmNo, -1, 0, 0, 0, 0, 0}
}
},
{ -1, -1, 288, 160, 248, 249, 250, 0, 251, -1, 8, 0, 6, 132, 22, 132, 124,
@@ -1028,46 +1046,46 @@ void KyraEngine::setupMenu() {
248, 249, 250, 0, -1, 0, 0, 0, 0, 0},
{1, 0, 0, 0, 184, 0, 134, 88, 15, 252, 253, -1, 255,
- 248, 249, 250, &KyraEngine::gui_cancelSubMenu, -1, 0, 0, 0, 0, 0},
+ 248, 249, 250, &KyraEngine_v1::gui_cancelSubMenu, -1, 0, 0, 0, 0, 0},
}
},
{ -1, -1, 288, 67, 248, 249, 250, 0, 251, -1, 8, 0, 3, -1, -1, -1, -1,
{
{1, 0, 0, 0, 24, 0, 44, 72, 15, 252, 253, -1, 255,
- 248, 249, 250, &KyraEngine::gui_savegameConfirm, -1, 0, 0, 0, 0, 0},
+ 248, 249, 250, &KyraEngine_v1::gui_savegameConfirm, -1, 0, 0, 0, 0, 0},
{1, 0, 0, 0, 192, 0, 44, 72, 15, 252, 253, -1, 255,
- 248, 249, 250, &KyraEngine::gui_cancelSubMenu, -1, 0, 0, 0, 0, 0}
+ 248, 249, 250, &KyraEngine_v1::gui_cancelSubMenu, -1, 0, 0, 0, 0, 0}
}
},
{ -1, -1, 208, 76, 248, 249, 250, 0, 251, -1, 8, 0, 2, -1, -1, -1, -1,
{
{1, 0, 0, 0, -1, -1, 30, 148, 15, 252, 253, 24, 0,
- 248, 249, 250, &KyraEngine::gui_loadGameMenu, -1, 0, 0, 0, 0, 0},
+ 248, 249, 250, &KyraEngine_v1::gui_loadGameMenu, -1, 0, 0, 0, 0, 0},
{1, 0, 0, 0, -1, -1, 47, 148, 15, 252, 253, 24, 0,
- 248, 249, 250, &KyraEngine::gui_quitPlaying, -1, 0, 0, 0, 0, 0}
+ 248, 249, 250, &KyraEngine_v1::gui_quitPlaying, -1, 0, 0, 0, 0, 0}
}
},
{ -1, -1, 208, 153, 248, 249, 250, 0, 251, -1, 8, 0, 6, -1, -1, -1, -1,
{
{1, 0, 0, 0, 110, 0, 30, 64, 15, 252, 253, 5, 0,
- 248, 249, 250, &KyraEngine::gui_controlsChangeMusic, -1, 0, 34, 32, 0, 0},
+ 248, 249, 250, &KyraEngine_v1::gui_controlsChangeMusic, -1, 0, 34, 32, 0, 0},
{1, 0, 0, 0, 110, 0, 47, 64, 15, 252, 253, 5, 0,
- 248, 249, 250, &KyraEngine::gui_controlsChangeSounds, -1, 0, 34, 49, 0, 0},
+ 248, 249, 250, &KyraEngine_v1::gui_controlsChangeSounds, -1, 0, 34, 49, 0, 0},
{1, 0, 0, 0, 110, 0, 64, 64, 15, 252, 253, 5, 0,
- 248, 249, 250, &KyraEngine::gui_controlsChangeWalk, -1, 0, 34, 66, 0, 0},
+ 248, 249, 250, &KyraEngine_v1::gui_controlsChangeWalk, -1, 0, 34, 66, 0, 0},
{1, 0, 0, 0, 110, 0, 81, 64, 15, 252, 253, 5, 0,
248, 249, 250, 0, -1, 0, 34, 83, 0, 0 },
{1, 0, 0, 0, 110, 0, 98, 64, 15, 252, 253, 5, 0,
- 248, 249, 250, &KyraEngine::gui_controlsChangeText, -1, 0, 34, 100, 0, 0 },
+ 248, 249, 250, &KyraEngine_v1::gui_controlsChangeText, -1, 0, 34, 100, 0, 0 },
{1, 0, 0, 0, 64, 0, 127, 92, 15, 252, 253, -1, 255,
- 248, 249, 250, &KyraEngine::gui_controlsApply, -1, -0, 0, 0, 0, 0}
+ 248, 249, 250, &KyraEngine_v1::gui_controlsApply, -1, -0, 0, 0, 0, 0}
}
}
};
@@ -1075,31 +1093,31 @@ void KyraEngine::setupMenu() {
_menu = menu;
}
-const uint8 KyraEngine::_magicMouseItemStartFrame[] = {
+const uint8 KyraEngine_v1::_magicMouseItemStartFrame[] = {
0xAD, 0xB7, 0xBE, 0x00
};
-const uint8 KyraEngine::_magicMouseItemEndFrame[] = {
+const uint8 KyraEngine_v1::_magicMouseItemEndFrame[] = {
0xB1, 0xB9, 0xC2, 0x00
};
-const uint8 KyraEngine::_magicMouseItemStartFrame2[] = {
+const uint8 KyraEngine_v1::_magicMouseItemStartFrame2[] = {
0xB2, 0xBA, 0xC3, 0x00
};
-const uint8 KyraEngine::_magicMouseItemEndFrame2[] = {
+const uint8 KyraEngine_v1::_magicMouseItemEndFrame2[] = {
0xB6, 0xBD, 0xC8, 0x00
};
-const uint16 KyraEngine::_amuletX[] = { 231, 275, 253, 253 };
-const uint16 KyraEngine::_amuletY[] = { 170, 170, 159, 181 };
+const uint16 KyraEngine_v1::_amuletX[] = { 231, 275, 253, 253 };
+const uint16 KyraEngine_v1::_amuletY[] = { 170, 170, 159, 181 };
-const uint16 KyraEngine::_amuletX2[] = { 0x000, 0x0FD, 0x0E7, 0x0FD, 0x113, 0x000 };
-const uint16 KyraEngine::_amuletY2[] = { 0x000, 0x09F, 0x0AA, 0x0B5, 0x0AA, 0x000 };
+const uint16 KyraEngine_v1::_amuletX2[] = { 0x000, 0x0FD, 0x0E7, 0x0FD, 0x113, 0x000 };
+const uint16 KyraEngine_v1::_amuletY2[] = { 0x000, 0x09F, 0x0AA, 0x0B5, 0x0AA, 0x000 };
// Kyra 2 and 3 main menu
-const char *KyraEngine::_mainMenuStrings[] = {
+const char *KyraEngine_v2::_mainMenuStrings[] = {
"Start a new game",
"Introduction",
"Load a game",
@@ -1195,6 +1213,34 @@ const char *KyraEngine_v2::_introSoundList[] = {
const int KyraEngine_v2::_introSoundListSize = ARRAYSIZE(KyraEngine_v2::_introSoundList);
+const char *KyraEngine_v2::_languageExtension[] = {
+ "ENG",
+ "FRE",
+ "GER"/*,
+ "ITA", Italian and Spanish was never included
+ "SPA"*/
+};
+
+const char *KyraEngine_v2::_scriptLangExt[] = {
+ "EMC",
+ "FMC",
+ "GMC"/*,
+ "IMC", Italian and Spanish was never included
+ "SMC"*/
+};
+
+int KyraEngine_v2::_characterFrameTable[] = {
+ 0x19, 0x09, 0x09, 0x12, 0x12, 0x12, 0x09, 0x09
+};
+
+int KyraEngine_v2::_inventoryX[] = {
+ 0x4F, 0x63, 0x77, 0x8B, 0x9F, 0x4F, 0x63, 0x77, 0x8B, 0x9F
+};
+
+int KyraEngine_v2::_inventoryY[] = {
+ 0x95, 0x95, 0x95, 0x95, 0x95, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA
+};
+
// kyra 3 static res
const char *KyraEngine_v3::_soundList[] = {
diff --git a/engines/kyra/text.cpp b/engines/kyra/text.cpp
index 58ce3c9d1e..e62410ca19 100644
--- a/engines/kyra/text.cpp
+++ b/engines/kyra/text.cpp
@@ -28,8 +28,6 @@
#include "kyra/kyra.h"
#include "kyra/screen.h"
#include "kyra/text.h"
-#include "kyra/animator.h"
-#include "kyra/sprites.h"
#include "common/events.h"
#include "common/system.h"
@@ -37,369 +35,6 @@
namespace Kyra {
-void KyraEngine::waitForChatToFinish(int vocFile, int16 chatDuration, const char *chatStr, uint8 charNum) {
- debugC(9, kDebugLevelMain, "KyraEngine::waitForChatToFinish(%i, %s, %i)", chatDuration, chatStr, charNum);
- bool hasUpdatedNPCs = false;
- bool runLoop = true;
- bool drawText = textEnabled();
- uint8 currPage;
- Common::Event event;
-
- //while (towns_isEscKeyPressed() )
- //towns_getKey();
-
- uint32 timeToEnd = strlen(chatStr) * 8 * _tickLength + _system->getMillis();
-
- if (_configVoice == 0 && chatDuration != -1) {
- switch (_configTextspeed) {
- case 0:
- chatDuration *= 2;
- break;
- case 2:
- chatDuration /= 4;
- break;
- case 3:
- chatDuration = -1;
- break;
- }
- }
-
- if (chatDuration != -1)
- chatDuration *= _tickLength;
-
- if (vocFile != -1) {
- snd_voiceWaitForFinish();
- snd_playVoiceFile(vocFile);
- }
-
- disableTimer(14);
- disableTimer(18);
- disableTimer(19);
-
- uint32 timeAtStart = _system->getMillis();
- uint32 loopStart;
- while (runLoop) {
- loopStart = _system->getMillis();
- if (_currentCharacter->sceneId == 210)
- if (seq_playEnd())
- break;
-
- if (_system->getMillis() > timeToEnd && !hasUpdatedNPCs) {
- hasUpdatedNPCs = true;
- disableTimer(15);
- _currHeadShape = 4;
- _animator->animRefreshNPC(0);
- _animator->animRefreshNPC(_talkingCharNum);
-
- if (_charSayUnk2 != -1) {
- _animator->sprites()[_charSayUnk2].active = 0;
- _sprites->_anims[_charSayUnk2].play = false;
- _charSayUnk2 = -1;
- }
- }
-
- updateGameTimers();
- _sprites->updateSceneAnims();
- _animator->restoreAllObjectBackgrounds();
- _animator->preserveAnyChangedBackgrounds();
- _animator->prepDrawAllObjects();
-
- if (drawText) {
- currPage = _screen->_curPage;
- _screen->_curPage = 2;
- _text->printCharacterText(chatStr, charNum, _characterList[charNum].x1);
- _animator->_updateScreen = true;
- _screen->_curPage = currPage;
- }
-
- _animator->copyChangedObjectsForward(0);
- updateTextFade();
-
- if ((chatDuration < (int16)(_system->getMillis() - timeAtStart)) && chatDuration != -1 && (!drawText || !snd_voiceIsPlaying()))
- break;
-
- uint32 nextTime = loopStart + _tickLength;
-
- while (_system->getMillis() < nextTime) {
- while (_eventMan->pollEvent(event)) {
- switch (event.type) {
- case Common::EVENT_KEYDOWN:
- if (event.kbd.keycode == '.')
- _skipFlag = true;
- break;
- case Common::EVENT_QUIT:
- quitGame();
- runLoop = false;
- break;
- case Common::EVENT_LBUTTONDOWN:
- runLoop = false;
- break;
- default:
- break;
- }
- }
-
- if (nextTime - _system->getMillis() >= 10) {
- _system->delayMillis(10);
- _system->updateScreen();
- }
- }
-
- if (_skipFlag)
- runLoop = false;
- }
-
- snd_voiceWaitForFinish();
- snd_stopVoice();
-
- enableTimer(14);
- enableTimer(15);
- enableTimer(18);
- enableTimer(19);
- //clearKyrandiaButtonIO();
-}
-
-void KyraEngine::endCharacterChat(int8 charNum, int16 convoInitialized) {
- _charSayUnk3 = -1;
-
- if (charNum > 4 && charNum < 11) {
- //TODO: weird _game_inventory stuff here
- warning("STUB: endCharacterChat() for high charnums");
- }
-
- if (convoInitialized != 0) {
- _talkingCharNum = -1;
- if (_currentCharacter->currentAnimFrame != 88)
- _currentCharacter->currentAnimFrame = 7;
- _animator->animRefreshNPC(0);
- _animator->updateAllObjectShapes();
- }
-}
-
-void KyraEngine::restoreChatPartnerAnimFrame(int8 charNum) {
- _talkingCharNum = -1;
-
- if (charNum > 0 && charNum < 5) {
- _characterList[charNum].currentAnimFrame = _currentChatPartnerBackupFrame;
- _animator->animRefreshNPC(charNum);
- }
-
- if (_currentCharacter->currentAnimFrame != 88)
- _currentCharacter->currentAnimFrame = 7;
-
- _animator->animRefreshNPC(0);
- _animator->updateAllObjectShapes();
-}
-
-void KyraEngine::backupChatPartnerAnimFrame(int8 charNum) {
- _talkingCharNum = 0;
-
- if (charNum < 5 && charNum > 0)
- _currentChatPartnerBackupFrame = _characterList[charNum].currentAnimFrame;
-
- if (_currentCharacter->currentAnimFrame != 88) {
- _currentCharacter->currentAnimFrame = 16;
- if (_scaleMode != 0)
- _currentCharacter->currentAnimFrame = 7;
- }
-
- _animator->animRefreshNPC(0);
- _animator->updateAllObjectShapes();
-}
-
-int8 KyraEngine::getChatPartnerNum() {
- uint8 sceneTable[] = {0x2, 0x5, 0x2D, 0x7, 0x1B, 0x8, 0x22, 0x9, 0x30, 0x0A};
- int pos = 0;
- int partner = -1;
-
- for (int i = 1; i < 6; i++) {
- if (_currentCharacter->sceneId == sceneTable[pos]) {
- partner = sceneTable[pos+1];
- break;
- }
- pos += 2;
- }
-
- for (int i = 1; i < 5; i++) {
- if (_characterList[i].sceneId == _currentCharacter->sceneId) {
- partner = i;
- break;
- }
- }
- return partner;
-}
-
-int KyraEngine::initCharacterChat(int8 charNum) {
- int returnValue = 0;
-
- if (_talkingCharNum == -1) {
- returnValue = 1;
- _talkingCharNum = 0;
-
- if (_currentCharacter->currentAnimFrame != 88) {
- _currentCharacter->currentAnimFrame = 16;
- if (_scaleMode != 0)
- _currentCharacter->currentAnimFrame = 7;
- }
-
- _animator->animRefreshNPC(0);
- _animator->updateAllObjectShapes();
- }
-
- _charSayUnk2 = -1;
- _animator->flagAllObjectsForBkgdChange();
- _animator->restoreAllObjectBackgrounds();
-
- if (charNum > 4 && charNum < 11) {
- // TODO: Fill in weird _game_inventory stuff here
- warning("STUB: initCharacterChat() for high charnums");
- }
-
- _animator->flagAllObjectsForRefresh();
- _animator->flagAllObjectsForBkgdChange();
- _animator->preserveAnyChangedBackgrounds();
- _charSayUnk3 = charNum;
-
- return returnValue;
-}
-
-void KyraEngine::characterSays(int vocFile, const char *chatStr, int8 charNum, int8 chatDuration) {
- debugC(9, kDebugLevelMain, "KyraEngine::characterSays('%s', %i, %d)", chatStr, charNum, chatDuration);
- uint8 startAnimFrames[] = { 0x10, 0x32, 0x56, 0x0, 0x0, 0x0 };
-
- uint16 chatTicks;
- int16 convoInitialized;
- int8 chatPartnerNum;
-
- if (_currentCharacter->sceneId == 210)
- return;
-
- convoInitialized = initCharacterChat(charNum);
- chatPartnerNum = getChatPartnerNum();
-
- if (chatPartnerNum >= 0 && chatPartnerNum < 5)
- backupChatPartnerAnimFrame(chatPartnerNum);
-
- if (charNum < 5) {
- _characterList[charNum].currentAnimFrame = startAnimFrames[charNum];
- _charSayUnk3 = charNum;
- _talkingCharNum = charNum;
- _animator->animRefreshNPC(charNum);
- }
-
- char *processedString = _text->preprocessString(chatStr);
- int lineNum = _text->buildMessageSubstrings(processedString);
-
- int16 yPos = _characterList[charNum].y1;
- yPos -= ((_scaleTable[yPos] * _characterList[charNum].height) >> 8);
- yPos -= 8;
- yPos -= lineNum * 10;
-
- if (yPos < 11)
- yPos = 11;
-
- if (yPos > 100)
- yPos = 100;
-
- _text->_talkMessageY = yPos;
- _text->_talkMessageH = lineNum * 10;
-
- if (textEnabled()) {
- _animator->restoreAllObjectBackgrounds();
-
- _screen->copyRegion(12, _text->_talkMessageY, 12, 136, 308, _text->_talkMessageH, 2, 2);
- _screen->hideMouse();
-
- _text->printCharacterText(processedString, charNum, _characterList[charNum].x1);
- _screen->showMouse();
- }
-
- if (chatDuration == -2)
- chatTicks = strlen(processedString) * 9;
- else
- chatTicks = chatDuration;
-
- if (!speechEnabled())
- vocFile = -1;
- waitForChatToFinish(vocFile, chatTicks, chatStr, charNum);
-
- if (textEnabled()) {
- _animator->restoreAllObjectBackgrounds();
-
- _screen->copyRegion(12, 136, 12, _text->_talkMessageY, 308, _text->_talkMessageH, 2, 2);
- _animator->preserveAllBackgrounds();
- _animator->prepDrawAllObjects();
- _screen->hideMouse();
-
- _screen->copyRegion(12, _text->_talkMessageY, 12, _text->_talkMessageY, 308, _text->_talkMessageH, 2, 0);
- _screen->showMouse();
- _animator->flagAllObjectsForRefresh();
- _animator->copyChangedObjectsForward(0);
- }
-
- if (chatPartnerNum != -1 && chatPartnerNum < 5)
- restoreChatPartnerAnimFrame(chatPartnerNum);
-
- endCharacterChat(charNum, convoInitialized);
-}
-
-void KyraEngine::drawSentenceCommand(const char *sentence, int color) {
- debugC(9, kDebugLevelMain, "KyraEngine::drawSentenceCommand('%s', %i)", sentence, color);
- _screen->hideMouse();
- _screen->fillRect(8, 143, 311, 152, 12);
-
- if (_startSentencePalIndex != color || _fadeText != false) {
- _currSentenceColor[0] = _screen->_currentPalette[765] = _screen->_currentPalette[color*3];
- _currSentenceColor[1] = _screen->_currentPalette[766] = _screen->_currentPalette[color*3+1];
- _currSentenceColor[2] = _screen->_currentPalette[767] = _screen->_currentPalette[color*3+2];
-
- _screen->setScreenPalette(_screen->_currentPalette);
- _startSentencePalIndex = 0;
- }
-
- _text->printText(sentence, 8, 143, 0xFF, 12, 0);
- _screen->showMouse();
- setTextFadeTimerCountdown(15);
- _fadeText = false;
-}
-
-void KyraEngine::updateSentenceCommand(const char *str1, const char *str2, int color) {
- debugC(9, kDebugLevelMain, "KyraEngine::updateSentenceCommand('%s', '%s', %i)", str1, str2, color);
- char sentenceCommand[500];
- strncpy(sentenceCommand, str1, 500);
- if (str2)
- strncat(sentenceCommand, str2, 500 - strlen(sentenceCommand));
-
- drawSentenceCommand(sentenceCommand, color);
- _screen->updateScreen();
-}
-
-void KyraEngine::updateTextFade() {
- debugC(9, kDebugLevelMain, "KyraEngine::updateTextFade()");
- if (!_fadeText)
- return;
-
- bool finished = false;
- for (int i = 0; i < 3; i++)
- if (_currSentenceColor[i] > 4)
- _currSentenceColor[i] -= 4;
- else
- if (_currSentenceColor[i]) {
- _currSentenceColor[i] = 0;
- finished = true;
- }
-
- _screen->_currentPalette[765] = _currSentenceColor[0];
- _screen->_currentPalette[766] = _currSentenceColor[1];
- _screen->_currentPalette[767] = _currSentenceColor[2];
- _screen->setScreenPalette(_screen->_currentPalette);
-
- if (finished) {
- _fadeText = false;
- _startSentencePalIndex = -1;
- }
-}
-
TextDisplayer::TextDisplayer(KyraEngine *vm, Screen *screen) {
_screen = screen;
_vm = vm;
diff --git a/engines/kyra/text_v1.cpp b/engines/kyra/text_v1.cpp
new file mode 100644
index 0000000000..c04aa2105f
--- /dev/null
+++ b/engines/kyra/text_v1.cpp
@@ -0,0 +1,399 @@
+/* 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 "kyra/kyra_v1.h"
+#include "kyra/screen_v1.h"
+#include "kyra/text.h"
+#include "kyra/animator_v1.h"
+#include "kyra/sprites.h"
+#include "kyra/timer.h"
+
+namespace Kyra {
+
+void KyraEngine_v1::waitForChatToFinish(int vocFile, int16 chatDuration, const char *chatStr, uint8 charNum) {
+ debugC(9, kDebugLevelMain, "KyraEngine_v1::waitForChatToFinish(%i, %s, %i)", chatDuration, chatStr, charNum);
+ bool hasUpdatedNPCs = false;
+ bool runLoop = true;
+ bool drawText = textEnabled();
+ uint8 currPage;
+ Common::Event event;
+
+ //while (towns_isEscKeyPressed() )
+ //towns_getKey();
+
+ uint32 timeToEnd = strlen(chatStr) * 8 * _tickLength + _system->getMillis();
+
+ if (_configVoice == 0 && chatDuration != -1) {
+ switch (_configTextspeed) {
+ case 0:
+ chatDuration *= 2;
+ break;
+ case 2:
+ chatDuration /= 4;
+ break;
+ case 3:
+ chatDuration = -1;
+ break;
+ }
+ }
+
+ if (chatDuration != -1)
+ chatDuration *= _tickLength;
+
+ if (vocFile != -1) {
+ snd_voiceWaitForFinish();
+ snd_playVoiceFile(vocFile);
+ }
+
+ _timer->disable(14);
+ _timer->disable(18);
+ _timer->disable(19);
+
+ uint32 timeAtStart = _system->getMillis();
+ uint32 loopStart;
+ while (runLoop) {
+ loopStart = _system->getMillis();
+ if (_currentCharacter->sceneId == 210)
+ if (seq_playEnd())
+ break;
+
+ if (_system->getMillis() > timeToEnd && !hasUpdatedNPCs) {
+ hasUpdatedNPCs = true;
+ _timer->disable(15);
+ _currHeadShape = 4;
+ _animator->animRefreshNPC(0);
+ _animator->animRefreshNPC(_talkingCharNum);
+
+ if (_charSayUnk2 != -1) {
+ _animator->sprites()[_charSayUnk2].active = 0;
+ _sprites->_anims[_charSayUnk2].play = false;
+ _charSayUnk2 = -1;
+ }
+ }
+
+ _timer->update();
+ _sprites->updateSceneAnims();
+ _animator->restoreAllObjectBackgrounds();
+ _animator->preserveAnyChangedBackgrounds();
+ _animator->prepDrawAllObjects();
+
+ if (drawText) {
+ currPage = _screen->_curPage;
+ _screen->_curPage = 2;
+ _text->printCharacterText(chatStr, charNum, _characterList[charNum].x1);
+ _animator->_updateScreen = true;
+ _screen->_curPage = currPage;
+ }
+
+ _animator->copyChangedObjectsForward(0);
+ updateTextFade();
+
+ if ((chatDuration < (int16)(_system->getMillis() - timeAtStart)) && chatDuration != -1 && (!drawText || !snd_voiceIsPlaying()))
+ break;
+
+ uint32 nextTime = loopStart + _tickLength;
+
+ while (_system->getMillis() < nextTime) {
+ while (_eventMan->pollEvent(event)) {
+ switch (event.type) {
+ case Common::EVENT_KEYDOWN:
+ if (event.kbd.keycode == '.')
+ _skipFlag = true;
+ break;
+ case Common::EVENT_QUIT:
+ quitGame();
+ runLoop = false;
+ break;
+ case Common::EVENT_LBUTTONDOWN:
+ runLoop = false;
+ break;
+ default:
+ break;
+ }
+ }
+
+ if (nextTime - _system->getMillis() >= 10) {
+ _system->delayMillis(10);
+ _system->updateScreen();
+ }
+ }
+
+ if (_skipFlag)
+ runLoop = false;
+ }
+
+ snd_voiceWaitForFinish();
+ snd_stopVoice();
+
+ _timer->enable(14);
+ _timer->enable(15);
+ _timer->enable(18);
+ _timer->enable(19);
+ //clearKyrandiaButtonIO();
+}
+
+void KyraEngine_v1::endCharacterChat(int8 charNum, int16 convoInitialized) {
+ _charSayUnk3 = -1;
+
+ if (charNum > 4 && charNum < 11) {
+ //TODO: weird _game_inventory stuff here
+ warning("STUB: endCharacterChat() for high charnums");
+ }
+
+ if (convoInitialized != 0) {
+ _talkingCharNum = -1;
+ if (_currentCharacter->currentAnimFrame != 88)
+ _currentCharacter->currentAnimFrame = 7;
+ _animator->animRefreshNPC(0);
+ _animator->updateAllObjectShapes();
+ }
+}
+
+void KyraEngine_v1::restoreChatPartnerAnimFrame(int8 charNum) {
+ _talkingCharNum = -1;
+
+ if (charNum > 0 && charNum < 5) {
+ _characterList[charNum].currentAnimFrame = _currentChatPartnerBackupFrame;
+ _animator->animRefreshNPC(charNum);
+ }
+
+ if (_currentCharacter->currentAnimFrame != 88)
+ _currentCharacter->currentAnimFrame = 7;
+
+ _animator->animRefreshNPC(0);
+ _animator->updateAllObjectShapes();
+}
+
+void KyraEngine_v1::backupChatPartnerAnimFrame(int8 charNum) {
+ _talkingCharNum = 0;
+
+ if (charNum < 5 && charNum > 0)
+ _currentChatPartnerBackupFrame = _characterList[charNum].currentAnimFrame;
+
+ if (_currentCharacter->currentAnimFrame != 88) {
+ _currentCharacter->currentAnimFrame = 16;
+ if (_scaleMode != 0)
+ _currentCharacter->currentAnimFrame = 7;
+ }
+
+ _animator->animRefreshNPC(0);
+ _animator->updateAllObjectShapes();
+}
+
+int8 KyraEngine_v1::getChatPartnerNum() {
+ uint8 sceneTable[] = {0x2, 0x5, 0x2D, 0x7, 0x1B, 0x8, 0x22, 0x9, 0x30, 0x0A};
+ int pos = 0;
+ int partner = -1;
+
+ for (int i = 1; i < 6; i++) {
+ if (_currentCharacter->sceneId == sceneTable[pos]) {
+ partner = sceneTable[pos+1];
+ break;
+ }
+ pos += 2;
+ }
+
+ for (int i = 1; i < 5; i++) {
+ if (_characterList[i].sceneId == _currentCharacter->sceneId) {
+ partner = i;
+ break;
+ }
+ }
+ return partner;
+}
+
+int KyraEngine_v1::initCharacterChat(int8 charNum) {
+ int returnValue = 0;
+
+ if (_talkingCharNum == -1) {
+ returnValue = 1;
+ _talkingCharNum = 0;
+
+ if (_currentCharacter->currentAnimFrame != 88) {
+ _currentCharacter->currentAnimFrame = 16;
+ if (_scaleMode != 0)
+ _currentCharacter->currentAnimFrame = 7;
+ }
+
+ _animator->animRefreshNPC(0);
+ _animator->updateAllObjectShapes();
+ }
+
+ _charSayUnk2 = -1;
+ _animator->flagAllObjectsForBkgdChange();
+ _animator->restoreAllObjectBackgrounds();
+
+ if (charNum > 4 && charNum < 11) {
+ // TODO: Fill in weird _game_inventory stuff here
+ warning("STUB: initCharacterChat() for high charnums");
+ }
+
+ _animator->flagAllObjectsForRefresh();
+ _animator->flagAllObjectsForBkgdChange();
+ _animator->preserveAnyChangedBackgrounds();
+ _charSayUnk3 = charNum;
+
+ return returnValue;
+}
+
+void KyraEngine_v1::characterSays(int vocFile, const char *chatStr, int8 charNum, int8 chatDuration) {
+ debugC(9, kDebugLevelMain, "KyraEngine_v1::characterSays('%s', %i, %d)", chatStr, charNum, chatDuration);
+ uint8 startAnimFrames[] = { 0x10, 0x32, 0x56, 0x0, 0x0, 0x0 };
+
+ uint16 chatTicks;
+ int16 convoInitialized;
+ int8 chatPartnerNum;
+
+ if (_currentCharacter->sceneId == 210)
+ return;
+
+ convoInitialized = initCharacterChat(charNum);
+ chatPartnerNum = getChatPartnerNum();
+
+ if (chatPartnerNum >= 0 && chatPartnerNum < 5)
+ backupChatPartnerAnimFrame(chatPartnerNum);
+
+ if (charNum < 5) {
+ _characterList[charNum].currentAnimFrame = startAnimFrames[charNum];
+ _charSayUnk3 = charNum;
+ _talkingCharNum = charNum;
+ _animator->animRefreshNPC(charNum);
+ }
+
+ char *processedString = _text->preprocessString(chatStr);
+ int lineNum = _text->buildMessageSubstrings(processedString);
+
+ int16 yPos = _characterList[charNum].y1;
+ yPos -= ((_scaleTable[yPos] * _characterList[charNum].height) >> 8);
+ yPos -= 8;
+ yPos -= lineNum * 10;
+
+ if (yPos < 11)
+ yPos = 11;
+
+ if (yPos > 100)
+ yPos = 100;
+
+ _text->_talkMessageY = yPos;
+ _text->_talkMessageH = lineNum * 10;
+
+ if (textEnabled()) {
+ _animator->restoreAllObjectBackgrounds();
+
+ _screen->copyRegion(12, _text->_talkMessageY, 12, 136, 308, _text->_talkMessageH, 2, 2);
+ _screen->hideMouse();
+
+ _text->printCharacterText(processedString, charNum, _characterList[charNum].x1);
+ _screen->showMouse();
+ }
+
+ if (chatDuration == -2)
+ chatTicks = strlen(processedString) * 9;
+ else
+ chatTicks = chatDuration;
+
+ if (!speechEnabled())
+ vocFile = -1;
+ waitForChatToFinish(vocFile, chatTicks, chatStr, charNum);
+
+ if (textEnabled()) {
+ _animator->restoreAllObjectBackgrounds();
+
+ _screen->copyRegion(12, 136, 12, _text->_talkMessageY, 308, _text->_talkMessageH, 2, 2);
+ _animator->preserveAllBackgrounds();
+ _animator->prepDrawAllObjects();
+ _screen->hideMouse();
+
+ _screen->copyRegion(12, _text->_talkMessageY, 12, _text->_talkMessageY, 308, _text->_talkMessageH, 2, 0);
+ _screen->showMouse();
+ _animator->flagAllObjectsForRefresh();
+ _animator->copyChangedObjectsForward(0);
+ }
+
+ if (chatPartnerNum != -1 && chatPartnerNum < 5)
+ restoreChatPartnerAnimFrame(chatPartnerNum);
+
+ endCharacterChat(charNum, convoInitialized);
+}
+
+void KyraEngine_v1::drawSentenceCommand(const char *sentence, int color) {
+ debugC(9, kDebugLevelMain, "KyraEngine_v1::drawSentenceCommand('%s', %i)", sentence, color);
+ _screen->hideMouse();
+ _screen->fillRect(8, 143, 311, 152, 12);
+
+ if (_startSentencePalIndex != color || _fadeText != false) {
+ _currSentenceColor[0] = _screen->_currentPalette[765] = _screen->_currentPalette[color*3];
+ _currSentenceColor[1] = _screen->_currentPalette[766] = _screen->_currentPalette[color*3+1];
+ _currSentenceColor[2] = _screen->_currentPalette[767] = _screen->_currentPalette[color*3+2];
+
+ _screen->setScreenPalette(_screen->_currentPalette);
+ _startSentencePalIndex = 0;
+ }
+
+ _text->printText(sentence, 8, 143, 0xFF, 12, 0);
+ _screen->showMouse();
+ setTextFadeTimerCountdown(15);
+ _fadeText = false;
+}
+
+void KyraEngine_v1::updateSentenceCommand(const char *str1, const char *str2, int color) {
+ debugC(9, kDebugLevelMain, "KyraEngine_v1::updateSentenceCommand('%s', '%s', %i)", str1, str2, color);
+ char sentenceCommand[500];
+ strncpy(sentenceCommand, str1, 500);
+ if (str2)
+ strncat(sentenceCommand, str2, 500 - strlen(sentenceCommand));
+
+ drawSentenceCommand(sentenceCommand, color);
+ _screen->updateScreen();
+}
+
+void KyraEngine_v1::updateTextFade() {
+ debugC(9, kDebugLevelMain, "KyraEngine_v1::updateTextFade()");
+ if (!_fadeText)
+ return;
+
+ bool finished = false;
+ for (int i = 0; i < 3; i++) {
+ if (_currSentenceColor[i] > 4)
+ _currSentenceColor[i] -= 4;
+ else
+ if (_currSentenceColor[i]) {
+ _currSentenceColor[i] = 0;
+ finished = true;
+ }
+ }
+
+ _screen->_currentPalette[765] = _currSentenceColor[0];
+ _screen->_currentPalette[766] = _currSentenceColor[1];
+ _screen->_currentPalette[767] = _currSentenceColor[2];
+ _screen->setScreenPalette(_screen->_currentPalette);
+
+ if (finished) {
+ _fadeText = false;
+ _startSentencePalIndex = -1;
+ }
+}
+
+} // end of namespace Kyra
diff --git a/engines/kyra/timer.cpp b/engines/kyra/timer.cpp
index a35b701697..dff191cbe0 100644
--- a/engines/kyra/timer.cpp
+++ b/engines/kyra/timer.cpp
@@ -11,7 +11,7 @@
* 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
+ * 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
@@ -24,269 +24,228 @@
*/
#include "kyra/kyra.h"
-#include "kyra/screen.h"
-#include "kyra/animator.h"
+#include "kyra/timer.h"
-#include "common/system.h"
+#include "common/func.h"
+#include "common/savefile.h"
namespace Kyra {
-void KyraEngine::setupTimers() {
- debugC(9, kDebugLevelMain, "KyraEngine::setupTimers()");
- memset(_timers, 0, sizeof(_timers));
-
- for (int i = 0; i < 34; i++)
- _timers[i].active = 1;
-
- _timers[0].func = _timers[1].func = _timers[2].func = _timers[3].func = _timers[4].func = 0; //Unused.
- _timers[5].func = _timers[6].func = _timers[7].func = _timers[8].func = _timers[9].func = 0; //_nullsub51;
- _timers[10].func = _timers[11].func = _timers[12].func = _timers[13].func = 0; //_nullsub50;
- _timers[14].func = &KyraEngine::timerCheckAnimFlag2; //_nullsub52;
- _timers[15].func = &KyraEngine::timerUpdateHeadAnims; //_nullsub48;
- _timers[16].func = &KyraEngine::timerSetFlags1; //_nullsub47;
- _timers[17].func = 0; //sub_15120;
- _timers[18].func = &KyraEngine::timerCheckAnimFlag1; //_nullsub53;
- _timers[19].func = &KyraEngine::timerRedrawAmulet; //_nullsub54;
- _timers[20].func = 0; //offset _timerDummy1
- _timers[21].func = 0; //sub_1517C;
- _timers[22].func = 0; //offset _timerDummy2
- _timers[23].func = 0; //offset _timerDummy3,
- _timers[24].func = 0; //_nullsub45;
- _timers[25].func = 0; //offset _timerDummy4
- _timers[26].func = 0; //_nullsub46;
- _timers[27].func = 0; //offset _timerDummy5,
- _timers[28].func = 0; //offset _timerDummy6
- _timers[29].func = 0; //offset _timerDummy7,
- _timers[30].func = 0; //offset _timerDummy8,
- _timers[31].func = &KyraEngine::timerFadeText; //sub_151F8;
- _timers[32].func = &KyraEngine::updateAnimFlag1; //_nullsub61;
- _timers[33].func = &KyraEngine::updateAnimFlag2; //_nullsub62;
-
- _timers[0].countdown = _timers[1].countdown = _timers[2].countdown = _timers[3].countdown = _timers[4].countdown = -1;
- _timers[5].countdown = 5;
- _timers[6].countdown = 7;
- _timers[7].countdown = 8;
- _timers[8].countdown = 9;
- _timers[9].countdown = 7;
- _timers[10].countdown = _timers[11].countdown = _timers[12].countdown = _timers[13].countdown = 420;
- _timers[14].countdown = 600;
- _timers[15].countdown = 11;
- _timers[16].countdown = _timers[17].countdown = 7200;
- _timers[18].countdown = _timers[19].countdown = 600;
- _timers[20].countdown = 7200;
- _timers[21].countdown = 18000;
- _timers[22].countdown = 7200;
- _timers[23].countdown = _timers[24].countdown = _timers[25].countdown = _timers[26].countdown = _timers[27].countdown = 10800;
- _timers[28].countdown = 21600;
- _timers[29].countdown = 7200;
- _timers[30].countdown = 10800;
- _timers[31].countdown = -1;
- _timers[32].countdown = 9;
- _timers[33].countdown = 3;
-}
-
-void KyraEngine::updateGameTimers() {
- debugC(9, kDebugLevelMain, "KyraEngine::updateGameTimers()");
-
- if (_system->getMillis() < _timerNextRun)
- return;
- _timerNextRun += 99999;
-
- for (int i = 0; i < 34; i++) {
- if (_timers[i].active && _timers[i].countdown > -1) {
- if (_timers[i].nextRun <=_system->getMillis()) {
- if (i > 4 && _timers[i].func)
- (*this.*_timers[i].func)(i);
-
- _timers[i].nextRun = _system->getMillis() + _timers[i].countdown * _tickLength;
- }
+namespace {
+struct TimerResync : public Common::UnaryFunction<TimerEntry&, void> {
+ uint32 _tickLength, _curTime;
+ TimerResync(KyraEngine *vm, uint32 curTime) : _tickLength(vm->tickLength()), _curTime(curTime) {}
+
+ void operator()(TimerEntry &entry) const {
+ if (entry.lastUpdate < 0) {
+ if ((entry.lastUpdate + _curTime) <= 0)
+ entry.nextRun = 0;
+ else
+ entry.nextRun = _curTime + entry.lastUpdate + entry.countdown * _tickLength;
+ } else {
+ uint32 nextRun = entry.lastUpdate + entry.countdown * _tickLength;
+ if (_curTime < nextRun)
+ nextRun = 0;
+ entry.nextRun = nextRun;
}
- if (_timers[i].nextRun < _timerNextRun)
- _timerNextRun = _timers[i].nextRun;
}
-}
-
-void KyraEngine::clearNextEventTickCount() {
- debugC(9, kDebugLevelMain, "KyraEngine::clearNextEventTickCount()");
- _timerNextRun = 0;
-}
+};
-void KyraEngine::setTimerDelay(uint8 timer, int32 countdown) {
- debugC(9, kDebugLevelMain, "KyraEngine::setTimerDelay(%i, %d)", timer, countdown);
- _timers[timer].countdown = countdown;
-}
+struct TimerEqual : public Common::UnaryFunction<const TimerEntry&, bool> {
+ uint8 _id;
+
+ TimerEqual(uint8 id) : _id(id) {}
-int16 KyraEngine::getTimerDelay(uint8 timer) {
- debugC(9, kDebugLevelMain, "KyraEngine::getTimerDelay(%i)", timer);
- return _timers[timer].countdown;
-}
+ bool operator()(const TimerEntry &entry) const {
+ return entry.id == _id;
+ }
+};
+} // end of anonymous namespace
-void KyraEngine::setTimerCountdown(uint8 timer, int32 countdown) {
- debugC(9, kDebugLevelMain, "KyraEngine::setTimerCountdown(%i, %i)", timer, countdown);
- _timers[timer].countdown = countdown;
- _timers[timer].nextRun = _system->getMillis() + countdown * _tickLength;
+void TimerManager::reset() {
+ for (Iterator pos = _timers.begin(); pos != _timers.end(); ++pos) {
+ delete pos->func;
+ }
- uint32 nextRun = _system->getMillis() + countdown * _tickLength;
- if (nextRun < _timerNextRun)
- _timerNextRun = nextRun;
+ _timers.clear();
}
-void KyraEngine::enableTimer(uint8 timer) {
- debugC(9, kDebugLevelMain, "KyraEngine::enableTimer(%i)", timer);
- _timers[timer].active = 1;
-}
+void TimerManager::addTimer(uint8 id, TimerFunc *func, int countdown, bool enabled) {
+ debugC(9, kDebugLevelTimer, "TimerManager::addTimer(%d, %p, %d, %d)", id, (const void*)func, countdown, enabled);
-void KyraEngine::disableTimer(uint8 timer) {
- debugC(9, kDebugLevelMain, "KyraEngine::disableTimer(%i)", timer);
- _timers[timer].active = 0;
+ TimerEntry newTimer;
+
+ newTimer.id = id;
+ newTimer.countdown = countdown;
+ newTimer.enabled = enabled ? 1 : 0;
+ newTimer.lastUpdate = newTimer.nextRun = 0;
+ newTimer.func = func;
+
+ _timers.push_back(newTimer);
}
-void KyraEngine::timerUpdateHeadAnims(int timerNum) {
- debugC(9, kDebugLevelMain, "KyraEngine::timerUpdateHeadAnims(%i)", timerNum);
- static int8 currentFrame = 0;
- static const int8 frameTable[] = {4, 5, 4, 5, 4, 5, 0, 1, 4, 5,
- 4, 4, 6, 4, 8, 1, 9, 4, -1};
+void TimerManager::update() {
+ debugC(9, kDebugLevelTimer, "TimerManager::update()");
- if (_talkingCharNum < 0)
+ if (_system->getMillis() < _nextRun)
return;
+
+ _nextRun += 99999;
+
+ for (Iterator pos = _timers.begin(); pos != _timers.end(); ++pos) {
+ if (pos->enabled && pos->countdown >= 0 && pos->nextRun <= _system->getMillis()) {
+ if (pos->func && *pos->func)
+ (*pos->func)(pos->id);
+
+ uint32 curTime = _system->getMillis();
+ pos->lastUpdate = curTime;
+ pos->nextRun = curTime + pos->countdown * _vm->tickLength();
+
+ _nextRun = MIN(_nextRun, pos->nextRun);
+ }
+ }
+}
- _currHeadShape = frameTable[currentFrame];
- currentFrame++;
+void TimerManager::resync() {
+ debugC(9, kDebugLevelTimer, "TimerManager::resync()");
- if (frameTable[currentFrame] == -1)
- currentFrame = 0;
+ _nextRun = 0; // force rerun
+ Common::for_each(_timers.begin(), _timers.end(), TimerResync(_vm, _system->getMillis()));
+}
- _animator->animRefreshNPC(0);
- _animator->animRefreshNPC(_talkingCharNum);
+void TimerManager::resetNextRun() {
+ debugC(9, kDebugLevelTimer, "TimerManager::resetNextRun()");
+ _nextRun = 0;
}
-void KyraEngine::timerSetFlags1(int timerNum) {
- debugC(9, kDebugLevelMain, "KyraEngine::timerSetFlags(%i)", timerNum);
- if (_currentCharacter->sceneId == 0x1C)
- return;
+void TimerManager::setCountdown(uint8 id, int32 countdown) {
+ debugC(9, kDebugLevelTimer, "TimerManager::setCountdown(%d, %d)", id, countdown);
- int rndNr = _rnd.getRandomNumberRng(0, 3);
+ Iterator timer = Common::find_if(_timers.begin(), _timers.end(), TimerEqual(id));
+ if (timer != _timers.end()) {
+ timer->countdown = countdown;
- for (int i = 0; i < 4; i++) {
- if (!queryGameFlag(rndNr + 17)) {
- setGameFlag(rndNr + 17);
- break;
- } else {
- rndNr++;
- if (rndNr > 3)
- rndNr = 0;
+ if (countdown >= 0) {
+ uint32 curTime = _system->getMillis();
+ timer->lastUpdate = curTime;
+ timer->nextRun = curTime + countdown * _vm->tickLength();
+
+ _nextRun = MIN(_nextRun, timer->nextRun);
}
+ } else {
+ warning("TimerManager::setCountdown: No timer %d", id);
}
}
-void KyraEngine::timerFadeText(int timerNum) {
- debugC(9, kDebugLevelMain, "KyraEngine::timerFadeText(%i)", timerNum);
- _fadeText = true;
-}
+void TimerManager::setDelay(uint8 id, int32 countdown) {
+ debugC(9, kDebugLevelTimer, "TimerManager::setDelay(%d, %d)", id, countdown);
-void KyraEngine::updateAnimFlag1(int timerNum) {
- debugC(9, kDebugLevelMain, "KyraEngine::updateAnimFlag1(%d)", timerNum);
- if (_brandonStatusBit & 2) {
- _brandonStatusBit0x02Flag = 1;
- }
+ Iterator timer = Common::find_if(_timers.begin(), _timers.end(), TimerEqual(id));
+ if (timer != _timers.end())
+ timer->countdown = countdown;
+ else
+ warning("TimerManager::setDelay: No timer %d", id);
}
-void KyraEngine::updateAnimFlag2(int timerNum) {
- debugC(9, kDebugLevelMain, "KyraEngine::updateAnimFlag2(%d)", timerNum);
- if (_brandonStatusBit & 0x20) {
- _brandonStatusBit0x20Flag = 1;
- }
-}
+int32 TimerManager::getDelay(uint8 id) const {
+ debugC(9, kDebugLevelTimer, "TimerManager::getDelay(%d)", id);
-void KyraEngine::setTextFadeTimerCountdown(int16 countdown) {
- debugC(9, kDebugLevelMain, "KyraEngine::setTextFadeTimerCountdown(%i)", countdown);
- //if (countdown == -1)
- //countdown = 32000;
+ CIterator timer = Common::find_if(_timers.begin(), _timers.end(), TimerEqual(id));
+ if (timer != _timers.end())
+ return timer->countdown;
- setTimerCountdown(31, countdown*60);
+ warning("TimerManager::getDelay: No timer %d", id);
+ return -1;
}
-void KyraEngine::timerSetFlags2(int timerNum) {
- debugC(9, kDebugLevelMain, "KyraEngine::timerSetFlags2(%i)", timerNum);
- if (!((uint32*)(_flagsTable+0x2D))[timerNum])
- ((uint32*)(_flagsTable+0x2D))[timerNum] = 1;
-}
+bool TimerManager::isEnabled(uint8 id) const {
+ debugC(9, kDebugLevelTimer, "TimerManager::isEnabled(%d)", id);
-void KyraEngine::timerCheckAnimFlag1(int timerNum) {
- debugC(9, kDebugLevelMain, "KyraEngine::timerCheckAnimFlag1(%i)", timerNum);
- if (_brandonStatusBit & 0x20) {
- checkAmuletAnimFlags();
- setTimerCountdown(18, -1);
- }
-}
+ CIterator timer = Common::find_if(_timers.begin(), _timers.end(), TimerEqual(id));
+ if (timer != _timers.end())
+ return (timer->enabled == 1);
-void KyraEngine::timerCheckAnimFlag2(int timerNum) {
- debugC(9, kDebugLevelMain, "KyraEngine::timerCheckAnimFlag1(%i)", timerNum);
- if (_brandonStatusBit & 0x2) {
- checkAmuletAnimFlags();
- setTimerCountdown(14, -1);
- }
+ warning("TimerManager::isEnabled: No timer %d", id);
+ return false;
}
-void KyraEngine::checkAmuletAnimFlags() {
- debugC(9, kDebugLevelMain, "KyraEngine::checkSpecialAnimFlags()");
- if (_brandonStatusBit & 2) {
- seq_makeBrandonNormal2();
- setTimerCountdown(19, 300);
- }
-
- if (_brandonStatusBit & 0x20) {
- seq_makeBrandonNormal();
- setTimerCountdown(19, 300);
- }
-}
+void TimerManager::enable(uint8 id) {
+ debugC(9, kDebugLevelTimer, "TimerManager::enable(%d)", id);
-void KyraEngine::timerRedrawAmulet(int timerNum) {
- debugC(9, kDebugLevelMain, "KyraEngine::timerRedrawAmulet(%i)", timerNum);
- if (queryGameFlag(0xF1)) {
- drawAmulet();
- setTimerCountdown(19, -1);
- }
+ Iterator timer = Common::find_if(_timers.begin(), _timers.end(), TimerEqual(id));
+ if (timer != _timers.end())
+ timer->enabled = 1;
+ else
+ warning("TimerManager::enable: No timer %d", id);
}
-void KyraEngine::drawAmulet() {
- debugC(9, kDebugLevelMain, "KyraEngine::drawAmulet()");
- static const int16 amuletTable1[] = {0x167, 0x162, 0x15D, 0x158, 0x153, 0x150, 0x155, 0x15A, 0x15F, 0x164, 0x145, -1};
- static const int16 amuletTable3[] = {0x167, 0x162, 0x15D, 0x158, 0x153, 0x14F, 0x154, 0x159, 0x15E, 0x163, 0x144, -1};
- static const int16 amuletTable2[] = {0x167, 0x162, 0x15D, 0x158, 0x153, 0x152, 0x157, 0x15C, 0x161, 0x166, 0x147, -1};
- static const int16 amuletTable4[] = {0x167, 0x162, 0x15D, 0x158, 0x153, 0x151, 0x156, 0x15B, 0x160, 0x165, 0x146, -1};
+void TimerManager::disable(uint8 id) {
+ debugC(9, kDebugLevelTimer, "TimerManager::disable(%d)", id);
- resetGameFlag(0xF1);
- _screen->hideMouse();
-
- int i = 0;
- while (amuletTable1[i] != -1) {
- if (queryGameFlag(87))
- _screen->drawShape(0, _shapes[amuletTable1[i]], _amuletX[0], _amuletY[0], 0, 0);
-
- if (queryGameFlag(89))
- _screen->drawShape(0, _shapes[amuletTable2[i]], _amuletX[1], _amuletY[1], 0, 0);
-
- if (queryGameFlag(86))
- _screen->drawShape(0, _shapes[amuletTable3[i]], _amuletX[2], _amuletY[2], 0, 0);
-
- if (queryGameFlag(88))
- _screen->drawShape(0, _shapes[amuletTable4[i]], _amuletX[3], _amuletY[3], 0, 0);
+ Iterator timer = Common::find_if(_timers.begin(), _timers.end(), TimerEqual(id));
+ if (timer != _timers.end())
+ timer->enabled = 0;
+ else
+ warning("TimerManager::disable: No timer %d", id);
+}
- _screen->updateScreen();
- delayWithTicks(3);
- i++;
+void TimerManager::loadDataFromFile(Common::InSaveFile *file, int version) {
+ debugC(9, kDebugLevelTimer, "TimerManager::loadDataFromFile(%p, %d)", (const void*)file, version);
+
+ if (version <= 7) {
+ _nextRun = 0;
+ for (int i = 0; i < 32; ++i) {
+ uint8 enabled = file->readByte();
+ int32 countdown = file->readSint32BE();
+ uint32 nextRun = file->readUint32BE();
+
+ Iterator timer = Common::find_if(_timers.begin(), _timers.end(), TimerEqual(i));
+ if (timer != _timers.end()) {
+ timer->enabled = enabled;
+ timer->countdown = countdown;
+
+ if (nextRun) {
+ timer->nextRun = nextRun + _system->getMillis();
+ timer->lastUpdate = timer->nextRun - countdown * _vm->tickLength();
+ } else {
+ uint32 curTime = _system->getMillis();
+ timer->nextRun = curTime;
+ timer->lastUpdate = curTime - countdown * _vm->tickLength();
+ }
+ } else {
+ warning("Loading timer data for non existing timer %d", i);
+ }
+ }
+ } else {
+ int entries = file->readByte();
+ for (int i = 0; i < entries; ++i) {
+ uint8 id = file->readByte();
+
+ Iterator timer = Common::find_if(_timers.begin(), _timers.end(), TimerEqual(id));
+ if (timer != _timers.end()) {
+ timer->enabled = file->readByte();
+ timer->countdown = file->readSint32BE();
+ timer->lastUpdate = file->readSint32BE();
+ } else {
+ warning("Loading timer data for non existing timer %d", id);
+ file->seek(7, SEEK_CUR);
+ }
+ }
+
+ resync();
}
- _screen->showMouse();
}
-void KyraEngine::setWalkspeed(uint8 newSpeed) {
- debugC(9, kDebugLevelMain, "KyraEngine::setWalkspeed(%i)", newSpeed);
- static const uint8 speeds[] = {11, 9, 6, 5, 3};
-
- assert(newSpeed < ARRAYSIZE(speeds));
- setTimerDelay(5, speeds[newSpeed]);
+void TimerManager::saveDataToFile(Common::OutSaveFile *file) const {
+ debugC(9, kDebugLevelTimer, "TimerManager::saveDataToFile(%p)", (const void*)file);
+
+ file->writeByte(count());
+ for (CIterator pos = _timers.begin(); pos != _timers.end(); ++pos) {
+ file->writeByte(pos->id);
+ file->writeByte(pos->enabled);
+ file->writeSint32BE(pos->countdown);
+ file->writeSint32BE(pos->lastUpdate - _system->getMillis());
+ }
}
} // end of namespace Kyra
-
diff --git a/engines/kyra/timer.h b/engines/kyra/timer.h
new file mode 100644
index 0000000000..1edeb92a42
--- /dev/null
+++ b/engines/kyra/timer.h
@@ -0,0 +1,93 @@
+/* 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 KYRA_TIMER_H
+#define KYRA_TIMER_H
+
+#include "kyra/kyra.h"
+#include "kyra/util.h"
+
+#include "common/list.h"
+
+namespace Common {
+class InSaveFile;
+class OutSaveFile;
+} // end of namespace Common
+
+namespace Kyra {
+
+typedef Functor1<int, void> TimerFunc;
+
+struct TimerEntry {
+ uint8 id;
+ int32 countdown;
+ int8 enabled;
+
+ int32 lastUpdate;
+ uint32 nextRun;
+
+ TimerFunc *func;
+};
+
+class TimerManager {
+public:
+ TimerManager(KyraEngine *vm, OSystem *sys) : _vm(vm), _system(sys), _timers(), _nextRun(0) {}
+ ~TimerManager() { reset(); }
+
+ void reset();
+
+ void addTimer(uint8 id, TimerFunc *func, int countdown, bool enabled);
+
+ int count() const { return _timers.size(); }
+
+ void update();
+
+ void resetNextRun();
+
+ void setCountdown(uint8 id, int32 countdown);
+ void setDelay(uint8 id, int32 countdown);
+ int32 getDelay(uint8 id) const;
+
+ bool isEnabled(uint8 id) const;
+ void enable(uint8 id);
+ void disable(uint8 id);
+
+ void resync();
+
+ void loadDataFromFile(Common::InSaveFile *file, int version);
+ void saveDataToFile(Common::OutSaveFile *file) const;
+private:
+ KyraEngine *_vm;
+ OSystem *_system;
+ Common::List<TimerEntry> _timers;
+ uint32 _nextRun;
+
+ typedef Common::List<TimerEntry>::iterator Iterator;
+ typedef Common::List<TimerEntry>::const_iterator CIterator;
+};
+
+} // end of namespace Kyra
+
+#endif
diff --git a/engines/kyra/timer_v1.cpp b/engines/kyra/timer_v1.cpp
new file mode 100644
index 0000000000..55dab4413f
--- /dev/null
+++ b/engines/kyra/timer_v1.cpp
@@ -0,0 +1,180 @@
+/* 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 "kyra/kyra.h"
+#include "kyra/kyra_v1.h"
+#include "kyra/screen.h"
+#include "kyra/animator_v1.h"
+#include "kyra/timer.h"
+
+#include "common/system.h"
+
+namespace Kyra {
+
+#define TimerV1(x) new Functor1Mem<int, void, KyraEngine_v1>(this, &KyraEngine_v1::x)
+
+void KyraEngine_v1::setupTimers() {
+ debugC(9, kDebugLevelMain | kDebugLevelTimer, "KyraEngine_v1::setupTimers()");
+
+ for (int i = 0; i <= 4; ++i)
+ _timer->addTimer(i, 0, -1, 1);
+
+ _timer->addTimer(5, 0, 5, 1);
+ _timer->addTimer(6, 0, 7, 1);
+ _timer->addTimer(7, 0, 8, 1);
+ _timer->addTimer(8, 0, 9, 1);
+ _timer->addTimer(9, 0, 7, 1);
+
+ for (int i = 10; i <= 13; ++i)
+ _timer->addTimer(i, 0, 420, 1);
+
+ _timer->addTimer(14, TimerV1(timerCheckAnimFlag2), 600, 1);
+ _timer->addTimer(15, TimerV1(timerUpdateHeadAnims), 11, 1);
+ _timer->addTimer(16, TimerV1(timerSetFlags1), 7200, 1);
+ _timer->addTimer(17, 0 /*sub_15120*/, 7200, 1);
+ _timer->addTimer(18, TimerV1(timerCheckAnimFlag1), 600, 1);
+ _timer->addTimer(19, TimerV1(timerRedrawAmulet), 600, 1);
+
+ _timer->addTimer(20, 0, 7200, 1);
+ _timer->addTimer(21, 0/*sub_1517C*/, 18000, 1);
+ _timer->addTimer(22, 0, 7200, 1);
+
+ for (int i = 23; i <= 27; ++i)
+ _timer->addTimer(i, 0, 10800, 1);
+
+ _timer->addTimer(28, 0, 21600, 1);
+ _timer->addTimer(29, 0, 7200, 1);
+ _timer->addTimer(30, 0, 10800, 1);
+
+ _timer->addTimer(31, TimerV1(timerFadeText), -1, 1);
+ _timer->addTimer(32, TimerV1(updateAnimFlag1), 9, 1);
+ _timer->addTimer(33, TimerV1(updateAnimFlag2), 3, 1);
+}
+
+void KyraEngine_v1::timerUpdateHeadAnims(int timerNum) {
+ debugC(9, kDebugLevelMain | kDebugLevelTimer, "KyraEngine_v1::timerUpdateHeadAnims(%i)", timerNum);
+ static int8 currentFrame = 0;
+ static const int8 frameTable[] = {4, 5, 4, 5, 4, 5, 0, 1, 4, 5,
+ 4, 4, 6, 4, 8, 1, 9, 4, -1};
+
+ if (_talkingCharNum < 0)
+ return;
+
+ _currHeadShape = frameTable[currentFrame];
+ currentFrame++;
+
+ if (frameTable[currentFrame] == -1)
+ currentFrame = 0;
+
+ _animator->animRefreshNPC(0);
+ _animator->animRefreshNPC(_talkingCharNum);
+}
+
+void KyraEngine_v1::timerSetFlags1(int timerNum) {
+ debugC(9, kDebugLevelMain | kDebugLevelTimer, "KyraEngine_v1::timerSetFlags(%i)", timerNum);
+ if (_currentCharacter->sceneId == 0x1C)
+ return;
+
+ int rndNr = _rnd.getRandomNumberRng(0, 3);
+
+ for (int i = 0; i < 4; i++) {
+ if (!queryGameFlag(rndNr + 17)) {
+ setGameFlag(rndNr + 17);
+ break;
+ } else {
+ rndNr++;
+ if (rndNr > 3)
+ rndNr = 0;
+ }
+ }
+}
+
+void KyraEngine_v1::timerFadeText(int timerNum) {
+ debugC(9, kDebugLevelMain | kDebugLevelTimer, "KyraEngine_v1::timerFadeText(%i)", timerNum);
+ _fadeText = true;
+}
+
+void KyraEngine_v1::updateAnimFlag1(int timerNum) {
+ debugC(9, kDebugLevelMain | kDebugLevelTimer, "KyraEngine_v1::updateAnimFlag1(%d)", timerNum);
+ if (_brandonStatusBit & 2) {
+ _brandonStatusBit0x02Flag = 1;
+ }
+}
+
+void KyraEngine_v1::updateAnimFlag2(int timerNum) {
+ debugC(9, kDebugLevelMain | kDebugLevelTimer, "KyraEngine_v1::updateAnimFlag2(%d)", timerNum);
+ if (_brandonStatusBit & 0x20) {
+ _brandonStatusBit0x20Flag = 1;
+ }
+}
+
+void KyraEngine_v1::setTextFadeTimerCountdown(int16 countdown) {
+ debugC(9, kDebugLevelMain | kDebugLevelTimer, "KyraEngine_v1::setTextFadeTimerCountdown(%i)", countdown);
+ if (countdown == -1)
+ countdown = 32000;
+
+ _timer->setCountdown(31, countdown*60);
+}
+
+void KyraEngine_v1::timerSetFlags2(int timerNum) {
+ debugC(9, kDebugLevelMain | kDebugLevelTimer, "KyraEngine_v1::timerSetFlags2(%i)", timerNum);
+ if (!((uint32*)(_flagsTable+0x2D))[timerNum])
+ ((uint32*)(_flagsTable+0x2D))[timerNum] = 1;
+}
+
+void KyraEngine_v1::timerCheckAnimFlag1(int timerNum) {
+ debugC(9, kDebugLevelMain | kDebugLevelTimer, "KyraEngine_v1::timerCheckAnimFlag1(%i)", timerNum);
+ if (_brandonStatusBit & 0x20) {
+ checkAmuletAnimFlags();
+ _timer->setCountdown(18, -1);
+ }
+}
+
+void KyraEngine_v1::timerCheckAnimFlag2(int timerNum) {
+ debugC(9, kDebugLevelMain | kDebugLevelTimer, "KyraEngine_v1::timerCheckAnimFlag2(%i)", timerNum);
+ if (_brandonStatusBit & 0x2) {
+ checkAmuletAnimFlags();
+ _timer->setCountdown(14, -1);
+ }
+}
+
+void KyraEngine_v1::timerRedrawAmulet(int timerNum) {
+ debugC(9, kDebugLevelMain | kDebugLevelTimer, "KyraEngine_v1::timerRedrawAmulet(%i)", timerNum);
+ if (queryGameFlag(0xF1)) {
+ drawAmulet();
+ _timer->setCountdown(19, -1);
+ }
+}
+
+void KyraEngine_v1::setWalkspeed(uint8 newSpeed) {
+ debugC(9, kDebugLevelMain | kDebugLevelTimer, "KyraEngine_v1::setWalkspeed(%i)", newSpeed);
+ static const uint8 speeds[] = {11, 9, 6, 5, 3};
+
+ assert(newSpeed < ARRAYSIZE(speeds));
+ _timer->setDelay(5, speeds[newSpeed]);
+}
+
+} // end of namespace Kyra
+
diff --git a/engines/kyra/timer_v2.cpp b/engines/kyra/timer_v2.cpp
new file mode 100644
index 0000000000..2db90f6ecc
--- /dev/null
+++ b/engines/kyra/timer_v2.cpp
@@ -0,0 +1,80 @@
+/* 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 "kyra/kyra_v2.h"
+#include "kyra/timer.h"
+
+namespace Kyra {
+
+#define TimerV2(x) new Functor1Mem<int, void, KyraEngine_v2>(this, &KyraEngine_v2::x)
+
+void KyraEngine_v2::setupTimers() {
+ debugC(9, kDebugLevelMain | kDebugLevelTimer, "KyraEngine_v2::setupTimers()");
+
+ _timer->addTimer(0, 0, 5, 1);
+ _timer->addTimer(1, TimerV2(timerFunc2), -1, 1);
+ _timer->addTimer(2, TimerV2(timerFunc3), 1, 1);
+ _timer->addTimer(3, TimerV2(timerFunc4), 1, 0);
+ _timer->addTimer(4, TimerV2(timerFunc5), 1, 0);
+ _timer->addTimer(5, TimerV2(timerFunc6), 1, 0);
+}
+
+void KyraEngine_v2::timerFunc2(int arg) {
+ debugC(9, kDebugLevelMain | kDebugLevelTimer, "KyraEngine_v2::timerFunc2(%d)", arg);
+ if (_shownMessage)
+ _msgUnk1 = 1;
+}
+
+void KyraEngine_v2::timerFunc3(int arg) {
+ debugC(9, kDebugLevelMain | kDebugLevelTimer, "KyraEngine_v2::timerFunc3(%d)", arg);
+ // XXX
+}
+
+void KyraEngine_v2::timerFunc4(int arg) {
+ debugC(9, kDebugLevelMain | kDebugLevelTimer, "KyraEngine_v2::timerFunc4(%d)", arg);
+ _timer->disable(3);
+ setGameFlag(0xD8);
+}
+
+void KyraEngine_v2::timerFunc5(int arg) {
+ debugC(9, kDebugLevelMain | kDebugLevelTimer, "KyraEngine_v2::timerFunc5(%d)", arg);
+ // XXX
+}
+
+void KyraEngine_v2::timerFunc6(int arg) {
+ debugC(9, kDebugLevelMain | kDebugLevelTimer, "KyraEngine_v2::timerFunc6(%d)", arg);
+ // XXX
+}
+
+void KyraEngine_v2::setTimer1DelaySecs(int secs) {
+ debugC(9, kDebugLevelMain | kDebugLevelTimer, "KyraEngine_v2::setTimer1DelaySecs(%d)", secs);
+
+ if (secs == -1)
+ secs = 32000;
+
+ _timer->setCountdown(1, secs * 60);
+}
+
+} // end of namespace Kyra
diff --git a/engines/kyra/util.h b/engines/kyra/util.h
new file mode 100644
index 0000000000..98692df015
--- /dev/null
+++ b/engines/kyra/util.h
@@ -0,0 +1,63 @@
+/* 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 KYRA_UTIL_H
+#define KYRA_UTIL_H
+
+#include "common/func.h"
+
+namespace Kyra {
+
+template<class Arg, class Res>
+struct Functor1 : public Common::UnaryFunction<Arg, Res> {
+ virtual ~Functor1() {}
+
+ virtual operator bool() const = 0;
+ virtual Res operator()(Arg) const = 0;
+};
+
+template<class Arg, class Res, class T>
+class Functor1Mem : public Functor1<Arg, Res> {
+public:
+ typedef Res (T::*FuncType)(Arg);
+
+ Functor1Mem(T *t, const FuncType &func) : _t(t), _func(func) {}
+
+ operator bool() const { return _func != 0; }
+ Res operator()(Arg v1) const {
+ return (_t->*_func)(v1);
+ }
+private:
+ mutable T *_t;
+ Res (T::*_func)(Arg);
+};
+
+struct ScriptState;
+
+typedef Functor1<ScriptState*, int> Opcode;
+
+} // end of namespace Kyra
+
+#endif
diff --git a/engines/kyra/wsamovie.cpp b/engines/kyra/wsamovie.cpp
index f0119101fd..7e9ec9b78b 100644
--- a/engines/kyra/wsamovie.cpp
+++ b/engines/kyra/wsamovie.cpp
@@ -28,10 +28,11 @@
#include "common/system.h"
#include "kyra/kyra.h"
+#include "kyra/kyra_v2.h"
#include "kyra/screen.h"
+#include "kyra/screen_v2.h"
#include "kyra/wsamovie.h"
-
namespace Kyra {
WSAMovieV1::WSAMovieV1(KyraEngine *vm) : Movie(vm) {}
WSAMovieV1::~WSAMovieV1() { close(); }
@@ -132,8 +133,8 @@ void WSAMovieV1::close() {
}
}
-void WSAMovieV1::displayFrame(int frameNum) {
- debugC(9, kDebugLevelMovie, "WSAMovieV1::displayFrame(%d)", frameNum);
+void WSAMovieV1::displayFrame(int frameNum, ...) {
+ debugC(9, kDebugLevelMovie, "WSAMovieV1::displayFrame(%d, ...)", frameNum);
if (frameNum >= _numFrames || !_opened)
return;
@@ -234,7 +235,7 @@ void WSAMovieAmiga::close() {
WSAMovieV1::close();
}
-void WSAMovieAmiga::displayFrame(int frameNum) {
+void WSAMovieAmiga::displayFrame(int frameNum, ...) {
debugC(9, kDebugLevelMovie, "WSAMovieAmiga::displayFrame(%d)", frameNum);
if (frameNum >= _numFrames || !_opened)
return;
@@ -340,7 +341,7 @@ void WSAMovieAmiga::processFrame(int frameNum, uint8 *dst) {
#pragma mark -
-WSAMovieV2::WSAMovieV2(KyraEngine *vm) : WSAMovieV1(vm), _xAdd(0), _yAdd(0) {}
+WSAMovieV2::WSAMovieV2(KyraEngine_v2 *vm) : WSAMovieV1(vm), _vm(vm), _xAdd(0), _yAdd(0), _oldOff(false) {}
int WSAMovieV2::open(const char *filename, int unk1, uint8 *palBuf) {
debugC(9, kDebugLevelMovie, "WSAMovieV2::open('%s', %d, %p)", filename, unk1, (const void *)palBuf);
@@ -419,5 +420,95 @@ int WSAMovieV2::open(const char *filename, int unk1, uint8 *palBuf) {
return _numFrames;
}
+void WSAMovieV2::displayFrame(int frameNum, ...) {
+ debugC(9, kDebugLevelMovie, "WSAMovieV2::displayFrame(%d, ...)", frameNum);
+ if (frameNum >= _numFrames || !_opened)
+ return;
+
+ uint8 *dst = 0;
+ if (_flags & WF_OFFSCREEN_DECODE)
+ dst = _offscreenBuffer;
+ else
+ dst = _vm->screen()->getPageRect(_drawPage, _x, _y, _width, _height);
+
+ if (_currentFrame == _numFrames) {
+ if (!(_flags & WF_NO_FIRST_FRAME)) {
+ if (_flags & WF_OFFSCREEN_DECODE)
+ Screen::decodeFrameDelta(dst, _deltaBuffer);
+ else
+ Screen::decodeFrameDeltaPage(dst, _deltaBuffer, _width, (_flags & WF_XOR) == 0);
+ }
+ _currentFrame = 0;
+ }
+
+ // try to reduce the number of needed frame operations
+ int diffCount = ABS(_currentFrame - frameNum);
+ int frameStep = 1;
+ int frameCount;
+ if (_currentFrame < frameNum) {
+ frameCount = _numFrames - frameNum + _currentFrame;
+ if (diffCount > frameCount)
+ frameStep = -1;
+ else
+ frameCount = diffCount;
+ } else {
+ frameCount = _numFrames - _currentFrame + frameNum;
+ if (frameCount >= diffCount) {
+ frameStep = -1;
+ frameCount = diffCount;
+ }
+ }
+
+ // process
+ if (frameStep > 0) {
+ uint16 cf = _currentFrame;
+ while (frameCount--) {
+ cf += frameStep;
+ processFrame(cf, dst);
+ if (cf == _numFrames)
+ cf = 0;
+ }
+ } else {
+ uint16 cf = _currentFrame;
+ while (frameCount--) {
+ if (cf == 0)
+ cf = _numFrames;
+ processFrame(cf, dst);
+ cf += frameStep;
+ }
+ }
+
+ // display
+ _currentFrame = frameNum;
+ if (_flags & WF_OFFSCREEN_DECODE) {
+ if (_oldOff) {
+ // Kyrandia 1 offscreen buffer -> screen copy method of Kyrandia 1, needs to be present
+ // for our intro code that doesn't supply all the needed parameters for the Kyrandia 2 method
+ _vm->screen()->copyBlockToPage(_drawPage, _x, _y, _width, _height, _offscreenBuffer);
+ } else {
+ // This is the offscreen buffer -> screen copy method of Kyrandia 2 as it's implemented
+ // in the original, we use this in game
+ Screen_v2 *screen = _vm->screen_v2();
+ int pageBackUp = screen->_curPage;
+ screen->_curPage = _drawPage;
+
+ va_list args;
+ va_start(args, frameNum);
+
+ int copyParam = va_arg(args, int);
+ int plotFunc = (copyParam & 0xFF00) >> 12;
+ int unk1 = copyParam & 0xFF;
+
+ const uint8 *unkPtr1 = va_arg(args, const uint8*);
+ const uint8 *unkPtr2 = va_arg(args, const uint8*);
+ va_end(args);
+
+ screen->copyWsaRect(_x, _y, _width, _height, 0, plotFunc, _offscreenBuffer, unk1, unkPtr1, unkPtr2);
+
+ screen->_curPage = pageBackUp;
+ }
+ }
+}
+
} // end of namespace Kyra
diff --git a/engines/kyra/wsamovie.h b/engines/kyra/wsamovie.h
index a3af9f16b7..0e93bd2a93 100644
--- a/engines/kyra/wsamovie.h
+++ b/engines/kyra/wsamovie.h
@@ -35,6 +35,7 @@ class SoundHandle;
namespace Kyra {
class KyraEngine;
+class KyraEngine_v2;
class Movie {
public:
@@ -48,7 +49,7 @@ public:
virtual int frames() = 0;
- virtual void displayFrame(int frameNum) = 0;
+ virtual void displayFrame(int frameNum, ...) = 0;
virtual void setX(int x) { _x = x; }
virtual void setY(int y) { _y = y; }
@@ -71,7 +72,7 @@ public:
virtual int frames() { return _opened ? _numFrames : -1; }
- virtual void displayFrame(int frameNum);
+ virtual void displayFrame(int frameNum, ...);
enum WSAFlags {
WF_OFFSCREEN_DECODE = 0x10,
@@ -101,7 +102,7 @@ public:
int open(const char *filename, int offscreen, uint8 *palette);
void close();
- void displayFrame(int frameNum);
+ void displayFrame(int frameNum, ...);
private:
void processFrame(int frameNum, uint8 *dst);
@@ -110,9 +111,11 @@ private:
class WSAMovieV2 : public WSAMovieV1 {
public:
- WSAMovieV2(KyraEngine *vm);
+ WSAMovieV2(KyraEngine_v2 *vm);
int open(const char *filename, int unk1, uint8 *palette);
+
+ virtual void displayFrame(int frameNum, ...);
void setX(int x) { _x = x + _xAdd; }
void setY(int y) { _y = y + _yAdd; }
@@ -122,10 +125,15 @@ public:
int width() const { return _width; }
int height() const { return _height; }
-protected:
+ // HACK for our intro code
+ void flagOldOff(bool enabled) { _oldOff = enabled; }
+protected:
+ KyraEngine_v2 *_vm;
+
int16 _xAdd;
int16 _yAdd;
+ bool _oldOff; // old offscreen copy, HACK for our intro code
};
} // end of namespace Kyra
diff --git a/engines/lure/game.cpp b/engines/lure/game.cpp
index 3ac25f83b8..5bffc6ade8 100644
--- a/engines/lure/game.cpp
+++ b/engines/lure/game.cpp
@@ -52,7 +52,7 @@ Game::~Game() {
delete _debugger;
}
-void Game::tick() {
+void Game::tick(bool fastSpeed) {
// 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
@@ -65,7 +65,11 @@ void Game::tick() {
int idSize = 0;
for (i = res.activeHotspots().begin(); i != res.activeHotspots().end(); ++i) {
Hotspot *hotspot = *i;
- idList[idSize++] = hotspot->hotspotId();
+
+ if (!fastSpeed || ((hotspot->layer() != 0xff) &&
+ (hotspot->hotspotId() < FIRST_NONCHARACTER_ID)))
+ // Add hotspot to list to execute
+ idList[idSize++] = hotspot->hotspotId();
}
debugC(ERROR_DETAILED, kLureDebugAnimations, "Hotspot ticks begin");
@@ -289,6 +293,7 @@ void Game::playerChangeRoom() {
uint16 roomNum = fields.playerNewPos().roomNumber;
fields.playerNewPos().roomNumber = 0;
Point &newPos = fields.playerNewPos().position;
+
delayList.clear();
RoomData *roomData = res.getRoom(roomNum);
@@ -302,7 +307,9 @@ void Game::playerChangeRoom() {
displayChuteAnimation();
else if (animFlag != 0)
displayBarrelAnimation();
+
fields.setField(ROOM_EXIT_ANIMATION, 0);
+ roomData->exitTime = g_system->getMillis();
// Change to the new room
Hotspot *player = res.getActiveHotspot(PLAYER_ID);
diff --git a/engines/lure/game.h b/engines/lure/game.h
index b1d1f8d21a..20e56df776 100644
--- a/engines/lure/game.h
+++ b/engines/lure/game.h
@@ -66,7 +66,7 @@ public:
static Game &getReference();
- void tick();
+ void tick(bool fastSpeed = false);
void nextFrame();
void execute();
void setState(uint8 flags) { _state = flags; }
diff --git a/engines/lure/hotspots.cpp b/engines/lure/hotspots.cpp
index 82b4725a70..7def0be9ab 100644
--- a/engines/lure/hotspots.cpp
+++ b/engines/lure/hotspots.cpp
@@ -689,7 +689,6 @@ void Hotspot::converse(uint16 destCharacterId, uint16 messageId, bool standStill
if (standStill) {
setDelayCtr(_data->talkCountdown);
_data->characterMode = CHARMODE_CONVERSING;
- //TODO: HS[3Eh]=character_hotspot_id, HS[40h]=active_hotspot_id
}
}
@@ -1332,7 +1331,10 @@ void Hotspot::doUse(HotspotData *hotspot) {
faceHotspot(hotspot);
endAction();
- // TODO: If character=3E9h, HS[-1]=28h, HS[1Fh]=50h
+ if (hotspotId() == RATPOUCH_ID) {
+ _tempDest.position.x = 40;
+ setFrameCtr(80);
+ }
uint16 sequenceOffset = res.getHotspotAction(hotspot->actionsOffset, USE);
@@ -1727,7 +1729,6 @@ void Hotspot::doBribe(HotspotData *hotspot) {
++tempId; // Move over entry's sequence offset
}
- // TODO: call to talk_setup
faceHotspot(hotspot);
setActionCtr(0);
endAction();
@@ -1738,8 +1739,8 @@ void Hotspot::doBribe(HotspotData *hotspot) {
if (sequenceOffset != 0) return;
}
- // TODO: talk_record_index
- showMessage(sequenceOffset);
+ uint16 talkIndex = res.fieldList().getField(TALK_INDEX);
+ showMessage((talkIndex == 6) ? 0x30 : 0x29);
}
void Hotspot::doExamine(HotspotData *hotspot) {
@@ -1811,7 +1812,7 @@ void Hotspot::npcHeySir(HotspotData *hotspot) {
return;
}
- // TODO: Check storage of hotspot Id in data_1090/data_1091=0
+ // TODO: Check storage of hotspot Id in talk_first=player/talk_second=0
// Get the npc to say "Hey Sir" to player
showMessage(0x22, PLAYER_ID);
@@ -2059,6 +2060,9 @@ void Hotspot::saveToStream(Common::WriteStream *stream) {
stream->writeSint16LE(_destX);
stream->writeSint16LE(_destY);
stream->writeUint16LE(_destHotspotId);
+ stream->writeByte(_tempDest.counter);
+ stream->writeSint16LE(_tempDest.position.x);
+ stream->writeSint16LE(_tempDest.position.y);
stream->writeUint16LE(_frameWidth);
stream->writeUint16LE(_height);
stream->writeUint16LE(_width);
@@ -2096,6 +2100,9 @@ void Hotspot::loadFromStream(Common::ReadStream *stream) {
_destX = stream->readSint16LE();
_destY = stream->readSint16LE();
_destHotspotId = stream->readUint16LE();
+ _tempDest.counter = stream->readByte();
+ _tempDest.position.x = stream->readSint16LE();
+ _tempDest.position.y = stream->readSint16LE();
_frameWidth = stream->readUint16LE();
_height = stream->readUint16LE();
_width = stream->readUint16LE();
@@ -2227,6 +2234,7 @@ void HotspotTickHandlers::standardCharacterAnimHandler(Hotspot &h) {
RoomPathsData &paths = Resources::getReference().getRoom(h.roomNumber())->paths;
PathFinder &pathFinder = h.pathFinder();
CurrentActionStack &actions = h.currentActions();
+ Hotspot *player = res.getActiveHotspot(PLAYER_ID);
uint16 impingingList[MAX_NUM_IMPINGING];
int numImpinging;
bool bumpedPlayer;
@@ -2276,8 +2284,6 @@ void HotspotTickHandlers::standardCharacterAnimHandler(Hotspot &h) {
if (numImpinging > 0) {
// Scan to check if the character has bumped into player
- Hotspot *player = res.getActiveHotspot(PLAYER_ID);
-
if (bumpedPlayer && (player->characterMode() == CHARMODE_IDLE)) {
// Signal the player to move out of the way automatically
player->setBlockedState(BS_INITIAL);
@@ -2300,8 +2306,12 @@ void HotspotTickHandlers::standardCharacterAnimHandler(Hotspot &h) {
h.setSkipFlag(false);
}
- // TODO: Handling of any set Tick Script Offset, as well as certain other
- // as of yet unknown hotspot flags
+ if (h.resource()->scriptHotspotId != 0) {
+ // Character bumped against another
+ fields.setField(USE_HOTSPOT_ID, h.resource()->scriptHotspotId);
+ Script::execute(h.resource()->tickScriptOffset);
+ h.resource()->scriptHotspotId = 0;
+ }
debugC(ERROR_DETAILED, kLureDebugAnimations, "Hotspot standard character point 4");
if (h.pauseCtr() != 0) {
@@ -2332,13 +2342,14 @@ void HotspotTickHandlers::standardCharacterAnimHandler(Hotspot &h) {
// All other character modes
if (h.delayCtr() > 0) {
// There is some countdown left to do
- bool decrementFlag = true;
+ h.updateMovement();
- if (!decrementFlag) {
- HotspotData *hotspot = res.getHotspot(0); // TODO: HS[50h]
- decrementFlag = (hotspot->roomNumber != h.roomNumber()) ? false :
+ bool decrementFlag = (h.resource()->actionHotspotId != 0);
+ if (decrementFlag) {
+ HotspotData *hotspot = res.getHotspot(h.resource()->actionHotspotId);
+ decrementFlag = (hotspot->roomNumber != h.hotspotId()) ? false :
Support::charactersIntersecting(hotspot, h.resource());
- }
+ }
if (decrementFlag) {
h.setDelayCtr(h.delayCtr() - 1);
@@ -2353,12 +2364,20 @@ void HotspotTickHandlers::standardCharacterAnimHandler(Hotspot &h) {
h.pathFinder().clear();
if ((currentMode == CHARMODE_WAIT_FOR_PLAYER) || (currentMode == CHARMODE_WAIT_FOR_INTERACT)) {
- // TODO: HS[33h]=0
+ h.resource()->talkOverride = 0;
h.showMessage(1);
}
return;
}
+ /* interactHotspotId never seems to be set
+ if ((h.resource()->interactHotspotId != 0) && !player->currentActions().isEmpty()) {
+ h.setActionCtr(99);
+ if (!actions.isEmpty())
+ actions.top().setAction(DISPATCH_ACTION);
+ }
+ */
+
debugC(ERROR_DETAILED, kLureDebugAnimations, "Hotspot standard character point 6");
CurrentAction action = actions.action();
PathFinderResult pfResult;
@@ -2567,7 +2586,9 @@ void HotspotTickHandlers::puzzledAnimHandler(Hotspot &h) {
}
void HotspotTickHandlers::roomExitAnimHandler(Hotspot &h) {
- RoomExitJoinData *rec = Resources::getReference().getExitJoin(h.hotspotId());
+ Resources &res = Resources::getReference();
+// ValueTableData &fields = res.fieldList();
+ RoomExitJoinData *rec = res.getExitJoin(h.hotspotId());
if (!rec) return;
byte *currentFrame, *destFrame;
@@ -2607,7 +2628,6 @@ void HotspotTickHandlers::playerAnimHandler(Hotspot &h) {
RoomPathsData &paths = Resources::getReference().getRoom(h.roomNumber())->paths;
PathFinder &pathFinder = h.pathFinder();
CurrentActionStack &actions = h.currentActions();
- ValueTableData &fields = res.fieldList();
uint16 impingingList[MAX_NUM_IMPINGING];
int numImpinging;
Action hsAction;
@@ -2637,7 +2657,17 @@ void HotspotTickHandlers::playerAnimHandler(Hotspot &h) {
return;
h.setSkipFlag(false);
}
- // TODO: HS[58h] check
+
+ /* interactHotspotId never seems to be set
+ if (h.resource()->interactHotspotId != 0) {
+ h.resource()->interactHotspotId = 0;
+ Hotspot *hotspot = res.getActiveHotspot(h.resource()->interactHotspotId);
+ assert(hotspot);
+ if ((hotspot->characterMode() != CHARMODE_WAIT_FOR_INTERACT) &&
+ !actions.isEmpty())
+ actions.top().setAction(ACTION_NONE);
+ }
+ */
if (h.pauseCtr() > 0) {
debugC(ERROR_DETAILED, kLureDebugAnimations, "Pause countdown = %d", h.pauseCtr());
@@ -2668,10 +2698,10 @@ void HotspotTickHandlers::playerAnimHandler(Hotspot &h) {
debugC(ERROR_DETAILED, kLureDebugAnimations, "Character mode = %d", h.characterMode());
h.setOccupied(false);
h.setCharacterMode(CHARMODE_NONE);
- if (fields.playerPendingPos().isSet) {
+ if (h.tempDest().counter != 0) {
// Start walking to the previously set destination
- fields.playerPendingPos().isSet = false;
- h.setDestPosition(fields.playerPendingPos().pos.x, fields.playerPendingPos().pos.y);
+ h.tempDest().counter = 0;
+ h.setDestPosition(h.tempDest().position.x, h.tempDest().position.y);
h.currentActions().addFront(START_WALKING, h.roomNumber());
h.setWalkFlag(false);
}
@@ -2753,9 +2783,9 @@ void HotspotTickHandlers::playerAnimHandler(Hotspot &h) {
return;
} else if (h.blockedState() != BS_NONE) {
- fields.playerPendingPos().pos.x = h.destX();
- fields.playerPendingPos().pos.y = h.destY();
- fields.playerPendingPos().isSet = true;
+ h.tempDest().position.x = h.destX();
+ h.tempDest().position.y = h.destY();
+ h.tempDest().counter = 1;
h.setBlockedState((BlockedState) ((int) h.blockedState() + 1));
h.setRandomDest();
return;
@@ -2795,7 +2825,7 @@ void HotspotTickHandlers::playerAnimHandler(Hotspot &h) {
// Walking done
if (room.cursorState() == CS_BUMPED)
room.setCursorState(CS_NONE);
- if (fields.playerPendingPos().isSet) {
+ if (h.tempDest().counter != 0) {
h.setCharacterMode(CHARMODE_PLAYER_WAIT);
h.setDelayCtr(IDLE_COUNTDOWN_SIZE);
return;
@@ -4474,9 +4504,9 @@ void Support::characterChangeRoom(Hotspot &h, uint16 roomNumber,
// TODO: Double-check.. is it impinging in leaving room (right now) or entering room
if (checkForIntersectingCharacter(h)) {
- fields.playerPendingPos().pos.x = h.destX();
- fields.playerPendingPos().pos.y = h.destY();
- fields.playerPendingPos().isSet = true;
+ h.tempDest().position.x = h.destX();
+ h.tempDest().position.y = h.destY();
+ h.tempDest().counter = 1;
Room::getReference().setCursorState(CS_BUMPED);
h.setActionCtr(0);
h.setBlockedState((BlockedState) ((int) h.blockedState() + 1));
diff --git a/engines/lure/hotspots.h b/engines/lure/hotspots.h
index 3f8bc544f6..fb3bb1478b 100644
--- a/engines/lure/hotspots.h
+++ b/engines/lure/hotspots.h
@@ -243,6 +243,11 @@ enum HotspotPrecheckResult {PC_EXECUTE, PC_NOT_IN_ROOM, PC_FAILED, PC_WAIT, PC_E
enum BarPlaceResult {BP_KEEP_TRYING, BP_GOT_THERE, BP_FAIL};
+struct DestStructure {
+ uint8 counter;
+ Point position;
+};
+
#define MAX_NUM_FRAMES 16
class Hotspot {
@@ -277,6 +282,7 @@ private:
bool _frameStartsUsed;
uint16 _frameStarts[MAX_NUM_FRAMES];
char _nameBuffer[MAX_HOTSPOT_NAME_SIZE];
+ DestStructure _tempDest;
// Runtime fields
uint16 _frameCtr;
@@ -516,6 +522,7 @@ public:
void doAction(Action action, HotspotData *hotspot);
CurrentActionStack &currentActions() { return _currentActions; }
PathFinder &pathFinder() { return _pathFinder; }
+ DestStructure &tempDest() { return _tempDest; }
uint16 frameCtr() { return _frameCtr; }
void setFrameCtr(uint16 value) { _frameCtr = value; }
void decrFrameCtr() { if (_frameCtr > 0) --_frameCtr; }
diff --git a/engines/lure/luredefs.h b/engines/lure/luredefs.h
index a715c4a1e7..d5991a5807 100644
--- a/engines/lure/luredefs.h
+++ b/engines/lure/luredefs.h
@@ -113,6 +113,8 @@ enum Action {
#define SUB_PALETTE_SIZE 64
// Palette resources have 220 palette entries
#define RES_PALETTE_ENTRIES 220
+// Main working palette size
+#define MAIN_PALETTE_SIZE 228
// Palette colour increment amouns for palette fade in/outs
#define PALETTE_FADE_INC_SIZE 4
diff --git a/engines/lure/res_struct.cpp b/engines/lure/res_struct.cpp
index 79bf0dfe6e..12cf61a58a 100644
--- a/engines/lure/res_struct.cpp
+++ b/engines/lure/res_struct.cpp
@@ -466,7 +466,7 @@ void HotspotData::saveToStream(WriteStream *stream) {
stream->writeUint16LE(talkCountdown);
stream->writeUint16LE(pauseCtr);
stream->writeUint16LE(useHotspotId);
- stream->writeUint16LE(use2HotspotId);
+ stream->writeUint16LE(scriptHotspotId);
stream->writeUint16LE(talkGate);
stream->writeUint16LE(actionHotspotId);
stream->writeUint16LE(talkOverride);
@@ -507,7 +507,7 @@ void HotspotData::loadFromStream(ReadStream *stream) {
talkCountdown = stream->readUint16LE();
pauseCtr = stream->readUint16LE();
useHotspotId = stream->readUint16LE();
- use2HotspotId = stream->readUint16LE();
+ scriptHotspotId = stream->readUint16LE();
talkGate = stream->readUint16LE();
actionHotspotId = stream->readUint16LE();
talkOverride = stream->readUint16LE();
@@ -1119,7 +1119,7 @@ int PausedCharacterList::check(uint16 charId, int numImpinging, uint16 *impingin
if ((charHotspot->characterMode() == CHARMODE_PAUSED) ||
((charHotspot->pauseCtr() == 0) &&
(charHotspot->characterMode() == CHARMODE_NONE))) {
- hotspot->resource()->use2HotspotId = charId;
+ hotspot->resource()->scriptHotspotId = charId;
}
hotspot->setPauseCtr(IDLE_COUNTDOWN_SIZE);
@@ -1206,9 +1206,6 @@ ValueTableData::ValueTableData() {
_playerNewPos.roomNumber = 0;
_playerNewPos.position.x = 0;
_playerNewPos.position.y = 0;
- _playerPendingPos.pos.x = 0;
- _playerPendingPos.pos.y = 0;
- _playerPendingPos.isSet = false;
_flags = GAMEFLAG_4 | GAMEFLAG_1;
_hdrFlagMask = 1;
@@ -1252,9 +1249,6 @@ void ValueTableData::saveToStream(Common::WriteStream *stream)
stream->writeSint16LE(_playerNewPos.position.x);
stream->writeSint16LE(_playerNewPos.position.y);
stream->writeUint16LE(_playerNewPos.roomNumber);
- stream->writeByte(_playerPendingPos.isSet);
- stream->writeSint16LE(_playerPendingPos.pos.x);
- stream->writeSint16LE(_playerPendingPos.pos.y);
stream->writeByte(_flags);
stream->writeByte(_hdrFlagMask);
@@ -1270,9 +1264,6 @@ void ValueTableData::loadFromStream(Common::ReadStream *stream)
_playerNewPos.position.x = stream->readSint16LE();
_playerNewPos.position.y = stream->readSint16LE();
_playerNewPos.roomNumber = stream->readUint16LE();
- _playerPendingPos.isSet = stream->readByte() != 0;
- _playerPendingPos.pos.x = stream->readSint16LE();
- _playerPendingPos.pos.y = stream->readSint16LE();
_flags = stream->readByte();
_hdrFlagMask = stream->readByte();
diff --git a/engines/lure/res_struct.h b/engines/lure/res_struct.h
index b5e4aef724..4d2c55e6b1 100644
--- a/engines/lure/res_struct.h
+++ b/engines/lure/res_struct.h
@@ -458,8 +458,7 @@ public:
uint16 talkGate;
uint16 actionHotspotId;
uint16 talkOverride;
-
- uint16 use2HotspotId;
+ uint16 scriptHotspotId;
void enable() { flags |= 0x80; }
void disable() { flags &= 0x7F; }
@@ -817,16 +816,10 @@ struct PlayerNewPosition {
uint16 roomNumber;
};
-struct PlayerPendingPosition {
- Point pos;
- bool isSet;
-};
-
class ValueTableData {
private:
uint16 _numGroats;
PlayerNewPosition _playerNewPos;
- PlayerPendingPosition _playerPendingPos;
uint8 _flags;
uint8 _hdrFlagMask;
@@ -845,7 +838,6 @@ public:
uint8 &flags() { return _flags; }
uint8 &hdrFlagMask() { return _hdrFlagMask; }
PlayerNewPosition &playerNewPos() { return _playerNewPos; }
- PlayerPendingPosition &playerPendingPos() { return _playerPendingPos; }
void saveToStream(Common::WriteStream *stream);
void loadFromStream(Common::ReadStream *stream);
diff --git a/engines/lure/room.cpp b/engines/lure/room.cpp
index 016432dfac..b48b50197b 100644
--- a/engines/lure/room.cpp
+++ b/engines/lure/room.cpp
@@ -24,6 +24,7 @@
#include "lure/luredefs.h"
#include "lure/res.h"
#include "lure/screen.h"
+#include "lure/game.h"
#include "lure/events.h"
#include "lure/strings.h"
#include "lure/scripts.h"
@@ -492,18 +493,26 @@ void Room::update() {
void Room::setRoomNumber(uint16 newRoomNumber, bool showOverlay) {
Resources &r = Resources::getReference();
+ Game &game = Game::getReference();
+ Mouse &mouse = Mouse::getReference();
+
+ mouse.pushCursorNum(CURSOR_DISK);
+
_roomData = r.getRoom(newRoomNumber);
if (!_roomData)
error("Tried to change to non-existant room: %d", newRoomNumber);
- bool leaveFlag = (_layers[0] && (newRoomNumber != _roomNumber));
+ bool leaveFlag = (_layers[0] && (newRoomNumber != _roomNumber) && (_roomNumber != 0));
_roomNumber = _roomData->roomNumber;
_descId = _roomData->descId;
+ if (leaveFlag) {
+ _screen.paletteFadeOut();
+ leaveRoom();
+ }
+
_screen.empty();
- _screen.resetPalette();
- if (leaveFlag) leaveRoom();
_numLayers = _roomData->numLayers;
if (showOverlay) ++_numLayers;
@@ -512,13 +521,9 @@ void Room::setRoomNumber(uint16 newRoomNumber, bool showOverlay) {
_layers[layerNum] = new RoomLayer(_roomData->layers[layerNum],
layerNum == 0);
- // Load in the palette, add in the two replacements segments, and then
- // set to the system palette
- Palette p(228, NULL, RGB64);
- Palette tempPalette(paletteId);
- p.copyFrom(&tempPalette);
- r.insertPaletteSubset(p);
- _screen.setPalette(&p);
+ // Load in the game palette and set the non-room specific colours at the top end of the palette
+ Palette mainPalette(GAME_PALETTE_RESOURCE_ID);
+ _screen.setPalette(&mainPalette, MAIN_PALETTE_SIZE, GAME_COLOURS - MAIN_PALETTE_SIZE);
// Set the new room number
r.fieldList().setField(ROOM_NUMBER, newRoomNumber);
@@ -527,8 +532,28 @@ void Room::setRoomNumber(uint16 newRoomNumber, bool showOverlay) {
Script::execute(_roomData->sequenceOffset);
loadRoomHotspots();
- checkCursor();
+
+ if (_roomData->exitTime != 0xffff)
+ {
+ // If time has passed, animation ticks needed before room is displayed
+ int numSeconds = (g_system->getMillis() - _roomData->exitTime) / 1000;
+ if (numSeconds > 300) numSeconds = 300;
+
+ while (numSeconds-- > 0)
+ game.tick(true);
+ }
+
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();
}
// checkCursor
diff --git a/engines/lure/screen.cpp b/engines/lure/screen.cpp
index 8477c0def4..0cd2dd9357 100644
--- a/engines/lure/screen.cpp
+++ b/engines/lure/screen.cpp
@@ -28,6 +28,7 @@
#include "lure/memory.h"
#include "lure/disk.h"
#include "lure/decode.h"
+#include "lure/events.h"
namespace Lure {
@@ -71,26 +72,40 @@ void Screen::setPalette(Palette *p) {
_system.updateScreen();
}
+// setPalette
+// 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);
+ _system.updateScreen();
+}
+
// paletteFadeIn
// Fades in the palette. For proper operation, the palette should have been
// previously set to empty
void Screen::paletteFadeIn(Palette *p) {
+ assert(p->numEntries() <= _palette->numEntries());
+ Events &events = Events::getReference();
bool changed;
- byte *const pDest = p->data();
- byte *const pTemp = _palette->data();
do {
changed = false;
+ byte *pFinal = p->data();
+ byte *pCurrent = _palette->data();
- for (int palCtr = 0; palCtr < p->numEntries() * 4; ++palCtr)
+ 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 = pTemp[palCtr] < pDest[palCtr];
+ bool isDifferent = *pCurrent < *pFinal;
+
if (isDifferent) {
- if (pDest[palCtr] - pTemp[palCtr] < PALETTE_FADE_INC_SIZE)
- pTemp[palCtr] = pDest[palCtr];
- else pTemp[palCtr] += PALETTE_FADE_INC_SIZE;
+ if ((*pFinal - *pCurrent) < PALETTE_FADE_INC_SIZE)
+ *pCurrent = *pFinal;
+ else
+ *pCurrent += PALETTE_FADE_INC_SIZE;
changed = true;
}
}
@@ -99,6 +114,7 @@ void Screen::paletteFadeIn(Palette *p) {
_system.setPalette(_palette->data(), 0, GAME_COLOURS);
_system.updateScreen();
_system.delayMillis(20);
+ events.pollEvent();
}
} while (changed);
}
@@ -106,14 +122,16 @@ void Screen::paletteFadeIn(Palette *p) {
// paletteFadeOut
// Fades the screen to black by gradually decreasing the palette colours
-void Screen::paletteFadeOut() {
+void Screen::paletteFadeOut(int numEntries) {
+ assert((uint32)numEntries <= _palette->palette()->size());
+ Events &events = Events::getReference();
bool changed;
do {
byte *pTemp = _palette->data();
changed = false;
- for (uint32 palCtr = 0; palCtr < _palette->palette()->size(); ++palCtr, ++pTemp) {
+ for (uint32 palCtr = 0; palCtr < (uint32)(numEntries * PALETTE_FADE_INC_SIZE); ++palCtr, ++pTemp) {
if (palCtr % PALETTE_FADE_INC_SIZE == (PALETTE_FADE_INC_SIZE - 1))
continue;
bool isDifferent = *pTemp > 0;
@@ -128,6 +146,7 @@ void Screen::paletteFadeOut() {
_system.setPalette(_palette->data(), 0, GAME_COLOURS);
_system.updateScreen();
_system.delayMillis(20);
+ events.pollEvent();
}
} while (changed);
}
diff --git a/engines/lure/screen.h b/engines/lure/screen.h
index 9197f64a8d..7182c4236b 100644
--- a/engines/lure/screen.h
+++ b/engines/lure/screen.h
@@ -49,9 +49,10 @@ public:
void setPaletteEmpty();
void setPalette(Palette *p);
+ void setPalette(Palette *p, uint16 start, uint16 num);
Palette &getPalette() { return *_palette; }
void paletteFadeIn(Palette *p);
- void paletteFadeOut();
+ void paletteFadeOut(int numEntries = MAIN_PALETTE_SIZE);
void resetPalette();
void empty();
void update();
diff --git a/engines/parallaction/animation.cpp b/engines/parallaction/animation.cpp
index d4f538c451..118f35e705 100644
--- a/engines/parallaction/animation.cpp
+++ b/engines/parallaction/animation.cpp
@@ -468,7 +468,7 @@ void jobRunScripts(void *parm, Job *j) {
while (((*inst)->_index != INST_SHOW) && (a->_flags & kFlagsActing)) {
- debugC(9, kDebugJobs, "Animation: %s, instruction: %s", a->_label._text, (*inst)->_index == INST_END ? "end" : _instructionNamesRes[(*inst)->_index - 1]);
+ 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
@@ -566,7 +566,7 @@ void jobRunScripts(void *parm, Job *j) {
case INST_CALL: // call
- _callables[(*inst)->_opBase._index](0);
+ _vm->callFunction((*inst)->_opBase._index, 0);
break;
case INST_WAIT: // wait
diff --git a/engines/parallaction/archive.cpp b/engines/parallaction/archive.cpp
deleted file mode 100644
index 9eef3f44e9..0000000000
--- a/engines/parallaction/archive.cpp
+++ /dev/null
@@ -1,208 +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/endian.h"
-#include "common/file.h"
-
-#include "parallaction/disk.h"
-#include "parallaction/parallaction.h"
-
-
-namespace Parallaction {
-
-// HACK: Several archives ('de', 'en', 'fr' and 'disk0') in the multi-lingual
-// Amiga version of Nippon Safes, and one archive ('fr') in the Amiga Demo of
-// Nippon Safes used different internal offsets than all the other archives.
-//
-// When an archive is opened in the Amiga demo, its size is checked against
-// SIZEOF_SMALL_ARCHIVE to detect when the smaller archive is used.
-//
-// When an archive is opened in Amiga multi-lingual version, the header is
-// checked again NDOS to detect when a smaller archive is used.
-//
-#define SIZEOF_SMALL_ARCHIVE 12778
-
-#define ARCHIVE_FILENAMES_OFS 0x16
-
-#define NORMAL_ARCHIVE_FILES_NUM 384
-#define SMALL_ARCHIVE_FILES_NUM 180
-
-#define NORMAL_ARCHIVE_SIZES_OFS 0x3016
-#define SMALL_ARCHIVE_SIZES_OFS 0x1696
-
-#define NORMAL_ARCHIVE_DATA_OFS 0x4000
-#define SMALL_ARCHIVE_DATA_OFS 0x1966
-
-Archive::Archive() {
- resetArchivedFile();
-}
-
-void Archive::open(const char *file) {
- debugC(1, kDebugDisk, "Archive::open(%s)", file);
-
- if (_archive.isOpen())
- close();
-
- char path[PATH_LEN];
-
- strcpy(path, file);
- if (!_archive.open(path))
- error("archive '%s' not found", path);
-
- _archiveName = file;
-
- bool isSmallArchive = false;
- if (_vm->getPlatform() == Common::kPlatformAmiga) {
- if (_vm->getFeatures() & GF_DEMO) {
- isSmallArchive = _archive.size() == SIZEOF_SMALL_ARCHIVE;
- } else if (_vm->getFeatures() & GF_LANG_MULT) {
- isSmallArchive = (_archive.readUint32BE() != MKID_BE('NDOS'));
- }
- }
-
- _numFiles = (isSmallArchive) ? SMALL_ARCHIVE_FILES_NUM : NORMAL_ARCHIVE_FILES_NUM;
-
- _archive.seek(ARCHIVE_FILENAMES_OFS);
- _archive.read(_archiveDir, _numFiles*32);
-
- _archive.seek((isSmallArchive) ? SMALL_ARCHIVE_SIZES_OFS : NORMAL_ARCHIVE_SIZES_OFS);
-
- uint32 dataOffset = (isSmallArchive) ? SMALL_ARCHIVE_DATA_OFS : NORMAL_ARCHIVE_DATA_OFS;
- for (uint16 i = 0; i < _numFiles; i++) {
- _archiveOffsets[i] = dataOffset;
- _archiveLenghts[i] = _archive.readUint32BE();
- dataOffset += _archiveLenghts[i];
- }
-
- return;
-}
-
-
-void Archive::close() {
- if (!_archive.isOpen()) return;
-
- resetArchivedFile();
-
- _archive.close();
- _archiveName.clear();
-}
-
-Common::String Archive::name() const {
- return _archiveName;
-}
-
-bool Archive::openArchivedFile(const char *filename) {
- debugC(3, kDebugDisk, "Archive::openArchivedFile(%s)", filename);
-
- resetArchivedFile();
-
- debugC(3, kDebugDisk, "Archive::openArchivedFile(%s)", filename);
-
- if (!_archive.isOpen())
- error("Archive::openArchivedFile: the archive is not open");
-
- uint16 i = 0;
- for ( ; i < _numFiles; i++) {
- if (!scumm_stricmp(_archiveDir[i], filename)) break;
- }
- if (i == _numFiles) return false;
-
- debugC(9, kDebugDisk, "Archive::openArchivedFile: '%s' found in slot %i", filename, i);
-
- _file = true;
-
- _fileOffset = _archiveOffsets[i];
- _fileCursor = _archiveOffsets[i];
- _fileEndOffset = _archiveOffsets[i] + _archiveLenghts[i];
-
- _archive.seek(_fileOffset);
-
- return true;
-}
-
-void Archive::resetArchivedFile() {
- _file = false;
- _fileCursor = 0;
- _fileOffset = 0;
- _fileEndOffset = 0;
-}
-
-void Archive::closeArchivedFile() {
- resetArchivedFile();
-}
-
-
-uint32 Archive::size() const {
- return (_file == true ? _fileEndOffset - _fileOffset : 0);
-}
-
-uint32 Archive::pos() const {
- return (_file == true ? _fileCursor - _fileOffset : 0 );
-}
-
-bool Archive::eos() const {
- return (_file == true ? _fileCursor == _fileEndOffset : true );
-}
-
-void Archive::seek(int32 offs, int whence) {
- assert(_file == true && _fileCursor <= _fileEndOffset);
-
- switch (whence) {
- case SEEK_CUR:
- _fileCursor += offs;
- break;
- case SEEK_SET:
- _fileCursor = _fileOffset + offs;
- break;
- case SEEK_END:
- _fileCursor = _fileEndOffset - offs;
- break;
- }
- assert(_fileCursor <= _fileEndOffset && _fileCursor >= _fileOffset);
-
- _archive.seek(_fileCursor, SEEK_SET);
-}
-
-uint32 Archive::read(void *dataPtr, uint32 dataSize) {
-// printf("read(%i, %i)\n", file->_cursor, file->_endOffset);
- if (_file == false)
- error("Archive::read: no archived file is currently open");
-
- if (_fileCursor >= _fileEndOffset)
- error("can't read beyond end of archived file");
-
- if (_fileEndOffset - _fileCursor < dataSize)
- dataSize = _fileEndOffset - _fileCursor;
-
- int32 readBytes = _archive.read(dataPtr, dataSize);
- _fileCursor += readBytes;
-
- return readBytes;
-}
-
-
-
-} // namespace Parallaction
diff --git a/engines/parallaction/callables.cpp b/engines/parallaction/callables.cpp
deleted file mode 100644
index be92ca1daa..0000000000
--- a/engines/parallaction/callables.cpp
+++ /dev/null
@@ -1,460 +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 "common/file.h"
-
-#include "parallaction/parallaction.h"
-#include "parallaction/menu.h"
-#include "parallaction/sound.h"
-
-
-namespace Parallaction {
-
-
-
-
-static Zone *_moveSarcZones[5];
-static Zone *_moveSarcExaZones[5];
-
-void _c_null(void *parm) {
-
- return;
-}
-
-void _c_play_boogie(void *parm) {
-
- static uint16 flag = 1;
-
- if (flag == 0)
- return;
- flag = 0;
-
- _vm->_soundMan->setMusicFile("boogie2");
- _vm->_soundMan->playMusic();
-
- return;
-}
-
-
-void _c_score(void *parm) {
- _score += 5;
- return;
-}
-
-void _c_fade(void *parm) {
-
- _vm->_gfx->setBlackPalette();
-
- Gfx::Palette pal;
- memset(pal, 0, sizeof(Gfx::Palette));
-
- for (uint16 _di = 0; _di < 64; _di++) {
- _vm->_gfx->fadePalette(pal);
- _vm->_gfx->setPalette(pal);
-
- _vm->waitTime( 1 );
- }
-
- return;
-}
-
-Zone *_moveSarcZone0 = NULL;
-int16 _introSarcData1 = 0;
-Zone *_moveSarcZone1 = NULL;
-
-void _c_moveSarc(void *parm) {
-
- Animation *a;
-
- if (_introSarcData2 != 0) {
-
- _introSarcData2 = 0;
- if (_moveSarcZones[0] == NULL) {
-
- _moveSarcZones[0] = _vm->findZone("sarc1");
- _moveSarcZones[1] = _vm->findZone("sarc2");
- _moveSarcZones[2] = _vm->findZone("sarc3");
- _moveSarcZones[3] = _vm->findZone("sarc4");
- _moveSarcZones[4] = _vm->findZone("sarc5");
-
- _moveSarcExaZones[0] = _vm->findZone("sarc1exa");
- _moveSarcExaZones[1] = _vm->findZone("sarc2exa");
- _moveSarcExaZones[2] = _vm->findZone("sarc3exa");
- _moveSarcExaZones[3] = _vm->findZone("sarc4exa");
- _moveSarcExaZones[4] = _vm->findZone("sarc5exa");
-
- }
-
- a = _vm->findAnimation("sposta");
-
- _moveSarcZone1 = (Zone*)parm;
-
- for (uint16 _si = 0; _si < 5; _si++) {
- if (_moveSarcZones[_si] == _moveSarcZone1) {
- _moveSarcZone0 = _moveSarcExaZones[_si];
- }
- }
-
- _introSarcData1 = _introSarcData3 - _moveSarcZone1->_left;
- a->_z = _introSarcData3;
- a->_frame = _moveSarcZone1->_top - (_introSarcData1 / 20);
- _introSarcData3 = _moveSarcZone1->_left;
-
- if (_introSarcData1 > 0) {
- a->_left = _introSarcData1 / 2;
- } else {
- a->_left = -_introSarcData1 / 2;
- }
-
- if (_introSarcData1 > 0) {
- a->_top = 2;
- } else {
- a->_top = -2;
- }
-
- return;
-
- }
-
- _introSarcData2 = 1;
- _moveSarcZone1->translate(_introSarcData1, -_introSarcData1 / 20);
- _moveSarcZone0->translate(_introSarcData1, -_introSarcData1 / 20);
-
- if (_moveSarcZones[0]->_left == 35 &&
- _moveSarcZones[1]->_left == 68 &&
- _moveSarcZones[2]->_left == 101 &&
- _moveSarcZones[3]->_left == 134 &&
- _moveSarcZones[4]->_left == 167) {
-
- a = _vm->findAnimation("finito");
-
- a->_flags |= (kFlagsActive | kFlagsActing);
- _localFlags[_vm->_currentLocationIndex] |= 0x20; // GROSS HACK: activates 'finito' flag in dinoit_museo.loc
- }
-
- return;
-
-}
-
-
-static uint16 num_foglie = 0;
-
-void _c_contaFoglie(void *parm) {
-
- num_foglie++;
- if (num_foglie != 6)
- return;
-
- _commandFlags |= 0x1000;
-
- return;
-}
-
-void _c_zeroFoglie(void *parm) {
- num_foglie = 0;
- return;
-}
-
-void _c_trasformata(void *parm) {
- _engineFlags ^= kEngineTransformedDonna;
- return;
-}
-
-void _c_offMouse(void *parm) {
- _vm->showCursor(false);
- _engineFlags |= kEngineBlockInput;
- return;
-}
-
-void _c_onMouse(void *parm) {
- _engineFlags &= ~kEngineBlockInput;
- _vm->showCursor(true);
- return;
-}
-
-
-
-void _c_setMask(void *parm) {
-
- _vm->_gfx->intGrottaHackMask();
-
- return;
-}
-
-void _c_endComment(void *param) {
-
- byte* _enginePal = _vm->_gfx->_palette;
- Gfx::Palette pal;
-
- uint32 si;
- for (si = 0; si < 32; si++) {
-
- byte al = _enginePal[si*3+1];
- if (al > _enginePal[si*3+2]) {
- al = _enginePal[si*3+1];
- } else {
- al = _enginePal[si*3+2];
- }
-
- if (al < _enginePal[si*3]) {
- al = _enginePal[si*3];
- } else {
- al = _enginePal[si*3+1];
- }
-
- if (al > _enginePal[si*3+2]) {
- al = _enginePal[si*3+1];
- } else {
- al = _enginePal[si*3+2];
- }
-
- pal[si*3] = al;
- pal[si*3+2] = al;
- pal[si*3+1] = al;
-
- }
-
- int16 w = 0, h = 0;
- _vm->_gfx->getStringExtent(_vm->_location._endComment, 130, &w, &h);
-
- Common::Rect r(w+5, h+5);
- r.moveTo(5, 5);
- _vm->_gfx->floodFill(Gfx::kBitFront, r, 0);
-
- r.setWidth(w+3);
- r.setHeight(h+3);
- r.moveTo(7, 7);
- _vm->_gfx->floodFill(Gfx::kBitFront, r, 1);
-
- _vm->_gfx->setFont(kFontDialogue);
- _vm->_gfx->displayWrappedString(_vm->_location._endComment, 3, 5, 0, 130);
- _vm->_gfx->updateScreen();
-
- uint32 di = 0;
- for (di = 0; di < PALETTE_COLORS; di++) {
- for (si = 0; si <= 93; si +=3) {
-
- int8 al;
-
- if (_enginePal[si] != pal[si]) {
- al = _enginePal[si];
- if (al > pal[si])
- al = 1;
- else
- al = -1;
- _enginePal[si] += al;
- }
-
- if (_enginePal[si+1] != pal[si+1]) {
- al = _enginePal[si+1];
- if (al > pal[si+1])
- al = 1;
- else
- al = -1;
- _enginePal[si+1] += al;
- }
-
- if (_enginePal[si+2] != pal[si+2]) {
- al = _enginePal[si+2];
- if (al > pal[si+2])
- al = 1;
- else
- al = -1;
- _enginePal[si+2] += al;
- }
-
- }
-
- _vm->_gfx->setPalette(_enginePal);
- }
-
- waitUntilLeftClick();
-
- return;
-}
-
-void _c_frankenstein(void *parm) {
-
- Gfx::Palette pal0;
- Gfx::Palette pal1;
-
- for (uint16 i = 0; i <= BASE_PALETTE_COLORS; i++) {
- pal0[(i+FIRST_BASE_COLOR)] = _vm->_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 _di = 0; _di < 30; _di++) {
- g_system->delayMillis(20);
- _vm->_gfx->setPalette(pal0, FIRST_BASE_COLOR, BASE_PALETTE_COLORS);
- g_system->delayMillis(20);
- _vm->_gfx->setPalette(pal1, FIRST_BASE_COLOR, BASE_PALETTE_COLORS);
- }
-
- _vm->_gfx->setPalette(_vm->_gfx->_palette);
-
- return;
-}
-// part completion messages
-const char *endMsg0[] = {"COMPLIMENTI!", "BRAVO!", "CONGRATULATIONS!", "PRIMA!"};
-const char *endMsg1[] = {"HAI FINITO QUESTA PARTE", "TU AS COMPLETE' CETTE AVENTURE", "YOU HAVE COMPLETED THIS PART", "DU HAST EIN ABENTEUER ERFOLGREICH"};
-const char *endMsg2[] = {"ORA COMPLETA IL RESTO ", "AVEC SUCCES.", "NOW GO ON WITH THE REST OF", "ZU ENDE GEFUHRT"};
-const char *endMsg3[] = {"DELL' AVVENTURA", "CONTINUE AVEC LES AUTRES", "THIS ADVENTURE", "MACH' MIT DEN ANDEREN WEITER"};
-// game completion messages
-const char *endMsg4[] = {"COMPLIMENTI!", "BRAVO!", "CONGRATULATIONS!", "PRIMA!"};
-const char *endMsg5[] = {"HAI FINITO LE TRE PARTI", "TU AS COMPLETE' LES TROIS PARTIES", "YOU HAVE COMPLETED THE THREE PARTS", "DU HAST DREI ABENTEURE ERFOLGREICH"};
-const char *endMsg6[] = {"DELL' AVVENTURA", "DE L'AVENTURE", "OF THIS ADVENTURE", "ZU ENDE GEFUHRT"};
-const char *endMsg7[] = {"ED ORA IL GRAN FINALE ", "ET MAINTENANT LE GRAND FINAL", "NOW THE GREAT FINAL", "UND YETZT DER GROSSE SCHLUSS!"};
-
-
-void _c_finito(void *parm) {
-
- const char **v8C = endMsg0;
- const char **v7C = endMsg1;
- const char **v6C = endMsg2;
- const char **v5C = endMsg3;
- const char **v4C = endMsg4;
- const char **v3C = endMsg5;
- const char **v2C = endMsg6;
- const char **v1C = endMsg7;
-
- Common::File stream;
-
- stream.open(_vm->_characterName, Common::File::kFileWriteMode);
- if (stream.isOpen())
- stream.close();
-
- Common::File streamDino, streamDough, streamDonna;
-
- streamDino.open("dino");
- streamDough.open("dough");
- streamDonna.open("donna");
-
- bool gameCompleted = streamDino.isOpen() && streamDough.isOpen() && streamDonna.isOpen();
-
- streamDino.close();
- streamDough.close();
- streamDonna.close();
-
- cleanInventory();
-
- _vm->_gfx->setPalette(_vm->_gfx->_palette);
-
- if (gameCompleted) {
- _vm->_gfx->setFont(kFontMenu);
- _vm->_gfx->displayCenteredString(70, v4C[_language]);
- _vm->_gfx->displayCenteredString(100, v3C[_language]);
- _vm->_gfx->displayCenteredString(130, v2C[_language]);
- _vm->_gfx->displayCenteredString(160, v1C[_language]);
-
- _vm->_gfx->updateScreen();
- waitUntilLeftClick();
-
- strcpy(_vm->_location._name, "estgrotta.drki");
-
- _engineFlags |= kEngineChangeLocation;
- } else {
- _vm->_gfx->setFont(kFontMenu);
- _vm->_gfx->displayCenteredString(70, v8C[_language]);
- _vm->_gfx->displayCenteredString(100, v7C[_language]);
- _vm->_gfx->displayCenteredString(130, v6C[_language]);
- _vm->_gfx->displayCenteredString(160, v5C[_language]);
-
- _vm->_gfx->updateScreen();
- waitUntilLeftClick();
-
- _vm->_menu->selectCharacter();
- }
-
- // this code saves main character animation from being removed from the following code
- _vm->_animations.remove(&_vm->_char._ani);
- _vm->_locationNames[0][0] = '\0';
- _vm->_numLocations = 0;
- _commandFlags = 0;
-
- // this flag tells freeZones to unconditionally remove *all* Zones
- _engineFlags |= kEngineQuit;
-
- // TODO (LIST): this sequence should be just _zones.clear()
- _vm->freeZones();
-
- // TODO (LIST): this sequence should be just _animations.clear()
- _vm->freeAnimations();
-
- // this dangerous flag can now be cleared
- _engineFlags &= ~kEngineQuit;
-
- // main character animation is restored
- _vm->_animations.push_front(&_vm->_char._ani);
- _score = 0;
-
- return;
-}
-
-void _c_ridux(void *parm) {
- _vm->changeCharacter(_minidinoName);
- return;
-}
-
-void _c_testResult(void *parm) {
- _vm->_gfx->swapBuffers();
-
- _vm->_disk->selectArchive("disk1");
- _vm->parseLocation("common");
-
- _vm->_gfx->setFont(kFontMenu);
-
- _vm->_gfx->displayCenteredString(38, _slideText[0]);
- _vm->_gfx->displayCenteredString(58, _slideText[1]);
-
- _vm->_gfx->copyScreen(Gfx::kBitFront, Gfx::kBitBack);
- _vm->_gfx->copyScreen(Gfx::kBitFront, Gfx::kBit2);
-
- return;
-}
-
-void _c_offSound(void*) {
- _vm->_soundMan->stopSfx(0);
- _vm->_soundMan->stopSfx(1);
- _vm->_soundMan->stopSfx(2);
- _vm->_soundMan->stopSfx(3);
-}
-
-void _c_startMusic(void*) {
- _vm->_soundMan->playMusic();
-}
-
-void _c_closeMusic(void*) {
- _vm->_soundMan->stopMusic();
-}
-
-} // namespace Parallaction
diff --git a/engines/parallaction/callables_br.cpp b/engines/parallaction/callables_br.cpp
new file mode 100644
index 0000000000..829195fd7a
--- /dev/null
+++ b/engines/parallaction/callables_br.cpp
@@ -0,0 +1,60 @@
+/* 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 {
+
+
+void Parallaction_br::_c_blufade(void*) {
+ warning("Parallaction_br::_c_blufade() not yet implemented");
+}
+
+void Parallaction_br::_c_resetpalette(void*) {
+ warning("Parallaction_br::_c_resetpalette() not yet implemented");
+}
+
+void Parallaction_br::_c_ferrcycle(void*) {
+ warning("Parallaction_br::_c_ferrcycle() not yet implemented");
+}
+
+void Parallaction_br::_c_lipsinc(void*) {
+ warning("Parallaction_br::_c_lipsinc() not yet implemented");
+}
+
+void Parallaction_br::_c_albcycle(void*) {
+ warning("Parallaction_br::_c_albcycle() not yet implemented");
+}
+
+void Parallaction_br::_c_password(void*) {
+ warning("Parallaction_br::_c_password() not yet implemented");
+}
+
+
+
+
+} // namespace Parallaction
diff --git a/engines/parallaction/callables_ns.cpp b/engines/parallaction/callables_ns.cpp
new file mode 100644
index 0000000000..94a0747ab1
--- /dev/null
+++ b/engines/parallaction/callables_ns.cpp
@@ -0,0 +1,718 @@
+/* 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 "common/file.h"
+
+#include "graphics/primitives.h" // for Graphics::drawLine
+
+#include "parallaction/parallaction.h"
+#include "parallaction/menu.h"
+#include "parallaction/sound.h"
+
+
+namespace Parallaction {
+
+/*
+ game callables data members
+*/
+
+static Zone *_moveSarcZone0 = NULL;
+static int16 _introSarcData1 = 0;
+static Zone *_moveSarcZone1 = NULL;
+
+// part completion messages
+static const char *endMsg0[] = {"COMPLIMENTI!", "BRAVO!", "CONGRATULATIONS!", "PRIMA!"};
+static const char *endMsg1[] = {"HAI FINITO QUESTA PARTE", "TU AS COMPLETE' CETTE AVENTURE", "YOU HAVE COMPLETED THIS PART", "DU HAST EIN ABENTEUER ERFOLGREICH"};
+static const char *endMsg2[] = {"ORA COMPLETA IL RESTO ", "AVEC SUCCES.", "NOW GO ON WITH THE REST OF", "ZU ENDE GEFUHRT"};
+static const char *endMsg3[] = {"DELL' AVVENTURA", "CONTINUE AVEC LES AUTRES", "THIS ADVENTURE", "MACH' MIT DEN ANDEREN WEITER"};
+// game completion messages
+static const char *endMsg4[] = {"COMPLIMENTI!", "BRAVO!", "CONGRATULATIONS!", "PRIMA!"};
+static const char *endMsg5[] = {"HAI FINITO LE TRE PARTI", "TU AS COMPLETE' LES TROIS PARTIES", "YOU HAVE COMPLETED THE THREE PARTS", "DU HAST DREI ABENTEURE ERFOLGREICH"};
+static const char *endMsg6[] = {"DELL' AVVENTURA", "DE L'AVENTURE", "OF THIS ADVENTURE", "ZU ENDE GEFUHRT"};
+static const char *endMsg7[] = {"ED ORA IL GRAN FINALE ", "ET MAINTENANT LE GRAND FINAL", "NOW THE GREAT FINAL", "UND YETZT DER GROSSE SCHLUSS!"};
+
+static uint16 num_foglie = 0;
+static Zone *_moveSarcZones[5];
+static Zone *_moveSarcExaZones[5];
+
+/*
+ intro callables data members
+*/
+
+static Animation *_rightHandAnim;
+
+static uint16 _rightHandPositions[684] = {
+ 0x0064, 0x0046, 0x006c, 0x0046, 0x0074, 0x0046, 0x007c, 0x0046,
+ 0x0084, 0x0046, 0x008c, 0x0046, 0x0094, 0x0046, 0x009c, 0x0046,
+ 0x00a4, 0x0046, 0x00ac, 0x0046, 0x00b4, 0x0046, 0x00bc, 0x0046,
+ 0x00c4, 0x0046, 0x00cc, 0x0046, 0x00d4, 0x0046, 0x00dc, 0x0046,
+ 0x00e4, 0x0046, 0x00ec, 0x0046, 0x00f4, 0x0046, 0x00fc, 0x0046,
+ 0x0104, 0x0046, 0x00ff, 0x0042, 0x00ff, 0x004a, 0x00ff, 0x0052,
+ 0x00ff, 0x005a, 0x00ff, 0x0062, 0x00ff, 0x006a, 0x00ff, 0x0072,
+ 0x00ff, 0x007a, 0x00ff, 0x0082, 0x00ff, 0x008a, 0x00ff, 0x0092,
+ 0x00ff, 0x009a, 0x00ff, 0x00a2, 0x0104, 0x0097, 0x00fc, 0x0097,
+ 0x00f4, 0x0097, 0x00ec, 0x0097, 0x00e4, 0x0097, 0x00dc, 0x0097,
+ 0x00d4, 0x0097, 0x00cc, 0x0097, 0x00c4, 0x0097, 0x00bc, 0x0097,
+ 0x00b4, 0x0097, 0x00ac, 0x0097, 0x00a4, 0x0097, 0x009c, 0x0097,
+ 0x0094, 0x0097, 0x008c, 0x0097, 0x0084, 0x0097, 0x007c, 0x0097,
+ 0x0074, 0x0097, 0x006c, 0x0097, 0x0064, 0x0097, 0x0066, 0x0042,
+ 0x0066, 0x004a, 0x0066, 0x0052, 0x0066, 0x005a, 0x0066, 0x0062,
+ 0x0066, 0x006a, 0x0066, 0x0072, 0x0066, 0x007a, 0x0066, 0x0082,
+ 0x0066, 0x008a, 0x0066, 0x0092, 0x0066, 0x009a, 0x0066, 0x00a2,
+ 0x008c, 0x0091, 0x0099, 0x0042, 0x0099, 0x004a, 0x0099, 0x0052,
+ 0x0099, 0x005a, 0x0099, 0x0062, 0x0099, 0x006a, 0x0099, 0x0072,
+ 0x0099, 0x007a, 0x0099, 0x0082, 0x0099, 0x008a, 0x0099, 0x0092,
+ 0x0099, 0x009a, 0x0099, 0x00a2, 0x00a0, 0x004d, 0x00cc, 0x0042,
+ 0x00cc, 0x004a, 0x00cc, 0x0052, 0x00cc, 0x005a, 0x00cc, 0x0062,
+ 0x00cc, 0x006a, 0x00cc, 0x0072, 0x00cc, 0x007a, 0x00cc, 0x0082,
+ 0x00cc, 0x008a, 0x00cc, 0x0092, 0x00cc, 0x009a, 0x00cc, 0x00a2,
+ 0x00ca, 0x0050, 0x00b1, 0x0050, 0x0081, 0x0052, 0x007e, 0x0052,
+ 0x007c, 0x0055, 0x007c, 0x005c, 0x007e, 0x005e, 0x0080, 0x005e,
+ 0x0082, 0x005c, 0x0082, 0x0054, 0x0080, 0x0052, 0x0078, 0x0052,
+ 0x007c, 0x005e, 0x0077, 0x0061, 0x0074, 0x006e, 0x0074, 0x0078,
+ 0x0076, 0x007a, 0x0079, 0x0078, 0x0079, 0x0070, 0x0078, 0x0070,
+ 0x0078, 0x006b, 0x007b, 0x0066, 0x007a, 0x006f, 0x0084, 0x006f,
+ 0x0085, 0x0066, 0x0086, 0x0070, 0x0085, 0x0070, 0x0085, 0x0079,
+ 0x0088, 0x0079, 0x008a, 0x0078, 0x008a, 0x006c, 0x0087, 0x0061,
+ 0x0085, 0x005f, 0x0082, 0x005f, 0x0080, 0x0061, 0x007e, 0x0061,
+ 0x007b, 0x005f, 0x007c, 0x006f, 0x007c, 0x0071, 0x0079, 0x0074,
+ 0x0079, 0x0089, 0x0076, 0x008c, 0x0076, 0x008e, 0x007a, 0x008e,
+ 0x007f, 0x0089, 0x007f, 0x0083, 0x007e, 0x0083, 0x007e, 0x0077,
+ 0x0080, 0x0077, 0x0080, 0x0083, 0x0080, 0x008b, 0x0084, 0x0090,
+ 0x0088, 0x0090, 0x0088, 0x008e, 0x0085, 0x008b, 0x0085, 0x0074,
+ 0x0082, 0x0071, 0x00b2, 0x0052, 0x00b0, 0x0054, 0x00b0, 0x0056,
+ 0x00ae, 0x0058, 0x00af, 0x0059, 0x00af, 0x005e, 0x00b2, 0x0061,
+ 0x00b5, 0x0061, 0x00b8, 0x005e, 0x00b8, 0x005a, 0x00b9, 0x0059,
+ 0x00b9, 0x0058, 0x00b7, 0x0056, 0x00b7, 0x0054, 0x00b5, 0x0052,
+ 0x00b2, 0x0052, 0x00ae, 0x005a, 0x00ab, 0x005b, 0x00ab, 0x006d,
+ 0x00ae, 0x0072, 0x00b8, 0x0072, 0x00bc, 0x006d, 0x00bc, 0x005b,
+ 0x00b9, 0x005a, 0x00bc, 0x005c, 0x00be, 0x005c, 0x00c1, 0x005f,
+ 0x00c4, 0x0067, 0x00c4, 0x006d, 0x00c1, 0x0076, 0x00c0, 0x0077,
+ 0x00bd, 0x0077, 0x00bb, 0x0075, 0x00bd, 0x0073, 0x00bb, 0x0072,
+ 0x00be, 0x0070, 0x00be, 0x006a, 0x00a9, 0x006a, 0x00a9, 0x0070,
+ 0x00ac, 0x0072, 0x00aa, 0x0073, 0x00ac, 0x0075, 0x00aa, 0x0077,
+ 0x00a7, 0x0077, 0x00a3, 0x006d, 0x00a3, 0x0067, 0x00a6, 0x005f,
+ 0x00a9, 0x005c, 0x00ab, 0x005c, 0x00ac, 0x0077, 0x00ac, 0x007c,
+ 0x00ab, 0x007c, 0x00ab, 0x0084, 0x00ac, 0x0084, 0x00ac, 0x008b,
+ 0x00a9, 0x008e, 0x00a9, 0x0090, 0x00ae, 0x0090, 0x00ae, 0x008d,
+ 0x00b2, 0x008c, 0x00b2, 0x0087, 0x00b1, 0x0086, 0x00b1, 0x007b,
+ 0x00b2, 0x0079, 0x00b4, 0x0079, 0x00b4, 0x007d, 0x00b5, 0x007d,
+ 0x00b5, 0x0087, 0x00b4, 0x0087, 0x00b4, 0x008c, 0x00b6, 0x008c,
+ 0x00b9, 0x0091, 0x00b4, 0x0091, 0x00bd, 0x008f, 0x00ba, 0x008c,
+ 0x00ba, 0x0083, 0x00bb, 0x0082, 0x00bb, 0x0075, 0x00cc, 0x006e,
+ 0x00d4, 0x006c, 0x00db, 0x0069, 0x00d9, 0x0068, 0x00d9, 0x0064,
+ 0x00dc, 0x0064, 0x00dc, 0x0060, 0x00df, 0x0056, 0x00e5, 0x0052,
+ 0x00e7, 0x0052, 0x00ec, 0x0056, 0x00ef, 0x005d, 0x00f1, 0x0065,
+ 0x00f3, 0x0064, 0x00f3, 0x0069, 0x00f0, 0x0069, 0x00ec, 0x0065,
+ 0x00ec, 0x005e, 0x00e9, 0x005f, 0x00e9, 0x005a, 0x00e7, 0x0058,
+ 0x00e4, 0x0058, 0x00e3, 0x0054, 0x00e3, 0x0058, 0x00e1, 0x005c,
+ 0x00e4, 0x0061, 0x00e7, 0x0061, 0x00e9, 0x005f, 0x00eb, 0x005d,
+ 0x00e4, 0x0062, 0x00e0, 0x0064, 0x00e0, 0x0069, 0x00e2, 0x006b,
+ 0x00e0, 0x0072, 0x00e0, 0x0077, 0x00ec, 0x0077, 0x00ec, 0x0071,
+ 0x00ea, 0x006b, 0x00ec, 0x006a, 0x00ec, 0x0063, 0x00e7, 0x0063,
+ 0x00e7, 0x0065, 0x00e1, 0x0069, 0x00e3, 0x0068, 0x00e6, 0x0069,
+ 0x00ec, 0x005e, 0x00ea, 0x006b, 0x00e7, 0x006b, 0x00e7, 0x006a,
+ 0x00e5, 0x006a, 0x00e5, 0x006b, 0x00e2, 0x006b, 0x00df, 0x006c,
+ 0x00dc, 0x006f, 0x00dc, 0x0071, 0x00da, 0x0073, 0x00d8, 0x0073,
+ 0x00d8, 0x006f, 0x00dc, 0x006b, 0x00dc, 0x0069, 0x00dd, 0x0068,
+ 0x00ef, 0x0068, 0x00f0, 0x0069, 0x00f0, 0x006b, 0x00f4, 0x006f,
+ 0x00f4, 0x0072, 0x00f3, 0x0073, 0x00f2, 0x0073, 0x00f0, 0x0071,
+ 0x00f0, 0x006f, 0x00ec, 0x006b, 0x00ec, 0x007a, 0x00eb, 0x007b,
+ 0x00eb, 0x007f, 0x00ec, 0x0080, 0x00ec, 0x0084, 0x00eb, 0x0085,
+ 0x00eb, 0x008b, 0x00ec, 0x008c, 0x00ec, 0x008f, 0x00ed, 0x0091,
+ 0x00e9, 0x0091, 0x00e9, 0x008f, 0x00e7, 0x008d, 0x00e7, 0x0090,
+ 0x00e7, 0x0089, 0x00e8, 0x0088, 0x00e8, 0x0086, 0x00e7, 0x0085,
+ 0x00e7, 0x007d, 0x00e6, 0x007c, 0x00e6, 0x0078, 0x00e5, 0x007d,
+ 0x00e5, 0x0085, 0x00e4, 0x0086, 0x00e4, 0x0088, 0x00e5, 0x0089,
+ 0x00e5, 0x0090, 0x00e5, 0x008b, 0x00e3, 0x0091, 0x00df, 0x0091,
+ 0x00e0, 0x0090, 0x00e0, 0x008c, 0x00e2, 0x008b, 0x00e1, 0x0085,
+ 0x00e0, 0x0084, 0x00e0, 0x0080, 0x00e1, 0x007f, 0x00e1, 0x007c,
+ 0x00e0, 0x007b, 0x00e0, 0x0077
+};
+
+struct Credit {
+ const char *_role;
+ const char *_name;
+} _credits[] = {
+ {"Music and Sound Effects", "MARCO CAPRELLI"},
+ {"PC Version", "RICCARDO BALLARINO"},
+ {"Project Manager", "LOVRANO CANEPA"},
+ {"Production", "BRUNO BOZ"},
+ {"Special Thanks to", "LUIGI BENEDICENTI - GILDA and DANILO"},
+ {"Copyright 1992 Euclidea s.r.l ITALY", "All rights reserved"}
+};
+
+/*
+ game callables
+*/
+
+void Parallaction_ns::_c_null(void *parm) {
+
+ return;
+}
+
+void Parallaction_ns::_c_play_boogie(void *parm) {
+
+ static uint16 flag = 1;
+
+ if (flag == 0)
+ return;
+ flag = 0;
+
+ _soundMan->setMusicFile("boogie2");
+ _soundMan->playMusic();
+
+ return;
+}
+
+
+void Parallaction_ns::_c_score(void *parm) {
+ _score += 5;
+ return;
+}
+
+void Parallaction_ns::_c_fade(void *parm) {
+
+ _gfx->setBlackPalette();
+
+ Gfx::Palette pal;
+ memset(pal, 0, sizeof(Gfx::Palette));
+
+ for (uint16 _di = 0; _di < 64; _di++) {
+ _gfx->fadePalette(pal, _gfx->_palette, 1);
+ _gfx->setPalette(pal);
+
+ _gfx->updateScreen();
+ g_system->delayMillis(20);
+ }
+
+ return;
+}
+
+
+
+void Parallaction_ns::_c_moveSarc(void *parm) {
+
+ Animation *a;
+
+ if (_introSarcData2 != 0) {
+
+ _introSarcData2 = 0;
+ if (_moveSarcZones[0] == NULL) {
+
+ _moveSarcZones[0] = findZone("sarc1");
+ _moveSarcZones[1] = findZone("sarc2");
+ _moveSarcZones[2] = findZone("sarc3");
+ _moveSarcZones[3] = findZone("sarc4");
+ _moveSarcZones[4] = findZone("sarc5");
+
+ _moveSarcExaZones[0] = findZone("sarc1exa");
+ _moveSarcExaZones[1] = findZone("sarc2exa");
+ _moveSarcExaZones[2] = findZone("sarc3exa");
+ _moveSarcExaZones[3] = findZone("sarc4exa");
+ _moveSarcExaZones[4] = findZone("sarc5exa");
+
+ }
+
+ a = findAnimation("sposta");
+
+ _moveSarcZone1 = (Zone*)parm;
+
+ for (uint16 _si = 0; _si < 5; _si++) {
+ if (_moveSarcZones[_si] == _moveSarcZone1) {
+ _moveSarcZone0 = _moveSarcExaZones[_si];
+ }
+ }
+
+ _introSarcData1 = _introSarcData3 - _moveSarcZone1->_left;
+ a->_z = _introSarcData3;
+ a->_frame = _moveSarcZone1->_top - (_introSarcData1 / 20);
+ _introSarcData3 = _moveSarcZone1->_left;
+
+ if (_introSarcData1 > 0) {
+ a->_left = _introSarcData1 / 2;
+ } else {
+ a->_left = -_introSarcData1 / 2;
+ }
+
+ if (_introSarcData1 > 0) {
+ a->_top = 2;
+ } else {
+ a->_top = -2;
+ }
+
+ return;
+
+ }
+
+ _introSarcData2 = 1;
+ _moveSarcZone1->translate(_introSarcData1, -_introSarcData1 / 20);
+ _moveSarcZone0->translate(_introSarcData1, -_introSarcData1 / 20);
+
+ if (_moveSarcZones[0]->_left == 35 &&
+ _moveSarcZones[1]->_left == 68 &&
+ _moveSarcZones[2]->_left == 101 &&
+ _moveSarcZones[3]->_left == 134 &&
+ _moveSarcZones[4]->_left == 167) {
+
+ a = findAnimation("finito");
+
+ a->_flags |= (kFlagsActive | kFlagsActing);
+ _localFlags[_currentLocationIndex] |= 0x20; // GROSS HACK: activates 'finito' flag in dinoit_museo.loc
+ }
+
+ return;
+
+}
+
+
+
+
+void Parallaction_ns::_c_contaFoglie(void *parm) {
+
+ num_foglie++;
+ if (num_foglie != 6)
+ return;
+
+ _commandFlags |= 0x1000;
+
+ return;
+}
+
+void Parallaction_ns::_c_zeroFoglie(void *parm) {
+ num_foglie = 0;
+ return;
+}
+
+void Parallaction_ns::_c_trasformata(void *parm) {
+ _engineFlags ^= kEngineTransformedDonna;
+ return;
+}
+
+void Parallaction_ns::_c_offMouse(void *parm) {
+ showCursor(false);
+ _engineFlags |= kEngineBlockInput;
+ return;
+}
+
+void Parallaction_ns::_c_onMouse(void *parm) {
+ _engineFlags &= ~kEngineBlockInput;
+ showCursor(true);
+ return;
+}
+
+
+
+void Parallaction_ns::_c_setMask(void *parm) {
+
+ _gfx->intGrottaHackMask();
+
+ 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();
+
+
+ Gfx::Palette pal;
+ _gfx->makeGrayscalePalette(pal);
+
+ for (uint di = 0; di < 64; di++) {
+ _gfx->fadePalette(_gfx->_palette, pal, 1);
+ _gfx->setPalette(_gfx->_palette);
+
+ _gfx->updateScreen();
+ g_system->delayMillis(20);
+ }
+
+ waitUntilLeftClick();
+
+ return;
+}
+
+void Parallaction_ns::_c_frankenstein(void *parm) {
+
+ Gfx::Palette pal0;
+ Gfx::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 _di = 0; _di < 30; _di++) {
+ g_system->delayMillis(20);
+ _gfx->setPalette(pal0, FIRST_BASE_COLOR, BASE_PALETTE_COLORS);
+ _gfx->updateScreen();
+ g_system->delayMillis(20);
+ _gfx->setPalette(pal1, FIRST_BASE_COLOR, BASE_PALETTE_COLORS);
+ _gfx->updateScreen();
+ }
+
+ _gfx->setPalette(_gfx->_palette);
+ _gfx->updateScreen();
+
+ return;
+}
+
+
+void Parallaction_ns::_c_finito(void *parm) {
+
+ const char **v8C = endMsg0;
+ const char **v7C = endMsg1;
+ const char **v6C = endMsg2;
+ const char **v5C = endMsg3;
+ const char **v4C = endMsg4;
+ const char **v3C = endMsg5;
+ const char **v2C = endMsg6;
+ const char **v1C = endMsg7;
+
+ Common::File stream;
+
+ stream.open(_characterName, Common::File::kFileWriteMode);
+ if (stream.isOpen())
+ stream.close();
+
+ Common::File streamDino, streamDough, streamDonna;
+
+ streamDino.open("dino");
+ streamDough.open("dough");
+ streamDonna.open("donna");
+
+ bool gameCompleted = streamDino.isOpen() && streamDough.isOpen() && streamDonna.isOpen();
+
+ streamDino.close();
+ streamDough.close();
+ streamDonna.close();
+
+ cleanInventory();
+
+ _gfx->setPalette(_gfx->_palette);
+
+ if (gameCompleted) {
+ _gfx->setFont(kFontMenu);
+ _gfx->displayCenteredString(70, v4C[_language]);
+ _gfx->displayCenteredString(100, v3C[_language]);
+ _gfx->displayCenteredString(130, v2C[_language]);
+ _gfx->displayCenteredString(160, v1C[_language]);
+
+ _gfx->updateScreen();
+ waitUntilLeftClick();
+
+ strcpy(_location._name, "estgrotta.drki");
+
+ _engineFlags |= kEngineChangeLocation;
+ } else {
+ _gfx->setFont(kFontMenu);
+ _gfx->displayCenteredString(70, v8C[_language]);
+ _gfx->displayCenteredString(100, v7C[_language]);
+ _gfx->displayCenteredString(130, v6C[_language]);
+ _gfx->displayCenteredString(160, v5C[_language]);
+
+ _gfx->updateScreen();
+ waitUntilLeftClick();
+
+ _menu->selectCharacter();
+ }
+
+ // this code saves main character animation from being removed from the following code
+ _animations.remove(&_char._ani);
+ _locationNames[0][0] = '\0';
+ _numLocations = 0;
+ _commandFlags = 0;
+
+ // this flag tells freeZones to unconditionally remove *all* Zones
+ _engineFlags |= kEngineQuit;
+
+ freeZones();
+ freeAnimations();
+
+ // this dangerous flag can now be cleared
+ _engineFlags &= ~kEngineQuit;
+
+ // main character animation is restored
+ _animations.push_front(&_char._ani);
+ _score = 0;
+
+ return;
+}
+
+void Parallaction_ns::_c_ridux(void *parm) {
+ changeCharacter(_minidinoName);
+ return;
+}
+
+void Parallaction_ns::_c_testResult(void *parm) {
+ _gfx->swapBuffers();
+
+ _disk->selectArchive("disk1");
+ parseLocation("common");
+
+ _gfx->setFont(kFontMenu);
+
+ _gfx->displayCenteredString(38, _slideText[0]);
+ _gfx->displayCenteredString(58, _slideText[1]);
+
+ _gfx->copyScreen(Gfx::kBitFront, Gfx::kBitBack);
+ _gfx->copyScreen(Gfx::kBitFront, Gfx::kBit2);
+
+ return;
+}
+
+void Parallaction_ns::_c_offSound(void*) {
+ _soundMan->stopSfx(0);
+ _soundMan->stopSfx(1);
+ _soundMan->stopSfx(2);
+ _soundMan->stopSfx(3);
+}
+
+void Parallaction_ns::_c_startMusic(void*) {
+ _soundMan->playMusic();
+}
+
+void Parallaction_ns::_c_closeMusic(void*) {
+ _soundMan->stopMusic();
+}
+
+/*
+ intro callables
+*/
+
+void Parallaction_ns::_c_startIntro(void *parm) {
+ _rightHandAnim = findAnimation("righthand");
+
+ if (getPlatform() == Common::kPlatformPC) {
+ _soundMan->setMusicFile("intro");
+ _soundMan->playMusic();
+ }
+
+ _engineFlags |= kEngineBlockInput;
+
+ return;
+}
+
+void Parallaction_ns::_c_endIntro(void *parm) {
+
+ _gfx->setFont(kFontMenu);
+
+ debugC(1, kDebugLocation, "endIntro()");
+
+ for (uint16 _si = 0; _si < 6; _si++) {
+ _gfx->displayCenteredString(80, _credits[_si]._role);
+ _gfx->displayCenteredString(100, _credits[_si]._name);
+
+ _gfx->updateScreen();
+
+ for (uint16 v2 = 0; v2 < 100; v2++) {
+ _mouseButtons = kMouseNone;
+ updateInput();
+ if (_mouseButtons == kMouseLeftUp)
+ break;
+
+ waitTime( 1 );
+ }
+
+ _gfx->copyScreen(Gfx::kBitBack, Gfx::kBitFront);
+ }
+ debugC(1, kDebugLocation, "endIntro(): done showing credits");
+
+ if ((getFeatures() & GF_DEMO) == 0) {
+ _gfx->displayCenteredString(80, "CLICK MOUSE BUTTON TO START");
+ _gfx->updateScreen();
+
+ waitUntilLeftClick();
+
+ _engineFlags &= ~kEngineBlockInput;
+ _menu->selectCharacter();
+ } else {
+ waitUntilLeftClick();
+ }
+
+ return;
+}
+
+void Parallaction_ns::_c_moveSheet(void *parm) {
+
+ static uint16 x = 319;
+
+ if (x > 66)
+ x -= 16;
+
+ Common::Rect r;
+
+ r.left = x;
+ r.top = 47;
+ r.right = (x + 32 > 319) ? 319 : (x + 32);
+ r.bottom = 199;
+ _gfx->floodFill(Gfx::kBitBack, r, 1);
+ _gfx->floodFill(Gfx::kBit2, r, 1);
+
+ if (x >= 104) return;
+
+ r.left = x+215;
+ r.top = 47;
+ r.right = (x + 247 > 319) ? 319 : (x + 247);
+ r.bottom = 199;
+ _gfx->floodFill(Gfx::kBitBack, r, 12);
+ _gfx->floodFill(Gfx::kBit2, r, 12);
+
+ return;
+}
+
+void plotPixel(int x, int y, int color, void *data) {
+ _vm->_gfx->plotMaskPixel(x, y, color);
+}
+
+void Parallaction_ns::_c_sketch(void *parm) {
+
+ static uint16 index = 1;
+
+ uint16 newy = _rightHandPositions[2*index+1];
+ uint16 newx = _rightHandPositions[2*index];
+
+ uint16 oldy = _rightHandPositions[2*(index-1)+1];
+ uint16 oldx = _rightHandPositions[2*(index-1)];
+
+ Graphics::drawLine(oldx, oldy, newx, newy, 0, plotPixel, NULL);
+
+ _rightHandAnim->_left = newx;
+ _rightHandAnim->_top = newy - 20;
+
+ index++;
+
+ return;
+}
+
+
+
+
+void Parallaction_ns::_c_shade(void *parm) {
+
+ Common::Rect r(
+ _rightHandAnim->_left - 36,
+ _rightHandAnim->_top - 36,
+ _rightHandAnim->_left,
+ _rightHandAnim->_top
+ );
+
+ _gfx->fillMaskRect(r, 0);
+
+ return;
+
+}
+
+void Parallaction_ns::_c_projector(void*) {
+#ifdef HALFBRITE
+ static int dword_16032 = 0;
+
+// Bitmap bm;
+// InitBitMap(&bm);
+
+ if (dword_16032 != 0) {
+/* // keep drawing spotlight in its final place
+ _gfx->flatBlitCnv(&scnv, 110, 25, Gfx::kBitFront);
+ BltBitMap(&bm, 0, 0, &_screen._bitMap, 110, 25, a3->??, a3->??, 0x20, 0x20);
+*/ return;
+ }
+
+ _gfx->setHalfbriteMode(true);
+/*
+ // move spot light around the stage
+ int d7, d6;
+ for (d7 = 0; d7 < 150; d7++) {
+
+ if (d7 < 100) {
+ int d1 = d7;
+ if (d1 < 0)
+ d1++;
+
+ d1 >>= 1;
+ d6 = 50 - d1;
+ } else {
+ int d1 = d7 / 100;
+ if (d1 < 0)
+ d1++;
+
+ d1 >>= 1;
+ d6 = d1;
+ }
+
+ BltBitMap(&bm, 0, 0, &_screen._bitMap, d7+20, d6, a3->??, a3->??, 0x20, 0x20);
+ sub_1590C(d6 + a3->??);
+ BltBitMap(&bm, 0, 0, &_screen._bitMap, d7+20, d6, a3->??, a3->??, 0xFA, 0x20);
+ }
+
+ for (d7 = 50; d7 > -10; d7--) {
+ BltBitMap(&bm, 0, 0, &_screen._bitMap, d7+120, d6, a3->??, a3->??, 0x20, 0x20);
+ sub_1590C(d6 + a3->??);
+ BltBitMap(&bm, 0, 0, &_screen._bitMap, d7+120, d6, a3->??, a3->??, 0xFA, 0x20);
+ }
+
+ BltBitMap(&bm, 0, 0, &_screen._bitMap, d7+120, d6, a3->??, a3->??, 0x20, 0x20);
+ _gfx->flatBlitCnv(&scnv, d7+120, d6, Gfx::kBitFront);
+*/
+
+ dword_16032 = 1;
+ return;
+#endif
+}
+
+void Parallaction_ns::_c_HBOff(void*) {
+#ifdef HALFBRITE
+ _gfx->setHalfbriteMode(false);
+#endif
+}
+
+void Parallaction_ns::_c_HBOn(void*) {
+#ifdef HALFBRITE
+ _gfx->setHalfbriteMode(true);
+#endif
+}
+
+
+} // namespace Parallaction
diff --git a/engines/parallaction/commands.cpp b/engines/parallaction/commands.cpp
index 15acdd2d86..dc392fde2c 100644
--- a/engines/parallaction/commands.cpp
+++ b/engines/parallaction/commands.cpp
@@ -274,6 +274,9 @@ void Parallaction::runCommands(CommandList& list, Zone *z) {
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
@@ -302,7 +305,7 @@ void Parallaction::runCommands(CommandList& list, Zone *z) {
break;
case CMD_CALL: // call
- _callables[u->_callable](z);
+ callFunction(u->_callable, z);
break;
case CMD_QUIT: // quit
@@ -314,7 +317,7 @@ void Parallaction::runCommands(CommandList& list, Zone *z) {
continue;
}
- WalkNodeList *vC = _vm->_char._builder.buildPath(u->_move._x, u->_move._y);
+ WalkNodeList *vC = _char._builder.buildPath(u->_move._x, u->_move._y);
addJob(&jobWalk, vC, kPriority19 );
_engineFlags |= kEngineWalking;
diff --git a/engines/parallaction/detection.cpp b/engines/parallaction/detection.cpp
index 8e069c5f08..84c45584a4 100644
--- a/engines/parallaction/detection.cpp
+++ b/engines/parallaction/detection.cpp
@@ -27,6 +27,7 @@
#include "base/plugins.h"
+#include "common/config-manager.h"
#include "common/advancedDetector.h"
#include "parallaction/parallaction.h"
@@ -47,8 +48,8 @@ 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}
};
@@ -140,6 +141,24 @@ static const PARALLACTIONGameDescription gameDescriptions[] = {
GF_LANG_IT,
},
+ {
+ {
+ "bra",
+ "Multi-lingual",
+ {
+ {"tbra.bmp", 0, "3174c095a0e1a4eaf05c403445711e9b", 80972 },
+ {"russia.fnt", 0, "57f85ff62aeca6334fdcaf718e313b49", 18344 },
+ {NULL, 0, NULL, 0 }
+ },
+ Common::UNK_LANG,
+ Common::kPlatformPC,
+ Common::ADGF_NO_FLAGS
+ },
+ GType_BRA,
+ GF_LANG_EN | GF_LANG_FR | GF_LANG_DE | GF_LANG_IT | GF_LANG_MULT
+ },
+
+
{ AD_TABLE_END_MARKER, 0, 0 }
};
@@ -157,7 +176,7 @@ static const Common::ADParams detectionParams = {
// Structure for autoupgrading obsolete targets
0,
// Name of single gameid (optional)
- "parallaction",
+ 0,
// List of files for file-based fallback detection (optional)
0,
// Fallback callback
@@ -166,7 +185,32 @@ static const Common::ADParams detectionParams = {
Common::kADFlagAugmentPreferredTarget
};
-ADVANCED_DETECTOR_DEFINE_PLUGIN(PARALLACTION, Parallaction::Parallaction, detectionParams);
+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();
+
+ if (!scumm_stricmp("nippon", gameid)) {
+ *engine = new Parallaction::Parallaction_ns(syst);
+ } else
+ if (!scumm_stricmp("bra", gameid)) {
+ *engine = new Parallaction::Parallaction_br(syst);
+ } else
+ error("Parallaction engine created with invalid gameid ('%s')", gameid);
+
+ return kNoError;
+}
REGISTER_PLUGIN(PARALLACTION, "Parallaction engine", "Nippon Safes Inc. (C) Dynabyte");
diff --git a/engines/parallaction/dialogue.cpp b/engines/parallaction/dialogue.cpp
index 7d2224164a..84ecde6e64 100644
--- a/engines/parallaction/dialogue.cpp
+++ b/engines/parallaction/dialogue.cpp
@@ -236,11 +236,12 @@ uint16 DialogueManager::askPassword() {
debugC(1, kDebugDialogue, "checkDialoguePassword()");
char password[100];
- uint16 passwordLen = 0;
+ uint16 passwordLen;
while (true) {
clear();
+ passwordLen = 0;
strcpy(password, ".......");
Common::Rect r(_answerBalloonW[0], _answerBalloonH[0]);
@@ -491,13 +492,12 @@ void Parallaction::runDialogue(SpeakData *data) {
_gfx->setFont(kFontDialogue);
- if (_vm->getPlatform() == Common::kPlatformPC)
+ if (getPlatform() == Common::kPlatformPC)
showCursor(false);
DialogueManager man(this, data);
man.run();
- refreshInventory(_characterName);
showCursor(true);
return;
diff --git a/engines/parallaction/disk.h b/engines/parallaction/disk.h
index 14ea4f0e16..ae572b1122 100644
--- a/engines/parallaction/disk.h
+++ b/engines/parallaction/disk.h
@@ -29,19 +29,8 @@
#include "parallaction/defs.h"
#include "common/file.h"
-namespace Audio {
- class AudioStream;
-}
-
namespace Parallaction {
-//------------------------------------------------------
-// ARCHIVE MANAGEMENT
-//------------------------------------------------------
-
-
-#define MAX_ARCHIVE_ENTRIES 384
-
class Table;
class Parallaction;
class Gfx;
@@ -51,22 +40,49 @@ class Font;
struct Cnv;
struct StaticCnv;
+
+class Disk {
+
+public:
+ Disk() { }
+ virtual ~Disk() { }
+
+ virtual Common::String selectArchive(const Common::String &name) = 0;
+ virtual void setLanguage(uint16 language) = 0;
+
+ 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 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 Table* loadTable(const char* name) = 0;
+ virtual Common::SeekableReadStream* loadMusic(const char* name) = 0;
+ virtual Common::ReadStream* loadSound(const char* name) = 0;
+};
+
+
+
+
+#define MAX_ARCHIVE_ENTRIES 384
+
class Archive : public Common::SeekableReadStream {
protected:
-
bool _file;
uint32 _fileOffset;
uint32 _fileCursor;
uint32 _fileEndOffset;
-
Common::String _archiveName;
char _archiveDir[MAX_ARCHIVE_ENTRIES][32];
uint32 _archiveLenghts[MAX_ARCHIVE_ENTRIES];
uint32 _archiveOffsets[MAX_ARCHIVE_ENTRIES];
-
Common::File _archive;
-
uint32 _numFiles;
protected:
@@ -77,21 +93,17 @@ public:
void open(const char* file);
void close();
-
Common::String name() const;
-
bool openArchivedFile(const char *name);
void closeArchivedFile();
-
uint32 size() const;
uint32 pos() const;
bool eos() const;
void seek(int32 offs, int whence = SEEK_SET);
-
uint32 read(void *dataPtr, uint32 dataSize);
};
-class Disk {
+class Disk_ns : public Disk {
protected:
Archive _resArchive;
@@ -103,29 +115,14 @@ protected:
void errorFileNotFound(const char *s);
public:
- Disk(Parallaction *vm);
- virtual ~Disk();
+ Disk_ns(Parallaction *vm);
+ virtual ~Disk_ns();
Common::String selectArchive(const Common::String &name);
void setLanguage(uint16 language);
-
- 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 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 Table* loadTable(const char* name) = 0;
- virtual Common::ReadStream* loadMusic(const char* name) = 0;
- virtual Common::ReadStream* loadSound(const char* name) = 0;
};
-class DosDisk : public Disk {
+class DosDisk_ns : public Disk_ns {
private:
void unpackBackground(Common::ReadStream *stream, byte *screen, byte *mask, byte *path);
@@ -142,8 +139,8 @@ protected:
Gfx *_gfx;
public:
- DosDisk(Parallaction *vm);
- virtual ~DosDisk();
+ DosDisk_ns(Parallaction *vm);
+ virtual ~DosDisk_ns();
Script* loadLocation(const char *name);
Script* loadScript(const char* name);
@@ -157,11 +154,11 @@ public:
void loadSlide(const char *filename);
void loadScenery(const char* background, const char* mask);
Table* loadTable(const char* name);
- Common::ReadStream* loadMusic(const char* name);
+ Common::SeekableReadStream* loadMusic(const char* name);
Common::ReadStream* loadSound(const char* name);
};
-class AmigaDisk : public Disk {
+class AmigaDisk_ns : public Disk_ns {
protected:
Cnv* makeCnv(Common::SeekableReadStream &stream);
@@ -176,8 +173,8 @@ protected:
void loadBackground(const char *name);
public:
- AmigaDisk(Parallaction *vm);
- virtual ~AmigaDisk();
+ AmigaDisk_ns(Parallaction *vm);
+ virtual ~AmigaDisk_ns();
Script* loadLocation(const char *name);
Script* loadScript(const char* name);
@@ -191,10 +188,45 @@ public:
void loadSlide(const char *filename);
void loadScenery(const char* background, const char* mask);
Table* loadTable(const char* name);
- Common::ReadStream* loadMusic(const char* name);
+ Common::SeekableReadStream* loadMusic(const char* name);
Common::ReadStream* loadSound(const char* name);
};
+
+// for the moment DosDisk_br subclasses Disk. When Amiga support will
+// be taken into consideration, it might be useful to add another level
+// like we did for Nippon Safes.
+class DosDisk_br : public Disk {
+
+protected:
+ Parallaction *_vm;
+
+protected:
+ void errorFileNotFound(const char *s);
+
+public:
+ DosDisk_br(Parallaction *vm);
+ virtual ~DosDisk_br();
+
+ Common::String selectArchive(const Common::String &name);
+ 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);
+ 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);
+ Table* loadTable(const char* name);
+ Common::SeekableReadStream* loadMusic(const char* name);
+ Common::ReadStream* loadSound(const char* name);
+};
+
+
} // namespace Parallaction
diff --git a/engines/parallaction/disk_br.cpp b/engines/parallaction/disk_br.cpp
new file mode 100644
index 0000000000..452b74be51
--- /dev/null
+++ b/engines/parallaction/disk_br.cpp
@@ -0,0 +1,134 @@
+/* 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 {
+
+
+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 "";
+}
+
+void DosDisk_br::setLanguage(uint16 language) {
+ debugC(5, kDebugDisk, "DosDisk_br::setLanguage");
+
+ return;
+}
+
+DosDisk_br::DosDisk_br(Parallaction* vm) : _vm(vm) {
+
+}
+
+DosDisk_br::~DosDisk_br() {
+}
+
+Cnv* DosDisk_br::loadTalk(const char *name) {
+ debugC(5, kDebugDisk, "DosDisk_br::loadTalk");
+
+ return 0;
+}
+
+Script* DosDisk_br::loadLocation(const char *name) {
+ debugC(5, kDebugDisk, "DosDisk_br::loadLocation");
+ return 0;
+}
+
+Script* DosDisk_br::loadScript(const char* name) {
+ debugC(5, kDebugDisk, "DosDisk_br::loadScript");
+ return 0;
+}
+
+// there are no Head resources in Big Red Adventure
+StaticCnv* DosDisk_br::loadHead(const char* name) {
+ debugC(5, kDebugDisk, "DosDisk_br::loadHead");
+ return 0;
+}
+
+
+StaticCnv* DosDisk_br::loadPointer() {
+ debugC(5, kDebugDisk, "DosDisk_br::loadPointer");
+ return 0;
+}
+
+
+Font* DosDisk_br::loadFont(const char* name) {
+ debugC(5, kDebugDisk, "DosDisk_br::loadFont");
+ return 0;
+}
+
+
+Cnv* DosDisk_br::loadObjects(const char *name) {
+ debugC(5, kDebugDisk, "DosDisk_br::loadObjects");
+ return 0;
+}
+
+
+StaticCnv* DosDisk_br::loadStatic(const char* name) {
+ debugC(5, kDebugDisk, "DosDisk_br::loadStatic");
+ return 0;
+}
+
+Cnv* DosDisk_br::loadFrames(const char* name) {
+ debugC(5, kDebugDisk, "DosDisk_br::loadFrames");
+ return 0;
+}
+
+// there are no Slide resources in Big Red Adventure
+void DosDisk_br::loadSlide(const char *filename) {
+ debugC(5, kDebugDisk, "DosDisk_br::loadSlide");
+ return;
+}
+
+void DosDisk_br::loadScenery(const char *name, const char *mask) {
+ debugC(5, kDebugDisk, "DosDisk_br::loadScenery");
+ return;
+}
+
+Table* DosDisk_br::loadTable(const char* name) {
+ debugC(5, kDebugDisk, "DosDisk_br::loadTable");
+ return 0;
+}
+
+Common::SeekableReadStream* DosDisk_br::loadMusic(const char* name) {
+ debugC(5, kDebugDisk, "DosDisk_br::loadMusic");
+ return 0;
+}
+
+
+Common::ReadStream* DosDisk_br::loadSound(const char* name) {
+ debugC(5, kDebugDisk, "DosDisk_br::loadSound");
+ return 0;
+}
+
+
+} // namespace Parallaction
diff --git a/engines/parallaction/disk.cpp b/engines/parallaction/disk_ns.cpp
index 2e6d9e4820..c0bb2691ef 100644
--- a/engines/parallaction/disk.cpp
+++ b/engines/parallaction/disk_ns.cpp
@@ -32,11 +32,188 @@
namespace Audio {
+ class AudioStream;
+
AudioStream *make8SVXStream(Common::ReadStream &input);
}
namespace Parallaction {
+
+// HACK: Several archives ('de', 'en', 'fr' and 'disk0') in the multi-lingual
+// Amiga version of Nippon Safes, and one archive ('fr') in the Amiga Demo of
+// Nippon Safes used different internal offsets than all the other archives.
+//
+// When an archive is opened in the Amiga demo, its size is checked against
+// SIZEOF_SMALL_ARCHIVE to detect when the smaller archive is used.
+//
+// When an archive is opened in Amiga multi-lingual version, the header is
+// checked again NDOS to detect when a smaller archive is used.
+//
+#define SIZEOF_SMALL_ARCHIVE 12778
+
+#define ARCHIVE_FILENAMES_OFS 0x16
+
+#define NORMAL_ARCHIVE_FILES_NUM 384
+#define SMALL_ARCHIVE_FILES_NUM 180
+
+#define NORMAL_ARCHIVE_SIZES_OFS 0x3016
+#define SMALL_ARCHIVE_SIZES_OFS 0x1696
+
+#define NORMAL_ARCHIVE_DATA_OFS 0x4000
+#define SMALL_ARCHIVE_DATA_OFS 0x1966
+
+Archive::Archive() {
+ resetArchivedFile();
+}
+
+void Archive::open(const char *file) {
+ debugC(1, kDebugDisk, "Archive::open(%s)", file);
+
+ if (_archive.isOpen())
+ close();
+
+ char path[PATH_LEN];
+
+ strcpy(path, file);
+ if (!_archive.open(path))
+ error("archive '%s' not found", path);
+
+ _archiveName = file;
+
+ bool isSmallArchive = false;
+ if (_vm->getPlatform() == Common::kPlatformAmiga) {
+ if (_vm->getFeatures() & GF_DEMO) {
+ isSmallArchive = _archive.size() == SIZEOF_SMALL_ARCHIVE;
+ } else if (_vm->getFeatures() & GF_LANG_MULT) {
+ isSmallArchive = (_archive.readUint32BE() != MKID_BE('NDOS'));
+ }
+ }
+
+ _numFiles = (isSmallArchive) ? SMALL_ARCHIVE_FILES_NUM : NORMAL_ARCHIVE_FILES_NUM;
+
+ _archive.seek(ARCHIVE_FILENAMES_OFS);
+ _archive.read(_archiveDir, _numFiles*32);
+
+ _archive.seek((isSmallArchive) ? SMALL_ARCHIVE_SIZES_OFS : NORMAL_ARCHIVE_SIZES_OFS);
+
+ uint32 dataOffset = (isSmallArchive) ? SMALL_ARCHIVE_DATA_OFS : NORMAL_ARCHIVE_DATA_OFS;
+ for (uint16 i = 0; i < _numFiles; i++) {
+ _archiveOffsets[i] = dataOffset;
+ _archiveLenghts[i] = _archive.readUint32BE();
+ dataOffset += _archiveLenghts[i];
+ }
+
+ return;
+}
+
+
+void Archive::close() {
+ if (!_archive.isOpen()) return;
+
+ resetArchivedFile();
+
+ _archive.close();
+ _archiveName.clear();
+}
+
+Common::String Archive::name() const {
+ return _archiveName;
+}
+
+bool Archive::openArchivedFile(const char *filename) {
+ debugC(3, kDebugDisk, "Archive::openArchivedFile(%s)", filename);
+
+ resetArchivedFile();
+
+ debugC(3, kDebugDisk, "Archive::openArchivedFile(%s)", filename);
+
+ if (!_archive.isOpen())
+ error("Archive::openArchivedFile: the archive is not open");
+
+ uint16 i = 0;
+ for ( ; i < _numFiles; i++) {
+ if (!scumm_stricmp(_archiveDir[i], filename)) break;
+ }
+ if (i == _numFiles) return false;
+
+ debugC(9, kDebugDisk, "Archive::openArchivedFile: '%s' found in slot %i", filename, i);
+
+ _file = true;
+
+ _fileOffset = _archiveOffsets[i];
+ _fileCursor = _archiveOffsets[i];
+ _fileEndOffset = _archiveOffsets[i] + _archiveLenghts[i];
+
+ _archive.seek(_fileOffset);
+
+ return true;
+}
+
+void Archive::resetArchivedFile() {
+ _file = false;
+ _fileCursor = 0;
+ _fileOffset = 0;
+ _fileEndOffset = 0;
+}
+
+void Archive::closeArchivedFile() {
+ resetArchivedFile();
+}
+
+
+uint32 Archive::size() const {
+ return (_file == true ? _fileEndOffset - _fileOffset : 0);
+}
+
+uint32 Archive::pos() const {
+ return (_file == true ? _fileCursor - _fileOffset : 0 );
+}
+
+bool Archive::eos() const {
+ return (_file == true ? _fileCursor == _fileEndOffset : true );
+}
+
+void Archive::seek(int32 offs, int whence) {
+ assert(_file == true && _fileCursor <= _fileEndOffset);
+
+ switch (whence) {
+ case SEEK_CUR:
+ _fileCursor += offs;
+ break;
+ case SEEK_SET:
+ _fileCursor = _fileOffset + offs;
+ break;
+ case SEEK_END:
+ _fileCursor = _fileEndOffset - offs;
+ break;
+ }
+ assert(_fileCursor <= _fileEndOffset && _fileCursor >= _fileOffset);
+
+ _archive.seek(_fileCursor, SEEK_SET);
+}
+
+uint32 Archive::read(void *dataPtr, uint32 dataSize) {
+// printf("read(%i, %i)\n", file->_cursor, file->_endOffset);
+ if (_file == false)
+ error("Archive::read: no archived file is currently open");
+
+ if (_fileCursor >= _fileEndOffset)
+ error("can't read beyond end of archived file");
+
+ if (_fileEndOffset - _fileCursor < dataSize)
+ dataSize = _fileEndOffset - _fileCursor;
+
+ int32 readBytes = _archive.read(dataPtr, dataSize);
+ _fileCursor += readBytes;
+
+ return readBytes;
+}
+
+
+
+
+
/*
This stream class is just a wrapper around Archive, so
deallocation is not a problem. In fact, this class doesn't
@@ -79,26 +256,26 @@ public:
-Disk::Disk(Parallaction *vm) : _vm(vm) {
-
+void Disk_ns::errorFileNotFound(const char *s) {
+ error("File '%s' not found", s);
}
-Disk::~Disk() {
+Disk_ns::Disk_ns(Parallaction *vm) : _vm(vm) {
}
-void Disk::errorFileNotFound(const char *s) {
- error("File '%s' not found", s);
+Disk_ns::~Disk_ns() {
+
}
-Common::String Disk::selectArchive(const Common::String& name) {
+Common::String Disk_ns::selectArchive(const Common::String& name) {
Common::String oldName = _resArchive.name();
_resArchive.open(name.c_str());
return oldName;
}
-void Disk::setLanguage(uint16 language) {
+void Disk_ns::setLanguage(uint16 language) {
debugC(1, kDebugDisk, "setLanguage(%i)", language);
switch (language) {
@@ -134,18 +311,18 @@ void Disk::setLanguage(uint16 language) {
-DosDisk::DosDisk(Parallaction* vm) : Disk(vm) {
+DosDisk_ns::DosDisk_ns(Parallaction* vm) : Disk_ns(vm) {
}
-DosDisk::~DosDisk() {
+DosDisk_ns::~DosDisk_ns() {
}
//
// loads a cnv from an external file
//
-Cnv* DosDisk::loadExternalCnv(const char *filename) {
+Cnv* DosDisk_ns::loadExternalCnv(const char *filename) {
// printf("Gfx::loadExternalCnv(%s)...", filename);
char path[PATH_LEN];
@@ -168,7 +345,7 @@ Cnv* DosDisk::loadExternalCnv(const char *filename) {
return new Cnv(numFrames, width, height, data);
}
-StaticCnv *DosDisk::loadExternalStaticCnv(const char *filename) {
+StaticCnv *DosDisk_ns::loadExternalStaticCnv(const char *filename) {
char path[PATH_LEN];
@@ -193,7 +370,7 @@ StaticCnv *DosDisk::loadExternalStaticCnv(const char *filename) {
return cnv;
}
-Cnv* DosDisk::loadCnv(const char *filename) {
+Cnv* DosDisk_ns::loadCnv(const char *filename) {
// printf("Gfx::loadCnv(%s)\n", filename);
char path[PATH_LEN];
@@ -218,7 +395,7 @@ Cnv* DosDisk::loadCnv(const char *filename) {
return new Cnv(numFrames, width, height, data);
}
-Cnv* DosDisk::loadTalk(const char *name) {
+Cnv* DosDisk_ns::loadTalk(const char *name) {
const char *ext = strstr(name, ".talk");
if (ext != NULL) {
@@ -243,7 +420,7 @@ Cnv* DosDisk::loadTalk(const char *name) {
return loadExternalCnv(v20);
}
-Script* DosDisk::loadLocation(const char *name) {
+Script* DosDisk_ns::loadLocation(const char *name) {
char archivefile[PATH_LEN];
@@ -260,11 +437,11 @@ Script* DosDisk::loadLocation(const char *name) {
strcat(archivefile, name);
strcat(archivefile, ".loc");
- debugC(3, kDebugDisk, "DosDisk::loadLocation(%s): trying '%s'", name, archivefile);
+ debugC(3, kDebugDisk, "DosDisk_ns::loadLocation(%s): trying '%s'", name, archivefile);
if (!_locArchive.openArchivedFile(archivefile)) {
sprintf(archivefile, "%s%s.loc", _languageDir, name);
- debugC(3, kDebugDisk, "DosDisk::loadLocation(%s): trying '%s'", name, archivefile);
+ debugC(3, kDebugDisk, "DosDisk_ns::loadLocation(%s): trying '%s'", name, archivefile);
if (!_locArchive.openArchivedFile(archivefile))
errorFileNotFound(name);
@@ -273,7 +450,7 @@ Script* DosDisk::loadLocation(const char *name) {
return new Script(new DummyArchiveStream(_locArchive), true);
}
-Script* DosDisk::loadScript(const char* name) {
+Script* DosDisk_ns::loadScript(const char* name) {
char vC8[PATH_LEN];
@@ -285,7 +462,7 @@ Script* DosDisk::loadScript(const char* name) {
return new Script(new DummyArchiveStream(_resArchive), true);
}
-StaticCnv* DosDisk::loadHead(const char* name) {
+StaticCnv* DosDisk_ns::loadHead(const char* name) {
char path[PATH_LEN];
@@ -300,19 +477,19 @@ StaticCnv* DosDisk::loadHead(const char* name) {
}
-StaticCnv* DosDisk::loadPointer() {
+StaticCnv* DosDisk_ns::loadPointer() {
return loadExternalStaticCnv("pointer");
}
-Font* DosDisk::loadFont(const char* name) {
+Font* DosDisk_ns::loadFont(const char* name) {
char path[PATH_LEN];
sprintf(path, "%scnv", name);
return createFont(name, loadExternalCnv(path));
}
-Cnv* DosDisk::loadObjects(const char *name) {
+Cnv* DosDisk_ns::loadObjects(const char *name) {
if (IS_MINI_CHARACTER(name)) {
name += 4;
@@ -324,7 +501,7 @@ Cnv* DosDisk::loadObjects(const char *name) {
}
-StaticCnv* DosDisk::loadStatic(const char* name) {
+StaticCnv* DosDisk_ns::loadStatic(const char* name) {
char path[PATH_LEN];
@@ -350,7 +527,7 @@ StaticCnv* DosDisk::loadStatic(const char* name) {
return cnv;
}
-Cnv* DosDisk::loadFrames(const char* name) {
+Cnv* DosDisk_ns::loadFrames(const char* name) {
return loadCnv(name);
}
@@ -362,7 +539,7 @@ Cnv* DosDisk::loadFrames(const char* name) {
// * mask data [bits 6-7] (z buffer)
// * path data [bit 8] (walkable areas)
//
-void DosDisk::unpackBackground(Common::ReadStream *stream, byte *screen, byte *mask, byte *path) {
+void DosDisk_ns::unpackBackground(Common::ReadStream *stream, byte *screen, byte *mask, byte *path) {
byte b;
uint32 i = 0;
@@ -380,7 +557,7 @@ void DosDisk::unpackBackground(Common::ReadStream *stream, byte *screen, byte *m
}
-void DosDisk::parseDepths(Common::SeekableReadStream &stream) {
+void DosDisk_ns::parseDepths(Common::SeekableReadStream &stream) {
_vm->_gfx->_bgLayers[0] = stream.readByte();
_vm->_gfx->_bgLayers[1] = stream.readByte();
_vm->_gfx->_bgLayers[2] = stream.readByte();
@@ -388,7 +565,7 @@ void DosDisk::parseDepths(Common::SeekableReadStream &stream) {
}
-void DosDisk::parseBackground(Common::SeekableReadStream &stream) {
+void DosDisk_ns::parseBackground(Common::SeekableReadStream &stream) {
stream.read(_vm->_gfx->_palette, BASE_PALETTE_SIZE);
_vm->_gfx->setPalette(_vm->_gfx->_palette);
@@ -405,16 +582,16 @@ void DosDisk::parseBackground(Common::SeekableReadStream &stream) {
}
-void DosDisk::loadBackground(const char *filename) {
+void DosDisk_ns::loadBackground(const char *filename) {
if (!_resArchive.openArchivedFile(filename))
errorFileNotFound(filename);
parseBackground(_resArchive);
- byte *bg = (byte*)calloc(1, SCREEN_WIDTH*SCREEN_HEIGHT);
- byte *mask = (byte*)calloc(1, SCREENMASK_WIDTH*SCREEN_HEIGHT);
- byte *path = (byte*)calloc(1, SCREENPATH_WIDTH*SCREEN_HEIGHT);
+ byte *bg = (byte*)calloc(1, _vm->_screenSize);
+ byte *mask = (byte*)calloc(1, _vm->_screenMaskSize);
+ byte *path = (byte*)calloc(1, _vm->_screenPathSize);
Graphics::PackBitsReadStream stream(_resArchive);
@@ -437,20 +614,20 @@ void DosDisk::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::loadMaskAndPath(const char *name) {
+void DosDisk_ns::loadMaskAndPath(const char *name) {
char path[PATH_LEN];
sprintf(path, "%s.msk", name);
if (!_resArchive.openArchivedFile(path))
errorFileNotFound(name);
- byte *maskBuf = (byte*)calloc(1, SCREENMASK_WIDTH*SCREEN_HEIGHT);
- byte *pathBuf = (byte*)calloc(1, SCREENPATH_WIDTH*SCREEN_HEIGHT);
+ byte *maskBuf = (byte*)calloc(1, _vm->_screenMaskSize);
+ byte *pathBuf = (byte*)calloc(1, _vm->_screenPathSize);
parseDepths(_resArchive);
- _resArchive.read(pathBuf, SCREENPATH_WIDTH*SCREEN_HEIGHT);
- _resArchive.read(maskBuf, SCREENMASK_WIDTH*SCREEN_HEIGHT);
+ _resArchive.read(pathBuf, _vm->_screenPathSize);
+ _resArchive.read(maskBuf, _vm->_screenMaskSize);
_vm->_gfx->setMask(maskBuf);
_vm->setPath(pathBuf);
@@ -458,13 +635,13 @@ void DosDisk::loadMaskAndPath(const char *name) {
return;
}
-void DosDisk::loadSlide(const char *filename) {
+void DosDisk_ns::loadSlide(const char *filename) {
char path[PATH_LEN];
sprintf(path, "%s.slide", filename);
loadBackground(path);
}
-void DosDisk::loadScenery(const char *name, const char *mask) {
+void DosDisk_ns::loadScenery(const char *name, const char *mask) {
char path[PATH_LEN];
sprintf(path, "%s.dyn", name);
loadBackground(path);
@@ -476,7 +653,7 @@ void DosDisk::loadScenery(const char *name, const char *mask) {
}
-Table* DosDisk::loadTable(const char* name) {
+Table* DosDisk_ns::loadTable(const char* name) {
char path[PATH_LEN];
sprintf(path, "%s.tab", name);
@@ -497,7 +674,7 @@ Table* DosDisk::loadTable(const char* name) {
return t;
}
-Common::ReadStream* DosDisk::loadMusic(const char* name) {
+Common::SeekableReadStream* DosDisk_ns::loadMusic(const char* name) {
char path[PATH_LEN];
sprintf(path, "%s.mid", name);
@@ -509,7 +686,7 @@ Common::ReadStream* DosDisk::loadMusic(const char* name) {
}
-Common::ReadStream* DosDisk::loadSound(const char* name) {
+Common::ReadStream* DosDisk_ns::loadSound(const char* name) {
return NULL;
}
@@ -684,12 +861,12 @@ public:
-AmigaDisk::AmigaDisk(Parallaction *vm) : Disk(vm) {
+AmigaDisk_ns::AmigaDisk_ns(Parallaction *vm) : Disk_ns(vm) {
}
-AmigaDisk::~AmigaDisk() {
+AmigaDisk_ns::~AmigaDisk_ns() {
}
@@ -699,7 +876,7 @@ AmigaDisk::~AmigaDisk() {
unpackFrame transforms images from 5-bitplanes format to
8-bit color-index mode
*/
-void AmigaDisk::unpackFrame(byte *dst, byte *src, uint16 planeSize) {
+void AmigaDisk_ns::unpackFrame(byte *dst, byte *src, uint16 planeSize) {
byte s0, s1, s2, s3, s4, mask, t0, t1, t2, t3, t4;
@@ -727,7 +904,7 @@ void AmigaDisk::unpackFrame(byte *dst, byte *src, uint16 planeSize) {
/*
patchFrame applies DLTA data (dlta) to specified buffer (dst)
*/
-void AmigaDisk::patchFrame(byte *dst, byte *dlta, uint16 bytesPerPlane, uint16 height) {
+void AmigaDisk_ns::patchFrame(byte *dst, byte *dlta, uint16 bytesPerPlane, uint16 height) {
uint32 *dataIndex = (uint32*)dlta;
uint32 *ofslenIndex = (uint32*)dlta + 8;
@@ -763,7 +940,7 @@ void AmigaDisk::patchFrame(byte *dst, byte *dlta, uint16 bytesPerPlane, uint16 h
}
// FIXME: no mask is loaded
-void AmigaDisk::unpackBitmap(byte *dst, byte *src, uint16 numFrames, uint16 bytesPerPlane, uint16 height) {
+void AmigaDisk_ns::unpackBitmap(byte *dst, byte *src, uint16 numFrames, uint16 bytesPerPlane, uint16 height) {
byte *baseFrame = src;
byte *tempBuffer = 0;
@@ -797,7 +974,7 @@ void AmigaDisk::unpackBitmap(byte *dst, byte *src, uint16 numFrames, uint16 byte
}
-StaticCnv* AmigaDisk::makeStaticCnv(Common::SeekableReadStream &stream) {
+StaticCnv* AmigaDisk_ns::makeStaticCnv(Common::SeekableReadStream &stream) {
stream.skip(1);
uint16 width = stream.readByte();
@@ -827,7 +1004,7 @@ StaticCnv* AmigaDisk::makeStaticCnv(Common::SeekableReadStream &stream) {
return cnv;
}
-Cnv* AmigaDisk::makeCnv(Common::SeekableReadStream &stream) {
+Cnv* AmigaDisk_ns::makeCnv(Common::SeekableReadStream &stream) {
uint16 numFrames = stream.readByte();
uint16 width = stream.readByte();
@@ -852,8 +1029,8 @@ Cnv* AmigaDisk::makeCnv(Common::SeekableReadStream &stream) {
}
#undef NUM_PLANES
-Script* AmigaDisk::loadLocation(const char *name) {
- debugC(1, kDebugDisk, "AmigaDisk()::loadLocation '%s'", name);
+Script* AmigaDisk_ns::loadLocation(const char *name) {
+ debugC(1, kDebugDisk, "AmigaDisk_ns()::loadLocation '%s'", name);
char path[PATH_LEN];
if (IS_MINI_CHARACTER(_vm->_characterName)) {
@@ -873,8 +1050,8 @@ Script* AmigaDisk::loadLocation(const char *name) {
return new Script(new PowerPackerStream(_locArchive), true);
}
-Script* AmigaDisk::loadScript(const char* name) {
- debugC(1, kDebugDisk, "AmigaDisk::loadScript '%s'", name);
+Script* AmigaDisk_ns::loadScript(const char* name) {
+ debugC(1, kDebugDisk, "AmigaDisk_ns::loadScript '%s'", name);
char vC8[PATH_LEN];
@@ -886,8 +1063,8 @@ Script* AmigaDisk::loadScript(const char* name) {
return new Script(new DummyArchiveStream(_resArchive), true);
}
-StaticCnv* AmigaDisk::loadPointer() {
- debugC(1, kDebugDisk, "AmigaDisk::loadPointer");
+StaticCnv* AmigaDisk_ns::loadPointer() {
+ debugC(1, kDebugDisk, "AmigaDisk_ns::loadPointer");
Common::File stream;
if (!stream.open("pointer"))
@@ -896,8 +1073,8 @@ StaticCnv* AmigaDisk::loadPointer() {
return makeStaticCnv(stream);
}
-StaticCnv* AmigaDisk::loadStatic(const char* name) {
- debugC(1, kDebugDisk, "AmigaDisk::loadStatic '%s'", name);
+StaticCnv* AmigaDisk_ns::loadStatic(const char* name) {
+ debugC(1, kDebugDisk, "AmigaDisk_ns::loadStatic '%s'", name);
Common::SeekableReadStream *s = openArchivedFile(name, true);
StaticCnv *cnv = makeStaticCnv(*s);
@@ -907,8 +1084,8 @@ StaticCnv* AmigaDisk::loadStatic(const char* name) {
return cnv;
}
-Common::SeekableReadStream *AmigaDisk::openArchivedFile(const char* name, bool errorOnFileNotFound) {
- debugC(3, kDebugDisk, "AmigaDisk::openArchivedFile(%s)", name);
+Common::SeekableReadStream *AmigaDisk_ns::openArchivedFile(const char* name, bool errorOnFileNotFound) {
+ debugC(3, kDebugDisk, "AmigaDisk_ns::openArchivedFile(%s)", name);
if (_resArchive.openArchivedFile(name)) {
return new DummyArchiveStream(_resArchive);
@@ -932,7 +1109,12 @@ Common::SeekableReadStream *AmigaDisk::openArchivedFile(const char* name, bool e
return NULL;
}
-// FIXME: mask values are not computed correctly for level 1 and 2
+/*
+ FIXME: mask values are not computed correctly for level 1 and 2
+
+ NOTE: this routine is only able to build masks for Nippon Safes, since mask widths are hardcoded
+ into the main loop.
+*/
void buildMask(byte* buf) {
byte mask1[16] = { 0, 0x80, 0x20, 0xA0, 8, 0x88, 0x28, 0xA8, 2, 0x82, 0x22, 0xA2, 0xA, 0x8A, 0x2A, 0xAA };
@@ -941,7 +1123,7 @@ void buildMask(byte* buf) {
byte plane0[40];
byte plane1[40];
- for (uint32 i = 0; i < 200; i++) {
+ for (int32 i = 0; i < _vm->_screenHeight; i++) {
memcpy(plane0, buf, 40);
memcpy(plane1, buf+40, 40);
@@ -1004,7 +1186,7 @@ public:
};
-void AmigaDisk::loadBackground(const char *name) {
+void AmigaDisk_ns::loadBackground(const char *name) {
Common::SeekableReadStream *s = openArchivedFile(name, true);
@@ -1025,14 +1207,17 @@ void AmigaDisk::loadBackground(const char *name) {
}
-void AmigaDisk::loadMask(const char *name) {
+void AmigaDisk_ns::loadMask(const char *name) {
+ debugC(5, kDebugDisk, "AmigaDisk_ns::loadMask(%s)", name);
char path[PATH_LEN];
sprintf(path, "%s.mask", name);
Common::SeekableReadStream *s = openArchivedFile(path, false);
- if (s == NULL)
+ if (s == NULL) {
+ debugC(5, kDebugDisk, "Mask file not found");
return; // no errors if missing mask files: not every location has one
+ }
s->seek(0x30, SEEK_SET);
@@ -1051,9 +1236,10 @@ void AmigaDisk::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(SCREENMASK_WIDTH*SCREEN_HEIGHT);
- stream.read(buf, SCREENMASK_WIDTH*SCREEN_HEIGHT);
+ byte *buf = (byte*)malloc(_vm->_screenMaskSize);
+ stream.read(buf, _vm->_screenMaskSize);
buildMask(buf);
+
_vm->_gfx->setMask(buf);
free(buf);
delete s;
@@ -1061,7 +1247,7 @@ void AmigaDisk::loadMask(const char *name) {
return;
}
-void AmigaDisk::loadPath(const char *name) {
+void AmigaDisk_ns::loadPath(const char *name) {
char path[PATH_LEN];
sprintf(path, "%s.path", name);
@@ -1074,8 +1260,8 @@ void AmigaDisk::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(SCREENPATH_WIDTH*SCREEN_HEIGHT);
- stream.read(buf, SCREENPATH_WIDTH*SCREEN_HEIGHT);
+ byte *buf = (byte*)malloc(_vm->_screenPathSize);
+ stream.read(buf, _vm->_screenPathSize);
_vm->setPath(buf);
free(buf);
delete s;
@@ -1083,21 +1269,27 @@ void AmigaDisk::loadPath(const char *name) {
return;
}
-void AmigaDisk::loadScenery(const char* background, const char* mask) {
- debugC(1, kDebugDisk, "AmigaDisk::loadScenery '%s', '%s'", background, mask);
+void AmigaDisk_ns::loadScenery(const char* background, const char* mask) {
+ debugC(1, kDebugDisk, "AmigaDisk_ns::loadScenery '%s', '%s'", background, mask);
char path[PATH_LEN];
sprintf(path, "%s.bkgnd", background);
loadBackground(path);
- loadMask(background);
- loadPath(background);
+
+ if (mask == NULL) {
+ loadMask(background);
+ loadPath(background);
+ } else {
+ loadMask(mask);
+ loadPath(mask);
+ }
return;
}
-void AmigaDisk::loadSlide(const char *name) {
- debugC(1, kDebugDisk, "AmigaDisk::loadSlide '%s'", name);
+void AmigaDisk_ns::loadSlide(const char *name) {
+ debugC(1, kDebugDisk, "AmigaDisk_ns::loadSlide '%s'", name);
char path[PATH_LEN];
sprintf(path, "slides/%s", name);
@@ -1110,8 +1302,8 @@ void AmigaDisk::loadSlide(const char *name) {
return;
}
-Cnv* AmigaDisk::loadFrames(const char* name) {
- debugC(1, kDebugDisk, "AmigaDisk::loadFrames '%s'", name);
+Cnv* AmigaDisk_ns::loadFrames(const char* name) {
+ debugC(1, kDebugDisk, "AmigaDisk_ns::loadFrames '%s'", name);
Common::SeekableReadStream *s;
@@ -1128,8 +1320,8 @@ Cnv* AmigaDisk::loadFrames(const char* name) {
return cnv;
}
-StaticCnv* AmigaDisk::loadHead(const char* name) {
- debugC(1, kDebugDisk, "AmigaDisk::loadHead '%s'", name);
+StaticCnv* AmigaDisk_ns::loadHead(const char* name) {
+ debugC(1, kDebugDisk, "AmigaDisk_ns::loadHead '%s'", name);
char path[PATH_LEN];
sprintf(path, "%s.head", name);
@@ -1143,8 +1335,8 @@ StaticCnv* AmigaDisk::loadHead(const char* name) {
}
-Cnv* AmigaDisk::loadObjects(const char *name) {
- debugC(1, kDebugDisk, "AmigaDisk::loadObjects");
+Cnv* AmigaDisk_ns::loadObjects(const char *name) {
+ debugC(1, kDebugDisk, "AmigaDisk_ns::loadObjects");
char path[PATH_LEN];
if (_vm->getFeatures() & GF_DEMO)
@@ -1161,8 +1353,8 @@ Cnv* AmigaDisk::loadObjects(const char *name) {
}
-Cnv* AmigaDisk::loadTalk(const char *name) {
- debugC(1, kDebugDisk, "AmigaDisk::loadTalk '%s'", name);
+Cnv* AmigaDisk_ns::loadTalk(const char *name) {
+ debugC(1, kDebugDisk, "AmigaDisk_ns::loadTalk '%s'", name);
Common::SeekableReadStream *s;
@@ -1183,8 +1375,8 @@ Cnv* AmigaDisk::loadTalk(const char *name) {
return cnv;
}
-Table* AmigaDisk::loadTable(const char* name) {
- debugC(1, kDebugDisk, "AmigaDisk::loadTable '%s'", name);
+Table* AmigaDisk_ns::loadTable(const char* name) {
+ debugC(1, kDebugDisk, "AmigaDisk_ns::loadTable '%s'", name);
char path[PATH_LEN];
sprintf(path, "%s.table", name);
@@ -1223,7 +1415,7 @@ Table* AmigaDisk::loadTable(const char* name) {
return t;
}
-Font* AmigaDisk::loadFont(const char* name) {
+Font* AmigaDisk_ns::loadFont(const char* name) {
debugC(1, kDebugDisk, "AmigaFullDisk::loadFont '%s'", name);
char path[PATH_LEN];
@@ -1245,11 +1437,11 @@ Font* AmigaDisk::loadFont(const char* name) {
}
-Common::ReadStream* AmigaDisk::loadMusic(const char* name) {
+Common::SeekableReadStream* AmigaDisk_ns::loadMusic(const char* name) {
return openArchivedFile(name);
}
-Common::ReadStream* AmigaDisk::loadSound(const char* name) {
+Common::ReadStream* AmigaDisk_ns::loadSound(const char* name) {
char path[PATH_LEN];
sprintf(path, "%s.snd", name);
diff --git a/engines/parallaction/font.cpp b/engines/parallaction/font.cpp
index 56c26b7b4f..13e94a4cda 100644
--- a/engines/parallaction/font.cpp
+++ b/engines/parallaction/font.cpp
@@ -408,7 +408,7 @@ void AmigaFont::drawString(byte *buffer, uint32 pitch, const char *s) {
}
-Font *DosDisk::createFont(const char *name, Cnv* cnv) {
+Font *DosDisk_ns::createFont(const char *name, Cnv* cnv) {
Font *f = 0;
if (!scumm_stricmp(name, "comic"))
@@ -425,7 +425,7 @@ Font *DosDisk::createFont(const char *name, Cnv* cnv) {
return f;
}
-Font *AmigaDisk::createFont(const char *name, Common::SeekableReadStream &stream) {
+Font *AmigaDisk_ns::createFont(const char *name, Common::SeekableReadStream &stream) {
// TODO: implement AmigaLabelFont for labels
return new AmigaFont(stream);
}
diff --git a/engines/parallaction/graphics.cpp b/engines/parallaction/graphics.cpp
index 59645381b6..8d45c4aaa9 100644
--- a/engines/parallaction/graphics.cpp
+++ b/engines/parallaction/graphics.cpp
@@ -30,9 +30,6 @@
#include "parallaction/parallaction.h"
-
-extern OSystem *g_system;
-
namespace Parallaction {
byte * Gfx::_buffers[];
@@ -83,7 +80,7 @@ void Gfx::drawBalloon(const Common::Rect& r, uint16 winding) {
winding = (winding == 0 ? 1 : 0);
byte *s = _resBalloon[winding];
- byte *d = _buffers[kBitFront] + (r.left + (r.width()+5)/2 - 5) + (r.bottom - 1) * SCREEN_WIDTH;
+ 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++) {
@@ -92,7 +89,7 @@ void Gfx::drawBalloon(const Common::Rect& r, uint16 winding) {
s++;
}
- d += (SCREEN_WIDTH - BALLOON_WIDTH);
+ d += (_vm->_screenWidth - BALLOON_WIDTH);
}
// printf("done\n");
@@ -142,7 +139,7 @@ void Gfx::setPalette(Palette pal, uint32 first, uint32 num) {
if (_vm->getPlatform() == Common::kPlatformAmiga)
g_system->setPalette(sysExtraPal, first+FIRST_EHB_COLOR, num);
- g_system->updateScreen();
+// g_system->updateScreen();
return;
}
@@ -206,14 +203,7 @@ void Gfx::animatePalette() {
return;
}
-void Gfx::fadePalette(Palette pal) {
- for (uint16 i = 0; i < BASE_PALETTE_COLORS * 3; i++)
- if (pal[i] < _palette[i]) pal[i]++;
-
- return;
-}
-
-void Gfx::buildBWPalette(Palette pal) {
+void Gfx::makeGrayscalePalette(Palette pal) {
for (uint16 i = 0; i < BASE_PALETTE_COLORS; i++) {
byte max;
@@ -229,11 +219,19 @@ void Gfx::buildBWPalette(Palette pal) {
return;
}
-void Gfx::quickFadePalette(Palette pal) {
+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] == _palette[i]) continue;
- pal[i] += (pal[i] < _palette[i] ? 4 : -4);
+ 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;
@@ -258,7 +256,7 @@ void Gfx::setHalfbriteMode(bool enable) {
void Gfx::updateScreen() {
// printf("Gfx::updateScreen()\n");
- g_system->copyRectToScreen(_buffers[kBitFront], SCREEN_WIDTH, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
+ g_system->copyRectToScreen(_buffers[kBitFront], _vm->_screenWidth, 0, 0, _vm->_screenWidth, _vm->_screenHeight);
g_system->updateScreen();
return;
}
@@ -277,7 +275,7 @@ void Gfx::swapBuffers() {
// graphic primitives
//
void Gfx::clearScreen(Gfx::Buffers buffer) {
- memset(_buffers[buffer], 0, SCREEN_WIDTH*SCREEN_HEIGHT);
+ memset(_buffers[buffer], 0, _vm->_screenSize);
if (buffer == kBitFront) updateScreen();
@@ -286,9 +284,9 @@ void Gfx::clearScreen(Gfx::Buffers buffer) {
void Gfx::copyScreen(Gfx::Buffers srcbuffer, Gfx::Buffers dstbuffer) {
- memcpy(_buffers[dstbuffer], _buffers[srcbuffer], SCREEN_WIDTH*SCREEN_HEIGHT);
+ memcpy(_buffers[dstbuffer], _buffers[srcbuffer], _vm->_screenSize);
- if (dstbuffer == kBitFront) updateScreen();
+// if (dstbuffer == kBitFront) updateScreen();
return;
}
@@ -296,25 +294,25 @@ void Gfx::copyScreen(Gfx::Buffers srcbuffer, Gfx::Buffers dstbuffer) {
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 * SCREEN_WIDTH);
+ byte *d = _buffers[buffer] + (r.left + r.top * _vm->_screenWidth);
uint16 w = r.width() + 1;
uint16 h = r.height() + 1;
for (uint16 i = 0; i < h; i++) {
memset(d, color, w);
- d += SCREEN_WIDTH;
+ d += _vm->_screenWidth;
}
return;
}
-void screenClip(Common::Rect& r, Common::Point& p) {
+void Gfx::screenClip(Common::Rect& r, Common::Point& p) {
int32 x = r.left;
int32 y = r.top;
- Common::Rect screen(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
+ Common::Rect screen(0, 0, _vm->_screenWidth, _vm->_screenHeight);
r.clip(screen);
@@ -335,7 +333,7 @@ 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 * SCREEN_WIDTH;
+ byte *d = _buffers[buffer] + dp.x + dp.y * _vm->_screenWidth;
for (uint16 i = q.top; i < q.bottom; i++) {
for (uint16 j = q.left; j < q.right; j++) {
@@ -345,7 +343,7 @@ void Gfx::flatBlit(const Common::Rect& r, byte *data, Gfx::Buffers buffer) {
}
s += (r.width() - q.width());
- d += (SCREEN_WIDTH - q.width());
+ d += (_vm->_screenWidth - q.width());
}
return;
@@ -360,12 +358,12 @@ 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 * SCREEN_WIDTH;
+ byte *d = _buffers[buffer] + dp.x + dp.y * _vm->_screenWidth;
for (uint16 i = q.top; i < q.bottom; i++) {
uint16 n = dp.x % 4;
- byte *m = _buffers[kMask0] + dp.x/4 + (dp.y + i - q.top)*SCREENMASK_WIDTH;
+ byte *m = _buffers[kMask0] + dp.x/4 + (dp.y + i - q.top)*_vm->_screenMaskWidth;
for (uint16 j = q.left; j < q.right; j++) {
if (*s != 0) {
@@ -382,7 +380,7 @@ void Gfx::blit(const Common::Rect& r, uint16 z, byte *data, Gfx::Buffers buffer)
}
s += (r.width() - q.right + q.left);
- d += (SCREEN_WIDTH - q.right + q.left);
+ d += (_vm->_screenWidth - q.right + q.left);
}
return;
@@ -420,8 +418,8 @@ void jobEraseLabel(void *parm, Job *j) {
if (_si < 0) _si = 0;
if (_di > 190) _di = 190;
- if (label->_cnv._width + _si > SCREEN_WIDTH)
- _si = SCREEN_WIDTH - label->_cnv._width;
+ 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]);
@@ -438,8 +436,8 @@ void Gfx::initMouse(uint16 arg_0) {
_mouseComposedArrow = _vm->_disk->loadPointer();
- byte temp[16*16];
- memcpy(temp, _mouseArrow, 16*16);
+ byte temp[MOUSEARROW_WIDTH*MOUSEARROW_HEIGHT];
+ memcpy(temp, _mouseArrow, MOUSEARROW_WIDTH*MOUSEARROW_HEIGHT);
uint16 k = 0;
for (uint16 i = 0; i < 4; i++) {
@@ -449,20 +447,30 @@ void Gfx::initMouse(uint16 arg_0) {
return;
}
+
void Gfx::setMousePointer(int16 index) {
if (index == kCursorArrow) { // standard mouse pointer
- g_system->setMouseCursor(_mouseArrow, 16, 16, 0, 0, 0);
+ g_system->setMouseCursor(_mouseArrow, MOUSEARROW_WIDTH, MOUSEARROW_HEIGHT, 0, 0, 0);
g_system->showMouse(true);
} else {
// inventory item pointer
byte *v8 = _mouseComposedArrow->_data0;
- // FIXME: target offseting is not clear
- extractInventoryGraphics(index, v8 + 7 + 32 * 7);
- g_system->setMouseCursor(v8, 32, 32, 0, 0, 0);
+ // 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;
@@ -505,13 +513,13 @@ void Gfx::blitCnv(StaticCnv *cnv, int16 x, int16 y, uint16 z, Gfx::Buffers buffe
void Gfx::backupDoorBackground(DoorData *data, int16 x, int16 y) {
- byte *s = _buffers[kBit2] + x + y * SCREEN_WIDTH;
+ 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 += SCREEN_WIDTH;
+ s += _vm->_screenWidth;
d += data->_cnv->_width;
}
@@ -521,7 +529,7 @@ void Gfx::backupDoorBackground(DoorData *data, int16 x, int16 y) {
void Gfx::backupGetBackground(GetData *data, int16 x, int16 y) {
byte *t = data->_cnv->_data0;
- byte *s = _buffers[kBitBack] + x + y * SCREEN_WIDTH;
+ byte *s = _buffers[kBitBack] + x + y * _vm->_screenWidth;
byte *d = data->_backup;
for (uint16 i = 0; i < data->_cnv->_height ; i++) {
@@ -533,16 +541,48 @@ void Gfx::backupGetBackground(GetData *data, int16 x, int16 y) {
s++;
}
- s += (SCREEN_WIDTH - data->_cnv->_width);
+ s += (_vm->_screenWidth - data->_cnv->_width);
+ }
+
+ return;
+}
+
+//
+// restores background according to specified frame
+//
+void Gfx::restoreDoorBackground(StaticCnv *cnv, const Common::Rect& r, byte* background) {
+
+ byte *t = cnv->_data0;
+ byte *s = background;
+ byte *d0 = _buffers[kBitBack] + r.left + r.top * _vm->_screenWidth;
+ byte *d1 = _buffers[kBit2] + r.left + r.top * _vm->_screenWidth;
+
+ for (uint16 i = 0; i < r.height() ; i++) {
+ for (uint16 j = 0; j < r.width() ; j++) {
+ if (*t) {
+ *d0 = *s;
+ *d1 = *s;
+ }
+
+ d0++;
+ d1++;
+ t++;
+ s++;
+ }
+
+ d0 += (_vm->_screenWidth - r.width());
+ d1 += (_vm->_screenWidth - r.width());
}
+
return;
}
+
//
// copies a rectangular bitmap on the background
//
-void Gfx::restoreZoneBackground(const Common::Rect& r, byte *data) {
+void Gfx::restoreGetBackground(const Common::Rect& r, byte *data) {
StaticCnv cnv;
@@ -584,17 +624,17 @@ void Gfx::makeCnvFromString(StaticCnv *cnv, char *text) {
}
void Gfx::displayString(uint16 x, uint16 y, const char *text, byte color) {
- byte *dst = _buffers[kBitFront] + x + y*SCREEN_WIDTH;
+ byte *dst = _buffers[kBitFront] + x + y*_vm->_screenWidth;
_font->setColor(color);
- _font->drawString(dst, SCREEN_WIDTH, text);
+ _font->drawString(dst, _vm->_screenWidth, text);
}
void Gfx::displayCenteredString(uint16 y, const char *text) {
- uint16 x = (SCREEN_WIDTH - getStringWidth(text)) / 2;
+ uint16 x = (_vm->_screenWidth - getStringWidth(text)) / 2;
displayString(x, y, text, 1);
}
-bool Gfx::displayWrappedString(char *text, uint16 x, uint16 y, byte color, uint16 wrapwidth) {
+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;
@@ -606,6 +646,9 @@ bool Gfx::displayWrappedString(char *text, uint16 x, uint16 y, byte color, uint1
char token[40];
+ if (wrapwidth == -1)
+ wrapwidth = _vm->_screenWidth;
+
while (strlen(text) > 0) {
text = parseNextToken(text, token, 40, " ", true);
@@ -694,11 +737,11 @@ void Gfx::restoreBackground(const Common::Rect& r) {
if (left < 0) left = 0;
if (top < 0) top = 0;
- if (left >= SCREEN_WIDTH) return;
- if (top >= SCREEN_HEIGHT) return;
+ if (left >= _vm->_screenWidth) return;
+ if (top >= _vm->_screenHeight) return;
- if (left+width >= SCREEN_WIDTH) width = SCREEN_WIDTH - left;
- if (top+height >= SCREEN_HEIGHT) height = SCREEN_HEIGHT - top;
+ if (left+width >= _vm->_screenWidth) width = _vm->_screenWidth - left;
+ if (top+height >= _vm->_screenHeight) height = _vm->_screenHeight - top;
Common::Rect q(width, height);
q.moveTo(left, top);
@@ -706,8 +749,8 @@ void Gfx::restoreBackground(const Common::Rect& r) {
copyRect(
kBitBack,
q,
- _buffers[kBit2] + q.left + q.top * SCREEN_WIDTH,
- SCREEN_WIDTH
+ _buffers[kBit2] + q.left + q.top * _vm->_screenWidth,
+ _vm->_screenWidth
);
return;
@@ -728,26 +771,26 @@ void Gfx::freeStaticCnv(StaticCnv *cnv) {
void Gfx::setBackground(byte *background) {
- memcpy(_buffers[kBitBack], background, SCREEN_WIDTH*SCREEN_HEIGHT);
+ memcpy(_buffers[kBitBack], background, _vm->_screenSize);
copyScreen(kBitBack, kBit2);
}
void Gfx::setMask(byte *mask) {
- memcpy(_buffers[kMask0], mask, SCREENMASK_WIDTH*SCREEN_HEIGHT);
+ memcpy(_buffers[kMask0], mask, _vm->_screenMaskSize);
}
void Gfx::copyRect(Gfx::Buffers dstbuffer, const Common::Rect& r, byte *src, uint16 pitch) {
- byte *d = _buffers[dstbuffer] + r.left + SCREEN_WIDTH * r.top;
+ 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 += SCREEN_WIDTH;
+ d += _vm->_screenWidth;
}
@@ -756,51 +799,49 @@ void Gfx::copyRect(Gfx::Buffers dstbuffer, const Common::Rect& r, byte *src, uin
void Gfx::grabRect(byte *dst, const Common::Rect& r, Gfx::Buffers srcbuffer, uint16 pitch) {
- byte *s = _buffers[srcbuffer] + r.left + SCREEN_WIDTH * r.top;
+ byte *s = _buffers[srcbuffer] + r.left + _vm->_screenWidth * r.top;
for (uint16 i = 0; i < r.height(); i++) {
memcpy(dst, s, r.width());
- s += SCREEN_WIDTH;
+ s += _vm->_screenWidth;
dst += pitch;
}
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 * SCREEN_WIDTH;
+ uint16 _ax = x + y * _vm->_screenWidth;
_buffers[kMask0][_ax >> 2] &= ~(3 << ((_ax & 3) << 1));
return;
}
-
-
-
void Gfx::fillMaskRect(const Common::Rect& r, byte color) {
- uint16 _di = r.left/4 + r.top*80;
+ 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 += 80;
+ _di += _vm->_screenMaskWidth;
}
return;
}
-
-// HACK
-// this routine is only invoked from the 'intgrotta scenario'
-//
void Gfx::intGrottaHackMask() {
memset(_buffers[kMask0] + 3600, 0, 3600);
_bgLayers[1] = 500;
return;
}
+
int16 Gfx::queryMask(int16 v) {
for (uint16 _si = 0; _si < 3; _si++) {
@@ -814,13 +855,13 @@ Gfx::Gfx(Parallaction* vm) :
_vm(vm) {
g_system->beginGFXTransaction();
- g_system->initSize(SCREEN_WIDTH, SCREEN_HEIGHT);
+ g_system->initSize(_vm->_screenWidth, _vm->_screenHeight);
g_system->endGFXTransaction();
- _buffers[kBitFront] = (byte*)malloc(SCREEN_SIZE);
- _buffers[kBitBack] = (byte*)malloc(SCREEN_SIZE);
- _buffers[kBit2] = (byte*)malloc(SCREEN_SIZE);
- _buffers[kMask0] = (byte*)malloc(SCREENMASK_WIDTH * SCREEN_HEIGHT);
+ _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);
setBlackPalette();
diff --git a/engines/parallaction/graphics.h b/engines/parallaction/graphics.h
index d535d3cf05..f518bd6625 100644
--- a/engines/parallaction/graphics.h
+++ b/engines/parallaction/graphics.h
@@ -36,14 +36,6 @@
namespace Parallaction {
-
-#define SCREEN_WIDTH 320
-#define SCREEN_HEIGHT 200
-#define SCREEN_SIZE SCREEN_WIDTH*SCREEN_HEIGHT
-
-#define SCREENMASK_WIDTH SCREEN_WIDTH/4
-#define SCREENPATH_WIDTH SCREEN_WIDTH/8
-
#define BASE_PALETTE_COLORS 32
#define FIRST_BASE_COLOR 0
#define LAST_BASE_COLOR (FIRST_BASE_COLOR+BASE_PALETTE_COLORS-1)
@@ -57,6 +49,12 @@ namespace Parallaction {
#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 {
@@ -162,12 +160,13 @@ public:
};
public:
+ void screenClip(Common::Rect& r, Common::Point& p);
// dialogue 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);
- bool displayWrappedString(char *text, uint16 x, uint16 y, byte color, uint16 wrapwidth = SCREEN_WIDTH);
+ bool displayWrappedString(char *text, uint16 x, uint16 y, byte color, int16 wrapwidth = -1);
uint16 getStringWidth(const char *text);
void getStringExtent(char *text, uint16 maxwidth, int16* width, int16* height);
@@ -176,7 +175,8 @@ public:
void freeStaticCnv(StaticCnv *cnv);
void backupDoorBackground(DoorData *data, int16 x, int16 y);
void backupGetBackground(GetData *data, int16 x, int16 y);
- void restoreZoneBackground(const Common::Rect& r, byte *data);
+ void restoreGetBackground(const Common::Rect& r, byte *data);
+ void restoreDoorBackground(StaticCnv *cnv, const Common::Rect& r, byte* background);
// location
void setBackground(byte *background);
@@ -210,9 +210,8 @@ public:
void setPalette(Palette palette, uint32 first = FIRST_BASE_COLOR, uint32 num = BASE_PALETTE_COLORS);
void setBlackPalette();
void animatePalette();
- void fadePalette(Palette palette);
- void buildBWPalette(Palette palette);
- void quickFadePalette(Palette palette);
+ 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);
diff --git a/engines/parallaction/intro.cpp b/engines/parallaction/intro.cpp
deleted file mode 100644
index 96a072b28d..0000000000
--- a/engines/parallaction/intro.cpp
+++ /dev/null
@@ -1,320 +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/menu.h"
-#include "parallaction/sound.h"
-
-#include "graphics/primitives.h"
-
-namespace Parallaction {
-
-static Animation *_rightHandAnim;
-
-static uint16 _rightHandPositions[684] = {
- 0x0064, 0x0046, 0x006c, 0x0046, 0x0074, 0x0046, 0x007c, 0x0046,
- 0x0084, 0x0046, 0x008c, 0x0046, 0x0094, 0x0046, 0x009c, 0x0046,
- 0x00a4, 0x0046, 0x00ac, 0x0046, 0x00b4, 0x0046, 0x00bc, 0x0046,
- 0x00c4, 0x0046, 0x00cc, 0x0046, 0x00d4, 0x0046, 0x00dc, 0x0046,
- 0x00e4, 0x0046, 0x00ec, 0x0046, 0x00f4, 0x0046, 0x00fc, 0x0046,
- 0x0104, 0x0046, 0x00ff, 0x0042, 0x00ff, 0x004a, 0x00ff, 0x0052,
- 0x00ff, 0x005a, 0x00ff, 0x0062, 0x00ff, 0x006a, 0x00ff, 0x0072,
- 0x00ff, 0x007a, 0x00ff, 0x0082, 0x00ff, 0x008a, 0x00ff, 0x0092,
- 0x00ff, 0x009a, 0x00ff, 0x00a2, 0x0104, 0x0097, 0x00fc, 0x0097,
- 0x00f4, 0x0097, 0x00ec, 0x0097, 0x00e4, 0x0097, 0x00dc, 0x0097,
- 0x00d4, 0x0097, 0x00cc, 0x0097, 0x00c4, 0x0097, 0x00bc, 0x0097,
- 0x00b4, 0x0097, 0x00ac, 0x0097, 0x00a4, 0x0097, 0x009c, 0x0097,
- 0x0094, 0x0097, 0x008c, 0x0097, 0x0084, 0x0097, 0x007c, 0x0097,
- 0x0074, 0x0097, 0x006c, 0x0097, 0x0064, 0x0097, 0x0066, 0x0042,
- 0x0066, 0x004a, 0x0066, 0x0052, 0x0066, 0x005a, 0x0066, 0x0062,
- 0x0066, 0x006a, 0x0066, 0x0072, 0x0066, 0x007a, 0x0066, 0x0082,
- 0x0066, 0x008a, 0x0066, 0x0092, 0x0066, 0x009a, 0x0066, 0x00a2,
- 0x008c, 0x0091, 0x0099, 0x0042, 0x0099, 0x004a, 0x0099, 0x0052,
- 0x0099, 0x005a, 0x0099, 0x0062, 0x0099, 0x006a, 0x0099, 0x0072,
- 0x0099, 0x007a, 0x0099, 0x0082, 0x0099, 0x008a, 0x0099, 0x0092,
- 0x0099, 0x009a, 0x0099, 0x00a2, 0x00a0, 0x004d, 0x00cc, 0x0042,
- 0x00cc, 0x004a, 0x00cc, 0x0052, 0x00cc, 0x005a, 0x00cc, 0x0062,
- 0x00cc, 0x006a, 0x00cc, 0x0072, 0x00cc, 0x007a, 0x00cc, 0x0082,
- 0x00cc, 0x008a, 0x00cc, 0x0092, 0x00cc, 0x009a, 0x00cc, 0x00a2,
- 0x00ca, 0x0050, 0x00b1, 0x0050, 0x0081, 0x0052, 0x007e, 0x0052,
- 0x007c, 0x0055, 0x007c, 0x005c, 0x007e, 0x005e, 0x0080, 0x005e,
- 0x0082, 0x005c, 0x0082, 0x0054, 0x0080, 0x0052, 0x0078, 0x0052,
- 0x007c, 0x005e, 0x0077, 0x0061, 0x0074, 0x006e, 0x0074, 0x0078,
- 0x0076, 0x007a, 0x0079, 0x0078, 0x0079, 0x0070, 0x0078, 0x0070,
- 0x0078, 0x006b, 0x007b, 0x0066, 0x007a, 0x006f, 0x0084, 0x006f,
- 0x0085, 0x0066, 0x0086, 0x0070, 0x0085, 0x0070, 0x0085, 0x0079,
- 0x0088, 0x0079, 0x008a, 0x0078, 0x008a, 0x006c, 0x0087, 0x0061,
- 0x0085, 0x005f, 0x0082, 0x005f, 0x0080, 0x0061, 0x007e, 0x0061,
- 0x007b, 0x005f, 0x007c, 0x006f, 0x007c, 0x0071, 0x0079, 0x0074,
- 0x0079, 0x0089, 0x0076, 0x008c, 0x0076, 0x008e, 0x007a, 0x008e,
- 0x007f, 0x0089, 0x007f, 0x0083, 0x007e, 0x0083, 0x007e, 0x0077,
- 0x0080, 0x0077, 0x0080, 0x0083, 0x0080, 0x008b, 0x0084, 0x0090,
- 0x0088, 0x0090, 0x0088, 0x008e, 0x0085, 0x008b, 0x0085, 0x0074,
- 0x0082, 0x0071, 0x00b2, 0x0052, 0x00b0, 0x0054, 0x00b0, 0x0056,
- 0x00ae, 0x0058, 0x00af, 0x0059, 0x00af, 0x005e, 0x00b2, 0x0061,
- 0x00b5, 0x0061, 0x00b8, 0x005e, 0x00b8, 0x005a, 0x00b9, 0x0059,
- 0x00b9, 0x0058, 0x00b7, 0x0056, 0x00b7, 0x0054, 0x00b5, 0x0052,
- 0x00b2, 0x0052, 0x00ae, 0x005a, 0x00ab, 0x005b, 0x00ab, 0x006d,
- 0x00ae, 0x0072, 0x00b8, 0x0072, 0x00bc, 0x006d, 0x00bc, 0x005b,
- 0x00b9, 0x005a, 0x00bc, 0x005c, 0x00be, 0x005c, 0x00c1, 0x005f,
- 0x00c4, 0x0067, 0x00c4, 0x006d, 0x00c1, 0x0076, 0x00c0, 0x0077,
- 0x00bd, 0x0077, 0x00bb, 0x0075, 0x00bd, 0x0073, 0x00bb, 0x0072,
- 0x00be, 0x0070, 0x00be, 0x006a, 0x00a9, 0x006a, 0x00a9, 0x0070,
- 0x00ac, 0x0072, 0x00aa, 0x0073, 0x00ac, 0x0075, 0x00aa, 0x0077,
- 0x00a7, 0x0077, 0x00a3, 0x006d, 0x00a3, 0x0067, 0x00a6, 0x005f,
- 0x00a9, 0x005c, 0x00ab, 0x005c, 0x00ac, 0x0077, 0x00ac, 0x007c,
- 0x00ab, 0x007c, 0x00ab, 0x0084, 0x00ac, 0x0084, 0x00ac, 0x008b,
- 0x00a9, 0x008e, 0x00a9, 0x0090, 0x00ae, 0x0090, 0x00ae, 0x008d,
- 0x00b2, 0x008c, 0x00b2, 0x0087, 0x00b1, 0x0086, 0x00b1, 0x007b,
- 0x00b2, 0x0079, 0x00b4, 0x0079, 0x00b4, 0x007d, 0x00b5, 0x007d,
- 0x00b5, 0x0087, 0x00b4, 0x0087, 0x00b4, 0x008c, 0x00b6, 0x008c,
- 0x00b9, 0x0091, 0x00b4, 0x0091, 0x00bd, 0x008f, 0x00ba, 0x008c,
- 0x00ba, 0x0083, 0x00bb, 0x0082, 0x00bb, 0x0075, 0x00cc, 0x006e,
- 0x00d4, 0x006c, 0x00db, 0x0069, 0x00d9, 0x0068, 0x00d9, 0x0064,
- 0x00dc, 0x0064, 0x00dc, 0x0060, 0x00df, 0x0056, 0x00e5, 0x0052,
- 0x00e7, 0x0052, 0x00ec, 0x0056, 0x00ef, 0x005d, 0x00f1, 0x0065,
- 0x00f3, 0x0064, 0x00f3, 0x0069, 0x00f0, 0x0069, 0x00ec, 0x0065,
- 0x00ec, 0x005e, 0x00e9, 0x005f, 0x00e9, 0x005a, 0x00e7, 0x0058,
- 0x00e4, 0x0058, 0x00e3, 0x0054, 0x00e3, 0x0058, 0x00e1, 0x005c,
- 0x00e4, 0x0061, 0x00e7, 0x0061, 0x00e9, 0x005f, 0x00eb, 0x005d,
- 0x00e4, 0x0062, 0x00e0, 0x0064, 0x00e0, 0x0069, 0x00e2, 0x006b,
- 0x00e0, 0x0072, 0x00e0, 0x0077, 0x00ec, 0x0077, 0x00ec, 0x0071,
- 0x00ea, 0x006b, 0x00ec, 0x006a, 0x00ec, 0x0063, 0x00e7, 0x0063,
- 0x00e7, 0x0065, 0x00e1, 0x0069, 0x00e3, 0x0068, 0x00e6, 0x0069,
- 0x00ec, 0x005e, 0x00ea, 0x006b, 0x00e7, 0x006b, 0x00e7, 0x006a,
- 0x00e5, 0x006a, 0x00e5, 0x006b, 0x00e2, 0x006b, 0x00df, 0x006c,
- 0x00dc, 0x006f, 0x00dc, 0x0071, 0x00da, 0x0073, 0x00d8, 0x0073,
- 0x00d8, 0x006f, 0x00dc, 0x006b, 0x00dc, 0x0069, 0x00dd, 0x0068,
- 0x00ef, 0x0068, 0x00f0, 0x0069, 0x00f0, 0x006b, 0x00f4, 0x006f,
- 0x00f4, 0x0072, 0x00f3, 0x0073, 0x00f2, 0x0073, 0x00f0, 0x0071,
- 0x00f0, 0x006f, 0x00ec, 0x006b, 0x00ec, 0x007a, 0x00eb, 0x007b,
- 0x00eb, 0x007f, 0x00ec, 0x0080, 0x00ec, 0x0084, 0x00eb, 0x0085,
- 0x00eb, 0x008b, 0x00ec, 0x008c, 0x00ec, 0x008f, 0x00ed, 0x0091,
- 0x00e9, 0x0091, 0x00e9, 0x008f, 0x00e7, 0x008d, 0x00e7, 0x0090,
- 0x00e7, 0x0089, 0x00e8, 0x0088, 0x00e8, 0x0086, 0x00e7, 0x0085,
- 0x00e7, 0x007d, 0x00e6, 0x007c, 0x00e6, 0x0078, 0x00e5, 0x007d,
- 0x00e5, 0x0085, 0x00e4, 0x0086, 0x00e4, 0x0088, 0x00e5, 0x0089,
- 0x00e5, 0x0090, 0x00e5, 0x008b, 0x00e3, 0x0091, 0x00df, 0x0091,
- 0x00e0, 0x0090, 0x00e0, 0x008c, 0x00e2, 0x008b, 0x00e1, 0x0085,
- 0x00e0, 0x0084, 0x00e0, 0x0080, 0x00e1, 0x007f, 0x00e1, 0x007c,
- 0x00e0, 0x007b, 0x00e0, 0x0077
-};
-
-extern Credit _credits[];
-
-void _c_startIntro(void *parm) {
- _rightHandAnim = _vm->findAnimation("righthand");
-
- if (_vm->getPlatform() == Common::kPlatformPC) {
- _vm->_soundMan->setMusicFile("intro");
- _vm->_soundMan->playMusic();
- }
-
- _engineFlags |= kEngineBlockInput;
-
- return;
-}
-
-void _c_endIntro(void *parm) {
-
- _vm->_gfx->setFont(kFontMenu);
-
- debugC(1, kDebugLocation, "endIntro()");
-
- for (uint16 _si = 0; _si < 6; _si++) {
- _vm->_gfx->displayCenteredString(80, _credits[_si]._role);
- _vm->_gfx->displayCenteredString(100, _credits[_si]._name);
-
- _vm->_gfx->updateScreen();
-
- for (uint16 v2 = 0; v2 < 100; v2++) {
- _mouseButtons = kMouseNone;
- _vm->updateInput();
- if (_mouseButtons == kMouseLeftUp)
- break;
-
- _vm->waitTime( 1 );
- }
-
- _vm->_gfx->copyScreen(Gfx::kBitBack, Gfx::kBitFront);
- }
- debugC(1, kDebugLocation, "endIntro(): done showing credits");
-
- if ((_vm->getFeatures() & GF_DEMO) == 0) {
- _vm->_gfx->displayCenteredString(80, "CLICK MOUSE BUTTON TO START");
- _vm->_gfx->updateScreen();
-
- waitUntilLeftClick();
-
- _engineFlags &= ~kEngineBlockInput;
- _vm->_menu->selectCharacter();
- } else {
- waitUntilLeftClick();
- }
-
- return;
-}
-
-void _c_moveSheet(void *parm) {
-
- static uint16 x = 319;
-
- if (x > 66)
- x -= 16;
-
- Common::Rect r;
-
- r.left = x;
- r.top = 47;
- r.right = (x + 32 > 319) ? 319 : (x + 32);
- r.bottom = 199;
- _vm->_gfx->floodFill(Gfx::kBitBack, r, 1);
- _vm->_gfx->floodFill(Gfx::kBit2, r, 1);
-
- if (x >= 104) return;
-
- r.left = x+215;
- r.top = 47;
- r.right = (x + 247 > 319) ? 319 : (x + 247);
- r.bottom = 199;
- _vm->_gfx->floodFill(Gfx::kBitBack, r, 12);
- _vm->_gfx->floodFill(Gfx::kBit2, r, 12);
-
- return;
-}
-
-void plotPixel(int x, int y, int color, void *data) {
- _vm->_gfx->plotMaskPixel(x, y, color);
-}
-
-void _c_sketch(void *parm) {
-
- static uint16 index = 1;
-
- uint16 newy = _rightHandPositions[2*index+1];
- uint16 newx = _rightHandPositions[2*index];
-
- uint16 oldy = _rightHandPositions[2*(index-1)+1];
- uint16 oldx = _rightHandPositions[2*(index-1)];
-
- Graphics::drawLine(oldx, oldy, newx, newy, 0, plotPixel, NULL);
-
- _rightHandAnim->_left = newx;
- _rightHandAnim->_top = newy - 20;
-
- index++;
-
- return;
-}
-
-
-
-
-void _c_shade(void *parm) {
-
- Common::Rect r(
- _rightHandAnim->_left - 36,
- _rightHandAnim->_top - 36,
- _rightHandAnim->_left,
- _rightHandAnim->_top
- );
-
- _vm->_gfx->fillMaskRect(r, 0);
-
- return;
-
-}
-
-void _c_projector(void*) {
-#ifdef HALFBRITE
- static int dword_16032 = 0;
-
-// Bitmap bm;
-// InitBitMap(&bm);
-
- if (dword_16032 != 0) {
-/* // keep drawing spotlight in its final place
- _vm->_gfx->flatBlitCnv(&scnv, 110, 25, Gfx::kBitFront);
- BltBitMap(&bm, 0, 0, &_screen._bitMap, 110, 25, a3->??, a3->??, 0x20, 0x20);
-*/ return;
- }
-
- _vm->_gfx->setHalfbriteMode(true);
-/*
- // move spot light around the stage
- int d7, d6;
- for (d7 = 0; d7 < 150; d7++) {
-
- if (d7 < 100) {
- int d1 = d7;
- if (d1 < 0)
- d1++;
-
- d1 >>= 1;
- d6 = 50 - d1;
- } else {
- int d1 = d7 / 100;
- if (d1 < 0)
- d1++;
-
- d1 >>= 1;
- d6 = d1;
- }
-
- BltBitMap(&bm, 0, 0, &_screen._bitMap, d7+20, d6, a3->??, a3->??, 0x20, 0x20);
- sub_1590C(d6 + a3->??);
- BltBitMap(&bm, 0, 0, &_screen._bitMap, d7+20, d6, a3->??, a3->??, 0xFA, 0x20);
- }
-
- for (d7 = 50; d7 > -10; d7--) {
- BltBitMap(&bm, 0, 0, &_screen._bitMap, d7+120, d6, a3->??, a3->??, 0x20, 0x20);
- sub_1590C(d6 + a3->??);
- BltBitMap(&bm, 0, 0, &_screen._bitMap, d7+120, d6, a3->??, a3->??, 0xFA, 0x20);
- }
-
- BltBitMap(&bm, 0, 0, &_screen._bitMap, d7+120, d6, a3->??, a3->??, 0x20, 0x20);
- _vm->_gfx->flatBlitCnv(&scnv, d7+120, d6, Gfx::kBitFront);
-*/
-
- dword_16032 = 1;
- return;
-#endif
-}
-
-void _c_HBOff(void*) {
-#ifdef HALFBRITE
- _vm->_gfx->setHalfbriteMode(false);
-#endif
-}
-
-void _c_HBOn(void*) {
-#ifdef HALFBRITE
- _vm->_gfx->setHalfbriteMode(true);
-#endif
-}
-
-} // namespace Parallaction
diff --git a/engines/parallaction/inventory.cpp b/engines/parallaction/inventory.cpp
index 3581b956a6..c9e74b2074 100644
--- a/engines/parallaction/inventory.cpp
+++ b/engines/parallaction/inventory.cpp
@@ -42,10 +42,6 @@ namespace Parallaction {
#define INVENTORY_MAX_ITEMS 30
#define INVENTORY_FIRST_ITEM 4 // first four entries are used up by verbs
-#define INVENTORYITEM_PITCH 32
-#define INVENTORYITEM_WIDTH 24
-#define INVENTORYITEM_HEIGHT 24
-
#define INVENTORY_ITEMS_PER_LINE 5
#define INVENTORY_LINES 6
@@ -89,7 +85,13 @@ InventoryItem _inventory[INVENTORY_MAX_ITEMS] = {
{ 0, 0 }
};
-void drawInventoryItem(uint16 pos, InventoryItem *item);
+
+int16 getNumUsedSlots() {
+ int16 num = 0;
+ while (num < INVENTORY_MAX_ITEMS && _inventory[num]._id != 0)
+ num++;
+ return num;
+}
// get inventory item index at position (x,y)
@@ -97,51 +99,55 @@ void drawInventoryItem(uint16 pos, InventoryItem *item);
//
int16 Parallaction::getHoverInventoryItem(int16 x, int16 y) {
- int16 slot = -1;
- do {
- slot++;
- } while (_inventory[slot]._id != 0);
-
+ int16 slot = getNumUsedSlots();
slot = (slot + 4) / INVENTORY_ITEMS_PER_LINE;
- if (_invPosition.x >= x) return -1;
- if ((_invPosition.x + INVENTORY_WIDTH) <= x) return -1;
+ Common::Rect r(INVENTORY_WIDTH, _numInvLines * INVENTORYITEM_HEIGHT);
+ r.moveTo(_invPosition);
- if (_invPosition.y >= y) return -1;
- if ((slot * INVENTORYITEM_HEIGHT + _invPosition.y) <= y) return -1;
+ if (!r.contains(Common::Point(x,y)))
+ return -1;
return ((x - _invPosition.x) / INVENTORYITEM_WIDTH) + (INVENTORY_ITEMS_PER_LINE * ((y - _invPosition.y) / INVENTORYITEM_HEIGHT));
}
+void drawInventoryItem(uint16 pos, InventoryItem *item) {
+
+ uint16 line = pos / INVENTORY_ITEMS_PER_LINE;
+ uint16 col = pos % INVENTORY_ITEMS_PER_LINE;
-void refreshInventory(const char *character) {
- for (uint16 i = 0; i < INVENTORY_MAX_ITEMS; i++) {
- drawInventoryItem(i, &_inventory[i]);
+ // 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;
+ for (uint32 i = 0; i < INVENTORYITEM_HEIGHT; i++) {
+ memcpy(d, s, INVENTORYITEM_WIDTH);
+
+ d += INVENTORY_WIDTH;
+ s += INVENTORYITEM_PITCH;
}
+
return;
}
-void refreshInventoryItem(const char *character, uint16 index) {
- drawInventoryItem(index, &_inventory[index]);
+
+void refreshInventory() {
+ for (uint16 i = 0; i < INVENTORY_MAX_ITEMS; i++)
+ drawInventoryItem(i, &_inventory[i]);
+
return;
}
int Parallaction::addInventoryItem(uint16 item) {
- uint16 slot = 0;
- while (_inventory[slot]._id != 0)
- slot++;
-
+ int16 slot = getNumUsedSlots();
if (slot == INVENTORY_MAX_ITEMS)
return -1;
_inventory[slot]._id = MAKE_INVENTORY_ID(item);
_inventory[slot]._index = item;
- refreshInventoryItem(_characterName, slot);
-
return 0;
}
@@ -160,8 +166,6 @@ void Parallaction::dropItem(uint16 v) {
memcpy(&_inventory[slot], &_inventory[slot+1], sizeof(InventoryItem));
}
- refreshInventory(_characterName);
-
return;
}
@@ -177,28 +181,6 @@ int16 Parallaction::isItemInInventory(int32 v) {
}
-
-
-
-
-void drawInventoryItem(uint16 pos, InventoryItem *item) {
-
- uint16 line = pos / INVENTORY_ITEMS_PER_LINE;
- uint16 col = pos % INVENTORY_ITEMS_PER_LINE;
-
- // 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;
- for (uint32 i = 0; i < INVENTORYITEM_HEIGHT; i++) {
- memcpy(d, s, INVENTORYITEM_WIDTH);
-
- d += INVENTORY_WIDTH;
- s += INVENTORYITEM_PITCH;
- }
-
- return;
-}
-
void drawBorder(const Common::Rect& r, byte *buffer, byte color) {
byte *d = buffer + r.left + INVENTORY_WIDTH * r.top;
@@ -237,33 +219,20 @@ void highlightInventoryItem(int16 pos, byte color) {
}
+int16 getInventoryItemIndex(int16 pos) {
+ // TODO: should assert against the number of items actually contained,
+ // not the theoretical limit.
+ assert(pos >= 0 && pos < INVENTORY_MAX_ITEMS);
+ return _inventory[pos]._index;
+}
-void extractInventoryGraphics(int16 pos, byte *dst) {
-// printf("extractInventoryGraphics(%i)\n", pos);
-
- int16 line = pos / INVENTORY_ITEMS_PER_LINE;
- int16 col = pos % INVENTORY_ITEMS_PER_LINE;
-
- // FIXME: this will end up in a general blit function
- byte* d = dst;
- byte* s = _buffer + col * INVENTORYITEM_WIDTH + line * _vm->_char._objs->_height * INVENTORY_WIDTH;
- for (uint32 i = 0; i < INVENTORYITEM_HEIGHT; i++) {
- memcpy(d, s, INVENTORYITEM_WIDTH);
-
- s += INVENTORY_WIDTH;
- d += INVENTORYITEM_PITCH;
- }
-
- return;
-}
void jobShowInventory(void *parm, Job *j) {
// printf("job_showInventory()...");
- _numInvLines = 0;
- while (_inventory[_numInvLines]._id != 0) _numInvLines++;
- _numInvLines = (_numInvLines + 4) / INVENTORY_ITEMS_PER_LINE;
+ int16 slot = getNumUsedSlots();
+ _numInvLines = (slot + 4) / INVENTORY_ITEMS_PER_LINE;
Common::Rect r(INVENTORY_WIDTH, _numInvLines * INVENTORYITEM_HEIGHT);
@@ -308,25 +277,13 @@ void jobHideInventory(void *parm, Job *j) {
void openInventory() {
_engineFlags |= kEngineInventory;
- uint16 slot = 0;
- while (_inventory[slot]._id != 0)
- slot++;
-
+ int16 slot = getNumUsedSlots();
uint16 lines = (slot + 4) / INVENTORY_ITEMS_PER_LINE;
- _invPosition.x = _vm->_mousePos.x - (INVENTORY_WIDTH / 2);
- if (_invPosition.x < 0)
- _invPosition.x = 0;
-
- if ((_invPosition.x + INVENTORY_WIDTH) > SCREEN_WIDTH)
- _invPosition.x = SCREEN_WIDTH - INVENTORY_WIDTH;
-
- _invPosition.y = _vm->_mousePos.y - 2 - (lines * INVENTORYITEM_HEIGHT);
- if (_invPosition.y < 0)
- _invPosition.y = 0;
+ _invPosition.x = CLIP(_vm->_mousePos.x - (INVENTORY_WIDTH / 2), 0, (int)(_vm->_screenWidth - INVENTORY_WIDTH));
+ _invPosition.y = CLIP(_vm->_mousePos.y - 2 - (lines * INVENTORYITEM_HEIGHT), 0, (int)(_vm->_screenHeight - lines * INVENTORYITEM_HEIGHT));
- if (_invPosition.y > SCREEN_HEIGHT - lines * INVENTORYITEM_HEIGHT)
- _invPosition.y = SCREEN_HEIGHT - lines * INVENTORYITEM_HEIGHT;
+ refreshInventory();
return;
diff --git a/engines/parallaction/inventory.h b/engines/parallaction/inventory.h
index 0f798ca502..4a3e07cc97 100644
--- a/engines/parallaction/inventory.h
+++ b/engines/parallaction/inventory.h
@@ -34,10 +34,14 @@ namespace Parallaction {
struct Cnv;
struct InventoryItem {
- uint32 _id; // lowest 16 bits are always zero
- uint16 _index;
+ uint32 _id; // object name (lowest 16 bits are always zero)
+ uint16 _index; // index to frame in objs file
};
+#define INVENTORYITEM_PITCH 32
+#define INVENTORYITEM_WIDTH 24
+#define INVENTORYITEM_HEIGHT 24
+
#define MAKE_INVENTORY_ID(x) (((x) & 0xFFFF) << 16)
@@ -47,14 +51,11 @@ void initInventory();
void destroyInventory();
void openInventory();
void closeInventory();
-int16 isItemInInventory(int32 v);
void cleanInventory();
void addInventoryItem(uint16 item);
+int16 getInventoryItemIndex(int16 pos);
void highlightInventoryItem(int16 pos, byte color);
-void refreshInventory(const char *character);
-
-void extractInventoryGraphics(int16 pos, byte *dst);
} // namespace Parallaction
diff --git a/engines/parallaction/location.cpp b/engines/parallaction/location.cpp
index 3c54460692..024938074b 100644
--- a/engines/parallaction/location.cpp
+++ b/engines/parallaction/location.cpp
@@ -25,6 +25,8 @@
#include "common/stdafx.h"
+#include "common/system.h"
+
#include "parallaction/parallaction.h"
#include "parallaction/sound.h"
@@ -249,7 +251,9 @@ void Parallaction::switchBackground(const char* background, const char* mask) {
_si += 3;
}
+ g_system->delayMillis(20);
_gfx->setPalette(pal);
+ _gfx->updateScreen();
}
_disk->loadScenery(background, mask);
@@ -371,6 +375,7 @@ void Parallaction::changeLocation(char *location) {
_gfx->copyScreen(Gfx::kBitBack, Gfx::kBitFront);
_gfx->copyScreen(Gfx::kBitBack, Gfx::kBit2);
_gfx->setBlackPalette();
+ _gfx->updateScreen();
if (_location._commands.size() > 0) {
runCommands(_location._commands);
@@ -419,7 +424,7 @@ void Parallaction::doLocationEnterTransition() {
}
byte pal[PALETTE_SIZE];
- _gfx->buildBWPalette(pal);
+ _gfx->makeGrayscalePalette(pal);
_gfx->setPalette(pal);
jobRunScripts(NULL, NULL);
@@ -447,9 +452,10 @@ void Parallaction::doLocationEnterTransition() {
// fades maximum intensity palette towards approximation of main palette
for (uint16 _si = 0; _si<6; _si++) {
- _gfx->quickFadePalette(pal);
+ _gfx->fadePalette(pal, _gfx->_palette, 4);
_gfx->setPalette(pal);
waitTime( 1 );
+ _gfx->updateScreen();
}
debugC(1, kDebugLocation, "doLocationEnterTransition completed");
diff --git a/engines/parallaction/menu.cpp b/engines/parallaction/menu.cpp
index 427f24a467..12b03ab4b0 100644
--- a/engines/parallaction/menu.cpp
+++ b/engines/parallaction/menu.cpp
@@ -87,14 +87,15 @@ const char *loadGameMsg[] = {
#define SLOT_Y 64
#define SLOT_WIDTH (BLOCK_WIDTH+2)
+#define PASSWORD_LEN 6
-static uint16 _amigaDinoKey[] = { 5, 3, 6, 2, 2, 7 };
-static uint16 _amigaDonnaKey[] = { 0, 3, 6, 2, 2, 6 };
-static uint16 _amigaDoughKey[] = { 1, 3 ,7, 2, 4, 6 };
+static uint16 _amigaDinoKey[PASSWORD_LEN] = { 5, 3, 6, 2, 2, 7 };
+static uint16 _amigaDonnaKey[PASSWORD_LEN] = { 0, 3, 6, 2, 2, 6 };
+static uint16 _amigaDoughKey[PASSWORD_LEN] = { 1, 3 ,7, 2, 4, 6 };
-static uint16 _pcDinoKey[] = { 5, 3, 6, 1, 4, 7 };
-static uint16 _pcDonnaKey[] = { 0, 2, 8, 5, 5, 1 };
-static uint16 _pcDoughKey[] = { 1, 7 ,7, 2, 2, 6 };
+static uint16 _pcDinoKey[PASSWORD_LEN] = { 5, 3, 6, 1, 4, 7 };
+static uint16 _pcDonnaKey[PASSWORD_LEN] = { 0, 2, 8, 5, 5, 1 };
+static uint16 _pcDoughKey[PASSWORD_LEN] = { 1, 7 ,7, 2, 2, 6 };
Menu::Menu(Parallaction *vm) {
@@ -130,11 +131,13 @@ void Menu::splash() {
_vm->_disk->loadSlide("intro");
_vm->_gfx->setPalette(_vm->_gfx->_palette);
_vm->_gfx->copyScreen(Gfx::kBitBack, Gfx::kBitFront);
+ _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->_gfx->updateScreen();
g_system->delayMillis(2000);
}
@@ -161,15 +164,16 @@ void Menu::newGame() {
_vm->_gfx->displayCenteredString(100, v14[2]);
_vm->_gfx->displayCenteredString(120, v14[3]);
+ _vm->showCursor(false);
+
_vm->_gfx->updateScreen();
- _vm->_gfx->copyScreen(Gfx::kBitFront, Gfx::kBitBack);
_mouseButtons = kMouseNone;
-
- for (; _mouseButtons != kMouseLeftUp; ) {
+ do {
_vm->updateInput();
- if (_mouseButtons == kMouseRightUp) break;
- }
+ } while (_mouseButtons != kMouseLeftUp && _mouseButtons != kMouseRightUp);
+
+ _vm->showCursor(true);
if (_mouseButtons != kMouseRightUp) {
strcpy(_vm->_location._name, "fogne");
@@ -203,14 +207,10 @@ uint16 Menu::chooseLanguage() {
_vm->_gfx->displayString(60, 30, "SELECT LANGUAGE", 1);
- _vm->_gfx->copyScreen(Gfx::kBitFront, Gfx::kBitBack);
- _vm->_gfx->copyScreen(Gfx::kBitBack, Gfx::kBit2);
-
_vm->changeCursor(kCursorArrow);
do {
_vm->updateInput();
- _vm->_gfx->swapBuffers();
if (_mouseButtons == kMouseLeftUp) {
for (uint16 _si = 0; _si < 4; _si++) {
@@ -242,7 +242,8 @@ uint16 Menu::chooseLanguage() {
}
}
- _vm->waitTime( 1 );
+ g_system->delayMillis(30);
+ _vm->_gfx->updateScreen();
} while (true);
@@ -261,41 +262,33 @@ uint16 Menu::selectGame() {
_vm->_disk->loadSlide("restore");
_vm->_gfx->setPalette(_vm->_gfx->_palette);
- _vm->_gfx->copyScreen(Gfx::kBitBack, Gfx::kBitFront);
-
- _vm->_gfx->copyScreen(Gfx::kBitBack, Gfx::kBit2);
-
uint16 _si = 0;
uint16 _di = 3;
- _vm->updateInput();
+ _mouseButtons = kMouseNone;
while (_mouseButtons != kMouseLeftUp) {
_vm->updateInput();
- _vm->_gfx->swapBuffers();
- _vm->waitTime( 1 );
- _si = 0;
- if (_vm->_mousePos.x > 160)
- _si = 1;
+ _si = (_vm->_mousePos.x > 160) ? 1 : 0;
- if (_si == _di) continue;
+ if (_si != _di) {
+ _di = _si;
- _di = _si;
- _vm->_gfx->copyScreen(Gfx::kBit2, Gfx::kBitFront);
+ _vm->_gfx->copyScreen(Gfx::kBitBack, Gfx::kBitFront);
+ if (_si != 0) {
+ // load a game
+ _vm->_gfx->displayString(60, 30, loadGameMsg[_language], 1);
+ } else {
+ // new game
+ _vm->_gfx->displayString(60, 30, newGameMsg[_language], 1);
+ }
- if (_si != 0) {
- // load a game
- _vm->_gfx->displayString(60, 30, loadGameMsg[_language], 1);
- } else {
- // new game
- _vm->_gfx->displayString(60, 30, newGameMsg[_language], 1);
}
+ g_system->delayMillis(30);
_vm->_gfx->updateScreen();
- _vm->_gfx->copyScreen(Gfx::kBitFront, Gfx::kBitBack);
-
}
if (_si == 0) return 0; // new game
@@ -316,6 +309,30 @@ uint16 Menu::selectGame() {
}
+int Menu::getSelectedBlock(const Common::Point &p, Common::Rect &r) {
+
+ for (uint16 _si = 0; _si < 9; _si++) {
+
+ Common::Rect q(
+ _si * BLOCK_X_OFFSET + BLOCK_SELECTION_X,
+ BLOCK_SELECTION_Y - _si * BLOCK_Y_OFFSET,
+ (_si + 1) * BLOCK_X_OFFSET + BLOCK_SELECTION_X,
+ BLOCK_SELECTION_Y + BLOCK_HEIGHT - _si * BLOCK_Y_OFFSET
+ );
+
+ if (q.contains(p)) {
+ r.setWidth(BLOCK_WIDTH);
+ r.setHeight(BLOCK_HEIGHT);
+ r.moveTo(_si * BLOCK_X_OFFSET + BLOCK_X, BLOCK_Y - _si * BLOCK_Y_OFFSET);
+ return _si;
+ }
+
+ }
+
+ return -1;
+}
+
+
//
// character selection and protection
//
@@ -323,11 +340,8 @@ void Menu::selectCharacter() {
debugC(1, kDebugMenu, "Menu::selectCharacter()");
uint16 _di = 0;
- bool askPassword = true;
- uint16 _donna_points = 0;
- uint16 _dino_points = 0;
- uint16 _dough_points = 0;
+ uint16 _donna_points, _dino_points, _dough_points;
StaticCnv v14;
@@ -343,51 +357,34 @@ void Menu::selectCharacter() {
_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->copyScreen(Gfx::kBitBack, Gfx::kBit2); //
+
_vm->_gfx->setPalette(_vm->_gfx->_palette);
- while (askPassword == true) {
+ while (true) {
- askPassword = false;
_di = 0;
_vm->_gfx->displayString(60, 30, introMsg1[_language], 1); // displays message
- _vm->_gfx->copyScreen(Gfx::kBitFront, Gfx::kBitBack);
_donna_points = 0;
_dino_points = 0;
_dough_points = 0;
- while (_di < 6) {
+ while (_di < PASSWORD_LEN) {
_mouseButtons = kMouseNone;
do {
_vm->updateInput();
- _vm->_gfx->swapBuffers();
- _vm->waitTime(1);
+ g_system->delayMillis(30);
+ _vm->_gfx->updateScreen();
} while (_mouseButtons != kMouseLeftUp); // waits for left click
- for (uint16 _si = 0; _si < 9; _si++) {
-
- Common::Rect r(
- _si * BLOCK_X_OFFSET + BLOCK_SELECTION_X,
- BLOCK_SELECTION_Y - _si * BLOCK_Y_OFFSET,
- (_si + 1) * BLOCK_X_OFFSET + BLOCK_SELECTION_X,
- BLOCK_SELECTION_Y + BLOCK_HEIGHT - _si * BLOCK_Y_OFFSET
- );
-
- if (!r.contains(_vm->_mousePos)) continue;
-
- r.setWidth(BLOCK_WIDTH);
- r.setHeight(BLOCK_HEIGHT);
- r.moveTo(_si * BLOCK_X_OFFSET + BLOCK_X, BLOCK_Y - _si * BLOCK_Y_OFFSET);
+ Common::Rect r;
+ int _si = getSelectedBlock(_vm->_mousePos, r);
+ if (_si != -1) {
_vm->_gfx->grabRect(v14._data0, r, Gfx::kBitFront, BLOCK_WIDTH);
-
- _vm->_gfx->flatBlitCnv(&v14, _di * SLOT_WIDTH + SLOT_X, SLOT_Y, Gfx::kBitBack);
_vm->_gfx->flatBlitCnv(&v14, _di * SLOT_WIDTH + SLOT_X, SLOT_Y, Gfx::kBitFront);
-
// beep();
if (_vm->getPlatform() == Common::kPlatformAmiga && (_vm->getFeatures() & GF_LANG_MULT)) {
@@ -408,33 +405,33 @@ void Menu::selectCharacter() {
_di++;
}
-
- askPassword = (_dino_points < 6 && _donna_points < 6 && _dough_points < 6);
}
- if (askPassword == false) break;
+ if (_dino_points == PASSWORD_LEN || _donna_points == PASSWORD_LEN || _dough_points == PASSWORD_LEN) {
+ break;
+ }
- _vm->_gfx->copyScreen(Gfx::kBit2, Gfx::kBitFront);
+ _vm->_gfx->copyScreen(Gfx::kBitBack, Gfx::kBitFront);
_vm->_gfx->displayString(60, 30, introMsg2[_language], 1);
_vm->_gfx->updateScreen();
g_system->delayMillis(2000);
- _vm->_gfx->copyScreen(Gfx::kBit2, Gfx::kBitFront);
+ _vm->_gfx->copyScreen(Gfx::kBitBack, Gfx::kBitFront);
}
-
- if (_dino_points > _donna_points && _dino_points > _dough_points) {
+ if (_dino_points == PASSWORD_LEN) {
sprintf(_vm->_location._name, "test.%s", _dinoName);
- } else {
- if (_donna_points > _dino_points && _donna_points > _dough_points) {
- sprintf(_vm->_location._name, "test.%s", _donnaName);
- } else {
- sprintf(_vm->_location._name, "test.%s", _doughName);
- }
+ } else
+ if (_donna_points == PASSWORD_LEN) {
+ sprintf(_vm->_location._name, "test.%s", _donnaName);
+ } else
+ if (_dough_points == PASSWORD_LEN) {
+ sprintf(_vm->_location._name, "test.%s", _doughName);
}
_vm->_gfx->setBlackPalette();
+ _vm->_gfx->updateScreen();
_engineFlags |= kEngineChangeLocation;
diff --git a/engines/parallaction/menu.h b/engines/parallaction/menu.h
index a0b8b95371..bb9eabdfb7 100644
--- a/engines/parallaction/menu.h
+++ b/engines/parallaction/menu.h
@@ -48,6 +48,7 @@ protected:
void newGame();
uint16 chooseLanguage();
uint16 selectGame();
+ int getSelectedBlock(const Common::Point &p, Common::Rect& r);
public:
diff --git a/engines/parallaction/module.mk b/engines/parallaction/module.mk
index 592c0cb6a3..b7f60eeb32 100644
--- a/engines/parallaction/module.mk
+++ b/engines/parallaction/module.mk
@@ -2,21 +2,23 @@ MODULE := engines/parallaction
MODULE_OBJS := \
animation.o \
- archive.o \
- callables.o \
+ callables_br.o \
+ callables_ns.o \
commands.o \
debug.o \
detection.o \
dialogue.o \
- disk.o \
+ disk_br.o \
+ disk_ns.o \
font.o \
graphics.o \
- intro.o \
inventory.o \
location.o \
menu.o \
parser.o \
parallaction.o \
+ parallaction_br.o \
+ parallaction_ns.o \
saveload.o \
sound.o \
staticres.o \
diff --git a/engines/parallaction/parallaction.cpp b/engines/parallaction/parallaction.cpp
index c830b575a9..986bc6ebd7 100644
--- a/engines/parallaction/parallaction.cpp
+++ b/engines/parallaction/parallaction.cpp
@@ -146,73 +146,40 @@ Parallaction::~Parallaction() {
int Parallaction::init() {
- // Detect game
- if (!detectGame()) {
- GUIErrorMessage("No valid games were found in the specified directory.");
- return -1;
- }
-
+ _engineFlags = 0;
_objectsNames = NULL;
_globalTable = NULL;
- _localFlagNames = NULL;
- initResources();
-
_hasLocationSound = false;
-
_skipMenu = false;
-
_transCurrentHoverItem = 0;
_actionAfterWalk = false; // actived when the character needs to move before taking an action
_activeItem._index = 0;
_activeItem._id = 0;
_procCurrentHoverItem = -1;
-
-// _musicData1 = 0;
- strcpy(_characterName1, "null");
-
- _soundMan = 0;
-
_baseTime = 0;
-
- if (getPlatform() == Common::kPlatformPC) {
- _disk = new DosDisk(this);
- } else {
- if (getFeatures() & GF_DEMO) {
- strcpy(_location._name, "fognedemo");
- }
- _disk = new AmigaDisk(this);
- _disk->selectArchive((_vm->getFeatures() & GF_DEMO) ? "disk0" : "disk1");
- }
-
- _engineFlags = 0;
-
- strcpy(_characterName, "dough");
-
- memset(_locationNames, 0, 120*32);
_numLocations = 0;
-
_location._startPosition.x = -1000;
_location._startPosition.y = -1000;
_location._startFrame = 0;
-
_location._comment = NULL;
_location._endComment = NULL;
- initWalk();
+ _screenMaskWidth = _screenWidth / 4;
+ _screenPathWidth = _screenWidth / 8;
+ _screenSize = _screenWidth * _screenHeight;
+ _screenMaskSize = _screenMaskWidth * _screenHeight;
+ _screenPathSize = _screenPathWidth * _screenHeight;
- initInventory();
+ strcpy(_characterName1, "null");
+ strcpy(_characterName, "dough");
- _animations.push_front(&_vm->_char._ani);
- _gfx = new Gfx(this);
+ memset(_locationNames, 0, 120*32);
- if (getPlatform() == Common::kPlatformPC) {
- int midiDriver = MidiDriver::detectMusicDriver(MDT_MIDI | MDT_ADLIB | MDT_PREFER_MIDI);
- MidiDriver *driver = MidiDriver::createMidi(midiDriver);
- _soundMan = new DosSoundMan(this, driver);
- _soundMan->setMusicVolume(ConfMan.getInt("music_volume"));
- } else {
- _soundMan = new AmigaSoundMan(this);
- }
+ initWalk(); // needs to be pushed into subclass
+ initInventory(); // needs to be pushed into subclass
+
+ _animations.push_front(&_char._ani);
+ _gfx = new Gfx(this);
_debugger = new Debugger(this);
@@ -252,9 +219,9 @@ void Parallaction::initGame() {
parseLocation(_location._name);
if (_location._startPosition.x != -1000) {
- _vm->_char._ani._left = _location._startPosition.x;
- _vm->_char._ani._top = _location._startPosition.y;
- _vm->_char._ani._frame = _location._startFrame;
+ _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;
}
@@ -346,7 +313,8 @@ void waitUntilLeftClick() {
break;
}
- g_system->delayMillis(10);
+ _vm->_gfx->updateScreen();
+ g_system->delayMillis(30);
}
@@ -498,9 +466,9 @@ void Parallaction::processInput(InputData *data) {
debugC(2, kDebugInput, "processInput: kEvWalk");
_hoverZone = NULL;
changeCursor(kCursorArrow);
- if (_vm->_char._ani._flags & kFlagsRemove) break;
- if ((_vm->_char._ani._flags & kFlagsActive) == 0) break;
- WalkNodeList *v4 = _vm->_char._builder.buildPath(data->_mousePos.x, data->_mousePos.y);
+ 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);
_engineFlags |= kEngineWalking; // inhibits processing of input until walking is over
}
@@ -716,27 +684,27 @@ void Parallaction::changeCursor(int32 index) {
void Parallaction::freeCharacter() {
debugC(3, kDebugLocation, "freeCharacter()");
- if (!IS_DUMMY_CHARACTER(_vm->_characterName)) {
+ if (!IS_DUMMY_CHARACTER(_characterName)) {
if (_objectsNames)
delete _objectsNames;
_objectsNames = NULL;
- if (_vm->_char._ani._cnv)
- delete _vm->_char._ani._cnv;
- _vm->_char._ani._cnv = NULL;
+ if (_char._ani._cnv)
+ delete _char._ani._cnv;
+ _char._ani._cnv = NULL;
- if (_vm->_char._talk)
- delete _vm->_char._talk;
- _vm->_char._talk = NULL;
+ if (_char._talk)
+ delete _char._talk;
+ _char._talk = NULL;
- _vm->_gfx->freeStaticCnv(_vm->_char._head);
- if (_vm->_char._head)
- delete _vm->_char._head;
- _vm->_char._head = NULL;
+ _gfx->freeStaticCnv(_char._head);
+ if (_char._head)
+ delete _char._head;
+ _char._head = NULL;
- if (_vm->_char._objs)
- delete _vm->_char._objs;
- _vm->_char._objs = NULL;
+ if (_char._objs)
+ delete _char._objs;
+ _char._objs = NULL;
}
return;
@@ -763,18 +731,17 @@ void Parallaction::changeCharacter(const char *name) {
// character for sanity before memory is freed
freeCharacter();
- Common::String oldArchive = _disk->selectArchive((_vm->getFeatures() & GF_LANG_MULT) ? "disk1" : "disk0");
- _vm->_char._ani._cnv = _disk->loadFrames(fullName);
+ Common::String oldArchive = _disk->selectArchive((getFeatures() & GF_LANG_MULT) ? "disk1" : "disk0");
+ _char._ani._cnv = _disk->loadFrames(fullName);
if (!IS_DUMMY_CHARACTER(name)) {
- if (_vm->getPlatform() == Common::kPlatformAmiga && (_vm->getFeatures() & GF_LANG_MULT))
+ if (getPlatform() == Common::kPlatformAmiga && (getFeatures() & GF_LANG_MULT))
_disk->selectArchive("disk0");
- _vm->_char._head = _disk->loadHead(baseName);
- _vm->_char._talk = _disk->loadTalk(baseName);
- _vm->_char._objs = _disk->loadObjects(baseName);
+ _char._head = _disk->loadHead(baseName);
+ _char._talk = _disk->loadTalk(baseName);
+ _char._objs = _disk->loadObjects(baseName);
_objectsNames = _disk->loadTable(baseName);
- refreshInventory(baseName);
_soundMan->playCharacterMusic(name);
diff --git a/engines/parallaction/parallaction.h b/engines/parallaction/parallaction.h
index 561b15acc9..31b125c92a 100644
--- a/engines/parallaction/parallaction.h
+++ b/engines/parallaction/parallaction.h
@@ -43,6 +43,7 @@ namespace GUI {
class CommandSender;
}
+extern OSystem *g_system;
namespace Parallaction {
@@ -159,11 +160,6 @@ public:
typedef Job* JobPointer;
typedef ManagedList<JobPointer> JobList;
-struct Credit {
- const char *_role;
- const char *_name;
-};
-
typedef void (*callable)(void*);
extern uint16 _mouseButtons;
@@ -181,8 +177,6 @@ extern uint16 _introSarcData3; // sarcophagus stuff to be saved
extern uint16 _introSarcData2; // sarcophagus stuff to be saved
extern char _saveData1[];
extern uint32 _commandFlags;
-extern const char *_instructionNamesRes[];
-extern const char *_commandsNamesRes[];
extern const char *_dinoName;
extern const char *_donnaName;
extern const char *_doughName;
@@ -360,6 +354,16 @@ private:
const PARALLACTIONGameDescription *_gameDescription;
public:
+ // info
+ int32 _screenWidth;
+ int32 _screenHeight;
+ int32 _screenSize;
+
+ int32 _screenMaskWidth;
+ int32 _screenMaskSize;
+ int32 _screenPathWidth;
+ int32 _screenPathSize;
+
SoundMan *_soundMan;
Gfx* _gfx;
@@ -424,7 +428,6 @@ protected: // members
void initGame();
void initGlobals();
- void initResources();
void runGame();
uint32 getElapsedTime();
void resetTimer();
@@ -467,6 +470,103 @@ protected: // members
int16 pickupItem(Zone *z);
int16 isItemInInventory(int32 v);
int16 getHoverInventoryItem(int16 x, int16 y);
+
+public:
+ virtual void callFunction(uint index, void* parm) { }
+
+public:
+ const char **_zoneFlagNamesRes;
+ const char **_zoneTypeNamesRes;
+ const char **_commandsNamesRes;
+ const char **_callableNamesRes;
+ const char **_instructionNamesRes;
+
+};
+
+class Parallaction_ns : public Parallaction {
+
+public:
+ Parallaction_ns(OSystem* syst) : Parallaction(syst) { }
+ ~Parallaction_ns() { }
+
+ int init();
+
+public:
+ typedef void (Parallaction_ns::*Callable)(void*);
+
+ virtual void callFunction(uint index, void* parm);
+
+private:
+ void initResources();
+
+ static const Callable _dosCallables[25];
+ static const Callable _amigaCallables[25];
+
+ // common callables
+ void _c_play_boogie(void*);
+ void _c_startIntro(void*);
+ void _c_endIntro(void*);
+ void _c_moveSheet(void*);
+ void _c_sketch(void*);
+ void _c_shade(void*);
+ void _c_score(void*);
+ void _c_fade(void*);
+ void _c_moveSarc(void*);
+ void _c_contaFoglie(void*);
+ void _c_zeroFoglie(void*);
+ void _c_trasformata(void*);
+ void _c_offMouse(void*);
+ void _c_onMouse(void*);
+ void _c_setMask(void*);
+ void _c_endComment(void*);
+ void _c_frankenstein(void*);
+ void _c_finito(void*);
+ void _c_ridux(void*);
+ void _c_testResult(void*);
+
+ // dos specific callables
+ void _c_null(void*);
+
+ // amiga specific callables
+ void _c_projector(void*);
+ void _c_HBOff(void*);
+ void _c_offSound(void*);
+ void _c_startMusic(void*);
+ void _c_closeMusic(void*);
+ void _c_HBOn(void*);
+
+ const Callable *_callables;
+};
+
+class Parallaction_br : public Parallaction {
+
+public:
+ Parallaction_br(OSystem* syst) : Parallaction(syst) { }
+ ~Parallaction_br() { }
+
+ int init();
+
+public:
+ typedef void (Parallaction_br::*Callable)(void*);
+ virtual void callFunction(uint index, void* parm);
+
+public:
+ Table *_audioCommandsNames;
+ const char **_audioCommandsNamesRes;
+
+private:
+ void initResources();
+
+ static const Callable _dosCallables[6];
+
+ void _c_blufade(void*);
+ void _c_resetpalette(void*);
+ void _c_ferrcycle(void*);
+ void _c_lipsinc(void*);
+ void _c_albcycle(void*);
+ void _c_password(void*);
+
+ const Callable *_callables;
};
// FIXME: remove global
diff --git a/engines/parallaction/parallaction_br.cpp b/engines/parallaction/parallaction_br.cpp
new file mode 100644
index 0000000000..7dcc94d7c6
--- /dev/null
+++ b/engines/parallaction/parallaction_br.cpp
@@ -0,0 +1,66 @@
+/* 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 {
+
+int Parallaction_br::init() {
+
+ // Detect game
+ if (!detectGame()) {
+ GUIErrorMessage("No valid games were found in the specified directory.");
+ return -1;
+ }
+
+ _screenWidth = 640;
+ _screenHeight = 400;
+
+ if (getGameType() == GType_BRA) {
+ if (getPlatform() == Common::kPlatformPC) {
+ _disk = new DosDisk_br(this);
+ } else
+ error("unsupported platform for Big Red Adventure");
+ } else
+ error("unknown game type");
+
+ _soundMan = new DummySoundMan(this);
+
+ initResources();
+
+ Parallaction::init();
+
+ return 0;
+}
+
+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);
+}
+
+} // namespace Parallaction
diff --git a/engines/parallaction/parallaction_ns.cpp b/engines/parallaction/parallaction_ns.cpp
new file mode 100644
index 0000000000..947cb22a7f
--- /dev/null
+++ b/engines/parallaction/parallaction_ns.cpp
@@ -0,0 +1,78 @@
+/* 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/config-manager.h"
+
+#include "parallaction/parallaction.h"
+#include "parallaction/sound.h"
+
+namespace Parallaction {
+
+int Parallaction_ns::init() {
+
+ // Detect game
+ if (!detectGame()) {
+ GUIErrorMessage("No valid games were found in the specified directory.");
+ return -1;
+ }
+
+ _screenWidth = 320;
+ _screenHeight = 200;
+
+ if (getPlatform() == Common::kPlatformPC) {
+ _disk = new DosDisk_ns(this);
+ } else {
+ if (getFeatures() & GF_DEMO) {
+ strcpy(_location._name, "fognedemo");
+ }
+ _disk = new AmigaDisk_ns(this);
+ _disk->selectArchive((getFeatures() & GF_DEMO) ? "disk0" : "disk1");
+ }
+
+ if (getPlatform() == Common::kPlatformPC) {
+ int midiDriver = MidiDriver::detectMusicDriver(MDT_MIDI | MDT_ADLIB | MDT_PREFER_MIDI);
+ MidiDriver *driver = MidiDriver::createMidi(midiDriver);
+ _soundMan = new DosSoundMan(this, driver);
+ _soundMan->setMusicVolume(ConfMan.getInt("music_volume"));
+ } else {
+ _soundMan = new AmigaSoundMan(this);
+ }
+
+ initResources();
+
+ Parallaction::init();
+
+ return 0;
+}
+
+void Parallaction_ns::callFunction(uint index, void* parm) {
+ assert(index < 25); // magic value 25 is maximum # of callables for Nippon Safes
+
+ (this->*_callables[index])(parm);
+}
+
+
+} // namespace Parallaction
diff --git a/engines/parallaction/saveload.cpp b/engines/parallaction/saveload.cpp
index 2a9431ef94..279dbda1b9 100644
--- a/engines/parallaction/saveload.cpp
+++ b/engines/parallaction/saveload.cpp
@@ -166,8 +166,6 @@ void Parallaction::doLoadGame(uint16 slot) {
// freeTable(_objectsNames);
// initTable(filename, _objectsNames);
-// refreshInventory(_vm->_characterName);
-
// parseLocation("common");
// force reload of character to solve inventory
@@ -238,11 +236,7 @@ void Parallaction::doSaveGame(uint16 slot, const char* name) {
delete f;
- refreshInventory(_characterName);
-
return;
-
-
}
enum {
diff --git a/engines/parallaction/sound.cpp b/engines/parallaction/sound.cpp
index 13b989e202..21dcc3c788 100644
--- a/engines/parallaction/sound.cpp
+++ b/engines/parallaction/sound.cpp
@@ -379,7 +379,7 @@ void AmigaSoundMan::playMusic() {
debugC(1, kDebugAudio, "AmigaSoundMan::playMusic()");
- Common::ReadStream *stream = _vm->_disk->loadMusic(_musicFile);
+ Common::SeekableReadStream *stream = _vm->_disk->loadMusic(_musicFile);
_musicStream = Audio::makeProtrackerStream(stream);
delete stream;
diff --git a/engines/parallaction/sound.h b/engines/parallaction/sound.h
index f244bd4070..7a903ec790 100644
--- a/engines/parallaction/sound.h
+++ b/engines/parallaction/sound.h
@@ -108,6 +108,22 @@ public:
void playLocationMusic(const char *location);
};
+class DummySoundMan : public SoundMan {
+
+public:
+ DummySoundMan(Parallaction *vm) : SoundMan(vm) { }
+ ~DummySoundMan() { }
+ void playMusic() { }
+ void stopMusic() { }
+
+ void playSfx(const char *filename, uint channel, bool looping, int volume, int rate) { }
+ void stopSfx(uint channel) { }
+
+ void playCharacterMusic(const char *character) { }
+ void playLocationMusic(const char *location) { }
+
+};
+
} // namespace Parallaction
#endif
diff --git a/engines/parallaction/staticres.cpp b/engines/parallaction/staticres.cpp
index e6cbc303b0..046176a933 100644
--- a/engines/parallaction/staticres.cpp
+++ b/engines/parallaction/staticres.cpp
@@ -219,7 +219,7 @@ byte _amigaTopazFont[2600] =
-const char *_zoneFlagNamesRes[] = {
+const char *_zoneFlagNamesRes_ns[] = {
"closed",
"active",
"remove",
@@ -234,7 +234,7 @@ const char *_zoneFlagNamesRes[] = {
"nowalk"
};
-const char *_zoneTypeNamesRes[] = {
+const char *_zoneTypeNamesRes_ns[] = {
"examine",
"door",
"get",
@@ -262,7 +262,7 @@ const char _gameNames[10][20] = {
"GAME10"
};
-const char *_commandsNamesRes[] = {
+const char *_commandsNamesRes_ns[] = {
"set",
"clear",
"start",
@@ -281,7 +281,7 @@ const char *_commandsNamesRes[] = {
"stop"
};
-const char *_instructionNamesRes[] = {
+const char *_instructionNamesRes_ns[] = {
"on",
"off",
"x",
@@ -302,7 +302,7 @@ const char *_instructionNamesRes[] = {
"move"
};
-const char *_callableNamesRes[] = {
+const char *_callableNamesRes_ns[] = {
"Projector",
"HBOff",
"StartIntro",
@@ -330,48 +330,146 @@ const char *_callableNamesRes[] = {
"TestResult"
};
-typedef void (*callable)(void*);
-
-
-void _c_play_boogie(void*);
-void _c_startIntro(void*);
-void _c_endIntro(void*);
-void _c_moveSheet(void*);
-void _c_sketch(void*);
-void _c_shade(void*);
-void _c_score(void*);
-void _c_fade(void*);
-void _c_moveSarc(void*);
-void _c_contaFoglie(void*);
-void _c_zeroFoglie(void*);
-void _c_trasformata(void*);
-void _c_offMouse(void*);
-void _c_onMouse(void*);
-void _c_setMask(void*);
-void _c_endComment(void*);
-void _c_frankenstein(void*);
-void _c_finito(void*);
-void _c_ridux(void*);
-void _c_testResult(void*);
-void _c_null(void*);
-
-void _c_projector(void*);
-void _c_HBOff(void*);
-void _c_offSound(void*);
-void _c_startMusic(void*);
-void _c_closeMusic(void*);
-void _c_HBOn(void*);
-
-callable _callables[25];
-
-
-Credit _credits[] = {
- {"Music and Sound Effects", "MARCO CAPRELLI"},
- {"PC Version", "RICCARDO BALLARINO"},
- {"Project Manager", "LOVRANO CANEPA"},
- {"Production", "BRUNO BOZ"},
- {"Special Thanks to", "LUIGI BENEDICENTI - GILDA and DANILO"},
- {"Copyright 1992 Euclidea s.r.l ITALY", "All rights reserved"}
+const char *_zoneTypeNamesRes_br[] = {
+ "examine",
+ "door",
+ "get",
+ "merge",
+ "taste",
+ "hear",
+ "feel",
+ "speak",
+ "none",
+ "trap",
+ "you",
+ "command",
+ "path",
+ "box"
+};
+
+const char *_zoneFlagNamesRes_br[] = {
+ "closed",
+ "active",
+ "remove",
+ "acting",
+ "locked",
+ "fixed",
+ "noname",
+ "nomasked",
+ "looping",
+ "added",
+ "character",
+ "nowalk",
+ "yourself",
+ "scaled",
+ "selfuse"
+};
+
+const char *_instructionNamesRes_br[] = {
+ "on",
+ "off",
+ "x",
+ "y",
+ "z",
+ "f",
+ "loop",
+ "endloop",
+ "show",
+ "inc",
+ "dec",
+ "set",
+ "put",
+ "call",
+ "wait",
+ "start",
+ "process",
+ "move",
+ "color",
+ "sound",
+ "mask",
+ "print",
+ "text",
+ "mul",
+ "div",
+ "if",
+ "ifeq",
+ "iflt",
+ "ifgt",
+ "endif",
+ "stop"
+};
+
+const char *_commandsNamesRes_br[] = {
+ "set",
+ "clear",
+ "start",
+ "speak",
+ "get"
+ "location",
+ "open",
+ "close",
+ "on",
+ "off",
+ "call",
+ "toggle",
+ "drop",
+ "quit",
+ "move",
+ "stop",
+ "character",
+ "followme",
+ "onmouse",
+ "offmouse",
+ "add",
+ "leave",
+ "inc",
+ "dec",
+ "text",
+ "dummy",
+ "dummy",
+ "let",
+ "music",
+ "fix",
+ "unfix",
+ "zeta",
+ "scroll",
+ "swap",
+ "give",
+ "text",
+ "part",
+ "dummy",
+ "return",
+ "onsave",
+ "offsave"
+};
+
+const char *_callableNamesRes_br[] = {
+ "blufade",
+ "resetpalette",
+ "ferrcycle",
+ "lipsinc",
+ "albycle",
+ "password"
+};
+
+const char *_audioCommandsNamesRes_br[] = {
+ "play",
+ "stop",
+ "pause",
+ "channel_level",
+ "fadein",
+ "fadeout",
+ "volume",
+ " ",
+ "faderate",
+ " ",
+ " ",
+ " ",
+ " ",
+ " ",
+ " ",
+ " ",
+ "loop"
};
const char *_dinoName = "dino";
@@ -384,73 +482,124 @@ const char *_minidonnaName = "minidonna";
const char *_minidoughName = "minidough";
const char *_minidrkiName = "minidrki";
+#define CALLABLE_NS(x) &Parallaction_ns::x
+
+const Parallaction_ns::Callable Parallaction_ns::_dosCallables[] = {
+ CALLABLE_NS(_c_play_boogie),
+ CALLABLE_NS(_c_play_boogie),
+ CALLABLE_NS(_c_startIntro),
+ CALLABLE_NS(_c_endIntro),
+ CALLABLE_NS(_c_moveSheet),
+ CALLABLE_NS(_c_sketch),
+ CALLABLE_NS(_c_shade),
+ CALLABLE_NS(_c_score),
+ CALLABLE_NS(_c_null),
+ CALLABLE_NS(_c_null),
+ CALLABLE_NS(_c_null),
+ CALLABLE_NS(_c_fade),
+ CALLABLE_NS(_c_play_boogie),
+ CALLABLE_NS(_c_moveSarc),
+ CALLABLE_NS(_c_contaFoglie),
+ CALLABLE_NS(_c_zeroFoglie),
+ CALLABLE_NS(_c_trasformata),
+ CALLABLE_NS(_c_offMouse),
+ CALLABLE_NS(_c_onMouse),
+ CALLABLE_NS(_c_setMask),
+ CALLABLE_NS(_c_endComment),
+ CALLABLE_NS(_c_frankenstein),
+ CALLABLE_NS(_c_finito),
+ CALLABLE_NS(_c_ridux),
+ CALLABLE_NS(_c_testResult)
+};
+
+const Parallaction_ns::Callable Parallaction_ns::_amigaCallables[] = {
+ CALLABLE_NS(_c_projector),
+ CALLABLE_NS(_c_HBOff),
+ CALLABLE_NS(_c_startIntro),
+ CALLABLE_NS(_c_endIntro),
+ CALLABLE_NS(_c_moveSheet),
+ CALLABLE_NS(_c_sketch),
+ CALLABLE_NS(_c_shade),
+ CALLABLE_NS(_c_score),
+ CALLABLE_NS(_c_offSound),
+ CALLABLE_NS(_c_startMusic),
+ CALLABLE_NS(_c_closeMusic),
+ CALLABLE_NS(_c_fade),
+ CALLABLE_NS(_c_play_boogie),
+ CALLABLE_NS(_c_moveSarc),
+ CALLABLE_NS(_c_contaFoglie),
+ CALLABLE_NS(_c_zeroFoglie),
+ CALLABLE_NS(_c_trasformata),
+ CALLABLE_NS(_c_offMouse),
+ CALLABLE_NS(_c_onMouse),
+ CALLABLE_NS(_c_setMask),
+ CALLABLE_NS(_c_endComment),
+ CALLABLE_NS(_c_frankenstein),
+ CALLABLE_NS(_c_finito),
+ CALLABLE_NS(_c_ridux),
+ CALLABLE_NS(_c_testResult)
+};
+
+#define CALLABLE_BR(x) &Parallaction_br::x
+
+const Parallaction_br::Callable Parallaction_br::_dosCallables[] = {
+ CALLABLE_BR(_c_blufade),
+ CALLABLE_BR(_c_resetpalette),
+ CALLABLE_BR(_c_ferrcycle),
+ CALLABLE_BR(_c_lipsinc),
+ CALLABLE_BR(_c_albcycle),
+ CALLABLE_BR(_c_password)
+};
+
+void Parallaction_ns::initResources() {
-void Parallaction::initResources() {
+ _zoneFlagNamesRes = _zoneFlagNamesRes_ns;
+ _zoneTypeNamesRes = _zoneTypeNamesRes_ns;
+ _commandsNamesRes = _commandsNamesRes_ns;
+ _callableNamesRes = _callableNamesRes_ns;
+ _instructionNamesRes = _instructionNamesRes_ns;
- _callableNames = new Table(ARRAYSIZE(_callableNamesRes), _callableNamesRes);
- _instructionNames = new Table(ARRAYSIZE(_instructionNamesRes), _instructionNamesRes);
- _zoneFlagNames = new Table(ARRAYSIZE(_zoneFlagNamesRes), _zoneFlagNamesRes);
- _zoneTypeNames = new Table(ARRAYSIZE(_zoneTypeNamesRes), _zoneTypeNamesRes);
- _commandsNames = new Table(ARRAYSIZE(_commandsNamesRes), _commandsNamesRes);
+ _callableNames = new Table(ARRAYSIZE(_callableNamesRes_ns), _callableNamesRes_ns);
+ _instructionNames = new Table(ARRAYSIZE(_instructionNamesRes_ns), _instructionNamesRes_ns);
+ _zoneFlagNames = new Table(ARRAYSIZE(_zoneFlagNamesRes_ns), _zoneFlagNamesRes_ns);
+ _zoneTypeNames = new Table(ARRAYSIZE(_zoneTypeNamesRes_ns), _zoneTypeNamesRes_ns);
+ _commandsNames = new Table(ARRAYSIZE(_commandsNamesRes_ns), _commandsNamesRes_ns);
_localFlagNames = new Table(120);
_localFlagNames->addData("visited");
if (getPlatform() == Common::kPlatformPC) {
- _callables[0] = _c_play_boogie;
- _callables[1] = _c_play_boogie;
- _callables[2] = _c_startIntro;
- _callables[3] = _c_endIntro;
- _callables[4] = _c_moveSheet;
- _callables[5] = _c_sketch;
- _callables[6] = _c_shade;
- _callables[7] = _c_score;
- _callables[8] = _c_null;
- _callables[9] = _c_null;
- _callables[10] = _c_null;
- _callables[11] = _c_fade;
- _callables[12] = _c_play_boogie;
- _callables[13] = _c_moveSarc;
- _callables[14] = _c_contaFoglie;
- _callables[15] = _c_zeroFoglie;
- _callables[16] = _c_trasformata;
- _callables[17] = _c_offMouse;
- _callables[18] = _c_onMouse;
- _callables[19] = _c_setMask;
- _callables[20] = _c_endComment;
- _callables[21] = _c_frankenstein;
- _callables[22] = _c_finito;
- _callables[23] = _c_ridux;
- _callables[24] = _c_testResult;
+ _callables = _dosCallables;
} else {
- _callables[0] = _c_projector;
- _callables[1] = _c_HBOff;
- _callables[2] = _c_startIntro;
- _callables[3] = _c_endIntro;
- _callables[4] = _c_moveSheet;
- _callables[5] = _c_sketch;
- _callables[6] = _c_shade;
- _callables[7] = _c_score;
- _callables[8] = _c_offSound;
- _callables[9] = _c_startMusic;
- _callables[10] = _c_closeMusic;
- _callables[11] = _c_fade;
- _callables[12] = _c_HBOn;
- _callables[13] = _c_moveSarc;
- _callables[14] = _c_contaFoglie;
- _callables[15] = _c_zeroFoglie;
- _callables[16] = _c_trasformata;
- _callables[17] = _c_offMouse;
- _callables[18] = _c_onMouse;
- _callables[19] = _c_setMask;
- _callables[20] = _c_endComment;
- _callables[21] = _c_frankenstein;
- _callables[22] = _c_finito;
- _callables[23] = _c_ridux;
- _callables[24] = _c_testResult;
+ _callables = _amigaCallables;
}
}
+void Parallaction_br::initResources() {
+
+ _zoneFlagNamesRes = _zoneFlagNamesRes_br;
+ _zoneTypeNamesRes = _zoneTypeNamesRes_br;
+ _commandsNamesRes = _commandsNamesRes_br;
+ _callableNamesRes = _callableNamesRes_br;
+ _instructionNamesRes = _instructionNamesRes_br;
+ _audioCommandsNamesRes = _audioCommandsNamesRes_br;
+
+ _callableNames = new Table(ARRAYSIZE(_callableNamesRes_br), _callableNamesRes_br);
+ _instructionNames = new Table(ARRAYSIZE(_instructionNamesRes_br), _instructionNamesRes_br);
+ _zoneFlagNames = new Table(ARRAYSIZE(_zoneFlagNamesRes_br), _zoneFlagNamesRes_br);
+ _zoneTypeNames = new Table(ARRAYSIZE(_zoneTypeNamesRes_br), _zoneTypeNamesRes_br);
+ _commandsNames = new Table(ARRAYSIZE(_commandsNamesRes_br), _commandsNamesRes_br);
+ _audioCommandsNames = new Table(ARRAYSIZE(_audioCommandsNamesRes_br), _audioCommandsNamesRes_br);
+
+ // TODO: make sure there are 120 max locations in Big Red Adventure
+ _localFlagNames = new Table(120);
+ _localFlagNames->addData("visited");
+
+ if (getPlatform() == Common::kPlatformPC) {
+ _callables = _dosCallables;
+ }
+
+}
} // namespace Parallaction
diff --git a/engines/parallaction/walk.cpp b/engines/parallaction/walk.cpp
index 43ded244c5..d57e9d2532 100644
--- a/engines/parallaction/walk.cpp
+++ b/engines/parallaction/walk.cpp
@@ -41,7 +41,7 @@ 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::loadPath() instead of doing it here.
+ // 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));
@@ -59,11 +59,11 @@ void PathBuilder::correctPathPoint(Common::Point &to) {
int16 left = to.x;
do {
right++;
- } while ((queryPath(right, to.y) == 0) && (right < SCREEN_WIDTH));
+ } while ((queryPath(right, to.y) == 0) && (right < _vm->_screenWidth));
do {
left--;
} while ((queryPath(left, to.y) == 0) && (left > 0));
- right = (right == SCREEN_WIDTH) ? 1000 : right - to.x;
+ right = (right == _vm->_screenWidth) ? 1000 : right - to.x;
left = (left == 0) ? 1000 : to.x - left;
@@ -74,9 +74,9 @@ void PathBuilder::correctPathPoint(Common::Point &to) {
} while ((queryPath(to.x, top) == 0) && (top > 0));
do {
bottom++;
- } while ((queryPath(to.x, bottom) == 0) && (bottom < SCREEN_HEIGHT));
+ } while ((queryPath(to.x, bottom) == 0) && (bottom < _vm->_screenHeight));
top = (top == 0) ? 1000 : to.y - top;
- bottom = (bottom == SCREEN_HEIGHT) ? 1000 : bottom - to.y;
+ bottom = (bottom == _vm->_screenHeight) ? 1000 : bottom - to.y;
int16 closeX = (right >= left) ? left : right;
@@ -272,19 +272,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 < SCREEN_WIDTH) && (queryPath(_vm->_char._ani.width()/2 + pos.x + 2, _vm->_char._ani.height() + pos.y) != 0)) {
+ if ((pos.x < from->_x) && (pos.x < _screenWidth) && (queryPath(_char._ani.width()/2 + pos.x + 2, _char._ani.height() + pos.y) != 0)) {
pos.x = (pos.x + 2 < from->_x) ? pos.x + 2 : from->_x;
}
- if ((pos.x > from->_x) && (pos.x > -20) && (queryPath(_vm->_char._ani.width()/2 + pos.x - 2, _vm->_char._ani.height() + pos.y) != 0)) {
+ if ((pos.x > from->_x) && (pos.x > -20) && (queryPath(_char._ani.width()/2 + pos.x - 2, _char._ani.height() + pos.y) != 0)) {
pos.x = (pos.x - 2 > from->_x) ? pos.x - 2 : from->_x;
}
- if ((pos.y < from->_y) && (pos.y < (SCREEN_HEIGHT - _vm->_char._ani.height())) && (queryPath(_vm->_char._ani.width()/2 + pos.x, _vm->_char._ani.height() + pos.y + 2) != 0)) {
+ 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)) {
pos.y = (pos.y + 2 <= from->_y) ? pos.y + 2 : from->_y;
}
- if ((pos.y > from->_y) && (pos.y > -20) && (queryPath(_vm->_char._ani.width()/2 + pos.x, _vm->_char._ani.height() + pos.y- 2) != 0)) {
+ if ((pos.y > from->_y) && (pos.y > -20) && (queryPath(_char._ani.width()/2 + pos.x, _char._ani.height() + pos.y- 2) != 0)) {
pos.y = (pos.y - 2 >= from->_y) ? pos.y - 2 :from->_y;
}
@@ -304,7 +304,7 @@ int16 Parallaction::selectWalkFrame(const Common::Point& pos, const WalkNode* fr
// walk frame selection
int16 v16;
- if (_vm->_char._ani.getFrameNum() == 20) {
+ if (_char._ani.getFrameNum() == 20) {
if (dist.x > dist.y) {
walkData2 = (from->_x > pos.x) ? 0 : 7;
@@ -336,49 +336,49 @@ int16 Parallaction::selectWalkFrame(const Common::Point& pos, const WalkNode* fr
uint16 Parallaction::checkDoor() {
// printf("checkDoor()...");
- if (_vm->_currentLocationIndex != _doorData1) {
- _doorData1 = _vm->_currentLocationIndex;
+ if (_currentLocationIndex != _doorData1) {
+ _doorData1 = _currentLocationIndex;
_zoneTrap = NULL;
}
_engineFlags &= ~kEngineWalking;
- Zone *z = _vm->hitZone(kZoneDoor, _vm->_char._ani._left + _vm->_char._ani.width() / 2, _vm->_char._ani._top + _vm->_char._ani.height());
+ Zone *z = hitZone(kZoneDoor, _char._ani._left + _char._ani.width() / 2, _char._ani._top + _char._ani.height());
if (z != NULL) {
if ((z->_flags & kFlagsClosed) == 0) {
- _vm->_location._startPosition.x = z->u.door->_startPos.x;
- _vm->_location._startPosition.y = z->u.door->_startPos.y;
- _vm->_location._startFrame = z->u.door->_startFrame;
- strcpy( _vm->_location._name, z->u.door->_location );
+ _location._startPosition.x = z->u.door->_startPos.x;
+ _location._startPosition.y = z->u.door->_startPos.y;
+ _location._startFrame = z->u.door->_startFrame;
+ strcpy(_location._name, z->u.door->_location);
_engineFlags |= kEngineChangeLocation;
_zoneTrap = NULL;
} else {
- _vm->runCommands(z->_commands, z);
+ runCommands(z->_commands, z);
}
}
- z = _vm->hitZone(kZoneTrap, _vm->_char._ani._left + _vm->_char._ani.width() / 2, _vm->_char._ani._top + _vm->_char._ani.height());
+ z = hitZone(kZoneTrap, _char._ani._left + _char._ani.width() / 2, _char._ani._top + _char._ani.height());
if (z != NULL) {
- _localFlags[_vm->_currentLocationIndex] |= kFlagsEnter;
- _vm->runCommands(z->_commands, z);
- _localFlags[_vm->_currentLocationIndex] &= ~kFlagsEnter;
+ _localFlags[_currentLocationIndex] |= kFlagsEnter;
+ runCommands(z->_commands, z);
+ _localFlags[_currentLocationIndex] &= ~kFlagsEnter;
_zoneTrap = z;
} else
if (_zoneTrap != NULL) {
- _localFlags[_vm->_currentLocationIndex] |= kFlagsExit;
- _vm->runCommands(_zoneTrap->_commands, _zoneTrap);
- _localFlags[_vm->_currentLocationIndex] &= ~kFlagsExit;
+ _localFlags[_currentLocationIndex] |= kFlagsExit;
+ runCommands(_zoneTrap->_commands, _zoneTrap);
+ _localFlags[_currentLocationIndex] &= ~kFlagsExit;
_zoneTrap = NULL;
}
// printf("done\n");
- _vm->_char._ani._frame = walkData2;
- return _vm->_char._ani._frame;
+ _char._ani._frame = walkData2;
+ return _char._ani._frame;
}
@@ -429,11 +429,11 @@ void jobWalk(void *parm, Job *j) {
void Parallaction::setPath(byte *path) {
- memcpy(_buffer, path, SCREENPATH_WIDTH*SCREEN_HEIGHT);
+ memcpy(_buffer, path, _screenPathSize);
}
void Parallaction::initWalk() {
- _buffer = (byte*)malloc(SCREENPATH_WIDTH * SCREEN_HEIGHT);
+ _buffer = (byte*)malloc(_screenPathSize);
}
diff --git a/engines/parallaction/zone.cpp b/engines/parallaction/zone.cpp
index d9bd36a1f5..50f63b3b75 100644
--- a/engines/parallaction/zone.cpp
+++ b/engines/parallaction/zone.cpp
@@ -295,6 +295,13 @@ void Parallaction::parseZoneTypeBlock(Script &script, Zone *z) {
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);
@@ -305,11 +312,10 @@ void Parallaction::displayCharacterComment(ExamineData *data) {
_gfx->drawBalloon(r, 0);
_gfx->displayWrappedString(data->_description, 140, 10, 0, 130);
- _gfx->updateScreen();
-
waitUntilLeftClick();
_gfx->copyScreen(Gfx::kBitBack, Gfx::kBitFront);
+ _gfx->updateScreen();
return;
}
@@ -332,7 +338,7 @@ void Parallaction::displayItemComment(ExamineData *data) {
char v68[PATH_LEN];
strcpy(v68, data->_filename);
data->_cnv = _disk->loadStatic(v68);
- _gfx->flatBlitCnv(data->_cnv, 140, (SCREEN_HEIGHT - data->_cnv->_height)/2, Gfx::kBitFront);
+ _gfx->flatBlitCnv(data->_cnv, 140, (_screenHeight - data->_cnv->_height)/2, Gfx::kBitFront);
_gfx->freeStaticCnv(data->_cnv);
delete data->_cnv;
@@ -343,7 +349,7 @@ void Parallaction::displayItemComment(ExamineData *data) {
Common::Rect r(v6C, v6A);
r.moveTo(0, 90);
_gfx->drawBalloon(r, 0);
- _gfx->flatBlitCnv(_vm->_char._head, 100, 152, Gfx::kBitFront);
+ _gfx->flatBlitCnv(_char._head, 100, 152, Gfx::kBitFront);
_gfx->displayWrappedString(data->_description, 0, 90, 0, 130);
jobEraseAnimations((void*)1, NULL);
@@ -353,6 +359,7 @@ void Parallaction::displayItemComment(ExamineData *data) {
_gfx->setHalfbriteMode(false);
_gfx->copyScreen(Gfx::kBitBack, Gfx::kBitFront);
+ _gfx->updateScreen();
return;
}
@@ -417,14 +424,17 @@ void jobToggleDoor(void *parm, Job *j) {
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);
- Common::Rect r(z->_left, z->_top, z->_left+z->u.door->_cnv->_width, z->_top+z->u.door->_cnv->_height);
-
- _vm->_gfx->restoreZoneBackground(r, z->u.door->_background);
+ _vm->_gfx->restoreDoorBackground(&v14, r, z->u.door->_background);
- uint16 _ax = (z->_flags & kFlagsClosed ? 0 : 1);
+ _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);
@@ -462,7 +472,7 @@ void jobRemovePickedItem(void *parm, Job *j) {
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->restoreZoneBackground(r, z->u.get->_backup);
+ _vm->_gfx->restoreGetBackground(r, z->u.get->_backup);
}
count++;
diff --git a/engines/queen/sound.cpp b/engines/queen/sound.cpp
index 6184060132..a4cac2417e 100644
--- a/engines/queen/sound.cpp
+++ b/engines/queen/sound.cpp
@@ -67,7 +67,9 @@ public:
MP3Sound(Audio::Mixer *mixer, QueenEngine *vm) : PCSound(mixer, vm) {}
protected:
void playSoundData(Common::File *f, uint32 size, Audio::SoundHandle *soundHandle) {
- _mixer->playInputStream(Audio::Mixer::kSFXSoundType, soundHandle, Audio::makeMP3Stream(f, size));
+ Common::MemoryReadStream *tmp = f->readStream(size);
+ assert(tmp);
+ _mixer->playInputStream(Audio::Mixer::kSFXSoundType, soundHandle, Audio::makeMP3Stream(tmp, true));
}
};
#endif
@@ -78,7 +80,9 @@ public:
OGGSound(Audio::Mixer *mixer, QueenEngine *vm) : PCSound(mixer, vm) {}
protected:
void playSoundData(Common::File *f, uint32 size, Audio::SoundHandle *soundHandle) {
- _mixer->playInputStream(Audio::Mixer::kSFXSoundType, soundHandle, Audio::makeVorbisStream(f, size));
+ Common::MemoryReadStream *tmp = f->readStream(size);
+ assert(tmp);
+ _mixer->playInputStream(Audio::Mixer::kSFXSoundType, soundHandle, Audio::makeVorbisStream(tmp, true));
}
};
#endif
@@ -89,7 +93,9 @@ public:
FLACSound(Audio::Mixer *mixer, QueenEngine *vm) : PCSound(mixer, vm) {}
protected:
void playSoundData(Common::File *f, uint32 size, Audio::SoundHandle *soundHandle) {
- _mixer->playInputStream(Audio::Mixer::kSFXSoundType, soundHandle, Audio::makeFlacStream(f, size));
+ Common::MemoryReadStream *tmp = f->readStream(size);
+ assert(tmp);
+ _mixer->playInputStream(Audio::Mixer::kSFXSoundType, soundHandle, Audio::makeFlacStream(tmp, true));
}
};
#endif // #ifdef USE_FLAC
diff --git a/engines/saga/actor.cpp b/engines/saga/actor.cpp
index d7882a78fd..c2ecff4a1a 100644
--- a/engines/saga/actor.cpp
+++ b/engines/saga/actor.cpp
@@ -897,7 +897,9 @@ void Actor::updateActorsScene(int actorsEntrance) {
}
}
- assert(_protagonist);
+ // _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) {
@@ -1605,7 +1607,9 @@ void Actor::handleActions(int msec, bool setup) {
if (actor->_lastZone)
stepZoneAction(actor, actor->_lastZone, true, false);
actor->_lastZone = hitZone;
- if (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);
}
}
@@ -2127,7 +2131,10 @@ bool Actor::actorWalkTo(uint16 actorId, const Location &toLocation) {
if ((((actor->_currentAction >= kActionWalkToPoint) &&
(actor->_currentAction <= kActionWalkDir)) || (actor == _protagonist)) &&
!_vm->_scene->canWalk(pointFrom)) {
- for (i = 1; i < 8; i++) {
+
+ int max = _vm->getGameType() == GType_ITE ? 8 : 4;
+
+ for (i = 1; i < max; i++) {
pointAdd = pointFrom;
pointAdd.y += i;
if (_vm->_scene->canWalk(pointAdd)) {
@@ -2140,17 +2147,19 @@ bool Actor::actorWalkTo(uint16 actorId, const Location &toLocation) {
pointFrom = pointAdd;
break;
}
- 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;
+ 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;
+ }
}
}
}
diff --git a/engines/saga/actor.h b/engines/saga/actor.h
index b9ec62337c..ef62661c6c 100644
--- a/engines/saga/actor.h
+++ b/engines/saga/actor.h
@@ -41,7 +41,7 @@ namespace Saga {
class HitZone;
-// #define ACTOR_DEBUG 1 //only for actor pathfinding debug!
+//#define ACTOR_DEBUG 1 //only for actor pathfinding debug!
#define ACTOR_BARRIERS_MAX 16
@@ -614,11 +614,6 @@ public:
void showActors(bool flag) { _showActors = flag; }
- /*
- uint16 _currentFrameIndex;
- void frameTest() {
- _currentFrameIndex++;
- }*/
protected:
friend class Script;
bool loadActorResources(ActorData *actor);
diff --git a/engines/saga/animation.cpp b/engines/saga/animation.cpp
index d29fc6ebe6..7b3bdcd665 100644
--- a/engines/saga/animation.cpp
+++ b/engines/saga/animation.cpp
@@ -24,6 +24,7 @@
*/
// Background animation management module
+
#include "saga/saga.h"
#include "saga/gfx.h"
@@ -94,7 +95,10 @@ void Anim::playCutaway(int cut, bool fade) {
startImmediately = true;
}
- _vm->_gfx->savePalette();
+ // 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();
if (fade) {
_vm->_gfx->getCurrentPal(saved_pal);
@@ -152,6 +156,12 @@ void Anim::playCutaway(int cut, bool fade) {
_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);
@@ -307,7 +317,17 @@ void Anim::clearCutaway(void) {
}
_vm->_interface->restoreMode();
- _vm->_gfx->showCursor(true);
+
+ 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 {
+ // Enable the save reminder state after each cutaway for the IHNM demo
+ _vm->_interface->setSaveReminderState(true);
+ }
}
}
@@ -367,16 +387,6 @@ void Anim::load(uint16 animId, const byte *animResourceData, size_t animResource
fillFrameOffsets(anim);
- /* char s[200];
- sprintf(s, "d:\\anim%i",animId);
- long flen=anim->resourceLength;
- char *buf=(char*)anim->resourceData;
- FILE*f;
- f=fopen(s,"wb");
- for (long i = 0; i < flen; i++)
- fputc(buf[i],f);
- fclose(f);*/
-
// Set animation data
anim->currentFrame = 0;
anim->completed = 0;
@@ -642,7 +652,7 @@ void Anim::decodeFrame(AnimationData *anim, size_t frameOffset, byte *buf, size_
yStart = readS.readUint16BE();
else
yStart = readS.readByte();
- readS.readByte(); /* Skip pad byte */
+ readS.readByte(); // Skip pad byte
/*xPos = */readS.readUint16BE();
/*yPos = */readS.readUint16BE();
/*width = */readS.readUint16BE();
diff --git a/engines/saga/animation.h b/engines/saga/animation.h
index 89a1e77807..f8cf90425f 100644
--- a/engines/saga/animation.h
+++ b/engines/saga/animation.h
@@ -154,6 +154,7 @@ public:
}
return (_animations[animId] != NULL);
}
+ int cutawayResourceID(int cutaway) { return _cutawayList[cutaway].animResourceId; }
private:
void decodeFrame(AnimationData *anim, size_t frameOffset, byte *buf, size_t bufLength);
void fillFrameOffsets(AnimationData *anim);
@@ -208,4 +209,4 @@ private:
} // End of namespace Saga
-#endif /* ANIMATION_H_ */
+#endif // ANIMATION_H_
diff --git a/engines/saga/detection.cpp b/engines/saga/detection.cpp
index 9b9a0ca872..c8918998f1 100644
--- a/engines/saga/detection.cpp
+++ b/engines/saga/detection.cpp
@@ -69,7 +69,19 @@ int SagaEngine::getFontsCount() const { return _gameDescription->fontsCount; }
int SagaEngine::getGameId() const { return _gameDescription->gameId; }
int SagaEngine::getGameType() const { return _gameDescription->gameType; }
-uint32 SagaEngine::getFeatures() const { return _gameDescription->features; }
+
+uint32 SagaEngine::getFeatures() const {
+ uint32 result = _gameDescription->features;
+
+ if (_gf_wyrmkeep)
+ result |= GF_WYRMKEEP;
+
+ if (_gf_compressed_sounds)
+ result |= GF_COMPRESSED_SOUNDS;
+
+ return result;
+}
+
Common::Language SagaEngine::getLanguage() const { return _gameDescription->desc.language; }
Common::Platform SagaEngine::getPlatform() const { return _gameDescription->desc.platform; }
int SagaEngine::getGameNumber() const { return _gameNumber; }
@@ -133,6 +145,26 @@ bool SagaEngine::initGame() {
_displayClip.right = getDisplayInfo().logicalWidth;
_displayClip.bottom = getDisplayInfo().logicalHeight;
+ if (Common::File::exists("graphics/credit3n.dlt")) {
+ _gf_wyrmkeep = true;
+ }
+
+ // If a compressed sound file is found in the game's directory, set the compressed flag to true
+ if (_gameDescription->gameType == GType_ITE) {
+ if (Common::File::exists("sounds.cmp") || Common::File::exists("soundsd.cmp") ||
+ Common::File::exists("voices.cmp") || Common::File::exists("voicesd.cmp") ||
+ Common::File::exists("inherit the earth voices.cmp")) {
+ _gf_compressed_sounds = true;
+ }
+ } else {
+ if (Common::File::exists("voicess.cmp") || Common::File::exists("voices1.cmp") ||
+ Common::File::exists("voices2.cmp") || Common::File::exists("voices3.cmp") ||
+ Common::File::exists("voices4.cmp") || Common::File::exists("voices5.cmp") ||
+ Common::File::exists("voices6.cmp") || Common::File::exists("voicesd.cmp")) {
+ _gf_compressed_sounds = true;
+ }
+ }
+
return _resource->createContexts();
}
diff --git a/engines/saga/detection_tables.h b/engines/saga/detection_tables.h
index da06255a82..0d57adb87d 100644
--- a/engines/saga/detection_tables.h
+++ b/engines/saga/detection_tables.h
@@ -23,6 +23,8 @@
*
*/
+// Game detection information and MD5s
+
namespace Saga {
static const GameResourceDescription ITE_Resources = {
@@ -36,6 +38,7 @@ static const GameResourceDescription ITE_Resources = {
RID_ITE_MAIN_PANEL_SPRITES,
0, // Option panel sprites (IHNM only)
RID_ITE_DEFAULT_PORTRAITS,
+ 0, // Psychic profile background (IHNM only)
RID_ITE_MAIN_STRINGS,
RID_ITE_ACTOR_NAMES
};
@@ -51,6 +54,7 @@ static const GameResourceDescription ITEDemo_Resources = {
RID_ITEDEMO_MAIN_PANEL_SPRITES,
0, // Option panel sprites (IHNM only)
RID_ITEDEMO_DEFAULT_PORTRAITS,
+ 0, // Psychic profile background (IHNM only)
RID_ITEDEMO_MAIN_STRINGS,
RID_ITEDEMO_ACTOR_NAMES
};
@@ -61,15 +65,6 @@ static const GameFontDescription ITEDEMO_GameFonts[] = {
{1}
};
-static const GameSoundInfo ITEDEMO_GameSound = {
- kSoundVOC,
- -1,
- -1,
- false,
- false,
- true
-};
-
// Inherit the Earth - Wyrmkeep Win32 Demo version
static const GameFontDescription ITEWINDEMO_GameFonts[] = {
@@ -132,16 +127,6 @@ static const GameSoundInfo ITEMACDEMO_GameMusic = {
true
};
-// Inherit the Earth - Wyrmkeep Linux Demo version
-static const GameSoundInfo ITELINDEMO_GameMusic = {
- kSoundPCM,
- 11025,
- 16,
- true,
- false,
- true
-};
-
static const GameSoundInfo ITEMACCD_G_GameSound = {
kSoundMacPCM,
22050,
@@ -201,7 +186,8 @@ static const GameSoundInfo ITECD_GameSound = {
true
};
-static const GamePatchDescription ITEWinPatch1_Files[] = {
+// 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},
@@ -235,31 +221,11 @@ static const GamePatchDescription ITEWinPatch1_Files[] = {
{ "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},
- { "p2_a.voc", GAME_VOICEFILE, 4, NULL}
-};
-
-static const GamePatchDescription ITEWinPatch2_Files[] = {
- { "cave.mid", GAME_RESOURCEFILE, 9, NULL},
- { "intro.mid", GAME_RESOURCEFILE, 10, NULL},
- { "fvillage.mid", GAME_RESOURCEFILE, 11, NULL},
- { "elkfanfare.mid", GAME_RESOURCEFILE, 19, NULL},
- { "bcexpl.mid", GAME_RESOURCEFILE, 20, NULL},
- { "boargtnt.mid", GAME_RESOURCEFILE, 21, NULL},
- { "explorea.mid", GAME_RESOURCEFILE, 23, NULL},
- { "sweet.mid", GAME_RESOURCEFILE, 32, 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},
+ { "credit4m.dlt", GAME_RESOURCEFILE, 1797, NULL}, // Macintosh
+ { "p2_a.voc", GAME_VOICEFILE, 4, NULL},
{ "p2_a.iaf", GAME_VOICEFILE, 4, &ITECD_GameSound}
-/* boarhall.bbm
- elkenter.bbm
- ferrets.bbm
- ratdoor.bbm
- sanctuar.bbm
- tycho.bbm*/
};
static const GamePatchDescription ITEMacPatch_Files[] = {
@@ -273,16 +239,6 @@ static const GamePatchDescription ITEMacPatch_Files[] = {
{ "p2_a.iaf", GAME_VOICEFILE, 4, &ITEMACCD_GameSound}
};
-static const GamePatchDescription ITELinPatch_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},
- { "credit3n.dlt", GAME_RESOURCEFILE, 1796, NULL},
- { "credit4n.dlt", GAME_RESOURCEFILE, 1797, NULL},
- { "P2_A.iaf", GAME_VOICEFILE, 4, &ITECD_GameSound}
-};
-
// IHNM section
static const GameResourceDescription IHNM_Resources = {
@@ -296,10 +252,27 @@ static const GameResourceDescription IHNM_Resources = {
RID_IHNM_MAIN_PANEL_SPRITES,
RID_IHNM_OPTION_PANEL_SPRITES,
0, // Default portraits (ITE only)
+ RID_IHNM_PROFILE_BG,
RID_IHNM_MAIN_STRINGS,
0 // Actors strings (ITE only)
};
+static const GameResourceDescription IHNMDEMO_Resources = {
+ RID_IHNMDEMO_SCENE_LUT, // Scene lookup table RN
+ RID_IHNMDEMO_SCRIPT_LUT, // Script lookup table RN
+ RID_IHNMDEMO_MAIN_PANEL,
+ RID_IHNMDEMO_CONVERSE_PANEL,
+ RID_IHNMDEMO_OPTION_PANEL,
+ RID_IHNMDEMO_WARNING_PANEL,
+ RID_IHNMDEMO_MAIN_SPRITES,
+ RID_IHNMDEMO_MAIN_PANEL_SPRITES,
+ RID_IHNMDEMO_OPTION_PANEL_SPRITES,
+ 0, // Default portraits (ITE only)
+ RID_IHNMDEMO_PROFILE_BG,
+ RID_IHNMDEMO_MAIN_STRINGS,
+ 0 // Actors strings (ITE only)
+};
+
static const GameFontDescription IHNMDEMO_GameFonts[] = {
{2},
{3},
@@ -326,6 +299,14 @@ static const GameSoundInfo IHNM_GameSound = {
};
static const SAGAGameDescription gameDescriptions[] = {
+ // ITE Section ////////////////////////////////////////////////////////////////////////////////////////////
+
+
+ // ITE Demos //////////////////////////////////////////////////////////////////////////////////////////////
+
+ // Note: This version is NOT supported yet
+ // Based on a very early version of the engine
+
// Inherit the earth - DOS Demo version
// sound unchecked
{
@@ -336,7 +317,7 @@ static const SAGAGameDescription gameDescriptions[] = {
{"ite.rsc", GAME_RESOURCEFILE, "986c79c4d2939dbe555576529fd37932", -1},
//{"ite.dmo", GAME_DEMOFILE}, "0b9a70eb4e120b6f00579b46c8cae29e"
{"scripts.rsc", GAME_SCRIPTFILE, "d5697dd3240a3ceaddaa986c47e1a2d7", -1},
- {"voices.rsc", GAME_SOUNDFILE | GAME_VOICEFILE, "c58e67c506af4ffa03fd0aac2079deb0", -1},
+ //{"voices.rsc", GAME_SOUNDFILE | GAME_VOICEFILE, "c58e67c506af4ffa03fd0aac2079deb0", -1},
{ NULL, 0, NULL, 0}
},
Common::EN_ANY,
@@ -350,24 +331,25 @@ static const SAGAGameDescription gameDescriptions[] = {
&ITEDemo_Resources,
ARRAYSIZE(ITEDEMO_GameFonts),
ITEDEMO_GameFonts,
- &ITEDEMO_GameSound,
- &ITEDEMO_GameSound,
- NULL,
+ &ITEDISK_GameSound,
+ &ITEDISK_GameSound,
+ &ITEMACCD_GameMusic, // note: this version did not originally have digital music
0,
NULL,
},
- // Inherit the earth - MAC Demo version 2
+
+ // Inherit the earth - MAC Demo version
{
{
"ite",
"Demo 2",
{
- {"ited.rsc", GAME_RESOURCEFILE, "addfc9d82bc2fa1f4cab23743c652c08", -1},
- {"scriptsd.rsc", GAME_SCRIPTFILE, "fded5c59b8b7c5976229f960d21e6b0b", -1},
- {"soundsd.rsc", GAME_SOUNDFILE, "b3a831fbed337d1f1300fee1dd474f6c", -1},
- {"voicesd.rsc", GAME_VOICEFILE, "e139d86bab2ee8ba3157337f894a92d4", -1},
- {"musicd.rsc", GAME_MUSICFILE, "495bdde51fd9f4bea2b9c911091b1ab2", -1},
+ {"ited.rsc", GAME_RESOURCEFILE, "addfc9d82bc2fa1f4cab23743c652c08", 1865461},
+ {"scriptsd.rsc", GAME_SCRIPTFILE, "fded5c59b8b7c5976229f960d21e6b0b", 70083},
+ //{"soundsd.rsc", GAME_SOUNDFILE, "b3a831fbed337d1f1300fee1dd474f6c", -1},
+ //{"voicesd.rsc", GAME_VOICEFILE, "e139d86bab2ee8ba3157337f894a92d4", -1},
+ //{"musicd.rsc", GAME_MUSICFILE, "495bdde51fd9f4bea2b9c911091b1ab2", -1},
{ NULL, 0, NULL, 0}
},
Common::EN_ANY,
@@ -388,17 +370,21 @@ static const SAGAGameDescription gameDescriptions[] = {
ITEMacPatch_Files,
},
+
+ // Note: This version is NOT supported yet
+ // Exiting the faire leads to a crash
+
// Inherit the earth - MAC Demo version 1
{
{
"ite",
"Demo 1",
{
- {"ited.rsc", GAME_RESOURCEFILE, "addfc9d82bc2fa1f4cab23743c652c08", -1},
- {"scriptsd.rsc", GAME_SCRIPTFILE, "fded5c59b8b7c5976229f960d21e6b0b", -1},
- {"soundsd.rsc", GAME_SOUNDFILE, "b3a831fbed337d1f1300fee1dd474f6c", -1},
- {"voicesd.rsc", GAME_VOICEFILE, "e139d86bab2ee8ba3157337f894a92d4", -1},
- {"musicd.rsc", GAME_MUSICFILE, "1a91cd60169f367ecb6c6e058d899b2f", -1},
+ {"ited.rsc", GAME_RESOURCEFILE, "addfc9d82bc2fa1f4cab23743c652c08", 1131098},
+ {"scriptsd.rsc", GAME_SCRIPTFILE, "fded5c59b8b7c5976229f960d21e6b0b", 38613},
+ //{"soundsd.rsc", GAME_SOUNDFILE, "b3a831fbed337d1f1300fee1dd474f6c", -1},
+ //{"voicesd.rsc", GAME_VOICEFILE, "e139d86bab2ee8ba3157337f894a92d4", -1},
+ //{"musicd.rsc", GAME_MUSICFILE, "1a91cd60169f367ecb6c6e058d899b2f", -1},
{ NULL, 0, NULL, 0}
},
Common::EN_ANY,
@@ -419,142 +405,19 @@ static const SAGAGameDescription gameDescriptions[] = {
ITEMacPatch_Files,
},
- // Inherit the earth - MAC CD Guild version
- {
- {
- "ite",
- "CD",
- {
- {"ite resources.bin", GAME_RESOURCEFILE | GAME_MACBINARY, "0bd506aa887bfc7965f695c6bd28237d", -1},
- {"ite scripts.bin", GAME_SCRIPTFILE | GAME_MACBINARY, "af0d7a2588e09ad3ecbc5b474ea238bf", -1},
- {"ite sounds.bin", GAME_SOUNDFILE | GAME_MACBINARY, "441426c6bb2a517f65c7e49b57f7a345", -1},
- {"ite music.bin", GAME_MUSICFILE_GM | GAME_MACBINARY, "c1d20324b7cdf1650e67061b8a93251c", -1},
- {"ite voices.bin", GAME_VOICEFILE | GAME_MACBINARY, "dba92ae7d57e942250fe135609708369", -1},
- { NULL, 0, NULL, 0}
- },
- Common::EN_ANY,
- Common::kPlatformMacintosh,
- Common::ADGF_NO_FLAGS
- },
- GType_ITE,
- GID_ITE_MACCD_G,
- GF_BIG_ENDIAN_DATA | GF_CD_FX,
- ITE_DEFAULT_SCENE,
- &ITE_Resources,
- ARRAYSIZE(ITEWINDEMO_GameFonts),
- ITEWINDEMO_GameFonts,
- &ITEMACCD_G_GameSound,
- &ITEMACCD_G_GameSound,
- NULL,
- 0,
- NULL,
- },
- // Inherit the earth - MAC CD Wyrmkeep version
+ // Inherit the earth - Win32 Demo version 2/3, Linux Demo version
+ // Win32 Version 3 and Linux Demo version have digital music, Win32 version 2 has MIDI music
{
{
"ite",
- "Wyrmkeep CD",
- {
- {"ite.rsc", GAME_RESOURCEFILE, "4f7fa11c5175980ed593392838523060", -1},
- {"scripts.rsc", GAME_SCRIPTFILE, "adf1f46c1d0589083996a7060c798ad0", -1},
- {"sounds.rsc", GAME_SOUNDFILE, "95863b89a0916941f6c5e1789843ba14", -1},
- {"inherit the earth voices", GAME_VOICEFILE, "c14c4c995e7a0d3828e3812a494301b7", -1},
- {"music.rsc", GAME_MUSICFILE, "1a91cd60169f367ecb6c6e058d899b2f", -1},
- { NULL, 0, NULL, 0}
- },
- Common::EN_ANY,
- Common::kPlatformMacintosh,
- Common::ADGF_NO_FLAGS
- },
- GType_ITE,
- GID_ITE_MACCD,
- GF_BIG_ENDIAN_DATA | GF_WYRMKEEP | GF_CD_FX,
- ITE_DEFAULT_SCENE,
- &ITE_Resources,
- ARRAYSIZE(ITEWINDEMO_GameFonts),
- ITEWINDEMO_GameFonts,
- &ITEMACCD_GameSound,
- &ITEMACCD_GameSound,
- &ITEMACCD_GameMusic,
- ARRAYSIZE(ITEMacPatch_Files),
- ITEMacPatch_Files,
- },
-
- // Inherit the earth - MAC CD Wyrmkeep version (compressed sound)
- {
- {
- "ite",
- "Wyrmkeep CD",
- {
- {"ite.rsc", GAME_RESOURCEFILE, "4f7fa11c5175980ed593392838523060", -1},
- {"scripts.rsc", GAME_SCRIPTFILE, "adf1f46c1d0589083996a7060c798ad0", -1},
- {"sounds.cmp", GAME_SOUNDFILE, NULL, -1},
- {"inherit the earth voices.cmp",GAME_VOICEFILE, NULL, -1},
- {"music.cmp", GAME_MUSICFILE, NULL, -1},
- { NULL, 0, NULL, 0}
- },
- Common::EN_ANY,
- Common::kPlatformMacintosh,
- Common::ADGF_NO_FLAGS
- },
- GType_ITE,
- GID_ITE_MACCD,
- GF_BIG_ENDIAN_DATA | GF_WYRMKEEP | GF_CD_FX | GF_COMPRESSED_SOUNDS,
- ITE_DEFAULT_SCENE,
- &ITE_Resources,
- ARRAYSIZE(ITEWINDEMO_GameFonts),
- ITEWINDEMO_GameFonts,
- &ITEMACCD_GameSound,
- &ITEMACCD_GameSound,
- &ITEMACCD_GameMusic,
- ARRAYSIZE(ITEMacPatch_Files),
- ITEMacPatch_Files,
- },
-
- // Inherit the earth - Linux Demo version
- // Note: it should be before GID_ITE_WINDEMO2 version
- {
- {
- "ite",
- "Demo",
- {
- {"ited.rsc", GAME_RESOURCEFILE, "3a450852cbf3c80773984d565647e6ac", -1},
- {"scriptsd.rsc", GAME_SCRIPTFILE, "3f12b67fa93e56e1a6be39d2921d80bb", -1},
- {"soundsd.rsc", GAME_SOUNDFILE, "95a6c148e22e99a8c243f2978223583c", 2026769},
- {"voicesd.rsc", GAME_VOICEFILE, "e139d86bab2ee8ba3157337f894a92d4", -1},
- {"musicd.rsc", GAME_MUSICFILE, "d6454756517f042f01210458abe8edd4", -1},
- { NULL, 0, NULL, 0}
- },
- Common::EN_ANY,
- Common::kPlatformLinux,
- Common::ADGF_DEMO
- },
- GType_ITE,
- GID_ITE_LINDEMO,
- GF_WYRMKEEP | GF_CD_FX | GF_SCENE_SUBSTITUTES,
- ITE_DEFAULT_SCENE,
- &ITE_Resources,
- ARRAYSIZE(ITEWINDEMO_GameFonts),
- ITEWINDEMO_GameFonts,
- &ITEWINDEMO2_GameVoice,
- &ITEWINDEMO2_GameSound,
- &ITELINDEMO_GameMusic,
- ARRAYSIZE(ITELinPatch_Files),
- ITELinPatch_Files,
- },
-
- // Inherit the earth - Win32 Demo version 3
- {
- {
- "ite",
- "Demo 3",
+ "Win Demo 2/3, Linux Demo",
{
- {"ited.rsc", GAME_RESOURCEFILE, "3a450852cbf3c80773984d565647e6ac", -1},
- {"scriptsd.rsc", GAME_SCRIPTFILE, "3f12b67fa93e56e1a6be39d2921d80bb", -1},
- {"soundsd.rsc", GAME_SOUNDFILE, "95a6c148e22e99a8c243f2978223583c", 2005074},
- {"voicesd.rsc", GAME_VOICEFILE, "e139d86bab2ee8ba3157337f894a92d4", -1},
- {"musicd.rsc", GAME_MUSICFILE, "d6454756517f042f01210458abe8edd4", -1},
+ {"ited.rsc", GAME_RESOURCEFILE, "3a450852cbf3c80773984d565647e6ac", 1951395},
+ {"scriptsd.rsc", GAME_SCRIPTFILE, "3f12b67fa93e56e1a6be39d2921d80bb", 70051},
+ //{"soundsd.rsc", GAME_SOUNDFILE, "95a6c148e22e99a8c243f2978223583c", -1},
+ //{"voicesd.rsc", GAME_VOICEFILE, "e139d86bab2ee8ba3157337f894a92d4", -1},
+ //{"musicd.rsc", GAME_MUSICFILE, "d6454756517f042f01210458abe8edd4", -1},
{ NULL, 0, NULL, 0}
},
Common::EN_ANY,
@@ -570,21 +433,25 @@ static const SAGAGameDescription gameDescriptions[] = {
ITEWINDEMO_GameFonts,
&ITEWINDEMO2_GameVoice,
&ITEWINDEMO2_GameSound,
- &ITELINDEMO_GameMusic,
- ARRAYSIZE(ITEWinPatch2_Files),
- ITEWinPatch2_Files,
+ &ITEMACCD_GameMusic,
+ ARRAYSIZE(ITEPatch_Files),
+ ITEPatch_Files,
},
- // Inherit the earth - Win32 Demo version 2
+
+ // Note: This version is NOT supported yet
+ // Exiting the faire leads to a crash
+
+ // Inherit the earth - Win32 Demo version 1
{
{
"ite",
- "Demo 2",
+ "Demo 1",
{
- {"ited.rsc", GAME_RESOURCEFILE, "3a450852cbf3c80773984d565647e6ac", -1},
- {"scriptsd.rsc", GAME_SCRIPTFILE, "3f12b67fa93e56e1a6be39d2921d80bb", -1},
- {"soundsd.rsc", GAME_SOUNDFILE, "95a6c148e22e99a8c243f2978223583c", 2005074},
- {"voicesd.rsc", GAME_VOICEFILE, "e139d86bab2ee8ba3157337f894a92d4", -1},
+ {"ited.rsc", GAME_RESOURCEFILE, "3a450852cbf3c80773984d565647e6ac", 1327323},
+ {"scriptsd.rsc", GAME_SCRIPTFILE, "3f12b67fa93e56e1a6be39d2921d80bb", 38613},
+ //{"soundsd.rsc", GAME_SOUNDFILE, "a741139dd7365a13f463cd896ff9969a", -1},
+ //{"voicesd.rsc", GAME_VOICEFILE, "0759eaf5b64ae19fd429920a70151ad3", -1},
{ NULL, 0, NULL, 0}
},
Common::EN_ANY,
@@ -592,86 +459,91 @@ static const SAGAGameDescription gameDescriptions[] = {
Common::ADGF_DEMO
},
GType_ITE,
- GID_ITE_WINDEMO2,
- GF_WYRMKEEP | GF_CD_FX | GF_SCENE_SUBSTITUTES,
+ GID_ITE_WINDEMO1,
+ GF_WYRMKEEP | GF_CD_FX,
ITE_DEFAULT_SCENE,
&ITE_Resources,
ARRAYSIZE(ITEWINDEMO_GameFonts),
ITEWINDEMO_GameFonts,
- &ITEWINDEMO2_GameVoice,
- &ITEWINDEMO2_GameSound,
- NULL,
- ARRAYSIZE(ITEWinPatch2_Files),
- ITEWinPatch2_Files,
+ &ITEWINDEMO1_GameSound,
+ &ITEWINDEMO1_GameSound,
+ &ITEMACCD_GameMusic, // note: this version did not originally have digital music
+ ARRAYSIZE(ITEPatch_Files),
+ ITEPatch_Files,
},
- // Inherit the earth - Win32 Demo version 1
+
+ // TODO: Add Amiga demos here (not supported yet)
+
+
+ // ITE Mac versions ///////////////////////////////////////////////////////////////////////////////////////
+
+ // Inherit the earth - MAC CD Guild version
{
{
"ite",
- "Demo 1",
+ "CD",
{
- {"ited.rsc", GAME_RESOURCEFILE, "3a450852cbf3c80773984d565647e6ac", -1},
- {"scriptsd.rsc", GAME_SCRIPTFILE, "3f12b67fa93e56e1a6be39d2921d80bb", -1},
- {"soundsd.rsc", GAME_SOUNDFILE, "a741139dd7365a13f463cd896ff9969a", -1},
- {"voicesd.rsc", GAME_VOICEFILE, "0759eaf5b64ae19fd429920a70151ad3", -1},
+ {"ite resources.bin", GAME_RESOURCEFILE | GAME_MACBINARY, "0bd506aa887bfc7965f695c6bd28237d", -1},
+ {"ite scripts.bin", GAME_SCRIPTFILE | GAME_MACBINARY, "af0d7a2588e09ad3ecbc5b474ea238bf", -1},
+ {"ite sounds.bin", GAME_SOUNDFILE | GAME_MACBINARY, "441426c6bb2a517f65c7e49b57f7a345", -1},
+ {"ite music.bin", GAME_MUSICFILE_GM | GAME_MACBINARY, "c1d20324b7cdf1650e67061b8a93251c", -1},
+ {"ite voices.bin", GAME_VOICEFILE | GAME_MACBINARY, "dba92ae7d57e942250fe135609708369", -1},
{ NULL, 0, NULL, 0}
},
Common::EN_ANY,
- Common::kPlatformWindows,
- Common::ADGF_DEMO
+ Common::kPlatformMacintosh,
+ Common::ADGF_NO_FLAGS
},
GType_ITE,
- GID_ITE_WINDEMO1,
- GF_WYRMKEEP | GF_CD_FX,
+ GID_ITE_MACCD_G,
+ GF_BIG_ENDIAN_DATA | GF_CD_FX,
ITE_DEFAULT_SCENE,
&ITE_Resources,
ARRAYSIZE(ITEWINDEMO_GameFonts),
ITEWINDEMO_GameFonts,
- &ITEWINDEMO1_GameSound,
- &ITEWINDEMO1_GameSound,
+ &ITEMACCD_G_GameSound,
+ &ITEMACCD_G_GameSound,
+ &ITEMACCD_GameMusic, // note: this version did not originally have digital music
+ 0,
NULL,
- ARRAYSIZE(ITEWinPatch1_Files),
- ITEWinPatch1_Files,
},
- // Inherit the earth - Wyrmkeep combined Windows/Mac/Linux CD
-
- // version is different from the other Wyrmkeep re-releases in that it does
- // not have any substitute files. Presumably the ite.rsc file has been
- // modified to include the Wyrmkeep changes. The resource files are little-
- // endian, except for the voice file which is big-endian.
+ // Inherit the earth - MAC CD Wyrmkeep version
{
{
"ite",
- "Multi-OS CD Version",
+ "Wyrmkeep CD",
{
- {"ite.rsc", GAME_RESOURCEFILE, "a6433e34b97b15e64fe8214651012db9", -1},
- {"scripts.rsc", GAME_SCRIPTFILE, "a891405405edefc69c9d6c420c868b84", -1},
- {"sounds.rsc", GAME_SOUNDFILE, "e2ccb61c325d6d1ead3be0e731fe29fe", -1},
- {"inherit the earth voices", GAME_VOICEFILE | GAME_SWAPENDIAN, "c14c4c995e7a0d3828e3812a494301b7", -1},
- {"music.rsc", GAME_MUSICFILE, "d6454756517f042f01210458abe8edd4", -1},
+ {"ite.rsc", GAME_RESOURCEFILE, "4f7fa11c5175980ed593392838523060", -1},
+ {"scripts.rsc", GAME_SCRIPTFILE, "adf1f46c1d0589083996a7060c798ad0", -1},
+ //{"sounds.rsc", GAME_SOUNDFILE, "95863b89a0916941f6c5e1789843ba14", -1},
+ //{"inherit the earth voices", GAME_VOICEFILE, "c14c4c995e7a0d3828e3812a494301b7", -1},
+ //{"music.rsc", GAME_MUSICFILE, "1a91cd60169f367ecb6c6e058d899b2f", -1},
{ NULL, 0, NULL, 0}
},
Common::EN_ANY,
- Common::kPlatformUnknown,
+ Common::kPlatformMacintosh,
Common::ADGF_NO_FLAGS
},
GType_ITE,
- GID_ITE_MULTICD,
- GF_WYRMKEEP | GF_CD_FX,
+ GID_ITE_MACCD,
+ GF_BIG_ENDIAN_DATA | GF_WYRMKEEP | GF_CD_FX,
ITE_DEFAULT_SCENE,
&ITE_Resources,
- ARRAYSIZE(ITECD_GameFonts),
- ITECD_GameFonts,
+ ARRAYSIZE(ITEWINDEMO_GameFonts),
+ ITEWINDEMO_GameFonts,
+ &ITEMACCD_GameSound,
&ITEMACCD_GameSound,
- &ITECD_GameSound,
&ITEMACCD_GameMusic,
- 0,
- NULL,
+ ARRAYSIZE(ITEMacPatch_Files),
+ ITEMacPatch_Files,
},
- // Inherit the earth - Wyrmkeep combined Windows/Mac/Linux CD (compressed sound)
+
+ // ITE PC CD versions //////////////////////////////////////////////////////////////////////////////////////
+
+ // Inherit the earth - Wyrmkeep combined Windows/Mac/Linux CD
// version is different from the other Wyrmkeep re-releases in that it does
// not have any substitute files. Presumably the ite.rsc file has been
@@ -684,9 +556,9 @@ static const SAGAGameDescription gameDescriptions[] = {
{
{"ite.rsc", GAME_RESOURCEFILE, "a6433e34b97b15e64fe8214651012db9", -1},
{"scripts.rsc", GAME_SCRIPTFILE, "a891405405edefc69c9d6c420c868b84", -1},
- {"sounds.cmp", GAME_SOUNDFILE, NULL, -1},
- {"inherit the earth voices.cmp",GAME_VOICEFILE | GAME_SWAPENDIAN, NULL, -1},
- {"music.cmp", GAME_MUSICFILE, NULL, -1},
+ //{"sounds.rsc", GAME_SOUNDFILE, "e2ccb61c325d6d1ead3be0e731fe29fe", -1},
+ //{"inherit the earth voices", GAME_VOICEFILE | GAME_SWAPENDIAN, "c14c4c995e7a0d3828e3812a494301b7", -1},
+ //{"music.rsc", GAME_MUSICFILE, "d6454756517f042f01210458abe8edd4", -1},
{ NULL, 0, NULL, 0}
},
Common::EN_ANY,
@@ -695,7 +567,7 @@ static const SAGAGameDescription gameDescriptions[] = {
},
GType_ITE,
GID_ITE_MULTICD,
- GF_WYRMKEEP | GF_CD_FX | GF_COMPRESSED_SOUNDS,
+ GF_WYRMKEEP | GF_CD_FX,
ITE_DEFAULT_SCENE,
&ITE_Resources,
ARRAYSIZE(ITECD_GameFonts),
@@ -707,138 +579,17 @@ static const SAGAGameDescription gameDescriptions[] = {
NULL,
},
- // Inherit the earth - Wyrmkeep Linux CD version
- {
- {
- "ite",
- "CD Version",
- {
- {"ite.rsc", GAME_RESOURCEFILE, "8f4315a9bb10ec839253108a032c8b54", -1},
- {"scripts.rsc", GAME_SCRIPTFILE, "a891405405edefc69c9d6c420c868b84", -1},
- {"sounds.rsc", GAME_SOUNDFILE, "e2ccb61c325d6d1ead3be0e731fe29fe", -1},
- {"voices.rsc", GAME_VOICEFILE, "41bb6b95d792dde5196bdb78740895a6", -1},
- {"music.rsc", GAME_MUSICFILE, "d6454756517f042f01210458abe8edd4", -1},
- { NULL, 0, NULL, 0}
- },
- Common::EN_ANY,
- Common::kPlatformLinux,
- Common::ADGF_NO_FLAGS
- },
- GType_ITE,
- GID_ITE_LINCD,
- GF_WYRMKEEP | GF_CD_FX,
- ITE_DEFAULT_SCENE,
- &ITE_Resources,
- ARRAYSIZE(ITECD_GameFonts),
- ITECD_GameFonts,
- &ITECD_GameSound,
- &ITECD_GameSound,
- &ITEMACCD_GameMusic,
- ARRAYSIZE(ITELinPatch_Files),
- ITELinPatch_Files,
- },
-
- // Inherit the earth - Wyrmkeep Linux CD version (compressed sound)
- {
- {
- "ite",
- "CD Version",
- {
- {"ite.rsc", GAME_RESOURCEFILE, "8f4315a9bb10ec839253108a032c8b54", -1},
- {"scripts.rsc", GAME_SCRIPTFILE, "a891405405edefc69c9d6c420c868b84", -1},
- {"sounds.cmp", GAME_SOUNDFILE, NULL, -1},
- {"voices.cmp", GAME_VOICEFILE, NULL, -1},
- {"music.cmp", GAME_MUSICFILE, NULL, -1},
- { NULL, 0, NULL, 0}
- },
- Common::EN_ANY,
- Common::kPlatformLinux,
- Common::ADGF_NO_FLAGS
- },
- GType_ITE,
- GID_ITE_LINCD,
- GF_WYRMKEEP | GF_CD_FX | GF_COMPRESSED_SOUNDS,
- ITE_DEFAULT_SCENE,
- &ITE_Resources,
- ARRAYSIZE(ITECD_GameFonts),
- ITECD_GameFonts,
- &ITECD_GameSound,
- &ITECD_GameSound,
- &ITEMACCD_GameMusic,
- ARRAYSIZE(ITELinPatch_Files),
- ITELinPatch_Files,
- },
-
- // Inherit the earth - Wyrmkeep Windows CD version
- {
- {
- "ite",
- "CD Version",
- {
- {"ite.rsc", GAME_RESOURCEFILE, "8f4315a9bb10ec839253108a032c8b54", -1},
- {"scripts.rsc", GAME_SCRIPTFILE, "a891405405edefc69c9d6c420c868b84", -1},
- {"sounds.rsc", GAME_SOUNDFILE, "e2ccb61c325d6d1ead3be0e731fe29fe", -1},
- {"voices.rsc", GAME_VOICEFILE, "41bb6b95d792dde5196bdb78740895a6", -1},
- { NULL, 0, NULL, 0}
- },
- Common::EN_ANY,
- Common::kPlatformWindows,
- Common::ADGF_NO_FLAGS
- },
- GType_ITE,
- GID_ITE_WINCD,
- GF_WYRMKEEP | GF_CD_FX,
- ITE_DEFAULT_SCENE,
- &ITE_Resources,
- ARRAYSIZE(ITECD_GameFonts),
- ITECD_GameFonts,
- &ITECD_GameSound,
- &ITECD_GameSound,
- NULL,
- ARRAYSIZE(ITEWinPatch1_Files),
- ITEWinPatch1_Files,
- },
-
- // Inherit the earth - Wyrmkeep Windows CD version (compressed sound)
+ // Inherit the earth - Windows/Linux/DOS CD version
{
{
"ite",
- "CD Version",
+ "Windows/Linux/DOS CD Version",
{
{"ite.rsc", GAME_RESOURCEFILE, "8f4315a9bb10ec839253108a032c8b54", -1},
{"scripts.rsc", GAME_SCRIPTFILE, "a891405405edefc69c9d6c420c868b84", -1},
- {"sounds.cmp", GAME_SOUNDFILE, NULL, -1},
- {"voices.cmp", GAME_VOICEFILE, NULL, -1},
- { NULL, 0, NULL, 0}
- },
- Common::EN_ANY,
- Common::kPlatformWindows,
- Common::ADGF_NO_FLAGS
- },
- GType_ITE,
- GID_ITE_WINCD,
- GF_WYRMKEEP | GF_CD_FX | GF_COMPRESSED_SOUNDS,
- ITE_DEFAULT_SCENE,
- &ITE_Resources,
- ARRAYSIZE(ITECD_GameFonts),
- ITECD_GameFonts,
- &ITECD_GameSound,
- &ITECD_GameSound,
- NULL,
- ARRAYSIZE(ITEWinPatch1_Files),
- ITEWinPatch1_Files,
- },
-
- // Inherit the earth - DOS CD version
- {
- {
- "ite",
- "CD Version",
- {
- {"ite.rsc", GAME_RESOURCEFILE, "8f4315a9bb10ec839253108a032c8b54", -1},
- {"scripts.rsc", GAME_SCRIPTFILE, "50a0d2d7003c926a3832d503c8534e90", -1},
- {"sounds.rsc", GAME_SOUNDFILE, "e2ccb61c325d6d1ead3be0e731fe29fe", -1},
- {"voices.rsc", GAME_VOICEFILE, "41bb6b95d792dde5196bdb78740895a6", -1},
+ //{"sounds.rsc", GAME_SOUNDFILE, "e2ccb61c325d6d1ead3be0e731fe29fe", -1},
+ //{"voices.rsc", GAME_VOICEFILE, "41bb6b95d792dde5196bdb78740895a6", -1},
+ //{"music.rsc", GAME_MUSICFILE, "d6454756517f042f01210458abe8edd4", -1},
{ NULL, 0, NULL, 0}
},
Common::EN_ANY,
@@ -846,7 +597,7 @@ static const SAGAGameDescription gameDescriptions[] = {
Common::ADGF_NO_FLAGS
},
GType_ITE,
- GID_ITE_CD_G,
+ GID_ITE_CD,
GF_CD_FX,
ITE_DEFAULT_SCENE,
&ITE_Resources,
@@ -854,12 +605,12 @@ static const SAGAGameDescription gameDescriptions[] = {
ITECD_GameFonts,
&ITECD_GameSound,
&ITECD_GameSound,
- NULL,
- 0,
- NULL,
+ &ITEMACCD_GameMusic,
+ ARRAYSIZE(ITEPatch_Files),
+ ITEPatch_Files,
},
- // Inherit the earth - DOS CD version (compressed sound)
+ // Inherit the earth - DOS CD version
{
{
"ite",
@@ -867,8 +618,8 @@ static const SAGAGameDescription gameDescriptions[] = {
{
{"ite.rsc", GAME_RESOURCEFILE, "8f4315a9bb10ec839253108a032c8b54", -1},
{"scripts.rsc", GAME_SCRIPTFILE, "50a0d2d7003c926a3832d503c8534e90", -1},
- {"sounds.cmp", GAME_SOUNDFILE, NULL, -1},
- {"voices.cmp", GAME_VOICEFILE, NULL, -1},
+ //{"sounds.rsc", GAME_SOUNDFILE, "e2ccb61c325d6d1ead3be0e731fe29fe", -1},
+ //{"voices.rsc", GAME_VOICEFILE, "41bb6b95d792dde5196bdb78740895a6", -1},
{ NULL, 0, NULL, 0}
},
Common::EN_ANY,
@@ -877,37 +628,6 @@ static const SAGAGameDescription gameDescriptions[] = {
},
GType_ITE,
GID_ITE_CD_G,
- GF_CD_FX | GF_COMPRESSED_SOUNDS,
- ITE_DEFAULT_SCENE,
- &ITE_Resources,
- ARRAYSIZE(ITECD_GameFonts),
- ITECD_GameFonts,
- &ITECD_GameSound,
- &ITECD_GameSound,
- NULL,
- 0,
- NULL,
- },
-
- // Inherit the earth - DOS CD version with digital music
- {
- {
- "ite",
- "CD Version",
- {
- {"ite.rsc", GAME_RESOURCEFILE, "8f4315a9bb10ec839253108a032c8b54", -1},
- {"scripts.rsc", GAME_SCRIPTFILE, "50a0d2d7003c926a3832d503c8534e90", -1},
- {"sounds.rsc", GAME_SOUNDFILE, "e2ccb61c325d6d1ead3be0e731fe29fe", -1},
- {"voices.rsc", GAME_VOICEFILE, "41bb6b95d792dde5196bdb78740895a6", -1},
- {"music.rsc", GAME_MUSICFILE, "d6454756517f042f01210458abe8edd4", -1},
- { NULL, 0, NULL, 0}
- },
- Common::EN_ANY,
- Common::kPlatformPC,
- Common::ADGF_NO_FLAGS
- },
- GType_ITE,
- GID_ITE_CD_G2,
GF_CD_FX,
ITE_DEFAULT_SCENE,
&ITE_Resources,
@@ -915,40 +635,9 @@ static const SAGAGameDescription gameDescriptions[] = {
ITECD_GameFonts,
&ITECD_GameSound,
&ITECD_GameSound,
- &ITEMACCD_GameMusic,
- 0,
- NULL,
- },
-
- // Inherit the earth - DOS CD version with digital music (compressed sound)
- {
- {
- "ite",
- "CD Version",
- {
- {"ite.rsc", GAME_RESOURCEFILE, "8f4315a9bb10ec839253108a032c8b54", -1},
- {"scripts.rsc", GAME_SCRIPTFILE, "50a0d2d7003c926a3832d503c8534e90", -1},
- {"sounds.cmp", GAME_SOUNDFILE, NULL, -1},
- {"voices.cmp", GAME_VOICEFILE, NULL, -1},
- {"music.cmp", GAME_MUSICFILE, NULL, -1},
- { NULL, 0, NULL, 0}
- },
- Common::EN_ANY,
- Common::kPlatformPC,
- Common::ADGF_NO_FLAGS
- },
- GType_ITE,
- GID_ITE_CD_G2,
- GF_CD_FX | GF_COMPRESSED_SOUNDS,
- ITE_DEFAULT_SCENE,
- &ITE_Resources,
- ARRAYSIZE(ITECD_GameFonts),
- ITECD_GameFonts,
- &ITECD_GameSound,
- &ITECD_GameSound,
- &ITEMACCD_GameMusic,
- 0,
- NULL,
+ &ITEMACCD_GameMusic, // note: this version did not originally have digital music
+ ARRAYSIZE(ITEPatch_Files),
+ ITEPatch_Files,
},
// Inherit the earth - DOS CD German version
@@ -960,8 +649,8 @@ static const SAGAGameDescription gameDescriptions[] = {
{
{"ite.rsc", GAME_RESOURCEFILE, "869fc23c8f38f575979ec67152914fee", -1},
{"scripts.rsc", GAME_SCRIPTFILE, "a891405405edefc69c9d6c420c868b84", -1},
- {"sounds.rsc", GAME_SOUNDFILE, "e2ccb61c325d6d1ead3be0e731fe29fe", -1},
- {"voices.rsc", GAME_VOICEFILE, "2fbad5d10b9b60a3415dc4aebbb11718", -1},
+ //{"sounds.rsc", GAME_SOUNDFILE, "e2ccb61c325d6d1ead3be0e731fe29fe", -1},
+ //{"voices.rsc", GAME_VOICEFILE, "2fbad5d10b9b60a3415dc4aebbb11718", -1},
{ NULL, 0, NULL, 0}
},
Common::DE_DEU,
@@ -977,163 +666,13 @@ static const SAGAGameDescription gameDescriptions[] = {
ITECD_GameFonts,
&ITECD_GameSound,
&ITECD_GameSound,
- NULL,
+ &ITEMACCD_GameMusic, // note: this version did not originally have digital music
0,
NULL,
},
- // Inherit the earth - DOS CD German version (compressed sound)
- // reported by mld. Bestsellergamers cover disk
- {
- {
- "ite",
- "CD Version",
- {
- {"ite.rsc", GAME_RESOURCEFILE, "869fc23c8f38f575979ec67152914fee", -1},
- {"scripts.rsc", GAME_SCRIPTFILE, "a891405405edefc69c9d6c420c868b84", -1},
- {"sounds.cmp", GAME_SOUNDFILE, NULL, -1},
- {"voices.cmp", GAME_VOICEFILE, NULL, -1},
- { NULL, 0, NULL, 0}
- },
- Common::DE_DEU,
- Common::kPlatformPC,
- Common::ADGF_NO_FLAGS
- },
- GType_ITE,
- GID_ITE_CD_DE,
- GF_CD_FX | GF_COMPRESSED_SOUNDS,
- ITE_DEFAULT_SCENE,
- &ITE_Resources,
- ARRAYSIZE(ITECD_GameFonts),
- ITECD_GameFonts,
- &ITECD_GameSound,
- &ITECD_GameSound,
- NULL,
- 0,
- NULL,
- },
- // Inherit the earth - DOS CD German version with digital music
- {
- {
- "ite",
- "CD Version",
- {
- {"ite.rsc", GAME_RESOURCEFILE, "869fc23c8f38f575979ec67152914fee", -1},
- {"scripts.rsc", GAME_SCRIPTFILE, "a891405405edefc69c9d6c420c868b84", -1},
- {"sounds.rsc", GAME_SOUNDFILE, "e2ccb61c325d6d1ead3be0e731fe29fe", -1},
- {"voices.rsc", GAME_VOICEFILE, "2fbad5d10b9b60a3415dc4aebbb11718", -1},
- {"music.rsc", GAME_MUSICFILE, "d6454756517f042f01210458abe8edd4", -1},
- { NULL, 0, NULL, 0}
- },
- Common::DE_DEU,
- Common::kPlatformPC,
- Common::ADGF_NO_FLAGS
- },
- GType_ITE,
- GID_ITE_CD_DE2,
- GF_CD_FX,
- ITE_DEFAULT_SCENE,
- &ITE_Resources,
- ARRAYSIZE(ITECD_GameFonts),
- ITECD_GameFonts,
- &ITECD_GameSound,
- &ITECD_GameSound,
- &ITEMACCD_GameMusic,
- 0,
- NULL,
- },
-
- // Inherit the earth - DOS CD German version with digital music (compressed sound)
- {
- {
- "ite",
- "CD Version",
- {
- {"ite.rsc", GAME_RESOURCEFILE, "869fc23c8f38f575979ec67152914fee", -1},
- {"scripts.rsc", GAME_SCRIPTFILE, "a891405405edefc69c9d6c420c868b84", -1},
- {"sounds.cmp", GAME_SOUNDFILE, NULL, -1},
- {"voices.cmp", GAME_VOICEFILE, NULL, -1},
- {"music.cmp", GAME_MUSICFILE, NULL, -1},
- { NULL, 0, NULL, 0}
- },
- Common::DE_DEU,
- Common::kPlatformPC,
- Common::ADGF_NO_FLAGS
- },
- GType_ITE,
- GID_ITE_CD_DE2,
- GF_CD_FX | GF_COMPRESSED_SOUNDS,
- ITE_DEFAULT_SCENE,
- &ITE_Resources,
- ARRAYSIZE(ITECD_GameFonts),
- ITECD_GameFonts,
- &ITECD_GameSound,
- &ITECD_GameSound,
- &ITEMACCD_GameMusic,
- 0,
- NULL,
- },
-
- // Inherit the earth - CD version
- {
- {
- "ite",
- "CD Version",
- {
- {"ite.rsc", GAME_RESOURCEFILE, "8f4315a9bb10ec839253108a032c8b54", -1},
- {"scripts.rsc", GAME_SCRIPTFILE, "a891405405edefc69c9d6c420c868b84", -1},
- {"sounds.rsc", GAME_SOUNDFILE, "e2ccb61c325d6d1ead3be0e731fe29fe", -1},
- {"voices.rsc", GAME_VOICEFILE, "41bb6b95d792dde5196bdb78740895a6", -1},
- { NULL, 0, NULL, 0}
- },
- Common::EN_ANY,
- Common::kPlatformPC,
- Common::ADGF_NO_FLAGS
- },
- GType_ITE,
- GID_ITE_CD,
- GF_CD_FX,
- ITE_DEFAULT_SCENE,
- &ITE_Resources,
- ARRAYSIZE(ITECD_GameFonts),
- ITECD_GameFonts,
- &ITECD_GameSound,
- &ITECD_GameSound,
- NULL,
- 0,
- NULL,
- },
-
- // Inherit the earth - CD version (compressed sound)
- {
- {
- "ite",
- "CD Version",
- {
- {"ite.rsc", GAME_RESOURCEFILE, "8f4315a9bb10ec839253108a032c8b54", -1},
- {"scripts.rsc", GAME_SCRIPTFILE, "a891405405edefc69c9d6c420c868b84", -1},
- {"sounds.cmp", GAME_SOUNDFILE, NULL, -1},
- {"voices.cmp", GAME_VOICEFILE, NULL, -1},
- { NULL, 0, NULL, 0}
- },
- Common::EN_ANY,
- Common::kPlatformPC,
- Common::ADGF_NO_FLAGS
- },
- GType_ITE,
- GID_ITE_CD,
- GF_CD_FX | GF_COMPRESSED_SOUNDS,
- ITE_DEFAULT_SCENE,
- &ITE_Resources,
- ARRAYSIZE(ITECD_GameFonts),
- ITECD_GameFonts,
- &ITECD_GameSound,
- &ITECD_GameSound,
- NULL,
- 0,
- NULL,
- },
+ // ITE floppy versions ////////////////////////////////////////////////////////////////////////////////////
// Inherit the earth - German Floppy version
{
@@ -1143,36 +682,7 @@ static const SAGAGameDescription gameDescriptions[] = {
{
{"ite.rsc", GAME_RESOURCEFILE, "869fc23c8f38f575979ec67152914fee", -1},
{"scripts.rsc", GAME_SCRIPTFILE, "516f7330f8410057b834424ea719d1ef", -1},
- {"voices.rsc", GAME_SOUNDFILE | GAME_VOICEFILE, "0c9113e630f97ef0996b8c3114badb08", -1},
- { NULL, 0, NULL, 0}
- },
- Common::DE_DEU,
- Common::kPlatformPC,
- Common::ADGF_NO_FLAGS
- },
- GType_ITE,
- GID_ITE_DISK_DE,
- 0,
- ITE_DEFAULT_SCENE,
- &ITE_Resources,
- ARRAYSIZE(ITEDISK_GameFonts),
- ITEDISK_GameFonts,
- &ITEDISK_GameSound,
- &ITEDISK_GameSound,
- NULL,
- 0,
- NULL,
- },
-
- // Inherit the earth - German Floppy version (compressed sound)
- {
- {
- "ite",
- "Floppy",
- {
- {"ite.rsc", GAME_RESOURCEFILE, "869fc23c8f38f575979ec67152914fee", -1},
- {"scripts.rsc", GAME_SCRIPTFILE, "516f7330f8410057b834424ea719d1ef", -1},
- {"voices.cmp", GAME_SOUNDFILE | GAME_VOICEFILE, NULL, -1},
+ //{"voices.rsc", GAME_SOUNDFILE | GAME_VOICEFILE, "0c9113e630f97ef0996b8c3114badb08", -1},
{ NULL, 0, NULL, 0}
},
Common::DE_DEU,
@@ -1181,74 +691,14 @@ static const SAGAGameDescription gameDescriptions[] = {
},
GType_ITE,
GID_ITE_DISK_DE,
- GF_COMPRESSED_SOUNDS,
- ITE_DEFAULT_SCENE,
- &ITE_Resources,
- ARRAYSIZE(ITEDISK_GameFonts),
- ITEDISK_GameFonts,
- &ITEDISK_GameSound,
- &ITEDISK_GameSound,
- NULL,
- 0,
- NULL,
- },
-
- // Inherit the earth - German Floppy version with digital music
- {
- {
- "ite",
- "Floppy",
- {
- {"ite.rsc", GAME_RESOURCEFILE, "869fc23c8f38f575979ec67152914fee", -1},
- {"scripts.rsc", GAME_SCRIPTFILE, "516f7330f8410057b834424ea719d1ef", -1},
- {"voices.rsc", GAME_SOUNDFILE | GAME_VOICEFILE, "0c9113e630f97ef0996b8c3114badb08", -1},
- {"music.rsc", GAME_MUSICFILE, "d6454756517f042f01210458abe8edd4", -1},
- { NULL, 0, NULL, 0}
- },
- Common::DE_DEU,
- Common::kPlatformPC,
- Common::ADGF_NO_FLAGS
- },
- GType_ITE,
- GID_ITE_DISK_DE2,
- 0,
- ITE_DEFAULT_SCENE,
- &ITE_Resources,
- ARRAYSIZE(ITEDISK_GameFonts),
- ITEDISK_GameFonts,
- &ITEDISK_GameSound,
- &ITEDISK_GameSound,
- &ITEMACCD_GameMusic,
0,
- NULL,
- },
-
- // Inherit the earth - German Floppy version with digital music (compressed sound)
- {
- {
- "ite",
- "Floppy",
- {
- {"ite.rsc", GAME_RESOURCEFILE, "869fc23c8f38f575979ec67152914fee", -1},
- {"scripts.rsc", GAME_SCRIPTFILE, "516f7330f8410057b834424ea719d1ef", -1},
- {"voices.cmp", GAME_SOUNDFILE | GAME_VOICEFILE, NULL, -1},
- {"music.cmp", GAME_MUSICFILE, NULL, -1},
- { NULL, 0, NULL, 0}
- },
- Common::DE_DEU,
- Common::kPlatformPC,
- Common::ADGF_NO_FLAGS
- },
- GType_ITE,
- GID_ITE_DISK_DE2,
- GF_COMPRESSED_SOUNDS,
ITE_DEFAULT_SCENE,
&ITE_Resources,
ARRAYSIZE(ITEDISK_GameFonts),
ITEDISK_GameFonts,
&ITEDISK_GameSound,
&ITEDISK_GameSound,
- &ITEMACCD_GameMusic,
+ &ITEMACCD_GameMusic, // note: this version did not originally have digital music
0,
NULL,
},
@@ -1261,7 +711,7 @@ static const SAGAGameDescription gameDescriptions[] = {
{
{"ite.rsc", GAME_RESOURCEFILE, "8f4315a9bb10ec839253108a032c8b54", -1},
{"scripts.rsc", GAME_SCRIPTFILE, "516f7330f8410057b834424ea719d1ef", -1},
- {"voices.rsc", GAME_SOUNDFILE | GAME_VOICEFILE, "c46e4392fcd2e89bc91e5567db33b62d", -1},
+ //{"voices.rsc", GAME_SOUNDFILE | GAME_VOICEFILE, "c46e4392fcd2e89bc91e5567db33b62d", -1},
{ NULL, 0, NULL, 0}
},
Common::EN_ANY,
@@ -1277,99 +727,18 @@ static const SAGAGameDescription gameDescriptions[] = {
ITEDISK_GameFonts,
&ITEDISK_GameSound,
&ITEDISK_GameSound,
- NULL,
- 0,
- NULL,
+ &ITEMACCD_GameMusic, // note: this version did not originally have digital music
+ ARRAYSIZE(ITEPatch_Files),
+ ITEPatch_Files,
},
- // Inherit the earth - Disk version (compressed sound)
- {
- {
- "ite",
- "Floppy",
- {
- {"ite.rsc", GAME_RESOURCEFILE, "8f4315a9bb10ec839253108a032c8b54", -1},
- {"scripts.rsc", GAME_SCRIPTFILE, "516f7330f8410057b834424ea719d1ef", -1},
- {"voices.cmp", GAME_SOUNDFILE | GAME_VOICEFILE, NULL, -1},
- { NULL, 0, NULL, 0}
- },
- Common::EN_ANY,
- Common::kPlatformPC,
- Common::ADGF_NO_FLAGS
- },
- GType_ITE,
- GID_ITE_DISK_G,
- GF_COMPRESSED_SOUNDS,
- ITE_DEFAULT_SCENE,
- &ITE_Resources,
- ARRAYSIZE(ITEDISK_GameFonts),
- ITEDISK_GameFonts,
- &ITEDISK_GameSound,
- &ITEDISK_GameSound,
- NULL,
- 0,
- NULL,
- },
- // Inherit the earth - Disk version with digital music
- {
- {
- "ite",
- "Floppy",
- {
- {"ite.rsc", GAME_RESOURCEFILE, "8f4315a9bb10ec839253108a032c8b54", -1},
- {"scripts.rsc", GAME_SCRIPTFILE, "516f7330f8410057b834424ea719d1ef", -1},
- {"voices.rsc", GAME_SOUNDFILE | GAME_VOICEFILE, "c46e4392fcd2e89bc91e5567db33b62d", -1},
- {"music.rsc", GAME_MUSICFILE, "d6454756517f042f01210458abe8edd4", -1},
- { NULL, 0, NULL, 0}
- },
- Common::EN_ANY,
- Common::kPlatformPC,
- Common::ADGF_NO_FLAGS
- },
- GType_ITE,
- GID_ITE_DISK_G2,
- 0,
- ITE_DEFAULT_SCENE,
- &ITE_Resources,
- ARRAYSIZE(ITEDISK_GameFonts),
- ITEDISK_GameFonts,
- &ITEDISK_GameSound,
- &ITEDISK_GameSound,
- &ITEMACCD_GameMusic,
- 0,
- NULL,
- },
+ // ITE Amiga versions /////////////////////////////////////////////////////////////////////////////////////
- // Inherit the earth - Disk version with digital music (compressed sound)
- {
- {
- "ite",
- "Floppy",
- {
- {"ite.rsc", GAME_RESOURCEFILE, "8f4315a9bb10ec839253108a032c8b54", -1},
- {"scripts.rsc", GAME_SCRIPTFILE, "516f7330f8410057b834424ea719d1ef", -1},
- {"voices.cmp", GAME_SOUNDFILE | GAME_VOICEFILE, NULL, -1},
- {"music.cmp", GAME_MUSICFILE, NULL, -1},
- { NULL, 0, NULL, 0}
- },
- Common::EN_ANY,
- Common::kPlatformPC,
- Common::ADGF_NO_FLAGS
- },
- GType_ITE,
- GID_ITE_DISK_G2,
- GF_COMPRESSED_SOUNDS,
- ITE_DEFAULT_SCENE,
- &ITE_Resources,
- ARRAYSIZE(ITEDISK_GameFonts),
- ITEDISK_GameFonts,
- &ITEDISK_GameSound,
- &ITEDISK_GameSound,
- &ITEMACCD_GameMusic,
- 0,
- NULL,
- },
+ // TODO: Add the Amiga versions here (not supported yet)
+
+
+ // IHNM Section ///////////////////////////////////////////////////////////////////////////////////////////
// I Have No Mouth And I Must Scream - Demo version
{
@@ -1377,10 +746,11 @@ static const SAGAGameDescription gameDescriptions[] = {
"ihnm",
"Demo",
{
+ {"music.res", GAME_MUSICFILE_FM, "0439083e3dfdc51b486071d45872ae52", -1},
{"scream.res", GAME_RESOURCEFILE, "46bbdc65d164ba7e89836a0935eec8e6", -1},
{"scripts.res", GAME_SCRIPTFILE, "9626bda8978094ff9b29198bc1ed5f9a", -1},
{"sfx.res", GAME_SOUNDFILE, "1c610d543f32ec8b525e3f652536f269", -1},
- {"voicesd.res", GAME_VOICEFILE, "3bbc16a8f741dbb511da506c660a0b54", -1},
+ //{"voicesd.res", GAME_VOICEFILE, "3bbc16a8f741dbb511da506c660a0b54", -1},
{ NULL, 0, NULL, 0}
},
Common::EN_ANY,
@@ -1390,8 +760,8 @@ static const SAGAGameDescription gameDescriptions[] = {
GType_IHNM,
GID_IHNM_DEMO,
0,
- 0,
- &IHNM_Resources,
+ IHNMDEMO_DEFAULT_SCENE,
+ &IHNMDEMO_Resources,
ARRAYSIZE(IHNMDEMO_GameFonts),
IHNMDEMO_GameFonts,
&IHNM_GameSound,
@@ -1413,13 +783,13 @@ static const SAGAGameDescription gameDescriptions[] = {
{"patch.re_", GAME_PATCHFILE | GAME_RESOURCEFILE, "58b79e61594779513c7f2d35509fa89e", -1},
{"scripts.res", GAME_SCRIPTFILE, "be38bbc5a26be809dbf39f13befebd01", -1},
{"sfx.res", GAME_SOUNDFILE, "1c610d543f32ec8b525e3f652536f269", -1},
- {"voicess.res", GAME_VOICEFILE, "54b1f2013a075338ceb0e258d97808bd", -1}, //order of voice bank file is important
- {"voices1.res", GAME_VOICEFILE, "fc6440b38025f4b2cc3ff55c3da5c3eb", -1},
- {"voices2.res", GAME_VOICEFILE, "b37f10fd1696ade7d58704ccaaebceeb", -1},
- {"voices3.res", GAME_VOICEFILE, "3bbc16a8f741dbb511da506c660a0b54", -1},
- {"voices4.res", GAME_VOICEFILE, "ebfa160122d2247a676ca39920e5d481", -1},
- {"voices5.res", GAME_VOICEFILE, "1f501ce4b72392bdd1d9ec38f6eec6da", -1},
- {"voices6.res", GAME_VOICEFILE, "f580ed7568c7d6ef34e934ba20adf834", -1},
+ //{"voicess.res", GAME_VOICEFILE, "54b1f2013a075338ceb0e258d97808bd", -1}, //order of voice bank file is important
+ //{"voices1.res", GAME_VOICEFILE, "fc6440b38025f4b2cc3ff55c3da5c3eb", -1},
+ //{"voices2.res", GAME_VOICEFILE, "b37f10fd1696ade7d58704ccaaebceeb", -1},
+ //{"voices3.res", GAME_VOICEFILE, "3bbc16a8f741dbb511da506c660a0b54", -1},
+ //{"voices4.res", GAME_VOICEFILE, "ebfa160122d2247a676ca39920e5d481", -1},
+ //{"voices5.res", GAME_VOICEFILE, "1f501ce4b72392bdd1d9ec38f6eec6da", -1},
+ //{"voices6.res", GAME_VOICEFILE, "f580ed7568c7d6ef34e934ba20adf834", -1},
{ NULL, 0, NULL, 0}
},
Common::EN_ANY,
@@ -1454,12 +824,12 @@ static const SAGAGameDescription gameDescriptions[] = {
{"scripts.res", GAME_SCRIPTFILE, "32aa01a89937520fe0ea513950117292", -1},
{"patch.re_", GAME_PATCHFILE | GAME_RESOURCEFILE, "58b79e61594779513c7f2d35509fa89e", -1},
{"sfx.res", GAME_SOUNDFILE, "1c610d543f32ec8b525e3f652536f269", -1},
- {"voicess.res", GAME_VOICEFILE, "8b09a196a52627cacb4eab13bfe0b2c3", -1}, //order of voice bank file is important
- {"voices1.res", GAME_VOICEFILE, "424971e1e2373187c3f5734fe36071a2", -1},
- {"voices2.res", GAME_VOICEFILE, "c270e0980782af43641a86e4a14e2a32", -1},
- {"voices3.res", GAME_VOICEFILE, "49e42befea883fd101ec3d0f5d0647b9", -1},
- {"voices5.res", GAME_VOICEFILE, "c477443c52a0aa56e686ebd8d051e4ab", -1},
- {"voices6.res", GAME_VOICEFILE, "2b9aea838f74b4eecfb29a8f205a2bd4", -1},
+ //{"voicess.res", GAME_VOICEFILE, "8b09a196a52627cacb4eab13bfe0b2c3", -1}, //order of voice bank file is important
+ //{"voices1.res", GAME_VOICEFILE, "424971e1e2373187c3f5734fe36071a2", -1},
+ //{"voices2.res", GAME_VOICEFILE, "c270e0980782af43641a86e4a14e2a32", -1},
+ //{"voices3.res", GAME_VOICEFILE, "49e42befea883fd101ec3d0f5d0647b9", -1},
+ //{"voices5.res", GAME_VOICEFILE, "c477443c52a0aa56e686ebd8d051e4ab", -1},
+ //{"voices6.res", GAME_VOICEFILE, "2b9aea838f74b4eecfb29a8f205a2bd4", -1},
{ NULL, 0, NULL, 0}
},
Common::DE_DEU,
@@ -1492,13 +862,13 @@ static const SAGAGameDescription gameDescriptions[] = {
{"patch.re_", GAME_PATCHFILE | GAME_RESOURCEFILE, "58b79e61594779513c7f2d35509fa89e", -1},
{"scripts.res", GAME_SCRIPTFILE, "be38bbc5a26be809dbf39f13befebd01", -1},
{"sfx.res", GAME_SOUNDFILE, "1c610d543f32ec8b525e3f652536f269", -1},
- {"voicess.res", GAME_VOICEFILE, "d869de9883c8faea7f687217a9ec7057", -1}, //order of voice bank file is important
- {"voices1.res", GAME_VOICEFILE, "dc6a34e3d1668730ea46815a92c7847f", -1},
- {"voices2.res", GAME_VOICEFILE, "dc6a5fa7a4cdc2ca5a6fd924e969986c", -1},
- {"voices3.res", GAME_VOICEFILE, "dc6a5fa7a4cdc2ca5a6fd924e969986c", -1},
- {"voices4.res", GAME_VOICEFILE, "0f87400b804232a58dd22e404420cc45", -1},
- {"voices5.res", GAME_VOICEFILE, "172668cfc5d8c305cb5b1a9b4d995fc0", -1},
- {"voices6.res", GAME_VOICEFILE, "96c9bda9a5f41d6bc232ed7bf6d371d9", -1},
+ //{"voicess.res", GAME_VOICEFILE, "d869de9883c8faea7f687217a9ec7057", -1}, //order of voice bank file is important
+ //{"voices1.res", GAME_VOICEFILE, "dc6a34e3d1668730ea46815a92c7847f", -1},
+ //{"voices2.res", GAME_VOICEFILE, "dc6a5fa7a4cdc2ca5a6fd924e969986c", -1},
+ //{"voices3.res", GAME_VOICEFILE, "dc6a5fa7a4cdc2ca5a6fd924e969986c", -1},
+ //{"voices4.res", GAME_VOICEFILE, "0f87400b804232a58dd22e404420cc45", -1},
+ //{"voices5.res", GAME_VOICEFILE, "172668cfc5d8c305cb5b1a9b4d995fc0", -1},
+ //{"voices6.res", GAME_VOICEFILE, "96c9bda9a5f41d6bc232ed7bf6d371d9", -1},
{ NULL, 0, NULL, 0}
},
Common::ES_ESP,
@@ -1531,13 +901,13 @@ static const SAGAGameDescription gameDescriptions[] = {
{"patch.re_", GAME_PATCHFILE | GAME_RESOURCEFILE, "58b79e61594779513c7f2d35509fa89e", -1},
{"scripts.res", GAME_SCRIPTFILE, "be38bbc5a26be809dbf39f13befebd01", -1},
{"sfx.res", GAME_SOUNDFILE, "1c610d543f32ec8b525e3f652536f269", -1},
- {"voicess.res", GAME_VOICEFILE, "9df7cd3b18ddaa16b5291b3432567036", -1}, //order of voice bank file is important
- {"voices1.res", GAME_VOICEFILE, "d6100d2dc3b2b9f2e1ad247f613dce9b", -1},
- {"voices2.res", GAME_VOICEFILE, "84f6f48ecc2832841ea6417a9a379430", -1},
- {"voices3.res", GAME_VOICEFILE, "ebb9501283047f27a0f54e27b3c8ba1e", -1},
- {"voices4.res", GAME_VOICEFILE, "4c145da5fa6d1306162a7ca8ce5a4f2e", -1},
- {"voices5.res", GAME_VOICEFILE, "871a559644281917677eca4af1b05620", -1},
- {"voices6.res", GAME_VOICEFILE, "211be5c24f066d69a2f6cfa953acfba6", -1},
+ //{"voicess.res", GAME_VOICEFILE, "9df7cd3b18ddaa16b5291b3432567036", -1}, //order of voice bank file is important
+ //{"voices1.res", GAME_VOICEFILE, "d6100d2dc3b2b9f2e1ad247f613dce9b", -1},
+ //{"voices2.res", GAME_VOICEFILE, "84f6f48ecc2832841ea6417a9a379430", -1},
+ //{"voices3.res", GAME_VOICEFILE, "ebb9501283047f27a0f54e27b3c8ba1e", -1},
+ //{"voices4.res", GAME_VOICEFILE, "4c145da5fa6d1306162a7ca8ce5a4f2e", -1},
+ //{"voices5.res", GAME_VOICEFILE, "871a559644281917677eca4af1b05620", -1},
+ //{"voices6.res", GAME_VOICEFILE, "211be5c24f066d69a2f6cfa953acfba6", -1},
{ NULL, 0, NULL, 0}
},
Common::RU_RUS,
@@ -1570,12 +940,12 @@ static const SAGAGameDescription gameDescriptions[] = {
{"scripts.res", GAME_SCRIPTFILE, "32aa01a89937520fe0ea513950117292", -1},
{"patch.re_", GAME_PATCHFILE | GAME_RESOURCEFILE, "58b79e61594779513c7f2d35509fa89e", -1},
{"sfx.res", GAME_SOUNDFILE, "1c610d543f32ec8b525e3f652536f269", -1},
- {"voicess.res", GAME_VOICEFILE, "b8642e943bbebf89cef2f48b31cb4305", -1}, //order of voice bank file is important
- {"voices1.res", GAME_VOICEFILE, "424971e1e2373187c3f5734fe36071a2", -1},
- {"voices2.res", GAME_VOICEFILE, "c2d93a35d2c2def9c3d6d242576c794b", -1},
- {"voices3.res", GAME_VOICEFILE, "49e42befea883fd101ec3d0f5d0647b9", -1},
- {"voices5.res", GAME_VOICEFILE, "f4c415de7c03de86b73f9a12b8bd632f", -1},
- {"voices6.res", GAME_VOICEFILE, "3fc5358a5d8eee43bdfab2740276572e", -1},
+ //{"voicess.res", GAME_VOICEFILE, "b8642e943bbebf89cef2f48b31cb4305", -1}, //order of voice bank file is important
+ //{"voices1.res", GAME_VOICEFILE, "424971e1e2373187c3f5734fe36071a2", -1},
+ //{"voices2.res", GAME_VOICEFILE, "c2d93a35d2c2def9c3d6d242576c794b", -1},
+ //{"voices3.res", GAME_VOICEFILE, "49e42befea883fd101ec3d0f5d0647b9", -1},
+ //{"voices5.res", GAME_VOICEFILE, "f4c415de7c03de86b73f9a12b8bd632f", -1},
+ //{"voices6.res", GAME_VOICEFILE, "3fc5358a5d8eee43bdfab2740276572e", -1},
{ NULL, 0, NULL, 0}
},
Common::FR_FRA,
diff --git a/engines/saga/displayinfo.h b/engines/saga/displayinfo.h
index 83bc536959..74bbcc4343 100644
--- a/engines/saga/displayinfo.h
+++ b/engines/saga/displayinfo.h
@@ -23,6 +23,8 @@
*
*/
+// Interface widget display information
+
#ifndef SAGA_DISPLAYINFO_H
#define SAGA_DISPLAYINFO_H
diff --git a/engines/saga/events.cpp b/engines/saga/events.cpp
index b93c6017c7..80e6b58595 100644
--- a/engines/saga/events.cpp
+++ b/engines/saga/events.cpp
@@ -35,6 +35,7 @@
#include "saga/palanim.h"
#include "saga/render.h"
#include "saga/sndres.h"
+#include "saga/rscfile.h"
#include "saga/music.h"
#include "saga/actor.h"
@@ -344,6 +345,39 @@ int Events::handleOneShot(Event *event) {
_vm->_actor->showActors(true);
}
break;
+ case kPsychicProfileBgEvent:
+ {
+ ResourceContext *context = _vm->_resource->getContext(GAME_RESOURCEFILE);
+
+ byte *resourceData;
+ size_t resourceDataLength;
+
+ _vm->_resource->loadResource(context, _vm->getResourceDescription()->psychicProfileResourceId, 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 profileRect(width, height);
+
+ bgSurface->blit(profileRect, buf);
+ _vm->_frameCount++;
+
+ _vm->_gfx->setPalette(palette);
+
+ free(buf);
+ free(resourceData);
+
+ // Draw the scene. It won't be drawn by Render::drawScene(), as the RF_PLACARD is set
+ _vm->_scene->draw();
+ }
+ break;
case kAnimEvent:
switch (event->op) {
case kEventPlay:
@@ -460,12 +494,13 @@ int Events::handleOneShot(Event *event) {
_vm->_gfx->showCursor(false);
break;
case kEventSetNormalCursor:
- // in ITE there is just one cursor
- if (_vm->getGameType() == GType_IHNM)
+ // in ITE and IHNM demo there is just one cursor
+ if (_vm->getGameType() == GType_IHNM && _vm->getGameId() != GID_IHNM_DEMO)
_vm->_gfx->setCursor(kCursorNormal);
break;
case kEventSetBusyCursor:
- if (_vm->getGameType() == GType_IHNM)
+ // in ITE and IHNM demo there is just one cursor
+ if (_vm->getGameType() == GType_IHNM && _vm->getGameId() != GID_IHNM_DEMO)
_vm->_gfx->setCursor(kCursorBusy);
break;
default:
diff --git a/engines/saga/events.h b/engines/saga/events.h
index d0af1fe916..2486525751 100644
--- a/engines/saga/events.h
+++ b/engines/saga/events.h
@@ -60,7 +60,8 @@ enum EventCodes {
kScriptEvent,
kCursorEvent,
kGraphicsEvent,
- kCutawayEvent
+ kCutawayEvent,
+ kPsychicProfileBgEvent
};
enum EventOps {
diff --git a/engines/saga/font.cpp b/engines/saga/font.cpp
index ece48512df..71cd6b0eef 100644
--- a/engines/saga/font.cpp
+++ b/engines/saga/font.cpp
@@ -24,6 +24,7 @@
*/
// Font management and font drawing module
+
#include "saga/saga.h"
#include "saga/gfx.h"
#include "saga/rscfile.h"
@@ -331,7 +332,7 @@ void Font::outFont(const FontStyle &drawFont, Surface *ds, const char *text, siz
// 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) {
+ if (c_code == FONT_CH_SPACE || c_code == 9) {
textPoint.x += drawFont.fontCharEntry[c_code].tracking;
continue;
}
@@ -629,7 +630,8 @@ void Font::textDrawRect(FontId fontId, Surface *ds, const char *text, const Comm
Font::FontId Font::knownFont2FontIdx(KnownFont font) {
FontId fontId = kSmallFont;
- if (_vm->getGameType() == GType_ITE) {
+ // 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)
{
case (kKnownFontSmall):
@@ -652,7 +654,7 @@ Font::FontId Font::knownFont2FontIdx(KnownFont font) {
fontId = _vm->_font->valid(kBigFont) ? kBigFont : kMediumFont;
break;
}
- } else if (_vm->getGameType() == GType_IHNM) {
+ } else if (_vm->getGameType() == GType_IHNM && _vm->getGameId() != GID_IHNM_DEMO) {
switch (font)
{
case (kKnownFontSmall):
diff --git a/engines/saga/gfx.cpp b/engines/saga/gfx.cpp
index a9c6801714..56ffe04c96 100644
--- a/engines/saga/gfx.cpp
+++ b/engines/saga/gfx.cpp
@@ -130,10 +130,7 @@ void Surface::drawPolyLine(const Point *points, int count, int color) {
}
}
-/**
-* Dissolve one image with another.
-* If flags if set to 1, do zero masking.
-*/
+// Dissolve one image with another. If flags is set to 1, do zero masking.
void Surface::transitionDissolve(const byte *sourceBuffer, const Common::Rect &sourceRect, int flags, double percent) {
#define XOR_MASK 0xB400;
int pixelcount = w * h;
@@ -431,7 +428,10 @@ void Gfx::setCursor(CursorType cursorType) {
switch (cursorType) {
case kCursorBusy:
- resourceId = RID_IHNM_HOURGLASS_CURSOR;
+ if (_vm->getGameId() != GID_IHNM_DEMO)
+ resourceId = RID_IHNM_HOURGLASS_CURSOR;
+ else
+ resourceId = (uint32)-1;
break;
default:
resourceId = (uint32)-1;
diff --git a/engines/saga/ihnm_introproc.cpp b/engines/saga/ihnm_introproc.cpp
index e122082322..631da37e82 100644
--- a/engines/saga/ihnm_introproc.cpp
+++ b/engines/saga/ihnm_introproc.cpp
@@ -31,6 +31,7 @@
#include "saga/animation.h"
#include "saga/events.h"
#include "saga/interface.h"
+#include "saga/rscfile.h"
#include "saga/sndres.h"
#include "saga/music.h"
@@ -39,7 +40,7 @@
namespace Saga {
SceneResourceData IHNM_IntroMovie1RL[] = {
- {30, 2, 0, 0, false} ,
+ {30, 2, 0, 0, false},
{31, 14, 0, 0, false}
};
@@ -50,7 +51,7 @@ SceneDescription IHNM_IntroMovie1Desc = {
};
SceneResourceData IHNM_IntroMovie2RL[] = {
- {32, 2, 0, 0, false} ,
+ {32, 2, 0, 0, false},
{33, 14, 0, 0, false}
};
@@ -82,28 +83,100 @@ SceneDescription IHNM_IntroMovie4Desc = {
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},
+};
+
+// 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
+
+ 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);
- n_introscenes = ARRAYSIZE(IHNM_IntroList);
-
- for (i = 0; i < n_introscenes; i++) {
- _vm->_scene->queueScene(&IHNM_IntroList[i]);
+ 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]);
+ }
+ } else {
+ for (i = 0; i < n_introscenes; i++) {
+ _vm->_scene->queueScene(&IHNMDEMO_IntroList[i]);
+ }
}
firstScene.loadFlag = kLoadBySceneNumber;
@@ -140,16 +213,40 @@ int Scene::IHNMIntroMovieProc1(int param) {
q_event = _vm->_events->queue(&event);
- _vm->_anim->setFrameTime(0, IHNM_INTRO_FRAMETIME);
- _vm->_anim->setFlag(0, ANIM_FLAG_ENDSCENE);
+ 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;
+ 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);
+ }
- q_event = _vm->_events->chain(q_event, &event);
break;
default:
break;
@@ -273,14 +370,16 @@ int Scene::IHNMIntroMovieProc3(int param) {
// 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.
- event.type = kEvTOneshot;
- event.code = kMusicEvent;
- event.param = 1;
- event.param2 = MUSIC_NORMAL;
- event.op = kEventPlay;
- event.time = 0;
+ 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;
- q_event = _vm->_events->chain(q_event, &event);
+ q_event = _vm->_events->chain(q_event, &event);
+ }
// Background for intro scene is the first frame of the intro
// animation; display it but don't set palette
@@ -317,7 +416,10 @@ int Scene::IHNMIntroMovieProc3(int param) {
event.type = kEvTOneshot;
event.code = kSceneEvent;
event.op = kEventEnd;
- event.time = _vm->_music->hasAdlib() ? IHNM_TITLE_TIME_FM : IHNM_TITLE_TIME_GM;
+ 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;
diff --git a/engines/saga/image.cpp b/engines/saga/image.cpp
index f76258c565..9f72036634 100644
--- a/engines/saga/image.cpp
+++ b/engines/saga/image.cpp
@@ -24,6 +24,7 @@
*/
// SAGA Image resource management routines
+
#include "saga/saga.h"
#include "saga/stream.h"
diff --git a/engines/saga/interface.cpp b/engines/saga/interface.cpp
index 55b2b0a996..8cfd993391 100644
--- a/engines/saga/interface.cpp
+++ b/engines/saga/interface.cpp
@@ -337,13 +337,23 @@ int Interface::activate() {
_vm->_script->_skipSpeeches = false;
_vm->_actor->_protagonist->_targetObject = ID_NOTHING;
unlockMode();
- if (_panelMode == kPanelMain || _panelMode == kPanelChapterSelection){
+ if (_panelMode == kPanelMain || _panelMode == kPanelChapterSelection) {
+ _saveReminderState = 1;
+ } else if (_panelMode == kPanelNull && _vm->getGameId() == GID_IHNM_DEMO) {
_saveReminderState = 1;
}
draw();
}
- _vm->_gfx->showCursor(true);
+ 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;
}
@@ -359,18 +369,18 @@ int Interface::deactivate() {
}
void Interface::rememberMode() {
- assert (_savedMode == -1);
+ debug(1, "rememberMode(%d)", _savedMode);
_savedMode = _panelMode;
-
- debug(1, "rememberMode(%d)", _savedMode);
}
void Interface::restoreMode(bool draw_) {
- assert (_savedMode != -1);
-
debug(1, "restoreMode(%d)", _savedMode);
+ // If _savedMode is -1 by a race condition, set it to kPanelMain
+ if (_savedMode == -1)
+ _savedMode = kPanelMain;
+
_panelMode = _savedMode;
_savedMode = -1;
@@ -386,10 +396,23 @@ void Interface::setMode(int mode) {
_saveReminderState = 1; //TODO: blinking timeout
} else if (mode == kPanelChapterSelection) {
_saveReminderState = 1;
+ } else if (mode == kPanelNull) {
+ 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
+ if (_vm->getGameId() == GID_IHNM_DEMO)
+ _vm->_gfx->showCursor(true);
} else {
if (mode == kPanelConverse) {
_inMainMode = false;
}
+
_saveReminderState = 0;
}
@@ -440,12 +463,18 @@ void Interface::setMode(int mode) {
_vm->_render->setFlag(RF_DEMO_SUBST);
break;
case kPanelProtect:
- _protectPanel.currentButton = NULL;
- _textInputMaxWidth = _protectEdit->width - 10;
- _textInput = true;
- _textInputString[0] = 0;
- _textInputStringLength = 0;
- _textInputPos = _textInputStringLength + 1;
+ if (_vm->getGameType() == GType_ITE) {
+ // This is used as the copy protection panel in ITE
+ _protectPanel.currentButton = NULL;
+ _textInputMaxWidth = _protectEdit->width - 10;
+ _textInput = true;
+ _textInputString[0] = 0;
+ _textInputStringLength = 0;
+ _textInputPos = _textInputStringLength + 1;
+ } else {
+ // In the IHNM demo, this panel mode is set by the scripts
+ // to flip through the pages of the help system
+ }
break;
}
@@ -476,6 +505,11 @@ 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();
+ }
break;
case kPanelCutaway:
if (ascii == 27) { // Esc
@@ -484,6 +518,11 @@ bool Interface::processAscii(uint16 ascii) {
_vm->_scene->cutawaySkip();
return true;
}
+
+ if (_vm->getGameId() == GID_IHNM_DEMO) {
+ if (_vm->_scene->currentSceneNumber() >= 144 && _vm->_scene->currentSceneNumber() <= 149)
+ _vm->_scene->showIHNMDemoSpecialScreen();
+ }
break;
case kPanelVideo:
if (ascii == 27) { // Esc
@@ -494,6 +533,12 @@ bool Interface::processAscii(uint16 ascii) {
_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();
}
break;
case kPanelOption:
@@ -632,18 +677,35 @@ bool Interface::processAscii(uint16 ascii) {
keyBossExit();
break;
case kPanelProtect:
- if (_textInput && processTextInput(ascii)) {
- return true;
- }
+ if (_vm->getGameType() == GType_ITE) {
+ if (_textInput && processTextInput(ascii)) {
+ return true;
+ }
- if (ascii == 27 || ascii == 13) { // Esc or Enter
- _vm->_script->wakeUpThreads(kWaitTypeRequest);
- _vm->_interface->setMode(kPanelMain);
-
- _protectHash = 0;
+ if (ascii == 27 || ascii == 13) { // Esc or Enter
+ _vm->_script->wakeUpThreads(kWaitTypeRequest);
+ _vm->_interface->setMode(kPanelMain);
+
+ _protectHash = 0;
- for (char *p = _textInputString; *p; p++)
- _protectHash = (_protectHash << 1) + toupper(*p);
+ for (char *p = _textInputString; *p; p++)
+ _protectHash = (_protectHash << 1) + toupper(*p);
+ }
+ } else {
+ // In the IHNM demo, this panel mode is set by the scripts
+ // to flip through the pages of the help system
+ }
+ break;
+ case kPanelPlacard:
+ if (_vm->getGameType() == GType_IHNM) {
+ // Any keypress here returns the user back to the game
+ if (_vm->getGameId() != GID_IHNM_DEMO) {
+ _vm->_scene->clearPsychicProfile();
+ } else {
+ setMode(kPanelConverse);
+ _vm->_scene->_textList.clear();
+ _vm->_script->wakeUpThreads(kWaitTypeDelay);
+ }
}
break;
}
@@ -656,6 +718,10 @@ void Interface::setStatusText(const char *text, int statusColor) {
if (_vm->getGameType() == GType_IHNM && _vm->_scene->currentChapterNumber() == 8)
return;
+ // Disable the status text in the introduction of the IHNM demo
+ if (_vm->getGameId() == GID_IHNM_DEMO && _vm->_scene->currentSceneNumber() == 0)
+ return;
+
assert(text != NULL);
assert(strlen(text) < STATUS_TEXT_LEN);
@@ -719,7 +785,8 @@ void Interface::draw() {
drawStatusBar();
- if (_panelMode == kPanelMain || _panelMode == kPanelMap) {
+ if (_panelMode == kPanelMain || _panelMode == kPanelMap ||
+ (_panelMode == kPanelNull && _vm->getGameId() == GID_IHNM_DEMO)) {
_mainPanel.getRect(rect);
backBuffer->blit(rect, _mainPanel.image);
@@ -745,7 +812,8 @@ void Interface::draw() {
}
if (_panelMode == kPanelMain || _panelMode == kPanelConverse ||
- _lockedMode == kPanelMain || _lockedMode == kPanelConverse) {
+ _lockedMode == kPanelMain || _lockedMode == kPanelConverse ||
+ (_panelMode == kPanelNull && _vm->getGameId() == GID_IHNM_DEMO)) {
leftPortraitPoint.x = _mainPanel.x + _vm->getDisplayInfo().leftPortraitXOffset;
leftPortraitPoint.y = _mainPanel.y + _vm->getDisplayInfo().leftPortraitYOffset;
_vm->_sprite->draw(backBuffer, _vm->getDisplayClip(), _defPortraits, _leftPortrait, leftPortraitPoint, 256);
@@ -1467,10 +1535,20 @@ void Interface::setOption(PanelButton *panelButton) {
switch (panelButton->id) {
case kTextContinuePlaying:
ConfMan.flushToDisk();
- if (!(_vm->getGameType() == GType_IHNM && _vm->_scene->currentChapterNumber() == 8))
+ if (_vm->getGameType() == GType_ITE) {
setMode(kPanelMain);
- else
- setMode(kPanelChapterSelection);
+ } 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 {
+ setMode(kPanelMain);
+ }
+ }
break;
case kTextQuitGame:
setMode(kPanelQuit);
@@ -1486,6 +1564,12 @@ 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;
+ }
+
if (!_vm->isSaveListFull() && (_optionSaveFileTitleNumber == 0)) {
_textInputString[0] = 0;
} else {
@@ -1536,7 +1620,12 @@ void Interface::update(const Point& mousePoint, int updateFlag) {
_vm->_actor->abortSpeech();
if (_vm->_scene->isInIntro() || _fadeMode == kFadeOut || !_active) {
- return;
+ // When opening the psychic profile, or the options screen in the non-interactive part of the IHNM demo,
+ // the interface is locked (_active is false)
+ // Don't return in those cases, so that mouse actions can be processed
+ if (!(_vm->getGameType() == GType_IHNM && _panelMode == kPanelPlacard && (updateFlag & UPDATE_MOUSECLICK)) &&
+ !(_vm->getGameId() == GID_IHNM_DEMO && (_panelMode == kPanelOption || _panelMode == kPanelQuit)))
+ return;
}
if (_statusTextInput) {
@@ -1682,6 +1771,27 @@ void Interface::update(const Point& mousePoint, int updateFlag) {
// No mouse interaction
break;
+ case kPanelPlacard:
+ if (_vm->getGameType() == GType_IHNM) {
+ // Any mouse click here returns the user back to the game
+ if (updateFlag & UPDATE_MOUSECLICK) {
+ if (_vm->getGameId() != GID_IHNM_DEMO) {
+ _vm->_scene->clearPsychicProfile();
+ } else {
+ setMode(kPanelConverse);
+ _vm->_scene->_textList.clear();
+ _vm->_script->wakeUpThreads(kWaitTypeDelay);
+ }
+ }
+ }
+ break;
+
+ case kPanelNull:
+ if (_vm->getGameId() == GID_IHNM_DEMO && (updateFlag & UPDATE_MOUSECLICK)) {
+ if (_vm->_scene->currentSceneNumber() >= 144 && _vm->_scene->currentSceneNumber() <= 149)
+ _vm->_scene->showIHNMDemoSpecialScreen();
+ }
+ break;
}
_lastMousePoint = mousePoint;
@@ -2016,10 +2126,10 @@ void Interface::drawButtonBox(Surface *ds, const Rect& rect, ButtonKind kind, bo
((byte *)ds->getBasePtr(x, ye))[0] = cornerColor;
((byte *)ds->getBasePtr(xe, y))[0] = cornerColor;
((byte *)ds->getBasePtr(xe, ye))[0] = cornerColor;
- ds->hLine(x + 1, y, x + 1 + w - 2, frameColor);
- ds->hLine(x + 1, ye, x + 1 + w - 2, frameColor);
- ds->vLine(x, y + 1, y + 1 + h - 2, frameColor);
- ds->vLine(xe, y + 1, y + 1 + h - 2, frameColor);
+ ds->hLine(x + 1, y, x + w - 2, frameColor);
+ ds->hLine(x + 1, ye, x + w - 2, frameColor);
+ ds->vLine(x, y + 1, y + h - 2, frameColor);
+ ds->vLine(xe, y + 1, y + h - 2, frameColor);
x++;
y++;
@@ -2029,7 +2139,7 @@ void Interface::drawButtonBox(Surface *ds, const Rect& rect, ButtonKind kind, bo
h -= 2;
ds->vLine(x, y, y + h - 1, odl);
ds->hLine(x, ye, x + w - 1, odl);
- ds->vLine(xe, y, y + h - 1, our);
+ ds->vLine(xe, y, y + h - 2, our);
ds->hLine(x + 1, y, x + 1 + w - 2, our);
x++;
@@ -2042,7 +2152,7 @@ void Interface::drawButtonBox(Surface *ds, const Rect& rect, ButtonKind kind, bo
((byte *)ds->getBasePtr(xe, ye))[0] = fillColor;
ds->vLine(x, y + 1, y + 1 + h - 2, idl);
ds->hLine(x + 1, ye, x + 1 + w - 2, idl);
- ds->vLine(xe, y, y + h - 1, iur);
+ ds->vLine(xe, y, y + h - 2, iur);
ds->hLine(x + 1, y, x + 1 + w - 2, iur);
x++; y++;
diff --git a/engines/saga/isomap.cpp b/engines/saga/isomap.cpp
index 124242204b..4f635c6e3b 100644
--- a/engines/saga/isomap.cpp
+++ b/engines/saga/isomap.cpp
@@ -24,6 +24,7 @@
*/
// Isometric level module
+
#include "saga/saga.h"
#include "saga/gfx.h"
@@ -1609,6 +1610,7 @@ void IsoMap::findTilePath(ActorData* actor, const Location &start, const Locatio
/* if (i > 64) {
i = 64;
}*/
+
actor->_walkStepsCount = i;
if (i) {
actor->setTileDirectionsSize(i, false);
diff --git a/engines/saga/ite_introproc.cpp b/engines/saga/ite_introproc.cpp
index ec4d07c069..1664969644 100644
--- a/engines/saga/ite_introproc.cpp
+++ b/engines/saga/ite_introproc.cpp
@@ -23,7 +23,6 @@
*
*/
-
// Intro sequence scene procedures
#include "saga/saga.h"
diff --git a/engines/saga/list.h b/engines/saga/list.h
index 28159475c3..1363155f43 100644
--- a/engines/saga/list.h
+++ b/engines/saga/list.h
@@ -23,6 +23,8 @@
*
*/
+// List functions
+
#ifndef SAGA_LIST_H
#define SAGA_LIST_H
diff --git a/engines/saga/music.cpp b/engines/saga/music.cpp
index 71b6964530..04e79c174d 100644
--- a/engines/saga/music.cpp
+++ b/engines/saga/music.cpp
@@ -22,6 +22,9 @@
* $Id$
*
*/
+
+// MIDI and digital music class
+
#include "saga/saga.h"
#include "saga/rscfile.h"
@@ -38,14 +41,12 @@ namespace Saga {
#define BUFFER_SIZE 4096
-// I haven't decided yet if it's a good idea to make looping part of the audio
-// stream class, or if I should use a "wrapper" class, like I did for Broken
-// Sword 2, to make it easier to add support for compressed music... but I'll
-// worry about that later.
-
-class RAWInputStream : public Audio::AudioStream {
+class DigitalMusicInputStream : public Audio::AudioStream {
private:
+ Audio::AudioStream *_compressedStream;
ResourceContext *_context;
+ ResourceData * resourceData;
+ GameSoundTypes soundType;
Common::File *_file;
uint32 _filePos;
uint32 _startPos;
@@ -56,6 +57,7 @@ private:
const int16 *_bufferEnd;
const int16 *_pos;
const GameSoundInfo *_musicInfo;
+ Common::MemoryReadStream *_memoryStream;
void refill();
bool eosIntern() const {
@@ -63,7 +65,10 @@ private:
}
public:
- RAWInputStream(SagaEngine *vm, ResourceContext *context, uint32 resourceId, bool looping, uint32 loopStart);
+ DigitalMusicInputStream(SagaEngine *vm, ResourceContext *context, uint32 resourceId, bool looping, uint32 loopStart);
+ ~DigitalMusicInputStream();
+
+ void createCompressedStream();
int readBuffer(int16 *buffer, const int numSamples);
@@ -72,17 +77,36 @@ public:
int getRate() const { return _musicInfo->frequency; }
};
-RAWInputStream::RAWInputStream(SagaEngine *vm, ResourceContext *context, uint32 resourceId, bool looping, uint32 loopStart)
+DigitalMusicInputStream::DigitalMusicInputStream(SagaEngine *vm, ResourceContext *context, uint32 resourceId, bool looping, uint32 loopStart)
: _context(context), _finished(false), _looping(looping), _bufferEnd(_buf + BUFFER_SIZE) {
- ResourceData * resourceData;
+ byte compressedHeader[10];
resourceData = vm->_resource->getResourceData(context, resourceId);
_file = context->getFile(resourceData);
_musicInfo = vm->getMusicInfo();
if (_musicInfo == NULL) {
- error("RAWInputStream() wrong musicInfo");
+ error("DigitalMusicInputStream() wrong musicInfo");
+ }
+
+ _compressedStream = NULL;
+
+ if (Common::File::exists("music.cmp")) {
+ // Read compressed header to determine compression type
+ _file->seek((long)resourceData->offset, SEEK_SET);
+ _file->read(compressedHeader, 9);
+
+ if (compressedHeader[0] == char(0)) {
+ soundType = kSoundMP3;
+ } else if (compressedHeader[0] == char(1)) {
+ soundType = kSoundOGG;
+ } else if (compressedHeader[0] == char(2)) {
+ soundType = kSoundFLAC;
+ }
+
+ createCompressedStream();
+ resourceData->offset += 9; // Skip compressed header
}
// Determine the end position
@@ -96,22 +120,59 @@ RAWInputStream::RAWInputStream(SagaEngine *vm, ResourceContext *context, uint32
refill();
}
-int RAWInputStream::readBuffer(int16 *buffer, const int numSamples) {
+DigitalMusicInputStream::~DigitalMusicInputStream() {
+ delete _compressedStream;
+}
+
+void DigitalMusicInputStream::createCompressedStream() {
+ uint numLoops = _looping ? 0 : 1;
+ _memoryStream = _file->readStream(resourceData->size);
+
+ switch (soundType) {
+#ifdef USE_MAD
+ case kSoundMP3:
+ debug(1, "Playing MP3 compressed digital music");
+ _compressedStream = Audio::makeMP3Stream(_memoryStream, true, 0, 0, numLoops);
+ break;
+#endif
+#ifdef USE_VORBIS
+ case kSoundOGG:
+ debug(1, "Playing OGG compressed digital music");
+ _compressedStream = Audio::makeVorbisStream(_memoryStream, true, 0, 0, numLoops);
+ break;
+#endif
+#ifdef USE_FLAC
+ case kSoundFLAC:
+ debug(1, "Playing FLAC compressed digital music");
+ _compressedStream = Audio::makeFlacStream(_memoryStream, true, 0, 0, numLoops);
+ break;
+#endif
+ default:
+ // Unknown compression
+ error("Trying to play a compressed digital music, but the compression is not known");
+ break;
+ }
+}
+
+int DigitalMusicInputStream::readBuffer(int16 *buffer, const int numSamples) {
+ if (_compressedStream != NULL)
+ return _compressedStream->readBuffer(buffer, numSamples);
+
int samples = 0;
while (samples < numSamples && !eosIntern()) {
- const int len = MIN(numSamples - samples, (int) (_bufferEnd - _pos));
+ int len = 0;
+ len = MIN(numSamples - samples, (int) (_bufferEnd - _pos));
memcpy(buffer, _pos, len * 2);
buffer += len;
_pos += len;
samples += len;
- if (_pos >= _bufferEnd) {
+ if (_pos >= _bufferEnd)
refill();
- }
}
return samples;
}
-void RAWInputStream::refill() {
+void DigitalMusicInputStream::refill() {
if (_finished)
return;
@@ -282,7 +343,7 @@ Music::Music(SagaEngine *vm, Audio::Mixer *mixer, MidiDriver *driver, int enable
xmidiParser = MidiParser::createParser_XMIDI();
smfParser = MidiParser::createParser_SMF();
- _musicContext = _vm->_resource->getContext(GAME_MUSICFILE);
+ _digitalMusicContext = _vm->_resource->getContext(GAME_MUSICFILE);
_songTableLen = 0;
_songTable = 0;
@@ -373,6 +434,10 @@ void Music::play(uint32 resourceId, MusicFlags flags) {
_player->stopMusic();
_mixer->stopHandle(_musicHandle);
+ if (!_vm->_musicVolume) {
+ return;
+ }
+
int realTrackNumber;
if (_vm->getGameType() == GType_ITE) {
@@ -405,7 +470,7 @@ void Music::play(uint32 resourceId, MusicFlags flags) {
if (_vm->getGameType() == GType_ITE) {
if (resourceId >= 9 && resourceId <= 34) {
- if (_musicContext != NULL) {
+ if (_digitalMusicContext != NULL) {
//TODO: check resource size
loopStart = 0;
// fix ITE sunstatm score
@@ -413,61 +478,8 @@ void Music::play(uint32 resourceId, MusicFlags flags) {
loopStart = 4 * 18727;
}
- if (!(_vm->getFeatures() & GF_COMPRESSED_SOUNDS)) {
- // uncompressed digital music
- audioStream = new RAWInputStream(_vm, _musicContext, resourceId - 9, flags == MUSIC_LOOP, loopStart);
- } else {
- // compressed digital music
- ResourceData * musicResourceData;
- Common::File *_file;
- byte compressedHeader[10];
- GameSoundTypes soundType;
-
- musicResourceData = _vm->_resource->getResourceData(_musicContext, resourceId - 9);
- _file = _musicContext->getFile(musicResourceData);
-
- if (_vm->getMusicInfo() == NULL) {
- error("RAWInputStream() wrong musicInfo");
- }
-
- _file->seek((long)musicResourceData->offset, SEEK_SET);
-
- _file->read(compressedHeader, 9);
-
- if (compressedHeader[0] == char(0)) {
- soundType = kSoundMP3;
- } else if (compressedHeader[0] == char(1)) {
- soundType = kSoundOGG;
- } else if (compressedHeader[0] == char(2)) {
- soundType = kSoundFLAC;
- }
-
- switch (soundType) {
-#ifdef USE_MAD
- case kSoundMP3:
- debug(1, "Playing MP3 compressed digital music");
- audioStream = Audio::makeMP3Stream(_file, musicResourceData->size);
- break;
-#endif
-#ifdef USE_VORBIS
- case kSoundOGG:
- debug(1, "Playing OGG compressed digital music");
- audioStream = Audio::makeVorbisStream(_file, musicResourceData->size);
- break;
-#endif
-#ifdef USE_FLAC
- case kSoundFLAC:
- debug(1, "Playing FLAC compressed digital music");
- audioStream = Audio::makeFlacStream(_file, musicResourceData->size);
- break;
-#endif
- default:
- // Unknown compression
- error("Trying to play a compressed digital music, but the compression is not known");
- break;
- }
-
- }
+ // digital music
+ audioStream = new DigitalMusicInputStream(_vm, _digitalMusicContext, resourceId - 9, flags == MUSIC_LOOP, loopStart);
}
}
}
@@ -512,8 +524,10 @@ void Music::play(uint32 resourceId, MusicFlags flags) {
// Oddly enough, the intro music (song 1) is very
// different in the two files. I have no idea why.
+ // Note that the IHNM demo has only got one music file
+ // (music.rsc). It is assumed that it contains FM music
- if (hasAdlib()) {
+ if (hasAdlib() || _vm->getGameId() == GID_IHNM_DEMO) {
context = _vm->_resource->getContext(GAME_MUSICFILE_FM);
} else {
context = _vm->_resource->getContext(GAME_MUSICFILE_GM);
diff --git a/engines/saga/music.h b/engines/saga/music.h
index 96d8608bcd..b038a25a11 100644
--- a/engines/saga/music.h
+++ b/engines/saga/music.h
@@ -137,7 +137,7 @@ private:
int _currentVolume;
int _currentVolumePercent;
- ResourceContext *_musicContext;
+ ResourceContext *_digitalMusicContext;
MidiParser *xmidiParser;
MidiParser *smfParser;
diff --git a/engines/saga/objectmap.cpp b/engines/saga/objectmap.cpp
index 52f2e89be7..9e633a6709 100644
--- a/engines/saga/objectmap.cpp
+++ b/engines/saga/objectmap.cpp
@@ -28,6 +28,7 @@
// Polygon Hit Test code ( HitTestPoly() ) adapted from code (C) Eric Haines
// appearing in Graphics Gems IV, "Point in Polygon Strategies."
// p. 24-46, code: p. 34-45
+
#include "saga/saga.h"
#include "saga/gfx.h"
diff --git a/engines/saga/puzzle.h b/engines/saga/puzzle.h
index 92bf73e2a0..3713cbaab7 100644
--- a/engines/saga/puzzle.h
+++ b/engines/saga/puzzle.h
@@ -23,6 +23,8 @@
*
*/
+// ITE puzzle scene
+
#ifndef SAGA_PUZZLE_H
#define SAGA_PUZZLE_H
diff --git a/engines/saga/render.cpp b/engines/saga/render.cpp
index 16536f762e..930476b4e2 100644
--- a/engines/saga/render.cpp
+++ b/engines/saga/render.cpp
@@ -24,6 +24,7 @@
*/
// Main rendering loop
+
#include "saga/saga.h"
#include "saga/actor.h"
diff --git a/engines/saga/rscfile.cpp b/engines/saga/rscfile.cpp
index 33e8a7d603..4d3ff1e47c 100644
--- a/engines/saga/rscfile.cpp
+++ b/engines/saga/rscfile.cpp
@@ -24,6 +24,7 @@
*/
// RSC Resource file management module
+
#include "saga/saga.h"
#include "saga/actor.h"
@@ -329,6 +330,7 @@ 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();
} else {
delete resourceData->patchData;
resourceData->patchData = NULL;
@@ -343,18 +345,188 @@ bool Resource::loadContext(ResourceContext *context) {
bool Resource::createContexts() {
int i;
ResourceContext *context;
+ char musicFileName[256];
+ char soundFileName[256];
+ char voicesFileName[256];
+ int soundFileIndex = 0;
+ int voicesFileIndex = 0;
+ bool digitalMusic = false;
+ bool soundFileInArray = false;
+ bool voicesFileInArray = false;
+ bool multipleVoices = false;
+ bool censoredVersion = false;
+ uint16 voiceFileType = GAME_VOICEFILE;
_contextsCount = 0;
- for (i = 0; _vm->getFilesDescriptions()[i].fileName; i++)
+ for (i = 0; _vm->getFilesDescriptions()[i].fileName; i++) {
_contextsCount++;
+ if (_vm->getFilesDescriptions()[i].fileType == GAME_SOUNDFILE)
+ soundFileInArray = true;
+ if (_vm->getFilesDescriptions()[i].fileType == GAME_VOICEFILE)
+ voicesFileInArray = true;
+ }
+
+ if (!soundFileInArray) {
+ if (_vm->getGameType() == GType_ITE) {
+ // If the sound file is not specified in the detector table, add it here
+ if (Common::File::exists("sounds.rsc") || Common::File::exists("sounds.cmp")) {
+ _contextsCount++;
+ soundFileIndex = _contextsCount - 1;
+ if (_vm->getFeatures() & GF_COMPRESSED_SOUNDS)
+ sprintf(soundFileName, "sounds.cmp");
+ else
+ sprintf(soundFileName, "sounds.rsc");
+ } else if (Common::File::exists("soundsd.rsc") || Common::File::exists("soundsd.cmp")) {
+ _contextsCount++;
+ soundFileIndex = _contextsCount - 1;
+ if (_vm->getFeatures() & GF_COMPRESSED_SOUNDS)
+ sprintf(soundFileName, "soundsd.cmp");
+ else
+ sprintf(soundFileName, "soundsd.rsc");
+ } else {
+ // No sound file found, don't add any file to the array
+ soundFileInArray = true;
+ // ITE floppy versions have both voices and sounds in voices.rsc
+ voiceFileType = GAME_SOUNDFILE | GAME_VOICEFILE;
+ }
+ } else {
+ // If the sound file is not specified in the detector table, add it here
+ if (Common::File::exists("sfx.res") || Common::File::exists("sfx.cmp")) {
+ _contextsCount++;
+ soundFileIndex = _contextsCount - 1;
+ if (_vm->getFeatures() & GF_COMPRESSED_SOUNDS)
+ sprintf(soundFileName, "sfx.cmp");
+ else
+ sprintf(soundFileName, "sfx.res");
+ } else {
+ // No sound file found, don't add any file to the array
+ soundFileInArray = true;
+ }
+ }
+ }
+
+ if (!voicesFileInArray) {
+ if (_vm->getGameType() == GType_ITE) {
+ // If the voices file is not specified in the detector table, add it here
+ if (Common::File::exists("voices.rsc") || Common::File::exists("voices.cmp")) {
+ _contextsCount++;
+ voicesFileIndex = _contextsCount - 1;
+ if (_vm->getFeatures() & GF_COMPRESSED_SOUNDS)
+ sprintf(voicesFileName, "voices.cmp");
+ else
+ sprintf(voicesFileName, "voices.rsc");
+ } else if (Common::File::exists("voicesd.rsc") || Common::File::exists("voicesd.cmp")) {
+ _contextsCount++;
+ voicesFileIndex = _contextsCount - 1;
+ if (_vm->getFeatures() & GF_COMPRESSED_SOUNDS)
+ sprintf(voicesFileName, "voicesd.cmp");
+ else
+ sprintf(voicesFileName, "voicesd.rsc");
+ } else if (Common::File::exists("inherit the earth voices") ||
+ Common::File::exists("inherit the earth voices.cmp")) {
+ _contextsCount++;
+ voicesFileIndex = _contextsCount - 1;
+ if (_vm->getFeatures() & GF_COMPRESSED_SOUNDS)
+ sprintf(voicesFileName, "inherit the earth voices.cmp");
+ else
+ sprintf(voicesFileName, "inherit the earth voices");
+ // The resources in the Wyrmkeep combined Windows/Mac/Linux CD version are little endian, but
+ // the voice file is big endian. If we got such a version with mixed files, mark this voice file
+ // as big endian
+ if (!_vm->isBigEndian())
+ voiceFileType = GAME_VOICEFILE | GAME_SWAPENDIAN; // This file is big endian
+ } else {
+ // No voice file found, don't add any file to the array
+ voicesFileInArray = true;
+ }
+ } else {
+ // If the voices file is not specified in the detector table, add it here
+ if (Common::File::exists("voicess.res") || Common::File::exists("voicess.cmp")) {
+ _contextsCount++;
+ voicesFileIndex = _contextsCount - 1;
+ // IHNM has multiple voice files
+ multipleVoices = true;
+ // Note: it is assumed that the voices are always last in the list
+ if (Common::File::exists("voices4.res") || Common::File::exists("voices4.cmp")) {
+ _contextsCount += 6; // voices1-voices6
+ } else {
+ // The German and French versions of IHNM don't have Nimdok's chapter, therefore the voices file
+ // for that chapter is missing
+ _contextsCount += 5; // voices1-voices3, voices4-voices5
+ censoredVersion = true;
+ }
+ if (_vm->getFeatures() & GF_COMPRESSED_SOUNDS)
+ sprintf(voicesFileName, "voicess.cmp");
+ else
+ sprintf(voicesFileName, "voicess.res");
+ } else if (Common::File::exists("voicesd.res") || Common::File::exists("voicesd.cmp")) {
+ _contextsCount++;
+ voicesFileIndex = _contextsCount - 1;
+ if (_vm->getFeatures() & GF_COMPRESSED_SOUNDS)
+ sprintf(voicesFileName, "voicesd.cmp");
+ else
+ sprintf(voicesFileName, "voicesd.res");
+ } else {
+ // No voice file found, don't add any file to the array
+ voicesFileInArray = true;
+ }
+ }
+ }
+
+ if (_vm->getGameType() == GType_ITE) {
+ // Check for digital music in ITE
+ if (Common::File::exists("music.rsc") || Common::File::exists("music.cmp")) {
+ _contextsCount++;
+ digitalMusic = true;
+ if (Common::File::exists("music.cmp"))
+ sprintf(musicFileName, "music.cmp");
+ else
+ sprintf(musicFileName, "music.rsc");
+ } else if (Common::File::exists("musicd.rsc") || Common::File::exists("musicd.cmp")) {
+ _contextsCount++;
+ digitalMusic = true;
+ if (Common::File::exists("musicd.cmp"))
+ sprintf(musicFileName, "musicd.cmp");
+ else
+ sprintf(musicFileName, "musicd.rsc");
+ } else {
+ digitalMusic = false;
+ }
+ }
_contexts = (ResourceContext*)calloc(_contextsCount, sizeof(*_contexts));
for (i = 0; i < _contextsCount; i++) {
context = &_contexts[i];
context->file = new Common::File();
- context->fileName = _vm->getFilesDescriptions()[i].fileName;
- context->fileType = _vm->getFilesDescriptions()[i].fileType;
+
+ // For ITE, add the digital music file and sfx file information here
+ if (_vm->getGameType() == GType_ITE && digitalMusic && i == _contextsCount - 1) {
+ context->fileName = musicFileName;
+ context->fileType = GAME_MUSICFILE;
+ } else if (!soundFileInArray && i == soundFileIndex) {
+ context->fileName = soundFileName;
+ context->fileType = GAME_SOUNDFILE;
+ } else if (!voicesFileInArray && i == voicesFileIndex) {
+ context->fileName = voicesFileName;
+ // can be GAME_VOICEFILE or GAME_SOUNDFILE | GAME_VOICEFILE or GAME_VOICEFILE | GAME_SWAPENDIAN
+ context->fileType = voiceFileType;
+ } else {
+ if (!(!voicesFileInArray && multipleVoices && (i > voicesFileIndex))) {
+ context->fileName = _vm->getFilesDescriptions()[i].fileName;
+ context->fileType = _vm->getFilesDescriptions()[i].fileType;
+ } else {
+ int token = (censoredVersion && (i - voicesFileIndex >= 4)) ? 1 : 0; // censored versions don't have voice4
+
+ if (_vm->getFeatures() & GF_COMPRESSED_SOUNDS)
+ sprintf(voicesFileName, "voices%i.cmp", i - voicesFileIndex + token);
+ else
+ sprintf(voicesFileName, "voices%i.res", i - voicesFileIndex + token);
+
+ context->fileName = voicesFileName;
+ context->fileType = GAME_VOICEFILE;
+ }
+ }
context->serial = 0;
// IHNM has serveral different voice files, so we need to allow
@@ -434,13 +606,20 @@ 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)
+ file->close();
}
static int metaResourceTable[] = { 0, 326, 517, 677, 805, 968, 1165, 0, 1271 };
+static int metaResourceTableDemo[] = { 0, 0, 0, 0, 0, 0, 0, 285, 0 };
void Resource::loadGlobalResources(int chapter, int actorsEntrance) {
- if (chapter < 0)
- chapter = 8;
+ if (chapter < 0) {
+ if (_vm->getGameId() != GID_IHNM_DEMO)
+ chapter = 8;
+ else
+ chapter = 7;
+ }
// TODO
//if (module.voiceLUT)
@@ -465,8 +644,13 @@ void Resource::loadGlobalResources(int chapter, int actorsEntrance) {
byte *resourcePointer;
size_t resourceLength;
- _vm->_resource->loadResource(resourceContext, metaResourceTable[chapter],
- resourcePointer, resourceLength);
+ if (_vm->getGameId() != GID_IHNM_DEMO) {
+ _vm->_resource->loadResource(resourceContext, metaResourceTable[chapter],
+ resourcePointer, resourceLength);
+ } else {
+ _vm->_resource->loadResource(resourceContext, metaResourceTableDemo[chapter],
+ resourcePointer, resourceLength);
+ }
if (resourceLength == 0) {
error("Resource::loadGlobalResources wrong metaResource");
@@ -555,22 +739,27 @@ void Resource::loadGlobalResources(int chapter, int actorsEntrance) {
_vm->_anim->loadCutawayList(resourcePointer, resourceLength);
- _vm->_resource->loadResource(resourceContext, _metaResource.songTableID, resourcePointer, resourceLength);
+ if (_metaResource.songTableID > 0) {
+ _vm->_resource->loadResource(resourceContext, _metaResource.songTableID, resourcePointer, resourceLength);
- if (resourceLength == 0) {
- error("Resource::loadGlobalResources Can't load songs list for current track");
- }
+ if (resourceLength == 0) {
+ error("Resource::loadGlobalResources Can't load songs list for current track");
+ }
- free(_vm->_music->_songTable);
-
- _vm->_music->_songTableLen = resourceLength / 4;
- _vm->_music->_songTable = (int32 *)malloc(sizeof(int32) * _vm->_music->_songTableLen);
+ free(_vm->_music->_songTable);
+
+ _vm->_music->_songTableLen = resourceLength / 4;
+ _vm->_music->_songTable = (int32 *)malloc(sizeof(int32) * _vm->_music->_songTableLen);
- MemoryReadStream songS(resourcePointer, resourceLength);
+ MemoryReadStream songS(resourcePointer, resourceLength);
- for (i = 0; i < _vm->_music->_songTableLen; i++)
- _vm->_music->_songTable[i] = songS.readSint32LE();
- free(resourcePointer);
+ for (i = 0; i < _vm->_music->_songTableLen; i++)
+ _vm->_music->_songTable[i] = songS.readSint32LE();
+ free(resourcePointer);
+ } else {
+ // The IHNM demo has a fixed music track and doesn't load a song table
+ _vm->_music->play(3, MUSIC_LOOP);
+ }
int voiceLUTResourceID = 0;
@@ -602,6 +791,9 @@ void Resource::loadGlobalResources(int chapter, int actorsEntrance) {
voiceLUTResourceID = 28;
break;
case 7:
+ // IHNM demo
+ _vm->_sndRes->setVoiceBank(0);
+ voiceLUTResourceID = 17;
break;
case 8:
_vm->_sndRes->setVoiceBank(0);
diff --git a/engines/saga/rscfile.h b/engines/saga/rscfile.h
index f8b6ddc3be..2df3b2eb7c 100644
--- a/engines/saga/rscfile.h
+++ b/engines/saga/rscfile.h
@@ -83,6 +83,8 @@ struct ResourceContext {
Common::File *getFile(ResourceData *resourceData) const {
if (resourceData->patchData != NULL) {
+ if (!resourceData->patchData->_patchFile->isOpen())
+ resourceData->patchData->_patchFile->open(resourceData->patchData->_patchDescription->fileName);
return resourceData->patchData->_patchFile;
} else {
return file;
diff --git a/engines/saga/saga.cpp b/engines/saga/saga.cpp
index 99462c5583..76731c201a 100644
--- a/engines/saga/saga.cpp
+++ b/engines/saga/saga.cpp
@@ -107,7 +107,6 @@ SagaEngine::SagaEngine(OSystem *syst)
// Mac CD Wyrmkeep
Common::File::addDefaultDirectory(_gameDataPath + "patch/");
-
// Setup mixer
if (!_mixer->isReady()) {
warning("Sound initialization failed.");
@@ -150,6 +149,8 @@ int SagaEngine::init() {
_subtitlesEnabled = ConfMan.getBool("subtitles");
_readingSpeed = getTalkspeed();
_copyProtection = ConfMan.getBool("copy_protection");
+ _gf_wyrmkeep = false;
+ _gf_compressed_sounds = false;
if (_readingSpeed > 3)
_readingSpeed = 0;
@@ -454,6 +455,9 @@ ColorId SagaEngine::KnownColor2ColorId(KnownColor knownColor) {
colorId = kITEColorTransBlack;
break;
+ case (kKnownColorBrightWhite):
+ colorId = kITEColorBrightWhite;
+ break;
case (kKnownColorBlack):
colorId = kIHNMColorBlack;
break;
diff --git a/engines/saga/saga.h b/engines/saga/saga.h
index 844a738418..43952fe564 100644
--- a/engines/saga/saga.h
+++ b/engines/saga/saga.h
@@ -301,6 +301,7 @@ struct GameResourceDescription {
uint32 mainPanelSpritesResourceId;
uint32 optionPanelSpritesResourceId;
uint32 defaultPortraitsResourceId;
+ uint32 psychicProfileResourceId;
uint32 mainStringsResourceId;
uint32 actorsStringsResourceId;
};
@@ -527,6 +528,8 @@ public:
int _readingSpeed;
bool _copyProtection;
+ bool _gf_wyrmkeep;
+ bool _gf_compressed_sounds;
SndRes *_sndRes;
Sound *_sound;
@@ -548,7 +551,7 @@ public:
Resource *_resource;
- /** Random number generator */
+ // Random number generator
Common::RandomSource _rnd;
private:
diff --git a/engines/saga/sagaresnames.h b/engines/saga/sagaresnames.h
index 94f97635c1..761ac1ab68 100644
--- a/engines/saga/sagaresnames.h
+++ b/engines/saga/sagaresnames.h
@@ -45,8 +45,9 @@ namespace Saga {
#define RID_IHNMDEMO_SCENE_LUT 286
#define RID_IHNMDEMO_SCRIPT_LUT 18
+#define RID_IHNMDEMO_SFX_LUT 222
-//obj names
+// Object names
#define ITE_OBJ_MAP 14
#define ITE_OBJ_MAGIC_HAT 0
@@ -54,10 +55,10 @@ namespace Saga {
#define RID_IHNM_DEFAULT_PALETTE 1
-//actor names
+// Actor names
#define ITE_ACTOR_PUZZLE 176
-// SCENES
+// Scenes
#define ITE_SCENE_INV -1
#define ITE_SCENE_PUZZLE 26
#define ITE_SCENE_LODGE 21
@@ -67,13 +68,14 @@ namespace Saga {
#define IHNM_DEFAULT_SCENE 151
#define ITEDEMO_DEFAULT_SCENE 68
+#define IHNMDEMO_DEFAULT_SCENE 144
-// FONTS
+// Fonts
#define RID_MEDIUM_FONT 0
#define RID_BIG_FONT 1
#define RID_SMALL_FONT 2
-// INTERFACE IMAGES
+// Interface images
#define RID_ITE_MAIN_PANEL 3
#define RID_ITE_CONVERSE_PANEL 4
#define RID_ITE_OPTION_PANEL 5
@@ -99,7 +101,7 @@ namespace Saga {
#define RID_IHNM_MAIN_PANEL 9
#define RID_IHNM_CONVERSE_PANEL 10
#define RID_IHNM_HOURGLASS_CURSOR 11
-#define RID_IHNM_MAIN_SPRITES 12 // TODO: verify this
+#define RID_IHNM_MAIN_SPRITES 12
#define RID_IHNM_MAIN_PANEL_SPRITES 12
#define RID_IHNM_ARROW_SPRITES 13
#define RID_IHNM_SAVEREMINDER_SPRITES 14
@@ -110,6 +112,20 @@ namespace Saga {
#define RID_IHNM_PROFILE_BG 20
#define RID_IHNM_MAIN_STRINGS 21
+#define RID_IHNMDEMO_MAIN_PANEL 5
+#define RID_IHNMDEMO_CONVERSE_PANEL 6
+#define RID_IHNMDEMO_HOURGLASS_CURSOR 6 // Does not exist in the demo
+#define RID_IHNMDEMO_MAIN_SPRITES 7
+#define RID_IHNMDEMO_MAIN_PANEL_SPRITES 7
+#define RID_IHNMDEMO_ARROW_SPRITES 8
+#define RID_IHNMDEMO_SAVEREMINDER_SPRITES 9
+#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_PROFILE_BG 15
+#define RID_IHNMDEMO_MAIN_STRINGS 16
+
// Puzzle portraits
#define RID_ITE_SAKKA_APPRAISING 6
#define RID_ITE_SAKKA_DENIAL 7
@@ -151,7 +167,7 @@ namespace Saga {
#define RID_ITE_INTRO_IMG_3 1561
#define RID_ITE_INTRO_IMG_4 1565
-// ITE_VOICES
+// ITE voices
#define RID_CAVE_VOICE_0 0
#define RID_CAVE_VOICE_1 1
#define RID_CAVE_VOICE_2 2
@@ -177,7 +193,7 @@ namespace Saga {
#define RID_BOAR_VOICE_006 245
#define RID_BOAR_VOICE_007 246
-// MUSIC
+// Music
#define MUSIC_1 9
#define MUSIC_2 10
#define MUSIC_SUNSPOT 26
@@ -185,7 +201,7 @@ namespace Saga {
// TODO: If the sound effects are numbered sequentially, we don't really need
// these constants. But for now they might be useful for debugging.
-// SOUND EFFECTS
+// Sound effects
#define FX_DOOR_OPEN 14
#define FX_DOOR_CLOSE 15
diff --git a/engines/saga/saveload.cpp b/engines/saga/saveload.cpp
index bb3164a79c..77d7816963 100644
--- a/engines/saga/saveload.cpp
+++ b/engines/saga/saveload.cpp
@@ -172,14 +172,6 @@ void SagaEngine::fillSaveList() {
}
i++;
}
-/* 4debug
- for (i = 0; i < 14; i++) {
- sprintf(_saveFiles[i].name,"test%i", i);
- _saveFiles[i].slotNumber = i;
- }
- _saveFilesCount = 14;
- _saveFilesMaxCount = 14;
- */
}
@@ -294,7 +286,10 @@ void SagaEngine::load(const char *fileName) {
_scene->setCurrentMusicTrack(in->readSint32LE());
_scene->setCurrentMusicRepeat(in->readSint32LE());
_music->stop();
- _music->play(_music->_songTable[_scene->getCurrentMusicTrack()], _scene->getCurrentMusicRepeat() ? MUSIC_LOOP : MUSIC_NORMAL);
+ if (getGameId() != GID_IHNM_DEMO)
+ _music->play(_music->_songTable[_scene->getCurrentMusicTrack()], _scene->getCurrentMusicRepeat() ? MUSIC_LOOP : MUSIC_NORMAL);
+ else
+ _music->play(3, MUSIC_LOOP);
}
// Inset scene
diff --git a/engines/saga/scene.cpp b/engines/saga/scene.cpp
index 362b212b14..c49fe546ee 100644
--- a/engines/saga/scene.cpp
+++ b/engines/saga/scene.cpp
@@ -570,8 +570,6 @@ void Scene::loadScene(LoadSceneParams *loadSceneParams) {
_chapterPointsChanged = false;
- _vm->_actor->showActors(false);
-
if ((_vm->getGameType() == GType_IHNM) && (loadSceneParams->chapter != NO_CHAPTER_CHANGE)) {
if (loadSceneParams->loadFlag != kLoadBySceneNumber) {
error("loadScene wrong usage");
@@ -581,7 +579,16 @@ void Scene::loadScene(LoadSceneParams *loadSceneParams) {
_vm->_interface->setLeftPortrait(0);
_vm->_anim->freeCutawayList();
- _vm->_script->freeModules();
+ // 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();
+
// deleteAllScenes();
// installSomeAlarm()
@@ -591,10 +598,14 @@ void Scene::loadScene(LoadSceneParams *loadSceneParams) {
_vm->_interface->addToInventory(IHNM_OBJ_PROFILE);
_vm->_interface->activate();
- if (loadSceneParams->chapter == 8 || loadSceneParams->chapter == -1)
- _vm->_interface->setMode(kPanelChapterSelection);
- else
+ if (loadSceneParams->chapter == 8 || loadSceneParams->chapter == -1) {
+ if (_vm->getGameId() != GID_IHNM_DEMO)
+ _vm->_interface->setMode(kPanelChapterSelection);
+ else
+ _vm->_interface->setMode(kPanelNull);
+ } else {
_vm->_interface->setMode(kPanelMain);
+ }
_inGame = true;
@@ -640,6 +651,15 @@ void Scene::loadScene(LoadSceneParams *loadSceneParams) {
debug(3, "Loading scene number %d:", _sceneNumber);
+ if (_vm->getGameId() == GID_IHNM_DEMO && _sceneNumber == 144) {
+ // 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
+ _vm->_interface->deactivate();
+ _vm->_interface->setMode(kPanelNull);
+ }
+
// Load scene descriptor and resource list resources
if (_loadDescription) {
debug(3, "Loading scene resource %i", _sceneResourceId);
@@ -1282,4 +1302,174 @@ void Scene::loadSceneEntryList(const byte* resourcePointer, size_t resourceLengt
}
}
+void Scene::clearPlacard() {
+ static PalEntry cur_pal[PAL_ENTRIES];
+ PalEntry *pal;
+ Event event;
+ Event *q_event;
+
+ _vm->_interface->restoreMode();
+
+ _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;
+
+ 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);
+
+ _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 = 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);
+}
+
+void Scene::showPsychicProfile(const char *text) {
+ int textHeight;
+ static PalEntry cur_pal[PAL_ENTRIES];
+ PalEntry *pal;
+ TextListEntry textEntry;
+ Event event;
+ Event *q_event;
+
+ if (_vm->_interface->getMode() == kPanelPlacard)
+ return;
+
+ _vm->_interface->rememberMode();
+ _vm->_interface->setMode(kPanelPlacard);
+ _vm->_gfx->savePalette();
+
+ event.type = kEvTOneshot;
+ event.code = kCursorEvent;
+ event.op = kEventHide;
+
+ q_event = _vm->_events->queue(&event);
+
+ _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;
+ event.code = kInterfaceEvent;
+ event.op = kEventClearStatus;
+
+ q_event = _vm->_events->chain(q_event, &event);
+
+ event.type = kEvTOneshot;
+ event.code = kGraphicsEvent;
+ event.op = kEventSetFlag;
+ event.param = RF_PLACARD;
+
+ 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();
+
+ if (text != NULL) {
+ textHeight = _vm->_font->getHeight(kKnownFontVerb, text, 226, kFontCentered);
+
+ textEntry.knownColor = kKnownColorBlack;
+ textEntry.useRect = true;
+ textEntry.rect.left = 245;
+ textEntry.rect.setHeight(210 + 76);
+ textEntry.rect.setWidth(226);
+ textEntry.rect.top = 210 - textHeight;
+ textEntry.font = kKnownFontVerb;
+ textEntry.flags = (FontEffectFlags)(kFontCentered);
+ textEntry.text = text;
+
+ TextListEntry *_psychicProfileTextEntry = _vm->_scene->_textList.addEntry(textEntry);
+
+ event.type = kEvTOneshot;
+ event.code = kTextEvent;
+ event.op = kEventDisplay;
+ event.data = _psychicProfileTextEntry;
+
+ 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);
+}
+
+void Scene::clearPsychicProfile() {
+ if (_vm->_interface->getMode() == kPanelPlacard || _vm->getGameId() == GID_IHNM_DEMO) {
+ _vm->_scene->clearPlacard();
+ _vm->_scene->_textList.clear();
+ _vm->_actor->showActors(false);
+ _vm->_gfx->restorePalette();
+ _vm->_scene->restoreScene();
+ _vm->_interface->activate();
+ }
+}
+
+void Scene::showIHNMDemoSpecialScreen() {
+ _vm->_gfx->showCursor(true);
+ _vm->_interface->clearInventory();
+ _vm->_scene->changeScene(150, 0, kTransitionFade);
+}
+
} // End of namespace Saga
diff --git a/engines/saga/scene.h b/engines/saga/scene.h
index 5fa4569949..da97bddff5 100644
--- a/engines/saga/scene.h
+++ b/engines/saga/scene.h
@@ -340,6 +340,11 @@ class Scene {
return _vm->getDisplayInfo().sceneHeight;
}
+ void clearPlacard();
+ void showPsychicProfile(const char *text);
+ void clearPsychicProfile();
+ void showIHNMDemoSpecialScreen();
+
private:
void loadScene(LoadSceneParams *loadSceneParams);
void loadSceneDescriptor(uint32 resourceId);
@@ -392,13 +397,11 @@ class Scene {
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_IHNMHateProc(int param, void *refCon);
private:
int IHNMIntroMovieProc1(int param);
int IHNMIntroMovieProc2(int param);
int IHNMIntroMovieProc3(int param);
- int IHNMHateProc(int param);
public:
static int SC_ITEIntroAnimProc(int param, void *refCon);
diff --git a/engines/saga/script.cpp b/engines/saga/script.cpp
index 262d63c51f..82fcb352c0 100644
--- a/engines/saga/script.cpp
+++ b/engines/saga/script.cpp
@@ -750,6 +750,10 @@ void Script::whichObject(const Point& mousePoint) {
_leftButtonVerb = _currentVerb;
newRightButtonVerb = getVerbType(kVerbNone);
+ // _protagonist can be null while loading a game from the command line
+ if (_vm->_actor->_protagonist == NULL)
+ return;
+
if (_vm->_actor->_protagonist->_currentAction != kActionWalkDir) {
if (_vm->_scene->getHeight() >= mousePoint.y) {
newObjectId = _vm->_actor->hitTest(mousePoint, true);
diff --git a/engines/saga/script.h b/engines/saga/script.h
index 5adfb6181a..5e5e702132 100644
--- a/engines/saga/script.h
+++ b/engines/saga/script.h
@@ -380,6 +380,7 @@ public:
setPointerVerb();
}
int getVerbType(VerbTypes verbType);
+ TextListEntry *getPlacardTextEntry() { return _placardTextEntry; }
private:
// When reading or writing data to the common buffer, we have to use a
@@ -443,6 +444,7 @@ private:
int _stickyVerb;
int _leftButtonVerb;
int _rightButtonVerb;
+ int _ihnmDemoCurrentY;
public:
uint16 _pendingObject[2];
@@ -590,11 +592,12 @@ private:
void sfScriptStartVideo(SCRIPTFUNC_PARAMS);
void sfScriptReturnFromVideo(SCRIPTFUNC_PARAMS);
void sfScriptEndVideo(SCRIPTFUNC_PARAMS);
- void sf87(SCRIPTFUNC_PARAMS);
- void sf88(SCRIPTFUNC_PARAMS);
- void sf89(SCRIPTFUNC_PARAMS);
+ void sfShowIHNMDemoHelpBg(SCRIPTFUNC_PARAMS);
+ void sfAddIHNMDemoHelpTextLine(SCRIPTFUNC_PARAMS);
+ void sfShowIHNMDemoHelpPage(SCRIPTFUNC_PARAMS);
void sfGetPoints(SCRIPTFUNC_PARAMS);
void sfSetGlobalFlag(SCRIPTFUNC_PARAMS);
+ void sf92(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 4954188a6e..c0e44584df 100644
--- a/engines/saga/sfuncs.cpp
+++ b/engines/saga/sfuncs.cpp
@@ -40,6 +40,7 @@
#include "saga/render.h"
#include "saga/sound.h"
#include "saga/sndres.h"
+#include "saga/rscfile.h"
#include "saga/script.h"
#include "saga/objectmap.h"
@@ -224,12 +225,12 @@ static const ScriptFunctionDescription IHNMscriptFunctionsList[IHNM_SCRIPT_FUNCT
OPCODE(sfScriptReturnFromVideo),
OPCODE(sfScriptEndVideo),
OPCODE(sfSetActorZ),
- OPCODE(sf87),
- OPCODE(sf88),
- OPCODE(sf89),
+ OPCODE(sfShowIHNMDemoHelpBg),
+ OPCODE(sfAddIHNMDemoHelpTextLine),
+ OPCODE(sfShowIHNMDemoHelpPage),
OPCODE(sfVstopFX),
OPCODE(sfVstopLoopedFX),
- OPCODE(sfNull),
+ OPCODE(sf92), // only used in the demo version of IHNM
OPCODE(sfDemoIsInteractive),
OPCODE(sfVsetTrack),
OPCODE(sfGetPoints),
@@ -277,7 +278,16 @@ void Script::sfTakeObject(SCRIPTFUNC_PARAMS) {
obj = _vm->_actor->getObj(objectId);
if (obj->_sceneNumber != ITE_SCENE_INV) {
obj->_sceneNumber = ITE_SCENE_INV;
- //4debug for (int j=0;j<17;j++)
+
+ // 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)
+ obj->_spriteListResourceId = 24;
+ if (obj->_spriteListResourceId == 3 && objectId == 16409)
+ obj->_spriteListResourceId = 25;
+ }
+
_vm->_interface->addToInventory(objectId);
}
}
@@ -562,16 +572,19 @@ void Script::sfScriptGotoScene(SCRIPTFUNC_PARAMS) {
}
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
- // to it.
- Event event;
- event.type = kEvTImmediate;
- event.code = kCutawayEvent;
- event.op = kEventClear;
- event.time = 0;
- event.duration = 0;
- _vm->_events->queue(&event);
+ // cutaway after the intro, this is probably the best place to do it
+ _vm->_anim->clearCutaway();
}
// It is possible to leave scene when converse panel is on,
@@ -868,10 +881,16 @@ void Script::sfDropObject(SCRIPTFUNC_PARAMS) {
_vm->_scene->currentSceneNumber() == 59 && obj->_id == 16385)
obj->_sceneNumber = -1;
- if (_vm->getGameType() == GType_IHNM)
- obj->_spriteListResourceId = spriteId;
- else
+ if (_vm->getGameType() == GType_IHNM) {
+ if (_vm->getGameId() != GID_IHNM_DEMO) {
+ obj->_spriteListResourceId = spriteId;
+ } else {
+ // Don't update the object's _spriteListResourceId in the IHNM demo, as this function is
+ // called incorrectly there (with spriteId == 0, which resets the object sprites)
+ }
+ } else {
obj->_spriteListResourceId = OBJ_SPRITE_BASE + spriteId;
+ }
obj->_location.x = x;
obj->_location.y = y;
@@ -1296,11 +1315,6 @@ void Script::sfPlacard(SCRIPTFUNC_PARAMS) {
Event event;
Event *q_event;
- if (_vm->getGameType() == GType_IHNM) {
- warning("Psychic profile is not implemented");
- return;
- }
-
thread->wait(kWaitTypePlacard);
_vm->_interface->rememberMode();
@@ -1397,72 +1411,24 @@ void Script::sfPlacard(SCRIPTFUNC_PARAMS) {
// Script function #49 (0x31)
void Script::sfPlacardOff(SCRIPTFUNC_PARAMS) {
- static PalEntry cur_pal[PAL_ENTRIES];
- PalEntry *pal;
- Event event;
- Event *q_event;
-
thread->wait(kWaitTypePlacard);
- _vm->_interface->restoreMode();
-
- _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;
-
- q_event = _vm->_events->chain(q_event, &event);
-
- event.type = kEvTOneshot;
- event.code = kTextEvent;
- event.op = kEventRemove;
- 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 = 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);
-
+ _vm->_scene->clearPlacard();
}
void Script::sfPsychicProfile(SCRIPTFUNC_PARAMS) {
- SF_stub("sfPsychicProfile", thread, nArgs);
+ thread->wait(kWaitTypePlacard);
+
+ int stringId = thread->pop();
+ _vm->_scene->showPsychicProfile(thread->_strings->getString(stringId));
}
void Script::sfPsychicProfileOff(SCRIPTFUNC_PARAMS) {
- SF_stub("sfPsychicProfileOff", thread, nArgs);
+ thread->wait(kWaitTypePlacard);
+
+ // This is called a while after the psychic profile is
+ // opened, to close it automatically
+ _vm->_scene->clearPsychicProfile();
}
// Script function #50 (0x32)
@@ -1695,7 +1661,7 @@ void Script::sfPlayMusic(SCRIPTFUNC_PARAMS) {
int16 param = thread->pop() + 9;
if (param >= 9 && param <= 34) {
- _vm->_music->setVolume(-1, 1);
+ _vm->_music->setVolume(_vm->_musicVolume == 10 ? -1 : _vm->_musicVolume * 25, 1);
_vm->_music->play(param);
} else {
_vm->_music->stop();
@@ -1712,7 +1678,7 @@ void Script::sfPlayMusic(SCRIPTFUNC_PARAMS) {
if (param1 >= _vm->_music->_songTableLen) {
warning("sfPlayMusic: Wrong song number (%d > %d)", param1, _vm->_music->_songTableLen - 1);
} else {
- _vm->_music->setVolume(-1, 1);
+ _vm->_music->setVolume(_vm->_musicVolume == 10 ? -1 : _vm->_musicVolume * 25, 1);
_vm->_music->play(_vm->_music->_songTable[param1], param2 ? MUSIC_LOOP : MUSIC_NORMAL);
if (!_vm->_scene->haveChapterPointsChanged()) {
_vm->_scene->setCurrentMusicTrack(param1);
@@ -2032,16 +1998,49 @@ void Script::sfScriptEndVideo(SCRIPTFUNC_PARAMS) {
_vm->_anim->endVideo();
}
-void Script::sf87(SCRIPTFUNC_PARAMS) {
- SF_stub("sf87", thread, nArgs);
+void Script::sfShowIHNMDemoHelpBg(SCRIPTFUNC_PARAMS) {
+ _ihnmDemoCurrentY = 0;
+ _vm->_scene->_textList.clear();
+ _vm->_interface->setMode(kPanelConverse);
+ _vm->_scene->showPsychicProfile(NULL);
}
-void Script::sf88(SCRIPTFUNC_PARAMS) {
- SF_stub("sf88", thread, nArgs);
+void Script::sfAddIHNMDemoHelpTextLine(SCRIPTFUNC_PARAMS) {
+ int stringId, textHeight;
+ 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;
+ textEntry.rect.setHeight(210 + 76);
+ textEntry.rect.setWidth(226);
+ textEntry.rect.top = 76 + _ihnmDemoCurrentY;
+ textEntry.font = kKnownFontVerb;
+ textEntry.flags = (FontEffectFlags)(kFontCentered);
+ textEntry.text = thread->_strings->getString(stringId);
+
+ TextListEntry *_psychicProfileTextEntry = _vm->_scene->_textList.addEntry(textEntry);
+
+ event.type = kEvTOneshot;
+ event.code = kTextEvent;
+ event.op = kEventDisplay;
+ event.data = _psychicProfileTextEntry;
+
+ _vm->_events->queue(&event);
+
+ _ihnmDemoCurrentY += 10;
}
-void Script::sf89(SCRIPTFUNC_PARAMS) {
- SF_stub("sf89", thread, nArgs);
+void Script::sfShowIHNMDemoHelpPage(SCRIPTFUNC_PARAMS) {
+ // Note: The IHNM demo changes panel mode to 8 (kPanelProtect in ITE)
+ // when changing pages
+ _vm->_interface->setMode(kPanelPlacard);
+ _ihnmDemoCurrentY = 0;
}
void Script::sfVstopFX(SCRIPTFUNC_PARAMS) {
@@ -2052,6 +2051,11 @@ 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::sfDemoIsInteractive(SCRIPTFUNC_PARAMS) {
thread->_returnValue = 0;
}
@@ -2144,7 +2148,7 @@ void Script::sfQueueMusic(SCRIPTFUNC_PARAMS) {
if (param1 >= _vm->_music->_songTableLen) {
warning("sfQueueMusic: Wrong song number (%d > %d)", param1, _vm->_music->_songTableLen - 1);
} else {
- _vm->_music->setVolume(-1, 1);
+ _vm->_music->setVolume(_vm->_musicVolume == 10 ? -1 : _vm->_musicVolume * 25, 1);
event.type = kEvTOneshot;
event.code = kMusicEvent;
event.param = _vm->_music->_songTable[param1];
diff --git a/engines/saga/sndres.cpp b/engines/saga/sndres.cpp
index ceb1ebf630..edbdebabab 100644
--- a/engines/saga/sndres.cpp
+++ b/engines/saga/sndres.cpp
@@ -44,7 +44,7 @@
namespace Saga {
SndRes::SndRes(SagaEngine *vm) : _vm(vm) {
- /* Load sound module resource file contexts */
+ // Load sound module resource file contexts
_sfxContext = _vm->_resource->getContext(GAME_SOUNDFILE);
if (_sfxContext == NULL) {
error("SndRes::SndRes resource context not found");
@@ -68,8 +68,13 @@ SndRes::SndRes(SagaEngine *vm) : _vm(vm) {
byte *resourcePointer;
size_t resourceLength;
- _vm->_resource->loadResource(resourceContext, RID_IHNM_SFX_LUT,
- resourcePointer, resourceLength);
+ if (_vm->getGameId() == GID_IHNM_DEMO) {
+ _vm->_resource->loadResource(resourceContext, RID_IHNMDEMO_SFX_LUT,
+ resourcePointer, resourceLength);
+ } else {
+ _vm->_resource->loadResource(resourceContext, RID_IHNM_SFX_LUT,
+ resourcePointer, resourceLength);
+ }
if (resourceLength == 0) {
error("Sndres::SndRes can't read SfxIDs table");
@@ -169,7 +174,6 @@ bool SndRes::load(ResourceContext *context, uint32 resourceId, SoundBuffer &buff
MemoryReadStream readS(soundResource, soundResourceLength);
resourceType = soundInfo->resourceType;
- buffer.isBigEndian = soundInfo->isBigEndian;
if (soundResourceLength >= 8) {
if (!memcmp(soundResource, "Creative", 8)) {
@@ -178,7 +182,17 @@ bool SndRes::load(ResourceContext *context, uint32 resourceId, SoundBuffer &buff
resourceType = kSoundWAV;
}
- if (_vm->getFeatures() & GF_COMPRESSED_SOUNDS) {
+ 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")))
+ uncompressedSound = true;
+
+ // FIXME: Currently, the SFX.RES file in IHNM cannot be compressed
+ if (_vm->getGameType() == GType_IHNM && (context->fileType & GAME_SOUNDFILE))
+ uncompressedSound = true;
+
+ if ((_vm->getFeatures() & GF_COMPRESSED_SOUNDS) && !uncompressedSound) {
if (soundResource[0] == char(0)) {
resourceType = kSoundMP3;
} else if (soundResource[0] == char(1)) {
@@ -190,6 +204,9 @@ bool SndRes::load(ResourceContext *context, uint32 resourceId, SoundBuffer &buff
}
+ buffer.isBigEndian = soundInfo->isBigEndian;
+ buffer.soundType = resourceType;
+ buffer.originalSize = 0;
switch (resourceType) {
case kSoundPCM:
@@ -319,7 +336,7 @@ int SndRes::getVoiceLength(uint32 resourceId) {
return -1;
}
- if (!(_vm->getFeatures() & GF_COMPRESSED_SOUNDS))
+ if (!(_vm->getFeatures() & GF_COMPRESSED_SOUNDS) || buffer.originalSize == 0)
msDouble = (double)buffer.size;
else
msDouble = (double)buffer.originalSize;
diff --git a/engines/saga/sound.cpp b/engines/saga/sound.cpp
index 6c2516c8a3..621b3ed310 100644
--- a/engines/saga/sound.cpp
+++ b/engines/saga/sound.cpp
@@ -83,31 +83,40 @@ void Sound::playSoundBuffer(Audio::SoundHandle *handle, SoundBuffer &buffer, int
if (!(_vm->getFeatures() & GF_COMPRESSED_SOUNDS)) {
_mixer->playRaw(Audio::Mixer::kSFXSoundType, handle, buffer.buffer, buffer.size, buffer.frequency, flags, -1, volume);
} else {
- buffer.soundFile->seek((long)buffer.fileOffset, SEEK_SET);
Audio::AudioStream *stream = NULL;
+ Common::MemoryReadStream *tmp = NULL;
switch (buffer.soundType) {
#ifdef USE_MAD
case kSoundMP3:
debug(1, "Playing MP3 compressed sound");
- stream = Audio::makeMP3Stream(buffer.soundFile, buffer.size);
+ buffer.soundFile->seek((long)buffer.fileOffset, SEEK_SET);
+ tmp = buffer.soundFile->readStream(buffer.size);
+ assert(tmp);
+ stream = Audio::makeMP3Stream(tmp, true);
break;
#endif
#ifdef USE_VORBIS
case kSoundOGG:
debug(1, "Playing OGG compressed sound");
- stream = Audio::makeVorbisStream(buffer.soundFile, buffer.size);
+ buffer.soundFile->seek((long)buffer.fileOffset, SEEK_SET);
+ tmp = buffer.soundFile->readStream(buffer.size);
+ assert(tmp);
+ stream = Audio::makeVorbisStream(tmp, true);
break;
#endif
#ifdef USE_FLAC
case kSoundFLAC:
debug(1, "Playing FLAC compressed sound");
- stream = Audio::makeFlacStream(buffer.soundFile, buffer.size);
+ buffer.soundFile->seek((long)buffer.fileOffset, SEEK_SET);
+ tmp = buffer.soundFile->readStream(buffer.size);
+ assert(tmp);
+ stream = Audio::makeFlacStream(tmp, true);
break;
#endif
default:
- // Unknown compression
- error("Trying to play a compressed sound, but the compression is not known");
+ // No compression, play it as raw sound
+ _mixer->playRaw(Audio::Mixer::kSFXSoundType, handle, buffer.buffer, buffer.size, buffer.frequency, flags, -1, volume);
break;
}
diff --git a/engines/saga/sprite.cpp b/engines/saga/sprite.cpp
index 607e7d0a0b..ac911e5a9c 100644
--- a/engines/saga/sprite.cpp
+++ b/engines/saga/sprite.cpp
@@ -24,6 +24,7 @@
*/
// Sprite management module
+
#include "saga/saga.h"
#include "saga/gfx.h"
@@ -57,8 +58,13 @@ Sprite::Sprite(SagaEngine *vm) : _vm(vm) {
loadList(_vm->getResourceDescription()->mainSpritesResourceId, _mainSprites);
_arrowSprites = _saveReminderSprites = _inventorySprites = _mainSprites;
} else {
- loadList(RID_IHNM_ARROW_SPRITES, _arrowSprites);
- loadList(RID_IHNM_SAVEREMINDER_SPRITES, _saveReminderSprites);
+ if (_vm->getGameId() == GID_IHNM_DEMO) {
+ loadList(RID_IHNMDEMO_ARROW_SPRITES, _arrowSprites);
+ loadList(RID_IHNMDEMO_SAVEREMINDER_SPRITES, _saveReminderSprites);
+ } else {
+ loadList(RID_IHNM_ARROW_SPRITES, _arrowSprites);
+ loadList(RID_IHNM_SAVEREMINDER_SPRITES, _saveReminderSprites);
+ }
}
}
@@ -113,7 +119,9 @@ void Sprite::loadList(int resourceId, SpriteList &spriteList) {
offset = readS.readUint16();
if (offset >= spriteListLength) {
- error("Sprite::loadList offset exceed");
+ // ITE Mac demos throw this warning
+ warning("Sprite::loadList offset exceeded");
+ return;
}
spritePointer = spriteListData;
diff --git a/engines/scumm/charset.cpp b/engines/scumm/charset.cpp
index 28012e5759..2271bf53a1 100644
--- a/engines/scumm/charset.cpp
+++ b/engines/scumm/charset.cpp
@@ -48,6 +48,11 @@ better separation of the various modules.
void ScummEngine::loadCJKFont() {
Common::File fp;
_useCJKMode = false;
+ _textSurfaceMultiplier = 1;
+
+ if (_game.platform == Common::kPlatformSegaCD)
+ return;
+
if (_language == Common::JA_JPN && _game.version <= 5) { // FM-TOWNS v3 / v5 Kanji
int numChar = 256 * 32;
_2byteWidth = 16;
@@ -60,6 +65,7 @@ void ScummEngine::loadCJKFont() {
fp.read(_2byteFontPtr, ((_2byteWidth + 7) / 8) * _2byteHeight * numChar);
fp.close();
}
+ _textSurfaceMultiplier = 2;
} else if (_language == Common::KO_KOR || _language == Common::JA_JPN || _language == Common::ZH_TWN) {
int numChar = 0;
const char *fontFile = NULL;
@@ -76,7 +82,7 @@ void ScummEngine::loadCJKFont() {
case Common::ZH_TWN:
if (_game.id == GID_CMI) {
fontFile = "chinese.fnt";
- numChar = 1; //FIXME
+ numChar = 13630;
}
break;
default:
@@ -85,9 +91,26 @@ void ScummEngine::loadCJKFont() {
if (fontFile && fp.open(fontFile)) {
debug(2, "Loading CJK Font");
_useCJKMode = true;
- fp.seek(2, SEEK_CUR);
- _2byteWidth = fp.readByte();
- _2byteHeight = fp.readByte();
+ _textSurfaceMultiplier = 1; // No multiplication here
+
+ switch (_language) {
+ case Common::KO_KOR:
+ fp.seek(2, SEEK_CUR);
+ _2byteWidth = fp.readByte();
+ _2byteHeight = fp.readByte();
+ break;
+ case Common::JA_JPN:
+ _2byteWidth = 16;
+ _2byteHeight = 16;
+ break;
+ case Common::ZH_TWN:
+ _2byteWidth = 16;
+ _2byteHeight = 15;
+ // 0xFE -> 0x21. also compared with 0x0d. perhaps a newline
+ break;
+ default:
+ break;
+ }
_2byteFontPtr = new byte[((_2byteWidth + 7) / 8) * _2byteHeight * numChar];
fp.read(_2byteFontPtr, ((_2byteWidth + 7) / 8) * _2byteHeight * numChar);
@@ -183,7 +206,7 @@ static int SJIStoFMTChunk(int f, int s) { //converts sjis code to fmt font offse
}
byte *ScummEngine::get2byteCharPtr(int idx) {
- switch (_language) {
+ switch (_language) {
case Common::KO_KOR:
idx = ((idx % 256) - 0xb0) * 94 + (idx / 256) - 0xa1;
break;
@@ -191,6 +214,43 @@ byte *ScummEngine::get2byteCharPtr(int idx) {
idx = SJIStoFMTChunk((idx % 256), (idx / 256));
break;
case Common::ZH_TWN:
+ {
+ int base = 0;
+ byte low = idx % 256;
+ int high = 0;
+
+ if (low >= 0x20 && low <= 0x7e) {
+ base = (low + low * 2 + 81012) * 5;
+ } else {
+ if (low >= 0xa1 && low <= 0xa3) {
+ base = 392820;
+ low += 0x5f;
+ } else if (low >= 0xa4 && low <= 0xc6) {
+ base = 0;
+ low += 0x5c;
+ } else if (low >= 0xc9 && low <= 0xf9) {
+ base = 162030;
+ low += 0x37;
+ } else {
+ base = 392820;
+ low = 0xff;
+ }
+
+ if (low != 0xff) {
+ high = idx / 256;
+ if (high >= 0x40 && high <= 0x7e) {
+ high -= 0x40;
+ } else {
+ high -= 0x62;
+ }
+
+ base += (low * 0x9d + high) * 30;
+ }
+ }
+
+ return _2byteFontPtr + base;
+ break;
+ }
default:
idx = 0;
}
@@ -311,7 +371,7 @@ int CharsetRenderer::getStringWidth(int arg, const byte *text) {
break;
}
} else {
- if (chr == '@')
+ if (chr == '@' && _vm->_language != Common::ZH_TWN)
continue;
if (chr == 255 || (_vm->_game.version <= 6 && chr == 254)) {
chr = text[pos++];
@@ -337,6 +397,15 @@ int CharsetRenderer::getStringWidth(int arg, const byte *text) {
continue;
}
}
+
+ // Some localizations may override colors
+ // See credits in Chinese COMI
+ if (chr == '^' && pos == 1) {
+ if (text[pos] == 'c') {
+ pos += 4;
+ chr = text[pos++];
+ }
+ }
}
if ((chr & 0x80) && _vm->_useCJKMode) {
pos++;
@@ -1257,18 +1326,18 @@ void CharsetRendererV3::printChar(int chr, bool ignoreCharsetMask) {
_hasMask = true;
_textScreenID = vs->number;
}
- if (ignoreCharsetMask || !vs->hasTwoBuffers) {
+ if ((ignoreCharsetMask || !vs->hasTwoBuffers) && !(_vm->_useCJKMode && _vm->_textSurfaceMultiplier == 2)) {
dst = vs->getPixels(_left, drawTop);
drawBits1(*vs, dst, charPtr, drawTop, origWidth, origHeight);
} else {
- dst = (byte *)_vm->_textSurface.pixels + _top * _vm->_textSurface.pitch + _left;
+ dst = (byte *)_vm->_textSurface.getBasePtr(_left * _vm->_textSurfaceMultiplier, _top * _vm->_textSurfaceMultiplier);
drawBits1(_vm->_textSurface, dst, charPtr, drawTop, origWidth, origHeight);
}
if (_str.left > _left)
_str.left = _left;
- _left += origWidth;
+ _left += origWidth / _vm->_textSurfaceMultiplier;
if (_str.right < _left) {
_str.right = _left;
@@ -1276,8 +1345,8 @@ void CharsetRendererV3::printChar(int chr, bool ignoreCharsetMask) {
_str.right++;
}
- if (_str.bottom < _top + height)
- _str.bottom = _top + height;
+ if (_str.bottom < _top + height / _vm->_textSurfaceMultiplier)
+ _str.bottom = _top + height / _vm->_textSurfaceMultiplier;
}
void CharsetRendererV3::drawChar(int chr, const Graphics::Surface &s, int x, int y) {
@@ -1391,8 +1460,8 @@ void CharsetRendererClassic::printChar(int chr, bool ignoreCharsetMask) {
_top += offsY;
_left += offsX;
- if (_left + origWidth > _right + 1 || _left < 0) {
- _left += origWidth;
+ if (_left + origWidth / _vm->_textSurfaceMultiplier > _right + 1 || _left < 0) {
+ _left += origWidth / _vm->_textSurfaceMultiplier;
_top -= offsY;
return;
}
@@ -1424,7 +1493,7 @@ void CharsetRendererClassic::printChar(int chr, bool ignoreCharsetMask) {
printCharIntern(is2byte, charPtr, origWidth, origHeight, width, height, vs, ignoreCharsetMask);
- _left += origWidth;
+ _left += origWidth / _vm->_textSurfaceMultiplier;
if (_str.right < _left) {
_str.right = _left;
@@ -1432,8 +1501,8 @@ void CharsetRendererClassic::printChar(int chr, bool ignoreCharsetMask) {
_str.right++;
}
- if (_str.bottom < _top + height)
- _str.bottom = _top + height;
+ if (_str.bottom < _top + height / _vm->_textSurfaceMultiplier)
+ _str.bottom = _top + height / _vm->_textSurfaceMultiplier;
_top -= offsY;
}
@@ -1473,12 +1542,12 @@ void CharsetRendererClassic::printCharIntern(bool is2byte, const byte *charPtr,
} else {
Graphics::Surface dstSurface;
Graphics::Surface backSurface;
- if (ignoreCharsetMask || !vs->hasTwoBuffers) {
+ if ((ignoreCharsetMask || !vs->hasTwoBuffers) && !(_vm->_useCJKMode && _vm->_textSurfaceMultiplier == 2)) {
dstSurface = *vs;
dstPtr = vs->getPixels(_left, drawTop);
} else {
dstSurface = _vm->_textSurface;
- dstPtr = (byte *)_vm->_textSurface.pixels + (_top - _vm->_screenTop) * _vm->_textSurface.pitch + _left;
+ dstPtr = (byte *)_vm->_textSurface.pixels + (_top - _vm->_screenTop) * _vm->_textSurface.pitch * _vm->_textSurfaceMultiplier + _left * _vm->_textSurfaceMultiplier;
}
if (_blitAlso && vs->hasTwoBuffers) {
@@ -1717,6 +1786,10 @@ void CharsetRendererNut::printChar(int chr, bool ignoreCharsetMask) {
if (_str.left > _left)
_str.left = _left;
+ // Original keeps glyph width and character dimensions separately
+ if (_vm->_language == Common::ZH_TWN && width == 16)
+ width = 17;
+
_left += width;
if (_str.right < shadow.right)
diff --git a/engines/scumm/detection.cpp b/engines/scumm/detection.cpp
index e9430337ff..be830cab64 100644
--- a/engines/scumm/detection.cpp
+++ b/engines/scumm/detection.cpp
@@ -231,14 +231,21 @@ static Common::Language detectLanguage(const FSList &fslist, byte id) {
switch (size) {
case 439080: // 2daf3db71d23d99d19fc9a544fcf6431
return Common::EN_ANY;
+ case 322602: // caba99f4f5a0b69963e5a4d69e6f90af
+ return Common::ZH_TWN;
case 493252: // 5d59594b24f3f1332e7d7e17455ed533
return Common::DE_DEU;
case 461746: // 35bbe0e4d573b318b7b2092c331fd1fa
return Common::FR_FRA;
case 443439: // 4689d013f67aabd7c35f4fd7c4b4ad69
return Common::IT_ITA;
+ case 398613: // d1f5750d142d34c4c8f1f330a1278709
+ return Common::KO_KOR;
case 440586: // 5a1d0f4fa00917bdbfe035a72a6bba9d
return Common::PT_BRA;
+ case 454457: // 0e5f450ec474a30254c0e36291fb4ebd
+ case 394083: // ad684ca14c2b4bf4c21a81c1dbed49bc
+ return Common::RU_RUS;
case 449787: // 64f3fe479d45b52902cf88145c41d172
return Common::ES_ESP;
}
diff --git a/engines/scumm/detection_tables.h b/engines/scumm/detection_tables.h
index 246126611e..acde4e5ad0 100644
--- a/engines/scumm/detection_tables.h
+++ b/engines/scumm/detection_tables.h
@@ -79,6 +79,7 @@ static const PlainGameDescriptor gameDescriptions[] = {
{ "comi", "The Curse of Monkey Island" },
#endif
+ { "brstorm", "Bear Stormin'" },
{ "fbear", "Fatty Bear's Birthday Surprise" },
{ "fbpack", "Fatty Bear's Fun Pack" },
{ "funpack", "Putt-Putt's Fun Pack" },
@@ -248,6 +249,7 @@ static const GameSettings gameVariantsTable[] = {
{"funpack", 0, 0, GID_FUNPACK, 6, 61, MDT_ADLIB | MDT_MIDI, GF_USE_KEY, UNK},
{"fbpack", 0, 0, GID_HEGAME, 6, 61, MDT_ADLIB | MDT_MIDI, GF_USE_KEY, UNK},
+ {"brstorm", 0, 0, GID_FBEAR, 6, 61, MDT_ADLIB | MDT_MIDI, GF_USE_KEY, UNK},
{"fbear", "HE 61", 0, GID_FBEAR, 6, 61, MDT_ADLIB | MDT_MIDI, GF_USE_KEY, UNK},
{"fbear", "HE 70", 0, GID_FBEAR, 6, 70, MDT_NONE, GF_USE_KEY, Common::kPlatformWindows},
@@ -461,6 +463,8 @@ static const GameFilenamePattern gameFilenamesTable[] = {
{ "fbpack", "fbpack", kGenHEPC, UNK_LANG, UNK, 0 },
{ "funpack", "funpack", kGenHEPC, UNK_LANG, UNK, 0 },
+ { "brstorm", "brstorm", kGenHEPC, UNK_LANG, UNK, 0 },
+
{ "fbear", "fbear", kGenHEPC, UNK_LANG, UNK, 0 },
{ "fbear", "fbdemo", kGenHEPC, UNK_LANG, UNK, 0 },
{ "fbear", "Fatty Bear Demo", kGenHEMacNoParens, UNK_LANG, Common::kPlatformMacintosh, 0 },
diff --git a/engines/scumm/gfx.cpp b/engines/scumm/gfx.cpp
index 3547986ce3..c1e06609b9 100644
--- a/engines/scumm/gfx.cpp
+++ b/engines/scumm/gfx.cpp
@@ -35,9 +35,12 @@
#include "scumm/usage_bits.h"
#include "scumm/he/wiz_he.h"
#include "scumm/util.h"
-#ifdef __DS__
-#include "blitters.h"
-#endif
+
+#ifdef USE_ARM_GFX_ASM
+extern "C" void DrawStripToScreenARM(int height, int width, byte const* text, byte const* src, byte* dst,
+ int vsPitch, int vmScreenWidth, int textSurfacePitch);
+extern "C" void Copy8ColARM(byte* dst, int dstPitch, const byte* src, int height);
+#endif /* USE_ARM_GFX_ASM */
namespace Scumm {
@@ -47,6 +50,7 @@ static void fill(byte *dst, int dstPitch, byte color, int w, int h);
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);
struct StripTable {
int offsets[160];
@@ -535,21 +539,18 @@ void ScummEngine::updateDirtyScreen(VirtScreenNumber slot) {
*/
void ScummEngine::drawStripToScreen(VirtScreen *vs, int x, int width, int top, int bottom) {
- if (bottom <= top)
+ // Short-circuit if nothing has to be drawn
+ if (bottom <= top || top >= vs->h)
return;
- if (top >= vs->h)
- return;
-
- assert(top >= 0 && bottom <= vs->h); // Paranoia checks
+ // Some paranoia checks
+ assert(top >= 0 && bottom <= vs->h);
assert(x >= 0 && width <= vs->pitch);
assert(_textSurface.pixels);
- assert(_compositeBuf);
+ // Perform some clipping
if (width > vs->w - x)
width = vs->w - x;
-
- // Clip to the visible part of the scene
if (top < _screenTop)
top = _screenTop;
if (bottom > _screenTop + _screenHeight)
@@ -559,64 +560,112 @@ void ScummEngine::drawStripToScreen(VirtScreen *vs, int x, int width, int top, i
int y = vs->topline + top - _screenTop;
int height = bottom - top;
- if (height <= 0 || width <= 0)
+ if (width <= 0 || height <= 0)
return;
- // Compute screen etc. buffer pointers
const byte *src = vs->getPixels(x, top);
- byte *dst = _compositeBuf + x + y * _screenWidth;
+ int m = _textSurfaceMultiplier;
+ byte *dst;
+ int vsPitch;
+ int pitch = vs->pitch;
+
+ if (_useCJKMode && _textSurfaceMultiplier == 2) {
+ dst = _fmtownsBuf;
+
+ scale2x(dst, _screenWidth * m, src, vs->pitch, width, height);
+ src = dst;
+ vsPitch = _screenWidth * m - width * m;
+
+ } else {
+ vsPitch = vs->pitch - width;
+ }
+
+ dst = _compositeBuf;
+
if (_game.version < 7) {
- // Handle the text mask in older games; newer (V7/V8) games do not use it anymore.
- const byte *text = (byte *)_textSurface.getBasePtr(x, y);
-
-#ifdef __DS__
- DS::asmDrawStripToScreen(height, width, text, src, dst, vs->pitch, _screenWidth, _textSurface.pitch);
-#else
+ // For The Dig, FT and COMI, we just blit everything to the screen at once.
+ // For older games, things are more complicated. First off, we need to
+ // deal with the _textSurface, which needs to be composited over the
+ // screen contents. Secondly, a rendering mode might be active, which
+ // means a filter has to be applied.
+
+ // Compute pointer to the text surface
+ assert(_compositeBuf);
+ const byte *text = (byte *)_textSurface.getBasePtr(x * m, y * m);
+
+ // The values x, width, etc. are all multiples of 8 at this point,
+ // so loop unrolloing might be a good idea...
+ assert(0 == ((long)text & 3));
+ assert(0 == (width & 3));
+
// Compose the text over the game graphics
- for (int h = 0; h < height; ++h) {
- for (int w = 0; w < width; ++w) {
- if (text[w] == CHARSET_MASK_TRANSPARENCY)
- dst[w] = src[w];
- else
- dst[w] = text[w];
+
+ // TODO: Optimize this code. There are several things that come immediately to mind:
+ // (1) Loop unrolling: We could read 4 or even 8 pixels at once, since everything is
+ // a multiple of 8 here.
+ // (2) More ASM versions (in particular, the ARM code for the NDS could be used on
+ // all ARM systems, couldn't it?)
+ // (3) Better encoding of the text surface data. This is the one with the biggest
+ // potential.
+ // (a) Keep an "isEmpty" marker for each pixel row in the _textSurface. The idea
+ // is that most rows won't contain any text data, so we can just use memcpy.
+ // (b) RLE encode the _textSurface row-wise. This is an improved variant of (a),
+ // but also more complicated to implement, and incurs a bigger overhead when
+ // writing to the text surface.
+#ifdef ARM_USE_GFX_ASM
+ DrawStripToScreenARM(height, width, text, src, dst, vs->pitch, width, _textSurface.pitch);
+#else
+ for (int h = 0; h < height * m; ++h) {
+ for (int w = 0; w < width * m; ++w) {
+ byte tmp = *text++;
+ if (tmp == CHARSET_MASK_TRANSPARENCY)
+ tmp = *src;
+ *dst++ = tmp;
+ src++;
}
- src += vs->pitch;
- dst += _screenWidth;
- text += _textSurface.pitch;
+ src += vsPitch;
+ text += _textSurface.pitch - width * m;
}
#endif
- } else {
- // Just do a simple blit in V7/V8 games.
- blit(dst, _screenWidth, src, vs->pitch, width, height);
- }
-
- if (_renderMode == Common::kRenderCGA)
- ditherCGA(_compositeBuf + x + y * _screenWidth, _screenWidth, x, y, width, height);
+ src = _compositeBuf;
+ pitch = width;
+
+ if (_renderMode == Common::kRenderHercA || _renderMode == Common::kRenderHercG) {
+ ditherHerc(_compositeBuf, _herculesBuf, width, &x, &y, &width, &height);
+
+ src = _herculesBuf + x + y * Common::kHercW;
+ pitch = Common::kHercW;
+
+ // center image on the screen
+ x += (Common::kHercW - _screenWidth * 2) / 2; // (720 - 320*2)/2 = 40
+ } else if (_useCJKMode && m == 2) {
+ pitch *= m;
+ x *= m;
+ y *= m;
+ width *= m;
+ height *= m;
+ } else {
+ if (_renderMode == Common::kRenderCGA)
+ ditherCGA(_compositeBuf, width, x, y, width, height);
+
+ // HACK: This is dirty hack which renders narrow NES rooms centered
+ // NES can address negative number strips and that poses problem for
+ // our code. So instead of adding zillions of fixes and potentially
+ // breaking other games, we shift it right at the rendering stage.
+ if ((_game.platform == Common::kPlatformNES) && (((_NESStartStrip > 0) && (vs->number == kMainVirtScreen)) || (vs->number == kTextVirtScreen))) {
+ x += 16;
+ while (x + width >= _screenWidth)
+ width -= 16;
+ if (width < 0)
+ return;
+ }
- if (_renderMode == Common::kRenderHercA || _renderMode == Common::kRenderHercG) {
- ditherHerc(_compositeBuf + x + y * _screenWidth, _herculesBuf, _screenWidth, &x, &y, &width, &height);
- // center image on the screen
- _system->copyRectToScreen(_herculesBuf + x + y * Common::kHercW,
- Common::kHercW, x + (Common::kHercW - _screenWidth * 2) / 2, y, width, height);
- } else {
- // Finally blit the whole thing to the screen
- int x1 = x;
-
- // HACK: This is dirty hack which renders narrow NES rooms centered
- // NES can address negative number strips and that poses problem for
- // our code. So instead of adding zillions of fixes and potentially
- // breaking other games, we shift it right at the rendering stage.
- if ((_game.platform == Common::kPlatformNES) && (((_NESStartStrip > 0) && (vs->number == kMainVirtScreen)) || (vs->number == kTextVirtScreen))) {
- x += 16;
- while (x + width >= _screenWidth)
- width -= 16;
- if (width < 0)
- return;
}
-
- _system->copyRectToScreen(_compositeBuf + x1 + y * _screenWidth, _screenWidth, x, y, width, height);
}
+
+ // Finally blit the whole thing to the screen
+ _system->copyRectToScreen(src, pitch, x, y, width, height);
}
// CGA
@@ -644,10 +693,10 @@ void ScummEngine::ditherCGA(byte *dst, int dstPitch, int x, int y, int width, in
for (int y1 = 0; y1 < height; y1++) {
ptr = dst + y1 * dstPitch;
- idx1 = (y + y1) % 2;
-
if (_game.version == 2)
idx1 = 0;
+ else
+ idx1 = (y + y1) % 2;
for (int x1 = 0; x1 < width; x1++) {
idx2 = (x + x1) % 2;
@@ -666,39 +715,52 @@ void ScummEngine::ditherCGA(byte *dst, int dstPitch, int x, int y, int width, in
// dd cccc0
// cccc1
// dddd0
-void ScummEngine::ditherHerc(byte *src, byte *hercbuf, int srcPitch, int *x, int *y, int *width, int *height) const {
+void ditherHerc(byte *src, byte *hercbuf, int srcPitch, int *x, int *y, int *width, int *height) {
byte *srcptr, *dstptr;
- int xo = *x, yo = *y, widtho = *width, heighto = *height;
- int idx1, idx2, dsty = 0, y1;
+ const int xo = *x, yo = *y, widtho = *width, heighto = *height;
+ int dsty = yo*2 - yo/4;
- // calculate dsty
- for (y1 = 0; y1 < yo; y1++) {
- dsty += 2;
- if (y1 % 4 == 3)
- dsty--;
- }
- *y = dsty;
- *x *= 2;
- *width *= 2;
- *height = 0;
+ for (int y1 = 0; y1 < heighto;) {
+ assert(dsty < Common::kHercH);
- for (y1 = 0; y1 < heighto;) {
srcptr = src + y1 * srcPitch;
dstptr = hercbuf + dsty * Common::kHercW + xo * 2;
- assert(dstptr < hercbuf + Common::kHercW * Common::kHercH + widtho * 2);
-
- idx1 = (dsty % 7) % 2;
+ const int idx1 = (dsty % 7) % 2;
for (int x1 = 0; x1 < widtho; x1++) {
- idx2 = (xo + x1) % 2;
- *dstptr++ = cgaDither[idx1][idx2][*srcptr & 0xF] >> 1;
- *dstptr++ = cgaDither[idx1][idx2][*srcptr & 0xF] & 0x1;
+ const int idx2 = (xo + x1) % 2;
+ const byte tmp = cgaDither[idx1][idx2][*srcptr & 0xF];
+ *dstptr++ = tmp >> 1;
+ *dstptr++ = tmp & 0x1;
srcptr++;
}
if (idx1 || dsty % 7 == 6)
y1++;
dsty++;
- (*height)++;
+ }
+
+ *x *= 2;
+ *y = yo*2 - yo/4;
+ *width *= 2;
+ *height = dsty - *y;
+}
+
+void ScummEngine::scale2x(byte *dst, int dstPitch, const byte *src, int srcPitch, int w, int h) {
+ byte *dstL1 = dst;
+ byte *dstL2 = dst + dstPitch;
+
+ int dstAdd = dstPitch * 2 - w * 2;
+ int srcAdd = srcPitch - w;
+
+ while (h--) {
+ for (int x = 0; x < w; ++x, dstL1 += 2, dstL2 += 2) {
+ uint16 col = *src++;
+ col |= col << 8;
+ *(uint16*)(dstL1) = col;
+ *(uint16*)(dstL2) = col;
+ }
+ dstL1 += dstAdd; dstL2 += dstAdd;
+ src += srcAdd;
}
}
@@ -1004,11 +1066,14 @@ static void fill(byte *dst, int dstPitch, byte color, int w, int h) {
}
}
+#ifdef ARM_USE_GFX_ASM
+
+#define copy8Col(A,B,C,D) copy8ColARM(A,B,C,D)
+
+#else
+
static void copy8Col(byte *dst, int dstPitch, const byte *src, int height) {
-#ifndef __DS__
-
-
do {
#if defined(SCUMM_NEED_ALIGNMENT)
memcpy(dst, src, 8);
@@ -1019,12 +1084,10 @@ static void copy8Col(byte *dst, int dstPitch, const byte *src, int height) {
dst += dstPitch;
src += dstPitch;
} while (--height);
-#else
- DS::asmCopy8Col(dst, dstPitch, src, height);
-#endif
-
}
+#endif /* ARM_USE_GFX_ASM */
+
static void clear8Col(byte *dst, int dstPitch, int height) {
do {
#if defined(SCUMM_NEED_ALIGNMENT)
@@ -1098,8 +1161,8 @@ void ScummEngine::drawBox(int x, int y, int x2, int y2, int color) {
error("can only copy bg to main window");
blit(backbuff, vs->pitch, bgbuff, vs->pitch, width, height);
if (_charset->_hasMask) {
- byte *mask = (byte *)_textSurface.getBasePtr(x, y - _screenTop);
- fill(mask, _textSurface.pitch, CHARSET_MASK_TRANSPARENCY, width, height);
+ byte *mask = (byte *)_textSurface.getBasePtr(x * _textSurfaceMultiplier, (y - _screenTop) * _textSurfaceMultiplier);
+ fill(mask, _textSurface.pitch, CHARSET_MASK_TRANSPARENCY, width * _textSurfaceMultiplier, height * _textSurfaceMultiplier);
}
} else if (_game.heversion >= 71) {
// Flags are used for different methods in HE games
@@ -3343,7 +3406,17 @@ void ScummEngine::dissolveEffect(int width, int height) {
for (i = 0; i < w * h; i++) {
x = offsets[i] % vs->pitch;
y = offsets[i] / vs->pitch;
- _system->copyRectToScreen(vs->getPixels(x, y), vs->pitch, x, y + vs->topline, width, height);
+
+ if (_useCJKMode && _textSurfaceMultiplier == 2) {
+ int m = _textSurfaceMultiplier;
+ byte *dst = _fmtownsBuf + x * m + y * m * _screenWidth * m;
+ scale2x(dst, _screenWidth * m, vs->getPixels(x, y), vs->pitch, width, height);
+
+ _system->copyRectToScreen(dst, _screenWidth * m, x * m, (y + vs->topline) * m, width * m, height * m);
+ } else {
+ _system->copyRectToScreen(vs->getPixels(x, y), vs->pitch, x, y + vs->topline, width, height);
+ }
+
if (++blits >= blits_before_refresh) {
blits = 0;
@@ -3372,16 +3445,30 @@ void ScummEngine::scrollEffect(int dir) {
step = (step * delay) / kScrolltime;
+ byte *src;
+ int m = _textSurfaceMultiplier;
+ int vsPitch = vs->pitch;
+
switch (dir) {
case 0:
//up
y = 1 + step;
while (y < vs->h) {
moveScreen(0, -step, vs->h);
- _system->copyRectToScreen(vs->getPixels(0, y - step),
- vs->pitch,
- 0, vs->h - step,
- vs->w, step);
+
+ src = vs->getPixels(0, y - step);
+ if (_useCJKMode && m == 2) {
+ int x1 = 0, y1 = vs->h - step;
+ byte *dst = _fmtownsBuf + x1 * m + y1 * m * _screenWidth * m;
+ scale2x(dst, _screenWidth * m, src, vs->pitch, vs->w, step);
+ src = dst;
+ vsPitch = _screenWidth * 2;
+ }
+
+ _system->copyRectToScreen(src,
+ vsPitch,
+ 0 * m, (vs->h - step) * m,
+ vs->w * m, step * m);
_system->updateScreen();
waitForTimer(delay);
@@ -3393,10 +3480,18 @@ void ScummEngine::scrollEffect(int dir) {
y = 1 + step;
while (y < vs->h) {
moveScreen(0, step, vs->h);
- _system->copyRectToScreen(vs->getPixels(0, vs->h - y),
- vs->pitch,
+ src = vs->getPixels(0, vs->h - y);
+ if (_useCJKMode && m == 2) {
+ int x1 = 0, y1 = 0;
+ byte *dst = _fmtownsBuf + x1 * m + y1 * m * _screenWidth * m;
+ scale2x(dst, _screenWidth * m, src, vs->pitch, vs->w, step);
+ src = dst;
+ vsPitch = _screenWidth * 2;
+ }
+ _system->copyRectToScreen(src,
+ vsPitch,
0, 0,
- vs->w, step);
+ vs->w * m, step * m);
_system->updateScreen();
waitForTimer(delay);
@@ -3408,10 +3503,18 @@ void ScummEngine::scrollEffect(int dir) {
x = 1 + step;
while (x < vs->w) {
moveScreen(-step, 0, vs->h);
- _system->copyRectToScreen(vs->getPixels(x - step, 0),
- vs->pitch,
- vs->w - step, 0,
- step, vs->h);
+ src = vs->getPixels(x - step, 0);
+ if (_useCJKMode && m == 2) {
+ int x1 = vs->w - step, y1 = 0;
+ byte *dst = _fmtownsBuf + x1 * m + y1 * m * _screenWidth * m;
+ scale2x(dst, _screenWidth * m, src, vs->pitch, step, vs->h);
+ src = dst;
+ vsPitch = _screenWidth * 2;
+ }
+ _system->copyRectToScreen(src,
+ vsPitch,
+ (vs->w - step) * m, 0,
+ step * m, vs->h * m);
_system->updateScreen();
waitForTimer(delay);
@@ -3423,8 +3526,16 @@ void ScummEngine::scrollEffect(int dir) {
x = 1 + step;
while (x < vs->w) {
moveScreen(step, 0, vs->h);
- _system->copyRectToScreen(vs->getPixels(vs->w - x, 0),
- vs->pitch,
+ src = vs->getPixels(vs->w - x, 0);
+ if (_useCJKMode && m == 2) {
+ int x1 = 0, y1 = 0;
+ byte *dst = _fmtownsBuf + x1 * m + y1 * m * _screenWidth * m;
+ scale2x(dst, _screenWidth * m, src, vs->pitch, step, vs->h);
+ src = dst;
+ vsPitch = _screenWidth * 2;
+ }
+ _system->copyRectToScreen(src,
+ vsPitch,
0, 0,
step, vs->h);
_system->updateScreen();
diff --git a/engines/scumm/gfxARM.s b/engines/scumm/gfxARM.s
new file mode 100755
index 0000000000..fa2457fb29
--- /dev/null
+++ b/engines/scumm/gfxARM.s
@@ -0,0 +1,120 @@
+@ ScummVM Scumm Interpreter
+@ Copyright (C) 2007 The ScummVM project
+@
+@ This program is free software@ you can redistribute it and/or
+@ modify it under the terms of the GNU General Public License
+@ as published by the Free Software Foundation@ either version 2
+@ of the License, or (at your option) any later version.
+@
+@ This program is distributed in the hope that it will be useful,
+@ but WITHOUT ANY WARRANTY; without even the implied warranty of
+@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+@ GNU General Public License for more details.
+@
+@ You should have received a copy of the GNU General Public License
+@ along with this program@ if not, write to the Free Software
+@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+@
+@ $URL: $
+@ $Id: $
+@
+@ @author Robin Watts (robin@wss.co.uk)
+
+ .text
+
+ .global asmDrawStripToScreen
+
+ @ ARM implementation of asmDrawStripToScreen.
+ @
+ @ C prototype would be:
+ @
+ @ extern "C" void asmDrawStripToScreen(int height,
+ @ int width,
+ @ byte const *text,
+ @ byte const *src,
+ @ byte *dst,
+ @ int vsPitch,
+ @ int vsScreenWidth,
+ @ int textSurfacePitch);
+ @
+ @ In addition, we assume that text, src and dst are all word (4 byte)
+ @ aligned. This is the same assumption that the old 'inline' version
+ @ made.
+asmDrawStripToScreen:
+ @ r0 = height
+ @ r1 = width
+ @ r2 = text
+ @ r3 = src
+ MOV r12,r13
+ STMFD r13!,{r4-r7,r9-r11,R14}
+ LDMIA r12,{r4,r5,r6,r7}
+ @ r4 = dst
+ @ r5 = vsPitch
+ @ r6 = vmScreenWidth
+ @ r7 = textSurfacePitch
+
+ CMP r0,#0 @ If height<=0
+ MOVLE r0,#1 @ height=1
+ CMP r1,#4 @ If width<4
+ BLT end @ return
+
+ @ Width &= ~4 ? What's that about then? Width &= ~3 I could have
+ @ understood...
+ BIC r1,r1,#4
+
+ SUB r5,r5,r1 @ vsPitch -= width
+ SUB r6,r6,r1 @ vmScreenWidth -= width
+ SUB r7,r7,r1 @ textSurfacePitch -= width
+ MOV r10,#253
+ ORR r10,r10,r10,LSL #8
+ ORR r10,r10,r10,LSL #16 @ r10 = mask
+yLoop:
+ MOV r14,r1 @ r14 = width
+xLoop:
+ LDR r12,[r2],#4 @ r12 = [text]
+ LDR r11,[r3],#4 @ r11 = [src]
+ CMP r12,r10
+ BNE singleByteCompare
+ SUBS r14,r14,#4
+ STR r11,[r4], #4 @ r4 = [dst]
+ BGT xLoop
+
+ ADD r2,r2,r7 @ text += textSurfacePitch
+ ADD r3,r3,r5 @ src += vsPitch
+ ADD r4,r4,r6 @ dst += vmScreenWidth
+ SUBS r0,r0,#1
+ BGT yLoop
+ LDMFD r13!,{r4-r7,r9-r11,PC}
+
+singleByteCompare:
+ MOV r9,r12,LSR #24 @ r9 = 1st byte of [text]
+ CMP r9,r10,LSR #24 @ if (r9 == mask)
+ MOVEQ r9,r11,LSR #24 @ r9 = 1st byte of [src]
+ ORR r12,r9,r12,LSL #8 @ r12 = combine r9 and r12
+
+ MOV r9,r12,LSR #24 @ r9 = 1st byte of [text]
+ CMP r9,r10,LSR #24 @ if (r9 == mask)
+ MOVEQ r9,r11,LSR #24 @ r9 = 1st byte of [src]
+ ORR r12,r9,r12,LSL #8 @ r12 = combine r9 and r12
+
+ MOV r9,r12,LSR #24 @ r9 = 1st byte of [text]
+ CMP r9,r10,LSR #24 @ if (r9 == mask)
+ MOVEQ r9,r11,LSR #24 @ r9 = 1st byte of [src]
+ ORR r12,r9,r12,LSL #8 @ r12 = combine r9 and r12
+
+ MOV r9,r12,LSR #24 @ r9 = 1st byte of [text]
+ CMP r9,r10,LSR #24 @ if (r9 == mask)
+ MOVEQ r9,r11,LSR #24 @ r9 = 1st byte of [src]
+ ORR r12,r9,r12,LSL #8 @ r12 = combine r9 and r12
+
+ STR r12,[r4],#4
+ SUBS r14,r14,#4
+ BGT xLoop
+
+ ADD r2,r2,r7 @ text += textSurfacePitch
+ ADD r3,r3,r5 @ src += vsPitch
+ ADD r4,r4,r6 @ dst += vmScreenWidth
+ SUBS r0,r0,#1
+ BGT yLoop
+end:
+ LDMFD r13!,{r4-r7,r9-r11,PC}
diff --git a/engines/scumm/imuse_digi/dimuse.cpp b/engines/scumm/imuse_digi/dimuse.cpp
index 0221657966..6d2e7dd217 100644
--- a/engines/scumm/imuse_digi/dimuse.cpp
+++ b/engines/scumm/imuse_digi/dimuse.cpp
@@ -166,10 +166,10 @@ void IMuseDigital::saveOrLoad(Serializer *ser) {
continue;
}
- track->soundHandle = _sound->openSound(track->soundId,
+ track->soundDesc = _sound->openSound(track->soundId,
track->soundName, track->soundType,
track->volGroupId, -1);
- if (!track->soundHandle) {
+ if (!track->soundDesc) {
warning("IMuseDigital::saveOrLoad: Can't open sound so will not be resumed, propably on diffrent CD");
track->streamSou = NULL;
track->stream = NULL;
@@ -180,14 +180,14 @@ void IMuseDigital::saveOrLoad(Serializer *ser) {
if (track->sndDataExtComp) {
track->regionOffset = 0;
}
- track->sndDataExtComp = _sound->isSndDataExtComp(track->soundHandle);
+ track->sndDataExtComp = _sound->isSndDataExtComp(track->soundDesc);
if (track->sndDataExtComp) {
track->regionOffset = 0;
}
- track->dataOffset = _sound->getRegionOffset(track->soundHandle, track->curRegion);
- int bits = _sound->getBits(track->soundHandle);
- int channels = _sound->getChannels(track->soundHandle);
- int freq = _sound->getFreq(track->soundHandle);
+ track->dataOffset = _sound->getRegionOffset(track->soundDesc, track->curRegion);
+ int bits = _sound->getBits(track->soundDesc);
+ int channels = _sound->getChannels(track->soundDesc);
+ int freq = _sound->getFreq(track->soundDesc);
track->feedSize = freq * channels;
track->mixerFlags = 0;
if (channels == 2)
@@ -221,6 +221,7 @@ void IMuseDigital::saveOrLoad(Serializer *ser) {
type = Audio::Mixer::kMusicSoundType;
_mixer->playInputStream(type, &track->mixChanHandle, track->stream, -1, vol, pan, false);
+ _mixer->pauseHandle(track->mixChanHandle, true);
}
}
}
@@ -284,8 +285,8 @@ void IMuseDigital::callback() {
continue;
}
- int bits = _sound->getBits(track->soundHandle);
- int channels = _sound->getChannels(track->soundHandle);
+ int bits = _sound->getBits(track->soundDesc);
+ int channels = _sound->getChannels(track->soundDesc);
int32 feedSize = track->feedSize / _callbackFps;
@@ -316,12 +317,12 @@ void IMuseDigital::callback() {
track->dataMod12Bit = feedSize - tmpLength12Bits;
int32 tmpOffset = (track->regionOffset * 3) / 4;
- int tmpFeedSize = _sound->getDataFromRegion(track->soundHandle, track->curRegion, &tmpPtr, tmpOffset, tmpFeedSize12Bits);
+ int tmpFeedSize = _sound->getDataFromRegion(track->soundDesc, track->curRegion, &tmpPtr, tmpOffset, tmpFeedSize12Bits);
curFeedSize = BundleCodecs::decode12BitsSample(tmpPtr, &tmpSndBufferPtr, tmpFeedSize);
free(tmpPtr);
} else if (bits == 16) {
- curFeedSize = _sound->getDataFromRegion(track->soundHandle, track->curRegion, &tmpSndBufferPtr, track->regionOffset, feedSize);
+ curFeedSize = _sound->getDataFromRegion(track->soundDesc, track->curRegion, &tmpSndBufferPtr, track->regionOffset, feedSize);
if (channels == 1) {
curFeedSize &= ~1;
}
@@ -329,7 +330,7 @@ void IMuseDigital::callback() {
curFeedSize &= ~3;
}
} else if (bits == 8) {
- curFeedSize = _sound->getDataFromRegion(track->soundHandle, track->curRegion, &tmpSndBufferPtr, track->regionOffset, feedSize);
+ curFeedSize = _sound->getDataFromRegion(track->soundDesc, track->curRegion, &tmpSndBufferPtr, track->regionOffset, feedSize);
if (channels == 2) {
curFeedSize &= ~1;
}
@@ -346,7 +347,7 @@ void IMuseDigital::callback() {
} else
delete[] tmpSndBufferPtr;
- if (_sound->isEndOfRegion(track->soundHandle, track->curRegion)) {
+ if (_sound->isEndOfRegion(track->soundDesc, track->curRegion)) {
switchToNextRegion(track);
if (track->toBeRemoved)
break;
@@ -379,7 +380,7 @@ void IMuseDigital::switchToNextRegion(Track *track) {
return;
}
- int num_regions = _sound->getNumRegions(track->soundHandle);
+ int num_regions = _sound->getNumRegions(track->soundDesc);
if (++track->curRegion == num_regions) {
track->toBeRemoved = true;
@@ -387,22 +388,22 @@ void IMuseDigital::switchToNextRegion(Track *track) {
return;
}
- ImuseDigiSndMgr::soundStruct *soundHandle = track->soundHandle;
- int jumpId = _sound->getJumpIdByRegionAndHookId(soundHandle, track->curRegion, track->curHookId);
+ ImuseDigiSndMgr::SoundDesc *soundDesc = track->soundDesc;
+ int jumpId = _sound->getJumpIdByRegionAndHookId(soundDesc, track->curRegion, track->curHookId);
if (jumpId == -1)
- jumpId = _sound->getJumpIdByRegionAndHookId(soundHandle, track->curRegion, 0);
+ jumpId = _sound->getJumpIdByRegionAndHookId(soundDesc, track->curRegion, 0);
if (jumpId != -1) {
- int region = _sound->getRegionIdByJumpId(soundHandle, jumpId);
+ int region = _sound->getRegionIdByJumpId(soundDesc, jumpId);
assert(region != -1);
- int sampleHookId = _sound->getJumpHookId(soundHandle, jumpId);
+ int sampleHookId = _sound->getJumpHookId(soundDesc, jumpId);
assert(sampleHookId != -1);
- int fadeDelay = (60 * _sound->getJumpFade(soundHandle, jumpId)) / 1000;
+ int fadeDelay = (60 * _sound->getJumpFade(soundDesc, jumpId)) / 1000;
if (sampleHookId != 0) {
if (track->curHookId == sampleHookId) {
if (fadeDelay != 0) {
Track *fadeTrack = cloneToFadeOutTrack(track, fadeDelay);
if (fadeTrack) {
- fadeTrack->dataOffset = _sound->getRegionOffset(fadeTrack->soundHandle, fadeTrack->curRegion);
+ fadeTrack->dataOffset = _sound->getRegionOffset(fadeTrack->soundDesc, fadeTrack->curRegion);
fadeTrack->regionOffset = 0;
debug(5, "switchToNextRegion-sound(%d) select region %d, curHookId: %d", fadeTrack->soundId, fadeTrack->curRegion, fadeTrack->curHookId);
fadeTrack->curHookId = 0;
@@ -416,7 +417,7 @@ void IMuseDigital::switchToNextRegion(Track *track) {
if (fadeDelay != 0) {
Track *fadeTrack = cloneToFadeOutTrack(track, fadeDelay);
if (fadeTrack) {
- fadeTrack->dataOffset = _sound->getRegionOffset(fadeTrack->soundHandle, fadeTrack->curRegion);
+ fadeTrack->dataOffset = _sound->getRegionOffset(fadeTrack->soundDesc, fadeTrack->curRegion);
fadeTrack->regionOffset = 0;
debug(5, "switchToNextRegion-sound(%d) select region %d, curHookId: %d", fadeTrack->soundId, fadeTrack->curRegion, fadeTrack->curHookId);
}
@@ -427,7 +428,7 @@ void IMuseDigital::switchToNextRegion(Track *track) {
}
debug(5, "switchToNextRegion-sound(%d) select region %d, curHookId: %d", track->soundId, track->curRegion, track->curHookId);
- track->dataOffset = _sound->getRegionOffset(soundHandle, track->curRegion);
+ track->dataOffset = _sound->getRegionOffset(soundDesc, track->curRegion);
track->regionOffset = 0;
}
diff --git a/engines/scumm/imuse_digi/dimuse.h b/engines/scumm/imuse_digi/dimuse.h
index 1b088298df..dca9baac60 100644
--- a/engines/scumm/imuse_digi/dimuse.h
+++ b/engines/scumm/imuse_digi/dimuse.h
@@ -98,7 +98,7 @@ private:
int32 dataMod12Bit; // value used between all callback to align 12 bit source of data
int32 mixerFlags; // flags for sound mixer's channel (kFlagStereo, kFlag16Bits, kFlagReverseStereo, kFlagUnsigned, kFlagLittleEndian)
- ImuseDigiSndMgr::soundStruct *soundHandle; // sound handle used by iMuse sound manager
+ ImuseDigiSndMgr::SoundDesc *soundDesc; // sound handle used by iMuse sound manager
Audio::SoundHandle mixChanHandle; // sound mixer's channel handle
Audio::AppendableAudioStream *stream; // sound mixer's audio stream handle for *.la1 and *.bun
Audio::AudioStream *streamSou; // sound mixer's audio stream handle for *.sou
diff --git a/engines/scumm/imuse_digi/dimuse_script.cpp b/engines/scumm/imuse_digi/dimuse_script.cpp
index 186d04483e..ddc0cd5107 100644
--- a/engines/scumm/imuse_digi/dimuse_script.cpp
+++ b/engines/scumm/imuse_digi/dimuse_script.cpp
@@ -179,8 +179,8 @@ void IMuseDigital::flushTracks() {
_mixer->stopHandle(track->mixChanHandle);
delete track->stream;
track->stream = NULL;
- _sound->closeSound(track->soundHandle);
- track->soundHandle = NULL;
+ _sound->closeSound(track->soundDesc);
+ track->soundDesc = NULL;
track->used = false;
}
} else if (track->streamSou) {
@@ -245,7 +245,7 @@ void IMuseDigital::getLipSync(int soundId, int syncId, int32 msPos, int32 &width
for (int l = 0; l < MAX_DIGITAL_TRACKS; l++) {
Track *track = _track[l];
if ((track->soundId == soundId) && track->used && !track->toBeRemoved) {
- _sound->getSyncSizeAndPtrById(track->soundHandle, syncId, sync_size, &sync_ptr);
+ _sound->getSyncSizeAndPtrById(track->soundDesc, syncId, sync_size, &sync_ptr);
if ((sync_size != 0) && (sync_ptr != NULL)) {
sync_size /= 4;
while (sync_size--) {
@@ -396,8 +396,8 @@ void IMuseDigital::stopAllSounds() {
_mixer->stopHandle(track->mixChanHandle);
delete track->stream;
track->stream = NULL;
- _sound->closeSound(track->soundHandle);
- track->soundHandle = NULL;
+ _sound->closeSound(track->soundDesc);
+ track->soundDesc = NULL;
} else if (track->streamSou) {
_mixer->stopHandle(track->mixChanHandle);
delete track->streamSou;
diff --git a/engines/scumm/imuse_digi/dimuse_sndmgr.cpp b/engines/scumm/imuse_digi/dimuse_sndmgr.cpp
index ce963eaeea..be80cb73e8 100644
--- a/engines/scumm/imuse_digi/dimuse_sndmgr.cpp
+++ b/engines/scumm/imuse_digi/dimuse_sndmgr.cpp
@@ -26,6 +26,7 @@
#include "common/scummsys.h"
#include "common/util.h"
+#include "sound/flac.h"
#include "sound/voc.h"
#include "sound/vorbis.h"
#include "sound/mp3.h"
@@ -40,7 +41,7 @@ namespace Scumm {
ImuseDigiSndMgr::ImuseDigiSndMgr(ScummEngine *scumm) {
for (int l = 0; l < MAX_IMUSE_SOUNDS; l++) {
- memset(&_sounds[l], 0, sizeof(soundStruct));
+ memset(&_sounds[l], 0, sizeof(SoundDesc));
}
_vm = scumm;
_disk = 0;
@@ -88,7 +89,7 @@ void ImuseDigiSndMgr::countElements(byte *ptr, int &numRegions, int &numJumps, i
} while (tag != MKID_BE('DATA'));
}
-void ImuseDigiSndMgr::prepareSoundFromRMAP(Common::File *file, soundStruct *sound, int32 offset, int32 size) {
+void ImuseDigiSndMgr::prepareSoundFromRMAP(Common::File *file, SoundDesc *sound, int32 offset, int32 size) {
int l;
file->seek(offset, SEEK_SET);
@@ -104,11 +105,11 @@ void ImuseDigiSndMgr::prepareSoundFromRMAP(Common::File *file, soundStruct *soun
sound->numRegions = file->readUint32BE();
sound->numJumps = file->readUint32BE();
sound->numSyncs = file->readUint32BE();
- sound->region = (_region *)malloc(sizeof(_region) * sound->numRegions);
+ sound->region = new Region[sound->numRegions];
assert(sound->region);
- sound->jump = (_jump *)malloc(sizeof(_jump) * sound->numJumps);
+ sound->jump = new Jump[sound->numJumps];
assert(sound->jump);
- sound->sync = (_sync *)malloc(sizeof(_sync) * sound->numSyncs);
+ sound->sync = new Sync[sound->numSyncs];
assert(sound->sync);
for (l = 0; l < sound->numRegions; l++) {
sound->region[l].offset = file->readUint32BE();
@@ -127,7 +128,7 @@ void ImuseDigiSndMgr::prepareSoundFromRMAP(Common::File *file, soundStruct *soun
}
}
-void ImuseDigiSndMgr::prepareSound(byte *ptr, soundStruct *sound) {
+void ImuseDigiSndMgr::prepareSound(byte *ptr, SoundDesc *sound) {
if (READ_BE_UINT32(ptr) == MKID_BE('Crea')) {
bool quit = false;
int len;
@@ -135,10 +136,16 @@ void ImuseDigiSndMgr::prepareSound(byte *ptr, soundStruct *sound) {
int32 offset = READ_LE_UINT16(ptr + 20);
int16 code = READ_LE_UINT16(ptr + 24);
- sound->region = (_region *)malloc(sizeof(_region) * 70);
+ sound->numRegions = 0;
+ sound->region = new Region[70];
assert(sound->region);
- sound->jump = (_jump *)malloc(sizeof(_jump));
+
+ sound->numJumps = 0;
+ sound->jump = new Jump[1];
assert(sound->jump);
+
+ sound->numSyncs = 0;
+
sound->resPtr = ptr;
sound->bits = 8;
sound->channels = 1;
@@ -205,11 +212,11 @@ void ImuseDigiSndMgr::prepareSound(byte *ptr, soundStruct *sound) {
sound->numJumps = 0;
sound->numSyncs = 0;
countElements(ptr, sound->numRegions, sound->numJumps, sound->numSyncs);
- sound->region = (_region *)malloc(sizeof(_region) * sound->numRegions);
+ sound->region = new Region[sound->numRegions];
assert(sound->region);
- sound->jump = (_jump *)malloc(sizeof(_jump) * sound->numJumps);
+ sound->jump = new Jump[sound->numJumps];
assert(sound->jump);
- sound->sync = (_sync *)malloc(sizeof(_sync) * sound->numSyncs);
+ sound->sync = new Sync[sound->numSyncs];
assert(sound->sync);
do {
@@ -260,7 +267,7 @@ void ImuseDigiSndMgr::prepareSound(byte *ptr, soundStruct *sound) {
}
}
-ImuseDigiSndMgr::soundStruct *ImuseDigiSndMgr::allocSlot() {
+ImuseDigiSndMgr::SoundDesc *ImuseDigiSndMgr::allocSlot() {
for (int l = 0; l < MAX_IMUSE_SOUNDS; l++) {
if (!_sounds[l].inUse) {
_sounds[l].inUse = true;
@@ -271,7 +278,7 @@ ImuseDigiSndMgr::soundStruct *ImuseDigiSndMgr::allocSlot() {
return NULL;
}
-bool ImuseDigiSndMgr::openMusicBundle(soundStruct *sound, int disk) {
+bool ImuseDigiSndMgr::openMusicBundle(SoundDesc *sound, int disk) {
bool result = false;
sound->bundle = new BundleMgr(_cacheBundleDir);
@@ -306,7 +313,7 @@ bool ImuseDigiSndMgr::openMusicBundle(soundStruct *sound, int disk) {
return result;
}
-bool ImuseDigiSndMgr::openVoiceBundle(soundStruct *sound, int disk) {
+bool ImuseDigiSndMgr::openVoiceBundle(SoundDesc *sound, int disk) {
bool result = false;
sound->bundle = new BundleMgr(_cacheBundleDir);
@@ -341,11 +348,11 @@ bool ImuseDigiSndMgr::openVoiceBundle(soundStruct *sound, int disk) {
return result;
}
-ImuseDigiSndMgr::soundStruct *ImuseDigiSndMgr::openSound(int32 soundId, const char *soundName, int soundType, int volGroupId, int disk) {
+ImuseDigiSndMgr::SoundDesc *ImuseDigiSndMgr::openSound(int32 soundId, const char *soundName, int soundType, int volGroupId, int disk) {
assert(soundId >= 0);
assert(soundType);
- soundStruct *sound = allocSlot();
+ SoundDesc *sound = allocSlot();
if (!sound) {
error("ImuseDigiSndMgr::openSound() can't alloc free sound slot");
}
@@ -423,99 +430,97 @@ ImuseDigiSndMgr::soundStruct *ImuseDigiSndMgr::openSound(int32 soundId, const ch
return sound;
}
-void ImuseDigiSndMgr::closeSound(soundStruct *soundHandle) {
- assert(checkForProperHandle(soundHandle));
+void ImuseDigiSndMgr::closeSound(SoundDesc *soundDesc) {
+ assert(checkForProperHandle(soundDesc));
- if (soundHandle->resPtr) {
+ if (soundDesc->resPtr) {
bool found = false;
for (int l = 0; l < MAX_IMUSE_SOUNDS; l++) {
- if ((_sounds[l].soundId == soundHandle->soundId) && (&_sounds[l] != soundHandle))
+ if ((_sounds[l].soundId == soundDesc->soundId) && (&_sounds[l] != soundDesc))
found = true;
}
if (!found)
- _vm->_res->unlock(rtSound, soundHandle->soundId);
+ _vm->_res->unlock(rtSound, soundDesc->soundId);
}
- if (soundHandle->compressedStream)
- delete soundHandle->compressedStream;
-
- delete soundHandle->bundle;
+ delete soundDesc->compressedStream;
+ delete soundDesc->bundle;
- for (int r = 0; r < soundHandle->numSyncs; r++)
- free(soundHandle->sync[r].ptr);
- free(soundHandle->region);
- free(soundHandle->jump);
- free(soundHandle->sync);
- memset(soundHandle, 0, sizeof(soundStruct));
+ for (int r = 0; r < soundDesc->numSyncs; r++)
+ free(soundDesc->sync[r].ptr);
+ delete[] soundDesc->region;
+ delete[] soundDesc->jump;
+ delete[] soundDesc->sync;
+ memset(soundDesc, 0, sizeof(SoundDesc));
}
-ImuseDigiSndMgr::soundStruct *ImuseDigiSndMgr::cloneSound(soundStruct *soundHandle) {
- assert(checkForProperHandle(soundHandle));
+ImuseDigiSndMgr::SoundDesc *ImuseDigiSndMgr::cloneSound(SoundDesc *soundDesc) {
+ assert(checkForProperHandle(soundDesc));
- return openSound(soundHandle->soundId, soundHandle->name, soundHandle->type, soundHandle->volGroupId, soundHandle->disk);
+ return openSound(soundDesc->soundId, soundDesc->name, soundDesc->type, soundDesc->volGroupId, soundDesc->disk);
}
-bool ImuseDigiSndMgr::checkForProperHandle(soundStruct *soundHandle) {
- if (!soundHandle)
+bool ImuseDigiSndMgr::checkForProperHandle(SoundDesc *soundDesc) {
+ if (!soundDesc)
return false;
for (int l = 0; l < MAX_IMUSE_SOUNDS; l++) {
- if (soundHandle == &_sounds[l])
+ if (soundDesc == &_sounds[l])
return true;
}
return false;
}
-bool ImuseDigiSndMgr::isSndDataExtComp(soundStruct *soundHandle) {
- assert(checkForProperHandle(soundHandle));
- return soundHandle->compressed;
+bool ImuseDigiSndMgr::isSndDataExtComp(SoundDesc *soundDesc) {
+ assert(checkForProperHandle(soundDesc));
+ return soundDesc->compressed;
}
-int ImuseDigiSndMgr::getFreq(soundStruct *soundHandle) {
- assert(checkForProperHandle(soundHandle));
- return soundHandle->freq;
+int ImuseDigiSndMgr::getFreq(SoundDesc *soundDesc) {
+ assert(checkForProperHandle(soundDesc));
+ return soundDesc->freq;
}
-int ImuseDigiSndMgr::getBits(soundStruct *soundHandle) {
- assert(checkForProperHandle(soundHandle));
- return soundHandle->bits;
+int ImuseDigiSndMgr::getBits(SoundDesc *soundDesc) {
+ assert(checkForProperHandle(soundDesc));
+ return soundDesc->bits;
}
-int ImuseDigiSndMgr::getChannels(soundStruct *soundHandle) {
- assert(checkForProperHandle(soundHandle));
- return soundHandle->channels;
+int ImuseDigiSndMgr::getChannels(SoundDesc *soundDesc) {
+ assert(checkForProperHandle(soundDesc));
+ return soundDesc->channels;
}
-bool ImuseDigiSndMgr::isEndOfRegion(soundStruct *soundHandle, int region) {
- assert(checkForProperHandle(soundHandle));
- assert(region >= 0 && region < soundHandle->numRegions);
- return soundHandle->endFlag;
+bool ImuseDigiSndMgr::isEndOfRegion(SoundDesc *soundDesc, int region) {
+ assert(checkForProperHandle(soundDesc));
+ assert(region >= 0 && region < soundDesc->numRegions);
+ return soundDesc->endFlag;
}
-int ImuseDigiSndMgr::getNumRegions(soundStruct *soundHandle) {
- assert(checkForProperHandle(soundHandle));
- return soundHandle->numRegions;
+int ImuseDigiSndMgr::getNumRegions(SoundDesc *soundDesc) {
+ assert(checkForProperHandle(soundDesc));
+ return soundDesc->numRegions;
}
-int ImuseDigiSndMgr::getNumJumps(soundStruct *soundHandle) {
- assert(checkForProperHandle(soundHandle));
- return soundHandle->numJumps;
+int ImuseDigiSndMgr::getNumJumps(SoundDesc *soundDesc) {
+ assert(checkForProperHandle(soundDesc));
+ return soundDesc->numJumps;
}
-int ImuseDigiSndMgr::getRegionOffset(soundStruct *soundHandle, int region) {
+int ImuseDigiSndMgr::getRegionOffset(SoundDesc *soundDesc, int region) {
debug(5, "getRegionOffset() region:%d", region);
- assert(checkForProperHandle(soundHandle));
- assert(region >= 0 && region < soundHandle->numRegions);
- return soundHandle->region[region].offset;
+ assert(checkForProperHandle(soundDesc));
+ assert(region >= 0 && region < soundDesc->numRegions);
+ return soundDesc->region[region].offset;
}
-int ImuseDigiSndMgr::getJumpIdByRegionAndHookId(soundStruct *soundHandle, int region, int hookId) {
+int ImuseDigiSndMgr::getJumpIdByRegionAndHookId(SoundDesc *soundDesc, int region, int hookId) {
debug(5, "getJumpIdByRegionAndHookId() region:%d, hookId:%d", region, hookId);
- assert(checkForProperHandle(soundHandle));
- assert(region >= 0 && region < soundHandle->numRegions);
- int32 offset = soundHandle->region[region].offset;
- for (int l = 0; l < soundHandle->numJumps; l++) {
- if (offset == soundHandle->jump[l].offset) {
- if (soundHandle->jump[l].hookId == hookId)
+ assert(checkForProperHandle(soundDesc));
+ assert(region >= 0 && region < soundDesc->numRegions);
+ int32 offset = soundDesc->region[region].offset;
+ for (int l = 0; l < soundDesc->numJumps; l++) {
+ if (offset == soundDesc->jump[l].offset) {
+ if (soundDesc->jump[l].hookId == hookId)
return l;
}
}
@@ -523,25 +528,25 @@ int ImuseDigiSndMgr::getJumpIdByRegionAndHookId(soundStruct *soundHandle, int re
return -1;
}
-void ImuseDigiSndMgr::getSyncSizeAndPtrById(soundStruct *soundHandle, int number, int32 &sync_size, byte **sync_ptr) {
- assert(checkForProperHandle(soundHandle));
+void ImuseDigiSndMgr::getSyncSizeAndPtrById(SoundDesc *soundDesc, int number, int32 &sync_size, byte **sync_ptr) {
+ assert(checkForProperHandle(soundDesc));
assert(number >= 0);
- if (number < soundHandle->numSyncs) {
- sync_size = soundHandle->sync[number].size;
- *sync_ptr = soundHandle->sync[number].ptr;
+ if (number < soundDesc->numSyncs) {
+ sync_size = soundDesc->sync[number].size;
+ *sync_ptr = soundDesc->sync[number].ptr;
} else {
sync_size = 0;
*sync_ptr = NULL;
}
}
-int ImuseDigiSndMgr::getRegionIdByJumpId(soundStruct *soundHandle, int jumpId) {
+int ImuseDigiSndMgr::getRegionIdByJumpId(SoundDesc *soundDesc, int jumpId) {
debug(5, "getRegionIdByJumpId() jumpId:%d", jumpId);
- assert(checkForProperHandle(soundHandle));
- assert(jumpId >= 0 && jumpId < soundHandle->numJumps);
- int32 dest = soundHandle->jump[jumpId].dest;
- for (int l = 0; l < soundHandle->numRegions; l++) {
- if (dest == soundHandle->region[l].offset) {
+ assert(checkForProperHandle(soundDesc));
+ assert(jumpId >= 0 && jumpId < soundDesc->numJumps);
+ int32 dest = soundDesc->jump[jumpId].dest;
+ for (int l = 0; l < soundDesc->numRegions; l++) {
+ if (dest == soundDesc->region[l].offset) {
return l;
}
}
@@ -549,89 +554,110 @@ int ImuseDigiSndMgr::getRegionIdByJumpId(soundStruct *soundHandle, int jumpId) {
return -1;
}
-int ImuseDigiSndMgr::getJumpHookId(soundStruct *soundHandle, int number) {
+int ImuseDigiSndMgr::getJumpHookId(SoundDesc *soundDesc, int number) {
debug(5, "getJumpHookId() number:%d", number);
- assert(checkForProperHandle(soundHandle));
- assert(number >= 0 && number < soundHandle->numJumps);
- return soundHandle->jump[number].hookId;
+ assert(checkForProperHandle(soundDesc));
+ assert(number >= 0 && number < soundDesc->numJumps);
+ return soundDesc->jump[number].hookId;
}
-int ImuseDigiSndMgr::getJumpFade(soundStruct *soundHandle, int number) {
+int ImuseDigiSndMgr::getJumpFade(SoundDesc *soundDesc, int number) {
debug(5, "getJumpFade() number:%d", number);
- assert(checkForProperHandle(soundHandle));
- assert(number >= 0 && number < soundHandle->numJumps);
- return soundHandle->jump[number].fadeDelay;
+ assert(checkForProperHandle(soundDesc));
+ assert(number >= 0 && number < soundDesc->numJumps);
+ return soundDesc->jump[number].fadeDelay;
}
-int32 ImuseDigiSndMgr::getDataFromRegion(soundStruct *soundHandle, int region, byte **buf, int32 offset, int32 size) {
- debug(5, "getDataFromRegion() region:%d, offset:%d, size:%d, numRegions:%d", region, offset, size, soundHandle->numRegions);
- assert(checkForProperHandle(soundHandle));
+int32 ImuseDigiSndMgr::getDataFromRegion(SoundDesc *soundDesc, int region, byte **buf, int32 offset, int32 size) {
+ debug(5, "getDataFromRegion() region:%d, offset:%d, size:%d, numRegions:%d", region, offset, size, soundDesc->numRegions);
+ assert(checkForProperHandle(soundDesc));
assert(buf && offset >= 0 && size >= 0);
- assert(region >= 0 && region < soundHandle->numRegions);
+ assert(region >= 0 && region < soundDesc->numRegions);
- int32 region_offset = soundHandle->region[region].offset;
- int32 region_length = soundHandle->region[region].length;
- int32 offset_data = soundHandle->offsetData;
+ int32 region_offset = soundDesc->region[region].offset;
+ int32 region_length = soundDesc->region[region].length;
+ int32 offset_data = soundDesc->offsetData;
int32 start = region_offset - offset_data;
if (offset + size + offset_data > region_length) {
size = region_length - offset;
- soundHandle->endFlag = true;
+ soundDesc->endFlag = true;
} else {
- soundHandle->endFlag = false;
+ soundDesc->endFlag = false;
}
- int header_size = soundHandle->offsetData;
+ int header_size = soundDesc->offsetData;
bool header_outside = ((_vm->_game.id == GID_CMI) && !(_vm->_game.features & GF_DEMO));
- if ((soundHandle->bundle) && (!soundHandle->compressed)) {
- size = soundHandle->bundle->decompressSampleByCurIndex(start + offset, size, buf, header_size, header_outside);
- } else if (soundHandle->resPtr) {
+ if ((soundDesc->bundle) && (!soundDesc->compressed)) {
+ size = soundDesc->bundle->decompressSampleByCurIndex(start + offset, size, buf, header_size, header_outside);
+ } else if (soundDesc->resPtr) {
*buf = new byte[size];
assert(*buf);
- memcpy(*buf, soundHandle->resPtr + start + offset + header_size, size);
- } else if ((soundHandle->bundle) && (soundHandle->compressed)) {
+ memcpy(*buf, soundDesc->resPtr + start + offset + header_size, size);
+ } else if ((soundDesc->bundle) && (soundDesc->compressed)) {
*buf = new byte[size];
assert(*buf);
char fileName[24];
- sprintf(fileName, "%s_reg%03d", soundHandle->name, region);
- if (scumm_stricmp(fileName, soundHandle->lastFileName) != 0) {
+ sprintf(fileName, "%s_reg%03d", soundDesc->name, region);
+ if (scumm_stricmp(fileName, soundDesc->lastFileName) != 0) {
int32 offs = 0, len = 0;
Common::File *cmpFile;
- bool oggMode = false;
- sprintf(fileName, "%s_reg%03d.mp3", soundHandle->name, region);
- cmpFile = soundHandle->bundle->getFile(fileName, offs, len);
-#ifndef USE_MAD
- if (len)
- error("Mad library compiled support needed!");
+ uint8 soundMode = 0;
+
+ sprintf(fileName, "%s_reg%03d.fla", soundDesc->name, region);
+ cmpFile = soundDesc->bundle->getFile(fileName, offs, len);
+ if (len) {
+#ifndef USE_FLAC
+ error("FLAC library compiled support needed!");
#endif
+ soundMode = 3;
+ }
if (!len) {
- sprintf(fileName, "%s_reg%03d.ogg", soundHandle->name, region);
- cmpFile = soundHandle->bundle->getFile(fileName, offs, len);
+ sprintf(fileName, "%s_reg%03d.ogg", soundDesc->name, region);
+ cmpFile = soundDesc->bundle->getFile(fileName, offs, len);
+ if (len) {
#ifndef USE_VORBIS
- if (len)
error("Vorbis library compiled support needed!");
#endif
- assert(len);
- oggMode = true;
+ soundMode = 2;
+ }
+ }
+ if (!len) {
+ sprintf(fileName, "%s_reg%03d.mp3", soundDesc->name, region);
+ cmpFile = soundDesc->bundle->getFile(fileName, offs, len);
+ if (len) {
+#ifndef USE_MAD
+ error("Mad library compiled support needed!");
+#endif
+ soundMode = 1;
+ }
}
- if (!soundHandle->compressedStream) {
+ assert(len);
+
+ if (!soundDesc->compressedStream) {
+ Common::MemoryReadStream *tmp = cmpFile->readStream(len);
+ assert(tmp);
+#ifdef USE_FLAC
+ if (soundMode == 3)
+ soundDesc->compressedStream = Audio::makeFlacStream(tmp, true);
+#endif
#ifdef USE_VORBIS
- if (oggMode)
- soundHandle->compressedStream = Audio::makeVorbisStream(cmpFile, len);
+ if (soundMode == 2)
+ soundDesc->compressedStream = Audio::makeVorbisStream(tmp, true);
#endif
#ifdef USE_MAD
- if (!oggMode)
- soundHandle->compressedStream = Audio::makeMP3Stream(cmpFile, len);
+ if (soundMode == 1)
+ soundDesc->compressedStream = Audio::makeMP3Stream(tmp, true);
#endif
- assert(soundHandle->compressedStream);
+ assert(soundDesc->compressedStream);
}
- strcpy(soundHandle->lastFileName, fileName);
+ strcpy(soundDesc->lastFileName, fileName);
}
- size = soundHandle->compressedStream->readBuffer((int16 *)*buf, size / 2) * 2;
- if (soundHandle->compressedStream->endOfData()) {
- delete soundHandle->compressedStream;
- soundHandle->compressedStream = NULL;
- soundHandle->lastFileName[0] = 0;
+ size = soundDesc->compressedStream->readBuffer((int16 *)*buf, size / 2) * 2;
+ if (soundDesc->compressedStream->endOfData()) {
+ delete soundDesc->compressedStream;
+ soundDesc->compressedStream = NULL;
+ soundDesc->lastFileName[0] = 0;
}
}
diff --git a/engines/scumm/imuse_digi/dimuse_sndmgr.h b/engines/scumm/imuse_digi/dimuse_sndmgr.h
index 5d2f8c88ba..e4e2e795a2 100644
--- a/engines/scumm/imuse_digi/dimuse_sndmgr.h
+++ b/engines/scumm/imuse_digi/dimuse_sndmgr.h
@@ -48,35 +48,39 @@ public:
#define IMUSE_VOLGRP_MUSIC 3
private:
- struct _region {
+ struct Region {
int32 offset; // offset of region
int32 length; // lenght of region
};
- struct _jump {
+ struct Jump {
int32 offset; // jump offset position
int32 dest; // jump to dest position
byte hookId; // id of hook
int16 fadeDelay; // fade delay in ms
};
- struct _sync {
+ struct Sync {
int32 size; // size of sync
byte *ptr; // pointer to sync
};
public:
- struct soundStruct {
+ struct SoundDesc {
uint16 freq; // frequency
byte channels; // stereo or mono
byte bits; // 8, 12, 16
+
int numJumps; // number of Jumps
+ Region *region;
+
int numRegions; // number of Regions
+ Jump *jump;
+
int numSyncs; // number of Syncs
- _region *region;
- _jump *jump;
- _sync *sync;
+ Sync *sync;
+
bool endFlag;
bool inUse;
byte *allData;
@@ -95,19 +99,19 @@ public:
private:
- soundStruct _sounds[MAX_IMUSE_SOUNDS];
+ SoundDesc _sounds[MAX_IMUSE_SOUNDS];
- bool checkForProperHandle(soundStruct *soundHandle);
- soundStruct *allocSlot();
- void prepareSound(byte *ptr, soundStruct *sound);
- void prepareSoundFromRMAP(Common::File *file, soundStruct *sound, int32 offset, int32 size);
+ bool checkForProperHandle(SoundDesc *soundDesc);
+ SoundDesc *allocSlot();
+ void prepareSound(byte *ptr, SoundDesc *sound);
+ void prepareSoundFromRMAP(Common::File *file, SoundDesc *sound, int32 offset, int32 size);
ScummEngine *_vm;
byte _disk;
BundleDirCache *_cacheBundleDir;
- bool openMusicBundle(soundStruct *sound, int disk);
- bool openVoiceBundle(soundStruct *sound, int disk);
+ bool openMusicBundle(SoundDesc *sound, int disk);
+ bool openVoiceBundle(SoundDesc *sound, int disk);
void countElements(byte *ptr, int &numRegions, int &numJumps, int &numSyncs);
@@ -116,25 +120,25 @@ public:
ImuseDigiSndMgr(ScummEngine *scumm);
~ImuseDigiSndMgr();
- soundStruct *openSound(int32 soundId, const char *soundName, int soundType, int volGroupId, int disk);
- void closeSound(soundStruct *soundHandle);
- soundStruct *cloneSound(soundStruct *soundHandle);
-
- bool isSndDataExtComp(soundStruct *soundHandle);
- int getFreq(soundStruct *soundHandle);
- int getBits(soundStruct *soundHandle);
- int getChannels(soundStruct *soundHandle);
- bool isEndOfRegion(soundStruct *soundHandle, int region);
- int getNumRegions(soundStruct *soundHandle);
- int getNumJumps(soundStruct *soundHandle);
- int getRegionOffset(soundStruct *soundHandle, int region);
- int getJumpIdByRegionAndHookId(soundStruct *soundHandle, int region, int hookId);
- int getRegionIdByJumpId(soundStruct *soundHandle, int jumpId);
- int getJumpHookId(soundStruct *soundHandle, int number);
- int getJumpFade(soundStruct *soundHandle, int number);
- void getSyncSizeAndPtrById(soundStruct *soundHandle, int number, int32 &sync_size, byte **sync_ptr);
-
- int32 getDataFromRegion(soundStruct *soundHandle, int region, byte **buf, int32 offset, int32 size);
+ SoundDesc *openSound(int32 soundId, const char *soundName, int soundType, int volGroupId, int disk);
+ void closeSound(SoundDesc *soundDesc);
+ SoundDesc *cloneSound(SoundDesc *soundDesc);
+
+ bool isSndDataExtComp(SoundDesc *soundDesc);
+ int getFreq(SoundDesc *soundDesc);
+ int getBits(SoundDesc *soundDesc);
+ int getChannels(SoundDesc *soundDesc);
+ bool isEndOfRegion(SoundDesc *soundDesc, int region);
+ int getNumRegions(SoundDesc *soundDesc);
+ int getNumJumps(SoundDesc *soundDesc);
+ int getRegionOffset(SoundDesc *soundDesc, int region);
+ int getJumpIdByRegionAndHookId(SoundDesc *soundDesc, int region, int hookId);
+ int getRegionIdByJumpId(SoundDesc *soundDesc, int jumpId);
+ int getJumpHookId(SoundDesc *soundDesc, int number);
+ int getJumpFade(SoundDesc *soundDesc, int number);
+ void getSyncSizeAndPtrById(SoundDesc *soundDesc, int number, int32 &sync_size, byte **sync_ptr);
+
+ int32 getDataFromRegion(SoundDesc *soundDesc, int region, byte **buf, int32 offset, int32 size);
};
} // End of namespace Scumm
diff --git a/engines/scumm/imuse_digi/dimuse_track.cpp b/engines/scumm/imuse_digi/dimuse_track.cpp
index 75dde5e60f..987e1bc3c9 100644
--- a/engines/scumm/imuse_digi/dimuse_track.cpp
+++ b/engines/scumm/imuse_digi/dimuse_track.cpp
@@ -117,20 +117,20 @@ void IMuseDigital::startSound(int soundId, const char *soundName, int soundType,
track->feedSize = 0;
track->souStreamUsed = true;
track->soundName[0] = 0;
- track->soundHandle = NULL;
+ track->soundDesc = NULL;
} else {
track->souStreamUsed = false;
strcpy(track->soundName, soundName);
- track->soundHandle = _sound->openSound(soundId, soundName, soundType, volGroupId, -1);
+ track->soundDesc = _sound->openSound(soundId, soundName, soundType, volGroupId, -1);
- if (track->soundHandle == NULL)
+ if (track->soundDesc == NULL)
return;
- track->sndDataExtComp = _sound->isSndDataExtComp(track->soundHandle);
+ track->sndDataExtComp = _sound->isSndDataExtComp(track->soundDesc);
- bits = _sound->getBits(track->soundHandle);
- channels = _sound->getChannels(track->soundHandle);
- freq = _sound->getFreq(track->soundHandle);
+ bits = _sound->getBits(track->soundDesc);
+ channels = _sound->getChannels(track->soundDesc);
+ freq = _sound->getFreq(track->soundDesc);
if ((soundId == kTalkSoundID) && (soundType == IMUSE_BUNDLE)) {
if (_vm->_actorToPrintStrFor != 0xFF && _vm->_actorToPrintStrFor != 0) {
@@ -325,15 +325,12 @@ IMuseDigital::Track *IMuseDigital::cloneToFadeOutTrack(const Track *track, int f
// Clone the settings of the given track
memcpy(fadeTrack, track, sizeof(Track));
- // Clone the soundhandle
- // FIXME: Shouldn't we check here whether track->soundHandle is NULL, resp. whether stream2
- // is being used (as in, we are using compressed data)...
- //
- // -- aquadran -- nope :) this is called only for bundle files and sound data in *.la1
- // from switchToNextRegion and fadeOutMusic func.
- // stream2 is used only for sou VOICE type sound data (FT) --
- fadeTrack->soundHandle = _sound->cloneSound(track->soundHandle);
- assert(fadeTrack->soundHandle);
+ // Clone the sound.
+ // According to aquadran, this is only called for bundle files and sound
+ // data in *.la1 from switchToNextRegion and fadeOutMusic func. Henc we
+ // know that track->soundDesc != NULL.
+ fadeTrack->soundDesc = _sound->cloneSound(track->soundDesc);
+ assert(fadeTrack->soundDesc);
// Set the volume fading parameters to indicate a fade out
fadeTrack->volFadeDelay = fadeDelay;
@@ -357,7 +354,7 @@ IMuseDigital::Track *IMuseDigital::cloneToFadeOutTrack(const Track *track, int f
type = Audio::Mixer::kPlainSoundType;
break;
}
- fadeTrack->stream = Audio::makeAppendableAudioStream(_sound->getFreq(fadeTrack->soundHandle), makeMixerFlags(fadeTrack->mixerFlags));
+ fadeTrack->stream = Audio::makeAppendableAudioStream(_sound->getFreq(fadeTrack->soundDesc), makeMixerFlags(fadeTrack->mixerFlags));
_mixer->playInputStream(type, &fadeTrack->mixChanHandle, fadeTrack->stream, -1, fadeTrack->vol / 1000, fadeTrack->pan, false);
fadeTrack->mixerStreamRunning = true;
diff --git a/engines/scumm/input.cpp b/engines/scumm/input.cpp
index ffcb7d03f2..6647e9fe8d 100644
--- a/engines/scumm/input.cpp
+++ b/engines/scumm/input.cpp
@@ -162,8 +162,11 @@ void ScummEngine::parseEvents() {
if (_renderMode == Common::kRenderHercA || _renderMode == Common::kRenderHercG) {
_mouse.x -= (Common::kHercW - _screenWidth * 2) / 2;
- _mouse.x /= 2;
+ _mouse.x >>= 1;
_mouse.y = _mouse.y * 4 / 7;
+ } else if (_useCJKMode && _textSurfaceMultiplier == 2) {
+ _mouse.x >>= 1;
+ _mouse.y >>= 1;
}
break;
case Common::EVENT_LBUTTONUP:
diff --git a/engines/scumm/module.mk b/engines/scumm/module.mk
index d8ef669410..a340f564b3 100644
--- a/engines/scumm/module.mk
+++ b/engines/scumm/module.mk
@@ -90,6 +90,11 @@ endif
endif
+ifdef USE_ARM_GFX_ASM
+MODULE_OBJS += \
+ gfxARM.o
+endif
+
ifndef DISABLE_HE
MODULE_OBJS += \
he/animation_he.o \
diff --git a/engines/scumm/scumm-md5.h b/engines/scumm/scumm-md5.h
index cd48ef4d02..4f6b2477c6 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 Mon Jul 2 22:44:41 2007
+ This file was generated by the md5table tool on Fri Jul 20 21:25:14 2007
DO NOT EDIT MANUALLY!
*/
@@ -25,10 +25,12 @@ static const MD5Table md5table[] = {
{ "04687cdf7f975a89d2474929f7b80946", "indy3", "FM-TOWNS", "", 7552, Common::EN_ANY, Common::kPlatformFMTowns },
{ "0557df19f046a84c2fdc63507c6616cb", "farm", "HE 72", "Demo", -1, Common::NL_NLD, Common::kPlatformWindows },
{ "055ffe4f47753e47594ac67823220c54", "puttrace", "HE 99", "", -1, Common::DE_DEU, Common::kPlatformUnknown },
+ { "057c9b456dedcc4d71b991a3072a20b3", "monkey", "SEGA", "", 9465, Common::JA_JPN, Common::kPlatformSegaCD },
{ "0650e8ab1432564607cd651c0fa3f344", "loom", "PC-Engine", "", -1, Common::EN_ANY, Common::kPlatformPCEngine },
{ "06b187468113f9ae5a400b148a847fac", "atlantis", "", "Floppy", 12075, Common::EN_ANY, Common::kPlatformMacintosh },
{ "06c3cf4f31daad8b1cd93153491db9e6", "pajama3", "", "", -1, Common::NL_NLD, Common::kPlatformMacintosh },
{ "07433205acdca3bc553d0e731588b35f", "airport", "", "", -1, Common::EN_ANY, Common::kPlatformWindows },
+ { "07a1eefd8ca95d77310311446c0f53d0", "brstorm", "", "Demo", 5433, Common::EN_ANY, Common::kPlatformUnknown },
{ "07b810e37be7489263f7bc7627d4765d", "freddi4", "unenc", "Unencrypted", -1, Common::RU_RUS, Common::kPlatformWindows },
{ "084ed0fa98a6d1e9368d67fe9cfbd417", "freddi", "HE 71", "Demo", -1, Common::EN_ANY, Common::kPlatformWindows },
{ "0855496dde35356b1a9691e22ba84cdc", "freddi", "HE 73", "Demo", -1, Common::EN_ANY, Common::kPlatformWindows },
@@ -320,6 +322,7 @@ static const MD5Table md5table[] = {
{ "86be8ada36371d4fdc35659d0e912a26", "indy3", "EGA", "EGA", -1, Common::ES_ESP, Common::kPlatformPC },
{ "86c9902b7bec1a17926d4dae85beaa45", "airport", "HE 71", "Demo", -1, Common::EN_ANY, Common::kPlatformWindows },
{ "870d1e3c86bc50846d808d14a36b4e08", "monkey", "VGA", "VGA", -1, Common::ES_ESP, Common::kPlatformAmiga },
+ { "8776caed014c321272af407c1502a2df", "monkey", "CD", "", 8955, Common::EN_ANY, Common::kPlatformMacintosh },
{ "87f6e8037b7cc996e13474b491a7a98e", "maniac", "V2", "V2", -1, Common::IT_ITA, Common::kPlatformPC },
{ "8801fb4a1200b347f7a38523339526dd", "jungle", "", "", -1, Common::EN_ANY, Common::kPlatformWindows },
{ "883af4b0af4f77a92f1dcf1d0a283140", "tentacle", "", "CD", -1, Common::ES_ESP, Common::kPlatformUnknown },
@@ -444,6 +447,7 @@ static const MD5Table md5table[] = {
{ "c8575e0b973ff1723aba6cd92c642db2", "puttrace", "HE 99", "Demo", -1, Common::FR_FRA, Common::kPlatformWindows },
{ "c8aac5e3e701874e2fa4117896f9e1b1", "freddi", "HE 73", "Demo", -1, Common::EN_ANY, Common::kPlatformMacintosh },
{ "c8c5baadcbfc8d0372ed4335abace8a7", "pajama3", "", "Demo", -1, Common::FR_FRA, Common::kPlatformWindows },
+ { "c9717ee6059f1e43b768b464493d2fba", "fbpack", "", "", -1, Common::JA_JPN, Common::kPlatform3DO },
{ "cb1559e8405d17a5a278a6b5ad9338d1", "freddi3", "", "Demo", 22718, Common::EN_ANY, Common::kPlatformUnknown },
{ "cc04a076779379524ed4d9c5ee3c6fb1", "tentacle", "", "CD", 282467632, Common::EN_ANY, Common::kPlatformMacintosh },
{ "cc8ba2b0df2f9c450bcf055fe2711979", "samnmax", "", "Demo", 7485, Common::DE_DEU, Common::kPlatformPC },
diff --git a/engines/scumm/scumm.cpp b/engines/scumm/scumm.cpp
index 2140b15544..e54060c9e1 100644
--- a/engines/scumm/scumm.cpp
+++ b/engines/scumm/scumm.cpp
@@ -480,7 +480,7 @@ ScummEngine::ScummEngine(OSystem *syst, const DetectorResult &dr)
_renderMode = Common::kRenderDefault;
}
- // Do some render mode restirctions
+ // Check some render mode restrictions
if (_game.version <= 1)
_renderMode = Common::kRenderDefault;
@@ -521,7 +521,11 @@ ScummEngine::ScummEngine(OSystem *syst, const DetectorResult &dr)
_screenHeight = 200;
}
- _compositeBuf = (byte *)malloc(_screenWidth * _screenHeight);
+ // Allocate gfx compositing buffer (not needed for V7/V8 games).
+ if (_game.version < 7)
+ _compositeBuf = (byte *)malloc(_screenWidth * _screenHeight);
+ else
+ _compositeBuf = 0;
_herculesBuf = 0;
if (_renderMode == Common::kRenderHercA || _renderMode == Common::kRenderHercG) {
@@ -583,6 +587,7 @@ ScummEngine::~ScummEngine() {
free(_compositeBuf);
free(_herculesBuf);
+ free(_fmtownsBuf);
delete _debugger;
@@ -1074,12 +1079,19 @@ int ScummEngine::init() {
_fileHandle = new ScummFile();
}
+ // Load CJK font, if present
+ // Load it earlier so _useCJKMode variable could be set
+ loadCJKFont();
+
// Initialize backend
_system->beginGFXTransaction();
bool defaultTo1XScaler = false;
if (_renderMode == Common::kRenderHercA || _renderMode == Common::kRenderHercG) {
_system->initSize(Common::kHercW, Common::kHercH);
defaultTo1XScaler = true;
+ } else if (_useCJKMode) {
+ _system->initSize(_screenWidth * _textSurfaceMultiplier, _screenHeight * _textSurfaceMultiplier);
+ defaultTo1XScaler = true;
} else {
_system->initSize(_screenWidth, _screenHeight);
defaultTo1XScaler = (_screenWidth > 320);
@@ -1131,14 +1143,11 @@ void ScummEngine::setupScumm() {
// Load localization data, if present
loadLanguageBundle();
- // Load CJK font, if present
- loadCJKFont();
-
// Create the charset renderer
setupCharsetRenderer();
// Create and clear the text surface
- _textSurface.create(_screenWidth, _screenHeight, 1);
+ _textSurface.create(_screenWidth * _textSurfaceMultiplier, _screenHeight * _textSurfaceMultiplier, 1);
clearTextSurface();
// Create the costume renderer
@@ -1206,6 +1215,13 @@ void ScummEngine::setupScumm() {
#if (defined(PALMOS_ARM) || defined(PALMOS_DEBUG) || defined(__GP32__))
Graphics::initfonts();
#endif
+
+ _fmtownsBuf = 0;
+ if (_game.platform == Common::kPlatformFMTowns && _language == Common::JA_JPN) {
+ _fmtownsBuf = (byte *)malloc(_screenWidth * _textSurfaceMultiplier * _screenHeight * _textSurfaceMultiplier);
+ }
+
+ _compositeBuf = (byte *)malloc(_screenWidth * _textSurfaceMultiplier * _screenHeight * _textSurfaceMultiplier);
}
#ifndef DISABLE_SCUMM_7_8
diff --git a/engines/scumm/scumm.h b/engines/scumm/scumm.h
index 4146846856..18c2275029 100644
--- a/engines/scumm/scumm.h
+++ b/engines/scumm/scumm.h
@@ -1026,11 +1026,12 @@ protected:
// Screen rendering
byte *_compositeBuf;
byte *_herculesBuf;
+ byte *_fmtownsBuf;
virtual void drawDirtyScreenParts();
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 ditherHerc(byte *src, byte *hercbuf, int srcPitch, 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);
@@ -1152,6 +1153,7 @@ public:
* drawStripToScreen() composits it over the game graphics.
*/
Graphics::Surface _textSurface;
+ int _textSurfaceMultiplier;
protected:
byte _charsetColor;
diff --git a/engines/scumm/smush/smush_player.cpp b/engines/scumm/smush/smush_player.cpp
index 2c744a16e2..ce39302e25 100644
--- a/engines/scumm/smush/smush_player.cpp
+++ b/engines/scumm/smush/smush_player.cpp
@@ -1178,12 +1178,15 @@ void SmushPlayer::tryCmpFile(const char *filename) {
char fname[260];
#endif
Common::File *file = new Common::File();
+
+ // FIXME: How about using AudioStream::openStreamFile instead of the code below?
+
#ifdef USE_VORBIS
memcpy(fname, filename, i - filename);
strcpy(fname + (i - filename), ".ogg");
if (file->open(fname)) {
_compressedFileMode = true;
- _vm->_mixer->playInputStream(Audio::Mixer::kSFXSoundType, &_compressedFileSoundHandle, Audio::makeVorbisStream(file, true, 0, 0));
+ _vm->_mixer->playInputStream(Audio::Mixer::kSFXSoundType, &_compressedFileSoundHandle, Audio::makeVorbisStream(file, true));
return;
}
#endif
@@ -1192,7 +1195,7 @@ void SmushPlayer::tryCmpFile(const char *filename) {
strcpy(fname + (i - filename), ".mp3");
if (file->open(fname)) {
_compressedFileMode = true;
- _vm->_mixer->playInputStream(Audio::Mixer::kSFXSoundType, &_compressedFileSoundHandle, Audio::makeMP3Stream(file, true, 0, 0));
+ _vm->_mixer->playInputStream(Audio::Mixer::kSFXSoundType, &_compressedFileSoundHandle, Audio::makeMP3Stream(file, true));
return;
}
#endif
diff --git a/engines/scumm/sound.cpp b/engines/scumm/sound.cpp
index e5720a013f..62f65c22c1 100644
--- a/engines/scumm/sound.cpp
+++ b/engines/scumm/sound.cpp
@@ -607,24 +607,31 @@ void Sound::startTalkSound(uint32 offset, uint32 b, int mode, Audio::SoundHandle
if (!_soundsPaused && _mixer->isReady()) {
Audio::AudioStream *input = NULL;
+ Common::MemoryReadStream *tmp = NULL;
switch (_soundMode) {
case kMP3Mode:
#ifdef USE_MAD
assert(size > 0);
- input = Audio::makeMP3Stream(_sfxFile, size);
+ tmp = _sfxFile->readStream(size);
+ assert(tmp);
+ input = Audio::makeMP3Stream(tmp, true);
#endif
break;
case kVorbisMode:
#ifdef USE_VORBIS
assert(size > 0);
- input = Audio::makeVorbisStream(_sfxFile, size);
+ tmp = _sfxFile->readStream(size);
+ assert(tmp);
+ input = Audio::makeVorbisStream(tmp, true);
#endif
break;
case kFlacMode:
#ifdef USE_FLAC
assert(size > 0);
- input = Audio::makeFlacStream(_sfxFile, size);
+ tmp = _sfxFile->readStream(size);
+ assert(tmp);
+ input = Audio::makeFlacStream(tmp, true);
#endif
break;
default:
@@ -831,7 +838,7 @@ void Sound::soundKludge(int *list, int num) {
}
void Sound::talkSound(uint32 a, uint32 b, int mode, int channel) {
- if (_vm->_game.version >= 6 && ConfMan.getBool("speech_mute"))
+ if (_vm->_game.version >= 5 && ConfMan.getBool("speech_mute"))
return;
if (mode == 1) {
diff --git a/engines/scumm/string.cpp b/engines/scumm/string.cpp
index 44e727b5d3..32fdf0e04e 100644
--- a/engines/scumm/string.cpp
+++ b/engines/scumm/string.cpp
@@ -172,6 +172,20 @@ void ScummEngine_v6::drawBlastTexts() {
if (c == 0x0B)
continue;
+ // Some localizations may override colors
+ // See credits in Chinese COMI
+ if (c == '^' && (buf == _blastTextQueue[i].text + 1)) {
+ int color;
+ switch (*buf) {
+ case 'c':
+ color = buf[3] - '0' + 10 *(buf[2] - '0');
+ _charset->setColor(color);
+
+ buf += 4;
+ c = *buf++;
+ }
+ }
+
if (c != 0 && c != 0xFF && c != '\n') {
if (c & 0x80 && _useCJKMode) {
if (_language == Common::JA_JPN && !checkSJISCode(c)) {
@@ -1060,7 +1074,7 @@ int ScummEngine::convertMessageToString(const byte *msg, byte *dst, int dstSize)
num += (_game.version == 8) ? 4 : 2;
}
} else {
- if (!(chr == '@' && _game.heversion <= 71)) {
+ if (!(chr == '@' && _game.heversion <= 71) || _language == Common::ZH_TWN) {
*dst++ = chr;
}
}
diff --git a/engines/sword1/music.cpp b/engines/sword1/music.cpp
index ebff7f9929..e6acd8f3cd 100644
--- a/engines/sword1/music.cpp
+++ b/engines/sword1/music.cpp
@@ -203,6 +203,10 @@ bool MusicHandle::play(const char *fileBase, bool loop) {
char fileName[30];
stop();
+ // FIXME: How about using AudioStream::openStreamFile instead of the code below?
+ // I.e.:
+ //_audioSource = Audio::AudioStream::openStreamFile(fileBase, 0, 0, loop ? 0 : 1);
+
#ifdef USE_FLAC
if (!_audioSource) {
sprintf(fileName, "%s.flac", fileBase);
diff --git a/engines/sword1/sound.cpp b/engines/sword1/sound.cpp
index 492672fad8..2594aaf8f4 100644
--- a/engines/sword1/sound.cpp
+++ b/engines/sword1/sound.cpp
@@ -201,7 +201,9 @@ bool Sound::startSpeech(uint16 roomNo, uint16 localNo) {
#ifdef USE_FLAC
else if (_cowMode == CowFlac) {
_cowFile.seek(index);
- _mixer->playInputStream(Audio::Mixer::kSpeechSoundType, &_speechHandle, Audio::makeFlacStream(&_cowFile, sampleSize), SOUND_SPEECH_ID, speechVol, speechPan);
+ Common::MemoryReadStream *tmp = _cowFile.readStream(sampleSize);
+ assert(tmp);
+ _mixer->playInputStream(Audio::Mixer::kSpeechSoundType, &_speechHandle, Audio::makeFlacStream(tmp, true), SOUND_SPEECH_ID, speechVol, speechPan);
// with compressed audio, we can't calculate the wave volume.
// so default to talking.
for (int cnt = 0; cnt < 480; cnt++)
@@ -212,7 +214,9 @@ bool Sound::startSpeech(uint16 roomNo, uint16 localNo) {
#ifdef USE_VORBIS
else if (_cowMode == CowVorbis) {
_cowFile.seek(index);
- _mixer->playInputStream(Audio::Mixer::kSpeechSoundType, &_speechHandle, Audio::makeVorbisStream(&_cowFile, sampleSize), SOUND_SPEECH_ID, speechVol, speechPan);
+ Common::MemoryReadStream *tmp = _cowFile.readStream(sampleSize);
+ assert(tmp);
+ _mixer->playInputStream(Audio::Mixer::kSpeechSoundType, &_speechHandle, Audio::makeVorbisStream(tmp, true), SOUND_SPEECH_ID, speechVol, speechPan);
// with compressed audio, we can't calculate the wave volume.
// so default to talking.
for (int cnt = 0; cnt < 480; cnt++)
@@ -223,7 +227,9 @@ bool Sound::startSpeech(uint16 roomNo, uint16 localNo) {
#ifdef USE_MAD
else if (_cowMode == CowMp3) {
_cowFile.seek(index);
- _mixer->playInputStream(Audio::Mixer::kSpeechSoundType, &_speechHandle, Audio::makeMP3Stream(&_cowFile, sampleSize), SOUND_SPEECH_ID, speechVol, speechPan);
+ Common::MemoryReadStream *tmp = _cowFile.readStream(sampleSize);
+ assert(tmp);
+ _mixer->playInputStream(Audio::Mixer::kSpeechSoundType, &_speechHandle, Audio::makeMP3Stream(tmp, true), SOUND_SPEECH_ID, speechVol, speechPan);
// with compressed audio, we can't calculate the wave volume.
// so default to talking.
for (int cnt = 0; cnt < 480; cnt++)
diff --git a/engines/sword2/music.cpp b/engines/sword2/music.cpp
index 28427e5d1b..c2374dad9f 100644
--- a/engines/sword2/music.cpp
+++ b/engines/sword2/music.cpp
@@ -139,21 +139,29 @@ static Audio::AudioStream *getAudioStream(SoundFileHandle *fh, const char *base,
}
fh->file.seek(pos, SEEK_SET);
+
+ Common::MemoryReadStream *tmp = 0;
switch (fh->fileType) {
case kCLUMode:
return makeCLUStream(&fh->file, enc_len);
#ifdef USE_MAD
case kMP3Mode:
- return Audio::makeMP3Stream(&fh->file, enc_len);
+ tmp = fh->file.readStream(enc_len);
+ assert(tmp);
+ return Audio::makeMP3Stream(tmp, true);
#endif
#ifdef USE_VORBIS
case kVorbisMode:
- return Audio::makeVorbisStream(&fh->file, enc_len);
+ tmp = fh->file.readStream(enc_len);
+ assert(tmp);
+ return Audio::makeVorbisStream(tmp, true);
#endif
#ifdef USE_FLAC
case kFlacMode:
- return Audio::makeFlacStream(&fh->file, enc_len);
+ tmp = fh->file.readStream(enc_len);
+ assert(tmp);
+ return Audio::makeFlacStream(tmp, true);
#endif
default:
return NULL;
@@ -659,8 +667,10 @@ void Sound::muteSpeech(bool mute) {
*/
void Sound::pauseSpeech() {
- _speechPaused = true;
- _vm->_mixer->pauseHandle(_soundHandleSpeech, true);
+ if (!_speechPaused) {
+ _speechPaused = true;
+ _vm->_mixer->pauseHandle(_soundHandleSpeech, true);
+ }
}
/**
@@ -668,8 +678,10 @@ void Sound::pauseSpeech() {
*/
void Sound::unpauseSpeech() {
- _speechPaused = false;
- _vm->_mixer->pauseHandle(_soundHandleSpeech, false);
+ if (_speechPaused) {
+ _speechPaused = false;
+ _vm->_mixer->pauseHandle(_soundHandleSpeech, false);
+ }
}
/**
@@ -793,26 +805,22 @@ int32 Sound::setFxIdVolumePan(int32 id, int vol, int pan) {
}
void Sound::pauseFx() {
- if (_fxPaused)
- return;
-
- for (int i = 0; i < FXQ_LENGTH; i++) {
- if (_fxQueue[i].resource)
- _vm->_mixer->pauseHandle(_fxQueue[i].handle, true);
+ if (!_fxPaused) {
+ for (int i = 0; i < FXQ_LENGTH; i++) {
+ if (_fxQueue[i].resource)
+ _vm->_mixer->pauseHandle(_fxQueue[i].handle, true);
+ }
+ _fxPaused = true;
}
-
- _fxPaused = true;
}
void Sound::unpauseFx() {
- if (!_fxPaused)
- return;
-
- for (int i = 0; i < FXQ_LENGTH; i++)
- if (_fxQueue[i].resource)
- _vm->_mixer->pauseHandle(_fxQueue[i].handle, false);
-
- _fxPaused = false;
+ if (_fxPaused) {
+ for (int i = 0; i < FXQ_LENGTH; i++)
+ if (_fxQueue[i].resource)
+ _vm->_mixer->pauseHandle(_fxQueue[i].handle, false);
+ _fxPaused = false;
+ }
}
} // End of namespace Sword2
diff --git a/engines/touche/graphics.cpp b/engines/touche/graphics.cpp
index 51fdcbd89a..2ca11a1f95 100644
--- a/engines/touche/graphics.cpp
+++ b/engines/touche/graphics.cpp
@@ -177,34 +177,58 @@ void Graphics::drawLine(uint8 *dst, int dstPitch, int x1, int y1, int x2, int y2
}
void Graphics::copyRect(uint8 *dst, int dstPitch, int dstX, int dstY, const uint8 *src, int srcPitch, int srcX, int srcY, int w, int h, int flags) {
- if (w != 0 && h != 0) {
- dst += dstY * dstPitch + dstX;
- src += srcY * srcPitch + srcX;
- while (h--) {
- for (int i = 0; i < w; ++i) {
- if ((flags & kTransparent) == 0 || src[i] != 0) {
- dst[i] = src[i];
- }
+ if (dstX < 0) {
+ w += dstX;
+ dstX = 0;
+ }
+ if (w <= 0) {
+ return;
+ }
+ if (dstY < 0) {
+ h += dstY;
+ dstY = 0;
+ }
+ if (h <= 0) {
+ return;
+ }
+ dst += dstY * dstPitch + dstX;
+ src += srcY * srcPitch + srcX;
+ while (h--) {
+ for (int i = 0; i < w; ++i) {
+ if ((flags & kTransparent) == 0 || src[i] != 0) {
+ dst[i] = src[i];
}
- dst += dstPitch;
- src += srcPitch;
}
+ dst += dstPitch;
+ src += srcPitch;
}
}
void Graphics::copyMask(uint8 *dst, int dstPitch, int dstX, int dstY, const uint8 *src, int srcPitch, int srcX, int srcY, int w, int h, uint8 fillColor) {
- if (w != 0 && h != 0) {
- dst += dstY * dstPitch + dstX;
- src += srcY * srcPitch + srcX;
- while (h--) {
- for (int i = 0; i < w; ++i) {
- if (src[i] != 0) {
- dst[i] = fillColor;
- }
+ if (dstX < 0) {
+ w += dstX;
+ dstX = 0;
+ }
+ if (w <= 0) {
+ return;
+ }
+ if (dstY < 0) {
+ h += dstY;
+ dstY = 0;
+ }
+ if (h <= 0) {
+ return;
+ }
+ dst += dstY * dstPitch + dstX;
+ src += srcY * srcPitch + srcX;
+ while (h--) {
+ for (int i = 0; i < w; ++i) {
+ if (src[i] != 0) {
+ dst[i] = fillColor;
}
- dst += dstPitch;
- src += srcPitch;
}
+ dst += dstPitch;
+ src += srcPitch;
}
}
diff --git a/engines/touche/midi.cpp b/engines/touche/midi.cpp
index 29e68a4562..b90d4082c5 100644
--- a/engines/touche/midi.cpp
+++ b/engines/touche/midi.cpp
@@ -32,8 +32,8 @@
namespace Touche {
-MidiPlayer::MidiPlayer(MidiDriver *driver)
- : _driver(driver), _parser(0), _midiData(0), _isLooping(false), _isPlaying(false), _masterVolume(0) {
+MidiPlayer::MidiPlayer(MidiDriver *driver, bool nativeMT32)
+ : _driver(driver), _parser(0), _midiData(0), _isLooping(false), _isPlaying(false), _masterVolume(0), _nativeMT32(nativeMT32) {
assert(_driver);
memset(_channelsTable, 0, sizeof(_channelsTable));
memset(_channelsVolume, 0, sizeof(_channelsVolume));
@@ -129,6 +129,11 @@ void MidiPlayer::send(uint32 b) {
return;
}
break;
+ default:
+ if ((b & 0xF0) == 0xC0 && _nativeMT32) { // program change
+ b = (b & 0xFFFF00FF) | (_gmToRol[(b >> 8) & 0x7F] << 8);
+ }
+ break;
}
if (!_channelsTable[ch]) {
_channelsTable[ch] = (ch == 9) ? _driver->getPercussionChannel() : _driver->allocateChannel();
diff --git a/engines/touche/midi.h b/engines/touche/midi.h
index 808ecfb205..3b128593db 100644
--- a/engines/touche/midi.h
+++ b/engines/touche/midi.h
@@ -46,7 +46,7 @@ public:
NUM_CHANNELS = 16
};
- MidiPlayer(MidiDriver *driver);
+ MidiPlayer(MidiDriver *driver, bool nativeMT32);
~MidiPlayer();
void play(Common::ReadStream &stream, int size, bool loop = false);
@@ -77,9 +77,12 @@ private:
bool _isLooping;
bool _isPlaying;
int _masterVolume;
+ bool _nativeMT32;
MidiChannel *_channelsTable[NUM_CHANNELS];
uint8 _channelsVolume[NUM_CHANNELS];
Common::Mutex _mutex;
+
+ static const uint8 _gmToRol[];
};
} // namespace Touche
diff --git a/engines/touche/opcodes.cpp b/engines/touche/opcodes.cpp
index f0ef748fbd..2680ab0fae 100644
--- a/engines/touche/opcodes.cpp
+++ b/engines/touche/opcodes.cpp
@@ -828,10 +828,16 @@ void ToucheEngine::op_setHitBoxText() {
void ToucheEngine::op_fadePalette() {
debugC(9, kDebugOpcodes, "ToucheEngine::op_fadePalette()");
int16 fadeOut = _script.readNextWord();
+ int colorsCount = 240;
+ // Workaround for bug #1751149. Script triggers a palette fading, but some
+ // of the room graphics use palette colors >= 240.
+ if (_currentEpisodeNum == 104 && _currentRoomNum == 68) {
+ colorsCount = 256;
+ }
if (fadeOut) {
- fadePalette(0, 240, 255, -2, 128);
+ fadePalette(0, colorsCount, 255, -2, 128);
} else {
- fadePalette(0, 240, 0, 2, 128);
+ fadePalette(0, colorsCount, 0, 2, 128);
}
}
diff --git a/engines/touche/resource.cpp b/engines/touche/resource.cpp
index 585e70c534..cd2124806d 100644
--- a/engines/touche/resource.cpp
+++ b/engines/touche/resource.cpp
@@ -44,7 +44,12 @@ enum {
struct CompressedSpeechFile {
const char *filename;
- Audio::AudioStream *(*makeStream)(Common::File *file, uint32 size);
+ Audio::AudioStream *(*makeStream)(
+ Common::SeekableReadStream *stream,
+ bool disposeAfterUse,
+ uint32 startTime,
+ uint32 duration,
+ uint numLoops);
};
static const CompressedSpeechFile compressedSpeechFilesTable[] = {
@@ -268,7 +273,7 @@ void ToucheEngine::res_decodeProgramData() {
ppd.x = READ_LE_UINT16(p); p += 2;
ppd.y = READ_LE_UINT16(p); p += 2;
ppd.z = READ_LE_UINT16(p); p += 2;
- ppd.priority = READ_LE_UINT16(p); p += 2;
+ ppd.order = READ_LE_UINT16(p); p += 2;
_programPointsTable.push_back(ppd);
if (ppd.x == -1) {
break;
@@ -516,19 +521,20 @@ void ToucheEngine::res_loadBackdrop() {
debugC(9, kDebugResource, "ToucheEngine::res_loadBackdrop()");
_currentBitmapWidth = _fData.readUint16LE();
_currentBitmapHeight = _fData.readUint16LE();
- uint8 *dst = _backdropBuffer;
for (int i = 0; i < _currentBitmapHeight; ++i) {
- res_decodeScanLineImageRLE(dst + _currentBitmapWidth * i, _currentBitmapWidth);
+ res_decodeScanLineImageRLE(_backdropBuffer + _currentBitmapWidth * i, _currentBitmapWidth);
}
_roomWidth = _currentBitmapWidth;
- dst = _backdropBuffer;
for (int i = 0; i < _currentBitmapWidth; ++i) {
- if (*dst == 255) {
+ if (_backdropBuffer[i] == 255) {
_roomWidth = i;
- *dst = 0;
+ _backdropBuffer[i] = 0;
break;
}
- ++dst;
+ }
+ // Workaround for bug #1751149 (original bitmap has a white pixel in its transparent area).
+ if (_currentRoomNum == 8 && _currentBitmapWidth == 860) {
+ _backdropBuffer[120 * _currentBitmapWidth + 734] = 0;
}
}
@@ -656,7 +662,9 @@ void ToucheEngine::res_loadSpeechSegment(int num) {
return;
}
_fSpeech[0].seek(offs);
- stream = (compressedSpeechFilesTable[_compressedSpeechData].makeStream)(&_fSpeech[0], size);
+ Common::MemoryReadStream *tmp = _fSpeech[0].readStream(size);
+ assert(tmp);
+ stream = (compressedSpeechFilesTable[_compressedSpeechData].makeStream)(tmp, true, 0, 0, 1);
}
if (stream) {
_speechPlaying = true;
diff --git a/engines/touche/saveload.cpp b/engines/touche/saveload.cpp
index c37c06aacb..5ff749fa68 100644
--- a/engines/touche/saveload.cpp
+++ b/engines/touche/saveload.cpp
@@ -131,7 +131,7 @@ static void saveOrLoad(S &s, KeyChar &key) {
saveOrLoad(s, key.followingKeyCharPos);
saveOrLoad(s, key.sequenceDataIndex);
saveOrLoad(s, key.sequenceDataOffset);
- saveOrLoad(s, key.walkPointsListCount);
+ saveOrLoad(s, key.walkPointsListIndex);
for (uint i = 0; i < 40; ++i) {
saveOrLoad(s, key.walkPointsList[i]);
}
@@ -209,7 +209,7 @@ static void saveOrLoad(S &s, ProgramPointData &data) {
saveOrLoad(s, data.x);
saveOrLoad(s, data.y);
saveOrLoad(s, data.z);
- saveOrLoad(s, data.priority);
+ saveOrLoad(s, data.order);
}
template <class S, class A>
@@ -280,8 +280,8 @@ void ToucheEngine::loadGameStateData(Common::ReadStream *stream) {
_newMusicNum = stream->readUint16LE();
_currentRoomNum = stream->readUint16LE();
res_loadRoom(_currentRoomNum);
- int16 roomOffsX = stream->readUint16LE();
- int16 roomOffsY = stream->readUint16LE();
+ int16 roomOffsX = _flagsTable[614] = stream->readUint16LE();
+ int16 roomOffsY = _flagsTable[615] = stream->readUint16LE();
_disabledInputCounter = stream->readUint16LE();
res_loadProgram(_currentEpisodeNum);
setupEpisode(-1);
@@ -291,7 +291,7 @@ void ToucheEngine::loadGameStateData(Common::ReadStream *stream) {
saveOrLoadCommonArray(*stream, _programWalkTable);
saveOrLoadCommonArray(*stream, _programPointsTable);
stream->read(_updatedRoomAreasTable, 200);
- for (uint i = 1; i <= _updatedRoomAreasTable[0]; ++i) {
+ for (uint i = 1; i < _updatedRoomAreasTable[0]; ++i) {
updateRoomAreas(_updatedRoomAreasTable[i], -1);
}
saveOrLoadStaticArray(*stream, _sequenceEntryTable, NUM_SEQUENCES);
@@ -327,7 +327,9 @@ void ToucheEngine::loadGameStateData(Common::ReadStream *stream) {
Graphics::copyRect(_offscreenBuffer, kScreenWidth, 0, 0,
_backdropBuffer, _currentBitmapWidth, _flagsTable[614], _flagsTable[615],
kScreenWidth, kRoomHeight);
+ updateRoomRegions();
updateEntireScreen();
+ _roomNeedRedraw = false;
if (_flagsTable[617] != 0) {
res_loadSpeech(_flagsTable[617]);
}
diff --git a/engines/touche/staticres.cpp b/engines/touche/staticres.cpp
index 4c3ea4855f..eb3ddc15ff 100644
--- a/engines/touche/staticres.cpp
+++ b/engines/touche/staticres.cpp
@@ -27,6 +27,7 @@
#include "touche/graphics.h"
#include "touche/touche.h"
+#include "touche/midi.h"
namespace Touche {
@@ -1332,5 +1333,15 @@ int Graphics::_fontSize = Graphics::_engFontSize;
const uint8 *Graphics::_fontData = Graphics::_engFontData;
+const uint8 MidiPlayer::_gmToRol[] = {
+ 0x01, 0x02, 0x03, 0x08, 0x04, 0x05, 0x11, 0x14, 0x66, 0x66, 0x66, 0x62, 0x69, 0x68, 0x67, 0x26,
+ 0x09, 0x0A, 0x0B, 0x0E, 0x0F, 0x10, 0x10, 0x10, 0x3C, 0x3D, 0x3D, 0x3D, 0x3D, 0x3E, 0x3F, 0x3F,
+ 0x47, 0x41, 0x42, 0x48, 0x45, 0x46, 0x1D, 0x1E, 0x35, 0x36, 0x37, 0x39, 0x33, 0x34, 0x3A, 0x71,
+ 0x31, 0x32, 0x31, 0x32, 0x23, 0x23, 0x23, 0x7B, 0x59, 0x5B, 0x5F, 0x5A, 0x5D, 0x60, 0x19, 0x1A,
+ 0x4F, 0x50, 0x51, 0x52, 0x55, 0x56, 0x57, 0x53, 0x4B, 0x49, 0x4D, 0x4E, 0x6F, 0x6C, 0x6D, 0x6E,
+ 0x30, 0x19, 0x4E, 0x2B, 0x28, 0x23, 0x19, 0x30, 0x21, 0x25, 0x1C, 0x21, 0x24, 0x22, 0x21, 0x22,
+ 0x2A, 0x25, 0x24, 0x26, 0x2E, 0x22, 0x29, 0x21, 0x40, 0x40, 0x6A, 0x6A, 0x68, 0x10, 0x35, 0x10,
+ 0x7F, 0x6B, 0x69, 0x75, 0x76, 0x72, 0x74, 0x01, 0x01, 0x70, 0x01, 0x7D, 0x7C, 0x01, 0x01, 0x01
+};
} // namespace Touche
diff --git a/engines/touche/touche.cpp b/engines/touche/touche.cpp
index 18d2ac5359..c67b1e9be3 100644
--- a/engines/touche/touche.cpp
+++ b/engines/touche/touche.cpp
@@ -97,8 +97,9 @@ int ToucheEngine::init() {
setupOpcodes();
int midiDriver = MidiDriver::detectMusicDriver(MDT_MIDI | MDT_ADLIB | MDT_PREFER_MIDI);
+ bool native_mt32 = ((midiDriver == MD_MT32) || ConfMan.getBool("native_mt32"));
MidiDriver *driver = MidiDriver::createMidi(midiDriver);
- _midiPlayer = new MidiPlayer(driver);
+ _midiPlayer = new MidiPlayer(driver, native_mt32);
_mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, ConfMan.getInt("sfx_volume"));
_mixer->setVolumeForSoundType(Audio::Mixer::kSpeechSoundType, ConfMan.getInt("speech_volume"));
@@ -642,7 +643,7 @@ void ToucheEngine::initKeyChars(int keyChar) {
key->sequenceDataOffset = 0;
key->walkDataNum = 0;
key->walkPointsList[0] = -1;
- key->walkPointsListCount = 0;
+ key->walkPointsListIndex = 0;
key->delay = 0;
key->waitingKeyChar = -1;
key->flags = 0;
@@ -869,11 +870,11 @@ void ToucheEngine::redrawRoom() {
}
}
-void ToucheEngine::fadePalette(int firstColor, int lastColor, int scale, int scaleInc, int fadingStepsCount) {
+void ToucheEngine::fadePalette(int firstColor, int colorCount, int scale, int scaleInc, int fadingStepsCount) {
for (int i = 0; i < fadingStepsCount; ++i) {
scale += scaleInc;
scale = CLIP(scale, 0, 255);
- setPalette(firstColor, lastColor, scale, scale, scale);
+ setPalette(firstColor, colorCount, scale, scale, scale);
_system->updateScreen();
_system->delayMillis(10);
}
@@ -2516,7 +2517,7 @@ void ToucheEngine::buildWalkPointsList(int keyChar) {
uint16 curPos, pos1, pos2;
if (key->pointsDataNum & 0x8000) {
const ProgramWalkData *pwd = &_programWalkTable[(key->pointsDataNum & 0x7FFF)];
- if (_programPointsTable[pwd->point1].priority < _programPointsTable[pwd->point2].priority) {
+ if (_programPointsTable[pwd->point1].order < _programPointsTable[pwd->point2].order) {
curPos = pwd->point1;
} else {
curPos = pwd->point2;
@@ -2525,7 +2526,7 @@ void ToucheEngine::buildWalkPointsList(int keyChar) {
curPos = key->pointsDataNum;
}
- int16 posNum = _programPointsTable[curPos].priority;
+ int16 posNum = _programPointsTable[curPos].order;
if (posNum == 32000) {
return;
}
@@ -2536,25 +2537,25 @@ void ToucheEngine::buildWalkPointsList(int keyChar) {
if ((_programWalkTable[i].point1 & 0x4000) == 0) {
pos1 = _programWalkTable[i].point1;
pos2 = _programWalkTable[i].point2;
- if (pos1 == curPos && posNum > _programPointsTable[pos2].priority) {
+ if (pos1 == curPos && posNum > _programPointsTable[pos2].order) {
curPos = pos2;
assert(walkPointsCount < 40);
key->walkPointsList[walkPointsCount] = curPos;
++walkPointsCount;
- posNum = _programPointsTable[pos2].priority;
+ posNum = _programPointsTable[pos2].order;
break;
}
- if (pos2 == curPos && posNum > _programPointsTable[pos1].priority) {
+ if (pos2 == curPos && posNum > _programPointsTable[pos1].order) {
curPos = pos1;
assert(walkPointsCount < 40);
key->walkPointsList[walkPointsCount] = curPos;
++walkPointsCount;
- posNum = _programPointsTable[pos1].priority;
+ posNum = _programPointsTable[pos1].order;
break;
}
}
}
- } while (_programPointsTable[curPos].priority != 0);
+ } while (_programPointsTable[curPos].order != 0);
assert(walkPointsCount < 40);
key->walkPointsList[walkPointsCount] = -1;
@@ -2562,7 +2563,7 @@ void ToucheEngine::buildWalkPointsList(int keyChar) {
key->yPosPrev = _programPointsTable[curPos].y;
key->zPosPrev = _programPointsTable[curPos].z;
key->prevWalkDataNum = findWalkDataNum(curPos, -1);
- key->walkPointsListCount = 0;
+ key->walkPointsListIndex = 0;
if (key->walkDataNum == -1) {
return;
}
@@ -2571,13 +2572,13 @@ void ToucheEngine::buildWalkPointsList(int keyChar) {
pos2 = _programWalkTable[key->walkDataNum].point2;
if (key->pointsDataNum == pos1) {
if (key->walkPointsList[1] == pos2) {
- ++key->walkPointsListCount;
+ ++key->walkPointsListIndex;
}
return;
}
if (key->pointsDataNum == pos2) {
if (key->walkPointsList[1] == pos1) {
- ++key->walkPointsListCount;
+ ++key->walkPointsListIndex;
}
return;
}
@@ -2678,7 +2679,7 @@ void ToucheEngine::unlockWalkPath(int num1, int num2) {
void ToucheEngine::resetPointsData(int num) {
debugC(9, kDebugEngine, "ToucheEngine::resetPointsData(%d)", num);
for (uint i = 1; i < _programPointsTable.size(); ++i) {
- _programPointsTable[i].priority = num;
+ _programPointsTable[i].order = num;
}
}
@@ -2689,32 +2690,33 @@ bool ToucheEngine::sortPointsData(int num1, int num2) {
if (num2 == -1) {
return false;
}
- _programPointsTable[num2].priority = 0;
+ _programPointsTable[num2].order = 0;
} else {
const int md1 = _programWalkTable[num1].point1;
- _programPointsTable[md1].priority = 0;
+ _programPointsTable[md1].order = 0;
const int md2 = _programWalkTable[num1].point2;
- _programPointsTable[md2].priority = 0;
+ _programPointsTable[md2].order = 0;
}
bool quit = false;
- int priority = 1;
+ int order = 1;
while (!quit) {
quit = true;
for (uint i = 0; i < _programWalkTable.size(); ++i) {
const int md1 = _programWalkTable[i].point1;
const int md2 = _programWalkTable[i].point2;
if ((md1 & 0x4000) == 0) {
- if (_programPointsTable[md1].priority == priority - 1 && _programPointsTable[md2].priority > priority) {
- _programPointsTable[md2].priority = priority;
+ assert((md2 & 0x4000) == 0);
+ if (_programPointsTable[md1].order == order - 1 && _programPointsTable[md2].order > order) {
+ _programPointsTable[md2].order = order;
quit = false;
}
- if (_programPointsTable[md2].priority == priority - 1 && _programPointsTable[md1].priority > priority) {
- _programPointsTable[md1].priority = priority;
+ if (_programPointsTable[md2].order == order - 1 && _programPointsTable[md1].order > order) {
+ _programPointsTable[md1].order = order;
quit = false;
}
}
}
- ++priority;
+ ++order;
}
return true;
}
@@ -2763,8 +2765,8 @@ void ToucheEngine::updateKeyCharWalkPath(KeyChar *key, int16 dx, int16 dy, int16
int16 xpos, ypos, zpos, walkPoint1, walkPoint2, newDirection, incDx, incDy, incDz;
while (1) {
- walkPoint1 = key->walkPointsList[key->walkPointsListCount];
- walkPoint2 = key->walkPointsList[key->walkPointsListCount + 1];
+ walkPoint1 = key->walkPointsList[key->walkPointsListIndex];
+ walkPoint2 = key->walkPointsList[key->walkPointsListIndex + 1];
key->currentWalkBox = walkPoint1;
if (walkPoint1 == -1) {
xpos = key->xPosPrev;
@@ -2804,9 +2806,9 @@ void ToucheEngine::updateKeyCharWalkPath(KeyChar *key, int16 dx, int16 dy, int16
key->pointsDataNum = walkPoint1;
if (walkPoint2 == -1) {
key->walkPointsList[0] = -1;
- key->walkPointsListCount = 0;
+ key->walkPointsListIndex = 0;
} else {
- ++key->walkPointsListCount;
+ ++key->walkPointsListIndex;
int16 walkDataNum = findWalkDataNum(walkPoint1, walkPoint2);
if (walkDataNum != -1) {
key->walkDataNum = walkDataNum;
@@ -2858,7 +2860,7 @@ void ToucheEngine::updateKeyCharWalkPath(KeyChar *key, int16 dx, int16 dy, int16
}
key->prevPointsDataNum = key->pointsDataNum;
key->pointsDataNum = walkPoint1;
- ++key->walkPointsListCount;
+ ++key->walkPointsListIndex;
if (newDirection != curDirection) {
key->facingDirection = newDirection;
key->currentAnimCounter = 0;
@@ -2902,7 +2904,7 @@ void ToucheEngine::updateKeyCharWalkPath(KeyChar *key, int16 dx, int16 dy, int16
}
key->prevPointsDataNum = key->pointsDataNum;
key->pointsDataNum = walkPoint1;
- ++key->walkPointsListCount;
+ ++key->walkPointsListIndex;
if (newDirection != curDirection) {
key->facingDirection = newDirection;
key->currentAnimCounter = 0;
@@ -2941,7 +2943,7 @@ void ToucheEngine::markWalkPoints(int keyChar) {
int16 pointsDataNum = key->pointsDataNum;
resetPointsData(0);
if (pointsDataNum != -1) {
- _programPointsTable[pointsDataNum].priority = 1;
+ _programPointsTable[pointsDataNum].order = 1;
bool quit = false;
while (!quit) {
quit = true;
@@ -2949,12 +2951,13 @@ void ToucheEngine::markWalkPoints(int keyChar) {
int16 md1 = _programWalkTable[i].point1;
int16 md2 = _programWalkTable[i].point2;
if ((md1 & 0x4000) == 0) {
- if (_programPointsTable[md1].priority != 0 && _programPointsTable[md2].priority == 0) {
- _programPointsTable[md2].priority = 1;
+ assert((md2 & 0x4000) == 0);
+ if (_programPointsTable[md1].order != 0 && _programPointsTable[md2].order == 0) {
+ _programPointsTable[md2].order = 1;
quit = false;
}
- if (_programPointsTable[md2].priority != 0 && _programPointsTable[md1].priority == 0) {
- _programPointsTable[md1].priority = 1;
+ if (_programPointsTable[md2].order != 0 && _programPointsTable[md1].order == 0) {
+ _programPointsTable[md1].order = 1;
quit = false;
}
}
@@ -2973,9 +2976,9 @@ void ToucheEngine::buildWalkPath(int dstPosX, int dstPosY, int keyChar) {
int minDistance = 0x7D000000;
int minPointsDataNum = -1;
for (uint i = 1; i < _programPointsTable.size(); ++i) {
- if (_programPointsTable[i].priority != 0) {
- int dx = ABS<int>(_programPointsTable[i].x - dstPosX);
- int dy = ABS<int>(_programPointsTable[i].y - dstPosY);
+ if (_programPointsTable[i].order != 0) {
+ int dx = _programPointsTable[i].x - dstPosX;
+ int dy = _programPointsTable[i].y - dstPosY;
int distance = dx * dx + dy * dy;
if (distance < minDistance) {
minDistance = distance;
@@ -2992,28 +2995,28 @@ void ToucheEngine::buildWalkPath(int dstPosX, int dstPosY, int keyChar) {
int distance = 32000;
ProgramPointData *pts1 = &_programPointsTable[pwd->point1];
ProgramPointData *pts2 = &_programPointsTable[pwd->point2];
- if (pts1->priority != 0) {
+ if (pts1->order != 0) {
int dx = pts2->x - pts1->x;
int dy = pts2->y - pts1->y;
if (dx == 0) {
if (dstPosY > MIN(pts2->y, pts1->y) && dstPosY < MAX(pts2->y, pts1->y)) {
- distance = ABS(dstPosX - pts1->x);
- if (distance <= 100) {
- distance *= distance;
+ int d = ABS(dstPosX - pts1->x);
+ if (d <= 100) {
+ distance = d * d;
}
}
} else if (dy == 0) {
if (dstPosX > MIN(pts2->x, pts1->x) && dstPosX < MAX(pts2->x, pts1->x)) {
- distance = ABS(dstPosY - pts1->y);
- if (distance <= 100) {
- distance *= distance;
+ int d = ABS(dstPosY - pts1->y);
+ if (d <= 100) {
+ distance = d * d;
}
}
} else {
if (dstPosY > MIN(pts2->y, pts1->y) && dstPosY < MAX(pts2->y, pts1->y) &&
dstPosX > MIN(pts2->x, pts1->x) && dstPosX < MAX(pts2->x, pts1->x) ) {
- distance = (dstPosY - pts1->y) * dx - (dstPosX - pts1->x) * dy;
- distance = (dx * dx + dy * dy) / distance;
+ distance = (dstPosX - pts1->x) * dy - (dstPosY - pts1->y) * dx;
+ distance /= (dx * dx + dy * dy);
}
}
if (distance < minDistance) {
@@ -3047,13 +3050,13 @@ void ToucheEngine::buildWalkPath(int dstPosX, int dstPosY, int keyChar) {
dstPosZ = pts2->z - (pts2->x - dstPosX) * dz / dx;
dstPosY = pts2->y - (pts2->x - dstPosX) * dy / dx;
}
- if (key->walkDataNum == key->prevWalkDataNum && key->walkPointsList[1] == -1) {
- if (key->walkPointsList[0] == _programWalkTable[minWalkDataNum].point1 || key->walkPointsList[0] == _programWalkTable[minWalkDataNum].point2) {
- ++key->walkPointsListCount;
- }
- }
}
key->prevWalkDataNum = minWalkDataNum;
+ if (key->walkDataNum == key->prevWalkDataNum && key->walkPointsList[1] == -1) {
+ if (key->walkPointsList[0] == _programWalkTable[minWalkDataNum].point1 || key->walkPointsList[0] == _programWalkTable[minWalkDataNum].point2) {
+ ++key->walkPointsListIndex;
+ }
+ }
key->xPosPrev = dstPosX;
key->yPosPrev = dstPosY;
key->zPosPrev = dstPosZ;
diff --git a/engines/touche/touche.h b/engines/touche/touche.h
index ce4f84b9a8..5aef0ef613 100644
--- a/engines/touche/touche.h
+++ b/engines/touche/touche.h
@@ -114,7 +114,7 @@ struct KeyChar {
int16 followingKeyCharPos;
uint16 sequenceDataIndex;
uint16 sequenceDataOffset;
- int16 walkPointsListCount;
+ int16 walkPointsListIndex;
int16 walkPointsList[40];
uint16 scriptDataStartOffset;
uint16 scriptDataOffset;
@@ -209,7 +209,7 @@ struct InventoryState {
struct ProgramPointData {
int16 x, y, z;
- int16 priority;
+ int16 order;
};
struct ProgramWalkData {
@@ -390,7 +390,7 @@ protected:
void centerScreenToKeyChar(int keyChar);
void waitForKeyCharsSet();
void redrawRoom();
- void fadePalette(int firstColor, int lastColor, int scale, int scaleInc, int fadingStepsCount);
+ void fadePalette(int firstColor, int colorCount, int scale, int scaleInc, int fadingStepsCount);
void fadePaletteFromFlags();
void moveKeyChar(uint8 *dst, int dstPitch, KeyChar *key);
void changeKeyCharFrame(KeyChar *key, int keyChar);